核心IRQ中斷向量

2021-09-25 18:59:57 字數 4406 閱讀 6398

首先看一下vector_irq的定義,此每處理器陣列變數,儲存每個處理器上中斷向量所對應的中斷號,其以中斷向量值為索引。系統中定義了256個中斷向量。相關**如下:

typedef int vector_irq_t[nr_vectors];

define_per_cpu(vector_irq_t, vector_irq) = ;

#define nr_vectors 256

另乙個是used_vector的定義,其為乙個位圖變數,用來標記系統中已經使用的中斷向量。

declare_bitmap(used_vectors, nr_vectors);
中斷初始化入口函式init_irq。為支援傳統的pic型別的終端控制器,如8259,核心預留了irq0_vector 到 irq15_vector 共16個中斷向量,分別對應irq號0到15。在初始化時,也不是全部預留這16個中斷向量,而是根據檢測到的傳統pic中斷控制器所支援中斷數量在預留,有可能小於16個。x86_init.irqs.intr_init()指標對應的為native_init_irq函式,接下來介紹。

void __init init_irq(void)

函式apic_intr_init負責分配系統自身所需的中斷向量。x86架構的idt中斷描述表可用的外部中斷向量由0x20(first_external_vector)開始,其中0x80(ia32_syscall_vector)為系統呼叫所用的中斷向量;0x30-0x3f共16個中斷向量保留給isa使用。interrupt函式參見檔案arch/x86/kernel/entry_64.s中的定義,表示中斷處理程式的入口位址,for_each_clear_bit_from迴圈將所有未使用的中斷向量的處理程式入口設定為interrupt的相應偏移。最後對於傳統的中斷控制器,irq2用作兩片控制器的級聯。

void __init native_init_irq(void)

if (!acpi_ioapic && !of_ioapic)

setup_irq(2, &irq2);

}

函式apic_intr_init。首先分配smp相關的中斷向量,參見函式smp_intr_init,隨後是分配其他的向量。這些中斷向量值由大到小分配,首先是:spurious_apic_vector(0xff),目前最小的是:local_timer_vector(0xef)。核心中定義了變數first_system_vector表示當前系統中斷向量的最小值。

static void __init apic_intr_init(void)

static void __init smp_intr_init(void)

alloc_intr_gate巨集由alloc_system_vector和set_intr_gate兩個函式組成。前者為註冊的系統中斷向量設定used_vectors中的使用標誌,並且更新系統最小向量值:first_system_vector。後者set_intr_gate函式設定處理器的idt表。

static inline void alloc_system_vector(int vector)

else

}#define alloc_intr_gate(n, addr) \

do while (0)

由如下函式irq_alloc_hwirqs可見,首先呼叫函式__irq_alloc_descs分配中斷號,核心中已經使用的中斷號標記在全域性位圖變數allocated_irqs中,函式的第乙個引數表示期望的中斷號,-1表示由系統來選擇中斷號。系統將在allocated_irqs點陣圖中選擇乙個不為零的位返回,作為新的中斷號。

函式arch_setup_hwirq負責為中斷號查詢合適的中斷向量。注意在執行過程**現錯誤的話,函式將執行回退處理,包括由函式irq_free_descs復位之前分配中斷號時設定的allocated_irqs中的位。arch_teardown_hwirq函式是對應arch_setup_hwirq函式的清理函式。

unsigned int irq_alloc_hwirqs(int cnt, int node)

return irq;

err:

for (i--; i >= irq; i--)

irq_free_descs(irq, cnt);

return 0;

}

arch_setup_hwirq函式的主體是由__assign_irq_vector函式完成,其定義如下。由於終端級別是由中斷向量後4位決定的,而本地的apic不能夠很好的處理多個同級別的中斷,所以核心以2的4次方,即16為區間,進行中斷向量的分配。

