一、GIC中斷使能
對(duì)于外設(shè)中斷,處理器可以通過(guò):
- 寫(xiě)入GICD_ISENABLERn 寄存器的對(duì)應(yīng)bit來(lái)使能該中斷。
- 寫(xiě)入 GICD_ICENABLERn 寄存器的對(duì)應(yīng)bit來(lái)禁止該中斷。
對(duì)于SGI中斷是否能通過(guò)上述兩個(gè)寄存器來(lái)enable和disable,這個(gè)由具體的實(shí)現(xiàn)( IMPLEMENTATION DEFINED)來(lái)定義。
此外寫(xiě)入GICD_ISENABLERn 和GICD_ICENABLERn 寄存器只是控制Distributor是否能將該中斷轉(zhuǎn)發(fā)到CPU interface,并不會(huì)阻止該中斷改變狀態(tài)。比如寫(xiě)入GICD_ICENABLERn 寄存器來(lái)disable對(duì)應(yīng)中斷,并不能阻止他變成pending狀態(tài)。
二、設(shè)置或清除一個(gè)中斷的Pending狀態(tài)
對(duì)于外設(shè)中斷,處理器可以:
- 寫(xiě)入GICD_ISPENDRn寄存器的對(duì)應(yīng)bit來(lái)設(shè)置中斷狀態(tài)為pending。
- 寫(xiě)入 GICD_ICPENDRn寄存器的對(duì)應(yīng)bit來(lái)清除該中斷的pending狀態(tài)。
- 對(duì)于電平敏感的中斷:
- 如果中斷信號(hào)已經(jīng)被assert,處理器再寫(xiě)入GICD_ICPENDRn寄存器的對(duì)應(yīng)bit來(lái)清除中斷將不產(chǎn)生作用。
- 如果處理器通過(guò)寫(xiě)入GICD_ISPENDRn來(lái)使對(duì)應(yīng)中斷狀態(tài)變?yōu)閜ending,將忽略該中斷的硬件信號(hào),并且保留pending狀態(tài),不管該中斷是被asserted還是deasserted。
- 包含pending的中斷狀態(tài)有兩種:
(1)pending
(2)active and pending - 對(duì)于邊沿觸發(fā)的中斷來(lái)講,包含pending的中斷狀態(tài)可以通過(guò)寫(xiě)入GICD_ISPENDRn寄存器,或者GIC對(duì)該中斷信號(hào)的assertion來(lái)進(jìn)行鎖定。
- 但是對(duì)于電平敏感的中斷來(lái)講,它的包含pending的中斷狀態(tài)可以通過(guò)寫(xiě)入GICD_ISPENDRn寄存器來(lái)鎖定,但是不能根據(jù)傳遞到GIC的中斷信號(hào)來(lái)鎖定。
以下是電平敏感中斷的電路邏輯示意圖:
此外,對(duì)于SGI中斷,GIC將忽略對(duì)GICD_ISPENDRn和GICD_ICPENDRn寄存器的寫(xiě)入,處理器不能通過(guò)寫(xiě)入這些寄存器來(lái)改變SGI中斷的中斷狀態(tài)。一般情況下,處理器可以通過(guò)寫(xiě)入 GICD_SGIR寄存器來(lái)使SGI中斷變成pending,在GICv2中,SGI的pending狀態(tài)可以通過(guò)直接寫(xiě)入GICD_SPENDSGIRn 和 GICD_CPENDSGIRn 寄存器的對(duì)應(yīng)位來(lái)改變。
2.1 Interrupt Set-Pending Registers, GICD_ISPENDRn
GICD_ISPENDRn寄存器提供一個(gè)Set-pending bit,對(duì)該bit寫(xiě)入1能夠?qū)?duì)應(yīng)外設(shè)中斷的狀態(tài)設(shè)置為pending,讀取對(duì)應(yīng)bit則可以知道該中斷是否處于pending狀態(tài)。
在多處理器系統(tǒng)中,GICD_ISPENDR0(PPI和SGI)寄存器被每個(gè)與GIC相連的處理器banked(復(fù)用)。
從GICD_ISPENDR0開(kāi)始,寄存器里每個(gè)bit代表一個(gè)不同中斷ID的中斷控制位,比如GICD_ISPENDR0[0]表示控制中斷ID為0的中斷。
對(duì)該寄存器進(jìn)行讀?。?/p>
- 讀到0:表明對(duì)應(yīng)中斷在任何處理器中都不處于pending狀態(tài)。
- 讀到1:
- 對(duì)于SGI和PPI中斷,當(dāng)前中斷在當(dāng)前處理器中是pending狀態(tài)的。
- 對(duì)于SPI中斷,當(dāng)前中斷至少在一個(gè)處理器中處于pending狀態(tài)。
上文提到過(guò),對(duì)于SGI中斷,寫(xiě)入GICD_ISPENDRn寄存器的操作將會(huì)被忽略,因?yàn)镾GI有自己的Set-pending寄存器 SGI
Set-Pending Registers, GICD_SPENDSGIRn。對(duì)于SPI和PPI中斷來(lái)講:
- 寫(xiě)入0:無(wú)影響
- 寫(xiě)入1:其效果取決于是邊緣觸發(fā)還是電平敏感中斷:
- 邊緣觸發(fā)(Edge-triggered),如果當(dāng)前中斷已經(jīng)是pending狀態(tài),則不受影響;如果之前是inactive狀態(tài),則會(huì)變成pending狀態(tài);如果之前是active狀態(tài),則會(huì)變成active and pending狀態(tài)。
- 電平敏感(Level sensitive),如果當(dāng)前中斷已經(jīng)是pending狀態(tài),如果對(duì)應(yīng)中斷信號(hào)已經(jīng)被asserted,寫(xiě)操作將不會(huì)改變中斷的狀態(tài),但是該中斷信號(hào)被deasserted后該中斷將仍保持pending狀態(tài);如果對(duì)應(yīng)中斷未處于pending狀態(tài),如果之前是inactive狀態(tài),則會(huì)變成pending狀態(tài);如果之前是active狀態(tài),則會(huì)變成active and pending狀態(tài)。
2.2 Interrupt Clear-Pending Registers, GICD_ICPENDRn
GICD_ICPENDRs為GIC支持的每個(gè)中斷提供一個(gè)Clear-pending bit。寫(xiě)入對(duì)應(yīng)中斷的Clear-pending位將清除該中斷的pending狀態(tài)。讀取該bit位是否為1可以確定中斷是否處于pending狀態(tài)。
對(duì)該寄存器進(jìn)行讀?。?/p>
- 讀到0:表明對(duì)應(yīng)中斷在任何處理器中都不處于pending狀態(tài)。
- 讀到1:
- 對(duì)于SGI和PPI中斷,當(dāng)前中斷在當(dāng)前處理器中是pending狀態(tài)的。
- 對(duì)于SPI中斷,當(dāng)前中斷至少在一個(gè)處理器中處于pending狀態(tài)。
對(duì)于SPI和PPI中斷來(lái)講:
- 寫(xiě)入0:無(wú)影響
- 寫(xiě)入1:其效果取決于是邊緣觸發(fā)還是電平敏感中斷:
- 邊緣觸發(fā)(Edge-triggered),如果中斷不處于pending狀態(tài),則不受影響。如果之前是pending狀態(tài),則會(huì)變成inactive狀態(tài);如果之前是active and pending狀態(tài),則會(huì)變成active狀態(tài)。
- 電平敏感(Level sensitive),如果當(dāng)前中斷的pending狀態(tài)是由于寫(xiě)入GICD_ISPENDRn寄存器導(dǎo)致的:如果之前是pending狀態(tài),則會(huì)變成inactive狀態(tài);如果之前是active and pending狀態(tài),則會(huì)變成active狀態(tài)。否則,如果中斷信號(hào)仍被asseted,中斷將保持pending狀態(tài)。
三、查找處于active或者pending狀態(tài)的中斷
若想知道一個(gè)中斷是否處于pending狀態(tài),可以讀取 GICD_ISPENDRn 或者GICD_ICPENDRn寄存器。若想知道中斷是否處于active狀態(tài),可以讀取 GICD_ISACTIVERn 或者GICD_ICACTIVERn,這兩個(gè)寄存器有Set-active和clear-active 位用來(lái)控制中斷的active狀態(tài)。
四、產(chǎn)生SGI中斷
處理器可以通過(guò)寫(xiě)入GICD_SGIR寄存器來(lái)產(chǎn)生一個(gè)SGI中斷,一個(gè)SGI中斷可以設(shè)置多個(gè)目標(biāo)處理器,并且SGIR寄存器里有目標(biāo)寄存器列表。GICD_SGIR包括如下優(yōu)化:
- 只中斷寫(xiě)入GICD_SGIR的處理器
- 中斷除寫(xiě)入GICD_SGIR的處理器以外的所有處理器
- 來(lái)自不同處理器的SGI中斷使用同一個(gè)中斷ID,所以任何目標(biāo)處理器可以收到來(lái)自不同處理器產(chǎn)生的相同中斷ID的SGI。但是如果以下條件不同,則任意兩個(gè)SGI中斷的pending狀態(tài)是獨(dú)立的:
- 中斷ID
- 源處理器
- 目標(biāo)處理器
在CPU interface中,在任何時(shí)候,一次只能有一個(gè)特定中斷ID的中斷處于active狀態(tài),這意味著CPU interface不能同時(shí)有兩個(gè)SGI處于active狀態(tài),甚至是不同處理器使用相同中斷ID的SGI中斷發(fā)送中斷信號(hào)到該處理器。
在目標(biāo)處理器的CPU interface中,通過(guò)讀取 GICC_IAR寄存器,可以獲得中斷ID,以及產(chǎn)生該中斷的CPU ID,即源處理器ID。中斷ID加上源處理器ID,可以讓目標(biāo)處理器獲知該中斷獨(dú)一無(wú)二的來(lái)源。
此外,在多處理器系統(tǒng)中,每個(gè)SGI中斷的優(yōu)先級(jí)可以為每個(gè)目標(biāo)處理器單獨(dú)設(shè)置,詳情可查看 Interrupt Priority Registers, GICD_IPRIORITYRn,中斷優(yōu)先級(jí)寄存器。對(duì)于每個(gè)CPU interface來(lái)講,對(duì)于所有優(yōu)先級(jí)相同的,特定中斷ID的,處于pending狀態(tài)的SGI中斷,CPU interface序列化地處理它們,具體的系列化處理順序取決于系統(tǒng)的實(shí)現(xiàn)定義(IMPLEMENTATION SPECIFIC.)。
4.1 Software Generated Interrupt Register, GICD_SGIR
處理器寫(xiě)入GICD_SGIR可以產(chǎn)生SGI中斷。使用限制:通過(guò)寫(xiě)入 GICD_CTLR寄存器來(lái)將Distributor的轉(zhuǎn)發(fā)功能禁止,是否會(huì)影響GICD_SGIR,這個(gè)由具體的實(shí)現(xiàn)定義( IMPLEMENTATION DEFINED)。以下是GICD_SGIR寄存器的字段分配圖:
- [25:24] TargetListFilter:這將決定Distributor如何處理被請(qǐng)求的SGI中斷,即要轉(zhuǎn)發(fā)到何處:
- 0b00:將中斷轉(zhuǎn)發(fā)到在CPUTargetList定義的CPU interface中
- 0b01:將中斷轉(zhuǎn)發(fā)到所有CPU interface中,除了當(dāng)前請(qǐng)求中斷的處理器。
- 0b10:將中斷轉(zhuǎn)發(fā)到當(dāng)前請(qǐng)求SGI中斷的處理器相連的CPU interface中。
- 0b11:保留
- [23:16] CPUTargetList:如果TargetListFilter的值為0b00,CPUTargetList中將定義Distributor必須被轉(zhuǎn)發(fā)到的CPU interface。CPUTargetList中共八個(gè)bit,每個(gè)bit代表一個(gè)處理器。比如CPUTargetList[0]對(duì)應(yīng)CPU interface 0,如果CPUTargetList[0]=1,表明該SGI中斷必須轉(zhuǎn)發(fā)到CPU interface 0。如果TargetListFilter的值為0b00,并且CPUTargetList也為0,說(shuō)明Distributor不需要將中斷轉(zhuǎn)發(fā)到任何CPU interface。
- [15] NSATT:僅在系統(tǒng)包含安全擴(kuò)展中實(shí)現(xiàn),如果沒(méi)有實(shí)現(xiàn)安全擴(kuò)展,這個(gè)字段將保留。NSATT指定SGI需要的security value:
- 只有當(dāng)SGI在該CPU interface上被配置為Group 0時(shí),才將SGIINTID字段中指定的SGI轉(zhuǎn)發(fā)到指定的CPU interface。
- 只有當(dāng)SGI在該CPU interface上被配置為Group 1時(shí),才將SGIINTID字段中指定的SGI轉(zhuǎn)發(fā)到指定的CPU interface。
- 該字段只可以在安全狀態(tài)下被寫(xiě)入,只有當(dāng)指定的SGI中斷被配置成group 1時(shí),任何對(duì)GICD_SGIR的非安全寫(xiě)入才會(huì)生成SGI,并且忽略NSATT的值。
- [3:0] SGIINTID :需要被轉(zhuǎn)發(fā)到指定的CPU interface中的SGI中斷的中斷ID,范圍是0到15。
4.2 安全擴(kuò)展下產(chǎn)生SGI中斷
如果GIC實(shí)現(xiàn)了安全擴(kuò)展,通過(guò)寫(xiě)入GICD_SGIR寄存器,使得SGI中斷轉(zhuǎn)發(fā)到指定的處理器,這取決于:
- 寫(xiě)入GICD_SGIR的是Group 0(secure)還是Group 1(non-secure)
- 對(duì)于secure寫(xiě)入SGIR,寫(xiě)入 GICD_SGIR的NSATT字段的值。
- 在目標(biāo)處理器中,特定的中斷是否被配置成Group 0(secure)還是Group 1(non-secure)。
GICD_IGROUPR0寄存器中保存了SGI中斷的安全狀態(tài)。在多處理器系統(tǒng)中, GICD_IGROUPR0被每個(gè)與之相聯(lián)的處理器banked(復(fù)用),所以系統(tǒng)可以為每個(gè)處理器獨(dú)立設(shè)置SGI中斷的安全狀態(tài)。對(duì)GICD_SGIR寄存器寫(xiě)一次,可以配置多個(gè)目標(biāo)處理器,對(duì)于每個(gè)目標(biāo)處理器,Distributor將決定是否將SGI中斷轉(zhuǎn)發(fā)到該處理器。
下表展示了Distributor是否可以將SGI轉(zhuǎn)發(fā)到指定的CPU interface的真值表:
五、GIC 1-N模型
GIC在多處理器實(shí)現(xiàn)中,會(huì)使用1-N模型,處理有多個(gè)目標(biāo)處理器的外設(shè)中斷,比如SPI。這意味著,這意味著,當(dāng)GIC從其中一個(gè)目標(biāo)處理器識(shí)別出一個(gè)中斷確認(rèn)時(shí),它將清除所有其他目標(biāo)處理器上的中斷的pending狀態(tài)。GIC必須確保使用1-N模型處理的任何中斷時(shí),只能被一個(gè)CPU interface確認(rèn),并且所有其他CPU interface都返回一個(gè)虛假中斷ID。
當(dāng)目標(biāo)處理器試圖確認(rèn)中斷時(shí),有兩種情況會(huì)發(fā)生:
- 處理器讀取 GICC_IAR寄存器,并獲得需要被服務(wù)的中斷的ID。在GICv1中,如果多個(gè)處理器讀取GICC_IAR寄存器的時(shí)間非常接近,可以會(huì)有多個(gè)處理器會(huì)獲取到該中斷ID。系統(tǒng)必修要求在目標(biāo)處理器上運(yùn)行的軟件來(lái)確保只有一個(gè)處理器能進(jìn)行中斷服務(wù)程序。一種典型的實(shí)現(xiàn)方案是使用共享內(nèi)存,并且在中斷服務(wù)程序(interrupt service routine,ISR)中加鎖。
- 處理器讀取 GICC_IAR寄存器,獲取到虛假中斷ID:1023。該處理器會(huì)從中斷服務(wù)程序中返回,并且不用寫(xiě)入GICC_EOIR寄存器。讀到虛假中斷ID,是因?yàn)樵嫉闹袛嗖辉?處于pending狀態(tài),一般是因?yàn)橛衅渌繕?biāo)處理器在處理該中斷。
評(píng)論