割り込み関連データ構造
各デバイスドライバの提供する割り込みハンドラの管理のためのLinuxのデータ構造は、基本的にはカーネル起動時にACPIの各テーブルなどから初期化され、以下のような目的な目的に利用されます。
- 割り込みベクタ番号から、どのハンドラをどのような引数で呼ぶかという情報を引く
- デバイスの追加などで、新たな割り込みハンドラが必要なとき、空いた割り込みベクタを見付ける
注意すべきは、単一の割り込みベクタが複数の割り込みハンドラにより共有されることがある点です。
これらの目的のため、以下のようなデータを組み合わせて利用しています。
- IDTそのもの
配列idt_table[vector] - acpi_link
ACPIのPCI Interrupt Linkデバイス (PNP0C0F) を管理するリスト (EL6ではacpi_link_list) - mp_irq[idx]
各割り込みについて、割り込み源バス、割り込みの種類 (通常の割り込みかNMIか、など)、宛先APIC、pin番号などを持つ - irq_vector[irq]、vector_irq[vector]
GSI番号とベクタ番号の対応表 (EL6ではirq_descの中で保持) - irq_desc[vector]
各割り込みベクタの情報。ハンドラ情報など (後述)。EL5では固定配列だが、EL6では動的確保。
struct irq_descの主なメンバ
x86では未使用のメンバがいくつかあります。
struct irq_desc {
struct irq_chip *chip; 割り込みコントローラ
struct irqaction *action; ドライバの割り込みルーチン
unsigned int irq_count; ハンドルされない割り込みの検出用
unsigned int irqs_unhandled; 同上
spinlock_t lock;
cpumask_t affinity; /proc/irq/<num>/smp_affinity
unsigned int cpu;
cpumask_t pending_mask; affinity設定時に利用
unsigned int move_irq; 同上
struct proc_dir_entry *dir; /proc/irq/<num>/NAME
}
irq_desc[]とchip、action
irq_desc[]のメンバのうち、最初の2つのポインタ (struct irq_chip *chipとstruct irqaction *action) の関係が分かりにくいため、図にしました。
ベクタ番号0がタイマ (i8253)、1番がキーボードコントローラ (i8042)、20番が2つのEHCIドライバの共有、そして60番がMSIをサポートしたBroadcomのNICドライバ (tg3) に、それぞれ割り当てられている様子です。