APIC (その 5)

LVT0 と LVT1 なレジスタの初期設定。この手続きでは

「LVT」の「LINT0」レジスタに、伝達モード「ExtINT」(111b)を設定し、「LINT1」レジスタには、伝達モード「NMI」(100b)を設定しています。
amazon:Linuxカーネル解析入門より引用

な設定を実施しているとの事。残りのコードは結構少ない。

    /*
     * Set up the virtual wire mode.
     */
    apic_write_around(APIC_LVT0, APIC_DM_EXTINT);
    value = APIC_DM_NMI;
    if (!APIC_INTEGRATED(ver))        /* 82489DX */
        value |= APIC_LVT_LEVEL_TRIGGER;
    apic_write_around(APIC_LVT1, value);

(init_bsp_APIC()#arch/i386/kernel/apic.c より引用)
上記のコードによれば、LVT0 レジスタAPIC_DM_EXTINT を出力し、LVT1 レジスタAPIC_DM_NMI を出力しているのが分かる。

#define            APIC_DM_NMI        0x00400
#define            APIC_DM_EXTINT        0x00700

(include/asm-i386/apicdef.h より)
LVT0 への出力ですが、APIC_DM_EXTINT をそのまんま出力しているんで、割り込みはマスクされてないし、割り込みベクタも 0 のまんまなんですが「スプリアス割り込み」が有効になってればなんとかなる状態なんだ、との認識で良いのかな。もしくは今から設定されるから保留、てコトかなぁ。あるいは BSP の eflags の IF ビットはこの時点ではクリアされている、とか??
で、もう一つの LVT1 レジスタについての処理はちょっとだけ条件分岐あり。ただ、この設定についての根拠が不明。トリガモードについての IA-32 Intel® ソフトウェア・デベロッパーズ・マニュアル 下巻 8.5.1. ローカル・ベクタ・テーブルの項の「トリガモード」の部分によると

  • トリガモードを (0) エッジ・センシティブと (1) レベル・センシティブとして選択 (ちなみに、「エッジ・トリガ」と「レベル・トリガ」については、amazon:Linuxカーネル解析入門の p.123 に詳細な解説あり)
  • このフラグは伝達モード (8 〜 10 ビット) が固定 (000b) の時のみ使用
  • 伝達モードが NMI、SMI、INIT の時はトリガモードは常にエッジ・センシティブ
  • 伝達モードが ExtINT の時はトリガモードは常にレベル・センシティブ
  • 他にも記述があるが略

むむ。LVT0 は ExtINT なのでレベルトリガな設定になっている事が分かるんですが、LVT1 は NMI なのでレベル・センシティブな設定にしているの??がしかし、仕様書によればこのフラグ使用されるのは伝達モードが「固定」の時のみ有効、とある。
あ、もしかして 82489DX なナニって APIC としてのまっとうな使い方がデキねぇから、PIC として両方ともレベルトリガな設定をするのかなぁ。
ちょっと微妙スギ (日本語も理解も)。もう少しきちんとした根拠の元にエントリ投入すべきだなぁ。疑問点については調査後に追記もしくは別途エントリ投入で勘弁して下さい。

追記

IA-32 Intel® ソフトウェア・デベロッパーズ・マニュアル 下巻の表 9-1 によると EFLAGS の電源投入時の初期値は 0x2 との事。てコトは IF はクリアされた状態だな。でもいつ sti するのか、が問題なんですが、start_kernel()#init/main.c で local_irq_enable() の呼び出し箇所っぽく見える。(類推)