Drop kvm_rebooting and all related uses. Virtualization is now disabled
immediately before a CPU shuts down, eliminating any chance of executing
virtualization instructions during reboot.
Signed-off-by: Xin Li (Intel) <xin@zytor.com>
---
arch/x86/kvm/svm/vmenter.S | 42 ++++++++++++--------------------------
arch/x86/kvm/vmx/tdx.c | 4 +---
arch/x86/kvm/vmx/vmenter.S | 2 --
arch/x86/kvm/x86.c | 8 ++------
include/linux/kvm_host.h | 1 -
virt/kvm/kvm_main.c | 15 ++------------
6 files changed, 18 insertions(+), 54 deletions(-)
diff --git a/arch/x86/kvm/svm/vmenter.S b/arch/x86/kvm/svm/vmenter.S
index 235c4af6b692..d530f62679b9 100644
--- a/arch/x86/kvm/svm/vmenter.S
+++ b/arch/x86/kvm/svm/vmenter.S
@@ -145,7 +145,6 @@ SYM_FUNC_START(__svm_vcpu_run)
*/
mov SVM_vmcb01_pa(%_ASM_DI), %_ASM_AX
1: vmload %_ASM_AX
-2:
/* Get svm->current_vmcb->pa into RAX. */
mov SVM_current_vmcb(%_ASM_DI), %_ASM_AX
@@ -173,8 +172,8 @@ SYM_FUNC_START(__svm_vcpu_run)
VM_CLEAR_CPU_BUFFERS
/* Enter guest mode */
-3: vmrun %_ASM_AX
-4:
+2: vmrun %_ASM_AX
+
/* Pop @svm to RAX while it's the only available register. */
pop %_ASM_AX
@@ -200,13 +199,11 @@ SYM_FUNC_START(__svm_vcpu_run)
mov %_ASM_AX, %_ASM_DI
mov SVM_vmcb01_pa(%_ASM_DI), %_ASM_AX
-5: vmsave %_ASM_AX
-6:
+3: vmsave %_ASM_AX
/* Restores GSBASE among other things, allowing access to percpu data. */
pop %_ASM_AX
-7: vmload %_ASM_AX
-8:
+4: vmload %_ASM_AX
/* IMPORTANT: Stuff the RSB immediately after VM-Exit, before RET! */
FILL_RETURN_BUFFER %_ASM_AX, RSB_CLEAR_LOOPS, X86_FEATURE_RSB_VMEXIT
@@ -269,23 +266,12 @@ SYM_FUNC_START(__svm_vcpu_run)
RESTORE_GUEST_SPEC_CTRL_BODY
RESTORE_HOST_SPEC_CTRL_BODY (%_ASM_SP)
-10: cmpb $0, _ASM_RIP(kvm_rebooting)
- jne 2b
- ud2
-30: cmpb $0, _ASM_RIP(kvm_rebooting)
- jne 4b
- ud2
-50: cmpb $0, _ASM_RIP(kvm_rebooting)
- jne 6b
- ud2
-70: cmpb $0, _ASM_RIP(kvm_rebooting)
- jne 8b
- ud2
-
- _ASM_EXTABLE(1b, 10b)
- _ASM_EXTABLE(3b, 30b)
- _ASM_EXTABLE(5b, 50b)
- _ASM_EXTABLE(7b, 70b)
+5: ud2
+
+ _ASM_EXTABLE(1b, 5b)
+ _ASM_EXTABLE(2b, 5b)
+ _ASM_EXTABLE(3b, 5b)
+ _ASM_EXTABLE(4b, 5b)
SYM_FUNC_END(__svm_vcpu_run)
@@ -343,7 +329,7 @@ SYM_FUNC_START(__svm_sev_es_vcpu_run)
/* Enter guest mode */
1: vmrun %rax
-2:
+
/* IMPORTANT: Stuff the RSB immediately after VM-Exit, before RET! */
FILL_RETURN_BUFFER %rax, RSB_CLEAR_LOOPS, X86_FEATURE_RSB_VMEXIT
@@ -365,11 +351,9 @@ SYM_FUNC_START(__svm_sev_es_vcpu_run)
RESTORE_GUEST_SPEC_CTRL_BODY
RESTORE_HOST_SPEC_CTRL_BODY %sil
-3: cmpb $0, kvm_rebooting(%rip)
- jne 2b
- ud2
+2: ud2
- _ASM_EXTABLE(1b, 3b)
+ _ASM_EXTABLE(1b, 2b)
SYM_FUNC_END(__svm_sev_es_vcpu_run)
#endif /* CONFIG_KVM_AMD_SEV */
diff --git a/arch/x86/kvm/vmx/tdx.c b/arch/x86/kvm/vmx/tdx.c
index 66744f5768c8..cfe5f8b63973 100644
--- a/arch/x86/kvm/vmx/tdx.c
+++ b/arch/x86/kvm/vmx/tdx.c
@@ -2052,10 +2052,8 @@ int tdx_handle_exit(struct kvm_vcpu *vcpu, fastpath_t fastpath)
* Handle TDX SW errors, including TDX_SEAMCALL_UD, TDX_SEAMCALL_GP and
* TDX_SEAMCALL_VMFAILINVALID.
*/
- if (unlikely((vp_enter_ret & TDX_SW_ERROR) == TDX_SW_ERROR)) {
- KVM_BUG_ON(!kvm_rebooting, vcpu->kvm);
+ if (unlikely((vp_enter_ret & TDX_SW_ERROR) == TDX_SW_ERROR))
goto unhandled_exit;
- }
if (unlikely(tdx_failed_vmentry(vcpu))) {
/*
diff --git a/arch/x86/kvm/vmx/vmenter.S b/arch/x86/kvm/vmx/vmenter.S
index 0a6cf5bff2aa..3457b5e1f856 100644
--- a/arch/x86/kvm/vmx/vmenter.S
+++ b/arch/x86/kvm/vmx/vmenter.S
@@ -293,8 +293,6 @@ SYM_INNER_LABEL_ALIGN(vmx_vmexit, SYM_L_GLOBAL)
RET
.Lfixup:
- cmpb $0, _ASM_RIP(kvm_rebooting)
- jne .Lvmfail
ud2
.Lvmfail:
/* VM-Fail: set return value to 1 */
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
index 8b9f64770684..1abc4550fd76 100644
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -687,15 +687,11 @@ static void drop_user_return_notifiers(void)
/*
* Handle a fault on a hardware virtualization (VMX or SVM) instruction.
- *
- * Hardware virtualization extension instructions may fault if a reboot turns
- * off virtualization while processes are running. Usually after catching the
- * fault we just panic; during reboot instead the instruction is ignored.
*/
noinstr void kvm_spurious_fault(void)
{
- /* Fault while not rebooting. We want the trace. */
- BUG_ON(!kvm_rebooting);
+ /* We want the trace. */
+ BUG_ON(true);
}
EXPORT_SYMBOL_GPL(kvm_spurious_fault);
diff --git a/include/linux/kvm_host.h b/include/linux/kvm_host.h
index 151305b33bce..2d9c306db4f0 100644
--- a/include/linux/kvm_host.h
+++ b/include/linux/kvm_host.h
@@ -2276,7 +2276,6 @@ static inline bool kvm_check_request(int req, struct kvm_vcpu *vcpu)
#ifdef CONFIG_KVM_GENERIC_HARDWARE_ENABLING
extern bool enable_virt_at_load;
-extern bool kvm_rebooting;
#endif
extern unsigned int halt_poll_ns;
diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c
index 6e86c6a45a71..0037761c1a51 100644
--- a/virt/kvm/kvm_main.c
+++ b/virt/kvm/kvm_main.c
@@ -5559,9 +5559,6 @@ bool enable_virt_at_load = true;
module_param(enable_virt_at_load, bool, 0444);
EXPORT_SYMBOL_GPL(enable_virt_at_load);
-__visible bool kvm_rebooting;
-EXPORT_SYMBOL_GPL(kvm_rebooting);
-
static DEFINE_PER_CPU(bool, virtualization_enabled);
static DEFINE_MUTEX(kvm_usage_lock);
static int kvm_usage_count;
@@ -5610,18 +5607,10 @@ static int kvm_offline_cpu(unsigned int cpu)
static void kvm_shutdown(void)
{
/*
- * Disable hardware virtualization and set kvm_rebooting to indicate
- * that KVM has asynchronously disabled hardware virtualization, i.e.
- * that relevant errors and exceptions aren't entirely unexpected.
- * Some flavors of hardware virtualization need to be disabled before
- * transferring control to firmware (to perform shutdown/reboot), e.g.
- * on x86, virtualization can block INIT interrupts, which are used by
- * firmware to pull APs back under firmware control. Note, this path
- * is used for both shutdown and reboot scenarios, i.e. neither name is
- * 100% comprehensive.
+ * Note, this path is used for both shutdown and reboot scenarios, i.e.
+ * neither name is 100% comprehensive.
*/
pr_info("kvm: exiting hardware virtualization\n");
- kvm_rebooting = true;
on_each_cpu(kvm_disable_virtualization_cpu, NULL, 1);
}
--
2.51.0
On Tue, Sep 09, 2025, Xin Li (Intel) wrote: > Drop kvm_rebooting and all related uses. Virtualization is now disabled > immediately before a CPU shuts down, eliminating any chance of executing > virtualization instructions during reboot. Wrong. KVM clears EFER.SVME in reponse to kvm_shutdown(), and thus can trip #UDs on e.g. VMRUN.
On 9/16/2025 10:56 AM, Sean Christopherson wrote: > On Tue, Sep 09, 2025, Xin Li (Intel) wrote: >> Drop kvm_rebooting and all related uses. Virtualization is now disabled >> immediately before a CPU shuts down, eliminating any chance of executing >> virtualization instructions during reboot. > > Wrong. KVM clears EFER.SVME in reponse to kvm_shutdown(), and thus can trip > #UDs on e.g. VMRUN. > This patch assumes that AMD SVM enable/disable has been moved to the CPU startup and shutdown routines. Accordingly, kvm_shutdown() no longer clears EFER.SVME, and the patch demonstrates the resulting simplification from removing kvm_rebooting. However, as noted in the cover letter, no actual modifications were made to AMD SVM. Is this what seems wrong to you? Thanks! Xin
On Wed, Sep 17, 2025, Xin Li wrote: > On 9/16/2025 10:56 AM, Sean Christopherson wrote: > > On Tue, Sep 09, 2025, Xin Li (Intel) wrote: > > > Drop kvm_rebooting and all related uses. Virtualization is now disabled > > > immediately before a CPU shuts down, eliminating any chance of executing > > > virtualization instructions during reboot. > > > > Wrong. KVM clears EFER.SVME in reponse to kvm_shutdown(), and thus can trip > > #UDs on e.g. VMRUN. > > > > This patch assumes that AMD SVM enable/disable has been moved to the CPU Ah, that wasn't exactly obvious. > startup and shutdown routines. Accordingly, kvm_shutdown() no longer clears > EFER.SVME, and the patch demonstrates the resulting simplification from > removing kvm_rebooting. However, as noted in the cover letter, no actual > modifications were made to AMD SVM. Heh, yeah, that's what's wrong.
© 2016 - 2025 Red Hat, Inc.