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)是唯一能同时访问安全与普通资源的特权层级。

核心记忆:EL0/PL0 应用 → EL1/PL1 内核 → EL2 虚拟化 → EL3/Monitor 安全监控。TrustZone 的“开关”就在 EL3/Monitor。

二、SCR 寄存器:安全世界的配置开关

SCR 是 CP15 协处理器寄存器(AArch32 中为 SCR,AArch64 中对应 SCR_EL3),它决定了 CPU 进入 Monitor 后如何对待两个世界。常用位段如下:

位段名称作用
bit0NS当前世界标志:0=安全,1=普通
bit1IRQ在 Monitor 中是否屏蔽 IRQ
bit2FIQ在 Monitor 中是否屏蔽 FIQ
bit3EA外部中止路由
bit4FWFIQ 是否路由到 Monitor
bit5AW异步中止路由
bit6nET是否允许普通世界访问 CP15 部分寄存器
bit7SCD是否禁用 SMC 指令
bit8HCE是否启用 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 与调用号 → 执行安全服务 → 恢复上下文 → 返回普通世界。

TrustZone 世界切换与 Monitor 模式 普通世界 Normal World EL0/PL0 应用 EL1/PL1 普通 OS 内核 SCR.NS = 1 发起 SMC 请求安全服务 安全世界 Secure World EL0/PL0 可信应用 TA EL1/PL1 安全 OS / TEE SCR.NS = 0 处理安全服务并返回 Monitor 模式 / EL3 异常向量表 · 上下文保存/恢复 读取 SCR.NS 判断来源 按 SMC 调用号分发服务 唯一可访问两个世界的特权层 SMC #0 切换 NS=0 返回 恢复 NS=1 SMC 是唯一软件触发的世界切换入口;SCR.NS 是硬件维护的世界标志位

四、AArch32 与 AArch64 的差异对照

移植过程中最容易踩坑的地方,就是两种执行状态下寄存器与异常模型的差异。下表给出关键对照:

维度AArch32AArch64
异常等级PL0–PL3EL0–EL3
安全监控层Monitor 模式(PL3)EL3
SCR 寄存器CP15 SCRSCR_EL3
SMC 指令SMC #immSMC #imm16
通用寄存器R0–R15X0–X30 + SP/PC
异常向量基址VBAR(CP15)VBAR_EL3
典型调用号0x84000000 段0xC4000000 段

五、典型场景:一次安全服务调用的完整路径

  1. 普通世界内核(EL1)准备参数,执行 SMC #0。
  2. 硬件保存 PSTATE 与返回地址到 ELR_EL3/SPSR_EL3,跳转到 EL3 异常向量。
  3. Monitor 读取 ESR_EL3 确认异常类型为 SMC,读取 SCR_EL3.NS 确认来自普通世界。
  4. 根据 X0 中的调用号,分发到对应安全服务处理函数。
  5. 服务完成后,Monitor 恢复普通世界上下文,执行 ERET 返回 EL1。
调试技巧:若 SMC 调用后系统挂死,优先检查 EL3 向量表是否正确安装、SCR_EL3 是否被误配置为屏蔽 SMC(SCD 位),以及调用号是否落在安全服务已注册的范围内。

六、常见误区与复盘

  • 误区一:把 Monitor 当成一个独立 CPU。 它只是同一 CPU 的特权模式,切换靠硬件上下文保存,不是多核并行。
  • 误区二:认为 AArch64 下没有 Monitor。 EL3 就是 AArch64 的 Monitor,功能等价,只是命名和寄存器不同。
  • 误区三:忽略 SCR.NS 的硬件自动更新。 软件不应手动改 NS 位来“假装”切换世界,必须通过 SMC/ERET 由硬件完成。
  • 误区四:SMC 调用号混用。 AArch32 与 AArch64 的 SMC 调用号段不同,移植时需同步修改调用方与被调用方。
在 32 位与 64 位混合系统中,普通世界可能是 AArch32,而安全世界运行 AArch64。此时 SMC 调用约定、参数传递寄存器宽度、返回码编码都必须显式对齐,否则会出现“调用成功但返回值错乱”的隐蔽故障。

掌握 AArch32/AArch64 的状态差异、SCR 寄存器的位定义、SMC 指令的触发机制以及 Monitor/EL3 的中转职责,是后续进行 TrustZone 平台移植与故障调试的基石。只有先看清“世界如何切换”,才能在日志与异常向量中找到真正的故障点。