你按下电脑的睡眠按钮,合上盖子,再打开——屏幕亮起,一切如初。这是现代计算最基础的承诺:CPU可以在无事可做时打个盹,醒来继续干活,像什么都没发生过。
ARM的架构规范把这条承诺写成了白纸黑字:WFI(Wait For Interrupt,即"等待中断")这条指令"不得造成架构状态丢失"。用人话说——CPU打个盹,醒来时寄存器(CPU内部比内存快几千倍的临时存数格子)里的数据应该原封不动。
但Apple M4芯片打破了这个承诺。当Linux内核在M4上执行WFI时,CPU确实睡着了,也确实被唤醒了——只是醒来后,三十二个通用寄存器被清零。就像一个人打了个盹,醒来忘了自己是谁、在干什么、手里拿着什么。
这不是偶发故障。这是设计。
一条省电指令,为什么成了内核杀手?
要理解这件事有多离谱,得先知道WFI到底在做什么。
CPU发呆的时间比你想象的多得多。你在读这句话时,处理器在几纳秒内完成了所有计算,然后干等——等内存把数据送上来、等下一个中断到来。这种等待中,CPU内部数十亿晶体管仍在疯狂翻转,白白耗电。WFI就是为这个场景设计的:一条"hint"指令(提示指令——它只是建议CPU这么做,不强制),等于告诉CPU"现在没什么事,你可以关掉大部分电路,有中断来了再叫你"。
ARM规范对这条指令做了严格限制:它可以只关时钟信号(clock-gating——数据保留、功耗降幅有限),也可以连电都断掉(power-gating——省得多但数据会丢),唯独不能弄丢数据。x0到x31这32个通用寄存器——CPU此刻所有计算结果的存放处——必须保持原样。ARM的架构手册专门加了一句:"若系统配置使WFI可完成,则WFI不得造成架构状态丢失。"
Apple在M1到M3芯片上遵守了这条规则——靠的是取巧。这几代芯片里藏了一个叫"chicken bit"的配置位。这个词源自芯片行业的俚语:工程师在硅片里留一个后门开关,出问题时可以"chicken out"——临阵退缩,关掉某个有风险的功能。这个配置位控制着WFI的行为:设为"仅时钟门控"模式时,CPU打盹但不忘事;设为"允许电源门控"模式时,CPU进入更深度的睡眠,功耗降得更狠,但醒来时寄存器清零。

macOS自己的内核(叫XNU)知道这件事。它在执行WFI之前会先把x0到x31全部压入栈中保存——栈是内存里一块按"后进先出"规则使用的临时存储区——等CPU醒来再恢复。相当于睡前给自己写好一张便利贴。
而Asahi Linux团队在为M1-M3做Linux适配时,通过m1n1——Asahi团队自研的一个微型引导程序——把这个chicken bit强制锁在"仅时钟门控"模式,让Linux根本撞不上这个坑。等后面他们自己实现了更聪明的电源管理驱动,再主动切回深度睡眠模式——前提是驱动会像XNU一样先保存再恢复。两条路都是安全的。
M4把这张牌桌掀了。
新的芯片上,这个控制WFI行为的寄存器被彻底锁死——或者说,被移除了。m1n1无法再改它。而默认行为恰好是那个"深度睡眠、醒来清零"的模式。Linux内核对此一无所知,在idle循环里照常执行dsb sy; wfi("等前面指令跑完,然后等中断")——CPU醒来,x0到x31全是零,内核瞬间崩溃。
那么问题来了:Linux明明有"打补丁"框架,为什么不用?
Linux内核其实早就准备好了应付这种情况的工具箱。
自2014年起,ARM64架构就有了一个叫"alternatives"的运行时自修补框架。它的逻辑很简单:内核镜像里同时打包原指令和替换指令,启动早期根据CPU型号判断是否需要修补——如果需要,就在内存里把wfi原地改写成nop(空操作,CPU执行它就像踩了一脚空油门,什么也不发生)。Intel的Spectre/Meltdown漏洞、AMD的Zenbleed数据泄露,走的都是这条路。

