3. ARM架构与TrustZone扩展
TrustZone 并不是一颗独立的安全芯片,而是 ARM 处理器在架构层面提供的一套安全扩展。理解它,必须先把三个基础概念串起来:处理器所处的执行状态(AArch32/AArch64)、控制安全世界切换的寄存器(SCR 等)、以及触发世界切换的指令(SMC)。这三者共同支撑起 Monitor 模式这一“安全世界与普通世界之间的守门人”。
一、核心原理:两种执行状态与四个异常等级
ARMv8 引入了 AArch64 与 AArch32 两种执行状态。AArch64 是 64 位执行环境,拥有 31 个通用寄存器(X0–X30)、独立的 SP/PC,异常等级为 EL0–EL3。AArch32 则兼容经典 ARMv7 的 32 位执行环境,异常等级映射为 PL0–PL3。TrustZone 的安全扩展在两种状态下都存在,但寄存器命名和切换细节不同。
关键点在于:安全世界与普通世界并不是两个 CPU,而是同一颗 CPU 在时间上分时复用。CPU 通过 SCR(Secure Configuration Register)等寄存器决定“当前处于哪个世界”,并通过 Monitor 模式完成切换。异常等级 EL3(AArch64)或 Monitor 模式(AArch32)是唯一能同时访问安全与普通资源的特权层级。
二、SCR 寄存器:安全世界的配置开关
SCR 是 CP15 协处理器寄存器(AArch32 中为 SCR,AArch64 中对应 SCR_EL3),它决定了 CPU 进入 Monitor 后如何对待两个世界。常用位段如下:
| 位段 | 名称 | 作用 |
|---|---|---|
| bit0 | NS | 当前世界标志:0=安全,1=普通 |
| bit1 | IRQ | 在 Monitor 中是否屏蔽 IRQ |
| bit2 | FIQ | 在 Monitor 中是否屏蔽 FIQ |
| bit3 | EA | 外部中止路由 |
| bit4 | FW | FIQ 是否路由到 Monitor |
| bit5 | AW | 异步中止路由 |
| bit6 | nET | 是否允许普通世界访问 CP15 部分寄存器 |
| bit7 | SCD | 是否禁用 SMC 指令 |
| bit8 | HCE | 是否启用 Hyp 调用 |
其中 NS 位是最直观的“世界指示器”。当 CPU 从普通世界通过 SMC 进入 Monitor 时,硬件会自动把 NS 置 1;返回安全世界时清 0。固件在 Monitor 中读取 SCR.NS 即可判断调用来源,从而决定是否允许本次服务请求。
三、SMC 指令与 Monitor 模式:世界切换的入口
SMC(Secure Monitor Call)是专门用于触发世界切换的指令。在 AArch32 中写作 SMC #imm,在 AArch64 中写作 SMC #imm16。它产生一个同步异常,把 CPU 送入 EL3/Monitor,由 Monitor 中的异常向量表接管。
; AArch32 示例:从普通世界请求安全服务
MOV r0, #0x84000000 ; SMC 功能号(如 PSCI 版本查询)
SMC #0 ; 触发进入 Monitor
; 返回后 r0 中为安全世界返回结果
// AArch64 示例
MOV x0, #0xC4000000 // SMC 调用号
SMC #0 // 进入 EL3
// 返回后 x0 保存结果
Monitor 模式(AArch32)或 EL3(AArch64)是切换的“中转站”。它保存当前世界的上下文,根据调用号分发到安全服务,再恢复目标世界上下文并返回。典型流程为:普通世界发起 SMC → 硬件切到 Monitor → 保存普通世界上下文 → 读取 SCR.NS 与调用号 → 执行安全服务 → 恢复上下文 → 返回普通世界。
四、AArch32 与 AArch64 的差异对照
移植过程中最容易踩坑的地方,就是两种执行状态下寄存器与异常模型的差异。下表给出关键对照:
| 维度 | AArch32 | AArch64 |
|---|---|---|
| 异常等级 | PL0–PL3 | EL0–EL3 |
| 安全监控层 | Monitor 模式(PL3) | EL3 |
| SCR 寄存器 | CP15 SCR | SCR_EL3 |
| SMC 指令 | SMC #imm | SMC #imm16 |
| 通用寄存器 | R0–R15 | X0–X30 + SP/PC |
| 异常向量基址 | VBAR(CP15) | VBAR_EL3 |
| 典型调用号 | 0x84000000 段 | 0xC4000000 段 |
五、典型场景:一次安全服务调用的完整路径
- 普通世界内核(EL1)准备参数,执行
SMC #0。 - 硬件保存 PSTATE 与返回地址到 ELR_EL3/SPSR_EL3,跳转到 EL3 异常向量。
- Monitor 读取 ESR_EL3 确认异常类型为 SMC,读取 SCR_EL3.NS 确认来自普通世界。
- 根据 X0 中的调用号,分发到对应安全服务处理函数。
- 服务完成后,Monitor 恢复普通世界上下文,执行
ERET返回 EL1。
六、常见误区与复盘
- 误区一:把 Monitor 当成一个独立 CPU。 它只是同一 CPU 的特权模式,切换靠硬件上下文保存,不是多核并行。
- 误区二:认为 AArch64 下没有 Monitor。 EL3 就是 AArch64 的 Monitor,功能等价,只是命名和寄存器不同。
- 误区三:忽略 SCR.NS 的硬件自动更新。 软件不应手动改 NS 位来“假装”切换世界,必须通过 SMC/ERET 由硬件完成。
- 误区四:SMC 调用号混用。 AArch32 与 AArch64 的 SMC 调用号段不同,移植时需同步修改调用方与被调用方。
掌握 AArch32/AArch64 的状态差异、SCR 寄存器的位定义、SMC 指令的触发机制以及 Monitor/EL3 的中转职责,是后续进行 TrustZone 平台移植与故障调试的基石。只有先看清“世界如何切换”,才能在日志与异常向量中找到真正的故障点。