ARM 架构的异常模型(Exception Model)
ARM 架构的异常模型(Exception Model)
ARM 架构的异常模型(Exception Model)。这是理解 ARM 处理器如何响应和处理中断、故障等突发事件的核心。
1. 什么是异常?
在 ARM 架构中,异常(Exception) 是一个广义的概念,指任何打断程序正常执行流程的事件。当异常发生时,处理器会暂停当前指令的执行,跳转到一个特定的地址(异常向量表)去执行相应的代码(异常处理程序),处理完成后(通常)再返回原来的程序继续执行。
常见的异常包括:
- 中断(Interrupt):来自外部硬件(如定时器、GPIO、外设)的异步信号。
- IRQ (Interrupt Request):普通中断,优先级较低。
- FIQ (Fast Interrupt Request):快速中断,优先级最高,通常用于要求实时响应的场景。
- 陷阱(Trap):由指令主动触发的同步异常,例如系统调用(
SVC
指令)、调试断点。 - 故障(Fault):由指令执行期间产生的错误触发的同步异常,例如访问非法内存(MMU 缺页异常)、执行未定义指令。
注意:在 ARM 的语境中,“中断”是“异常”的一种子类型。这与一些其他架构(如 x86)将“中断”和“异常”并列区分有所不同。
2. 异常模型的核心组件
a. 操作模式(Operation Modes)
ARM 处理器有多种操作模式,不同模式拥有不同的寄存器组和权限级别。异常发生时,处理器会自动切换到对应的模式。
模式 | 缩写 | 描述 | 典型用途 |
---|---|---|---|
User | USR | 非特权模式 | 运行普通应用程序 |
FIQ | FIQ | 特权模式 | 处理快速中断(FIQ) |
IRQ | IRQ | 特权模式 | 处理普通中断(IRQ) |
Supervisor | SVC | 特权模式 | 操作系统内核、处理复位和 SVC 指令 |
Abort | ABT | 特权模式 | 处理内存访问异常 |
Undefined | UND | 特权模式 | 处理未定义指令异常 |
Monitor | MON | 特权模式 | 安全世界与非安全世界的切换(TrustZone) |
System | SYS | 特权模式 | 与 User 模式共享寄存器,用于运行特权操作系统任务 |
注:除了 User 模式,其他都是特权模式。
b. 异常向量表(Exception Vector Table)
这是一个包含一系列跳转指令的特定内存区域(通常是地址 0x00000000
或 0xFFFF0000
)。每个异常类型在表中都有一个固定的、占 4 字节的入口地址。
地址偏移(来自向量表基址) | 异常类型 | 进入的模式 |
---|---|---|
0x00 | Reset | Supervisor |
0x04 | Undefined Instruction | Undefined |
0x08 | Supervisor Call (SVC) | Supervisor |
0x0C | Prefetch Abort | Abort |
0x10 | Data Abort | Abort |
0x14 | IRQ | IRQ |
0x18 | FIQ | FIQ |
当异常发生时,硬件自动将 PC
指向对应的向量地址,并执行那里的指令(通常是一条跳转到具体处理函数的指令)。
c. 寄存器组
ARM 异常模型的一个巧妙设计是Banked Registers。
- User 和 System 模式:共享同一组寄存器(R0-R14, CPSR)。
- 其他特权模式(FIQ, IRQ, SVC, Abort, Undef):拥有自己独有的副本寄存器,最重要的是 SP(Stack Pointer) 和 LR(Link Register)。
- 优势:当异常发生时,处理器自动切换到对应模式的 SP 和 LR,无需手动保存通用寄存器,极大地加快了异常响应速度。
- 特别地,FIQ 模式甚至有自己独有的
R8-R12
,这意味着 FIQ 处理程序一开始就可以使用这些寄存器,无需保存,从而更快地执行,这也是“快速”中断的由来。
关键寄存器:
- CPSR (Current Program Status Register):包含条件标志位(N,Z,C,V)、中断禁用位(I, F)、执行状态位(T, J)以及当前模式位。
- SPSR_ (Saved Program Status Register):当异常发生时,硬件会自动将发生异常时的
CPSR
保存到对应异常模式的SPSR
中。这样在异常返回时,可以恢复之前的处理器状态。
3. 异常处理流程
异常处理是一个由硬件和软件协同完成的过程。
a. 异常产生时(硬件自动完成):
- 保存现场:
- 将下一条待执行指令的地址保存到异常模式下的 LR(
LR_<mode>
)。注意:ARM 流水线结构使得保存的地址需要根据异常类型进行偏移调整(例如,PC+4 或 PC+8)。 - 将当前的
CPSR
复制到异常模式下的 SPSR(SPSR_<mode>
)。
- 将下一条待执行指令的地址保存到异常模式下的 LR(
- 切换模式:
- 根据异常类型,改变
CPSR
中的模式位(M[4:0]),切换到对应的特权模式(如 IRQ 模式)。
- 根据异常类型,改变
- 禁用中断(可选,但通常是默认行为):
- 自动设置
CPSR
中的I
位(禁用 IRQ)。如果是 FIQ 异常,还会设置F
位(禁用 FIQ),以防止嵌套中断。
- 自动设置
- 跳转:
- 将
PC
设置为异常向量表中对应异常的地址,开始执行异常处理程序。
- 将
b. 执行异常处理程序(软件完成):
-
保护现场:进一步将通用寄存器(R0-R3, R12)压入异常模式的栈中,防止这些寄存器被修改。
-
识别异常源(特别是对于 IRQ):读取中断控制器(如 GIC)的寄存器,判断是哪个硬件产生的中断。
-
处理异常:执行真正的处理逻辑(例如,检查内存地址、响应外设请求)。
-
恢复现场:将之前压入栈的通用寄存器弹出。
-
返回:这是最关键的一步,需要两条特殊指令协同完成:
SUBS PC, LR, #4 ; 一种常见的IRQ返回方式
或者更通用的方式:
MOVS PC, LR
SUBS PC, LR, #4
或MOVS PC, LR
这条指令完成了三件事:- 将连接寄存器
LR
的值(可能减去一个偏移量,以修正流水线效应)赋给程序计数器PC
,从而跳回到被中断的代码。 S
后缀表示这条指令同时会将当前模式的SPSR
复制回CPSR
,自动恢复之前的状态(包括模式切换回用户模式)。
- 将连接寄存器
4. 举例:IRQ 处理流程
- 程序在 User 模式下正常执行。
- 一个外设触发了 IRQ 中断。
- 硬件自动:
- 将
PC+4
保存到LR_irq
。 - 将
CPSR
保存到SPSR_irq
。 - 切换到 IRQ 模式,禁用 IRQ(设置
CPSR.I=1
)。 - 跳转到向量表地址
0x18
执行。
- 将
- 在
0x18
处的指令通常是LDR PC, [PC, #0x18]
,它会跳转到真正的 IRQ 处理函数(irq_handler
)。 irq_handler
软件开始执行:- 压栈保护
R0-R3, R12
。 - 查询中断控制器,确定中断源。
- 调用对应的中断服务例程(ISR)进行处理。
- 弹出栈,恢复
R0-R3, R12
。 - 执行
SUBS PC, LR, #4
返回。这条指令将PC
指回之前被中断的指令,并将SPSR_irq
(即之前的 User 模式 CPSR)恢复,处理器切换回 User 模式,继续执行。
- 压栈保护
总结
ARM 异常模型是一个高效、精细的硬件机制,其核心思想在于:
- 模式划分:通过不同的特权模式为不同异常提供隔离的执行环境。
- 硬件自动保存:硬件自动保存返回地址和状态(到 LR 和 SPSR),并切换栈指针(SP),极大提高了响应速度。
- 向量表跳转:提供统一、快速的入口点分发机制。
- Banked 寄存器:关键寄存器的独有副本避免了不必要的内存保存/恢复操作。
理解这个模型是进行 ARM 底层系统开发(如编写操作系统、驱动、固件)的基础。