今日はacpi_parse_madt_lapic_entries()を見ていこう。と言ってもコードよりもACPIの仕様書読むほうがメインかも。。
901 static int __init acpi_parse_madt_lapic_entries(void) 902 { 903 int count; 904 int x2count = 0; 905 906 if (!cpu_has_apic) 907 return -ENODEV; 908 909 /* 910 * Note that the LAPIC address is obtained from the MADT (32-bit value) 911 * and (optionally) overriden by a LAPIC_ADDR_OVR entry (64-bit value). 912 */ 913 914 count = 915 acpi_table_parse_madt(ACPI_MADT_TYPE_LOCAL_APIC_OVERRIDE, 916 acpi_parse_lapic_addr_ovr, 0); 917 if (count < 0) { 918 printk(KERN_ERR PREFIX 919 "Error parsing LAPIC address override entry\n"); 920 return count; 921 }
この範囲ではacpi_table_parse_madt()の実行が主要処理なのでここを調べる。
コメントにLAPICのアドレスは32bitもしくは64bitの模様。ちなみにACPI_MADT_TYPE_LOCAL_APIC_OVERRIDEはinclude/acpi/actbl1.hによると以下のように定義されている。
650 /* Values for MADT subtable type in struct acpi_subtable_header */ 651 652 enum acpi_madt_type { 653 ACPI_MADT_TYPE_LOCAL_APIC = 0, ~略~ 657 ACPI_MADT_TYPE_LOCAL_APIC_NMI = 4, 658 ACPI_MADT_TYPE_LOCAL_APIC_OVERRIDE = 5, 659 ACPI_MADT_TYPE_IO_SAPIC = 6, ~略~ 666 ACPI_MADT_TYPE_RESERVED = 13 /* 13 and greater are reserved */ 667 };
ACPIの資料にあるMADTのテーブルリスト(Table 5-43 Multiple APIC Description Table (MADT) Format)ではこのような要素があるので32bitと言っている部分はここかな。
Field | Byte Length | Byte Offset | Description |
Local Interrupt Controller Address | 4 | 36 | The 32-bit physical address at which each processor can access its local interrupt controller. |
では64bitのほうはというと同じくMADTなんだけど、これはMADTの44バイト目から始まる可変部分にある「Local APIC Address Override」ですかね。
Field | Byte Length | Byte Offset | Description |
Interrupt Controller Structure[n] | -- | 44 |
Descriptionでは「ここには I/O APIC, I/O SAPIC, Local APIC, Local SAPIC, Interrupt Source Override, Non-maskable Interrupt Source, Local APIC NMI Source, Local APIC Address Override, Platform Interrupt Sources, Local x2APIC, Local x2APIC NMI,GIC and GICDなどのデータを入れておく」なんでことが書いてある。
また「Table 5-45 APIC Structure Types」に「Local APIC Address Override」は5とあるので間違いなさそう。
ということで、これのデータ構造を探すと「5.2.12.8 Local APIC Address Override Structure」にあって、内容は以下のとおり。
Field | Byte Length | Byte Offset | Description |
Type | 1 | 0 | これのタイプは5 |
Length | 1 | 1 | このテーブルのサイズで12 |
Reserved | 2 | 2 | 予約済み |
Local APIC Address | 8 | 4 | Local APICの物理アドレス |
ということで、「Local APIC Address Override Structure」があればLocal APICのアドレスは64bitで扱って、なければMADTの「Local Interrupt Controller Address」にある32bitのアドレスという感じかな。
そしてacpi_parse_madt_lapic_entries()に戻って
923 register_lapic_address(acpi_lapic_addr); 924 925 count = acpi_table_parse_madt(ACPI_MADT_TYPE_LOCAL_SAPIC, 926 acpi_parse_sapic, MAX_LOCAL_APIC);
register_lapic_address()はまあ飛ばしても良いかな。次にまたacpi_table_parse_madt()を呼ぶけど、今度のタイプは7の「Local SAPIC」。SAPIC? 仕様書にある用語集によるとこの用な説明。
A local Streamlined Advanced Programmable Interrupt Controller receives interrupts from the I/O SAPIC.
これだけだと「お、おう」としか言いようがないのでググってみると我らがIntel® Itanium® Processorのマニュアル(Intel® Itanium® Processor Family Interrupt Architecture Guide)に辿り着く( ´∀`)bグッ!
これの「1.3 Objectives of SAPIC」によると
The SAPIC architecture minimizes software context switching overhead, which is inherent with the APIC architecture. ~
というような説明が。
Local SAPIC Structureのテーブル構造はACPIの仕様書「5.2.12.10 Local SAPIC Structure」にあるので、そちらを参照。
で、またacpi_parse_madt_lapic_entries()に戻って、Local SAPICが見つからなければ次はタイプが9の「Processor Local x2APIC」&タイプ0の「Processor Local APIC」を探しにいく。
928 if (!count) { 929 x2count = acpi_table_parse_madt(ACPI_MADT_TYPE_LOCAL_X2APIC, 930 acpi_parse_x2apic, MAX_LOCAL_APIC); 931 count = acpi_table_parse_madt(ACPI_MADT_TYPE_LOCAL_APIC, 932 acpi_parse_lapic, MAX_LOCAL_APIC); 933 }
単なるエラーチェック。
934 if (!count && !x2count) { 935 printk(KERN_ERR PREFIX "No LAPIC entries present\n"); 936 /* TBD: Cleanup to allow fallback to MPS */ 937 return -ENODEV; 938 } else if (count < 0 || x2count < 0) { 939 printk(KERN_ERR PREFIX "Error parsing LAPIC entry\n"); 940 /* TBD: Cleanup to allow fallback to MPS */ 941 return count; 942 } 943
そして最後はタイプ0x0aの「Local x2APIC NMI」とタイプ4の「Local APIC NMI」をチェック。
944 x2count = 945 acpi_table_parse_madt(ACPI_MADT_TYPE_LOCAL_X2APIC_NMI, 946 acpi_parse_x2apic_nmi, 0); 947 count = 948 acpi_table_parse_madt(ACPI_MADT_TYPE_LOCAL_APIC_NMI, acpi_parse_lapic_nmi, 0); 949 if (count < 0 || x2count < 0) { 950 printk(KERN_ERR PREFIX "Error parsing LAPIC NMI entry\n"); 951 /* TBD: Cleanup to allow fallback to MPS */ 952 return count; 953 } 954 return 0; 955 }
ここまでで使用しているPCのAPICの構成がつかめた感じですかね。
ああ、そういえばacpi_table_parse_madt()は2番目の引数に関数ポインタを渡していて acpi_table_parse_entries()で対象のテーブルが見つかった場合にこの関数で何かしらの処理させているので次はacpi_parse_x2apic()とかacpi_parse_x2apic_nmi()が何をやっているのかを調べようφ( ̄ー ̄ )メモメモ
Debug Hacks -デバッグを極めるテクニック&ツール
- 作者: 吉岡弘隆,大和一洋,大岩尚宏,安部東洋,吉田俊輔
- 出版社/メーカー: オライリージャパン
- 発売日: 2009/04/27
- メディア: 単行本(ソフトカバー)
- 購入: 12人 クリック: 419回
- この商品を含むブログ (73件) を見る