1993 年的秋天,Atari 把最后一张牌拍在了桌上。这台叫 Jaguar 的游戏机带着”64 位”的喧嚣而来,又在两年后悄无声息地消失。谁也没想到,三十多年后,有人让它跑起了 Linux。
不是模拟器,不是 FPGA 重实现。就是那台 2MB 内存、无 MMU、搭载摩托罗拉 68000 处理器的原版 Atari Jaguar,在 2026 年 7 月的某一天,屏幕上打印出了 Linux 内核的启动信息。

干这件事的人叫 cakehonolulu,一位西班牙系统软件开发工程师。他在自己的博客上详细记录了整个移植过程——从内核裁剪到编译器踩坑,从内存布局到 BusyBox 用户空间。读完之后你会觉得,这完全是一次教科书级别的嵌入式 Linux bringup。
Atari Jaguar:一个被遗忘的”64 位”遗珠
在讲技术之前,先说说这台机器本身。Atari Jaguar 于 1993 年 11 月在北美首发,被标榜为”世界上第一台 64 位游戏机”。这个说法在当时就争议很大——它的主 CPU 其实是 16/32 位的摩托罗拉 68000(1979 年发布的老将),所谓的 64 位能力来自两颗定制芯片:Tom(图形处理单元)和 Jerry(数字信号处理器)。

硬件配置在今天看来寒酸到令人发笑:2MB RAM,6MB ROM 上限(卡带),一颗 13.3MHz 的 68000。没有内存管理单元(MMU),没有浮点单元。作为对比,当下随便一台智能灯泡可能都有更多内存。
但这台机器也有它的奇妙之处。Tom 和 Jerry 这对组合——名字显然来自经典动画《猫和老鼠》——提供了当时相当先进的图形和音频能力。Tom 是一个 64 位对象处理器和位块传输器(blitter),Jerry 是一个 32 位 DSP,带两个定时器和串行接口。正是这些外围硬件,为三十多年后的 Linux 移植提供了基础设施。
Jaguar 最终成为 Atari 在家用游戏机市场的绝唱。CD 扩展配件 Jaguar CD 没能救它,PlayStation 和世嘉土星的到来彻底终结了它的命运。据估计,整个生命周期只卖出了不到 25 万台。
为什么是 Linux?
cakehonolulu 博客里有一句话精准概括了动机:「Well, it’s easy; because we can (-ish).」——因为我们可以。差不多能行。
但”因为我们可以”背后有一套技术上的巧合。Linux 内核至今仍然维护着 arch/m68k/ 架构代码,覆盖了 68000 全系列处理器:68000、68010、68020、68030、68040。这意味着,理论上,只要你能把代码加载到内存里,Linux 就可能在任意一台使用 68000 的设备上运行。
问题在于”加载到内存里”这件事。Jaguar 只有 2MB 内存。一个裁剪过的 Linux 内核镜像通常也要几 MB,再加上 initramfs,2MB 根本塞不下。
另一个更致命的问题是 MMU。传统 Linux 内核依赖 MMU 来管理虚拟内存、隔离进程、实现写时复制。68000 没有 MMU。但 Linux 有一个特殊的分支——uClinux,专门为无 MMU 系统设计。它曾经是独立的下游 fork,后来合并进了主线内核,而且对 m68k 架构有原生支持。
于是路径清晰了:用 uClinux 的 nommu 模式编译,精简到极致,然后想办法塞进 Jaguar。
把大象塞进冰箱
如果你以为”编译一个 -nommu 内核然后跑起来就行”,那你就太天真了。cakehonolulu 遇到的是一连串的问题。
内存三角:RAM、ROM 和 XIP
第一个问题是内存布局。Jaguar 的 2MB RAM 映射在地址 0x000000,最高 6MB 的 ROM(卡带)映射在 0x800000。一个完整的 Linux 内核镜像显然超过了 2MB。
解决方案是 XIP(eXecute-In-Place,原地执行)。Linux 允许把内核的只读部分(.rodata、.text)放在 ROM 中直接执行,而可写部分(.data、.bss)放在 RAM 中。cakehonolulu 利用这个机制,把大部分内核代码塞进了卡带空间,RAM 只用来存放动态数据。
编译器陷阱
即使内存布局对了,内核也跑不起来。为什么?出在编译器上。
Ubuntu 软件仓库里的 m68k-linux- 交叉编译工具链,即使在编译时显式指定 -68000 参数,仍然会生成未对齐内存访问指令。而基础版 68000 处理器——跟 68020 及后续型号不同——不支持未对齐内存访问。所以内核一执行就崩溃,而且没有任何错误信息。
这个问题的排查过程本身就是一堂硬件调试课。cakehonolulu 尝试了 MAME 模拟器的 gdbstub 调试,发现 gdb-multiarch 在协调 gdbstub 时行为异常,会随机跳转到地址空间的任意位置。最终他不得不从源码编译了一版专门针对 m68k 的 gdb,才让调试器正常工作。
编译器也得从源码编译——用 m68k-elf- 目标重新构建 GCC,确保它老老实实只生成对齐的内存访问。
中断向量和启动跳转
还有一个更隐蔽的问题:68000 的中断向量表(VBR)默认在地址 0x000000。但 Jaguar 的 ROM 在 0x800000。如果内核尝试跳转到向量表所在位置,那里什么都没有,CPU 就会”燃烧殆尽”(cakehonolulu 原话)。
解决办法是在 Jaguar 平台特定的 Linux 初始化代码中,手动把向量表从 ROM 复制到 RAM 的开头。
串口和定时器
要让内核启动时有输出,需要串口。Jaguar 的 Jerry DSP 芯片有 TXD 和 RXD 引脚。cakehonolulu 写了一个简单的 console 驱动,用 bit-bang 方式操作这些引脚来输出 earlyprintk 消息。这并不优雅,但足够让你看到内核在说什么。
定时器同样来自 Jerry。它有两个硬件定时器,原本设计给音频使用。cakehonolulu 重写了 68000 的板级初始化代码,把其中一个定时器指定为 Linux 的 PIT(Programmable Interval Timer),用来驱动调度器和系统时钟。
它真的跑起来了
做完这一切之后,内核终于打印出了信息:
Linux version 7.2.0-rc1+ (cakehonolulu@jaguar)
(m68k-elf-gcc (GCC) 16.1.0, GNU ld (GNU Binutils) 2.46.1)
#38 Sun Jul 5 11:56:37 CEST 2026
printk: legacy bootconsole [early_jerry0] enabled
uClinux with CPU MC68000
Flat model support
Calibrating delay loop... 1.04 BogoMIPS (lpj=5248)
1.04 BogoMIPS。这是 Jaguar 的”性能指标”。不是 1.04G,是 1.04。一个现代的树莓派跑 Linux 有几百 BogoMIPS。但重点从来不是性能。
内核启动后试图寻找 init 进程,当然没找到——又是一个内核崩溃。接下来是更费劲的用户空间构建。
BusyBox 和 FLAT 二进制
因为无 MMU,Jaguar 不能运行标准的 ELF 可执行文件,只能用 FLAT 二进制格式(bFLT)。这意味着整个工具链都得重新折腾。
cakehonolulu 发现 elf2flt(ELF 到 FLAT 的转换工具)很难独立编译——它依赖一些在 68000 的默认 binutils + GCC 配置中已经消失的库文件和头文件。幸运的是,Buildroot 在 2026 年 5 月——就在写博客的两个月前——收到了一个补丁,专门为 m68k nommu 目标修复了这个问题。cakehonolulu 特别感谢了 linuxmd 项目(他们在几周前刚把 Linux 移植到世嘉 MegaDrive 上)。
BusyBox 是少数支持 nommu 目标的项目之一。但即使把它编译成 FLAT 二进制,问题还没完:执行 busybox --install(BusyBox 的初始化命令,会创建所有 applet 的符号链接)会导致 OOM。2MB 内存实在太拮据。
所以最终的 init 脚本极简到什么程度?
#!/bin/busybox sh
/bin/busybox sh
就两行。启动 BusyBox shell,给你一个命令行。没有 ls,没有 cat,没有其他 applet——只有 sh。创建符号链接的过程都会耗尽内存。
还有一个细节:uClibc 的默认 malloc 策略是”更智能、更快的分配方式”,但它的元数据开销太大。cakehonolulu 在 Buildroot 的 uClibc menuconfig 里把 malloc 策略改成了 malloc-simple——最简单最省内存的分配器——才避免了内核 panic。
真正的硬件也能跑
cakehonolulu 还专门为 Tom 芯片写了一个简单的 console 驱动,让 Linux 的输出可以显示在 Jaguar 的屏幕上,而不只是通过串口。这意味着不需要外接调试设备,在真正的 Jaguar 硬件上插上一张特制卡带,就能看到 Linux 启动。
当然,要在真机上运行,还有一些额外的准备:内核编译时需要加上 8KB 的偏移量给 Jaguar 卡带头部,ROM 起始地址和长度要相应调整。但这些只是”体力活”,最难的部分已经完成了。
复古硬件跑 Linux:潮流已至
Atari Jaguar 不是第一个被攻克的 90 年代游戏机。2026 年 6 月 29 日,也就是 Jaguar Linux 出现的几周前,Hackaday 报道了世嘉 MegaDrive(Genesis)跑 Linux 的项目。那个项目叫 linuxmd,使用了特殊的卡带映射器(基于《超级街头霸王 2》的 mapper),额外增加了 4MB RAM。
再往前追溯:2021 年,有人让 Nintendo 64 运行了 Linux。2023 年,Linux 被移植到了基于 SuperH 处理器的世嘉 Dreamcast——其实 Dreamcast 早就有 NetBSD 支持了。
这些项目的共同点不是实用性——没人会用 Jaguar 当 NAS 或跑 Docker。它们的意义在于证明可能。在一个 2MB 内存、无 MMU 的硬件上启动一个现代操作系统内核,这件事本身就说明了很多问题:Linux 内核的架构抽象有多成熟、uClinux 的 nommu 支持有多健壮、以及复古硬件社区有多顽强。
cakehonolulu 在他的博客末尾说了一句很真实的话:Jaguar 没有 linuxmd 那种特殊卡带映射器(能多给 4MB),所以他在内存上没法奢侈到加一个 u-boot 引导器——直接 jmp _linux,硬跳。
这是最纯粹的嵌入式开发精神:没有引导加载程序,没有 bootloader,没有 initramfs 膨胀,只有你、CPU 和一段精打细算到每一个字节的代码。
你能试试吗?
完整的修改版 Linux 内核代码在 GitHub 上:cakehonolulu/linux_jag。cakehonolulu 在博客末尾还提供了 BusyBox 配置文件和 init 脚本,方便有兴趣的人复现。
如果你有一台 Atari Jaguar 和一张可烧录卡带,理论上你现在就可以在自己的 Jaguar 上看到那个熟悉的 penguin——虽然只是一个文本模式的 shell,但那是 Linux,运行在一台 1993 年的 64 位(号称)游戏机上。
三十年前,Jaguar 输给了 PlayStation。三十年后,它用一种最不商业的方式赢回了一点尊严:跑起了这个星球上最重要的操作系统。
参考链接:
- https://hackaday.com/2026/07/07/the-atari-jaguar-runs-linux/ (Hackaday 原报道)
- https://cakehonolulu.github.io/linux-for-jaguar/ (cakehonolulu 的技术博客)
- https://github.com/cakehonolulu/linux_jag (修改版 Linux 内核源码)
- https://www.tomshardware.com/software/linux/dev-ports-linux-to-ataris-notorious-jaguar-console-from-1993-the-first-64-bit-console-features-2mb-of-ram-13-3-mhz-cpu-and-tom-and-jerry-co-processors-the-jag-was-notoriously-difficult-to-program-and-flopped (Tom’s Hardware 报道)
- https://hackaday.com/2026/06/29/its-linux-on-a-sega-megadrive/ (世嘉 MegaDrive 跑 Linux)