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.c123
1 files changed, 63 insertions, 60 deletions
diff --git a/arch/x86/kernel/apic_32.c b/arch/x86/kernel/apic_32.c
index 4b99b1bdeb6c..3e58b676d23b 100644
--- a/arch/x86/kernel/apic_32.c
+++ b/arch/x86/kernel/apic_32.c
@@ -52,30 +52,41 @@
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
85static struct resource lapic_resource = {
86 .name = "Local APIC",
87 .flags = IORESOURCE_MEM | IORESOURCE_BUSY,
88};
89
79static unsigned int calibration_result; 90static unsigned int calibration_result;
80 91
81static int lapic_next_event(unsigned long delta, 92static int lapic_next_event(unsigned long delta,
@@ -545,7 +556,7 @@ void __init setup_boot_APIC_clock(void)
545 lapic_clockevent.features &= ~CLOCK_EVT_FEAT_DUMMY; 556 lapic_clockevent.features &= ~CLOCK_EVT_FEAT_DUMMY;
546 else 557 else
547 printk(KERN_WARNING "APIC timer registered as dummy," 558 printk(KERN_WARNING "APIC timer registered as dummy,"
548 " due to nmi_watchdog=1!\n"); 559 " due to nmi_watchdog=%d!\n", nmi_watchdog);
549 } 560 }
550 561
551 /* Setup the lapic or request the broadcast */ 562 /* Setup the lapic or request the broadcast */
@@ -963,7 +974,7 @@ void __cpuinit setup_local_APIC(void)
963 * Double-check whether this APIC is really registered. 974 * Double-check whether this APIC is really registered.
964 */ 975 */
965 if (!apic_id_registered()) 976 if (!apic_id_registered())
966 BUG(); 977 WARN_ON_ONCE(1);
967 978
968 /* 979 /*
969 * Intel recommends to set DFR, LDR and TPR before enabling 980 * Intel recommends to set DFR, LDR and TPR before enabling
@@ -1094,7 +1105,7 @@ static int __init detect_init_APIC(void)
1094 u32 h, l, features; 1105 u32 h, l, features;
1095 1106
1096 /* Disabled by kernel option? */ 1107 /* Disabled by kernel option? */
1097 if (enable_local_apic < 0) 1108 if (disable_apic)
1098 return -1; 1109 return -1;
1099 1110
1100 switch (boot_cpu_data.x86_vendor) { 1111 switch (boot_cpu_data.x86_vendor) {
@@ -1117,7 +1128,7 @@ static int __init detect_init_APIC(void)
1117 * Over-ride BIOS and try to enable the local APIC only if 1128 * Over-ride BIOS and try to enable the local APIC only if
1118 * "lapic" specified. 1129 * "lapic" specified.
1119 */ 1130 */
1120 if (enable_local_apic <= 0) { 1131 if (!force_enable_local_apic) {
1121 printk(KERN_INFO "Local APIC disabled by BIOS -- " 1132 printk(KERN_INFO "Local APIC disabled by BIOS -- "
1122 "you can enable it with \"lapic\"\n"); 1133 "you can enable it with \"lapic\"\n");
1123 return -1; 1134 return -1;
@@ -1154,9 +1165,6 @@ static int __init detect_init_APIC(void)
1154 if (l & MSR_IA32_APICBASE_ENABLE) 1165 if (l & MSR_IA32_APICBASE_ENABLE)
1155 mp_lapic_addr = l & MSR_IA32_APICBASE_BASE; 1166 mp_lapic_addr = l & MSR_IA32_APICBASE_BASE;
1156 1167
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"); 1168 printk(KERN_INFO "Found and enabled local APIC!\n");
1161 1169
1162 apic_pm_activate(); 1170 apic_pm_activate();
@@ -1195,36 +1203,6 @@ void __init init_apic_mappings(void)
1195 if (boot_cpu_physical_apicid == -1U) 1203 if (boot_cpu_physical_apicid == -1U)
1196 boot_cpu_physical_apicid = GET_APIC_ID(read_apic_id()); 1204 boot_cpu_physical_apicid = GET_APIC_ID(read_apic_id());
1197 1205
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} 1206}
1229 1207
1230/* 1208/*
@@ -1236,7 +1214,7 @@ int apic_version[MAX_APICS];
1236 1214
1237int __init APIC_init_uniprocessor(void) 1215int __init APIC_init_uniprocessor(void)
1238{ 1216{
1239 if (enable_local_apic < 0) 1217 if (disable_apic)
1240 clear_cpu_cap(&boot_cpu_data, X86_FEATURE_APIC); 1218 clear_cpu_cap(&boot_cpu_data, X86_FEATURE_APIC);
1241 1219
1242 if (!smp_found_config && !cpu_has_apic) 1220 if (!smp_found_config && !cpu_has_apic)
@@ -1265,10 +1243,14 @@ int __init APIC_init_uniprocessor(void)
1265#ifdef CONFIG_CRASH_DUMP 1243#ifdef CONFIG_CRASH_DUMP
1266 boot_cpu_physical_apicid = GET_APIC_ID(read_apic_id()); 1244 boot_cpu_physical_apicid = GET_APIC_ID(read_apic_id());
1267#endif 1245#endif
1268 phys_cpu_present_map = physid_mask_of_physid(boot_cpu_physical_apicid); 1246 physid_set_mask_of_physid(boot_cpu_physical_apicid, &phys_cpu_present_map);
1269 1247
1270 setup_local_APIC(); 1248 setup_local_APIC();
1271 1249
1250#ifdef CONFIG_X86_IO_APIC
1251 if (!smp_found_config || skip_ioapic_setup || !nr_ioapics)
1252#endif
1253 localise_nmi_watchdog();
1272 end_local_APIC_setup(); 1254 end_local_APIC_setup();
1273#ifdef CONFIG_X86_IO_APIC 1255#ifdef CONFIG_X86_IO_APIC
1274 if (smp_found_config) 1256 if (smp_found_config)
@@ -1351,13 +1333,13 @@ void __init smp_intr_init(void)
1351 * The reschedule interrupt is a CPU-to-CPU reschedule-helper 1333 * The reschedule interrupt is a CPU-to-CPU reschedule-helper
1352 * IPI, driven by wakeup. 1334 * IPI, driven by wakeup.
1353 */ 1335 */
1354 set_intr_gate(RESCHEDULE_VECTOR, reschedule_interrupt); 1336 alloc_intr_gate(RESCHEDULE_VECTOR, reschedule_interrupt);
1355 1337
1356 /* IPI for invalidation */ 1338 /* IPI for invalidation */
1357 set_intr_gate(INVALIDATE_TLB_VECTOR, invalidate_interrupt); 1339 alloc_intr_gate(INVALIDATE_TLB_VECTOR, invalidate_interrupt);
1358 1340
1359 /* IPI for generic function call */ 1341 /* IPI for generic function call */
1360 set_intr_gate(CALL_FUNCTION_VECTOR, call_function_interrupt); 1342 alloc_intr_gate(CALL_FUNCTION_VECTOR, call_function_interrupt);
1361} 1343}
1362#endif 1344#endif
1363 1345
@@ -1370,15 +1352,15 @@ void __init apic_intr_init(void)
1370 smp_intr_init(); 1352 smp_intr_init();
1371#endif 1353#endif
1372 /* self generated IPI for local APIC timer */ 1354 /* self generated IPI for local APIC timer */
1373 set_intr_gate(LOCAL_TIMER_VECTOR, apic_timer_interrupt); 1355 alloc_intr_gate(LOCAL_TIMER_VECTOR, apic_timer_interrupt);
1374 1356
1375 /* IPI vectors for APIC spurious and error interrupts */ 1357 /* IPI vectors for APIC spurious and error interrupts */
1376 set_intr_gate(SPURIOUS_APIC_VECTOR, spurious_interrupt); 1358 alloc_intr_gate(SPURIOUS_APIC_VECTOR, spurious_interrupt);
1377 set_intr_gate(ERROR_APIC_VECTOR, error_interrupt); 1359 alloc_intr_gate(ERROR_APIC_VECTOR, error_interrupt);
1378 1360
1379 /* thermal monitor LVT interrupt */ 1361 /* thermal monitor LVT interrupt */
1380#ifdef CONFIG_X86_MCE_P4THERMAL 1362#ifdef CONFIG_X86_MCE_P4THERMAL
1381 set_intr_gate(THERMAL_APIC_VECTOR, thermal_interrupt); 1363 alloc_intr_gate(THERMAL_APIC_VECTOR, thermal_interrupt);
1382#endif 1364#endif
1383} 1365}
1384 1366
@@ -1513,6 +1495,9 @@ void __cpuinit generic_processor_info(int apicid, int version)
1513 */ 1495 */
1514 cpu = 0; 1496 cpu = 0;
1515 1497
1498 if (apicid > max_physical_apicid)
1499 max_physical_apicid = apicid;
1500
1516 /* 1501 /*
1517 * Would be preferable to switch to bigsmp when CONFIG_HOTPLUG_CPU=y 1502 * Would be preferable to switch to bigsmp when CONFIG_HOTPLUG_CPU=y
1518 * but we need to work other dependencies like SMP_SUSPEND etc 1503 * but we need to work other dependencies like SMP_SUSPEND etc
@@ -1520,7 +1505,7 @@ void __cpuinit generic_processor_info(int apicid, int version)
1520 * if (CPU_HOTPLUG_ENABLED || num_processors > 8) 1505 * if (CPU_HOTPLUG_ENABLED || num_processors > 8)
1521 * - Ashok Raj <ashok.raj@intel.com> 1506 * - Ashok Raj <ashok.raj@intel.com>
1522 */ 1507 */
1523 if (num_processors > 8) { 1508 if (max_physical_apicid >= 8) {
1524 switch (boot_cpu_data.x86_vendor) { 1509 switch (boot_cpu_data.x86_vendor) {
1525 case X86_VENDOR_INTEL: 1510 case X86_VENDOR_INTEL:
1526 if (!APIC_XAPIC(version)) { 1511 if (!APIC_XAPIC(version)) {
@@ -1534,9 +1519,9 @@ void __cpuinit generic_processor_info(int apicid, int version)
1534 } 1519 }
1535#ifdef CONFIG_SMP 1520#ifdef CONFIG_SMP
1536 /* are we being called early in kernel startup? */ 1521 /* are we being called early in kernel startup? */
1537 if (x86_cpu_to_apicid_early_ptr) { 1522 if (early_per_cpu_ptr(x86_cpu_to_apicid)) {
1538 u16 *cpu_to_apicid = x86_cpu_to_apicid_early_ptr; 1523 u16 *cpu_to_apicid = early_per_cpu_ptr(x86_cpu_to_apicid);
1539 u16 *bios_cpu_apicid = x86_bios_cpu_apicid_early_ptr; 1524 u16 *bios_cpu_apicid = early_per_cpu_ptr(x86_bios_cpu_apicid);
1540 1525
1541 cpu_to_apicid[cpu] = apicid; 1526 cpu_to_apicid[cpu] = apicid;
1542 bios_cpu_apicid[cpu] = apicid; 1527 bios_cpu_apicid[cpu] = apicid;
@@ -1703,14 +1688,14 @@ static void apic_pm_activate(void) { }
1703 */ 1688 */
1704static int __init parse_lapic(char *arg) 1689static int __init parse_lapic(char *arg)
1705{ 1690{
1706 enable_local_apic = 1; 1691 force_enable_local_apic = 1;
1707 return 0; 1692 return 0;
1708} 1693}
1709early_param("lapic", parse_lapic); 1694early_param("lapic", parse_lapic);
1710 1695
1711static int __init parse_nolapic(char *arg) 1696static int __init parse_nolapic(char *arg)
1712{ 1697{
1713 enable_local_apic = -1; 1698 disable_apic = 1;
1714 clear_cpu_cap(&boot_cpu_data, X86_FEATURE_APIC); 1699 clear_cpu_cap(&boot_cpu_data, X86_FEATURE_APIC);
1715 return 0; 1700 return 0;
1716} 1701}
@@ -1740,3 +1725,21 @@ static int __init apic_set_verbosity(char *str)
1740} 1725}
1741__setup("apic=", apic_set_verbosity); 1726__setup("apic=", apic_set_verbosity);
1742 1727
1728static int __init lapic_insert_resource(void)
1729{
1730 if (!apic_phys)
1731 return -1;
1732
1733 /* Put local APIC into the resource map. */
1734 lapic_resource.start = apic_phys;
1735 lapic_resource.end = lapic_resource.start + PAGE_SIZE - 1;
1736 insert_resource(&iomem_resource, &lapic_resource);
1737
1738 return 0;
1739}
1740
1741/*
1742 * need call insert after e820_reserve_resources()
1743 * that is using request_resource
1744 */
1745late_initcall(lapic_insert_resource);