ARM v8 AArch64 Programmers’ model
最近准备更新下自己的ARMv8架构知识库。特简单记录下,特别是AArch64状态的特点。主要参考资料是官方的<ARMv8-A architecture reference manual>。
异常等级(EL)
v8定义了EL0 ~ EL3一系列异常等级,这些不同等级有如下含义:
- 数字的增长代表的软件执行特权的提升。
- EL0也称为unprivileged execution。
- EL2提供Non-secure下虚拟化操作支持。
- EL3提供Secure和Non-secure状态下的切换支持。
对处理器来说,并不是每个EL都需要实现。但EL0和EL1是必须实现的,EL2和EL3是可选的。
另外,处理器运行在AArch64状态时,EL等级迁移只能是发生异常或者从异常返回,EL迁移规则如下:
- 发生异常时,EL只能提升或维持当前等级。
- 当前异常返回时,EL只能降低或维持。
除EL0,其它EL都有自己的转换页表和相关控制寄存器。
寄存器
通用寄存器
v8有R0 ~ R30共31个通用寄存器。以64-bit访问时,为X0 ~ X30;以32-bit访问时,为W0 ~ W30。
栈指针寄存器(SP)
在AArch64状态,每个EL都有自己的SP寄存器。具体如下:
- SP_EL0
- SP_EL1
- SP_EL2
- SP_EL3
一般情况下,EL都是使用自己的SP。但也可以通过PSTATE.SP来配置成使用SP_EL0寄存器(但EL0只能只用SP_EL0寄存器不能配置)。比如运行在EL1,除了使用SP_EL1,也可以通过配置修改成使用SP_EL0。并且通过t和h来表明具体使用的是EL0还是当前EL自己的SP。如下表:
备份程序状态寄存器(SPSR)
在AArch64状态,异常触发的EL会有自己的SPSR寄存器。
- EL1等级操作EL1_SPSR寄存器
- EL2等级操作EL2_SPSR寄存器
- EL3等级操作EL3_SPSR寄存器
处理器在处理异常前会先将处理器的状态保存到异常所陷入EL对应的SPSR寄存器中。比如处理器运行在EL0,当发生异常陷入EL1时,处理器就会状态保存到了EL1_SPSR寄存器中。保存在SPSR寄存器中的处理器状态一方面在从异常返回时能恢复处理器的先前状态,另一方面在运行过程中通过检查SPSR寄存器中的相关状态标志位也能确定处理器的状态和EL级别等信息。
复位
v8-A支持两种复位,冷复位和热复位。两者主要区别是冷复位会将debug功能模块也一同复位,热复位在默认情况则不会复位debug功能模块。
处理器收到复位信号后,依据处理器的具体实现进入所支持的最高EL(可能是EL3/EL2,甚至EL1),SP寄存器也使用的是对应EL下的寄存器。复位后程序起始执行地址是预先定义的,直接从这个预先定义的地址处开始执行。RVBAR_ELx寄存器保存着这个预先定义的起始执行地址。
可配置指令以及Trap
v8通过配置寄存器的某些bit位可以使能或禁止执行某些指令。或者允许执行到某些指令后能陷入到更高等级的EL。比如通过设置SCTLR_EL1.UCI位,当该bit配置为1时,执行cache维护相关指令便不会陷入EL1,但配置为0时,执行cache维护相关指令会陷入EL1。EL1/EL2/EL3下都有大量的可配置位,具体在manual都已列出。
系统调用(system call)
类似于早期架构中的SWI指令,v8架构下处理器又添加了SVC,HVC,SMC指令。通过指令能触发处理器陷入对应EL。
- SVC指令可让处理器进入EL1。这使得运行在EL0的软件有能力通过这条指令进入EL1
- HVC指令可让处理器进入EL2。但在EL0或EL1 secure state下执行这条指令是未定义状态。(换句话说EL1 none-secure才可以通过HVC陷入EL2?)。
- SMC指令可以产生异常进入EL3。但EL0下执行这条指令是未定义状态。
使用这些指令有如下约定:
- 当前EL低于所陷入EL或相等。
- 指令不会陷入不同的EL(也就是不会降低EL)。
具体比如在EL0执行SVC时可以陷入EL1,但在EL3执行SVC或HVC指令时,所产生的异常是需要在EL3下处理,并不会导致处理器切换到EL1或EL2。另外,通过配置是可以禁止这些系统调用产生异常的。比如在EL2或EL3下可以通过配置寄存器来禁止产生HVC异常,在EL3下可以通过配置来禁止SMC产生的异常等。
总结
v8相比v7变化挺大的,特别是支持了AArch64模式。但万变不离其宗,使用过程中注意细节差异。
参考文献
[1] ARM architecture reference manual,ARMv8, for ARMv8-A