|
|
ff41e30 |
From a57e456a7b28431b55e407e5ab78ebd5b378d19e Mon Sep 17 00:00:00 2001
|
|
|
ff41e30 |
From: Thomas Gleixner <tglx@linutronix.de>
|
|
|
ff41e30 |
Date: Sat, 22 Aug 2015 16:41:17 +0200
|
|
|
ff41e30 |
Subject: [PATCH] x86/apic: Fix fallout from x2apic cleanup
|
|
|
ff41e30 |
|
|
|
ff41e30 |
In the recent x2apic cleanup I got two things really wrong:
|
|
|
ff41e30 |
1) The safety check in __disable_x2apic which allows the function to
|
|
|
ff41e30 |
be called unconditionally is backwards. The check is there to
|
|
|
ff41e30 |
prevent access to the apic MSR in case that the machine has no
|
|
|
ff41e30 |
apic. Though right now it returns if the machine has an apic and
|
|
|
ff41e30 |
therefor the disabling of x2apic is never invoked.
|
|
|
ff41e30 |
|
|
|
ff41e30 |
2) x2apic_disable() sets x2apic_mode to 0 after registering the local
|
|
|
ff41e30 |
apic. That's wrong, because register_lapic_address() checks x2apic
|
|
|
ff41e30 |
mode and therefor takes the wrong code path.
|
|
|
ff41e30 |
|
|
|
ff41e30 |
This results in boot failures on machines with x2apic preenabled by
|
|
|
ff41e30 |
BIOS and can also lead to an fatal MSR access on machines without
|
|
|
ff41e30 |
apic.
|
|
|
ff41e30 |
|
|
|
ff41e30 |
The solutions are simple:
|
|
|
ff41e30 |
1) Correct the sanity check for apic availability
|
|
|
ff41e30 |
2) Clear x2apic_mode _before_ calling register_lapic_address()
|
|
|
ff41e30 |
|
|
|
ff41e30 |
Fixes: 659006bf3ae3 'x86/x2apic: Split enable and setup function'
|
|
|
ff41e30 |
Reported-and-tested-by: Javier Monteagudo <javiermon@gmail.com>
|
|
|
ff41e30 |
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
|
|
|
ff41e30 |
Link: https://bugzilla.redhat.com/show_bug.cgi?id=1224764
|
|
|
ff41e30 |
Cc: stable@vger.kernel.org # 4.0+
|
|
|
ff41e30 |
Cc: Laura Abbott <labbott@redhat.com>
|
|
|
ff41e30 |
Cc: Jiang Liu <jiang.liu@linux.intel.com>
|
|
|
ff41e30 |
Cc: Joerg Roedel <joro@8bytes.org>
|
|
|
ff41e30 |
Cc: Tony Luck <tony.luck@intel.com>
|
|
|
ff41e30 |
Cc: Borislav Petkov <bp@alien8.de>
|
|
|
ff41e30 |
---
|
|
|
ff41e30 |
arch/x86/kernel/apic/apic.c | 14 +++++++-------
|
|
|
ff41e30 |
1 file changed, 7 insertions(+), 7 deletions(-)
|
|
|
ff41e30 |
|
|
|
ff41e30 |
diff --git a/arch/x86/kernel/apic/apic.c b/arch/x86/kernel/apic/apic.c
|
|
|
ff41e30 |
index dcb5285..cde732c 100644
|
|
|
ff41e30 |
--- a/arch/x86/kernel/apic/apic.c
|
|
|
ff41e30 |
+++ b/arch/x86/kernel/apic/apic.c
|
|
|
ff41e30 |
@@ -1424,7 +1424,7 @@ static inline void __x2apic_disable(void)
|
|
|
ff41e30 |
{
|
|
|
ff41e30 |
u64 msr;
|
|
|
ff41e30 |
|
|
|
ff41e30 |
- if (cpu_has_apic)
|
|
|
ff41e30 |
+ if (!cpu_has_apic)
|
|
|
ff41e30 |
return;
|
|
|
ff41e30 |
|
|
|
ff41e30 |
rdmsrl(MSR_IA32_APICBASE, msr);
|
|
|
ff41e30 |
@@ -1483,10 +1483,13 @@ void x2apic_setup(void)
|
|
|
ff41e30 |
|
|
|
ff41e30 |
static __init void x2apic_disable(void)
|
|
|
ff41e30 |
{
|
|
|
ff41e30 |
- u32 x2apic_id;
|
|
|
ff41e30 |
+ u32 x2apic_id, state = x2apic_state;
|
|
|
ff41e30 |
|
|
|
ff41e30 |
- if (x2apic_state != X2APIC_ON)
|
|
|
ff41e30 |
- goto out;
|
|
|
ff41e30 |
+ x2apic_mode = 0;
|
|
|
ff41e30 |
+ x2apic_state = X2APIC_DISABLED;
|
|
|
ff41e30 |
+
|
|
|
ff41e30 |
+ if (state != X2APIC_ON)
|
|
|
ff41e30 |
+ return;
|
|
|
ff41e30 |
|
|
|
ff41e30 |
x2apic_id = read_apic_id();
|
|
|
ff41e30 |
if (x2apic_id >= 255)
|
|
|
ff41e30 |
@@ -1494,9 +1497,6 @@ static __init void x2apic_disable(void)
|
|
|
ff41e30 |
|
|
|
ff41e30 |
__x2apic_disable();
|
|
|
ff41e30 |
register_lapic_address(mp_lapic_addr);
|
|
|
ff41e30 |
-out:
|
|
|
ff41e30 |
- x2apic_state = X2APIC_DISABLED;
|
|
|
ff41e30 |
- x2apic_mode = 0;
|
|
|
ff41e30 |
}
|
|
|
ff41e30 |
|
|
|
ff41e30 |
static __init void x2apic_enable(void)
|
|
|
ff41e30 |
--
|
|
|
ff41e30 |
2.4.3
|
|
|
ff41e30 |
|