2. TrustZone基础概念

TrustZone 是 ARM 在 CPU 架构层面提供的一套硬件安全隔离机制。它并不是一个独立的协处理器或外挂安全芯片,而是把同一颗 CPU 的执行资源在时间维度上划分为两个相互隔离的世界:安全世界(Secure World)与非安全世界(Normal World / Non-secure World)。理解这两个世界的关系、切换方式以及它们与异常等级(Exception Level, EL)的对应关系,是后续平台移植与故障调试的根基。

一、核心原理:一个 CPU,两个世界

在 TrustZone 架构中,CPU 的每一条指令、每一次内存访问、每一个外设操作,都会携带一个安全状态位(NS bit)。这个位决定了当前访问是落在安全地址空间还是非安全地址空间。硬件通过总线上的 NS 信号,把访问请求路由到对应的内存控制器或外设控制器,从而实现物理层面的隔离。

两个世界各自拥有独立的软件栈:

  • 安全世界:运行安全操作系统(如 OP-TEE、Trusty)、安全监控器(Secure Monitor)以及可信应用(TA)。它掌握密钥、加解密引擎、安全存储等敏感资源。
  • 非安全世界:运行我们熟悉的 Rich OS,如 Linux、Android、RTOS。普通应用、驱动、内核都位于此世界,即使被攻破也无法直接读取安全世界的内存。

需要特别强调的是,两个世界共享同一套寄存器组和流水线,因此切换不是"换一颗 CPU",而是"换一套视图"。这也是 TrustZone 高效的原因,也是调试时容易混淆的根源。

二、安全状态切换:SMC 与 Monitor

安全世界与非安全世界之间的切换,必须经过一个受控的入口——安全监控器(Secure Monitor),它运行在最高的异常等级 EL3。切换的触发方式主要有三类:

  1. SMC 指令:非安全世界通过执行 SMC(Secure Monitor Call)指令主动请求安全服务,例如让 OP-TEE 执行一次加解密。
  2. 中断与异常:安全中断(如安全定时器、安全外设中断)可以抢占非安全世界的执行,进入安全世界处理。
  3. 硬件复位与启动:系统上电后通常先进入安全世界完成初始化,再跳转到非安全世界。

切换过程中,Monitor 负责保存当前世界的上下文(寄存器、栈指针、返回地址),并恢复目标世界的上下文。这个过程称为世界切换(World Switch)。下面是一段典型的 SMC 调用示意:

/* 非安全世界发起 SMC 调用 */
register uint32_t r0 asm("r0") = TA_CMD_ENCRYPT;
register uint32_t r1 asm("r1") = (uint32_t)input_buf;
register uint32_t r2 asm("r2") = (uint32_t)output_buf;

asm volatile(
    "smc #0\n"
    : "=r"(r0)
    : "r"(r0), "r"(r1), "r"(r2)
    : "memory");

/* 返回后 r0 为安全世界返回的结果码 */
if (r0 != 0) {
    log_error("SMC call failed: %u", r0);
}

从调试视角看,SMC 是排查"安全服务调用失败"的第一现场。若 SMC 返回错误码,问题可能出在参数传递、TA 未加载、或 Monitor 未正确配置。

三、异常等级与执行环境

ARMv8-A 定义了四个异常等级 EL0~EL3,TrustZone 与它们的关系如下表所示:

异常等级 典型执行环境 安全属性 说明
EL0 用户态应用 安全 / 非安全 权限最低,通过 SVC 进入内核
EL1 Rich OS 内核 / 安全 OS 内核 安全 / 非安全 操作系统内核,管理页表与中断
EL2 Hypervisor 通常非安全 虚拟化扩展,可选
EL3 Secure Monitor 安全 世界切换的唯一入口

可以看到,安全世界与非安全世界并不是简单的"两个 EL",而是横跨 EL0~EL3 的完整软件栈。安全世界可以拥有自己的 EL0 应用(TA)和 EL1 内核(TEE OS),非安全世界同样如此。EL3 则始终属于安全侧,是切换的仲裁者。

关键理解:安全状态(Secure/Non-secure)与异常等级(EL0~EL3)是两个正交的维度。同一个 EL1,既可能是 Linux 内核,也可能是 OP-TEE 内核,区别在于 NS 位。

四、场景案例:一次安全加解密请求的完整路径

假设 Android 应用需要调用 TEE 完成一次 AES 加密,其执行路径如下:

  1. 应用在 EL0(非安全)调用 TEE Client API,陷入 EL1 的 Linux 内核。
  2. Linux 驱动在 EL1(非安全)准备好共享内存,执行 SMC 指令。
  3. CPU 进入 EL3,Secure Monitor 保存非安全上下文,切换到安全世界。
  4. 安全世界在 EL1 运行 OP-TEE 内核,调度对应 TA 在 EL0(安全)执行加密。
  5. 加密完成后,TA 返回 OP-TEE 内核,再经 Monitor 切回非安全世界。
  6. Linux 驱动收到返回值,应用拿到密文。

这条路径中任何一环出错,都会表现为"调用超时"或"返回错误码"。调试时需要分别确认:SMC 是否被正确触发、Monitor 是否正常切换、TA 是否已加载、共享内存是否映射正确。

五、常见误区与复盘

误区一:认为安全世界是"另一颗 CPU"。实际上它是同一颗 CPU 的时间片切换,寄存器是共享的,切换时必须显式保存上下文。

误区二:认为非安全世界无法访问安全内存。硬件会拦截非法访问并触发异常,但若 TZASC/TZPC 配置错误,隔离可能失效,这是移植中最危险的配置项之一。

误区三:把 EL3 当成"非安全世界的最高级"。EL3 永远属于安全侧,非安全世界无法直接进入 EL3,只能通过 SMC 请求。

复盘时建议建立一张"世界—异常等级—软件组件"的对照表,把每个模块的 NS 位、EL 级别、入口指令都标注清楚。这样在遇到切换失败、TA 加载异常、中断丢失等问题时,可以快速定位是配置问题、上下文保存问题,还是隔离策略问题。

TrustZone 安全世界 / 非安全世界与异常等级 EL3 · Secure Monitor 世界切换唯一入口 · 保存/恢复上下文 安全世界 Secure World NS = 0 EL1 · TEE OS 内核 OP-TEE / Trusty 调度与内存管理 EL0 · 可信应用 TA 加解密 · 密钥管理 · 安全存储 安全资源 安全内存 · 加密引擎 · 安全外设 TZASC / TZPC 隔离控制 非安全世界 Non-secure World NS = 1 EL1 · Rich OS 内核 Linux / Android / RTOS EL0 · 普通应用 App · 驱动 · 服务 非安全资源 普通内存 · 通用外设 · 文件系统 无法直接访问安全资源 SMC 调用 切换进入 返回 切回 安全状态(NS 位)与异常等级(EL0–EL3)正交:同一 EL 可属于不同世界

掌握以上概念后,后续在移植 TEE OS、配置 TZASC、调试 SMC 调用时,就能清楚地知道每一步发生在哪个世界、哪个异常等级,从而把问题范围快速缩小到具体的软件模块或硬件配置上。