aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86/kernel/apic/apic.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/x86/kernel/apic/apic.c')
-rw-r--r--arch/x86/kernel/apic/apic.c113
1 files changed, 61 insertions, 52 deletions
diff --git a/arch/x86/kernel/apic/apic.c b/arch/x86/kernel/apic/apic.c
index 0a1c2830ec66..a34601f52987 100644
--- a/arch/x86/kernel/apic/apic.c
+++ b/arch/x86/kernel/apic/apic.c
@@ -36,6 +36,7 @@
36#include <linux/mm.h> 36#include <linux/mm.h>
37 37
38#include <asm/perf_counter.h> 38#include <asm/perf_counter.h>
39#include <asm/x86_init.h>
39#include <asm/pgalloc.h> 40#include <asm/pgalloc.h>
40#include <asm/atomic.h> 41#include <asm/atomic.h>
41#include <asm/mpspec.h> 42#include <asm/mpspec.h>
@@ -49,6 +50,7 @@
49#include <asm/mtrr.h> 50#include <asm/mtrr.h>
50#include <asm/smp.h> 51#include <asm/smp.h>
51#include <asm/mce.h> 52#include <asm/mce.h>
53#include <asm/kvm_para.h>
52 54
53unsigned int num_processors; 55unsigned int num_processors;
54 56
@@ -1361,52 +1363,80 @@ void enable_x2apic(void)
1361} 1363}
1362#endif /* CONFIG_X86_X2APIC */ 1364#endif /* CONFIG_X86_X2APIC */
1363 1365
1364void __init enable_IR_x2apic(void) 1366int __init enable_IR(void)
1365{ 1367{
1366#ifdef CONFIG_INTR_REMAP 1368#ifdef CONFIG_INTR_REMAP
1367 int ret;
1368 unsigned long flags;
1369 struct IO_APIC_route_entry **ioapic_entries = NULL;
1370
1371 ret = dmar_table_init();
1372 if (ret) {
1373 pr_debug("dmar_table_init() failed with %d:\n", ret);
1374 goto ir_failed;
1375 }
1376
1377 if (!intr_remapping_supported()) { 1369 if (!intr_remapping_supported()) {
1378 pr_debug("intr-remapping not supported\n"); 1370 pr_debug("intr-remapping not supported\n");
1379 goto ir_failed; 1371 return 0;
1380 } 1372 }
1381 1373
1382
1383 if (!x2apic_preenabled && skip_ioapic_setup) { 1374 if (!x2apic_preenabled && skip_ioapic_setup) {
1384 pr_info("Skipped enabling intr-remap because of skipping " 1375 pr_info("Skipped enabling intr-remap because of skipping "
1385 "io-apic setup\n"); 1376 "io-apic setup\n");
1386 return; 1377 return 0;
1387 } 1378 }
1388 1379
1380 if (enable_intr_remapping(x2apic_supported()))
1381 return 0;
1382
1383 pr_info("Enabled Interrupt-remapping\n");
1384
1385 return 1;
1386
1387#endif
1388 return 0;
1389}
1390
1391void __init enable_IR_x2apic(void)
1392{
1393 unsigned long flags;
1394 struct IO_APIC_route_entry **ioapic_entries = NULL;
1395 int ret, x2apic_enabled = 0;
1396 int dmar_table_init_ret = 0;
1397
1398#ifdef CONFIG_INTR_REMAP
1399 dmar_table_init_ret = dmar_table_init();
1400 if (dmar_table_init_ret)
1401 pr_debug("dmar_table_init() failed with %d:\n",
1402 dmar_table_init_ret);
1403#endif
1404
1389 ioapic_entries = alloc_ioapic_entries(); 1405 ioapic_entries = alloc_ioapic_entries();
1390 if (!ioapic_entries) { 1406 if (!ioapic_entries) {
1391 pr_info("Allocate ioapic_entries failed: %d\n", ret); 1407 pr_err("Allocate ioapic_entries failed\n");
1392 goto end; 1408 goto out;
1393 } 1409 }
1394 1410
1395 ret = save_IO_APIC_setup(ioapic_entries); 1411 ret = save_IO_APIC_setup(ioapic_entries);
1396 if (ret) { 1412 if (ret) {
1397 pr_info("Saving IO-APIC state failed: %d\n", ret); 1413 pr_info("Saving IO-APIC state failed: %d\n", ret);
1398 goto end; 1414 goto out;
1399 } 1415 }
1400 1416
1401 local_irq_save(flags); 1417 local_irq_save(flags);
1402 mask_IO_APIC_setup(ioapic_entries);
1403 mask_8259A(); 1418 mask_8259A();
1419 mask_IO_APIC_setup(ioapic_entries);
1404 1420
1405 ret = enable_intr_remapping(x2apic_supported()); 1421 if (dmar_table_init_ret)
1406 if (ret) 1422 ret = 0;
1407 goto end_restore; 1423 else
1424 ret = enable_IR();
1408 1425
1409 pr_info("Enabled Interrupt-remapping\n"); 1426 if (!ret) {
1427 /* IR is required if there is APIC ID > 255 even when running
1428 * under KVM
1429 */
1430 if (max_physical_apicid > 255 || !kvm_para_available())
1431 goto nox2apic;
1432 /*
1433 * without IR all CPUs can be addressed by IOAPIC/MSI
1434 * only in physical mode
1435 */
1436 x2apic_force_phys();
1437 }
1438
1439 x2apic_enabled = 1;
1410 1440
1411 if (x2apic_supported() && !x2apic_mode) { 1441 if (x2apic_supported() && !x2apic_mode) {
1412 x2apic_mode = 1; 1442 x2apic_mode = 1;
@@ -1414,41 +1444,25 @@ void __init enable_IR_x2apic(void)
1414 pr_info("Enabled x2apic\n"); 1444 pr_info("Enabled x2apic\n");
1415 } 1445 }
1416 1446
1417end_restore: 1447nox2apic:
1418 if (ret) 1448 if (!ret) /* IR enabling failed */
1419 /*
1420 * IR enabling failed
1421 */
1422 restore_IO_APIC_setup(ioapic_entries); 1449 restore_IO_APIC_setup(ioapic_entries);
1423
1424 unmask_8259A(); 1450 unmask_8259A();
1425 local_irq_restore(flags); 1451 local_irq_restore(flags);
1426 1452
1427end: 1453out:
1428 if (ioapic_entries) 1454 if (ioapic_entries)
1429 free_ioapic_entries(ioapic_entries); 1455 free_ioapic_entries(ioapic_entries);
1430 1456
1431 if (!ret) 1457 if (x2apic_enabled)
1432 return; 1458 return;
1433 1459
1434ir_failed:
1435 if (x2apic_preenabled) 1460 if (x2apic_preenabled)
1436 panic("x2apic enabled by bios. But IR enabling failed"); 1461 panic("x2apic: enabled by BIOS but kernel init failed.");
1437 else if (cpu_has_x2apic) 1462 else if (cpu_has_x2apic)
1438 pr_info("Not enabling x2apic,Intr-remapping\n"); 1463 pr_info("Not enabling x2apic, Intr-remapping init failed.\n");
1439#else
1440 if (!cpu_has_x2apic)
1441 return;
1442
1443 if (x2apic_preenabled)
1444 panic("x2apic enabled prior OS handover,"
1445 " enable CONFIG_X86_X2APIC, CONFIG_INTR_REMAP");
1446#endif
1447
1448 return;
1449} 1464}
1450 1465
1451
1452#ifdef CONFIG_X86_64 1466#ifdef CONFIG_X86_64
1453/* 1467/*
1454 * Detect and enable local APICs on non-SMP boards. 1468 * Detect and enable local APICs on non-SMP boards.
@@ -1549,8 +1563,6 @@ no_apic:
1549#ifdef CONFIG_X86_64 1563#ifdef CONFIG_X86_64
1550void __init early_init_lapic_mapping(void) 1564void __init early_init_lapic_mapping(void)
1551{ 1565{
1552 unsigned long phys_addr;
1553
1554 /* 1566 /*
1555 * If no local APIC can be found then go out 1567 * If no local APIC can be found then go out
1556 * : it means there is no mpatable and MADT 1568 * : it means there is no mpatable and MADT
@@ -1558,11 +1570,9 @@ void __init early_init_lapic_mapping(void)
1558 if (!smp_found_config) 1570 if (!smp_found_config)
1559 return; 1571 return;
1560 1572
1561 phys_addr = mp_lapic_addr; 1573 set_fixmap_nocache(FIX_APIC_BASE, mp_lapic_addr);
1562
1563 set_fixmap_nocache(FIX_APIC_BASE, phys_addr);
1564 apic_printk(APIC_VERBOSE, "mapped APIC to %16lx (%16lx)\n", 1574 apic_printk(APIC_VERBOSE, "mapped APIC to %16lx (%16lx)\n",
1565 APIC_BASE, phys_addr); 1575 APIC_BASE, mp_lapic_addr);
1566 1576
1567 /* 1577 /*
1568 * Fetch the APIC ID of the BSP in case we have a 1578 * Fetch the APIC ID of the BSP in case we have a
@@ -1651,7 +1661,6 @@ int __init APIC_init_uniprocessor(void)
1651 APIC_INTEGRATED(apic_version[boot_cpu_physical_apicid])) { 1661 APIC_INTEGRATED(apic_version[boot_cpu_physical_apicid])) {
1652 pr_err("BIOS bug, local APIC 0x%x not detected!...\n", 1662 pr_err("BIOS bug, local APIC 0x%x not detected!...\n",
1653 boot_cpu_physical_apicid); 1663 boot_cpu_physical_apicid);
1654 clear_cpu_cap(&boot_cpu_data, X86_FEATURE_APIC);
1655 return -1; 1664 return -1;
1656 } 1665 }
1657#endif 1666#endif
@@ -1701,7 +1710,7 @@ int __init APIC_init_uniprocessor(void)
1701 localise_nmi_watchdog(); 1710 localise_nmi_watchdog();
1702#endif 1711#endif
1703 1712
1704 setup_boot_clock(); 1713 x86_init.timers.setup_percpu_clockev();
1705#ifdef CONFIG_X86_64 1714#ifdef CONFIG_X86_64
1706 check_nmi_watchdog(); 1715 check_nmi_watchdog();
1707#endif 1716#endif