/*
** 中斷觸發時,調用的 handle_arch_irq 入口地址。
** 因為此時,掛接的就是 gic_handle_irq 函數!gic_handle_irq 是個全局函數指針,
** static void __exception_irq_entry gic_handle_irq(struct pt_regs *regs)
** 它是Linux內核中處理GIC中斷的核心函數,響應來自GIC的中斷請求,完成中斷狀態的讀取、
** 確認(ACK)、處理(ISR調用)和結束(EOI)的完整生命周期。函數通過循環處理可能存在
** 的多個掛起中斷。
** 形參 regs 是 long 類型的數組指針,用于保存CPU切換上下文時刻的CPU寄存器現場數據。
** ARM的GIC-V2架構手冊內,對中斷ID號段的類型劃分如下:
** 0-15 軟中斷(SGI),核間私有;Software-generated interrupt (SGI) 。
** 16-31 外設私有中斷(PPI),核間私有;Private Peripheral Interrupt (PPI) 。
** 32-1019 外設共享中斷(SPI),核間共享;Shared Peripheral Interrupt (SPI) 。
** 1020-1023 當前仍被保留的中斷編號。
**
*/
static void __exception_irq_entry gic_handle_irq(struct pt_regs *regs)
{u32 irqstat, irqnr;/* gic_data 是 struct gic_chip_data 類型的全局數組 */struct gic_chip_data *gic = &gic_data[0];void __iomem *cpu_base = gic_data_cpu_base(gic);/*** 多中斷處理?:當多個中斷同時到達時,GIC會通過優先級排序依次處理,直到無掛起中斷。** 搶占限制?:Linux默認不啟用中斷搶占,當前中斷處理完成后才會響應新中斷。** RTOS幾乎都是中斷搶占的!*/do {/* 讀取CPU接口的GICC_IAR(Interrupt Acknowledge Register),該操作會返回當前最高優先級的中斷ID,并將該中斷狀態從Pending轉為Active?。 */irqstat = readl_relaxed(cpu_base + GIC_CPU_INTACK);/* 獲得硬中斷ID:GICC_IAR_INT_ID_MASK用于過濾保留位,僅保留有效中斷號(0-1019) */irqnr = irqstat & GICC_IAR_INT_ID_MASK;/* ?外設中斷處理(PPI和SPI:16-1019)? */if (likely(irqnr > 15 && irqnr < 1020)) {if (static_branch_likely(&supports_deactivate_key))/* EOI操作?:向GICC_EOIR寄存器寫入中斷ID,通知GIC中斷處理完成,狀態從Active轉為Inactive */writel_relaxed(irqstat, cpu_base + GIC_CPU_EOI);isb();/* 路由?對應的ISR:handle_domain_irq通過中斷描述符表(gic->domain)找到對應的中斷處理函數(ISR)。 */handle_domain_irq(gic->domain, irqnr, regs);continue;}if (irqnr < 16) { /* 軟中斷處理(SGI:0-15)? */writel_relaxed(irqstat, cpu_base + GIC_CPU_EOI);if (static_branch_likely(&supports_deactivate_key))writel_relaxed(irqstat, cpu_base + GIC_CPU_DEACTIVATE);
#ifdef CONFIG_SMP /* 若支持多核CPU的協同處理 *//** Ensure any shared data written by the CPU sending* the IPI is read after we've read the ACK register* on the GIC.** Pairs with the write barrier in gic_raise_softirq*/smp_rmb();handle_IPI(irqnr, regs);
#endifcontinue;}break;} while (1);
}
兩條路線的對比
這兩條路線,最終都執行到了__handle_domain_irq 函數這里來,但是他們傳入的參數不同。
實際采納的路線 gic_handle_irq:
默認路線:
所以得出結論,不支持domain路由機制的舊版本的 linux generic interrupt layer 正如2.6.25版本說的,這種legacy,只是為了向前兼容,會慢慢過度,直到被廢棄。
GIC-V3 重要的新特性 Affinity routing
這個比較重要,硬件層面新增了許多實用的特性來支持linux這種操作系統里中斷管理層的工作,互相配合,提升性能。 Affinity 有關于實時性的支持。 GIC-V2 不支持 Affinity ,是V3版本后引入的。
???????