ARMv8-A架构基础:AArch64与AArch32执行状态、异常等级与安全世界切换
ARMv8-A架构是TrustZone技术的核心硬件基础。理解AArch64与AArch32两种执行状态、异常等级(Exception Levels, EL0-EL3)以及安全世界与非安全世界之间的切换机制,是掌握TrustZone安全隔离原理的必修课。本章将系统梳理这些基础概念,并通过结构图与表格帮助建立清晰的架构认知。
2.1 执行状态:AArch64与AArch32
ARMv8-A架构引入了两种执行状态,分别对应不同的指令集和寄存器模型:
- AArch64:64位执行状态,使用64位通用寄存器(X0-X30),支持A64指令集。地址空间可达64位,但实际实现通常使用48位或52位虚拟地址。
- AArch32:32位执行状态,兼容ARMv7-A的32位寄存器模型(R0-R15),支持A32(ARM)和T32(Thumb)指令集。地址空间为32位。
关键点:AArch64和AArch32是两种独立的执行状态,而非简单的“64位模式”与“32位模式”。处理器在复位时默认进入AArch64状态,但可以通过异常等级切换在两种状态之间迁移。
| 特性 | AArch64 | AArch32 |
|---|---|---|
| 寄存器宽度 | 64位通用寄存器(X0-X30) | 32位通用寄存器(R0-R14) |
| 指令集 | A64(固定32位指令) | A32(32位)/ T32(16/32位混合) |
| 异常等级支持 | EL0-EL3全部支持 | EL0-EL3全部支持 |
| 虚拟地址宽度 | 最多52位(典型48位) | 32位 |
| TrustZone支持 | 原生支持 | 原生支持 |
| 兼容性 | 全新64位软件栈 | 向后兼容ARMv7-A软件 |
实战提示:在TrustZone开发中,安全世界通常运行在AArch64状态以利用更大的地址空间和更强的隔离特性,但非安全世界可以混合运行AArch64和AArch32的应用程序。
2.2 异常等级(Exception Levels, EL0-EL3)
ARMv8-A定义了四个异常等级,用于实现不同特权级别的软件隔离。每个异常等级对应不同的执行权限和资源访问能力:
- EL0:用户态,最低特权级。运行普通应用程序,无法直接访问系统寄存器或控制硬件。
- EL1:操作系统内核态。运行操作系统内核(如Linux、RTOS),管理虚拟内存、进程调度和中断。
- EL2:虚拟机监控器(Hypervisor)态。运行虚拟化管理程序,支持虚拟化扩展。
- EL3:安全监控器(Secure Monitor)态。最高特权级,负责安全世界与非安全世界之间的切换,是TrustZone的核心组件。
注意:异常等级的数字越大,特权级越高。EL3拥有对所有系统资源的完全控制权,包括安全与非安全世界的内存、外设和中断控制器。
2.3 安全世界与非安全世界切换机制
TrustZone将物理处理器核心虚拟化为两个“世界”:安全世界(Secure World)和非安全世界(Normal World)。两个世界共享同一个物理CPU核心,但拥有独立的系统视图。切换由EL3的安全监控器(Secure Monitor)通过安全监控器调用(SMC, Secure Monitor Call)指令触发。
2.3.1 世界切换流程
- 非安全世界发起SMC调用:非安全世界的软件(如Linux内核)执行SMC指令,触发同步异常,处理器提升到EL3。
- EL3安全监控器接管:安全监控器保存非安全世界的上下文(寄存器、系统状态),并根据SMC功能号决定目标世界。
- 上下文切换:安全监控器恢复安全世界的上下文,然后执行ERET指令返回到安全世界的指定入口。
- 安全世界执行:安全世界完成安全服务(如加解密、安全存储访问),然后再次通过SMC返回非安全世界。
- 恢复非安全世界:安全监控器恢复非安全世界的上下文,ERET返回到非安全世界继续执行。
性能考量:世界切换涉及完整的上下文保存与恢复,包括通用寄存器、系统寄存器、中断状态等。频繁切换会引入显著延迟,因此应尽量减少跨世界调用的频率。
2.3.2 世界切换的关键指令与寄存器
| 指令/寄存器 | 作用 | 所属异常等级 |
|---|---|---|
| SMC #imm | 安全监控器调用,触发EL3异常,用于世界切换 | EL0/EL1/EL2 |
| ERET | 从异常返回,恢复目标世界的上下文并跳转 | EL3 |
| SCR_EL3 | 安全配置寄存器,控制安全世界与非安全世界的路由策略 | EL3 |
| VBAR_EL3 | EL3异常向量表基地址寄存器,指向安全监控器的异常处理入口 | EL3 |
| CNTFRQ_EL0 | 系统计数器频率寄存器,两个世界共享,用于时间同步 | EL0 |
2.3.3 安全与非安全世界的隔离边界
TrustZone的隔离不仅体现在异常等级上,还通过硬件机制确保两个世界无法互相干扰:
- 内存隔离:通过TZASC(TrustZone Address Space Controller)或TZC-400等硬件控制器,将物理内存划分为安全区域和非安全区域。非安全世界的DMA和CPU访问无法穿透安全区域。
- 外设隔离:通过TZPC(TrustZone Protection Controller)或TZMA(TrustZone Memory Adapter)控制外设的访问权限。安全外设只能由安全世界访问。
- 中断隔离:GIC(Generic Interrupt Controller)支持安全中断和非安全中断分组。安全中断只能由安全世界处理,非安全世界无法屏蔽或劫持安全中断。
- 缓存与TLB隔离:安全世界和非安全世界使用独立的缓存和TLB标记,避免信息泄露。
实战建议:在驱动开发中,务必确认外设的TZPC配置是否正确。如果安全世界驱动无法访问某个外设,首先检查该外设是否被配置为非安全访问权限。
2.4 异常等级与安全世界的组合视图
将异常等级与安全世界结合,可以得到完整的ARMv8-A安全架构视图。每个异常等级在两个世界中都有对应的软件组件:
2.5 异常等级切换的典型场景
在实际系统中,异常等级切换发生在多种场景下。以下表格总结了最常见的切换场景及其触发方式:
| 场景 | 触发方式 | 源EL | 目标EL | 说明 |
|---|---|---|---|---|
| 系统调用 | SVC指令 | EL0 | EL1 | 用户态请求内核服务 |
| 中断处理 | IRQ/FIQ | EL0/EL1 | EL1/EL2/EL3 | 根据中断路由配置决定目标等级 |
| 虚拟化调用 | HVC指令 | EL1 | EL2 | Guest OS请求Hypervisor服务 |
| 安全世界切换 | SMC指令 | EL0/EL1/EL2 | EL3 | 非安全世界请求安全服务 |
| 安全中断 | FIQ(安全中断) | EL0/EL1 | EL3 | 安全外设中断直接路由到EL3 |
| 系统复位 | 硬件复位 | 任意 | EL3 | 复位后默认进入EL3安全监控器 |
安全风险提示:如果非安全世界能够通过漏洞触发EL3异常或篡改异常向量表,可能导致安全世界被攻破。务必确保VBAR_EL3指向的异常向量表位于安全内存区域,且不可被非安全世界修改。