1. 安全世界初始化总览
1.1 TrustZone 架构概述
ARM TrustZone 是系统级安全扩展,将物理处理器和内存子系统划分为两个隔离的执行环境:安全世界(Secure World)和非安全世界(Normal World)。硬件强制隔离确保非安全世界无法直接访问安全世界资源,可信执行环境(TEE)运行在安全世界,提供密钥管理、安全存储、可信用户界面等核心服务。
| 特性 | 安全世界 | 非安全世界 |
|---|---|---|
| 运行环境 | 可信 OS(如 OP-TEE、Trusty) | 普通 OS(如 Linux、Android) |
| 内存保护 | NS 位=0,仅安全世界可访问 | NS 位=1,无法访问安全内存 |
| 中断模型 | FIQ 分配给安全世界 | IRQ 分配给非安全世界 |
| 外设访问 | 受 TrustZone Address Space Controller 保护 | 仅能访问非安全外设 |
| 启动顺序 | 先于非安全世界完成初始化 | 由安全世界启动并移交控制权 |
1.2 安全世界与非安全世界隔离
隔离机制由硬件和固件共同实现:
- 处理器扩展:增加安全状态位(NS位),记录当前执行环境;上下文切换由 Monitor 模式负责
- 内存系统:TZASC(TrustZone Address Space Controller)将内存划分为安全和非安全区域,地址访问被硬件阻断
- 总线与外设:AXI 总线增加安全信号线,外设通过配置被标记为安全或非安全
- 中断控制器:GIC 支持将中断配置为安全中断(FIQs)或非安全中断(IRQs)
实践经验:隔离的根基在于硬件强制,软件配置一旦固化(如TZASC锁定),非安全世界任何特权级都无法绕过。开发和调试需在安全世界完成初始配置后才释放非安全世界。
1.3 初始化流程核心步骤
安全世界初始化是系统上电后第一个软件执行阶段,必须在非安全世界获得 CPU 控制权之前完成。核心步骤包括:
- Boot ROM 加载安全引导加载程序:芯片内置 ROM 代码验证并加载 BL1(安全引导加载程序)
- 设置 ARM 安全监视器:配置 SCR(Secure Configuration Register),初始化 Monitor 模式向量表
- 配置 GIC 中断路由:将安全中断(FIQs)分配给安全世界,非安全中断(IRQs)给非安全世界
- 初始化 TZASC:划分安全和非安全物理内存区域,锁定配置
- 加载可信 OS 内核:从安全存储(如 eMMC 安全分区)加载 TEE OS 映像
- 启用异常处理与 IPC:建立安全监控调用接口(SMC),允许非安全世界安全调用
- 移交非安全世界:跳转到非安全世界入口,开始运行普通 OS/固件
架构关系与启动流向(图1-1)
下图展示 TrustZone 系统层次结构及安全世界初始化在整个启动流程中的位置。从 Boot ROM 开始,安全世界完成隔离配置后,非安全世界获得控制权运行 Linux/Android。
下图展示 TrustZone 系统层次结构及安全世界初始化在整个启动流程中的位置。从 Boot ROM 开始,安全世界完成隔离配置后,非安全世界获得控制权运行 Linux/Android。
严重警告:步骤 4(TZASC 配置)一旦完成并锁定,非安全世界无法再修改内存保护区域。若配置错误(如安全关键数据区域被标记为非安全),会导致安全漏洞或系统无法启动。调试阶段需要在锁定前验证所有地址范围。
1.4 关键寄存器配置
初始化过程中涉及的核心系统寄存器(以 Cortex-A 系列为例):
- SCR (Secure Configuration Register):位于协处理器 CP15,控制全局安全状态。必须设置
SCR.NS=0确保当前为安全世界;SCR.FIQ/SCR.IRQ位用于中断目标。 - VBAR (Vector Base Address Register):Monitor 模式向量表基址,必须指向安全监控调用(SMC)和异常入口。
- GICD_IGROUPRn:中断组寄存器,每 bit 对应一个中断 ID,0 为安全组,1 为非安全组。
- TZASC_REGION_ATTRIBUTES:配置各内存区域的基址、大小、安全/非安全属性及锁定位。
示例:SCR 寄存器典型配置
// ARMv7-A / Cortex-A15 安全初始化阶段
// 设置 SCR 前确保处于 Monitor 模式
MRS R0, SCR_NS ; 读取当前 SCR
BIC R0, R0, #1 ; 清除 NS 位 (Bit0) → 安全世界
ORR R0, R0, #(1<<1) ; 设置 FIQ 位 (Bit1) → FIQ 路由到安全世界
ORR R0, R0, #(1<<2) ; 设置 IRQ 位 (Bit2) → IRQ 路由到非安全世界 (可留空)
ORR R0, R0, #(1<<3) ; 设置 EA 位 (Bit3) → 外部中止路由到安全世界
MSR SCR_NS, R0 ; 写入生效
DSB ; 数据同步屏障,确保配置完成
ISB ; 指令同步屏障,刷新流水线
1.5 调试手段与常见错误
| 调试手段 | 适用阶段 | 说明 |
|---|---|---|
| JTAG/SWD 安全调试 | 初始开发 | 使用调试器连接安全世界内核,设置硬件断点观察寄存器与内存 |
| Semihosting 输出 | BL1/BL2阶段 | 通过调试通道打印安全固件日志,无需UART初始化 |
| GIC 状态轮询 | 初始化完成后 | 读取 GICD_ISPENDR 判断安全中断是否被正确配置 |
| 内存访问模式陷阱 | 集成阶段 | 故意访问安全内存区域并验证 Data Abort 是否由非安全世界触发 |
| TZASC 锁定状态检查 | 调试后期 | 读取 TZASC 锁定寄存器确认保护已生效 |
稳定与优化:确保安全世界初始化使用栈与数据段位于安全内存内部,否则写入非安全内存会被硬件阻断。抽离关键配置到结构体(如
struct tee_init_params)便于调整内存地址与中断路由参数,减少在汇编代码中硬编码维护的成本。