处理器执行状态
ARMv8处理器支持两种执行状态——AArch64状态和AArch32状态。AArch64状态是ARMv8新增的64位执行状态,而AArch32是为了兼容ARMv7架构的32位执行状态。当处理器运行在AArch64状态下时运行A64指令集;而当运行在AArch32状态下时,可以运行A32指令集或者T32指令集。
Aarch64异常等级
AArch64状态的异常等级(exception level)确定了处理器当前运行的特权级别,类似于ARMv7架构中的特权等级。
- EL0:用户特权,用于运行普通用户程序。
- EL1:系统特权,通常用于运行操作系统。
- EL2:运行虚拟化扩展的虚拟监控程序(hypervisor)。
- EL3:运行安全世界中的安全监控器(secure monitor)。
ARMv8寄存器
通用寄存器
AArch64运行状态支持31个64位的通用寄存器,分别是X0~X30寄存器,而AArch32状态支持16个32位的通用寄存器。通用寄存器除了用于数据运算和存储之外,还可以在函数调用过程中起到特殊作用,ARM64架构的函数调用标准和规范对此有所约定。
在AArch64状态下,使用X来表示64位通用寄存器,如X0、X30等。另外,还可以使用W来表示低32位的数据,如w0表示X0寄存器的低32位数据,w1表示X1寄存器的低32位数据
程序状态寄存器
在AArch64里使用PSTATE寄存器来表示。
特殊寄存器
ARMv8架构除了支持31个通用寄存器之外,还提供多个特殊的寄存器:
零寄存器
ARMv8架构提供两个零寄存器(zero register),这些寄存器的内容全是0,可以用作源寄存器,也可以用作目标寄存器。WZR寄存器是32位的零寄存器,XZR是64位的零寄存器。
PC寄存器
PC寄存器通常用来指向当前运行指令的下一条指令的地址,用于控制程序中指令的运行顺序,但是编程人员不能通过指令来直接访问它。
SP寄存器
ARMv8架构支持4个异常等级,每一个异常等级都有一个专门的SP寄存器SP_ELn,如处理器运行在EL1时选择SP_EL1寄存器作为SP寄存器。
- SP_EL0:EL0下的SP寄存器。
- SP_EL1:EL1下的SP寄存器。
- SP_EL2:EL2下的SP寄存器。
- SP_EL3:EL3下的SP寄存器。
当处理器运行在比EL0高的异常等级时,处理器可以访问如下寄存器。当前异常等级对应的SP寄存器SP_ELn。
EL0对应的SP寄存器SP_EL0可以当作一个临时寄存器,如Linux内核里使用该寄存器存放进程的task_struct数据结构的指针。
当处理器运行在EL0时,它只能访问SP_EL0,而不能访问其他高级的SP寄存器。
保存处理状态寄存器
当我们运行一个异常处理器时,处理器的处理状态会保存到保存处理状态寄存器(Saved Process StatusRegister,SPSR)里,这个寄存器非常类似于ARMv7架构中的CPSR。当异常将要发生时,处理器会把PSTATE寄存器的值暂时保存到SPSR里;当异常处理完成并返回时,再把SPSR的值恢复到PSTATE寄存器。SPSR的格式如图1.30所示,SPSR的重要字段如表1.6所示:
ELR
ELR存放了异常返回地址。
CurrentEL寄存器
该寄存器表示PSTATE寄存器中的EL字段,其中保存了当前异常等级。使用MRS指令可以读取当前异常等级。
- 0:表示EL0。
- 1:表示EL1。
- 2:表示EL2。
- 3:表示EL3。
DAIF寄存器
该寄存器表示PSTATE寄存器中的{D, A, I, F}字段。
SPSel寄存器
该寄存器表示PSTATE寄存器中的SP字段,用于在SP_EL0和SP_ELn
中选择SP寄存器。
PAN寄存器
该寄存器表示PSTATE寄存器中的PAN(Privileged Access Never,特权禁止访问)字段。可以通过MSR和MRS指令来设置PAN寄存器。
UAO寄存器
该寄存器表示PSTATE寄存器中的UAO(User Access Override,用户访问覆盖)字段。可以通过MSR和MRS指令来设置UAO寄存器。
NZCV寄存器
该寄存器表示PSTATE寄存器中的{N,Z,C,V}字段。
系统寄存器
除了上面介绍的通用寄存器和特殊寄存器之外,ARMv8架构还定义了很多的系统寄存器,通过访问和设置这些系统寄存器来完成对处理器不同的功能配置。在ARMv7架构里,我们需要通过访问CP15协处理器来间接访问这些系统寄存器,而在ARMv8架构中没有协处理器,可直接访问系统寄存器。ARMv8架构支持如下7类系统寄存器:
- 通用系统控制寄存器
- 调试寄存器
- 性能监控寄存器
- 活动监控寄存器
- 统计扩展寄存器
- RAS寄存器
- 通用定时器寄存器
系统寄存器支持不同的异常等级的访问,通常系统寄存器会使用“Reg_ELn
”的方式来表示。
Reg_EL1:处理器处于EL1、EL2以及EL3时可以访问该寄存器。
Reg_EL2:处理器处于EL2和EL3时可以访问该寄存器。
大部分系统寄存器不支持处理器处于EL0时访问,但也有一些例外,如CTR_EL0寄存器。
相关参考
- 《奔跑吧,Linux内核》