悪い癖で

ソフトウェア・デベロッパーズ・マニュアルとかamazon:Linuxカーネル解析入門などを見ておるに IA32_APIC_BASE_MSR レジスタについての記述あり。

ローカル APIC のステータスと位置は、IA32_APIC_BASE_MSR (P6 ファミリ・プロセッサでは、APIC_BASE_MSR) に格納される。
(IA-32 Intel® アーキテクチャ ソフトウェア・デベロッパーズ・マニュアル 下巻より引用)

ナンダコレハ、とゆー事で調べてみる。
ちなみに MSR とは Machine Specific Register との事 (amazon:Linuxカーネル解析入門より)。
とりあえず arch/i386/kernel/apic.c にそれ系なナニがあるだろ、との判断よりソースを開いて「MSR」な文字列探索。こんなのにヒット。(disable_local_APIC()#arch/i386/kernel/apic.c より)

        rdmsr(MSR_IA32_APICBASE, l, h);
        l &= ~MSR_IA32_APICBASE_ENABLE;
        wrmsr(MSR_IA32_APICBASE, l, h);

む、rdmsr ですか、と言いつつ ETAGS をナニしてみると、include/asm-i386/msr.h 内にて定義されているマクロに行きつく。

#define rdmsr(msr,val1,val2) \
    __asm__ __volatile__("rdmsr" \
              : "=a" (val1), "=d" (val2) \
              : "c" (msr))

ほほー、と言いつつおもむろに IA-32 Intel® アーキテクチャ ソフトウェア・デベロッパーズ・マニュアル 中巻 B を開いて rdmsr 命令に関するページを見てみると、MSR に関する説明が下巻の付録 B にある、との事。とは言え、下巻の 8.4.4.ローカル APIC のステータスと位置 という項にも各フィールドについての説明や MSR アドレスについての記述もある。なかなかに微妙なレジスタらしい。
てか、レジスタってコトは CPU 固有?? てコトは MP だったら複数あるのか。そん時ゃ APICBASE を CPU 毎に固有の値にマッピングしなおすのかな?? マニュアル的にはデキる、と言っているが Linux がそれをしてるかどうか、はソース読まんと分かりませんな。
で、init_bsp_APIC()#arch/i386/kernel/apic.c にて呼出している apic_read() とか apic_write() なんですが、定義元を探してみるに以下のようなカンジだった (一部を引用)。

static __inline void apic_write(unsigned long reg, unsigned long v)
{
    *((volatile unsigned long *)(APIC_BASE+reg)) = v;
}

static __inline unsigned long apic_read(unsigned long reg)
{
    return *((volatile unsigned long *)(APIC_BASE+reg));
}

APIC_BASE って何だ、と言いつつ探してみるんですが、ちなみに呼出し元では 0xFEE00000 番地からのオフセットのみを渡しているのは承知しております。ので、APIC_BASE って 0xFEE00000 かと思いきや、MP だったら違うかもしれない訳ですな。
で、ETAGS に調査をお願いすると、こんなのが出てきた。

#define APIC_BASE (fix_to_virt(FIX_APIC_BASE))
(include/asm-i386/apicdef.h より)

魔境に足を踏み入れるのを覚悟で掘りすすんでみる。まず、FIX_APIC_BASE の捜索を ETAGS に依頼すると

enum fixed_addresses {
    FIX_HOLE,
    FIX_VSYSCALL,
#ifdef CONFIG_X86_LOCAL_APIC
    FIX_APIC_BASE,    /* local (CPU) APIC) -- required for SMP or not */
#endif
(後略)
(include/asm-i386/fixmap.h より)

普通に考えると FIX_APIC_BASE は 2 ですか??とりあえず、fix_to_virt も捜索依頼。以下に一部のみを引用。

        return __fix_to_virt(idx);
(include/asm-i386/fixmap.h より)

__fix_to_virt に 2 を渡してるのな。__fix_to_virt も捜索依頼すると同一ソース。

#define __fix_to_virt(x)    (FIXADDR_TOP - ((x) << PAGE_SHIFT))
(include/asm-i386/fixmap.h より)

なんかどんどんワケワカな記号が出てくるぞ。FIXADDR_TOP って何だ。あ、直上にてマクロ定義済み。

#define FIXADDR_TOP    ((unsigned long)__FIXADDR_TOP)
(include/asm-i386/fixmap.h より)

次は __FIXADDR_TOP です。同一ソースのてっぺんで定義。

#define __FIXADDR_TOP    0xfffff000
(include/asm-i386/fixmap.h より)

では残りの PAGE_SHIFT を。

#define PAGE_SHIFT    12
(include/asm-i386/page.h より)

てコトは、__fix_to_virt(2) は (0xfffff000 - (2 << 12)) で置換されるワケですか。gdb で確認。

(gdb) p/x (0xfffff000 - ((2) << 12))
$4 = 0xffffd000
(gdb)

違うぢゃん (怒
怒っても仕方が無いので、fixed_addresses なんてキーワードでググってみた。と、以下のコンテンツに hit。

アヤシげな事が書いてあるので以下に一部を引用。

Fixmaps are compile time fixed virtual addresses which are used for some special purposes. These virtual addresses are mapped to physical pages at boot time using the macro set_fixmap(). These virtual addresses are allocated from the very end of memory (0xFFFFE000, 4GB - 8k) backwards. The fixed addresses can be calculated using the enum fixed_addresses.
fixmapsより引用

コンパイル時には仮想アドレス??起動時に set_fixmap マクロでマッピング??

大ヤケドしそうな気がするんでツッコミは一時停止して APICBASE は 0xFEE00000 とゆー事で直前エントリの続きを見ます。(泣
# 大体が初期化の部分を無視して微妙な部分をツッコんでるのが駄目スギ。