Linus,

please pull the latest x86-urgent-for-linus git tree from:

   git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip.git 
x86-urgent-for-linus

A single fix for the WBINVD issue introduced by the SME support which
causes kexec fails on non AMD/SME capable CPUs. Issue WBINVD only when the
CPU has SME and avoid doing so in a loop.

Thanks,

        tglx

------------------>
Tom Lendacky (1):
      x86/mm: Rework wbinvd, hlt operation in stop_this_cpu()


 arch/x86/kernel/process.c | 25 +++++++++++++++----------
 1 file changed, 15 insertions(+), 10 deletions(-)

diff --git a/arch/x86/kernel/process.c b/arch/x86/kernel/process.c
index 832a6acd730f..cb368c2a22ab 100644
--- a/arch/x86/kernel/process.c
+++ b/arch/x86/kernel/process.c
@@ -380,19 +380,24 @@ void stop_this_cpu(void *dummy)
        disable_local_APIC();
        mcheck_cpu_clear(this_cpu_ptr(&cpu_info));
 
+       /*
+        * Use wbinvd on processors that support SME. This provides support
+        * for performing a successful kexec when going from SME inactive
+        * to SME active (or vice-versa). The cache must be cleared so that
+        * if there are entries with the same physical address, both with and
+        * without the encryption bit, they don't race each other when flushed
+        * and potentially end up with the wrong entry being committed to
+        * memory.
+        */
+       if (boot_cpu_has(X86_FEATURE_SME))
+               native_wbinvd();
        for (;;) {
                /*
-                * Use wbinvd followed by hlt to stop the processor. This
-                * provides support for kexec on a processor that supports
-                * SME. With kexec, going from SME inactive to SME active
-                * requires clearing cache entries so that addresses without
-                * the encryption bit set don't corrupt the same physical
-                * address that has the encryption bit set when caches are
-                * flushed. To achieve this a wbinvd is performed followed by
-                * a hlt. Even if the processor is not in the kexec/SME
-                * scenario this only adds a wbinvd to a halting processor.
+                * Use native_halt() so that memory contents don't change
+                * (stack usage and variables) after possibly issuing the
+                * native_wbinvd() above.
                 */
-               asm volatile("wbinvd; hlt" : : : "memory");
+               native_halt();
        }
 }
 

Reply via email to