根据实现选择,体系结构支持多级执行特权,由从EL0到EL3的不同异常级别表示。EL0对应于最低的特权级别,通常被描述为无特权。应用层程序员模型是在EL0上执行软件的程序员模型。
系统软件决定异常级别,因此决定软件运行的特权级别。当操作系统同时支持EL1和EL0执行时,应用程序通常在EL0上运行。
- 允许操作系统以唯一的或共享的方式将系统资源分配给应用程序。
- 从其他进程中提供一定程度的保护,因此有助于保护操作系统免受软件故障的影响。
在EL0之上的任何异常级别执行通常被称为特权执行。
Registers in AArch64 state
R0-R30
31个通用寄存器,从R0到R30。每个寄存器可按以下方式访问:
一个64位通用寄存器,名为x0到x30。
一个32位通用寄存器,名为W0到W30。
X30通用寄存器用作过程调用链接寄存器。
在指令编码中,值0b11111(31)用来表示ZR(零寄存器)。这表示参数接受值0,但不表示ZR是作为物理寄存器实现的。
SP
一个64位专用堆栈指针寄存器。堆栈指针最低有效的32位可以通过寄存器名WSP访问。
在指令中使用SP作为操作数,表示使用当前堆栈指针。
堆栈指针对齐到16字节边界在EL1是可配置的。
PC
保存当前指令地址的64位程序计数器。
软件不能直接写入PC。它只能在分支、异常条目或异常返回上更新。
试图执行未按字对齐的A64指令会产生PC对齐错误
V0-V31
32个SIMD&FP寄存器,从V0到V31。每个寄存器可按以下方式访问:
- A 128-bit register named Q0 to Q31.
- A 64-bit register named D0 to D31.
- A 32-bit register named S0 to S31.
- A 16-bit register named H0 to H31.
- An 8-bit register named B0 to B31.
- A 128-bit vector of elements.
- A 64-bit vector of elements.
当寄存器名所描述的位的数量不占据整个SIMD&FP寄存器时,它指的是最不重要的位。
FPCR, FPSR两个SIMD和浮点控制和状态寄存器
Process state, PSTATE
处理状态或PSTATE是处理状态信息的抽象。所有的指令集都提供了操作PSTATE元素的指令。
以下PSTATE信息可通过EL0访问:
状态标志
标志设置指令设置这些。它们是:
N :负状态标志。如果指令的结果是2的带符号整数,则PE将其设为:
1:如果结果是负数。
0:如果结果是正的或零。
Z :零状态标志。
1:如果指令的结果是零。
0:如果指令的结果不是零。
结果为零通常表示比较结果相等。
C:进位状态标志。设置为:
1:如果指令导致一个进位条件,例如一个由加法产生的无符号溢出。
0: otherwise.
V:溢出状态标志。设置为:
1:如果指令导致溢出,例如由加法产生的带符号溢出。
0: otherwise
条件指令测试N、Z、C和V条件标志,并将它们与指令的条件代码组合起来,以确定指令是否必须执行。这样,指令的执行取决于前一个操作的结果。
异常屏蔽位
D:调试异常掩码位。当启用EL0来修改掩码位时,该位是可见的,可以修改。但是,EL0在体系结构上忽略了这一点。
A: SError中断掩码位。
I:IRQ中断掩码位。
F: FIQ中断掩码位。
每一位的值是:
0:异常不被屏蔽。
1:异常被屏蔽。
使用AArch64状态访问EL0取决于SCTLR_EL1.UMA。
在EL0访问PSTATE字段
在使用AArch64状态的EL0上,可以使用特殊用途的寄存器来访问PSTATE字段,可以使用MRS指令直接读取PSTATE字段,并使用MSR (register)指令直接写入PSTATE字段了在PE位于EL0时使用AArch64访问保存AArch64状态的PSTATE字段的专用寄存器。所有其他PSTATE字段在EL0上没有直接读写访问。
软件也可以使用MSR (immediate)指令直接写入PSTATE.{D, A, I, F}。可以直接写入PSTATE. {D, A, I, F} 的MSR (immediate)操作数。当PE在EL0使用AArch64状态。
但是,访问PSTATE.{D, A, I, F}字段在EL0使用AArch64状态取决于SCTLR_EL1.UMA。
对PSTATE字段的写操作对PE操作的各个方面都有副作用。所有这些副作用,是有保证的:
- 对执行流中较早的指令不可见。
- 对执行流中的后续指令可见。
System registers
系统寄存器为执行控制、状态和一般系统配置提供支持。在EL0中,大多数系统寄存器是不可访问的。
然而,一些系统寄存器可以配置为允许从在EL0执行的软件进行访问。从EL0到系统寄存器的任何访问都禁用了访问权限,这将导致指令表现为未定义。可以从EL0访问的寄存器有:
Cache ID registers
CTR_EL0和DCZID_EL0寄存器为EL0缓存管理支持提供实现参数。
Debug registers
MDCCSR_EL0、DBGDTR_EL0、DBGDTRRX_EL0和DBGDTRTX_EL0寄存器支持调试通信通道。
Performance Monitors registers
Performance Monitors扩展提供计数器和配置寄存器。在EL1或更高的异常级别执行的软件可以将其中一些寄存器配置为可在EL0访问。
Activity Monitors registers
活动监视器扩展提供计数器和配置寄存器。在EL1或更高的异常级别执行的软件可以将这些寄存器配置为可在EL0访问。
Thread ID registers
TPIDR_EL0和TPIDRRO_EL0寄存器是两个具有不同访问权限的线程ID寄存器。
Timer registers
在ARMv8中执行以下操作:
- 使用CNTFRQ_EL0读取对系统时钟频率的访问。
- 物理和虚拟计时器计数寄存器,CNTPCT_EL0和CNTVCT_EL0。
- 物理上计数比较、下计数值和计时器控制寄存器CNTP_CVAL_EL0、CNTP_TVAL_EL0和CNTP_CTL_EL0。
- 虚拟计数比较、下计数值和计时器控制寄存器CNTV_CVAL_EL0、CNTV_TVAL_EL0和CNTV_CTL_EL0。
软件控制功能和EL0
异常处理
在Arm架构中,异常会导致程序流的更改。异常处理程序的执行从与所采取的异常相关的已定义向量开始,其异常级别高于EL0。
异常包括:
- Interrupts.
- Memory system aborts.
- 试图执行未定义的指令时生成的异常。
- 系统调用。
- Secure monitor or Hypervisor traps.
- Debug exceptions.
异常处理的大多数细节对应用程序级软件是不可见的,
SVC指令导致一个管理器调用异常。这为非特权软件提供了一种对操作系统进行系统调用的机制。
BRK指令生成一个断点指令异常。这提供了一种使用在相同PE上执行的调试器来调试软件的机制,
BRK指令只支持A64指令集。T32和A32指令集中的等效指令是BKPT。
等待中断和事件
发出WFI指令表示在WFI唤醒事件发生之前不需要进一步执行,这允许进入低功率状态。
发出WFE指令表示在WFE唤醒事件发生之前不需要进一步执行,这允许进入低功率状态。
The YIELD instruction
YIELD指令提供了一个提示,说明线程执行的任务的重要性很低,因此它可以YIELD,这种机制可用于提高对称多线程(SMT)或对称多处理(SMP)系统的整体性能。
YIELD指令可能被使用的例子包括位于自旋锁中的线程,或者SMP系统中snoop位的仲裁优先级被修改的地方。YIELD指令允许SMT和SMP系统之间的二进制兼容性。
YIELD指令是一个NOP (无操作)提示指令。
YIELD指令在单线程系统中没有任何作用,但是这类系统的开发人员可以使用该指令来标记将来迁移到多处理器或多线程系统的预期用途。操作系统可以在需要YIELD提示的地方使用YIELD,因为它们知道,如果没有实现上的好处,那么它将被视为NOP。
应用程序级缓存管理
在EL0上,可以使用SCTLR_EL1系统寄存器从更高级别的特权启用少量缓存管理指令。从EL0到禁用访问权限的操作的任何访问都将导致该指令表现为未定义的。
与调试相关的说明
引用BRK指令,BRK指令生成断点指令异常。此外,在AArch64状态和AArch32状态下,HLT指令会导致PE停止执行并进入调试状态。这为使用PE外部的调试器调试软件提供了一种机制
在AArch32状态下,以前版本的体系结构定义了DBG指令,这可以为调试系统提供提示。在ARMv8中,这条指令作为NOP执行。Arm不赞成使用DBG指令。
关于 PSTATE.DIT
Data Independent Timing (DIT) bit.
只有在实现ARMv8.4-DIT时才会实现这个位。
在重置为AArch64状态时,该位设置为0。
为数据处理指令提供了独立的定时功能
PSTATE。说,CPSR。说字段。
当 PSTATE.DIT为1时:
- DIT中列出的指令是必须要有的;
- 与任何寄存器中提供的数据值和NZCV标志的值无关的时序。
- 对异步异常的响应不会根据其寄存器中提供的值或NZCV标志的值而变化。
- 所有加载和存储都必须具有对加载或存储的数据的值不敏感的定时。
ARM建议ARMv8.3指针身份验证指令的时间不依赖于指针身份验证中使用的键值,而与PSTATE.DIT无关。
当PSTATE.DIT的值是0,架构没有声明任何指令的时序属性。然而,这些指令很可能具有在许多情况下数据不变的时序。
对应的DIT位被添加到AArch64状态的PSTATE和AArch32状态的CPSR。
当异常从AArch64状态转移到AArch64状态时,PSTATE.DIT将它复制到SPSR_ELx.DIT。
当一个异常从AArch32状态变为AArch64状态时,CPSR.DIT将它复制到SPSR_ELx.DIT。
当一个异常从AArch64状态返回到AArch64状态时,SPSR_ELx.DIT复制到PSTATE.DIT。
当一个异常从AArch64状态返回到AArch32状态时,SPSR_ELx.DIT它被复制到CPSR.DIT。
PSTATE.DIT 它可以在所有异常级别读写。
PSTATE.DIT 进入调试状态时DIT没有改变。
PSTATE.DIT 它不能保证在调试状态下有任何效果。