From: Sean Christopherson <seanjc@google.com>
To: Sean Christopherson <seanjc@google.com>,
Paolo Bonzini <pbonzini@redhat.com>
Cc: kvm@vger.kernel.org, linux-kernel@vger.kernel.org,
Rick Edgecombe <rick.p.edgecombe@intel.com>,
Xiaoyao Li <xiaoyao.li@intel.com>,
Binbin Wu <binbin.wu@linux.intel.com>,
Kai Huang <kai.huang@intel.com>, Yan Zhao <yan.y.zhao@intel.com>
Subject: [PATCH v2 1/8] KVM: VMX: Move the shared "IRQs off" exit handler(s) to common code
Date: Wed, 26 Aug 2026 10:12:39 -0700 [thread overview]
Message-ID: <20260826171246.777729-2-seanjc@google.com> (raw)
In-Reply-To: <20260826171246.777729-1-seanjc@google.com>
Move vmx_handle_exit_irqoff() and its helpers to common.h / main.c to
capture that it's a common handler and to allow guarding against incorrectly
using to_vmx().
Opportunistically use a "vt" prefix instead of "vmx" to communicate that
it's a shared handler.
No functional change intended.
Cc: Rick Edgecombe <rick.p.edgecombe@intel.com>
Cc: Xiaoyao Li <xiaoyao.li@intel.com>
Cc: Binbin Wu <binbin.wu@linux.intel.com>
Cc: Kai Huang <kai.huang@intel.com>
Cc: Yan Zhao <yan.y.zhao@intel.com>
Signed-off-by: Sean Christopherson <seanjc@google.com>
---
arch/x86/kvm/vmx/common.h | 6 ++++
arch/x86/kvm/vmx/main.c | 71 +++++++++++++++++++++++++++++++++++-
arch/x86/kvm/vmx/vmx.c | 74 --------------------------------------
arch/x86/kvm/vmx/x86_ops.h | 1 -
4 files changed, 76 insertions(+), 76 deletions(-)
diff --git a/arch/x86/kvm/vmx/common.h b/arch/x86/kvm/vmx/common.h
index 08005676702c..88f637c81353 100644
--- a/arch/x86/kvm/vmx/common.h
+++ b/arch/x86/kvm/vmx/common.h
@@ -74,6 +74,12 @@ static __always_inline bool is_td_vcpu(struct kvm_vcpu *vcpu) { return false; }
#endif
+static inline bool is_xfd_nm_fault(struct kvm_vcpu *vcpu)
+{
+ return vcpu->arch.guest_fpu.fpstate->xfd &&
+ !kvm_is_cr0_bit_set(vcpu, X86_CR0_TS);
+}
+
static inline bool vt_is_tdx_private_gpa(struct kvm *kvm, gpa_t gpa)
{
/* For TDX the direct mask is the shared mask. */
diff --git a/arch/x86/kvm/vmx/main.c b/arch/x86/kvm/vmx/main.c
index 4c52ab8d0786..274200b0a307 100644
--- a/arch/x86/kvm/vmx/main.c
+++ b/arch/x86/kvm/vmx/main.c
@@ -1,4 +1,5 @@
// SPDX-License-Identifier: GPL-2.0
+#include <linux/entry-common.h>
#include <linux/moduleparam.h>
#include "x86_ops.h"
@@ -876,6 +877,74 @@ static int vt_gmem_max_mapping_level(struct kvm *kvm, kvm_pfn_t pfn,
#define vt_op_tdx_only(name) NULL
#endif /* CONFIG_KVM_INTEL_TDX */
+static void handle_nm_fault_irqoff(struct kvm_vcpu *vcpu)
+{
+ /*
+ * Save xfd_err to guest_fpu before interrupt is enabled, so the
+ * MSR value is not clobbered by the host activity before the guest
+ * has chance to consume it.
+ *
+ * Update the guest's XFD_ERR if and only if XFD is enabled, as the #NM
+ * interception may have been caused by L1 interception. Per the SDM,
+ * XFD_ERR is not modified for non-XFD #NM, i.e. if CR0.TS=1.
+ *
+ * Note, XFD_ERR is updated _before_ the #NM interception check, i.e.
+ * unlike CR2 and DR6, the value is not a payload that is attached to
+ * the #NM exception.
+ */
+ if (is_xfd_nm_fault(vcpu))
+ rdmsrq(MSR_IA32_XFD_ERR, vcpu->arch.guest_fpu.xfd_err);
+}
+
+static void handle_exception_irqoff(struct kvm_vcpu *vcpu, u32 intr_info)
+{
+ /* if exit due to PF check for async PF */
+ if (is_page_fault(intr_info))
+ vcpu->arch.apf.host_apf_flags = kvm_read_and_reset_apf_flags();
+ /* if exit due to NM, handle before interrupts are enabled */
+ else if (is_nm_fault(intr_info))
+ handle_nm_fault_irqoff(vcpu);
+ /* Handle machine checks before interrupts are enabled */
+ else if (is_machine_check(intr_info))
+ kvm_machine_check();
+}
+
+static void handle_external_interrupt_irqoff(struct kvm_vcpu *vcpu,
+ u32 intr_info)
+{
+ unsigned int vector = intr_info & INTR_INFO_VECTOR_MASK;
+
+ if (KVM_BUG(!is_external_intr(intr_info), vcpu->kvm,
+ "unexpected VM-Exit interrupt info: 0x%x", intr_info))
+ return;
+
+ kvm_before_interrupt(vcpu, KVM_HANDLING_IRQ);
+ x86_entry_from_kvm(EVENT_TYPE_EXTINT, vector);
+ kvm_after_interrupt(vcpu);
+
+ vcpu->arch.at_instruction_boundary = true;
+}
+
+static void vt_handle_exit_irqoff(struct kvm_vcpu *vcpu)
+{
+ if (to_vt(vcpu)->emulation_required)
+ return;
+
+ switch (vmx_get_exit_reason(vcpu).basic) {
+ case EXIT_REASON_EXTERNAL_INTERRUPT:
+ handle_external_interrupt_irqoff(vcpu, vmx_get_intr_info(vcpu));
+ break;
+ case EXIT_REASON_EXCEPTION_NMI:
+ handle_exception_irqoff(vcpu, vmx_get_intr_info(vcpu));
+ break;
+ case EXIT_REASON_MCE_DURING_VMENTRY:
+ kvm_machine_check();
+ break;
+ default:
+ break;
+ }
+}
+
#define VMX_REQUIRED_APICV_INHIBITS \
(BIT(APICV_INHIBIT_REASON_DISABLED) | \
BIT(APICV_INHIBIT_REASON_ABSENT) | \
@@ -1000,7 +1069,7 @@ struct kvm_x86_ops vt_x86_ops __initdata = {
.load_mmu_pgd = vt_op(load_mmu_pgd),
.check_intercept = vmx_check_intercept,
- .handle_exit_irqoff = vmx_handle_exit_irqoff,
+ .handle_exit_irqoff = vt_handle_exit_irqoff,
.update_cpu_dirty_logging = vt_op(update_cpu_dirty_logging),
diff --git a/arch/x86/kvm/vmx/vmx.c b/arch/x86/kvm/vmx/vmx.c
index 504630f0eb40..adf2bc13bed2 100644
--- a/arch/x86/kvm/vmx/vmx.c
+++ b/arch/x86/kvm/vmx/vmx.c
@@ -5379,12 +5379,6 @@ bool vmx_guest_inject_ac(struct kvm_vcpu *vcpu)
(kvm_get_rflags(vcpu) & X86_EFLAGS_AC);
}
-static bool is_xfd_nm_fault(struct kvm_vcpu *vcpu)
-{
- return vcpu->arch.guest_fpu.fpstate->xfd &&
- !kvm_is_cr0_bit_set(vcpu, X86_CR0_TS);
-}
-
static int vmx_handle_page_fault(struct kvm_vcpu *vcpu, u32 error_code)
{
unsigned long cr2 = vmx_get_exit_qual(vcpu);
@@ -7143,74 +7137,6 @@ void vmx_load_eoi_exitmap(struct kvm_vcpu *vcpu, u64 *eoi_exit_bitmap)
vmcs_write64(EOI_EXIT_BITMAP3, eoi_exit_bitmap[3]);
}
-static void handle_nm_fault_irqoff(struct kvm_vcpu *vcpu)
-{
- /*
- * Save xfd_err to guest_fpu before interrupt is enabled, so the
- * MSR value is not clobbered by the host activity before the guest
- * has chance to consume it.
- *
- * Update the guest's XFD_ERR if and only if XFD is enabled, as the #NM
- * interception may have been caused by L1 interception. Per the SDM,
- * XFD_ERR is not modified for non-XFD #NM, i.e. if CR0.TS=1.
- *
- * Note, XFD_ERR is updated _before_ the #NM interception check, i.e.
- * unlike CR2 and DR6, the value is not a payload that is attached to
- * the #NM exception.
- */
- if (is_xfd_nm_fault(vcpu))
- rdmsrq(MSR_IA32_XFD_ERR, vcpu->arch.guest_fpu.xfd_err);
-}
-
-static void handle_exception_irqoff(struct kvm_vcpu *vcpu, u32 intr_info)
-{
- /* if exit due to PF check for async PF */
- if (is_page_fault(intr_info))
- vcpu->arch.apf.host_apf_flags = kvm_read_and_reset_apf_flags();
- /* if exit due to NM, handle before interrupts are enabled */
- else if (is_nm_fault(intr_info))
- handle_nm_fault_irqoff(vcpu);
- /* Handle machine checks before interrupts are enabled */
- else if (is_machine_check(intr_info))
- kvm_machine_check();
-}
-
-static void handle_external_interrupt_irqoff(struct kvm_vcpu *vcpu,
- u32 intr_info)
-{
- unsigned int vector = intr_info & INTR_INFO_VECTOR_MASK;
-
- if (KVM_BUG(!is_external_intr(intr_info), vcpu->kvm,
- "unexpected VM-Exit interrupt info: 0x%x", intr_info))
- return;
-
- kvm_before_interrupt(vcpu, KVM_HANDLING_IRQ);
- x86_entry_from_kvm(EVENT_TYPE_EXTINT, vector);
- kvm_after_interrupt(vcpu);
-
- vcpu->arch.at_instruction_boundary = true;
-}
-
-void vmx_handle_exit_irqoff(struct kvm_vcpu *vcpu)
-{
- if (to_vt(vcpu)->emulation_required)
- return;
-
- switch (vmx_get_exit_reason(vcpu).basic) {
- case EXIT_REASON_EXTERNAL_INTERRUPT:
- handle_external_interrupt_irqoff(vcpu, vmx_get_intr_info(vcpu));
- break;
- case EXIT_REASON_EXCEPTION_NMI:
- handle_exception_irqoff(vcpu, vmx_get_intr_info(vcpu));
- break;
- case EXIT_REASON_MCE_DURING_VMENTRY:
- kvm_machine_check();
- break;
- default:
- break;
- }
-}
-
/*
* The kvm parameter can be NULL (module initialization, or invocation before
* VM creation). Be sure to check the kvm parameter before using it.
diff --git a/arch/x86/kvm/vmx/x86_ops.h b/arch/x86/kvm/vmx/x86_ops.h
index 054fd14bb2e1..7ac02c68457f 100644
--- a/arch/x86/kvm/vmx/x86_ops.h
+++ b/arch/x86/kvm/vmx/x86_ops.h
@@ -27,7 +27,6 @@ void vmx_vcpu_reset(struct kvm_vcpu *vcpu, bool init_event);
void vmx_vcpu_load(struct kvm_vcpu *vcpu, int cpu);
void vmx_vcpu_put(struct kvm_vcpu *vcpu);
int vmx_handle_exit(struct kvm_vcpu *vcpu, fastpath_t exit_fastpath);
-void vmx_handle_exit_irqoff(struct kvm_vcpu *vcpu);
int vmx_skip_emulated_instruction(struct kvm_vcpu *vcpu);
void vmx_update_emulated_instruction(struct kvm_vcpu *vcpu);
bool vmx_unhandleable_emulation_required(struct kvm_vcpu *vcpu);
--
2.55.0.887.g758fc8c411-goog
next prev parent reply other threads:[~2026-08-26 17:12 UTC|newest]
Thread overview: 23+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-08-26 17:12 [PATCH v2 0/8] KVM: VMX: Harden against interpreting TDX vCPU as vcpu_vmx Sean Christopherson
2026-08-26 17:12 ` Sean Christopherson [this message]
2026-08-27 10:48 ` [PATCH v2 1/8] KVM: VMX: Move the shared "IRQs off" exit handler(s) to common code Xiaoyao Li
2026-08-27 19:34 ` Sean Christopherson
2026-08-26 17:12 ` [PATCH v2 2/8] KVM: VMX: Move the shared NMI handler/trampoline " Sean Christopherson
2026-08-27 11:20 ` Xiaoyao Li
2026-08-26 17:12 ` [PATCH v2 3/8] KVM: VMX: Disallowing using to_vmx() in common VT code Sean Christopherson
2026-08-27 2:32 ` Huang, Kai
2026-08-27 11:21 ` Xiaoyao Li
2026-08-26 17:12 ` [PATCH v2 4/8] KVM: VMX: Rename posted interrupt prefixes from "vmx" to "vt" Sean Christopherson
2026-08-27 2:35 ` Huang, Kai
2026-08-27 11:38 ` Xiaoyao Li
2026-08-27 14:17 ` Sean Christopherson
2026-08-26 17:12 ` [PATCH v2 5/8] KVM: VMX: Rename EPT violation handler prefix " Sean Christopherson
2026-08-27 2:36 ` Huang, Kai
2026-08-27 11:48 ` Xiaoyao Li
2026-08-26 17:12 ` [PATCH v2 6/8] KVM: VMX: Use dummy pseudo-overlay struct for to_vt() and vt_to_vcpu() Sean Christopherson
2026-08-27 11:58 ` Xiaoyao Li
2026-08-26 17:12 ` [PATCH v2 7/8] KVM: VMX: Move common VT getters/converters to common.h Sean Christopherson
2026-08-27 12:02 ` Xiaoyao Li
2026-08-26 17:12 ` [PATCH v2 8/8] KVM: VMX: Rename common exit info getters prefixes from "vmx" to "vt" Sean Christopherson
2026-08-27 12:09 ` Xiaoyao Li
2026-08-27 2:53 ` [PATCH v2 0/8] KVM: VMX: Harden against interpreting TDX vCPU as vcpu_vmx Huang, Kai
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260826171246.777729-2-seanjc@google.com \
--to=seanjc@google.com \
--cc=binbin.wu@linux.intel.com \
--cc=kai.huang@intel.com \
--cc=kvm@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=pbonzini@redhat.com \
--cc=rick.p.edgecombe@intel.com \
--cc=xiaoyao.li@intel.com \
--cc=yan.y.zhao@intel.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®