3. 安全中断向量表:ARMv8-A异常向量表结构、安全与非安全中断向量表配置、VBAR_EL3与VBAR_EL1
在ARMv8-A架构中,异常向量表(Exception Vector Table)是处理器响应异常(中断、陷阱、系统错误)的入口点。对于TrustZone安全扩展,系统必须为安全世界和非安全世界分别配置独立的向量表,并通过VBAR_EL3、VBAR_EL1等系统寄存器进行定位。本章深入剖析异常向量表的结构、安全与非安全配置差异,以及关键寄存器的编程方法。
3.1 ARMv8-A异常向量表结构
ARMv8-A的异常向量表采用固定偏移的表格结构,每个异常类型占用0x80字节(32条指令)的入口空间。整个向量表大小为2KB(0x800字节),分为四个异常类别,每个类别包含四个入口。
核心概念:异常向量表基地址必须2KB对齐(即地址低11位为0),这是硬件强制要求。
| 偏移地址 | 异常类别 | 异常类型 | 描述 |
|---|---|---|---|
| 0x000 | Synchronous | EL1t Sync | 当前EL使用SP_EL0时的同步异常 |
| 0x080 | IRQ | EL1t IRQ | 当前EL使用SP_EL0时的IRQ中断 |
| 0x100 | FIQ | EL1t FIQ | 当前EL使用SP_EL0时的FIQ中断 |
| 0x180 | SError | EL1t SError | 当前EL使用SP_EL0时的系统错误 |
| 0x200 | Synchronous | EL1h Sync | 当前EL使用SP_ELx时的同步异常 |
| 0x280 | IRQ | EL1h IRQ | 当前EL使用SP_ELx时的IRQ中断 |
| 0x300 | FIQ | EL1h FIQ | 当前EL使用SP_ELx时的FIQ中断 |
| 0x380 | SError | EL1h SError | 当前EL使用SP_ELx时的系统错误 |
| 0x400 | Synchronous | AArch64 Sync | 从AArch64状态进入的同步异常 |
| 0x480 | IRQ | AArch64 IRQ | 从AArch64状态进入的IRQ中断 |
| 0x500 | FIQ | AArch64 FIQ | 从AArch64状态进入的FIQ中断 |
| 0x580 | SError | AArch64 SError | 从AArch64状态进入的系统错误 |
| 0x600 | Synchronous | AArch32 Sync | 从AArch32状态进入的同步异常 |
| 0x680 | IRQ | AArch32 IRQ | 从AArch32状态进入的IRQ中断 |
| 0x700 | FIQ | AArch32 FIQ | 从AArch32状态进入的FIQ中断 |
| 0x780 | SError | AArch32 SError | 从AArch32状态进入的系统错误 |
实践提示:在安全监控器(Secure Monitor)中,通常只需要处理EL3级别的异常向量表。EL1和EL2的向量表由对应的操作系统或Hypervisor管理。
3.2 安全与非安全中断向量表配置
在TrustZone架构中,安全世界和非安全世界拥有各自独立的异常向量表。安全监控器(运行在EL3)负责在两种世界之间切换,并确保中断能够被正确路由到对应的向量表。
3.2.1 安全世界向量表(Secure World)
- VBAR_EL1:指向安全EL1的异常向量表基地址。
- VBAR_EL2:如果启用了虚拟化,指向安全EL2的向量表。
- VBAR_EL3:指向EL3(安全监控器)的向量表,处理安全监控器调用(SMC)和中断路由。
3.2.2 非安全世界向量表(Non-Secure World)
- VBAR_EL1:指向非安全EL1的异常向量表基地址(通常由Rich OS如Linux管理)。
- VBAR_EL2:如果启用了虚拟化,指向非安全EL2的向量表(由Hypervisor管理)。
关键安全约束:安全世界和非安全世界的向量表必须物理隔离。非安全世界无法读取或修改安全世界的VBAR_EL1/EL3寄存器,这是TrustZone硬件强制保护的核心机制。
| 寄存器 | 异常级别 | 安全状态 | 用途 | 可访问性 |
|---|---|---|---|---|
VBAR_EL3 |
EL3 | 安全 | 安全监控器异常向量表 | 仅EL3可读写 |
VBAR_EL2 |
EL2 | 安全/非安全 | 虚拟化异常向量表 | EL2/EL3可读写 |
VBAR_EL1 |
EL1 | 安全 | 安全OS异常向量表 | 安全EL1/EL3可读写 |
VBAR_EL1 |
EL1 | 非安全 | 非安全OS异常向量表 | 非安全EL1/EL2/EL3可读写 |
3.3 VBAR_EL3与VBAR_EL1
VBAR_EL3和VBAR_EL1是ARMv8-A中最重要的异常向量表基地址寄存器。它们的正确配置是TrustZone安全中断处理的基础。
3.3.1 VBAR_EL3:安全监控器向量表
- 作用:指向EL3异常向量表的基地址,处理所有进入EL3的异常,包括SMC、安全中断、FIQ等。
- 配置时机:在系统启动早期,由安全固件(如ARM Trusted Firmware)在EL3中设置。
- 安全属性:仅EL3可读写,非安全世界无法访问。
3.3.2 VBAR_EL1:操作系统向量表
- 作用:指向EL1异常向量表的基地址,处理操作系统级别的异常。
- 安全属性:安全世界和非安全世界各自拥有独立的VBAR_EL1实例,硬件根据当前安全状态自动选择。
- 配置时机:在操作系统启动时由内核设置。
编程要点:在安全监控器中,当检测到安全中断时,必须通过
SCR_EL3(安全配置寄存器)的IRQ和FIQ位来控制中断路由。例如,设置SCR_EL3.IRQ=0可将IRQ路由到非安全世界。
3.3.3 配置示例代码
以下代码展示了如何在安全监控器初始化阶段配置VBAR_EL3和VBAR_EL1:
/* 安全监控器初始化 - 配置异常向量表 */
.globl secure_monitor_init
secure_monitor_init:
/* 1. 设置VBAR_EL3指向安全监控器向量表 */
ldr x0, =monitor_vector_table
msr vbar_el3, x0
isb
/* 2. 设置VBAR_EL1指向安全OS向量表 */
ldr x0, =secure_os_vector_table
msr vbar_el1, x0
isb
/* 3. 配置SCR_EL3控制中断路由 */
mrs x0, scr_el3
/* 设置NS位=0(安全世界),IRQ位=0(IRQ路由到EL3),FIQ位=1(FIQ路由到EL3) */
bic x0, x0, #(1 << 0) /* 清除NS位 */
bic x0, x0, #(1 << 1) /* 清除IRQ位,IRQ路由到EL3 */
orr x0, x0, #(1 << 2) /* 设置FIQ位,FIQ路由到EL3 */
msr scr_el3, x0
isb
/* 4. 启用异常路由 */
mrs x0, cptr_el3
bic x0, x0, #(1 << 1) /* 允许访问CPACR */
msr cptr_el3, x0
isb
ret
/* 安全监控器向量表(仅展示前两个入口) */
.align 11 /* 2KB对齐 */
monitor_vector_table:
/* EL3使用SP_EL0时的同步异常 */
.align 7
b monitor_sync_sp0
/* EL3使用SP_EL0时的IRQ */
.align 7
b monitor_irq_sp0
/* ... 其他入口 ... */
常见错误:忘记在配置VBAR后执行
ISB(指令同步屏障)指令,可能导致处理器使用旧的向量表地址,引发不可预测的行为。务必在每次修改VBAR后立即执行ISB。
3.4 中断路由与向量表选择流程
当系统接收到中断时,硬件根据当前安全状态和中断类型自动选择对应的向量表。以下是典型的中断路由流程: