ARM 架構簡介

最後更新: 2025-06-07 09:28:40 +0800 +0800
原文以英文撰寫。您正在閱讀AI翻譯版本。

Arm 定義的是一系列指令集架構(ISA),而不是一種處理器實作。架構規範程式設計師可見的狀態、指令語意、例外、特權和記憶體順序。核心的管線、快取階層和分支預測器屬於微架構選擇。

架構設定檔用於區分部署需求。A-profile 以具備虛擬記憶體的應用程式處理器為目標,R-profile 以即時系統為目標,M-profile 以微控制器為目標。除非另有說明,以下介紹的執行狀態和特權模型均針對 A-profile 系統。

執行狀態與指令集 #

AArch32 提供 32 位元通用暫存器,可以執行 A32 指令集,或執行歷史上稱為 Thumb 的可變長度 T32 指令集。由 Armv8-A 引入的 AArch64 提供 31 個 64 位元通用暫存器和固定寬度的 A64 指令集。X0 到 X30 表示 64 位元暫存器;W0 到 W30 表示對應暫存器的低 32 位元。寫入 W 暫存器會清除其對應 X 暫存器的高半部。

處理器可以實作多個執行狀態,但不能根據產品具備 64 位元能力來推斷其支援哪些狀態。Armv8-A 允許 AArch64 作業系統支援 AArch32 應用程式,而後續架構版本允許實作在選定的例外層級不支援 AArch32。因此,軟體必須使用平台文件和作業系統介面來判定可用的狀態。

執行狀態不只是暫存器寬度。AArch32 和 AArch64 具有不同的指令編碼、例外模型、系統暫存器和 ABI。程式碼不能透過普通分支切換狀態;必須透過例外返回或其他由架構定義的轉換來建立目標狀態。

暫存器與程序呼叫 #

A64 是一種載入-儲存 ISA:算術運算在暫存器上執行,而明確的載入和儲存指令存取記憶體。

asm
ldr w0, [x1]        // 載入 32 位元值
add w0, w0, #1
str w0, [x1]

多個暫存器名稱具有架構規定或慣例上的角色:

暫存器AAPCS64 中的角色
X0-X7整數引數與結果
X8間接結果位置暫存器
X9-X15呼叫者保存的暫存器
X16-X17程序內呼叫暫存器
X18平台暫存器或暫存器,取決於平台 ABI
X19-X28被呼叫者保存的暫存器
X29依慣例作為框架指標
X30連結暫存器
SP堆疊指標

BL 將返回位址寫入 X30,而 RET 通常透過 X30 進行分支。Arm 64 位元架構的程序呼叫標準(AAPCS64)也定義浮點/向量引數暫存器、聚合型別傳遞、被呼叫者保存狀態,以及 16 位元組堆疊對齊。這些規則是 ABI 契約,而不是 A64 指令語法的屬性。與編譯程式碼互通的手寫組合語言必須遵循平台的完整 ABI。

例外層級與轉換 #

A-profile 系統使用例外層級,數字越大表示特權越高:

  • EL0 執行非特權應用程式。
  • EL1 通常執行作業系統核心。
  • EL2 為虛擬機器監視器提供虛擬化控制。
  • EL3 在有實作的系統上提供安全監視器功能。

實作不必提供所有層級。安全狀態和虛擬化也會影響某個 EL 可存取的資源,因此僅憑 EL 編號無法描述完整的保護網域。

例外包括同步例外、IRQ、FIQ 和系統錯誤。發生例外時,返回位址和儲存的處理器狀態會記錄在 ELR_ELx 和 SPSR_ELx 中,系統會從目標 EL 的向量表選取一個進入點,並遮罩或變更選定的狀態。處理常式驗證該狀態後,ERET 會還原儲存的狀態。系統呼叫通常使用 SVC 進入 EL1;啟用後,虛擬機器監視器呼叫和安全監視器呼叫分別使用 HVC 和 SMC。

轉譯表和存取控制暫存器會強制執行記憶體隔離。EL2 可以在 EL1 客體的第一階段對映上增加第二階段轉譯,而 TrustZone 安全狀態還可以施加另一層存取邊界。可用性和暫存器的確切行為取決於所實作的架構版本。

記憶體順序、屏障與原子操作 #

Arm 使用弱順序記憶體模型。在沒有架構同步機制限制時,核心可能會以不同於程式順序的順序觀察彼此獨立的載入和儲存。快取一致性確保參與的觀察者對同一位置的寫入順序達成一致;但一致性本身不會規定對不同位置的存取順序。

並行程式碼應表達其協定所需的最小順序限制:

  • Acquire 載入可防止後續存取移動到 Acquire 之前。
  • Release 儲存可防止先前存取移動到 Release 之後。
  • 讀-改-寫原子操作提供具有指定順序語意的不可分割更新。
  • DMB 在選定的可共享性和存取網域內,為相關記憶體觀察排序。
  • DSB 等待指定的記憶體效果完成。
  • ISB 刷新指令管線,使後續指令在先前內容變更操作建立的內容中執行。

AArch64 支援 LDXR/STXR 等獨佔載入/獨佔儲存迴圈。支援 Large System Extensions 的系統也可以提供單一指令的原子讀-改-寫操作。兩種形式都需要重試或競爭處理,且都無法修復語言層級的資料競爭。C 和 C++ 程式應使用語言提供的原子操作,因為編譯器會將這些語意對映到適當的指令和屏障。

主要參考資料 #

評論

在 GitHub 上閱讀或評論(發表評論需要登入)