3、硬件隔离机制:系统总线与AXI总线中的安全属性、TZASC与TZMA控制器

好,咱们进入第三章节。前面聊了TrustZone的基本概念和软件视图,今天要深入到底层——硬件是怎么把「安全」和「非安全」这两个世界真正隔开的。

说白了,TrustZone的隔离不是靠软件魔法,而是靠硬件总线上的「安检员」。这个安检员就是系统总线和AXI总线上的安全属性信号,以及两个关键控制器:TZASC和TZMA。我当年第一次调TZASC的时候,因为配错了一个地址窗口,导致安全世界访问非安全内存直接挂死……嗯,从那以后我再也不敢小看这些寄存器了。

3.1 AXI总线上的安全属性:NS位与安全信号

ARM的AMBA AXI总线是SoC内部的主干道。TrustZone在AXI总线上增加了一组关键信号,用来标记每一次总线事务的安全属性。

核心就一个信号:AxPROT[1],也就是我们常说的NS位(Non-Secure bit)。

  • AxPROT[1] = 0:表示当前事务是安全(Secure)访问。
  • AxPROT[1] = 1:表示当前事务是非安全(Non-Secure)访问。

你想想看,CPU发起一次读内存操作,这个NS位就跟着地址和控制信号一起,沿着总线一路传到内存控制器。沿途所有的总线组件——互连、桥接、外设——都会检查这个位。

关键理解:TrustZone的隔离本质上是「事务级」的。不是靠物理上多一套总线,而是在每笔事务上打上安全标签。这个标签从源头(CPU/GPU/DMA)一直传递到终点(内存/外设)。

除了AxPROT[1],还有另外两个位也值得注意:

信号位 含义 说明
AxPROT[0] Data/Opcode 0=操作码获取,1=数据访问
AxPROT[1] Secure/Non-Secure 0=安全,1=非安全
AxPROT[2] Privileged/User 0=特权,1=用户

这三个位组合起来,可以描述8种不同的访问类型。但在TrustZone语境下,最重要的还是AxPROT[1]。

3.2 系统总线中的安全域划分

有了NS位,系统总线就能实现「安全域」的划分。一个典型的SoC总线拓扑中,会有多个主设备(Masters)和多个从设备(Slaves)。

主设备包括:

  • CPU核心(每个核心有独立的NS位)
  • GPU
  • DMA控制器
  • 显示控制器
  • USB/以太网等高速外设

从设备包括:

  • 内存控制器(DRAM)
  • 片上SRAM
  • 各种外设寄存器空间

总线互连(NIC-400/CCI-500等)会检查每个主设备发起的NS位,并根据配置决定是否允许该事务通过。我见过一个坑:某个DMA控制器被配置成「始终非安全」,结果安全世界的加密引擎想通过DMA搬运数据,直接被总线拒绝了。后来加了一个AXI-APB桥接的安全配置才搞定。

注意:不是所有主设备都能自由切换安全状态。有些硬件模块(比如某些老旧的DMA控制器)的NS位是硬连线的,无法通过软件修改。设计时一定要确认每个主设备的安全能力。

3.3 TZASC:TrustZone地址空间控制器

TZASC(TrustZone Address Space Controller)是TrustZone硬件隔离的核心组件。它负责对内存区域进行安全属性的划分。

你可以把TZASC想象成一个「带安检的内存分区管理员」。它把物理内存分成若干个区域(Region),每个区域可以独立配置安全属性。

3.3.1 TZASC的工作原理

TZASC挂在系统总线和内存控制器之间。每次内存访问请求到达TZASC时,它会做两件事:

  1. 地址匹配:检查目标地址落在哪个Region中。
  2. 权限检查:根据该Region的安全配置,判断当前事务的NS位是否允许通过。

如果检查通过,事务继续发往内存控制器。如果不通过,TZASC会返回一个错误响应(SLVERR或DECERR),CPU会触发Data Abort异常。

个人经验:调试TZASC配置时,我习惯先配一个「全开放」的Region做验证,确认系统能正常启动。然后再逐步收紧权限。否则一上来就配错,系统直接挂死,连调试入口都没有。

3.3.2 TZASC的典型配置

以ARM的TZC-400为例,它支持最多8个Region。每个Region的配置包括:

配置项 说明 典型值
Region基地址 Region的起始地址 0x80000000
Region大小 Region的地址范围 0x10000000 (256MB)
安全属性 Secure/Non-Secure/混合 Secure
子区域过滤 按子区域粒度控制 使能/禁用
访问权限 读/写/执行 读+写

一个典型的安全内存布局可能是这样的:

Region 0: 0x80000000 - 0x8FFFFFFF  (非安全, 256MB)  // 普通操作系统
Region 1: 0x90000000 - 0x90FFFFFF  (安全,   16MB)   // 安全世界代码
Region 2: 0x91000000 - 0x91FFFFFF  (安全,   16MB)   // 安全数据
Region 3: 0x92000000 - 0x92FFFFFF  (非安全, 16MB)   // 共享缓冲区