Yureka——这位独立开发者,也是本篇故事的主角——最初提交的正是一套基于alternatives的补丁:检测到Apple的芯片ID且在裸机EL2权限(ARM处理器最高的特权级之一,只有操作系统内核和虚拟机管理器能跑在这个级别)下运行时,自动把所有WFI替换成NOP。
但Linux内核ARM64架构的维护者Will Deacon否决了这个方案。他的质疑一针见血:"你如何保证在补丁生效之前,没有CPU核心执行过WFI?"
这是一个时序黑洞。补丁生效的时刻到来之前,辅助核心可能已经被启动了,而它们一启动就会进idle循环执行WFI。哪怕窗口只有几毫秒,也足够崩掉。
更棘手的还在后面——虚拟化场景。macOS自带的虚拟机管理器(Hypervisor)可以在虚拟机里跑Linux,而虚拟机里的Linux看到的是同一个Apple芯片ID,甚至嵌套虚拟化下看起来也在EL2权限。但这里WFI是被Hypervisor安全捕获并用来调度不同虚拟机的——如果把它NOP掉,虚拟机调度就废了。要区分"我在裸机上"还是"我在虚拟机里",在嵌套虚拟化下极其困难,甚至没有可靠的检测手段。
Will Deacon提出的替代方案很像x86世界早已存在的东西:一个新的内核启动参数idle=nop。由引导器——也就是m1n1——来判断是不是M4裸机,如果是,就在启动Linux时偷偷加上这个参数。Linux内核看到idle=nop,就自动把idle循环里的WFI替换成NOP。
这个方案有一个明显的代价:CPU不再省电了。平时idle时CPU应该进入深度睡眠,功耗降到只剩静态漏电流——也就是晶体管即使不切换、也会自然漏掉的微弱电流,这是芯片能省到的极限——现在却要在空循环里干烧。对于笔记本,这意味着电池续航会受影响。
但它是正确的。2026年8月,这套方案被合入了Linux内核的上游主线——也就是Linux官方版本,全球所有Linux发行版都从这里取代码。同时合入的还有m1n1的对应改动。从此,任何人在M4、M4 Pro、M4 Max甚至M5芯片上启动最新版Linux,所有核心都能正常使用。
值得一提的是,历史上几乎每一起重大CPU硅级缺陷的软件补救,都付出了类似的代价。1997年Intel Pentium的F00F漏洞,只需四个字节就能让任意用户态程序冻结整台机器——操作系统靠拦截非法指令来绕过。2007年AMD Phenom处理器在内存地址翻译环节的一个缺陷,Linux补丁让部分应用性能暴跌近20%——十个程序里有两个明显变慢。2014年Intel Haswell有一项叫TSX的指令集功能——专门用来加速多线程程序的并发处理——因为一个无法微码修复的硬件bug被全线禁用。花了大价钱设计的功能,直接消失。相比之下,M4的WFI修复只是多耗一点电,已经是相当体面的结局了。
从一台Mac mini到整个ARM生态
讲到这里,你可能会问:这件事跟我有什么关系?
最直接的受益者是开发者。M4 Mac mini起售价约599美元(约合人民币4300元),能效比极高——把它变成一台安静的ARM64 Linux服务器,跑编译、跑容器、跑持续集成,性价比是同等算力x86服务器的数倍。WFI修复之前,Linux只能在M4上启动单核;修复之后,全部核心可用,高速固态硬盘和PCIe总线也已经在后续工作中被打通。Asahi Linux与Fedora合作的发行版,正在让Apple Silicon从"能跑Linux"走向"好用的Linux桌面"。
但这远不只是一台Mac的事。Apple Silicon所用的ARM64架构,正在从手机向服务器、桌面、甚至超算全面渗透。AWS Graviton、Ampere Altra、NVIDIA Grace——每一个ARM服务器芯片的背后,都有Linux内核的ARM64支持在托底。M4的WFI修复被直接提交到了上游主线,意味着任何基于较新ARM架构的芯片,只要遇到类似的"WFI不守规矩"问题,都能复用同一套idle=nop机制。
当然,边界条件也必须诚实地说出来:M4上的Linux现在只有CPU核心和存储是好的。GPU、显示控制器、WiFi、Thunderbolt、摄像头——这些外设的逆向工程仍在缓慢推进。Apple在新芯片上强制启用了SPTM(安全页表监视器——一种加固macOS内核安全的硬件机制),这让通过虚拟机跟踪macOS驱动行为变得极为困难。Yureka在博客末尾说了一句意味深长的话:"有时候,如果某些获得了大量资金的项目能更透明地展示它们是如何从上游项目的进展中获益的,那会很好。"——这句话没有点名,但如果你知道Asahi Linux是一个完全靠社区捐赠运转的志愿者项目,而某些商业ARM Linux发行版正默默享用着这些志愿者的上游提交,你就明白了这句话的重量。
从2024年11月买下那台M4 Mac mini,到2026年4月首次用"把所有WFI替换成NOP"的暴力方法启动成功,再到8月方案被合入主线——Yureka花了将近两年时间。而整件事的开端,不过是CPU里一条用于省电的指令,不肯遵守它自己写在规范里的承诺。
有些bug是代码写错的;有些bug是硅片在制造时就有了的。而最棘手的那一类,是设计者明知道它存在,却在规格书之外另做了一套只有自己操作系统才知道的补救方案——把其他所有人都关在了门外。
修好它的那个人,用一台Mac mini、一根串口线、和一个往内核里插"打印字母a"的笨办法,把门推开了。