public inbox for kvm@vger.kernel.org
 help / color / mirror / Atom feed
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


  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