aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86/kernel/apic/apic.c
diff options
context:
space:
mode:
authorSuresh Siddha <suresh.b.siddha@intel.com>2011-08-23 20:05:18 -0400
committerIngo Molnar <mingo@elte.hu>2011-09-21 04:21:50 -0400
commit41750d31fc9599fd81763e685a6b7b42d298c4f8 (patch)
tree6cacc746aa159c8bd08f151270f0bffe126caa9d /arch/x86/kernel/apic/apic.c
parent9d037a777695993ec7437e5f451647dea7919d4c (diff)
x86, x2apic: Enable the bios request for x2apic optout
On the platforms which are x2apic and interrupt-remapping capable, Linux kernel is enabling x2apic even if the BIOS doesn't. This is to take advantage of the features that x2apic brings in. Some of the OEM platforms are running into issues because of this, as their bios is not x2apic aware. For example, this was resulting in interrupt migration issues on one of the platforms. Also if the BIOS SMI handling uses APIC interface to send SMI's, then the BIOS need to be aware of x2apic mode that OS has enabled. On some of these platforms, BIOS doesn't have a HW mechanism to turnoff the x2apic feature to prevent OS from enabling it. To resolve this mess, recent changes to the VT-d2 specification: http://download.intel.com/technology/computing/vptech/Intel(r)_VT_for_Direct_IO.pdf includes a mechanism that provides BIOS a way to request system software to opt out of enabling x2apic mode. Look at the x2apic optout flag in the DMAR tables before enabling the x2apic mode in the platform. Also print a warning that we have disabled x2apic based on the BIOS request. Kernel boot parameter "intremap=no_x2apic_optout" can be used to override the BIOS x2apic optout request. Signed-off-by: Youquan Song <youquan.song@intel.com> Signed-off-by: Suresh Siddha <suresh.b.siddha@intel.com> Cc: yinghai@kernel.org Cc: joerg.roedel@amd.com Cc: tony.luck@intel.com Cc: dwmw2@infradead.org Link: http://lkml.kernel.org/r/20110824001456.171766616@sbsiddha-desk.sc.intel.com Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'arch/x86/kernel/apic/apic.c')
-rw-r--r--arch/x86/kernel/apic/apic.c31
1 files changed, 15 insertions, 16 deletions
diff --git a/arch/x86/kernel/apic/apic.c b/arch/x86/kernel/apic/apic.c
index 52fa56399a50..6b9874a5c7af 100644
--- a/arch/x86/kernel/apic/apic.c
+++ b/arch/x86/kernel/apic/apic.c
@@ -1440,24 +1440,18 @@ int __init enable_IR(void)
1440#ifdef CONFIG_INTR_REMAP 1440#ifdef CONFIG_INTR_REMAP
1441 if (!intr_remapping_supported()) { 1441 if (!intr_remapping_supported()) {
1442 pr_debug("intr-remapping not supported\n"); 1442 pr_debug("intr-remapping not supported\n");
1443 return 0; 1443 return -1;
1444 } 1444 }
1445 1445
1446 if (!x2apic_preenabled && skip_ioapic_setup) { 1446 if (!x2apic_preenabled && skip_ioapic_setup) {
1447 pr_info("Skipped enabling intr-remap because of skipping " 1447 pr_info("Skipped enabling intr-remap because of skipping "
1448 "io-apic setup\n"); 1448 "io-apic setup\n");
1449 return 0; 1449 return -1;
1450 } 1450 }
1451 1451
1452 if (enable_intr_remapping(x2apic_supported())) 1452 return enable_intr_remapping();
1453 return 0;
1454
1455 pr_info("Enabled Interrupt-remapping\n");
1456
1457 return 1;
1458
1459#endif 1453#endif
1460 return 0; 1454 return -1;
1461} 1455}
1462 1456
1463void __init enable_IR_x2apic(void) 1457void __init enable_IR_x2apic(void)
@@ -1481,11 +1475,11 @@ void __init enable_IR_x2apic(void)
1481 mask_ioapic_entries(); 1475 mask_ioapic_entries();
1482 1476
1483 if (dmar_table_init_ret) 1477 if (dmar_table_init_ret)
1484 ret = 0; 1478 ret = -1;
1485 else 1479 else
1486 ret = enable_IR(); 1480 ret = enable_IR();
1487 1481
1488 if (!ret) { 1482 if (ret < 0) {
1489 /* IR is required if there is APIC ID > 255 even when running 1483 /* IR is required if there is APIC ID > 255 even when running
1490 * under KVM 1484 * under KVM
1491 */ 1485 */
@@ -1499,6 +1493,9 @@ void __init enable_IR_x2apic(void)
1499 x2apic_force_phys(); 1493 x2apic_force_phys();
1500 } 1494 }
1501 1495
1496 if (ret == IRQ_REMAP_XAPIC_MODE)
1497 goto nox2apic;
1498
1502 x2apic_enabled = 1; 1499 x2apic_enabled = 1;
1503 1500
1504 if (x2apic_supported() && !x2apic_mode) { 1501 if (x2apic_supported() && !x2apic_mode) {
@@ -1508,19 +1505,21 @@ void __init enable_IR_x2apic(void)
1508 } 1505 }
1509 1506
1510nox2apic: 1507nox2apic:
1511 if (!ret) /* IR enabling failed */ 1508 if (ret < 0) /* IR enabling failed */
1512 restore_ioapic_entries(); 1509 restore_ioapic_entries();
1513 legacy_pic->restore_mask(); 1510 legacy_pic->restore_mask();
1514 local_irq_restore(flags); 1511 local_irq_restore(flags);
1515 1512
1516out: 1513out:
1517 if (x2apic_enabled) 1514 if (x2apic_enabled || !x2apic_supported())
1518 return; 1515 return;
1519 1516
1520 if (x2apic_preenabled) 1517 if (x2apic_preenabled)
1521 panic("x2apic: enabled by BIOS but kernel init failed."); 1518 panic("x2apic: enabled by BIOS but kernel init failed.");
1522 else if (cpu_has_x2apic) 1519 else if (ret == IRQ_REMAP_XAPIC_MODE)
1523 pr_info("Not enabling x2apic, Intr-remapping init failed.\n"); 1520 pr_info("x2apic not enabled, IRQ remapping is in xapic mode\n");
1521 else if (ret < 0)
1522 pr_info("x2apic not enabled, IRQ remapping init failed\n");
1524} 1523}
1525 1524
1526#ifdef CONFIG_X86_64 1525#ifdef CONFIG_X86_64