うちではデスクトップとして使っているPCにIntel® Core™ i7-3770S Processorを使っていて、コア数が4、8スレッドということで/proc/cpuinfoでは8個のcpuがLinuxによって認識されています。では、これがどのような手順で認識されていったのか?というのをちょっと調べて見たくなった訳です(/ω\)
まずは本題に入る前に、x86でのSMPに関する仕様はIntelが出している仕様書がIntelのWebサイトからダウンロードできます。
あとは、ずっと前に自分がはてなダイアリーのほうに書いた記事ですがこんなのとか見ておくと予備知識になるかも。これらはMinix 2.0でSMP対応した人が居てそのコードを読みながら調べたやつです。
- MP Floating Pointer Structureを調べる
- MP Configuration table Headerの仕組み
- MP Configuration Table Entriesの内容
Linuxのソースを見ていて、名前からsmp_init()が初期処理なんだろうと思ったら実は違っていて、この関数の実行時点ではCPUがいくつあるかとかは既に判明しているっぽいのです。なので
dmesgでログを見て、順番に追いかけていこうと思います。
最初に見つかったのがこれで「 found SMP MP-table ~」とありますね。これが見つかったということはCPUが複数有るのは確定できます。
[ 0.000000] e820: update [mem 0x7b800000-0xffffffff] usable ==> reserved [ 0.000000] e820: last_pfn = 0x7b000 max_arch_pfn = 0x400000000 [ 0.000000] found SMP MP-table at [mem 0x000fd7d0-0x000fd7df] mapped at [ffff8800000fd7d0] [ 0.000000] Scanning 1 areas for low memory corruption [ 0.000000] Base memory trampoline at [ffff880000097000] 97000 size 24576
次に見つかるのがこれ。SMPの設定にMADTを使いますよとい内容のログが。
[ 0.000000] ACPI: IRQ9 used by override. [ 0.000000] Using ACPI (MADT) for SMP configuration information
そしてしばらく進むとこんなログが。これはログの先頭に「smpboot:」が有るしどこで出したログかは分かりやすそう。
で、最後の行で8cpuがアクティブになったと言ってます。
[ 0.103172] smpboot: CPU0: Intel(R) Core(TM) i7-3770S CPU @ 3.10GHz (fam: 06, model: 3a, stepping: 09) [ 0.103177] TSC deadline timer enabled [ 0.103184] Performance Events: PEBS fmt1+, 16-deep LBR, IvyBridge events, full-width counters, Intel PMU driver. [ 0.103190] ... version: 3 [ 0.103191] ... bit width: 48 [ 0.103192] ... generic registers: 4 [ 0.103192] ... value mask: 0000ffffffffffff [ 0.103193] ... max period: 0000ffffffffffff [ 0.103194] ... fixed-purpose events: 3 [ 0.103195] ... event mask: 000000070000000f [ 0.130009] x86: Booting SMP configuration: [ 0.143576] NMI watchdog: enabled on all CPUs, permanently consumes one hw-PMU counter. [ 0.130011] .... node #0, CPUs: #1 #2 #3 #4 #5 #6 #7 [ 0.264952] x86: Booted up 1 node, 8 CPUs [ 0.264955] smpboot: Total of 8 processors activated (49668.45 BogoMIPS)
では、「found SMP MP-table at ~」はどこでだしているのか見ていこう。この文字列で検索をかけるとarch/x86/kernel/mpparse.cがヒットします。
564 static int __init smp_scan_config(unsigned long base, unsigned long length) 565 { 566 unsigned int *bp = phys_to_virt(base); 567 struct mpf_intel *mpf; 568 unsigned long mem; 569 570 apic_printk(APIC_VERBOSE, "Scan for SMP in [mem %#010lx-%#010lx]\n", 571 base, base + length - 1); 572 BUILD_BUG_ON(sizeof(*mpf) != 16); 573 574 while (length > 0) { 575 mpf = (struct mpf_intel *)bp; 576 if ((*bp == SMP_MAGIC_IDENT) && 577 (mpf->length == 1) && 578 !mpf_checksum((unsigned char *)bp, 16) && 579 ((mpf->specification == 1) 580 || (mpf->specification == 4))) { 581 #ifdef CONFIG_X86_LOCAL_APIC 582 smp_found_config = 1; 583 #endif 584 mpf_found = mpf; 585 586 printk(KERN_INFO "found SMP MP-table at [mem %#010llx-%#010llx] mapped at [%p]\n", 587 (unsigned long long) virt_to_phys(mpf), 588 (unsigned long long) virt_to_phys(mpf) + 589 sizeof(*mpf) - 1, mpf); 590 591 mem = virt_to_phys(mpf); 592 memblock_reserve(mem, sizeof(*mpf)); 593 if (mpf->physptr) 594 smp_reserve_memory(mpf); 595 596 return 1; 597 } 598 bp += 4; 599 length -= 16; 600 } 601 return 0; 602 }
ここでやっている内容はまさしく「MP Floating Pointer Structureを調べる」で調べた内容です。ここで探しているのは「MP Floating Pointer Structure」というものです。これは以下の場所にあります。
- Extended BIOS Data Area(EBDA)の最初の1KB以内。または、
- EDBAが定義されていない場合は、ベースメモリ領域の最後の1KB(ベースメモリ領域が640KBなら639-640KBの範囲)。または、
- BIOSのROM内。アドレス0F0000h~0FFFFFの範囲。
smp_scan_config()を呼んでいるdefault_find_smp_config()を見るとこのようになっています。
604 void __init default_find_smp_config(void) 605 { 606 unsigned int address; 607 608 /* 609 * FIXME: Linux assumes you have 640K of base ram.. 610 * this continues the error... 611 * 612 * 1) Scan the bottom 1K for a signature 613 * 2) Scan the top 1K of base RAM 614 * 3) Scan the 64K of bios 615 */ 616 if (smp_scan_config(0x0, 0x400) || 617 smp_scan_config(639 * 0x400, 0x400) || 618 smp_scan_config(0xF0000, 0x10000)) 619 return; 620 /*
さて、smp_scan_config()ではこのテーブルを見つけるまでが仕事ですね。この関数までのコールフローは以下のような感じです。
start_kernel()
-> setup_arch()
-> find_smp_config()
-> default_find_smp_config()
-> smp_scan_config()
(´-`).。oO(次は「Using ACPI (MADT) for SMP configuration information」を見よう
Linuxカーネル Hacks ―パフォーマンス改善、開発効率向上、省電力化のためのテクニック
- 作者: 池田宗広,大岩尚宏,島本裕志,竹部晶雄,平松雅巳,高橋浩和
- 出版社/メーカー: オライリージャパン
- 発売日: 2011/07/26
- メディア: 単行本(ソフトカバー)
- 購入: 4人 クリック: 50回
- この商品を含むブログ (4件) を見る