エンタープライズ:特集 | 2003/01/28 09:44:00 更新 |
Linuxでハイパー・スレッディング――Pentium4/3.06GHzで遊ぼう
第2回 泥沼のRedHatカーネルデバッギング (5/5)
デバッギングその2:mpparse.c
さてsmp_scan_config()自体は短いからちょっと見ていただこう。
static int __init smp_scan_config (unsigned long base,
unsigned long length) { unsigned long *bp = phys_to_virt(base); struct intel_mp_floating *mpf; Dprintk("Scan SMP from %p for %ld bytes.\n", bp,length); while (length > 0) { smp_found_config = 1; |
ここで、SMP_MAGIC_IDENTというシンボルは「/usr/src/linux-2.4.20/include/asm_i386/mpspec.h」で定義されていて、
#define SMP_MAGIC_IDENT (('_'<<24)|('P'<<16)|('M'<<8)|'_') |
となっている。つまり「_MP_」という文字列で、smp_scan_config()は与えられたアドレスからこの文字列を探してゆき、どこかで見つかったらsmp_found_configに「1」を設定して返す、という作業を行っている。いっぽうこの関数を呼び出すのは「find_intel_smp()」という関数で、
void __init find_intel_smp (void) { unsigned int address; /* address = *(unsigned short *)phys_to_virt(0x40E); |
といった感じだ。ちょっと長いが、コメントを見れば判るとおり
・アドレス先頭の1Kバイト ・ベースメモリ先頭の1Kバイト ・BIOS中の64Kバイト |
の3つの個所を検索し、そこに「_MP_」という文字列の入った領域が含まれているかを確認しているようだ。もっとも単に含まれているかどうかだけではなく、その文字列に続く構造体でMP Specification 1.1か1.4であることも確認しており、それらが格納されていればSMP対応とみなして、必要なデータをそこから引っ張り出すという作業をしている。
そこで、BIOSなりメモリエリアにこうしたデータが入っていないために、smp_found_configが0のままなのではないか、というのが筆者の想像である。これを確認するために、find_intel_smp()を
/* * FIXME: Linux assumes you have 640K of base ram.. * this continues the error... * * 1) Scan the bottom 1K for a signature * 2) Scan the top 1K of base RAM * 3) Scan the 64K of bios */ if (smp_scan_config(0x0,0x400) || smp_scan_config(639*0x400,0x400) || smp_scan_config(0xF0000,0x10000)) return; /* Add by Ohara */ printk( "Ohara_scan_config_1 : %d\n", smp_scan_config(0x0,0x400)); printk( "Ohara_scan_config_2 : %d\n", smp_scan_config(639*0x400,0x400)); printk( "Ohara_scan_config_3 : %d\n", smp_scan_config(0xF0000,0x10000)); /* End of Ohara */ |
てな具合に書き換えてみた上で、カーネルを再構築してみた。さて、リブート後に/var/log/messagesを見てみると
Jan 22 22:39:47 localhost kernel: BIOS-provided physical
RAM map: Jan 22 22:39:47 localhost kernel: BIOS-e820: 0000000000000000 - 000000000009fc00 (usable) Jan 22 22:39:47 localhost kernel: BIOS-e820: 000000000009fc00 - 00000000000a0000 (reserved) Jan 22 22:39:47 localhost kernel: BIOS-e820: 00000000000f0000 - 0000000000100000 (reserved) Jan 22 22:39:47 localhost kernel: BIOS-e820: 0000000000100000 - 000000003ffec000 (usable) Jan 22 22:39:47 localhost kernel: BIOS-e820: 000000003ffec000 - 000000003ffef000 (ACPI data) Jan 22 22:39:47 localhost kernel: BIOS-e820: 000000003ffef000 - 000000003ffff000 (reserved) Jan 22 22:39:47 localhost kernel: BIOS-e820: 000000003ffff000 - 0000000040000000 (ACPI NVS) Jan 22 22:39:47 localhost kernel: BIOS-e820: 00000000fec00000 - 00000000fec01000 (reserved) Jan 22 22:39:47 localhost kernel: BIOS-e820: 00000000fee00000 - 00000000fee01000 (reserved) Jan 22 22:39:47 localhost syslog: klogd startup succeeded Jan 22 22:39:47 localhost kernel: BIOS-e820: 00000000ffff0000 - 0000000100000000 (reserved) Jan 22 22:39:47 localhost kernel: Warning only 896MB will be used. Jan 22 22:39:47 localhost kernel: Use a HIGHMEM enabled kernel. Jan 22 22:39:47 localhost kernel: 896MB LOWMEM available. Jan 22 22:39:47 localhost kernel: Ohara_scan_config_1 : 0 Jan 22 22:39:47 localhost kernel: Ohara_scan_config_2 : 0 Jan 22 22:39:47 localhost kernel: Ohara_scan_config_3 : 0 Jan 22 22:39:47 localhost kernel: On node 0 totalpages: 229376 |
といった具合。先に示した/var/log/messagesと比較していただけるとわかるが、筆者の追加した「printk()」がちゃんと働いていることが分かる。それはさておき、smp_scan_config()の結果を見ると、どれも0が返ってきている。
ということで今回の結論
さて、要するに845マザーではどこにもSMP用のテーブルが用意されていない、というのがLinux 2.4.20カーネルでHTが有効にならない直接的な理由であることはこれで確認できた。ただ不思議なのは、Windows XPとかWindows 2000では、このマザーボードを使ってもちゃんとHTが有効になることだ。となると考えられるのは
・Intel 845PEでは、今回find_intel_smp()で検索した「以外の」領域にSMP用のテーブルが置かれている ・Intel 845PEにはSMP用のテーブルはそもそも置かれていない。したがって、別の方法でSMP用の情報を認識する方法がある |
のどちらかということになる。次回はこのあたりを調査してお知らせしたい。が、いつになるやら…。
[大原雄介,ITmedia]