aboutsummaryrefslogtreecommitdiff
path: root/arch/x86/include/asm/smp.h
diff options
context:
space:
mode:
authorGravatar Thomas Gleixner <tglx@linutronix.de> 2023-06-15 22:33:57 +0200
committerGravatar Thomas Gleixner <tglx@linutronix.de> 2023-06-20 14:51:47 +0200
commitd7893093a7417527c0d73c9832244e65c9d0114f (patch)
tree95c8ee15bad1d6c51449392e5dae3f3a5c09bab2 /arch/x86/include/asm/smp.h
parentx86/smp: Use dedicated cache-line for mwait_play_dead() (diff)
downloadlinux-d7893093a7417527c0d73c9832244e65c9d0114f.tar.gz
linux-d7893093a7417527c0d73c9832244e65c9d0114f.tar.bz2
linux-d7893093a7417527c0d73c9832244e65c9d0114f.zip
x86/smp: Cure kexec() vs. mwait_play_dead() breakage
TLDR: It's a mess. When kexec() is executed on a system with offline CPUs, which are parked in mwait_play_dead() it can end up in a triple fault during the bootup of the kexec kernel or cause hard to diagnose data corruption. The reason is that kexec() eventually overwrites the previous kernel's text, page tables, data and stack. If it writes to the cache line which is monitored by a previously offlined CPU, MWAIT resumes execution and ends up executing the wrong text, dereferencing overwritten page tables or corrupting the kexec kernels data. Cure this by bringing the offlined CPUs out of MWAIT into HLT. Write to the monitored cache line of each offline CPU, which makes MWAIT resume execution. The written control word tells the offlined CPUs to issue HLT, which does not have the MWAIT problem. That does not help, if a stray NMI, MCE or SMI hits the offlined CPUs as those make it come out of HLT. A follow up change will put them into INIT, which protects at least against NMI and SMI. Fixes: ea53069231f9 ("x86, hotplug: Use mwait to offline a processor, fix the legacy case") Reported-by: Ashok Raj <ashok.raj@intel.com> Signed-off-by: Thomas Gleixner <tglx@linutronix.de> Tested-by: Ashok Raj <ashok.raj@intel.com> Reviewed-by: Ashok Raj <ashok.raj@intel.com> Cc: stable@vger.kernel.org Link: https://lore.kernel.org/r/20230615193330.492257119@linutronix.de
Diffstat (limited to 'arch/x86/include/asm/smp.h')
-rw-r--r--arch/x86/include/asm/smp.h2
1 files changed, 2 insertions, 0 deletions
diff --git a/arch/x86/include/asm/smp.h b/arch/x86/include/asm/smp.h
index 4e91054c84be..d4ce5cb5c953 100644
--- a/arch/x86/include/asm/smp.h
+++ b/arch/x86/include/asm/smp.h
@@ -132,6 +132,8 @@ void wbinvd_on_cpu(int cpu);
int wbinvd_on_all_cpus(void);
void cond_wakeup_cpu0(void);
+void smp_kick_mwait_play_dead(void);
+
void native_smp_send_reschedule(int cpu);
void native_send_call_func_ipi(const struct cpumask *mask);
void native_send_call_func_single_ipi(int cpu);