aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86/kernel/smpboot.c
diff options
context:
space:
mode:
authorJack Steiner <steiner@sgi.com>2008-03-28 15:12:16 -0400
committerIngo Molnar <mingo@elte.hu>2008-04-17 11:41:33 -0400
commitac23d4ee3f84de33c16ed7e68f9adee2386e74fb (patch)
tree296346293480fb5d67a15d7552bf41bd0cadd4cf /arch/x86/kernel/smpboot.c
parent570da318cf0e3053e62030253494c410a18d4be7 (diff)
x86: support for new UV apic
UV supports really big systems. So big, in fact, that the APICID register does not contain enough bits to contain an APICID that is unique across all cpus. The UV BIOS supports 3 APICID modes: - legacy mode. This mode uses the old APIC mode where APICID is in bits [31:24] of the APICID register. - x2apic mode. This mode is whitebox-compatible. APICIDs are unique across all cpus. Standard x2apic APIC operations (Intel-defined) can be used for IPIs. The node identifier fits within the Intel-defined portion of the APICID register. - x2apic-uv mode. In this mode, the APICIDs on each node have unique IDs, but IDs on different node are not unique. For example, if each mode has 32 cpus, the APICIDs on each node might be 0 - 31. Every node has the same set of IDs. The UV hub is used to route IPIs/interrupts to the correct node. Traditional APIC operations WILL NOT WORK. In x2apic-uv mode, the ACPI tables all contain a full unique ID (note: exact bit layout still changing but the following is close): nnnnnnnnnnlc0cch n = unique node number l = socket number on board c = core h = hyperthread Only the "lc0cch" bits are written to the APICID register. The remaining bits are supplied by having the get_apic_id() function "OR" the extra bits into the value read from the APICID register. (Hmmm.. why not keep the ENTIRE APICID register in per-cpu data....) The x2apic-uv mode is recognized by the MADT table containing: oem_id = "SGI" oem_table_id = "UV-X" Signed-off-by: Jack Steiner <steiner@sgi.com> Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'arch/x86/kernel/smpboot.c')
-rw-r--r--arch/x86/kernel/smpboot.c5
1 files changed, 5 insertions, 0 deletions
diff --git a/arch/x86/kernel/smpboot.c b/arch/x86/kernel/smpboot.c
index 5da35d2cdbd8..22bf6c29454f 100644
--- a/arch/x86/kernel/smpboot.c
+++ b/arch/x86/kernel/smpboot.c
@@ -1101,6 +1101,7 @@ static __init void disable_smp(void)
1101 */ 1101 */
1102static int __init smp_sanity_check(unsigned max_cpus) 1102static int __init smp_sanity_check(unsigned max_cpus)
1103{ 1103{
1104 preempt_disable();
1104 if (!physid_isset(hard_smp_processor_id(), phys_cpu_present_map)) { 1105 if (!physid_isset(hard_smp_processor_id(), phys_cpu_present_map)) {
1105 printk(KERN_WARNING "weird, boot CPU (#%d) not listed" 1106 printk(KERN_WARNING "weird, boot CPU (#%d) not listed"
1106 "by the BIOS.\n", hard_smp_processor_id()); 1107 "by the BIOS.\n", hard_smp_processor_id());
@@ -1112,6 +1113,7 @@ static int __init smp_sanity_check(unsigned max_cpus)
1112 * get out of here now! 1113 * get out of here now!
1113 */ 1114 */
1114 if (!smp_found_config && !acpi_lapic) { 1115 if (!smp_found_config && !acpi_lapic) {
1116 preempt_enable();
1115 printk(KERN_NOTICE "SMP motherboard not detected.\n"); 1117 printk(KERN_NOTICE "SMP motherboard not detected.\n");
1116 disable_smp(); 1118 disable_smp();
1117 if (APIC_init_uniprocessor()) 1119 if (APIC_init_uniprocessor())
@@ -1130,6 +1132,7 @@ static int __init smp_sanity_check(unsigned max_cpus)
1130 boot_cpu_physical_apicid); 1132 boot_cpu_physical_apicid);
1131 physid_set(hard_smp_processor_id(), phys_cpu_present_map); 1133 physid_set(hard_smp_processor_id(), phys_cpu_present_map);
1132 } 1134 }
1135 preempt_enable();
1133 1136
1134 /* 1137 /*
1135 * If we couldn't find a local APIC, then get out of here now! 1138 * If we couldn't find a local APIC, then get out of here now!
@@ -1205,11 +1208,13 @@ void __init native_smp_prepare_cpus(unsigned int max_cpus)
1205 return; 1208 return;
1206 } 1209 }
1207 1210
1211 preempt_disable();
1208 if (GET_APIC_ID(read_apic_id()) != boot_cpu_physical_apicid) { 1212 if (GET_APIC_ID(read_apic_id()) != boot_cpu_physical_apicid) {
1209 panic("Boot APIC ID in local APIC unexpected (%d vs %d)", 1213 panic("Boot APIC ID in local APIC unexpected (%d vs %d)",
1210 GET_APIC_ID(read_apic_id()), boot_cpu_physical_apicid); 1214 GET_APIC_ID(read_apic_id()), boot_cpu_physical_apicid);
1211 /* Or can we switch back to PIC here? */ 1215 /* Or can we switch back to PIC here? */
1212 } 1216 }
1217 preempt_enable();
1213 1218
1214#ifdef CONFIG_X86_32 1219#ifdef CONFIG_X86_32
1215 connect_bsp_APIC(); 1220 connect_bsp_APIC();