鐵人賽
昨日已經介紹 Memory-mapped control region 前 16KB 的各種暫存器,今日我們來介紹 IDC 結構,以及其他 APLIC 的相關補充吧。
當 interrupt domain 處於 domaincfg DM=0時,interrupt 從 APLIC 直接傳送到 hart,在這種情況下,domain 的 memory-mapped control region 在末尾包含一組 IDC 結構,第一個 IDC 結構用於 index 為 0 的 hart;第二個 IDC 結構用於 index 為 1 的 hart;以此類推。
接下來將更仔細介紹 IDC 結構!
每個 IDC structure是 32 byte,下圖為 IDC 所包含的暫存器
如果 IDC structure 適用於一個無效的 hart index,則這些暫存器全部只讀零
idelivery 是一個 WARL 暫存器,用來控制 interrupt 是否要傳遞給 hart,使他們將相對應的 MIP bit 舉起
0 = interrupt delivery is disabled
1 = interrupt delivery is enabled
如果 IDC 結構用於不存在的 hart,即使將 idelivery 設置為 1 也不會向任何 hart 傳遞 interrupt 。
iforce 是一個用來測試的 WARL 暫存器,只允許值為 0 和 1。
當domaincfg IE=1且啟用idelivery 允許對 hart 傳遞 interrutp 時,設置 iforce=1 時會向相對應的 hart 發 interrupt 。當 topi 為零時,會為 hart 創建一個虛擬的 external interrupt。
當讀取claimi 回傳0時,會自動將 iforce 清除為 0。
ithreshold 是一個 WLRL 暫存器,用來確定要向 hart 發出的 interurpt 是最小的優先級(最大優先級編號)。
ithreshold 完全實現了 IPRIOLEN 位,因此能夠保存從 0 到 2 ^IPRIOLEN - 1 的所有優先級數。
當 ithreshold 為零時,所有啟用的 interrupt source 都可以向 hart 發送 interrupt signal。
topi 是一個只讀暫存器,表示當前 hart 最高優先級的interrupt。
如果讀取 topi 回傳為0,則表示當前沒有同時舉起 enable 和 pending bit 的 interrupt。
下圖為 topi 的格式:
claimi 與 topi 具有相同的值。當此值不為零時,如果讀取 claimi 會同時清除 interrutp 的 pending bit。
當讀取 cliam 返回零時,同時會將 iforce 設置為零。
當 interrupt domain 被配置為使用 APLIC 直接向 hart傳送 interrupt (domaincfg DM=0)時,APLIC 為 hart 提供 external interrupt signal,只要以下其中一個為真:
在 APLIC 到 hart 的每個 interrupt singal 都是來自domaincfg IE 以及 memory-mapped control region 中的 IDC structure的當前狀態。如果 domaincfg IE = 0 或透過 idelivery 禁用了向 hart 傳送 interrupt (idelivery = 0),則 interrupt signal 依舊無效。
當 domaincfg IE = 1 並且啟用 interrupt 傳遞 (idelivery = 1) 時,只要 iforce 或 topi 不為零,就會確保 interrupt signal。
通過 APLIC 用於 external interrupt 處理程序大致流程如下:
保存 prcessor 暫存器
i = 從 APLIC 的 hart 的 IDC 結構中讀取 claim
i = i>>16
調用 external interrupt i 的 interrupt 處理程序
恢復 prcessor 暫存器
從trap中返回
在 MSI delivery mode(domain DM =1),interrupt domain 透過 MSI 將 interrupt 轉發到 target hart
只有當 source 相對應的pending 和 enable bit為1且domaincfg IE=1時,才會幫 source 送 MSI
當發送 MSI 時,source 的pending 被清除為0。
透過 MSI 轉發 interrupt,APLIC 需要知道每個 MSI 的 target 地址。
對於任何系統,如果可以的話是應該透過 hardwire 連接到APLIC 讓這些地址固定,但有一些 APLIC 是需要軟體提供 MSI target 地址,在這種情況下 root domain 可以透過mmsiaddrcfg mmsiaddrcfgh 以及 smiaddrcfg smsiaddrcfgh 配置 interrupt domain 的 MSI 地址,
如果 MSI target 由軟體實現,則只能在適當的特權模式下進行配置,通常是系統 reset 後的前期進行一次配置。
對於 M level interrupt domain,如果 MSI target 地址由 mmsiaddrcfg mmsiaddrcfgh 配置,則 MSI target 地址計算如下:
對於 S level interrupt domain ,如果 MSI target 地址由 smsiaddrcfg smsiaddrcfgh 配置的話,為了使 interrupt source i 建構 MSI target 地址,要先將 target[i] 的 hart index 轉換為 M level domain 同一 hart index,計算過程如下圖:
當 level-sensitive interrupt 藉由 MSI 轉發,APLIC 會清除 interrupt pending bit,然後忽略該 source 直到該 singal 傳入 de-asseted 為止。
在發送 MSI 時,清除 pending bit 是必要的,以避免相同 interrupt 從 APLCI 到 target hart 不斷送相同 MSI,然而,在 ISR 處理完之後,儘管 APLIC 上的 pending bit 已經被清除,但是還有一種可能性,會讓傳入的 interrupt 在 APLIC 上保持 asserted 的狀態,如果 ISR 就這樣退出,則該 interrupt source 便永遠不會被注意到。
為了避免以這種方式丟棄 interrupt,level-sensitive 在 ISR 退出之前進行以下操作:
第一,透過讀取 APLIC 上相對應的 in_clrip 測試 APLIC 當中的 interrupt 是否仍被 assert,如果傳入的 interrupt 仍然被 assert,則可以重複執行 ISR,以查出需要處理的 interrupt 原因,並解決。一旦觀察到傳入的 interrupt 沒有 assert, 則 ISR 可以安全的退出,因為任何新的 interrutp assert 都會重新設定 pending bit 並向 hart 發送新的 MSI。
第二種選擇是,在 ISR 退出之前將 interrupt source ID 寫入 seripnum 當中,如果 source 仍在 assert 狀態,則將 interrupt pending bit 再次設為 1,如果 source not assert 狀態則不會
這幾天終於把 APLIC 給介紹完啦~其實可以發現它跟 PLIC 功能實際上蠻類似的,只是多了將 wire interrupt 轉換成 MSI的形式。
怕有些人不懂 assert VS de-assert 附個補充說明
明天讓我們來開始介紹 Duo-PLIC,為何有了 PLIC ,又有了 APLIC,現在怎麼又來了一個 Duo-PLIC ,明天讓我們來揭曉吧!