05-Exception Handling Framework
引流關鍵詞: 中斷、同步異常、異步異常、irq、fiq、BL1,BL2,BL3,BL31,BL32,BL33,AP_BL1,AP_BL2,AP_BL3,AP_BL31,AP_BL32,AP_BL33,SCP_BL1,SCP_BL2,BL0,BL30, optee、ATF、TF-A、Trustzone、optee3.14、MMU、VMSA、cache、TLB、arm、armv8、armv9、TEE、安全、內存管理、頁表…
快速鏈接:
.
👉👉👉 個人博客筆記導讀目錄(全部) 👈👈👈
[專欄目錄]-ATF/FF-A/specification學習
術語
EHF : Exception Handling Framework
5.異常處理框架
本文檔描述了運行時固件 (BL31) 針對 EL3(而非 SMC)處理異常的framework。EHF將處理以下異常:
- 中斷
- 同步外部中止 (Synchronous External Aborts)
- 異步外部中止(Asynchronous External Aborts)
固件設計文檔中描述了TF-A對從較低 EL 引發的同步SMC異常。然而, EHF描述了除 SMC之外的中斷處理和同步異常的語義
通過將構建選項設置為 來選擇EHF(EL3_EXCEPTION_HANDLING=1) ,并且僅適用于 AArch64 系統。
5.1 介紹
通過寄存器中的各種控制位SCR_EL3,Arm 架構允許將異步異常路由到 EL3。如 中斷管理框架文檔中所述,根據所選的中斷路由模型,TF-A 適當地設置寄存器的FIQ和IRQ位 SCR_EL3以實現此路由。對于大多數用例,除了促進正常和安全世界之間的上下文切換之外,路由到 EL3 的 FIQ 和 IRQ 不需要在 EL3 中處理。
然而,不斷發展的系統和標準環境要求在 EL3 中針對和處理各種異常。例如:
-
從 ARMv8.2 架構擴展開始,許多 RAS 特性被引入到 Arm 架構中。實施 RAS 功能后,系統的各種組件可以使用其中一種異步異常來向 PE 發出錯誤信號。這些錯誤情況具有嚴重的性質,必須盡早采取糾正或補救措施。因此,通常遵循固件優先處理方法來響應系統中的 RAS 事件。
-
Arm SDEI 規范定義了 Normal world 與 Runtime Firmware 交互以請求系統事件通知的接口。SDEI規范要求通知這些事件,即使在正常世界執行時屏蔽了異常。這也意味著需要固件優先處理,其中事件首先由 EL3 固件接收,然后通過純軟件機制發送到普通世界。
對于TF-A,固件優先處理意味著異步異常被適當地路由到 EL3,并且運行時固件 (BL31) 被擴展為包括能夠處理以 EL3 為目標的那些異常的軟件組件。這些組件(通常稱為調度程序 : dispatchers )可以選擇:
- 完全在 EL3 中接收和處理異常,這意味著異常處理在 EL3 中終止。
- 接收異常,但在 EL3 中處理部分異常,并將其余處理委托給在較低安全 EL 上運行的專用軟件堆棧。在該方案中,處理跨越各種安全 EL。
- 接收異常,但在 EL3 中處理部分異常,并將錯誤的處理委托給在較低安全 EL 上運行的專用軟件堆棧(如上);此外,普通世界也可能需要參與處理,或被通知此類事件(例如,作為SDEI事件)。在此方案中,異常處理可能且最大程度地跨越安全和正常世界中的所有 EL。
在任何給定的系統上,所有上述處理模型都可以獨立使用,具體取決于平臺選擇和接收到的異常的性質。
5.2. 異常處理框架的作用
作為上述用例的推論,EHF的主要作用是促進固件優先處理 Arm 系統上的異常。因此,EHF使運行時固件中的多個異常分派器能夠共存、注冊和處理針對 EL3 的異常。本節概述了基礎知識,本文檔的其余部分擴展了EHF的各個方面。
為了在調度程序之間仲裁異常處理,EHF操作基于優先級方案。這種優先級方案與 Arm GIC 架構如何定義它密切相關,盡管它也適用于非中斷異常(例如 SErrors)。
平臺需要將安全優先級空間劃分為適用于安全軟件堆棧的優先級。然后它將調度程序分配給一個或多個優先級。然后調度程序在運行時為優先級注冊處理程序。調度程序可以為多個優先級注冊處理程序。
當處于該優先級的處理程序當前正在 EL3 中執行或已將執行委托給較低的 EL 時,該優先級處于活動狀態。對于中斷,當一個中斷在 EL3 被定位和確認時,這是隱含的,并且已確認中斷的優先級用于匹配其注冊的處理程序。當中斷處理通過 EOI 中斷結束時,優先級同樣被隱式禁用。
非中斷異常(例如 SErrors)沒有優先級的概念。為了使優先級仲裁起作用,EHF提供了 API,以便這些非中斷異常具有優先級,并與中斷交互。因此,處理此類異常的調度程序必須在處理或委派它們時顯式激活和停用相應的優先級。
因為中斷處理的優先級激活和停用是隱式的并且涉及 GIC 優先級屏蔽,所以較低優先級的中斷不可能搶占較高優先級的中斷。通過擴展,這意味著較低優先級的調度程序不能搶占較高優先級的調度程序。然而,非中斷異常的優先級激活和停用必須是明確的。因此,EHF不允許在較高優先級處于活動狀態時激活較低優先級,并且會導致恐慌。同樣,如果在較高優先級處于活動狀態時嘗試停用較低優先級,則會導致恐慌。
本質上,優先級激活和停用在概念上就像一個堆棧——優先級以嚴格遞增的方式堆疊,并且需要以嚴格的相反順序取消堆疊。對于中斷,GIC 確保是這種情況;對于非中斷,EHF監控并斷言這一點。請參閱 優先級轉換。
5.3. 中斷處理
EHF是中斷管理框架的客戶端,并為針對 EL3 的中斷注冊頂級處理程序,如 中斷管理框架文檔中所述。這具有以下含義:
-
在 GICv3 系統上,當在 S-EL1 中執行時,具有足夠優先級的未決非安全中斷將作為 FIQ 發出信號,因此將被路由到 EL3。因此,S-EL1 軟件不能期望在 S-EL1 處處理非安全中斷。本質上,這不贊成描述為CSS=0, TEL3=0的路由模式。
-
為了讓 S-EL1 軟件在 啟用EHF時處理非安全中斷,調度程序必須采用一種模型,即在 EL3 接收非安全中斷,然后同步 處理到 S-EL1。
-
在 GICv2 系統上,需要將構建選項GICV2_G0_FOR_EL3設置為,1以便Group 0中斷以 EL3 為目標。
-
在安全世界中執行時,EHF將 GIC 優先級掩碼寄存器設置為最低安全優先級。這意味著沒有非安全中斷可以搶占安全執行。有關更多詳細信息,請參閱對 SMC 調用的影響。
如上所述,使用EHF時,平臺需要將Group 0 中斷劃分為不同的優先級。選擇接收中斷的調度程序然后可以擁有一個或多個優先級,并為它們注冊中斷處理程序。給定的優先級只能分配給一個處理程序。調度程序可以注冊多個優先級。
分派器分兩步分配中斷優先級:
5.3.1。分區優先級
通過對中斷進行分組和分配優先級的方式,中斷與調度程序相關聯。換句話說,所有針對特定調度程序的中斷都應該屬于特定的優先級。對于優先級分配:
-
Arm GIC 架構允許的 8 位優先級中,第 7 位必須為 0(安全空間)。
-
根據要支持的調度程序的數量,平臺必須選擇使用剩余 7 個位中的前n位來識別中斷并將其分配給各個調度程序。選擇n位最多支持 2 n 個 不同的調度程序。例如,通過選擇 2 個附加位(即位 6 和 5),平臺可以劃分為 4 個安全優先級范圍:0x0、 0x20、0x40和0x60。請參閱中斷處理示例。
注意: Arm GIC 架構要求支持兩種安全狀態的 GIC 實現必須實現至少 32 個優先級;即,8位中的至少5個高位是可寫的。In the scheme described above, when choosing n bits for priority range assignment, the platform must ensure that at least n+1top bits of GIC priority are writeable.
因此分配給中斷的優先級也用于確定較低 EL 中委派執行的優先級。較低 EL 中的委托執行與使用ehf_activate_priority()API 選擇的優先級相關聯(稍后描述)。選擇的優先級還決定了在較低 EL 中執行時屏蔽的中斷,因此控制了委托執行的搶占。
平臺通過聲明優先級描述符數組來表達選擇的優先級。數組中的每個條目都是類型 ehf_pri_desc_t,并聲明一個優先級,并應由 EHF_PRI_DESC()宏填充。
注意:宏EHF_PRI_DESC()將描述符安裝在數組中的計算索引處,而不必將宏放置在數組中的位置。因此,數組的大小可能比它看起來的要大。因此ARRAY_SIZE()應該使用宏來確定數組的大小。
最后,這個描述符數組通過 宏暴露給EHF 。EHF_REGISTER_PRIORITIES()
使用方法請參考中斷處理示例。另請參閱:中斷優先級考慮。
5.3.2. 編程優先級
分區優先級中的文本僅描述了平臺如何表達所需的優先級。然而,它不會選擇中斷,也不會在 GIC 中編程所需的優先級。
固件設計指南解釋了配置安全中斷的方法。EHF要求平臺枚舉安全中斷的中斷屬性(而不僅僅是數量)。安全中斷的優先級必須與上面分區優先級部分中確定的相匹配 。
請參閱限制,另請參閱中斷處理示例以進行說明。
5.4. 注冊處理程序
調度程序通過以下 API 為其優先級注冊處理程序:
int ehf_register_priority_handler(int pri, ehf_handler_t handler)API 有兩個參數:
-
注冊處理程序的優先級;
-
要注冊的處理程序。處理程序必須對齊到 4 個字節。
如果調度程序擁有多個優先級,它必須為每個優先級調用 API。
API 將成功并返回0,僅在以下情況下:
-
存在具有請求的優先級的描述符。
-
之前調用 API 時沒有注冊處理程序。
否則,API 返回-1.
中斷處理程序應具有以下簽名:
typedef int (*ehf_handler_t)(uint32_t intr_raw, uint32_t flags, void *handle,void *cookie);這些參數是從頂級EL3 中斷處理程序中獲得的。
例如,SDEI 調度程序期望平臺分配兩個不同的優先級 - PLAT_SDEI_CRITICAL_PRI和PLAT_SDEI_NORMAL_PRI- 并注冊相同的處理程序來處理這兩個級別。
5.5. 中斷處理示例?
以下帶注釋的片段演示了平臺如何選擇將中斷分配給虛構的調度程序:
#include <common/interrupt_props.h> #include <drivers/arm/gic_common.h> #include <exception_mgmt.h>.../** This platform uses 2 bits for interrupt association. In total, 3 upper* bits are in use.** 7 6 5 3 0* .-.-.-.----------.* |0|b|b| ..0.. |* '-'-'-'----------'*/ #define PLAT_PRI_BITS 2/* Priorities for individual dispatchers */ #define DISP0_PRIO 0x00 /* Not used */ #define DISP1_PRIO 0x20 #define DISP2_PRIO 0x40 #define DISP3_PRIO 0x60/* Install priority level descriptors for each dispatcher */ ehf_pri_desc_t plat_exceptions[] = {EHF_PRI_DESC(PLAT_PRI_BITS, DISP1_PRIO),EHF_PRI_DESC(PLAT_PRI_BITS, DISP2_PRIO),EHF_PRI_DESC(PLAT_PRI_BITS, DISP3_PRIO), };/* Expose priority descriptors to Exception Handling Framework */ EHF_REGISTER_PRIORITIES(plat_exceptions, ARRAY_SIZE(plat_exceptions),PLAT_PRI_BITS);.../* List interrupt properties for GIC driver. All interrupts target EL3 */ const interrupt_prop_t plat_interrupts[] = {/* Dispatcher 1 owns interrupts d1_0 and d1_1, so assigns priority DISP1_PRIO */INTR_PROP_DESC(d1_0, DISP1_PRIO, INTR_TYPE_EL3, GIC_INTR_CFG_LEVEL),INTR_PROP_DESC(d1_1, DISP1_PRIO, INTR_TYPE_EL3, GIC_INTR_CFG_LEVEL),/* Dispatcher 2 owns interrupts d2_0 and d2_1, so assigns priority DISP2_PRIO */INTR_PROP_DESC(d2_0, DISP2_PRIO, INTR_TYPE_EL3, GIC_INTR_CFG_LEVEL),INTR_PROP_DESC(d2_1, DISP2_PRIO, INTR_TYPE_EL3, GIC_INTR_CFG_LEVEL),/* Dispatcher 3 owns interrupts d3_0 and d3_1, so assigns priority DISP3_PRIO */INTR_PROP_DESC(d3_0, DISP3_PRIO, INTR_TYPE_EL3, GIC_INTR_CFG_LEVEL),INTR_PROP_DESC(d3_1, DISP3_PRIO, INTR_TYPE_EL3, GIC_INTR_CFG_LEVEL), };.../* Dispatcher 1 registers its handler */ ehf_register_priority_handler(DISP1_PRIO, disp1_handler);/* Dispatcher 2 registers its handler */ ehf_register_priority_handler(DISP2_PRIO, disp2_handler);/* Dispatcher 3 registers its handler */ ehf_register_priority_handler(DISP3_PRIO, disp3_handler);...另請參閱構建時流程和運行時流程。
5.6. 激活和停用優先級
當處理該優先級的異常時,該優先級被認為是活動的:對于中斷,這在中斷被確認時是隱含的;對于非中斷異常,例如 SErrors 或SDEI 顯式調度,這必須通過調用來完成ehf_activate_priority()。請參閱運行時流程。
相反,當調度程序已經達到異常原因的邏輯解決方案時,相應的優先級應該被停用。如上,對于中斷,當中斷為 GIC 中的 EOId 時,這是隱含的;對于其他例外情況,這必須通過調用來完成 ehf_deactivate_priority()。
由于異常委派的不同規定,可能有不止一個工作流程用于停用:
-
調度程序已解決異常的原因,并決定不采取進一步措施。在這種情況下,調度程序的處理程序在返回EHF之前停用優先級。運行時固件在通過 退出時,會ERET在中斷發生之前恢復執行。
-
SMC調度程序必須將執行委托給較低的 EL,并且只有當較低的 EL在未來的某個時間點返回完成(通過 an )信號時,才能認為異常的原因已解決。出現以下順序:
(1)、調度員調用setjmp()設置一個跳轉點,并安排在下一個 EL 時進入較低的 EL ERET。
(2)、通過隨后ERET的運行時固件,將執行委托給較低的 EL。
(3)、較低的 EL 完成其執行,并通過 SMC.
(4)、由SMC之前處理異常的同一調度程序處理。注意到異常處理的結束,調度程序確實longjmp()恢復到前一個跳轉點之外。
如上所述,EHF提供以下 API 用于激活和停用中斷:
-
ehf_activate_priority()激活提供的優先級,但前提是當前活動的優先級高于給定的優先級;否則恐慌。此外,為了防止被較低優先級的物理中斷中斷,EHF將對應于 PE 的優先級掩碼寄存器編程為被激活的優先級。調度程序通常只需要在處理除中斷以外的異常時調用它,并且它需要將執行委托給所需優先級的較低 EL。
-
ehf_deactivate_priority()停用給定的優先級,但前提是當前活動的優先級等于給定的優先級;否則恐慌。EHF 還將PE對應的Priority Mask Registerehf_activate_priority()恢復到調用之前的優先級。調度程序通常只需要在處理除中斷以外的異常后調用它。
API 的調用取決于允許的轉換。另請參見 運行時流程。
5.7. 優先級的轉換
可以調用EHF APIehf_activate_priority()來轉換 PE 上的當前優先級。ehf_deactivate_priority()對這些 API 的給定調用序列受以下條件的約束:
-
對于激活,EHF只允許增加優先級(即數值減少);
-
對于停用,EHF只允許降低優先級(即增加數值)。此外,被停用的優先級必須是當前優先級。
如果違反這些,就會導致恐慌。
5.8. 對 SMC 呼叫的影響
一般來說,安全執行被認為比非安全執行更重要。正如本文檔其他地方所討論的,EL3 執行以及之后的任何委派執行都具有提高 GIC 優先級掩碼的效果——無論是通過確認安全中斷隱含地,還是在調度程序調用ehf_activate_priority(). 因此,非安全中斷不能搶占任何安全執行。
來自非安全世界的 SMC 是同步異常,是非安全世界請求安全服務的機制。它們被廣泛歸類為 快速或屈服(參見SMCCC)。
-
從調用者的角度來看,快速SMC 是原子的。即,它們僅在安全世界完成服務請求時才返回給調用者。同時掛起的任何非安全中斷都不能搶占安全執行。
-
Yielding SMC 帶有可搶占的、低優先級請求的語義。掛起的非安全中斷可以搶占處理 Yielding SMC 的安全執行。即,調用者可能會在以下任一情況下觀察到 Yielding SMC 返回:
(1)安全世界完成請求,調用者將找到SMC_OK 作為返回碼。
(2)非安全中斷搶占安全執行。處理非安全中斷,并在SMC指令后恢復非安全執行。 -
處理 Yielding SMC 的調度程序必須向非安全調用方提供不同的返回碼,以區分后一種情況。但是,此返回代碼不是標準化的(例如,與SMC_UNKNOWNor不同SMC_OK),因此會因處理請求的調度程序而異。
對于上面的后一種情況,EHF之前的調度程序期望將非安全中斷帶到 S-EL1 2,因此將有機會在屈服于非安全世界之前填充指定的搶占錯誤代碼。
EHF的引入改變了中斷處理中描述的行為。
啟用EHF時,為了允許非安全中斷搶占 Yielding SMC 處理,調度程序必須調用ehf_allow_ns_preemption() API。API 采用一個參數,即在被搶占后返回到非安全世界的錯誤代碼。
5.9. 構建時流程
構建時流程涉及以下步驟:
(1)平臺通過為各個調度程序安裝優先級描述符來分配優先級,如分區優先級中所述。
(2)平臺為 GIC 驅動程序提供中斷屬性,如 編程優先級中所述。
(3)調度程序調用ehf_register_priority_handler()以注冊中斷處理程序。
5.10。運行時流
以下是中斷的示例流程:
(1)GIC 驅動程序在初始化期間迭代平臺提供的中斷屬性(請參閱編程優先級),并配置中斷。這會對屬于不同調度程序的中斷編程適當的優先級和組(組 0)。
(2)EHF在其初始化過程中,向 EL3 中斷的中斷管理框架注冊一個頂級中斷處理程序。這也導致設置路由位SCR_EL3。
(3)當屬于調度程序的中斷觸發時,GIC 引發 EL3/Group 0 中斷,并被帶到 EL3。
(4)執行頂級 EL3 中斷處理程序。處理程序確認中斷,讀取其運行優先級,并據此確定調度程序處理程序。
(5)EHF將PE 的優先級屏蔽寄存器編程為接收到的中斷的優先級。
(6)EHF將該優先級標記為active,并跳轉到調度程序處理程序。
(7)一旦調度程序處理程序完成其工作,它必須在返回EHF之前立即 停用優先級。請參閱 停用工作流程。
以下是針對除中斷以外的 EL3 的異常的示例流程:
(1)該平臺為特定類型的異常提供處理程序。
(2)異常到來,相應的處理程序被執行。
(3)處理程序調用ehf_activate_priority()以激活所需的優先級。這也具有提高 GIC 優先級掩碼的效果,從而防止較低優先級的中斷搶占處理。處理程序可以選擇完全在 EL3 中進行處理或委托給較低的 EL。
(4)一旦異常處理結束,處理程序將調用 ehf_deactivate_priority()以停用先前激活的優先級。這也具有將 GIC 優先級掩碼降低到以前的效果。
5.11。中斷優先級考慮
根據設計,GIC 優先級方案將安全中斷優先于普通世界中斷。該平臺通過EHF進一步在安全調度員之間分配相對優先級。
如分區優先級中所述,針對不同調度程序的中斷屬于不同的優先級。因為它們是通過 GIC 路由的,所以到 PE 的中斷傳遞受 GIC 優先級規則的約束。特別是,當 PE 正在處理中斷時(即中斷處于活動狀態),即使具有相同或較低優先級的中斷未決,也只有較高優先級的中斷會被發送到 PE。這會產生一個副作用,即一個調度程序由于另一個調度程序處理其(更高優先級)中斷而缺乏中斷。
EHF不強制執行特定的優先級策略,但平臺應仔細考慮將優先級分配給集成到運行時固件中的調度程序。平臺應根據不同調度員的性質,明智地為其劃分優先級。特別是,關鍵性質的調度程序(例如 RAS)應該被分配比其他調度程序更高的優先級(例如SDEI);在SDEI中,關鍵優先級 SDEI的優先級應高于正常優先級。
5.12。限制
EHF具有以下限制:
-
盡管 GIC 優先級方案最多可支持 128 個安全調度程序,但 EHF_REGISTER_PRIORITIES()當前使用宏公開的描述符數組的大小限制為 32 個。這適用于大多數預期的用例。如果用例需要,這可能會在未來擴展。
-
平臺必須確保異常描述符中分配給調度程序的優先級與調度程序處理的中斷的編程優先級匹配。EHF無法驗證這是否已被遵循。
總結
以上是生活随笔為你收集整理的05-Exception Handling Framework的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 04-Debug FS
- 下一篇: 06-Firmware Configur