05-异常模型
快速鏈接:
.
👉👉👉 個(gè)人博客筆記導(dǎo)讀目錄(全部) 👈👈👈
相關(guān)鏈接: (專題:《learn-the-architecture系列》)
- 01-Introducing the Arm architecture
- 02-Armv8-A Instruction Set Architecture
- 03_Introduction_to_AMBA_AXI
- 04-TrustZone for Armv8-A
- 05-Exception model
- 06-GICv3_v4_overview
- 07-Armv8-A virtualization
- 08-Isolation using virtualization in the Secure World_Whitepaper
- 09-LearnTheArchitecture-MemoryManagement
- 10-Armv8-A memory model guide–ongoing
- 11-Memory Management Examples
- 12-Generic Timer
- 13-Introduction to security
- 14-Providing protection for complex software
- 15-Arm-Confidential-Compute-Software-Stack
- 16-Understanding the Armv8.x extensions
目錄
- 1 簡介
- 2 特權(quán)和異常模型
- 2.1. 特權(quán)的類型
- 2.2. 內(nèi)存特權(quán)
- 2.3. 寄存器的訪問
- 3 執(zhí)行狀態(tài)和安全狀態(tài)
- 3.1. 執(zhí)行狀態(tài)
- 3.2. 安全狀態(tài)
- 3.3. 執(zhí)行狀態(tài)的改變
- 3.4. 安全狀態(tài)的改變
- 3.5. 實(shí)現(xiàn)定義的異常級別和執(zhí)行狀態(tài)
- 4 異常類型
- 4.1. 同步異常
- 4.2. 異步異常
- 4.3. IRQ and FIQ
- 4.4. SError
- 5 Handling exceptions
- 5.1. Exception terminology
- 5.2. Taking an exception
- 5.3. Routing asynchronous exceptions
- 5.4. Determining which Execution state an exception is taken to
- 5.5. Returning from an exception
- 5.6. Exception stacks
- 6 The vector tables
1 簡介
本文介紹了 Armv8-A 中的異常和特權(quán)模型。 本文涵蓋了 Arm 架構(gòu)中不同類型的異常,以及處理器在收到異常時(shí)的行為。本文適用于底層代碼的開發(fā)人員,例如引導(dǎo)代碼或驅(qū)動(dòng)程序。 它與編寫代碼來設(shè)置或管理異常的任何人都特別相關(guān)。
2 特權(quán)和異常模型
在講解Armv8-A異常模型的細(xì)節(jié)之前,我們先來介紹一下特權(quán)的概念。 現(xiàn)代軟件期望被分成不同的模塊,每個(gè)模塊對系統(tǒng)和處理器資源的訪問級別不同。 這方面的一個(gè)例子是操作系統(tǒng)內(nèi)核(具有對系統(tǒng)資源的高級訪問權(quán)限)和用戶應(yīng)用程序訪問呢的系統(tǒng)資源是有限的。
Armv8-A 通過實(shí)現(xiàn)不同級別的權(quán)限來實(shí)現(xiàn)這種拆分。 當(dāng)前權(quán)限級別只能在處理器接受或從異常中返回時(shí)更改。 因此,這些特權(quán)級別在 Armv8-A 架構(gòu)中被稱為異常級別。 每個(gè)異常級別都有編號(hào),特權(quán)級別越高,編號(hào)越大。
如下圖所示,異常級別稱為 EL,其中 x 為 0 到 3 之間的數(shù)字。例如,最低權(quán)限級別稱為 EL0。
一個(gè)常見的使用模型是應(yīng)用程序代碼在 EL0 上運(yùn)行,操作系統(tǒng)在 EL1 上運(yùn)行。 EL2 由hypervisror使用,EL3 由TrustedFirmware使用。
注意:體系結(jié)構(gòu)不強(qiáng)制執(zhí)行此軟件模型,但標(biāo)準(zhǔn)軟件采用此模型。 出于這個(gè)原因,本文的其余部分假設(shè)了這種使用模型
2.1. 特權(quán)的類型
有兩種與此相關(guān)的特權(quán)。 第一個(gè)是內(nèi)存系統(tǒng)中的特權(quán),第二個(gè)是從訪問處理器資源的角度來看的特權(quán)。 兩者都受當(dāng)前異常級別的影響。
2.2. 內(nèi)存特權(quán)
Armv8-A 實(shí)現(xiàn)了一個(gè)虛擬內(nèi)存系統(tǒng),其中內(nèi)存管理單元 (MMU) 允許軟件為內(nèi)存區(qū)域分配屬性。 這些屬性包括讀/寫權(quán)限,可以配置兩個(gè)自由度。 此配置允許特權(quán)和非特權(quán)訪問的單獨(dú)訪問權(quán)限。
當(dāng)處理器在 EL0 中執(zhí)行時(shí)啟動(dòng)的內(nèi)存訪問將根據(jù)非特權(quán)訪問權(quán)限進(jìn)行檢查。 來自 EL1、EL2 和 EL3 的內(nèi)存訪問將根據(jù)特權(quán)訪問權(quán)限進(jìn)行檢查。
由于此內(nèi)存配置是由軟件使用 MMU 的轉(zhuǎn)換表編程的,因此您應(yīng)該考慮對這些表進(jìn)行編程所需的特權(quán)。 MMU 配置存儲(chǔ)在系統(tǒng)寄存器中,訪問這些寄存器的能力也受當(dāng)前異常級別控制。
2.3. 寄存器的訪問
Armv8-A 處理器的配置設(shè)置保存在一系列稱為系統(tǒng)寄存器的寄存器中。 系統(tǒng)寄存器中的設(shè)置組合定義了當(dāng)前的處理器上下文。 對系統(tǒng)寄存器的訪問由當(dāng)前異常級別控制
系統(tǒng)寄存器的名稱表示可以訪問該寄存器的最低異常級別。 例如,TTBR0_EL1 是保存 EL0 和 EL1 使用的轉(zhuǎn)換表的基地址的寄存器。 無法從 EL0 訪問該寄存器,任何嘗試這樣做都會(huì)導(dǎo)致生成異常。
該體系結(jié)構(gòu)有許多具有概念上相似功能的寄存器,它們的名稱僅在異常級別后綴上有所不同。 這些是獨(dú)立的、單獨(dú)的寄存器,在指令集中有自己的編碼,并將在硬件中單獨(dú)實(shí)現(xiàn)。 例如,以下寄存器都為不同的轉(zhuǎn)換機(jī)制執(zhí)行 MMU 配置。 寄存器具有相似的名稱以反映它們執(zhí)行相似的任務(wù),但它們是完全獨(dú)立的寄存器,具有自己的訪問語義:
- SCTLR_EL1 – Top level system control for EL0 and EL1
- SCTLR_EL2 – Top level system control for EL2
- SCTLR_EL3 – Top level system control for EL3
注意:EL1 和 EL0 共享相同的 MMU 配置,并且控制僅限于在 EL1 上運(yùn)行的特權(quán)代碼。 因此,沒有 SCTLR_EL0,所有控制都來自 EL1 可訪問寄存器。 其他控制寄存器通常遵循此模型。
較高的異常級別有權(quán)訪問控制較低級別的寄存器。 例如,EL2 有權(quán)在必要時(shí)訪問 SCTLR_EL1。 在系統(tǒng)的一般操作中,特權(quán)異常級別通常會(huì)控制自己的配置。 然而,更高的特權(quán)級別有時(shí)會(huì)訪問與較低異常級別相關(guān)聯(lián)的寄存器,例如,實(shí)現(xiàn)虛擬化功能或在上下文切換或電源管理操作期間作為保存和恢復(fù)操作的一部分讀取和寫入寄存器集。
3 執(zhí)行狀態(tài)和安全狀態(tài)
Armv8-A 處理器的當(dāng)前狀態(tài)由異常級別和其他兩個(gè)重要狀態(tài)決定。 當(dāng)前執(zhí)行狀態(tài)定義了通用寄存器的標(biāo)準(zhǔn)寬度和可用指令集。執(zhí)行狀態(tài)也會(huì)影響內(nèi)存模型的各個(gè)方面以及如何管理異常。
當(dāng)前安全狀態(tài)控制當(dāng)前有效的異常級別、當(dāng)前可以訪問的內(nèi)存區(qū)域以及這些訪問在系統(tǒng)內(nèi)存總線上的表示方式。
下圖顯示了異常級別和安全狀態(tài),使用了不同的執(zhí)行狀態(tài):
3.1. 執(zhí)行狀態(tài)
Armv8-A提供兩種執(zhí)行狀態(tài):
- AArch32: The 32-bit Execution state. Operation in this state is compatible with Armv7-A. There are two available instruction sets: T32 and A32. The standard register width is 32 bits.
- AArch64: The 64-bit Execution state. There is one available instruction set: A64. The standard register width is 64 bits
3.2. 安全狀態(tài)
Armv8-A 架構(gòu)允許實(shí)現(xiàn)兩種安全狀態(tài)。 這允許進(jìn)一步劃分軟件以隔離和劃分受信任的軟件。
這兩種安全狀態(tài)是:
- Secure state
在這種狀態(tài)下,處理元件 (PE) 可以訪問安全和非安全物理地址空間。 在這種狀態(tài)下,PE 可以訪問安全和非安全系統(tǒng)寄存器。 在此狀態(tài)下運(yùn)行的軟件只能確認(rèn)安全中斷。 - Non-secure state
在這種狀態(tài)下,PE 只能訪問非安全物理地址空間。 PE 也只能訪問允許非安全訪問的系統(tǒng)寄存器。 在此狀態(tài)下運(yùn)行的軟件只能確認(rèn)非安全中斷
3.3. 執(zhí)行狀態(tài)的改變
PE 只能在reset或異常級別更改時(shí)更改執(zhí)行狀態(tài).
復(fù)位時(shí)的執(zhí)行狀態(tài)由 IMPLEMENTATION DEFINED 機(jī)制確定。 一些實(shí)現(xiàn)修復(fù)了重置時(shí)的執(zhí)行狀態(tài)。 例如,Cortex-A32 將始終重置為 AArch32 狀態(tài)。 在 Armv8-A 的大多數(shù)實(shí)現(xiàn)中,復(fù)位后的執(zhí)行狀態(tài)由在復(fù)位時(shí)采樣的信號(hào)控制。 這允許在片上系統(tǒng)級別控制復(fù)位執(zhí)行狀態(tài)。
當(dāng) PE 在 Exception 級別之間發(fā)生變化時(shí),也可以更改 Execution 狀態(tài)。 AArch32 和 AArch64 之間的轉(zhuǎn)換只允許遵守某些規(guī)則
- 當(dāng)從較低的異常級別移動(dòng)到較高級別時(shí),執(zhí)行狀態(tài)可以保持不變或更改為 AArch64
- 當(dāng)從較高的異常級別移動(dòng)到較低級別時(shí),執(zhí)行狀態(tài)可以保持不變或更改為 AArch32。
將這兩個(gè)規(guī)則放在一起意味著 64 位之上可以允許 32 位,但反過來不行。 例如,64 位操作系統(tǒng)內(nèi)核可以同時(shí)托管 64 位和 32 位應(yīng)用程序,而 32 位操作系統(tǒng)內(nèi)核只能托管 32 位應(yīng)用程序。
在此示例中,我們使用了操作系統(tǒng)和應(yīng)用程序,但相同的規(guī)則適用于所有異常級別。 例如,EL2 的 32 位虛擬機(jī)管理程序只能托管 EL1 的 32 位虛擬機(jī)
3.4. 安全狀態(tài)的改變
EL3 始終被視為在安全狀態(tài)下執(zhí)行。 使用 SCR_EL3,EL3 代碼可以更改所有較低異常級別的安全狀態(tài)。 如果軟件使用 SCR_EL3 更改較低異常級別的安全狀態(tài),則 PE 將不會(huì)更改安全狀態(tài),直到它更改為較低的異常級別。
3.5. 實(shí)現(xiàn)定義的異常級別和執(zhí)行狀態(tài)
Armv8-A 架構(gòu)允許實(shí)現(xiàn)選擇是否實(shí)現(xiàn)所有異常級別,并為每個(gè)實(shí)現(xiàn)的異常級別選擇允許哪些執(zhí)行狀態(tài)
EL0 和 EL1 是唯一必須實(shí)現(xiàn)的異常級別。 EL2 和 EL3 是可選的。 選擇不實(shí)施 EL3 或 EL2 具有重要意義
EL3 是唯一可以更改安全狀態(tài)的級別。 如果實(shí)現(xiàn)選擇不實(shí)現(xiàn) EL3,則該 PE 將無法訪問單個(gè)安全狀態(tài)
同樣,EL2 包含許多虛擬化功能。 沒有 EL2 的實(shí)現(xiàn)可以訪問這些功能。 該架構(gòu)的所有當(dāng)前 Arm 實(shí)現(xiàn)都實(shí)現(xiàn)了所有異常級別,如果沒有所有異常級別,就不可能使用大多數(shù)標(biāo)準(zhǔn)軟件
實(shí)現(xiàn)還可以選擇對每個(gè)異常級別有效的執(zhí)行狀態(tài)。 如果在異常級別允許使用 AArch32,則必須允許所有較低的異常級別。 例如,如果 EL3 允許 AArch32,那么它必須在所有較低的異常級別上都允許
許多實(shí)現(xiàn)允許所有執(zhí)行狀態(tài)和所有異常級別,但存在有限制的現(xiàn)有實(shí)現(xiàn)。 例如,Cortex-A32 只允許任何異常級別的 AArch32
一些現(xiàn)代實(shí)現(xiàn),例如 Cortex-A55,實(shí)現(xiàn)了所有異常級別,但只允許 AArch32 在 EL0。(例如可參考這篇文章:Cortex-A76僅EL0支持aarch32) 其他異常級別 EL1、EL2 和 EL3 必須是 AArch64.
4 異常類型
異常是可以導(dǎo)致當(dāng)前正在執(zhí)行的程序被掛起并導(dǎo)致狀態(tài)發(fā)生變化以執(zhí)行代碼來處理該異常的任何事件。 其他處理器架構(gòu)可能將此描述為中斷。 在 Armv8-A 架構(gòu)中,中斷是一種外部產(chǎn)生的異常。 Armv8-A 架構(gòu)將異常分為兩大類:同步異常和異步異常。
4.1. 同步異常
同步異常是可能由剛剛執(zhí)行的指令引起或與之相關(guān)的異常。 這意味著同步異常與執(zhí)行流同步。
嘗試執(zhí)行無效指令可能會(huì)導(dǎo)致同步異常,無論是當(dāng)前異常級別不允許的指令還是已禁用的指令。
由于地址未對齊或 MMU 權(quán)限檢查之一失敗,內(nèi)存訪問也可能導(dǎo)致同步異常。 由于這些錯(cuò)誤是同步的,因此可以在嘗試訪問內(nèi)存之前發(fā)生異常。 內(nèi)存訪問也可以產(chǎn)生異步異常,這將在本節(jié)中討論。 內(nèi)存管理指南中更詳細(xì)地討論了內(nèi)存訪問錯(cuò)誤。
Armv8-A 架構(gòu)有一系列異常生成指令:SVC、HVC 和 SMC。 這些指令不同于簡單的無效指令,因?yàn)樗鼈冡槍Σ煌漠惓<墑e,并且在對異常進(jìn)行優(yōu)先級排序時(shí)被區(qū)別對待。 這些指令用于實(shí)現(xiàn)系統(tǒng)調(diào)用接口,以允許較低特權(quán)的代碼從較高特權(quán)的代碼請求服務(wù)。
Debug exceptions也是同步異常
4.2. 異步異常
某些類型的異常是在外部生成的,因此與當(dāng)前指令流不同步。 這意味著無法準(zhǔn)確保證何時(shí)會(huì)發(fā)生異步異常。 Armv8-A 架構(gòu)只要求它在有限的時(shí)間內(nèi)發(fā)生。 異步異常也可以暫時(shí)屏蔽。 這意味著在發(fā)生異常之前,異步異常可以處于掛起狀態(tài)。
異步異常的種類有:
Physical interrupts
? SError (System Error)
? IRQ
? FIQ
Virtual Interrupts
? vSError (Virtual System Error)
? vIRQ (Virtual IRQ)
? vFIQ (Virtual FIQ)
物理中斷是響應(yīng)于 PE 外產(chǎn)生的信號(hào)而產(chǎn)生的。 虛擬中斷可以由外部產(chǎn)生,也可以由在EL2執(zhí)行的軟件產(chǎn)生。
4.3. IRQ and FIQ
Armv8-A 架構(gòu)有兩種異常類型,IRQ 和 FIQ,旨在用于生成外設(shè)中斷。 在其他版本的 Arm 架構(gòu)中,FIQ 被用作更高優(yōu)先級的快速中斷。 這與 Armv8-A 不同,其中FIQ 與 IRQ 具有相同的優(yōu)先級。
IRQ 和 FIQ 具有獨(dú)立的路由控制,通常用于實(shí)現(xiàn)安全和非安全中斷,如通用中斷控制器指南中所述
4.4. SError
SError 是一種異常類型,旨在由內(nèi)存系統(tǒng)生成以響應(yīng)錯(cuò)誤的內(nèi)存訪問。 SError 的典型用途是以前稱為外部的異步中止,例如已通過所有 MMU 檢查但在內(nèi)存總線上遇到錯(cuò)誤的內(nèi)存訪問。 這可能會(huì)被異步報(bào)告,因?yàn)樵撝噶羁赡芤呀?jīng)退出。 SError 中斷也可能由某些 RAM 上的奇偶校驗(yàn)或糾錯(cuò)碼 (ECC) 檢查引起,例如內(nèi)置緩存中的那些。
5 Handling exceptions
當(dāng)發(fā)生異常時(shí),當(dāng)前程序流程被中斷。 處理元素 (PE) 將更新當(dāng)前狀態(tài)并分支到向量表中的某個(gè)位置。 通常這個(gè)位置將包含通用代碼,用于將當(dāng)前程序的狀態(tài)推送到堆棧上,然后分支到進(jìn)一步的代碼。
5.1. Exception terminology
識(shí)別出異常時(shí)處理器所處的狀態(tài)稱為taken from 。 異常發(fā)生后 PE 立即所處的狀態(tài)是taken to。 例如,可以從 AArch32 EL0 到 AArch64 EL1 進(jìn)行異常處理。
Armv8-A 架構(gòu)具有觸發(fā)異常返回的指令。 在那種情況下,執(zhí)行該指令時(shí) PE 所處的狀態(tài)就是return from。 異常返回指令執(zhí)行后的狀態(tài)就是return to
每個(gè)異常類型都針對一個(gè)異常級別。 異步異常可以路由到不同的異常級別。
5.2. Taking an exception
當(dāng)發(fā)生異常時(shí),必須保留當(dāng)前狀態(tài)以便可以返回。 PE 會(huì)自動(dòng)保存異常返回地址和當(dāng)前 PSTATE
存儲(chǔ)在通用寄存器中的狀態(tài)必須由軟件保存。 PE 然后將當(dāng)前 PSTATE 更新為架構(gòu)中為該異常類型定義的 PSTATE,并跳轉(zhuǎn)到向量表中的異常處理程序。
發(fā)生異常的taken from的PSTATE 存儲(chǔ)在系統(tǒng)寄存器 SPSR_ELx 中,其中 是taken to的編號(hào)。 異常返回地址存儲(chǔ)在 ELR_ELx 中,其中 是taken to的編號(hào)。
5.3. Routing asynchronous exceptions
三種物理中斷類型可以獨(dú)立路由到特權(quán)異常級別之一,EL1、EL2 或 EL3。 下圖以 IRQ 為例:
此路由是使用 SCR_EL3 和 HCR_EL2 配置的。 使用 SCR_EL3 進(jìn)行的路由配置將覆蓋使用 HCR_EL2 進(jìn)行的路由配置。 這些控件允許將不同的中斷類型路由到不同的軟件。
路由到比正在執(zhí)行的級別更低的異常級別的異常被隱式屏蔽。 異常將被掛起,直到 PE 更改為等于或低于路由到的異常級別
5.4. Determining which Execution state an exception is taken to
異常被采取的異常級別的執(zhí)行狀態(tài)由更高的異常級別確定。 假設(shè)實(shí)現(xiàn)了所有異常級別,下表顯示了如何確定執(zhí)行狀態(tài):
5.5. Returning from an exception
軟件可以通過執(zhí)行來自 AArch64 的 ERET 指令來啟動(dòng)從異常返回。 這將導(dǎo)致根據(jù) SPSR_ELx 的值配置返回的異常級別,其中 是從中返回的級別。 SPSR_ELx 包含要返回的目標(biāo)級別和目標(biāo)執(zhí)行狀態(tài)。
注意 SPSR_ELx 中指定的 Execution state 必須與 SCR_EL3.RW 或 HCR_EL2.RW 中的配置匹配,否則會(huì)產(chǎn)生非法異常返回。
執(zhí)行 ERET 指令時(shí),狀態(tài)將從 SPSR_ELx 恢復(fù),PC將更新為 ELR_ELx 中的值。 這兩個(gè)更新將以原子方式且不可分割地執(zhí)行,以便 PE 不會(huì)處于未定義狀態(tài)。
5.6. Exception stacks
在 AArch64 中執(zhí)行時(shí),該架構(gòu)允許選擇兩個(gè)堆棧指針寄存器; SP_EL0 或 SP_ELx,其中 是當(dāng)前異常級別。 例如,在 EL1 可以選擇 SP_EL0 或 SP_EL1.
在一般執(zhí)行期間,預(yù)計(jì)所有代碼都使用 SP_EL0。 發(fā)生異常時(shí),最初選擇 SP_ELx。 這允許為初始異常處理維護(hù)單獨(dú)的堆棧。 這對于在處理由堆棧溢出引起的異常時(shí)維護(hù)有效堆棧很有用。
6 The vector tables
在 Armv8-A 中,向量表是包含指令的普通內(nèi)存區(qū)域。 處理器元素 (PE) 將表的基地址保存在系統(tǒng)寄存器中,并且每個(gè)異常類型都具有一個(gè)相對于該基址的定義偏移量。
每個(gè)特權(quán)異常級別都有自己的向量表,由向量基地址寄存器 VBAR_ELx 定義,其中 是 1,2 或 3。
VBAR 寄存器的值在復(fù)位后未定義,因此必須在啟用中斷之前對其進(jìn)行配置.
向量表的格式如下所示:
每種異常類型都可以導(dǎo)致跳轉(zhuǎn)到四個(gè)位置之一,具體取決于從中獲取異常的taken form的狀態(tài)。
總結(jié)
- 上一篇: 03_Introduction_to_A
- 下一篇: 06-GICv3_v4_overview