中斷類型
- locality- specific peripheral interrupt(LPI):LPI是一個有針對性的外設中斷,通過affinity路由到特定的PE。
- 為非安全group1中斷
- 邊沿觸發
- 可以通過its進行路由
- 沒有active狀態,所以不需要明確的停用操作
- LPI總是message-based interrupt
- private peripheral interrupt(PPI):PPI是針對單個特定PE的外設中斷,不同的PE可以使用同一個中斷號來表示不同的事件
- 可以是任意group中斷
- 支持電平觸發或邊沿觸發
- 不使用ITS進行路由
- 有active狀態,所以需要明確的停用操作
- 通常情況下,PPI被每個PE上的同一個中斷源的不同實例所使用,從而允許一個共同的中斷號被用于特定的事件,例如來自私有定時器的中斷。
- shared peripheral interrupt(SPI):SPI時一種物理中斷,它可以通過distributor路由到特定的PE進行除了,或路由到PE集群中某一個配置為可以接收這種中斷類型的PE上。
- 可以是任意group中斷
- 支持電平觸發或邊沿觸發
- 從不使用ITS進行路由
- 有active狀態,所以需要明確的停用操作
- 可以是message- based的中斷
- software generated interrupt(SGI):SGI通常用于處理器間通信。通過向gic中的一個寄存器寫入產生
- 可以是任意group中斷
- 邊沿觸發
- 從不使用ITS進行路由
- 有active狀態,所以需要明確的停用操作
邊沿觸發:在檢測到一個中斷信號的上升沿時被斷言,然后無論該信號的狀態如何都會保持斷言,直到該中斷被軟件確認。
電平觸發:只要中斷信號的電平處于活動狀態,它就會被斷言。只要電平不活動,就會解除斷言。
中斷的路由與分發
INTIDs
中斷會通過中斷ID進行區分,中斷ID需要遵循以下規則:
- 對于gicd與gicr中支持的中斷ID位數有著如下限制:
- 如果不支持LPI,gicd中的INTID位數被限制在10位(2^10=1024),與早期的gic版本相同
- 如果支持LPI,INTID位數范圍為14-24(8192~),具體在GICD_TYPER寄存器中定義
- 對于ITS中支持的INTID位數:
- 如果支持LPI,INTID位數范圍為14-24,具體在GICS_TYPER寄存器中定義。
- ITS必須設置INTID位數,以便被轉發到gicr中的中斷是在它所支持的中斷范圍內,否則該行為是不可預測的。
- 對于CPU interface中支持的INTID位數:
- 在GIC V3中CPU interface支持16bits和24bits兩種INTID字段。支持的中斷ID位數由ICC_CTLR_EL1的ID位以及ICC_CTLR_EL3的ID位表示
有效的INTID位數由gicd和CPU interface中定義的大小來共同決定。將大于支持的位數大小的INTID轉發給CPU interface是一個編程錯誤。未使用的INTID位數是RAZ(read as zero)。
Affinity Routing
親和路由是一種基于分層地址的方式,用于識別特定的PE節點進行中斷路由。
對于一個PE,親和路由在aarch64狀態下由MPIDR_EL1寄存器中定義,在aarch32狀態下由MPIDR寄存器定義。親和路由是一個32位的值,是由4個8位的親和路由字段組成。
- 親和路由級數:gic v3在aarch64狀態下,支持4級或3級親和路由。而在aarch32下只支持3級親和路由。ICC_CTLR_EL3.A3V,ICC_CTLR_EL1.A3V,和GICD_TYPER.AV3表示是實現4級還是3級親和路由。
- 親和路由的使能:安全狀態的親和路由是在gicd中通過配置affinity routing enable位(ARE)來啟用的。對于安全中斷,GICD_CTLR.ARE_S 位被設置為1。對于非安全中斷GICD_CTLR.ARE_NS位被設置為1。
中斷處理與優先級
中斷生命周期
GIC中斷處理需要基于GIC中斷的生命周期。這是一系列適用于任何GIC框架的高級過程。它為描述中斷處理過程的詳細步驟提供了基礎。GIC還維護了一個狀態機,在生命周期內控制中斷狀態的轉換。
- generate interrupt:中斷是由外設或者軟件產生的。
- distribute:IRI執行中斷分組、中斷優先級并且控制終端向CPU interface的轉發。
- deliver:CPU接口將中斷傳送到相應的PE。
- activate:當PE中的軟件確認了一個信號,gic將最高的活動優先級設置給被激活的中斷。對于SPI、SGI和PPI中斷狀態變為activate。
- priority drop:軟件向gic發出信號,表示最高優先級的中斷已經被處理到了可以放棄運行優先級的程度。然后運行優先級的值恢復到中斷被確認前的值。這就是中斷處理程序所指示的中斷結束點。中斷結束點也可以被配置成為中斷的deactivation。
- deactivation:清除中斷的活動狀態,從而允許中斷在pending狀態下可以再次被使用。deactivation對于LPI來說是不需要的。deactivation可以被配置為在priority drop時同時發生,也可以在它之后發生。
CPU interface
CPU接口接收由gic IRI確認優先級的待處理中斷,并且確認該中斷是否為CPU接口中啟用的中斷分組,并且有足夠的優先級向PE發出信號。接口連接的PE可以在任何時刻通過讀取ICC_HPPIR0_EL1 or ICC_HPPIR1_EL1寄存器的值來確定pending狀態下優先級最高的中斷的INTID,以及通過讀取ICC_RPR_EL1寄存器的值來確定CPU接口的運行優先級(running priority:對于沒有發生過優先級下降的active中斷的優先級稱為運行優先級)。
當LPI被確認時,在gicr中,中斷的pending狀態變為not pending。gicr不會為LPI維持active
中斷處理狀態機
- A1、A2 : add pending state。這可能是外設產生中斷的結果,也可能是軟件產生中斷的結果
- B1、B2 : remove pending state。如果中斷是一個電平觸發的中斷,那么當中斷被外設轉置時或軟件改變了等待狀態時,就會發生這種轉換。對于LPI,這種轉換發生在對中斷的確認時
- C :pending to active。如果中斷是邊沿觸發的SPI、SGI和PPI,當PE確認了這個中斷時,會發生這種轉換。
- D:pending to active and pending。如果中斷是電平觸發的SPI、SGI和PPI,當PE確認了這個中斷時,會發生這種轉換。
- E1、E2:remove active state。當軟件deactivate一個SPI、SGI或PPI中斷時發生。
中斷分組
ARM架構提供了兩種安全狀態(安全、非安全),每一個狀態都關聯獨立的物理地址空間。GIC V3架構支持路由和處理兩種安全狀態相關的中斷。GIC V3使用中斷分組作為一種機制,使中斷處理與ARM V8的異常模型和安全模型相匹配。
- group 0 的中斷:ARM會在EL3處理這個中斷
- 安全group 1的中斷:ARM會在安全狀態EL1處理這個中斷
- 非安全的group 1的中斷:在使用虛擬化的系統中,ARM會在非安全的EL2處理這個中斷;在不使用虛擬化的系統中,ARM會在非安全的EL1處理這個中斷。
在多處理器系統中,某個PE可能只支持安全狀態下可用資源的訪問或非安全狀態下訪問資源。如果:
- group 0 或者安全的group 1中斷被轉發到只支持非安全的PE上
- 非安全的group 1中斷被轉發到只支持安全的PE上
會被視為一個編程錯誤。
當一個group 0 的物理中斷在所有的pending中斷中有著最高的優先級,并且自身優先級足夠時,通常被表示為FIQ。
當一個group 1 的物理中斷在所有的pending中斷中有著最高的優先級、自身優先級足夠且滿足以下條件中的某一個時,表示為FIQ,否則為IRQ
- 這個中斷時其他安全狀態的中斷,即與當前PE執行的安全狀態不同
- 該PE在EL3執行
中斷優先級
中斷優先級描述了:
- 中斷優先權的配置和控制
- 待定中斷的執行順序
- 確定中斷對目標PE的可見時間,包括中斷優先級屏蔽、優先級分組、活動中斷搶占。
在GIC優先級方案中,優先級數值越小,優先級越高。
GIC對中斷優先級進行了分組。講優先級值分成兩個字段,即group priority組優先級 和 subpriority子優先級。搶占時,具有相同組優先級的中斷被認為具有相同的優先級,不關注子優先級值為多少。當多個待處理中斷具有相同的組優先級時,GIC會使用子優先級來決定優先處理哪一個pending狀態的中斷。當子優先級也相同時,GIC對于pending中斷的選擇是由具體實現來決定的。
GIC使用組優先級來決定一個pending狀態的中斷是否擁有足夠的優先級(sufficient priority)來搶占正在PE執行的中斷。
- pending中斷的組優先級數值必須低于PE的運行優先級
- 中斷的優先級值必須低于其優先級掩碼的值
ICC_BPR0_EL1:表明了group 0中斷組優先級和子優先級的位數
ICC_BPR1_EL1:表明了group 1中斷組優先級和子優先級的位數
中斷的搶占
定義:CPU interface支持在active中斷完成前向目標PE發出優先級更高的待處理中斷信號。
一個待處理中斷只有在以下兩種情況都滿足時才會被CPU interface發給PE:
- 其優先級高于該CPU interface的屏蔽優先級(由ICC_PMR_EL1寄存器定義。該寄存器的復位值為0,會屏蔽所有的中斷,GIC不向相關的PE發出信號。GIC在比較pending中斷的優先級和優先級閾值時不使用組優先級)
- 它的組優先級高于該CPU interface上的運行優先級
搶占發生在PE接收新的中斷時,并開始處理新的中斷,而不是處理先前的active中斷或者當前運行的程序。當這種情況發生時,最初的active中斷被稱為已經被搶占了。進程狀態PSTATE中的DAIF位決定了PE是否通過采取中斷來響應中斷信號。
GIC多芯片操作
在多芯片系統中,主要影響的是SPI的行為。在多芯片系統中,每個chip上都要集成一個GIC。GIC對于多芯片系統最多支持16個chip。對于多芯片系統,PPI不需要任何特定的考慮。因為它們是被限制在單個chip上,并且通過對應chip上的相關GICR寄存器進行編程的。SGI在多芯片和單芯片配置中的表現也是一樣的,它的路由尋址都是通過MPIDR進行的。
為了控制所有芯片配置的一致性,GIC使用了一組寄存器,它們定義了chip之間的連接。這些寄存器被稱為路由表,由三種類型的寄存器組成:
- 芯片寄存器GICD_CHIPR
- 默認芯片寄存器GICD_DCHIPR
- 芯片狀態寄存器GICD_CHIPSR
GICD_CHIPR定義了路由表。它規定了芯片所擁有的spi,以及芯片的訪問方式。這個寄存器存在于多芯片配置中的每一個芯片上,因此每個芯片都有一個路由表的副本。
GICD_DCHIPR定義了當前負責路由表一致性的芯片。并且表明在什么時候進行路由表的更新。在多芯片配置中的每個芯片上都有該寄存器的一個副本
GICD_CHIPSR定義了當前芯片的狀態細節。在多芯片配置中的每個芯片上都有該寄存器的一個副本。
復位時,在多芯片配置中的每個芯片實際上是一個獨立的全功能GIC。為了使多芯片配置連貫,所有配置中的芯片都必須互相連接。并且一個芯片必須得擁有路由表。當配置中的多芯片連接起來之后,每32個spi被分為一個集合,每個芯片可以擁有若干個spi的集合,也就是芯片之間的SPI空間是分段的。按照路由表,不屬于任何芯片的spi不能被使用。芯片上的SPI線只能用于屬于自己的SPI。但是message-base SPI支持對任何芯片擁有的spi的訪問。