1. ARMv9 架构概览:从 v8 到 v9 的演进、核心特性与 AArch64 执行状态详解
各位好,我是老周。今天咱们正式开讲 ARMv9。说实话,我第一次拿到 ARMv9 的架构手册时,第一反应是——这不就是 v8 的加强版吗?但深入看下去才发现,事情没那么简单。
ARMv9 是 ARM 公司在 2021 年发布的重大架构版本。它并不是推倒重来,而是在 v8 的基础上做了三个方向的深度进化:安全、可扩展、高性能计算。你想想看,从手机到服务器,从嵌入式到超算,ARM 想用 v9 一统天下,没点真功夫可不行。
核心观点:ARMv9 不是 v8 的替代品,而是 v8 的进化版。v8 的代码可以在 v9 上直接跑,但 v9 新增的特性,v8 永远用不了。
1.1 从 v8 到 v9:到底改了啥?
我习惯用一张表来对比这两个架构。这样最直观。
| 特性维度 | ARMv8 | ARMv9 |
|---|---|---|
| 指令集 | A64 + A32/T32 | A64 为主,A32 逐步淘汰 |
| 地址空间 | 48 位虚拟地址 | 52 位虚拟地址(可选) |
| 安全架构 | TrustZone | CCA(机密计算架构)+ TrustZone |
| 向量扩展 | NEON(128 位) | SVE2(可伸缩向量,128-2048 位) |
| 调试与跟踪 | CoreSight | CoreSight + 增强分支记录 |
| 虚拟化 | VHE(虚拟化主机扩展) | 增强 VHE + 嵌套虚拟化 |
看到没?v9 最大的变化在三个地方:SVE2、CCA、52 位地址。咱们一个一个说。
1.2 ARMv9 三大核心特性
1.2.1 SVE2:可伸缩向量扩展第二代
SVE2 是 v9 最亮眼的特性之一。说白了,它让 CPU 能一次处理更多数据。我在做 AI 推理加速时,SVE2 的向量长度灵活性帮了大忙。
- 向量长度可变:128 位到 2048 位,步长 128 位。同一个二进制,在不同核心上自动适配。
- 谓词执行:每条向量指令都可以带一个谓词掩码,实现条件化运算。这比传统分支预测高效得多。
- 聚集/分散加载:支持非连续内存访问,处理稀疏数据时性能提升明显。
避坑指南:我曾经在一个项目中,直接用 NEON 指令优化图像处理算法。后来移植到支持 SVE2 的核上,发现向量化程度不够。SVE2 的编程模型和 NEON 完全不同,建议尽早用 arm_sve.h 头文件做开发。
1.2.2 CCA:机密计算架构
CCA 是 v9 在安全领域的杀手锏。TrustZone 把世界分成安全和非安全两个世界,但 CCA 更进一步——它允许在非安全世界中创建多个领域(Realm)。
每个 Realm 就像一个黑盒子。操作系统看不到 Realm 里的内容,Hypervisor 也看不到。只有 Realm 自己知道自己在干什么。
- 动态创建:Realm 可以在运行时创建和销毁。
- 硬件隔离:基于页表的二级地址转换,加上内存加密。
- 远程证明:Realm 可以向远程客户端证明自己的身份和完整性。
注意:CCA 需要硬件支持。目前只有 ARMv9.2 以上的核心才完整支持 CCA。如果你的芯片是 v9.0,只能使用 TrustZone,没有 Realm 功能。
1.2.3 52 位虚拟地址空间
这个特性其实 v8.2 就有了,但 v9 把它变成了标准配置。52 位虚拟地址意味着什么?
- 最大虚拟地址空间:2^52 = 4 PB
- 物理地址同样支持 52 位
- 页表层级从 3 级变成 4 级(或 5 级)
嗯,这里要注意:52 位地址不是默认开启的。你需要设置 TCR_ELx.TxSZ 字段,并且操作系统要支持大地址空间。我在调试一个数据库缓存系统时,48 位地址不够用,切换到 52 位后,问题迎刃而解。
1.3 AArch64 执行状态详解
AArch64 是 v8/v9 的 64 位执行状态。v9 只保留 AArch64,AArch32 被标记为 deprecated。我个人建议,新项目直接上 AArch64,别回头。
1.3.1 异常等级(Exception Levels)
AArch64 有 4 个异常等级,从 EL0 到 EL3。每个等级有独立的寄存器组和权限。
| 异常等级 | 运行模式 | 典型软件 | 权限 |
|---|---|---|---|
| EL0 | 用户态 | 应用程序 | 最低,不能访问系统寄存器 |
| EL1 | 内核态 | 操作系统内核 | 可管理内存、中断、进程 |
| EL2 | Hypervisor 态 | 虚拟机监视器 | 虚拟化扩展,控制虚拟机 |
| EL3 | 安全监控态 | Secure Monitor | 最高,控制安全状态切换 |
你想想看,这种分层设计让安全隔离变得非常自然。EL3 管安全,EL2 管虚拟化,EL1 管操作系统,EL0 跑应用。每一层都只能看到自己该看的东西。
1.3.2 寄存器模型
AArch64 有 31 个通用寄存器,X0-X30。每个都是 64 位。还有一堆系统寄存器,以 _ELx 结尾,表示它们属于哪个异常等级。
// 读取当前异常等级
mrs x0, CurrentEL
// x0 的低两位表示当前 EL
// 0b00 = EL0, 0b01 = EL1, 0b10 = EL2, 0b11 = EL3
// 设置中断掩码
msr DAIFSet, #0x0F // 屏蔽所有中断
我记得刚开始写 AArch64 汇编时,最不习惯的就是系统寄存器的命名。比如 TTBR0_EL1 是 EL1 的页表基址寄存器,TTBR0_EL2 是 EL2 的。名字一样,后缀不同,功能完全不同。写错一个,系统直接挂掉。
1.3.3 内存模型与页表
AArch64 使用 4KB 或 64KB 页。页表层级取决于地址宽度和页大小。
- 4KB 页 + 48 位地址:4 级页表(L0-L3)
- 4KB 页 + 52 位地址:5 级页表(L0-L4)
- 64KB 页 + 48 位地址:3 级页表(L0-L2)
页表项(PTE)包含物理地址、权限位、属性位。其中 XN(不可执行)和 PXN(特权不可执行)是安全关键位。我见过一个案例,有人把栈区域设成了可执行,结果被 ROP 攻击利用。所以,永远不要给数据区域设置可执行权限。
经验之谈:调试页表问题,我推荐用 readelf -l 查看段权限,用 cat /proc/self/maps 看进程地址空间。如果发现 rwx 的段,十有八九是配置错了。
1.4 ARMv9 知识体系总览
下面这张 SVG 图,把 v9 的核心知识点串起来了。你可以把它当作本章的思维导图。
1.5 从 v8 迁移到 v9:你需要知道的事
如果你手头有 v8 的项目要迁移到 v9,我建议你关注以下几点:
- 检查编译器支持:GCC 10+、LLVM 11+ 才支持 SVE2 和 CCA 指令。
- 更新启动代码:v9 的异常向量表格式和 v8 略有不同,主要是新增了
SError同步异常的处理。 - 重新配置 MMU:如果要用 52 位地址,页表层级和
TCR_ELx必须重新设置。 - 安全固件升级:CCA 需要 EL3 固件支持,建议使用 TF-A 2.6+ 版本。
重要提醒:不要以为 v8 的代码直接编译就能在 v9 上获得性能提升。SVE2 的向量化需要手动改写代码。我见过一个团队,把 v8 的 NEON 代码直接编译到 v9 上跑,性能反而下降了——因为编译器自动生成了 SVE2 指令,但数据布局没优化,导致 cache miss 严重。
1.6 本章小结
ARMv9 不是小修小补,而是面向未来十年的架构。SVE2 解决了向量化编程的碎片化问题,CCA 重新定义了云原生安全,AArch64 则统一了 64 位生态。
我个人觉得,v9 最值得投入精力的两个方向是:SVE2 的向量化优化和CCA 的 Realm 开发。前者能直接提升计算性能,后者能让你在安全领域建立技术壁垒。
好了,第一章就到这里。记住这张知识体系图,后面每一章都会围绕它展开。