轉自:http://www.lujun.org.cn/?p=3874
GICv3架構是GICv2架構的升級版,增加了很多東西。變化在於以下:
-
使用屬性層次(affinity hierarchies),來對core進行標識,使gic支持更多的core
-
將cpu interface獨立出來,用戶可以將其設計在core內部
-
增加redistributor組件,用來連接distributor和cpu interface
-
增加了LPI,使用ITS來解析
-
對於cpu interface的寄存器,增加系統寄存器訪問方式
一、gicv3結構
下圖是gicv3的架構。
包含了以下的組件:
-
distributor:SPI中斷的管理,將中斷發送給redistributor
-
redistributor:PPI,SGI,LPI中斷的管理,將中斷發送給cpu interface
-
cpu interface:傳輸中斷給core
-
ITS:用來解析LPI中斷
其中,cpu interface是實現在core內部的,distributor,redistributor,ITS是實現在gic內部的。
cpu interface和gic的redistributor通信,通過AXI-Stream協議,來實現通信。
二、屬性層次
gicv3的一大變化,是對core的標識。對core不在使用單一數字來表示,而是使用屬性層次來標識,和arm core,使用MPIDR_EL1系統寄存器來標識core一致。
每個core,根據屬性層次的不同,使用不同的標號來識別。如下圖所示,是一個4層結構,那么對於一個core來說,就可以用 xxx.xxx.xxx.xxx 來識別。
這種標識方式,和ARMv8架構的使用MPIDR_EL1寄存器,來標識core是一樣的。
每個core,連接一個cpu interface,而cpu interface會連接gic中的一個redistributor。redistributor的標識和core的標識一樣。
三、中斷分組
gicv3,將中斷分成了2個大組,group0和group1。
-
group0:提供給EL3使用
-
group1:又分為2組,分別給安全中斷和非安全中斷使用
如下圖所示:
以下是IRQ,FIQ與組的對應關系。
四、中斷生命周期
中斷生命周期,如下圖所示:
-
generate:外設發起一個中斷
-
distribute:distributor對收到的中斷源進行仲裁,然后發送給對應的cpu interface
-
deliver:cpu interface將中斷發送給core
-
activate:core通過讀取 GICC_IAR 寄存器,來對中斷進行認可
-
priority drop: core通過寫 GICC_EOIR 寄存器,來實現優先級重置
-
deactivation:core通過寫 GICC_DIR 寄存器,來無效該中斷
這個中斷生命周期,和gicv2的中斷生命周期是一樣的。
五、中斷流程
下圖是gic的中斷流程,中斷分成2類:
-
一類是中斷要通過distributor,比如SPI中斷
-
一類是中斷不通過distributor,比如LPI中斷
中斷要通過distributor的中斷流程
-
外設發起中斷,發送給distributor
-
distributor將該中斷,分發給合適的re-distributor
-
re-distributor將中斷信息,發送給cpu interface。
-
cpu interface產生合適的中斷異常給處理器
-
處理器接收該異常,並且軟件處理該中斷
LPI中斷的中斷流程
-
外設發起中斷,發送給ITS
-
ITS分析中斷,決定將來發送的re-distributor
-
ITS將中斷發送給合適的re-distributor
-
re-distributor將中斷信息,發送給cpu interface。
-
cpu interface產生合適的中斷異常給處理器
-
處理器接收該異常,並且軟件處理該中斷
六、中斷處理
中斷處理,分為邊沿觸發處理和電平觸發處理
1、邊沿觸發處理
外部邊沿中斷到達,中斷狀態被置為pending狀態。
軟件讀取IAR寄存器值,表示PE認可該中斷,中斷狀態被置為active狀態
軟件中斷處理完畢后,寫EOIR寄存器,表示優先級重置。過一段時間后,寫DIR寄存器,中斷狀態被置為idle狀態。
2、電平觸發處理
外部高電平中斷到達,中斷狀態置為pending狀態。
軟件讀取IAR寄存器,表示PE認可該中斷。但中斷依然為高,中斷狀態進入pending and active狀態。
軟件中斷處理完畢后,寫EOIR寄存器,表示優先級重置。過一段時間后,寫DIR寄存器,中斷狀態被置為idle狀態。
七、寄存器
gicv3中,多了很多寄存器。而且對寄存器,提供了2種訪問方式,一種是memory-mapped的訪問,一種是系統寄存器訪問:
memory-mapped訪問的寄存器:
-
GICC: cpu interface寄存器
-
GICD: distributor寄存器
-
GICH: virtual interface控制寄存器,在hypervisor模式訪問
-
GICR: redistributor寄存器
-
GICV: virtual cpu interface寄存器
-
GITS: ITS寄存器
系統寄存器訪問的寄存器:
-
ICC: 物理 cpu interface 系統寄存器
-
ICV: 虛擬 cpu interface 系統寄存器
-
ICH: 虛擬 cpu interface 控制系統寄存器
下圖是gicv3中,各個寄存器,所在的位置。
對於系統寄存器訪問方式的gic寄存器,是實現在core內部的。而memory-mapped訪問方式的gic寄存器,是在gic內部的。
gicv3架構中,沒有強制,系統寄存器訪問方式的寄存器,是不能通過memory-mapped方式訪問的。也就是ICC, ICV, ICH寄存器,也是可以實現在gic內部,通過memory-mapped方式去訪問。但是一般的實現中,是沒有這樣的實現的。
下圖是ICC的系統寄存器,和memory-mepped方式寄存器的對應關系的一部分,更多的就要查看gicv3的spec。
那么,問題來了,gicv3中,為什么選擇將cpu interface,從gic中抽離,實現在core內部?為什么要將cpu interface的寄存器,增加系統寄存器訪問方式,實現在core的內部?這樣做,是有什么好處?
我認為,gicv3的上述安排,第一是為了軟件編寫能夠簡單,通用,第二是為了讓中斷響應能夠更快。
首先要先了解,在gic的寄存器中,哪一些寄存器,是會頻繁被core所訪問的,哪一些寄存器,是不會頻繁被core所訪問的。毫無疑問,cpu interface的寄存器,是會頻繁被core所訪問的,因為core需要訪問cpu interface的寄存器,來認可中斷,來中斷完成,來無效中斷。而其他的寄存器,是配置中斷的,只有在core需要去配置中斷的時候,才用訪問得到。有了這個認識,那么理解之后我所講述的,就比較容易了。
在gicv2中,cpu interface的寄存器,是實現在gic內部的,因此當core收到一個中斷時,會通過axi總線(假設memory總線是axi總線),去訪問cpu interface的寄存器。而中斷在一個soc系統中,是會頻繁的產生的,這就意味着,core會頻繁的去訪問gic的寄存器,這樣會占用axi總線的帶寬,總而會影響中斷的實時響應。而且core通過axi總線去訪問cpu interface寄存器,延遲,也比較大。
在gicv3中,將cpu interface從gic中抽離出來,實現在core內部,而不實現在gic中。core對cpu interface的訪問,通過系統寄存器方式訪問,也就是使用msr,mrs訪問,那么core對cpu interface的寄存器訪問,就加速了,而且還不占用axi總線帶寬。這樣core對中斷的處理,就加速了。
cpu interface與gic之間,是通過專用的AXI-stream總線,來傳輸信息的,這樣也不會占用AXI總線的帶寬。
gicv3架構的內容,比較多,我這邊會拆成幾個部分。
下一部分,會介紹gic stream協議。也就是cpu interface與gic之間的通信。