使用靜態變數current_vector和current_offset分別記錄當前的區間起始值和區間內偏移。第一次分配中斷向量時,current_vector為33,偏移值為1,所以第乙個可供分配的中斷向量為34。

static int __assign_irq_vector(int irq, struct irq_cfg *cfg, const struct cpumask *mask)

內部的迴圈由標籤和goto語句組成。每次遍歷16長度的區間中的第乙個偏移向量值,一直遍歷完所有的區間。之後,當vector向量值大於最大可用向量值first_system_vector時,重新由第乙個區間的第二個偏移值開始遍歷。

如果遍歷的向量值沒有被使用,即used_vectors點陣圖沒有置位。並且,tmp_mask中的所有有效處理器上vector_irq對映還沒有被占用,表明此中斷向量可用。

1324         vector = current_vector;

1325 offset = current_offset;

1326 next:

1329 vector += 16;

1330 if (vector >= first_system_vector)

1334

1335 if (unlikely(current_vector == vector))

1352

1353 if (test_bit(vector, used_vectors))

1355 goto next;

1357

1358 for_each_cpu_and(new_cpu, tmp_mask, cpu_online_mask)

成功找到可用的中斷向量之後,更新靜態的current_vector和current_offset的值,並更新tmp_mask中所有處理器的vector_irq中斷向量和中斷號對映值,寫入分配的irq中斷號,表明此中斷向量已被占用。使用cfg中的domain成員記錄有效的處理器列表。

除去第一次申請中斷向量外,系統也可能動態的調整中斷向量,及為其服務的處理器列表,old_domain用來儲存調整前的處理器列表,move_in_progress表示是否正處於調整期間,調整結束之後old_domain為空,move_in_progress也值為0。

1362         /* found one! */

1363 current_vector = vector;

1364 current_offset = offset;

1365 if (cfg->vector)

1380 for_each_cpu_and(new_cpu, tmp_mask, cpu_online_mask)

1381 per_cpu(vector_irq, new_cpu)[vector] = irq;

1382 cfg->vector = vector;

1383 cpumask_copy(cfg->domain, tmp_mask);

1387

1388 err = 0;

1389 break;

另外,在中斷調整時,如果服務的處理器列表調整前後一致,直接跳出迴圈(cpumask_equal(tmp_mask, cfg->domain))。如果新的處理器列表是調整預處理器列表的子集,移除多餘的處理器,並更新domain為調整之後的處理器列表。

1294         apic->vector_allocation_domain(cpu, tmp_mask, mask);

1295

1296 if (cpumask_subset(tmp_mask, cfg->domain))

以上的介紹打亂了**的順序,以行號為準。

核心版本:3.10.0

向量irq與非向量irq

推薦向量中斷就是不同的中斷有不同的入口位址,非向量中斷就只有乙個入口位址,進去了再判斷中斷標誌來識別具體是哪個中斷。向量中斷實時性好,非向量中斷簡單 向量中斷控制器vic具有32個中斷請求輸入,可將其程式設計分為3類,fiq,向量irq和非向量irq。fiq fast interrpt reques...

ARM 之FIQ 快速中斷 IRQ(中斷)

irq,fiq定義 這就是個普通中斷,當我們程式定義了該中斷,並且在程式執行的時候產生了irq中斷,則此時的晶元是這樣執行的 中斷處理器吧利用irq請求線來高速arm,arm就知道有個irq中斷來了,然後arm切換到irq模式執行。類似的如果該中斷設定為fiq,那麼當該中斷產生的時候,中斷處理器通過...

IRQ中斷過程

請問irq中斷過程是怎樣的?問題 irq中斷過程 回答 標準中斷步驟 irq 1 aic已經正確程式設計,aic svr也已經寫入正確的中斷服務程式的入口位址。且中斷已經使能 2 位址0x18 irq的中斷向量位址 的指令為 ldr pc,pc,f20 當nirq到來,且cpsr的i位為0時,步驟如...