エンタープライズ:特集 | 2003/01/28 09:44:00 更新 |
Linuxでハイパー・スレッディング――Pentium4/3.06GHzで遊ぼう
第2回 泥沼のRedHatカーネルデバッギング (4/5)
デバッギングその1:smpboot.c
さて、「/var/log/messages」を見てみると、こんな具合だ。
Jan 21 21:13:05 localhost kernel: Linux version 2.4.20
(root@localhost.localdomain) (gcc version 3.2 20020903 (Red Hat Linux 8.0 3.2-7))
#4 SMP Mon Jan 20 19:54:51 JST 2003 Jan 21 21:13:05 localhost kernel: BIOS-provided physical RAM map: Jan 21 21:13:05 localhost kernel: BIOS-e820: 0000000000000000 - 000000000009fc00 (usable) Jan 21 21:13:05 localhost kernel: BIOS-e820: 000000000009fc00 - 00000000000a0000 (reserved) Jan 21 21:13:05 localhost kernel: BIOS-e820: 00000000000f0000 - 0000000000100000 (reserved) Jan 21 21:13:05 localhost kernel: BIOS-e820: 0000000000100000 - 000000003ffec000 (usable) Jan 21 21:13:05 localhost kernel: BIOS-e820: 000000003ffec000 - 000000003ffef000 (ACPI data) Jan 21 21:13:05 localhost kernel: BIOS-e820: 000000003ffef000 - 000000003ffff000 (reserved) Jan 21 21:13:05 localhost kernel: BIOS-e820: 000000003ffff000 - 0000000040000000 (ACPI NVS) Jan 21 21:13:05 localhost kernel: BIOS-e820: 00000000fec00000 - 00000000fec01000 (reserved) Jan 21 21:13:05 localhost kernel: BIOS-e820: 00000000fee00000 - 00000000fee01000 (reserved) Jan 21 21:13:05 localhost kernel: BIOS-e820: 00000000ffff0000 - 0000000100000000 (reserved) Jan 21 21:13:05 localhost kernel: Warning only 896MB will be used. Jan 21 21:13:05 localhost kernel: Use a HIGHMEM enabled kernel. Jan 21 21:13:05 localhost kernel: 896MB LOWMEM available. Jan 21 21:13:05 localhost kernel: On node 0 totalpages: 229376 : (途中省略) : Jan 21 21:13:05 localhost kernel: mtrr: v1.40 (20010327) Richard Gooch (rgooch@atnf.csiro.au)←(1) Jan 21 21:13:05 localhost kernel: mtrr: detected mtrr type: Intel Jan 21 21:13:05 localhost kernel: CPU: L1 I cache: 0K, L1 D cache: 8K←(2) Jan 21 21:13:05 localhost kernel: CPU: L2 cache: 512K Jan 21 21:13:05 localhost kernel: CPU: Physical Processor ID: 0 Jan 21 21:13:05 localhost syslog: klogd startup succeeded Jan 21 21:13:05 localhost kernel: Intel machine check reporting enabled on CPU#0. Jan 21 21:13:05 localhost kernel: CPU0: Intel(R) Pentium(R) 4 CPU 3.06GHz stepping 07 Jan 21 21:13:05 localhost kernel: per-CPU timeslice cutoff: 1462.86 usecs.←(3) Jan 21 21:13:05 localhost kernel: SMP motherboard not detected.←(4) Jan 21 21:13:05 localhost kernel: enabled ExtINT on CPU#0 : (以下略) |
とりあえずこの「SMP motherboard not detected.」を表示している場所を探すと、これは「/usr/src/linux-2.4.20/arch/i386/kernel/smpboot.c」の中の「smp_boot_cpus()」という関数の中である。ちなみにこのソースファイル、1238行もあって、おまけにこの関数自体も300行近い代物なので、いきなり見ても分からない。そこでCall Tree(関数呼び出しの構造を示したもの)を作成してみたら、これまた700行近い分量になって、ちょっと見るに耐えない。とりあえず順序にそっておもな関数を追っかけてみると
smp_boot_cpus() // 関数が呼び出される mtrr_init_boot_cpu() // MTRR(Memory Type Range Register)の初期化(1) init_cpu_to_apicid() // CPUにあわせてAPIC IDを振る smp_store_cpu_info() // 最初のCPUの情報を格納 print_cpu_info() // 最初のCPUの情報を表示(2) set_bit() // 不明その1 |
といった具合になっている。ここで「set_bit()」から「init_idle()」までの「不明」というのは、同じディレクトリに当該ソースが見当たらないという意味である。(1)〜(4)までの数字は、それぞれ/var/log/messageのリスト部に対応する。さて問題の判断部だが、ソースを見ると
if (!smp_found_config) { printk(KERN_NOTICE "SMP motherboard not detected.\n"); : (以下略) |
となっており、「smp_found_config」という変数が「0」であるために、SMP対応マザーボードではないと判断されているようだ。ではこの変数に値を入れているのはどこか?ざっと探してみると
[root@localhost kernel]# grep smp_found_config *.c apic.c: if (smp_found_config || !cpu_has_apic) apic.c: if (!smp_found_config && detect_init_APIC()) { apic.c: if (smp_found_config) { apic.c: smp_found_config = 0; apic.c: if (!smp_found_config && !cpu_has_apic) apic.c: if (smp_found_config) mpparse.c:int smp_found_config; mpparse.c:smp_found_config = 0; mpparse.c:smp_found_config = 1; mpparse.c:if (smp_found_config) mpparse.c:smp_found_config = 1; setup.c: if (smp_found_config) smpboot.c:if (!smp_found_config) { smpboot.c:smp_found_config = 0; |
といった具合になっている。「smpboot.c」の中でも値を設定しているが、これはエラー処理(何らかの理由でSMP構成にできない場合、この値も0に設定しなおす)ということで、怪しいのは「mpparse.c」の中のようだ。そこで、mpparse.cの中で「smp_found_config」を探すと、
smp_scan_config() find_visws_smp() |
という2つの関数の中で、「smp_found_config = 1;」の設定がなされており、このどちらかの関数が呼ばれない事がSMP構成にならない理由のようだ。ただしコメントを見ると、
/* * - Intel MP Configuration Table * - or SGI Visual Workstation configuration */ void __init find_smp_config (void) { #ifdef CONFIG_X86_LOCAL_APIC find_intel_smp(); #endif #ifdef CONFIG_VISWS find_visws_smp(); #endif } |
とあって、「find_visws_smp()」はSGIのVisual Workstationのみで使われるから、関係するのは「smp_scan_config()」ということになる。
[大原雄介,ITmedia]