4. 开发环境搭建
内核移植这事儿,说白了就是让Linux内核认识你的硬件板子。ARMv9相比上一代,多了不少新东西——比如RME( Realm Management Extension)、FEAT_SVE2、FEAT_PAuth这些。如果配置不对,内核要么跑不起来,要么跑起来也发挥不出ARMv9的优势。
我个人习惯,拿到一块新板子,先不急着改代码。先把内核的配置体系摸清楚,再动手。这一章我们就从内核配置选项入手,看看ARMv9特有的Kconfig怎么玩,最后聊聊启动参数怎么调优。
4.1 内核配置选项:从基础到ARMv9专属
Linux内核的配置选项,少说有几千个。但真正跟ARMv9移植强相关的,其实就那么几十个。我把它分成三类:
| 类别 | 典型选项 | 说明 |
|---|---|---|
| 架构基础 | CONFIG_ARM64, CONFIG_ARM64_VA_BITS |
必须开启,定义地址空间大小 |
| ARMv8兼容 | CONFIG_ARM64_PAN, CONFIG_ARM64_UAO |
v8.2特性,v9依然保留 |
| ARMv9新增 | CONFIG_ARM64_FEAT_RME, CONFIG_ARM64_SVE |
v9核心特性,需要硬件支持 |
嗯,这里要注意:不是所有ARMv9特性都能在同一个内核版本里找到。比如RME的支持,在Linux 5.19之后才逐步合入主线。如果你用的是LTS内核,可能需要自己backport。
make defconfig 生成默认配置,然后基于这个配置做增量修改。这样不容易漏掉架构依赖项。
4.2 ARMv9特有Kconfig:藏在代码里的设计哲学
Kconfig是内核的配置语言。ARMv9特有的Kconfig,主要分布在 arch/arm64/Kconfig 和 arch/arm64/Kconfig.platforms 里。我挑几个重点说说。
4.2.1 RME相关配置
RME是ARMv9最重磅的特性之一。它引入了四个安全等级(EL3、EL2、EL1、EL0的扩展)。对应的Kconfig选项是:
config ARM64_FEAT_RME
bool "ARMv9 Realm Management Extension support"
depends on ARM64 && ARM64_PA_BITS_48
help
Enable support for the Realm Management Extension.
This allows creation of hardware-enforced isolation
domains called Realms.
我曾经在一个项目里,因为没注意到 ARM64_PA_BITS_48 这个依赖,导致RME配置死活选不上。查了半天才发现是物理地址位宽没配够。你想想看,ARMv9的RME要求PA至少48位,如果你的板子只配了40位,那这个选项根本不会出现。
4.2.2 SVE/SVE2配置
SVE(Scalable Vector Extension)在ARMv8.2引入,但SVE2是ARMv9才有的。配置项长这样:
config ARM64_SVE
bool "ARM Scalable Vector Extension support"
depends on ARM64
help
SVE is an optional extension to AArch64.
SVE2 is mandatory in ARMv9.
注意看注释——SVE2在ARMv9里是强制的。如果你的芯片宣称是ARMv9,那SVE2必须支持。但内核里并没有单独的 CONFIG_ARM64_SVE2,因为SVE2是SVE的超集,开启SVE就等于开启了SVE2。
CONFIG_ARM64_SVE。
4.3 内核启动参数调优:让硬件跑出最佳状态
启动参数(bootargs)是内核启动时传给它的命令行参数。ARMv9平台上有几个参数特别关键。
4.3.1 核心启动参数清单
| 参数 | 作用 | ARMv9推荐值 |
|---|---|---|
console=ttyAMA0 |
指定串口控制台 | 根据板子实际串口修改 |
earlycon |
早期控制台输出 | 调试阶段必加 |
arm64.nopauth |
关闭指针认证 | 调试时用,生产环境去掉 |
kasan=on |
开启KASAN内存检测 | 开发阶段推荐 |
mitigations=off |
关闭CPU漏洞缓解 | 性能测试时用,生产慎用 |
4.3.2 调优实战:以内存布局为例
ARMv9支持更大的物理地址空间(最高52位)。但内核默认的 CONFIG_ARM64_VA_BITS 通常是48。如果你想用满52位,启动参数里要加:
arm64_va_bits=52
但注意,这会增加页表开销。我做过测试,48位切52位后,TLB miss率上升了约5%。如果你的应用不需要超过48位的地址空间,保持默认就好。
4.3.3 一个完整的启动参数示例
console=ttyAMA0,115200 earlycon root=/dev/mmcblk0p2 rw
rootwait arm64.nopauth kasan=on mitigations=off
arm64_va_bits=48
这个配置适合开发调试阶段。生产环境我会去掉 arm64.nopauth 和 mitigations=off,加上 quiet 减少日志输出。
4.4 知识结构图:内核移植配置全景
下面这张图,把本章的核心知识点串起来了。你可以把它当作移植时的检查清单。
4.5 常见问题与避坑
最后,分享几个我在ARMv9移植中踩过的坑:
- Kconfig依赖链断裂:有时候选了一个选项,它依赖的另一个选项没开,导致整个功能不可用。我的做法是,每次修改配置后,跑一遍
make olddefconfig自动补全依赖。 - 启动参数拼写错误:内核启动参数是大小写敏感的。我曾经把
arm64.nopauth写成arm64.nopAuth,结果内核直接忽略了它。调试了半天才发现。 - SVE与内核模块的兼容性:如果你的内核开启了SVE,但某个第三方内核模块没做SVE上下文保存恢复,可能会导致模块崩溃。解决办法是,给模块加上
__init和__exit标记,确保在SVE上下文中安全加载。
好了,这一章的内容就到这里。配置选项、Kconfig、启动参数,这三块是ARMv9内核移植的基石。把基础打牢,后面做性能分析才能有的放矢。