aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86/kernel/apic_32.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/x86/kernel/apic_32.c')
-rw-r--r--arch/x86/kernel/apic_32.c98
1 files changed, 39 insertions, 59 deletions
diff --git a/arch/x86/kernel/apic_32.c b/arch/x86/kernel/apic_32.c
index 4b99b1bdeb6..6dea8306d8c 100644
--- a/arch/x86/kernel/apic_32.c
+++ b/arch/x86/kernel/apic_32.c
@@ -52,30 +52,36 @@
52 52
53unsigned long mp_lapic_addr; 53unsigned long mp_lapic_addr;
54 54
55DEFINE_PER_CPU(u16, x86_bios_cpu_apicid) = BAD_APICID;
56EXPORT_PER_CPU_SYMBOL(x86_bios_cpu_apicid);
57
58/* 55/*
59 * Knob to control our willingness to enable the local APIC. 56 * Knob to control our willingness to enable the local APIC.
60 * 57 *
61 * -1=force-disable, +1=force-enable 58 * +1=force-enable
62 */ 59 */
63static int enable_local_apic __initdata; 60static int force_enable_local_apic;
61int disable_apic;
64 62
65/* Local APIC timer verification ok */ 63/* Local APIC timer verification ok */
66static int local_apic_timer_verify_ok; 64static int local_apic_timer_verify_ok;
67/* Disable local APIC timer from the kernel commandline or via dmi quirk 65/* Disable local APIC timer from the kernel commandline or via dmi quirk */
68 or using CPU MSR check */ 66static int local_apic_timer_disabled;
69int local_apic_timer_disabled;
70/* Local APIC timer works in C2 */ 67/* Local APIC timer works in C2 */
71int local_apic_timer_c2_ok; 68int local_apic_timer_c2_ok;
72EXPORT_SYMBOL_GPL(local_apic_timer_c2_ok); 69EXPORT_SYMBOL_GPL(local_apic_timer_c2_ok);
73 70
71int first_system_vector = 0xfe;
72
73char system_vectors[NR_VECTORS] = { [0 ... NR_VECTORS-1] = SYS_VECTOR_FREE};
74
74/* 75/*
75 * Debug level, exported for io_apic.c 76 * Debug level, exported for io_apic.c
76 */ 77 */
77int apic_verbosity; 78int apic_verbosity;
78 79
80int pic_mode;
81
82/* Have we found an MP table */
83int smp_found_config;
84
79static unsigned int calibration_result; 85static unsigned int calibration_result;
80 86
81static int lapic_next_event(unsigned long delta, 87static int lapic_next_event(unsigned long delta,
@@ -545,7 +551,7 @@ void __init setup_boot_APIC_clock(void)
545 lapic_clockevent.features &= ~CLOCK_EVT_FEAT_DUMMY; 551 lapic_clockevent.features &= ~CLOCK_EVT_FEAT_DUMMY;
546 else 552 else
547 printk(KERN_WARNING "APIC timer registered as dummy," 553 printk(KERN_WARNING "APIC timer registered as dummy,"
548 " due to nmi_watchdog=1!\n"); 554 " due to nmi_watchdog=%d!\n", nmi_watchdog);
549 } 555 }
550 556
551 /* Setup the lapic or request the broadcast */ 557 /* Setup the lapic or request the broadcast */
@@ -1094,7 +1100,7 @@ static int __init detect_init_APIC(void)
1094 u32 h, l, features; 1100 u32 h, l, features;
1095 1101
1096 /* Disabled by kernel option? */ 1102 /* Disabled by kernel option? */
1097 if (enable_local_apic < 0) 1103 if (disable_apic)
1098 return -1; 1104 return -1;
1099 1105
1100 switch (boot_cpu_data.x86_vendor) { 1106 switch (boot_cpu_data.x86_vendor) {
@@ -1117,7 +1123,7 @@ static int __init detect_init_APIC(void)
1117 * Over-ride BIOS and try to enable the local APIC only if 1123 * Over-ride BIOS and try to enable the local APIC only if
1118 * "lapic" specified. 1124 * "lapic" specified.
1119 */ 1125 */
1120 if (enable_local_apic <= 0) { 1126 if (!force_enable_local_apic) {
1121 printk(KERN_INFO "Local APIC disabled by BIOS -- " 1127 printk(KERN_INFO "Local APIC disabled by BIOS -- "
1122 "you can enable it with \"lapic\"\n"); 1128 "you can enable it with \"lapic\"\n");
1123 return -1; 1129 return -1;
@@ -1154,9 +1160,6 @@ static int __init detect_init_APIC(void)
1154 if (l & MSR_IA32_APICBASE_ENABLE) 1160 if (l & MSR_IA32_APICBASE_ENABLE)
1155 mp_lapic_addr = l & MSR_IA32_APICBASE_BASE; 1161 mp_lapic_addr = l & MSR_IA32_APICBASE_BASE;
1156 1162
1157 if (nmi_watchdog != NMI_NONE && nmi_watchdog != NMI_DISABLED)
1158 nmi_watchdog = NMI_LOCAL_APIC;
1159
1160 printk(KERN_INFO "Found and enabled local APIC!\n"); 1163 printk(KERN_INFO "Found and enabled local APIC!\n");
1161 1164
1162 apic_pm_activate(); 1165 apic_pm_activate();
@@ -1195,36 +1198,6 @@ void __init init_apic_mappings(void)
1195 if (boot_cpu_physical_apicid == -1U) 1198 if (boot_cpu_physical_apicid == -1U)
1196 boot_cpu_physical_apicid = GET_APIC_ID(read_apic_id()); 1199 boot_cpu_physical_apicid = GET_APIC_ID(read_apic_id());
1197 1200
1198#ifdef CONFIG_X86_IO_APIC
1199 {
1200 unsigned long ioapic_phys, idx = FIX_IO_APIC_BASE_0;
1201 int i;
1202
1203 for (i = 0; i < nr_ioapics; i++) {
1204 if (smp_found_config) {
1205 ioapic_phys = mp_ioapics[i].mpc_apicaddr;
1206 if (!ioapic_phys) {
1207 printk(KERN_ERR
1208 "WARNING: bogus zero IO-APIC "
1209 "address found in MPTABLE, "
1210 "disabling IO/APIC support!\n");
1211 smp_found_config = 0;
1212 skip_ioapic_setup = 1;
1213 goto fake_ioapic_page;
1214 }
1215 } else {
1216fake_ioapic_page:
1217 ioapic_phys = (unsigned long)
1218 alloc_bootmem_pages(PAGE_SIZE);
1219 ioapic_phys = __pa(ioapic_phys);
1220 }
1221 set_fixmap_nocache(idx, ioapic_phys);
1222 printk(KERN_DEBUG "mapped IOAPIC to %08lx (%08lx)\n",
1223 __fix_to_virt(idx), ioapic_phys);
1224 idx++;
1225 }
1226 }
1227#endif
1228} 1201}
1229 1202
1230/* 1203/*
@@ -1236,7 +1209,7 @@ int apic_version[MAX_APICS];
1236 1209
1237int __init APIC_init_uniprocessor(void) 1210int __init APIC_init_uniprocessor(void)
1238{ 1211{
1239 if (enable_local_apic < 0) 1212 if (disable_apic)
1240 clear_cpu_cap(&boot_cpu_data, X86_FEATURE_APIC); 1213 clear_cpu_cap(&boot_cpu_data, X86_FEATURE_APIC);
1241 1214
1242 if (!smp_found_config && !cpu_has_apic) 1215 if (!smp_found_config && !cpu_has_apic)
@@ -1265,10 +1238,14 @@ int __init APIC_init_uniprocessor(void)
1265#ifdef CONFIG_CRASH_DUMP 1238#ifdef CONFIG_CRASH_DUMP
1266 boot_cpu_physical_apicid = GET_APIC_ID(read_apic_id()); 1239 boot_cpu_physical_apicid = GET_APIC_ID(read_apic_id());
1267#endif 1240#endif
1268 phys_cpu_present_map = physid_mask_of_physid(boot_cpu_physical_apicid); 1241 physid_set_mask_of_physid(boot_cpu_physical_apicid, &phys_cpu_present_map);
1269 1242
1270 setup_local_APIC(); 1243 setup_local_APIC();
1271 1244
1245#ifdef CONFIG_X86_IO_APIC
1246 if (!smp_found_config || skip_ioapic_setup || !nr_ioapics)
1247#endif
1248 localise_nmi_watchdog();
1272 end_local_APIC_setup(); 1249 end_local_APIC_setup();
1273#ifdef CONFIG_X86_IO_APIC 1250#ifdef CONFIG_X86_IO_APIC
1274 if (smp_found_config) 1251 if (smp_found_config)
@@ -1351,13 +1328,13 @@ void __init smp_intr_init(void)
1351 * The reschedule interrupt is a CPU-to-CPU reschedule-helper 1328 * The reschedule interrupt is a CPU-to-CPU reschedule-helper
1352 * IPI, driven by wakeup. 1329 * IPI, driven by wakeup.
1353 */ 1330 */
1354 set_intr_gate(RESCHEDULE_VECTOR, reschedule_interrupt); 1331 alloc_intr_gate(RESCHEDULE_VECTOR, reschedule_interrupt);
1355 1332
1356 /* IPI for invalidation */ 1333 /* IPI for invalidation */
1357 set_intr_gate(INVALIDATE_TLB_VECTOR, invalidate_interrupt); 1334 alloc_intr_gate(INVALIDATE_TLB_VECTOR, invalidate_interrupt);
1358 1335
1359 /* IPI for generic function call */ 1336 /* IPI for generic function call */
1360 set_intr_gate(CALL_FUNCTION_VECTOR, call_function_interrupt); 1337 alloc_intr_gate(CALL_FUNCTION_VECTOR, call_function_interrupt);
1361} 1338}
1362#endif 1339#endif
1363 1340
@@ -1370,15 +1347,15 @@ void __init apic_intr_init(void)
1370 smp_intr_init(); 1347 smp_intr_init();
1371#endif 1348#endif
1372 /* self generated IPI for local APIC timer */ 1349 /* self generated IPI for local APIC timer */
1373 set_intr_gate(LOCAL_TIMER_VECTOR, apic_timer_interrupt); 1350 alloc_intr_gate(LOCAL_TIMER_VECTOR, apic_timer_interrupt);
1374 1351
1375 /* IPI vectors for APIC spurious and error interrupts */ 1352 /* IPI vectors for APIC spurious and error interrupts */
1376 set_intr_gate(SPURIOUS_APIC_VECTOR, spurious_interrupt); 1353 alloc_intr_gate(SPURIOUS_APIC_VECTOR, spurious_interrupt);
1377 set_intr_gate(ERROR_APIC_VECTOR, error_interrupt); 1354 alloc_intr_gate(ERROR_APIC_VECTOR, error_interrupt);
1378 1355
1379 /* thermal monitor LVT interrupt */ 1356 /* thermal monitor LVT interrupt */
1380#ifdef CONFIG_X86_MCE_P4THERMAL 1357#ifdef CONFIG_X86_MCE_P4THERMAL
1381 set_intr_gate(THERMAL_APIC_VECTOR, thermal_interrupt); 1358 alloc_intr_gate(THERMAL_APIC_VECTOR, thermal_interrupt);
1382#endif 1359#endif
1383} 1360}
1384 1361
@@ -1513,6 +1490,9 @@ void __cpuinit generic_processor_info(int apicid, int version)
1513 */ 1490 */
1514 cpu = 0; 1491 cpu = 0;
1515 1492
1493 if (apicid > max_physical_apicid)
1494 max_physical_apicid = apicid;
1495
1516 /* 1496 /*
1517 * Would be preferable to switch to bigsmp when CONFIG_HOTPLUG_CPU=y 1497 * Would be preferable to switch to bigsmp when CONFIG_HOTPLUG_CPU=y
1518 * but we need to work other dependencies like SMP_SUSPEND etc 1498 * but we need to work other dependencies like SMP_SUSPEND etc
@@ -1520,7 +1500,7 @@ void __cpuinit generic_processor_info(int apicid, int version)
1520 * if (CPU_HOTPLUG_ENABLED || num_processors > 8) 1500 * if (CPU_HOTPLUG_ENABLED || num_processors > 8)
1521 * - Ashok Raj <ashok.raj@intel.com> 1501 * - Ashok Raj <ashok.raj@intel.com>
1522 */ 1502 */
1523 if (num_processors > 8) { 1503 if (max_physical_apicid >= 8) {
1524 switch (boot_cpu_data.x86_vendor) { 1504 switch (boot_cpu_data.x86_vendor) {
1525 case X86_VENDOR_INTEL: 1505 case X86_VENDOR_INTEL:
1526 if (!APIC_XAPIC(version)) { 1506 if (!APIC_XAPIC(version)) {
@@ -1534,9 +1514,9 @@ void __cpuinit generic_processor_info(int apicid, int version)
1534 } 1514 }
1535#ifdef CONFIG_SMP 1515#ifdef CONFIG_SMP
1536 /* are we being called early in kernel startup? */ 1516 /* are we being called early in kernel startup? */
1537 if (x86_cpu_to_apicid_early_ptr) { 1517 if (early_per_cpu_ptr(x86_cpu_to_apicid)) {
1538 u16 *cpu_to_apicid = x86_cpu_to_apicid_early_ptr; 1518 u16 *cpu_to_apicid = early_per_cpu_ptr(x86_cpu_to_apicid);
1539 u16 *bios_cpu_apicid = x86_bios_cpu_apicid_early_ptr; 1519 u16 *bios_cpu_apicid = early_per_cpu_ptr(x86_bios_cpu_apicid);
1540 1520
1541 cpu_to_apicid[cpu] = apicid; 1521 cpu_to_apicid[cpu] = apicid;
1542 bios_cpu_apicid[cpu] = apicid; 1522 bios_cpu_apicid[cpu] = apicid;
@@ -1703,14 +1683,14 @@ static void apic_pm_activate(void) { }
1703 */ 1683 */
1704static int __init parse_lapic(char *arg) 1684static int __init parse_lapic(char *arg)
1705{ 1685{
1706 enable_local_apic = 1; 1686 force_enable_local_apic = 1;
1707 return 0; 1687 return 0;
1708} 1688}
1709early_param("lapic", parse_lapic); 1689early_param("lapic", parse_lapic);
1710 1690
1711static int __init parse_nolapic(char *arg) 1691static int __init parse_nolapic(char *arg)
1712{ 1692{
1713 enable_local_apic = -1; 1693 disable_apic = 1;
1714 clear_cpu_cap(&boot_cpu_data, X86_FEATURE_APIC); 1694 clear_cpu_cap(&boot_cpu_data, X86_FEATURE_APIC);
1715 return 0; 1695 return 0;
1716} 1696}