13-SDEI: Software Delegated Exception Interface
引流關鍵詞: 中斷、同步異常、異步異常、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學習
13.1. 介紹
軟件委托異常接口 ( SDEI :Software Delegated Exception Interface) 是非安全世界的 Arm 規范,用于向固件注冊處理程序以接收有關系統事件的通知。固件將首先通過異步異常的方式接收系統事件,并在響應中安排注冊的處理程序在非安全 EL 中執行。
與 SDEI 調度程序交互(發出 SDEI 請求和接收通知)的普通世界軟件稱為SDEI 客戶端。即使客戶端在屏蔽異常的情況下執行時,它也會在注冊的處理程序處收到事件通知。
下圖描述了一個涉及 SDEI 客戶端在 EL2 上執行的一般序列以及由觸發綁定中斷產生的事件調度。如下:
作為初始化的一部分,SDEI 客戶端綁定一個非安全中斷 [1],并且 SDEI 調度程序返回一個平臺動態事件編號 [2]。然后,客戶端為該事件注冊一個處理程序 [3],啟用該事件 [5],并取消屏蔽當前 PE 上的所有事件 [7]。此序列是 SDEI 客戶端的典型序列,但可能涉及其他 SDEI 調用。
在稍后的時間點,當綁定中斷觸發 [9] 時,它會被trapped在 EL3 中。中斷被移交給 SDEI 調度程序,然后安排執行注冊的處理程序 [10]。客戶端使用SDEI_EVENT_COMPLETE[11]終止其執行 ,然后調度程序恢復原始 EL2 執行 [13]。請注意,在客戶端處理程序完成之前,SDEI 中斷保持活動狀態,此時 EL3 執行 EOI [12]。
除了綁定到中斷的事件(如上面的序列所示)之外,還可以明確調度 SDEI 事件以響應其他異常,例如,在接收到SError或同步外部中止時(SError or Synchronous External Abort)。
13.2. 定義事件
選擇包含 SDEI 調度程序的平臺還必須定義平臺上可用的事件及其屬性。
該平臺預計將提供兩個事件描述符數組:一個用于private events,另一個用于shared events。該SDEI調度提供 SDEI_PRIVATE_EVENT()和SDEI_SHARED_EVENT()函數來填充事件描述符。兩個函數都有 3 個參數:
- 事件編號:這必須是一個 32 位正整數。
- 對于backing interrupt中斷的事件,該事件綁定到的中斷號:
如果它不適用于某個事件,則應將其保留為0。
如果事件是動態的,則應將其指定為SDEI_DYN_IRQ。 - A bit map of Event flags
要定義事件 0,應使用SDEI_DEFINE_EVENT_0()宏。這個宏只需要一個參數:一個 SGI 編號來通知其他 PE。
要定義旨在顯式調度的事件(即,不是作為接收 SDEI 中斷的結果),SDEI_EXPLICIT_EVENT() 應使用宏。它接受兩個參數:
- 事件編號;
- 事件優先級:SDEI_MAPF_CRITICAL或SDEI_MAPF_NORMAL
一旦定義了事件描述符數組,就應該使用REGISTER_SDEI_MAP()宏將它們導出到 SDEI 調度程序,分別將指向私有和共享事件描述符數組的指針傳遞給它。請注意, REGISTER_SDEI_MAP()宏必須在定義數組的同一文件中使用。關于事件描述符:
- 對于事件 0:
私有數組中必須只有一個描述符,而共享數組中沒有。
該事件應使用SDEI_DEFINE_EVENT_0().
必須綁定到平臺上的安全 SGI。 - 顯式事件應該只在私有數組中使用。
- 靜態綁定的共享和私有中斷必須分別綁定到平臺上的共享和私有中斷。請參閱異常處理框架中的配置部分 。
- 兩個數組都應該是一維的。該REGISTER_SDEI_MAP()宏接受復制的私人事件平臺上的每個PE的照顧。
- 兩個數組都必須按事件編號的遞增順序排序。
13.2.1. 事件標志
- SDEI_MAPF_DYNAMIC:將事件標記為動態。動態事件可以在運行時通過SDEI_INTERRUPT_BIND和SDEI_INTERRUPT_RELEASE調用綁定到(或從中釋放)任何非安全中斷 。
- SDEI_MAPF_BOUND:將事件標記為靜態綁定到中斷。這些事件不能在運行時重新綁定。
- SDEI_MAPF_NORMAL:將事件標記為具有普通優先級。這是默認優先級。
- SDEI_MAPF_CRITICAL:將事件標記為具有嚴重優先級
13.3. 事件定義示例
static sdei_ev_map_t plat_private_sdei[] = {/* Event 0 definition */SDEI_DEFINE_EVENT_0(8),/* PPI */SDEI_PRIVATE_EVENT(8, 23, SDEI_MAPF_BOUND),/* Dynamic private events */SDEI_PRIVATE_EVENT(100, SDEI_DYN_IRQ, SDEI_MAPF_DYNAMIC),SDEI_PRIVATE_EVENT(101, SDEI_DYN_IRQ, SDEI_MAPF_DYNAMIC)/* Events for explicit dispatch */SDEI_EXPLICIT_EVENT(2000, SDEI_MAPF_NORMAL);SDEI_EXPLICIT_EVENT(2000, SDEI_MAPF_CRITICAL); };/* Shared event mappings */ static sdei_ev_map_t plat_shared_sdei[] = {SDEI_SHARED_EVENT(804, 0, SDEI_MAPF_DYNAMIC),/* Dynamic shared events */SDEI_SHARED_EVENT(3000, SDEI_DYN_IRQ, SDEI_MAPF_DYNAMIC),SDEI_SHARED_EVENT(3001, SDEI_DYN_IRQ, SDEI_MAPF_DYNAMIC) };/* Export SDEI events */ REGISTER_SDEI_MAP(plat_private_sdei, plat_shared_sdei);13.4. 異常處理框架內的配置
SDEI 調度程序與異常處理框架一起運行。這意味著平臺必須為平臺的正常和關鍵 SDEI 中斷分配優先級:
-
為正常和關鍵 SDEI 中斷安裝優先級描述符。
-
對于那些靜態綁定的中斷(即定義為具有SDEI_MAPF_BOUND屬性的事件),枚舉它們的屬性以便 GIC 驅動程序相應地配置中斷。
-
中斷必須配置為以 EL3 為目標。這意味著它們應配置為Group 0。此外,在 GICv2 系統上,構建選項 GICV2_G0_FOR_EL3必須設置為1.
13.5. 確定客戶端 EL
SDEI 規范要求物理SDEI 客戶端在系統上實現的最高非安全 EL 中執行。這意味著調度程序將只允許從以下位置進行 SDEI 調用:
-
EL2,如果實現了 EL2。Hypervisor 預計將實現一個 虛擬SDEI 調度程序,以支持在非安全 EL1 中執行的客戶操作系統中的 SDEI 客戶端。
-
非安全 EL1,如果 EL2 未實現或禁用。
請參閱 中的函數在sdei_private.h中的sdei_client_el()
13.6. 顯式分派事件
通常,SDEI 事件調度是由 PE 接收綁定到 SDEI 事件的中斷引起的。但是,在某些情況下,安全世界需要將 SDEI 事件作為過去活動的直接或間接結果進行調度,例如接收安全中斷或異常。
SDEI 調度程序實現sdei_dispatch_event()為此提供了 API。API 具有以下簽名:
int sdei_dispatch_event(int ev_num);參數ev_num是要調度的事件編號。API0 在成功或-1失敗時返回。
下圖描述了一個涉及顯式分派 SDEI 事件的場景。評論如下:
作為初始化的一部分,SDEI 客戶端為平臺事件 [1] 注冊一個處理程序,啟用事件 [3],并取消屏蔽當前 PE [5]。請注意,與一般的 SDEI 調度不同,這不涉及中斷綁定,因為綁定或動態事件不能被顯式調度(參見下面的部分)。
在稍后的時間點,關鍵事件2被困在 EL3 [7] 中。EL3 執行事件的第一級分類,RAS 組件承擔進一步處理 [8]。分派完成,但打算讓非安全世界參與進一步處理,因此決定顯式分派一個事件 [10](客戶端已經為 [1] 注冊了該事件)。其余的順序與一般的 SDEI 分派類似:將請求的事件分派給客戶端(假設所有條件都滿足),當處理程序完成時,搶占執行恢復。
13.6.1. 事件派發的條件?
必須滿足以下所有要求才能返回 API0并分派事件:
-
必須在 PE 上取消屏蔽 SDEI 事件。即客戶必須 PE_UNMASK事先打電話。
-
無法分派事件 0。
-
必須使用上述SDEI_EXPLICIT_EVENT()宏聲明事件。
-
該事件必須是 PE 私有的。
-
該事件必須已注冊并啟用。
-
同一事件的調度不得未完成。即它還沒有被發送并且還沒有完成。
-
事件的優先級(嚴重或正常,由平臺在構建時配置)不應導致優先級反轉。這意味著:
-
如果它是 Normal 優先級,那么在 PE 上,Normal 和 Critical 優先級調度都必須是未完成的。
-
如果它具有關鍵優先級,則 PE 上必須沒有未完成的關鍵優先級調度。
此外,調用者應了解調度程序所做的以下假設:
-
API的調用者是運行在EL3中的組件;例如,RAS 驅動程序。
-
異常處理框架將允許請求的調度。即調用者必須確保請求的調度具有足夠的優先級,以免在異常處理框架內引起優先級倒置。
-
調用者必須為 SDEI 調度程序恢復非安全上下文做好準備,并將其標記為活動上下文。
-
調用將阻塞,直到 SDEI 客戶端完成事件(即當客戶端調用SDEI_EVENT_COMPLETE或時SDEI_COMPLETE_AND_RESUME)。
-
調用者必須準備好讓這個 API 返回失敗并進行相應的處理。
13.7. 移植要求
移植指南中概述了 SDEI 調度程序的移植要求 。
13.8. 編寫 SDEI 事件處理程序的注意事項?
本節與一般的 SDEI 事件處理程序有關,而不僅僅是在使用 TF-A SDEI 調度程序時。
SDEI 規范要求事件處理程序保留所有寄存器的內容,x0除了x17. 如果事件處理程序是用 C 編寫的,這很重要:編譯器通常會在 C 函數的開頭和結尾調整堆棧幀。例如,AArch64 GCC 通常會產生以下函數 prologue 和 epilogue:
c_event_handler:stp x29, x30, [sp,#-32]!mov x29, sp...bl ......ldp x29, x30, [sp],#32ret該寄存器x29在序言中用作幀指針。因為無論是有效的SDEI_EVENT_COMPLETE還是SDEI_EVENT_COMPLETE_AND_RESUME調用都不會返回到處理程序,結語永遠不會被執行,并且寄存器x29 和x30(在上面的情況下)被無意中破壞了。這違反了 SDEI 規范,之后的正常執行將導致意外行為。
為了解決這個問題,建議頂級事件處理程序在程序集中實現,遵循以下類似模式:
asm_event_handler:/* Save link register whilst maintaining stack alignment */stp xzr, x30, [sp, #-16]!bl c_event_handler/* Restore link register */ldp xzr, x30, [sp], #16/* Complete call */ldr x0, =SDEI_EVENT_COMPLETEsmc #0b . 《新程序員》:云原生和全面數字化實踐50位技術專家共同創作,文字、視頻、音頻交互閱讀總結
以上是生活随笔為你收集整理的13-SDEI: Software Delegated Exception Interface的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 12- Library at ROM
- 下一篇: 19-Realm Management