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: 41+ 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-05-15 9:03 ` Xiaoyao Li
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-21 6:18 ` Binbin Wu
2026-04-17 7:35 ` [RFC PATCH 09/27] KVM: x86: Use overlays of KVM CPU capabilities Binbin Wu
2026-04-21 5:31 ` 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-21 6:43 ` 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-21 6:51 ` Binbin Wu
2026-04-17 7:36 ` Binbin Wu [this message]
2026-04-21 7:55 ` [RFC PATCH 17/27] KVM: x86: Init allowed masks for extended " Binbin Wu
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-22 8:22 ` Binbin Wu
2026-04-17 7:36 ` [RFC PATCH 22/27] KVM: x86: Verify userspace CPUID inputs in paranoid mode Binbin Wu
2026-04-22 8:59 ` Binbin Wu
2026-04-17 7:36 ` [RFC PATCH 23/27] KVM: x86: Account for runtime CPUID features " Binbin Wu
2026-04-23 2:41 ` 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-23 3:02 ` 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
2026-04-23 3:25 ` Binbin Wu
2026-05-15 8:08 ` [RFC PATCH 00/27] KVM: x86: Add a paranoid mode for CPUID verification Xiaoyao Li
2026-05-15 15:45 ` Edgecombe, Rick P
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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.