From: Binbin Wu <binbin.wu@linux.intel.com>
To: kvm@vger.kernel.org
Cc: pbonzini@redhat.com, seanjc@google.com,
rick.p.edgecombe@intel.com, xiaoyao.li@intel.com,
chao.gao@intel.com, kai.huang@intel.com,
binbin.wu@linux.intel.com
Subject: [RFC PATCH 17/27] KVM: x86: Init allowed masks for extended CPUID range in paranoid mode
Date: Fri, 17 Apr 2026 15:36:00 +0800 [thread overview]
Message-ID: <20260417073610.3246316-18-binbin.wu@linux.intel.com> (raw)
In-Reply-To: <20260417073610.3246316-1-binbin.wu@linux.intel.com>
Populate the CPUID paranoid mode validation data for the extended CPUID
range (0x80000000 through 0x80000022).
As with the basic range, each register follows one of three rules: ignored
(skipped during validation), mask/value checked, or zero checked (for
reserved or unsupported registers).
Most added extended range leaves are AMD-specific and are initialized
for the SVM overlay only. A few registers (max extended leaf, brand
string, cache line size) are relevant to all overlays but are ignored
since KVM doesn't meaningfully constrain them.
Notable leaf-specific handling:
- 0x80000000: EAX (max extended leaf) ignored for all overlays.
EBX/ECX/EDX (vendor string) ignored for SVM only.
- 0x80000001: EAX ignored for all overlays — reserved on Intel but
userspace may set it. EBX allowed mask initialized for SVM.
- 0x80000002–0x80000004: brand string, all registers ignored.
- 0x80000005: L1 cache/TLB info, ignored for SVM only.
- 0x80000006: cache info — EAX/EBX ignored for SVM, ECX ignored for
all overlays, EDX allowed mask for SVM.
- 0x80000008: EAX allowed bits 23:0 (phys/virt address widths) for
all overlays. ECX (core count/APIC ID size) for SVM only.
- 0x8000000A: SVM revision (EAX) allowed if SVM is supported.
ASID count (EBX) is ignored.
- 0x8000001A: performance optimization identifiers, intersected with
raw host CPUID.
- 0x8000001D: AMD cache topology (analogous to CPUID 4), with
sub-leaf common pattern mapping added.
- 0x8000001E: extended topology, initialized when TOPOEXT is
supported.
- 0x8000001F: EBX allows bits 11:0 only (excludes VMPL fields).
- 0x80000021: EBX allows the ERAPS size field (bits 23:16) when
ERAPS is supported.
- 0x80000022: EBX allows core performance counter count (bits 3:0)
when PERFMON_V2 is supported and PMU is enabled.
- 0x80000000: EAX (max extended leaf) is ignored for all overlays, it
could be checked in the future if needed. EBX/ECX/EDX are ignored for
SVM only.
Signed-off-by: Binbin Wu <binbin.wu@linux.intel.com>
---
arch/x86/include/asm/kvm_host.h | 13 +++++++
arch/x86/kvm/cpuid.c | 68 +++++++++++++++++++++++++++++++++
arch/x86/kvm/reverse_cpuid.h | 13 +++++++
3 files changed, 94 insertions(+)
diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h
index 90514791f0fd..2ec4d92e3e79 100644
--- a/arch/x86/include/asm/kvm_host.h
+++ b/arch/x86/include/asm/kvm_host.h
@@ -837,6 +837,19 @@ enum kvm_only_cpuid_leafs {
CPUID_1F_0_EBX,
CPUID_1F_0_ECX,
CPUID_24_0_EAX,
+ CPUID_8000_0001_EBX,
+ CPUID_8000_0006_EDX,
+ CPUID_8000_0008_EAX,
+ CPUID_8000_0008_ECX,
+ CPUID_8000_000A_EAX,
+ CPUID_8000_001A_EAX,
+ CPUID_8000_001D_EAX,
+ CPUID_8000_001D_EDX,
+ CPUID_8000_001E_EBX,
+ CPUID_8000_001E_ECX,
+ CPUID_8000_001F_EBX,
+ CPUID_8000_0021_EBX,
+ CPUID_8000_0022_EBX,
NR_KVM_CPU_CAPS_PARANOID,
NKVMCAPINTS = NR_KVM_CPU_CAPS_PARANOID - NCAPINTS,
diff --git a/arch/x86/kvm/cpuid.c b/arch/x86/kvm/cpuid.c
index 59f0b3166eaa..471733eb68d8 100644
--- a/arch/x86/kvm/cpuid.c
+++ b/arch/x86/kvm/cpuid.c
@@ -434,6 +434,7 @@ static bool __maybe_unused is_cpuid_subleaf_common_pattern(u32 func, u32 *index)
case 4:
case 0xB:
case 0x1F:
+ case 0x8000001D:
*index = 0;
return true;
case 0xD:
@@ -1310,6 +1311,18 @@ void kvm_initialize_cpu_caps(void)
F(AVX10_VNNI_INT, F_CPUID_DEFAULT),
);
+ kvm_cpu_cap_ignore(0x80000000, 0, 0, BIT(CPUID_EAX),
+ F_CPUID_DEFAULT | F_CPUID_TDX);
+ kvm_cpu_cap_ignore(0x80000000, 0, 0, BIT(CPUID_EBX) | BIT(CPUID_ECX) | BIT(CPUID_EDX),
+ F_CPUID_SVM);
+
+ /*
+ * Although EAX is reserved for Intel platforms, userspace may set it,
+ * to avoid breaking userspace, ignore it for VMX/TDX as well.
+ */
+ kvm_cpu_cap_ignore(0x80000001, 0, 0, BIT(CPUID_EAX), F_CPUID_DEFAULT | F_CPUID_TDX);
+ kvm_cpu_cap_init_mf(CPUID_8000_0001_EBX, ~GENMASK_U32(27, 16), F_CPUID_SVM);
+
kvm_cpu_cap_init(CPUID_8000_0001_ECX,
F(LAHF_LM, F_CPUID_DEFAULT | F_CPUID_TDX),
F(CMP_LEGACY, F_CPUID_DEFAULT),
@@ -1367,10 +1380,31 @@ void kvm_initialize_cpu_caps(void)
if (!tdp_enabled && IS_ENABLED(CONFIG_X86_64))
kvm_cpu_cap_set(X86_FEATURE_GBPAGES, F_CPUID_DEFAULT);
+ kvm_cpu_cap_ignore(0x80000002, 0, 0,
+ BIT(CPUID_EAX) | BIT(CPUID_EBX) | BIT(CPUID_ECX) | BIT(CPUID_EDX),
+ F_CPUID_DEFAULT | F_CPUID_TDX);
+ kvm_cpu_cap_ignore(0x80000003, 0, 0,
+ BIT(CPUID_EAX) | BIT(CPUID_EBX) | BIT(CPUID_ECX) | BIT(CPUID_EDX),
+ F_CPUID_DEFAULT | F_CPUID_TDX);
+ kvm_cpu_cap_ignore(0x80000004, 0, 0,
+ BIT(CPUID_EAX) | BIT(CPUID_EBX) | BIT(CPUID_ECX) | BIT(CPUID_EDX),
+ F_CPUID_DEFAULT | F_CPUID_TDX);
+
+ kvm_cpu_cap_ignore(0x80000005, 0, 0,
+ BIT(CPUID_EAX) | BIT(CPUID_EBX) | BIT(CPUID_ECX) | BIT(CPUID_EDX),
+ F_CPUID_SVM);
+
+ kvm_cpu_cap_ignore(0x80000006, 0, 0, BIT(CPUID_EAX) | BIT(CPUID_EBX), F_CPUID_SVM);
+ kvm_cpu_cap_ignore(0x80000006, 0, 0, BIT(CPUID_ECX), F_CPUID_DEFAULT | F_CPUID_TDX);
+ kvm_cpu_cap_init_mf(CPUID_8000_0006_EDX, ~GENMASK_U32(17, 16), F_CPUID_SVM);
+
kvm_cpu_cap_init(CPUID_8000_0007_EDX,
SCATTERED_F(CONSTANT_TSC, F_CPUID_DEFAULT | F_CPUID_TDX),
);
+ kvm_cpu_cap_init_mf(CPUID_8000_0008_EAX, GENMASK_U32(23, 0),
+ F_CPUID_DEFAULT | F_CPUID_TDX);
+
kvm_cpu_cap_init(CPUID_8000_0008_EBX,
F(CLZERO, F_CPUID_DEFAULT),
F(XSAVEERPTR, F_CPUID_DEFAULT),
@@ -1388,6 +1422,10 @@ void kvm_initialize_cpu_caps(void)
F(AMD_IBPB_RET, F_CPUID_DEFAULT),
);
+ kvm_cpu_cap_init_mf(CPUID_8000_0008_ECX, GENMASK_U32(17, 12) | GENMASK_U32(7, 0),
+ F_CPUID_SVM);
+ kvm_cpu_cap_ignore(0x80000008, 0, 0, BIT(CPUID_EDX), F_CPUID_SVM);
+
/*
* AMD has separate bits for each SPEC_CTRL bit.
* arch/x86/kernel/cpu/bugs.c is kind enough to
@@ -1415,6 +1453,11 @@ void kvm_initialize_cpu_caps(void)
!boot_cpu_has(X86_FEATURE_AMD_SSBD))
kvm_cpu_cap_set(X86_FEATURE_VIRT_SSBD, F_CPUID_SVM);
+ if (kvm_cpu_cap_has(NULL, X86_FEATURE_SVM)) {
+ kvm_cpu_cap_init_mf(CPUID_8000_000A_EAX, GENMASK_U32(7, 0), F_CPUID_SVM);
+ kvm_cpu_cap_ignore(0x8000000A, 0, 0, BIT(CPUID_EBX), F_CPUID_SVM);
+ }
+
/* All SVM features required additional vendor module enabling. */
kvm_cpu_cap_init(CPUID_8000_000A_EDX,
VENDOR_F(NPT),
@@ -1431,6 +1474,21 @@ void kvm_initialize_cpu_caps(void)
VENDOR_F(SVME_ADDR_CHK),
);
+ kvm_cpu_cap_ignore(0x80000019, 0, 0, BIT(CPUID_EAX) | BIT(CPUID_EBX), F_CPUID_SVM);
+
+ kvm_cpu_cap_check_and_init_mf(CPUID_8000_001A_EAX, GENMASK_U32(2, 0), F_CPUID_SVM);
+
+ kvm_cpu_cap_init_mf(CPUID_8000_001D_EAX, GENMASK_U32(25, 14) | GENMASK_U32(9, 0),
+ F_CPUID_SVM);
+ kvm_cpu_cap_ignore(0x8000001D, 0, -1, BIT(CPUID_EBX) | BIT(CPUID_ECX), F_CPUID_SVM);
+ kvm_cpu_cap_init_mf(CPUID_8000_001D_EDX, GENMASK_U32(1, 0), F_CPUID_SVM);
+
+ if (kvm_cpu_cap_has(NULL, X86_FEATURE_TOPOEXT)) {
+ kvm_cpu_cap_ignore(0x8000001E, 0, 0, BIT(CPUID_EAX), F_CPUID_SVM);
+ kvm_cpu_cap_init_mf(CPUID_8000_001E_EBX, GENMASK_U32(15, 0), F_CPUID_SVM);
+ kvm_cpu_cap_init_mf(CPUID_8000_001E_ECX, GENMASK_U32(10, 0), F_CPUID_SVM);
+ }
+
kvm_cpu_cap_init(CPUID_8000_001F_EAX,
VENDOR_F(SME),
VENDOR_F(SEV),
@@ -1439,6 +1497,9 @@ void kvm_initialize_cpu_caps(void)
F(SME_COHERENT, F_CPUID_DEFAULT),
);
+ /* KVM does not support VMPL */
+ kvm_cpu_cap_init_mf(CPUID_8000_001F_EBX, GENMASK_U32(11, 0), F_CPUID_SVM);
+
kvm_cpu_cap_init(CPUID_8000_0021_EAX,
F(NO_NESTED_DATA_BP, F_CPUID_DEFAULT),
F(WRMSR_XX_BASE_NS, F_CPUID_DEFAULT),
@@ -1472,6 +1533,9 @@ void kvm_initialize_cpu_caps(void)
F(SRSO_USER_KERNEL_NO, F_CPUID_DEFAULT),
);
+ if (kvm_cpu_cap_has(NULL, X86_FEATURE_ERAPS))
+ kvm_cpu_cap_init_mf(CPUID_8000_0021_EBX, GENMASK_U32(23, 16), F_CPUID_SVM);
+
kvm_cpu_cap_init(CPUID_8000_0021_ECX,
SYNTHESIZED_F(TSA_SQ_NO, F_CPUID_DEFAULT),
SYNTHESIZED_F(TSA_L1_NO, F_CPUID_DEFAULT),
@@ -1481,6 +1545,10 @@ void kvm_initialize_cpu_caps(void)
F(PERFMON_V2, F_CPUID_DEFAULT),
);
+ /* Only expose number of core performance counters. */
+ if (enable_pmu && kvm_cpu_cap_has(NULL, X86_FEATURE_PERFMON_V2))
+ kvm_cpu_cap_init_mf(CPUID_8000_0022_EBX, GENMASK_U32(3, 0), F_CPUID_SVM);
+
if (!static_cpu_has_bug(X86_BUG_NULL_SEG))
kvm_cpu_cap_set(X86_FEATURE_NULL_SEL_CLR_BASE, F_CPUID_SVM);
diff --git a/arch/x86/kvm/reverse_cpuid.h b/arch/x86/kvm/reverse_cpuid.h
index 5c7c0fbb0fec..1bdb05aaa852 100644
--- a/arch/x86/kvm/reverse_cpuid.h
+++ b/arch/x86/kvm/reverse_cpuid.h
@@ -155,6 +155,19 @@ static const struct cpuid_reg reverse_cpuid[] = {
[CPUID_1F_0_EBX] = { 0x1f, 0, CPUID_EBX},
[CPUID_1F_0_ECX] = { 0x1f, 0, CPUID_ECX},
[CPUID_24_0_EAX] = { 0x24, 0, CPUID_EAX},
+ [CPUID_8000_0001_EBX] = {0x80000001, 0, CPUID_EBX},
+ [CPUID_8000_0006_EDX] = {0x80000006, 0, CPUID_EDX},
+ [CPUID_8000_0008_EAX] = {0x80000008, 0, CPUID_EAX},
+ [CPUID_8000_0008_ECX] = {0x80000008, 0, CPUID_ECX},
+ [CPUID_8000_000A_EAX] = {0x8000000a, 0, CPUID_EAX},
+ [CPUID_8000_001A_EAX] = {0x8000001a, 0, CPUID_EAX},
+ [CPUID_8000_001D_EAX] = {0x8000001d, 0, CPUID_EAX},
+ [CPUID_8000_001D_EDX] = {0x8000001d, 0, CPUID_EDX},
+ [CPUID_8000_001E_EBX] = {0x8000001e, 0, CPUID_EBX},
+ [CPUID_8000_001E_ECX] = {0x8000001e, 0, CPUID_ECX},
+ [CPUID_8000_001F_EBX] = {0x8000001f, 0, CPUID_EBX},
+ [CPUID_8000_0021_EBX] = {0x80000021, 0, CPUID_EBX},
+ [CPUID_8000_0022_EBX] = {0x80000022, 0, CPUID_EBX},
};
/*
--
2.46.0
next prev parent reply other threads:[~2026-04-17 7:32 UTC|newest]
Thread overview: 28+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-04-17 7:35 [RFC PATCH 00/27] KVM: x86: Add a paranoid mode for CPUID verification Binbin Wu
2026-04-17 7:35 ` [RFC PATCH 01/27] KVM: x86: Fix emulated CPUID features being applied to wrong sub-leaf Binbin Wu
2026-04-17 7:35 ` [RFC PATCH 02/27] KVM: x86: Reorder the features for CPUID 7 Binbin Wu
2026-04-17 7:35 ` [RFC PATCH 03/27] KVM: x86: Add definitions for CPUID overlays Binbin Wu
2026-04-17 7:35 ` [RFC PATCH 04/27] KVM: x86: Extend F() and its variants " Binbin Wu
2026-04-17 7:35 ` [RFC PATCH 05/27] KVM: x86: Extend kvm_cpu_cap_{set/clear}() to configure overlays Binbin Wu
2026-04-17 7:35 ` [RFC PATCH 06/27] KVM: x86: Populate TDX CPUID overlay with supported feature bits Binbin Wu
2026-04-17 7:35 ` [RFC PATCH 07/27] KVM: x86: Support KVM_GET_{SUPPORTED,EMULATED}_CPUID as VM scope ioctls Binbin Wu
2026-04-17 7:35 ` [RFC PATCH 08/27] KVM: x86: Thread @kvm to KVM CPU capability helpers Binbin Wu
2026-04-17 7:35 ` [RFC PATCH 09/27] KVM: x86: Use overlays of KVM CPU capabilities Binbin Wu
2026-04-17 7:35 ` [RFC PATCH 10/27] KVM: x86: Use vendor-specific overlay flags instead of F_CPUID_DEFAULT Binbin Wu
2026-04-17 7:35 ` [RFC PATCH 11/27] KVM: SVM: Drop unnecessary clears of unsupported common x86 features Binbin Wu
2026-04-17 7:35 ` [RFC PATCH 12/27] KVM: x86: Split KVM CPU cap leafs into two parts Binbin Wu
2026-04-17 7:35 ` [RFC PATCH 13/27] KVM: x86: Add a helper to initialize CPUID multi-bit fields Binbin Wu
2026-04-17 7:35 ` [RFC PATCH 14/27] KVM: x86: Add a helper to init multiple feature bits based on raw CPUID Binbin Wu
2026-04-17 7:35 ` [RFC PATCH 15/27] KVM: x86: Add infrastructure to track CPUID entries ignored in paranoid mode Binbin Wu
2026-04-17 7:35 ` [RFC PATCH 16/27] KVM: x86: Init allowed masks for basic CPUID range " Binbin Wu
2026-04-17 7:36 ` Binbin Wu [this message]
2026-04-17 7:36 ` [RFC PATCH 18/27] KVM: x86: Handle Centaur CPUID leafs " Binbin Wu
2026-04-17 7:36 ` [RFC PATCH 19/27] KVM: x86: Track KVM PV CPUID features for " Binbin Wu
2026-04-17 7:36 ` [RFC PATCH 20/27] KVM: x86: Add per-VM flag to track CPUID " Binbin Wu
2026-04-17 7:36 ` [RFC PATCH 21/27] KVM: x86: Make kvm_vcpu_after_set_cpuid() return an error code Binbin Wu
2026-04-17 7:36 ` [RFC PATCH 22/27] KVM: x86: Verify userspace CPUID inputs in paranoid mode Binbin Wu
2026-04-17 7:36 ` [RFC PATCH 23/27] KVM: x86: Account for runtime CPUID features " Binbin Wu
2026-04-17 7:36 ` [RFC PATCH 24/27] KVM: x86: Skip paranoid CPUID check for KVM PV leafs when base is relocated Binbin Wu
2026-04-17 7:36 ` [RFC PATCH 25/27] KVM: x86: Add new KVM_CAP_X86_CPUID_PARANOID Binbin Wu
2026-04-17 7:36 ` [RFC PATCH 26/27] KVM: x86: Add a helper to query the allowed CPUID mask Binbin Wu
2026-04-17 7:36 ` [RFC PATCH 27/27] KVM: TDX: Replace hardcoded CPUID filtering with the allowed mask Binbin Wu
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=20260417073610.3246316-18-binbin.wu@linux.intel.com \
--to=binbin.wu@linux.intel.com \
--cc=chao.gao@intel.com \
--cc=kai.huang@intel.com \
--cc=kvm@vger.kernel.org \
--cc=pbonzini@redhat.com \
--cc=rick.p.edgecombe@intel.com \
--cc=seanjc@google.com \
--cc=xiaoyao.li@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