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,
Hao Zhang <zhanghao1@kylinos.cn>
Subject: [PATCH v4 1/6] KVM: x86: Extract VMX's unhandleable emulation check to common x86
Date: Mon, 27 Jul 2026 17:43:46 -0700 [thread overview]
Message-ID: <20260728004351.887076-2-seanjc@google.com> (raw)
In-Reply-To: <20260728004351.887076-1-seanjc@google.com>
Expose VMX's check for unhandleable emulation as its own kvm_x86_ops hook,
and move the actual pre-KVM_RUN check into common x86. This will allow
sharing the core logic with KVM's RSM emulation without needed to add a
post-RSM hook, and is a step towards removing the .vcpu_pre_run() hook
entirely.
Alternatively, KVM could provide a post-RSM hook as mentioned, but pre/post
hooks tend to be unwieldy as the exact "timing" of the call often matters
greatly. E.g. in this case, the call must slot in exactly between loading
guest state from SMRAM and the hack to force the vCPU out of L2 on SHUTDOWN.
Signed-off-by: Sean Christopherson <seanjc@google.com>
---
arch/x86/include/asm/kvm-x86-ops.h | 1 +
arch/x86/include/asm/kvm_host.h | 2 ++
arch/x86/kvm/vmx/main.c | 15 +++++++++++++--
arch/x86/kvm/vmx/vmx.c | 12 +-----------
arch/x86/kvm/vmx/x86_ops.h | 2 +-
arch/x86/kvm/x86.c | 5 +++++
6 files changed, 23 insertions(+), 14 deletions(-)
diff --git a/arch/x86/include/asm/kvm-x86-ops.h b/arch/x86/include/asm/kvm-x86-ops.h
index 5cb132eca3c3..e5b0458afc25 100644
--- a/arch/x86/include/asm/kvm-x86-ops.h
+++ b/arch/x86/include/asm/kvm-x86-ops.h
@@ -68,6 +68,7 @@ KVM_X86_OP(vcpu_run)
KVM_X86_OP(handle_exit)
KVM_X86_OP(skip_emulated_instruction)
KVM_X86_OP_OPTIONAL(update_emulated_instruction)
+KVM_X86_OP_OPTIONAL_RET0(unhandleable_emulation_required)
KVM_X86_OP(set_interrupt_shadow)
KVM_X86_OP(get_interrupt_shadow)
KVM_X86_OP(patch_hypercall)
diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h
index 7a258831616f..7e3cacb2df9b 100644
--- a/arch/x86/include/asm/kvm_host.h
+++ b/arch/x86/include/asm/kvm_host.h
@@ -1593,6 +1593,8 @@ struct kvm_x86_ops {
enum exit_fastpath_completion exit_fastpath);
int (*skip_emulated_instruction)(struct kvm_vcpu *vcpu);
void (*update_emulated_instruction)(struct kvm_vcpu *vcpu);
+ bool (*unhandleable_emulation_required)(struct kvm_vcpu *vcpu);
+
void (*set_interrupt_shadow)(struct kvm_vcpu *vcpu, int mask);
u32 (*get_interrupt_shadow)(struct kvm_vcpu *vcpu);
void (*patch_hypercall)(struct kvm_vcpu *vcpu,
diff --git a/arch/x86/kvm/vmx/main.c b/arch/x86/kvm/vmx/main.c
index 04f986e3d439..924a629c21e2 100644
--- a/arch/x86/kvm/vmx/main.c
+++ b/arch/x86/kvm/vmx/main.c
@@ -145,7 +145,7 @@ static int vt_vcpu_pre_run(struct kvm_vcpu *vcpu)
if (is_td_vcpu(vcpu))
return tdx_vcpu_pre_run(vcpu);
- return vmx_vcpu_pre_run(vcpu);
+ return 1;
}
static fastpath_t vt_vcpu_run(struct kvm_vcpu *vcpu, u64 run_flags)
@@ -165,6 +165,16 @@ static int vt_handle_exit(struct kvm_vcpu *vcpu,
return vmx_handle_exit(vcpu, fastpath);
}
+static bool vt_unhandleable_emulation_required(struct kvm_vcpu *vcpu)
+{
+ if (is_td_vcpu(vcpu)) {
+ WARN_ON_ONCE(to_vt(vcpu)->emulation_required);
+ return false;
+ }
+
+ return vmx_unhandleable_emulation_required(vcpu);
+}
+
static int vt_set_msr(struct kvm_vcpu *vcpu, struct msr_data *msr_info)
{
if (unlikely(is_td_vcpu(vcpu)))
@@ -939,11 +949,12 @@ struct kvm_x86_ops vt_x86_ops __initdata = {
.flush_tlb_gva = vt_op(flush_tlb_gva),
.flush_tlb_guest = vt_op(flush_tlb_guest),
- .vcpu_pre_run = vt_op(vcpu_pre_run),
+ .vcpu_pre_run = vt_op_tdx_only(vcpu_pre_run),
.vcpu_run = vt_op(vcpu_run),
.handle_exit = vt_op(handle_exit),
.skip_emulated_instruction = vmx_skip_emulated_instruction,
.update_emulated_instruction = vmx_update_emulated_instruction,
+ .unhandleable_emulation_required = vt_op(unhandleable_emulation_required),
.set_interrupt_shadow = vt_op(set_interrupt_shadow),
.get_interrupt_shadow = vt_op(get_interrupt_shadow),
.patch_hypercall = vt_op(patch_hypercall),
diff --git a/arch/x86/kvm/vmx/vmx.c b/arch/x86/kvm/vmx/vmx.c
index e4b9ac7fed9f..76160adf8297 100644
--- a/arch/x86/kvm/vmx/vmx.c
+++ b/arch/x86/kvm/vmx/vmx.c
@@ -6035,7 +6035,7 @@ static int handle_nmi_window(struct kvm_vcpu *vcpu)
* with unsrestricted guest mode disabled) and KVM can't faithfully emulate the
* current vCPU state.
*/
-static bool vmx_unhandleable_emulation_required(struct kvm_vcpu *vcpu)
+bool vmx_unhandleable_emulation_required(struct kvm_vcpu *vcpu)
{
struct vcpu_vmx *vmx = to_vmx(vcpu);
@@ -6110,16 +6110,6 @@ static int handle_invalid_guest_state(struct kvm_vcpu *vcpu)
return 1;
}
-int vmx_vcpu_pre_run(struct kvm_vcpu *vcpu)
-{
- if (vmx_unhandleable_emulation_required(vcpu)) {
- kvm_prepare_emulation_failure_exit(vcpu);
- return 0;
- }
-
- return 1;
-}
-
/*
* Indicate a busy-waiting vcpu in spinlock. We do not enable the PAUSE
* exiting, so only get here on cpu with PAUSE-Loop-Exiting.
diff --git a/arch/x86/kvm/vmx/x86_ops.h b/arch/x86/kvm/vmx/x86_ops.h
index 409858074246..4d2dd88afe7f 100644
--- a/arch/x86/kvm/vmx/x86_ops.h
+++ b/arch/x86/kvm/vmx/x86_ops.h
@@ -21,7 +21,6 @@ int vmx_vm_init(struct kvm *kvm);
void vmx_vm_destroy(struct kvm *kvm);
int vmx_vcpu_precreate(struct kvm *kvm);
int vmx_vcpu_create(struct kvm_vcpu *vcpu);
-int vmx_vcpu_pre_run(struct kvm_vcpu *vcpu);
fastpath_t vmx_vcpu_run(struct kvm_vcpu *vcpu, u64 run_flags);
void vmx_vcpu_free(struct kvm_vcpu *vcpu);
void vmx_vcpu_reset(struct kvm_vcpu *vcpu, bool init_event);
@@ -31,6 +30,7 @@ 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);
int vmx_set_msr(struct kvm_vcpu *vcpu, struct msr_data *msr_info);
#ifdef CONFIG_KVM_SMM
int vmx_smi_allowed(struct kvm_vcpu *vcpu, bool for_injection);
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
index 0f1a829032c0..64a13acc37be 100644
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -8867,6 +8867,11 @@ static int kvm_x86_vcpu_pre_run(struct kvm_vcpu *vcpu)
!kvm_apic_init_sipi_allowed(vcpu))
return -EINVAL;
+ if (kvm_x86_call(unhandleable_emulation_required)(vcpu)) {
+ kvm_prepare_emulation_failure_exit(vcpu);
+ return 0;
+ }
+
return kvm_x86_call(vcpu_pre_run)(vcpu);
}
--
2.55.0.229.g6434b31f56-goog
next prev parent reply other threads:[~2026-07-28 0:43 UTC|newest]
Thread overview: 11+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-07-28 0:43 [PATCH v4 0/6] KVM: nVMX: Synthesize SHUTDOWN on RSM with bad state Sean Christopherson
2026-07-28 0:43 ` Sean Christopherson [this message]
2026-07-28 0:58 ` [PATCH v4 1/6] KVM: x86: Extract VMX's unhandleable emulation check to common x86 sashiko-bot
2026-07-28 1:01 ` Sean Christopherson
2026-07-28 0:43 ` [PATCH v4 2/6] KVM: nVMX: Synthesize SHUTDOWN on RSM if L2 requires emulation Sean Christopherson
2026-07-28 0:43 ` [PATCH v4 3/6] KVM: x86: Rework kvm_x86_ops.vcpu_pre_run() into .vcpu_needs_initialization() Sean Christopherson
2026-07-28 0:43 ` [PATCH v4 4/6] KVM: selftests: Use port 0x80 in invalid nVMX guest state test Sean Christopherson
2026-07-28 0:43 ` [PATCH v4 5/6] KVM: selftests: Refactor invalid nVMX state test to prepare for RSM testcase Sean Christopherson
2026-07-28 0:51 ` sashiko-bot
2026-07-28 0:43 ` [PATCH v4 6/6] KVM: selftests: Extend the invalid nVMX guest state test to cover RSM Sean Christopherson
2026-07-28 3:01 ` Hao Zhang
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=20260728004351.887076-2-seanjc@google.com \
--to=seanjc@google.com \
--cc=kvm@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=pbonzini@redhat.com \
--cc=zhanghao1@kylinos.cn \
/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