ARMv8 AArch64异常处理机制概览

1 处理机制概述

相对于ARMv7中的异常向量表(Exception Vector Table),ARMv8异常处理机制更为复杂,涉及处理器的异常等级(Exception Levels, ELn)、运行状态(Execution States)和安全模式(Secure Mode)。

这种特性意味着我们在描述异常时需要说明异常是在什么异常等级下发生的,返回时处理器的异常等级、运行状态和安全模式发生了什么变化,比如“在当前异常等级下发生Sync异常,异常等级从EL2切换到EL1,使处理器的运行状态从AArch64转到AArch32”。

ARMv8共有4个异常等级ELn(n=0,1,2,3),EL3最高,EL2最低。复位处理(Reset Handler)和异常向量表分开,支持为每个异常等级提供独立的异常向量表和栈指针寄存器(Stack Pointer,SP)。异常等级只能在复位、异常发生和退出时变更,且进入异常不能降低异常等级、退出异常不能提升异常等级。


2 异常向量表

ARMv8的异常向量表也有固定的区域划分,不过更大——单张异常向量表起始地址0x800字节对齐,内部每段0x80字节对齐,如图2-1。
在这里插入图片描述图2-1 ARMv8异常向量表的结构

上图只是一个异常等级的异常向量表,一般来说需要为EL3、EL2和EL1各提供一张异常向量表。不同异常等级ELn的异常向量表起始地址可以通过寄存器VBAR_ELn(n=1,2,3)设置。

向量表可分为两部分,偏移地址0x000-0x400的用于相应当前异常等级的异常,偏移地址0x400-0x780的向量用于接收低一等级的异常。比如EL2的异常向量表,这部分就用于处理EL1的异常。

ARMv8提供了4个堆栈指针寄存器,不同异常等级ELn(n=1,2,3)可通过寄存器SPSel选择SP_ELn或者EL0作为堆栈指针,这将决定在当前异常等级下发生异常时PC跳转的位置。比如当前异常等级(假设为EL2)下发生IRQ中断,如果当前选择的堆栈指针为SP0,PC就会跳转到异常向量表的0x080偏移位置,如果当前选择的堆栈为SP_EL2,PC就会跳转到异常向量表的偏移地址0x280处。

值得一提的是,堆栈指针寄存器的使用和ARMv7没啥差别。向SPSel值选择了当前异常等级的堆栈指针后,SP寄存器和选定的SP_ELn会产生关联,二者的值会保持一致。同步机制还没有在手册里看到,暂且可以认为SP是引用了SP_ELn的值。

此外,习惯上用后缀t表示当前异常等级选择的堆栈是SP_EL0,比如SP_EL1t,用后缀h表示选择的是ELn,比如SP_EL1h。


3 异常处理

处于AArch64运行状态的ARMv8处理器根据异常的类型、发生异常的异常等级、当前使用的堆栈指针(SP in use)、寄存器组的状态(state of the register file)。

3.1 Taken 和 Return
Taken关乎异常的处理,Return关乎异常的返回。
Taken指的是处理器对异常的响应(Responds),即因异常做出动作。Taken from描述异常的来源,指处理器在Taken发生前一刻的状态。Taken to则描述异常的去向,指的是处理器在Taken发生后一刻的状态。
在异常处理的语境下,Return指的是,额,使用异常返回指令(Exception return instruction)触发的动作?Return form描述异常从何退出,指的是Return前处理器的状态。Return to描述异常退出结果,指的是Return后处理器的状态。

3.2 异常处理入口
产生异常的指令有HVC/SMC/SVC。
如果异常taken to一个使用AArch64运行状态的异常等级ELn,那么处理器在将PC跳转到异常向量表的对应位置前,将执行以下动作:
 将Taken from的PSTATE保存到SPSR_ELn寄存器
 将优先返回地址(preferred exception return address)保存到ELR_ELn寄存器
 配置Taken to的PSTATE寄存器
 如果是Synchronous或者SError异常,异常综合信息写入ESR_ELn寄存器
 跳转到异常向量表对应位置
上述Taken to的PSTATE配置遵循以下规则:
 PSTATE.EL 设置为ELn。
 PSTATE.{D, A, I, F, SP, TCO} 设置为 1
 PSTATE.SSBS 设置为 SCTLR_ELn.DSSBS 的值
 PSTATE.{IL, nRw, UAO} 设置为 0
 PSTATE.BTYPE 设置为 0b00
 PSTATE.SS 根据v8手册Chapter D2 AArch64 Self-hosted Debug中的规则设置
 对于以下任何一种情况,PSTATE.PAN 设置为 1:
—— 目标异常级别为 EL1并且SCTLR_EL1为 0
—— Taken from EL0,Taken to AArch64状态且打开安全模式的EL2,HCR_EL2.{TGE, E2H}是{1, 1},并且SCTLR_EL2.SPAN是0.
 PSTATE.ALLINT 设置为SCTLR_ELx.SPINTMASK的值取反

3.3 退出异常
退出异常的指令有ERET/ERETAA/ERETAB,异常等级EL0不支持异常退出指令。退出时切换到的目标异常等级可通过当前异常等级ELn的SPSR_ELn设置。
在这里插入图片描述
图3-3-1 通过SPSR_ELn选择Target EL

下面是从EL3切换到EL1的例程

.global _el3_to_el1
.type _el3_to_el1, "function"
_el3_to_el1:
	// Initialize the SCTLR_EL1 register before entering EL1
	MSR SCTLR_EL1, XZR
	// Determine the EL1 Execution state
	MRS X0, SCR_EL3
	ORR X0, X0, #(1<<10) // RW, EL2 Execution state is AArch64
	// Determine the EL1 Security Mode
	AND X0, X0, #0xFFFFFFFFFFFFFFFE // NS, EL1 is Secure world
	MSR SCR_EL3, x0
	MOV X0, #0b00101
	MSR SPSR_EL3, X0 // M[4:0]=01001 EL1h, must match SCR_EL3.RW
	// Determine EL2 entry.
	ADR X0, el2_entry
	MSR ELR_EL3, X0
	ERET

3.4 异常等级切换
ARMv8有EL3、EL2、EL1、EL0共四个异常等级,用户可通过产生或退出异常切换异常等级。切换异常等级需注意配置目标异常等级的栈指针寄存器、运行状态和安全模式。

EL0,EL1有安全模式和非安全模式的区别。 EL2是虚拟机管理级别并且只有非安全模式。 EL3是最高优先级并且只存在安全模式。
此外,EL3直接切换到EL1只能选择安全模式,因此EL3切换到EL1只有两个路径,一种是EL3(S)->EL2(NS)->EL1(S),另一种是EL3(S)->EL1(S)。


4 相关的指令和寄存器

4.1 ERET
4.2 SCR_EL3
4.3 SPSR_ELn.DAIF
4.4 ELR_ELn
4.5 SCTLR_EL2
4.6 HCR_EL2
4.7 ELR


5 架构相关的补充信息

要想真正理解ARMv8的异常处理机制,就需要理解ARMv8架构的特性,概要地说,至少需要通过阅读指令集手册理解以下几个概念。

5.1 运行状态
5.2 安全模式
5.3 Warm Reset

6 参考

  1. Application Note Bare-metal Boot Code for ARMv8-A Processors Version 1.0 Non-Confidential Arm® Architecture Reference Manual for A-profile architecture
  2. Arm® Architecture Reference Manual for A-profile architecture
  3. Github仓库 WaterCutter/pickArm
  • 1
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值