1 Armv8架构简介
1.1 关于Arm架构
本架构参考手册中描述的Arm架构定义了一个抽象机器的行为,称为一个处理元件,通常缩写为PE (processing elements)。符合Arm架构的实现必须符合所描述的处理元件的行为。它不打算描述如何构建PE的实现,也不打算限制这些实现超出已定义的行为的范围。
除了体系结构指定不同的地方,符合Arm体系结构的实现的程序员可见行为必须与程序在处理元件上的简单顺序执行相同。这个程序员可见的行为不包括程序的执行时间。
Arm架构参考手册也描述了软件使用处理元件的规则。
Arm体系结构是一种精简指令集计算机(RISC)体系结构,具有以下RISC体系结构特点:
- 一个大型统一寄存器文件。
- 一个加载/存储架构,数据处理操作只对寄存器内容进行操作,而不是直接对内存内容进行操作。
- 简单的寻址模式,所有加载/存储地址仅由寄存器内容和指令字段决定。
该体系结构定义了PE与内存(包括缓存)的交互,并包括一个内存转换系统。它还描述了多个PEs如何相互交互以及如何与系统中的其他观察者交互。
Arm架构支持跨广泛性能点的实现。实现规模、性能和非常低的功耗是Arm架构的关键属性。
Armv8体系结构的一个重要特性是向后兼容性,以及在广泛的标准和更专业的用例中实现最佳实现的自由度。Armv8架构支持:
- 64位执行状态AArch64。
- 32位执行状态AArch32,与Arm架构的早期版本兼容。
两种执行状态都支持SIMD和浮点指令:
AArch32状态规定:
- 在32位通用寄存器上操作的基本指令集中的SIMD指令。
- 在SIMD和浮点寄存器上操作的高级SIMD指令(SIMD&FP寄存器)文件。
- 对SIMD&FP寄存器文件中的寄存器进行操作的浮点指令。
AArch64状态规定:
- 高级SIMD指令,操作在SIMD&FP寄存器文件中的寄存器。
- 对SIMD&FP寄存器中的寄存器进行操作的浮点指令。
[注]
SIMD :Single Instruction Multiple Data,单指令多数据流
RISC:Reduced Instruction Set Computing 精简指令集计算机
精简指令集与复杂指令集的区别:
从硬件角度来看CISC处理的是不等长指令集,它必须对不等长指令进行分割,因此在执行单一指令的时候需要进行较多的处理工作。而RISC执行的是等长精简指令集,CPU在执行指令的时候速度较快且性能稳定。因此在并行处理方面RISC明显优于CISC,RISC可同时执行多条指令,它可将一条指令分割成若干个进程或线程,交由多个处理器同时执行。由于RISC执行的是精简指令集,所以它的制造工艺简单且成本低廉。
从软件角度来看,CISC运行的则是我们所熟识的DOS、Windows操作系统。而且它拥有大量的应用程序。因为全世界有65%以上的软件厂商都理为基于CISC体系结构的PC及其兼容机服务的,像赫赫有名的Microsoft就是其中的一家。而RISC在此方面却显得有些势单力薄。虽然在RISC上也可运行DOS、Windows,但是需要一个翻译过程,所以运行速度要慢许多。
1.2 架构配置文件
自从Arm架构被引入以来,它已经有了显著的发展,并且Arm还在继续开发它。到目前为止,已经定义了该体系结构的八个主要版本,由版本号1到8表示。其中,前三个版本已经过时了。
通用名称AArch64和AArch32描述了64位和32位的执行状态:
- AArch64是64位的执行状态,这意味着地址保存在64位寄存器中,基本指令集中的指令可以使用64位寄存器进行处理。AArch64状态支持A64指令集。
- AArch32是32位的执行状态,这意味着地址保存在32位寄存器中,基本指令集中的指令使用32位寄存器进行处理。AArch32 state支持T32和A32指令集。
Arm定义了三个架构配置文件:
A (Application profile) 应用程序配置文件:
- 支持基于内存管理单元(MMU)的虚拟内存系统架构(VMSA)。
- 支持A64、A32和T32指令集。
R (Real-time profile) 实时配置文件:
- 支持基于内存保护单位(MPU)的受保护内存系统架构(PMSA)。
- 支持A32和T32指令集。
M (Microcontroller profile) 微控制器配置文件:
- 实现了一个设计用于低延迟中断处理的程序员模型,使用寄存器的硬件堆叠,支持用高级语言编写中断处理程序。
- 实现R-profile PMSA的一个变体。
- 支持T32指令集的变体。
1.3
Armv8对Arm架构进行了重大更改,同时与以前版本的架构保持了高度的一致性。Armv8体系结构参考手册对用于描述体系结构的术语做了重大修改,本部分介绍了Armv8体系结构的概念和相关的术语。
1.3.1执行状态
执行状态定义PE执行环境,包括:
- 支持的寄存器宽度。
- 支持的指令集。
- 重要方面:
- 异常模式。
- 虚拟内存系统架构(VMSA)。
- 程序员模型。
执行状态包括:
AArch64 64位执行状态,此执行状态:
- 提供31个64位通用寄存器,其中X30用作过程链接寄存器。
- 提供64位程序计数器(PC)、堆栈指针(SPs)和异常链接寄存器(ELRs)。
- 为SIMD矢量和标量浮点支持提供32个128位寄存器。
- 提供单个指令集A64。
- 定义Armv8异常模型,有多达四个异常级别,即EL0 - EL3,它提供了一个执行特权层次结构。
- 提供对64位虚拟地址的支持。
- 定义包含PE状态的多个进程状态(PSTATE)元素。
- A64指令集包括直接操作各种PSTATE元素的指令。
- 使用后缀来命名每个系统寄存器,该后缀表示可以访问寄存器的最低异常级别。
AArch32 32位执行状态,此执行状态:
- 提供13个32位通用寄存器和一个32位PC、SP和链接寄存器(LR)。
LR既用作ELR,也用作过程链接寄存器。
其中一些寄存器有多个已存储的实例,可在不同的PE模式下使用。
- 提供一个单一的ELR,用于从Hyp模式返回异常。[注] HYP 超级监护者模式
- 为高级SIMD矢量和标量浮点支持提供32位寄存器。
- 提供两个指令集,A32和T32。
- 支持基于PE模式的Armv7-A异常模型,并将其映射到基于异常级别的Armv8异常模型上。
- 提供对32位虚拟寻址的支持。
- 定义包含PE状态的多个进程状态(PSTATE)元素。A32和T32指令集包括直接操作各种PSTATE元素的指令,以及使用应用程序状态寄存器(APSR)或当前程序状态寄存器(CPSR)访问PSTATE的指令
1.3.2 Armv8指令集
在Armv8中,合适的指令集取决于执行状态:
AArch64
AArch64状态只支持一个称为A64的指令集。这是一个固定长度的指令集,使用32位指令编码。
AArch32
AArch32状态支持以下指令集:
A32这是一个固定长度的指令集,使用32位指令编码。
T32这是一个可变长度的指令集,同时使用16位和32位指令编码。
1.3.3 系统寄存器
系统寄存器提供架构特性的控制和状态信息。
系统寄存器使用标准的命名格式:<register_name>,<bit_field_name>来标识特定寄存器以及寄存器中的控制位和状态位。
位也可以通过<register_name>[x:y]或位[x:y]的形式描述其数值位置。
在AArch64状态下,大多数寄存器名都包含最低的异常级别,可以通过寄存器名的后缀访问寄存器:
- <register_name>_ELx,其中x为0,1,2或3。
系统寄存器包括:
- 以下是本手册中描述的寄存器
- 一般系统控制寄存器。
- 调试寄存器。
- 通用计时器寄存器。
- 可选,性能监视器寄存器。
- 可选,活动监视寄存器。
- 可选的,在其他Arm架构规范中定义的以下寄存器组中的一个或多个:
- 跟踪系统寄存器,在嵌入式跟踪宏单元体系结构规范中定义,ETMv4。
- 可伸缩向量扩展系统寄存器,
- 通用中断控制器(GIC)系统寄存器。
- 扩展系统寄存器,RAS扩展是Armv8.2体系结构的强制性扩展,也是Armv8.0和Armv8.1体系结构的可选扩展。
1.4 Arm内存模型
Arm内存模型支持:
- 在未对齐的内存访问上生成异常。
- 限制应用程序访问指定的内存区域。
- 将执行指令提供的虚拟地址(VAs)转换为物理地址(PAs)。
- 在大端(big-endian)和小端(little-endian)之间改变多字节数据的解释。
- 控制访问内存的顺序。
- 控制缓存和地址转换结构。
- 由多个PEs同步访问共享内存。
- 控制和防止投机性访问内存的屏障。
VA支持取决于执行状态,如下所示:
AArch64状态
支持64位虚拟寻址,转换控制寄存器决定支持的VA范围。EL1和EL0的执行支持两个独立的VA范围,每个范围都有自己的转换控件。
AArch32状态
支持32位虚拟寻址,转换控制寄存器决定支持的VA范围。为了在EL1和EL0执行,系统软件可以把VA范围分成两个子程序,每个子程序都有自己的转换控制。
所支持的PA空间是实现定义的,可以由系统软件发现。无论执行状态如何,虚拟内存系统架构(VMSA)都可以将VAs转换为受支持的PA空间内的内存块或内存页。
2 AArch64应用程序级程序员模型
2.1 关于应用程序级程序员模型
本章包含开发程序所需的程序员模型信息。
本章中的信息不同于在操作系统或更高级别的系统软件下服务和支持应用程序执行所需的系统信息。但是,需要了解一些系统信息,才能将应用程序级程序员的模型放到上下文中。
根据不同的实现选择,体系结构支持多个执行特权级别,由从EL0到EL3的不同异常级别表示。EL0对应于最低的特权级别,通常被描述为无特权。
应用程序级程序员模型是在EL0上执行软件的程序员模型。
系统软件决定异常级别,从而决定软件运行时的特权级别。当操作系统同时支持在EL1和EL0上执行时,应用程序通常在EL0上无特权运行。
- 允许操作系统以唯一的或共享的方式将系统资源分配给应用程序。
- 提供一定程度的保护,使其不受其他进程的影响,从而帮助保护操作系统不受软件故障的影响。
本章指出了系统级别的理解在哪些地方是必要的,在相关的地方,它给出了系统级别描述的参考。
在EL0以上的任何异常级别上执行通常称为特权执行。
2.2
2.2.1 AArch64状态的寄存器
在AArch64应用层视图中,一个Arm处理元件有:
R0-R30 31个通用寄存器,每个寄存器可通过以下方式存取:
一个名为X0到X30的64位通用寄存器。
一个名为W0到W30的32位通用寄存器。
X30通用寄存器用作过程调用链接寄存器。
SP 一个64位专用堆栈指针寄存器。堆栈指针的最低32位可以使用寄存器名WSP访问。
在指令中使用SP作为操作数,表示使用当前堆栈指针。
PC 保存当前指令地址的64位程序计数器。
软件不能直接写入PC。它只能在分支、异常条目或异常返回上更新。
32个SIMD&FP寄存器,V0到V31。每个寄存器可通过以下方式访问:
- 一个名为Q0到Q31的128位寄存器。
- 一个名为D0到D31的64位寄存器。
- 一个名为S0到S31的32位寄存器。
- 一个名为H0到H31的16位寄存器。
- 一个名为B0到B31的8位寄存器。
- 一个128位元素的向量。
- 一个64位元素的向量。
由寄存器名描述的位数不占整个SIMD&FP寄存器,它指的是最低有效位。
AArch64状态寄存器的伪代码描述
在伪代码中访问寄存器的函数:
- 赋值表用于寄存器写。
- 非赋值用于寄存器读。
X[]函数的用途为:
- 读取或写入X0-X30,使用n索引所需的寄存器。
- 读取0寄存器ZR,以X[31]访问。
AArch64sp[]函数用于读取或写入当前的SP。
AArch64pc[]函数用于读取PC。
AArch64 V[]函数用于读取或写入高级SIMD和浮点寄存器V0-V31,使用参数n索引所需的寄存器。
AArch64 Vpart[]函数用于读取或写入V0-V31的一部分,使用参数n索引所需的寄存器,使用参数部分表示寄存器所需的部分,详细信息请参阅函数描述。
2.2.2 流程状态,PSTATE
进程状态(PSTATE)是进程状态信息的抽象。所有的指令集都提供了操作PSTATE元素的指令。
以下PSTATE信息可在EL0访问:
条件标志
标志设置指令设置这些。它们是:
N 负条件标志。
如果指令的结果被认为是一个2的整数补数,
如果结果是负数,则PE将其设置为:
- 1 如果结果为正或为0条件标志。
- 0 如果指令的结果为零,则设置为:1。
Z 0条件标志。
- 1 如果结果为0
- 0 否则
结果为零表示从比较得到的结果相等。
C 进位条件标志。
- 1如果指令导致进位条件,例如由加法导致的无符号溢出。
- 0否则
V 溢出条件标志。
- 1 如果指令导致溢出,例如加法导致的有符号溢出。
- 0否则
条件指令测试N、Z、C和V条件标志,将它们与指令的条件代码结合起来,以确定是否必须执行该指令。通过这种方式,指令的执行取决于前一个操作的结果。
异常屏蔽位
D 调试异常掩码位。当启用EL0来修改掩码位时,这个位是可见的,并且可以修改。但是,EL0在架构上忽略了这个位。
A SError中断掩码位。
I IRQ中断掩码位。
F FIQ中断掩码位。
对于每一位,其值为:
0 异常未被屏蔽。
1例外屏蔽。
在EL0访问PSTATE字段
在使用AArch64 state的EL0中,可以使用特殊用途的寄存器访问PSTATE字段,这些寄存器可以使用MRS指令直接读取,也可以使用MSR (register)指令直接写入。表B1-1显示了
专用寄存器,当PE处于EL0时访问持有AArch64状态的PSTATE字段
AArch64。所有其他PSTATE字段在EL0上没有直接读写访问权。
软件也可以使用MSR (immediate)指令直接写入PSTATE。{D, A, I, F}表B1-2显示了可以直接写入PSTATE的MSR(立即)操作数。{D, A, I, F},当PE在EL0使用AArch64状态。
但是,访问PSTATE。{D, A, I, F}字段在EL0使用AArch64状态依赖于SCTLR_EL1.UMA。
捕获对PSTATE的EL0访问的EL1。{D, A, I, F}在D1-2371页上的中断掩码。
写入PSTATE字段会对PE操作的各个方面产生副作用。所有这些副作用,都是有保证的:
- 对执行流中的先前指令不可见。
- 在执行流中对后面的指令可见。
2.3 系统寄存器
系统寄存器为执行控制、状态和一般系统配置提供支持。大多数的在EL0无法访问系统寄存器。
但是,一些系统寄存器可以配置为允许从执行在EL0的软件进行访问。从EL0到系统寄存器的任何访问权限被禁用都会导致指令的行为为未定义。可以从EL0访问的寄存器有:
缓存ID寄存器
CTR_EL0和DCZID_EL0寄存器为EL0缓存管理支持提供了实现参数。
调试寄存器
MDCCSR_EL0、DBGDTR_EL0支持调试通信通道,DBGDTRRX_EL0和DBGDTRTX_EL0寄存器。
性能监控寄存器
Performance Monitors扩展提供计数器和配置寄存器。
在EL1或更高异常级别执行的软件可以将其中一些寄存器配置为在EL0可访问。
活动监视寄存器
Activity Monitors扩展提供了计数器和配置寄存器。在EL1或更高异常级别执行的软件可以将这些寄存器配置为在EL0可访问。
线程ID寄存器
TPIDR_EL0和TPIDRRO_EL0寄存器是两个具有不同访问权限的线程ID寄存器。
定时器寄存器
在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。