do_IRQ 呼び出し以降の排他処理

割り込み処理の全体をざっくり見渡してみる。
__do_IRQ() の呼出し元の do_IRQ() では排他な手続きは行なっていないものと勝手読み。handle_IRQ_event() ではどうなっているか、という事も気になるんで無理矢理 inline で展開させてみた。

__do_IRQ() {

spin_lock(&desc->lock);
PIC に 割り込みマスク指示および EOI の送信 (EFLAGS の退避と復帰)

(中略)

for(多くて 2 回繰り返し) {
    spin_unlock(&desc->lock);

    action_ret = handle_IRQ_event(irq, regs, action);
    # 無理矢理 inline 展開してみたり (こら
    # inline 展開ココカラ
        if( action->flags が SA_INTERRUPT でない場合 )
            local_irq_enable();

        do {
            ret = action->handler(irq, action->dev_id, regs);
            action = action->next;
        } while (action が NULL でない間)

        local_irq_disable();
    # inline 展開ココマデ

    spin_lock(&desc->lock);
}

PIC に割り込みアンマスク指示 (EFLAGS の退避と復帰)
spin_unlock(&desc->lock);

}

とりあえず UP で i8259A な環境を前提として意味を類推してみる前に ....

一点気になるのは、action->flags が SA_INTERRUPT でない場合の処理。ちなみに flags が SA_INTERRUPT な状態というのは、割り込みハンドラ内で別の割り込みに応答しないようにする、との情報あり。なので SA_INTERRUPT でない場合には sti するというのは理解できるんですが、どこで cli しているのでしょうか。ちなみに action->handler() を呼び出すループを脱出した時点で cli は実行。これもどこで sti するんだろう。

整理すると

  • action->flags が SA_INTERRUPT な状態であれば別な割り込みに応答しない
    • SA_INTERRUPT でない場合、local_irq_enable() を呼び出して sti する。
    • SA_INTERRUPT な場合は何もしない
    • てコトは以前に local_irq_disable() を呼び出して cli してるのか??してないとおかしい。
  • handle_IRQ_event() 末端にて local_irq_disable() を呼び出して cli している。
    • この後のどこかのタイミングで local_irq_enable() を呼び出して sti しないとマズイのではないか。

うーむ。ワケワカ。
とりあえず、もっかいよく見てみる必要あり。PIC のマニュアルやら intel のマニュアルやらもよく見た方が良いかも、と思いつつ。(多分また何かをスッ飛ばしてるんだろな。とほほ)

キ※チガイなエントリになっているとは思いますが、思考の過程を残す、とゆーコトで勘弁して下さい。

追加で何点か気づいた点を列挙。

  • 割り込みマスク〜アンマスク間では PIC 的に当該 IRQ 番号の割り込みが抑止されている状態。
  • EFLAGS の IF がどういった状態で __do_IRQ() に飛んでくるのかが微妙。(これは上記の通り)
    優先して調べてみる必要あり?
  • 異なる IRQ に割り込まれる可能性あり?(これも EFLAGS レジスタの IF の状態による)
  • 割り込みマスク/アンマスク処理中に IRQ 番号ユニークなスピンロックで排他をかけている (割り込みマスク/アンマスクはポイント高い処理なので同一 IRQ な割り込みの発生の可能性を考慮して同期処理をしている?)
  • action->handler() な処理の詳細はドライバのソースを読まんと分からん

追記

intel なマニュアルにヒントになりそうな記述 (上巻の 6.4.1.割り込み/例外処理プロシージャのコール操作とリターン操作) を発見。別途きちんと確認してみます。

追記 2

若干記述を修正

もすこし追加で補足すると

  • __do_IRQ() 内においては、割り込んだ IRQ 番号な割り込みは抑止されている状態
  • action->handler() を呼び出すループでは、割り込みがネストする可能性がある
    当該 IRQ の spin_lock も解除されており、sti されている可能性もある (action->flags の状態による)

上記二点については色々な書籍や文書に書いてある事と整合している、はず。