From: Zack Rusin <zack.rusin@broadcom.com>
To: Sean Christopherson <seanjc@google.com>,
Paolo Bonzini <pbonzini@redhat.com>,
kvm@vger.kernel.org
Cc: "Doug Covelli" <doug.covelli@broadcom.com>,
"Thomas Gleixner" <tglx@kernel.org>,
"Ingo Molnar" <mingo@redhat.com>,
"Borislav Petkov" <bp@alien8.de>,
"Dave Hansen" <dave.hansen@linux.intel.com>,
x86@kernel.org, "H. Peter Anvin" <hpa@zytor.com>,
"Jonathan Corbet" <corbet@lwn.net>,
"Randy Dunlap" <rdunlap@infradead.org>,
"Shuah Khan" <shuah@kernel.org>,
"Vitaly Kuznetsov" <vkuznets@redhat.com>,
"David Woodhouse" <dwmw2@infradead.org>,
"Paul Durrant" <paul@xen.org>, "Xin Li" <xin@zytor.com>,
"Francesco Lavra" <flavra@baylibre.com>,
"Radim Krčmář" <rkrcmar@ventanamicro.com>,
"Liran Alon" <liran.alon@oracle.com>,
"Arbel Moshe" <arbel.moshe@oracle.com>,
linux-doc@vger.kernel.org, linux-kselftest@vger.kernel.org,
bcm-kernel-feedback-list@broadcom.com,
linux-kernel@vger.kernel.org,
"Zack Rusin" <zack.rusin@broadcom.com>
Subject: [PATCH v3 03/12] KVM: x86: Encapsulate VMware backdoor checks
Date: Wed, 11 Nov 2026 00:59:52 -0500 [thread overview]
Message-ID: <76008acc660e337e7bbeab3310623a87046ac70d.1794374897.git.zack.rusin@broadcom.com> (raw)
In-Reply-To: <cover.1794374897.git.zack.rusin@broadcom.com>
Add kvm_is_vmware_backdoor_enabled(), kvm_is_vmware_io_port(),
kvm_is_vmware_backdoor_pmc() and kvm_is_vmware_backdoor_opcode(), and
use them instead of checking enable_vmware_backdoor and the VMware port
and pseudo-PMC numbers directly. Make the module parameter and the
pseudo-PMC numbers private to vmware.c, and take the backdoor port
numbers from <asm/vmware.h> instead of keeping a second copy.
The next patches make the backdoor a per-VM setting. With every caller
asking whether a vCPU accepts a VMware interface, instead of reading a
global, that change stays inside vmware.c.
Check the enabled state inside the port and pseudo-PMC predicates, so
that no caller can treat a port or PMC index as VMware's for a VM that
hasn't enabled the backdoor.
No functional change intended.
Suggested-by: Sean Christopherson <seanjc@google.com>
Link: https://lore.kernel.org/r/aIEgVpjXDR0BXgHq@google.com
Signed-off-by: Zack Rusin <zack.rusin@broadcom.com>
---
arch/x86/kvm/emulate.c | 5 +--
arch/x86/kvm/pmu.c | 6 +--
arch/x86/kvm/svm/svm.c | 6 +--
arch/x86/kvm/vmware.c | 92 +++++++++++++++++++++++++-----------------
arch/x86/kvm/vmware.h | 19 +++------
arch/x86/kvm/vmx/vmx.c | 4 +-
arch/x86/kvm/x86.c | 2 +-
7 files changed, 72 insertions(+), 62 deletions(-)
diff --git a/arch/x86/kvm/emulate.c b/arch/x86/kvm/emulate.c
index a7bcde6f0359..da626bed93c5 100644
--- a/arch/x86/kvm/emulate.c
+++ b/arch/x86/kvm/emulate.c
@@ -2539,8 +2539,7 @@ static bool emulator_io_port_access_allowed(struct x86_emulate_ctxt *ctxt,
* VMware allows access to these ports even if denied
* by TSS I/O permission bitmap. Mimic behavior.
*/
- if (enable_vmware_backdoor &&
- ((port == VMWARE_PORT_VMPORT) || (port == VMWARE_PORT_VMRPC)))
+ if (kvm_is_vmware_io_port(ctxt->vcpu, port))
return true;
ops->get_segment(ctxt, &tr, &tr_seg, &base3, VCPU_SREG_TR);
@@ -3908,7 +3907,7 @@ static int check_rdpmc(struct x86_emulate_ctxt *ctxt)
* VMware allows access to these Pseduo-PMCs even when read via RDPMC
* in Ring3 when CR4.PCE=0.
*/
- if (enable_vmware_backdoor && is_vmware_backdoor_pmc(rcx))
+ if (kvm_is_vmware_backdoor_pmc(ctxt->vcpu, rcx))
return X86EMUL_CONTINUE;
/*
diff --git a/arch/x86/kvm/pmu.c b/arch/x86/kvm/pmu.c
index ae7000c44677..dacd40ca8620 100644
--- a/arch/x86/kvm/pmu.c
+++ b/arch/x86/kvm/pmu.c
@@ -726,8 +726,8 @@ int kvm_pmu_rdpmc(struct kvm_vcpu *vcpu, unsigned idx, u64 *data)
if (!pmu->version)
return 1;
- if (enable_vmware_backdoor && is_vmware_backdoor_pmc(idx))
- return kvm_pmu_rdpmc_vmware(vcpu, idx, data);
+ if (kvm_is_vmware_backdoor_pmc(vcpu, idx))
+ return kvm_vmware_pmu_rdpmc(vcpu, idx, data);
pmc = kvm_pmu_call(rdpmc_ecx_to_pmc)(vcpu, idx, &mask);
if (!pmc)
@@ -773,7 +773,7 @@ bool kvm_need_rdpmc_intercept(struct kvm_vcpu *vcpu)
* VMware allows access to these Pseduo-PMCs even when read via RDPMC
* in Ring3 when CR4.PCE=0.
*/
- if (enable_vmware_backdoor)
+ if (kvm_is_vmware_backdoor_enabled(vcpu))
return true;
return kvm_need_any_pmc_intercept(vcpu) ||
diff --git a/arch/x86/kvm/svm/svm.c b/arch/x86/kvm/svm/svm.c
index 980841d153f3..a2196d8f60aa 100644
--- a/arch/x86/kvm/svm/svm.c
+++ b/arch/x86/kvm/svm/svm.c
@@ -237,7 +237,7 @@ int svm_set_efer(struct kvm_vcpu *vcpu, u64 efer)
svm_leave_nested(vcpu);
/* #GP intercept is still needed for vmware backdoor */
- if (!enable_vmware_backdoor)
+ if (!kvm_is_vmware_backdoor_enabled(vcpu))
clr_exception_intercept(svm, GP_VECTOR);
/*
@@ -1159,7 +1159,7 @@ static void init_vmcb(struct kvm_vcpu *vcpu, bool init_event)
* We intercept those #GP and allow access to them anyway
* as VMware does.
*/
- if (enable_vmware_backdoor)
+ if (kvm_is_vmware_backdoor_enabled(vcpu))
set_exception_intercept(svm, GP_VECTOR);
svm_set_intercept(svm, INTERCEPT_INTR);
@@ -2410,7 +2410,7 @@ static int gp_interception(struct kvm_vcpu *vcpu)
* VMware backdoor emulation on #GP interception only handles
* IN{S}, OUT{S}, and RDPMC, and only for L1.
*/
- if (!enable_vmware_backdoor || is_guest_mode(vcpu))
+ if (!kvm_is_vmware_backdoor_enabled(vcpu) || is_guest_mode(vcpu))
goto reinject;
return kvm_emulate_instruction(vcpu, EMULTYPE_VMWARE_GP | EMULTYPE_NO_DECODE);
diff --git a/arch/x86/kvm/vmware.c b/arch/x86/kvm/vmware.c
index 772f295f8ff5..e1062144b750 100644
--- a/arch/x86/kvm/vmware.c
+++ b/arch/x86/kvm/vmware.c
@@ -8,15 +8,35 @@
#include <linux/moduleparam.h>
-#include "kvm_emulate.h"
+#include <asm/vmware.h>
+
#include "vmware.h"
-bool __read_mostly enable_vmware_backdoor;
-EXPORT_SYMBOL_FOR_KVM_INTERNAL(enable_vmware_backdoor);
+static bool __read_mostly enable_vmware_backdoor;
module_param(enable_vmware_backdoor, bool, 0444);
-bool is_vmware_backdoor_pmc(u32 pmc_idx)
+#define VMWARE_BACKDOOR_PMC_HOST_TSC 0x10000
+#define VMWARE_BACKDOOR_PMC_REAL_TIME 0x10001
+#define VMWARE_BACKDOOR_PMC_APPARENT_TIME 0x10002
+
+bool kvm_is_vmware_backdoor_enabled(struct kvm_vcpu *vcpu)
{
+ return enable_vmware_backdoor;
+}
+EXPORT_SYMBOL_FOR_KVM_INTERNAL(kvm_is_vmware_backdoor_enabled);
+
+bool kvm_is_vmware_io_port(struct kvm_vcpu *vcpu, u16 port)
+{
+ return kvm_is_vmware_backdoor_enabled(vcpu) &&
+ (port == VMWARE_HYPERVISOR_PORT ||
+ port == VMWARE_HYPERVISOR_PORT_HB);
+}
+
+bool kvm_is_vmware_backdoor_pmc(struct kvm_vcpu *vcpu, u32 pmc_idx)
+{
+ if (!kvm_is_vmware_backdoor_enabled(vcpu))
+ return false;
+
switch (pmc_idx) {
case VMWARE_BACKDOOR_PMC_HOST_TSC:
case VMWARE_BACKDOOR_PMC_REAL_TIME:
@@ -26,7 +46,38 @@ bool is_vmware_backdoor_pmc(u32 pmc_idx)
return false;
}
-int kvm_pmu_rdpmc_vmware(struct kvm_vcpu *vcpu, unsigned int idx, u64 *data)
+bool kvm_is_vmware_backdoor_opcode(u8 opcode_len, u8 opcode)
+{
+ switch (opcode_len) {
+ case 1:
+ switch (opcode) {
+ case 0xe4: /* IN */
+ case 0xe5:
+ case 0xec:
+ case 0xed:
+ case 0xe6: /* OUT */
+ case 0xe7:
+ case 0xee:
+ case 0xef:
+ case 0x6c: /* INS */
+ case 0x6d:
+ case 0x6e: /* OUTS */
+ case 0x6f:
+ return true;
+ }
+ break;
+ case 2:
+ switch (opcode) {
+ case 0x33: /* RDPMC */
+ return true;
+ }
+ break;
+ }
+
+ return false;
+}
+
+int kvm_vmware_pmu_rdpmc(struct kvm_vcpu *vcpu, unsigned int idx, u64 *data)
{
u64 ctr_val;
@@ -48,34 +99,3 @@ int kvm_pmu_rdpmc_vmware(struct kvm_vcpu *vcpu, unsigned int idx, u64 *data)
*data = ctr_val;
return 0;
}
-
-bool is_vmware_backdoor_opcode(struct x86_emulate_ctxt *ctxt)
-{
- switch (ctxt->opcode_len) {
- case 1:
- switch (ctxt->b) {
- case 0xe4: /* IN */
- case 0xe5:
- case 0xec:
- case 0xed:
- case 0xe6: /* OUT */
- case 0xe7:
- case 0xee:
- case 0xef:
- case 0x6c: /* INS */
- case 0x6d:
- case 0x6e: /* OUTS */
- case 0x6f:
- return true;
- }
- break;
- case 2:
- switch (ctxt->b) {
- case 0x33: /* RDPMC */
- return true;
- }
- break;
- }
-
- return false;
-}
diff --git a/arch/x86/kvm/vmware.h b/arch/x86/kvm/vmware.h
index debabaff9654..bf250cc6e232 100644
--- a/arch/x86/kvm/vmware.h
+++ b/arch/x86/kvm/vmware.h
@@ -4,19 +4,10 @@
#include <linux/kvm_host.h>
-struct x86_emulate_ctxt;
-
-#define VMWARE_BACKDOOR_PMC_HOST_TSC 0x10000
-#define VMWARE_BACKDOOR_PMC_REAL_TIME 0x10001
-#define VMWARE_BACKDOOR_PMC_APPARENT_TIME 0x10002
-
-#define VMWARE_PORT_VMPORT (0x5658)
-#define VMWARE_PORT_VMRPC (0x5659)
-
-extern bool enable_vmware_backdoor;
-
-bool is_vmware_backdoor_pmc(u32 pmc_idx);
-int kvm_pmu_rdpmc_vmware(struct kvm_vcpu *vcpu, unsigned int idx, u64 *data);
-bool is_vmware_backdoor_opcode(struct x86_emulate_ctxt *ctxt);
+bool kvm_is_vmware_backdoor_enabled(struct kvm_vcpu *vcpu);
+bool kvm_is_vmware_io_port(struct kvm_vcpu *vcpu, u16 port);
+bool kvm_is_vmware_backdoor_pmc(struct kvm_vcpu *vcpu, u32 pmc_idx);
+bool kvm_is_vmware_backdoor_opcode(u8 opcode_len, u8 opcode);
+int kvm_vmware_pmu_rdpmc(struct kvm_vcpu *vcpu, unsigned int idx, u64 *data);
#endif /* __KVM_X86_VMWARE_H */
diff --git a/arch/x86/kvm/vmx/vmx.c b/arch/x86/kvm/vmx/vmx.c
index d407eecf1034..edcc5714cb6f 100644
--- a/arch/x86/kvm/vmx/vmx.c
+++ b/arch/x86/kvm/vmx/vmx.c
@@ -918,7 +918,7 @@ void vmx_update_exception_bitmap(struct kvm_vcpu *vcpu)
* We intercept those #GP and allow access to them anyway
* as VMware does.
*/
- if (enable_vmware_backdoor)
+ if (kvm_is_vmware_backdoor_enabled(vcpu))
eb |= (1u << GP_VECTOR);
if ((vcpu->guest_debug &
(KVM_GUESTDBG_ENABLE | KVM_GUESTDBG_USE_SW_BP)) ==
@@ -5483,7 +5483,7 @@ static int handle_exception_nmi(struct kvm_vcpu *vcpu)
error_code = vmcs_read32(VM_EXIT_INTR_ERROR_CODE);
if (!vmx->rmode.vm86_active && is_gp_fault(intr_info)) {
- WARN_ON_ONCE(!enable_vmware_backdoor);
+ WARN_ON_ONCE(!kvm_is_vmware_backdoor_enabled(vcpu));
/*
* VMware backdoor emulation on #GP interception only handles
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
index 389ae6213c85..0548e34bf634 100644
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -6402,7 +6402,7 @@ int x86_emulate_instruction(struct kvm_vcpu *vcpu, gpa_t cr2_or_gpa,
}
if ((emulation_type & EMULTYPE_VMWARE_GP) &&
- !is_vmware_backdoor_opcode(ctxt)) {
+ !kvm_is_vmware_backdoor_opcode(ctxt->opcode_len, ctxt->b)) {
kvm_queue_exception_e(vcpu, GP_VECTOR, 0);
return 1;
}
--
2.53.0
next prev parent reply other threads:[~2026-11-11 6:07 UTC|newest]
Thread overview: 13+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-11-11 5:59 [PATCH v3 00/12] KVM: Improve VMware guest support Zack Rusin
2026-11-11 5:59 ` [PATCH v3 01/12] KVM: x86/pmu: Honor enable_vmware_backdoor for VMware pseudo-PMCs Zack Rusin
2026-11-11 5:59 ` [PATCH v3 02/12] KVM: x86: Move VMware backdoor support to separate files Zack Rusin
2026-11-11 5:59 ` Zack Rusin [this message]
2026-11-11 5:59 ` [PATCH v3 04/12] KVM: x86: Add CONFIG_KVM_VMWARE Zack Rusin
2026-11-11 5:59 ` [PATCH v3 05/12] KVM: x86: Add a unified VMware capability Zack Rusin
2026-11-11 5:59 ` [PATCH v3 06/12] KVM: x86: Forward VMware hypercalls to userspace Zack Rusin
2026-11-11 5:59 ` [PATCH v3 07/12] KVM: x86: Route nested VMware backdoors to KVM Zack Rusin
2026-11-11 5:59 ` [PATCH v3 08/12] KVM: selftests: Add helpers to run x86 guest code in user mode Zack Rusin
2026-11-11 5:59 ` [PATCH v3 09/12] KVM: selftests: Port VMware backdoor coverage Zack Rusin
2026-11-11 5:59 ` [PATCH v3 10/12] KVM: selftests: Test VMware hypercall exits Zack Rusin
2026-11-11 6:00 ` [PATCH v3 11/12] KVM: selftests: Test VMware hypercall exits with nested Hyper-V flushes Zack Rusin
2026-11-11 6:00 ` [PATCH v3 12/12] KVM: selftests: Test nested VMware backdoor routing Zack Rusin
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=76008acc660e337e7bbeab3310623a87046ac70d.1794374897.git.zack.rusin@broadcom.com \
--to=zack.rusin@broadcom.com \
--cc=arbel.moshe@oracle.com \
--cc=bcm-kernel-feedback-list@broadcom.com \
--cc=bp@alien8.de \
--cc=corbet@lwn.net \
--cc=dave.hansen@linux.intel.com \
--cc=doug.covelli@broadcom.com \
--cc=dwmw2@infradead.org \
--cc=flavra@baylibre.com \
--cc=hpa@zytor.com \
--cc=kvm@vger.kernel.org \
--cc=linux-doc@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-kselftest@vger.kernel.org \
--cc=liran.alon@oracle.com \
--cc=mingo@redhat.com \
--cc=paul@xen.org \
--cc=pbonzini@redhat.com \
--cc=rdunlap@infradead.org \
--cc=rkrcmar@ventanamicro.com \
--cc=seanjc@google.com \
--cc=shuah@kernel.org \
--cc=tglx@kernel.org \
--cc=vkuznets@redhat.com \
--cc=x86@kernel.org \
--cc=xin@zytor.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®