Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit a6d4fc8c authored by Sean Christopherson's avatar Sean Christopherson Committed by Greg Kroah-Hartman
Browse files

x86/reboot: Force all cpus to exit VMX root if VMX is supported



commit ed72736183c45a413a8d6974dd04be90f514cb6b upstream.

Force all CPUs to do VMXOFF (via NMI shootdown) during an emergency
reboot if VMX is _supported_, as VMX being off on the current CPU does
not prevent other CPUs from being in VMX root (post-VMXON).  This fixes
a bug where a crash/panic reboot could leave other CPUs in VMX root and
prevent them from being woken via INIT-SIPI-SIPI in the new kernel.

Fixes: d176720d ("x86: disable VMX on all CPUs on reboot")
Cc: stable@vger.kernel.org
Suggested-by: default avatarSean Christopherson <seanjc@google.com>
Signed-off-by: default avatarDavid P. Reed <dpreed@deepplum.com>
[sean: reworked changelog and further tweaked comment]
Signed-off-by: default avatarSean Christopherson <seanjc@google.com>
Message-Id: <20201231002702.2223707-3-seanjc@google.com>
Signed-off-by: default avatarPaolo Bonzini <pbonzini@redhat.com>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent 4a7bf4f5
Loading
Loading
Loading
Loading
+10 −19
Original line number Diff line number Diff line
@@ -479,29 +479,20 @@ static void emergency_vmx_disable_all(void)
	local_irq_disable();

	/*
	 * We need to disable VMX on all CPUs before rebooting, otherwise
	 * we risk hanging up the machine, because the CPU ignore INIT
	 * signals when VMX is enabled.
	 * Disable VMX on all CPUs before rebooting, otherwise we risk hanging
	 * the machine, because the CPU blocks INIT when it's in VMX root.
	 *
	 * We can't take any locks and we may be on an inconsistent
	 * state, so we use NMIs as IPIs to tell the other CPUs to disable
	 * VMX and halt.
	 * We can't take any locks and we may be on an inconsistent state, so
	 * use NMIs as IPIs to tell the other CPUs to exit VMX root and halt.
	 *
	 * For safety, we will avoid running the nmi_shootdown_cpus()
	 * stuff unnecessarily, but we don't have a way to check
	 * if other CPUs have VMX enabled. So we will call it only if the
	 * CPU we are running on has VMX enabled.
	 *
	 * We will miss cases where VMX is not enabled on all CPUs. This
	 * shouldn't do much harm because KVM always enable VMX on all
	 * CPUs anyway. But we can miss it on the small window where KVM
	 * is still enabling VMX.
	 * Do the NMI shootdown even if VMX if off on _this_ CPU, as that
	 * doesn't prevent a different CPU from being in VMX root operation.
	 */
	if (cpu_has_vmx() && cpu_vmx_enabled()) {
		/* Disable VMX on this CPU. */
		cpu_vmxoff();
	if (cpu_has_vmx()) {
		/* Safely force _this_ CPU out of VMX root operation. */
		__cpu_emergency_vmxoff();

		/* Halt and disable VMX on the other CPUs */
		/* Halt and exit VMX root operation on the other CPUs. */
		nmi_shootdown_cpus(vmxoff_nmi);

	}