エンタープライズ:特集 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
  logical_smp_processor_id()  // 不明その2
  map_cpu_to_boot_apicid()  // 不明その3
  init_idle()      // 不明その4
  smp_tune_scheduling()    // タイムスライスの値を設定(3)
  →この直後に、SMP対応マザーでないと判断される(4)

といった具合になっている。ここで「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()」ということになる。

前のページ | 1 2 3 4 5 | 次のページ

[大原雄介,ITmedia]