x86/smp: Cure kexec() vs. mwait_play_dead() breakage
authorThomas Gleixner <tglx@linutronix.de>
Thu, 15 Jun 2023 20:33:57 +0000 (22:33 +0200)
committerThomas Gleixner <tglx@linutronix.de>
Tue, 20 Jun 2023 12:51:47 +0000 (14:51 +0200)
commitd7893093a7417527c0d73c9832244e65c9d0114f
tree95c8ee15bad1d6c51449392e5dae3f3a5c09bab2
parentf9c9987bf52f4e42e940ae217333ebb5a4c3b506
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
arch/x86/include/asm/smp.h
arch/x86/kernel/smp.c
arch/x86/kernel/smpboot.c