ARM架构基础知识
ARM公司除了提供处理器IP和配套工具外,主要还定义了一系列的ARM兼容指令集来构建整个ARM的软件生态系统。
到了ARMv7指令集,处理器以Cortex命名,又分成A、R和M系列,通常A系列针对大型嵌入式系统(例如手机),R系列针对实时性系统,M系列针对单片机市场。Cortex-A7、Cortex-A9处理器是前几年手机的主流配置,是32位处理器。虚拟化和安全特性在ARMv7上已经实现。
ARMv8-A是ARM公司发布的第一代支持64位处理器的指令集和架构。它在扩充64位寄存器的同时,提供对上一代架构指令集的兼容,通过定义AArch32与AArch64两套运行环境来分别运行64位和32位指令集,因而能同时提供运行32位和64位应用程序的执行环境。AArch32也称ARM32,AArch64也称ARM64。
常见的ARMv8处理器:Cortex-A53、Cortex-A57、Cortex-A72。
ARMv8-A架构中的基本概念
- 处理单元
ARM公司的官方技术手册中提到了一个概念,可以把处理器处理事务的过程抽象为处理单元(Processing Element,PE)。
- 执行状态
执行状态(execution state)是处理器运行时的环境,包括寄存器的位宽、支持的指令集、异常模型、内存管理以及编程模型等。ARMv8架构定义了两种执行模式。
- AArch64:64位的执行状态
- AArch32:32的执行状态
- ARMv8指令集
ARMv8架构根据不同的执行状态提供对不同指令集的支持。
- 系统寄存器命名
在AArch64状态下,很多系统寄存器会根据不同的异常等级提供不同的变种寄存器。
<register_name>_ELx,where x is 0,1,2,or 3
比如,SP_EL0表示EL0下的栈指针寄存器,SP_EL1表示EL1下的栈指针寄存器。
- 异常等级
AArch64架构的异常等级(exception level)确定了处理器当前运行的特权级别,类似于ARMv7架构中的特权等级,如图所示。
- ARMv8架构支持的数据宽度
- 不对齐访问
不对齐访问有两种情况。一种是指令对齐,另一种是数据对齐。A64指令集要求指令存放的位置必须以字(word,32位宽)为单位对齐。访问存储位置不是以字为单位对齐的指令会导致PC对齐异常(PC aligment fault)。
对于数据访问,需要区分不同的内存类型。对内存类型是设备内存的不对齐访问会触发对齐异常(alignment fault)。
对于访问普通内存,除了使用独占。加载/独占-存储(load-exclusive/store-exchusive)指令或加载-获取/存储-释放(load-acquire/store-release)指令外,还这可使用其他的用于加载或存储单个或多个寄存器的所有指令。如果访问地址和要访问的数据元素大小不对齐,那么可以根据以下两种情况进行处理。
当然,处理器支持的不对齐访问也有一些限制。
- 通用寄存器
AArch64运行状态支持31个64位的通用寄存器,分别是x0-x30寄存器,而AArch32运行状态支持16个32位的通用寄存器。
通用寄存器除了用于数据运算和存储之外,还可以在函数调用过程中起到特殊作用。ARM64架构的函数调用标准和规范对此有所约定,如图所示。
在AArch64运行状态下,使用X来表示64位通用寄存器,比如X0、X30等。另外,还可以使用W来表示低32位的寄存器,比如W0表示X0寄存器的低32位数据,W1表示X1寄存器的低32位数据,如图所示。
- 状态寄存器
- 特殊寄存器
- 零寄存器
ARMv8架构提供两个零寄存器,这两个零寄存器的内容全是0,可以用作源寄存器,也可以用作目标寄存器。WZR是32位的零寄存器,XZR是64位的零寄存器。 - 栈指针寄存器
ARMv8架构支持4个异常等级,每一个异常等级都有专门的SP_ELn寄存器。当处理器处于比EL0高的异常等级时,可以将SP_EL0当作临时寄存器。但运行在EL0时,只能使用SP_EL0寄存器。 - PC寄存器
用来指向当前运行指令的下一条指令的地址。 - 异常链接寄存器
异常链接寄存器(ELR)用来存放异常返回的地址。 - 保存处理器状态寄存器
当我们进行异常处理时,处理器的处理状态会保存到保存处理器状态寄存器(SPSR)里。当异常将要发生时,处理器会把处理器状态寄存器(PSTATE)的值暂时保存到SPSR里,当异常处理完成并返回时,再把SPSR中的值恢复到处理器状态寄存器中。 - CurrentEL寄存器
PSTATE寄存器中的EL字段保存了当前异常等级。使用MRS可以读取当前异常等级。
- 系统寄存器
可以通过访问和设置这些系统寄存器来完成对处理器不同功能的配置。ARMv8支持以下七大类的系统寄存器:
通用系统控制寄存器、调试寄存器、性能监控寄存器、活动监控寄存器、统计扩展寄存器、RAS寄存器、通用定时器寄存器。
- A64指令集
A64指令集和A32指令集是不兼容的,它们是两套完全不一样的指令集架构,它们的指令编码也不一样。需要注意的是,A64指令集的指令为32位宽,而不是64位宽。
具体指令集详见书上85~94页。
- ARM64异常处理
在ARMv8架构中,中断是异常的一种。
同步异常是指处理器需要等待异常处理的结果,然后再继续处理后面的指令。
异步异常是指处理器正在处理的指令和中断完全没有关系。
当CPU检测到异常后,CPU会自动做如下一些事情。
上述是ARMv8处理器检测到异常发生后自动做的事情。操作系统需要做的事情是从中断向量表开始,根据异常发生的类型,跳转到合适的异常向量表。异常向量表中的每项会保存一个异常处理的跳转函数,然后跳转到恰当的异常处理函数并处理异常。
当操作系统的异常处理完成后,执行一条eret指令即可从异常返回。这条指令会自动完成如下工作。
中断处理过程是在中断关闭的情况下进行的,那么中断处理完成后,应该在什么时候把中断打开呢?
当中断发生时,CPU会把PSTATE寄存器中的值保存到对应目标异常等级的SPSR_ELx中,并且把PSTATE寄存器里的DAIF域都设置为1,这相当于把本地CPU的中断关闭了。
当中断完成后,操作系统调用eret指令以返回中断现场,此时会把SPSR_ELx恢复到PSTATE寄存器中,这就相当于把中断打开了。
ARMv8架构的异常向量表每一个表项需要128字节,这样可以存放32条指令。异常向量表存放的基地址可以通过VBAR(Vector Base Address Register)来设置。VBAR是异常向量表的基地址寄存器。
- ARM64内存管理
页表查询的过程由硬件自动完成,但是页表的维护需要由软件完成。
AArch64架构中的MMU不仅支持单一阶段的地址转换,还支持虚拟化扩展中的两阶段页表转换。
在AArch64架构中,因为地址总线位宽最多支持48位,所以虚拟地址被划分为两个空间,每个空间最多支持256TB。