2. 基础知识:ARM体系结构基础

ARMv9架构作为当前Arm技术路线中的旗舰级设计,其体系结构基础决定了上层软件系统的运行方式与安全边界。理解指令集、异常模型、内存模型、寄存器组及特权级别这五大核心要素,是后续深入学习MMU、GIC、TrustZone与RME(Realm Management Extension)的必备前提。本章将从底层机制出发,结合AArch64执行状态,系统梳理这些基础概念,并建立它们之间的内在关联。

ARMv9体系结构基础核心关系图 特权级别 (EL0-EL3) 指令集 A64 / A32 / T32 异常模型 同步/异步 · 路由 内存模型 一致性 · 内存属性 寄存器组 通用/系统/VFP 关键关联逻辑: • 指令集决定可用的寄存器视图与异常返回行为(AArch64 ↔ AArch32 切换) • 异常模型依赖特权级别进行路由判定,EL3 拥有最高路由决策权 • 内存模型通过系统寄存器(如 MAIR_EL1、TCR_EL1)配置,与 MMU 协同工作 • 寄存器组中的 PSTATE 直接反映当前异常级别与执行状态

2.1 指令集:A64与执行状态切换

ARMv9架构的核心执行状态为AArch64,其对应的A64指令集采用固定32位编码,提供31个64位通用寄存器(X0-X30)以及专用的栈指针(SP)和程序计数器(PC)。A64指令集的设计强调低延迟异常处理与高效的加载/存储架构,所有数据处理操作均在寄存器中完成,内存访问仅通过显式的LDR/STR系列指令进行。

在兼容性方面,ARMv9保留了AArch32执行状态以支持存量32位软件。系统通过异常返回或异常进入时的SPSR_ELx.M字段实现两种执行状态的切换。例如,当EL0的32位应用触发系统调用(SVC #0)时,处理器切换到AArch64的EL1,异常返回时通过ERET指令恢复32位状态。这种设计使得SoC可以同时运行64位操作系统与32位遗留应用。

核心原理:A64指令集采用统一编码,简化了指令解码逻辑,使得超标量流水线可以更高效地并行发射指令。同时,A64取消了条件执行的普遍使用(仅保留少量条件指令如CSEL),减少了分支预测失败的开销,提升了高频运行时的能效比。

2.1.1 指令集对比与选择

特性A64 (ARMv8/9)A32 (ARMv7)T32 (Thumb-2)
指令长度固定32位固定32位16/32位混合
通用寄存器31×64位15×32位15×32位
条件执行仅少数指令几乎全部指令部分指令
PC访问不可直接读可读可读
适用场景现代OS、应用处理器传统应用、MCU代码密度敏感场景

2.2 异常模型:同步与异步的统一处理

ARMv9的异常模型将中断、陷阱、系统调用统一抽象为“异常”(Exception)。异常分为同步异常(如未定义指令、数据中止、SVC指令)和异步异常(如IRQ、FIQ、SError)。所有异常都通过异常向量表(Vector Table)分发,向量表基地址由VBAR_ELx寄存器指定,每个异常级别拥有独立的向量表。

异常进入时,处理器自动保存当前状态到SPSR_ELx,将返回地址存入ELR_ELx,并根据异常类型跳转到对应向量偏移。异常返回使用ERET指令,该指令同时完成PC恢复与PSTATE恢复。值得注意的是,ARMv9引入了异常路由机制:EL3(Secure Monitor)可以配置中断路由策略,例如将FIQ强制路由到EL3,用于实现安全世界与普通世界之间的快速切换。

实战场景:在系统启动阶段,ATF(Arm Trusted Firmware)运行在EL3,通过配置SCR_EL3寄存器中的IRQ/FIQ路由位,决定中断是直接进入EL3还是被屏蔽到EL1。例如,当启用Secure-EL1的定时器中断时,需要将FIQ路由到EL3,再由EL3转发到S-EL1,确保安全世界的中断不被普通世界抢占。

2.2.1 异常向量表布局

// 每个异常级别(EL0-EL3)的向量表共16个条目,每个条目占128字节
// 偏移布局如下:
// 0x000: SP_EL0 同步异常
// 0x080: SP_EL0 IRQ
// 0x100: SP_EL0 FIQ
// 0x180: SP_EL0 SError
// 0x200: SP_ELx 同步异常
// 0x280: SP_ELx IRQ
// 0x300: SP_ELx FIQ
// 0x380: SP_ELx SError
// 0x400: 低EL AArch64 同步异常
// 0x480: 低EL AArch64 IRQ
// 0x500: 低EL AArch64 FIQ
// 0x580: 低EL AArch64 SError
// 0x600: 低EL AArch32 同步异常
// 0x680: 低EL AArch32 IRQ
// 0x700: 低EL AArch32 FIQ
// 0x780: 低EL AArch32 SError

2.3 内存模型:从单核到多核一致性

ARMv9内存模型定义了处理器对内存访问的观测顺序与一致性规则。其核心是弱内存模型(Weakly Ordered),即在不违反数据依赖关系的前提下,允许处理器和编译器重排内存访问指令。为了在弱模型下保证正确性,ARM提供了内存屏障指令(DMB、DSB、ISB)以及获取/释放语义的原子指令(LDXR/STXR、CAS)。

内存属性通过页表项中的属性字段配置,包括缓存策略(Write-Back/Write-Through)、共享属性(Non-shareable/Inner-shareable/Outer-shareable)以及执行权限(XN位)。多核系统中,处理器通过缓存一致性协议(如MESI)维护共享数据的一致性,而内存模型则定义了不同共享域之间的同步语义。

常见误区:许多开发者误以为ARMv9内存模型与x86完全一致,从而在编写无锁数据结构时省略屏障。实际上,ARM允许存储指令在加载指令之前完成(StoreLoad重排),这与x86的TSO模型有本质区别。必须使用LDAR/STLR或显式屏障来保证顺序。

2.3.1 内存属性配置示例

MAIR索引属性典型用途
0x00Device-nGnRnE外设寄存器(UART、GIC)
0x04Normal Non-cacheableDMA描述符
0x44Normal Write-Back常规RAM
0xffNormal Write-Through帧缓冲(部分场景)

2.4 寄存器组:通用、系统与状态寄存器

AArch64架构提供31个64位通用寄存器(X0-X30),其中X30作为链接寄存器(LR)保存函数返回地址。此外,系统寄存器(System Registers)通过MRS/MSR指令访问,用于配置MMU、异常、调试等核心功能。每个异常级别拥有独立的系统寄存器视图,例如TCR_EL1与TCR_EL2分别控制EL1/EL0和EL2/EL1的地址翻译配置。

状态寄存器PSTATE并非一个物理寄存器,而是由多个字段组成的抽象视图,包括条件标志位(NZCV)、当前异常级别(EL)、执行状态(AArch64/AArch32)以及中断屏蔽位(DAIF)。异常进入时,PSTATE被保存到SPSR_ELx;异常返回时,ERET从SPSR_ELx恢复PSTATE。

案例拆解:以Linux内核上下文切换为例,当CPU从用户态(EL0)进入内核态(EL1)时,硬件自动保存ELR_EL1(用户PC)和SPSR_EL1(用户PSTATE)。内核软件负责保存被调用者保存寄存器(X19-X28、FP、LR)到当前任务的栈中。切换任务时,内核更新SP_EL1指向新任务的栈,并通过ERET返回用户态。整个过程涉及通用寄存器、系统寄存器(TTBR0_EL1用于用户地址空间)和PSTATE的协同操作。

2.5 特权级别:安全世界的分层与隔离

ARMv9定义了四个异常级别(EL0-EL3),其中EL0为用户态,EL1为操作系统内核,EL2为虚拟化层(Hypervisor),EL3为安全监控器(Secure Monitor)。EL0-EL2在普通世界(Normal World)运行,而EL3负责在普通世界与安全世界(Secure World)之间切换。安全世界拥有独立的EL0/EL1,运行可信固件与安全服务。

特权级别的核心价值在于隔离:低特权级别无法直接访问高特权级别的资源,所有跨级别操作必须通过异常进入。例如,EL0应用无法直接操作MMU配置,必须通过SVC指令陷入EL1内核。ARMv9的RME扩展进一步引入了Realm Management Extension,在EL2之下新增了R-EL2级别,用于保护机密计算场景中的Realm世界。

判断方法:在调试系统时,可通过读取CurrentEL系统寄存器判断当前异常级别。例如,在U-Boot或ATF中打印CurrentEL的值,若为0b01表示EL1,0b10表示EL2,0b11表示EL3。这有助于确认固件是否运行在预期的特权级别。

2.5.1 特权级别与典型软件栈

异常级别典型软件主要职责
EL0应用程序用户逻辑、不直接访问硬件
EL1Linux/RTOS内核进程调度、内存管理、驱动
EL2Hypervisor (KVM/Xen)虚拟CPU调度、内存虚拟化
EL3ATF (BL31)安全世界切换、PSCI电源管理

2.6 综合案例:系统启动时的特权级别迁移

以ARMv9应用处理器启动流程为例,系统上电后首先在EL3执行ROM代码,随后加载ATF BL31到EL3。BL31初始化安全世界环境后,通过ERET降级到EL2执行Hypervisor或直接降级到EL1执行内核。内核启动过程中,通过配置SCR_EL3允许EL1访问必要的系统寄存器,并设置VBAR_EL1指向内核异常向量表。

当用户态应用需要读取硬件信息时,执行SVC #0指令,处理器陷入EL1,内核根据SVC编号分发处理。若需要与安全世界通信,内核通过SMC指令陷入EL3,由BL31切换到安全世界执行可信服务。整个过程体现了异常模型、特权级别与寄存器组的紧密协作。

风险提示:在自定义固件开发中,若错误配置SCR_EL3的NS位,可能导致安全世界与普通世界的内存映射混淆,引发严重的安全漏洞。务必在切换世界之前,确保MMU页表与缓存状态完全隔离。

2.7 总结与常见误区复盘

本章系统梳理了ARMv9体系结构的五大基础模块。在实际开发中,常见误区包括:混淆AArch64与AArch32的寄存器视图、忽略内存屏障导致的数据竞争、错误配置异常向量表基地址、以及在EL3代码中直接访问EL1专用寄存器。建议开发者始终从特权级别视角审视代码路径,明确当前执行上下文,并利用ARM架构参考手册中的伪代码验证关键操作。

复盘要点:① 指令集决定寄存器宽度与异常行为;② 异常模型是跨特权级别交互的唯一通道;③ 内存模型需要显式同步机制保证多核正确性;④ 寄存器组是软硬件交互的接口;⑤ 特权级别是安全隔离的基石。掌握这五点,即可为后续学习MMU、GIC与RME打下坚实基础。