* [PATCH v3 0/4] KVM: x86: Virtualize AMD's "disable CPUID in usermode"
@ 2026-05-13 22:46 Jim Mattson
2026-05-13 22:46 ` [PATCH v3 1/4] KVM: x86: Consolidate CPUID fault handling for emulator and interception logic Jim Mattson
` (3 more replies)
0 siblings, 4 replies; 7+ messages in thread
From: Jim Mattson @ 2026-05-13 22:46 UTC (permalink / raw)
To: seanjc, pbonzini, tglx, mingo, bp, dave.hansen, x86, hpa, shuah,
kvm, linux-kernel, linux-kselftest, ctpence
Cc: Jim Mattson
AMD's "disable CPUID in usermode" feature is analogous to Intel's "CPUID
faulting" feature, but it is advertised and activated differently. The AMD
feature is advertised via CPUID.80000021H:EAX.CpuidUserDis[bit 17] and
activated by setting HWCR.CpuidUserDis[bit 35].
Add virtualization support for the AMD feature.
v2 -> v3:
* Logic consolidation between emulator and CPUID VM-exit handler [Sean]
* Define MSR_K7_HWCR_CPUID_USER_DIS
* Keep u64 in the selftest (oops)
* Fixe the selftest failre on Intel hosts
v1: https://lore.kernel.org/kvm/20260402223108.650572-1-jmattson@google.com/
v2: https://lore.kernel.org/kvm/20260508170714.489136-1-jmattson@google.com/
Jim Mattson (3):
KVM: x86: Remove supports_cpuid_fault() helper
KVM: x86: Virtualize AMD CPUID faulting
KVM: selftests: Update hwcr_msr_test for CPUID faulting bit
Sean Christopherson (1):
KVM: x86: Consolidate CPUID fault handling for emulator and
interception logic
arch/x86/include/asm/kvm_host.h | 1 -
arch/x86/include/asm/msr-index.h | 1 +
arch/x86/kvm/cpuid.c | 7 ++--
arch/x86/kvm/cpuid.h | 14 ++++---
arch/x86/kvm/emulate.c | 6 +--
arch/x86/kvm/kvm_emulate.h | 1 +
arch/x86/kvm/x86.c | 38 +++++++++----------
.../selftests/kvm/include/x86/processor.h | 1 +
.../testing/selftests/kvm/x86/hwcr_msr_test.c | 9 ++++-
9 files changed, 43 insertions(+), 35 deletions(-)
base-commit: 85f871f6ba46f20d7fbc0b016b4db648c33220dd
--
2.54.0.631.ge1b05301d1-goog
^ permalink raw reply [flat|nested] 7+ messages in thread
* [PATCH v3 1/4] KVM: x86: Consolidate CPUID fault handling for emulator and interception logic
2026-05-13 22:46 [PATCH v3 0/4] KVM: x86: Virtualize AMD's "disable CPUID in usermode" Jim Mattson
@ 2026-05-13 22:46 ` Jim Mattson
2026-05-14 8:41 ` Binbin Wu
2026-05-13 22:46 ` [PATCH v3 2/4] KVM: x86: Remove supports_cpuid_fault() helper Jim Mattson
` (2 subsequent siblings)
3 siblings, 1 reply; 7+ messages in thread
From: Jim Mattson @ 2026-05-13 22:46 UTC (permalink / raw)
To: seanjc, pbonzini, tglx, mingo, bp, dave.hansen, x86, hpa, shuah,
kvm, linux-kernel, linux-kselftest, ctpence
Cc: Jim Mattson
From: Sean Christopherson <seanjc@google.com>
Extract the logic for emulating CPUID faulting (where CPUID #GPs at CPL>0
outside of SMM) into a dedicated helper and use the helper for both the
full emulator and the intercepted-CPUID paths.
Opportunistically drop kvm_require_cpl(), as kvm_require_cpl() was the one
and only user.
No functional change intended.
Signed-off-by: Sean Christopherson <seanjc@google.com>
Signed-off-by: Jim Mattson <jmattson@google.com>
---
arch/x86/include/asm/kvm_host.h | 1 -
arch/x86/kvm/cpuid.c | 5 +++--
arch/x86/kvm/cpuid.h | 8 ++++++++
arch/x86/kvm/emulate.c | 6 +-----
arch/x86/kvm/kvm_emulate.h | 1 +
arch/x86/kvm/x86.c | 18 ++++++------------
6 files changed, 19 insertions(+), 20 deletions(-)
diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h
index c470e40a00aa..a9005c61619b 100644
--- a/arch/x86/include/asm/kvm_host.h
+++ b/arch/x86/include/asm/kvm_host.h
@@ -2285,7 +2285,6 @@ void kvm_requeue_exception(struct kvm_vcpu *vcpu, unsigned int nr,
void kvm_inject_page_fault(struct kvm_vcpu *vcpu, struct x86_exception *fault);
void kvm_inject_emulated_page_fault(struct kvm_vcpu *vcpu,
struct x86_exception *fault);
-bool kvm_require_cpl(struct kvm_vcpu *vcpu, int required_cpl);
bool kvm_require_dr(struct kvm_vcpu *vcpu, int dr);
static inline int __kvm_irq_line_state(unsigned long *irq_state,
diff --git a/arch/x86/kvm/cpuid.c b/arch/x86/kvm/cpuid.c
index e69156b54cff..1c95d1fa3ead 100644
--- a/arch/x86/kvm/cpuid.c
+++ b/arch/x86/kvm/cpuid.c
@@ -2161,9 +2161,10 @@ int kvm_emulate_cpuid(struct kvm_vcpu *vcpu)
{
u32 eax, ebx, ecx, edx;
- if (!is_smm(vcpu) && cpuid_fault_enabled(vcpu) &&
- !kvm_require_cpl(vcpu, 0))
+ if (!kvm_is_cpuid_allowed(vcpu)) {
+ kvm_queue_exception_e(vcpu, GP_VECTOR, 0);
return 1;
+ }
eax = kvm_rax_read(vcpu);
ecx = kvm_rcx_read(vcpu);
diff --git a/arch/x86/kvm/cpuid.h b/arch/x86/kvm/cpuid.h
index 039b8e6f40ba..bc4a8428b836 100644
--- a/arch/x86/kvm/cpuid.h
+++ b/arch/x86/kvm/cpuid.h
@@ -7,6 +7,8 @@
#include <asm/processor.h>
#include <uapi/asm/kvm_para.h>
+#include "smm.h"
+
extern u32 kvm_cpu_caps[NR_KVM_CPU_CAPS] __read_mostly;
extern bool kvm_is_configuring_cpu_caps __read_mostly;
@@ -192,6 +194,12 @@ static inline bool cpuid_fault_enabled(struct kvm_vcpu *vcpu)
MSR_MISC_FEATURES_ENABLES_CPUID_FAULT;
}
+static inline bool kvm_is_cpuid_allowed(struct kvm_vcpu *vcpu)
+{
+ return !cpuid_fault_enabled(vcpu) || is_smm(vcpu) ||
+ !kvm_x86_call(get_cpl)(vcpu);
+}
+
static __always_inline void kvm_cpu_cap_clear(unsigned int x86_feature)
{
unsigned int x86_leaf = __feature_leaf(x86_feature);
diff --git a/arch/x86/kvm/emulate.c b/arch/x86/kvm/emulate.c
index c8c6cc0406d6..3ba09093b5ab 100644
--- a/arch/x86/kvm/emulate.c
+++ b/arch/x86/kvm/emulate.c
@@ -3593,12 +3593,8 @@ static int em_sti(struct x86_emulate_ctxt *ctxt)
static int em_cpuid(struct x86_emulate_ctxt *ctxt)
{
u32 eax, ebx, ecx, edx;
- u64 msr = 0;
- ctxt->ops->get_msr(ctxt, MSR_MISC_FEATURES_ENABLES, &msr);
- if (!ctxt->ops->is_smm(ctxt) &&
- (msr & MSR_MISC_FEATURES_ENABLES_CPUID_FAULT) &&
- ctxt->ops->cpl(ctxt))
+ if (!ctxt->ops->is_cpuid_allowed(ctxt))
return emulate_gp(ctxt, 0);
eax = reg_read(ctxt, VCPU_REGS_RAX);
diff --git a/arch/x86/kvm/kvm_emulate.h b/arch/x86/kvm/kvm_emulate.h
index 0abff36d0994..45d4a03b202e 100644
--- a/arch/x86/kvm/kvm_emulate.h
+++ b/arch/x86/kvm/kvm_emulate.h
@@ -225,6 +225,7 @@ struct x86_emulate_ops {
struct x86_instruction_info *info,
enum x86_intercept_stage stage);
+ bool (*is_cpuid_allowed)(struct x86_emulate_ctxt *ctxt);
bool (*get_cpuid)(struct x86_emulate_ctxt *ctxt, u32 *eax, u32 *ebx,
u32 *ecx, u32 *edx, bool exact_only);
bool (*guest_has_movbe)(struct x86_emulate_ctxt *ctxt);
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
index 0a1b63c63d1a..01c6b18d1fe5 100644
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -1021,18 +1021,6 @@ void kvm_queue_exception_e(struct kvm_vcpu *vcpu, unsigned nr, u32 error_code)
}
EXPORT_SYMBOL_FOR_KVM_INTERNAL(kvm_queue_exception_e);
-/*
- * Checks if cpl <= required_cpl; if true, return true. Otherwise queue
- * a #GP and return false.
- */
-bool kvm_require_cpl(struct kvm_vcpu *vcpu, int required_cpl)
-{
- if (kvm_x86_call(get_cpl)(vcpu) <= required_cpl)
- return true;
- kvm_queue_exception_e(vcpu, GP_VECTOR, 0);
- return false;
-}
-
bool kvm_require_dr(struct kvm_vcpu *vcpu, int dr)
{
if ((dr != 4 && dr != 5) || !kvm_is_cr4_bit_set(vcpu, X86_CR4_DE))
@@ -8819,6 +8807,11 @@ static int emulator_intercept(struct x86_emulate_ctxt *ctxt,
&ctxt->exception);
}
+static bool emulator_is_cpuid_allowed(struct x86_emulate_ctxt *ctxt)
+{
+ return kvm_is_cpuid_allowed(emul_to_vcpu(ctxt));
+}
+
static bool emulator_get_cpuid(struct x86_emulate_ctxt *ctxt,
u32 *eax, u32 *ebx, u32 *ecx, u32 *edx,
bool exact_only)
@@ -8955,6 +8948,7 @@ static const struct x86_emulate_ops emulate_ops = {
.wbinvd = emulator_wbinvd,
.fix_hypercall = emulator_fix_hypercall,
.intercept = emulator_intercept,
+ .is_cpuid_allowed = emulator_is_cpuid_allowed,
.get_cpuid = emulator_get_cpuid,
.guest_has_movbe = emulator_guest_has_movbe,
.guest_has_fxsr = emulator_guest_has_fxsr,
--
2.54.0.631.ge1b05301d1-goog
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [PATCH v3 2/4] KVM: x86: Remove supports_cpuid_fault() helper
2026-05-13 22:46 [PATCH v3 0/4] KVM: x86: Virtualize AMD's "disable CPUID in usermode" Jim Mattson
2026-05-13 22:46 ` [PATCH v3 1/4] KVM: x86: Consolidate CPUID fault handling for emulator and interception logic Jim Mattson
@ 2026-05-13 22:46 ` Jim Mattson
2026-05-14 8:51 ` Binbin Wu
2026-05-13 22:46 ` [PATCH v3 3/4] KVM: x86: Virtualize AMD CPUID faulting Jim Mattson
2026-05-13 22:46 ` [PATCH v3 4/4] KVM: selftests: Update hwcr_msr_test for CPUID faulting bit Jim Mattson
3 siblings, 1 reply; 7+ messages in thread
From: Jim Mattson @ 2026-05-13 22:46 UTC (permalink / raw)
To: seanjc, pbonzini, tglx, mingo, bp, dave.hansen, x86, hpa, shuah,
kvm, linux-kernel, linux-kselftest, ctpence
Cc: Jim Mattson
The function, supports_cpuid_fault(), tests specifically for guest support
of Intel's CPUID faulting feature. It does not test for guest support of
AMD's CPUID faulting feature.
To avoid confusion, remove the helper.
Signed-off-by: Jim Mattson <jmattson@google.com>
---
arch/x86/kvm/cpuid.h | 5 -----
arch/x86/kvm/x86.c | 2 +-
2 files changed, 1 insertion(+), 6 deletions(-)
diff --git a/arch/x86/kvm/cpuid.h b/arch/x86/kvm/cpuid.h
index bc4a8428b836..95d09ccbf951 100644
--- a/arch/x86/kvm/cpuid.h
+++ b/arch/x86/kvm/cpuid.h
@@ -183,11 +183,6 @@ static inline int guest_cpuid_stepping(struct kvm_vcpu *vcpu)
return x86_stepping(best->eax);
}
-static inline bool supports_cpuid_fault(struct kvm_vcpu *vcpu)
-{
- return vcpu->arch.msr_platform_info & MSR_PLATFORM_INFO_CPUID_FAULT;
-}
-
static inline bool cpuid_fault_enabled(struct kvm_vcpu *vcpu)
{
return vcpu->arch.msr_misc_features_enables &
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
index 01c6b18d1fe5..c60773349f35 100644
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -4252,7 +4252,7 @@ int kvm_set_msr_common(struct kvm_vcpu *vcpu, struct msr_data *msr_info)
case MSR_MISC_FEATURES_ENABLES:
if (data & ~MSR_MISC_FEATURES_ENABLES_CPUID_FAULT ||
(data & MSR_MISC_FEATURES_ENABLES_CPUID_FAULT &&
- !supports_cpuid_fault(vcpu)))
+ !(vcpu->arch.msr_platform_info & MSR_PLATFORM_INFO_CPUID_FAULT)))
return 1;
vcpu->arch.msr_misc_features_enables = data;
break;
--
2.54.0.631.ge1b05301d1-goog
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [PATCH v3 3/4] KVM: x86: Virtualize AMD CPUID faulting
2026-05-13 22:46 [PATCH v3 0/4] KVM: x86: Virtualize AMD's "disable CPUID in usermode" Jim Mattson
2026-05-13 22:46 ` [PATCH v3 1/4] KVM: x86: Consolidate CPUID fault handling for emulator and interception logic Jim Mattson
2026-05-13 22:46 ` [PATCH v3 2/4] KVM: x86: Remove supports_cpuid_fault() helper Jim Mattson
@ 2026-05-13 22:46 ` Jim Mattson
2026-05-13 22:46 ` [PATCH v3 4/4] KVM: selftests: Update hwcr_msr_test for CPUID faulting bit Jim Mattson
3 siblings, 0 replies; 7+ messages in thread
From: Jim Mattson @ 2026-05-13 22:46 UTC (permalink / raw)
To: seanjc, pbonzini, tglx, mingo, bp, dave.hansen, x86, hpa, shuah,
kvm, linux-kernel, linux-kselftest, ctpence
Cc: Jim Mattson
On AMD CPUs, CPUID faulting support is advertised via
CPUID.80000021H:EAX.CpuidUserDis[bit 17] and enabled by setting
HWCR.CpuidUserDis[bit 35].
Advertise the feature to userspace regardless of host CPU support. Allow
writes to HWCR to set bit 35 when the guest CPUID advertises
CpuidUserDis. Update cpuid_fault_enabled() to check HWCR.CpuidUserDis
as well as MSR_FEATURE_ENABLES.CPUID_GP_ON_CPL_GT_0.
Signed-off-by: Jim Mattson <jmattson@google.com>
---
arch/x86/include/asm/msr-index.h | 1 +
arch/x86/kvm/cpuid.c | 2 +-
arch/x86/kvm/cpuid.h | 5 +++--
arch/x86/kvm/x86.c | 18 ++++++++++++------
4 files changed, 17 insertions(+), 9 deletions(-)
diff --git a/arch/x86/include/asm/msr-index.h b/arch/x86/include/asm/msr-index.h
index 6673601246b3..0eeae121b0a6 100644
--- a/arch/x86/include/asm/msr-index.h
+++ b/arch/x86/include/asm/msr-index.h
@@ -888,6 +888,7 @@
#define MSR_K7_HWCR_IRPERF_EN_BIT 30
#define MSR_K7_HWCR_IRPERF_EN BIT_ULL(MSR_K7_HWCR_IRPERF_EN_BIT)
#define MSR_K7_HWCR_CPUID_USER_DIS_BIT 35
+#define MSR_K7_HWCR_CPUID_USER_DIS BIT_ULL(MSR_K7_HWCR_CPUID_USER_DIS_BIT)
#define MSR_K7_FID_VID_CTL 0xc0010041
#define MSR_K7_FID_VID_STATUS 0xc0010042
#define MSR_K7_HWCR_CPB_DIS_BIT 25
diff --git a/arch/x86/kvm/cpuid.c b/arch/x86/kvm/cpuid.c
index 1c95d1fa3ead..8e5340dd2621 100644
--- a/arch/x86/kvm/cpuid.c
+++ b/arch/x86/kvm/cpuid.c
@@ -1248,7 +1248,7 @@ void kvm_initialize_cpu_caps(void)
F(AUTOIBRS),
EMULATED_F(NO_SMM_CTL_MSR),
/* PrefetchCtlMsr */
- /* GpOnUserCpuid */
+ EMULATED_F(GP_ON_USER_CPUID),
/* EPSF */
F(PREFETCHI),
F(AVX512_BMM),
diff --git a/arch/x86/kvm/cpuid.h b/arch/x86/kvm/cpuid.h
index 95d09ccbf951..fc96ba86c644 100644
--- a/arch/x86/kvm/cpuid.h
+++ b/arch/x86/kvm/cpuid.h
@@ -185,8 +185,9 @@ static inline int guest_cpuid_stepping(struct kvm_vcpu *vcpu)
static inline bool cpuid_fault_enabled(struct kvm_vcpu *vcpu)
{
- return vcpu->arch.msr_misc_features_enables &
- MSR_MISC_FEATURES_ENABLES_CPUID_FAULT;
+ return (vcpu->arch.msr_misc_features_enables &
+ MSR_MISC_FEATURES_ENABLES_CPUID_FAULT) ||
+ (vcpu->arch.msr_hwcr & MSR_K7_HWCR_CPUID_USER_DIS);
}
static inline bool kvm_is_cpuid_allowed(struct kvm_vcpu *vcpu)
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
index c60773349f35..6581018db16b 100644
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -3990,22 +3990,28 @@ int kvm_set_msr_common(struct kvm_vcpu *vcpu, struct msr_data *msr_info)
break;
case MSR_EFER:
return set_efer(vcpu, msr_info);
- case MSR_K7_HWCR:
- data &= ~(u64)0x40; /* ignore flush filter disable */
- data &= ~(u64)0x100; /* ignore ignne emulation enable */
- data &= ~(u64)0x8; /* ignore TLB cache disable */
-
+ case MSR_K7_HWCR: {
/*
* Allow McStatusWrEn and TscFreqSel. (Linux guests from v3.2
* through at least v6.6 whine if TscFreqSel is clear,
* depending on F/M/S.
*/
- if (data & ~(BIT_ULL(18) | BIT_ULL(24))) {
+ u64 valid = BIT_ULL(18) | BIT_ULL(24);
+
+ data &= ~(u64)0x40; /* ignore flush filter disable */
+ data &= ~(u64)0x100; /* ignore ignne emulation enable */
+ data &= ~(u64)0x8; /* ignore TLB cache disable */
+
+ if (guest_cpu_cap_has(vcpu, X86_FEATURE_GP_ON_USER_CPUID))
+ valid |= MSR_K7_HWCR_CPUID_USER_DIS;
+
+ if (data & ~valid) {
kvm_pr_unimpl_wrmsr(vcpu, msr, data);
return 1;
}
vcpu->arch.msr_hwcr = data;
break;
+ }
case MSR_FAM10H_MMIO_CONF_BASE:
if (data != 0) {
kvm_pr_unimpl_wrmsr(vcpu, msr, data);
--
2.54.0.631.ge1b05301d1-goog
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [PATCH v3 4/4] KVM: selftests: Update hwcr_msr_test for CPUID faulting bit
2026-05-13 22:46 [PATCH v3 0/4] KVM: x86: Virtualize AMD's "disable CPUID in usermode" Jim Mattson
` (2 preceding siblings ...)
2026-05-13 22:46 ` [PATCH v3 3/4] KVM: x86: Virtualize AMD CPUID faulting Jim Mattson
@ 2026-05-13 22:46 ` Jim Mattson
3 siblings, 0 replies; 7+ messages in thread
From: Jim Mattson @ 2026-05-13 22:46 UTC (permalink / raw)
To: seanjc, pbonzini, tglx, mingo, bp, dave.hansen, x86, hpa, shuah,
kvm, linux-kernel, linux-kselftest, ctpence
Cc: Jim Mattson
Add BIT_ULL(35) (CpuidUserDis) to the valid mask in hwcr_msr_test, now that
KVM accepts writes to this bit when the guest CPUID advertises
CpuidUserDis.
Signed-off-by: Jim Mattson <jmattson@google.com>
---
tools/testing/selftests/kvm/include/x86/processor.h | 1 +
tools/testing/selftests/kvm/x86/hwcr_msr_test.c | 9 +++++++--
2 files changed, 8 insertions(+), 2 deletions(-)
diff --git a/tools/testing/selftests/kvm/include/x86/processor.h b/tools/testing/selftests/kvm/include/x86/processor.h
index 77f576ee7789..9cb1efd910ec 100644
--- a/tools/testing/selftests/kvm/include/x86/processor.h
+++ b/tools/testing/selftests/kvm/include/x86/processor.h
@@ -209,6 +209,7 @@ struct kvm_x86_cpu_feature {
#define X86_FEATURE_SEV KVM_X86_CPU_FEATURE(0x8000001F, 0, EAX, 1)
#define X86_FEATURE_SEV_ES KVM_X86_CPU_FEATURE(0x8000001F, 0, EAX, 3)
#define X86_FEATURE_SEV_SNP KVM_X86_CPU_FEATURE(0x8000001F, 0, EAX, 4)
+#define X86_FEATURE_GP_ON_USER_CPUID KVM_X86_CPU_FEATURE(0x80000021, 0, EAX, 17)
#define X86_FEATURE_PERFMON_V2 KVM_X86_CPU_FEATURE(0x80000022, 0, EAX, 0)
#define X86_FEATURE_LBR_PMC_FREEZE KVM_X86_CPU_FEATURE(0x80000022, 0, EAX, 2)
diff --git a/tools/testing/selftests/kvm/x86/hwcr_msr_test.c b/tools/testing/selftests/kvm/x86/hwcr_msr_test.c
index 8e20a03b3329..53b7971aa072 100644
--- a/tools/testing/selftests/kvm/x86/hwcr_msr_test.c
+++ b/tools/testing/selftests/kvm/x86/hwcr_msr_test.c
@@ -11,12 +11,17 @@
void test_hwcr_bit(struct kvm_vcpu *vcpu, unsigned int bit)
{
const u64 ignored = BIT_ULL(3) | BIT_ULL(6) | BIT_ULL(8);
- const u64 valid = BIT_ULL(18) | BIT_ULL(24);
- const u64 legal = ignored | valid;
+ u64 valid = BIT_ULL(18) | BIT_ULL(24);
u64 val = BIT_ULL(bit);
u64 actual;
+ u64 legal;
int r;
+ if (kvm_cpu_has(X86_FEATURE_GP_ON_USER_CPUID))
+ valid |= BIT_ULL(35);
+
+ legal = ignored | valid;
+
r = _vcpu_set_msr(vcpu, MSR_K7_HWCR, val);
TEST_ASSERT(val & ~legal ? !r : r == 1,
"Expected KVM_SET_MSRS(MSR_K7_HWCR) = 0x%lx to %s",
--
2.54.0.631.ge1b05301d1-goog
^ permalink raw reply related [flat|nested] 7+ messages in thread
* Re: [PATCH v3 1/4] KVM: x86: Consolidate CPUID fault handling for emulator and interception logic
2026-05-13 22:46 ` [PATCH v3 1/4] KVM: x86: Consolidate CPUID fault handling for emulator and interception logic Jim Mattson
@ 2026-05-14 8:41 ` Binbin Wu
0 siblings, 0 replies; 7+ messages in thread
From: Binbin Wu @ 2026-05-14 8:41 UTC (permalink / raw)
To: Jim Mattson
Cc: seanjc, pbonzini, tglx, mingo, bp, dave.hansen, x86, hpa, shuah,
kvm, linux-kernel, linux-kselftest, ctpence
On 5/14/2026 6:46 AM, Jim Mattson wrote:
> From: Sean Christopherson <seanjc@google.com>
>
> Extract the logic for emulating CPUID faulting (where CPUID #GPs at CPL>0
> outside of SMM) into a dedicated helper and use the helper for both the
> full emulator and the intercepted-CPUID paths.
>
> Opportunistically drop kvm_require_cpl(), as kvm_require_cpl() was the one
^
Typo:
kvm_require_cpl() -> kvm_emulate_cpuid()
> and only user.
>
> No functional change intended.
>
> Signed-off-by: Sean Christopherson <seanjc@google.com>
> Signed-off-by: Jim Mattson <jmattson@google.com>
Reviewed-by: Binbin Wu <binbin.wu@linux.intel.com>
> ---
> arch/x86/include/asm/kvm_host.h | 1 -
> arch/x86/kvm/cpuid.c | 5 +++--
> arch/x86/kvm/cpuid.h | 8 ++++++++
> arch/x86/kvm/emulate.c | 6 +-----
> arch/x86/kvm/kvm_emulate.h | 1 +
> arch/x86/kvm/x86.c | 18 ++++++------------
> 6 files changed, 19 insertions(+), 20 deletions(-)
>
> diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h
> index c470e40a00aa..a9005c61619b 100644
> --- a/arch/x86/include/asm/kvm_host.h
> +++ b/arch/x86/include/asm/kvm_host.h
> @@ -2285,7 +2285,6 @@ void kvm_requeue_exception(struct kvm_vcpu *vcpu, unsigned int nr,
> void kvm_inject_page_fault(struct kvm_vcpu *vcpu, struct x86_exception *fault);
> void kvm_inject_emulated_page_fault(struct kvm_vcpu *vcpu,
> struct x86_exception *fault);
> -bool kvm_require_cpl(struct kvm_vcpu *vcpu, int required_cpl);
> bool kvm_require_dr(struct kvm_vcpu *vcpu, int dr);
>
> static inline int __kvm_irq_line_state(unsigned long *irq_state,
> diff --git a/arch/x86/kvm/cpuid.c b/arch/x86/kvm/cpuid.c
> index e69156b54cff..1c95d1fa3ead 100644
> --- a/arch/x86/kvm/cpuid.c
> +++ b/arch/x86/kvm/cpuid.c
> @@ -2161,9 +2161,10 @@ int kvm_emulate_cpuid(struct kvm_vcpu *vcpu)
> {
> u32 eax, ebx, ecx, edx;
>
> - if (!is_smm(vcpu) && cpuid_fault_enabled(vcpu) &&
> - !kvm_require_cpl(vcpu, 0))
> + if (!kvm_is_cpuid_allowed(vcpu)) {
> + kvm_queue_exception_e(vcpu, GP_VECTOR, 0);
> return 1;
> + }
>
> eax = kvm_rax_read(vcpu);
> ecx = kvm_rcx_read(vcpu);
> diff --git a/arch/x86/kvm/cpuid.h b/arch/x86/kvm/cpuid.h
> index 039b8e6f40ba..bc4a8428b836 100644
> --- a/arch/x86/kvm/cpuid.h
> +++ b/arch/x86/kvm/cpuid.h
> @@ -7,6 +7,8 @@
> #include <asm/processor.h>
> #include <uapi/asm/kvm_para.h>
>
> +#include "smm.h"
> +
> extern u32 kvm_cpu_caps[NR_KVM_CPU_CAPS] __read_mostly;
> extern bool kvm_is_configuring_cpu_caps __read_mostly;
>
> @@ -192,6 +194,12 @@ static inline bool cpuid_fault_enabled(struct kvm_vcpu *vcpu)
> MSR_MISC_FEATURES_ENABLES_CPUID_FAULT;
> }
>
> +static inline bool kvm_is_cpuid_allowed(struct kvm_vcpu *vcpu)
> +{
> + return !cpuid_fault_enabled(vcpu) || is_smm(vcpu) ||
> + !kvm_x86_call(get_cpl)(vcpu);
> +}
> +
> static __always_inline void kvm_cpu_cap_clear(unsigned int x86_feature)
> {
> unsigned int x86_leaf = __feature_leaf(x86_feature);
> diff --git a/arch/x86/kvm/emulate.c b/arch/x86/kvm/emulate.c
> index c8c6cc0406d6..3ba09093b5ab 100644
> --- a/arch/x86/kvm/emulate.c
> +++ b/arch/x86/kvm/emulate.c
> @@ -3593,12 +3593,8 @@ static int em_sti(struct x86_emulate_ctxt *ctxt)
> static int em_cpuid(struct x86_emulate_ctxt *ctxt)
> {
> u32 eax, ebx, ecx, edx;
> - u64 msr = 0;
>
> - ctxt->ops->get_msr(ctxt, MSR_MISC_FEATURES_ENABLES, &msr);
> - if (!ctxt->ops->is_smm(ctxt) &&
> - (msr & MSR_MISC_FEATURES_ENABLES_CPUID_FAULT) &&
> - ctxt->ops->cpl(ctxt))
> + if (!ctxt->ops->is_cpuid_allowed(ctxt))
> return emulate_gp(ctxt, 0);
>
> eax = reg_read(ctxt, VCPU_REGS_RAX);
> diff --git a/arch/x86/kvm/kvm_emulate.h b/arch/x86/kvm/kvm_emulate.h
> index 0abff36d0994..45d4a03b202e 100644
> --- a/arch/x86/kvm/kvm_emulate.h
> +++ b/arch/x86/kvm/kvm_emulate.h
> @@ -225,6 +225,7 @@ struct x86_emulate_ops {
> struct x86_instruction_info *info,
> enum x86_intercept_stage stage);
>
> + bool (*is_cpuid_allowed)(struct x86_emulate_ctxt *ctxt);
> bool (*get_cpuid)(struct x86_emulate_ctxt *ctxt, u32 *eax, u32 *ebx,
> u32 *ecx, u32 *edx, bool exact_only);
> bool (*guest_has_movbe)(struct x86_emulate_ctxt *ctxt);
> diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
> index 0a1b63c63d1a..01c6b18d1fe5 100644
> --- a/arch/x86/kvm/x86.c
> +++ b/arch/x86/kvm/x86.c
> @@ -1021,18 +1021,6 @@ void kvm_queue_exception_e(struct kvm_vcpu *vcpu, unsigned nr, u32 error_code)
> }
> EXPORT_SYMBOL_FOR_KVM_INTERNAL(kvm_queue_exception_e);
>
> -/*
> - * Checks if cpl <= required_cpl; if true, return true. Otherwise queue
> - * a #GP and return false.
> - */
> -bool kvm_require_cpl(struct kvm_vcpu *vcpu, int required_cpl)
> -{
> - if (kvm_x86_call(get_cpl)(vcpu) <= required_cpl)
> - return true;
> - kvm_queue_exception_e(vcpu, GP_VECTOR, 0);
> - return false;
> -}
> -
> bool kvm_require_dr(struct kvm_vcpu *vcpu, int dr)
> {
> if ((dr != 4 && dr != 5) || !kvm_is_cr4_bit_set(vcpu, X86_CR4_DE))
> @@ -8819,6 +8807,11 @@ static int emulator_intercept(struct x86_emulate_ctxt *ctxt,
> &ctxt->exception);
> }
>
> +static bool emulator_is_cpuid_allowed(struct x86_emulate_ctxt *ctxt)
> +{
> + return kvm_is_cpuid_allowed(emul_to_vcpu(ctxt));
> +}
> +
> static bool emulator_get_cpuid(struct x86_emulate_ctxt *ctxt,
> u32 *eax, u32 *ebx, u32 *ecx, u32 *edx,
> bool exact_only)
> @@ -8955,6 +8948,7 @@ static const struct x86_emulate_ops emulate_ops = {
> .wbinvd = emulator_wbinvd,
> .fix_hypercall = emulator_fix_hypercall,
> .intercept = emulator_intercept,
> + .is_cpuid_allowed = emulator_is_cpuid_allowed,
> .get_cpuid = emulator_get_cpuid,
> .guest_has_movbe = emulator_guest_has_movbe,
> .guest_has_fxsr = emulator_guest_has_fxsr,
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH v3 2/4] KVM: x86: Remove supports_cpuid_fault() helper
2026-05-13 22:46 ` [PATCH v3 2/4] KVM: x86: Remove supports_cpuid_fault() helper Jim Mattson
@ 2026-05-14 8:51 ` Binbin Wu
0 siblings, 0 replies; 7+ messages in thread
From: Binbin Wu @ 2026-05-14 8:51 UTC (permalink / raw)
To: Jim Mattson
Cc: seanjc, pbonzini, tglx, mingo, bp, dave.hansen, x86, hpa, shuah,
kvm, linux-kernel, linux-kselftest, ctpence
On 5/14/2026 6:46 AM, Jim Mattson wrote:
> The function, supports_cpuid_fault(), tests specifically for guest support
> of Intel's CPUID faulting feature. It does not test for guest support of
> AMD's CPUID faulting feature.
>
> To avoid confusion, remove the helper.
>
> Signed-off-by: Jim Mattson <jmattson@google.com>
Reviewed-by: Binbin Wu <binbin.wu@linux.intel.com>
> ---
> arch/x86/kvm/cpuid.h | 5 -----
> arch/x86/kvm/x86.c | 2 +-
> 2 files changed, 1 insertion(+), 6 deletions(-)
>
> diff --git a/arch/x86/kvm/cpuid.h b/arch/x86/kvm/cpuid.h
> index bc4a8428b836..95d09ccbf951 100644
> --- a/arch/x86/kvm/cpuid.h
> +++ b/arch/x86/kvm/cpuid.h
> @@ -183,11 +183,6 @@ static inline int guest_cpuid_stepping(struct kvm_vcpu *vcpu)
> return x86_stepping(best->eax);
> }
>
> -static inline bool supports_cpuid_fault(struct kvm_vcpu *vcpu)
> -{
> - return vcpu->arch.msr_platform_info & MSR_PLATFORM_INFO_CPUID_FAULT;
> -}
> -
> static inline bool cpuid_fault_enabled(struct kvm_vcpu *vcpu)
> {
> return vcpu->arch.msr_misc_features_enables &
> diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
> index 01c6b18d1fe5..c60773349f35 100644
> --- a/arch/x86/kvm/x86.c
> +++ b/arch/x86/kvm/x86.c
> @@ -4252,7 +4252,7 @@ int kvm_set_msr_common(struct kvm_vcpu *vcpu, struct msr_data *msr_info)
> case MSR_MISC_FEATURES_ENABLES:
> if (data & ~MSR_MISC_FEATURES_ENABLES_CPUID_FAULT ||
> (data & MSR_MISC_FEATURES_ENABLES_CPUID_FAULT &&
> - !supports_cpuid_fault(vcpu)))
> + !(vcpu->arch.msr_platform_info & MSR_PLATFORM_INFO_CPUID_FAULT)))
> return 1;
> vcpu->arch.msr_misc_features_enables = data;
> break;
^ permalink raw reply [flat|nested] 7+ messages in thread
end of thread, other threads:[~2026-05-14 8:51 UTC | newest]
Thread overview: 7+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-05-13 22:46 [PATCH v3 0/4] KVM: x86: Virtualize AMD's "disable CPUID in usermode" Jim Mattson
2026-05-13 22:46 ` [PATCH v3 1/4] KVM: x86: Consolidate CPUID fault handling for emulator and interception logic Jim Mattson
2026-05-14 8:41 ` Binbin Wu
2026-05-13 22:46 ` [PATCH v3 2/4] KVM: x86: Remove supports_cpuid_fault() helper Jim Mattson
2026-05-14 8:51 ` Binbin Wu
2026-05-13 22:46 ` [PATCH v3 3/4] KVM: x86: Virtualize AMD CPUID faulting Jim Mattson
2026-05-13 22:46 ` [PATCH v3 4/4] KVM: selftests: Update hwcr_msr_test for CPUID faulting bit Jim Mattson
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox