轉自:http://www.lujun.org.cn/?p=3861
ARM的cpu,特別是cortex-A系列的CPU,目前都是多core的cpu,因此對於多core的cpu的中斷管理,就不能像單core那樣簡單去管理,由此arm定義了GICv2架構,來支持多核cpu的中斷管理。
一、gicv2架構
GICv2,支持最大8個core。其框圖如下圖所示:
在gicv2中,gic由兩個大模塊組成:
-
distributor:實現中斷分發,對於PPI,SGI是各個core獨有的中斷,不參與目的core的仲裁,SPI,是所有core共享的,根據配置決定中斷發往的core。最后選擇最高優先級中斷發送給cpu interface。寄存器使用 GICD_ 作為前綴。一個gic中,只有一個GICD。
-
cpu interface:將GICD發送的中斷信息,通過IRQ,FIQ管腳,傳輸給core。寄存器使用 GICC_ 作為前綴。每一個core,有一個cpu interface。
-
virtual cpu interface:將GICD發送的虛擬中斷信息,通過VIRQ,VFIQ管腳,傳輸給core。每一個core,有一個virtual cpu interface。而在這virtual cpu interface中,又包含以下兩個組件:
-
virtual interface control:寄存器使用 GICH_ 作為前綴
-
virtual cpu interface:寄存器使用 GICV_ 作為前綴
圖中的virtual interface,是用於支持虛擬中斷,本系列不討論虛擬中斷。
GICv2支持中斷旁路模式,也就是gic外部的FIQ,IRQ直接接到core的FIQ,IRQ上,相當於gic是不使能的。也就是CFGSDISABLE是有效的,將GIC給無效掉。
gicv2,定義了自己的一些寄存器,這些寄存器,都是使用memory-mapped的方式去訪問的,也就是在soc中,會留有一片空間,給gic。cpu通過訪問這部分空間,來對gic進行操作。
寄存器,分為以下:
-
GICD_*: distributor的寄存器
-
GICH_*: 虛擬interface的控制寄存器
-
GICV_*:虛擬interface的控制寄存器
-
GICC_*: 虛擬cpu interface的寄存器
二、中斷分組
givc2,將中斷,分成了group0和group1。使用寄存器GICD_IGROUPRn來對每個中斷,設置組。
-
group0:安全中斷,由nFIQ驅動
-
group1:非安全中斷,由nIRQ驅動
三、中斷號
gicv2,支持最大1020個中斷。其中斷號分配如下:
中斷號 |
分配 |
中斷來源 |
寄存器 |
ID0-ID7 |
非安全軟中斷 |
軟件 |
GICD_SGIR |
ID8-ID15 |
安全軟中斷 |
軟件 |
GICD_SGIR |
ID16-ID31 |
私有中斷 |
外設 |
no |
ID32-ID1019 |
共享中斷 |
外設 |
no |
四、gic結構
gic主要包括以下兩個組件:
-
distributor
-
cpu interface
1、distributor
中斷分發器,用來收集所有的中斷來源,並且為每個中斷源設置中斷優先級,中斷分組,中斷目的core。當有中斷產生時,將當前最高優先級中斷,發送給對應的cpu interface。
distributor對中斷提供以下的功能:
-
全局中斷使能
-
每個中斷的使能
-
中斷的優先級
-
中斷的分組
-
中斷的目的core
-
中斷觸發方式
-
對於SGI中斷,傳輸中斷到指定的core
-
每個中斷的狀態管理
-
提供軟件,可以修改中斷的pending狀態
2、cpu interface
cpu interface,將GICD發送的中斷信息,通過IRQ,FIQ管腳,發送給連接到該cpu接口的core。
cpu interface提供了一下的功能:
-
將中斷請求發送給cpu
-
對中斷進行認可(acknowledging an interrupt)
-
中斷完成識別(indicating completion of an interrupt)
-
設置中斷優先級屏蔽
-
定義中斷搶占策略
-
決定當前處於pending狀態最高優先級中斷
五、中斷認可
中斷認可,是指cpu響應該中斷。此時中斷狀態從pending狀態,變為active狀態。通過訪問GICC_IAR寄存器,來對中斷進行認可。
-
GICC_IAR: 認可group0的中斷
-
GICC_AIAR: 認可group1的中斷
六、中斷完成
中斷完成,是指cpu處理完中斷。此時中斷狀態從active狀態,變為inactive狀態。gic中,對中斷完成,定義了以下兩個stage:
-
優先級重置(priority drop):將當前中斷屏蔽的最高優先級進行重置,以便能夠響應低優先級中斷。group0中斷,通過寫GICC_EOIR寄存器,來實現優先級重置,group1中斷,通過寫 GICC_AEOIR 寄存器,來實現優先級重置。
-
中斷無效(interrupt deactivation):將中斷的狀態,設置為inactive狀態。通過寫 GICC_DIR 寄存器,來實現中斷無效。
這里為什么要對中斷完成,定義2個stage,其實是有考慮的。對於中斷來說,我們是希望中斷處理程序越短越好,但是有些中斷處理程序,就是比較長,在這種情況下,就會使其他中斷得到相應,從而影響實時性。
比如當前cpu在響應優先級為4的中斷A,但是這個中斷A的中斷處理程序比較長,此時如果有優先級為5的中斷B到來,那么cpu是不會響應這個中斷的。
在軟件上,會將中斷處理程序分為兩部分,分為上半部分,和下半部分。在上半部分,完成中斷最緊急的任務,然后就可以通知GIC,降低當前的中斷處理優先級,以便其他中斷能夠得到響應。在下半部分,處理該中斷的其他事情。
在這種機制下,低優先級的中斷,不用等待高優先級的中斷,完全執行完中斷處理程序后,就可以被cpu所響應,提高實時性。
為了實現上述機制,就將中斷完成分成了2步。還是剛剛的例子,cpu在響應優先級為4的中斷A,當中斷A的上半部分完成后,通知GIC,優先級重置(drop priority),GIC將當前的最高優先級中斷重置,重置到響應中斷A之前的優先級,比如優先級6,那么此時優先級為5的中斷B,就可以被cpu響應。最后中斷A的下半部分完成后,通知GIC,將該中斷A的狀態,設置為inactive狀態,此時中斷A就真正的完成了。
當然,也可以不將中斷完成分成2步,就1步。通過控制 GICC_CTLR寄存器的EOImode比特,來決定是否將中斷完成分成2步。
七、bypass功能
gicv2支持bypass功能,這樣gic就不起作用了,core的中斷管腳,直接由soc的其他部門信號驅動。
如下圖所示,通過控制 GICC_CLTR 寄存器的一些比特位,來實現bypass功能。不過這個功能一般不使用,不然何必要在arm的soc中,加入gic呢?
八、中斷處理流程
中斷處理流程,包含了以下幾步:
-
GIC決定每個中斷的使能狀態,不使能的中斷,是不能發送中斷的
-
如果某個中斷的中斷源有效,GIC將該中斷的狀態設置為pending狀態,然后判斷該中斷的目標core
-
對於每一個core,GIC將當前處於pending狀態的優先級最高的中斷,發送給該core的cpu interface
-
cpu interface接收GIC發送的中斷請求,判斷優先級是否滿足要求,如果滿足,就將中斷通過nFIQ或nIRQ管腳,發送給core。
-
core響應該中斷,通過讀取 GICC_IAR 寄存器,來認可該中斷。讀取該寄存器,如果是軟中斷,返回源處理器ID,否則返回中斷號。
-
當core認可該中斷后,GIC將該中斷的狀態,修改為active狀態
-
當core完成該中斷后,通過寫 EOIR (end of interrupt register)來實現優先級重置,寫 GICC_DIR 寄存器,來無效該中斷
九、中斷使能和禁止
通過設置GICD_ISENABLERn寄存器,來使中斷使能,通過設置GICD_ICENABLERn寄存器,來使中斷禁止。
這兩個寄存器,都是bit有效的寄存器,也就是一個bit,關聯一個中斷。
比如對於GICD_ISENABLER寄存器,描述如下:
十、中斷pending
通過設置GICD_ISPENDRn或GICD_ICPENDRn寄存器,可以讀取和修改中斷的pending狀態。這兩個寄存器,也是bit有效的寄存器,一個bit,關聯一個中斷。
十一、中斷active
通過設置GICD_ISACTIVERn或GICD_ICACTIVERn寄存器,可以讀取和修改中斷的active狀態。這兩個寄存器,也是bit有效的寄存器,一個bit,關聯一個中斷。
十二、產生軟中斷
通過寫 GICD_SGIR 寄存器,來產生軟中斷。軟中斷,可以指定產生中斷,發往執行的core,也可以發送多個core。
對於軟中斷,這個是軟件產生的中斷。比如軟件,想給執行自己的core,發送一個中斷,就可以通過軟中斷來產生。或者軟件,想起其他的core,發送一個中斷,也可以通過軟中斷來產生。
寄存器如下:
1、TargetListFileter
對於TargetListFileter:決定distributor將軟中斷,如何發送給cpu interface。
-
0b00:按照CPUTargetList的指定,來發送軟中斷
-
0b01:按照CPUTargetList的指定,來發送軟中斷,但是不能發送給自己
-
0b10:軟中斷,只能發送給自己
2、CPUTargetList
描述如下:
對於多core的系統,會給每個core一個編號。gicv2支持最多8個core,因此core的編號就是0-7,剛好8個bit,可以表示。
這樣的CPUTargetList,就和8個cpu相對應。第0bit,表示core0,第7bit,表示core7。
如果想給core1,core2,core7發送軟中斷,那么此時這個位域要填入0x84。
3、NSATT
描述如下:
這個用來支持安全擴展,在gicv2中,將中斷進行了分組
-
group0:安全中斷
-
group1:非安全中斷
這個bit,用來表示發送的軟中斷,是安全中斷,還是非安全中斷。而且這個bit,只有core處於安全狀態的時候,才能寫。如果core是處於非安全狀態,那么這個bit被忽略,也就是只能發非安全的軟中斷。
4、SGIINTID
發送的軟中斷的中斷號。
十三、中斷優先級
gicv2,支持最小16個,最大256個中斷優先級,如下圖所示:
如果實現的中斷優先級小於256個,那么最低的幾個bit,是為0的。
通過設置GICD_IPRIORITYRn寄存器,來設置中斷的優先級。這個寄存器是字節有效的,也就是一個字節,對應一個中斷的優先級。優先級數值越小,那么這個中斷的優先級越高。
高優先級的中斷,是可以搶占低優先級的中斷。
十四、gic使用例子
下圖是gic的使用例子:
外部的中斷,連接到gic。由distributor進行中斷分組。中斷請求,由distributor發送給cpu interface,cpu interface再發送給處理器。
對於支持安全擴展,其應用如下:
安全中斷,處於group0,非安全中斷處於group1。
十五、gic寄存器
gic寄存器,分為兩部分,一部分是distributor的寄存器,另一部分是cpu interface的寄存器。
兩部分的寄存器,均是通過memory-mapped的方式來訪問。
下圖是distributor的寄存器:
下圖是cpu interface的寄存器:
十六、總結
以上就是GICv2的介紹,更多的內容,需要查看gicv2的文檔。
gicv2比較簡單,最多只能支持8個core,超過了8個core,那么就不能使用gicv2了。不過這也不是大問題,對於手機的arm處理器來說,最多也就8個core。但是對於服務器,桌面級的arm處理器,那么就可能會超過8個core,此時gicv2就不適用了,所以ARM后面又加入GICv3,v4架構。
GICv2的寄存器,都是通過memory-mapped的方式訪問。但是中斷在一個soc系統中,是經常會產生的,那么處理器就會經常的讀取gic的寄存器,而使用memory-mapped的方式去訪問,就會影響中斷響應速度。在之后的GICv3,v3中,就加入了使用系統寄存器來進行訪問,加快中斷處理。
GICv2只是一個gic的架構,其實現的對應的IP是gic400。