一 、ARM64架构基础
1 ARMv8 A 架构介绍
ARMv8 - A是ARM公司发布的第一代支持64位处理器的指令集和架构。它在扩充64位寄存器的同时提供对上一代架构指令集的兼容,因而能同时提供运行 32位 和 64位应用程序的执行环境。
- 超大物理地址空间(large Physical Address),提供超过4GB物理内存的访问。
- 64位宽的虚拟地址空间(64-bit Virtual Addressing)
- 提供31个64位宽的通用寄存器,可以减少对栈的访问,从而提高性能。
- 提供16KB 和 64KB的页面,有助于降低TLB的未命中率。
- 全新的异常处理模型,有助于降低操作系统 和 虚拟化的实现复杂度。
- 全新的加载 - 获取,存储 - 释放指令 (Load - Acquire, Store - Release Instructions)。
2 ARMv8 A 基础概念
2.1 处理器单元
处理器处理事务的过程抽象为处理单元。(PE:Processing Element)
2.2 执行状态
AArch64: 64位的执行状态
- 提供31个64位通用寄存器。
- 提供64位的程序计数寄存器 PC、栈指针寄存器SP、异常链接寄存器ELR。
- 提供AArch64指令集
- 定义Armv8异常模型,支持4个异常等级,El0 ~ EL3
- 提供64位的内存模型
- 定义一组处理器状态(PSTATE)用来保存PE的状态。
AArch32:32位的执行状态 ---- 待分析
2.3 ARMv8 指令集
ARMv8架构根据不同的执行状态提供不同指令集的支持。
A64指令集:运行在AArch64状态,提供64位指令集支持。
A32指令集:运行在AArch32状态,提供32位指令集支持。
T32指令集:运行在AArch32状态,提供16和32位指令集支持。
2.4 系统寄存器命名
系统寄存器 提供控制和状态。
在AArch64 状态下,很多系统寄存器会根据不同的异常等级,提供不同的变种寄存器。
- 命名规则:<register_name>_ELx where x is 0, 1, 2, or 3 。
- 比如:SP_EL0 表示在EL0下的栈指针寄存器,SP_EL1表示在EL1下的栈指针。
- 系统寄存器 描述在ARv8.6手册的D13章。
3 ARMv8 A 运行状态 & 异常等级
ARMv8 处理器支持两种运行状态 – AArch64 状态 和AArch32 状态。
3.1 异常等级
AArch64架构的一场等级(Exception level)确定了处理当前运行的特权级别。类似ARMv7 架构中的特权等级。
EL0:用户特权,用于运行普通用户程序
EL1:系统特权,通常用于运行操作系统
EL2;运行虚拟化扩展的虚拟监控程序 (Hypervisor)
EL3:运行安全世界中的安全监控器(secure monitor)
3.2 数据宽度 & 指令对齐
数据宽度
- ARMv8 架构支持如下几种数据宽度。
字节(byte): 8位&16进制2位 / 1字节
半字(halfword):16位 / 2字节
字(word):32位 / 4字节
4字节(quadword): 128位 / 16字节 - 通用寄存器:支持64bit和32bit的通用寄存器
- SIMD/FP寄存器:支持128bit寄存器
不对齐访问
一种是指令对齐,另一种是数据对齐 - Arm64 指令集要求指令存放的位置必须以字(word)- 4字节为单位对齐。
- 访问存储位置不是以字为单位对齐的指令会导致PC对齐异常(PC aligment fault)。
- 对于数据访问,需要区分不同的内存类型。对内存类型是设备内存的不对齐访问会触发对齐异常。
- 对于访问普通内存,除了使用独占之另外,还可以使用其他的用于加载和存储单个或多个寄存器的所有指令。
- 如果访问地址和要访问的数据元素大小不对齐,根据一下进行处理:
- 若对应的异常等级中的SCTLR_ELx 寄存器的 A域 设置为1,则说明打开地址对齐检查功能,会触发对齐异常。
- 若对齐的异常等级中的SCTLR_ELx 寄存器的 A域 设置为0,则说明处理器支持不对齐访问。
- 当然处理器支持的不不对齐访问也有一些限制
- 不能保证单次访问原子地完成,有可能复制多次。
- 不对齐访问 比 对齐访问需要更多的处理时间。
- 不对齐的地址访问,可能会引发中止(abort)。
二、ARMv8 寄存器
4 通用寄存器
AArch64 运行状态支持31个64位通用寄存器,分别是x0 ~ x30寄存器,而AArch32运行状态支持16个32位的通用寄存器。
-
x0 ~ x30 :通用寄存器
-
<x0 - x7 传参和结果> <x8 间接结果寄存器> <x9 - x15 调用函数需要保存,临时寄存器>
-
<x16 - x18 平台寄存器> <x19 - x28 被调用函数需保存> <x29/ FP 栈桢寄存器> <X30/LR 链接寄存器>
-
SP :栈指针寄存器
-
PC :程序计数寄存器
-
在AArch64 运行状态下,使用 x 表示64位通用寄存器,比如:x0,x20等。
-
W表示低32位的寄存器,比如W0 表示 X0寄存器的低32位数据,W1表示 X1寄存器的低32位数据
5 处理器状态寄存器组(Processor State)
在ARMv7 中使用CPSR来表示当前处理器的状态,而在AArch64架构中使用处理状态寄存器组,简称PSTATE。
5.1 条件标志位 - NZCV (The Condition flags)
- 举例
cmp 指令:使用cmp指令来比较两个变量的大小,它会做减法运算,并且影响PASTAT寄存器的C标志位。
小伙伴可以使用“updates the condition” 关键字来搜索哪些指令会影响pstate的条件标志位
5.2 异常掩码标志位
0 :表示enable,没有屏蔽这个异常
1 :表示disable, 屏蔽这个异常
5.3 执行状态控制位
5.4 处理器状态寄存器访问
在EL0访问pstate的问题,部分pstate的域可以通过特殊寄存器来访问,
部分pstate域在EL0里不能被访问,比如CurrenEL。
6 特殊寄存器
ARMv8架构除了支持31个通用寄存器之外,还提供多个特殊的寄存器。
零寄存器(Zero Register)
WZR寄存器是32位的零寄存器,XZR是64位的零寄存器。
栈指针(Stack Pointer)
- SP_EL0:EL0下的栈指针寄存器。
- SP_EL1:EL1下的栈指针寄存器。
- SP_EL2:EL2下的栈指针寄存器。
- SP_EL3:EL3下的栈指针寄存器。
当处理器运行在比EL0高级别的异常等级时,处理器可以访问: - 当前异常等级对应的栈指针SP_ELn
- EL0对应的栈指针SP_EL0寄存器可以当做一个临时寄存器,比如:Linux 内核使用这种临时寄存器存放进程的 task_struct 数据结构的指针。
- EL0时,处理器只能访问SP_EL0寄存器,而不能访问其他高等级的SP寄存器。
PC指针(Program Counter)
PC(Program Counter)寄存器通常用来指向当前运行指令的下一条指令的地址,用于控制程序种指令的执行顺序,但是编程人员不能通过指令来直接访问。
异常链接寄存器(Exception Link Register,ELR)
异常链接寄存器(Exception Link Register),用来存放异常返回地址。
保存处理状态寄存器(Saved Process Status Register,SPSR)
当我们进行异常处理时,处理器的处理状态会保存到 保存处理状态寄存器(SPSR) 中。这种寄存器类似ARMv7中的CPSR。
当异常将要发生时,处理器会把 处理器状态寄存器 (PSTATE) 的值保存到 保存处理状态寄存器(SPSR)中.
当异常处理完成并返回时。再把 保存处理状态寄存器(SPSR)中的值恢复 到 处理器状态寄存器 (PSTATE)中。
M[4] :处理器异常处理过程中处于哪种运行模式下,若为0 表示AArch64
M[3:0] : 异常模式
通过msr/mrs指令来访问
CurrentEL寄存器
聊聊SOC启动(七) SPL启动分析 - 知乎 (zhihu.com)
处理器状态PSTATE中的EL字段保存了当前异常等级。使用MRS指令可以读取当前异常等级。
0: 表示EL0 (0<<2)
1: 表示EL1 (1<<2)
2: 表示EL2 (2<<2)
3: 表示EL3 (3<<2)
#define CurrentEL_EL1 (1 << 2)
#define CurrentEL_EL2 (2 << 2)
#define CurrentEL_EL3 (3 << 2)
DAIF寄存器
- 表示处理器状态PSTATE中的{D, A, I, F}字段
SPSel寄存器 - 表示处理器状态PSTATE中的SP字段,用来在SP_EL0和SP_ELn中选择栈指针寄存器
7 系统寄存器
ARMv8 架构定义了其他相关系统寄存器,通过访问和设置这些系统寄存器来完成对处理器不同的功能配置。
- ARmv8 架构支持7大类系统寄存器
- 通用系统控制寄存器
- 调试寄存器
- 性能监控寄存器
- 活动监控寄存器
- 统计扩展寄存器
- RAS寄存器
- 通用定时器寄存器
- 系统寄存器命名规范
- 系统寄存器支持不同异常等级下的访问,通常系统寄存器可使用< Reg_ELn > 的方式来表示:
- Reg_EL1:处理器处于EL1、EL2、EL3时可以访问该寄存器
- Reg_EL2: 处理器处于EL2、EL3是可以访问该寄存器
- 系统寄存器访问指令
- 程序可以通过MSR和MRS指令访问系统寄存器,比如:
- mrs x0, TTBR0_EL1 //把TTBR0_EL1寄存器的值复制到X0寄存器
- msr TTBR0_EL1, x0 //把x0寄存器的值拷贝到TTBR0_EL1寄存器
三、ARM64 指令集
… 待梳理
五、ARM64 内存管理