3.ARM Processor Modes and Registers
ARM架构是一种多模式架构。在引入安全扩展(Security Extensions)之前,它有七种处理器模式,如下表所示。其中有六种特权模式和一种非特权的用户模式。特权指的是执行某些在用户(非特权)模式下无法完成的任务的能力。在用户模式下,对于影响整体系统配置的操作存在限制,例如MMU(内存管理单元)配置和缓存操作。模式与异常事件相关。
TrustZone安全扩展的引入为处理器创建了两个独立于特权和处理器模式的安全状态,并新增了一个监控模式(Monitor mode),作为安全状态与非安全状态之间的桥梁。每个安全状态都有各自独立的模式。
目前来说,对于实现TrustZone扩展的处理器,系统安全性是通过将设备的所有硬件和软件资源划分为两部分来实现的:一种是在安全子系统中的安全世界(Secure world),另一种是用于其他所有内容的普通(非安全)世界(Normal/Non-secure world)。当处理器处于非安全状态时,它无法访问分配给安全状态的内存。
在这种情况下,安全监控器(Secure Monitor)充当在这两个世界之间切换的桥梁。如果实现了安全扩展,则在监控模式(Monitor mode)下执行的软件会控制处理器在安全和非安全状态之间的转换。
ARMv7-A架构的虚拟化扩展增加了一个管理程序模式(Hyp),这是在现有特权模式之外的另一种模式。虚拟化使得多个操作系统可以在同一系统上共存和运行。因此,ARM虚拟化扩展使得在同一平台上运行多个操作系统成为可能。
如果实现了虚拟化扩展,则会有一个不同于以前架构的特权模型。在非安全状态下,可能存在三个特权级别:PL0、PL1和PL2。
PL0
应用软件的特权级别,运行在用户模式(User mode)下。在用户模式下运行的软件被称为非特权软件。此类软件无法访问架构的一些功能,特别是它不能更改许多配置设置。
在PL0级别运行的软件只能进行非特权内存访问。
PL1
所有除用户模式(User mode)和Hyp模式以外的模式下的软件执行都在PL1级别。通常,操作系统软件在PL1级别运行。
PL1模式指的是除用户模式和Hyp模式之外的所有模式。
操作系统通常在所有PL1模式下运行,其应用程序则在PL0(用户模式)下执行。
PL2
Hyp模式通常由管理程序(hypervisor)使用,它负责控制并可以在运行于PL1级别的来宾操作系统之间进行切换。
如果实现了虚拟化扩展,则管理程序将在PL2(Hyp模式)级别执行。管理程序将控制并使多个操作系统能够在同一处理器系统上共存并执行。
这些特权级别与TrustZone的安全(Secure)和普通(非安全,Non-secure)设置是分开的。
注意
特权级别定义了在当前安全状态下访问资源的能力,但并不意味着对另一个安全状态下资源的访问能力。
特定处理器模式和状态的存在取决于处理器是否实现了相关的架构扩展。
通用操作系统(如Linux)及其应用程序通常运行在非安全状态下。安全状态则通常由特定厂商的固件或对安全敏感的软件占据。在某些情况下,运行在安全状态下的软件甚至比运行在非安全状态下的软件拥有更高的特权。
当前处理器模式和执行状态包含在当前程序状态寄存器(CPSR)中。处理器状态和模式的改变可以由特权软件显式完成,或者是由于发生异常而导致的。
3.1 Registers
ARM架构提供了16个32位通用寄存器(R0-R15)供软件使用。其中15个(R0-R14)可用于通用数据存储,而R15则是程序计数器,其值会随着内核执行指令而改变。软件对R15的显式写操作将改变程序的执行流程。软件还可以访问CPSR(当前程序状态寄存器),并访问从之前执行模式中保存的CPSR副本,称为保存的程序状态寄存器(SPSR)。
虽然软件可以访问寄存器,但根据软件执行的模式以及所访问的寄存器,某个寄存器可能对应不同的物理存储位置。这种情况称为“寄存器银行”(banking)。在下图中,阴影部分的寄存器是银行化的(banked)。它们使用物理上独立的存储空间,通常只有当进程在特定模式下执行时才能访问这些寄存器。
在所有模式下,“低寄存器”和R15共享相同的物理存储位置。上图显示了一些“高寄存器”在某些模式下是银行化的。例如,R8-R12在FIQ模式下是银行化的,也就是说,对它们的访问会指向不同的物理存储位置。在除了用户模式(User)和系统模式(System)以外的所有模式下,R13和SPSR是银行化的。
对于银行化的寄存器,软件通常不会指定要访问的是哪一个寄存器实例,这是由访问发生的模式隐含决定的。例如,在用户模式(User mode)中执行并指定了R13的程序将访问R13_usr。在SVC模式下执行并指定了R13的程序将访问R13_svc。
R13(在所有模式下)是操作系统的栈指针,但在不需要进行栈操作时,也可以用作通用寄存器。
R14(链接寄存器,Link Register)保存了使用带链接(BL)指令进入的子程序的返回地址。当它不用于支持从子程序返回时,也可以用作通用寄存器。R14_svc、R14_irq、R14_fiq、R14_abt和R14_und与R15类似,用于在中断和异常发生时保存返回值,或者在中断或异常例程中执行分支和链接指令时使用。
R15是程序计数器,保存当前的程序地址(实际上,在ARM状态下总是指向当前指令前面的8个字节,在Thumb状态下指向当前指令前面的4个字节,这是原始ARM1处理器的三阶段流水线的遗留)。在ARM状态下读取R15时,位[1:0]为零,位[31:2]包含PC。在Thumb状态下,位[0]总是读取为零。
重置后的R0-R14值是不可预测的。SP(栈指针)必须在使用栈之前由引导代码为每个模式进行初始化。《ARM架构过程调用标准》(AAPCS)或《ARM嵌入式ABI》(AEABI)规定了软件应如何使用通用寄存器,以便在不同的工具链或编程语言之间进行互操作。
3.1.1 Hypervisor mode
支持虚拟化扩展的实现具有在管理程序(Hyp)模式下可用的额外寄存器。管理程序模式在PL2特权级别上运行。它有其自己的R13(SP)和SPSR版本。它使用用户模式链接寄存器来存储函数返回地址,并有一个专用寄存器,称为ELR_hyp,用于存储异常返回地址。Hyp模式仅在普通世界中可用,并提供虚拟化功能,仅在此模式中可访问。有关更多信息,请看相关章节。
3.1.2 Program Status Registers
在任何给定时刻,您都可以访问16个寄存器(R0-R15)和当前程序状态寄存器(CPSR)。在用户模式下,访问的是CPSR的受限形式,称为应用程序状态寄存器(APSR)。
当前程序状态寄存器(CPSR)用于存储:
APSR标志。
当前处理器模式。
中断禁用标志。
当前处理器状态(ARM、Thumb、ThumbEE或Jazelle)。
字节序(Endianness)。
IT块的执行状态位。
程序状态寄存器(PSRs)构成了一组额外的银行化寄存器。每个异常模式都有其自己的保存程序状态寄存器(SPSR),其中会存储异常发生之前的CPSR副本,并在异常发生时自动保存。这些寄存器无法从用户模式访问。
应用程序程序员必须使用APSR来访问CPSR中可以在非特权模式下更改的部分。APSR只能用来访问N、Z、C、V、Q和GE[3:0]位。这些位通常不被直接访问,而是由条件代码设置指令和由条件代码执行的指令来设置。例如,CMP R0, R1指令比较R0和R1的值,如果相等则设置零标志(Z)。
以下是翻译内容:
各个独立的位代表以下含义:
N – 从ALU(算术逻辑单元)运算得到的负结果。
Z – 从ALU运算得到的零结果。
C – ALU运算的进位输出。
V – ALU运算溢出。
Q – 累积饱和(也称为粘性)。
J – 表示内核是否处于Jazelle状态。
GE[3:0] – 被某些SIMD指令使用。
IT[7:2] – Thumb-2指令组的If-Then条件执行。
E 位 – 控制加载/存储的字节序。
A 位 – 禁用异步中止。
I 位 – 禁用IRQ(普通中断请求)。
F 位 – 禁用FIQ(快速中断请求)。
T 位 – 指示内核是否处于Thumb状态。
M[4:0] – 指定处理器模式(FIQ、IRQ等)。
处理器可以使用直接写入CPSR模式位的指令在模式之间进行切换。更常见的是,处理器会因异常事件自动更改模式。在用户模式下,无法操作控制处理器模式的PSR位[4:0]或控制是否启用或禁用异常的A、I和F位。
3.1.3 Coprocessor 15
CP15,系统控制协处理器,提供对内核许多功能的控制。它可以包含最多16个32位主寄存器。对CP15的访问受到特权控制,且用户模式下无法访问。CP15寄存器访问指令指定所需的主寄存器,指令中的其他字段用于更准确地定义访问的地址并增加CP15中物理32位寄存器的数量。这16个主寄存器被命名为c0到c15,但通常被简称。例如,CP15系统控制寄存器称为CP15.SCTLR。
下表总结了Cortex-A系列处理器中使用的一些更相关的协处理器寄存器的功能。
所有系统架构功能都是通过从协处理器15内的一组寄存器(CRn)读取或写入通用处理器寄存器(Rt)来控制的。指令的Op1、Op2和CRm字段也可用于选择寄存器或操作。其格式如示例如下图所示。
我们将不会详细介绍各种CP15寄存器,因为这些参考信息可以很容易地从《ARM架构参考手册》或产品文档中获取。
作为如何从这些寄存器之一读取信息的示例,我们将以只读主ID寄存器(MIDR)为例,其格式如下图所示。
在特权模式下,我们可以使用以下指令读取该寄存器:
MRC p15, 0, R1, c0, c0, 0
结果将被放入寄存器R1中,告知软件它正在运行的处理器类型。对于ARM Cortex处理器,结果的解释如下:
位[31:24] – 实现者,对于ARM设计的处理器,这将是0x41。
位[23:20] – 变体,显示处理器的修订号。
位[19:16] – 架构,对于ARM架构v7,该值为0xF。
位[15:4] – 部件号,例如Cortex-A8处理器的部件号为0xC08。
位[3:0] – 修订,显示处理器的补丁修订号。
3.1.4 System control register (SCTLR)
SCTLR是使用CP15访问的许多寄存器之一,它控制标准内存、系统功能,并提供内核中实现的功能的状态信息。
系统控制寄存器只能从PL1或更高级别访问。
各个独立的位代表以下含义:
TE – Thumb异常使能。控制异常是在ARM状态还是Thumb状态下发生。
NMFI – 不可屏蔽的FIQ(NMFI)支持。
EE – 异常的字节序。这定义了异常进入时CPSR.E位的值。
U – 表示对齐模型的使用。
FI – FIQ配置使能。
V – 该位选择异常向量表的基地址。
I – 指令缓存使能位。
Z – 分支预测使能位。
C – 缓存使能位。
A – 对齐检查使能位。
M – 启用MMU(内存管理单元)。
引导代码序列的一部分通常会设置CP15(系统控制寄存器)中的Z位,以启用分支预测。示例代码序列在下图中显示。