ARM架构基础:处理器模式、异常模型、内存管理单元(MMU)、缓存与一致性基础
TrustZone 技术的本质是系统级隔离,它并非一个独立的硬件模块,而是深度嵌入 ARM 处理器的架构特性。要真正理解 TrustZone 如何实现安全世界与普通世界的隔离,必须先掌握 ARM 处理器的底层运行机制。本章将围绕四个核心支柱展开:处理器模式与异常模型(决定代码如何被调度和响应)、内存管理单元(决定地址如何被翻译和权限如何被检查)、缓存与一致性(决定数据在多核与内存间如何保持同步)。这四个部分共同构成了 TrustZone 安全扩展的硬件基础,也是后续编写 TEE 代码、配置安全世界内存时必须面对的底层约束。
2.1 处理器模式:特权级与状态保存
核心原理
ARM 处理器(Cortex-A 系列)采用模式(Mode)与异常级别(Exception Level)双重维度来管理特权。在 ARMv7 及更早架构中,处理器模式包括 USR(用户)、SVC(管理模式)、IRQ(中断)、FIQ(快速中断)、ABT(中止)、UND(未定义)、SYS(系统)等。进入 ARMv8 后,AArch64 架构引入了更清晰的异常级别模型:EL0(用户态)、EL1(内核态)、EL2(虚拟化)、EL3(安全固件)。TrustZone 正是利用 EL3 作为安全世界与普通世界的切换枢纽。
每个模式拥有独立的堆栈指针(SP)和保存程序状态寄存器(SPSR)。当异常发生时,处理器自动将当前 CPSR 保存到对应模式的 SPSR,并将返回地址保存到 LR(链接寄存器),然后切换到目标模式。这种机制保证了异常处理现场不会破坏用户态的状态。
判断方法
- 查看当前模式:读取 CPSR 的 M[4:0] 字段,例如 0b10000 表示 USR 模式,0b10011 表示 SVC 模式。
- 确认异常级别:在 AArch64 中,读取 CurrentEL 寄存器,返回 0/1/2/3 对应 EL0-EL3。
- 检查特权指令可用性:尝试执行 MSR/MRS 操作系统寄存器,若触发 UND 异常,则当前处于 EL0。
案例拆解:TEE 上下文切换
在 OP-TEE 中,当普通世界调用 SMC 指令时,CPU 从 EL1(普通世界内核)陷入 EL3(ATF 固件),ATF 保存普通世界上下文,然后切换到安全世界的 EL1。整个过程涉及两次模式切换:EL1→EL3→EL1(安全)。每次切换都需要保存通用寄存器、系统寄存器(如 TTBR0_EL1、SCTLR_EL1)以及栈指针。如果遗漏某个寄存器的保存,安全世界可能读取到普通世界的残留数据,造成信息泄漏。
stp 指令批量保存寄存器对,并确保 SPSR 中保存了完整的 PSTATE。调试时可通过 JTAG 读取 CurrentEL 和 SPSR_EL3 验证切换是否完整。
2.2 异常模型:向量表与同步/异步处理
核心原理
ARM 异常模型定义了处理器响应外部事件(中断、复位)或内部事件(未定义指令、SVC、SMC)的机制。异常向量表(Vector Table)位于内存固定地址(或由 VBAR 寄存器指定),每个异常类型对应一个入口。TrustZone 引入了一个新的异常类型——SMC(Secure Monitor Call),它只能在 EL3 被处理,是普通世界请求安全服务的唯一合法途径。
异常分为同步异常(与当前指令直接相关,如数据中止、未定义指令)和异步异常(外部中断 IRQ/FIQ)。在 TrustZone 中,FIQ 通常被配置为安全中断,用于安全世界内部的外设响应,而 IRQ 则用于普通世界。这种分配方式确保安全世界的中断不会被普通世界屏蔽。
操作流程:配置向量表
- 在启动代码中定义异常向量表,每个入口 16 字节对齐。
- 设置 VBAR_EL3 指向安全世界向量表,VBAR_EL1 指向普通世界向量表。
- 为 SMC 异常编写处理函数,解析参数并分发到对应 TEE 服务。
- 使用
eret指令从异常返回,恢复处理器状态。
常见误区
2.3 内存管理单元(MMU):地址翻译与权限控制
核心原理
MMU 负责将虚拟地址(VA)翻译为物理地址(PA),并执行内存访问权限检查。ARMv8 使用页表描述符中的多个字段控制访问:AP[2:1] 控制读写权限,UXN/PXN 控制执行权限,而最关键的是 NS(Non-Secure)位。NS 位决定了该物理地址属于安全世界还是普通世界。当 CPU 处于安全状态时,可以访问 NS=0 和 NS=1 的内存;当处于普通世界时,只能访问 NS=1 的内存。这是 TrustZone 内存隔离的基石。
MMU 还通过 TCR(Translation Control Register)配置页表基地址、粒度大小(4K/16K/64K)以及地址空间划分。MAIR(Memory Attribute Indirection Register)定义内存属性(如 Device-nGnRnE、Normal Write-Back),用于控制缓存策略。
判断方法:检查页表配置
| 寄存器 | 字段 | 作用 | TrustZone 相关 |
|---|---|---|---|
| TTBR0_EL1 | BADDR | 用户空间页表基址 | 普通世界 EL0/EL1 |
| TTBR1_EL1 | BADDR | 内核空间页表基址 | 普通世界内核 |
| TTBR0_EL3 | BADDR | 安全固件页表 | EL3 代码 |
| MAIR_EL1 | Attr | 内存属性编码 | 配置 Normal/Device 区域 |
案例拆解:安全内存隔离配置
假设我们需要在安全世界中保留 4MB 的 SRAM(地址 0x2E000000),并在普通世界中不可见。操作步骤如下:
- 在安全世界页表中,将该区域映射为 NS=0,AP=0b00(EL1 读写),MAIR 属性为 Normal Write-Back。
- 在普通世界页表中,不建立该区域的映射,或将其映射为 Fault 条目。
- 配置 TZASC(TrustZone Address Space Controller)将该物理地址段标记为安全,即使普通世界通过 MMU 访问也会被总线拒绝。
2.4 缓存与一致性:多核环境下的数据同步
核心原理
现代 ARM 处理器采用多级缓存架构:L1 是私有缓存(每个核心独有),L2 是共享缓存(通常一组核心共享),L3 可选。缓存以 Cache Line(通常 64 字节)为粒度工作。TrustZone 的引入带来了新的挑战:安全世界和普通世界共享同一套缓存物理资源,但逻辑上需要隔离。如果安全世界的数据残留在缓存中,普通世界通过缓存探测攻击可能获取敏感信息。
ARM 通过缓存维护操作(Clean/Invalidate)和一致性协议(MESI/MOESI)来管理数据同步。在 TrustZone 切换时,软件必须执行缓存清理操作,确保安全世界的数据不会泄漏到普通世界。此外,多核系统中,SCU(Snoop Control Unit)或 CCI(Cache Coherent Interconnect)负责维护各核心缓存的一致性。
操作流程:安全上下文切换时的缓存维护
// 伪代码:切换到安全世界前
DSB SY; // 确保所有内存访问完成
DC CIVAC, x0; // Clean and Invalidate by VA to PoC
DSB SY;
// 切换到普通世界前
DC CISW, x0; // Clean and Invalidate by Set/Way
DSB SY;
ISB; // 指令同步屏障
常见误区与复盘
DC CIVAC 操作所有相关地址,或者通过 CCI 的广播清理功能。否则,普通世界核心可能从 L2 缓存中读取到安全世界的残留数据。
另一个常见问题是缓存一致性协议与 TrustZone 的交互。当安全世界修改了某块内存,而普通世界的缓存中仍有旧副本时,如果普通世界直接读取,会得到过期数据。因此,在共享内存(通过 SMC 传递的缓冲区)场景中,双方都需要执行缓存清理操作。
2.5 综合案例:基于 TrustZone 的安全启动流程
将上述知识整合,我们来看一个典型的安全启动流程:
- ROM 代码(EL3):上电后 CPU 进入 EL3,配置 MMU 映射安全 ROM 和 SRAM,设置向量表。
- 加载 ATF(EL3):验证 BL31 镜像签名,加载到安全内存,跳转执行。
- 初始化 TZASC:配置内存区域安全属性,将 TEE 内存标记为安全。
- 切换到普通世界:ATF 设置 EL1 的页表和向量表,执行
eret进入普通世界 U-Boot。 - 普通世界启动内核:内核运行在 EL1,通过 SMC 调用安全世界服务(如密钥管理)。
整个流程中,每一步都依赖处理器模式切换、异常处理、MMU 配置和缓存维护。任何一个环节的疏漏都可能导致安全启动失败或信息泄漏。
info registers 观察模式切换,并通过 pagewalk 命令检查页表 NS 位,加深理解。