本文声明:内容来源于网络,进行整合/再创作;部分内容由AI辅助生成。
在 ARMv8-A 架构中,当处理器接收到一个异常时,它会自动执行一系列操作,其中一个关键环节就是决定接下来要使用哪种执行状态 以及进入哪个异常级别。
执行状态指的是处理器的指令集模式(AArch64 或 AArch32),而异常级别(EL0-EL3)则代表了软件执行的权限层级。
核心机制:利用 SPSR 保存现场
- 保存状态:当异常发生时,处理器会自动将当前的执行状态和异常级别保存到保存程序状态寄存器SPSR_Eln(n表示异常级别)中。
- 恢复现场:当执行异常返回指令时,处理器会使用 SPSR_Eln 中保存的值,恢复到发生异常之前的执行状态和异常级别。
各异常级别执行状态的控制逻辑
异常处理程序在哪个执行状态下运行,是由当前异常级别更高一层的某个控制位决定的。这种设计确保了高权限级别能够控制低权限级别的执行环境。
1、最高异常级别(通常是 EL3,但并非一定是它)的初始状态
- 复位时决定:系统上电复位时,最高异常级别的执行状态通常由硬件引脚配置决定。
- 运行时 改变:软件可以通过配置 RMR_ELn 寄存器来触发一个软复位,从而在运行时更改最高异常级别的执行状态。
2、EL3 的执行状态(安全监视器)
执行状态固定:EL3 通常运行安全监视器(Secure Monitor)代码,这是一段对稳定性要求极高的可信代码。它的执行状态是设计时就确定并固定的。
3、EL2 的执行状态(虚拟化)
由 EL3 控制:EL2(常用于虚拟化管理)的执行状态由位于 EL3 的 SCR_EL3.RW 位控制。这个位决定了其下一个较低级别(即 EL2)的运行状态。
4、EL1 的执行状态(操作系统内核)
由 EL2 控制:EL1(常用于操作系统内核)的执行状态由位于 EL2 的 HCR_EL2.RW 位控制。这个位决定了其下一个较低级别(即 EL1 和 EL0)的运行状态。
5、EL0 的执行状态(用户应用程序)
从不处理异常 :EL0 用于运行无特权权限的应用程序,永远不会直接在 EL0 处理异常。
实例分析:从 EL0 的应用程序到 EL1 的内核异常处理程序
EL0 与 EL1 异常切换
为了更直观地理解上述机制,分析一个典型的 IRQ 中断场景。
1、初始状态:一个用户应用程序在 EL0 运行,使用 AArch32 执行状态。
2、触发异常:外部设备产生了一个 IRQ 中断。
3、确定处理程序执行状态:
- 处理器接收到 IRQ 信号,准备从 EL0 跳转至 EL1,由于异常将在 EL1 处理,处理器需要确定 EL1 使用哪种执行状态。
- 根据规则,EL1 的执行状态由它的上一级,即 EL2 的 HCR_EL2.RW 位决定。
- 假设该位被配置为 1,表示 EL1 应运行在 AArch64 状态。
4、确定处理程序异常级别:
系统设计决定了这个 IRQ 应该被 EL1 处理,而不是留在 EL0。
5、执行切换:
- 处理器将当前状态(AArch32, EL0)的PSTATE信息信息保存到 SPSR_EL1 中。
- 处理器检测到 HCR_EL2.RW 位被置1,切换到 AArch64 执行状态,并进入 EL1。
- 开始执行 EL1 的 IRQ 处理程序(AArch64 代码)。
总结:异常与异常级别的关系
- 级别提升原则:异常触发后,异常级别保持不变或升高(取决于配置,但绝不会更低)。
- EL0 的不可达性:无论当前处于何种状态,异常永远不会被在 EL0 进行处理。EL0 始终是异常发生的源头,而非处理的终点。
通过这种分层控制机制(SCR_EL3 控制 EL2,HCR_EL2 控制 EL1/0),ARM 架构实现了灵活且安全的混合执行环境。即使底层的应用程序运行在 32 位模式下,高权限的异常处理程序(如安全监视器、虚拟机监控器、操作系统内核)依然可以运行在 64 位模式下,从而实现了灵活的混合位宽系统设计。
EL0 与 EL1 异常切换