Merge branch 'x86-platform-for-linus' of git://git.kernel.org/pub/scm/linux/kernel...
[linux-2.6-block.git] / arch / x86 / kernel / process.c
index 832a6acd730fad70e1426052d502f6438b30e38e..03408b942adbad2bd1bca42b89e559e2d198d9da 100644 (file)
@@ -21,7 +21,6 @@
 #include <linux/dmi.h>
 #include <linux/utsname.h>
 #include <linux/stackprotector.h>
-#include <linux/tick.h>
 #include <linux/cpuidle.h>
 #include <trace/events/power.h>
 #include <linux/hw_breakpoint.h>
@@ -380,19 +379,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();
        }
 }