|
@@ -146,7 +146,8 @@ __setup("apicpmtimer", setup_apicpmtimer);
|
|
|
int x2apic_mode;
|
|
|
#ifdef CONFIG_X86_X2APIC
|
|
|
/* x2apic enabled before OS handover */
|
|
|
-static int x2apic_preenabled;
|
|
|
+int x2apic_preenabled;
|
|
|
+static int x2apic_disabled;
|
|
|
static __init int setup_nox2apic(char *str)
|
|
|
{
|
|
|
if (x2apic_enabled()) {
|
|
@@ -1432,6 +1433,40 @@ void __init bsp_end_local_APIC_setup(void)
|
|
|
}
|
|
|
|
|
|
#ifdef CONFIG_X86_X2APIC
|
|
|
+/*
|
|
|
+ * Need to disable xapic and x2apic at the same time and then enable xapic mode
|
|
|
+ */
|
|
|
+static inline void __disable_x2apic(u64 msr)
|
|
|
+{
|
|
|
+ wrmsrl(MSR_IA32_APICBASE,
|
|
|
+ msr & ~(X2APIC_ENABLE | XAPIC_ENABLE));
|
|
|
+ wrmsrl(MSR_IA32_APICBASE, msr & ~X2APIC_ENABLE);
|
|
|
+}
|
|
|
+
|
|
|
+static void disable_x2apic(void)
|
|
|
+{
|
|
|
+ u64 msr;
|
|
|
+
|
|
|
+ if (!cpu_has_x2apic)
|
|
|
+ return;
|
|
|
+
|
|
|
+ rdmsrl(MSR_IA32_APICBASE, msr);
|
|
|
+ if (msr & X2APIC_ENABLE) {
|
|
|
+ u32 x2apic_id = read_apic_id();
|
|
|
+
|
|
|
+ if (x2apic_id >= 255)
|
|
|
+ panic("Cannot disable x2apic, id: %08x\n", x2apic_id);
|
|
|
+
|
|
|
+ pr_info("Disabling x2apic\n");
|
|
|
+ __disable_x2apic(msr);
|
|
|
+
|
|
|
+ x2apic_disabled = 1;
|
|
|
+ x2apic_mode = 0;
|
|
|
+
|
|
|
+ register_lapic_address(mp_lapic_addr);
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
void check_x2apic(void)
|
|
|
{
|
|
|
if (x2apic_enabled()) {
|
|
@@ -1442,15 +1477,20 @@ void check_x2apic(void)
|
|
|
|
|
|
void enable_x2apic(void)
|
|
|
{
|
|
|
- int msr, msr2;
|
|
|
+ u64 msr;
|
|
|
+
|
|
|
+ rdmsrl(MSR_IA32_APICBASE, msr);
|
|
|
+ if (x2apic_disabled) {
|
|
|
+ __disable_x2apic(msr);
|
|
|
+ return;
|
|
|
+ }
|
|
|
|
|
|
if (!x2apic_mode)
|
|
|
return;
|
|
|
|
|
|
- rdmsr(MSR_IA32_APICBASE, msr, msr2);
|
|
|
if (!(msr & X2APIC_ENABLE)) {
|
|
|
printk_once(KERN_INFO "Enabling x2apic\n");
|
|
|
- wrmsr(MSR_IA32_APICBASE, msr | X2APIC_ENABLE, msr2);
|
|
|
+ wrmsrl(MSR_IA32_APICBASE, msr | X2APIC_ENABLE);
|
|
|
}
|
|
|
}
|
|
|
#endif /* CONFIG_X86_X2APIC */
|
|
@@ -1487,7 +1527,7 @@ void __init enable_IR_x2apic(void)
|
|
|
ret = save_ioapic_entries();
|
|
|
if (ret) {
|
|
|
pr_info("Saving IO-APIC state failed: %d\n", ret);
|
|
|
- goto out;
|
|
|
+ return;
|
|
|
}
|
|
|
|
|
|
local_irq_save(flags);
|
|
@@ -1499,13 +1539,19 @@ void __init enable_IR_x2apic(void)
|
|
|
else
|
|
|
ret = enable_IR();
|
|
|
|
|
|
+ if (!x2apic_supported())
|
|
|
+ goto nox2apic;
|
|
|
+
|
|
|
if (ret < 0) {
|
|
|
/* IR is required if there is APIC ID > 255 even when running
|
|
|
* under KVM
|
|
|
*/
|
|
|
if (max_physical_apicid > 255 ||
|
|
|
- !hypervisor_x2apic_available())
|
|
|
+ !hypervisor_x2apic_available()) {
|
|
|
+ if (x2apic_preenabled)
|
|
|
+ disable_x2apic();
|
|
|
goto nox2apic;
|
|
|
+ }
|
|
|
/*
|
|
|
* without IR all CPUs can be addressed by IOAPIC/MSI
|
|
|
* only in physical mode
|
|
@@ -1513,8 +1559,10 @@ void __init enable_IR_x2apic(void)
|
|
|
x2apic_force_phys();
|
|
|
}
|
|
|
|
|
|
- if (ret == IRQ_REMAP_XAPIC_MODE)
|
|
|
+ if (ret == IRQ_REMAP_XAPIC_MODE) {
|
|
|
+ pr_info("x2apic not enabled, IRQ remapping is in xapic mode\n");
|
|
|
goto nox2apic;
|
|
|
+ }
|
|
|
|
|
|
x2apic_enabled = 1;
|
|
|
|
|
@@ -1529,17 +1577,6 @@ nox2apic:
|
|
|
restore_ioapic_entries();
|
|
|
legacy_pic->restore_mask();
|
|
|
local_irq_restore(flags);
|
|
|
-
|
|
|
-out:
|
|
|
- if (x2apic_enabled || !x2apic_supported())
|
|
|
- return;
|
|
|
-
|
|
|
- if (x2apic_preenabled)
|
|
|
- panic("x2apic: enabled by BIOS but kernel init failed.");
|
|
|
- else if (ret == IRQ_REMAP_XAPIC_MODE)
|
|
|
- pr_info("x2apic not enabled, IRQ remapping is in xapic mode\n");
|
|
|
- else if (ret < 0)
|
|
|
- pr_info("x2apic not enabled, IRQ remapping init failed\n");
|
|
|
}
|
|
|
|
|
|
#ifdef CONFIG_X86_64
|