Atari Jaguar 主机 Linux 内核移植技术挑战全记录
一、项目背景与硬件概述
1.1 Atari Jaguar 的历史定位
1993 年由 Atari 公司发布的 Jaguar 是游戏主机史上极具争议的产品。官方宣传将其定义为全球首款 64 位游戏主机,但实际硬件架构却充满了妥协与隐患:
- 主 CPU:摩托罗拉 MC68000,运行频率 26.842 MHz(PAL)/ 26.590 MHz(NTSC)
- 协处理器:Tom(GPU)与 Jerry(DSP)两颗自研芯片,各 26 MHz
- 内存配置:标配 2 MB 主存,卡带可扩展至 4 MB
- 存储介质:ROM Cartridge + Jaguar CD 光驱(外设)
1.2 为什么要在 Jaguar 上跑 Linux
在一台仅有 2 MB RAM、缺乏 MMU 的游戏机上运行现代操作系统内核,听起来像是一项 "不可能的任务"。但从技术研究的角度,移植工作包含以下价值:
- 验证 无 MMU 的 m68k 架构 在极端内存环境下的内核裁剪能力
- 复刻一套完整的 外设驱动框架(Tom/Jerry 寄存器级别)
- 探索 从零搭建引导链 的逆向工程方法论
二、核心硬件挑战分析
2.1 M68K 处理器无 MMU 问题
Jaguar 采用的 MC68000 是经典的 16/32 位混合处理器,但它是 68000 系列中唯一不带内存管理单元(MMU) 的型号。这意味着:
- 无法实现虚拟内存与进程地址空间隔离
- 缺页异常(Page Fault)机制彻底失效
- 内核必须以 单一物理地址空间 视角运行
2.2 内存资源极度受限
| 资源项 | 容量 | 用途分配 |
|---|---|---|
| 主 RAM | 2 MB | 内核 + 数据段 |
| 显存 | 共享部分主存 | 帧缓冲 |
| Cartridge | 4 MB Max | 根文件系统镜像 |
| Jaguar CD RAM | 512 KB | CD 缓存 |
Linux 4.x 内核压缩后最小接近 600 KB,仅是 内核本体 就几乎占满可用内存,文件系统与运行时分配空间被严重挤压。
2.3 自研芯片带来的驱动真空
Tom 与 Jerry 没有任何公开的寄存器手册(仅有零散的逆向文档)。社区主要参考来源包括:
- Atari 官方泄漏文档(部分残缺)
- Scout 调试器源码(Atari 内部工具)
- 催化剂 Jaguar SDK 反汇编
- 硬件发烧友论坛的嗅探器输出
三、引导流程的逆向重建
3.1 原始启动机制剖析
Jaguar 上电后执行流程:
- ROM Bootstrap:固化在系统芯片中的 256 字节引导代码初始化 68000 栈
- 检测 Cartridge:从
$800000起始地址读取 Cartridge 头部 - 跳转执行:头部第 4–7 字节为入口地址指针,直接跳转至 Cartridge 入口
该 256 字节的引导 ROM 无法被替换,且不支持块设备加载,因此不能简单套用传统 bootloader 思路。
3.2 自制二级 Bootloader 设计
为突破原始引导限制,需要构建一套 链式启动方案:
Cartridge ROM (Stage1) → 内核镜像头 (Stage2) → Linux 内核Stage1 阶段:
- 接管 68000 的中断向量表
- 通过 Tom 芯片的 GPU 通道从 Cartridge 余下空间复制内核到主 RAM
- 实现 LZ4 解压(避免占用 Cartridge 中的宝贵解压器空间)
Stage2 阶段:
- 完成 中断控制器初始化(Jaguar 中断为向量式,无 8259 等价物)
- 设置 内核入口栈(68000 的 A7 寄存器)
- 向 MMU-less 的 Linux 传递
atari Jaguar平台标识
3.3 内核入口汇编的关键差异
由于缺少 MMU,head.S 的处理流程与传统 m68k 平台有显著区别:
- 跳过 TLB 初始化段(uClinux 分支)
- 直接构建 swapper_pg_dir 的物理等价结构
- 手工将 BSS 段清零(uClinux 不依赖链接脚本自动扩展)
四、内存管理子系统适配
4.1 uClinux 方案的取舍
主线 Linux 已移除对 68000(无 MMU)的支持,因此项目基于 uClinux-m68k-legacy 分支进行移植。关键差异:
| 特性 | MMU Linux | uClinux 移植版 |
|---|---|---|
| 进程隔离 | 完整实现 | 不支持 |
fork() | 写时复制 | vfork() 模拟 |
| 内存分配 | vmalloc/伙伴系统 | 仅使用 kmalloc |
| 用户态 | 真实虚拟地址 | flat 地址空间 |
4.2 零碎页分配的应对策略
面对 2 MB 的物理内存,必须将 页大小 从默认的 4 KB 调整为 自定义 16 KB 大页,以减少页表开销并提升 DMA 连续性。PAGE_SHIFT 在 arch/m68k/include/asm/page.h 中被覆写。
4.3 交换分区设计
由于内存极其紧张,Cartridge 余下的 3 MB 空间被格式化为 极简交换区:
- 块大小 1 KB(节省元数据)
- 单文件交换 + 内存映射回写策略
- 配置
/proc/sys/vm/swappiness为 0,避免积极换出
五、外设驱动开发实录
5.1 Tom 芯片的寄存器映射
Tom 本质上是 复合型 GPU + 内存控制器,主要寄存器区域:
0xF00000 - Tom 控制寄存器
0xF10000 - GPU 命令队列
0xF20000 - 像素引擎 (BLITTER)
0xF40000 - 视频时序驱动框架通过 platform_driver 注册,提供以下子模块:
jaguar-tom-blit.c:硬件位图传送jaguar-tom-video.c:视频模式配置jaguar-tom-dma.c:链式 DMA 描述符
5.2 Jerry 芯片的 DSP 驱动
Jerry 提供 DSP 加速与 I/O 总线桥接。在 Linux 视角下,Jerry 主要承担:
- 串口(经 Jaguar CD 附加卡)
- 控制器扫描(PAD 端口)
- 音频 PCM 流输出
驱动以 i2c_adapter 的衍生模式实现控制器轮询,使用工作队列而非中断(因 Jerry 中断源已被 GPU 占用)。
5.3 输入子系统适配
Jaguar 手柄仅含 6 个按钮 + 1 个 D-Pad,通过 9 针串行接口轮询。内核侧驱动映射为标准的 evdev 设备:
static const struct jaguar_button_map {
unsigned int btn; // BTN_A 等标准键码
unsigned int shift; // Jerry 端口位偏移
} jaguar_pad_map[] = {
{ BTN_A, 1 },
{ BTN_B, 2 },
{ BTN_C, 3 },
{ BTN_X, 4 },
{ BTN_Y, 5 },
{ BTN_Z, 6 },
};5.4 Jaguar CD 子系统
光驱子系统是整个移植工程中 最难的部分。CD 控制器通过并行 DMA 与主机通信:
- 自定义 SCSI 子集协议
- 内置 512 KB 缓存(提升吞吐)
- 通过
/dev/jcd暴露给用户态
六、调试方法论
6.1 多重日志输出策略
在没有标准串口的 Jaguar 上,调试输出必须另辟蹊径:
| 阶段 | 输出方式 | 速率 |
|---|---|---|
| Stage1 Boot | Tom 显存叠加层 | 人类可读 |
| 内核 early printk | 修改 Jerry 内部 UART 仿真 | 9600 bps |
| 用户态 console | Jaguar CD 串口卡 | 115200 bps |
6.2 LED 状态机编码
为诊断早期 panic,将 Jaguar 正面仅有的 Power LED 改造为 多状态指示器:
- 常亮:内核成功引导
- 慢闪 1 Hz:MMU 初始化异常
- 快闪 4 Hz:驱动注册失败
- 三短一长:文件系统挂载错误
通过 led_pattern 内核参数动态修改编码。
6.3 与 MAME/Jaguar 仿真器的协同验证
每次修改驱动需在仿真器与真机双向验证:
- 在 MAME 中启用 trace 模式,记录寄存器访问
- 使用 Virtual Jaguar 快速迭代
- 真机仅用于最后冒烟测试,避免损耗硬件
七、当前进展与未来展望
7.1 已实现里程碑
- ✅ Stage1/Stage2 引导链完整闭环
- ✅ uClinux 内核可在 2 MB 内存下引导至 Shell
- ✅ Tom GPU 显示 80×25 文本控制台
- ✅ Jaguar CD 块设备可挂载 ISO
- ⚠️ 控制器按键偶尔出现抖动(中断时序问题)
7.2 待解决的关键挑战
- 音频子系统尚未稳定:Jerry DSP 的 PCM 流存在溢出
- 网络栈缺失:无内置以太网,需要 Jaguar CD 调制解调器适配
- 多任务稳定性:
vfork实现的进程模型在高负载下偶发死锁
7.3 长远意义
在 Atari Jaguar 这一历史遗留平台上成功移植 Linux 内核,验证了三大技术命题:
- 嵌入式 Linux 完全可以运行在 68000 这种 "古董" 架构上,为工业控制系统旧设备升级提供了新思路
- 极端受限环境下的驱动开发 倒逼出更高效的寄存器抽象模型
- 逆向工程的系统化方法 可应用于其他未文档化的游戏主机(如 3DO、Neo Geo CD)
注:该项目代码托管于 GitHub 镜像仓库jaguar-linux-m68k,欢迎社区贡献者提交 Pull Request。每一次git push都是对 1993 年那台短命主机的致敬。