aboutsummaryrefslogtreecommitdiffstats
path: root/arch/i386/kernel/apic.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/i386/kernel/apic.c')
-rw-r--r--arch/i386/kernel/apic.c81
1 files changed, 64 insertions, 17 deletions
diff --git a/arch/i386/kernel/apic.c b/arch/i386/kernel/apic.c
index 5546ddebec33..8d81b7bf7ad2 100644
--- a/arch/i386/kernel/apic.c
+++ b/arch/i386/kernel/apic.c
@@ -803,6 +803,7 @@ no_apic:
803 803
804void __init init_apic_mappings(void) 804void __init init_apic_mappings(void)
805{ 805{
806 unsigned int orig_apicid;
806 unsigned long apic_phys; 807 unsigned long apic_phys;
807 808
808 /* 809 /*
@@ -824,8 +825,11 @@ void __init init_apic_mappings(void)
824 * Fetch the APIC ID of the BSP in case we have a 825 * Fetch the APIC ID of the BSP in case we have a
825 * default configuration (or the MP table is broken). 826 * default configuration (or the MP table is broken).
826 */ 827 */
827 if (boot_cpu_physical_apicid == -1U) 828 orig_apicid = boot_cpu_physical_apicid;
828 boot_cpu_physical_apicid = GET_APIC_ID(apic_read(APIC_ID)); 829 boot_cpu_physical_apicid = GET_APIC_ID(apic_read(APIC_ID));
830 if ((orig_apicid != -1U) && (orig_apicid != boot_cpu_physical_apicid))
831 printk(KERN_WARNING "Boot APIC ID in local APIC unexpected (%d vs %d)",
832 orig_apicid, boot_cpu_physical_apicid);
829 833
830#ifdef CONFIG_X86_IO_APIC 834#ifdef CONFIG_X86_IO_APIC
831 { 835 {
@@ -1046,9 +1050,11 @@ static unsigned int calibration_result;
1046 1050
1047void __init setup_boot_APIC_clock(void) 1051void __init setup_boot_APIC_clock(void)
1048{ 1052{
1053 unsigned long flags;
1049 apic_printk(APIC_VERBOSE, "Using local APIC timer interrupts.\n"); 1054 apic_printk(APIC_VERBOSE, "Using local APIC timer interrupts.\n");
1050 using_apic_timer = 1; 1055 using_apic_timer = 1;
1051 1056
1057 local_irq_save(flags);
1052 local_irq_disable(); 1058 local_irq_disable();
1053 1059
1054 calibration_result = calibrate_APIC_clock(); 1060 calibration_result = calibrate_APIC_clock();
@@ -1057,7 +1063,7 @@ void __init setup_boot_APIC_clock(void)
1057 */ 1063 */
1058 setup_APIC_timer(calibration_result); 1064 setup_APIC_timer(calibration_result);
1059 1065
1060 local_irq_enable(); 1066 local_irq_restore(flags);
1061} 1067}
1062 1068
1063void __devinit setup_secondary_APIC_clock(void) 1069void __devinit setup_secondary_APIC_clock(void)
@@ -1254,40 +1260,81 @@ fastcall void smp_error_interrupt(struct pt_regs *regs)
1254} 1260}
1255 1261
1256/* 1262/*
1257 * This initializes the IO-APIC and APIC hardware if this is 1263 * This initializes the IO-APIC and APIC hardware.
1258 * a UP kernel.
1259 */ 1264 */
1260int __init APIC_init_uniprocessor (void) 1265int __init APIC_init(void)
1261{ 1266{
1262 if (enable_local_apic < 0) 1267 if (enable_local_apic < 0) {
1263 clear_bit(X86_FEATURE_APIC, boot_cpu_data.x86_capability); 1268 printk(KERN_INFO "APIC disabled\n");
1269 return -1;
1270 }
1264 1271
1265 if (!smp_found_config && !cpu_has_apic) 1272 /* See if we have a SMP configuration or have forced enabled
1273 * the local apic.
1274 */
1275 if (!smp_found_config && !acpi_lapic && !cpu_has_apic) {
1276 enable_local_apic = -1;
1266 return -1; 1277 return -1;
1278 }
1267 1279
1268 /* 1280 /*
1269 * Complain if the BIOS pretends there is one. 1281 * Complain if the BIOS pretends there is an apic.
1282 * Then get out because we don't have an a local apic.
1270 */ 1283 */
1271 if (!cpu_has_apic && APIC_INTEGRATED(apic_version[boot_cpu_physical_apicid])) { 1284 if (!cpu_has_apic && APIC_INTEGRATED(apic_version[boot_cpu_physical_apicid])) {
1272 printk(KERN_ERR "BIOS bug, local APIC #%d not detected!...\n", 1285 printk(KERN_ERR "BIOS bug, local APIC #%d not detected!...\n",
1273 boot_cpu_physical_apicid); 1286 boot_cpu_physical_apicid);
1287 printk(KERN_ERR "... forcing use of dummy APIC emulation. (tell your hw vendor)\n");
1288 enable_local_apic = -1;
1274 return -1; 1289 return -1;
1275 } 1290 }
1276 1291
1277 verify_local_APIC(); 1292 verify_local_APIC();
1278 1293
1294 /*
1295 * Should not be necessary because the MP table should list the boot
1296 * CPU too, but we do it for the sake of robustness anyway.
1297 * Makes no sense to do this check in clustered apic mode, so skip it
1298 */
1299 if (!check_phys_apicid_present(boot_cpu_physical_apicid)) {
1300 printk("weird, boot CPU (#%d) not listed by the BIOS.\n",
1301 boot_cpu_physical_apicid);
1302 physid_set(hard_smp_processor_id(), phys_cpu_present_map);
1303 }
1304
1305 /*
1306 * Switch from PIC to APIC mode.
1307 */
1279 connect_bsp_APIC(); 1308 connect_bsp_APIC();
1309 setup_local_APIC();
1280 1310
1281 phys_cpu_present_map = physid_mask_of_physid(boot_cpu_physical_apicid); 1311#ifdef CONFIG_X86_IO_APIC
1312 /*
1313 * Now start the IO-APICs
1314 */
1315 if (smp_found_config && !skip_ioapic_setup && nr_ioapics)
1316 setup_IO_APIC();
1317#endif
1318 return 0;
1319}
1282 1320
1283 setup_local_APIC(); 1321void __init APIC_late_time_init(void)
1322{
1323 /* Improve our loops per jiffy estimate */
1324 loops_per_jiffy = ((1000 + HZ - 1)/HZ)*cpu_khz;
1325 boot_cpu_data.loops_per_jiffy = loops_per_jiffy;
1326 cpu_data[0].loops_per_jiffy = loops_per_jiffy;
1327
1328 /* setup_apic_nmi_watchdog doesn't work properly before cpu_khz is
1329 * initialized. So redo it here to ensure the boot cpu is setup
1330 * properly.
1331 */
1332 if (nmi_watchdog == NMI_LOCAL_APIC)
1333 setup_apic_nmi_watchdog();
1284 1334
1285#ifdef CONFIG_X86_IO_APIC 1335#ifdef CONFIG_X86_IO_APIC
1286 if (smp_found_config) 1336 if (smp_found_config && !skip_ioapic_setup && nr_ioapics)
1287 if (!skip_ioapic_setup && nr_ioapics) 1337 IO_APIC_late_time_init();
1288 setup_IO_APIC();
1289#endif 1338#endif
1290 setup_boot_APIC_clock(); 1339 setup_boot_APIC_clock();
1291
1292 return 0;
1293} 1340}