aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorYinghai Lu <yinghai@kernel.org>2011-12-21 20:45:17 -0500
committerH. Peter Anvin <hpa@linux.intel.com>2011-12-23 14:01:01 -0500
commitfb209bd891645bb87b9618b724f0b4928e0df3de (patch)
tree3b59766238dfedbe9f2164048008f4bb2c18a54e
parenta35fd28256e7736cc84af8931a16224f0bfaaf6c (diff)
x86, x2apic: Fallback to xapic when BIOS doesn't setup interrupt-remapping
On some of the recent Intel SNB platforms, by default bios is pre-enabling x2apic mode in the cpu with out setting up interrupt-remapping. This case was resulting in the kernel to panic as the cpu is already in x2apic mode but the OS was not able to enable interrupt-remapping (which is a pre-req for using x2apic capability). On these platforms all the apic-ids are < 255 and the kernel can fallback to xapic mode if the bios has not enabled interrupt-remapping (which is mostly the case if the bios has not exported interrupt-remapping tables to the OS). Reported-by: Berck E. Nash <flyboy@gmail.com> Signed-off-by: Yinghai Lu <yinghai@kernel.org> Link: http://lkml.kernel.org/r/20111222014632.600418637@sbsiddha-desk.sc.intel.com Signed-off-by: Suresh Siddha <suresh.b.siddha@intel.com> Signed-off-by: H. Peter Anvin <hpa@linux.intel.com>
-rw-r--r--arch/x86/include/asm/apic.h4
-rw-r--r--arch/x86/include/asm/apicdef.h1
-rw-r--r--arch/x86/kernel/apic/apic.c73
-rw-r--r--arch/x86/kernel/apic/io_apic.c4
4 files changed, 64 insertions, 18 deletions
diff --git a/arch/x86/include/asm/apic.h b/arch/x86/include/asm/apic.h
index a0f541a30944..a12d57193fef 100644
--- a/arch/x86/include/asm/apic.h
+++ b/arch/x86/include/asm/apic.h
@@ -176,6 +176,7 @@ static inline u64 native_x2apic_icr_read(void)
176} 176}
177 177
178extern int x2apic_phys; 178extern int x2apic_phys;
179extern int x2apic_preenabled;
179extern void check_x2apic(void); 180extern void check_x2apic(void);
180extern void enable_x2apic(void); 181extern void enable_x2apic(void);
181extern void x2apic_icr_write(u32 low, u32 id); 182extern void x2apic_icr_write(u32 low, u32 id);
@@ -198,6 +199,9 @@ static inline void x2apic_force_phys(void)
198 x2apic_phys = 1; 199 x2apic_phys = 1;
199} 200}
200#else 201#else
202static inline void disable_x2apic(void)
203{
204}
201static inline void check_x2apic(void) 205static inline void check_x2apic(void)
202{ 206{
203} 207}
diff --git a/arch/x86/include/asm/apicdef.h b/arch/x86/include/asm/apicdef.h
index 3925d8007864..134bba00df09 100644
--- a/arch/x86/include/asm/apicdef.h
+++ b/arch/x86/include/asm/apicdef.h
@@ -144,6 +144,7 @@
144 144
145#define APIC_BASE (fix_to_virt(FIX_APIC_BASE)) 145#define APIC_BASE (fix_to_virt(FIX_APIC_BASE))
146#define APIC_BASE_MSR 0x800 146#define APIC_BASE_MSR 0x800
147#define XAPIC_ENABLE (1UL << 11)
147#define X2APIC_ENABLE (1UL << 10) 148#define X2APIC_ENABLE (1UL << 10)
148 149
149#ifdef CONFIG_X86_32 150#ifdef CONFIG_X86_32
diff --git a/arch/x86/kernel/apic/apic.c b/arch/x86/kernel/apic/apic.c
index 07832363b729..2c07aebbb6f2 100644
--- a/arch/x86/kernel/apic/apic.c
+++ b/arch/x86/kernel/apic/apic.c
@@ -146,7 +146,8 @@ __setup("apicpmtimer", setup_apicpmtimer);
146int x2apic_mode; 146int x2apic_mode;
147#ifdef CONFIG_X86_X2APIC 147#ifdef CONFIG_X86_X2APIC
148/* x2apic enabled before OS handover */ 148/* x2apic enabled before OS handover */
149static int x2apic_preenabled; 149int x2apic_preenabled;
150static int x2apic_disabled;
150static __init int setup_nox2apic(char *str) 151static __init int setup_nox2apic(char *str)
151{ 152{
152 if (x2apic_enabled()) { 153 if (x2apic_enabled()) {
@@ -1432,6 +1433,40 @@ void __init bsp_end_local_APIC_setup(void)
1432} 1433}
1433 1434
1434#ifdef CONFIG_X86_X2APIC 1435#ifdef CONFIG_X86_X2APIC
1436/*
1437 * Need to disable xapic and x2apic at the same time and then enable xapic mode
1438 */
1439static inline void __disable_x2apic(u64 msr)
1440{
1441 wrmsrl(MSR_IA32_APICBASE,
1442 msr & ~(X2APIC_ENABLE | XAPIC_ENABLE));
1443 wrmsrl(MSR_IA32_APICBASE, msr & ~X2APIC_ENABLE);
1444}
1445
1446static void disable_x2apic(void)
1447{
1448 u64 msr;
1449
1450 if (!cpu_has_x2apic)
1451 return;
1452
1453 rdmsrl(MSR_IA32_APICBASE, msr);
1454 if (msr & X2APIC_ENABLE) {
1455 u32 x2apic_id = read_apic_id();
1456
1457 if (x2apic_id >= 255)
1458 panic("Cannot disable x2apic, id: %08x\n", x2apic_id);
1459
1460 pr_info("Disabling x2apic\n");
1461 __disable_x2apic(msr);
1462
1463 x2apic_disabled = 1;
1464 x2apic_mode = 0;
1465
1466 register_lapic_address(mp_lapic_addr);
1467 }
1468}
1469
1435void check_x2apic(void) 1470void check_x2apic(void)
1436{ 1471{
1437 if (x2apic_enabled()) { 1472 if (x2apic_enabled()) {
@@ -1442,15 +1477,20 @@ void check_x2apic(void)
1442 1477
1443void enable_x2apic(void) 1478void enable_x2apic(void)
1444{ 1479{
1445 int msr, msr2; 1480 u64 msr;
1481
1482 rdmsrl(MSR_IA32_APICBASE, msr);
1483 if (x2apic_disabled) {
1484 __disable_x2apic(msr);
1485 return;
1486 }
1446 1487
1447 if (!x2apic_mode) 1488 if (!x2apic_mode)
1448 return; 1489 return;
1449 1490
1450 rdmsr(MSR_IA32_APICBASE, msr, msr2);
1451 if (!(msr & X2APIC_ENABLE)) { 1491 if (!(msr & X2APIC_ENABLE)) {
1452 printk_once(KERN_INFO "Enabling x2apic\n"); 1492 printk_once(KERN_INFO "Enabling x2apic\n");
1453 wrmsr(MSR_IA32_APICBASE, msr | X2APIC_ENABLE, msr2); 1493 wrmsrl(MSR_IA32_APICBASE, msr | X2APIC_ENABLE);
1454 } 1494 }
1455} 1495}
1456#endif /* CONFIG_X86_X2APIC */ 1496#endif /* CONFIG_X86_X2APIC */
@@ -1487,7 +1527,7 @@ void __init enable_IR_x2apic(void)
1487 ret = save_ioapic_entries(); 1527 ret = save_ioapic_entries();
1488 if (ret) { 1528 if (ret) {
1489 pr_info("Saving IO-APIC state failed: %d\n", ret); 1529 pr_info("Saving IO-APIC state failed: %d\n", ret);
1490 goto out; 1530 return;
1491 } 1531 }
1492 1532
1493 local_irq_save(flags); 1533 local_irq_save(flags);
@@ -1499,13 +1539,19 @@ void __init enable_IR_x2apic(void)
1499 else 1539 else
1500 ret = enable_IR(); 1540 ret = enable_IR();
1501 1541
1542 if (!x2apic_supported())
1543 goto nox2apic;
1544
1502 if (ret < 0) { 1545 if (ret < 0) {
1503 /* IR is required if there is APIC ID > 255 even when running 1546 /* IR is required if there is APIC ID > 255 even when running
1504 * under KVM 1547 * under KVM
1505 */ 1548 */
1506 if (max_physical_apicid > 255 || 1549 if (max_physical_apicid > 255 ||
1507 !hypervisor_x2apic_available()) 1550 !hypervisor_x2apic_available()) {
1551 if (x2apic_preenabled)
1552 disable_x2apic();
1508 goto nox2apic; 1553 goto nox2apic;
1554 }
1509 /* 1555 /*
1510 * without IR all CPUs can be addressed by IOAPIC/MSI 1556 * without IR all CPUs can be addressed by IOAPIC/MSI
1511 * only in physical mode 1557 * only in physical mode
@@ -1513,8 +1559,10 @@ void __init enable_IR_x2apic(void)
1513 x2apic_force_phys(); 1559 x2apic_force_phys();
1514 } 1560 }
1515 1561
1516 if (ret == IRQ_REMAP_XAPIC_MODE) 1562 if (ret == IRQ_REMAP_XAPIC_MODE) {
1563 pr_info("x2apic not enabled, IRQ remapping is in xapic mode\n");
1517 goto nox2apic; 1564 goto nox2apic;
1565 }
1518 1566
1519 x2apic_enabled = 1; 1567 x2apic_enabled = 1;
1520 1568
@@ -1529,17 +1577,6 @@ nox2apic:
1529 restore_ioapic_entries(); 1577 restore_ioapic_entries();
1530 legacy_pic->restore_mask(); 1578 legacy_pic->restore_mask();
1531 local_irq_restore(flags); 1579 local_irq_restore(flags);
1532
1533out:
1534 if (x2apic_enabled || !x2apic_supported())
1535 return;
1536
1537 if (x2apic_preenabled)
1538 panic("x2apic: enabled by BIOS but kernel init failed.");
1539 else if (ret == IRQ_REMAP_XAPIC_MODE)
1540 pr_info("x2apic not enabled, IRQ remapping is in xapic mode\n");
1541 else if (ret < 0)
1542 pr_info("x2apic not enabled, IRQ remapping init failed\n");
1543} 1580}
1544 1581
1545#ifdef CONFIG_X86_64 1582#ifdef CONFIG_X86_64
diff --git a/arch/x86/kernel/apic/io_apic.c b/arch/x86/kernel/apic/io_apic.c
index 6d939d7847e2..45b461fdb344 100644
--- a/arch/x86/kernel/apic/io_apic.c
+++ b/arch/x86/kernel/apic/io_apic.c
@@ -2948,6 +2948,10 @@ static inline void __init check_timer(void)
2948 } 2948 }
2949 local_irq_disable(); 2949 local_irq_disable();
2950 apic_printk(APIC_QUIET, KERN_INFO "..... failed :(.\n"); 2950 apic_printk(APIC_QUIET, KERN_INFO "..... failed :(.\n");
2951 if (x2apic_preenabled)
2952 apic_printk(APIC_QUIET, KERN_INFO
2953 "Perhaps problem with the pre-enabled x2apic mode\n"
2954 "Try booting with x2apic and interrupt-remapping disabled in the bios.\n");
2951 panic("IO-APIC + timer doesn't work! Boot with apic=debug and send a " 2955 panic("IO-APIC + timer doesn't work! Boot with apic=debug and send a "
2952 "report. Then try booting with the 'noapic' option.\n"); 2956 "report. Then try booting with the 'noapic' option.\n");
2953out: 2957out: