ARM AArch32和AArch64通用寄存器、状态寄存器
文章目录
1. ARM CPU Mode
在学习ARM寄存器之前要先理解ARM CPU Mode的演变,因为逻辑寄存器通常会因为CPU Mode的不同有多个物理寄存器备份。本节以ARMv8体系结构为例,因为它包含了32位和64位的体系结构。
目标:
- 搞清楚ARM PL/EL的区别和联系
1.1 ARM32 CPU Mode
-
PL(Privilege Level)
-
ARMv8的PL继承自前身版本,分为PL0代表用户态和PL1代表系统态;此外,ARM将PL又划分为7种详细的Mode,其中1种(usr)属于PL0,另外6种属于PL1分别为:
- usr:用户模式
- fiq:处理FIQ快速中断模式
- irq:处理IRQ中断模式
- svc:Supervisor Mode 监视模式
- abt:Abort Mode 所有同内存保护相关的异常均在这种模式下执行
- und:处理无效指令的异常
- sys:系统模式
-
在ARMv7-A种引入了security扩展和虚拟化扩展
-
security扩展:支持可信赖的执行环境(trust execution environment, TEE)而引入。security扩展将ARM运行环境分成Secure World和Non-Secure(或Normal) World。
为了实现这两个World的切换,在原PL基础上增加了Monitor Mode。Mon应属于Secure World的PL1
-
虚拟化扩展:可以在一个物理硬件平台虚拟出多个虚拟化硬件平台供不同的用户使用。ARM为了支持虚拟化扩展,新增了一个PL等级PL2,并新增了Hypervisor Mode,Hyp仅存在于Non-Secure World
-
-
ARM32 CPU Mode
-
-
在ARM32种,mode有着十分重要的作用。PL只是一个虚拟出来的概念,在体系结构中并没有明确的结果表明为何种PL级别,而是通过不同的mode来标识级别。
1.2 ARM64 CPU Mode
-
EL(Exception Level)
-
ARMv8体系结构中,统一使用EL来进行权限描述,不仅包括AArch64,还包括32位体系结构AArch32。而对于纯64位体系结构,只有EL;对于32位体系结构因为要被64位兼容,则继续保留了mode、PL和EL。
- 如果实现的是64位体系结构,则只用EL描述,不存在mode概念
- 32位体系结构不能跑64位程序,一个AArch64产生的Exception不可能由AArch32来处理
-
EL和PL的基础上变化,主要体现在:
- PL0对应EL0
- PL2对应EL2
- 除了Secure下的Monitor外的PL1对应EL1
- 将Secure的Monitor单独抽取谁来,对应EL3
-
由于EL2的Hypervisor是虚拟扩展引入的,只存在于Non-Secure,所以得出EL模型如下:
-
EL只会在以下情况之一发生的时候才会发生Level Change
- 发生异常
- 从一个异常返回
- 处理器重启
- 从Debug状态返回
- 在Debug中,执行了DCPSx指令
- 在Debug中,执行了DRPS指令
-
ARM将PL和EL这两个架构统称为PE
1.3 EL、AArch32 modes 和 execution privilege 映射
Exception Level有四个等级:EL0, EL1, EL2, EL3
AArch32 modes有:User, Monitor, System, Supervisor, Abort, Undefined, IRQ和FIQ
-
在Secure状态:
- Monitor只在EL3执行,并且只有在EL3运行AArch32指令集时才能获得
- System, Supervisor, Abort, Undefined, IRQ, FIQ在:
- 当EL3运行AArch64时在EL1执行
- 当EL3运行AArch32时在EL3运行
总结来说:
- 当EL3在运行AArch64时:
- 不支持Monitor
- 当EL1运行AArch32,那么System, Supervisor, Abort, Undefined, IRQ和FIQ运行在Secure的EL1
- 当EL3在运行AArch32时:
- Monitor运行在Secure的EL3
- System, Supervisor, Abort, Undefined, IRQ和FIQ运行在Secure的EL3
- 不支持Secure下的EL1
-
在Non-secure状态:
- PL1 modes:System, Supervisor, Abort, Undefined, IRQ和FIQ总是运行在EL1
- User mode总是运行在EL0
- Hyp mode总是运行在Non-secure的EL2
得出下图所示(copy自ARM手册)
2. ARM32 寄存器
目标:
- 学习ARM32通用寄存器及其不同CPU Mode下的映射关系
- 学习ARM32基本状态寄存器
2.1 通用寄存器
-
ARM32有16个32位通用寄存器,其中:
- R0~R7
- 不分组寄存器,可以在所有mode下工作,是真正意义物理上被通用的寄存器
- R8~R14
- 分组寄存器,用于处理当前特定的处理器mode,每种模式都有专用的分组寄存器用于快速异常处理
- R13通常为Stack Pointer Register
- R14通常为Link Register
- R15
- 用作程序计数器PC
- R0~R7
-
ARM32 通用寄存器与物理寄存器映射表如下(copy自ARM手册)
- 从上表得知,通用寄存器一共有34个物理寄存器
- R0~R7共8个寄存器用于任意Mode
- R8~R12有两组共10个寄存器:一组用于FIQ,一组用于其他Mode
- R13共有8个物理寄存器,usr和sys共用一个,其他7个mode分别用一个
- R14共有7个物理寄存器,usr和sys共用一个,hyp使用的寄存器是特殊寄存器ELR_hyp(不属于通用寄存器),其他6个mode分别用一个
- R15只有一个物理寄存器
- USR和SYS Mode共享相同的通用寄存器
- 从上表得知,通用寄存器一共有34个物理寄存器
2.2 状态寄存器
- 从上面的映射表可以看出:
- ARM32共有1个CPSR(Current Program Status Register)
- 所有的CPU mode下都共享一个CPSR
- 7个备用的SPSR(Saved Program Status Register)
- usr和sys没有备份的SPSR之外,其他CPU mode都有一个自己的SPSR
- ARM32共有1个CPSR(Current Program Status Register)
3. ARM64寄存器
3.1 通用寄存器
-
ARM64通用寄存器不再像ARM32那样根据CPU mode设置相应的物理备份,而是所有EL下共享一堆通用寄存器,如下图:
-
ARM64共有31个64位通用寄存器,PC寄存器属于特殊寄存器,需要使用特殊指令进行访问
- X0~X7
- 参数寄存器,用作临时寄存器或可以保存的调用者保存的寄存器变量函数内的中间值
- X8
- 保存子程序的返回地址,尽量不要使用
- X9~X15
- 调用者保存的临时寄存器
- 如果调用者使用这些寄存器,需要提前把这些寄存器的值保存在自己的堆栈中,使用结束后恢复
- X16~X17
- 子程序内部调用临时寄存器
- X18
- 平台寄存器,尽量不要使用
- X19~X28
- 被调用者保存的临时寄存器
- 被调用者使用这些寄存器,也需要提前把寄存器的值保存在自己的堆栈中,使用后恢复
- X29
- 帧指针寄存器(FP)
- X30
- 链接寄存器(LR),用于保存函数调用的返回地址。例如,BL(Branch with Link)指令调用函数时,LR寄存器会存储调用时的下一条指令的地址,即返回地址。
- X0~X7
-
栈指针寄存器
- 每个实现的EL都会有专用的栈指针寄存器
- SP_EL0
- SP_EL1
- 如果EL2实现了,SP_EL2
- 如果EL3实现了,SP_EL3
- 每个实现的EL都会有专用的栈指针寄存器
-
ARM64通用寄存器可以分别当作64位和32位的寄存器使用
- 31 64-bit 寄存器,X0-X30.
- 31 32-bit 寄存器,W0-W30.
3.2 状态寄存器
-
ARM64使用PSTATE(Process State)来替换ARM32中的CPSR
-
ARM64一共有3个SPSR,分别为SPSR_EL1,SPSR_EL2,SPSR_EL3