中斷控制器的驅(qū)動(dòng)解析
這里主要分析 linux kernel 中 GIC v3 中斷控制器的代碼(drivers/irqchip/irq-gic-v3.c)。
設(shè)備樹
先來看下一個(gè)中斷控制器的設(shè)備樹信息:
compatible:用于匹配GICV3驅(qū)動(dòng)
reg?:GIC的物理基地址,分別對(duì)應(yīng)GICD,GICR,GICC…
#interrupt-cells:這是一個(gè)中斷控制器節(jié)點(diǎn)的屬性。它聲明了該中斷控制器的中斷指示符(interrupts)中 cell 的個(gè)數(shù)
interrupt-controller: 表示該節(jié)點(diǎn)是一個(gè)中斷控制器
interrupts:分別代表中斷類型,中斷號(hào),中斷類型, PPI中斷親和, 保留字段
關(guān)于設(shè)備數(shù)的各個(gè)字段含義,詳細(xì)可以參考 Documentation/devicetree/bindings 下的對(duì)應(yīng)信息。
初始化
1. irq chip driver 的聲明:
定義 IRQCHIP_DECLARE 之后,相應(yīng)的內(nèi)容會(huì)保存到 __irqchip_of_table 里邊:
__irqchip_of_table 在鏈接腳本 vmlinux.lds 里,被放到了 __irqchip_begin 和 __irqchip_of_end 之間,該段用于存放中斷控制器信息:
在內(nèi)核啟動(dòng)初始化中斷的函數(shù)中,of_irq_init 函數(shù)會(huì)去查找設(shè)備節(jié)點(diǎn)信息,該函數(shù)的傳入?yún)?shù)就是 __irqchip_of_table 段,由于 IRQCHIP_DECLARE 已經(jīng)將信息填充好了,of_irq_init 函數(shù)會(huì)根據(jù) “arm,gic-v3” 去查找對(duì)應(yīng)的設(shè)備節(jié)點(diǎn),并獲取設(shè)備的信息。or_irq_init 函數(shù)中,最終會(huì)回調(diào) IRQCHIP_DECLARE 聲明的回調(diào)函數(shù),也就是 gic_of_init,而這個(gè)函數(shù)就是 GIC 驅(qū)動(dòng)的初始化入口。
2. gic_of_init 流程:
映射 GICD 的寄存器地址空間。
驗(yàn)證 GICD 的版本是 GICV3 還是 GICV4(主要通過讀GICD_PIDR2寄存器bit[7:4]. 0x1代表GICV1, 0x2代表GICV2…以此類推)。
通過 DTS 讀取 redistributor-regions 的值。
為一個(gè) GICR 域分配基地址。
通過 DTS 讀取 redistributor-stride 的值。
下面詳細(xì)介紹。
設(shè)置一組 PPI 的親和性。
確認(rèn)支持 SPI 中斷號(hào)最大的值為多少。
向系統(tǒng)中注冊(cè)一個(gè) irq domain 的數(shù)據(jù)結(jié)構(gòu),irq_domain主要作用是將硬件中斷號(hào)映射到IRQ number,后面會(huì)做詳細(xì)的介紹。
設(shè)定 arch 相關(guān)的 irq handler。gic_irq_handle 是內(nèi)核 gic 中斷處理的入口函數(shù),后面會(huì)做詳細(xì)的介紹。
gic 虛擬化相關(guān)的內(nèi)容。
初始化 ITS。
設(shè)置 SMP 核間交互的回調(diào)函數(shù),用于 IPI,回到函數(shù)為 gic_raise_softir。
初始化 Distributor。
初始化 CPU interface。
初始化 GIC 電源管理。

【文章福利】小編推薦自己的Linux內(nèi)核技術(shù)交流群:【749907784】整理了一些個(gè)人覺得比較好的學(xué)習(xí)書籍、視頻資料共享在群文件里面,有需要的可以自行添加哦!?。。ê曨l教程、電子書、實(shí)戰(zhàn)項(xiàng)目及代碼)??

?

中斷映射
當(dāng)早期的系統(tǒng)只存在一個(gè)中斷控制器,而且中斷數(shù)目也不多的時(shí)候,一個(gè)很簡(jiǎn)單的做法就是一個(gè)中斷號(hào)對(duì)應(yīng)到中斷控制器的一個(gè)號(hào),可以說是簡(jiǎn)單的線性映射:

但當(dāng)一個(gè)系統(tǒng)中有多個(gè)中斷控制器,而且中斷號(hào)也逐漸增加的時(shí)候。linux 內(nèi)核為了應(yīng)對(duì)此問題,引入了 irq_domain 的概念。

irq_domain 的引入相當(dāng)于一個(gè)中斷控制器就是一個(gè) irq_domain。這樣一來所有的中斷控制器就會(huì)出現(xiàn)級(jí)聯(lián)的布局。利用樹狀的結(jié)構(gòu)可以充分的利用 irq 數(shù)目,而且每一個(gè) irq_domain 區(qū)域可以自己去管理自己 interrupt 的特性。
每一個(gè)中斷控制器對(duì)應(yīng)多個(gè)中斷號(hào), 而硬件中斷號(hào)在不同的中斷控制器上是會(huì)重復(fù)編碼的, 這時(shí)僅僅用硬中斷號(hào)已經(jīng)不能唯一標(biāo)識(shí)一個(gè)外設(shè)中斷,因此 linux kernel 提供了一個(gè)虛擬中斷號(hào)的概念。
原文作者:人人極客社區(qū)
