1. 特權和異常級別(Privilege and Exception level)
現代軟件開發(fā)成不同的模塊,每個模塊對系統(tǒng)和處理器資源有不同級別的訪問。操作系統(tǒng)(OS)內核和應用程序就是一個例子。OS需要執(zhí)行不期望應用程序能夠執(zhí)行的操作。內核需要對系統(tǒng)資源的高級訪問,而應用程序需要有限的配置系統(tǒng)的能力。特權(privilege)規(guī)定了軟件實體可以看到和控制哪些處理器資源。
AArch64架構通過不同級別的特權來實現這種劃分。當前權限級別只能在處理器接受異?;驈漠惓7祷貢r更改。這些特權級別在Arm架構中稱為異常級別。
1.1 ?異常級別
在AArch64中,特權privilege叫作異常級別(Exception level),縮寫為EL。異常級別有編號,縮寫為EL<x>,x是0到3之間的數字。特權級別越高,數字就越高。最低級別的特權為EL0。
如下圖所示,有四個異常級別:EL0, EL1, EL2和EL3。
常見的使用模型是在EL0上運行應用程序,在EL1上運行rich OS,如Linux等。管理程序(hypervisor)可以使用EL2,固件和安全網關代碼可以使用EL3。例如,Linux可以在EL3調用固件函數,使用軟件接口標準,從底層細節(jié)中抽象出啟動或關閉core的意圖。這個模型意味著大量的PE處理通常發(fā)生在EL0/1。
那什么是rich OS呢?嵌入式系統(tǒng)可以按操作系統(tǒng)分成三類:Rich OS類、RTOS類、Bare-metal類。
Rich OS類(全能操作系統(tǒng)):這類嵌入式系統(tǒng)運行功能非常齊全的操作系統(tǒng),例如Linux、Android、iOS等。
RTOS類(實時操作系統(tǒng)):這類嵌入式系統(tǒng)運行功能緊湊但具有很強實時性的RTOS,例如FreeRTOS、RT-Threads、uC/OS-II等。這類系統(tǒng)通常使用微控制器,也就是俗稱的單片機。
Bare-metal類:不包含任何操作系統(tǒng),可能會包含事件調度器。這類系統(tǒng)也使用微控制器。這類系統(tǒng)主要是功能比較單一的應用。
異常級別只能在以下情況發(fā)生時更改:
接受異常
從異常中返回
處理器復位
在調試狀態(tài)中
從調試狀態(tài)退出
當發(fā)生異常時,異常級別可以增加或保持不變。永遠不能通過接受異常來移動到較低的特權級別。當從異常返回時,異常級別可以降低或保持不變。從異常返回永遠不能移動到更高的權限級別。
1.2 ?特權類型(Types of privilege)
與AArch64 異常模型相關的特權有兩種類型:
內存系統(tǒng)中的特權
從訪問處理器資源的角度來看的特權
這兩種類型的特權都受到當前特權異常級別的影響。
Memory privilege:
Arm架構的A-profile實現了虛擬內存系統(tǒng),其中內存管理單元MMU允許軟件為內存區(qū)域分配屬性。這些屬性包括可配置為允許特權訪問和非特權訪問的單獨訪問權限的讀/寫權限。
發(fā)生在EL0的內存訪問將對照非特權訪問權限進行檢查。EL1,EL2和EL3的訪問將對照特權訪問權限進行檢查。
由于內存配置是由軟件使用MMU轉換表編程的,所以在對這些表進行編程時要考慮所需的特權。MMU配置存儲在系統(tǒng)寄存器中,并且訪問這些寄存器的能力也由當前的異常級別控制。
Register access:
AArch64處理器的配置設置保存在系統(tǒng)寄存器(System register)中。系統(tǒng)寄存器的設置組合定義了當前處理器的上下文。對系統(tǒng)寄存器的訪問由當前異常級別控制。
例如,VBAR_EL1是向量基址寄存器(Vector Base Address Register)。它的_EL1后綴表示軟件至少需要EL1特權才能訪問該寄存器。
該體系結構有許多具有功能相似的寄存器,這些寄存器的名稱僅在異常級別后綴上有所不同。它們是獨立的寄存器,在指令集中有自己的編碼,在硬件中單獨實現。
這些寄存器的名稱相似,反映了它們執(zhí)行的任務相似,但它們是完全獨立的寄存器,具有自己的訪問語義。系統(tǒng)寄存器名字的后綴表示可以訪問該寄存器的最低異常級別。
每個實現的異常級別都有一個系統(tǒng)控制寄存器(SCTLR)。每個寄存器控制該EL的架構特性,例如MMU、緩存和對齊檢查:
SCTLR_EL1:EL0和EL1的頂級系統(tǒng)控制。
SCTLR_EL2:EL2的頂級系統(tǒng)控制。
SCTLR_EL3:EL3的頂級系統(tǒng)控制。
注意:EL1和EL0共享相同的MMU配置,且只能由運行在EL1上的代碼進行控制。因此沒有SCTLR_EL0,所有的控制都來自EL1可訪問的寄存器。其他控制寄存器通常遵循此模型。
較高的異常級別有權訪問控制較低級別的寄存器。例如,EL2在必要時擁有訪問SCTLR_EL1的權限。但是不能從EL0訪問該寄存器,這樣做會產生異常。
在一般的系統(tǒng)操作中,特權異常級別控制自己的配置。然而,特權級別高的級別有時會訪問與低異常級別的寄存器。例如,通過這樣來實現虛擬化特性和上下文切換。
以下系統(tǒng)寄存器將用于討論與AArch64異常模型相關的問題。
2. ?執(zhí)行和安全狀態(tài)(Execution and Security states)
AArch64架構提供了四種異常級別。還有兩個執(zhí)行狀態(tài)和最多四個安全狀態(tài)。Armv8-A或Armv9-A處理器的當前狀態(tài)由異常級別和當前執(zhí)行狀態(tài)決定。
2.1 ?執(zhí)行狀態(tài)(Execution states)
當前的執(zhí)行狀態(tài)定義了通用寄存器的標準寬度和可用的指令集。執(zhí)行狀態(tài)還影響內存模型的各個方面以及異常的管理方式。
Armv8-A和Armv9-A支持兩種Execution狀態(tài):AArch32和AArch64。
AArch32是32位的執(zhí)行狀態(tài)。這種狀態(tài)下的操作與以前的體系結構向后兼容。它支持T32和A32指令集。標準寄存器寬度是32位。
AArch64是64位的執(zhí)行狀態(tài)。它支持A64指令集。標準寄存器寬度是64位。
2.2 ?安全狀態(tài)(Security states)
AArch64允許實現多個安全狀態(tài),可進一步對軟件進行分區(qū),以隔離和劃分可信軟件。大多數處理器支持兩種安全狀態(tài):
安全狀態(tài):Processing?Element?(PE)可以訪問安全的和非安全的物理地址空間,以及存儲寄存器的安全副本。
非安全狀態(tài):通常也被稱為正常世界。此時PE只能訪問非安全的物理地址空間。PE只能訪問允許非安全訪問的系統(tǒng)寄存器。
安全狀態(tài)定義了可以訪問哪些異常級別,當前可以訪問哪些內存區(qū)域,以及這些訪問在系統(tǒng)內存總線上是如何表示的。處于非安全狀態(tài)時,PE只能訪問非安全物理地址空間。在安全狀態(tài)下,PE可以訪問安全和非安全的物理地址空間。
舉一個例子: 可以讓操作系統(tǒng)(如Android)在正常世界中運行,在安全世界中運行支付或DRM系統(tǒng)。我們需要對安全世界系統(tǒng)有更高程度的信任,并將它們分開以保護支付細節(jié)和密鑰之類的信息。擁有兩個安全狀態(tài)提供了這種分離。
下圖顯示了異常級別和安全狀態(tài),以及不同的執(zhí)行狀態(tài)。
改變安全狀態(tài)
如果實現了TrustZone,那么處理器可以處于安全狀態(tài)或非安全狀態(tài)。這是由SCR_EL3.NS bit來選擇的。當沒有實現RME時,SCR_EL3.NS為0表明EL0和EL1為安全狀態(tài),SCR_EL3.NS為1表明EL0、EL1和EL2為非安全狀態(tài),SCR_EL3.{EEL2, NS} == {1, 0}表面EL2為安全狀態(tài)。
在前面的圖中,EL3處于安全狀態(tài)。EL3是特權最高的異常級別,EL3的安全狀態(tài)是固定的。EL3能夠訪問banked System register的所有副本。
在Armv8-A中EL3始終處于安全狀態(tài)。在Armv9-A中,除非實現RME,否則EL3是安全狀態(tài)的一部分。如果實現了RME,Root狀態(tài)是EL3與安全狀態(tài)的其余部分的分離。
當你想從一個安全狀態(tài)切換到另一個安全狀態(tài)時,必須通過EL3。EL3的軟件負責管理對不同安全狀態(tài)的訪問并充當守門人,控制對EL2、EL1和EL0的安全狀態(tài)的訪問。SCR_EL3.NS位允許從EL3返回時更改安全狀態(tài)。
注意:在EL0、EL1和EL2時,PE可以處于安全狀態(tài)或非安全狀態(tài)。經常會看到這樣的情況。NS_EL1:非安全狀態(tài),異常級別1;S_EL1:安全狀態(tài),異常級別1。
Realm Management Extension(RME)
Armv9-A引入了對Realm Management Extension(RME)的支持。在實現RME時,還支持兩種額外的安全狀態(tài):
Realm狀態(tài):PE可以訪問非安全和Realm的物理地址空間。
Root狀態(tài):PE可以訪問所有的物理地址空間。Root狀態(tài)僅在EL3中可用。
RME將EL3與所有其他安全狀態(tài)隔離。使用RME,EL3從安全狀態(tài)移出,進入自己的叫作Root的安全狀態(tài)。EL3承載平臺和初始boot代碼,因此必須在安全、非安全和Realm狀態(tài)下受軟件信任。
2.3 ?異常級別實現的影響
對于一個處理器,是否實現所有異常級別,以及每個異常級別允許哪些執(zhí)行狀態(tài),都是實現選擇的。
EL0和EL1是必須實現的,而EL2和EL3是可選的。如果EL3或EL2沒有實現,那么需要考慮以下幾點:
EL2包含許多虛擬化功能。沒有EL2的實現不能訪問這些特性。
EL3是唯一可以更改安全狀態(tài)的級別。如果不實現EL3,PE只能訪問一個安全狀態(tài)。因此,永久處于的狀態(tài)是實現定義的。
已經開發(fā)的一些軟件實現要求平臺支持這些異常級別。例如,KVM Linux要求為EL2、EL1、EL0。
3. ?異常類型(Exception type)
異常是需要由特權軟件采取補救措施或更新系統(tǒng)狀態(tài)以確保系統(tǒng)平穩(wěn)運行的條件或系統(tǒng)事件。因此,異??梢允菍е庐斍罢趫?zhí)行的程序暫停的任何事件。接受異常會導致狀態(tài)發(fā)生變化,以執(zhí)行處理該異常的代碼。
其他處理器架構可能將此描述為中斷。在AArch64中,中斷是一種特定類型的外部生成的異常。
異常有很多不同的原因,包括以下:模擬虛擬設備、虛擬內存管理、處理軟件錯誤、處理硬件錯誤、調試、執(zhí)行對不同特權或安全狀態(tài)的調用、處理中斷(定時器,設備交互)、跨不同的執(zhí)行狀態(tài)的處理(稱為interprocessing)。
當發(fā)生異常時,處理器不會移動到當前代碼中的下一條指令,而是停止當前的執(zhí)行并分支到一段代碼來處理請求。這段代碼稱為異常處理程序(exception handler)。一旦事件被處理,執(zhí)行就可以返回到原始程序。每種異常類型都有自己的異常處理程序。
Arm架構將異常分為兩大類:同步異常和異步異常。
3.1 ?同步異常
同步異常是由當前正在執(zhí)行的指令或者與之相關的操作引起的異常。同步異常與執(zhí)行流是同步的,因為它們與當前執(zhí)行的指令直接相關。例如,同步異常將由試圖寫入MMU定義的只讀位置的指令觸發(fā)。
如果以下所有情況都適用,則異常是同步的:
異常是直接或嘗試執(zhí)行指令的結果。
異常處理后要返回的地址與引起異常的指令有架構定義的關系。
異常是精確的,這意味著在異常處理程序中顯示的寄存器狀態(tài)與違規(guī)指令執(zhí)行之前的每條指令一致,而在違規(guī)指令執(zhí)行之后則不一致。
同步異常有許多不同的類型,一個給定的指令可能會導致多個同步異常。Arm架構為同步異常提供了固定的優(yōu)先級順序。
3.2 ?異步異常
某些類型的異常是在外部生成的,因此與當前指令流不同步。異步異常與當前執(zhí)行的指令沒有直接關聯,通常來自處理器外部的系統(tǒng)事件??赡苁擒浖枰憫南到y(tǒng)事件,例如計時器的活動或屏幕的觸摸。我們不知道什么時候會發(fā)生。
根據定義,如果異常不是同步的,那么它就是異步的。異步異常也稱為中斷。在接受異步異常時,程序流被中斷,并傳遞給專門處理此請求的代碼。不可能準確地保證異步異常何時發(fā)生,AArch64架構只要求它在有限的時間內發(fā)生。
3.2.1 ?物理中斷
物理中斷是對來自PE外部設備的信號的響應而產生的中斷。與core不斷輪詢外部信號不同,系統(tǒng)通過生成中斷來通知core必須發(fā)生某些事情。
例如,系統(tǒng)可能使用UART接口與外部世界通信。當UART接收到數據時,它需要一種機制來告訴處理器新數據已經到達并準備好進行處理。UART可以生成中斷來向處理器發(fā)出信號。
下面是不同類型的物理中斷:
系統(tǒng)錯誤(SError)
系統(tǒng)錯誤(SError)是內存系統(tǒng)響應意外事件時產生的一種異常類型。我們并不期待這些事件發(fā)生,但需要知道是否已經發(fā)生。這些事件是異步報告的,因為觸發(fā)事件的指令可能已經retire了。
SError的一個典型示例是外部異步abort。SError中斷的例子包括:
已通過所有MMU檢查的內存訪問,但隨后在內存總線上遇到錯誤
校驗或錯誤糾正碼(ECC)檢查某些ram,例如內置緩存中的ram
由臟數據從緩存線回寫到外部內存觸發(fā)的abort
SError被視為一個單獨的異步異常類,因為通常會有單獨的處理程序來處理這些情況。SError的產生是實現定義的。
IRQ和FIQ
Arm架構有兩種異步異常類型,IRQ和FIQ,用于支持外設中斷的處理。它們用于發(fā)出外部事件的信號,例如計時器停止,而不代表系統(tǒng)錯誤。它們是與處理器指令流異步的預期事件。
IRQ和FIQ具有獨立的路由控制,通常用于實現安全和非安全中斷。(注意:在Arm架構的舊版本中,FIQ被用作高優(yōu)先級的快速中斷。這與AArch64不同,在AArch64中FIQ與IRQ具有相同的優(yōu)先級。)
3.2.2 ?虛擬中斷
使用虛擬化的系統(tǒng)對中斷處理有更復雜的需求。有些中斷可能由hypervisor傳遞,有些可能在VM中處理。VM看到的中斷是虛擬中斷。虛擬中斷可以由連接到中斷控制器的設備在外部生成,也可以由軟件生成。因此需要額外的機制來支持這一點,在AArch64中顯式地支持虛擬中斷。
vSError,虛擬系統(tǒng)錯誤
vIRQ,虛擬IRQ
vFIQ,虛擬FIQ
虛擬中斷根據中斷類型進行控制。這些虛擬中斷的功能與物理中斷相同,但是只能向EL1發(fā)送信號。
虛擬中斷可以從位于EL2的hypervisor生成,也可以使用中斷控制器生成。hypervisor必須在Hypervisor配置寄存器(HCR_EL2)中設置相應的routing bit。例如,要啟用vIRQ信號,hypervisor必須設置HCR_EL2.IMO。該設置將物理IRQ異常路由到EL2,并將虛擬異常發(fā)送到EL1。
在HCR_EL2中有三個bit控制虛擬中斷的產生:
VSE:設置這個位注冊一個vSError。
VI:設置該位注冊一個vIRQ。
VF:設置該位注冊一個vFIQ。
設置其中一個位相當于中斷控制器將中斷信號斷言給一個vCPU。這種方法的一個含義是,hypervisor隨后需要模擬VM中中斷控制器的操作。當用于頻繁操作時,這會導致顯著的開銷,因此建議使用中斷控制器。
3.2.3 ?屏蔽
物理和虛擬的異步異常都可以被臨時屏蔽。這意味著異步異??梢砸恢北3衷趻炱馉顟B(tài),直到它們被解除屏蔽并接受異常。這對于處理嵌套異常特別有用。
同步異常不能被屏蔽。這是因為同步異常是由指令的執(zhí)行直接引起的,如果它們被掛起或忽略,就會阻塞執(zhí)行。
2021擴展的Armv8.8-A和Armv9.3-A增加了不可屏蔽中斷(NMI)的支持。當支持并啟用該功能時,可以通過該功能將中斷作為具有Superpriority的方式呈現給處理器。Superpriority允許在沒有Superpriority的中斷將被屏蔽時接受中斷。
ARM架構內容復雜繁多,學習起來會比較費時費力,推薦以下ARM學習視頻,可以快速熟悉和掌握ARM處理器架構,做到事半功倍,有需要的可以嘗試一下~