Jiri Slaby ef7db2
From: Sean Christopherson <seanjc@google.com>
Jiri Slaby ef7db2
Date: Wed, 30 Nov 2022 23:36:49 +0000
Jiri Slaby ef7db2
Subject: [PATCH] x86/reboot: Disable virtualization in an emergency if SVM is
Jiri Slaby ef7db2
 supported
Jiri Slaby ef7db2
References: bsc#1012628
Jiri Slaby ef7db2
Patch-mainline: 6.2.3
Jiri Slaby ef7db2
Git-commit: d81f952aa657b76cea381384bef1fea35c5fd266
Jiri Slaby ef7db2
Jiri Slaby ef7db2
commit d81f952aa657b76cea381384bef1fea35c5fd266 upstream.
Jiri Slaby ef7db2
Jiri Slaby ef7db2
Disable SVM on all CPUs via NMI shootdown during an emergency reboot.
Jiri Slaby ef7db2
Like VMX, SVM can block INIT, e.g. if the emergency reboot is triggered
Jiri Slaby ef7db2
between CLGI and STGI, and thus can prevent bringing up other CPUs via
Jiri Slaby ef7db2
INIT-SIPI-SIPI.
Jiri Slaby ef7db2
Jiri Slaby ef7db2
Cc: stable@vger.kernel.org
Jiri Slaby ef7db2
Reviewed-by: Thomas Gleixner <tglx@linutronix.de>
Jiri Slaby ef7db2
Link: https://lore.kernel.org/r/20221130233650.1404148-4-seanjc@google.com
Jiri Slaby ef7db2
Signed-off-by: Sean Christopherson <seanjc@google.com>
Jiri Slaby ef7db2
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Jiri Slaby ef7db2
Signed-off-by: Jiri Slaby <jslaby@suse.cz>
Jiri Slaby ef7db2
---
Jiri Slaby ef7db2
 arch/x86/kernel/reboot.c | 23 +++++++++++------------
Jiri Slaby ef7db2
 1 file changed, 11 insertions(+), 12 deletions(-)
Jiri Slaby ef7db2
Jiri Slaby ef7db2
diff --git a/arch/x86/kernel/reboot.c b/arch/x86/kernel/reboot.c
Jiri Slaby ef7db2
index 374c14b3..d03c551d 100644
Jiri Slaby ef7db2
--- a/arch/x86/kernel/reboot.c
Jiri Slaby ef7db2
+++ b/arch/x86/kernel/reboot.c
Jiri Slaby ef7db2
@@ -530,27 +530,26 @@ static inline void kb_wait(void)
Jiri Slaby ef7db2
 
Jiri Slaby ef7db2
 static inline void nmi_shootdown_cpus_on_restart(void);
Jiri Slaby ef7db2
 
Jiri Slaby ef7db2
-/* Use NMIs as IPIs to tell all CPUs to disable virtualization */
Jiri Slaby ef7db2
-static void emergency_vmx_disable_all(void)
Jiri Slaby ef7db2
+static void emergency_reboot_disable_virtualization(void)
Jiri Slaby ef7db2
 {
Jiri Slaby ef7db2
 	/* Just make sure we won't change CPUs while doing this */
Jiri Slaby ef7db2
 	local_irq_disable();
Jiri Slaby ef7db2
 
Jiri Slaby ef7db2
 	/*
Jiri Slaby ef7db2
-	 * Disable VMX on all CPUs before rebooting, otherwise we risk hanging
Jiri Slaby ef7db2
-	 * the machine, because the CPU blocks INIT when it's in VMX root.
Jiri Slaby ef7db2
+	 * Disable virtualization on all CPUs before rebooting to avoid hanging
Jiri Slaby ef7db2
+	 * the system, as VMX and SVM block INIT when running in the host.
Jiri Slaby ef7db2
 	 *
Jiri Slaby ef7db2
 	 * We can't take any locks and we may be on an inconsistent state, so
Jiri Slaby ef7db2
-	 * use NMIs as IPIs to tell the other CPUs to exit VMX root and halt.
Jiri Slaby ef7db2
+	 * use NMIs as IPIs to tell the other CPUs to disable VMX/SVM and halt.
Jiri Slaby ef7db2
 	 *
Jiri Slaby ef7db2
-	 * Do the NMI shootdown even if VMX if off on _this_ CPU, as that
Jiri Slaby ef7db2
-	 * doesn't prevent a different CPU from being in VMX root operation.
Jiri Slaby ef7db2
+	 * Do the NMI shootdown even if virtualization is off on _this_ CPU, as
Jiri Slaby ef7db2
+	 * other CPUs may have virtualization enabled.
Jiri Slaby ef7db2
 	 */
Jiri Slaby ef7db2
-	if (cpu_has_vmx()) {
Jiri Slaby ef7db2
-		/* Safely force _this_ CPU out of VMX root operation. */
Jiri Slaby ef7db2
-		__cpu_emergency_vmxoff();
Jiri Slaby ef7db2
+	if (cpu_has_vmx() || cpu_has_svm(NULL)) {
Jiri Slaby ef7db2
+		/* Safely force _this_ CPU out of VMX/SVM operation. */
Jiri Slaby ef7db2
+		cpu_emergency_disable_virtualization();
Jiri Slaby ef7db2
 
Jiri Slaby ef7db2
-		/* Halt and exit VMX root operation on the other CPUs. */
Jiri Slaby ef7db2
+		/* Disable VMX/SVM and halt on other CPUs. */
Jiri Slaby ef7db2
 		nmi_shootdown_cpus_on_restart();
Jiri Slaby ef7db2
 	}
Jiri Slaby ef7db2
 }
Jiri Slaby ef7db2
@@ -587,7 +586,7 @@ static void native_machine_emergency_restart(void)
Jiri Slaby ef7db2
 	unsigned short mode;
Jiri Slaby ef7db2
 
Jiri Slaby ef7db2
 	if (reboot_emergency)
Jiri Slaby ef7db2
-		emergency_vmx_disable_all();
Jiri Slaby ef7db2
+		emergency_reboot_disable_virtualization();
Jiri Slaby ef7db2
 
Jiri Slaby ef7db2
 	tboot_shutdown(TB_SHUTDOWN_REBOOT);
Jiri Slaby ef7db2
 
Jiri Slaby ef7db2
-- 
Jiri Slaby ef7db2
2.35.3
Jiri Slaby ef7db2