3.3.3 子区域过滤(Subregion Filter)

TZASC还支持子区域过滤。每个Region可以分成8个等大小的子区域,每个子区域可以独立配置安全属性。这个功能在需要精细控制内存权限时非常有用。

举个例子:一个256MB的Region,分成8个32MB的子区域。你可以让前4个子区域是安全的,后4个是非安全的。这样就不用拆成多个Region了。

避坑指南:子区域过滤的粒度是Region大小的1/8。如果Region是1MB,子区域就是128KB。但有些SoC的实现有最小粒度限制(比如64KB)。我曾经在某个平台上配了一个4KB的子区域,结果TZASC直接忽略了配置——因为它不支持那么细的粒度。一定要查芯片手册!

3.4 TZMA:TrustZone内存适配器

TZMA(TrustZone Memory Adapter)是TZASC的「轻量版」。它专门用于片上SRAM的安全隔离。

为什么需要TZMA?因为片上SRAM通常没有复杂的总线接口,直接挂TZASC太浪费。TZMA提供了一个更简单的接口,只支持将SRAM分成两个区域:安全区和非安全区。

3.4.1 TZMA的工作原理

TZMA的核心是一个大小配置寄存器。它定义了SRAM中安全区域的大小。比如:

  • SRAM总大小:256KB
  • 安全区域大小:64KB(地址范围:0x2E000000 - 0x2E00FFFF)
  • 非安全区域大小:192KB(地址范围:0x2E010000 - 0x2E03FFFF)

安全区域只能被安全事务访问。非安全区域可以被安全和非安全事务访问。

对比一下:

  • TZASC:支持多个Region,粒度细,配置灵活,适合DRAM。
  • TZMA:只支持两个区域(安全/非安全),配置简单,适合SRAM。

3.4.2 TZMA的配置示例

假设我们有一个256KB的片上SRAM,基地址为0x2E000000。我们希望将前64KB作为安全内存,后192KB作为非安全内存。

// 伪代码:配置TZMA
#define TZMA_BASE        0x2E000000
#define TZMA_SIZE_REG    (TZMA_BASE + 0x000)  // 大小配置寄存器

// 设置安全区域大小为64KB
// 具体位域定义请参考芯片手册
write_reg(TZMA_SIZE_REG, 0x40);  // 0x40 = 64KB

配置完成后:

  • 安全世界可以访问0x2E000000 - 0x2E03FFFF(整个SRAM)
  • 非安全世界只能访问0x2E010000 - 0x2E03FFFF(后192KB)

3.5 硬件隔离的整体流程

咱们把整个流程串起来看看。当安全世界想读取一段加密数据时:

  1. CPU发起一次AXI读事务,AxPROT[1] = 0(安全)。
  2. 事务经过系统总线互连,互连检查NS位,确认是安全事务。
  3. 事务到达TZASC,TZASC检查目标地址落在哪个Region。
  4. 如果目标地址在安全Region中,TZASC放行,事务到达内存控制器。
  5. 内存控制器返回数据,原路返回给CPU。

如果非安全世界试图访问同一段安全内存:

  1. CPU发起AXI读事务,AxPROT[1] = 1(非安全)。
  2. 事务到达TZASC,TZASC检查发现目标地址在安全Region中。
  3. TZASC返回错误响应(DECERR)。
  4. CPU触发Data Abort异常,非安全世界的操作系统崩溃或收到SIGSEGV。

你看,整个过程不需要软件干预,完全由硬件自动完成。这就是TrustZone「硬件隔离」的精髓。

我个人的调试习惯:在系统刚启动时,我会在安全监控模式(Monitor Mode)下打印TZASC和TZMA的配置寄存器,确认硬件隔离已经生效。然后再切换到非安全世界,尝试访问安全内存,验证是否真的会触发异常。这一步虽然简单,但能避免很多后期调试的噩梦。

3.6 本章小结

硬件隔离是TrustZone的基石。AXI总线上的NS位是安全标签的载体,TZASC和TZMA是执行安全策略的「守门员」。理解这些硬件机制,你才能真正掌握TrustZone的隔离原理。

下一章我们会深入软件层面,看看安全世界和非安全世界是如何通过Monitor模式切换的。但今天先把硬件基础打牢——相信我,后面调驱动的时候,你会感谢今天认真看TZASC配置的自己。

TrustZone硬件隔离核心逻辑 TrustZone 硬件隔离核心逻辑 主设备 CPU Core GPU DMA AxPROT[1] = 0/1 系统总线互连 NIC-400 / CCI-500 检查NS位 TZASC 地址空间控制器 Region 0: 非安全 Region 1: 安全 Region 2: 安全 内存控制器 DRAM / SRAM 安全区 + 非安全区 TZMA 片上SRAM隔离 核心流程 1. 主设备发起事务 2. 总线检查NS位 3. TZASC/TZMA裁决