mirror of
https://gitee.com/bianbu-linux/linux-6.6
synced 2025-07-04 00:03:25 -04:00
x86/reboot: Force all cpus to exit VMX root if VMX is supported
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: d176720d34
("x86: disable VMX on all CPUs on reboot")
Cc: stable@vger.kernel.org
Suggested-by: Sean Christopherson <seanjc@google.com>
Signed-off-by: David P. Reed <dpreed@deepplum.com>
[sean: reworked changelog and further tweaked comment]
Signed-off-by: Sean Christopherson <seanjc@google.com>
Message-Id: <20201231002702.2223707-3-seanjc@google.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
This commit is contained in:
parent
aec511ad15
commit
ed72736183
1 changed files with 10 additions and 20 deletions
|
@ -538,31 +538,21 @@ static void emergency_vmx_disable_all(void)
|
||||||
local_irq_disable();
|
local_irq_disable();
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* We need to disable VMX on all CPUs before rebooting, otherwise
|
* Disable VMX on all CPUs before rebooting, otherwise we risk hanging
|
||||||
* we risk hanging up the machine, because the CPU ignores INIT
|
* the machine, because the CPU blocks INIT when it's in VMX root.
|
||||||
* signals when VMX is enabled.
|
|
||||||
*
|
*
|
||||||
* We can't take any locks and we may be on an inconsistent
|
* We can't take any locks and we may be on an inconsistent state, so
|
||||||
* state, so we use NMIs as IPIs to tell the other CPUs to disable
|
* use NMIs as IPIs to tell the other CPUs to exit VMX root and halt.
|
||||||
* VMX and halt.
|
|
||||||
*
|
*
|
||||||
* For safety, we will avoid running the nmi_shootdown_cpus()
|
* Do the NMI shootdown even if VMX if off on _this_ CPU, as that
|
||||||
* stuff unnecessarily, but we don't have a way to check
|
* doesn't prevent a different CPU from being in VMX root operation.
|
||||||
* 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.
|
|
||||||
*/
|
*/
|
||||||
if (cpu_has_vmx() && cpu_vmx_enabled()) {
|
if (cpu_has_vmx()) {
|
||||||
/* Disable VMX on this CPU. */
|
/* Safely force _this_ CPU out of VMX root operation. */
|
||||||
cpu_vmxoff();
|
__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);
|
nmi_shootdown_cpus(vmxoff_nmi);
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue