2024 年 11 月,开发者 Yureka Lilian 买下了一台搭载 M4 芯片的 Mac mini。按照前几代苹果芯片被攻破的速度,让它跑上开源系统似乎指日可待。直到 17 个月后,这台机器的 CPU 才终于带着全部核心启动到了命令行界面。
苹果拆掉了虚拟机的监控探头
过去几年,开源社区对苹果芯片的逆向工程有一套成熟的打法。他们用定制的虚拟机去抓取 macOS 系统驱动与硬件交互的 MMIO 轨迹。这就好比观察系统怎么发号施令,再把指令复制到 Linux 里。
到了 M4,苹果关掉了灯。这代芯片强制启用了 SPTM 机制来加固系统内核。原先靠抓取内存交互轨迹的老办法直接失效。要让系统跑在虚拟机下,开发者必须对底层架构做伤筋动骨的改造。开源社区必须和一本没有文档的黑盒系统死磕。
图:Sven Peter 2025 年 4 月在 Mastodon 上的发言。来源:yuka.dev
靠打印单个字符排雷
复杂的侦察工具瘫痪后,开发者只能退回到最基础的试错方式。M4 上的启动程序 m1n1 只能在最基础的 BRINGUP 模式启动。只要初始化某些硬件或者写入正确的复位基址,机器就会直接崩溃。
Yureka Lilian 搬来了最简单的汇编例程。作者将其改成只打印单个字符 a,塞进内核启动的最初阶段。通过不断移动代码位置,靠二分法缩小范围,最终定位到了引发崩溃的具体指令。在这个过程中暴露出的锁死寄存器,直到后来的固件更新才被悄悄解开。
图:M4 Mac mini 上 Linux 首次启动到 shell,hyfetch 显示宿主为 Apple Mac Mini (M4, 2024)。来源:yuka.dev
芯片休眠强制清空寄存器
前期的启动崩溃只是门槛。真正卡住开发者的,是 M4 芯片上一个违反架构常理的硬件行为。
早期 M 系列芯片上设计了一个隐藏开关。一旦触发等待中断的休眠指令,CPU 就会清零 32 个通用寄存器里的数据。当时的 Linux 开发者为了换取更深的睡眠和省电,主动开启了开关,并在休眠前后手动保存数据。
图:M4 成功多核启动到 shell 后的系统信息。来源:yuka.dev
苹果在 M4 上把清空数据的行为变成了默认且无法关闭的硬性设计。这直接违背了 ARM64 的官方规范。规范明确要求休眠指令不能导致架构状态丢失。开发者在黑盒里摸索了很久才确认,这颗 CPU 只要一打盹,寄存器记忆就会被强制抹除。
替换空指令绕过硬件墙
面对这种蛮横的硬件设计,社区给出的解法非常直接。2026 年 4 月,开发者在内核里把所有的休眠指令替换成了空指令(NOP)。M4 的所有核心终于成功跑了起来。
他们没有选择打上可能误伤其他环境的补丁。相反,他们给 Linux 内核主线提交了一个早期启动参数选项,允许系统遇到休眠指令时主动绕过。苹果把未公开的硬件行为变成了 M4 上的硬门槛。开源社区只能靠一次次试错把无字天书破译出来,甚至反向要求上游内核为主流之外的特殊设计打补丁。在封闭的芯片孤岛面前,这是一场靠耐心拼下来的胜利。
参考链接:
- yuka.dev 博客记录
- Asahi Linux 社区动态