一 、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 內存管理