在ARMv8/v9架构中,异常处理是处理器核心功能之一。当发生中断、系统调用或指令异常时,处理器需要保存当前执行状态以便异常返回后恢复现场。Saved Program Status Register(SPSR)就是专为这一机制设计的关键寄存器。
以EL2(Hypervisor层)和EL3(Secure Monitor层)为例,每个异常级别都有对应的SPSR寄存器:
这些寄存器在异常发生时自动捕获处理器状态(PSTATE),在异常返回时恢复状态。其设计特点包括:
关键点:SPSR不是通用寄存器,只能通过MRS/MSR指令在对应异常级别访问。例如EL1无法直接读写SPSR_EL2,否则会触发Undefined Instruction异常。
这些位直接反映程序执行状态,用于条件分支判断:
| 位域 | 名称 | 功能描述 |
|---|---|---|
| N[31] | Negative | 运算结果为负时置1,对应PSTATE.N |
| Z[30] | Zero | 运算结果为零时置1,对应PSTATE.Z |
| C[29] | Carry | 无符号运算溢出时置1,对应PSTATE.C |
| V[28] | Overflow | 有符号运算溢出时置1,对应PSTATE.V |
典型应用场景:
assembly复制// 异常发生时处理器自动执行:
SPSR_EL2.N = PSTATE.N;
SPSR_EL2.Z = PSTATE.Z;
// ...其他标志位同理
// 异常返回时:
PSTATE.N = SPSR_EL2.N;
PSTATE.Z = SPSR_EL2.Z;
控制关键异常类型的屏蔽状态:
| 位域 | 中断类型 | 功能说明 |
|---|---|---|
| D[9] | Debug | 调试异常屏蔽位 |
| A[8] | SError | 系统错误异常屏蔽位 |
| I[7] | IRQ | 普通中断屏蔽位 |
| F[6] | FIQ | 快速中断屏蔽位(EL3特有) |
配置示例:
c复制// 在EL3异常处理中临时屏蔽所有中断:
msr SPSR_EL3, #0xC0 // 设置I和F位
定义异常返回的目标级别和栈指针:
| M[3:0] | 目标状态 |
|---|---|
| 0b0101 | EL1h(使用SP_EL1) |
| 0b1001 | EL2h(使用SP_EL2) |
| 0b1101 | EL3h(使用SP_EL3) |
注意:非法组合(如0b1111)会导致异常返回失败
内存标签扩展(Memory Tagging Extension)引入的Tag Check Override位:
assembly复制// 启用MTE检查
mrs x0, SPSR_EL2
orr x0, x0, #(1 << 25) // 设置TCO位
msr SPSR_EL2, x0
Speculative Store Bypass Safe控制位:
c复制// 在EL3启用SSBS防护
#define SSBS_MASK (1 << 12)
uint64_t val;
__asm__ volatile("mrs %0, SPSR_EL3" : "=r"(val));
val |= SSBS_MASK;
__asm__ volatile("msr SPSR_EL3, %0" :: "r"(val));
| 当前EL | 可访问的SPSR |
|---|---|
| EL0 | 无 |
| EL1 | 仅SPSR_abt/mode等 |
| EL2 | SPSR_EL2, SPSR_EL1 |
| EL3 | SPSR_EL3 |
状态保存示例:
assembly复制// 在EL2异常处理入口:
mrs x0, SPSR_EL2
stp x0, x1, [sp, #-16]! // 保存到栈
// 修改条件标志
bic x0, x0, #(1 << 29) // 清除C标志
msr SPSR_EL2, x0
// 异常返回前恢复:
ldp x0, x1, [sp], #16
msr SPSR_EL2, x0
eret
所有SPSR字段在温复位(Warm reset)时的行为:
推荐初始化流程:
症状:执行ERET指令触发Illegal Return异常
排查步骤:
可能原因:
assembly复制mrs x0, SPSR_EL2
bic x0, x0, #(1 << 7) // 清除I位
msr SPSR_EL2, x0
EL3关键位保护:
虚拟化场景:
c复制// Hypervisor需验证Guest的SPSR_EL1配置
if (guest_spsr & ILLEGAL_MASK) {
inject_undef_exception();
}
调试接口防护: