APIC (その2)

Intel のソフトウェア・デベロッパーズ・マニュアル 下巻の付録 D に LINT0 入力と LINT1 入力のプログラミングという項があり、そこに初期化手順が掲載されている。手順としては以下と記載されている。(IA-32 Intel® アーキテクチャ ソフトウェア・デベロッパーズ・マニュアル 下巻より引用)

次の手順を使用して LINT[1:0] ピンをプログラムする。

  1. 8259 割り込みをマスクする。
  2. まだイネーブルになっていない場合は、SVR (スプリアス・ベクタレジスタ) によって APIC をイネーブルにする。
  3. LVT1 を ExtINT としてプログラムする。この ExtINT は、外部的に接続されている割り込みコントローラで始まった割り込みとしてディスティネーションにリストされているすべてのプロセッサ・コアの INTR 信号に信号を送信する。
  4. LVT2 を NMI としてプログラムする。これはディスティネーションにリストされているすべてのプロセッサ・コアの NMI 信号で信号を送信する。


上記記述に沿った形で init_bsp_APIC()#arch/i386/kernel/apic.c は進行していくハズ、との勝手なナニを元に読み進めてみる。
まず最初の_8259 割り込みマスク_なナニは意味不明なのでとりあえず置いとく。又、apic_read() とか apic_write() 関連もレジスタ読み書き、との認識でざっくりと全体を分類してみて、それを検証する方向で読んでみる事に。(間違えてるかもしれないんですが、その時どうするかはそん時に考えるとゆー事で)
まず、この部分は初期手続き。

    value = apic_read(APIC_LVR);
    ver = GET_APIC_VERSION(value);

    /*
     * Do not trust the local APIC being empty at bootup.
     */
    clear_local_APIC();

で、2 の_SVR による APIC のイネーブル化が以下か。

    /*
     * Enable APIC.
     */
    value = apic_read(APIC_SPIV);
    value &= ~APIC_VECTOR_MASK;
    value |= APIC_SPIV_APIC_ENABLED;
    
    /* This bit is reserved on P4/Xeon and should be cleared */
    if ((boot_cpu_data.x86_vendor == X86_VENDOR_INTEL) && (boot_cpu_data.x86 == 15))
        value &= ~APIC_SPIV_FOCUS_DISABLED;
    else
        value |= APIC_SPIV_FOCUS_DISABLED;
    value |= SPURIOUS_APIC_VECTOR;
    apic_write_around(APIC_SPIV, value);

で、3 と 4 が以下と見た。

    /*
     * 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);

virtual wire mode って表現が微妙。amazon:Linuxカーネル解析入門によると以下のような説明がある。

このモードは、従来の「8259A」を使った割り込みを、「APIC」を使って、あたかも「8259A」から直接プロセッサに結線されているかのように見せる仕組みです。
amazon:Linuxカーネル解析入門より引用

うーん。も少しきちんとマニュアル読んだ方が良さげ。仮想ワイヤモードに関する記述も発見しているんですが、若干微妙。以降のエントリにてちょっとづつほじくり返してみたいかな、と。