ELR 和SPSR 寄存器 、PSTATE寄存器
ERET指令
el3--->el1
ERET指令用于异常返回,返回地址和处理器状态是从当前EL(exception level)下的ELR和SPSR寄存器中恢复的。即ELR寄存器中的值就是BL1最后跳转的目的地址,SPSR寄存器的值就是跳转之后处理器的状态。所以在代码中重点关注这两个值的初始化
处理异常的流程
ARMv8的四个异常级别只能通过异常获取/返回的方式在异常等级之间跳转。
- 将PSTATE寄存器内容保存到对应等级的SPSR_ELx中(保存PSTATE现场)
- 保存返回地址到对应等级的ELR_ELx寄存器中(保存返回地址)
- 将PSTATE中的DAIF设1,即关闭调试异常、SError、IRQ和FIQ
- 设置对应异常等级下的栈指针,自动切换SP到SP_ELx
- 切换到对应目标异常等级,跳转到异常向量表执行
以上都是处理器自动完成的,OS所需要做的事就是从中断向量表开始,根据发生的异常类型,跳转到合适的异常向量。
当异常处理完后,执行eret指令从异常返回。eret 指令会从ELR_ELx中恢复PC指针并且从SPSR_ELx中恢复到PSTATE中。
fucntion el3 exit
msr spsr_el3 x0
msr elr_el3 x1
isb
eret
软件产生的异常
ARMv8提供了3中软件产生的异常,发生此异常的原因是软件企图进入更高的异常等级。
- SVC 允许用户模式下的程序请求os服务
- HVC 允许客户机(Linux os)请求主机服务
- SMC 允许普通世界的程序请求安全服务
对EL2/EL3的系统调用
SVC指令可以用来从EL0的用户应用程序调用到EL1的内核。HVC和SMC系统调用指令以类似的方式将处理器移动到EL2和EL3。当处理器在EL0(应用程序)执行时,它不能直接调用管理程序(EL2)或安全监视器(EL3)。这只有在EL1和以上的地方才有可能。因此,应用程序必须使用SVC来调用内核,并允许内核代表它们调用更高的异常级别。
在操作系统内核(EL1),软件可以用HVC指令调用管理程序(EL2),或用SMC指令调用安全监视器(EL3)。如果处理器是用EL3实现的,就可以提供让EL2从EL1捕获SMC指令的能力。如果没有EL3,SMC是未分配的,并在当前的异常级别触发。
同样,从管理程序代码(EL2)中,程序可以用SMC指令调用安全监视器(EL3)。如果你在EL2或EL3时进行SMC调用,它仍然会在同一个异常级别上引起一个同步异常,该异常级别的处理程序可以决定如何响应