🐧 记一次折腾 Linux ARM64 内核的经历
玩了这么多年 Linux 发行版,这次还是第一次折腾调试 Linux 内核本身。
🗃️ 版本选择
我使用米板 5 已经一年有余,发行版从 Arch Linux ARM 换成了对 ARM64 支持更好的 AOSC OS,内核版本也从 6.1.10 用到 6.12.0,再到 6.14.0。
6.14 之后,社区开发者又发布了手写笔充电补丁、手写笔 120Hz 触控采样率补丁等,而我都没有吃上。于是我准备折腾一个更新一些的内核,合一些新的补丁进去。
眼下 7.0 内核临近发布,而高通平台在 6.2 内核就曾经出现过「睡不着」的问题,我担心在这个板子上未经测试的新内核会出现更多回归问题影响使用,就选择了社区已经测试成熟的 6.16.x 内核。
🤨 初见端倪
我下载了社区打好 BSP 补丁集的 6.16.0 内核源码之后,拉取并 rebase 到了该分支最新的 6.16.12 版本,打上了 BORE 调度器补丁、AOSC OS 补丁集,打上了几个群里的零散补丁,就准备着手开始编译。
我使用的是 LLVM Clang 交叉工具链。开始编译前,必然要通过 nconfig 调节一些选项,以调节 defconfig 中不适合我使用场景的选项。我之前在主力机上一直在用 CachyOS 的优化内核,该内核开启了 ThinLTO 优化。我虽然不懂 LTO 具体做了什么,但印象里它会有性能提升的效果,还是在菜单里开启了。
该选项旁边有一个大大的 EXPERIMENTAL,但我想着,「这功能都出了好几年了,应该不会出什么问题吧」,就没想太多。
💥 爆炸与慌乱
十五分钟后过后,热乎的内核新鲜出炉了。
我把内核做成 boot.img 刷到板子上之后,并没有成功点亮 —— 启动半路 panic 挂掉了。
新内核带有高清字体支持,板子是高 DPI 屏幕所以默认开启了,根本看不清几行日志,只能看见 stack trace 的最后几行,以及「30 秒后重启」的提示。
本以为是合并补丁的时候,不小心搞进去了某个和高通平台不兼容的补丁,但直觉告诉我,以我现在的能力,再加上 2026 年 AI 的帮助,足以调试并修好这个问题。
在 AI 的指导下,我通过设置 bootargs 开启了更小的 VGA8x16 字体,重启之后,看见了惨烈的死状 —— CPU: 6 UID: 0 PID: 801 Comm: tailscaled 导致了崩溃,PC(程序计数器)停在 rt6_multipath_hash+0x2f8/0x7d8。

这时,我回想到,BSP sm8150.config 里并没有开启太多网络功能,为了顺利使用 Docker 等涉及到网桥 / TUN 的工具,我开启了很多网络相关的模块。
本来决定关掉这些设置,重新编译再试,AI 却一直叫我使用调试工具看 rt6_multipath_hash 的源码 / 反汇编 …
🧐 深入崩溃
开始 Vibe debugging。
一边登上服务器,恢复原本的 defconfig 重新编译内核,一边学习使用调试工具。
一开始我使用 gdb 未果,并没有看到任何源码,按照 AI 的建议使用 addr2line 也什么都没有看到。
之后我才反应过来:内核是交叉编译的(并不是 x86_64 而是 arm64),而且使用的是 LLVM 而非 GNU 工具链,用 gdb / binutils 能看到东西就有鬼了。
使用 LLVM 的工具追踪到崩溃的行,是一个 READ_ONCE,而反编译出的对应汇编指令是 ldar。
1 | u32 seed = READ_ONCE(net->ipv4.sysctl.multipath_hash_seed); |
我没有学过 ARM64 体系结构,于是把死状截图和这条指令发给了 AI …

AI 一下子就定位到了问题所在,是一条指令没对齐。
哦,这下看懂了,是 ... .load(Ordering::Acquire)(?),而它一次只能读取 8 字节对齐的地址。
绝对是编译器干的。
🔍 修复方案
回想起之前开了 LTO 这个不稳定的特性,看来需要关掉它了。
改配置,编译,刷写。果然,成功点亮。
但我还是不死心 —— 明明在主力的 x64 电脑上用 LTO 内核用得好好的,怎么在 arm 板子上 LTO 内核就起不来了呢?
以 rt6 multipath seed READ_ONCE ldar 作为关键词在网上搜索,我搜到了这条补丁 —— https://patchew.org/linux/20260302060247.7066-1-yuuchihsu@gmail.com/ 。
按照邮件里的说明,这个 fib_multipath_hash_seed 结构体是 4 字节对齐的,而 READ_ONCE 在 LTO 激进的优化下有可能导致指令重排序错误,于是被编译成了要求 8 字节对齐的 ldar。
打上补丁,打开 LTO,编译,刷写,再次成功点亮。
觉得这次折腾的经历很有趣,正巧最近在学习操作系统相关的知识,于是写下这篇博客记录一下。
操作系统是一个复杂严密的学科,且涉及到体系结构、编译器等相关的底层知识,看来我还是要继续好好学,继续「补依赖」呀,不然也不至于连这种问题都要去问 AI 了。