ちょい脱線?? ('bout CPUID)

Intel のソフトウェア・デベロッパーズ・マニュアル中巻をめくってみると、あった。ざっくりベースで把握している事をメモしておくと eax に 1 を設定して CPUID 命令を発行すると、edx に (直前エントリで言えば_Onboard APIC_かどうか等の) 機能情報が格納されるとの事。
今回は ETAGS と grep を無理矢理使って調べてみました。
こんな感じ。(ちょっと効率悪そげ)

$ (for i in `find include/asm-i386 -name '*.[chS]'` ; \
> do echo $i; grep cpuid $i; done) | lv

(ケースによって include/asm-i386 とか arch/i386/ とか使い分け)
とりあえず CPUID 命令を発行している関数 (インラインですが) は cpuid()#include/asm-i386/processor.h な模様。do_cpuid()#arch/i386/kernel/cpuid.c などとゆーのもあった。これらの使い分けについてはその内分かってくるだろう、としてスルー。
で、今度は cpu_has_apic マクロなナニに出ていた struct cpuinfo_x86 型の boot_cpu_data の x86_capability というエントリに着目して grep を。
と arch/i386/kernel/apic.c なんてゆーモロな名前のファイルでも使用してるしナニしてるし、みたいな感じで限定して引用。

arch/i386/kernel/apic.c
        clear_bit(X86_FEATURE_APIC, boot_cpu_data.x86_capability);
        set_bit(X86_FEATURE_APIC, boot_cpu_data.x86_capability);
                clear_bit(X86_FEATURE_APIC, boot_cpu_data.x86_capability);

と、また脱線しちゃって clear_bit とか set_bit って何かー、と思い ETAGS を探したら CLEAR_BIT なんてゆーマクロに hit。引数一つだし。(関係ないけど引用)

#define SET_BIT(n) (1<<(n))
#define CLEAR_BIT(n) (tmp &= ~(1<<n))

ファイル名をよく見りゃドライバのソースだし (drivers/video/kyro/STG4000Reg.h)。これはサスガに違うだろ、と思い再度 grep をかけた所、test_bit が定義してある include/asm-i386/bitops.h に定義してありそげなナニが。bts とか btr なんてゆー命令も Intel ソフトウェア・デベロッパーズ・マニュアルにあったんですが、脱線気味でもあるし別途調査、ってコトで最初に設定な部分はどこだろか、とアタリを付けてみた。以下は x86_capability を arch/i386 以下のディレクトリを *.chS について grep してみた出力の一部。

arch/i386/kernel/cpu/common.c
                        c->x86_capability[0] = capability;
                        c->x86_capability[4] = excap;
                                c->x86_capability[1] = cpuid_edx(0x80000001);
                                c->x86_capability[6] = cpuid_ecx(0x80000001);

ファイル名もアヤシげ、とゆー事で開いてみた。generic_identify()#arch/i386/kernel/cpu/common.c より一部を引用。

        /* Intel-defined flags: level 0x00000001 */
        if ( c->cpuid_level >= 0x00000001 ) {
            u32 capability, excap;
            cpuid(0x00000001, &tfms, &junk, &excap, &capability);
            c->x86_capability[0] = capability;
            c->x86_capability[4] = excap;

初期設定してるっぽく見える。がしかし未だ類推ベースですので注意が必要。あと、include/asm-i386/cpufeature.h は x86_capability な所以というか状態が Intel の資料とツキアワせてみてどうか、というチェックも入れてみたいが時間が ...
ただ、ヘッダによれば x86_capability の要素数は 7 でそれぞれ

  • 0 番目は cpuid 0x1 な戻りの edx が格納
  • 1 番目は cpuid 0x80000001 な戻りが格納されている模様 (拡張 CPUID との事にてドキュメントには情報薄い)
  • 2 番目は Transmeta-defined とか出てる。cpuid 0x80860001 とか微妙。
  • 3 番目は Linux-defined mapping となっている。詳細は不明。
  • 4 番目は cpuid 0x1 な戻りの ecx が格納
  • 5 番目は cpuid 0xC0000001 な戻りが格納されている模様。これも詳細不明。
  • 6 番目は cpuid 0x80000001 な戻りが格納されている模様。1 番目の要素と同様。

上記コードでも 0 番目に edx、4 番目に ecx な戻りを格納してますな。おそらく初期設定と見て当たりかと。その内呼出し元が出てくるのか (でもブートのトコって見なさげ)。

妙なトコをツツキ始めるとキリが無いなぁ。しかし前回エントリに出てきた cpu_has_apic なんてマクロはこうして見るに結構カッコいい。