* [PATCH v6 00/90] x86: Introduce a centralized CPUID data model
@ 2026-03-27 2:15 Ahmed S. Darwish
2026-03-27 2:15 ` [PATCH v6 01/90] ASoC: Intel: avs: Check maximum valid CPUID leaf Ahmed S. Darwish
` (91 more replies)
0 siblings, 92 replies; 101+ messages in thread
From: Ahmed S. Darwish @ 2026-03-27 2:15 UTC (permalink / raw)
To: Borislav Petkov, Dave Hansen, Ingo Molnar
Cc: Thomas Gleixner, Andrew Cooper, H. Peter Anvin,
Sean Christopherson, David Woodhouse, Peter Zijlstra,
Christian Ludloff, Sohil Mehta, John Ogness, x86, x86-cpuid, LKML,
Ahmed S. Darwish
Hi,
Introduce a centralized x86 CPUID model, tables, and API.
Rationale for this work can be found at:
https://lore.kernel.org/lkml/874ixernra.ffs@tglx
https://gitlab.com/x86-cpuid.org/x86-cpuid-db
By the end of this series, route all X86_FEATURE queries to the CPUID
tables and fully remove x86_capability[].
The introduced tables and APIs then become a "single source of truth" for
all x86 feature state, both the hardware-backed and the Linux-synthetic.
The series is divided as follows:
# Generic updates and fixes
1 ASoC: Intel: avs: Check maximum valid CPUID leaf
2 ASoC: Intel: avs: Include CPUID header at file scope
3 tools/x86/kcpuid: Update bitfields to x86-cpuid-db v3.0
# Header disentanglement (<asm/processor.h> <=> <asm/cpuid/api.h>)
4 treewide: Explicitly include the x86 CPUID headers
5 x86/cpu: <asm/processor.h>: Do not include the CPUID API header
6 x86/cpuid: Rename cpuid_leaf()/cpuid_subleaf() APIs
7 x86/cpuid: Introduce <asm/cpuid/leaf_types.h>
# CPUID Model (v6)
8 x86: Introduce a centralized CPUID data model
9 x86/cpuid: Introduce a centralized CPUID parser
10 x86/cpu: Rescan CPUID table after disabling PSN
11 x86/cpu: centaur/zhaoxin: Rescan CPUID(0xc0000001) after MSR writes
12 x86/cpu/transmeta: Rescan CPUID(0x1) after capability unhide
13 x86/cpu/intel: Rescan CPUID table after leaf unlock
# CPUID(0x0), CPUID(0x1), CPUID(0x80000000), CPUID(0x8000000[234])
14 x86/cpu: Use parsed CPUID(0x0)
15 x86/lib: Add CPUID(0x1) family and model calculation
16 x86/cpu: Use parsed CPUID(0x1)
17 x86/cpuid: Parse CPUID(0x80000000)
18 x86/cpu: Use parsed CPUID(0x80000000)
19 x86/cpuid: Parse CPUID(0x80000002) to CPUID(0x80000004)
20 x86/cpu: Use parsed CPUID(0x80000002) to CPUID(0x80000004)
# CPUID Model: x86 vendor discernment + debugfs support
21 x86/cpuid: Split parser tables and add vendor-qualified parsing
22 x86/cpuid: Introduce a parser debugfs interface
# CPUID(0x16), Transmeta CPUID(0x8086000[0123456]), Centaur CPUID(0xc000000[01])
23 x86/cpuid: Parse CPUID(0x16)
24 x86/tsc: Use parsed CPUID(0x16)
25 x86/cpuid: Parse Transmeta and Centaur extended ranges
26 x86/cpu: transmeta: Use parsed CPUID(0x80860000)->CPUID(0x80860006)
27 x86/cpu: transmeta: Refactor CPU information printing
28 x86/cpu: centaur: Use parsed CPUID(0xc0000001)
29 x86/cpu: zhaoxin: Use parsed CPUID(0xc0000001)
# Intel cache descriptors; CPUID(0x2)
30 x86/cpuid: Parse CPUID(0x2)
31 x86/cpuid: Warn once on invalid CPUID(0x2) iteration count
32 x86/cpuid: Introduce parsed CPUID(0x2) API
33 x86/cpu: Use parsed CPUID(0x2)
34 x86/cacheinfo: Use parsed CPUID(0x2)
35 x86/cpuid: Remove direct CPUID(0x2) query helpers
# Intel/AMD deterministic cache; CPUID(0x4), CPUID(0x8000001d)
36 x86/cpuid: Parse deterministic cache parameters CPUID leaves
37 x86/cacheinfo: Pass a 'struct cpuinfo_x86' refrence to CPUID(0x4) code
38 x86/cacheinfo: Use parsed CPUID(0x4)
39 x86/cacheinfo: Use parsed CPUID(0x8000001d)
# Cache/TLB/mm info; CPUID(0x8000000[568])
40 x86/cpuid: Parse CPUID(0x80000005), CPUID(0x80000006), CPUID(0x80000008)
41 x86/cacheinfo: Use auto-generated data types
42 x86/cacheinfo: Use parsed CPUID(0x80000005) and CPUID(0x80000006)
43 x86/cacheinfo: Use parsed CPUID(0x80000006)
44 x86/cpu: Use parsed CPUID(0x80000005) and CPUID(0x80000006)
45 x86/cpu/amd: Use parsed CPUID(0x80000005)
46 x86/cpu/amd: Refactor TLB detection code
47 x86/cpu/amd: Use parsed CPUID(CPUID(0x80000005) and CPUID(0x80000006)
48 x86/cpu/hygon: Use parsed CPUID(0x80000005) and CPUID(0x80000006)
49 x86/cpu/centaur: Use parsed CPUID(0x80000005)
50 x86/cpu: Use parsed CPUID(0x80000008)
# PerfMon; CPUID(0xa), CPUID(0x1c), CPUID(0x23), CPUID(0x80000022)
51 x86/cpuid: Parse CPUID(0xa) and CPUID(0x1c)
52 x86/cpu/intel: Use parsed CPUID(0xa)
53 x86/cpu/centaur: Use parsed CPUID(0xa)
54 x86/cpu/zhaoxin: Use parsed CPUID(0xa)
55 perf/x86/intel: Use parsed CPUID(0xa)
56 perf/x86/zhaoxin: Use parsed CPUID(0xa)
57 x86/xen: Use parsed CPUID(0xa)
58 KVM: x86: Use standard CPUID(0xa) types
59 KVM: x86/pmu: Use standard CPUID(0xa) types
60 perf/x86: Remove custom CPUID(0xa) types
61 perf/x86/lbr: Use parsed CPUID(0x1c)
62 perf/x86/lbr: Remove custom CPUID(0x1c) types
63 x86/cpuid: Parse CPUID(0x23)
64 perf/x86/intel: Use parsed per-CPU CPUID(0x23)
65 perf/x86/intel: Remove custom CPUID(0x23) types
66 x86/cpuid: Parse CPUID(0x80000022)
67 perf/x86/amd/lbr: Use parsed CPUID(0x80000022)
68 perf/x86/amd: Use parsed CPUID(0x80000022)
69 KVM: x86: Use standard CPUID(0x80000022) types
70 perf/x86: Remove custom CPUID(0x80000022) types
# Power management flags; CPUID(0x80000007).EBX
71 x86/cpuid: Parse CPUID(0x80000007)
72 x86/cpu: Use parsed CPUID(0x80000007)
73 x86/cpu: amd/hygon: Use parsed CPUID(0x80000007)
74 x86/cpu: cpuinfo: Use parsed CPUID(0x80000007)
75 KVM: x86: Use parsed CPUID(0x80000007)
# Model: X86_FEATURE routing to the CPUID tables
76 x86/microcode: Allocate cpuinfo_x86 snapshots on the heap
77 x86/cpuid: Parse leaves backing X86_FEATURE words
78 x86/cpuid: Parse Linux synthetic CPUID leaves
79 x86/cpuid: Introduce a compile-time X86_FEATURE word map
80 x86/cpuid: Introduce X86_FEATURE and CPUID word APIs
81 x86/percpu: Add offset argument to x86_this_cpu_test_bit()
82 x86/cpufeature: Factor out a __static_cpu_has() helper
83 x86/asm/32: Cache CPUID(0x1).EDX in cpuid_table
84 x86: Route all feature queries to the CPUID tables
# x86_capability[] removal
85 x86/cpu: Remove x86_capability[] and x86_power initialization
86 x86/cpu/transmeta: Remove x86_capability[] CPUID initialization
87 x86/cpu: centaur/zhaoxin: Remove x86_capability[] initialization
88 KVM: x86: Remove BUILD_BUG_ON() x86_capability[] check
89 x86/cpu: Remove x86_capability[] and x86_power
# Finally
90 MAINTAINERS: Extend x86 CPUID DATABASE file coverage
Changelog v6
============
This iteration adds the following:
(I.) X86_FEATURE integration
----------------------------
The X86_FEATURE words at <asm/cpufeatures.h> are of two kinds:
(a.) Hardware-defined feature words, mirroring one CPUID output register
(b.) Linux-defined x86 feature words
For the hardware-backed words, the CPUID tables and x86_capability[] fully
overlap. Route those X86_FEATURE words to the CPUID tables instead.
For the Linux-synthetic feature words, only x86_capability[] defines them
as they have no hardware backing. Unify their handling by defining them in
x86-cpuid-db as a synthetic CPUID leaf:
<leaf id="0x4c780001">
<desc>Linux-defined synthetic feature flags</desc>
<text>
This is a Linux-defined synthetic CPUID leaf, where "Linux" is a
virtual vendor mirroring hardware vendors like AMD and Intel. The leaf
ID prefix 0x4c78 is for Linux, in its shorthand ASCII form "Lx".
The bit listing mirrors what Linux defines in its synthetic X86_FEATURE
words. The listed feature bits are expected to be stable, and
allocated new bits must be filled in that order: subleaf 0 (EAX->EDX),
subleaf 1 (EAX->EDX), and so on.
</text>
<vendors>
<vendor>Linux</vendor>
</vendors>
<subleaf id="0">
<eax>
<desc>X86_FEATURE word 3: Miscellaneous flags</desc>
<!-- .. bitfields .. -->
</eax>
<ebx>
<desc>X86_FEATURE word 7: Auxiliary flags</desc>
<!-- .. bitfields .. -->
</ebx>
<ecx>
<desc>X86_FEATURE word 8: Virtualization flags</desc>
<!-- .. bitfields .. -->
</ecx>
<!-- and so on -->
</subleaf>
</leaf>
Cover all the synthetic feature and bug words by defining CPUID(0x4c780001)
subleaf 0, CPUID(0x4c780001) subleaf 1, and CPUID(0x4c780002) for the CPU
bugs words, X86_BUG.
(II.) Preserve optimized X86_FEATURE query paths
------------------------------------------------
Feature querying is one of the hottest code paths in the x86 subsystem.
This is evident from the bitops usage and the post-boot ALTERNATIVE_TERNARY
opcode patching at <asm/cpufeature.h>.
Preserve that fast path by implementing a pure compile-time mapping from an
X86_FEATURE word to a CPUID table entry in <asm/cpuid/types.h>:
#define CPUID_FEATURE_WORDS_MAP { \
/* X86_FEATURE word, Leaf, Subleaf, Output reg */ \
__cpu_feature_word(0, 0x1, 0, CPUID_EDX), \
__cpu_feature_word(1, 0x80000001, 0, CPUID_EDX), \
__cpu_feature_word(2, 0x80860001, 0, CPUID_EDX), \
__cpu_feature_word(3, 0x4c780001, 0, CPUID_EAX), \
__cpu_feature_word(4, 0x1, 0, CPUID_ECX), \
__cpu_feature_word(5, 0xc0000001, 0, CPUID_EDX), \
__cpu_feature_word(6, 0x80000001, 0, CPUID_ECX), \
__cpu_feature_word(7, 0x4c780001, 0, CPUID_EBX), \
... \
}
Ensure that all mapped X86_FEATURE words remain "unsigned long" aligned so
that bitops access continues to work. Translate an X86_FEATURE query, at
compile time, to a bitops-ready bitmap plus bit offset.
The synthetic x86-cpuid-db CPUID leaves (0x4c78 range), remove any need to
distinguish between synthetic and hardware-backed X86_FEATURE words.
Across this whole series, treat both classes identically.
(III.) Partial CPUID Table refresh APIs
---------------------------------------
The CPUID tables now host all the X86_FEATURE words, so /never/ repopulate
those tables wholesale. Doing so would corrupt the kernel maintained state
of set and cleared feature bits, for both hardware-backed and synthetic
words. This is especially true since once all direct CPUID queries are
forbidden from the kernel, the kernel will gain even more freedom to modify
the hardware-backed feature bits at will.
But... there are areas in the kernel where parts of the table need to be
refreshed. This can happen after MSR writes, where CPUID leaves can appear
or disapper, or individual feature bits within them can get set or cleared.
To handle that, introduce the partial CPUID table refresh APIs:
void cpuid_refresh_leaf(struct cpuinfo_x86 *c, u32 leaf);
void cpuid_refresh_range(struct cpuinfo_x86 *c, u32 start, u32 end);
The CPUID tables are not a normal array, but a compile-time collection of
different types. Nonetheless, a reliable implementation was found to
bridge the compile-time layout and the run-time partial refresh logic.
(IV.) Convert more CPUID leaves
-------------------------------
Convert many more call sites to the new CPUID APIs, in the ongoing quest to
forbid the CPUID instruction in all kernel code outside the CPUID parser.
Parse the CPUID leaves required for hardware-backed X86_FEATURE words:
CPUID(0x6)
CPUID(0x7).0
CPUID(0x7).1
CPUID(0xd).1
CPUID(0x80000001)
CPUID(0x80000007)
CPUID(0x80000008)
CPUID(0x8000000a)
CPUID(0x8000001f)
CPUID(0x80000021)
Parse all Transmeta and Centaur/Zhaoxin leaves, and convert their call
sites:
CPUID(0x80860000)
CPUID(0x80860001)
CPUID(0x80860002)
CPUID(0x80860003)
CPUID(0x80860004)
CPUID(0x80860005)
CPUID(0x80860006)
CPUID(0xc0000000)
CPUID(0xc0000001)
Parse and convert the call sites for the performance monitoring
(PerfMon) leaves:
CPUID(0xa)
CPUID(0x1c)
CPUID(0x23)
CPUID(0x80000022)
Remove the custom CPUID output types from perf's <asm/perf_event.h> and
use the auto generated x86-cpuid-db output types instead.
Complete all call-site conversions for:
CPUID(0x80000005)
CPUID(0x80000006)
CPUID(0x80000008)
Previous iterations converted only the cacheinfo.c logic. This iteration
also converts cpu/common.c, cpu/centaur.c, and cpu/zhaoxin.c.
(V.) Handle Boris' review remarks
---------------------------------
Get rid of the "static vs. dynamic" CPUID leaf distinction, since that
terminology does not exist in the hardware manuals. What was previously
called a dynamic leaf is now described simply as a leaf with a subleaf
range. Adjust the CPUID API function names and update all their
kernel-doc.
Reduce commit log verbosity where appropriate. In general, keep detailed
kernel-doc only for the exported call-site APIs.
Shorten function names for the CPUID parser call-site APIs; e.g.
cpuid_parse_cpu(), cpuid_refresh_leaf(), etc.
(VI.) State of affairs
----------------------
Besides the X86_FEATURE query routing, 36 CPUID leaves are now converted
to the CPUID API. Namely:
CPUID(0x0)
CPUID(0x1)
CPUID(0x2)
CPUID(0x4)
CPUID(0x6)
CPUID(0x7)
CPUID(0x7).1
CPUID(0xa)
CPUID(0xd).1
CPUID(0x16)
CPUID(0x1c)
CPUID(0x23)
CPUID(0x23).1
CPUID(0x23).2
CPUID(0x80000000)
CPUID(0x80000001)
CPUID(0x80000002)
CPUID(0x80000003)
CPUID(0x80000004)
CPUID(0x80000005)
CPUID(0x80000006)
CPUID(0x80000007)
CPUID(0x80000008)
CPUID(0x8000000a)
CPUID(0x8000001d)
CPUID(0x8000001f)
CPUID(0x80000021)
CPUID(0x80000022)
CPUID(0x80860000)
CPUID(0x80860001)
CPUID(0x80860002)
CPUID(0x80860003)
CPUID(0x80860004)
CPUID(0x80860005)
CPUID(0x80860006)
CPUID(0xc0000000)
CPUID(0xc0000001)
(VII.) Previous iterations
--------------------------
Previous iterations of this work document the evolution of the call site
CPUID APIs. Please see:
(v5) https://lore.kernel.org/lkml/20250905121515.192792-1-darwi@linutronix.de
The cover letter there details the v1-v5 progression in full.
Thank you!
Ahmed
8<-----
base-commit: c369299895a591d96745d6492d4888259b004a9e
--
2.53.0
^ permalink raw reply [flat|nested] 101+ messages in thread
* [PATCH v6 01/90] ASoC: Intel: avs: Check maximum valid CPUID leaf
2026-03-27 2:15 [PATCH v6 00/90] x86: Introduce a centralized CPUID data model Ahmed S. Darwish
@ 2026-03-27 2:15 ` Ahmed S. Darwish
2026-03-27 9:26 ` Cezary Rojewski
2026-03-27 23:52 ` [tip: x86/cpu] " tip-bot2 for Ahmed S. Darwish
2026-03-27 2:15 ` [PATCH v6 02/90] ASoC: Intel: avs: Include CPUID header at file scope Ahmed S. Darwish
` (90 subsequent siblings)
91 siblings, 2 replies; 101+ messages in thread
From: Ahmed S. Darwish @ 2026-03-27 2:15 UTC (permalink / raw)
To: Borislav Petkov, Dave Hansen, Ingo Molnar
Cc: Thomas Gleixner, Andrew Cooper, H. Peter Anvin,
Sean Christopherson, David Woodhouse, Peter Zijlstra,
Christian Ludloff, Sohil Mehta, John Ogness, x86, x86-cpuid, LKML,
Ahmed S. Darwish
The Intel AVS driver queries CPUID(0x15) before checking if the CPUID leaf
is available. Check the maximum-valid CPU standard leaf beforehand.
Use the CPUID_LEAF_TSC macro instead of defining a custom local one for the
CPUID(0x15) leaf number.
Note, the inclusion of a header file from within a C function will be fixed
in a separate commit next.
Fixes: cbe37a4d2b3c ("ASoC: Intel: avs: Configure basefw on TGL-based platforms")
Signed-off-by: Ahmed S. Darwish <darwi@linutronix.de>
---
sound/soc/intel/avs/tgl.c | 9 ++++++---
1 file changed, 6 insertions(+), 3 deletions(-)
diff --git a/sound/soc/intel/avs/tgl.c b/sound/soc/intel/avs/tgl.c
index afb066516101..4649d749b41e 100644
--- a/sound/soc/intel/avs/tgl.c
+++ b/sound/soc/intel/avs/tgl.c
@@ -11,8 +11,6 @@
#include "debug.h"
#include "messages.h"
-#define CPUID_TSC_LEAF 0x15
-
static int avs_tgl_dsp_core_power(struct avs_dev *adev, u32 core_mask, bool power)
{
core_mask &= AVS_MAIN_CORE_MASK;
@@ -49,7 +47,11 @@ static int avs_tgl_config_basefw(struct avs_dev *adev)
unsigned int ecx;
#include <asm/cpuid/api.h>
- ecx = cpuid_ecx(CPUID_TSC_LEAF);
+
+ if (boot_cpu_data.cpuid_level < CPUID_LEAF_TSC)
+ goto no_cpuid;
+
+ ecx = cpuid_ecx(CPUID_LEAF_TSC);
if (ecx) {
ret = avs_ipc_set_fw_config(adev, 1, AVS_FW_CFG_XTAL_FREQ_HZ, sizeof(ecx), &ecx);
if (ret)
@@ -57,6 +59,7 @@ static int avs_tgl_config_basefw(struct avs_dev *adev)
}
#endif
+no_cpuid:
hwid.device = pci->device;
hwid.subsystem = pci->subsystem_vendor | (pci->subsystem_device << 16);
hwid.revision = pci->revision;
--
2.53.0
^ permalink raw reply related [flat|nested] 101+ messages in thread
* [PATCH v6 02/90] ASoC: Intel: avs: Include CPUID header at file scope
2026-03-27 2:15 [PATCH v6 00/90] x86: Introduce a centralized CPUID data model Ahmed S. Darwish
2026-03-27 2:15 ` [PATCH v6 01/90] ASoC: Intel: avs: Check maximum valid CPUID leaf Ahmed S. Darwish
@ 2026-03-27 2:15 ` Ahmed S. Darwish
2026-03-27 9:25 ` Cezary Rojewski
2026-03-27 2:15 ` [PATCH v6 03/90] tools/x86/kcpuid: Update bitfields to x86-cpuid-db v3.0 Ahmed S. Darwish
` (89 subsequent siblings)
91 siblings, 1 reply; 101+ messages in thread
From: Ahmed S. Darwish @ 2026-03-27 2:15 UTC (permalink / raw)
To: Borislav Petkov, Dave Hansen, Ingo Molnar
Cc: Thomas Gleixner, Andrew Cooper, H. Peter Anvin,
Sean Christopherson, David Woodhouse, Peter Zijlstra,
Christian Ludloff, Sohil Mehta, John Ogness, x86, x86-cpuid, LKML,
Ahmed S. Darwish
Commit
cbe37a4d2b3c ("ASoC: Intel: avs: Configure basefw on TGL-based platforms")
includes the main CPUID header from within a C function. This works by
luck and forbids valid refactorings inside that header.
Include the CPUID header at file scope instead.
Remove the COMPILE_TEST build flag so that the CONFIG_X86 conditionals can
be removed. The driver gets enough compilation testing already on x86.
For clarity, refactor the CPUID(0x15) code into its own function without
changing any of the driver's logic.
Suggested-by: Borislav Petkov <bp@alien8.de> # CONFIG_X86 removal
Signed-off-by: Ahmed S. Darwish <darwi@linutronix.de>
Fixes: cbe37a4d2b3c ("ASoC: Intel: avs: Configure basefw on TGL-based platforms")
References: 47a1886a610a ("ASoC: Intel: avs: Enable AVS driver only on x86 platforms")
Link: https://lore.kernel.org/r/20251016105514.GCaPDPEu016XyDocfY@fat_crate.local
Link: https://lore.kernel.org/r/da5bf77b-5bdb-440f-92b5-db35d8687987@intel.com
---
sound/soc/intel/Kconfig | 2 +-
sound/soc/intel/avs/tgl.c | 37 ++++++++++++++++++++++++-------------
2 files changed, 25 insertions(+), 14 deletions(-)
diff --git a/sound/soc/intel/Kconfig b/sound/soc/intel/Kconfig
index 412555e626b8..63367364916a 100644
--- a/sound/soc/intel/Kconfig
+++ b/sound/soc/intel/Kconfig
@@ -95,7 +95,7 @@ config SND_SOC_INTEL_KEEMBAY
config SND_SOC_INTEL_AVS
tristate "Intel AVS driver"
- depends on X86 || COMPILE_TEST
+ depends on X86
depends on PCI
depends on COMMON_CLK
select ACPI_NHLT if ACPI
diff --git a/sound/soc/intel/avs/tgl.c b/sound/soc/intel/avs/tgl.c
index 4649d749b41e..a7123639de43 100644
--- a/sound/soc/intel/avs/tgl.c
+++ b/sound/soc/intel/avs/tgl.c
@@ -7,6 +7,7 @@
//
#include <linux/pci.h>
+#include <asm/cpuid/api.h>
#include "avs.h"
#include "debug.h"
#include "messages.h"
@@ -38,28 +39,38 @@ static int avs_tgl_dsp_core_stall(struct avs_dev *adev, u32 core_mask, bool stal
return avs_dsp_core_stall(adev, core_mask, stall);
}
-static int avs_tgl_config_basefw(struct avs_dev *adev)
+/*
+ * Succeed if CPUID(0x15) is not available, or if the nominal core crystal clock
+ * frequency cannot be enumerated from it. There is nothing to do in both cases.
+ */
+static int avs_tgl_set_xtal_freq(struct avs_dev *adev)
{
- struct pci_dev *pci = adev->base.pci;
- struct avs_bus_hwid hwid;
+ unsigned int freq;
int ret;
-#ifdef CONFIG_X86
- unsigned int ecx;
-
-#include <asm/cpuid/api.h>
if (boot_cpu_data.cpuid_level < CPUID_LEAF_TSC)
- goto no_cpuid;
+ return 0;
- ecx = cpuid_ecx(CPUID_LEAF_TSC);
- if (ecx) {
- ret = avs_ipc_set_fw_config(adev, 1, AVS_FW_CFG_XTAL_FREQ_HZ, sizeof(ecx), &ecx);
+ freq = cpuid_ecx(CPUID_LEAF_TSC);
+ if (freq) {
+ ret = avs_ipc_set_fw_config(adev, 1, AVS_FW_CFG_XTAL_FREQ_HZ, sizeof(freq), &freq);
if (ret)
return AVS_IPC_RET(ret);
}
-#endif
-no_cpuid:
+ return 0;
+}
+
+static int avs_tgl_config_basefw(struct avs_dev *adev)
+{
+ struct pci_dev *pci = adev->base.pci;
+ struct avs_bus_hwid hwid;
+ int ret;
+
+ ret = avs_tgl_set_xtal_freq(adev);
+ if (ret)
+ return ret;
+
hwid.device = pci->device;
hwid.subsystem = pci->subsystem_vendor | (pci->subsystem_device << 16);
hwid.revision = pci->revision;
--
2.53.0
^ permalink raw reply related [flat|nested] 101+ messages in thread
* [PATCH v6 03/90] tools/x86/kcpuid: Update bitfields to x86-cpuid-db v3.0
2026-03-27 2:15 [PATCH v6 00/90] x86: Introduce a centralized CPUID data model Ahmed S. Darwish
2026-03-27 2:15 ` [PATCH v6 01/90] ASoC: Intel: avs: Check maximum valid CPUID leaf Ahmed S. Darwish
2026-03-27 2:15 ` [PATCH v6 02/90] ASoC: Intel: avs: Include CPUID header at file scope Ahmed S. Darwish
@ 2026-03-27 2:15 ` Ahmed S. Darwish
2026-03-27 2:15 ` [PATCH v6 04/90] treewide: Explicitly include the x86 CPUID headers Ahmed S. Darwish
` (88 subsequent siblings)
91 siblings, 0 replies; 101+ messages in thread
From: Ahmed S. Darwish @ 2026-03-27 2:15 UTC (permalink / raw)
To: Borislav Petkov, Dave Hansen, Ingo Molnar
Cc: Thomas Gleixner, Andrew Cooper, H. Peter Anvin,
Sean Christopherson, David Woodhouse, Peter Zijlstra,
Christian Ludloff, Sohil Mehta, John Ogness, x86, x86-cpuid, LKML,
Ahmed S. Darwish
Update kcpuid's CSV to version 3.0, as generated by x86-cpuid-db.
Summary of the v2.5 changes:
- Reduce the verbosity of leaf and bitfields descriptions, as formerly
requested by Boris.
- Leaf 0x8000000a: Add Page Modification Logging (PML) bit.
Summary of the v3.0 changes:
- Leaf 0x23: Introduce subleaf 2, Auto Counter Reload (ACR)
- Leaf 0x23: Introduce subleaf 4/5, PEBS capabilities and counters
- Leaf 0x1c: Return LBR depth as a bitmask instead of individual bits
- Leaf 0x0a: Use more descriptive PMU bitfield names
- Leaf 0x0a: Add various missing PMU events
- Leaf 0x06: Add missing IA32_HWP_CTL flag
- Leaf 0x0f: Add missing non-CPU (IO) Intel RDT bits
Thanks to Dave Hansen for reporting multiple missing bits.
Signed-off-by: Ahmed S. Darwish <darwi@linutronix.de>
Link: https://gitlab.com/x86-cpuid.org/x86-cpuid-db/-/blob/v2.5/CHANGELOG.rst
Link: https://gitlab.com/x86-cpuid.org/x86-cpuid-db/-/blob/v3.0/CHANGELOG.rst
---
tools/arch/x86/kcpuid/cpuid.csv | 671 +++++++++++++++++---------------
1 file changed, 347 insertions(+), 324 deletions(-)
diff --git a/tools/arch/x86/kcpuid/cpuid.csv b/tools/arch/x86/kcpuid/cpuid.csv
index 8d925ce9750f..9f5155c825ca 100644
--- a/tools/arch/x86/kcpuid/cpuid.csv
+++ b/tools/arch/x86/kcpuid/cpuid.csv
@@ -1,5 +1,5 @@
# SPDX-License-Identifier: CC0-1.0
-# Generator: x86-cpuid-db v2.4
+# Generator: x86-cpuid-db v3.0
#
# Auto-generated file.
@@ -10,9 +10,9 @@
# LEAF, SUBLEAVES, reg, bits, short_name , long_description
# Leaf 0H
-# Maximum standard leaf number + CPU vendor string
+# Maximum standard leaf + CPU vendor string
- 0x0, 0, eax, 31:0, max_std_leaf , Highest standard CPUID leaf supported
+ 0x0, 0, eax, 31:0, max_std_leaf , Highest standard CPUID leaf
0x0, 0, ebx, 31:0, cpu_vendorid_0 , CPU vendor ID string bytes 0 - 3
0x0, 0, ecx, 31:0, cpu_vendorid_2 , CPU vendor ID string bytes 8 - 11
0x0, 0, edx, 31:0, cpu_vendorid_1 , CPU vendor ID string bytes 4 - 7
@@ -134,23 +134,23 @@
0x4, 31:0, edx, 2, complex_indexing , Not a direct-mapped cache (complex function)
# Leaf 5H
-# MONITOR/MWAIT instructions enumeration
+# MONITOR/MWAIT instructions
0x5, 0, eax, 15:0, min_mon_size , Smallest monitor-line size, in bytes
0x5, 0, ebx, 15:0, max_mon_size , Largest monitor-line size, in bytes
- 0x5, 0, ecx, 0, mwait_ext , Enumeration of MONITOR/MWAIT extensions is supported
- 0x5, 0, ecx, 1, mwait_irq_break , Interrupts as a break-event for MWAIT is supported
- 0x5, 0, edx, 3:0, n_c0_substates , Number of C0 sub C-states supported using MWAIT
- 0x5, 0, edx, 7:4, n_c1_substates , Number of C1 sub C-states supported using MWAIT
- 0x5, 0, edx, 11:8, n_c2_substates , Number of C2 sub C-states supported using MWAIT
- 0x5, 0, edx, 15:12, n_c3_substates , Number of C3 sub C-states supported using MWAIT
- 0x5, 0, edx, 19:16, n_c4_substates , Number of C4 sub C-states supported using MWAIT
- 0x5, 0, edx, 23:20, n_c5_substates , Number of C5 sub C-states supported using MWAIT
- 0x5, 0, edx, 27:24, n_c6_substates , Number of C6 sub C-states supported using MWAIT
- 0x5, 0, edx, 31:28, n_c7_substates , Number of C7 sub C-states supported using MWAIT
+ 0x5, 0, ecx, 0, mwait_ext , MONITOR/MWAIT extensions
+ 0x5, 0, ecx, 1, mwait_irq_break , Interrupts as a break event for MWAIT
+ 0x5, 0, edx, 3:0, n_c0_substates , Number of C0 sub C-states
+ 0x5, 0, edx, 7:4, n_c1_substates , Number of C1 sub C-states
+ 0x5, 0, edx, 11:8, n_c2_substates , Number of C2 sub C-states
+ 0x5, 0, edx, 15:12, n_c3_substates , Number of C3 sub C-states
+ 0x5, 0, edx, 19:16, n_c4_substates , Number of C4 sub C-states
+ 0x5, 0, edx, 23:20, n_c5_substates , Number of C5 sub C-states
+ 0x5, 0, edx, 27:24, n_c6_substates , Number of C6 sub C-states
+ 0x5, 0, edx, 31:28, n_c7_substates , Number of C7 sub C-states
# Leaf 6H
-# Thermal and Power Management enumeration
+# Thermal and power management
0x6, 0, eax, 0, dtherm , Digital temperature sensor
0x6, 0, eax, 1, turbo_boost , Intel Turbo Boost
@@ -158,24 +158,25 @@
0x6, 0, eax, 4, pln , Power Limit Notification (PLN) event
0x6, 0, eax, 5, ecmd , Clock modulation duty cycle extension
0x6, 0, eax, 6, pts , Package thermal management
- 0x6, 0, eax, 7, hwp , HWP (Hardware P-states) base registers are supported
+ 0x6, 0, eax, 7, hwp , HWP (Hardware P-states) base registers
0x6, 0, eax, 8, hwp_notify , HWP notification (IA32_HWP_INTERRUPT MSR)
- 0x6, 0, eax, 9, hwp_act_window , HWP activity window (IA32_HWP_REQUEST[bits 41:32]) supported
+ 0x6, 0, eax, 9, hwp_act_window , HWP activity window (IA32_HWP_REQUEST[bits 41:32])
0x6, 0, eax, 10, hwp_epp , HWP Energy Performance Preference
0x6, 0, eax, 11, hwp_pkg_req , HWP Package Level Request
- 0x6, 0, eax, 13, hdc_base_regs , HDC base registers are supported
+ 0x6, 0, eax, 13, hdc_base_regs , HDC base registers
0x6, 0, eax, 14, turbo_boost_3_0 , Intel Turbo Boost Max 3.0
0x6, 0, eax, 15, hwp_capabilities , HWP Highest Performance change
0x6, 0, eax, 16, hwp_peci_override , HWP PECI override
0x6, 0, eax, 17, hwp_flexible , Flexible HWP
0x6, 0, eax, 18, hwp_fast , IA32_HWP_REQUEST MSR fast access mode
- 0x6, 0, eax, 19, hfi , HW_FEEDBACK MSRs supported
- 0x6, 0, eax, 20, hwp_ignore_idle , Ignoring idle logical CPU HWP req is supported
- 0x6, 0, eax, 23, thread_director , Intel thread director support
- 0x6, 0, eax, 24, therm_interrupt_bit25 , IA32_THERM_INTERRUPT MSR bit 25 is supported
+ 0x6, 0, eax, 19, hfi , HW_FEEDBACK MSRs
+ 0x6, 0, eax, 20, hwp_ignore_idle , Ignoring idle logical CPU HWP request is supported
+ 0x6, 0, eax, 22, hwp_ctl , IA32_HWP_CTL MSR
+ 0x6, 0, eax, 23, thread_director , Intel thread director
+ 0x6, 0, eax, 24, therm_interrupt_bit25 , IA32_THERM_INTERRUPT MSR bit 25
0x6, 0, ebx, 3:0, n_therm_thresholds , Digital thermometer thresholds
0x6, 0, ecx, 0, aperfmperf , MPERF/APERF MSRs (effective frequency interface)
- 0x6, 0, ecx, 3, epb , IA32_ENERGY_PERF_BIAS MSR support
+ 0x6, 0, ecx, 3, epb , IA32_ENERGY_PERF_BIAS MSR
0x6, 0, ecx, 15:8, thrd_director_nclasses , Number of classes, Intel thread director
0x6, 0, edx, 0, perfcap_reporting , Performance capability reporting
0x6, 0, edx, 1, encap_reporting , Energy efficiency capability reporting
@@ -183,11 +184,11 @@
0x6, 0, edx, 31:16, this_lcpu_hwfdbk_idx , This logical CPU hardware feedback interface index
# Leaf 7H
-# Extended CPU features enumeration
+# Extended CPU features
0x7, 0, eax, 31:0, leaf7_n_subleaves , Number of leaf 0x7 subleaves
- 0x7, 0, ebx, 0, fsgsbase , FSBASE/GSBASE read/write support
- 0x7, 0, ebx, 1, tsc_adjust , IA32_TSC_ADJUST MSR supported
+ 0x7, 0, ebx, 0, fsgsbase , FSBASE/GSBASE read/write
+ 0x7, 0, ebx, 1, tsc_adjust , IA32_TSC_ADJUST MSR
0x7, 0, ebx, 2, sgx , Intel SGX (Software Guard Extensions)
0x7, 0, ebx, 3, bmi1 , Bit manipulation extensions group 1
0x7, 0, ebx, 4, hle , Hardware Lock Elision
@@ -227,7 +228,7 @@
0x7, 0, ecx, 7, cet_ss , CET shadow stack features
0x7, 0, ecx, 8, gfni , Galois field new instructions
0x7, 0, ecx, 9, vaes , Vector AES instructions
- 0x7, 0, ecx, 10, vpclmulqdq , VPCLMULQDQ 256-bit instruction support
+ 0x7, 0, ecx, 10, vpclmulqdq , VPCLMULQDQ 256-bit instruction
0x7, 0, ecx, 11, avx512_vnni , Vector neural network instructions
0x7, 0, ecx, 12, avx512_bitalg , AVX-512 bitwise algorithms
0x7, 0, ecx, 13, tme , Intel total memory encryption
@@ -235,34 +236,34 @@
0x7, 0, ecx, 16, la57 , 57-bit linear addresses (five-level paging)
0x7, 0, ecx, 21:17, mawau_val_lm , BNDLDX/BNDSTX MAWAU value in 64-bit mode
0x7, 0, ecx, 22, rdpid , RDPID instruction
- 0x7, 0, ecx, 23, key_locker , Intel key locker support
+ 0x7, 0, ecx, 23, key_locker , Intel key locker
0x7, 0, ecx, 24, bus_lock_detect , OS bus-lock detection
0x7, 0, ecx, 25, cldemote , CLDEMOTE instruction
0x7, 0, ecx, 27, movdiri , MOVDIRI instruction
0x7, 0, ecx, 28, movdir64b , MOVDIR64B instruction
- 0x7, 0, ecx, 29, enqcmd , Enqueue stores supported (ENQCMD{,S})
+ 0x7, 0, ecx, 29, enqcmd , Enqueue stores (ENQCMD{,S})
0x7, 0, ecx, 30, sgx_lc , Intel SGX launch configuration
0x7, 0, ecx, 31, pks , Protection keys for supervisor-mode pages
0x7, 0, edx, 1, sgx_keys , Intel SGX attestation services
0x7, 0, edx, 2, avx512_4vnniw , AVX-512 neural network instructions
0x7, 0, edx, 3, avx512_4fmaps , AVX-512 multiply accumulation single precision
0x7, 0, edx, 4, fsrm , Fast short REP MOV
- 0x7, 0, edx, 5, uintr , CPU supports user interrupts
+ 0x7, 0, edx, 5, uintr , User interrupts
0x7, 0, edx, 8, avx512_vp2intersect , VP2INTERSECT{D,Q} instructions
- 0x7, 0, edx, 9, srdbs_ctrl , SRBDS mitigation MSR available
- 0x7, 0, edx, 10, md_clear , VERW MD_CLEAR microcode support
+ 0x7, 0, edx, 9, srdbs_ctrl , SRBDS mitigation MSR
+ 0x7, 0, edx, 10, md_clear , VERW MD_CLEAR microcode
0x7, 0, edx, 11, rtm_always_abort , XBEGIN (RTM transaction) always aborts
- 0x7, 0, edx, 13, tsx_force_abort , MSR TSX_FORCE_ABORT, RTM_ABORT bit, supported
+ 0x7, 0, edx, 13, tsx_force_abort , MSR TSX_FORCE_ABORT, RTM_ABORT bit
0x7, 0, edx, 14, serialize , SERIALIZE instruction
0x7, 0, edx, 15, hybrid_cpu , The CPU is identified as a 'hybrid part'
0x7, 0, edx, 16, tsxldtrk , TSX suspend/resume load address tracking
0x7, 0, edx, 18, pconfig , PCONFIG instruction
0x7, 0, edx, 19, arch_lbr , Intel architectural LBRs
0x7, 0, edx, 20, ibt , CET indirect branch tracking
- 0x7, 0, edx, 22, amx_bf16 , AMX-BF16: tile bfloat16 support
+ 0x7, 0, edx, 22, amx_bf16 , AMX-BF16: tile bfloat16
0x7, 0, edx, 23, avx512_fp16 , AVX-512 FP16 instructions
- 0x7, 0, edx, 24, amx_tile , AMX-TILE: tile architecture support
- 0x7, 0, edx, 25, amx_int8 , AMX-INT8: tile 8-bit integer support
+ 0x7, 0, edx, 24, amx_tile , AMX-TILE: tile architecture
+ 0x7, 0, edx, 25, amx_int8 , AMX-INT8: tile 8-bit integer
0x7, 0, edx, 26, spec_ctrl , Speculation Control (IBRS/IBPB: indirect branch restrictions)
0x7, 0, edx, 27, intel_stibp , Single thread indirect branch predictors
0x7, 0, edx, 28, flush_l1d , FLUSH L1D cache: IA32_FLUSH_CMD MSR
@@ -273,7 +274,7 @@
0x7, 1, eax, 5, avx512_bf16 , AVX-512 bfloat16 instructions
0x7, 1, eax, 6, lass , Linear address space separation
0x7, 1, eax, 7, cmpccxadd , CMPccXADD instructions
- 0x7, 1, eax, 8, arch_perfmon_ext , ArchPerfmonExt: leaf 0x23 is supported
+ 0x7, 1, eax, 8, arch_perfmon_ext , ArchPerfmonExt: leaf 0x23
0x7, 1, eax, 10, fzrm , Fast zero-length REP MOVSB
0x7, 1, eax, 11, fsrs , Fast short REP STOSB
0x7, 1, eax, 12, fsrc , Fast Short REP CMPSB/SCASB
@@ -282,7 +283,7 @@
0x7, 1, eax, 19, wrmsrns , WRMSRNS instruction (WRMSR-non-serializing)
0x7, 1, eax, 20, nmi_src , NMI-source reporting with FRED event data
0x7, 1, eax, 21, amx_fp16 , AMX-FP16: FP16 tile operations
- 0x7, 1, eax, 22, hreset , History reset support
+ 0x7, 1, eax, 22, hreset , HRESET (Thread director history reset)
0x7, 1, eax, 23, avx_ifma , Integer fused multiply add
0x7, 1, eax, 26, lam , Linear address masking
0x7, 1, eax, 27, rd_wr_msrlist , RDMSRLIST/WRMSRLIST instructions
@@ -298,35 +299,40 @@
0x7, 2, edx, 3, ddp_ctrl , MSR bit IA32_SPEC_CTRL.DDPD_U
0x7, 2, edx, 4, bhi_ctrl , MSR bit IA32_SPEC_CTRL.BHI_DIS_S
0x7, 2, edx, 5, mcdt_no , MCDT mitigation not needed
- 0x7, 2, edx, 6, uclock_disable , UC-lock disable is supported
+ 0x7, 2, edx, 6, uclock_disable , UC-lock disable
# Leaf 9H
-# Intel DCA (Direct Cache Access) enumeration
+# Intel DCA (Direct Cache Access)
0x9, 0, eax, 0, dca_enabled_in_bios , DCA is enabled in BIOS
# Leaf AH
-# Intel PMU (Performance Monitoring Unit) enumeration
+# Intel PMU (Performance Monitoring Unit)
0xa, 0, eax, 7:0, pmu_version , Performance monitoring unit version ID
- 0xa, 0, eax, 15:8, pmu_n_gcounters , Number of general PMU counters per logical CPU
- 0xa, 0, eax, 23:16, pmu_gcounters_nbits , Bitwidth of PMU general counters
- 0xa, 0, eax, 31:24, pmu_cpuid_ebx_bits , Length of leaf 0xa EBX bit vector
- 0xa, 0, ebx, 0, no_core_cycle_evt , Core cycle event not available
- 0xa, 0, ebx, 1, no_insn_retired_evt , Instruction retired event not available
- 0xa, 0, ebx, 2, no_refcycle_evt , Reference cycles event not available
- 0xa, 0, ebx, 3, no_llc_ref_evt , LLC-reference event not available
- 0xa, 0, ebx, 4, no_llc_miss_evt , LLC-misses event not available
- 0xa, 0, ebx, 5, no_br_insn_ret_evt , Branch instruction retired event not available
- 0xa, 0, ebx, 6, no_br_mispredict_evt , Branch mispredict retired event not available
- 0xa, 0, ebx, 7, no_td_slots_evt , Topdown slots event not available
+ 0xa, 0, eax, 15:8, num_counters_gp , Number of general-purpose PMU counters per logical CPU
+ 0xa, 0, eax, 23:16, bit_width_gp , Bitwidth of PMU general-purpose counters
+ 0xa, 0, eax, 31:24, events_mask_len , Length of CPUID(0xa).EBX bit vector
+ 0xa, 0, ebx, 0, no_core_cycle , Core cycle event not available
+ 0xa, 0, ebx, 1, no_instruction_retired , Instruction retired event not available
+ 0xa, 0, ebx, 2, no_reference_cycles , Reference cycles event not available
+ 0xa, 0, ebx, 3, no_llc_reference , LLC-reference event not available
+ 0xa, 0, ebx, 4, no_llc_misses , LLC-misses event not available
+ 0xa, 0, ebx, 5, no_br_insn_retired , Branch instruction retired event not available
+ 0xa, 0, ebx, 6, no_br_misses_retired , Branch mispredict retired event not available
+ 0xa, 0, ebx, 7, no_topdown_slots , Topdown slots event not available
+ 0xa, 0, ebx, 8, no_backend_bound , Topdown backend bound not available
+ 0xa, 0, ebx, 9, no_bad_speculation , Topdown bad speculation not available
+ 0xa, 0, ebx, 10, no_frontend_bound , Topdown frontend bound not available
+ 0xa, 0, ebx, 11, no_retiring , Topdown retiring not available
+ 0xa, 0, ebx, 12, no_lbr_inserts , LBR inserts not available
0xa, 0, ecx, 31:0, pmu_fcounters_bitmap , Fixed-function PMU counters support bitmap
- 0xa, 0, edx, 4:0, pmu_n_fcounters , Number of fixed PMU counters
- 0xa, 0, edx, 12:5, pmu_fcounters_nbits , Bitwidth of PMU fixed counters
- 0xa, 0, edx, 15, anythread_depr , AnyThread deprecation
+ 0xa, 0, edx, 4:0, num_counters_fixed , Number of fixed PMU counters
+ 0xa, 0, edx, 12:5, bitwidth_fixed , Bitwidth of PMU fixed counters
+ 0xa, 0, edx, 15, anythread_deprecation , AnyThread mode deprecation
# Leaf BH
-# CPUs v1 extended topology enumeration
+# CPU extended topology v1
0xb, 1:0, eax, 4:0, x2apic_id_shift , Bit width of this level (previous levels inclusive)
0xb, 1:0, ebx, 15:0, domain_lcpus_count , Logical CPUs count across all instances of this domain
@@ -335,107 +341,109 @@
0xb, 1:0, edx, 31:0, x2apic_id , x2APIC ID of current logical CPU
# Leaf DH
-# Processor extended state enumeration
-
- 0xd, 0, eax, 0, xcr0_x87 , XCR0.X87 (bit 0) supported
- 0xd, 0, eax, 1, xcr0_sse , XCR0.SEE (bit 1) supported
- 0xd, 0, eax, 2, xcr0_avx , XCR0.AVX (bit 2) supported
- 0xd, 0, eax, 3, xcr0_mpx_bndregs , XCR0.BNDREGS (bit 3) supported (MPX BND0-BND3 registers)
- 0xd, 0, eax, 4, xcr0_mpx_bndcsr , XCR0.BNDCSR (bit 4) supported (MPX BNDCFGU/BNDSTATUS registers)
- 0xd, 0, eax, 5, xcr0_avx512_opmask , XCR0.OPMASK (bit 5) supported (AVX-512 k0-k7 registers)
- 0xd, 0, eax, 6, xcr0_avx512_zmm_hi256 , XCR0.ZMM_Hi256 (bit 6) supported (AVX-512 ZMM0->ZMM7/15 registers)
- 0xd, 0, eax, 7, xcr0_avx512_hi16_zmm , XCR0.HI16_ZMM (bit 7) supported (AVX-512 ZMM16->ZMM31 registers)
- 0xd, 0, eax, 9, xcr0_pkru , XCR0.PKRU (bit 9) supported (XSAVE PKRU registers)
- 0xd, 0, eax, 11, xcr0_cet_u , XCR0.CET_U (bit 11) supported (CET user state)
- 0xd, 0, eax, 12, xcr0_cet_s , XCR0.CET_S (bit 12) supported (CET supervisor state)
- 0xd, 0, eax, 17, xcr0_tileconfig , XCR0.TILECONFIG (bit 17) supported (AMX can manage TILECONFIG)
- 0xd, 0, eax, 18, xcr0_tiledata , XCR0.TILEDATA (bit 18) supported (AMX can manage TILEDATA)
- 0xd, 0, ebx, 31:0, xsave_sz_xcr0_enabled , XSAVE/XRSTOR area byte size, for XCR0 enabled features
+# CPU extended state
+
+ 0xd, 0, eax, 0, xcr0_x87 , XCR0.X87
+ 0xd, 0, eax, 1, xcr0_sse , XCR0.SSE
+ 0xd, 0, eax, 2, xcr0_avx , XCR0.AVX
+ 0xd, 0, eax, 3, xcr0_mpx_bndregs , XCR0.BNDREGS: MPX BND0-BND3 registers
+ 0xd, 0, eax, 4, xcr0_mpx_bndcsr , XCR0.BNDCSR: MPX BNDCFGU/BNDSTATUS registers
+ 0xd, 0, eax, 5, xcr0_avx512_opmask , XCR0.OPMASK: AVX-512 k0-k7 registers
+ 0xd, 0, eax, 6, xcr0_avx512_zmm_hi256 , XCR0.ZMM_Hi256: AVX-512 ZMM0->ZMM7/15 registers
+ 0xd, 0, eax, 7, xcr0_avx512_hi16_zmm , XCR0.HI16_ZMM: AVX-512 ZMM16->ZMM31 registers
+ 0xd, 0, eax, 9, xcr0_pkru , XCR0.PKRU: XSAVE PKRU registers
+ 0xd, 0, eax, 11, xcr0_cet_u , XCR0.CET_U: CET user state
+ 0xd, 0, eax, 12, xcr0_cet_s , XCR0.CET_S: CET supervisor state
+ 0xd, 0, eax, 17, xcr0_tileconfig , XCR0.TILECONFIG: AMX can manage TILECONFIG
+ 0xd, 0, eax, 18, xcr0_tiledata , XCR0.TILEDATA: AMX can manage TILEDATA
+ 0xd, 0, ebx, 31:0, xsave_sz_xcr0 , XSAVE/XRSTOR area byte size, for XCR0 enabled features
0xd, 0, ecx, 31:0, xsave_sz_max , XSAVE/XRSTOR area max byte size, all CPU features
- 0xd, 0, edx, 30, xcr0_lwp , AMD XCR0.LWP (bit 62) supported (Light-weight Profiling)
+ 0xd, 0, edx, 30, xcr0_lwp , AMD XCR0.LWP: Light-weight Profiling
0xd, 1, eax, 0, xsaveopt , XSAVEOPT instruction
0xd, 1, eax, 1, xsavec , XSAVEC instruction
0xd, 1, eax, 2, xgetbv1 , XGETBV instruction with ECX = 1
0xd, 1, eax, 3, xsaves , XSAVES/XRSTORS instructions (and XSS MSR)
- 0xd, 1, eax, 4, xfd , Extended feature disable support
- 0xd, 1, ebx, 31:0, xsave_sz_xcr0_xmms_enabled, XSAVE area size, all XCR0 and XMMS features enabled
- 0xd, 1, ecx, 8, xss_pt , PT state, supported
- 0xd, 1, ecx, 10, xss_pasid , PASID state, supported
- 0xd, 1, ecx, 11, xss_cet_u , CET user state, supported
- 0xd, 1, ecx, 12, xss_cet_p , CET supervisor state, supported
- 0xd, 1, ecx, 13, xss_hdc , HDC state, supported
- 0xd, 1, ecx, 14, xss_uintr , UINTR state, supported
- 0xd, 1, ecx, 15, xss_lbr , LBR state, supported
- 0xd, 1, ecx, 16, xss_hwp , HWP state, supported
- 0xd, 63:2, eax, 31:0, xsave_sz , Size of save area for subleaf-N feature, in bytes
- 0xd, 63:2, ebx, 31:0, xsave_offset , Offset of save area for subleaf-N feature, in bytes
- 0xd, 63:2, ecx, 0, is_xss_bit , Subleaf N describes an XSS bit, otherwise XCR0 bit
- 0xd, 63:2, ecx, 1, compacted_xsave_64byte_aligned, When compacted, subleaf-N feature XSAVE area is 64-byte aligned
+ 0xd, 1, eax, 4, xfd , Extended feature disable
+ 0xd, 1, ebx, 31:0, xsave_sz_xcr0_xss , XSAVES/XSAVEC area byte size, for XCR0|XSS enabled features
+ 0xd, 1, ecx, 8, xss_pt , PT state
+ 0xd, 1, ecx, 10, xss_pasid , PASID state
+ 0xd, 1, ecx, 11, xss_cet_u , CET user state
+ 0xd, 1, ecx, 12, xss_cet_p , CET supervisor state
+ 0xd, 1, ecx, 13, xss_hdc , HDC state
+ 0xd, 1, ecx, 14, xss_uintr , UINTR state
+ 0xd, 1, ecx, 15, xss_lbr , LBR state
+ 0xd, 1, ecx, 16, xss_hwp , HWP state
+ 0xd, 63:2, eax, 31:0, xsave_sz , Subleaf-N feature save area size, in bytes
+ 0xd, 63:2, ebx, 31:0, xsave_offset , Subleaf-N feature save area offset, in bytes
+ 0xd, 63:2, ecx, 0, is_xss_bit , Subleaf N describes an XSS bit (otherwise XCR0)
+ 0xd, 63:2, ecx, 1, compacted_xsave_64byte_aligned, When compacted, subleaf-N XSAVE area is 64-byte aligned
# Leaf FH
# Intel RDT / AMD PQoS resource monitoring
- 0xf, 0, ebx, 31:0, core_rmid_max , RMID max, within this core, all types (0-based)
- 0xf, 0, edx, 1, cqm_llc , LLC QoS-monitoring supported
+ 0xf, 0, ebx, 31:0, core_rmid_max , RMID max within this core (0-based)
+ 0xf, 0, edx, 1, cqm_llc , LLC QoS-monitoring
0xf, 1, eax, 7:0, l3c_qm_bitwidth , L3 QoS-monitoring counter bitwidth (24-based)
0xf, 1, eax, 8, l3c_qm_overflow_bit , QM_CTR MSR bit 61 is an overflow bit
+ 0xf, 1, eax, 9, io_rdt_cmt , non-CPU agent supporting Intel RDT CMT present
+ 0xf, 1, eax, 10, io_rdt_mbm , non-CPU agent supporting Intel RDT MBM present
0xf, 1, ebx, 31:0, l3c_qm_conver_factor , QM_CTR MSR conversion factor to bytes
0xf, 1, ecx, 31:0, l3c_qm_rmid_max , L3 QoS-monitoring max RMID
- 0xf, 1, edx, 0, cqm_occup_llc , L3 QoS occupancy monitoring supported
- 0xf, 1, edx, 1, cqm_mbm_total , L3 QoS total bandwidth monitoring supported
- 0xf, 1, edx, 2, cqm_mbm_local , L3 QoS local bandwidth monitoring supported
+ 0xf, 1, edx, 0, cqm_occup_llc , L3 QoS occupancy monitoring
+ 0xf, 1, edx, 1, cqm_mbm_total , L3 QoS total bandwidth monitoring
+ 0xf, 1, edx, 2, cqm_mbm_local , L3 QoS local bandwidth monitoring
# Leaf 10H
-# Intel RDT / AMD PQoS allocation enumeration
+# Intel RDT / AMD PQoS allocation
- 0x10, 0, ebx, 1, cat_l3 , L3 Cache Allocation Technology supported
- 0x10, 0, ebx, 2, cat_l2 , L2 Cache Allocation Technology supported
- 0x10, 0, ebx, 3, mba , Memory Bandwidth Allocation supported
+ 0x10, 0, ebx, 1, cat_l3 , L3 Cache Allocation Technology
+ 0x10, 0, ebx, 2, cat_l2 , L2 Cache Allocation Technology
+ 0x10, 0, ebx, 3, mba , Memory Bandwidth Allocation
0x10, 2:1, eax, 4:0, cat_cbm_len , L3/L2_CAT capacity bitmask length, minus-one notation
- 0x10, 2:1, ebx, 31:0, cat_units_bitmap , L3/L2_CAT bitmap of allocation units
+ 0x10, 2:1, ebx, 31:0, cat_units_bitmap , L3/L2_CAT allocation units bitmap
0x10, 2:1, ecx, 1, l3_cat_cos_infreq_updates, L3_CAT COS updates should be infrequent
- 0x10, 2:1, ecx, 2, cdp_l3 , L3/L2_CAT CDP (Code and Data Prioritization)
- 0x10, 2:1, ecx, 3, cat_sparse_1s , L3/L2_CAT non-contiguous 1s value supported
- 0x10, 2:1, edx, 15:0, cat_cos_max , L3/L2_CAT max COS (Class of Service) supported
+ 0x10, 2:1, ecx, 2, cdp_l3 , L3/L2_CAT Code and Data Prioritization
+ 0x10, 2:1, ecx, 3, cat_sparse_1s , L3/L2_CAT non-contiguous 1s value
+ 0x10, 2:1, edx, 15:0, cat_cos_max , L3/L2_CAT max Class of Service
0x10, 3, eax, 11:0, mba_max_delay , Max MBA throttling value; minus-one notation
- 0x10, 3, ecx, 0, per_thread_mba , Per-thread MBA controls are supported
+ 0x10, 3, ecx, 0, per_thread_mba , Per-thread MBA controls
0x10, 3, ecx, 2, mba_delay_linear , Delay values are linear
- 0x10, 3, edx, 15:0, mba_cos_max , MBA max Class of Service supported
+ 0x10, 3, edx, 15:0, mba_cos_max , MBA max Class of Service
# Leaf 12H
-# Intel Software Guard Extensions (SGX) enumeration
-
- 0x12, 0, eax, 0, sgx1 , SGX1 leaf functions supported
- 0x12, 0, eax, 1, sgx2 , SGX2 leaf functions supported
- 0x12, 0, eax, 5, enclv_leaves , ENCLV leaves (E{INC,DEC}VIRTCHILD, ESETCONTEXT) supported
- 0x12, 0, eax, 6, encls_leaves , ENCLS leaves (ENCLS ETRACKC, ERDINFO, ELDBC, ELDUC) supported
- 0x12, 0, eax, 7, enclu_everifyreport2 , ENCLU leaf EVERIFYREPORT2 supported
- 0x12, 0, eax, 10, encls_eupdatesvn , ENCLS leaf EUPDATESVN supported
- 0x12, 0, eax, 11, sgx_edeccssa , ENCLU leaf EDECCSSA supported
- 0x12, 0, ebx, 0, miscselect_exinfo , SSA.MISC frame: reporting #PF and #GP exceptions inside enclave supported
- 0x12, 0, ebx, 1, miscselect_cpinfo , SSA.MISC frame: reporting #CP exceptions inside enclave supported
+# Intel SGX (Software Guard Extensions)
+
+ 0x12, 0, eax, 0, sgx1 , SGX1 leaf functions
+ 0x12, 0, eax, 1, sgx2 , SGX2 leaf functions
+ 0x12, 0, eax, 5, enclv_leaves , ENCLV leaves
+ 0x12, 0, eax, 6, encls_leaves , ENCLS leaves
+ 0x12, 0, eax, 7, enclu_everifyreport2 , ENCLU leaf EVERIFYREPORT2
+ 0x12, 0, eax, 10, encls_eupdatesvn , ENCLS leaf EUPDATESVN
+ 0x12, 0, eax, 11, sgx_edeccssa , ENCLU leaf EDECCSSA
+ 0x12, 0, ebx, 0, miscselect_exinfo , SSA.MISC frame: Enclave #PF and #GP reporting
+ 0x12, 0, ebx, 1, miscselect_cpinfo , SSA.MISC frame: Enclave #CP reporting
0x12, 0, edx, 7:0, max_enclave_sz_not64 , Maximum enclave size in non-64-bit mode (log2)
0x12, 0, edx, 15:8, max_enclave_sz_64 , Maximum enclave size in 64-bit mode (log2)
- 0x12, 1, eax, 0, secs_attr_init , ATTRIBUTES.INIT supported (enclave initialized by EINIT)
- 0x12, 1, eax, 1, secs_attr_debug , ATTRIBUTES.DEBUG supported (enclave permits debugger read/write)
- 0x12, 1, eax, 2, secs_attr_mode64bit , ATTRIBUTES.MODE64BIT supported (enclave runs in 64-bit mode)
- 0x12, 1, eax, 4, secs_attr_provisionkey , ATTRIBUTES.PROVISIONKEY supported (provisioning key available)
- 0x12, 1, eax, 5, secs_attr_einittoken_key, ATTRIBUTES.EINITTOKEN_KEY supported (EINIT token key available)
- 0x12, 1, eax, 6, secs_attr_cet , ATTRIBUTES.CET supported (enable CET attributes)
- 0x12, 1, eax, 7, secs_attr_kss , ATTRIBUTES.KSS supported (Key Separation and Sharing enabled)
- 0x12, 1, eax, 10, secs_attr_aexnotify , ATTRIBUTES.AEXNOTIFY supported (enclave threads may get AEX notifications
- 0x12, 1, ecx, 0, xfrm_x87 , Enclave XFRM.X87 (bit 0) supported
- 0x12, 1, ecx, 1, xfrm_sse , Enclave XFRM.SEE (bit 1) supported
- 0x12, 1, ecx, 2, xfrm_avx , Enclave XFRM.AVX (bit 2) supported
- 0x12, 1, ecx, 3, xfrm_mpx_bndregs , Enclave XFRM.BNDREGS (bit 3) supported (MPX BND0-BND3 registers)
- 0x12, 1, ecx, 4, xfrm_mpx_bndcsr , Enclave XFRM.BNDCSR (bit 4) supported (MPX BNDCFGU/BNDSTATUS registers)
- 0x12, 1, ecx, 5, xfrm_avx512_opmask , Enclave XFRM.OPMASK (bit 5) supported (AVX-512 k0-k7 registers)
- 0x12, 1, ecx, 6, xfrm_avx512_zmm_hi256 , Enclave XFRM.ZMM_Hi256 (bit 6) supported (AVX-512 ZMM0->ZMM7/15 registers)
- 0x12, 1, ecx, 7, xfrm_avx512_hi16_zmm , Enclave XFRM.HI16_ZMM (bit 7) supported (AVX-512 ZMM16->ZMM31 registers)
- 0x12, 1, ecx, 9, xfrm_pkru , Enclave XFRM.PKRU (bit 9) supported (XSAVE PKRU registers)
- 0x12, 1, ecx, 17, xfrm_tileconfig , Enclave XFRM.TILECONFIG (bit 17) supported (AMX can manage TILECONFIG)
- 0x12, 1, ecx, 18, xfrm_tiledata , Enclave XFRM.TILEDATA (bit 18) supported (AMX can manage TILEDATA)
- 0x12, 31:2, eax, 3:0, subleaf_type , Subleaf type (dictates output layout)
+ 0x12, 1, eax, 0, secs_attr_init , Enclave initialized by EINIT
+ 0x12, 1, eax, 1, secs_attr_debug , Enclave permits debugger read/write
+ 0x12, 1, eax, 2, secs_attr_mode64bit , Enclave runs in 64-bit mode
+ 0x12, 1, eax, 4, secs_attr_provisionkey , Provisioning key
+ 0x12, 1, eax, 5, secs_attr_einittoken_key, EINIT token key
+ 0x12, 1, eax, 6, secs_attr_cet , CET attributes
+ 0x12, 1, eax, 7, secs_attr_kss , Key Separation and Sharing
+ 0x12, 1, eax, 10, secs_attr_aexnotify , Enclave threads: AEX notifications
+ 0x12, 1, ecx, 0, xfrm_x87 , Enclave XFRM.X87
+ 0x12, 1, ecx, 1, xfrm_sse , Enclave XFRM.SEE
+ 0x12, 1, ecx, 2, xfrm_avx , Enclave XFRM.AVX
+ 0x12, 1, ecx, 3, xfrm_mpx_bndregs , Enclave XFRM.BNDREGS (MPX BND0-BND3 registers)
+ 0x12, 1, ecx, 4, xfrm_mpx_bndcsr , Enclave XFRM.BNDCSR (MPX BNDCFGU/BNDSTATUS registers)
+ 0x12, 1, ecx, 5, xfrm_avx512_opmask , Enclave XFRM.OPMASK (AVX-512 k0-k7 registers)
+ 0x12, 1, ecx, 6, xfrm_avx512_zmm_hi256 , Enclave XFRM.ZMM_Hi256 (AVX-512 ZMM0->ZMM7/15 registers)
+ 0x12, 1, ecx, 7, xfrm_avx512_hi16_zmm , Enclave XFRM.HI16_ZMM (AVX-512 ZMM16->ZMM31 registers)
+ 0x12, 1, ecx, 9, xfrm_pkru , Enclave XFRM.PKRU (XSAVE PKRU registers)
+ 0x12, 1, ecx, 17, xfrm_tileconfig , Enclave XFRM.TILECONFIG (AMX can manage TILECONFIG)
+ 0x12, 1, ecx, 18, xfrm_tiledata , Enclave XFRM.TILEDATA (AMX can manage TILEDATA)
+ 0x12, 31:2, eax, 3:0, subleaf_type , Subleaf type
0x12, 31:2, eax, 31:12, epc_sec_base_addr_0 , EPC section base address, bits[12:31]
0x12, 31:2, ebx, 19:0, epc_sec_base_addr_1 , EPC section base address, bits[32:51]
0x12, 31:2, ecx, 3:0, epc_sec_type , EPC section type / property encoding
@@ -443,44 +451,44 @@
0x12, 31:2, edx, 19:0, epc_sec_size_1 , EPC section size, bits[32:51]
# Leaf 14H
-# Intel Processor Trace enumeration
+# Intel Processor Trace
0x14, 0, eax, 31:0, pt_max_subleaf , Maximum leaf 0x14 subleaf
0x14, 0, ebx, 0, cr3_filtering , IA32_RTIT_CR3_MATCH is accessible
0x14, 0, ebx, 1, psb_cyc , Configurable PSB and cycle-accurate mode
0x14, 0, ebx, 2, ip_filtering , IP/TraceStop filtering; Warm-reset PT MSRs preservation
0x14, 0, ebx, 3, mtc_timing , MTC timing packet; COFI-based packets suppression
- 0x14, 0, ebx, 4, ptwrite , PTWRITE support
- 0x14, 0, ebx, 5, power_event_trace , Power Event Trace support
- 0x14, 0, ebx, 6, psb_pmi_preserve , PSB and PMI preservation support
- 0x14, 0, ebx, 7, event_trace , Event Trace packet generation through IA32_RTIT_CTL.EventEn
- 0x14, 0, ebx, 8, tnt_disable , TNT packet generation disable through IA32_RTIT_CTL.DisTNT
- 0x14, 0, ecx, 0, topa_output , ToPA output scheme support
+ 0x14, 0, ebx, 4, ptwrite , PTWRITE instruction
+ 0x14, 0, ebx, 5, power_event_trace , Power Event Trace
+ 0x14, 0, ebx, 6, psb_pmi_preserve , PSB and PMI preservation
+ 0x14, 0, ebx, 7, event_trace , Event Trace packet generation
+ 0x14, 0, ebx, 8, tnt_disable , TNT packet generation disable
+ 0x14, 0, ecx, 0, topa_output , ToPA output scheme
0x14, 0, ecx, 1, topa_multiple_entries , ToPA tables can hold multiple entries
- 0x14, 0, ecx, 2, single_range_output , Single-range output scheme supported
- 0x14, 0, ecx, 3, trance_transport_output, Trace Transport subsystem output support
+ 0x14, 0, ecx, 2, single_range_output , Single-range output
+ 0x14, 0, ecx, 3, trance_transport_output, Trace Transport subsystem output
0x14, 0, ecx, 31, ip_payloads_lip , IP payloads have LIP values (CS base included)
- 0x14, 1, eax, 2:0, num_address_ranges , Filtering number of configurable Address Ranges
- 0x14, 1, eax, 31:16, mtc_periods_bmp , Bitmap of supported MTC period encodings
- 0x14, 1, ebx, 15:0, cycle_thresholds_bmp , Bitmap of supported Cycle Threshold encodings
- 0x14, 1, ebx, 31:16, psb_periods_bmp , Bitmap of supported Configurable PSB frequency encodings
+ 0x14, 1, eax, 2:0, num_address_ranges , Number of configurable Address Ranges
+ 0x14, 1, eax, 31:16, mtc_periods_bmp , MTC period encodings bitmap
+ 0x14, 1, ebx, 15:0, cycle_thresholds_bmp , Cycle Threshold encodings bitmap
+ 0x14, 1, ebx, 31:16, psb_periods_bmp , Configurable PSB frequency encodings bitmap
# Leaf 15H
-# Intel TSC (Time Stamp Counter) enumeration
+# Intel TSC (Time Stamp Counter)
0x15, 0, eax, 31:0, tsc_denominator , Denominator of the TSC/'core crystal clock' ratio
0x15, 0, ebx, 31:0, tsc_numerator , Numerator of the TSC/'core crystal clock' ratio
0x15, 0, ecx, 31:0, cpu_crystal_hz , Core crystal clock nominal frequency, in Hz
# Leaf 16H
-# Intel processor frequency enumeration
+# Intel processor frequency
0x16, 0, eax, 15:0, cpu_base_mhz , Processor base frequency, in MHz
0x16, 0, ebx, 15:0, cpu_max_mhz , Processor max frequency, in MHz
0x16, 0, ecx, 15:0, bus_mhz , Bus reference frequency, in MHz
# Leaf 17H
-# Intel SoC vendor attributes enumeration
+# Intel SoC vendor attributes
0x17, 0, eax, 31:0, soc_max_subleaf , Maximum leaf 0x17 subleaf
0x17, 0, ebx, 15:0, soc_vendor_id , SoC vendor ID
@@ -493,32 +501,32 @@
0x17, 3:1, edx, 31:0, vendor_brand_d , Vendor Brand ID string, bytes subleaf_nr * (12 -> 15)
# Leaf 18H
-# Intel determenestic address translation (TLB) parameters
+# Intel deterministic address translation (TLB) parameters
0x18, 31:0, eax, 31:0, tlb_max_subleaf , Maximum leaf 0x18 subleaf
- 0x18, 31:0, ebx, 0, tlb_4k_page , TLB 4KB-page entries supported
- 0x18, 31:0, ebx, 1, tlb_2m_page , TLB 2MB-page entries supported
- 0x18, 31:0, ebx, 2, tlb_4m_page , TLB 4MB-page entries supported
- 0x18, 31:0, ebx, 3, tlb_1g_page , TLB 1GB-page entries supported
- 0x18, 31:0, ebx, 10:8, hard_partitioning , (Hard/Soft) partitioning between logical CPUs sharing this structure
+ 0x18, 31:0, ebx, 0, tlb_4k_page , TLB supports 4KB-page entries
+ 0x18, 31:0, ebx, 1, tlb_2m_page , TLB supports 2MB-page entries
+ 0x18, 31:0, ebx, 2, tlb_4m_page , TLB supports 4MB-page entries
+ 0x18, 31:0, ebx, 3, tlb_1g_page , TLB supports 1GB-page entries
+ 0x18, 31:0, ebx, 10:8, hard_partitioning , Partitioning between logical CPUs
0x18, 31:0, ebx, 31:16, n_way_associative , Ways of associativity
0x18, 31:0, ecx, 31:0, n_sets , Number of sets
0x18, 31:0, edx, 4:0, tlb_type , Translation cache type (TLB type)
0x18, 31:0, edx, 7:5, tlb_cache_level , Translation cache level (1-based)
- 0x18, 31:0, edx, 8, is_fully_associative , Fully-associative structure
- 0x18, 31:0, edx, 25:14, tlb_max_addressible_ids, Max number of addressable IDs for logical CPUs sharing this TLB - 1
+ 0x18, 31:0, edx, 8, is_fully_associative , Fully-associative
+ 0x18, 31:0, edx, 25:14, tlb_max_addressible_ids, Max number of addressable IDs - 1
# Leaf 19H
-# Intel Key Locker enumeration
+# Intel key locker
- 0x19, 0, eax, 0, kl_cpl0_only , CPL0-only key Locker restriction supported
- 0x19, 0, eax, 1, kl_no_encrypt , No-encrypt key locker restriction supported
- 0x19, 0, eax, 2, kl_no_decrypt , No-decrypt key locker restriction supported
- 0x19, 0, ebx, 0, aes_keylocker , AES key locker instructions supported
- 0x19, 0, ebx, 2, aes_keylocker_wide , AES wide key locker instructions supported
- 0x19, 0, ebx, 4, kl_msr_iwkey , Key locker MSRs and IWKEY backups supported
- 0x19, 0, ecx, 0, loadiwkey_no_backup , LOADIWKEY NoBackup parameter supported
- 0x19, 0, ecx, 1, iwkey_rand , IWKEY randomization (KeySource encoding 1) supported
+ 0x19, 0, eax, 0, kl_cpl0_only , CPL0-only key Locker restriction
+ 0x19, 0, eax, 1, kl_no_encrypt , No-encrypt key locker restriction
+ 0x19, 0, eax, 2, kl_no_decrypt , No-decrypt key locker restriction
+ 0x19, 0, ebx, 0, aes_keylocker , AES key locker instructions
+ 0x19, 0, ebx, 2, aes_keylocker_wide , AES wide key locker instructions
+ 0x19, 0, ebx, 4, kl_msr_iwkey , Key locker MSRs and IWKEY backups
+ 0x19, 0, ecx, 0, loadiwkey_no_backup , LOADIWKEY NoBackup parameter
+ 0x19, 0, ecx, 1, iwkey_rand , IWKEY randomization
# Leaf 1AH
# Intel hybrid CPUs identification (e.g. Atom, Core)
@@ -527,7 +535,7 @@
0x1a, 0, eax, 31:24, core_type , This core's type
# Leaf 1BH
-# Intel PCONFIG (Platform configuration) enumeration
+# Intel PCONFIG (Platform configuration)
0x1b, 31:0, eax, 11:0, pconfig_subleaf_type , CPUID 0x1b subleaf type
0x1b, 31:0, ebx, 31:0, pconfig_target_id_x , A supported PCONFIG target ID
@@ -535,25 +543,18 @@
0x1b, 31:0, edx, 31:0, pconfig_target_id_z , A supported PCONFIG target ID
# Leaf 1CH
-# Intel LBR (Last Branch Record) enumeration
-
- 0x1c, 0, eax, 0, lbr_depth_8 , Max stack depth (number of LBR entries) = 8
- 0x1c, 0, eax, 1, lbr_depth_16 , Max stack depth (number of LBR entries) = 16
- 0x1c, 0, eax, 2, lbr_depth_24 , Max stack depth (number of LBR entries) = 24
- 0x1c, 0, eax, 3, lbr_depth_32 , Max stack depth (number of LBR entries) = 32
- 0x1c, 0, eax, 4, lbr_depth_40 , Max stack depth (number of LBR entries) = 40
- 0x1c, 0, eax, 5, lbr_depth_48 , Max stack depth (number of LBR entries) = 48
- 0x1c, 0, eax, 6, lbr_depth_56 , Max stack depth (number of LBR entries) = 56
- 0x1c, 0, eax, 7, lbr_depth_64 , Max stack depth (number of LBR entries) = 64
+# Intel LBR (Last Branch Record)
+
+ 0x1c, 0, eax, 7:0, lbr_depth_mask , Max LBR stack depth bitmask
0x1c, 0, eax, 30, lbr_deep_c_reset , LBRs maybe cleared on MWAIT C-state > C1
- 0x1c, 0, eax, 31, lbr_ip_is_lip , LBR IP contain Last IP, otherwise effective IP
- 0x1c, 0, ebx, 0, lbr_cpl , CPL filtering (non-zero IA32_LBR_CTL[2:1]) supported
- 0x1c, 0, ebx, 1, lbr_branch_filter , Branch filtering (non-zero IA32_LBR_CTL[22:16]) supported
- 0x1c, 0, ebx, 2, lbr_call_stack , Call-stack mode (IA32_LBR_CTL[3] = 1) supported
- 0x1c, 0, ecx, 0, lbr_mispredict , Branch misprediction bit supported (IA32_LBR_x_INFO[63])
- 0x1c, 0, ecx, 1, lbr_timed_lbr , Timed LBRs (CPU cycles since last LBR entry) supported
- 0x1c, 0, ecx, 2, lbr_branch_type , Branch type field (IA32_LBR_INFO_x[59:56]) supported
- 0x1c, 0, ecx, 19:16, lbr_events_gpc_bmp , LBR PMU-events logging support; bitmap for first 4 GP (general-purpose) Counters
+ 0x1c, 0, eax, 31, lbr_ip_is_lip , LBR IP contain Last IP (otherwise effective IP)
+ 0x1c, 0, ebx, 0, lbr_cpl , CPL filtering
+ 0x1c, 0, ebx, 1, lbr_branch_filter , Branch filtering
+ 0x1c, 0, ebx, 2, lbr_call_stack , Call-stack mode
+ 0x1c, 0, ecx, 0, lbr_mispredict , Branch misprediction bit
+ 0x1c, 0, ecx, 1, lbr_timed_lbr , Timed LBRs (CPU cycles since last LBR entry)
+ 0x1c, 0, ecx, 2, lbr_branch_type , Branch type field
+ 0x1c, 0, ecx, 19:16, lbr_events_gpc_bmp , PMU-events logging support
# Leaf 1DH
# Intel AMX (Advanced Matrix Extensions) tile information
@@ -566,13 +567,13 @@
0x1d, 1, ecx, 15:0, amx_tile_nr_rows , AMX tile max number of rows
# Leaf 1EH
-# Intel AMX, TMUL (Tile-matrix MULtiply) accelerator unit enumeration
+# Intel TMUL (Tile-matrix Multiply)
0x1e, 0, ebx, 7:0, tmul_maxk , TMUL unit maximum height, K (rows or columns)
0x1e, 0, ebx, 23:8, tmul_maxn , TMUL unit maximum SIMD dimension, N (column bytes)
# Leaf 1FH
-# Intel extended topology enumeration v2
+# Intel extended topology v2
0x1f, 5:0, eax, 4:0, x2apic_id_shift , Bit width of this level (previous levels inclusive)
0x1f, 5:0, ebx, 15:0, domain_lcpus_count , Logical CPUs count across all instances of this domain
@@ -581,13 +582,13 @@
0x1f, 5:0, edx, 31:0, x2apic_id , x2APIC ID of current logical CPU
# Leaf 20H
-# Intel HRESET (History Reset) enumeration
+# Intel HRESET (History Reset)
0x20, 0, eax, 31:0, hreset_nr_subleaves , CPUID 0x20 max subleaf + 1
- 0x20, 0, ebx, 0, hreset_thread_director , HRESET of Intel thread director is supported
+ 0x20, 0, ebx, 0, hreset_thread_director , Intel thread director HRESET
# Leaf 21H
-# Intel TD (Trust Domain) guest execution environment enumeration
+# Intel TD (Trust Domain)
0x21, 0, ebx, 31:0, tdx_vendorid_0 , TDX vendor ID string bytes 0 - 3
0x21, 0, ecx, 31:0, tdx_vendorid_2 , CPU vendor ID string bytes 8 - 11
@@ -596,43 +597,64 @@
# Leaf 23H
# Intel Architectural Performance Monitoring Extended (ArchPerfmonExt)
- 0x23, 0, eax, 1, subleaf_1_counters , Subleaf 1, PMU counters bitmaps, is valid
- 0x23, 0, eax, 3, subleaf_3_events , Subleaf 3, PMU events bitmaps, is valid
- 0x23, 0, ebx, 0, unitmask2 , IA32_PERFEVTSELx MSRs UnitMask2 is supported
- 0x23, 0, ebx, 1, zbit , IA32_PERFEVTSELx MSRs Z-bit is supported
- 0x23, 1, eax, 31:0, pmu_gp_counters_bitmap , General-purpose PMU counters bitmap
- 0x23, 1, ebx, 31:0, pmu_f_counters_bitmap , Fixed PMU counters bitmap
- 0x23, 3, eax, 0, core_cycles_evt , Core cycles event supported
- 0x23, 3, eax, 1, insn_retired_evt , Instructions retired event supported
- 0x23, 3, eax, 2, ref_cycles_evt , Reference cycles event supported
- 0x23, 3, eax, 3, llc_refs_evt , Last-level cache references event supported
- 0x23, 3, eax, 4, llc_misses_evt , Last-level cache misses event supported
- 0x23, 3, eax, 5, br_insn_ret_evt , Branch instruction retired event supported
- 0x23, 3, eax, 6, br_mispr_evt , Branch mispredict retired event supported
- 0x23, 3, eax, 7, td_slots_evt , Topdown slots event supported
- 0x23, 3, eax, 8, td_backend_bound_evt , Topdown backend bound event supported
- 0x23, 3, eax, 9, td_bad_spec_evt , Topdown bad speculation event supported
- 0x23, 3, eax, 10, td_frontend_bound_evt , Topdown frontend bound event supported
- 0x23, 3, eax, 11, td_retiring_evt , Topdown retiring event support
+ 0x23, 0, eax, 0, subleaf_0 , Subleaf 0, this subleaf
+ 0x23, 0, eax, 1, counters_subleaf , Subleaf 1, PMU counter bitmaps
+ 0x23, 0, eax, 2, acr_subleaf , Subleaf 2, Auto Counter Reload bitmaps
+ 0x23, 0, eax, 3, events_subleaf , Subleaf 3, PMU event bitmaps
+ 0x23, 0, eax, 4, pebs_caps_subleaf , Subleaf 4, PEBS capabilities
+ 0x23, 0, eax, 5, pebs_subleaf , Subleaf 5, Arch PEBS bitmaps
+ 0x23, 0, ebx, 0, unitmask2 , IA32_PERFEVTSELx MSRs UnitMask2 bit
+ 0x23, 0, ebx, 1, eq , IA32_PERFEVTSELx MSRs EQ bit
+ 0x23, 0, ebx, 2, rdpmc_user_disable , RDPMC userspace disable
+ 0x23, 1, eax, 31:0, gp_counters , Bitmap of general-purpose PMU counters
+ 0x23, 1, ebx, 31:0, fixed_counters , Bitmap of fixed PMU counters
+ 0x23, 2, eax, 31:0, acr_gp_reload , Bitmap of general-purpose counters that can be reloaded
+ 0x23, 2, ebx, 31:0, acr_fixed_reload , Bitmap of fixed counters that can be reloaded
+ 0x23, 2, ecx, 31:0, acr_gp_trigger , Bitmap of general-purpose counters that can trigger reloads
+ 0x23, 2, edx, 31:0, acr_fixed_trigger , Bitmap of fixed counters that can trigger reloads
+ 0x23, 3, eax, 0, core_cycles_evt , Core cycles event
+ 0x23, 3, eax, 1, insn_retired_evt , Instructions retired event
+ 0x23, 3, eax, 2, ref_cycles_evt , Reference cycles event
+ 0x23, 3, eax, 3, llc_refs_evt , Last-level cache references event
+ 0x23, 3, eax, 4, llc_misses_evt , Last-level cache misses event
+ 0x23, 3, eax, 5, br_insn_ret_evt , Branch instruction retired event
+ 0x23, 3, eax, 6, br_mispr_evt , Branch mispredict retired event
+ 0x23, 3, eax, 7, td_slots_evt , Topdown slots event
+ 0x23, 3, eax, 8, td_backend_bound_evt , Topdown backend bound event
+ 0x23, 3, eax, 9, td_bad_spec_evt , Topdown bad speculation event
+ 0x23, 3, eax, 10, td_frontend_bound_evt , Topdown frontend bound event
+ 0x23, 3, eax, 11, td_retiring_evt , Topdown retiring event
+ 0x23, 4, ebx, 3, allow_in_record , ALLOW_IN_RECORD bit in MSRs
+ 0x23, 4, ebx, 4, counters_gp , Counters group sub-group general-purpose counters
+ 0x23, 4, ebx, 5, counters_fixed , Counters group sub-group fixed-function counters
+ 0x23, 4, ebx, 6, counters_metrics , Counters group sub-group performance metrics
+ 0x23, 4, ebx, 9:8, lbr , LBR group
+ 0x23, 4, ebx, 23:16, xer , XER group
+ 0x23, 4, ebx, 29, gpr , GPR group
+ 0x23, 4, ebx, 30, aux , AUX group
+ 0x23, 5, eax, 31:0, pebs_gp , Architectural PEBS general-purpose counters
+ 0x23, 5, ebx, 31:0, pebs_pdist_gp , Architectural PEBS PDIST general-purpose counters
+ 0x23, 5, ecx, 31:0, pebs_fixed , Architectural PEBS fixed counters
+ 0x23, 5, edx, 31:0, pebs_pdist_fixed , Architectural PEBS PDIST fixed counters
# Leaf 40000000H
-# Maximum hypervisor standard leaf + hypervisor vendor string
+# Maximum hypervisor leaf + hypervisor vendor string
-0x40000000, 0, eax, 31:0, max_hyp_leaf , Maximum hypervisor standard leaf number
+0x40000000, 0, eax, 31:0, max_hyp_leaf , Maximum hypervisor leaf
0x40000000, 0, ebx, 31:0, hypervisor_id_0 , Hypervisor ID string bytes 0 - 3
0x40000000, 0, ecx, 31:0, hypervisor_id_1 , Hypervisor ID string bytes 4 - 7
0x40000000, 0, edx, 31:0, hypervisor_id_2 , Hypervisor ID string bytes 8 - 11
# Leaf 80000000H
-# Maximum extended leaf number + AMD/Transmeta CPU vendor string
+# Maximum extended leaf + CPU vendor string
-0x80000000, 0, eax, 31:0, max_ext_leaf , Maximum extended CPUID leaf supported
+0x80000000, 0, eax, 31:0, max_ext_leaf , Maximum extended CPUID leaf
0x80000000, 0, ebx, 31:0, cpu_vendorid_0 , Vendor ID string bytes 0 - 3
0x80000000, 0, ecx, 31:0, cpu_vendorid_2 , Vendor ID string bytes 8 - 11
0x80000000, 0, edx, 31:0, cpu_vendorid_1 , Vendor ID string bytes 4 - 7
# Leaf 80000001H
-# Extended CPU feature identifiers
+# Extended CPU features
0x80000001, 0, eax, 3:0, e_stepping_id , Stepping ID
0x80000001, 0, eax, 7:4, e_base_model , Base processor model
@@ -723,7 +745,7 @@
0x80000004, 0, edx, 31:0, cpu_brandid_11 , CPU brand ID string, bytes 44 - 47
# Leaf 80000005H
-# AMD/Transmeta L1 cache and L1 TLB enumeration
+# AMD/Transmeta L1 cache and TLB
0x80000005, 0, eax, 7:0, l1_itlb_2m_4m_nentries , L1 ITLB #entries, 2M and 4M pages
0x80000005, 0, eax, 15:8, l1_itlb_2m_4m_assoc , L1 ITLB associativity, 2M and 4M pages
@@ -743,7 +765,7 @@
0x80000005, 0, edx, 31:24, l1_icache_size_kb , L1 icache size, in KB
# Leaf 80000006H
-# (Mostly AMD) L2 TLB, L2 cache, and L3 cache enumeration
+# (Mostly AMD) L2/L3 cache and TLB
0x80000006, 0, eax, 11:0, l2_itlb_2m_4m_nentries , L2 iTLB #entries, 2M and 4M pages
0x80000006, 0, eax, 15:12, l2_itlb_2m_4m_assoc , L2 iTLB associativity, 2M and 4M pages
@@ -763,7 +785,7 @@
0x80000006, 0, edx, 31:18, l3_size_range , L3 cache size range
# Leaf 80000007H
-# CPU power management (mostly AMD) and AMD RAS enumeration
+# CPU power management (mostly AMD) and AMD RAS
0x80000007, 0, ebx, 0, overflow_recov , MCA overflow conditions not fatal
0x80000007, 0, ebx, 1, succor , Software containment of uncorrectable errors
@@ -792,14 +814,14 @@
0x80000008, 0, eax, 7:0, phys_addr_bits , Max physical address bits
0x80000008, 0, eax, 15:8, virt_addr_bits , Max virtual address bits
0x80000008, 0, eax, 23:16, guest_phys_addr_bits , Max nested-paging guest physical address bits
-0x80000008, 0, ebx, 0, clzero , CLZERO supported
+0x80000008, 0, ebx, 0, clzero , CLZERO instruction
0x80000008, 0, ebx, 1, irperf , Instruction retired counter MSR
0x80000008, 0, ebx, 2, xsaveerptr , XSAVE/XRSTOR always saves/restores FPU error pointers
-0x80000008, 0, ebx, 3, invlpgb , INVLPGB broadcasts a TLB invalidate to all threads
-0x80000008, 0, ebx, 4, rdpru , RDPRU (Read Processor Register at User level) supported
+0x80000008, 0, ebx, 3, invlpgb , INVLPGB broadcasts a TLB invalidate
+0x80000008, 0, ebx, 4, rdpru , RDPRU (Read Processor Register at User level)
0x80000008, 0, ebx, 6, mba , Memory Bandwidth Allocation (AMD bit)
-0x80000008, 0, ebx, 8, mcommit , MCOMMIT (Memory commit) supported
-0x80000008, 0, ebx, 9, wbnoinvd , WBNOINVD supported
+0x80000008, 0, ebx, 8, mcommit , MCOMMIT instruction
+0x80000008, 0, ebx, 9, wbnoinvd , WBNOINVD instruction
0x80000008, 0, ebx, 12, amd_ibpb , Indirect Branch Prediction Barrier
0x80000008, 0, ebx, 13, wbinvd_int , Interruptible WBINVD/WBNOINVD
0x80000008, 0, ebx, 14, amd_ibrs , Indirect Branch Restricted Speculation
@@ -808,8 +830,8 @@
0x80000008, 0, ebx, 17, amd_stibp_always_on , STIBP always-on preferred
0x80000008, 0, ebx, 18, ibrs_fast , IBRS is preferred over software solution
0x80000008, 0, ebx, 19, ibrs_same_mode , IBRS provides same mode protection
-0x80000008, 0, ebx, 20, no_efer_lmsle , EFER[LMSLE] bit (Long-Mode Segment Limit Enable) unsupported
-0x80000008, 0, ebx, 21, tlb_flush_nested , INVLPGB RAX[5] bit can be set (nested translations)
+0x80000008, 0, ebx, 20, no_efer_lmsle , Long-Mode Segment Limit Enable unsupported
+0x80000008, 0, ebx, 21, tlb_flush_nested , INVLPGB RAX[5] bit can be set
0x80000008, 0, ebx, 23, amd_ppin , Protected Processor Inventory Number
0x80000008, 0, ebx, 24, amd_ssbd , Speculative Store Bypass Disable
0x80000008, 0, ebx, 25, virt_ssbd , virtualized SSBD (Speculative Store Bypass Disable)
@@ -818,7 +840,7 @@
0x80000008, 0, ebx, 28, amd_psfd , Predictive Store Forward Disable
0x80000008, 0, ebx, 29, btc_no , CPU not affected by Branch Type Confusion
0x80000008, 0, ebx, 30, ibpb_ret , IBPB clears RSB/RAS too
-0x80000008, 0, ebx, 31, brs , Branch Sampling supported
+0x80000008, 0, ebx, 31, brs , Branch Sampling
0x80000008, 0, ecx, 7:0, cpu_nthreads , Number of physical threads - 1
0x80000008, 0, ecx, 15:12, apicid_coreid_len , Number of thread core ID bits (shift) in APIC ID
0x80000008, 0, ecx, 17:16, perf_tsc_len , Performance time-stamp counter size
@@ -826,10 +848,11 @@
0x80000008, 0, edx, 31:16, rdpru_max_reg_id , RDPRU max register ID (ECX input)
# Leaf 8000000AH
-# AMD SVM (Secure Virtual Machine) enumeration
+# AMD SVM (Secure Virtual Machine)
0x8000000a, 0, eax, 7:0, svm_version , SVM revision number
0x8000000a, 0, ebx, 31:0, svm_nasid , Number of address space identifiers (ASID)
+0x8000000a, 0, ecx, 4, pml , Page Modification Logging (PML)
0x8000000a, 0, edx, 0, npt , Nested paging
0x8000000a, 0, edx, 1, lbrv , LBR virtualization
0x8000000a, 0, edx, 2, svm_lock , SVM lock
@@ -856,7 +879,7 @@
0x8000000a, 0, edx, 28, svme_addr_chk , Guest SVME address check
# Leaf 80000019H
-# AMD TLB 1G-pages enumeration
+# AMD TLB characteristics for 1GB pages
0x80000019, 0, eax, 11:0, l1_itlb_1g_nentries , L1 iTLB #entries, 1G pages
0x80000019, 0, eax, 15:12, l1_itlb_1g_assoc , L1 iTLB associativity, 1G pages
@@ -868,64 +891,64 @@
0x80000019, 0, ebx, 31:28, l2_dtlb_1g_assoc , L2 dTLB associativity, 1G pages
# Leaf 8000001AH
-# AMD instruction optimizations enumeration
+# AMD instruction optimizations
0x8000001a, 0, eax, 0, fp_128 , Internal FP/SIMD exec data path is 128-bits wide
0x8000001a, 0, eax, 1, movu_preferred , SSE: MOVU* better than MOVL*/MOVH*
0x8000001a, 0, eax, 2, fp_256 , internal FP/SSE exec data path is 256-bits wide
# Leaf 8000001BH
-# AMD IBS (Instruction-Based Sampling) enumeration
-
-0x8000001b, 0, eax, 0, ibs_flags_valid , IBS feature flags valid
-0x8000001b, 0, eax, 1, ibs_fetch_sampling , IBS fetch sampling supported
-0x8000001b, 0, eax, 2, ibs_op_sampling , IBS execution sampling supported
-0x8000001b, 0, eax, 3, ibs_rdwr_op_counter , IBS read/write of op counter supported
-0x8000001b, 0, eax, 4, ibs_op_count , IBS OP counting mode supported
-0x8000001b, 0, eax, 5, ibs_branch_target , IBS branch target address reporting supported
+# AMD IBS (Instruction-Based Sampling)
+
+0x8000001b, 0, eax, 0, ibs_flags , IBS feature flags
+0x8000001b, 0, eax, 1, ibs_fetch_sampling , IBS fetch sampling
+0x8000001b, 0, eax, 2, ibs_op_sampling , IBS execution sampling
+0x8000001b, 0, eax, 3, ibs_rdwr_op_counter , IBS read/write of op counter
+0x8000001b, 0, eax, 4, ibs_op_count , IBS OP counting mode
+0x8000001b, 0, eax, 5, ibs_branch_target , IBS branch target address reporting
0x8000001b, 0, eax, 6, ibs_op_counters_ext , IBS IbsOpCurCnt/IbsOpMaxCnt extend by 7 bits
-0x8000001b, 0, eax, 7, ibs_rip_invalid_chk , IBS invalid RIP indication supported
-0x8000001b, 0, eax, 8, ibs_op_branch_fuse , IBS fused branch micro-op indication supported
-0x8000001b, 0, eax, 9, ibs_fetch_ctl_ext , IBS Fetch Control Extended MSR (0xc001103c) supported
-0x8000001b, 0, eax, 10, ibs_op_data_4 , IBS op data 4 MSR supported
-0x8000001b, 0, eax, 11, ibs_l3_miss_filter , IBS L3-miss filtering supported (Zen4+)
+0x8000001b, 0, eax, 7, ibs_rip_invalid_chk , IBS invalid RIP indication
+0x8000001b, 0, eax, 8, ibs_op_branch_fuse , IBS fused branch micro-op indication
+0x8000001b, 0, eax, 9, ibs_fetch_ctl_ext , IBS Fetch Control Extended MSR
+0x8000001b, 0, eax, 10, ibs_op_data_4 , IBS op data 4 MSR
+0x8000001b, 0, eax, 11, ibs_l3_miss_filter , IBS L3-miss filtering (Zen4+)
# Leaf 8000001CH
# AMD LWP (Lightweight Profiling)
-0x8000001c, 0, eax, 0, os_lwp_avail , LWP is available to application programs (supported by OS)
-0x8000001c, 0, eax, 1, os_lpwval , LWPVAL instruction is supported by OS
-0x8000001c, 0, eax, 2, os_lwp_ire , Instructions Retired Event is supported by OS
-0x8000001c, 0, eax, 3, os_lwp_bre , Branch Retired Event is supported by OS
-0x8000001c, 0, eax, 4, os_lwp_dme , Dcache Miss Event is supported by OS
-0x8000001c, 0, eax, 5, os_lwp_cnh , CPU Clocks Not Halted event is supported by OS
-0x8000001c, 0, eax, 6, os_lwp_rnh , CPU Reference clocks Not Halted event is supported by OS
-0x8000001c, 0, eax, 29, os_lwp_cont , LWP sampling in continuous mode is supported by OS
-0x8000001c, 0, eax, 30, os_lwp_ptsc , Performance Time Stamp Counter in event records is supported by OS
-0x8000001c, 0, eax, 31, os_lwp_int , Interrupt on threshold overflow is supported by OS
-0x8000001c, 0, ebx, 7:0, lwp_lwpcb_sz , LWP Control Block size, in quadwords
-0x8000001c, 0, ebx, 15:8, lwp_event_sz , LWP event record size, in bytes
-0x8000001c, 0, ebx, 23:16, lwp_max_events , LWP max supported EventID value (EventID 255 not included)
-0x8000001c, 0, ebx, 31:24, lwp_event_offset , LWP events area offset in the LWP Control Block
-0x8000001c, 0, ecx, 4:0, lwp_latency_max , Number of bits in cache latency counters (10 to 31)
-0x8000001c, 0, ecx, 5, lwp_data_adddr , Cache miss events report the data address of the reference
-0x8000001c, 0, ecx, 8:6, lwp_latency_rnd , Amount by which cache latency is rounded
-0x8000001c, 0, ecx, 15:9, lwp_version , LWP implementation version
-0x8000001c, 0, ecx, 23:16, lwp_buf_min_sz , LWP event ring buffer min size, in units of 32 event records
+0x8000001c, 0, eax, 0, os_lwp_avail , OS: LWP is available to application programs
+0x8000001c, 0, eax, 1, os_lpwval , OS: LWPVAL instruction
+0x8000001c, 0, eax, 2, os_lwp_ire , OS: Instructions Retired Event
+0x8000001c, 0, eax, 3, os_lwp_bre , OS: Branch Retired Event
+0x8000001c, 0, eax, 4, os_lwp_dme , OS: Dcache Miss Event
+0x8000001c, 0, eax, 5, os_lwp_cnh , OS: CPU Clocks Not Halted event
+0x8000001c, 0, eax, 6, os_lwp_rnh , OS: CPU Reference clocks Not Halted event
+0x8000001c, 0, eax, 29, os_lwp_cont , OS: LWP sampling in continuous mode
+0x8000001c, 0, eax, 30, os_lwp_ptsc , OS: Performance Time Stamp Counter in event records
+0x8000001c, 0, eax, 31, os_lwp_int , OS: Interrupt on threshold overflow
+0x8000001c, 0, ebx, 7:0, lwp_lwpcb_sz , Control Block size, in quadwords
+0x8000001c, 0, ebx, 15:8, lwp_event_sz , Event record size, in bytes
+0x8000001c, 0, ebx, 23:16, lwp_max_events , Max EventID supported
+0x8000001c, 0, ebx, 31:24, lwp_event_offset , Control Block events area offset
+0x8000001c, 0, ecx, 4:0, lwp_latency_max , Cache latency counters number of bits
+0x8000001c, 0, ecx, 5, lwp_data_addr , Cache miss events report data cache address
+0x8000001c, 0, ecx, 8:6, lwp_latency_rnd , Cache latency rounding amount
+0x8000001c, 0, ecx, 15:9, lwp_version , LWP version
+0x8000001c, 0, ecx, 23:16, lwp_buf_min_sz , LWP event ring buffer min size, 32 event records units
0x8000001c, 0, ecx, 28, lwp_branch_predict , Branches Retired events can be filtered
-0x8000001c, 0, ecx, 29, lwp_ip_filtering , IP filtering (IPI, IPF, BaseIP, and LimitIP @ LWPCP) supported
-0x8000001c, 0, ecx, 30, lwp_cache_levels , Cache-related events can be filtered by cache level
-0x8000001c, 0, ecx, 31, lwp_cache_latency , Cache-related events can be filtered by latency
-0x8000001c, 0, edx, 0, hw_lwp_avail , LWP is available in hardware
-0x8000001c, 0, edx, 1, hw_lpwval , LWPVAL instruction is available in hardware
-0x8000001c, 0, edx, 2, hw_lwp_ire , Instructions Retired Event is available in hardware
-0x8000001c, 0, edx, 3, hw_lwp_bre , Branch Retired Event is available in hardware
-0x8000001c, 0, edx, 4, hw_lwp_dme , Dcache Miss Event is available in hardware
-0x8000001c, 0, edx, 5, hw_lwp_cnh , Clocks Not Halted event is available in hardware
-0x8000001c, 0, edx, 6, hw_lwp_rnh , Reference clocks Not Halted event is available in hardware
-0x8000001c, 0, edx, 29, hw_lwp_cont , LWP sampling in continuous mode is available in hardware
-0x8000001c, 0, edx, 30, hw_lwp_ptsc , Performance Time Stamp Counter in event records is available in hardware
-0x8000001c, 0, edx, 31, hw_lwp_int , Interrupt on threshold overflow is available in hardware
+0x8000001c, 0, ecx, 29, lwp_ip_filtering , IP filtering (IPI, IPF, BaseIP, and LimitIP @ LWPCP)
+0x8000001c, 0, ecx, 30, lwp_cache_levels , Cache-related events: filter by cache level
+0x8000001c, 0, ecx, 31, lwp_cache_latency , Cache-related events: filter by latency
+0x8000001c, 0, edx, 0, hw_lwp_avail , HW: LWP available
+0x8000001c, 0, edx, 1, hw_lpwval , HW: LWPVAL available
+0x8000001c, 0, edx, 2, hw_lwp_ire , HW: Instructions Retired Event
+0x8000001c, 0, edx, 3, hw_lwp_bre , HW: Branch Retired Event
+0x8000001c, 0, edx, 4, hw_lwp_dme , HW: Dcache Miss Event
+0x8000001c, 0, edx, 5, hw_lwp_cnh , HW: Clocks Not Halted event
+0x8000001c, 0, edx, 6, hw_lwp_rnh , HW: Reference clocks Not Halted event
+0x8000001c, 0, edx, 29, hw_lwp_cont , HW: LWP sampling in continuous mode
+0x8000001c, 0, edx, 30, hw_lwp_ptsc , HW: Performance Time Stamp Counter in event records
+0x8000001c, 0, edx, 31, hw_lwp_int , HW: Interrupt on threshold overflow
# Leaf 8000001DH
# AMD deterministic cache parameters
@@ -943,49 +966,49 @@
0x8000001d, 31:0, edx, 1, ll_inclusive , Cache is inclusive of Lower-Level caches
# Leaf 8000001EH
-# AMD CPU topology enumeration
+# AMD CPU topology
0x8000001e, 0, eax, 31:0, ext_apic_id , Extended APIC ID
0x8000001e, 0, ebx, 7:0, core_id , Unique per-socket logical core unit ID
-0x8000001e, 0, ebx, 15:8, core_nthreas , #Threads per core (zero-based)
+0x8000001e, 0, ebx, 15:8, core_nthreads , #Threads per core (zero-based)
0x8000001e, 0, ecx, 7:0, node_id , Node (die) ID of invoking logical CPU
0x8000001e, 0, ecx, 10:8, nnodes_per_socket , #nodes in invoking logical CPU's package/socket
# Leaf 8000001FH
-# AMD encrypted memory capabilities enumeration (SME/SEV)
-
-0x8000001f, 0, eax, 0, sme , Secure Memory Encryption supported
-0x8000001f, 0, eax, 1, sev , Secure Encrypted Virtualization supported
-0x8000001f, 0, eax, 2, vm_page_flush , VM Page Flush MSR (0xc001011e) available
-0x8000001f, 0, eax, 3, sev_es , SEV Encrypted State supported
-0x8000001f, 0, eax, 4, sev_nested_paging , SEV secure nested paging supported
-0x8000001f, 0, eax, 5, vm_permission_levels , VMPL supported
-0x8000001f, 0, eax, 6, rpmquery , RPMQUERY instruction supported
-0x8000001f, 0, eax, 7, vmpl_sss , VMPL supervisor shadow stack supported
-0x8000001f, 0, eax, 8, secure_tsc , Secure TSC supported
+# AMD encrypted memory capabilities (SME/SEV)
+
+0x8000001f, 0, eax, 0, sme , Secure Memory Encryption
+0x8000001f, 0, eax, 1, sev , Secure Encrypted Virtualization
+0x8000001f, 0, eax, 2, vm_page_flush , VM Page Flush MSR
+0x8000001f, 0, eax, 3, sev_es , SEV Encrypted State
+0x8000001f, 0, eax, 4, sev_nested_paging , SEV secure nested paging
+0x8000001f, 0, eax, 5, vm_permission_levels , VMPL
+0x8000001f, 0, eax, 6, rpmquery , RPMQUERY instruction
+0x8000001f, 0, eax, 7, vmpl_sss , VMPL supervisor shadow stack
+0x8000001f, 0, eax, 8, secure_tsc , Secure TSC
0x8000001f, 0, eax, 9, v_tsc_aux , Hardware virtualizes TSC_AUX
-0x8000001f, 0, eax, 10, sme_coherent , Cache coherency is enforced across encryption domains
+0x8000001f, 0, eax, 10, sme_coherent , Cache coherency enforcement across encryption domains
0x8000001f, 0, eax, 11, req_64bit_hypervisor , SEV guest mandates 64-bit hypervisor
0x8000001f, 0, eax, 12, restricted_injection , Restricted Injection supported
0x8000001f, 0, eax, 13, alternate_injection , Alternate Injection supported
-0x8000001f, 0, eax, 14, debug_swap , SEV-ES: full debug state swap is supported
-0x8000001f, 0, eax, 15, disallow_host_ibs , SEV-ES: Disallowing IBS use by the host is supported
+0x8000001f, 0, eax, 14, debug_swap , SEV-ES: Full debug state swap
+0x8000001f, 0, eax, 15, disallow_host_ibs , SEV-ES: Disallowing IBS use by the host
0x8000001f, 0, eax, 16, virt_transparent_enc , Virtual Transparent Encryption
-0x8000001f, 0, eax, 17, vmgexit_paremeter , VmgexitParameter is supported in SEV_FEATURES
-0x8000001f, 0, eax, 18, virt_tom_msr , Virtual TOM MSR is supported
-0x8000001f, 0, eax, 19, virt_ibs , IBS state virtualization is supported for SEV-ES guests
-0x8000001f, 0, eax, 24, vmsa_reg_protection , VMSA register protection is supported
-0x8000001f, 0, eax, 25, smt_protection , SMT protection is supported
-0x8000001f, 0, eax, 28, svsm_page_msr , SVSM communication page MSR (0xc001f000) is supported
-0x8000001f, 0, eax, 29, nested_virt_snp_msr , VIRT_RMPUPDATE/VIRT_PSMASH MSRs are supported
-0x8000001f, 0, ebx, 5:0, pte_cbit_pos , PTE bit number used to enable memory encryption
-0x8000001f, 0, ebx, 11:6, phys_addr_reduction_nbits, Reduction of phys address space when encryption is enabled, in bits
-0x8000001f, 0, ebx, 15:12, vmpl_count , Number of VM permission levels (VMPL) supported
-0x8000001f, 0, ecx, 31:0, enc_guests_max , Max supported number of simultaneous encrypted guests
+0x8000001f, 0, eax, 17, vmgexit_parameter , SEV_FEATURES: VmgexitParameter
+0x8000001f, 0, eax, 18, virt_tom_msr , Virtual TOM MSR
+0x8000001f, 0, eax, 19, virt_ibs , SEV-ES guests: IBS state virtualization
+0x8000001f, 0, eax, 24, vmsa_reg_protection , VMSA register protection
+0x8000001f, 0, eax, 25, smt_protection , SMT protection
+0x8000001f, 0, eax, 28, svsm_page_msr , SVSM communication page MSR
+0x8000001f, 0, eax, 29, nested_virt_snp_msr , VIRT_RMPUPDATE/VIRT_PSMASH MSRs
+0x8000001f, 0, ebx, 5:0, pte_cbit_pos , PTE bit number to enable memory encryption
+0x8000001f, 0, ebx, 11:6, phys_addr_reduction_nbits, Reduction of phys address space in bits
+0x8000001f, 0, ebx, 15:12, vmpl_count , Number of VM permission levels (VMPL)
+0x8000001f, 0, ecx, 31:0, enc_guests_max , Max number of simultaneous encrypted guests
0x8000001f, 0, edx, 31:0, min_sev_asid_no_sev_es , Minimum ASID for SEV-enabled SEV-ES-disabled guest
# Leaf 80000020H
-# AMD Platform QoS extended feature IDs
+# AMD PQoS (Platform QoS) extended features
0x80000020, 0, ebx, 1, mba , Memory Bandwidth Allocation support
0x80000020, 0, ebx, 2, smba , Slow Memory Bandwidth Allocation support
@@ -1007,7 +1030,7 @@
0x80000020, 3, ecx, 6, bmec_all_dirty_victims , Dirty QoS victims to all types of memory can be tracked
# Leaf 80000021H
-# AMD extended features enumeration 2
+# AMD extended CPU features 2
0x80000021, 0, eax, 0, no_nested_data_bp , No nested data breakpoints
0x80000021, 0, eax, 1, fsgs_non_serializing , WRMSR to {FS,GS,KERNEL_GS}_BASE is non-serializing
@@ -1016,43 +1039,43 @@
0x80000021, 0, eax, 6, null_sel_clr_base , Null selector clears base
0x80000021, 0, eax, 7, upper_addr_ignore , EFER MSR Upper Address Ignore
0x80000021, 0, eax, 8, autoibrs , EFER MSR Automatic IBRS
-0x80000021, 0, eax, 9, no_smm_ctl_msr , SMM_CTL MSR (0xc0010116) is not available
+0x80000021, 0, eax, 9, no_smm_ctl_msr , SMM_CTL MSR not available
0x80000021, 0, eax, 10, fsrs , Fast Short Rep STOSB
0x80000021, 0, eax, 11, fsrc , Fast Short Rep CMPSB
-0x80000021, 0, eax, 13, prefetch_ctl_msr , Prefetch control MSR is available
+0x80000021, 0, eax, 13, prefetch_ctl_msr , Prefetch control MSR
0x80000021, 0, eax, 16, opcode_reclaim , Reserves opcode space
-0x80000021, 0, eax, 17, user_cpuid_disable , #GP when executing CPUID at CPL > 0 is supported
+0x80000021, 0, eax, 17, user_cpuid_disable , #GP when executing CPUID at CPL > 0
0x80000021, 0, eax, 18, epsf , Enhanced Predictive Store Forwarding
0x80000021, 0, eax, 22, wl_feedback , Workload-based heuristic feedback to OS
0x80000021, 0, eax, 24, eraps , Enhanced Return Address Predictor Security
0x80000021, 0, eax, 27, sbpb , Selective Branch Predictor Barrier
0x80000021, 0, eax, 28, ibpb_brtype , Branch predictions flushed from CPU branch predictor
-0x80000021, 0, eax, 29, srso_no , CPU is not subject to the SRSO vulnerability
-0x80000021, 0, eax, 30, srso_uk_no , CPU is not vulnerable to SRSO at user-kernel boundary
-0x80000021, 0, eax, 31, srso_msr_fix , Software may use MSR BP_CFG[BpSpecReduce] to mitigate SRSO
-0x80000021, 0, ebx, 15:0, microcode_patch_size , Size of microcode patch, in 16-byte units
+0x80000021, 0, eax, 29, srso_no , No SRSO vulnerability
+0x80000021, 0, eax, 30, srso_uk_no , No SRSO at user-kernel boundary
+0x80000021, 0, eax, 31, srso_msr_fix , MSR BP_CFG[BpSpecReduce] SRSO mitigation
+0x80000021, 0, ebx, 15:0, microcode_patch_size , Microcode patch size, in 16-byte units
0x80000021, 0, ebx, 23:16, rap_size , Return Address Predictor size
# Leaf 80000022H
-# AMD Performance Monitoring v2 enumeration
+# AMD extended performance monitoring
-0x80000022, 0, eax, 0, perfmon_v2 , Performance monitoring v2 supported
+0x80000022, 0, eax, 0, perfmon_v2 , Performance monitoring v2
0x80000022, 0, eax, 1, lbr_v2 , Last Branch Record v2 extensions (LBR Stack)
-0x80000022, 0, eax, 2, lbr_pmc_freeze , Freezing core performance counters / LBR Stack supported
+0x80000022, 0, eax, 2, lbr_pmc_freeze , Freezing core performance counters / LBR Stack
0x80000022, 0, ebx, 3:0, n_pmc_core , Number of core performance counters
-0x80000022, 0, ebx, 9:4, lbr_v2_stack_size , Number of available LBR stack entries
-0x80000022, 0, ebx, 15:10, n_pmc_northbridge , Number of available northbridge (data fabric) performance counters
-0x80000022, 0, ebx, 21:16, n_pmc_umc , Number of available UMC performance counters
+0x80000022, 0, ebx, 9:4, lbr_v2_stack_size , Number of LBR stack entries
+0x80000022, 0, ebx, 15:10, n_pmc_northbridge , Number of northbridge performance counters
+0x80000022, 0, ebx, 21:16, n_pmc_umc , Number of UMC performance counters
0x80000022, 0, ecx, 31:0, active_umc_bitmask , Active UMCs bitmask
# Leaf 80000023H
-# AMD Secure Multi-key Encryption enumeration
+# AMD multi-key encrypted memory
-0x80000023, 0, eax, 0, mem_hmk_mode , MEM-HMK encryption mode is supported
-0x80000023, 0, ebx, 15:0, mem_hmk_avail_keys , MEM-HMK mode: total number of available encryption keys
+0x80000023, 0, eax, 0, mem_hmk_mode , MEM-HMK encryption mode
+0x80000023, 0, ebx, 15:0, mem_hmk_avail_keys , Total number of available encryption keys
# Leaf 80000026H
-# AMD extended topology enumeration v2
+# AMD extended CPU topology
0x80000026, 3:0, eax, 4:0, x2apic_id_shift , Bit width of this level (previous levels inclusive)
0x80000026, 3:0, eax, 29, core_has_pwreff_ranking, This core has a power efficiency ranking
@@ -1067,15 +1090,15 @@
0x80000026, 3:0, edx, 31:0, x2apic_id , x2APIC ID of current logical CPU
# Leaf 80860000H
-# Maximum Transmeta leaf number + CPU vendor ID string
+# Maximum Transmeta leaf + CPU vendor string
-0x80860000, 0, eax, 31:0, max_tra_leaf , Maximum supported Transmeta leaf number
+0x80860000, 0, eax, 31:0, max_tra_leaf , Maximum Transmeta leaf
0x80860000, 0, ebx, 31:0, cpu_vendorid_0 , Transmeta Vendor ID string bytes 0 - 3
0x80860000, 0, ecx, 31:0, cpu_vendorid_2 , Transmeta Vendor ID string bytes 8 - 11
0x80860000, 0, edx, 31:0, cpu_vendorid_1 , Transmeta Vendor ID string bytes 4 - 7
# Leaf 80860001H
-# Transmeta extended CPU information
+# Transmeta extended CPU features
0x80860001, 0, eax, 3:0, stepping , Stepping ID
0x80860001, 0, eax, 7:4, base_model , Base CPU model ID
@@ -1091,7 +1114,7 @@
0x80860001, 0, edx, 3, lrti , LongRun Table Interface
# Leaf 80860002H
-# Transmeta Code Morphing Software (CMS) enumeration
+# Transmeta CMS (Code Morphing Software)
0x80860002, 0, eax, 31:0, cpu_rev_id , CPU revision ID
0x80860002, 0, ebx, 7:0, cms_rev_mask_2 , CMS revision ID, mask component 2
@@ -1141,9 +1164,9 @@
0x80860007, 0, edx, 31:0, cpu_cur_gate_delay , Current CPU gate delay, in femtoseconds
# Leaf C0000000H
-# Maximum Centaur/Zhaoxin leaf number
+# Maximum Centaur/Zhaoxin leaf
-0xc0000000, 0, eax, 31:0, max_cntr_leaf , Maximum Centaur/Zhaoxin leaf number
+0xc0000000, 0, eax, 31:0, max_cntr_leaf , Maximum Centaur/Zhaoxin leaf
# Leaf C0000001H
# Centaur/Zhaoxin extended CPU features
--
2.53.0
^ permalink raw reply related [flat|nested] 101+ messages in thread
* [PATCH v6 04/90] treewide: Explicitly include the x86 CPUID headers
2026-03-27 2:15 [PATCH v6 00/90] x86: Introduce a centralized CPUID data model Ahmed S. Darwish
` (2 preceding siblings ...)
2026-03-27 2:15 ` [PATCH v6 03/90] tools/x86/kcpuid: Update bitfields to x86-cpuid-db v3.0 Ahmed S. Darwish
@ 2026-03-27 2:15 ` Ahmed S. Darwish
2026-03-27 2:15 ` [PATCH v6 05/90] x86/cpu: <asm/processor.h>: Do not include the CPUID API header Ahmed S. Darwish
` (87 subsequent siblings)
91 siblings, 0 replies; 101+ messages in thread
From: Ahmed S. Darwish @ 2026-03-27 2:15 UTC (permalink / raw)
To: Borislav Petkov, Dave Hansen, Ingo Molnar
Cc: Thomas Gleixner, Andrew Cooper, H. Peter Anvin,
Sean Christopherson, David Woodhouse, Peter Zijlstra,
Christian Ludloff, Sohil Mehta, John Ogness, x86, x86-cpuid, LKML,
Ahmed S. Darwish
Modify all CPUID call sites which implicitly include any of the CPUID
headers to explicitly include them instead.
For KVM's reverse_cpuid.h, just include <asm/cpuid/types.h> since it
references the CPUID_EAX..EDX symbols without using the CPUID APIs.
Note, this allows removing the inclusion of <asm/cpuid/api.h> from within
<asm/processor.h> next. That allows the CPUID API headers to include
<asm/processor.h> without introducing a circular dependency.
Signed-off-by: Ahmed S. Darwish <darwi@linutronix.de>
---
arch/x86/boot/compressed/pgtable_64.c | 1 +
arch/x86/boot/startup/sme.c | 1 +
arch/x86/coco/tdx/tdx.c | 1 +
arch/x86/events/amd/core.c | 2 ++
arch/x86/events/amd/ibs.c | 1 +
arch/x86/events/amd/lbr.c | 2 ++
arch/x86/events/amd/power.c | 3 +++
arch/x86/events/amd/uncore.c | 1 +
arch/x86/events/intel/core.c | 1 +
arch/x86/events/intel/lbr.c | 1 +
arch/x86/events/zhaoxin/core.c | 1 +
arch/x86/include/asm/acrn.h | 2 ++
arch/x86/include/asm/microcode.h | 1 +
arch/x86/include/asm/xen/hypervisor.h | 1 +
arch/x86/kernel/apic/apic.c | 1 +
arch/x86/kernel/cpu/amd.c | 1 +
arch/x86/kernel/cpu/centaur.c | 1 +
arch/x86/kernel/cpu/hygon.c | 1 +
arch/x86/kernel/cpu/mce/core.c | 1 +
arch/x86/kernel/cpu/mce/inject.c | 1 +
arch/x86/kernel/cpu/microcode/amd.c | 1 +
arch/x86/kernel/cpu/microcode/core.c | 1 +
arch/x86/kernel/cpu/microcode/intel.c | 1 +
arch/x86/kernel/cpu/mshyperv.c | 1 +
arch/x86/kernel/cpu/resctrl/core.c | 1 +
arch/x86/kernel/cpu/resctrl/monitor.c | 1 +
arch/x86/kernel/cpu/scattered.c | 1 +
arch/x86/kernel/cpu/sgx/driver.c | 3 +++
arch/x86/kernel/cpu/sgx/main.c | 3 +++
arch/x86/kernel/cpu/topology_amd.c | 1 +
arch/x86/kernel/cpu/topology_common.c | 1 +
arch/x86/kernel/cpu/topology_ext.c | 1 +
arch/x86/kernel/cpu/transmeta.c | 3 +++
arch/x86/kernel/cpu/vmware.c | 1 +
arch/x86/kernel/cpu/zhaoxin.c | 1 +
arch/x86/kernel/cpuid.c | 1 +
arch/x86/kernel/jailhouse.c | 1 +
arch/x86/kernel/kvm.c | 1 +
arch/x86/kernel/paravirt.c | 1 +
arch/x86/kvm/mmu/mmu.c | 1 +
arch/x86/kvm/mmu/spte.c | 1 +
arch/x86/kvm/reverse_cpuid.h | 2 ++
arch/x86/kvm/svm/sev.c | 1 +
arch/x86/kvm/svm/svm.c | 1 +
arch/x86/kvm/vmx/pmu_intel.c | 1 +
arch/x86/kvm/vmx/sgx.c | 1 +
arch/x86/kvm/vmx/vmx.c | 1 +
arch/x86/mm/pti.c | 1 +
arch/x86/pci/xen.c | 1 +
arch/x86/xen/enlighten_hvm.c | 1 +
arch/x86/xen/pmu.c | 1 +
arch/x86/xen/time.c | 1 +
drivers/char/agp/efficeon-agp.c | 1 +
drivers/cpufreq/longrun.c | 1 +
drivers/cpufreq/powernow-k7.c | 1 +
drivers/cpufreq/powernow-k8.c | 1 +
drivers/cpufreq/speedstep-lib.c | 1 +
drivers/firmware/efi/libstub/x86-5lvl.c | 1 +
drivers/gpu/drm/gma500/mmu.c | 2 ++
drivers/hwmon/fam15h_power.c | 1 +
drivers/hwmon/k10temp.c | 2 ++
drivers/hwmon/k8temp.c | 1 +
drivers/net/ethernet/stmicro/stmmac/dwmac-intel.c | 1 +
drivers/ras/amd/fmpm.c | 1 +
drivers/thermal/intel/intel_hfi.c | 1 +
drivers/thermal/intel/x86_pkg_temp_thermal.c | 1 +
drivers/virt/acrn/hsm.c | 1 +
drivers/xen/events/events_base.c | 1 +
drivers/xen/grant-table.c | 1 +
drivers/xen/xenbus/xenbus_xs.c | 3 +++
70 files changed, 86 insertions(+)
diff --git a/arch/x86/boot/compressed/pgtable_64.c b/arch/x86/boot/compressed/pgtable_64.c
index 0e89e197e112..1b2fb35704f9 100644
--- a/arch/x86/boot/compressed/pgtable_64.c
+++ b/arch/x86/boot/compressed/pgtable_64.c
@@ -2,6 +2,7 @@
#include "misc.h"
#include <asm/bootparam.h>
#include <asm/bootparam_utils.h>
+#include <asm/cpuid/api.h>
#include <asm/e820/types.h>
#include <asm/pgtable.h>
#include <asm/processor.h>
diff --git a/arch/x86/boot/startup/sme.c b/arch/x86/boot/startup/sme.c
index b76a7c95dfe1..c07a2c381ed1 100644
--- a/arch/x86/boot/startup/sme.c
+++ b/arch/x86/boot/startup/sme.c
@@ -43,6 +43,7 @@
#include <asm/init.h>
#include <asm/setup.h>
#include <asm/sections.h>
+#include <asm/cpuid/api.h>
#include <asm/coco.h>
#include <asm/sev.h>
diff --git a/arch/x86/coco/tdx/tdx.c b/arch/x86/coco/tdx/tdx.c
index 7b2833705d47..168388be3a3e 100644
--- a/arch/x86/coco/tdx/tdx.c
+++ b/arch/x86/coco/tdx/tdx.c
@@ -14,6 +14,7 @@
#include <asm/ia32.h>
#include <asm/insn.h>
#include <asm/insn-eval.h>
+#include <asm/cpuid/api.h>
#include <asm/paravirt_types.h>
#include <asm/pgtable.h>
#include <asm/set_memory.h>
diff --git a/arch/x86/events/amd/core.c b/arch/x86/events/amd/core.c
index 0c92ed5f464b..d66a357f219d 100644
--- a/arch/x86/events/amd/core.c
+++ b/arch/x86/events/amd/core.c
@@ -8,8 +8,10 @@
#include <linux/slab.h>
#include <linux/delay.h>
#include <linux/jiffies.h>
+
#include <asm/apicdef.h>
#include <asm/apic.h>
+#include <asm/cpuid/api.h>
#include <asm/msr.h>
#include <asm/nmi.h>
diff --git a/arch/x86/events/amd/ibs.c b/arch/x86/events/amd/ibs.c
index aca89f23d2e0..1bb94f1f4334 100644
--- a/arch/x86/events/amd/ibs.c
+++ b/arch/x86/events/amd/ibs.c
@@ -15,6 +15,7 @@
#include <linux/sched/clock.h>
#include <asm/apic.h>
+#include <asm/cpuid/api.h>
#include <asm/msr.h>
#include "../perf_event.h"
diff --git a/arch/x86/events/amd/lbr.c b/arch/x86/events/amd/lbr.c
index d24da377df77..5b437dc8e4ce 100644
--- a/arch/x86/events/amd/lbr.c
+++ b/arch/x86/events/amd/lbr.c
@@ -1,5 +1,7 @@
// SPDX-License-Identifier: GPL-2.0
#include <linux/perf_event.h>
+
+#include <asm/cpuid/api.h>
#include <asm/msr.h>
#include <asm/perf_event.h>
diff --git a/arch/x86/events/amd/power.c b/arch/x86/events/amd/power.c
index dad42790cf7d..744dffa42dee 100644
--- a/arch/x86/events/amd/power.c
+++ b/arch/x86/events/amd/power.c
@@ -10,8 +10,11 @@
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/perf_event.h>
+
#include <asm/cpu_device_id.h>
+#include <asm/cpuid/api.h>
#include <asm/msr.h>
+
#include "../perf_event.h"
/* Event code: LSB 8 bits, passed in attr->config any other bit is reserved. */
diff --git a/arch/x86/events/amd/uncore.c b/arch/x86/events/amd/uncore.c
index dd956cfcadef..05cff39968ec 100644
--- a/arch/x86/events/amd/uncore.c
+++ b/arch/x86/events/amd/uncore.c
@@ -16,6 +16,7 @@
#include <linux/smp.h>
#include <asm/perf_event.h>
+#include <asm/cpuid/api.h>
#include <asm/msr.h>
#define NUM_COUNTERS_NB 4
diff --git a/arch/x86/events/intel/core.c b/arch/x86/events/intel/core.c
index 36c68210d4d2..d1107129d5ad 100644
--- a/arch/x86/events/intel/core.c
+++ b/arch/x86/events/intel/core.c
@@ -17,6 +17,7 @@
#include <linux/kvm_host.h>
#include <asm/cpufeature.h>
+#include <asm/cpuid/api.h>
#include <asm/debugreg.h>
#include <asm/hardirq.h>
#include <asm/intel-family.h>
diff --git a/arch/x86/events/intel/lbr.c b/arch/x86/events/intel/lbr.c
index 72f2adcda7c6..cae2e02fe6cc 100644
--- a/arch/x86/events/intel/lbr.c
+++ b/arch/x86/events/intel/lbr.c
@@ -4,6 +4,7 @@
#include <linux/types.h>
#include <asm/cpu_device_id.h>
+#include <asm/cpuid/api.h>
#include <asm/perf_event.h>
#include <asm/msr.h>
diff --git a/arch/x86/events/zhaoxin/core.c b/arch/x86/events/zhaoxin/core.c
index 4bdfcf091200..6ed644fe89aa 100644
--- a/arch/x86/events/zhaoxin/core.c
+++ b/arch/x86/events/zhaoxin/core.c
@@ -13,6 +13,7 @@
#include <linux/nmi.h>
#include <asm/cpufeature.h>
+#include <asm/cpuid/api.h>
#include <asm/hardirq.h>
#include <asm/apic.h>
#include <asm/msr.h>
diff --git a/arch/x86/include/asm/acrn.h b/arch/x86/include/asm/acrn.h
index fab11192c60a..db42b477c41d 100644
--- a/arch/x86/include/asm/acrn.h
+++ b/arch/x86/include/asm/acrn.h
@@ -2,6 +2,8 @@
#ifndef _ASM_X86_ACRN_H
#define _ASM_X86_ACRN_H
+#include <asm/cpuid/api.h>
+
/*
* This CPUID returns feature bitmaps in EAX.
* Guest VM uses this to detect the appropriate feature bit.
diff --git a/arch/x86/include/asm/microcode.h b/arch/x86/include/asm/microcode.h
index 8b41f26f003b..645e65ac1586 100644
--- a/arch/x86/include/asm/microcode.h
+++ b/arch/x86/include/asm/microcode.h
@@ -3,6 +3,7 @@
#define _ASM_X86_MICROCODE_H
#include <asm/msr.h>
+#include <asm/cpuid/api.h>
struct cpu_signature {
unsigned int sig;
diff --git a/arch/x86/include/asm/xen/hypervisor.h b/arch/x86/include/asm/xen/hypervisor.h
index c2fc7869b996..7c596cebfb78 100644
--- a/arch/x86/include/asm/xen/hypervisor.h
+++ b/arch/x86/include/asm/xen/hypervisor.h
@@ -37,6 +37,7 @@ extern struct shared_info *HYPERVISOR_shared_info;
extern struct start_info *xen_start_info;
#include <asm/bug.h>
+#include <asm/cpuid/api.h>
#include <asm/processor.h>
#define XEN_SIGNATURE "XenVMMXenVMM"
diff --git a/arch/x86/kernel/apic/apic.c b/arch/x86/kernel/apic/apic.c
index 961714e6adae..28fe5f5672da 100644
--- a/arch/x86/kernel/apic/apic.c
+++ b/arch/x86/kernel/apic/apic.c
@@ -64,6 +64,7 @@
#include <asm/tsc.h>
#include <asm/hypervisor.h>
#include <asm/cpu_device_id.h>
+#include <asm/cpuid/api.h>
#include <asm/intel-family.h>
#include <asm/irq_regs.h>
#include <asm/cpu.h>
diff --git a/arch/x86/kernel/cpu/amd.c b/arch/x86/kernel/cpu/amd.c
index 09de584e4c8f..224420f53ea9 100644
--- a/arch/x86/kernel/cpu/amd.c
+++ b/arch/x86/kernel/cpu/amd.c
@@ -15,6 +15,7 @@
#include <asm/cacheinfo.h>
#include <asm/cpu.h>
#include <asm/cpu_device_id.h>
+#include <asm/cpuid/api.h>
#include <asm/spec-ctrl.h>
#include <asm/smp.h>
#include <asm/numa.h>
diff --git a/arch/x86/kernel/cpu/centaur.c b/arch/x86/kernel/cpu/centaur.c
index 81695da9c524..681d2da49341 100644
--- a/arch/x86/kernel/cpu/centaur.c
+++ b/arch/x86/kernel/cpu/centaur.c
@@ -5,6 +5,7 @@
#include <asm/cpu.h>
#include <asm/cpufeature.h>
+#include <asm/cpuid/api.h>
#include <asm/e820/api.h>
#include <asm/mtrr.h>
#include <asm/msr.h>
diff --git a/arch/x86/kernel/cpu/hygon.c b/arch/x86/kernel/cpu/hygon.c
index 7f95a74e4c65..3e8891a9caf2 100644
--- a/arch/x86/kernel/cpu/hygon.c
+++ b/arch/x86/kernel/cpu/hygon.c
@@ -10,6 +10,7 @@
#include <asm/apic.h>
#include <asm/cpu.h>
+#include <asm/cpuid/api.h>
#include <asm/smp.h>
#include <asm/numa.h>
#include <asm/cacheinfo.h>
diff --git a/arch/x86/kernel/cpu/mce/core.c b/arch/x86/kernel/cpu/mce/core.c
index 8dd424ac5de8..f6499132cba6 100644
--- a/arch/x86/kernel/cpu/mce/core.c
+++ b/arch/x86/kernel/cpu/mce/core.c
@@ -49,6 +49,7 @@
#include <asm/fred.h>
#include <asm/cpu_device_id.h>
+#include <asm/cpuid/api.h>
#include <asm/processor.h>
#include <asm/traps.h>
#include <asm/tlbflush.h>
diff --git a/arch/x86/kernel/cpu/mce/inject.c b/arch/x86/kernel/cpu/mce/inject.c
index d02c4f556cd0..42c82c14c48a 100644
--- a/arch/x86/kernel/cpu/mce/inject.c
+++ b/arch/x86/kernel/cpu/mce/inject.c
@@ -26,6 +26,7 @@
#include <asm/amd/nb.h>
#include <asm/apic.h>
+#include <asm/cpuid/api.h>
#include <asm/irq_vectors.h>
#include <asm/mce.h>
#include <asm/msr.h>
diff --git a/arch/x86/kernel/cpu/microcode/amd.c b/arch/x86/kernel/cpu/microcode/amd.c
index e533881284a1..874b5b70c0d2 100644
--- a/arch/x86/kernel/cpu/microcode/amd.c
+++ b/arch/x86/kernel/cpu/microcode/amd.c
@@ -34,6 +34,7 @@
#include <asm/microcode.h>
#include <asm/processor.h>
+#include <asm/cpuid/api.h>
#include <asm/cmdline.h>
#include <asm/setup.h>
#include <asm/cpu.h>
diff --git a/arch/x86/kernel/cpu/microcode/core.c b/arch/x86/kernel/cpu/microcode/core.c
index 651202e6fefb..56d791aeac4e 100644
--- a/arch/x86/kernel/cpu/microcode/core.c
+++ b/arch/x86/kernel/cpu/microcode/core.c
@@ -34,6 +34,7 @@
#include <asm/apic.h>
#include <asm/cpu_device_id.h>
+#include <asm/cpuid/api.h>
#include <asm/perf_event.h>
#include <asm/processor.h>
#include <asm/cmdline.h>
diff --git a/arch/x86/kernel/cpu/microcode/intel.c b/arch/x86/kernel/cpu/microcode/intel.c
index 8744f3adc2a0..f0cae188b584 100644
--- a/arch/x86/kernel/cpu/microcode/intel.c
+++ b/arch/x86/kernel/cpu/microcode/intel.c
@@ -25,6 +25,7 @@
#include <linux/mm.h>
#include <asm/cpu_device_id.h>
+#include <asm/cpuid/api.h>
#include <asm/processor.h>
#include <asm/tlbflush.h>
#include <asm/setup.h>
diff --git a/arch/x86/kernel/cpu/mshyperv.c b/arch/x86/kernel/cpu/mshyperv.c
index 9befdc557d9e..45705f8e64a4 100644
--- a/arch/x86/kernel/cpu/mshyperv.c
+++ b/arch/x86/kernel/cpu/mshyperv.c
@@ -19,6 +19,7 @@
#include <linux/random.h>
#include <asm/processor.h>
#include <asm/hypervisor.h>
+#include <asm/cpuid/api.h>
#include <hyperv/hvhdk.h>
#include <asm/mshyperv.h>
#include <asm/desc.h>
diff --git a/arch/x86/kernel/cpu/resctrl/core.c b/arch/x86/kernel/cpu/resctrl/core.c
index 7667cf7c4e94..9c01d2562b7a 100644
--- a/arch/x86/kernel/cpu/resctrl/core.c
+++ b/arch/x86/kernel/cpu/resctrl/core.c
@@ -22,6 +22,7 @@
#include <linux/cpuhotplug.h>
#include <asm/cpu_device_id.h>
+#include <asm/cpuid/api.h>
#include <asm/msr.h>
#include <asm/resctrl.h>
#include "internal.h"
diff --git a/arch/x86/kernel/cpu/resctrl/monitor.c b/arch/x86/kernel/cpu/resctrl/monitor.c
index 9bd87bae4983..145be7abee52 100644
--- a/arch/x86/kernel/cpu/resctrl/monitor.c
+++ b/arch/x86/kernel/cpu/resctrl/monitor.c
@@ -21,6 +21,7 @@
#include <linux/resctrl.h>
#include <asm/cpu_device_id.h>
+#include <asm/cpuid/api.h>
#include <asm/msr.h>
#include "internal.h"
diff --git a/arch/x86/kernel/cpu/scattered.c b/arch/x86/kernel/cpu/scattered.c
index 42c7eac0c387..226a4796d227 100644
--- a/arch/x86/kernel/cpu/scattered.c
+++ b/arch/x86/kernel/cpu/scattered.c
@@ -6,6 +6,7 @@
#include <asm/memtype.h>
#include <asm/apic.h>
+#include <asm/cpuid/api.h>
#include <asm/processor.h>
#include "cpu.h"
diff --git a/arch/x86/kernel/cpu/sgx/driver.c b/arch/x86/kernel/cpu/sgx/driver.c
index 473619741bc4..9268289cd9f9 100644
--- a/arch/x86/kernel/cpu/sgx/driver.c
+++ b/arch/x86/kernel/cpu/sgx/driver.c
@@ -6,7 +6,10 @@
#include <linux/mman.h>
#include <linux/security.h>
#include <linux/suspend.h>
+
+#include <asm/cpuid/api.h>
#include <asm/traps.h>
+
#include "driver.h"
#include "encl.h"
diff --git a/arch/x86/kernel/cpu/sgx/main.c b/arch/x86/kernel/cpu/sgx/main.c
index 38b7fd2f63be..4505f808af5e 100644
--- a/arch/x86/kernel/cpu/sgx/main.c
+++ b/arch/x86/kernel/cpu/sgx/main.c
@@ -15,9 +15,12 @@
#include <linux/slab.h>
#include <linux/sysfs.h>
#include <linux/vmalloc.h>
+
+#include <asm/cpuid/api.h>
#include <asm/msr.h>
#include <asm/sgx.h>
#include <asm/archrandom.h>
+
#include "driver.h"
#include "encl.h"
#include "encls.h"
diff --git a/arch/x86/kernel/cpu/topology_amd.c b/arch/x86/kernel/cpu/topology_amd.c
index 6ac097e13106..cc103c85b96d 100644
--- a/arch/x86/kernel/cpu/topology_amd.c
+++ b/arch/x86/kernel/cpu/topology_amd.c
@@ -2,6 +2,7 @@
#include <linux/cpu.h>
#include <asm/apic.h>
+#include <asm/cpuid/api.h>
#include <asm/memtype.h>
#include <asm/msr.h>
#include <asm/processor.h>
diff --git a/arch/x86/kernel/cpu/topology_common.c b/arch/x86/kernel/cpu/topology_common.c
index 71625795d711..fccfac4cd5a6 100644
--- a/arch/x86/kernel/cpu/topology_common.c
+++ b/arch/x86/kernel/cpu/topology_common.c
@@ -6,6 +6,7 @@
#include <asm/intel-family.h>
#include <asm/apic.h>
#include <asm/processor.h>
+#include <asm/cpuid/api.h>
#include <asm/smp.h>
#include "cpu.h"
diff --git a/arch/x86/kernel/cpu/topology_ext.c b/arch/x86/kernel/cpu/topology_ext.c
index 467b0326bf1a..eb915c73895f 100644
--- a/arch/x86/kernel/cpu/topology_ext.c
+++ b/arch/x86/kernel/cpu/topology_ext.c
@@ -2,6 +2,7 @@
#include <linux/cpu.h>
#include <asm/apic.h>
+#include <asm/cpuid/api.h>
#include <asm/memtype.h>
#include <asm/processor.h>
diff --git a/arch/x86/kernel/cpu/transmeta.c b/arch/x86/kernel/cpu/transmeta.c
index 42c939827621..1fdcd69c625c 100644
--- a/arch/x86/kernel/cpu/transmeta.c
+++ b/arch/x86/kernel/cpu/transmeta.c
@@ -3,8 +3,11 @@
#include <linux/sched.h>
#include <linux/sched/clock.h>
#include <linux/mm.h>
+
#include <asm/cpufeature.h>
+#include <asm/cpuid/api.h>
#include <asm/msr.h>
+
#include "cpu.h"
static void early_init_transmeta(struct cpuinfo_x86 *c)
diff --git a/arch/x86/kernel/cpu/vmware.c b/arch/x86/kernel/cpu/vmware.c
index a3e6936839b1..121512951f10 100644
--- a/arch/x86/kernel/cpu/vmware.c
+++ b/arch/x86/kernel/cpu/vmware.c
@@ -33,6 +33,7 @@
#include <asm/div64.h>
#include <asm/x86_init.h>
#include <asm/hypervisor.h>
+#include <asm/cpuid/api.h>
#include <asm/timer.h>
#include <asm/apic.h>
#include <asm/vmware.h>
diff --git a/arch/x86/kernel/cpu/zhaoxin.c b/arch/x86/kernel/cpu/zhaoxin.c
index 031379b7d4fa..761aef5590ac 100644
--- a/arch/x86/kernel/cpu/zhaoxin.c
+++ b/arch/x86/kernel/cpu/zhaoxin.c
@@ -4,6 +4,7 @@
#include <asm/cpu.h>
#include <asm/cpufeature.h>
+#include <asm/cpuid/api.h>
#include <asm/msr.h>
#include "cpu.h"
diff --git a/arch/x86/kernel/cpuid.c b/arch/x86/kernel/cpuid.c
index dae436253de4..cbd04b677fd1 100644
--- a/arch/x86/kernel/cpuid.c
+++ b/arch/x86/kernel/cpuid.c
@@ -37,6 +37,7 @@
#include <linux/gfp.h>
#include <linux/completion.h>
+#include <asm/cpuid/api.h>
#include <asm/processor.h>
#include <asm/msr.h>
diff --git a/arch/x86/kernel/jailhouse.c b/arch/x86/kernel/jailhouse.c
index 9e9a591a5fec..f58ce9220e0f 100644
--- a/arch/x86/kernel/jailhouse.c
+++ b/arch/x86/kernel/jailhouse.c
@@ -17,6 +17,7 @@
#include <asm/io_apic.h>
#include <asm/acpi.h>
#include <asm/cpu.h>
+#include <asm/cpuid/api.h>
#include <asm/hypervisor.h>
#include <asm/i8259.h>
#include <asm/irqdomain.h>
diff --git a/arch/x86/kernel/kvm.c b/arch/x86/kernel/kvm.c
index 3bc062363814..f1240d5605b2 100644
--- a/arch/x86/kernel/kvm.c
+++ b/arch/x86/kernel/kvm.c
@@ -41,6 +41,7 @@
#include <asm/hypervisor.h>
#include <asm/mtrr.h>
#include <asm/tlb.h>
+#include <asm/cpuid/api.h>
#include <asm/cpuidle_haltpoll.h>
#include <asm/msr.h>
#include <asm/ptrace.h>
diff --git a/arch/x86/kernel/paravirt.c b/arch/x86/kernel/paravirt.c
index a6ed52cae003..22c7ba9a1bcc 100644
--- a/arch/x86/kernel/paravirt.c
+++ b/arch/x86/kernel/paravirt.c
@@ -24,6 +24,7 @@
#include <asm/time.h>
#include <asm/pgalloc.h>
#include <asm/irq.h>
+#include <asm/cpuid/api.h>
#include <asm/delay.h>
#include <asm/fixmap.h>
#include <asm/apic.h>
diff --git a/arch/x86/kvm/mmu/mmu.c b/arch/x86/kvm/mmu/mmu.c
index b922a8b00057..f134fc70cc17 100644
--- a/arch/x86/kvm/mmu/mmu.c
+++ b/arch/x86/kvm/mmu/mmu.c
@@ -52,6 +52,7 @@
#include <asm/page.h>
#include <asm/memtype.h>
#include <asm/cmpxchg.h>
+#include <asm/cpuid/api.h>
#include <asm/io.h>
#include <asm/set_memory.h>
#include <asm/spec-ctrl.h>
diff --git a/arch/x86/kvm/mmu/spte.c b/arch/x86/kvm/mmu/spte.c
index 85a0473809b0..4e753386c8d4 100644
--- a/arch/x86/kvm/mmu/spte.c
+++ b/arch/x86/kvm/mmu/spte.c
@@ -15,6 +15,7 @@
#include "x86.h"
#include "spte.h"
+#include <asm/cpuid/api.h>
#include <asm/e820/api.h>
#include <asm/memtype.h>
#include <asm/vmx.h>
diff --git a/arch/x86/kvm/reverse_cpuid.h b/arch/x86/kvm/reverse_cpuid.h
index 657f5f743ed9..2ad25781cefb 100644
--- a/arch/x86/kvm/reverse_cpuid.h
+++ b/arch/x86/kvm/reverse_cpuid.h
@@ -3,8 +3,10 @@
#define ARCH_X86_KVM_REVERSE_CPUID_H
#include <uapi/asm/kvm.h>
+
#include <asm/cpufeature.h>
#include <asm/cpufeatures.h>
+#include <asm/cpuid/types.h>
/*
* Define a KVM-only feature flag.
diff --git a/arch/x86/kvm/svm/sev.c b/arch/x86/kvm/svm/sev.c
index 3f9c1aa39a0a..9da85c9bec05 100644
--- a/arch/x86/kvm/svm/sev.c
+++ b/arch/x86/kvm/svm/sev.c
@@ -23,6 +23,7 @@
#include <asm/pkru.h>
#include <asm/trapnr.h>
+#include <asm/cpuid/api.h>
#include <asm/fpu/xcr.h>
#include <asm/fpu/xstate.h>
#include <asm/debugreg.h>
diff --git a/arch/x86/kvm/svm/svm.c b/arch/x86/kvm/svm/svm.c
index e6477affac9a..9d3b8df7b658 100644
--- a/arch/x86/kvm/svm/svm.c
+++ b/arch/x86/kvm/svm/svm.c
@@ -41,6 +41,7 @@
#include <asm/irq_remapping.h>
#include <asm/spec-ctrl.h>
#include <asm/cpu_device_id.h>
+#include <asm/cpuid/api.h>
#include <asm/traps.h>
#include <asm/reboot.h>
#include <asm/fpu/api.h>
diff --git a/arch/x86/kvm/vmx/pmu_intel.c b/arch/x86/kvm/vmx/pmu_intel.c
index 27eb76e6b6a0..74e0b01185b8 100644
--- a/arch/x86/kvm/vmx/pmu_intel.c
+++ b/arch/x86/kvm/vmx/pmu_intel.c
@@ -15,6 +15,7 @@
#include <linux/perf_event.h>
#include <asm/msr.h>
#include <asm/perf_event.h>
+#include <asm/cpuid/api.h>
#include "x86.h"
#include "cpuid.h"
#include "lapic.h"
diff --git a/arch/x86/kvm/vmx/sgx.c b/arch/x86/kvm/vmx/sgx.c
index df1d0cf76947..29a1f8e3be60 100644
--- a/arch/x86/kvm/vmx/sgx.c
+++ b/arch/x86/kvm/vmx/sgx.c
@@ -2,6 +2,7 @@
/* Copyright(c) 2021 Intel Corporation. */
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+#include <asm/cpuid/api.h>
#include <asm/msr.h>
#include <asm/sgx.h>
diff --git a/arch/x86/kvm/vmx/vmx.c b/arch/x86/kvm/vmx/vmx.c
index 8b24e682535b..54ac6e26dc57 100644
--- a/arch/x86/kvm/vmx/vmx.c
+++ b/arch/x86/kvm/vmx/vmx.c
@@ -33,6 +33,7 @@
#include <asm/asm.h>
#include <asm/cpu.h>
#include <asm/cpu_device_id.h>
+#include <asm/cpuid/api.h>
#include <asm/debugreg.h>
#include <asm/desc.h>
#include <asm/fpu/api.h>
diff --git a/arch/x86/mm/pti.c b/arch/x86/mm/pti.c
index f7546e9e8e89..4bc0150b1f70 100644
--- a/arch/x86/mm/pti.c
+++ b/arch/x86/mm/pti.c
@@ -31,6 +31,7 @@
#include <asm/cpufeature.h>
#include <asm/hypervisor.h>
+#include <asm/cpuid/api.h>
#include <asm/vsyscall.h>
#include <asm/cmdline.h>
#include <asm/pti.h>
diff --git a/arch/x86/pci/xen.c b/arch/x86/pci/xen.c
index 6818515a501b..550c631bc77f 100644
--- a/arch/x86/pci/xen.c
+++ b/arch/x86/pci/xen.c
@@ -18,6 +18,7 @@
#include <linux/io.h>
#include <asm/io_apic.h>
#include <asm/pci_x86.h>
+#include <asm/cpuid/api.h>
#include <asm/xen/hypervisor.h>
diff --git a/arch/x86/xen/enlighten_hvm.c b/arch/x86/xen/enlighten_hvm.c
index fe57ff85d004..bd57259a02e6 100644
--- a/arch/x86/xen/enlighten_hvm.c
+++ b/arch/x86/xen/enlighten_hvm.c
@@ -20,6 +20,7 @@
#include <asm/setup.h>
#include <asm/idtentry.h>
#include <asm/hypervisor.h>
+#include <asm/cpuid/api.h>
#include <asm/e820/api.h>
#include <asm/early_ioremap.h>
diff --git a/arch/x86/xen/pmu.c b/arch/x86/xen/pmu.c
index 8f89ce0b67e3..5f50a3ee08f5 100644
--- a/arch/x86/xen/pmu.c
+++ b/arch/x86/xen/pmu.c
@@ -2,6 +2,7 @@
#include <linux/types.h>
#include <linux/interrupt.h>
+#include <asm/cpuid/api.h>
#include <asm/msr.h>
#include <asm/xen/hypercall.h>
#include <xen/xen.h>
diff --git a/arch/x86/xen/time.c b/arch/x86/xen/time.c
index 6f9f665bb7ae..d62c14334b35 100644
--- a/arch/x86/xen/time.c
+++ b/arch/x86/xen/time.c
@@ -18,6 +18,7 @@
#include <linux/timekeeper_internal.h>
#include <linux/sched/cputime.h>
+#include <asm/cpuid/api.h>
#include <asm/pvclock.h>
#include <asm/timer.h>
#include <asm/xen/hypervisor.h>
diff --git a/drivers/char/agp/efficeon-agp.c b/drivers/char/agp/efficeon-agp.c
index 0d25bbdc7e6a..4d0b7d7c0aad 100644
--- a/drivers/char/agp/efficeon-agp.c
+++ b/drivers/char/agp/efficeon-agp.c
@@ -27,6 +27,7 @@
#include <linux/gfp.h>
#include <linux/page-flags.h>
#include <linux/mm.h>
+#include <asm/cpuid/api.h>
#include "agp.h"
#include "intel-agp.h"
diff --git a/drivers/cpufreq/longrun.c b/drivers/cpufreq/longrun.c
index 1caaec7c280b..f3aaca0496a4 100644
--- a/drivers/cpufreq/longrun.c
+++ b/drivers/cpufreq/longrun.c
@@ -14,6 +14,7 @@
#include <asm/msr.h>
#include <asm/processor.h>
#include <asm/cpu_device_id.h>
+#include <asm/cpuid/api.h>
static struct cpufreq_driver longrun_driver;
diff --git a/drivers/cpufreq/powernow-k7.c b/drivers/cpufreq/powernow-k7.c
index 6b7caf4ae20d..6a930d7e6a5c 100644
--- a/drivers/cpufreq/powernow-k7.c
+++ b/drivers/cpufreq/powernow-k7.c
@@ -29,6 +29,7 @@
#include <asm/timer.h> /* Needed for recalibrate_cpu_khz() */
#include <asm/msr.h>
#include <asm/cpu_device_id.h>
+#include <asm/cpuid/api.h>
#ifdef CONFIG_X86_POWERNOW_K7_ACPI
#include <linux/acpi.h>
diff --git a/drivers/cpufreq/powernow-k8.c b/drivers/cpufreq/powernow-k8.c
index 4d77eef53fe0..2b791f1ec51b 100644
--- a/drivers/cpufreq/powernow-k8.c
+++ b/drivers/cpufreq/powernow-k8.c
@@ -39,6 +39,7 @@
#include <asm/msr.h>
#include <asm/cpu_device_id.h>
+#include <asm/cpuid/api.h>
#include <linux/acpi.h>
#include <linux/mutex.h>
diff --git a/drivers/cpufreq/speedstep-lib.c b/drivers/cpufreq/speedstep-lib.c
index f8b42e981635..973716c1c29c 100644
--- a/drivers/cpufreq/speedstep-lib.c
+++ b/drivers/cpufreq/speedstep-lib.c
@@ -15,6 +15,7 @@
#include <linux/init.h>
#include <linux/cpufreq.h>
+#include <asm/cpuid/api.h>
#include <asm/msr.h>
#include <asm/tsc.h>
#include "speedstep-lib.h"
diff --git a/drivers/firmware/efi/libstub/x86-5lvl.c b/drivers/firmware/efi/libstub/x86-5lvl.c
index c00d0ae7ed5d..c3da05c0df8b 100644
--- a/drivers/firmware/efi/libstub/x86-5lvl.c
+++ b/drivers/firmware/efi/libstub/x86-5lvl.c
@@ -2,6 +2,7 @@
#include <linux/efi.h>
#include <asm/boot.h>
+#include <asm/cpuid/api.h>
#include <asm/desc.h>
#include <asm/efi.h>
diff --git a/drivers/gpu/drm/gma500/mmu.c b/drivers/gpu/drm/gma500/mmu.c
index 6b6b44e426cf..4fbc22a59ac7 100644
--- a/drivers/gpu/drm/gma500/mmu.c
+++ b/drivers/gpu/drm/gma500/mmu.c
@@ -7,6 +7,8 @@
#include <linux/highmem.h>
#include <linux/vmalloc.h>
+#include <asm/cpuid/api.h>
+
#include "mmu.h"
#include "psb_drv.h"
#include "psb_reg.h"
diff --git a/drivers/hwmon/fam15h_power.c b/drivers/hwmon/fam15h_power.c
index efcbea2d070e..ad4ed4162b57 100644
--- a/drivers/hwmon/fam15h_power.c
+++ b/drivers/hwmon/fam15h_power.c
@@ -19,6 +19,7 @@
#include <linux/sched.h>
#include <linux/topology.h>
#include <asm/processor.h>
+#include <asm/cpuid/api.h>
#include <asm/msr.h>
MODULE_DESCRIPTION("AMD Family 15h CPU processor power monitor");
diff --git a/drivers/hwmon/k10temp.c b/drivers/hwmon/k10temp.c
index a5d8f45b7881..de0760dc597d 100644
--- a/drivers/hwmon/k10temp.c
+++ b/drivers/hwmon/k10temp.c
@@ -20,7 +20,9 @@
#include <linux/module.h>
#include <linux/pci.h>
#include <linux/pci_ids.h>
+
#include <asm/amd/node.h>
+#include <asm/cpuid/api.h>
#include <asm/processor.h>
MODULE_DESCRIPTION("AMD Family 10h+ CPU core temperature monitor");
diff --git a/drivers/hwmon/k8temp.c b/drivers/hwmon/k8temp.c
index 2b80ac410cd1..53241164570e 100644
--- a/drivers/hwmon/k8temp.c
+++ b/drivers/hwmon/k8temp.c
@@ -15,6 +15,7 @@
#include <linux/err.h>
#include <linux/mutex.h>
#include <asm/processor.h>
+#include <asm/cpuid/api.h>
#define TEMP_FROM_REG(val) (((((val) >> 16) & 0xff) - 49) * 1000)
#define REG_TEMP 0xe4
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-intel.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-intel.c
index 92d77b0c2f54..abed30a5efbb 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac-intel.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-intel.c
@@ -6,6 +6,7 @@
#include <linux/pci.h>
#include <linux/dmi.h>
#include <linux/platform_data/x86/intel_pmc_ipc.h>
+#include <asm/cpuid/api.h>
#include "dwmac-intel.h"
#include "dwmac4.h"
#include "stmmac.h"
diff --git a/drivers/ras/amd/fmpm.c b/drivers/ras/amd/fmpm.c
index 34ef75af31cb..4ccaaf7b70bf 100644
--- a/drivers/ras/amd/fmpm.c
+++ b/drivers/ras/amd/fmpm.c
@@ -52,6 +52,7 @@
#include <acpi/apei.h>
#include <asm/cpu_device_id.h>
+#include <asm/cpuid/api.h>
#include <asm/mce.h>
#include "../debugfs.h"
diff --git a/drivers/thermal/intel/intel_hfi.c b/drivers/thermal/intel/intel_hfi.c
index 1a1a95b39405..640df74f1a77 100644
--- a/drivers/thermal/intel/intel_hfi.c
+++ b/drivers/thermal/intel/intel_hfi.c
@@ -41,6 +41,7 @@
#include <linux/topology.h>
#include <linux/workqueue.h>
+#include <asm/cpuid/api.h>
#include <asm/msr.h>
#include "intel_hfi.h"
diff --git a/drivers/thermal/intel/x86_pkg_temp_thermal.c b/drivers/thermal/intel/x86_pkg_temp_thermal.c
index 540109761f0a..d1dd2f5910e4 100644
--- a/drivers/thermal/intel/x86_pkg_temp_thermal.c
+++ b/drivers/thermal/intel/x86_pkg_temp_thermal.c
@@ -20,6 +20,7 @@
#include <linux/debugfs.h>
#include <asm/cpu_device_id.h>
+#include <asm/cpuid/api.h>
#include <asm/msr.h>
#include "thermal_interrupt.h"
diff --git a/drivers/virt/acrn/hsm.c b/drivers/virt/acrn/hsm.c
index 74f2086fa59f..f170ff4617fd 100644
--- a/drivers/virt/acrn/hsm.c
+++ b/drivers/virt/acrn/hsm.c
@@ -16,6 +16,7 @@
#include <linux/slab.h>
#include <asm/acrn.h>
+#include <asm/cpuid/api.h>
#include <asm/hypervisor.h>
#include "acrn_drv.h"
diff --git a/drivers/xen/events/events_base.c b/drivers/xen/events/events_base.c
index bc9a41662efc..6ea945508a89 100644
--- a/drivers/xen/events/events_base.c
+++ b/drivers/xen/events/events_base.c
@@ -40,6 +40,7 @@
#include <linux/ktime.h>
#ifdef CONFIG_X86
+#include <asm/cpuid/api.h>
#include <asm/desc.h>
#include <asm/ptrace.h>
#include <asm/idtentry.h>
diff --git a/drivers/xen/grant-table.c b/drivers/xen/grant-table.c
index 97e27f754d39..9a62023966d1 100644
--- a/drivers/xen/grant-table.c
+++ b/drivers/xen/grant-table.c
@@ -59,6 +59,7 @@
#include <xen/swiotlb-xen.h>
#include <xen/balloon.h>
#ifdef CONFIG_X86
+#include <asm/cpuid/api.h>
#include <asm/xen/cpuid.h>
#endif
#include <xen/mem-reservation.h>
diff --git a/drivers/xen/xenbus/xenbus_xs.c b/drivers/xen/xenbus/xenbus_xs.c
index 82b0a34ded70..c202e7c553a6 100644
--- a/drivers/xen/xenbus/xenbus_xs.c
+++ b/drivers/xen/xenbus/xenbus_xs.c
@@ -47,6 +47,9 @@
#include <linux/rwsem.h>
#include <linux/mutex.h>
#include <asm/xen/hypervisor.h>
+#ifdef CONFIG_X86
+#include <asm/cpuid/api.h>
+#endif
#include <xen/xenbus.h>
#include <xen/xen.h>
#include "xenbus.h"
--
2.53.0
^ permalink raw reply related [flat|nested] 101+ messages in thread
* [PATCH v6 05/90] x86/cpu: <asm/processor.h>: Do not include the CPUID API header
2026-03-27 2:15 [PATCH v6 00/90] x86: Introduce a centralized CPUID data model Ahmed S. Darwish
` (3 preceding siblings ...)
2026-03-27 2:15 ` [PATCH v6 04/90] treewide: Explicitly include the x86 CPUID headers Ahmed S. Darwish
@ 2026-03-27 2:15 ` Ahmed S. Darwish
2026-03-27 2:15 ` [PATCH v6 06/90] x86/cpuid: Rename cpuid_leaf()/cpuid_subleaf() APIs Ahmed S. Darwish
` (86 subsequent siblings)
91 siblings, 0 replies; 101+ messages in thread
From: Ahmed S. Darwish @ 2026-03-27 2:15 UTC (permalink / raw)
To: Borislav Petkov, Dave Hansen, Ingo Molnar
Cc: Thomas Gleixner, Andrew Cooper, H. Peter Anvin,
Sean Christopherson, David Woodhouse, Peter Zijlstra,
Christian Ludloff, Sohil Mehta, John Ogness, x86, x86-cpuid, LKML,
Ahmed S. Darwish
<asm/processor.h> includes <asm/cpuid/api.h> but it does not need it.
Remove the include.
This allows the CPUID APIs header to include <asm/processor.h> at a later
step without introducing a circular dependency.
Note, all call sites which implicitly included the CPUID API through
<asm/processor.h> have been modified to explicitly include the CPUID APIs
instead.
Signed-off-by: Ahmed S. Darwish <darwi@linutronix.de>
---
arch/x86/include/asm/processor.h | 1 -
1 file changed, 1 deletion(-)
diff --git a/arch/x86/include/asm/processor.h b/arch/x86/include/asm/processor.h
index a24c7805acdb..bea05fea5729 100644
--- a/arch/x86/include/asm/processor.h
+++ b/arch/x86/include/asm/processor.h
@@ -16,7 +16,6 @@ struct vm86;
#include <uapi/asm/sigcontext.h>
#include <asm/current.h>
#include <asm/cpufeatures.h>
-#include <asm/cpuid/api.h>
#include <asm/page.h>
#include <asm/pgtable_types.h>
#include <asm/percpu.h>
--
2.53.0
^ permalink raw reply related [flat|nested] 101+ messages in thread
* [PATCH v6 06/90] x86/cpuid: Rename cpuid_leaf()/cpuid_subleaf() APIs
2026-03-27 2:15 [PATCH v6 00/90] x86: Introduce a centralized CPUID data model Ahmed S. Darwish
` (4 preceding siblings ...)
2026-03-27 2:15 ` [PATCH v6 05/90] x86/cpu: <asm/processor.h>: Do not include the CPUID API header Ahmed S. Darwish
@ 2026-03-27 2:15 ` Ahmed S. Darwish
2026-03-27 2:15 ` [PATCH v6 07/90] x86/cpuid: Introduce <asm/cpuid/leaf_types.h> Ahmed S. Darwish
` (85 subsequent siblings)
91 siblings, 0 replies; 101+ messages in thread
From: Ahmed S. Darwish @ 2026-03-27 2:15 UTC (permalink / raw)
To: Borislav Petkov, Dave Hansen, Ingo Molnar
Cc: Thomas Gleixner, Andrew Cooper, H. Peter Anvin,
Sean Christopherson, David Woodhouse, Peter Zijlstra,
Christian Ludloff, Sohil Mehta, John Ogness, x86, x86-cpuid, LKML,
Ahmed S. Darwish
A new CPUID model will be added where its APIs will be designated as the
official CPUID API. Free the cpuid_leaf() and cpuid_subleaf() function
names for that API. Rename them accordingly to cpuid_read() and
cpuid_read_subleaf().
For kernel/cpuid.c, rename its local file operations read function from
cpuid_read() to cpuid_read_f() so that it does not conflict with the new
API.
No functional change.
Signed-off-by: Ahmed S. Darwish <darwi@linutronix.de>
---
arch/x86/include/asm/cpuid/api.h | 6 +++---
arch/x86/kernel/cpu/topology_amd.c | 2 +-
arch/x86/kernel/cpu/topology_ext.c | 2 +-
arch/x86/kernel/cpuid.c | 5 ++---
4 files changed, 7 insertions(+), 8 deletions(-)
diff --git a/arch/x86/include/asm/cpuid/api.h b/arch/x86/include/asm/cpuid/api.h
index 44fa82e1267c..2b9750cc8a75 100644
--- a/arch/x86/include/asm/cpuid/api.h
+++ b/arch/x86/include/asm/cpuid/api.h
@@ -131,12 +131,12 @@ static inline void __cpuid_read(u32 leaf, u32 subleaf, u32 *regs)
__cpuid(regs + CPUID_EAX, regs + CPUID_EBX, regs + CPUID_ECX, regs + CPUID_EDX);
}
-#define cpuid_subleaf(leaf, subleaf, regs) { \
+#define cpuid_read_subleaf(leaf, subleaf, regs) { \
static_assert(sizeof(*(regs)) == 16); \
__cpuid_read(leaf, subleaf, (u32 *)(regs)); \
}
-#define cpuid_leaf(leaf, regs) { \
+#define cpuid_read(leaf, regs) { \
static_assert(sizeof(*(regs)) == 16); \
__cpuid_read(leaf, 0, (u32 *)(regs)); \
}
@@ -228,7 +228,7 @@ static inline u32 cpuid_base_hypervisor(const char *sig, u32 leaves)
*/
static inline void cpuid_leaf_0x2(union leaf_0x2_regs *regs)
{
- cpuid_leaf(0x2, regs);
+ cpuid_read(0x2, regs);
/*
* All Intel CPUs must report an iteration count of 1. In case
diff --git a/arch/x86/kernel/cpu/topology_amd.c b/arch/x86/kernel/cpu/topology_amd.c
index cc103c85b96d..da080d732e10 100644
--- a/arch/x86/kernel/cpu/topology_amd.c
+++ b/arch/x86/kernel/cpu/topology_amd.c
@@ -80,7 +80,7 @@ static bool parse_8000_001e(struct topo_scan *tscan)
if (!boot_cpu_has(X86_FEATURE_TOPOEXT))
return false;
- cpuid_leaf(0x8000001e, &leaf);
+ cpuid_read(0x8000001e, &leaf);
/*
* If leaf 0xb/0x26 is available, then the APIC ID and the domain
diff --git a/arch/x86/kernel/cpu/topology_ext.c b/arch/x86/kernel/cpu/topology_ext.c
index eb915c73895f..60dfaa02ffd0 100644
--- a/arch/x86/kernel/cpu/topology_ext.c
+++ b/arch/x86/kernel/cpu/topology_ext.c
@@ -71,7 +71,7 @@ static inline bool topo_subleaf(struct topo_scan *tscan, u32 leaf, u32 subleaf,
default: return false;
}
- cpuid_subleaf(leaf, subleaf, &sl);
+ cpuid_read_subleaf(leaf, subleaf, &sl);
if (!sl.num_processors || sl.type == INVALID_TYPE)
return false;
diff --git a/arch/x86/kernel/cpuid.c b/arch/x86/kernel/cpuid.c
index cbd04b677fd1..b55fe9c7359a 100644
--- a/arch/x86/kernel/cpuid.c
+++ b/arch/x86/kernel/cpuid.c
@@ -59,8 +59,7 @@ static void cpuid_smp_cpuid(void *cmd_block)
complete(&cmd->done);
}
-static ssize_t cpuid_read(struct file *file, char __user *buf,
- size_t count, loff_t *ppos)
+static ssize_t cpuid_read_f(struct file *file, char __user *buf, size_t count, loff_t *ppos)
{
char __user *tmp = buf;
struct cpuid_regs_done cmd;
@@ -120,7 +119,7 @@ static int cpuid_open(struct inode *inode, struct file *file)
static const struct file_operations cpuid_fops = {
.owner = THIS_MODULE,
.llseek = no_seek_end_llseek,
- .read = cpuid_read,
+ .read = cpuid_read_f,
.open = cpuid_open,
};
--
2.53.0
^ permalink raw reply related [flat|nested] 101+ messages in thread
* [PATCH v6 07/90] x86/cpuid: Introduce <asm/cpuid/leaf_types.h>
2026-03-27 2:15 [PATCH v6 00/90] x86: Introduce a centralized CPUID data model Ahmed S. Darwish
` (5 preceding siblings ...)
2026-03-27 2:15 ` [PATCH v6 06/90] x86/cpuid: Rename cpuid_leaf()/cpuid_subleaf() APIs Ahmed S. Darwish
@ 2026-03-27 2:15 ` Ahmed S. Darwish
2026-03-27 2:15 ` [PATCH v6 08/90] x86: Introduce a centralized CPUID data model Ahmed S. Darwish
` (84 subsequent siblings)
91 siblings, 0 replies; 101+ messages in thread
From: Ahmed S. Darwish @ 2026-03-27 2:15 UTC (permalink / raw)
To: Borislav Petkov, Dave Hansen, Ingo Molnar
Cc: Thomas Gleixner, Andrew Cooper, H. Peter Anvin,
Sean Christopherson, David Woodhouse, Peter Zijlstra,
Christian Ludloff, Sohil Mehta, John Ogness, x86, x86-cpuid, LKML,
Ahmed S. Darwish
To centralize all CPUID access across the x86 subsystem, introduce
<asm/cpuid/leaf_types.h>. It is generated by the x86-cpuid-db project and
provides C99 bitfield listings for all publicly known CPUID leaves.
Add the header to MAINTAINERS "x86 CPUID database" entry as well.
Suggested-by: Thomas Gleixner <tglx@kernel.org>
Signed-off-by: Ahmed S. Darwish <darwi@linutronix.de>
Link: https://gitlab.com/x86-cpuid.org/x86-cpuid-db/-/blob/v3.0/CHANGELOG.rst
---
MAINTAINERS | 1 +
arch/x86/include/asm/cpuid/leaf_types.h | 2350 +++++++++++++++++++++++
2 files changed, 2351 insertions(+)
create mode 100644 arch/x86/include/asm/cpuid/leaf_types.h
diff --git a/MAINTAINERS b/MAINTAINERS
index 7d10988cbc62..8cb3b9fcface 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -28564,6 +28564,7 @@ R: Ahmed S. Darwish <darwi@linutronix.de>
L: x86-cpuid@lists.linux.dev
S: Maintained
W: https://x86-cpuid.org
+F: arch/x86/include/asm/cpuid/leaf_types.h
F: tools/arch/x86/kcpuid/
X86 ENTRY CODE
diff --git a/arch/x86/include/asm/cpuid/leaf_types.h b/arch/x86/include/asm/cpuid/leaf_types.h
new file mode 100644
index 000000000000..5b0008e455e2
--- /dev/null
+++ b/arch/x86/include/asm/cpuid/leaf_types.h
@@ -0,0 +1,2350 @@
+/* SPDX-License-Identifier: MIT */
+/* Generator: x86-cpuid-db v3.0 */
+
+/*
+ * Auto-generated file.
+ * Please submit all updates and bugfixes to https://x86-cpuid.org
+ */
+
+#ifndef _ASM_X86_CPUID_LEAF_TYPES
+#define _ASM_X86_CPUID_LEAF_TYPES
+
+#include <linux/types.h>
+
+/*
+ * Leaf 0x0
+ * Maximum standard leaf + CPU vendor string
+ */
+
+struct leaf_0x0_0 {
+ // eax
+ u32 max_std_leaf : 32; // Highest standard CPUID leaf
+ // ebx
+ u32 cpu_vendorid_0 : 32; // CPU vendor ID string bytes 0 - 3
+ // ecx
+ u32 cpu_vendorid_2 : 32; // CPU vendor ID string bytes 8 - 11
+ // edx
+ u32 cpu_vendorid_1 : 32; // CPU vendor ID string bytes 4 - 7
+};
+
+/*
+ * Leaf 0x1
+ * CPU FMS (Family/Model/Stepping) + standard feature flags
+ */
+
+struct leaf_0x1_0 {
+ // eax
+ u32 stepping : 4, // Stepping ID
+ base_model : 4, // Base CPU model ID
+ base_family_id : 4, // Base CPU family ID
+ cpu_type : 2, // CPU type
+ : 2, // Reserved
+ ext_model : 4, // Extended CPU model ID
+ ext_family : 8, // Extended CPU family ID
+ : 4; // Reserved
+ // ebx
+ u32 brand_id : 8, // Brand index
+ clflush_size : 8, // CLFLUSH instruction cache line size
+ n_logical_cpu : 8, // Logical CPU count
+ local_apic_id : 8; // Initial local APIC physical ID
+ // ecx
+ u32 sse3 : 1, // Streaming SIMD Extensions 3 (SSE3)
+ pclmulqdq : 1, // PCLMULQDQ instruction support
+ dtes64 : 1, // 64-bit DS save area
+ monitor : 1, // MONITOR/MWAIT support
+ dscpl : 1, // CPL Qualified Debug Store
+ vmx : 1, // Virtual Machine Extensions
+ smx : 1, // Safer Mode Extensions
+ est : 1, // Enhanced Intel SpeedStep
+ tm2 : 1, // Thermal Monitor 2
+ ssse3 : 1, // Supplemental SSE3
+ cntxt_id : 1, // L1 Context ID
+ sdbg : 1, // Silicon Debug
+ fma : 1, // FMA extensions using YMM state
+ cx16 : 1, // CMPXCHG16B instruction support
+ xtpr_update : 1, // xTPR Update Control
+ pdcm : 1, // Perfmon and Debug Capability
+ : 1, // Reserved
+ pcid : 1, // Process-context identifiers
+ dca : 1, // Direct Cache Access
+ sse4_1 : 1, // SSE4.1
+ sse4_2 : 1, // SSE4.2
+ x2apic : 1, // X2APIC support
+ movbe : 1, // MOVBE instruction support
+ popcnt : 1, // POPCNT instruction support
+ tsc_deadline_timer : 1, // APIC timer one-shot operation
+ aes : 1, // AES instructions
+ xsave : 1, // XSAVE (and related instructions) support
+ osxsave : 1, // XSAVE (and related instructions) are enabled by OS
+ avx : 1, // AVX instructions support
+ f16c : 1, // Half-precision floating-point conversion support
+ rdrand : 1, // RDRAND instruction support
+ guest_status : 1; // System is running as guest; (para-)virtualized system
+ // edx
+ u32 fpu : 1, // Floating-Point Unit on-chip (x87)
+ vme : 1, // Virtual-8086 Mode Extensions
+ de : 1, // Debugging Extensions
+ pse : 1, // Page Size Extension
+ tsc : 1, // Time Stamp Counter
+ msr : 1, // Model-Specific Registers (RDMSR and WRMSR support)
+ pae : 1, // Physical Address Extensions
+ mce : 1, // Machine Check Exception
+ cx8 : 1, // CMPXCHG8B instruction
+ apic : 1, // APIC on-chip
+ : 1, // Reserved
+ sep : 1, // SYSENTER, SYSEXIT, and associated MSRs
+ mtrr : 1, // Memory Type Range Registers
+ pge : 1, // Page Global Extensions
+ mca : 1, // Machine Check Architecture
+ cmov : 1, // Conditional Move Instruction
+ pat : 1, // Page Attribute Table
+ pse36 : 1, // Page Size Extension (36-bit)
+ psn : 1, // Processor Serial Number
+ clflush : 1, // CLFLUSH instruction
+ : 1, // Reserved
+ ds : 1, // Debug Store
+ acpi : 1, // Thermal monitor and clock control
+ mmx : 1, // MMX instructions
+ fxsr : 1, // FXSAVE and FXRSTOR instructions
+ sse : 1, // SSE instructions
+ sse2 : 1, // SSE2 instructions
+ selfsnoop : 1, // Self Snoop
+ htt : 1, // Hyper-threading
+ tm : 1, // Thermal Monitor
+ ia64 : 1, // Legacy IA-64 (Itanium) support bit, now reserved
+ pbe : 1; // Pending Break Enable
+};
+
+/*
+ * Leaf 0x2
+ * Intel cache and TLB information one-byte descriptors
+ */
+
+struct leaf_0x2_0 {
+ // eax
+ u32 iteration_count : 8, // Number of times this leaf must be queried
+ desc1 : 8, // Descriptor #1
+ desc2 : 8, // Descriptor #2
+ desc3 : 7, // Descriptor #3
+ eax_invalid : 1; // Descriptors 1-3 are invalid if set
+ // ebx
+ u32 desc4 : 8, // Descriptor #4
+ desc5 : 8, // Descriptor #5
+ desc6 : 8, // Descriptor #6
+ desc7 : 7, // Descriptor #7
+ ebx_invalid : 1; // Descriptors 4-7 are invalid if set
+ // ecx
+ u32 desc8 : 8, // Descriptor #8
+ desc9 : 8, // Descriptor #9
+ desc10 : 8, // Descriptor #10
+ desc11 : 7, // Descriptor #11
+ ecx_invalid : 1; // Descriptors 8-11 are invalid if set
+ // edx
+ u32 desc12 : 8, // Descriptor #12
+ desc13 : 8, // Descriptor #13
+ desc14 : 8, // Descriptor #14
+ desc15 : 7, // Descriptor #15
+ edx_invalid : 1; // Descriptors 12-15 are invalid if set
+};
+
+/*
+ * Leaf 0x4
+ * Intel deterministic cache parameters
+ */
+
+struct leaf_0x4_n {
+ // eax
+ u32 cache_type : 5, // Cache type field
+ cache_level : 3, // Cache level (1-based)
+ cache_self_init : 1, // Self-initializing cache level
+ fully_associative : 1, // Fully-associative cache
+ : 4, // Reserved
+ num_threads_sharing : 12, // Number logical CPUs sharing this cache
+ num_cores_on_die : 6; // Number of cores in the physical package
+ // ebx
+ u32 cache_linesize : 12, // System coherency line size (0-based)
+ cache_npartitions : 10, // Physical line partitions (0-based)
+ cache_nways : 10; // Ways of associativity (0-based)
+ // ecx
+ u32 cache_nsets : 31, // Cache number of sets (0-based)
+ : 1; // Reserved
+ // edx
+ u32 wbinvd_rll_no_guarantee : 1, // WBINVD/INVD not guaranteed for Remote Lower-Level caches
+ ll_inclusive : 1, // Cache is inclusive of Lower-Level caches
+ complex_indexing : 1, // Not a direct-mapped cache (complex function)
+ : 29; // Reserved
+};
+
+#define LEAF_0x4_SUBLEAF_N_FIRST 0
+#define LEAF_0x4_SUBLEAF_N_LAST 31
+
+/*
+ * Leaf 0x5
+ * MONITOR/MWAIT instructions
+ */
+
+struct leaf_0x5_0 {
+ // eax
+ u32 min_mon_size : 16, // Smallest monitor-line size, in bytes
+ : 16; // Reserved
+ // ebx
+ u32 max_mon_size : 16, // Largest monitor-line size, in bytes
+ : 16; // Reserved
+ // ecx
+ u32 mwait_ext : 1, // MONITOR/MWAIT extensions
+ mwait_irq_break : 1, // Interrupts as a break event for MWAIT
+ : 30; // Reserved
+ // edx
+ u32 n_c0_substates : 4, // Number of C0 sub C-states
+ n_c1_substates : 4, // Number of C1 sub C-states
+ n_c2_substates : 4, // Number of C2 sub C-states
+ n_c3_substates : 4, // Number of C3 sub C-states
+ n_c4_substates : 4, // Number of C4 sub C-states
+ n_c5_substates : 4, // Number of C5 sub C-states
+ n_c6_substates : 4, // Number of C6 sub C-states
+ n_c7_substates : 4; // Number of C7 sub C-states
+};
+
+/*
+ * Leaf 0x6
+ * Thermal and power management
+ */
+
+struct leaf_0x6_0 {
+ // eax
+ u32 digital_temp : 1, // Digital temperature sensor
+ turbo_boost : 1, // Intel Turbo Boost
+ lapic_timer_always_on : 1, // Always-Running APIC Timer (not affected by p-state)
+ : 1, // Reserved
+ power_limit_event : 1, // Power Limit Notification (PLN) event
+ ecmd : 1, // Clock modulation duty cycle extension
+ package_thermal : 1, // Package thermal management
+ hwp_base_regs : 1, // HWP (Hardware P-states) base registers
+ hwp_notify : 1, // HWP notification (IA32_HWP_INTERRUPT MSR)
+ hwp_activity_window : 1, // HWP activity window (IA32_HWP_REQUEST[bits 41:32])
+ hwp_energy_perf_pr : 1, // HWP Energy Performance Preference
+ hwp_package_req : 1, // HWP Package Level Request
+ : 1, // Reserved
+ hdc_base_regs : 1, // HDC base registers
+ turbo_boost_3_0 : 1, // Intel Turbo Boost Max 3.0
+ hwp_capabilities : 1, // HWP Highest Performance change
+ hwp_peci_override : 1, // HWP PECI override
+ hwp_flexible : 1, // Flexible HWP
+ hwp_fast : 1, // IA32_HWP_REQUEST MSR fast access mode
+ hw_feedback : 1, // HW_FEEDBACK MSRs
+ hwp_ignore_idle : 1, // Ignoring idle logical CPU HWP request is supported
+ : 1, // Reserved
+ hwp_ctl : 1, // IA32_HWP_CTL MSR
+ thread_director : 1, // Intel thread director
+ therm_interrupt_bit25 : 1, // IA32_THERM_INTERRUPT MSR bit 25
+ : 7; // Reserved
+ // ebx
+ u32 n_therm_thresholds : 4, // Digital thermometer thresholds
+ : 28; // Reserved
+ // ecx
+ u32 aperf_mperf : 1, // MPERF/APERF MSRs (effective frequency interface)
+ : 2, // Reserved
+ energy_perf_bias : 1, // IA32_ENERGY_PERF_BIAS MSR
+ : 4, // Reserved
+ thrd_director_nclasses : 8, // Number of classes, Intel thread director
+ : 16; // Reserved
+ // edx
+ u32 perfcap_reporting : 1, // Performance capability reporting
+ encap_reporting : 1, // Energy efficiency capability reporting
+ : 6, // Reserved
+ feedback_sz : 4, // Feedback interface structure size, in 4K pages
+ : 4, // Reserved
+ this_lcpu_hwfdbk_idx : 16; // This logical CPU hardware feedback interface index
+};
+
+/*
+ * Leaf 0x7
+ * Extended CPU features
+ */
+
+struct leaf_0x7_0 {
+ // eax
+ u32 leaf7_n_subleaves : 32; // Number of leaf 0x7 subleaves
+ // ebx
+ u32 fsgsbase : 1, // FSBASE/GSBASE read/write
+ tsc_adjust : 1, // IA32_TSC_ADJUST MSR
+ sgx : 1, // Intel SGX (Software Guard Extensions)
+ bmi1 : 1, // Bit manipulation extensions group 1
+ hle : 1, // Hardware Lock Elision
+ avx2 : 1, // AVX2 instruction set
+ fdp_excptn_only : 1, // FPU Data Pointer updated only on x87 exceptions
+ smep : 1, // Supervisor Mode Execution Protection
+ bmi2 : 1, // Bit manipulation extensions group 2
+ erms : 1, // Enhanced REP MOVSB/STOSB
+ invpcid : 1, // INVPCID instruction (Invalidate Processor Context ID)
+ rtm : 1, // Intel restricted transactional memory
+ pqm : 1, // Intel RDT-CMT / AMD Platform-QoS cache monitoring
+ zero_fcs_fds : 1, // Deprecated FPU CS/DS (stored as zero)
+ mpx : 1, // Intel memory protection extensions
+ rdt_a : 1, // Intel RDT / AMD Platform-QoS Enforcement
+ avx512f : 1, // AVX-512 foundation instructions
+ avx512dq : 1, // AVX-512 double/quadword instructions
+ rdseed : 1, // RDSEED instruction
+ adx : 1, // ADCX/ADOX instructions
+ smap : 1, // Supervisor mode access prevention
+ avx512ifma : 1, // AVX-512 integer fused multiply add
+ : 1, // Reserved
+ clflushopt : 1, // CLFLUSHOPT instruction
+ clwb : 1, // CLWB instruction
+ intel_pt : 1, // Intel processor trace
+ avx512pf : 1, // AVX-512 prefetch instructions
+ avx512er : 1, // AVX-512 exponent/reciprocal instructions
+ avx512cd : 1, // AVX-512 conflict detection instructions
+ sha : 1, // SHA/SHA256 instructions
+ avx512bw : 1, // AVX-512 byte/word instructions
+ avx512vl : 1; // AVX-512 VL (128/256 vector length) extensions
+ // ecx
+ u32 prefetchwt1 : 1, // PREFETCHWT1 (Intel Xeon Phi only)
+ avx512vbmi : 1, // AVX-512 Vector byte manipulation instructions
+ umip : 1, // User mode instruction protection
+ pku : 1, // Protection keys for user-space
+ ospke : 1, // OS protection keys enable
+ waitpkg : 1, // WAITPKG instructions
+ avx512_vbmi2 : 1, // AVX-512 vector byte manipulation instructions group 2
+ cet_ss : 1, // CET shadow stack features
+ gfni : 1, // Galois field new instructions
+ vaes : 1, // Vector AES instructions
+ vpclmulqdq : 1, // VPCLMULQDQ 256-bit instruction
+ avx512_vnni : 1, // Vector neural network instructions
+ avx512_bitalg : 1, // AVX-512 bitwise algorithms
+ tme : 1, // Intel total memory encryption
+ avx512_vpopcntdq : 1, // AVX-512: POPCNT for vectors of DWORD/QWORD
+ : 1, // Reserved
+ la57 : 1, // 57-bit linear addresses (five-level paging)
+ mawau_val_lm : 5, // BNDLDX/BNDSTX MAWAU value in 64-bit mode
+ rdpid : 1, // RDPID instruction
+ key_locker : 1, // Intel key locker
+ bus_lock_detect : 1, // OS bus-lock detection
+ cldemote : 1, // CLDEMOTE instruction
+ : 1, // Reserved
+ movdiri : 1, // MOVDIRI instruction
+ movdir64b : 1, // MOVDIR64B instruction
+ enqcmd : 1, // Enqueue stores (ENQCMD{,S})
+ sgx_lc : 1, // Intel SGX launch configuration
+ pks : 1; // Protection keys for supervisor-mode pages
+ // edx
+ u32 : 1, // Reserved
+ sgx_keys : 1, // Intel SGX attestation services
+ avx512_4vnniw : 1, // AVX-512 neural network instructions
+ avx512_4fmaps : 1, // AVX-512 multiply accumulation single precision
+ fsrm : 1, // Fast short REP MOV
+ uintr : 1, // User interrupts
+ : 2, // Reserved
+ avx512_vp2intersect : 1, // VP2INTERSECT{D,Q} instructions
+ srdbs_ctrl : 1, // SRBDS mitigation MSR
+ md_clear : 1, // VERW MD_CLEAR microcode
+ rtm_always_abort : 1, // XBEGIN (RTM transaction) always aborts
+ : 1, // Reserved
+ tsx_force_abort : 1, // MSR TSX_FORCE_ABORT, RTM_ABORT bit
+ serialize : 1, // SERIALIZE instruction
+ hybrid_cpu : 1, // The CPU is identified as a 'hybrid part'
+ tsxldtrk : 1, // TSX suspend/resume load address tracking
+ : 1, // Reserved
+ pconfig : 1, // PCONFIG instruction
+ arch_lbr : 1, // Intel architectural LBRs
+ cet_ibt : 1, // CET indirect branch tracking
+ : 1, // Reserved
+ amx_bf16 : 1, // AMX-BF16: tile bfloat16
+ avx512_fp16 : 1, // AVX-512 FP16 instructions
+ amx_tile : 1, // AMX-TILE: tile architecture
+ amx_int8 : 1, // AMX-INT8: tile 8-bit integer
+ spec_ctrl : 1, // Speculation Control (IBRS/IBPB: indirect branch restrictions)
+ intel_stibp : 1, // Single thread indirect branch predictors
+ flush_l1d : 1, // FLUSH L1D cache: IA32_FLUSH_CMD MSR
+ arch_capabilities : 1, // Intel IA32_ARCH_CAPABILITIES MSR
+ core_capabilities : 1, // IA32_CORE_CAPABILITIES MSR
+ spec_ctrl_ssbd : 1; // Speculative store bypass disable
+};
+
+struct leaf_0x7_1 {
+ // eax
+ u32 : 4, // Reserved
+ avx_vnni : 1, // AVX-VNNI instructions
+ avx512_bf16 : 1, // AVX-512 bfloat16 instructions
+ lass : 1, // Linear address space separation
+ cmpccxadd : 1, // CMPccXADD instructions
+ arch_perfmon_ext : 1, // ArchPerfmonExt: leaf 0x23
+ : 1, // Reserved
+ fzrm : 1, // Fast zero-length REP MOVSB
+ fsrs : 1, // Fast short REP STOSB
+ fsrc : 1, // Fast Short REP CMPSB/SCASB
+ : 4, // Reserved
+ fred : 1, // FRED: Flexible return and event delivery transitions
+ lkgs : 1, // LKGS: Load 'kernel' (userspace) GS
+ wrmsrns : 1, // WRMSRNS instruction (WRMSR-non-serializing)
+ nmi_src : 1, // NMI-source reporting with FRED event data
+ amx_fp16 : 1, // AMX-FP16: FP16 tile operations
+ hreset : 1, // HRESET (Thread director history reset)
+ avx_ifma : 1, // Integer fused multiply add
+ : 2, // Reserved
+ lam : 1, // Linear address masking
+ rd_wr_msrlist : 1, // RDMSRLIST/WRMSRLIST instructions
+ : 4; // Reserved
+ // ebx
+ u32 intel_ppin : 1, // Protected processor inventory number (PPIN{,_CTL} MSRs)
+ : 31; // Reserved
+ // ecx
+ u32 : 32; // Reserved
+ // edx
+ u32 : 4, // Reserved
+ avx_vnni_int8 : 1, // AVX-VNNI-INT8 instructions
+ avx_ne_convert : 1, // AVX-NE-CONVERT instructions
+ : 2, // Reserved
+ amx_complex : 1, // AMX-COMPLEX instructions (starting from Granite Rapids)
+ : 5, // Reserved
+ prefetchit_0_1 : 1, // PREFETCHIT0/1 instructions
+ : 3, // Reserved
+ cet_sss : 1, // CET supervisor shadow stacks safe to use
+ : 13; // Reserved
+};
+
+struct leaf_0x7_2 {
+ // eax
+ u32 : 32; // Reserved
+ // ebx
+ u32 : 32; // Reserved
+ // ecx
+ u32 : 32; // Reserved
+ // edx
+ u32 intel_psfd : 1, // Intel predictive store forward disable
+ ipred_ctrl : 1, // MSR bits IA32_SPEC_CTRL.IPRED_DIS_{U,S}
+ rrsba_ctrl : 1, // MSR bits IA32_SPEC_CTRL.RRSBA_DIS_{U,S}
+ ddp_ctrl : 1, // MSR bit IA32_SPEC_CTRL.DDPD_U
+ bhi_ctrl : 1, // MSR bit IA32_SPEC_CTRL.BHI_DIS_S
+ mcdt_no : 1, // MCDT mitigation not needed
+ uclock_disable : 1, // UC-lock disable
+ : 25; // Reserved
+};
+
+/*
+ * Leaf 0x9
+ * Intel DCA (Direct Cache Access)
+ */
+
+struct leaf_0x9_0 {
+ // eax
+ u32 dca_enabled_in_bios : 1, // DCA is enabled in BIOS
+ : 31; // Reserved
+ // ebx
+ u32 : 32; // Reserved
+ // ecx
+ u32 : 32; // Reserved
+ // edx
+ u32 : 32; // Reserved
+};
+
+/*
+ * Leaf 0xa
+ * Intel PMU (Performance Monitoring Unit)
+ */
+
+struct leaf_0xa_0 {
+ // eax
+ u32 pmu_version : 8, // Performance monitoring unit version ID
+ num_counters_gp : 8, // Number of general-purpose PMU counters per logical CPU
+ bit_width_gp : 8, // Bitwidth of PMU general-purpose counters
+ events_mask_len : 8; // Length of CPUID(0xa).EBX bit vector
+ // ebx
+ u32 no_core_cycle : 1, // Core cycle event not available
+ no_instruction_retired : 1, // Instruction retired event not available
+ no_reference_cycles : 1, // Reference cycles event not available
+ no_llc_reference : 1, // LLC-reference event not available
+ no_llc_misses : 1, // LLC-misses event not available
+ no_br_insn_retired : 1, // Branch instruction retired event not available
+ no_br_misses_retired : 1, // Branch mispredict retired event not available
+ no_topdown_slots : 1, // Topdown slots event not available
+ no_backend_bound : 1, // Topdown backend bound not available
+ no_bad_speculation : 1, // Topdown bad speculation not available
+ no_frontend_bound : 1, // Topdown frontend bound not available
+ no_retiring : 1, // Topdown retiring not available
+ no_lbr_inserts : 1, // LBR inserts not available
+ : 19; // Reserved
+ // ecx
+ u32 pmu_fcounters_bitmap : 32; // Fixed-function PMU counters support bitmap
+ // edx
+ u32 num_counters_fixed : 5, // Number of fixed PMU counters
+ bitwidth_fixed : 8, // Bitwidth of PMU fixed counters
+ : 2, // Reserved
+ anythread_deprecation : 1, // AnyThread mode deprecation
+ : 16; // Reserved
+};
+
+/*
+ * Leaf 0xb
+ * CPU extended topology v1
+ */
+
+struct leaf_0xb_n {
+ // eax
+ u32 x2apic_id_shift : 5, // Bit width of this level (previous levels inclusive)
+ : 27; // Reserved
+ // ebx
+ u32 domain_lcpus_count : 16, // Logical CPUs count across all instances of this domain
+ : 16; // Reserved
+ // ecx
+ u32 domain_nr : 8, // This domain level (subleaf ID)
+ domain_type : 8, // This domain type
+ : 16; // Reserved
+ // edx
+ u32 x2apic_id : 32; // x2APIC ID of current logical CPU
+};
+
+#define LEAF_0xb_SUBLEAF_N_FIRST 0
+#define LEAF_0xb_SUBLEAF_N_LAST 1
+
+/*
+ * Leaf 0xd
+ * CPU extended state
+ */
+
+struct leaf_0xd_0 {
+ // eax
+ u32 xcr0_x87 : 1, // XCR0.X87
+ xcr0_sse : 1, // XCR0.SSE
+ xcr0_avx : 1, // XCR0.AVX
+ xcr0_mpx_bndregs : 1, // XCR0.BNDREGS: MPX BND0-BND3 registers
+ xcr0_mpx_bndcsr : 1, // XCR0.BNDCSR: MPX BNDCFGU/BNDSTATUS registers
+ xcr0_avx512_opmask : 1, // XCR0.OPMASK: AVX-512 k0-k7 registers
+ xcr0_avx512_zmm_hi256 : 1, // XCR0.ZMM_Hi256: AVX-512 ZMM0->ZMM7/15 registers
+ xcr0_avx512_hi16_zmm : 1, // XCR0.HI16_ZMM: AVX-512 ZMM16->ZMM31 registers
+ : 1, // Reserved
+ xcr0_pkru : 1, // XCR0.PKRU: XSAVE PKRU registers
+ : 1, // Reserved
+ xcr0_cet_u : 1, // XCR0.CET_U: CET user state
+ xcr0_cet_s : 1, // XCR0.CET_S: CET supervisor state
+ : 4, // Reserved
+ xcr0_tileconfig : 1, // XCR0.TILECONFIG: AMX can manage TILECONFIG
+ xcr0_tiledata : 1, // XCR0.TILEDATA: AMX can manage TILEDATA
+ : 13; // Reserved
+ // ebx
+ u32 xsave_sz_xcr0 : 32; // XSAVE/XRSTOR area byte size, for XCR0 enabled features
+ // ecx
+ u32 xsave_sz_max : 32; // XSAVE/XRSTOR area max byte size, all CPU features
+ // edx
+ u32 : 30, // Reserved
+ xcr0_lwp : 1, // AMD XCR0.LWP: Light-weight Profiling
+ : 1; // Reserved
+};
+
+struct leaf_0xd_1 {
+ // eax
+ u32 xsaveopt : 1, // XSAVEOPT instruction
+ xsavec : 1, // XSAVEC instruction
+ xgetbv1 : 1, // XGETBV instruction with ECX = 1
+ xsaves : 1, // XSAVES/XRSTORS instructions (and XSS MSR)
+ xfd : 1, // Extended feature disable
+ : 27; // Reserved
+ // ebx
+ u32 xsave_sz_xcr0_xss : 32; // XSAVES/XSAVEC area byte size, for XCR0|XSS enabled features
+ // ecx
+ u32 : 8, // Reserved
+ xss_pt : 1, // PT state
+ : 1, // Reserved
+ xss_pasid : 1, // PASID state
+ xss_cet_u : 1, // CET user state
+ xss_cet_p : 1, // CET supervisor state
+ xss_hdc : 1, // HDC state
+ xss_uintr : 1, // UINTR state
+ xss_lbr : 1, // LBR state
+ xss_hwp : 1, // HWP state
+ : 15; // Reserved
+ // edx
+ u32 : 32; // Reserved
+};
+
+struct leaf_0xd_n {
+ // eax
+ u32 xsave_sz : 32; // Subleaf-N feature save area size, in bytes
+ // ebx
+ u32 xsave_offset : 32; // Subleaf-N feature save area offset, in bytes
+ // ecx
+ u32 is_xss_bit : 1, // Subleaf N describes an XSS bit (otherwise XCR0)
+ compacted_xsave_64byte_aligned : 1, // When compacted, subleaf-N XSAVE area is 64-byte aligned
+ : 30; // Reserved
+ // edx
+ u32 : 32; // Reserved
+};
+
+#define LEAF_0xd_SUBLEAF_N_FIRST 2
+#define LEAF_0xd_SUBLEAF_N_LAST 63
+
+/*
+ * Leaf 0xf
+ * Intel RDT / AMD PQoS resource monitoring
+ */
+
+struct leaf_0xf_0 {
+ // eax
+ u32 : 32; // Reserved
+ // ebx
+ u32 core_rmid_max : 32; // RMID max within this core (0-based)
+ // ecx
+ u32 : 32; // Reserved
+ // edx
+ u32 : 1, // Reserved
+ llc_qos_mon : 1, // LLC QoS-monitoring
+ : 30; // Reserved
+};
+
+struct leaf_0xf_1 {
+ // eax
+ u32 l3c_qm_bitwidth : 8, // L3 QoS-monitoring counter bitwidth (24-based)
+ l3c_qm_overflow_bit : 1, // QM_CTR MSR bit 61 is an overflow bit
+ io_rdt_cmt : 1, // non-CPU agent supporting Intel RDT CMT present
+ io_rdt_mbm : 1, // non-CPU agent supporting Intel RDT MBM present
+ : 21; // Reserved
+ // ebx
+ u32 l3c_qm_conver_factor : 32; // QM_CTR MSR conversion factor to bytes
+ // ecx
+ u32 l3c_qm_rmid_max : 32; // L3 QoS-monitoring max RMID
+ // edx
+ u32 l3c_qm_occupancy : 1, // L3 QoS occupancy monitoring
+ l3c_qm_mbm_total : 1, // L3 QoS total bandwidth monitoring
+ l3c_qm_mbm_local : 1, // L3 QoS local bandwidth monitoring
+ : 29; // Reserved
+};
+
+/*
+ * Leaf 0x10
+ * Intel RDT / AMD PQoS allocation
+ */
+
+struct leaf_0x10_0 {
+ // eax
+ u32 : 32; // Reserved
+ // ebx
+ u32 : 1, // Reserved
+ cat_l3 : 1, // L3 Cache Allocation Technology
+ cat_l2 : 1, // L2 Cache Allocation Technology
+ mba : 1, // Memory Bandwidth Allocation
+ : 28; // Reserved
+ // ecx
+ u32 : 32; // Reserved
+ // edx
+ u32 : 32; // Reserved
+};
+
+struct leaf_0x10_n {
+ // eax
+ u32 cat_cbm_len : 5, // L3/L2_CAT capacity bitmask length, minus-one notation
+ : 27; // Reserved
+ // ebx
+ u32 cat_units_bitmap : 32; // L3/L2_CAT allocation units bitmap
+ // ecx
+ u32 : 1, // Reserved
+ l3_cat_cos_infreq_updates : 1, // L3_CAT COS updates should be infrequent
+ cat_cdp_supported : 1, // L3/L2_CAT Code and Data Prioritization
+ cat_sparse_1s : 1, // L3/L2_CAT non-contiguous 1s value
+ : 28; // Reserved
+ // edx
+ u32 cat_cos_max : 16, // L3/L2_CAT max Class of Service
+ : 16; // Reserved
+};
+
+#define LEAF_0x10_SUBLEAF_N_FIRST 1
+#define LEAF_0x10_SUBLEAF_N_LAST 2
+
+struct leaf_0x10_3 {
+ // eax
+ u32 mba_max_delay : 12, // Max MBA throttling value; minus-one notation
+ : 20; // Reserved
+ // ebx
+ u32 : 32; // Reserved
+ // ecx
+ u32 mba_per_thread : 1, // Per-thread MBA controls
+ : 1, // Reserved
+ mba_delay_linear : 1, // Delay values are linear
+ : 29; // Reserved
+ // edx
+ u32 mba_cos_max : 16, // MBA max Class of Service
+ : 16; // Reserved
+};
+
+/*
+ * Leaf 0x12
+ * Intel SGX (Software Guard Extensions)
+ */
+
+struct leaf_0x12_0 {
+ // eax
+ u32 sgx1 : 1, // SGX1 leaf functions
+ sgx2 : 1, // SGX2 leaf functions
+ : 3, // Reserved
+ enclv_leaves : 1, // ENCLV leaves
+ encls_leaves : 1, // ENCLS leaves
+ enclu_everifyreport2 : 1, // ENCLU leaf EVERIFYREPORT2
+ : 2, // Reserved
+ encls_eupdatesvn : 1, // ENCLS leaf EUPDATESVN
+ enclu_edeccssa : 1, // ENCLU leaf EDECCSSA
+ : 20; // Reserved
+ // ebx
+ u32 miscselect_exinfo : 1, // SSA.MISC frame: Enclave #PF and #GP reporting
+ miscselect_cpinfo : 1, // SSA.MISC frame: Enclave #CP reporting
+ : 30; // Reserved
+ // ecx
+ u32 : 32; // Reserved
+ // edx
+ u32 max_enclave_sz_not64 : 8, // Maximum enclave size in non-64-bit mode (log2)
+ max_enclave_sz_64 : 8, // Maximum enclave size in 64-bit mode (log2)
+ : 16; // Reserved
+};
+
+struct leaf_0x12_1 {
+ // eax
+ u32 secs_attr_init : 1, // Enclave initialized by EINIT
+ secs_attr_debug : 1, // Enclave permits debugger read/write
+ secs_attr_mode64bit : 1, // Enclave runs in 64-bit mode
+ : 1, // Reserved
+ secs_attr_provisionkey : 1, // Provisioning key
+ secs_attr_einittoken_key : 1, // EINIT token key
+ secs_attr_cet : 1, // CET attributes
+ secs_attr_kss : 1, // Key Separation and Sharing
+ : 2, // Reserved
+ secs_attr_aexnotify : 1, // Enclave threads: AEX notifications
+ : 21; // Reserved
+ // ebx
+ u32 : 32; // Reserved
+ // ecx
+ u32 xfrm_x87 : 1, // Enclave XFRM.X87
+ xfrm_sse : 1, // Enclave XFRM.SEE
+ xfrm_avx : 1, // Enclave XFRM.AVX
+ xfrm_mpx_bndregs : 1, // Enclave XFRM.BNDREGS (MPX BND0-BND3 registers)
+ xfrm_mpx_bndcsr : 1, // Enclave XFRM.BNDCSR (MPX BNDCFGU/BNDSTATUS registers)
+ xfrm_avx512_opmask : 1, // Enclave XFRM.OPMASK (AVX-512 k0-k7 registers)
+ xfrm_avx512_zmm_hi256 : 1, // Enclave XFRM.ZMM_Hi256 (AVX-512 ZMM0->ZMM7/15 registers)
+ xfrm_avx512_hi16_zmm : 1, // Enclave XFRM.HI16_ZMM (AVX-512 ZMM16->ZMM31 registers)
+ : 1, // Reserved
+ xfrm_pkru : 1, // Enclave XFRM.PKRU (XSAVE PKRU registers)
+ : 7, // Reserved
+ xfrm_tileconfig : 1, // Enclave XFRM.TILECONFIG (AMX can manage TILECONFIG)
+ xfrm_tiledata : 1, // Enclave XFRM.TILEDATA (AMX can manage TILEDATA)
+ : 13; // Reserved
+ // edx
+ u32 : 32; // Reserved
+};
+
+struct leaf_0x12_n {
+ // eax
+ u32 subleaf_type : 4, // Subleaf type
+ : 8, // Reserved
+ epc_sec_base_addr_0 : 20; // EPC section base address, bits[12:31]
+ // ebx
+ u32 epc_sec_base_addr_1 : 20, // EPC section base address, bits[32:51]
+ : 12; // Reserved
+ // ecx
+ u32 epc_sec_type : 4, // EPC section type / property encoding
+ : 8, // Reserved
+ epc_sec_size_0 : 20; // EPC section size, bits[12:31]
+ // edx
+ u32 epc_sec_size_1 : 20, // EPC section size, bits[32:51]
+ : 12; // Reserved
+};
+
+#define LEAF_0x12_SUBLEAF_N_FIRST 2
+#define LEAF_0x12_SUBLEAF_N_LAST 31
+
+/*
+ * Leaf 0x14
+ * Intel Processor Trace
+ */
+
+struct leaf_0x14_0 {
+ // eax
+ u32 pt_max_subleaf : 32; // Maximum leaf 0x14 subleaf
+ // ebx
+ u32 cr3_filtering : 1, // IA32_RTIT_CR3_MATCH is accessible
+ psb_cyc : 1, // Configurable PSB and cycle-accurate mode
+ ip_filtering : 1, // IP/TraceStop filtering; Warm-reset PT MSRs preservation
+ mtc_timing : 1, // MTC timing packet; COFI-based packets suppression
+ ptwrite : 1, // PTWRITE instruction
+ power_event_trace : 1, // Power Event Trace
+ psb_pmi_preserve : 1, // PSB and PMI preservation
+ event_trace : 1, // Event Trace packet generation
+ tnt_disable : 1, // TNT packet generation disable
+ : 23; // Reserved
+ // ecx
+ u32 topa_output : 1, // ToPA output scheme
+ topa_multiple_entries : 1, // ToPA tables can hold multiple entries
+ single_range_output : 1, // Single-range output
+ trance_transport_output : 1, // Trace Transport subsystem output
+ : 27, // Reserved
+ ip_payloads_lip : 1; // IP payloads have LIP values (CS base included)
+ // edx
+ u32 : 32; // Reserved
+};
+
+struct leaf_0x14_1 {
+ // eax
+ u32 num_address_ranges : 3, // Number of configurable Address Ranges
+ : 13, // Reserved
+ mtc_periods_bmp : 16; // MTC period encodings bitmap
+ // ebx
+ u32 cycle_thresholds_bmp : 16, // Cycle Threshold encodings bitmap
+ psb_periods_bmp : 16; // Configurable PSB frequency encodings bitmap
+ // ecx
+ u32 : 32; // Reserved
+ // edx
+ u32 : 32; // Reserved
+};
+
+/*
+ * Leaf 0x15
+ * Intel TSC (Time Stamp Counter)
+ */
+
+struct leaf_0x15_0 {
+ // eax
+ u32 tsc_denominator : 32; // Denominator of the TSC/'core crystal clock' ratio
+ // ebx
+ u32 tsc_numerator : 32; // Numerator of the TSC/'core crystal clock' ratio
+ // ecx
+ u32 cpu_crystal_hz : 32; // Core crystal clock nominal frequency, in Hz
+ // edx
+ u32 : 32; // Reserved
+};
+
+/*
+ * Leaf 0x16
+ * Intel processor frequency
+ */
+
+struct leaf_0x16_0 {
+ // eax
+ u32 cpu_base_mhz : 16, // Processor base frequency, in MHz
+ : 16; // Reserved
+ // ebx
+ u32 cpu_max_mhz : 16, // Processor max frequency, in MHz
+ : 16; // Reserved
+ // ecx
+ u32 bus_mhz : 16, // Bus reference frequency, in MHz
+ : 16; // Reserved
+ // edx
+ u32 : 32; // Reserved
+};
+
+/*
+ * Leaf 0x17
+ * Intel SoC vendor attributes
+ */
+
+struct leaf_0x17_0 {
+ // eax
+ u32 soc_max_subleaf : 32; // Maximum leaf 0x17 subleaf
+ // ebx
+ u32 soc_vendor_id : 16, // SoC vendor ID
+ is_vendor_scheme : 1, // Assigned by industry enumeration scheme (not Intel)
+ : 15; // Reserved
+ // ecx
+ u32 soc_proj_id : 32; // SoC project ID, assigned by vendor
+ // edx
+ u32 soc_stepping_id : 32; // Soc project stepping ID, assigned by vendor
+};
+
+struct leaf_0x17_n {
+ // eax
+ u32 vendor_brand_a : 32; // Vendor Brand ID string, bytes subleaf_nr * (0 -> 3)
+ // ebx
+ u32 vendor_brand_b : 32; // Vendor Brand ID string, bytes subleaf_nr * (4 -> 7)
+ // ecx
+ u32 vendor_brand_c : 32; // Vendor Brand ID string, bytes subleaf_nr * (8 -> 11)
+ // edx
+ u32 vendor_brand_d : 32; // Vendor Brand ID string, bytes subleaf_nr * (12 -> 15)
+};
+
+#define LEAF_0x17_SUBLEAF_N_FIRST 1
+#define LEAF_0x17_SUBLEAF_N_LAST 3
+
+/*
+ * Leaf 0x18
+ * Intel deterministic address translation (TLB) parameters
+ */
+
+struct leaf_0x18_n {
+ // eax
+ u32 tlb_max_subleaf : 32; // Maximum leaf 0x18 subleaf
+ // ebx
+ u32 tlb_4k_page : 1, // TLB supports 4KB-page entries
+ tlb_2m_page : 1, // TLB supports 2MB-page entries
+ tlb_4m_page : 1, // TLB supports 4MB-page entries
+ tlb_1g_page : 1, // TLB supports 1GB-page entries
+ : 4, // Reserved
+ hard_partitioning : 3, // Partitioning between logical CPUs
+ : 5, // Reserved
+ n_way_associative : 16; // Ways of associativity
+ // ecx
+ u32 n_sets : 32; // Number of sets
+ // edx
+ u32 tlb_type : 5, // Translation cache type (TLB type)
+ tlb_cache_level : 3, // Translation cache level (1-based)
+ is_fully_associative : 1, // Fully-associative
+ : 5, // Reserved
+ tlb_max_addressible_ids : 12, // Max number of addressable IDs - 1
+ : 6; // Reserved
+};
+
+#define LEAF_0x18_SUBLEAF_N_FIRST 0
+#define LEAF_0x18_SUBLEAF_N_LAST 31
+
+/*
+ * Leaf 0x19
+ * Intel key locker
+ */
+
+struct leaf_0x19_0 {
+ // eax
+ u32 kl_cpl0_only : 1, // CPL0-only key Locker restriction
+ kl_no_encrypt : 1, // No-encrypt key locker restriction
+ kl_no_decrypt : 1, // No-decrypt key locker restriction
+ : 29; // Reserved
+ // ebx
+ u32 aes_keylocker : 1, // AES key locker instructions
+ : 1, // Reserved
+ aes_keylocker_wide : 1, // AES wide key locker instructions
+ : 1, // Reserved
+ kl_msr_iwkey : 1, // Key locker MSRs and IWKEY backups
+ : 27; // Reserved
+ // ecx
+ u32 loadiwkey_no_backup : 1, // LOADIWKEY NoBackup parameter
+ iwkey_rand : 1, // IWKEY randomization
+ : 30; // Reserved
+ // edx
+ u32 : 32; // Reserved
+};
+
+/*
+ * Leaf 0x1a
+ * Intel hybrid CPUs identification (e.g. Atom, Core)
+ */
+
+struct leaf_0x1a_0 {
+ // eax
+ u32 core_native_model : 24, // This core's native model ID
+ core_type : 8; // This core's type
+ // ebx
+ u32 : 32; // Reserved
+ // ecx
+ u32 : 32; // Reserved
+ // edx
+ u32 : 32; // Reserved
+};
+
+/*
+ * Leaf 0x1b
+ * Intel PCONFIG (Platform configuration)
+ */
+
+struct leaf_0x1b_n {
+ // eax
+ u32 pconfig_subleaf_type : 12, // CPUID 0x1b subleaf type
+ : 20; // Reserved
+ // ebx
+ u32 pconfig_target_id_x : 32; // A supported PCONFIG target ID
+ // ecx
+ u32 pconfig_target_id_y : 32; // A supported PCONFIG target ID
+ // edx
+ u32 pconfig_target_id_z : 32; // A supported PCONFIG target ID
+};
+
+#define LEAF_0x1b_SUBLEAF_N_FIRST 0
+#define LEAF_0x1b_SUBLEAF_N_LAST 31
+
+/*
+ * Leaf 0x1c
+ * Intel LBR (Last Branch Record)
+ */
+
+struct leaf_0x1c_0 {
+ // eax
+ u32 lbr_depth_mask : 8, // Max LBR stack depth bitmask
+ : 22, // Reserved
+ lbr_deep_c_reset : 1, // LBRs maybe cleared on MWAIT C-state > C1
+ lbr_ip_is_lip : 1; // LBR IP contain Last IP (otherwise effective IP)
+ // ebx
+ u32 lbr_cpl : 1, // CPL filtering
+ lbr_branch_filter : 1, // Branch filtering
+ lbr_call_stack : 1, // Call-stack mode
+ : 29; // Reserved
+ // ecx
+ u32 lbr_mispredict : 1, // Branch misprediction bit
+ lbr_timed_lbr : 1, // Timed LBRs (CPU cycles since last LBR entry)
+ lbr_branch_type : 1, // Branch type field
+ : 13, // Reserved
+ lbr_events_gpc_bmp : 4, // PMU-events logging support
+ : 12; // Reserved
+ // edx
+ u32 : 32; // Reserved
+};
+
+/*
+ * Leaf 0x1d
+ * Intel AMX (Advanced Matrix Extensions) tile information
+ */
+
+struct leaf_0x1d_0 {
+ // eax
+ u32 amx_max_palette : 32; // Highest palette ID / subleaf ID
+ // ebx
+ u32 : 32; // Reserved
+ // ecx
+ u32 : 32; // Reserved
+ // edx
+ u32 : 32; // Reserved
+};
+
+struct leaf_0x1d_1 {
+ // eax
+ u32 amx_palette_size : 16, // AMX palette total tiles size, in bytes
+ amx_tile_size : 16; // AMX single tile's size, in bytes
+ // ebx
+ u32 amx_tile_row_size : 16, // AMX tile single row's size, in bytes
+ amx_palette_nr_tiles : 16; // AMX palette number of tiles
+ // ecx
+ u32 amx_tile_nr_rows : 16, // AMX tile max number of rows
+ : 16; // Reserved
+ // edx
+ u32 : 32; // Reserved
+};
+
+/*
+ * Leaf 0x1e
+ * Intel TMUL (Tile-matrix Multiply)
+ */
+
+struct leaf_0x1e_0 {
+ // eax
+ u32 : 32; // Reserved
+ // ebx
+ u32 tmul_maxk : 8, // TMUL unit maximum height, K (rows or columns)
+ tmul_maxn : 16, // TMUL unit maximum SIMD dimension, N (column bytes)
+ : 8; // Reserved
+ // ecx
+ u32 : 32; // Reserved
+ // edx
+ u32 : 32; // Reserved
+};
+
+/*
+ * Leaf 0x1f
+ * Intel extended topology v2
+ */
+
+struct leaf_0x1f_n {
+ // eax
+ u32 x2apic_id_shift : 5, // Bit width of this level (previous levels inclusive)
+ : 27; // Reserved
+ // ebx
+ u32 domain_lcpus_count : 16, // Logical CPUs count across all instances of this domain
+ : 16; // Reserved
+ // ecx
+ u32 domain_level : 8, // This domain level (subleaf ID)
+ domain_type : 8, // This domain type
+ : 16; // Reserved
+ // edx
+ u32 x2apic_id : 32; // x2APIC ID of current logical CPU
+};
+
+#define LEAF_0x1f_SUBLEAF_N_FIRST 0
+#define LEAF_0x1f_SUBLEAF_N_LAST 5
+
+/*
+ * Leaf 0x20
+ * Intel HRESET (History Reset)
+ */
+
+struct leaf_0x20_0 {
+ // eax
+ u32 hreset_nr_subleaves : 32; // CPUID 0x20 max subleaf + 1
+ // ebx
+ u32 hreset_thread_director : 1, // Intel thread director HRESET
+ : 31; // Reserved
+ // ecx
+ u32 : 32; // Reserved
+ // edx
+ u32 : 32; // Reserved
+};
+
+/*
+ * Leaf 0x21
+ * Intel TD (Trust Domain)
+ */
+
+struct leaf_0x21_0 {
+ // eax
+ u32 : 32; // Reserved
+ // ebx
+ u32 tdx_vendorid_0 : 32; // TDX vendor ID string bytes 0 - 3
+ // ecx
+ u32 tdx_vendorid_2 : 32; // CPU vendor ID string bytes 8 - 11
+ // edx
+ u32 tdx_vendorid_1 : 32; // CPU vendor ID string bytes 4 - 7
+};
+
+/*
+ * Leaf 0x23
+ * Intel Architectural Performance Monitoring Extended (ArchPerfmonExt)
+ */
+
+struct leaf_0x23_0 {
+ // eax
+ u32 subleaf_0 : 1, // Subleaf 0, this subleaf
+ counters_subleaf : 1, // Subleaf 1, PMU counter bitmaps
+ acr_subleaf : 1, // Subleaf 2, Auto Counter Reload bitmaps
+ events_subleaf : 1, // Subleaf 3, PMU event bitmaps
+ pebs_caps_subleaf : 1, // Subleaf 4, PEBS capabilities
+ pebs_subleaf : 1, // Subleaf 5, Arch PEBS bitmaps
+ : 26; // Reserved
+ // ebx
+ u32 unitmask2 : 1, // IA32_PERFEVTSELx MSRs UnitMask2 bit
+ eq : 1, // IA32_PERFEVTSELx MSRs EQ bit
+ rdpmc_user_disable : 1, // RDPMC userspace disable
+ : 29; // Reserved
+ // ecx
+ u32 : 32; // Reserved
+ // edx
+ u32 : 32; // Reserved
+};
+
+struct leaf_0x23_1 {
+ // eax
+ u32 gp_counters : 32; // Bitmap of general-purpose PMU counters
+ // ebx
+ u32 fixed_counters : 32; // Bitmap of fixed PMU counters
+ // ecx
+ u32 : 32; // Reserved
+ // edx
+ u32 : 32; // Reserved
+};
+
+struct leaf_0x23_2 {
+ // eax
+ u32 acr_gp_reload : 32; // Bitmap of general-purpose counters that can be reloaded
+ // ebx
+ u32 acr_fixed_reload : 32; // Bitmap of fixed counters that can be reloaded
+ // ecx
+ u32 acr_gp_trigger : 32; // Bitmap of general-purpose counters that can trigger reloads
+ // edx
+ u32 acr_fixed_trigger : 32; // Bitmap of fixed counters that can trigger reloads
+};
+
+struct leaf_0x23_3 {
+ // eax
+ u32 core_cycles_evt : 1, // Core cycles event
+ insn_retired_evt : 1, // Instructions retired event
+ ref_cycles_evt : 1, // Reference cycles event
+ llc_refs_evt : 1, // Last-level cache references event
+ llc_misses_evt : 1, // Last-level cache misses event
+ br_insn_ret_evt : 1, // Branch instruction retired event
+ br_mispr_evt : 1, // Branch mispredict retired event
+ td_slots_evt : 1, // Topdown slots event
+ td_backend_bound_evt : 1, // Topdown backend bound event
+ td_bad_spec_evt : 1, // Topdown bad speculation event
+ td_frontend_bound_evt : 1, // Topdown frontend bound event
+ td_retiring_evt : 1, // Topdown retiring event
+ : 20; // Reserved
+ // ebx
+ u32 : 32; // Reserved
+ // ecx
+ u32 : 32; // Reserved
+ // edx
+ u32 : 32; // Reserved
+};
+
+struct leaf_0x23_4 {
+ // eax
+ u32 : 32; // Reserved
+ // ebx
+ u32 : 3, // Reserved
+ allow_in_record : 1, // ALLOW_IN_RECORD bit in MSRs
+ counters_gp : 1, // Counters group sub-group general-purpose counters
+ counters_fixed : 1, // Counters group sub-group fixed-function counters
+ counters_metrics : 1, // Counters group sub-group performance metrics
+ : 1, // Reserved
+ lbr : 2, // LBR group
+ : 6, // Reserved
+ xer : 8, // XER group
+ : 5, // Reserved
+ gpr : 1, // GPR group
+ aux : 1, // AUX group
+ : 1; // Reserved
+ // ecx
+ u32 : 32; // Reserved
+ // edx
+ u32 : 32; // Reserved
+};
+
+struct leaf_0x23_5 {
+ // eax
+ u32 pebs_gp : 32; // Architectural PEBS general-purpose counters
+ // ebx
+ u32 pebs_pdist_gp : 32; // Architectural PEBS PDIST general-purpose counters
+ // ecx
+ u32 pebs_fixed : 32; // Architectural PEBS fixed counters
+ // edx
+ u32 pebs_pdist_fixed : 32; // Architectural PEBS PDIST fixed counters
+};
+
+/*
+ * Leaf 0x40000000
+ * Maximum hypervisor leaf + hypervisor vendor string
+ */
+
+struct leaf_0x40000000_0 {
+ // eax
+ u32 max_hyp_leaf : 32; // Maximum hypervisor leaf
+ // ebx
+ u32 hypervisor_id_0 : 32; // Hypervisor ID string bytes 0 - 3
+ // ecx
+ u32 hypervisor_id_1 : 32; // Hypervisor ID string bytes 4 - 7
+ // edx
+ u32 hypervisor_id_2 : 32; // Hypervisor ID string bytes 8 - 11
+};
+
+/*
+ * Leaf 0x4c780001
+ * Linux-defined synthetic feature flags
+ */
+
+struct leaf_0x4c780001_0 {
+ // eax
+ u32 cxmmx : 1, // Cyrix MMX extensions
+ k6_mtrr : 1, // AMD K6 nonstandard MTRRs
+ cyrix_arr : 1, // Cyrix ARRs (= MTRRs)
+ centaur_mcr : 1, // Centaur MCRs (= MTRRs)
+ k8 : 1, // Opteron, Athlon64
+ zen5 : 1, // CPU based on Zen5 micro-architecture
+ zen6 : 1, // CPU based on Zen6 micro-architecture
+ : 1, // Reserved
+ constant_tsc : 1, // TSC ticks at a constant rate
+ up : 1, // SMP kernel running on UP
+ art : 1, // Always running timer (ART)
+ arch_perfmon : 1, // Intel Architectural PerfMon
+ pebs : 1, // Precise-Event Based Sampling
+ bts : 1, // Branch Trace Store
+ syscall32 : 1, // SYSCALL in IA32 userspace
+ sysenter32 : 1, // SYSENTER in IA32 userspace
+ rep_good : 1, // REP microcode works well
+ amd_lbr_v2 : 1, // AMD Last Branch Record Extension version 2
+ clear_cpu_buf : 1, // Clear CPU buffers using VERW
+ acc_power : 1, // AMD Accumulated Power Mechanism
+ nopl : 1, // The NOPL instructions
+ always : 1, // Always-present feature
+ xtopology : 1, // CPU topology enumeration extensions
+ tsc_reliable : 1, // TSC is known to be reliable
+ nonstop_tsc : 1, // TSC does not stop in C states
+ cpuid : 1, // CPU has the CPUID instruction
+ extd_apicid : 1, // Extended APIC ID (8 bits)
+ amd_dcm : 1, // AMD multi-node processor
+ aperfmperf : 1, // APERF/MPERF MSRs: P-State hardware coordination feedback
+ rapl : 1, // AMD/Hygon RAPL interface
+ nonstop_tsc_s3 : 1, // TSC does not stop in S3 state
+ tsc_known_freq : 1; // TSC has known frequency
+ // ebx
+ u32 ring3mwait : 1, // Ring 3 MONITOR/MWAIT instructions
+ cpuid_fault : 1, // Intel CPUID faulting
+ cpb : 1, // AMD Core Performance Boost
+ epb : 1, // IA32_ENERGY_PERF_BIAS support
+ cat_l3 : 1, // Cache Allocation Technology L3
+ cat_l2 : 1, // Cache Allocation Technology L2
+ cdp_l3 : 1, // Code and Data Prioritization L3
+ tdx_host_platform : 1, // Platform supports being a TDX host
+ hw_pstate : 1, // AMD Hardware P-state control
+ proc_feedback : 1, // AMD Processor Feedback Interface
+ xcompacted : 1, // Use compacted XSTATE (XSAVES or XSAVEC)
+ pti : 1, // Kernel Page Table Isolation enabled
+ kernel_ibrs : 1, // Set/clear IBRS on kernel entry/exit
+ rsb_vmexit : 1, // Fill RSB on VM-Exit
+ intel_ppin : 1, // Intel Processor Inventory Number
+ cdp_l2 : 1, // Code and Data Prioritization L2
+ msr_spec_ctrl : 1, // MSR SPEC_CTRL is implemented
+ ssbd : 1, // Speculative Store Bypass Disable
+ mba : 1, // Memory Bandwidth Allocation
+ rsb_ctxsw : 1, // Fill RSB on context switches
+ perfmon_v2 : 1, // AMD Performance Monitoring Version 2
+ : 1, // Reserved
+ use_ibrs_fw : 1, // Use IBRS during runtime firmware calls
+ ss_bypass_disable : 1, // Disable Speculative Store Bypass
+ ls_cfg_ssbd : 1, // AMD SSBD implementation via LS_CFG MSR
+ ibrs : 1, // Indirect Branch Restricted Speculation
+ ibpb : 1, // Indirect Branch Prediction Barrier (without RSB flush guarantee)
+ stibp : 1, // Single Thread Indirect Branch Predictors
+ zen : 1, // Generic flag for all Zen and newer
+ l1tf_pteinv : 1, // L1TF workaround PTE inversion
+ ibrs_enhanced : 1, // Enhanced IBRS
+ msr_ia32_feat_ctl : 1; // MSR IA32_FEAT_CTL configured
+ // ecx
+ u32 tpr_shadow : 1, // Intel TPR Shadow
+ flexpriority : 1, // Intel FlexPriority
+ ept : 1, // Intel Extended Page Table
+ vpid : 1, // Intel Virtual Processor ID
+ coherency_sfw_no : 1, // SNP cache coherency software work around not needed
+ : 10, // Reserved
+ vmmcall : 1, // Prefer VMMCALL to VMCALL
+ xenpv : 1, // Xen paravirtual guest
+ ept_ad : 1, // Intel Extended Page Table access-dirty bit
+ VMCALL : 1, // Hypervisor supports the VMCALL instruction
+ vmw_vmmcall : 1, // VMware prefers the VMMCALL instruction
+ pvunlock : 1, // PV unlock function
+ vcpupreempt : 1, // PV vcpu_is_preempted function
+ tdx_guest : 1, // Intel Trust Domain Extensions Guest
+ : 9; // Reserved
+ // edx
+ u32 cqm_llc : 1, // LLC QoS
+ cqm_occup_llc : 1, // LLC occupancy monitoring
+ cqm_mbm_total : 1, // LLC Total MBM monitoring
+ cqm_mbm_local : 1, // LLC Local MBM monitoring
+ fence_swapgs_user : 1, // LFENCE in user entry SWAPGS path
+ fence_swapgs_kernel : 1, // LFENCE in kernel entry SWAPGS path
+ split_lock_detect : 1, // #AC for split lock
+ per_thread_mba : 1, // Per-thread Memory Bandwidth Allocation
+ sgx1 : 1, // SGX Basic
+ sgx2 : 1, // SGX Enclave Dynamic Memory Management (EDMM)
+ entry_ibpb : 1, // Issue an IBPB on kernel entry
+ rrsba_ctrl : 1, // RET prediction control
+ retpoline : 1, // Generic Retpoline mitigation for Spectre variant 2
+ retpoline_lfence : 1, // Use LFENCE for Spectre variant 2
+ rethunk : 1, // Use Return THUNK
+ unret : 1, // AMD BTB untrain return
+ use_ibpb_fw : 1, // Use IBPB during runtime firmware calls
+ rsb_vmexit_lite : 1, // Fill RSB on VM exit when EIBRS is enabled
+ sgx_edeccssa : 1, // SGX EDECCSSA user leaf function
+ call_depth : 1, // Call depth tracking for RSB stuffing
+ msr_tsx_ctrl : 1, // MSR IA32_TSX_CTRL (Intel) implemented
+ smba : 1, // Slow Memory Bandwidth Allocation
+ bmec : 1, // Bandwidth Monitoring Event Configuration
+ user_shstk : 1, // Shadow stack support for user mode applications
+ srso : 1, // AMD BTB untrain RETs
+ srso_alias : 1, // AMD BTB untrain RETs through aliasing
+ ibpb_on_vmexit : 1, // Issue an IBPB only on VMEXIT
+ apic_msrs_fence : 1, // IA32_TSC_DEADLINE and X2APIC MSRs need fencing
+ zen2 : 1, // CPU based on Zen2 microarchitecture
+ zen3 : 1, // CPU based on Zen3 microarchitecture
+ zen4 : 1, // CPU based on Zen4 microarchitecture
+ zen1 : 1; // CPU based on Zen1 microarchitecture
+};
+
+struct leaf_0x4c780001_1 {
+ // eax
+ u32 overflow_recov : 1, // MCA overflow recovery support
+ succor : 1, // Uncorrectable error containment and recovery
+ : 1, // Reserved
+ smca : 1, // Scalable MCA
+ : 28; // Reserved
+ // ebx
+ u32 amd_lbr_pmc_freeze : 1, // AMD LBR and PMC Freeze
+ clear_bhb_loop : 1, // Clear branch history at SYSCALL entry using SW loop
+ bhi_ctrl : 1, // BHI_DIS_S HW control available
+ clear_bhb_hw : 1, // BHI_DIS_S HW control enabled
+ clear_bhb_vmexit : 1, // Clear branch history at VMEXIT using SW loop
+ amd_fast_cppc : 1, // AMD fast Collaborative Processor Performance Control
+ amd_htr_cores : 1, // Heterogeneous Core Topology
+ amd_workload_class : 1, // Workload Classification
+ prefer_ymm : 1, // Avoid ZMM registers due to downclocking
+ apx : 1, // Advanced Performance Extensions
+ indirect_thunk_its : 1, // Use thunk for indirect branches in lower half of cache line
+ tsa_sq_no : 1, // AMD CPU not vulnerable to TSA-SQ
+ tsa_l1_no : 1, // AMD CPU not vulnerable to TSA-L1
+ clear_cpu_buf_vm : 1, // Clear CPU buffers using VERW before VMRUN
+ ibpb_exit_to_user : 1, // Use IBPB on exit-to-userspace, see VMSCAPE bug
+ : 17; // Reserved
+ // ecx
+ u32 : 32; // Reserved
+ // edx
+ u32 : 32; // Reserved
+};
+
+/*
+ * Leaf 0x4c780002
+ * Linux-defined synthetic CPU bug flags
+ */
+
+struct leaf_0x4c780002_0 {
+ // eax
+ u32 f00f : 1, // Intel F00F
+ fdiv : 1, // FPU FDIV
+ coma : 1, // Cyrix 6x86 coma
+ amd_tlb_mmatch : 1, // AMD Erratum 383
+ amd_apic_c1e : 1, // AMD Erratum 400
+ bug_11ap : 1, // Bad local APIC aka 11AP
+ fxsave_leak : 1, // FXSAVE leaks FOP/FIP/FOP
+ clflush_monitor : 1, // AAI65, CLFLUSH required before MONITOR
+ sysret_ss_attrs : 1, // SYSRET does not fix up SS attributes
+ espfix : 1, // IRET to 16-bit SS corrupts ESP/RSP high bits (x86-32)
+ null_seg : 1, // Setting a selector to NULL preserves the base
+ swapgs_fence : 1, // SWAPGS without input dep on GS
+ monitor : 1, // IPI required to wake up remote CPU
+ amd_e400 : 1, // CPU is among the affected by Erratum 400
+ cpu_meltdown : 1, // CPU affected by meltdown; needs kernel page table isolation
+ spectre_v1 : 1, // CPU affected by Spectre variant 1 with conditional branches
+ specture_v2 : 1, // CPU affected by Spectre variant 2 with indirect branches
+ spec_store_bypass : 1, // CPU affected by speculative store bypass attack
+ l1tf : 1, // CPU affected by L1 Terminal Fault
+ mds : 1, // CPU affected by Microarchitectural data sampling
+ msbds_only : 1, // Microarchitectural data sampling: CPU only affected by the MSDBS variant
+ swapgs : 1, // CPU affected by speculation through SWAPGS
+ taa : 1, // CPU is affected by TSX Async Abort (TAA)
+ itlb_multihit : 1, // CPU may incur MCE during certain page attribute changes
+ srbds : 1, // CPU may leak RNG bits if not mitigated
+ mmio_stale_data : 1, // CPU affected by Processor MMIO Stale Data vulnerabilities
+ : 1, // Reserved
+ retbleed : 1, // CPU affected by Retbleed
+ eibrs_pbrsb : 1, // EIBRS is vulnerable to Post Barrier RSB Predictions
+ smt_rsb : 1, // CPU vulnerable to Cross-Thread Return Address Predictions
+ gds : 1, // CPU affected by Gather Data Sampling
+ tdx_pw_mce : 1; // CPU may incur #MC if non-TD software does partial write to TDX private memory
+ // ebx
+ u32 srso : 1, // AMD SRSO bug
+ div0 : 1, // AMD DIV0 speculation bug
+ rfds : 1, // CPU vulnerable to Register File Data Sampling
+ bhi : 1, // CPU affected by Branch History Injection
+ ibpb_no_ret : 1, // IBPB omits return target predictions
+ spectre_v2_user : 1, // CPU affected by Spectre variant 2 between user processes
+ old_microcode : 1, // CPU has old microcode; it must be vulnerable to something
+ its : 1, // CPU affected by Indirect Target Selection
+ its_native_only : 1, // CPU affected by ITS; VMX is not affected
+ tsa : 1, // CPU affected by Transient Scheduler Attacks
+ vmscape : 1, // CPU affected by VMSCAPE attacks from guests
+ : 21; // Reserved
+ // ecx
+ u32 : 32; // Reserved
+ // edx
+ u32 : 32; // Reserved
+};
+
+/*
+ * Leaf 0x80000000
+ * Maximum extended leaf + CPU vendor string
+ */
+
+struct leaf_0x80000000_0 {
+ // eax
+ u32 max_ext_leaf : 32; // Maximum extended CPUID leaf
+ // ebx
+ u32 cpu_vendorid_0 : 32; // Vendor ID string bytes 0 - 3
+ // ecx
+ u32 cpu_vendorid_2 : 32; // Vendor ID string bytes 8 - 11
+ // edx
+ u32 cpu_vendorid_1 : 32; // Vendor ID string bytes 4 - 7
+};
+
+/*
+ * Leaf 0x80000001
+ * Extended CPU features
+ */
+
+struct leaf_0x80000001_0 {
+ // eax
+ u32 e_stepping_id : 4, // Stepping ID
+ e_base_model : 4, // Base processor model
+ e_base_family : 4, // Base processor family
+ e_base_type : 2, // Base processor type (Transmeta)
+ : 2, // Reserved
+ e_ext_model : 4, // Extended processor model
+ e_ext_family : 8, // Extended processor family
+ : 4; // Reserved
+ // ebx
+ u32 brand_id : 16, // Brand ID
+ : 12, // Reserved
+ pkg_type : 4; // Package type
+ // ecx
+ u32 lahf_lm : 1, // LAHF and SAHF in 64-bit mode
+ cmp_legacy : 1, // Multi-processing legacy mode (No HT)
+ svm : 1, // Secure Virtual Machine
+ extapic : 1, // Extended APIC space
+ cr8_legacy : 1, // LOCK MOV CR0 means MOV CR8
+ lzcnt_abm : 1, // LZCNT advanced bit manipulation
+ sse4a : 1, // SSE4A support
+ misaligned_sse : 1, // Misaligned SSE mode
+ _3dnow_prefetch : 1, // 3DNow PREFETCH/PREFETCHW support
+ osvw : 1, // OS visible workaround
+ ibs : 1, // Instruction based sampling
+ xop : 1, // XOP: extended operation (AVX instructions)
+ skinit : 1, // SKINIT/STGI support
+ wdt : 1, // Watchdog timer support
+ : 1, // Reserved
+ lwp : 1, // Lightweight profiling
+ fma4 : 1, // 4-operand FMA instruction
+ tce : 1, // Translation cache extension
+ : 1, // Reserved
+ nodeid_msr : 1, // NodeId MSR (0xc001100c)
+ : 1, // Reserved
+ tbm : 1, // Trailing bit manipulations
+ topoext : 1, // Topology Extensions (leaf 0x8000001d)
+ perfctr_core : 1, // Core performance counter extensions
+ perfctr_nb : 1, // NB/DF performance counter extensions
+ : 1, // Reserved
+ data_bp_ext : 1, // Data access breakpoint extension
+ perf_tsc : 1, // Performance time-stamp counter
+ perfctr_llc : 1, // LLC (L3) performance counter extensions
+ mwaitx : 1, // MWAITX/MONITORX support
+ addr_mask_ext : 1, // Breakpoint address mask extension (to bit 31)
+ : 1; // Reserved
+ // edx
+ u32 e_fpu : 1, // Floating-Point Unit on-chip (x87)
+ e_vme : 1, // Virtual-8086 Mode Extensions
+ e_de : 1, // Debugging Extensions
+ e_pse : 1, // Page Size Extension
+ e_tsc : 1, // Time Stamp Counter
+ e_msr : 1, // Model-Specific Registers (RDMSR and WRMSR support)
+ pae : 1, // Physical Address Extensions
+ mce : 1, // Machine Check Exception
+ cx8 : 1, // CMPXCHG8B instruction
+ apic : 1, // APIC on-chip
+ : 1, // Reserved
+ syscall : 1, // SYSCALL and SYSRET instructions
+ mtrr : 1, // Memory Type Range Registers
+ pge : 1, // Page Global Extensions
+ mca : 1, // Machine Check Architecture
+ cmov : 1, // Conditional Move Instruction
+ pat : 1, // Page Attribute Table
+ pse36 : 1, // Page Size Extension (36-bit)
+ : 1, // Reserved
+ obsolete_mp_bit : 1, // Out-of-spec AMD Multiprocessing bit
+ nx : 1, // No-execute page protection
+ : 1, // Reserved
+ mmxext : 1, // AMD MMX extensions
+ e_mmx : 1, // MMX instructions
+ e_fxsr : 1, // FXSAVE and FXRSTOR instructions
+ fxsr_opt : 1, // FXSAVE and FXRSTOR optimizations
+ page1gb : 1, // 1-GB large page support
+ rdtscp : 1, // RDTSCP instruction
+ : 1, // Reserved
+ lm : 1, // Long mode (x86-64, 64-bit support)
+ _3dnowext : 1, // AMD 3DNow extensions
+ _3dnow : 1; // 3DNow instructions
+};
+
+/*
+ * Leaf 0x80000002
+ * CPU brand ID string, bytes 0 - 15
+ */
+
+struct leaf_0x80000002_0 {
+ // eax
+ u32 cpu_brandid_0 : 32; // CPU brand ID string, bytes 0 - 3
+ // ebx
+ u32 cpu_brandid_1 : 32; // CPU brand ID string, bytes 4 - 7
+ // ecx
+ u32 cpu_brandid_2 : 32; // CPU brand ID string, bytes 8 - 11
+ // edx
+ u32 cpu_brandid_3 : 32; // CPU brand ID string, bytes 12 - 15
+};
+
+/*
+ * Leaf 0x80000003
+ * CPU brand ID string, bytes 16 - 31
+ */
+
+struct leaf_0x80000003_0 {
+ // eax
+ u32 cpu_brandid_4 : 32; // CPU brand ID string bytes, 16 - 19
+ // ebx
+ u32 cpu_brandid_5 : 32; // CPU brand ID string bytes, 20 - 23
+ // ecx
+ u32 cpu_brandid_6 : 32; // CPU brand ID string bytes, 24 - 27
+ // edx
+ u32 cpu_brandid_7 : 32; // CPU brand ID string bytes, 28 - 31
+};
+
+/*
+ * Leaf 0x80000004
+ * CPU brand ID string, bytes 32 - 47
+ */
+
+struct leaf_0x80000004_0 {
+ // eax
+ u32 cpu_brandid_8 : 32; // CPU brand ID string, bytes 32 - 35
+ // ebx
+ u32 cpu_brandid_9 : 32; // CPU brand ID string, bytes 36 - 39
+ // ecx
+ u32 cpu_brandid_10 : 32; // CPU brand ID string, bytes 40 - 43
+ // edx
+ u32 cpu_brandid_11 : 32; // CPU brand ID string, bytes 44 - 47
+};
+
+/*
+ * Leaf 0x80000005
+ * AMD/Transmeta L1 cache and TLB
+ */
+
+struct leaf_0x80000005_0 {
+ // eax
+ u32 l1_itlb_2m_4m_nentries : 8, // L1 ITLB #entries, 2M and 4M pages
+ l1_itlb_2m_4m_assoc : 8, // L1 ITLB associativity, 2M and 4M pages
+ l1_dtlb_2m_4m_nentries : 8, // L1 DTLB #entries, 2M and 4M pages
+ l1_dtlb_2m_4m_assoc : 8; // L1 DTLB associativity, 2M and 4M pages
+ // ebx
+ u32 l1_itlb_4k_nentries : 8, // L1 ITLB #entries, 4K pages
+ l1_itlb_4k_assoc : 8, // L1 ITLB associativity, 4K pages
+ l1_dtlb_4k_nentries : 8, // L1 DTLB #entries, 4K pages
+ l1_dtlb_4k_assoc : 8; // L1 DTLB associativity, 4K pages
+ // ecx
+ u32 l1_dcache_line_size : 8, // L1 dcache line size, in bytes
+ l1_dcache_nlines : 8, // L1 dcache lines per tag
+ l1_dcache_assoc : 8, // L1 dcache associativity
+ l1_dcache_size_kb : 8; // L1 dcache size, in KB
+ // edx
+ u32 l1_icache_line_size : 8, // L1 icache line size, in bytes
+ l1_icache_nlines : 8, // L1 icache lines per tag
+ l1_icache_assoc : 8, // L1 icache associativity
+ l1_icache_size_kb : 8; // L1 icache size, in KB
+};
+
+/*
+ * Leaf 0x80000006
+ * (Mostly AMD) L2/L3 cache and TLB
+ */
+
+struct leaf_0x80000006_0 {
+ // eax
+ u32 l2_itlb_2m_4m_nentries : 12, // L2 iTLB #entries, 2M and 4M pages
+ l2_itlb_2m_4m_assoc : 4, // L2 iTLB associativity, 2M and 4M pages
+ l2_dtlb_2m_4m_nentries : 12, // L2 dTLB #entries, 2M and 4M pages
+ l2_dtlb_2m_4m_assoc : 4; // L2 dTLB associativity, 2M and 4M pages
+ // ebx
+ u32 l2_itlb_4k_nentries : 12, // L2 iTLB #entries, 4K pages
+ l2_itlb_4k_assoc : 4, // L2 iTLB associativity, 4K pages
+ l2_dtlb_4k_nentries : 12, // L2 dTLB #entries, 4K pages
+ l2_dtlb_4k_assoc : 4; // L2 dTLB associativity, 4K pages
+ // ecx
+ u32 l2_line_size : 8, // L2 cache line size, in bytes
+ l2_nlines : 4, // L2 cache number of lines per tag
+ l2_assoc : 4, // L2 cache associativity
+ l2_size_kb : 16; // L2 cache size, in KB
+ // edx
+ u32 l3_line_size : 8, // L3 cache line size, in bytes
+ l3_nlines : 4, // L3 cache number of lines per tag
+ l3_assoc : 4, // L3 cache associativity
+ : 2, // Reserved
+ l3_size_range : 14; // L3 cache size range
+};
+
+/*
+ * Leaf 0x80000007
+ * CPU power management (mostly AMD) and AMD RAS
+ */
+
+struct leaf_0x80000007_0 {
+ // eax
+ u32 : 32; // Reserved
+ // ebx
+ u32 mca_overflow_recovery : 1, // MCA overflow conditions not fatal
+ succor : 1, // Software containment of uncorrectable errors
+ hw_assert : 1, // Hardware assert MSRs
+ scalable_mca : 1, // Scalable MCA (MCAX MSRs)
+ : 28; // Reserved
+ // ecx
+ u32 cpu_pwr_sample_ratio : 32; // CPU power sample time ratio
+ // edx
+ u32 digital_temp : 1, // Digital temperature sensor
+ powernow_freq_id : 1, // PowerNOW! frequency scaling
+ powernow_volt_id : 1, // PowerNOW! voltage scaling
+ thermal_trip : 1, // THERMTRIP (Thermal Trip)
+ hw_thermal_control : 1, // Hardware thermal control
+ sw_thermal_control : 1, // Software thermal control
+ _100mhz_steps : 1, // 100 MHz multiplier control
+ hw_pstate : 1, // Hardware P-state control
+ constant_tsc : 1, // TSC ticks at constant rate across all P and C states
+ core_perf_boost : 1, // Core performance boost
+ eff_freq_ro : 1, // Read-only effective frequency interface
+ proc_feedback : 1, // Processor feedback interface (deprecated)
+ proc_power_reporting : 1, // Processor power reporting interface
+ connected_standby : 1, // CPU Connected Standby support
+ rapl_interface : 1, // Runtime Average Power Limit interface
+ : 17; // Reserved
+};
+
+/*
+ * Leaf 0x80000008
+ * CPU capacity parameters and extended feature flags (mostly AMD)
+ */
+
+struct leaf_0x80000008_0 {
+ // eax
+ u32 phys_addr_bits : 8, // Max physical address bits
+ virt_addr_bits : 8, // Max virtual address bits
+ guest_phys_addr_bits : 8, // Max nested-paging guest physical address bits
+ : 8; // Reserved
+ // ebx
+ u32 clzero : 1, // CLZERO instruction
+ insn_retired_perf : 1, // Instruction retired counter MSR
+ xsave_err_ptr : 1, // XSAVE/XRSTOR always saves/restores FPU error pointers
+ invlpgb : 1, // INVLPGB broadcasts a TLB invalidate
+ rdpru : 1, // RDPRU (Read Processor Register at User level)
+ : 1, // Reserved
+ mba : 1, // Memory Bandwidth Allocation (AMD bit)
+ : 1, // Reserved
+ mcommit : 1, // MCOMMIT instruction
+ wbnoinvd : 1, // WBNOINVD instruction
+ : 2, // Reserved
+ ibpb : 1, // Indirect Branch Prediction Barrier
+ wbinvd_int : 1, // Interruptible WBINVD/WBNOINVD
+ ibrs : 1, // Indirect Branch Restricted Speculation
+ stibp : 1, // Single Thread Indirect Branch Prediction mode
+ ibrs_always_on : 1, // IBRS always-on preferred
+ stibp_always_on : 1, // STIBP always-on preferred
+ ibrs_fast : 1, // IBRS is preferred over software solution
+ ibrs_same_mode : 1, // IBRS provides same mode protection
+ no_efer_lmsle : 1, // Long-Mode Segment Limit Enable unsupported
+ tlb_flush_nested : 1, // INVLPGB RAX[5] bit can be set
+ : 1, // Reserved
+ amd_ppin : 1, // Protected Processor Inventory Number
+ amd_ssbd : 1, // Speculative Store Bypass Disable
+ virt_ssbd : 1, // virtualized SSBD (Speculative Store Bypass Disable)
+ amd_ssb_no : 1, // SSBD is not needed (fixed in hardware)
+ cppc : 1, // Collaborative Processor Performance Control
+ amd_psfd : 1, // Predictive Store Forward Disable
+ btc_no : 1, // CPU not affected by Branch Type Confusion
+ ibpb_ret : 1, // IBPB clears RSB/RAS too
+ branch_sampling : 1; // Branch Sampling
+ // ecx
+ u32 cpu_nthreads : 8, // Number of physical threads - 1
+ : 4, // Reserved
+ apicid_coreid_len : 4, // Number of thread core ID bits (shift) in APIC ID
+ perf_tsc_len : 2, // Performance time-stamp counter size
+ : 14; // Reserved
+ // edx
+ u32 invlpgb_max_pages : 16, // INVLPGB maximum page count
+ rdpru_max_reg_id : 16; // RDPRU max register ID (ECX input)
+};
+
+/*
+ * Leaf 0x8000000a
+ * AMD SVM (Secure Virtual Machine)
+ */
+
+struct leaf_0x8000000a_0 {
+ // eax
+ u32 svm_version : 8, // SVM revision number
+ : 24; // Reserved
+ // ebx
+ u32 svm_nasid : 32; // Number of address space identifiers (ASID)
+ // ecx
+ u32 : 4, // Reserved
+ pml : 1, // Page Modification Logging (PML)
+ : 27; // Reserved
+ // edx
+ u32 nested_pt : 1, // Nested paging
+ lbr_virt : 1, // LBR virtualization
+ svm_lock : 1, // SVM lock
+ nrip_save : 1, // NRIP save support on #VMEXIT
+ tsc_rate_msr : 1, // MSR based TSC rate control
+ vmcb_clean : 1, // VMCB clean bits support
+ flush_by_asid : 1, // Flush by ASID + Extended VMCB TLB_Control
+ decode_assists : 1, // Decode Assists support
+ : 2, // Reserved
+ pause_filter : 1, // Pause intercept filter
+ : 1, // Reserved
+ pf_threshold : 1, // Pause filter threshold
+ avic : 1, // Advanced virtual interrupt controller
+ : 1, // Reserved
+ v_vmsave_vmload : 1, // Virtual VMSAVE/VMLOAD (nested virtualization)
+ v_gif : 1, // Virtualize the Global Interrupt Flag
+ gmet : 1, // Guest mode execution trap
+ x2avic : 1, // Virtual x2APIC
+ sss_check : 1, // Supervisor Shadow Stack restrictions
+ v_spec_ctrl : 1, // Virtual SPEC_CTRL
+ ro_gpt : 1, // Read-Only guest page table support
+ : 1, // Reserved
+ h_mce_override : 1, // Host MCE override
+ tlbsync_int : 1, // TLBSYNC intercept + INVLPGB/TLBSYNC in VMCB
+ nmi_virt : 1, // NMI virtualization
+ ibs_virt : 1, // IBS Virtualization
+ ext_lvt_off_chg : 1, // Extended LVT offset fault change
+ svme_addr_chk : 1, // Guest SVME address check
+ : 3; // Reserved
+};
+
+/*
+ * Leaf 0x80000019
+ * AMD TLB characteristics for 1GB pages
+ */
+
+struct leaf_0x80000019_0 {
+ // eax
+ u32 l1_itlb_1g_nentries : 12, // L1 iTLB #entries, 1G pages
+ l1_itlb_1g_assoc : 4, // L1 iTLB associativity, 1G pages
+ l1_dtlb_1g_nentries : 12, // L1 dTLB #entries, 1G pages
+ l1_dtlb_1g_assoc : 4; // L1 dTLB associativity, 1G pages
+ // ebx
+ u32 l2_itlb_1g_nentries : 12, // L2 iTLB #entries, 1G pages
+ l2_itlb_1g_assoc : 4, // L2 iTLB associativity, 1G pages
+ l2_dtlb_1g_nentries : 12, // L2 dTLB #entries, 1G pages
+ l2_dtlb_1g_assoc : 4; // L2 dTLB associativity, 1G pages
+ // ecx
+ u32 : 32; // Reserved
+ // edx
+ u32 : 32; // Reserved
+};
+
+/*
+ * Leaf 0x8000001a
+ * AMD instruction optimizations
+ */
+
+struct leaf_0x8000001a_0 {
+ // eax
+ u32 fp_128 : 1, // Internal FP/SIMD exec data path is 128-bits wide
+ movu_preferred : 1, // SSE: MOVU* better than MOVL*/MOVH*
+ fp_256 : 1, // internal FP/SSE exec data path is 256-bits wide
+ : 29; // Reserved
+ // ebx
+ u32 : 32; // Reserved
+ // ecx
+ u32 : 32; // Reserved
+ // edx
+ u32 : 32; // Reserved
+};
+
+/*
+ * Leaf 0x8000001b
+ * AMD IBS (Instruction-Based Sampling)
+ */
+
+struct leaf_0x8000001b_0 {
+ // eax
+ u32 ibs_flags : 1, // IBS feature flags
+ ibs_fetch_sampling : 1, // IBS fetch sampling
+ ibs_op_sampling : 1, // IBS execution sampling
+ ibs_rdwr_op_counter : 1, // IBS read/write of op counter
+ ibs_op_count : 1, // IBS OP counting mode
+ ibs_branch_target : 1, // IBS branch target address reporting
+ ibs_op_counters_ext : 1, // IBS IbsOpCurCnt/IbsOpMaxCnt extend by 7 bits
+ ibs_rip_invalid_chk : 1, // IBS invalid RIP indication
+ ibs_op_branch_fuse : 1, // IBS fused branch micro-op indication
+ ibs_fetch_ctl_ext : 1, // IBS Fetch Control Extended MSR
+ ibs_op_data_4 : 1, // IBS op data 4 MSR
+ ibs_l3_miss_filter : 1, // IBS L3-miss filtering (Zen4+)
+ : 20; // Reserved
+ // ebx
+ u32 : 32; // Reserved
+ // ecx
+ u32 : 32; // Reserved
+ // edx
+ u32 : 32; // Reserved
+};
+
+/*
+ * Leaf 0x8000001c
+ * AMD LWP (Lightweight Profiling)
+ */
+
+struct leaf_0x8000001c_0 {
+ // eax
+ u32 os_lwp_avail : 1, // OS: LWP is available to application programs
+ os_lpwval : 1, // OS: LWPVAL instruction
+ os_lwp_ire : 1, // OS: Instructions Retired Event
+ os_lwp_bre : 1, // OS: Branch Retired Event
+ os_lwp_dme : 1, // OS: Dcache Miss Event
+ os_lwp_cnh : 1, // OS: CPU Clocks Not Halted event
+ os_lwp_rnh : 1, // OS: CPU Reference clocks Not Halted event
+ : 22, // Reserved
+ os_lwp_cont : 1, // OS: LWP sampling in continuous mode
+ os_lwp_ptsc : 1, // OS: Performance Time Stamp Counter in event records
+ os_lwp_int : 1; // OS: Interrupt on threshold overflow
+ // ebx
+ u32 lwp_lwpcb_sz : 8, // Control Block size, in quadwords
+ lwp_event_sz : 8, // Event record size, in bytes
+ lwp_max_events : 8, // Max EventID supported
+ lwp_event_offset : 8; // Control Block events area offset
+ // ecx
+ u32 lwp_latency_max : 5, // Cache latency counters number of bits
+ lwp_data_addr : 1, // Cache miss events report data cache address
+ lwp_latency_rnd : 3, // Cache latency rounding amount
+ lwp_version : 7, // LWP version
+ lwp_buf_min_sz : 8, // LWP event ring buffer min size, 32 event records units
+ : 4, // Reserved
+ lwp_branch_predict : 1, // Branches Retired events can be filtered
+ lwp_ip_filtering : 1, // IP filtering (IPI, IPF, BaseIP, and LimitIP @ LWPCP)
+ lwp_cache_levels : 1, // Cache-related events: filter by cache level
+ lwp_cache_latency : 1; // Cache-related events: filter by latency
+ // edx
+ u32 hw_lwp_avail : 1, // HW: LWP available
+ hw_lpwval : 1, // HW: LWPVAL available
+ hw_lwp_ire : 1, // HW: Instructions Retired Event
+ hw_lwp_bre : 1, // HW: Branch Retired Event
+ hw_lwp_dme : 1, // HW: Dcache Miss Event
+ hw_lwp_cnh : 1, // HW: Clocks Not Halted event
+ hw_lwp_rnh : 1, // HW: Reference clocks Not Halted event
+ : 22, // Reserved
+ hw_lwp_cont : 1, // HW: LWP sampling in continuous mode
+ hw_lwp_ptsc : 1, // HW: Performance Time Stamp Counter in event records
+ hw_lwp_int : 1; // HW: Interrupt on threshold overflow
+};
+
+/*
+ * Leaf 0x8000001d
+ * AMD deterministic cache parameters
+ */
+
+struct leaf_0x8000001d_n {
+ // eax
+ u32 cache_type : 5, // Cache type field
+ cache_level : 3, // Cache level (1-based)
+ cache_self_init : 1, // Self-initializing cache level
+ fully_associative : 1, // Fully-associative cache
+ : 4, // Reserved
+ num_threads_sharing : 12, // Number of logical CPUs sharing cache
+ : 6; // Reserved
+ // ebx
+ u32 cache_linesize : 12, // System coherency line size (0-based)
+ cache_npartitions : 10, // Physical line partitions (0-based)
+ cache_nways : 10; // Ways of associativity (0-based)
+ // ecx
+ u32 cache_nsets : 31, // Cache number of sets (0-based)
+ : 1; // Reserved
+ // edx
+ u32 wbinvd_rll_no_guarantee : 1, // WBINVD/INVD not guaranteed for Remote Lower-Level caches
+ ll_inclusive : 1, // Cache is inclusive of Lower-Level caches
+ : 30; // Reserved
+};
+
+#define LEAF_0x8000001d_SUBLEAF_N_FIRST 0
+#define LEAF_0x8000001d_SUBLEAF_N_LAST 31
+
+/*
+ * Leaf 0x8000001e
+ * AMD CPU topology
+ */
+
+struct leaf_0x8000001e_0 {
+ // eax
+ u32 ext_apic_id : 32; // Extended APIC ID
+ // ebx
+ u32 core_id : 8, // Unique per-socket logical core unit ID
+ core_nthreads : 8, // #Threads per core (zero-based)
+ : 16; // Reserved
+ // ecx
+ u32 node_id : 8, // Node (die) ID of invoking logical CPU
+ nnodes_per_socket : 3, // #nodes in invoking logical CPU's package/socket
+ : 21; // Reserved
+ // edx
+ u32 : 32; // Reserved
+};
+
+/*
+ * Leaf 0x8000001f
+ * AMD encrypted memory capabilities (SME/SEV)
+ */
+
+struct leaf_0x8000001f_0 {
+ // eax
+ u32 sme : 1, // Secure Memory Encryption
+ sev : 1, // Secure Encrypted Virtualization
+ vm_page_flush : 1, // VM Page Flush MSR
+ sev_encrypted_state : 1, // SEV Encrypted State
+ sev_nested_paging : 1, // SEV secure nested paging
+ vm_permission_levels : 1, // VMPL
+ rpmquery : 1, // RPMQUERY instruction
+ vmpl_sss : 1, // VMPL supervisor shadow stack
+ secure_tsc : 1, // Secure TSC
+ virt_tsc_aux : 1, // Hardware virtualizes TSC_AUX
+ sme_coherent : 1, // Cache coherency enforcement across encryption domains
+ req_64bit_hypervisor : 1, // SEV guest mandates 64-bit hypervisor
+ restricted_injection : 1, // Restricted Injection supported
+ alternate_injection : 1, // Alternate Injection supported
+ debug_swap : 1, // SEV-ES: Full debug state swap
+ disallow_host_ibs : 1, // SEV-ES: Disallowing IBS use by the host
+ virt_transparent_enc : 1, // Virtual Transparent Encryption
+ vmgexit_parameter : 1, // SEV_FEATURES: VmgexitParameter
+ virt_tom_msr : 1, // Virtual TOM MSR
+ virt_ibs : 1, // SEV-ES guests: IBS state virtualization
+ : 4, // Reserved
+ vmsa_reg_protection : 1, // VMSA register protection
+ smt_protection : 1, // SMT protection
+ : 2, // Reserved
+ svsm_page_msr : 1, // SVSM communication page MSR
+ nested_virt_snp_msr : 1, // VIRT_RMPUPDATE/VIRT_PSMASH MSRs
+ : 2; // Reserved
+ // ebx
+ u32 pte_cbit_pos : 6, // PTE bit number to enable memory encryption
+ phys_addr_reduction_nbits : 6, // Reduction of phys address space in bits
+ vmpl_count : 4, // Number of VM permission levels (VMPL)
+ : 16; // Reserved
+ // ecx
+ u32 enc_guests_max : 32; // Max number of simultaneous encrypted guests
+ // edx
+ u32 min_sev_asid_no_sev_es : 32; // Minimum ASID for SEV-enabled SEV-ES-disabled guest
+};
+
+/*
+ * Leaf 0x80000020
+ * AMD PQoS (Platform QoS) extended features
+ */
+
+struct leaf_0x80000020_0 {
+ // eax
+ u32 : 32; // Reserved
+ // ebx
+ u32 : 1, // Reserved
+ mba : 1, // Memory Bandwidth Allocation support
+ smba : 1, // Slow Memory Bandwidth Allocation support
+ bmec : 1, // Bandwidth Monitoring Event Configuration support
+ l3rr : 1, // L3 Range Reservation support
+ abmc : 1, // Assignable Bandwidth Monitoring Counters
+ sdciae : 1, // Smart Data Cache Injection (SDCI) Allocation Enforcement
+ : 25; // Reserved
+ // ecx
+ u32 : 32; // Reserved
+ // edx
+ u32 : 32; // Reserved
+};
+
+struct leaf_0x80000020_1 {
+ // eax
+ u32 mba_limit_len : 32; // MBA enforcement limit size
+ // ebx
+ u32 : 32; // Reserved
+ // ecx
+ u32 : 32; // Reserved
+ // edx
+ u32 mba_cos_max : 32; // MBA max Class of Service number (zero-based)
+};
+
+struct leaf_0x80000020_2 {
+ // eax
+ u32 smba_limit_len : 32; // SMBA enforcement limit size
+ // ebx
+ u32 : 32; // Reserved
+ // ecx
+ u32 : 32; // Reserved
+ // edx
+ u32 smba_cos_max : 32; // SMBA max Class of Service number (zero-based)
+};
+
+struct leaf_0x80000020_3 {
+ // eax
+ u32 : 32; // Reserved
+ // ebx
+ u32 bmec_num_events : 8, // BMEC number of bandwidth events available
+ : 24; // Reserved
+ // ecx
+ u32 bmec_local_reads : 1, // Local NUMA reads can be tracked
+ bmec_remote_reads : 1, // Remote NUMA reads can be tracked
+ bmec_local_nontemp_wr : 1, // Local NUMA non-temporal writes can be tracked
+ bmec_remote_nontemp_wr : 1, // Remote NUMA non-temporal writes can be tracked
+ bmec_local_slow_mem_rd : 1, // Local NUMA slow-memory reads can be tracked
+ bmec_remote_slow_mem_rd : 1, // Remote NUMA slow-memory reads can be tracked
+ bmec_all_dirty_victims : 1, // Dirty QoS victims to all types of memory can be tracked
+ : 25; // Reserved
+ // edx
+ u32 : 32; // Reserved
+};
+
+/*
+ * Leaf 0x80000021
+ * AMD extended CPU features 2
+ */
+
+struct leaf_0x80000021_0 {
+ // eax
+ u32 no_nested_data_bp : 1, // No nested data breakpoints
+ fsgs_non_serializing : 1, // WRMSR to {FS,GS,KERNEL_GS}_BASE is non-serializing
+ lfence_serializing : 1, // LFENCE always serializing / synchronizes RDTSC
+ smm_page_cfg_lock : 1, // SMM paging configuration lock
+ : 2, // Reserved
+ null_sel_clr_base : 1, // Null selector clears base
+ upper_addr_ignore : 1, // EFER MSR Upper Address Ignore
+ auto_ibrs : 1, // EFER MSR Automatic IBRS
+ no_smm_ctl_msr : 1, // SMM_CTL MSR not available
+ fsrs : 1, // Fast Short Rep STOSB
+ fsrc : 1, // Fast Short Rep CMPSB
+ : 1, // Reserved
+ prefetch_ctl_msr : 1, // Prefetch control MSR
+ : 2, // Reserved
+ opcode_reclaim : 1, // Reserves opcode space
+ user_cpuid_disable : 1, // #GP when executing CPUID at CPL > 0
+ epsf : 1, // Enhanced Predictive Store Forwarding
+ : 3, // Reserved
+ wl_feedback : 1, // Workload-based heuristic feedback to OS
+ : 1, // Reserved
+ eraps : 1, // Enhanced Return Address Predictor Security
+ : 2, // Reserved
+ sbpb : 1, // Selective Branch Predictor Barrier
+ ibpb_brtype : 1, // Branch predictions flushed from CPU branch predictor
+ srso_no : 1, // No SRSO vulnerability
+ srso_uk_no : 1, // No SRSO at user-kernel boundary
+ srso_msr_fix : 1; // MSR BP_CFG[BpSpecReduce] SRSO mitigation
+ // ebx
+ u32 microcode_patch_size : 16, // Microcode patch size, in 16-byte units
+ rap_size : 8, // Return Address Predictor size
+ : 8; // Reserved
+ // ecx
+ u32 : 32; // Reserved
+ // edx
+ u32 : 32; // Reserved
+};
+
+/*
+ * Leaf 0x80000022
+ * AMD extended performance monitoring
+ */
+
+struct leaf_0x80000022_0 {
+ // eax
+ u32 perfmon_v2 : 1, // Performance monitoring v2
+ lbr_v2 : 1, // Last Branch Record v2 extensions (LBR Stack)
+ lbr_pmc_freeze : 1, // Freezing core performance counters / LBR Stack
+ : 29; // Reserved
+ // ebx
+ u32 n_pmc_core : 4, // Number of core performance counters
+ lbr_v2_stack_size : 6, // Number of LBR stack entries
+ n_pmc_northbridge : 6, // Number of northbridge performance counters
+ n_pmc_umc : 6, // Number of UMC performance counters
+ : 10; // Reserved
+ // ecx
+ u32 active_umc_bitmask : 32; // Active UMCs bitmask
+ // edx
+ u32 : 32; // Reserved
+};
+
+/*
+ * Leaf 0x80000023
+ * AMD multi-key encrypted memory
+ */
+
+struct leaf_0x80000023_0 {
+ // eax
+ u32 mem_hmk_mode : 1, // MEM-HMK encryption mode
+ : 31; // Reserved
+ // ebx
+ u32 mem_hmk_avail_keys : 16, // Total number of available encryption keys
+ : 16; // Reserved
+ // ecx
+ u32 : 32; // Reserved
+ // edx
+ u32 : 32; // Reserved
+};
+
+/*
+ * Leaf 0x80000026
+ * AMD extended CPU topology
+ */
+
+struct leaf_0x80000026_n {
+ // eax
+ u32 x2apic_id_shift : 5, // Bit width of this level (previous levels inclusive)
+ : 24, // Reserved
+ core_has_pwreff_ranking : 1, // This core has a power efficiency ranking
+ domain_has_hybrid_cores : 1, // This domain level has hybrid (E, P) cores
+ domain_core_count_asymm : 1; // The 'Core' domain has asymmetric cores count
+ // ebx
+ u32 domain_lcpus_count : 16, // Number of logical CPUs at this domain instance
+ core_pwreff_ranking : 8, // This core's static power efficiency ranking
+ core_native_model_id : 4, // This core's native model ID
+ core_type : 4; // This core's type
+ // ecx
+ u32 domain_level : 8, // This domain level (subleaf ID)
+ domain_type : 8, // This domain type
+ : 16; // Reserved
+ // edx
+ u32 x2apic_id : 32; // x2APIC ID of current logical CPU
+};
+
+#define LEAF_0x80000026_SUBLEAF_N_FIRST 0
+#define LEAF_0x80000026_SUBLEAF_N_LAST 3
+
+/*
+ * Leaf 0x80860000
+ * Maximum Transmeta leaf + CPU vendor string
+ */
+
+struct leaf_0x80860000_0 {
+ // eax
+ u32 max_tra_leaf : 32; // Maximum Transmeta leaf
+ // ebx
+ u32 cpu_vendorid_0 : 32; // Transmeta Vendor ID string bytes 0 - 3
+ // ecx
+ u32 cpu_vendorid_2 : 32; // Transmeta Vendor ID string bytes 8 - 11
+ // edx
+ u32 cpu_vendorid_1 : 32; // Transmeta Vendor ID string bytes 4 - 7
+};
+
+/*
+ * Leaf 0x80860001
+ * Transmeta extended CPU features
+ */
+
+struct leaf_0x80860001_0 {
+ // eax
+ u32 stepping : 4, // Stepping ID
+ base_model : 4, // Base CPU model ID
+ base_family_id : 4, // Base CPU family ID
+ cpu_type : 2, // CPU type
+ : 18; // Reserved
+ // ebx
+ u32 cpu_rev_mask_minor : 8, // CPU revision ID, mask minor
+ cpu_rev_mask_major : 8, // CPU revision ID, mask major
+ cpu_rev_minor : 8, // CPU revision ID, minor
+ cpu_rev_major : 8; // CPU revision ID, major
+ // ecx
+ u32 cpu_base_mhz : 32; // CPU nominal frequency, in MHz
+ // edx
+ u32 recovery : 1, // Recovery CMS is active (after bad flush)
+ longrun : 1, // LongRun power management capabilities
+ : 1, // Reserved
+ lrti : 1, // LongRun Table Interface
+ : 28; // Reserved
+};
+
+/*
+ * Leaf 0x80860002
+ * Transmeta CMS (Code Morphing Software)
+ */
+
+struct leaf_0x80860002_0 {
+ // eax
+ u32 cpu_rev_id : 32; // CPU revision ID
+ // ebx
+ u32 cms_rev_mask_2 : 8, // CMS revision ID, mask component 2
+ cms_rev_mask_1 : 8, // CMS revision ID, mask component 1
+ cms_rev_minor : 8, // CMS revision ID, minor
+ cms_rev_major : 8; // CMS revision ID, major
+ // ecx
+ u32 cms_rev_mask_3 : 32; // CMS revision ID, mask component 3
+ // edx
+ u32 : 32; // Reserved
+};
+
+/*
+ * Leaf 0x80860003
+ * Transmeta CPU information string, bytes 0 - 15
+ */
+
+struct leaf_0x80860003_0 {
+ // eax
+ u32 cpu_info_0 : 32; // CPU info string bytes 0 - 3
+ // ebx
+ u32 cpu_info_1 : 32; // CPU info string bytes 4 - 7
+ // ecx
+ u32 cpu_info_2 : 32; // CPU info string bytes 8 - 11
+ // edx
+ u32 cpu_info_3 : 32; // CPU info string bytes 12 - 15
+};
+
+/*
+ * Leaf 0x80860004
+ * Transmeta CPU information string, bytes 16 - 31
+ */
+
+struct leaf_0x80860004_0 {
+ // eax
+ u32 cpu_info_4 : 32; // CPU info string bytes 16 - 19
+ // ebx
+ u32 cpu_info_5 : 32; // CPU info string bytes 20 - 23
+ // ecx
+ u32 cpu_info_6 : 32; // CPU info string bytes 24 - 27
+ // edx
+ u32 cpu_info_7 : 32; // CPU info string bytes 28 - 31
+};
+
+/*
+ * Leaf 0x80860005
+ * Transmeta CPU information string, bytes 32 - 47
+ */
+
+struct leaf_0x80860005_0 {
+ // eax
+ u32 cpu_info_8 : 32; // CPU info string bytes 32 - 35
+ // ebx
+ u32 cpu_info_9 : 32; // CPU info string bytes 36 - 39
+ // ecx
+ u32 cpu_info_10 : 32; // CPU info string bytes 40 - 43
+ // edx
+ u32 cpu_info_11 : 32; // CPU info string bytes 44 - 47
+};
+
+/*
+ * Leaf 0x80860006
+ * Transmeta CPU information string, bytes 48 - 63
+ */
+
+struct leaf_0x80860006_0 {
+ // eax
+ u32 cpu_info_12 : 32; // CPU info string bytes 48 - 51
+ // ebx
+ u32 cpu_info_13 : 32; // CPU info string bytes 52 - 55
+ // ecx
+ u32 cpu_info_14 : 32; // CPU info string bytes 56 - 59
+ // edx
+ u32 cpu_info_15 : 32; // CPU info string bytes 60 - 63
+};
+
+/*
+ * Leaf 0x80860007
+ * Transmeta live CPU information
+ */
+
+struct leaf_0x80860007_0 {
+ // eax
+ u32 cpu_cur_mhz : 32; // Current CPU frequency, in MHz
+ // ebx
+ u32 cpu_cur_voltage : 32; // Current CPU voltage, in millivolts
+ // ecx
+ u32 cpu_cur_perf_pctg : 32; // Current CPU performance percentage, 0 - 100
+ // edx
+ u32 cpu_cur_gate_delay : 32; // Current CPU gate delay, in femtoseconds
+};
+
+/*
+ * Leaf 0xc0000000
+ * Maximum Centaur/Zhaoxin leaf
+ */
+
+struct leaf_0xc0000000_0 {
+ // eax
+ u32 max_cntr_leaf : 32; // Maximum Centaur/Zhaoxin leaf
+ // ebx
+ u32 : 32; // Reserved
+ // ecx
+ u32 : 32; // Reserved
+ // edx
+ u32 : 32; // Reserved
+};
+
+/*
+ * Leaf 0xc0000001
+ * Centaur/Zhaoxin extended CPU features
+ */
+
+struct leaf_0xc0000001_0 {
+ // eax
+ u32 : 32; // Reserved
+ // ebx
+ u32 : 32; // Reserved
+ // ecx
+ u32 : 32; // Reserved
+ // edx
+ u32 ccs_sm2 : 1, // CCS SM2 instructions
+ ccs_sm2_en : 1, // CCS SM2 enabled
+ rng : 1, // Random Number Generator
+ rng_en : 1, // RNG enabled
+ ccs_sm3_sm4 : 1, // CCS SM3 and SM4 instructions
+ ccs_sm3_sm4_en : 1, // CCS SM3/SM4 enabled
+ ace : 1, // Advanced Cryptography Engine
+ ace_en : 1, // ACE enabled
+ ace2 : 1, // Advanced Cryptography Engine v2
+ ace2_en : 1, // ACE v2 enabled
+ phe : 1, // PadLock Hash Engine
+ phe_en : 1, // PHE enabled
+ pmm : 1, // PadLock Montgomery Multiplier
+ pmm_en : 1, // PMM enabled
+ : 2, // Reserved
+ parallax : 1, // Parallax auto adjust processor voltage
+ parallax_en : 1, // Parallax enabled
+ : 2, // Reserved
+ tm3 : 1, // Thermal Monitor v3
+ tm3_en : 1, // TM v3 enabled
+ : 3, // Reserved
+ phe2 : 1, // PadLock Hash Engine v2 (SHA384/SHA512)
+ phe2_en : 1, // PHE v2 enabled
+ rsa : 1, // RSA instructions (XMODEXP/MONTMUL2)
+ rsa_en : 1, // RSA instructions enabled
+ : 3; // Reserved
+};
+
+#endif /* _ASM_X86_CPUID_LEAF_TYPES */
--
2.53.0
^ permalink raw reply related [flat|nested] 101+ messages in thread
* [PATCH v6 08/90] x86: Introduce a centralized CPUID data model
2026-03-27 2:15 [PATCH v6 00/90] x86: Introduce a centralized CPUID data model Ahmed S. Darwish
` (6 preceding siblings ...)
2026-03-27 2:15 ` [PATCH v6 07/90] x86/cpuid: Introduce <asm/cpuid/leaf_types.h> Ahmed S. Darwish
@ 2026-03-27 2:15 ` Ahmed S. Darwish
2026-03-27 2:15 ` [PATCH v6 09/90] x86/cpuid: Introduce a centralized CPUID parser Ahmed S. Darwish
` (83 subsequent siblings)
91 siblings, 0 replies; 101+ messages in thread
From: Ahmed S. Darwish @ 2026-03-27 2:15 UTC (permalink / raw)
To: Borislav Petkov, Dave Hansen, Ingo Molnar
Cc: Thomas Gleixner, Andrew Cooper, H. Peter Anvin,
Sean Christopherson, David Woodhouse, Peter Zijlstra,
Christian Ludloff, Sohil Mehta, John Ogness, x86, x86-cpuid, LKML,
Ahmed S. Darwish
** Context
The x86-cpuid-db project generates a C header file with full C99 bitfield
listings for all known CPUID leaf/subleaf query outputs.
That header is now merged by parent commits at <asm/cpuid/leaf_types.h>,
and is in the form:
struct leaf_0x0_0 { /* CPUID(0x0).0 C99 bitfields */ };
...
struct leaf_0x4_n { /* CPUID(0x4).n C99 bitfields */ };
...
struct leaf_0xd_0 { /* CPUID(0xd).0 C99 bitfields */ };
struct leaf_0xd_1 { /* CPUID(0xd).1 C99 bitfields */ };
struct leaf_0xd_n { /* CPUID(0xd).n C99 bitfields */ };
...
** Goal
Introduce a structured, size-efficient, per-CPU, CPUID data repository.
Use the x86-cpuid-db auto-generated data types, and custom CPUID leaf
parsers, to build that repository. Given a leaf, subleaf, and index,
provide direct memory access to the parsed and cached per-CPU CPUID output.
** Long-term goal
Remove the need for drivers and other areas in the kernel to invoke direct
CPUID queries. Only one place in the kernel should be allowed to use the
CPUID instruction: the CPUID parser code.
** Implementation
Introduce CPUID_LEAF()/CPUID_LEAF_N() to build a compact CPUID storage
layout in the form:
struct leaf_0x0_0 leaf_0x0_0[1];
struct leaf_parse_info leaf_0x0_0_info;
struct leaf_0x1_0 leaf_0x1_0[1];
struct leaf_parse_info leaf_0x0_0_info;
struct leaf_0x4_n leaf_0x4_n[8];
struct leaf_parse_info leaf_0x4_n_info;
...
where each CPUID query stores its output at the designated leaf/subleaf
array and has an associated "CPUID query info" structure.
Embed the CPUID tables inside "struct cpuinfo_x86" to ensure early-boot and
per-CPU access through the CPUs capability structures.
Use an array of CPUID output storage entries for each leaf/subleaf
combination to accommodate leaves which produce the same output format for
a large subleaf range. This is typical for CPUID leaves enumerating
hierarchical objects; e.g. CPUID(0x4) cache topology enumeration,
CPUID(0xd) XSAVE enumeration, and CPUID(0x12) SGX Enclave Page Cache
enumeration.
** New CPUID APIs
Assuming a CPU capability structure 'c', provide macros to access the
parsed and cached CPUID leaf/subleaf output. These macros resolve to a
compile-time tokenization that ensures type-safety:
const struct leaf_0x7_0 *l7_0;
l7_0 = cpuid_subleaf(c, 0x7, 0);
| | └────────┐
| └─────────┐ |
* * *
&c.cpuid.leaf_0x7_0[0]
For CPUID leaves with multiple subleaves having the same output format,
provide the APIs:
const struct leaf_0x4_n *l4_0, *l4_1;
l4_0 = cpuid_subleaf_n(c, 0x4, 0);
| | └──────────┐
| └─────────┐ |
* * v
&c.cpuid.leaf_0x4_n[0]
l4_1 = cpuid_subleaf_n(c, 0x4, 1);
| | └──────────┐
| └─────────┐ |
* * v
&c.cpuid.leaf_0x4_n[1]
where the indices 0, 1, n above can be passed dynamically; e.g., in an
enumeration for loop.
Add a clear rationale on why call sites should use the these new APIs
instead of directly invoking CPUID.
** Next steps
For now, define cached parse entries for CPUID(0x0) and CPUID(0x1).
Generic parser logic to fill the CPUID tables, along with more CPUID leaves
support, will be added next.
Suggested-by: Thomas Gleixner <tglx@kernel.org> # CPUID data model
Suggested-by: Andrew Cooper <andrew.cooper3@citrix.com> # x86-cpuid-db schema
Suggested-by: Borislav Petkov <bp@alien8.de> # Early CPUID centralization drafts
Suggested-by: Ingo Molnar <mingo@kernel.org> # CPUID headers restructuring
Suggested-by: Sean Christopherson <seanjc@google.com> # cpuid_subleaf_n() APIs
Signed-off-by: Ahmed S. Darwish <darwi@linutronix.de>
Link: https://lore.kernel.org/lkml/874ixernra.ffs@tglx
Link: https://gitlab.com/x86-cpuid.org/x86-cpuid-db
Link: https://lore.kernel.org/lkml/aBnSgu_JyEi8fvog@gmail.com
Link: https://lore.kernel.org/lkml/aJ9TbaNMgaplKSbH@google.com
---
arch/x86/include/asm/cpuid/api.h | 238 +++++++++++++++++++++++++++++
arch/x86/include/asm/cpuid/types.h | 98 ++++++++++++
arch/x86/include/asm/processor.h | 2 +
3 files changed, 338 insertions(+)
diff --git a/arch/x86/include/asm/cpuid/api.h b/arch/x86/include/asm/cpuid/api.h
index 2b9750cc8a75..b868902dbf5f 100644
--- a/arch/x86/include/asm/cpuid/api.h
+++ b/arch/x86/include/asm/cpuid/api.h
@@ -289,4 +289,242 @@ static inline bool cpuid_amd_hygon_has_l3_cache(void)
return cpuid_edx(0x80000006);
}
+/*
+ * 'struct cpuid_leaves' accessors (without sanity checks):
+ *
+ * For internal use by the CPUID parser.
+ */
+
+/* Return constified pointers for all call-site APIs */
+#define __const_ptr(_ptr) \
+ ((const __typeof__(*(_ptr)) *)(_ptr))
+
+#define __cpuid_leaves_subleaf(_leaves, _leaf, _subleaf) \
+ __const_ptr(&((_leaves)->leaf_ ## _leaf ## _ ## _subleaf)[0])
+
+#define __cpuid_leaves_subleaf_n(_leaves, _leaf, _index) \
+ __const_ptr(&((_leaves)->leaf_ ## _leaf ## _ ## n)[_index])
+
+#define __cpuid_leaves_subleaf_info(_leaves, _leaf, _subleaf) \
+ __const_ptr(&((_leaves)->leaf_ ## _leaf ## _ ## _subleaf ## _ ## info))
+
+/*
+ * 'struct cpuid_table' accessors (with sanity checks):
+ *
+ * For internal use by the CPUID parser.
+ */
+
+#define __cpuid_table_nr_filled_subleaves(_table, _leaf, _subleaf) \
+ __cpuid_leaves_subleaf_info(&((_table)->leaves), _leaf, _subleaf)->nr_entries
+
+#define __cpuid_table_subleaf_range_size(_table, _leaf) \
+ ARRAY_SIZE((_table)->leaves.leaf_ ## _leaf ## _n)
+
+#define __cpuid_table_invalid_subleaf(_table, _leaf, _subleaf) \
+ (((_subleaf) < (__cpuid_leaf_first_subleaf(_leaf))) || \
+ ((_subleaf) > (__cpuid_leaf_first_subleaf(_leaf) + \
+ __cpuid_table_subleaf_range_size(_table, _leaf) - 1)))
+
+/* Return NULL if the parser did not fill that leaf. Check cpuid_subleaf(). */
+#define __cpuid_table_subleaf(_table, _leaf, _subleaf) \
+({ \
+ unsigned int ____f = __cpuid_table_nr_filled_subleaves(_table, _leaf, _subleaf); \
+ \
+ (____f != 1) ? NULL : __cpuid_leaves_subleaf(&((_table)->leaves), _leaf, _subleaf); \
+})
+
+/*
+ * Return NULL if the CPUID parser did not fill this leaf, or if the given
+ * dynamic subleaf value is out of range. Check cpuid_subleaf_n().
+ */
+#define __cpuid_table_subleaf_n(_table, _leaf, _subleaf) \
+({ \
+ unsigned int ____i = (_subleaf) - __cpuid_leaf_first_subleaf(_leaf); \
+ unsigned int ____f = __cpuid_table_nr_filled_subleaves(_table, _leaf, n); \
+ \
+ /* CPUID parser might not have filled the entire subleaf range */ \
+ ((____i >= ____f) || __cpuid_table_invalid_subleaf(_table, _leaf, _subleaf)) ? \
+ NULL : __cpuid_leaves_subleaf_n(&((_table)->leaves), _leaf, ____i); \
+})
+
+/*
+ * Compile-time checks for leaves with a subleaf range:
+ */
+
+#define __cpuid_assert_subleaf_range(_cpuinfo, _leaf) \
+ static_assert(__cpuid_table_subleaf_range_size(&(_cpuinfo)->cpuid, _leaf) > 1)
+
+#define __cpuid_assert_subleaf_within_range(_cpuinfo, _leaf, _subleaf) \
+ BUILD_BUG_ON(__builtin_constant_p(_subleaf) && \
+ __cpuid_table_invalid_subleaf(&(_cpuinfo)->cpuid, _leaf, _subleaf))
+
+/*
+ * CPUID Parser Call-site APIs
+ *
+ * Call sites should use below APIs instead of invoking direct CPUID queries.
+ *
+ * Benefits include:
+ *
+ * - Return CPUID output as typed C structures that are auto-generated from a
+ * centralized database (see <asm/cpuid/leaf_types.h). Such data types have a
+ * full C99 bitfield layout per CPUID leaf/subleaf combination. Call sites
+ * can thus avoid doing ugly and cryptic bitwise operations on raw CPUID data.
+ *
+ * - Return cached, per-CPU, CPUID output. Below APIs do not invoke any CPUID
+ * queries, thus avoiding their side effects like serialization and VM exits.
+ * Call-site-specific hard coded constants and macros for caching CPUID query
+ * outputs can also be avoided.
+ *
+ * - Return sanitized CPUID data. Below APIs return NULL if the given CPUID
+ * leaf/subleaf input is not supported by hardware, or if the hardware CPUID
+ * output was deemed invalid by the CPUID parser. This centralizes all CPUID
+ * data sanitization in one place (the kernel's CPUID parser.)
+ *
+ * - A centralized global view of system CPUID data. Below APIs will reflect
+ * any kernel-enforced feature masking or overrides, unlike ad hoc parsing of
+ * raw CPUID output by drivers and individual call sites.
+ */
+
+/*
+ * Call-site APIs for CPUID leaves with a single subleaf:
+ */
+
+/**
+ * cpuid_subleaf() - Access parsed CPUID
+ * @_cpuinfo: CPU capability structure reference ('struct cpuinfo_x86')
+ * @_leaf: CPUID leaf, in compile-time 0xN format; e.g. 0x7, 0xf
+ * @_subleaf: CPUID subleaf, in compile-time decimal format; e.g. 0, 1, 3
+ *
+ * Returns a pointer to parsed CPUID output, from the CPUID table inside
+ * @_cpuinfo, as a <cpuid/leaf_types.h> data type: 'struct leaf_0xM_N', where
+ * 0xM is the token provided at @_leaf, and N is the token provided at
+ * @_subleaf; e.g. struct leaf_0x7_0.
+ *
+ * Returns NULL if the requested CPUID @_leaf/@_subleaf query output is not
+ * present at the parsed CPUID table inside @_cpuinfo. This can happen if:
+ *
+ * - The CPUID table inside @_cpuinfo has not yet been populated.
+ * - The CPUID table inside @_cpuinfo was populated, but the CPU does not
+ * implement the requested CPUID @_leaf/@_subleaf combination.
+ * - The CPUID table inside @_cpuinfo was populated, but the kernel's CPUID
+ * parser has predetermined that the requested CPUID @_leaf/@_subleaf
+ * hardware output is invalid or unsupported.
+ *
+ * Example usage::
+ *
+ * const struct leaf_0x7_0 *l7_0 = cpuid_subleaf(c, 0x7, 0);
+ * if (!l7_0) {
+ * // Handle error
+ * }
+ *
+ * const struct leaf_0x7_1 *l7_1 = cpuid_subleaf(c, 0x7, 1);
+ * if (!l7_1) {
+ * // Handle error
+ * }
+ */
+#define cpuid_subleaf(_cpuinfo, _leaf, _subleaf) \
+ __cpuid_table_subleaf(&(_cpuinfo)->cpuid, _leaf, _subleaf) \
+
+/**
+ * cpuid_leaf() - Access parsed CPUID data
+ * @_cpuinfo: CPU capability structure reference ('struct cpuinfo_x86')
+ * @_leaf: CPUID leaf, in compile-time 0xN format; e.g. 0x0, 0x2, 0x80000000
+ *
+ * Similar to cpuid_subleaf(), but with a CPUID subleaf = 0.
+ *
+ * Example usage::
+ *
+ * const struct leaf_0x0_0 *l0 = cpuid_leaf(c, 0x0);
+ * if (!l0) {
+ * // Handle error
+ * }
+ *
+ * const struct leaf_0x80000000_0 *el0 = cpuid_leaf(c, 0x80000000);
+ * if (!el0) {
+ * // Handle error
+ * }
+ */
+#define cpuid_leaf(_cpuinfo, _leaf) \
+ cpuid_subleaf(_cpuinfo, _leaf, 0)
+
+/**
+ * cpuid_leaf_raw() - Access parsed CPUID data in raw format
+ * @_cpuinfo: CPU capability structure reference ('struct cpuinfo_x86')
+ * @_leaf: CPUID leaf, in compile-time 0xN format
+ *
+ * Similar to cpuid_leaf(), but returns a raw 'struct cpuid_regs' pointer to
+ * the parsed CPUID data instead of a "typed" <asm/cpuid/leaf_types.h> pointer.
+ */
+#define cpuid_leaf_raw(_cpuinfo, _leaf) \
+ ((const struct cpuid_regs *)(cpuid_leaf(_cpuinfo, _leaf)))
+
+/*
+ * Call-site APIs for CPUID leaves with a subleaf range:
+ */
+
+/**
+ * cpuid_subleaf_n() - Access parsed CPUID data for leaf with a subleaf range
+ * @_cpuinfo: CPU capability structure reference ('struct cpuinfo_x86')
+ * @_leaf: CPUID leaf, in compile-time 0xN format; e.g. 0x4, 0x8000001d
+ * @_subleaf: Subleaf number, which can be passed dynamically. It must be smaller
+ * than cpuid_subleaf_count(@_cpuinfo, @_leaf).
+ *
+ * Build-time errors will be emitted in the following cases:
+ *
+ * - @_leaf has no subleaf range. Leaves with a subleaf range have an '_n' type
+ * suffix and are listed at <asm/cpuid/types.h> using the CPUID_LEAF_N() macro.
+ *
+ * - @_subleaf is known at compile-time but is out of range.
+ *
+ * Example usage::
+ *
+ * const struct leaf_0x4_n *l4;
+ *
+ * for (int i = 0; i < cpuid_subleaf_count(c, 0x4); i++) {
+ * l4 = cpuid_subleaf_n(c, 0x4, i);
+ * if (!l4) {
+ * // Handle error
+ * }
+ * ...
+ * }
+ *
+ * Beside the standard error situations detailed at cpuid_subleaf(), this
+ * macro will also return NULL if @_subleaf is out of the leaf's subleaf range.
+ */
+#define cpuid_subleaf_n(_cpuinfo, _leaf, _subleaf) \
+({ \
+ __cpuid_assert_subleaf_range(_cpuinfo, _leaf); \
+ __cpuid_assert_subleaf_within_range(_cpuinfo, _leaf, _subleaf); \
+ __cpuid_table_subleaf_n(&(_cpuinfo)->cpuid, _leaf, _subleaf); \
+})
+
+/**
+ * cpuid_subleaf_n_raw() - Access parsed CPUID data for leaf with subleaf range
+ * @_cpuinfo: CPU capability structure reference ('struct cpuinfo_x86')
+ * @_leaf: CPUID leaf, in compile-time 0xN format; e.g. 0x4, 0x8000001d
+ * @_subleaf: Subleaf number, which can be passed dynamically. It must be smaller
+ * than cpuid_subleaf_count(@_cpuinfo, @_leaf).
+ *
+ * Similar to cpuid_subleaf_n(), but returns a raw 'struct cpuid_regs' pointer to
+ * the parsed CPUID data instead of a "typed" <asm/cpuid/leaf_types.h> pointer.
+ */
+#define cpuid_subleaf_n_raw(_cpuinfo, _leaf, _subleaf) \
+ ((const struct cpuid_regs *)cpuid_subleaf_n(_cpuinfo, _leaf, _subleaf))
+
+/**
+ * cpuid_subleaf_count() - Number of filled subleaves for @_leaf
+ * @_cpuinfo: CPU capability structure reference ('struct cpuinfo_x86')
+ * @_leaf: CPUID leaf, in compile-time 0xN format; e.g. 0x4, 0x8000001d
+ *
+ * Return the number of subleaves filled by the CPUID parser for @_leaf.
+ *
+ * @_leaf must have subleaf range. Leaves with a subleaf range have an '_n' type
+ * suffix and are listed at <asm/cpuid/types.h> using the CPUID_LEAF_N() macro.
+ */
+#define cpuid_subleaf_count(_cpuinfo, _leaf) \
+({ \
+ __cpuid_assert_subleaf_range(_cpuinfo, _leaf); \
+ __cpuid_table_nr_filled_subleaves(&(_cpuinfo)->cpuid, _leaf, n); \
+})
+
#endif /* _ASM_X86_CPUID_API_H */
diff --git a/arch/x86/include/asm/cpuid/types.h b/arch/x86/include/asm/cpuid/types.h
index 8a00364b79de..3d0e611c97ba 100644
--- a/arch/x86/include/asm/cpuid/types.h
+++ b/arch/x86/include/asm/cpuid/types.h
@@ -5,6 +5,8 @@
#include <linux/build_bug.h>
#include <linux/types.h>
+#include <asm/cpuid/leaf_types.h>
+
/*
* Types for raw CPUID access:
*/
@@ -30,6 +32,12 @@ enum cpuid_regs_idx {
#define CPUID_LEAF_FREQ 0x16
#define CPUID_LEAF_TILE 0x1d
+#define CPUID_RANGE(idx) ((idx) & 0xffff0000)
+#define CPUID_RANGE_MAX(idx) (CPUID_RANGE(idx) + 0xffff)
+
+#define CPUID_BASE_START 0x00000000
+#define CPUID_BASE_END CPUID_RANGE_MAX(CPUID_BASE_START)
+
/*
* Types for CPUID(0x2) parsing:
*/
@@ -124,4 +132,94 @@ extern const struct leaf_0x2_table cpuid_0x2_table[256];
*/
#define TLB_0x63_2M_4M_ENTRIES 32
+/*
+ * Types for centralized CPUID tables:
+ *
+ * For internal use by the CPUID parser.
+ */
+
+/**
+ * struct leaf_parse_info - CPUID query parse info
+ * @nr_entries: Number of valid entries filled by the CPUID parser
+ */
+struct leaf_parse_info {
+ unsigned int nr_entries;
+};
+
+/**
+ * __CPUID_LEAF() - Define a CPUID output and parse info entry
+ * @_name: Struct type name of the CPUID leaf/subleaf (e.g. 'leaf_0x7_0'). Such
+ * types are defined at <cpuid/leaf_types.h> and follow the leaf_0xM_N
+ * format, where 0xM is the leaf and N is the subleaf.
+ * @_count: Number of storage entries to allocate for this leaf/subleaf.
+ *
+ * For a given leaf/subleaf, define an array of CPUID storage entries and an associated
+ * query info structure.
+ *
+ * Use an array of storage entries to accommodate CPUID leaves with multiple subleaves
+ * having the same output format. This is common for hierarchical enumeration; e.g.,
+ * CPUID(0x4), CPUID(0x12), and CPUID(0x8000001d).
+ */
+#define __CPUID_LEAF(_name, _count) \
+ struct _name _name[_count]; \
+ struct leaf_parse_info _name##_info
+
+/**
+ * CPUID_LEAF() - Define a 'struct cpuid_leaves' storage entry
+ * @_leaf: Leaf number, in compile-time 0xN format
+ * @_subleaf: Subleaf number, in compile-time decimal format
+ *
+ * Convenience wrapper around __CPUID_LEAF().
+ */
+#define CPUID_LEAF(_leaf, _subleaf) \
+ __CPUID_LEAF(leaf_ ## _leaf ## _ ## _subleaf, 1)
+
+#define __cpuid_leaf_first_subleaf(_l) \
+ LEAF_ ## _l ## _ ## SUBLEAF_N_FIRST
+#define __cpuid_leaf_last_subleaf(_l) \
+ LEAF_ ## _l ## _ ## SUBLEAF_N_LAST
+
+#define __cpuid_leaf_subleaf_count_min(_l) 2
+#define __cpuid_leaf_subleaf_count_max(_l) \
+ (__cpuid_leaf_last_subleaf(_l) - __cpuid_leaf_first_subleaf(_l) + 1)
+
+/**
+ * CPUID_LEAF_N() - Define a 'struct cpuid_leaves' storage entry
+ * @_leaf: Leaf number, in compile-time 0xN format
+ * @_count: Number of storage entries to allocate for that leaf. It must not exceed
+ * the limits defined at <cpuid/leaf_types.h>.
+ *
+ * Convenience wrapper around __CPUID_LEAF().
+ */
+#define CPUID_LEAF_N(_leaf, _count) \
+ static_assert(_count >= __cpuid_leaf_subleaf_count_min(_leaf)); \
+ static_assert(_count <= __cpuid_leaf_subleaf_count_max(_leaf)); \
+ __CPUID_LEAF(leaf_ ## _leaf ## _ ## n, _count)
+
+/*
+ * struct cpuid_leaves - Parsed CPUID data
+ */
+struct cpuid_leaves {
+ /* Leaf Subleaf number (or max number of subleaves) */
+ CPUID_LEAF ( 0x0, 0 );
+ CPUID_LEAF ( 0x1, 0 );
+};
+
+/*
+ * Types for centralized CPUID tables:
+ *
+ * For external use.
+ */
+
+/**
+ * struct cpuid_table - Per-CPU CPUID data repository
+ * @leaves: Parsed CPUID queries output and their metadata
+ *
+ * This is to be embedded inside 'struct cpuinfo_x86' to provide parsed and
+ * sanitized CPUID data per CPU.
+ */
+struct cpuid_table {
+ struct cpuid_leaves leaves;
+};
+
#endif /* _ASM_X86_CPUID_TYPES_H */
diff --git a/arch/x86/include/asm/processor.h b/arch/x86/include/asm/processor.h
index bea05fea5729..5ee0dcbd548c 100644
--- a/arch/x86/include/asm/processor.h
+++ b/arch/x86/include/asm/processor.h
@@ -16,6 +16,7 @@ struct vm86;
#include <uapi/asm/sigcontext.h>
#include <asm/current.h>
#include <asm/cpufeatures.h>
+#include <asm/cpuid/types.h>
#include <asm/page.h>
#include <asm/pgtable_types.h>
#include <asm/percpu.h>
@@ -164,6 +165,7 @@ struct cpuinfo_x86 {
char x86_vendor_id[16];
char x86_model_id[64];
struct cpuinfo_topology topo;
+ struct cpuid_table cpuid;
/* in KB - valid for CPUS which support this call: */
unsigned int x86_cache_size;
int x86_cache_alignment; /* In bytes */
--
2.53.0
^ permalink raw reply related [flat|nested] 101+ messages in thread
* [PATCH v6 09/90] x86/cpuid: Introduce a centralized CPUID parser
2026-03-27 2:15 [PATCH v6 00/90] x86: Introduce a centralized CPUID data model Ahmed S. Darwish
` (7 preceding siblings ...)
2026-03-27 2:15 ` [PATCH v6 08/90] x86: Introduce a centralized CPUID data model Ahmed S. Darwish
@ 2026-03-27 2:15 ` Ahmed S. Darwish
2026-03-27 2:15 ` [PATCH v6 10/90] x86/cpu: Rescan CPUID table after disabling PSN Ahmed S. Darwish
` (82 subsequent siblings)
91 siblings, 0 replies; 101+ messages in thread
From: Ahmed S. Darwish @ 2026-03-27 2:15 UTC (permalink / raw)
To: Borislav Petkov, Dave Hansen, Ingo Molnar
Cc: Thomas Gleixner, Andrew Cooper, H. Peter Anvin,
Sean Christopherson, David Woodhouse, Peter Zijlstra,
Christian Ludloff, Sohil Mehta, John Ogness, x86, x86-cpuid, LKML,
Ahmed S. Darwish
Introduce a CPUID parser for populating the system's CPUID tables.
Since accessing a leaf within the CPUID table requires compile time
tokenization, split the parser into two stages:
(a) Compile-time macros for tokenizing the leaf/subleaf offsets within
the CPUID table.
(b) Generic runtime code to fill the CPUID data, using a parsing table
which collects these compile-time offsets.
For actual CPUID output parsing, support both generic and leaf-specific
read functions.
To ensure CPUID data early availability, invoke the parser during early
boot, early Xen boot, and at early secondary CPUs bring up.
Provide call site APIs to refresh a single leaf, or a leaf range, within
the CPUID tables. This is for sites issuing MSR writes that partially
changes the CPU's CPUID layout. Doing full CPUID table rescans in such
cases will be destructive since the CPUID tables will host all of the
kernel's X86_FEATURE flags at a later stage.
Suggested-by: Thomas Gleixner <tglx@kernel.org>
Signed-off-by: Ahmed S. Darwish <darwi@linutronix.de>
---
arch/x86/include/asm/cpuid/api.h | 9 ++
arch/x86/kernel/cpu/Makefile | 1 +
arch/x86/kernel/cpu/common.c | 5 +-
arch/x86/kernel/cpu/cpuid_parser.c | 182 +++++++++++++++++++++++++++++
arch/x86/kernel/cpu/cpuid_parser.h | 120 +++++++++++++++++++
arch/x86/xen/enlighten.c | 3 +-
arch/x86/xen/enlighten_pv.c | 1 +
7 files changed, 319 insertions(+), 2 deletions(-)
create mode 100644 arch/x86/kernel/cpu/cpuid_parser.c
create mode 100644 arch/x86/kernel/cpu/cpuid_parser.h
diff --git a/arch/x86/include/asm/cpuid/api.h b/arch/x86/include/asm/cpuid/api.h
index b868902dbf5f..82eddfa2347b 100644
--- a/arch/x86/include/asm/cpuid/api.h
+++ b/arch/x86/include/asm/cpuid/api.h
@@ -7,6 +7,7 @@
#include <linux/build_bug.h>
#include <linux/types.h>
+#include <asm/processor.h>
#include <asm/string.h>
/*
@@ -527,4 +528,12 @@ static inline bool cpuid_amd_hygon_has_l3_cache(void)
__cpuid_table_nr_filled_subleaves(&(_cpuinfo)->cpuid, _leaf, n); \
})
+/*
+ * CPUID parser exported APIs:
+ */
+
+void cpuid_scan_cpu(struct cpuinfo_x86 *c);
+void cpuid_refresh_leaf(struct cpuinfo_x86 *c, u32 leaf);
+void cpuid_refresh_range(struct cpuinfo_x86 *c, u32 start, u32 end);
+
#endif /* _ASM_X86_CPUID_API_H */
diff --git a/arch/x86/kernel/cpu/Makefile b/arch/x86/kernel/cpu/Makefile
index 2f8a58ef690e..d2e8a849f180 100644
--- a/arch/x86/kernel/cpu/Makefile
+++ b/arch/x86/kernel/cpu/Makefile
@@ -19,6 +19,7 @@ KCSAN_SANITIZE_common.o := n
obj-y := cacheinfo.o scattered.o
obj-y += topology_common.o topology_ext.o topology_amd.o
+obj-y += cpuid_parser.o
obj-y += common.o
obj-y += rdrand.o
obj-y += match.o
diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c
index a8ff4376c286..303faa612a6c 100644
--- a/arch/x86/kernel/cpu/common.c
+++ b/arch/x86/kernel/cpu/common.c
@@ -1775,6 +1775,7 @@ static void __init cpu_parse_early_param(void)
static void __init early_identify_cpu(struct cpuinfo_x86 *c)
{
memset(&c->x86_capability, 0, sizeof(c->x86_capability));
+ memset(&c->cpuid, 0, sizeof(c->cpuid));
c->extended_cpuid_level = 0;
if (!cpuid_feature())
@@ -1782,6 +1783,7 @@ static void __init early_identify_cpu(struct cpuinfo_x86 *c)
/* cyrix could have cpuid enabled via c_identify()*/
if (cpuid_feature()) {
+ cpuid_scan_cpu(c);
cpu_detect(c);
get_cpu_vendor(c);
intel_unlock_cpuid_leafs(c);
@@ -1954,8 +1956,8 @@ static void generic_identify(struct cpuinfo_x86 *c)
if (!cpuid_feature())
return;
+ cpuid_scan_cpu(c);
cpu_detect(c);
-
get_cpu_vendor(c);
intel_unlock_cpuid_leafs(c);
get_cpu_cap(c);
@@ -2007,6 +2009,7 @@ static void identify_cpu(struct cpuinfo_x86 *c)
#endif
c->x86_cache_alignment = c->x86_clflush_size;
memset(&c->x86_capability, 0, sizeof(c->x86_capability));
+ memset(&c->cpuid, 0, sizeof(c->cpuid));
#ifdef CONFIG_X86_VMX_FEATURE_NAMES
memset(&c->vmx_capability, 0, sizeof(c->vmx_capability));
#endif
diff --git a/arch/x86/kernel/cpu/cpuid_parser.c b/arch/x86/kernel/cpu/cpuid_parser.c
new file mode 100644
index 000000000000..898b0c441431
--- /dev/null
+++ b/arch/x86/kernel/cpu/cpuid_parser.c
@@ -0,0 +1,182 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * CPUID parser; for populating the system's CPUID tables.
+ */
+
+#include <linux/kernel.h>
+
+#include <asm/cpuid/api.h>
+#include <asm/processor.h>
+
+#include "cpuid_parser.h"
+
+/* Clear a single CPUID table entry */
+static void cpuid_clear(const struct cpuid_parse_entry *e, const struct cpuid_read_output *output)
+{
+ struct cpuid_regs *regs = output->regs;
+
+ for (int i = 0; i < e->maxcnt; i++, regs++)
+ memset(regs, 0, sizeof(*regs));
+
+ memset(output->info, 0, sizeof(*output->info));
+}
+
+/*
+ * Leaf read functions:
+ */
+
+/*
+ * Default CPUID read function
+ * Satisfies the requirements stated at 'struct cpuid_parse_entry'->read().
+ */
+static void
+cpuid_read_generic(const struct cpuid_parse_entry *e, const struct cpuid_read_output *output)
+{
+ struct cpuid_regs *regs = output->regs;
+
+ for (int i = 0; i < e->maxcnt; i++, regs++, output->info->nr_entries++)
+ cpuid_read_subleaf(e->leaf, e->subleaf + i, regs);
+}
+
+/*
+ * CPUID parser table:
+ */
+
+static const struct cpuid_parse_entry cpuid_parse_entries[] = {
+ CPUID_PARSE_ENTRIES
+};
+
+/*
+ * Leaf-independent parser code:
+ */
+
+static unsigned int cpuid_range_max_leaf(const struct cpuid_table *t, unsigned int range)
+{
+ const struct leaf_0x0_0 *l0 = __cpuid_table_subleaf(t, 0x0, 0);
+
+ switch (range) {
+ case CPUID_BASE_START: return l0 ? l0->max_std_leaf : 0;
+ default: return 0;
+ }
+}
+
+static void
+__cpuid_reset_table(struct cpuid_table *t, const struct cpuid_parse_entry entries[],
+ unsigned int nr_entries, unsigned int start, unsigned int end, bool fill)
+{
+ const struct cpuid_parse_entry *entry = entries;
+ unsigned int range = CPUID_RANGE(start);
+
+ for (unsigned int i = 0; i < nr_entries; i++, entry++) {
+ struct cpuid_read_output output = {
+ .regs = cpuid_table_regs_p(t, entry->regs_offs),
+ .info = cpuid_table_info_p(t, entry->info_offs),
+ };
+
+ if (entry->leaf < start || entry->leaf > end)
+ continue;
+
+ cpuid_clear(entry, &output);
+
+ /*
+ * Read the range's anchor leaf unconditionally so that the cached
+ * maximum valid leaf value is available for the remaining entries.
+ */
+ if (fill && (entry->leaf == range || entry->leaf <= cpuid_range_max_leaf(t, range)))
+ entry->read(entry, &output);
+ }
+}
+
+/*
+ * Zero all cached CPUID entries within [@start-@end] range. This is needed when
+ * certain operations like MSR writes induce changes to the CPU's CPUID layout.
+ */
+static void
+__cpuid_zero_table(struct cpuid_table *t, const struct cpuid_parse_entry entries[],
+ unsigned int nr_entries, unsigned int start, unsigned int end)
+{
+ __cpuid_reset_table(t, entries, nr_entries, start, end, false);
+}
+
+static void
+__cpuid_fill_table(struct cpuid_table *t, const struct cpuid_parse_entry entries[],
+ unsigned int nr_entries, unsigned int start, unsigned int end)
+{
+ __cpuid_reset_table(t, entries, nr_entries, start, end, true);
+}
+
+static void
+cpuid_fill_table(struct cpuid_table *t, const struct cpuid_parse_entry entries[], unsigned int nr_entries)
+{
+ static const struct {
+ unsigned int start;
+ unsigned int end;
+ } ranges[] = {
+ { CPUID_BASE_START, CPUID_BASE_END },
+ };
+
+ for (unsigned int i = 0; i < ARRAY_SIZE(ranges); i++)
+ __cpuid_fill_table(t, entries, nr_entries, ranges[i].start, ranges[i].end);
+}
+
+static void __cpuid_scan_cpu_full(struct cpuinfo_x86 *c)
+{
+ unsigned int nr_entries = ARRAY_SIZE(cpuid_parse_entries);
+ struct cpuid_table *table = &c->cpuid;
+
+ cpuid_fill_table(table, cpuid_parse_entries, nr_entries);
+}
+
+static void
+__cpuid_scan_cpu_partial(struct cpuinfo_x86 *c, unsigned int start_leaf, unsigned int end_leaf)
+{
+ unsigned int nr_entries = ARRAY_SIZE(cpuid_parse_entries);
+ struct cpuid_table *table = &c->cpuid;
+
+ __cpuid_zero_table(table, cpuid_parse_entries, nr_entries, start_leaf, end_leaf);
+ __cpuid_fill_table(table, cpuid_parse_entries, nr_entries, start_leaf, end_leaf);
+}
+
+/*
+ * Call-site APIs:
+ */
+
+/**
+ * cpuid_scan_cpu() - Populate current CPU's CPUID table
+ * @c: CPU capability structure associated with the current CPU
+ *
+ * Populate the CPUID table embedded within @c with parsed CPUID data. All CPUID
+ * instructions are invoked locally, so this must be called on the CPU associated
+ * with @c.
+ */
+void cpuid_scan_cpu(struct cpuinfo_x86 *c)
+{
+ __cpuid_scan_cpu_full(c);
+}
+
+/**
+ * cpuid_refresh_range() - Rescan a CPUID table's leaf range
+ * @c: CPU capability structure associated with the current CPU
+ * @start: Start of leaf range to be re-scanned
+ * @end: End of leaf range
+ */
+void cpuid_refresh_range(struct cpuinfo_x86 *c, u32 start, u32 end)
+{
+ if (WARN_ON_ONCE(start > end))
+ return;
+
+ if (WARN_ON_ONCE(CPUID_RANGE(start) != CPUID_RANGE(end)))
+ return;
+
+ __cpuid_scan_cpu_partial(c, start, end);
+}
+
+/**
+ * cpuid_refresh_leaf() - Rescan a CPUID table's leaf
+ * @c: CPU capability structure associated with the current CPU
+ * @leaf: Leaf to be re-scanned
+ */
+void cpuid_refresh_leaf(struct cpuinfo_x86 *c, u32 leaf)
+{
+ cpuid_refresh_range(c, leaf, leaf);
+}
diff --git a/arch/x86/kernel/cpu/cpuid_parser.h b/arch/x86/kernel/cpu/cpuid_parser.h
new file mode 100644
index 000000000000..df627306cc8c
--- /dev/null
+++ b/arch/x86/kernel/cpu/cpuid_parser.h
@@ -0,0 +1,120 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef _ARCH_X86_CPUID_PARSER_H
+#define _ARCH_X86_CPUID_PARSER_H
+
+#include <asm/cpuid/types.h>
+
+/*
+ * Since accessing the CPUID leaves at 'struct cpuid_leaves' require compile time
+ * tokenization, split the CPUID parser into two stages: compile time macros for
+ * tokenizing the leaf/subleaf output offsets within the table, and generic runtime
+ * code to write to the relevant CPUID leaves using such offsets.
+ *
+ * The output of the compile time macros is cached by a compile time "parse entry"
+ * table (see 'struct cpuid_parse_entry'). The runtime parser code will utilize
+ * such offsets by passing them to the cpuid_table_*_p() functions.
+ */
+
+/*
+ * Compile time CPUID table offset calculations:
+ *
+ * @_leaf: CPUID leaf, in 0xN format
+ * @_subleaf: CPUID subleaf, in decimal format
+ */
+
+#define __cpuid_leaves_regs_offset(_leaf, _subleaf) \
+ offsetof(struct cpuid_leaves, leaf_ ## _leaf ## _ ## _subleaf)
+
+#define __cpuid_leaves_info_offset(_leaf, _subleaf) \
+ offsetof(struct cpuid_leaves, leaf_ ## _leaf ## _ ## _subleaf ## _ ## info)
+
+#define __cpuid_leaves_regs_maxcnt(_leaf, _subleaf) \
+ ARRAY_SIZE(((struct cpuid_leaves *)NULL)->leaf_ ## _leaf ## _ ## _subleaf)
+
+/*
+ * Translation of compile time offsets to generic runtime pointers:
+ */
+
+static inline struct cpuid_regs *
+cpuid_table_regs_p(const struct cpuid_table *t, unsigned long regs_offset)
+{
+ return (struct cpuid_regs *)((unsigned long)(&t->leaves) + regs_offset);
+}
+
+static inline struct leaf_parse_info *
+cpuid_table_info_p(const struct cpuid_table *t, unsigned long info_offset)
+{
+ return (struct leaf_parse_info *)((unsigned long)(&t->leaves) + info_offset);
+}
+
+/**
+ * struct cpuid_read_output - Output of a CPUID read operation
+ * @regs: Pointer to an array of CPUID outputs, where each array element covers the
+ * full EAX->EDX output range.
+ * @info: Pointer to query info; for saving the number of filled elements at @regs.
+ *
+ * A CPUID parser read function like cpuid_read_generic() or cpuid_read_0xN() uses this
+ * structure to save the CPUID query outputs. Actual storage for @regs and @info is
+ * provided by the read function caller, and is typically within the CPU's CPUID table.
+ *
+ * See struct cpuid_parse_entry.read().
+ */
+struct cpuid_read_output {
+ struct cpuid_regs *regs;
+ struct leaf_parse_info *info;
+};
+
+/**
+ * struct cpuid_parse_entry - CPUID parse table entry
+ * @leaf: Leaf number to be parsed
+ * @subleaf: Subleaf number to be parsed
+ * @regs_offs: Offset within 'struct cpuid_leaves' for saving the CPUID query output; to be
+ * passed to cpuid_table_regs_p().
+ * @info_offs: Offset within 'struct cpuid_leaves' for saving the CPUID query parse info; to be
+ * passed to cpuid_table_info_p().
+ * @maxcnt: Maximum number of output storage entries available for the CPUID query.
+ * @read: Read function for this entry. It must save the parsed CPUID output to the passed
+ * 'struct cpuid_read_output'->regs array of size >= @maxcnt. It must set
+ * 'struct cpuid_read_output'->info.nr_entries to the number of CPUID output entries
+ * parsed and filled. A generic implementation is provided at cpuid_read_generic().
+ */
+struct cpuid_parse_entry {
+ unsigned int leaf;
+ unsigned int subleaf;
+ unsigned int regs_offs;
+ unsigned int info_offs;
+ unsigned int maxcnt;
+ void (*read)(const struct cpuid_parse_entry *e, const struct cpuid_read_output *o);
+};
+
+#define __CPUID_PARSE_ENTRY(_leaf, _subleaf, _suffix, _reader_fn) \
+ { \
+ .leaf = _leaf, \
+ .subleaf = _subleaf, \
+ .regs_offs = __cpuid_leaves_regs_offset(_leaf, _suffix), \
+ .info_offs = __cpuid_leaves_info_offset(_leaf, _suffix), \
+ .maxcnt = __cpuid_leaves_regs_maxcnt(_leaf, _suffix), \
+ .read = cpuid_read_ ## _reader_fn, \
+ }
+
+/*
+ * CPUID_PARSE_ENTRY_N() is for parsing CPUID leaves with a subleaf range.
+ * Check <asm/cpuid/types.h> __CPUID_LEAF() vs. CPUID_LEAF_N().
+ */
+
+#define CPUID_PARSE_ENTRY(_leaf, _subleaf, _reader_fn) \
+ __CPUID_PARSE_ENTRY(_leaf, _subleaf, _subleaf, _reader_fn)
+
+#define CPUID_PARSE_ENTRY_N(_leaf, _reader_fn) \
+ __CPUID_PARSE_ENTRY(_leaf, __cpuid_leaf_first_subleaf(_leaf), n, _reader_fn)
+
+/*
+ * CPUID parser table:
+ */
+
+#define CPUID_PARSE_ENTRIES \
+ /* Leaf Subleaf Reader function */ \
+ CPUID_PARSE_ENTRY ( 0x0, 0, generic ), \
+ CPUID_PARSE_ENTRY ( 0x1, 0, generic ), \
+
+#endif /* _ARCH_X86_CPUID_PARSER_H */
diff --git a/arch/x86/xen/enlighten.c b/arch/x86/xen/enlighten.c
index 23b91bf9b663..cf061ed45ce8 100644
--- a/arch/x86/xen/enlighten.c
+++ b/arch/x86/xen/enlighten.c
@@ -17,7 +17,7 @@
#include <asm/xen/hypercall.h>
#include <asm/xen/hypervisor.h>
#include <asm/cpu.h>
-#include <asm/e820/api.h>
+#include <asm/e820/api.h>
#include <asm/setup.h>
#include "xen-ops.h"
@@ -76,6 +76,7 @@ unsigned long xen_released_pages;
static __ref void xen_get_vendor(void)
{
init_cpu_devs();
+ cpuid_scan_cpu(&boot_cpu_data);
cpu_detect(&boot_cpu_data);
get_cpu_vendor(&boot_cpu_data);
}
diff --git a/arch/x86/xen/enlighten_pv.c b/arch/x86/xen/enlighten_pv.c
index eaad22b47206..033b09714d48 100644
--- a/arch/x86/xen/enlighten_pv.c
+++ b/arch/x86/xen/enlighten_pv.c
@@ -1433,6 +1433,7 @@ asmlinkage __visible void __init xen_start_kernel(struct start_info *si)
xen_build_dynamic_phys_to_machine();
/* Work out if we support NX */
+ cpuid_scan_cpu(&boot_cpu_data);
get_cpu_cap(&boot_cpu_data);
x86_configure_nx();
--
2.53.0
^ permalink raw reply related [flat|nested] 101+ messages in thread
* [PATCH v6 10/90] x86/cpu: Rescan CPUID table after disabling PSN
2026-03-27 2:15 [PATCH v6 00/90] x86: Introduce a centralized CPUID data model Ahmed S. Darwish
` (8 preceding siblings ...)
2026-03-27 2:15 ` [PATCH v6 09/90] x86/cpuid: Introduce a centralized CPUID parser Ahmed S. Darwish
@ 2026-03-27 2:15 ` Ahmed S. Darwish
2026-03-27 2:15 ` [PATCH v6 11/90] x86/cpu: centaur/zhaoxin: Rescan CPUID(0xc0000001) after MSR writes Ahmed S. Darwish
` (81 subsequent siblings)
91 siblings, 0 replies; 101+ messages in thread
From: Ahmed S. Darwish @ 2026-03-27 2:15 UTC (permalink / raw)
To: Borislav Petkov, Dave Hansen, Ingo Molnar
Cc: Thomas Gleixner, Andrew Cooper, H. Peter Anvin,
Sean Christopherson, David Woodhouse, Peter Zijlstra,
Christian Ludloff, Sohil Mehta, John Ogness, x86, x86-cpuid, LKML,
Ahmed S. Darwish
On Pentium-III and Transmeta CPUs, disabling the CPUID(0x3) Processor
Serial Number (PSN) can affect the maximum valid CPUID standard leaf.
Rescan the CPU's CPUID table in that case not to have stale cached data.
Rescan only the changed CPUID leaves, not to override any of the kernel's
previously force-set or unset cached CPUID bits.
Rename squash_the_stupid_serial_number() to disable_cpu_serial_number() and
explain the rationale behind disabling the CPU's PSN.
Signed-off-by: Ahmed S. Darwish <darwi@linutronix.de>
---
arch/x86/kernel/cpu/common.c | 28 +++++++++++++++++++++-------
1 file changed, 21 insertions(+), 7 deletions(-)
diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c
index 303faa612a6c..8fd7d2f480bf 100644
--- a/arch/x86/kernel/cpu/common.c
+++ b/arch/x86/kernel/cpu/common.c
@@ -336,15 +336,19 @@ bool cpuid_feature(void)
return flag_is_changeable_p(X86_EFLAGS_ID);
}
-static void squash_the_stupid_serial_number(struct cpuinfo_x86 *c)
+/*
+ * For privacy concerns, disable legacy Intel and Transmeta CPUID(0x3)
+ * feature, Processor Serial Number, by default.
+ */
+static void disable_cpu_serial_number(struct cpuinfo_x86 *c)
{
+ const struct leaf_0x0_0 *l0;
+ unsigned int rescan_from;
unsigned long lo, hi;
if (!cpu_has(c, X86_FEATURE_PN) || !disable_x86_serial_nr)
return;
- /* Disable processor serial number: */
-
rdmsr(MSR_IA32_BBL_CR_CTL, lo, hi);
lo |= 0x200000;
wrmsr(MSR_IA32_BBL_CR_CTL, lo, hi);
@@ -352,8 +356,18 @@ static void squash_the_stupid_serial_number(struct cpuinfo_x86 *c)
pr_notice("CPU serial number disabled.\n");
clear_cpu_cap(c, X86_FEATURE_PN);
- /* Disabling the serial number may affect the cpuid level */
- c->cpuid_level = cpuid_eax(0);
+ /*
+ * Disabling CPUID(0x3) can change the maximum standard CPUID level
+ */
+
+ cpuid_refresh_leaf(c, 0x0);
+ l0 = cpuid_leaf(c, 0x0);
+ if (!l0)
+ return;
+
+ rescan_from = min_t(int, l0->max_std_leaf, c->cpuid_level) + 1;
+ cpuid_refresh_range(c, rescan_from, CPUID_BASE_END);
+ c->cpuid_level = l0->max_std_leaf;
}
static int __init x86_serial_nr_setup(char *s)
@@ -363,7 +377,7 @@ static int __init x86_serial_nr_setup(char *s)
}
__setup("serialnumber", x86_serial_nr_setup);
#else
-static inline void squash_the_stupid_serial_number(struct cpuinfo_x86 *c)
+static inline void disable_cpu_serial_number(struct cpuinfo_x86 *c)
{
}
#endif
@@ -2046,7 +2060,7 @@ static void identify_cpu(struct cpuinfo_x86 *c)
bus_lock_init();
/* Disable the PN if appropriate */
- squash_the_stupid_serial_number(c);
+ disable_cpu_serial_number(c);
setup_smep(c);
setup_smap(c);
--
2.53.0
^ permalink raw reply related [flat|nested] 101+ messages in thread
* [PATCH v6 11/90] x86/cpu: centaur/zhaoxin: Rescan CPUID(0xc0000001) after MSR writes
2026-03-27 2:15 [PATCH v6 00/90] x86: Introduce a centralized CPUID data model Ahmed S. Darwish
` (9 preceding siblings ...)
2026-03-27 2:15 ` [PATCH v6 10/90] x86/cpu: Rescan CPUID table after disabling PSN Ahmed S. Darwish
@ 2026-03-27 2:15 ` Ahmed S. Darwish
2026-03-27 2:15 ` [PATCH v6 12/90] x86/cpu/transmeta: Rescan CPUID(0x1) after capability unhide Ahmed S. Darwish
` (80 subsequent siblings)
91 siblings, 0 replies; 101+ messages in thread
From: Ahmed S. Darwish @ 2026-03-27 2:15 UTC (permalink / raw)
To: Borislav Petkov, Dave Hansen, Ingo Molnar
Cc: Thomas Gleixner, Andrew Cooper, H. Peter Anvin,
Sean Christopherson, David Woodhouse, Peter Zijlstra,
Christian Ludloff, Sohil Mehta, John Ogness, x86, x86-cpuid, LKML,
Ahmed S. Darwish
Force-enabling Centaur/Zhaoxin CPU features through MSR writes leads to the
CPUID(0xc0000001) EDX feature flags getting changed.
Rescan CPUID(0xc0000001) in that case.
Signed-off-by: Ahmed S. Darwish <darwi@linutronix.de>
---
arch/x86/kernel/cpu/centaur.c | 6 ++++--
arch/x86/kernel/cpu/zhaoxin.c | 5 +++--
2 files changed, 7 insertions(+), 4 deletions(-)
diff --git a/arch/x86/kernel/cpu/centaur.c b/arch/x86/kernel/cpu/centaur.c
index 681d2da49341..a97e38fa6a9f 100644
--- a/arch/x86/kernel/cpu/centaur.c
+++ b/arch/x86/kernel/cpu/centaur.c
@@ -44,9 +44,11 @@ static void init_c3(struct cpuinfo_x86 *c)
pr_info("CPU: Enabled h/w RNG\n");
}
- /* store Centaur Extended Feature Flags as
- * word 5 of the CPU capability bit array
+ /*
+ * Force-enabling CPU features affects the CPUID(0xc0000001)
+ * EDX feature bits. Refresh the leaf.
*/
+ cpuid_refresh_leaf(c, 0xc0000001);
c->x86_capability[CPUID_C000_0001_EDX] = cpuid_edx(0xC0000001);
}
#ifdef CONFIG_X86_32
diff --git a/arch/x86/kernel/cpu/zhaoxin.c b/arch/x86/kernel/cpu/zhaoxin.c
index 761aef5590ac..55bc656aaa95 100644
--- a/arch/x86/kernel/cpu/zhaoxin.c
+++ b/arch/x86/kernel/cpu/zhaoxin.c
@@ -46,9 +46,10 @@ static void init_zhaoxin_cap(struct cpuinfo_x86 *c)
}
/*
- * Store Extended Feature Flags as word 5 of the CPU
- * capability bit array
+ * Force-enabling CPU features affects the CPUID(0xc0000001)
+ * EDX feature bits. Refresh the leaf.
*/
+ cpuid_refresh_leaf(c, 0xc0000001);
c->x86_capability[CPUID_C000_0001_EDX] = cpuid_edx(0xC0000001);
}
--
2.53.0
^ permalink raw reply related [flat|nested] 101+ messages in thread
* [PATCH v6 12/90] x86/cpu/transmeta: Rescan CPUID(0x1) after capability unhide
2026-03-27 2:15 [PATCH v6 00/90] x86: Introduce a centralized CPUID data model Ahmed S. Darwish
` (10 preceding siblings ...)
2026-03-27 2:15 ` [PATCH v6 11/90] x86/cpu: centaur/zhaoxin: Rescan CPUID(0xc0000001) after MSR writes Ahmed S. Darwish
@ 2026-03-27 2:15 ` Ahmed S. Darwish
2026-03-27 2:15 ` [PATCH v6 13/90] x86/cpu/intel: Rescan CPUID table after leaf unlock Ahmed S. Darwish
` (79 subsequent siblings)
91 siblings, 0 replies; 101+ messages in thread
From: Ahmed S. Darwish @ 2026-03-27 2:15 UTC (permalink / raw)
To: Borislav Petkov, Dave Hansen, Ingo Molnar
Cc: Thomas Gleixner, Andrew Cooper, H. Peter Anvin,
Sean Christopherson, David Woodhouse, Peter Zijlstra,
Christian Ludloff, Sohil Mehta, John Ogness, x86, x86-cpuid, LKML,
Ahmed S. Darwish
Transmeta CPUs allow masking CPUID(0x1).EDX feature flags via MSR writes.
If a bit is cleared in the 0x80860004 MSR, its corresponding feature flag
is not reported by CPUID.
Refresh the CPUID parser's CPUID(0x1) cache while all of that MSR bits are
unmasked.
Note, the MSR 0x80860004 semantics are documented at the "BIOS Programmer's
Guide: Transmeta Crusoe Processor", dated June 14, 2002.
Signed-off-by: Ahmed S. Darwish <darwi@linutronix.de>
---
arch/x86/kernel/cpu/transmeta.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/arch/x86/kernel/cpu/transmeta.c b/arch/x86/kernel/cpu/transmeta.c
index 1fdcd69c625c..d9e0edb379b8 100644
--- a/arch/x86/kernel/cpu/transmeta.c
+++ b/arch/x86/kernel/cpu/transmeta.c
@@ -88,6 +88,7 @@ static void init_transmeta(struct cpuinfo_x86 *c)
/* Unhide possibly hidden capability flags */
rdmsr(0x80860004, cap_mask, uk);
wrmsr(0x80860004, ~0, uk);
+ cpuid_refresh_leaf(c, 0x1);
c->x86_capability[CPUID_1_EDX] = cpuid_edx(0x00000001);
wrmsr(0x80860004, cap_mask, uk);
--
2.53.0
^ permalink raw reply related [flat|nested] 101+ messages in thread
* [PATCH v6 13/90] x86/cpu/intel: Rescan CPUID table after leaf unlock
2026-03-27 2:15 [PATCH v6 00/90] x86: Introduce a centralized CPUID data model Ahmed S. Darwish
` (11 preceding siblings ...)
2026-03-27 2:15 ` [PATCH v6 12/90] x86/cpu/transmeta: Rescan CPUID(0x1) after capability unhide Ahmed S. Darwish
@ 2026-03-27 2:15 ` Ahmed S. Darwish
2026-03-27 2:15 ` [PATCH v6 14/90] x86/cpu: Use parsed CPUID(0x0) Ahmed S. Darwish
` (78 subsequent siblings)
91 siblings, 0 replies; 101+ messages in thread
From: Ahmed S. Darwish @ 2026-03-27 2:15 UTC (permalink / raw)
To: Borislav Petkov, Dave Hansen, Ingo Molnar
Cc: Thomas Gleixner, Andrew Cooper, H. Peter Anvin,
Sean Christopherson, David Woodhouse, Peter Zijlstra,
Christian Ludloff, Sohil Mehta, John Ogness, x86, x86-cpuid, LKML,
Ahmed S. Darwish
Intel CPUs have a "limit CPUID" MSR bit to limit CPUID enumeration only up
to CPUID(0x2). This can be set by old BIOSen before booting Linux.
If that MSR bit was set, refresh the cached CPUID table after clearing it.
Scan only the newly-found CPUID leaves, not to override any of the kernel's
previously force-set or unset CPUID bits.
References: 066941bd4eeb ("x86: unmask CPUID levels on Intel CPUs")
References: 0c2f6d04619e ("x86/topology/intel: Unlock CPUID before evaluating anything")
Signed-off-by: Ahmed S. Darwish <darwi@linutronix.de>
---
arch/x86/kernel/cpu/intel.c | 26 ++++++++++++++++++++------
1 file changed, 20 insertions(+), 6 deletions(-)
diff --git a/arch/x86/kernel/cpu/intel.c b/arch/x86/kernel/cpu/intel.c
index 646ff33c4651..08869fecdf30 100644
--- a/arch/x86/kernel/cpu/intel.c
+++ b/arch/x86/kernel/cpu/intel.c
@@ -183,20 +183,34 @@ static void detect_tme_early(struct cpuinfo_x86 *c)
keyid_bits);
}
+/*
+ * Intel CPUs have an MSR bit to limit CPUID enumeration to CPUID(0x2), which
+ * can be set by old BIOSes before booting Linux. Clear that bit.
+ *
+ * Scan any newly-found CPUID leaves afterwards.
+ */
void intel_unlock_cpuid_leafs(struct cpuinfo_x86 *c)
{
+ const struct leaf_0x0_0 *l0;
+ unsigned int rescan_from;
+
if (boot_cpu_data.x86_vendor != X86_VENDOR_INTEL)
return;
if (c->x86_vfm < INTEL_PENTIUM_M_DOTHAN)
return;
- /*
- * The BIOS can have limited CPUID to leaf 2, which breaks feature
- * enumeration. Unlock it and update the maximum leaf info.
- */
- if (msr_clear_bit(MSR_IA32_MISC_ENABLE, MSR_IA32_MISC_ENABLE_LIMIT_CPUID_BIT) > 0)
- c->cpuid_level = cpuid_eax(0);
+ if (msr_clear_bit(MSR_IA32_MISC_ENABLE, MSR_IA32_MISC_ENABLE_LIMIT_CPUID_BIT) <= 0)
+ return;
+
+ cpuid_refresh_leaf(c, 0x0);
+ l0 = cpuid_leaf(c, 0x0);
+ if (!l0)
+ return;
+
+ rescan_from = min_t(int, l0->max_std_leaf, c->cpuid_level) + 1;
+ cpuid_refresh_range(c, rescan_from, CPUID_BASE_END);
+ c->cpuid_level = l0->max_std_leaf;
}
static void early_init_intel(struct cpuinfo_x86 *c)
--
2.53.0
^ permalink raw reply related [flat|nested] 101+ messages in thread
* [PATCH v6 14/90] x86/cpu: Use parsed CPUID(0x0)
2026-03-27 2:15 [PATCH v6 00/90] x86: Introduce a centralized CPUID data model Ahmed S. Darwish
` (12 preceding siblings ...)
2026-03-27 2:15 ` [PATCH v6 13/90] x86/cpu/intel: Rescan CPUID table after leaf unlock Ahmed S. Darwish
@ 2026-03-27 2:15 ` Ahmed S. Darwish
2026-03-27 2:15 ` [PATCH v6 15/90] x86/lib: Add CPUID(0x1) family and model calculation Ahmed S. Darwish
` (77 subsequent siblings)
91 siblings, 0 replies; 101+ messages in thread
From: Ahmed S. Darwish @ 2026-03-27 2:15 UTC (permalink / raw)
To: Borislav Petkov, Dave Hansen, Ingo Molnar
Cc: Thomas Gleixner, Andrew Cooper, H. Peter Anvin,
Sean Christopherson, David Woodhouse, Peter Zijlstra,
Christian Ludloff, Sohil Mehta, John Ogness, x86, x86-cpuid, LKML,
Ahmed S. Darwish
Use parsed CPUID(0x0) instead of a direct CPUID query.
Signed-off-by: Ahmed S. Darwish <darwi@linutronix.de>
---
arch/x86/kernel/cpu/common.c | 14 +++++++++-----
1 file changed, 9 insertions(+), 5 deletions(-)
diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c
index 8fd7d2f480bf..882754f10a4f 100644
--- a/arch/x86/kernel/cpu/common.c
+++ b/arch/x86/kernel/cpu/common.c
@@ -940,11 +940,15 @@ void get_cpu_vendor(struct cpuinfo_x86 *c)
void cpu_detect(struct cpuinfo_x86 *c)
{
- /* Get vendor name */
- cpuid(0x00000000, (unsigned int *)&c->cpuid_level,
- (unsigned int *)&c->x86_vendor_id[0],
- (unsigned int *)&c->x86_vendor_id[8],
- (unsigned int *)&c->x86_vendor_id[4]);
+ const struct leaf_0x0_0 *l0 = cpuid_leaf(c, 0x0);
+
+ if (!l0)
+ return;
+
+ c->cpuid_level = l0->max_std_leaf;
+ *(u32 *)&c->x86_vendor_id[0] = l0->cpu_vendorid_0;
+ *(u32 *)&c->x86_vendor_id[4] = l0->cpu_vendorid_1;
+ *(u32 *)&c->x86_vendor_id[8] = l0->cpu_vendorid_2;
c->x86 = 4;
/* Intel-defined flags: level 0x00000001 */
--
2.53.0
^ permalink raw reply related [flat|nested] 101+ messages in thread
* [PATCH v6 15/90] x86/lib: Add CPUID(0x1) family and model calculation
2026-03-27 2:15 [PATCH v6 00/90] x86: Introduce a centralized CPUID data model Ahmed S. Darwish
` (13 preceding siblings ...)
2026-03-27 2:15 ` [PATCH v6 14/90] x86/cpu: Use parsed CPUID(0x0) Ahmed S. Darwish
@ 2026-03-27 2:15 ` Ahmed S. Darwish
2026-03-27 2:15 ` [PATCH v6 16/90] x86/cpu: Use parsed CPUID(0x1) Ahmed S. Darwish
` (76 subsequent siblings)
91 siblings, 0 replies; 101+ messages in thread
From: Ahmed S. Darwish @ 2026-03-27 2:15 UTC (permalink / raw)
To: Borislav Petkov, Dave Hansen, Ingo Molnar
Cc: Thomas Gleixner, Andrew Cooper, H. Peter Anvin,
Sean Christopherson, David Woodhouse, Peter Zijlstra,
Christian Ludloff, Sohil Mehta, John Ogness, x86, x86-cpuid, LKML,
Ahmed S. Darwish
The x86 library provides x86_family() and x86_model(). They take raw
CPUID(0x1) register output and calculate the CPU family and model from it.
In follow-up work, the x86 subsystem will use parsed CPUID APIs instead of
invoking direct CPUID queries. These new APIs force using the auto
generated leaf data types at <asm/cpuid/leaf_types.h>.
Introduce x86 family and model calculation functions that take these
auto-generated data types. Refactor the original code so that no logic is
duplicated.
Signed-off-by: Ahmed S. Darwish <darwi@linutronix.de>
---
arch/x86/include/asm/cpu.h | 6 +++++
arch/x86/lib/cpu.c | 45 ++++++++++++++++++++++++--------------
2 files changed, 35 insertions(+), 16 deletions(-)
diff --git a/arch/x86/include/asm/cpu.h b/arch/x86/include/asm/cpu.h
index ad235dda1ded..90902cd91335 100644
--- a/arch/x86/include/asm/cpu.h
+++ b/arch/x86/include/asm/cpu.h
@@ -7,7 +7,9 @@
#include <linux/topology.h>
#include <linux/nodemask.h>
#include <linux/percpu.h>
+
#include <asm/ibt.h>
+#include <asm/cpuid/leaf_types.h>
#ifndef CONFIG_SMP
#define cpu_physical_id(cpu) boot_cpu_physical_apicid
@@ -25,6 +27,10 @@ int mwait_usable(const struct cpuinfo_x86 *);
unsigned int x86_family(unsigned int sig);
unsigned int x86_model(unsigned int sig);
unsigned int x86_stepping(unsigned int sig);
+
+unsigned int cpuid_family(const struct leaf_0x1_0 *l);
+unsigned int cpuid_model(const struct leaf_0x1_0 *l);
+
#ifdef CONFIG_X86_BUS_LOCK_DETECT
extern void __init sld_setup(struct cpuinfo_x86 *c);
extern bool handle_user_split_lock(struct pt_regs *regs, long error_code);
diff --git a/arch/x86/lib/cpu.c b/arch/x86/lib/cpu.c
index 7ad68917a51e..4d0beeeb4885 100644
--- a/arch/x86/lib/cpu.c
+++ b/arch/x86/lib/cpu.c
@@ -1,33 +1,36 @@
// SPDX-License-Identifier: GPL-2.0-only
#include <linux/types.h>
#include <linux/export.h>
+
#include <asm/cpu.h>
+#include <asm/cpuid/leaf_types.h>
-unsigned int x86_family(unsigned int sig)
+static unsigned int __x86_family(unsigned int base_fam, unsigned int ext_fam)
{
- unsigned int x86;
+ if (base_fam == 0xf)
+ base_fam += ext_fam;
- x86 = (sig >> 8) & 0xf;
+ return base_fam;
+}
- if (x86 == 0xf)
- x86 += (sig >> 20) & 0xff;
+static unsigned int
+__x86_model(unsigned int family, unsigned int base_model, unsigned int ext_model)
+{
+ if (family >= 0x6)
+ base_model |= ext_model << 4;
- return x86;
+ return base_model;
+}
+
+unsigned int x86_family(unsigned int sig)
+{
+ return __x86_family((sig >> 8) & 0xf, (sig >> 20) & 0xff);
}
EXPORT_SYMBOL_GPL(x86_family);
unsigned int x86_model(unsigned int sig)
{
- unsigned int fam, model;
-
- fam = x86_family(sig);
-
- model = (sig >> 4) & 0xf;
-
- if (fam >= 0x6)
- model += ((sig >> 16) & 0xf) << 4;
-
- return model;
+ return __x86_model(x86_family(sig), (sig >> 4) & 0xf, (sig >> 16) & 0xf);
}
EXPORT_SYMBOL_GPL(x86_model);
@@ -36,3 +39,13 @@ unsigned int x86_stepping(unsigned int sig)
return sig & 0xf;
}
EXPORT_SYMBOL_GPL(x86_stepping);
+
+unsigned int cpuid_family(const struct leaf_0x1_0 *l)
+{
+ return __x86_family(l->base_family_id, l->ext_family);
+}
+
+unsigned int cpuid_model(const struct leaf_0x1_0 *l)
+{
+ return __x86_model(cpuid_family(l), l->base_model, l->ext_model);
+}
--
2.53.0
^ permalink raw reply related [flat|nested] 101+ messages in thread
* [PATCH v6 16/90] x86/cpu: Use parsed CPUID(0x1)
2026-03-27 2:15 [PATCH v6 00/90] x86: Introduce a centralized CPUID data model Ahmed S. Darwish
` (14 preceding siblings ...)
2026-03-27 2:15 ` [PATCH v6 15/90] x86/lib: Add CPUID(0x1) family and model calculation Ahmed S. Darwish
@ 2026-03-27 2:15 ` Ahmed S. Darwish
2026-03-27 2:15 ` [PATCH v6 17/90] x86/cpuid: Parse CPUID(0x80000000) Ahmed S. Darwish
` (75 subsequent siblings)
91 siblings, 0 replies; 101+ messages in thread
From: Ahmed S. Darwish @ 2026-03-27 2:15 UTC (permalink / raw)
To: Borislav Petkov, Dave Hansen, Ingo Molnar
Cc: Thomas Gleixner, Andrew Cooper, H. Peter Anvin,
Sean Christopherson, David Woodhouse, Peter Zijlstra,
Christian Ludloff, Sohil Mehta, John Ogness, x86, x86-cpuid, LKML,
Ahmed S. Darwish
On early boot CPU detection, use parsed CPUID(0x1) instead of a direct
CPUID query.
Beside the parser's centralization benefits, this allows using the auto
generated CPUID data types, and their C99 bitfields, instead of doing ugly
bitwise operations.
Signed-off-by: Ahmed S. Darwish <darwi@linutronix.de>
---
arch/x86/kernel/cpu/common.c | 17 +++++++----------
1 file changed, 7 insertions(+), 10 deletions(-)
diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c
index 882754f10a4f..f31746c216c9 100644
--- a/arch/x86/kernel/cpu/common.c
+++ b/arch/x86/kernel/cpu/common.c
@@ -941,6 +941,7 @@ void get_cpu_vendor(struct cpuinfo_x86 *c)
void cpu_detect(struct cpuinfo_x86 *c)
{
const struct leaf_0x0_0 *l0 = cpuid_leaf(c, 0x0);
+ const struct leaf_0x1_0 *l1 = cpuid_leaf(c, 0x1);
if (!l0)
return;
@@ -951,17 +952,13 @@ void cpu_detect(struct cpuinfo_x86 *c)
*(u32 *)&c->x86_vendor_id[8] = l0->cpu_vendorid_2;
c->x86 = 4;
- /* Intel-defined flags: level 0x00000001 */
- if (c->cpuid_level >= 0x00000001) {
- u32 junk, tfms, cap0, misc;
-
- cpuid(0x00000001, &tfms, &misc, &junk, &cap0);
- c->x86 = x86_family(tfms);
- c->x86_model = x86_model(tfms);
- c->x86_stepping = x86_stepping(tfms);
+ if (l1) {
+ c->x86 = cpuid_family(l1);
+ c->x86_model = cpuid_model(l1);
+ c->x86_stepping = l1->stepping;
- if (cap0 & (1<<19)) {
- c->x86_clflush_size = ((misc >> 8) & 0xff) * 8;
+ if (l1->clflush) {
+ c->x86_clflush_size = l1->clflush_size * 8;
c->x86_cache_alignment = c->x86_clflush_size;
}
}
--
2.53.0
^ permalink raw reply related [flat|nested] 101+ messages in thread
* [PATCH v6 17/90] x86/cpuid: Parse CPUID(0x80000000)
2026-03-27 2:15 [PATCH v6 00/90] x86: Introduce a centralized CPUID data model Ahmed S. Darwish
` (15 preceding siblings ...)
2026-03-27 2:15 ` [PATCH v6 16/90] x86/cpu: Use parsed CPUID(0x1) Ahmed S. Darwish
@ 2026-03-27 2:15 ` Ahmed S. Darwish
2026-03-27 2:15 ` [PATCH v6 18/90] x86/cpu: Use parsed CPUID(0x80000000) Ahmed S. Darwish
` (74 subsequent siblings)
91 siblings, 0 replies; 101+ messages in thread
From: Ahmed S. Darwish @ 2026-03-27 2:15 UTC (permalink / raw)
To: Borislav Petkov, Dave Hansen, Ingo Molnar
Cc: Thomas Gleixner, Andrew Cooper, H. Peter Anvin,
Sean Christopherson, David Woodhouse, Peter Zijlstra,
Christian Ludloff, Sohil Mehta, John Ogness, x86, x86-cpuid, LKML,
Ahmed S. Darwish
Add CPUID parser logic for CPUID(0x80000000).
Verify the CPUID output since legacy Intel machines without an extended
range will repeat the highest standard CPUID leaf output instead.
This verification is similar to what is done at arch/x86/kernel/head_32.S
and arch/x86/kernel/cpu/common.c.
References: 8a50e5135af0 ("x86-32: Use symbolic constants, safer CPUID when enabling EFER.NX")
References: 67ad24e6d39c ("- pre5: - Rasmus Andersen: add proper...") # Historical git
Signed-off-by: Ahmed S. Darwish <darwi@linutronix.de>
Cc: "H. Peter Anvin" <hpa@zytor.com>
Link: https://lore.kernel.org/r/d4fcfd91-cc92-4b3c-9dd2-56ecd754cecc@citrix.com
---
arch/x86/include/asm/cpuid/types.h | 4 ++++
arch/x86/kernel/cpu/cpuid_parser.c | 21 +++++++++++++++++++++
arch/x86/kernel/cpu/cpuid_parser.h | 1 +
3 files changed, 26 insertions(+)
diff --git a/arch/x86/include/asm/cpuid/types.h b/arch/x86/include/asm/cpuid/types.h
index 3d0e611c97ba..c020fb8fed59 100644
--- a/arch/x86/include/asm/cpuid/types.h
+++ b/arch/x86/include/asm/cpuid/types.h
@@ -36,7 +36,10 @@ enum cpuid_regs_idx {
#define CPUID_RANGE_MAX(idx) (CPUID_RANGE(idx) + 0xffff)
#define CPUID_BASE_START 0x00000000
+#define CPUID_EXT_START 0x80000000
+
#define CPUID_BASE_END CPUID_RANGE_MAX(CPUID_BASE_START)
+#define CPUID_EXT_END CPUID_RANGE_MAX(CPUID_EXT_START)
/*
* Types for CPUID(0x2) parsing:
@@ -203,6 +206,7 @@ struct cpuid_leaves {
/* Leaf Subleaf number (or max number of subleaves) */
CPUID_LEAF ( 0x0, 0 );
CPUID_LEAF ( 0x1, 0 );
+ CPUID_LEAF ( 0x80000000, 0 );
};
/*
diff --git a/arch/x86/kernel/cpu/cpuid_parser.c b/arch/x86/kernel/cpu/cpuid_parser.c
index 898b0c441431..2cebe15f75d4 100644
--- a/arch/x86/kernel/cpu/cpuid_parser.c
+++ b/arch/x86/kernel/cpu/cpuid_parser.c
@@ -38,6 +38,24 @@ cpuid_read_generic(const struct cpuid_parse_entry *e, const struct cpuid_read_ou
cpuid_read_subleaf(e->leaf, e->subleaf + i, regs);
}
+static void
+cpuid_read_0x80000000(const struct cpuid_parse_entry *e, const struct cpuid_read_output *output)
+{
+ struct leaf_0x80000000_0 *el0 = (struct leaf_0x80000000_0 *)output->regs;
+
+ cpuid_read_subleaf(e->leaf, e->subleaf, el0);
+
+ /*
+ * Protect against Intel 32-bit CPUs lacking an extended CPUID range. A
+ * CPUID(0x80000000) query on such machines will repeat the output of the
+ * highest standard CPUID leaf instead.
+ */
+ if (CPUID_RANGE(el0->max_ext_leaf) != CPUID_EXT_START)
+ return;
+
+ output->info->nr_entries = 1;
+}
+
/*
* CPUID parser table:
*/
@@ -53,9 +71,11 @@ static const struct cpuid_parse_entry cpuid_parse_entries[] = {
static unsigned int cpuid_range_max_leaf(const struct cpuid_table *t, unsigned int range)
{
const struct leaf_0x0_0 *l0 = __cpuid_table_subleaf(t, 0x0, 0);
+ const struct leaf_0x80000000_0 *el0 = __cpuid_table_subleaf(t, 0x80000000, 0);
switch (range) {
case CPUID_BASE_START: return l0 ? l0->max_std_leaf : 0;
+ case CPUID_EXT_START: return el0 ? el0->max_ext_leaf : 0;
default: return 0;
}
}
@@ -113,6 +133,7 @@ cpuid_fill_table(struct cpuid_table *t, const struct cpuid_parse_entry entries[]
unsigned int end;
} ranges[] = {
{ CPUID_BASE_START, CPUID_BASE_END },
+ { CPUID_EXT_START, CPUID_EXT_END },
};
for (unsigned int i = 0; i < ARRAY_SIZE(ranges); i++)
diff --git a/arch/x86/kernel/cpu/cpuid_parser.h b/arch/x86/kernel/cpu/cpuid_parser.h
index df627306cc8c..7d41bde0c0ec 100644
--- a/arch/x86/kernel/cpu/cpuid_parser.h
+++ b/arch/x86/kernel/cpu/cpuid_parser.h
@@ -116,5 +116,6 @@ struct cpuid_parse_entry {
/* Leaf Subleaf Reader function */ \
CPUID_PARSE_ENTRY ( 0x0, 0, generic ), \
CPUID_PARSE_ENTRY ( 0x1, 0, generic ), \
+ CPUID_PARSE_ENTRY ( 0x80000000, 0, 0x80000000 ), \
#endif /* _ARCH_X86_CPUID_PARSER_H */
--
2.53.0
^ permalink raw reply related [flat|nested] 101+ messages in thread
* [PATCH v6 18/90] x86/cpu: Use parsed CPUID(0x80000000)
2026-03-27 2:15 [PATCH v6 00/90] x86: Introduce a centralized CPUID data model Ahmed S. Darwish
` (16 preceding siblings ...)
2026-03-27 2:15 ` [PATCH v6 17/90] x86/cpuid: Parse CPUID(0x80000000) Ahmed S. Darwish
@ 2026-03-27 2:15 ` Ahmed S. Darwish
2026-03-27 2:15 ` [PATCH v6 19/90] x86/cpuid: Parse CPUID(0x80000002) to CPUID(0x80000004) Ahmed S. Darwish
` (73 subsequent siblings)
91 siblings, 0 replies; 101+ messages in thread
From: Ahmed S. Darwish @ 2026-03-27 2:15 UTC (permalink / raw)
To: Borislav Petkov, Dave Hansen, Ingo Molnar
Cc: Thomas Gleixner, Andrew Cooper, H. Peter Anvin,
Sean Christopherson, David Woodhouse, Peter Zijlstra,
Christian Ludloff, Sohil Mehta, John Ogness, x86, x86-cpuid, LKML,
Ahmed S. Darwish
At early boot code, use parsed CPUID(0x80000000) instead of invoking a
direct CPUID query.
The original code has the check:
extended_cpuid_level = ((eax & 0xffff0000) == 0x80000000) ? eax : 0;
to protect against Intel 32-bit machines without an extended range, where a
CPUID(0x80000000) query will repeat the output of the max-valid standard
CPUID leaf output.
A similar check is already done at the CPUID parser's own CPUID(0x80000000)
read function:
if (CPUID_RANGE(el0->max_ext_leaf) != CPUID_EXT_START) {
// Handle error
}
Thus, for the call-site, the parsed CPUID NULL check below:
el0 = cpuid_leaf(c, 0x80000000);
extended_cpuid_level = el0 ? el0->max_ext_leaf : 0;
is sufficient.
Signed-off-by: Ahmed S. Darwish <darwi@linutronix.de>
---
arch/x86/kernel/cpu/common.c | 8 ++------
1 file changed, 2 insertions(+), 6 deletions(-)
diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c
index f31746c216c9..204c1f65f265 100644
--- a/arch/x86/kernel/cpu/common.c
+++ b/arch/x86/kernel/cpu/common.c
@@ -1017,6 +1017,7 @@ static void init_speculation_control(struct cpuinfo_x86 *c)
void get_cpu_cap(struct cpuinfo_x86 *c)
{
+ const struct leaf_0x80000000_0 *el0 = cpuid_leaf(c, 0x80000000);
u32 eax, ebx, ecx, edx;
/* Intel-defined flags: level 0x00000001 */
@@ -1052,12 +1053,7 @@ void get_cpu_cap(struct cpuinfo_x86 *c)
c->x86_capability[CPUID_D_1_EAX] = eax;
}
- /*
- * Check if extended CPUID leaves are implemented: Max extended
- * CPUID leaf must be in the 0x80000001-0x8000ffff range.
- */
- eax = cpuid_eax(0x80000000);
- c->extended_cpuid_level = ((eax & 0xffff0000) == 0x80000000) ? eax : 0;
+ c->extended_cpuid_level = el0 ? el0->max_ext_leaf : 0;
if (c->extended_cpuid_level >= 0x80000001) {
cpuid(0x80000001, &eax, &ebx, &ecx, &edx);
--
2.53.0
^ permalink raw reply related [flat|nested] 101+ messages in thread
* [PATCH v6 19/90] x86/cpuid: Parse CPUID(0x80000002) to CPUID(0x80000004)
2026-03-27 2:15 [PATCH v6 00/90] x86: Introduce a centralized CPUID data model Ahmed S. Darwish
` (17 preceding siblings ...)
2026-03-27 2:15 ` [PATCH v6 18/90] x86/cpu: Use parsed CPUID(0x80000000) Ahmed S. Darwish
@ 2026-03-27 2:15 ` Ahmed S. Darwish
2026-03-27 2:15 ` [PATCH v6 20/90] x86/cpu: Use parsed " Ahmed S. Darwish
` (72 subsequent siblings)
91 siblings, 0 replies; 101+ messages in thread
From: Ahmed S. Darwish @ 2026-03-27 2:15 UTC (permalink / raw)
To: Borislav Petkov, Dave Hansen, Ingo Molnar
Cc: Thomas Gleixner, Andrew Cooper, H. Peter Anvin,
Sean Christopherson, David Woodhouse, Peter Zijlstra,
Christian Ludloff, Sohil Mehta, John Ogness, x86, x86-cpuid, LKML,
Ahmed S. Darwish
Add CPUID(0x80000002) => CPUID(0x80000004) support to the CPUID parser.
This allows converting their call sites to the CPUID API next.
Signed-off-by: Ahmed S. Darwish <darwi@linutronix.de>
---
arch/x86/include/asm/cpuid/types.h | 3 +++
arch/x86/kernel/cpu/cpuid_parser.h | 3 +++
2 files changed, 6 insertions(+)
diff --git a/arch/x86/include/asm/cpuid/types.h b/arch/x86/include/asm/cpuid/types.h
index c020fb8fed59..8be2c2ba874a 100644
--- a/arch/x86/include/asm/cpuid/types.h
+++ b/arch/x86/include/asm/cpuid/types.h
@@ -207,6 +207,9 @@ struct cpuid_leaves {
CPUID_LEAF ( 0x0, 0 );
CPUID_LEAF ( 0x1, 0 );
CPUID_LEAF ( 0x80000000, 0 );
+ CPUID_LEAF ( 0x80000002, 0 );
+ CPUID_LEAF ( 0x80000003, 0 );
+ CPUID_LEAF ( 0x80000004, 0 );
};
/*
diff --git a/arch/x86/kernel/cpu/cpuid_parser.h b/arch/x86/kernel/cpu/cpuid_parser.h
index 7d41bde0c0ec..3e11e13fa76c 100644
--- a/arch/x86/kernel/cpu/cpuid_parser.h
+++ b/arch/x86/kernel/cpu/cpuid_parser.h
@@ -117,5 +117,8 @@ struct cpuid_parse_entry {
CPUID_PARSE_ENTRY ( 0x0, 0, generic ), \
CPUID_PARSE_ENTRY ( 0x1, 0, generic ), \
CPUID_PARSE_ENTRY ( 0x80000000, 0, 0x80000000 ), \
+ CPUID_PARSE_ENTRY ( 0x80000002, 0, generic ), \
+ CPUID_PARSE_ENTRY ( 0x80000003, 0, generic ), \
+ CPUID_PARSE_ENTRY ( 0x80000004, 0, generic ), \
#endif /* _ARCH_X86_CPUID_PARSER_H */
--
2.53.0
^ permalink raw reply related [flat|nested] 101+ messages in thread
* [PATCH v6 20/90] x86/cpu: Use parsed CPUID(0x80000002) to CPUID(0x80000004)
2026-03-27 2:15 [PATCH v6 00/90] x86: Introduce a centralized CPUID data model Ahmed S. Darwish
` (18 preceding siblings ...)
2026-03-27 2:15 ` [PATCH v6 19/90] x86/cpuid: Parse CPUID(0x80000002) to CPUID(0x80000004) Ahmed S. Darwish
@ 2026-03-27 2:15 ` Ahmed S. Darwish
2026-03-27 2:15 ` [PATCH v6 21/90] x86/cpuid: Split parser tables and add vendor-qualified parsing Ahmed S. Darwish
` (71 subsequent siblings)
91 siblings, 0 replies; 101+ messages in thread
From: Ahmed S. Darwish @ 2026-03-27 2:15 UTC (permalink / raw)
To: Borislav Petkov, Dave Hansen, Ingo Molnar
Cc: Thomas Gleixner, Andrew Cooper, H. Peter Anvin,
Sean Christopherson, David Woodhouse, Peter Zijlstra,
Christian Ludloff, Sohil Mehta, John Ogness, x86, x86-cpuid, LKML,
Ahmed S. Darwish
For CPU brand string enumeration, use parsed CPUID(0x80000002) to
CPUID(0x80000004) instead of invoking direct CPUID queries.
This centralizes CPUID invocation to the system's CPUID parser.
Signed-off-by: Ahmed S. Darwish <darwi@linutronix.de>
---
arch/x86/kernel/cpu/common.c | 14 ++++++++------
1 file changed, 8 insertions(+), 6 deletions(-)
diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c
index 204c1f65f265..060f69ab3739 100644
--- a/arch/x86/kernel/cpu/common.c
+++ b/arch/x86/kernel/cpu/common.c
@@ -824,16 +824,18 @@ static const struct cpu_dev *cpu_devs[X86_VENDOR_NUM] = {};
static void get_model_name(struct cpuinfo_x86 *c)
{
- unsigned int *v;
+ const struct leaf_0x80000002_0 *l2 = cpuid_leaf(c, 0x80000002);
+ const struct leaf_0x80000003_0 *l3 = cpuid_leaf(c, 0x80000003);
+ const struct leaf_0x80000004_0 *l4 = cpuid_leaf(c, 0x80000004);
char *p, *q, *s;
- if (c->extended_cpuid_level < 0x80000004)
+ if (!l2 || !l3 || !l4)
return;
- v = (unsigned int *)c->x86_model_id;
- cpuid(0x80000002, &v[0], &v[1], &v[2], &v[3]);
- cpuid(0x80000003, &v[4], &v[5], &v[6], &v[7]);
- cpuid(0x80000004, &v[8], &v[9], &v[10], &v[11]);
+ *(struct leaf_0x80000002_0 *)&c->x86_model_id[0] = *l2;
+ *(struct leaf_0x80000003_0 *)&c->x86_model_id[16] = *l3;
+ *(struct leaf_0x80000004_0 *)&c->x86_model_id[32] = *l4;
+
c->x86_model_id[48] = 0;
/* Trim whitespace */
--
2.53.0
^ permalink raw reply related [flat|nested] 101+ messages in thread
* [PATCH v6 21/90] x86/cpuid: Split parser tables and add vendor-qualified parsing
2026-03-27 2:15 [PATCH v6 00/90] x86: Introduce a centralized CPUID data model Ahmed S. Darwish
` (19 preceding siblings ...)
2026-03-27 2:15 ` [PATCH v6 20/90] x86/cpu: Use parsed " Ahmed S. Darwish
@ 2026-03-27 2:15 ` Ahmed S. Darwish
2026-03-27 2:15 ` [PATCH v6 22/90] x86/cpuid: Introduce a parser debugfs interface Ahmed S. Darwish
` (70 subsequent siblings)
91 siblings, 0 replies; 101+ messages in thread
From: Ahmed S. Darwish @ 2026-03-27 2:15 UTC (permalink / raw)
To: Borislav Petkov, Dave Hansen, Ingo Molnar
Cc: Thomas Gleixner, Andrew Cooper, H. Peter Anvin,
Sean Christopherson, David Woodhouse, Peter Zijlstra,
Christian Ludloff, Sohil Mehta, John Ogness, x86, x86-cpuid, LKML,
Ahmed S. Darwish
For the CPUID parser, introduce a table listing vendor-specific CPUID
leaves. Not all CPUID leaves should be queried on all x86 vendors, so the
parser will enumerate such leaves only if the boot machine's x86 vendor is
listed as supported.
This provides the following benefits:
(a) Even when a CPUID leaf falls within the CPU's standard or extended
maximum leaf range, querying architecturally unsupported and reserved
CPUID leaves may trigger new kernel boot behaviors or subtle bugs;
especially on legacy machines.
(b) Associating x86 vendor information with CPUID leaves will enable the
CPUID parser to emit (lightweight) error messages when malformed CPUID
leaf output is detected. This is due to the parser now being more
certain that the queried leaf is valid on the machine.
(c) Attaching x86 vendor information to CPUID leaves will relieve call
sites, especially drivers, from ugly x86 vendor checks before querying a
CPUID leaf. Just checking if the CPUID APIs did not return NULL will be
sufficient.
Split the CPUID parsing table into an "early boot" table and a standard
one. The early boot phase parses only CPUID(0x0) and CPUID(0x1) since they
are needed to identify the CPU's x86 vendor.
Once the x86 vendor info is saved to the CPU's capability structure, invoke
the CPUID parser again to parse the rest of the CPUID table. In that
second phase, the parser assumes that "boot_cpu_data.x86_vendor" is valid
and uses it for the CPUID leaves x86 vendor validity checks.
For each vendor-specific CPUID leaf, build its list of matching x86 vendors
using CPP varargs. Encoding this as bitflags was not doable, since the x86
vendor IDs are just raw monotonic numbers from 0 (Intel) to 11 (Vortex).
Keep the CPUID parser's leaf vendors table empty for now. Leaves like
CPUID(0x2), CPUID(0x4), CPUID(0x16), and CPUID(0x8000001d) will be added to
the parser vendor table once their support is actually implemented.
Signed-off-by: Ahmed S. Darwish <darwi@linutronix.de>
---
arch/x86/include/asm/cpuid/api.h | 1 +
arch/x86/kernel/cpu/common.c | 9 ++-
arch/x86/kernel/cpu/cpuid_parser.c | 100 +++++++++++++++++++++++++----
arch/x86/kernel/cpu/cpuid_parser.h | 52 ++++++++++++++-
arch/x86/xen/enlighten.c | 2 +-
5 files changed, 146 insertions(+), 18 deletions(-)
diff --git a/arch/x86/include/asm/cpuid/api.h b/arch/x86/include/asm/cpuid/api.h
index 82eddfa2347b..3d5a0d4918cc 100644
--- a/arch/x86/include/asm/cpuid/api.h
+++ b/arch/x86/include/asm/cpuid/api.h
@@ -532,6 +532,7 @@ static inline bool cpuid_amd_hygon_has_l3_cache(void)
* CPUID parser exported APIs:
*/
+void cpuid_scan_cpu_early(struct cpuinfo_x86 *c);
void cpuid_scan_cpu(struct cpuinfo_x86 *c);
void cpuid_refresh_leaf(struct cpuinfo_x86 *c, u32 leaf);
void cpuid_refresh_range(struct cpuinfo_x86 *c, u32 start, u32 end);
diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c
index 060f69ab3739..f7372833dd50 100644
--- a/arch/x86/kernel/cpu/common.c
+++ b/arch/x86/kernel/cpu/common.c
@@ -1019,9 +1019,11 @@ static void init_speculation_control(struct cpuinfo_x86 *c)
void get_cpu_cap(struct cpuinfo_x86 *c)
{
- const struct leaf_0x80000000_0 *el0 = cpuid_leaf(c, 0x80000000);
+ const struct leaf_0x80000000_0 *el0;
u32 eax, ebx, ecx, edx;
+ cpuid_scan_cpu(c);
+
/* Intel-defined flags: level 0x00000001 */
if (c->cpuid_level >= 0x00000001) {
cpuid(0x00000001, &eax, &ebx, &ecx, &edx);
@@ -1055,6 +1057,7 @@ void get_cpu_cap(struct cpuinfo_x86 *c)
c->x86_capability[CPUID_D_1_EAX] = eax;
}
+ el0 = cpuid_leaf(c, 0x80000000);
c->extended_cpuid_level = el0 ? el0->max_ext_leaf : 0;
if (c->extended_cpuid_level >= 0x80000001) {
@@ -1796,7 +1799,7 @@ static void __init early_identify_cpu(struct cpuinfo_x86 *c)
/* cyrix could have cpuid enabled via c_identify()*/
if (cpuid_feature()) {
- cpuid_scan_cpu(c);
+ cpuid_scan_cpu_early(c);
cpu_detect(c);
get_cpu_vendor(c);
intel_unlock_cpuid_leafs(c);
@@ -1969,7 +1972,7 @@ static void generic_identify(struct cpuinfo_x86 *c)
if (!cpuid_feature())
return;
- cpuid_scan_cpu(c);
+ cpuid_scan_cpu_early(c);
cpu_detect(c);
get_cpu_vendor(c);
intel_unlock_cpuid_leafs(c);
diff --git a/arch/x86/kernel/cpu/cpuid_parser.c b/arch/x86/kernel/cpu/cpuid_parser.c
index 2cebe15f75d4..97b7f296df03 100644
--- a/arch/x86/kernel/cpu/cpuid_parser.c
+++ b/arch/x86/kernel/cpu/cpuid_parser.c
@@ -21,6 +21,10 @@ static void cpuid_clear(const struct cpuid_parse_entry *e, const struct cpuid_re
memset(output->info, 0, sizeof(*output->info));
}
+static const struct cpuid_vendor_entry cpuid_vendor_entries[] = {
+ CPUID_VENDOR_ENTRIES
+};
+
/*
* Leaf read functions:
*/
@@ -57,17 +61,57 @@ cpuid_read_0x80000000(const struct cpuid_parse_entry *e, const struct cpuid_read
}
/*
- * CPUID parser table:
+ * CPUID parser tables:
+ *
+ * At early boot, only leaves at cpuid_early_entries[] should be parsed.
*/
-static const struct cpuid_parse_entry cpuid_parse_entries[] = {
- CPUID_PARSE_ENTRIES
+static const struct cpuid_parse_entry cpuid_early_entries[] = {
+ CPUID_EARLY_ENTRIES
+};
+
+static const struct cpuid_parse_entry cpuid_common_entries[] = {
+ CPUID_COMMON_ENTRIES
+};
+
+static const struct {
+ const struct cpuid_parse_entry *table;
+ int nr_entries;
+} cpuid_phases[] = {
+ { cpuid_early_entries, ARRAY_SIZE(cpuid_early_entries) },
+ { cpuid_common_entries, ARRAY_SIZE(cpuid_common_entries) },
};
/*
* Leaf-independent parser code:
*/
+static bool cpuid_leaf_matches_vendor(unsigned int leaf, u8 cpu_vendor)
+{
+ const struct cpuid_parse_entry *p = cpuid_early_entries;
+ const struct cpuid_vendor_entry *v = cpuid_vendor_entries;
+
+ /* Leaves in the early boot parser table are vendor agnostic */
+ for (int i = 0; i < ARRAY_SIZE(cpuid_early_entries); i++, p++)
+ if (p->leaf == leaf)
+ return true;
+
+ /* Leaves in the vendor table must pass a CPU vendor check */
+ for (int i = 0; i < ARRAY_SIZE(cpuid_vendor_entries); i++, v++) {
+ if (v->leaf != leaf)
+ continue;
+
+ for (unsigned int j = 0; j < v->nvendors; j++)
+ if (cpu_vendor == v->vendors[j])
+ return true;
+
+ return false;
+ }
+
+ /* Remaining leaves are vendor agnostic */
+ return true;
+}
+
static unsigned int cpuid_range_max_leaf(const struct cpuid_table *t, unsigned int range)
{
const struct leaf_0x0_0 *l0 = __cpuid_table_subleaf(t, 0x0, 0);
@@ -96,6 +140,9 @@ __cpuid_reset_table(struct cpuid_table *t, const struct cpuid_parse_entry entrie
if (entry->leaf < start || entry->leaf > end)
continue;
+ if (!cpuid_leaf_matches_vendor(entry->leaf, boot_cpu_data.x86_vendor))
+ continue;
+
cpuid_clear(entry, &output);
/*
@@ -140,28 +187,51 @@ cpuid_fill_table(struct cpuid_table *t, const struct cpuid_parse_entry entries[]
__cpuid_fill_table(t, entries, nr_entries, ranges[i].start, ranges[i].end);
}
-static void __cpuid_scan_cpu_full(struct cpuinfo_x86 *c)
+static void __cpuid_scan_cpu_full(struct cpuinfo_x86 *c, bool early_boot)
{
- unsigned int nr_entries = ARRAY_SIZE(cpuid_parse_entries);
+ int nphases = early_boot ? 1 : ARRAY_SIZE(cpuid_phases);
struct cpuid_table *table = &c->cpuid;
- cpuid_fill_table(table, cpuid_parse_entries, nr_entries);
+ for (int i = 0; i < nphases; i++)
+ cpuid_fill_table(table, cpuid_phases[i].table, cpuid_phases[i].nr_entries);
}
static void
-__cpuid_scan_cpu_partial(struct cpuinfo_x86 *c, unsigned int start_leaf, unsigned int end_leaf)
+__cpuid_scan_cpu_partial(struct cpuinfo_x86 *c, bool early_boot, unsigned int start_leaf, unsigned int end_leaf)
{
- unsigned int nr_entries = ARRAY_SIZE(cpuid_parse_entries);
+ int nphases = early_boot ? 1 : ARRAY_SIZE(cpuid_phases);
struct cpuid_table *table = &c->cpuid;
- __cpuid_zero_table(table, cpuid_parse_entries, nr_entries, start_leaf, end_leaf);
- __cpuid_fill_table(table, cpuid_parse_entries, nr_entries, start_leaf, end_leaf);
+ for (int i = 0; i < nphases; i++) {
+ const struct cpuid_parse_entry *entries = cpuid_phases[i].table;
+ unsigned int nr_entries = cpuid_phases[i].nr_entries;
+
+ __cpuid_zero_table(table, entries, nr_entries, start_leaf, end_leaf);
+ __cpuid_fill_table(table, entries, nr_entries, start_leaf, end_leaf);
+ }
}
/*
* Call-site APIs:
*/
+/**
+ * cpuid_scan_cpu_early() - Populate CPUID table on early boot
+ * @c: CPU capability structure associated with the current CPU
+ *
+ * Populate the CPUID table embedded within @c with parsed CPUID data.
+ *
+ * This must be called at early boot, so that early boot code can identify the
+ * CPU's x86 vendor. Only CPUID(0x0) and CPUID(0x1) are parsed.
+ *
+ * cpuid_scan_cpu() must be called later to complete the CPUID table. That is,
+ * after saving the x86 vendor info to the CPU capability structure @c.
+ */
+void cpuid_scan_cpu_early(struct cpuinfo_x86 *c)
+{
+ __cpuid_scan_cpu_full(c, true);
+}
+
/**
* cpuid_scan_cpu() - Populate current CPU's CPUID table
* @c: CPU capability structure associated with the current CPU
@@ -169,10 +239,12 @@ __cpuid_scan_cpu_partial(struct cpuinfo_x86 *c, unsigned int start_leaf, unsigne
* Populate the CPUID table embedded within @c with parsed CPUID data. All CPUID
* instructions are invoked locally, so this must be called on the CPU associated
* with @c.
+ *
+ * cpuid_scan_cpu_early() must have been called earlier on @c.
*/
void cpuid_scan_cpu(struct cpuinfo_x86 *c)
{
- __cpuid_scan_cpu_full(c);
+ __cpuid_scan_cpu_full(c, false);
}
/**
@@ -180,6 +252,8 @@ void cpuid_scan_cpu(struct cpuinfo_x86 *c)
* @c: CPU capability structure associated with the current CPU
* @start: Start of leaf range to be re-scanned
* @end: End of leaf range
+ *
+ * cpuid_scan_cpu_early() must have been called earlier on @c.
*/
void cpuid_refresh_range(struct cpuinfo_x86 *c, u32 start, u32 end)
{
@@ -189,13 +263,15 @@ void cpuid_refresh_range(struct cpuinfo_x86 *c, u32 start, u32 end)
if (WARN_ON_ONCE(CPUID_RANGE(start) != CPUID_RANGE(end)))
return;
- __cpuid_scan_cpu_partial(c, start, end);
+ __cpuid_scan_cpu_partial(c, false, start, end);
}
/**
* cpuid_refresh_leaf() - Rescan a CPUID table's leaf
* @c: CPU capability structure associated with the current CPU
* @leaf: Leaf to be re-scanned
+ *
+ * cpuid_scan_cpu_early() must have been called earlier on @c.
*/
void cpuid_refresh_leaf(struct cpuinfo_x86 *c, u32 leaf)
{
diff --git a/arch/x86/kernel/cpu/cpuid_parser.h b/arch/x86/kernel/cpu/cpuid_parser.h
index 3e11e13fa76c..a3f7dcc6c03f 100644
--- a/arch/x86/kernel/cpu/cpuid_parser.h
+++ b/arch/x86/kernel/cpu/cpuid_parser.h
@@ -2,6 +2,7 @@
#ifndef _ARCH_X86_CPUID_PARSER_H
#define _ARCH_X86_CPUID_PARSER_H
+#include <linux/types.h>
#include <asm/cpuid/types.h>
/*
@@ -109,16 +110,63 @@ struct cpuid_parse_entry {
__CPUID_PARSE_ENTRY(_leaf, __cpuid_leaf_first_subleaf(_leaf), n, _reader_fn)
/*
- * CPUID parser table:
+ * CPUID parser tables:
*/
-#define CPUID_PARSE_ENTRIES \
+/*
+ * Early-boot CPUID leaves (to be parsed before x86 vendor detection)
+ *
+ * These leaves must be parsed at early boot to identify the x86 vendor. The
+ * parser treats them as universally valid across all vendors.
+ *
+ * At early boot, only leaves in this table must be parsed. For all other
+ * leaves, the CPUID parser will assume that "boot_cpu_data.x86_vendor" is
+ * properly set beforehand.
+ *
+ * Note: If these entries are to be modified, please adapt the kernel-doc of
+ * cpuid_scan_cpu_early() accordingly.
+ */
+#define CPUID_EARLY_ENTRIES \
/* Leaf Subleaf Reader function */ \
CPUID_PARSE_ENTRY ( 0x0, 0, generic ), \
CPUID_PARSE_ENTRY ( 0x1, 0, generic ), \
+
+/*
+ * Common CPUID leaves
+ *
+ * These leaves can be parsed once basic x86 vendor detection is in place.
+ * Further vendor-agnostic leaves, which are not needed at early boot, are also
+ * listed here.
+ *
+ * For vendor-specific leaves, a matching entry must be added to the CPUID leaf
+ * vendor table later defined. Leaves which are here, but without a matching
+ * vendor entry, are treated by the CPUID parser as valid for all x86 vendors.
+ */
+#define CPUID_COMMON_ENTRIES \
+ /* Leaf Subleaf Reader function */ \
CPUID_PARSE_ENTRY ( 0x80000000, 0, 0x80000000 ), \
CPUID_PARSE_ENTRY ( 0x80000002, 0, generic ), \
CPUID_PARSE_ENTRY ( 0x80000003, 0, generic ), \
CPUID_PARSE_ENTRY ( 0x80000004, 0, generic ), \
+/*
+ * CPUID leaf vendor table:
+ */
+
+struct cpuid_vendor_entry {
+ unsigned int leaf;
+ u8 vendors[X86_VENDOR_NUM];
+ u8 nvendors;
+};
+
+#define CPUID_VENDOR_ENTRY(_leaf, ...) \
+ { \
+ .leaf = _leaf, \
+ .vendors = { __VA_ARGS__ }, \
+ .nvendors = (sizeof((u8[]){__VA_ARGS__})/sizeof(u8)), \
+ }
+
+#define CPUID_VENDOR_ENTRIES \
+ /* Leaf Vendor list */ \
+
#endif /* _ARCH_X86_CPUID_PARSER_H */
diff --git a/arch/x86/xen/enlighten.c b/arch/x86/xen/enlighten.c
index cf061ed45ce8..b8444fdf77dc 100644
--- a/arch/x86/xen/enlighten.c
+++ b/arch/x86/xen/enlighten.c
@@ -76,7 +76,7 @@ unsigned long xen_released_pages;
static __ref void xen_get_vendor(void)
{
init_cpu_devs();
- cpuid_scan_cpu(&boot_cpu_data);
+ cpuid_scan_cpu_early(&boot_cpu_data);
cpu_detect(&boot_cpu_data);
get_cpu_vendor(&boot_cpu_data);
}
--
2.53.0
^ permalink raw reply related [flat|nested] 101+ messages in thread
* [PATCH v6 22/90] x86/cpuid: Introduce a parser debugfs interface
2026-03-27 2:15 [PATCH v6 00/90] x86: Introduce a centralized CPUID data model Ahmed S. Darwish
` (20 preceding siblings ...)
2026-03-27 2:15 ` [PATCH v6 21/90] x86/cpuid: Split parser tables and add vendor-qualified parsing Ahmed S. Darwish
@ 2026-03-27 2:15 ` Ahmed S. Darwish
2026-03-27 2:15 ` [PATCH v6 23/90] x86/cpuid: Parse CPUID(0x16) Ahmed S. Darwish
` (69 subsequent siblings)
91 siblings, 0 replies; 101+ messages in thread
From: Ahmed S. Darwish @ 2026-03-27 2:15 UTC (permalink / raw)
To: Borislav Petkov, Dave Hansen, Ingo Molnar
Cc: Thomas Gleixner, Andrew Cooper, H. Peter Anvin,
Sean Christopherson, David Woodhouse, Peter Zijlstra,
Christian Ludloff, Sohil Mehta, John Ogness, x86, x86-cpuid, LKML,
Ahmed S. Darwish
Introduce the debugfs files "x86/cpuid/[0-ncpus]" to dump each CPU's cached
CPUID table. For each cached leaf/subleaf, invoke the CPUID instruction on
the target CPU and compare the hardware result against its cached values.
Mark any mismatched cached CPUID output value with an asterisk. This
should help with tricky bug reports in the future if the cached CPUID data
get unexpectedly out of sync with actual hardware state.
Note, expose cpuid_phases[] via "cpuid_parser.h" to allow the debugfs code
to traverse and dump parsed CPUID data.
Note, this debugfs interface also simplifies the development and testing of
adding new leaves to the CPUID parser.
Signed-off-by: Ahmed S. Darwish <darwi@linutronix.de>
---
arch/x86/kernel/cpu/Makefile | 2 +-
arch/x86/kernel/cpu/cpuid_debugfs.c | 108 ++++++++++++++++++++++++++++
arch/x86/kernel/cpu/cpuid_parser.c | 9 ++-
arch/x86/kernel/cpu/cpuid_parser.h | 12 ++++
4 files changed, 125 insertions(+), 6 deletions(-)
create mode 100644 arch/x86/kernel/cpu/cpuid_debugfs.c
diff --git a/arch/x86/kernel/cpu/Makefile b/arch/x86/kernel/cpu/Makefile
index d2e8a849f180..d62e2d60a965 100644
--- a/arch/x86/kernel/cpu/Makefile
+++ b/arch/x86/kernel/cpu/Makefile
@@ -62,7 +62,7 @@ obj-$(CONFIG_HYPERVISOR_GUEST) += vmware.o hypervisor.o mshyperv.o
obj-$(CONFIG_BHYVE_GUEST) += bhyve.o
obj-$(CONFIG_ACRN_GUEST) += acrn.o
-obj-$(CONFIG_DEBUG_FS) += debugfs.o
+obj-$(CONFIG_DEBUG_FS) += debugfs.o cpuid_debugfs.o
obj-$(CONFIG_X86_BUS_LOCK_DETECT) += bus_lock.o
diff --git a/arch/x86/kernel/cpu/cpuid_debugfs.c b/arch/x86/kernel/cpu/cpuid_debugfs.c
new file mode 100644
index 000000000000..4bd874bffffc
--- /dev/null
+++ b/arch/x86/kernel/cpu/cpuid_debugfs.c
@@ -0,0 +1,108 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * CPUID parser debugfs entries: x86/cpuid/[0-ncpus]
+ *
+ * Dump each CPU's cached CPUID table and compare its values against current
+ * CPUID output on that CPU. Mark changed entries with an asterisk.
+ */
+
+#include <linux/debugfs.h>
+#include <linux/init.h>
+#include <linux/smp.h>
+#include <linux/types.h>
+
+#include <asm/cpuid/api.h>
+#include <asm/percpu.h>
+#include <asm/processor.h>
+
+#include "cpuid_parser.h"
+
+static void cpuid_this_cpu(void *info)
+{
+ struct cpuid_regs *regs = info;
+
+ __cpuid(®s->eax, ®s->ebx, ®s->ecx, ®s->edx);
+}
+
+static void
+cpuid_show_leaf(struct seq_file *m, uintptr_t cpu_id, const struct cpuid_parse_entry *entry,
+ const struct leaf_parse_info *info, const struct cpuid_regs *cached)
+{
+ for (int j = 0; j < info->nr_entries; j++) {
+ u32 subleaf = entry->subleaf + j;
+ struct cpuid_regs regs = {
+ .eax = entry->leaf,
+ .ecx = subleaf,
+ };
+ int ret;
+
+ seq_printf(m, "Leaf 0x%08x, subleaf %u:\n", entry->leaf, subleaf);
+
+ ret = smp_call_function_single(cpu_id, cpuid_this_cpu, ®s, true);
+ if (ret) {
+ seq_printf(m, "Failed to invoke CPUID on CPU %lu: %d\n\n", cpu_id, ret);
+ continue;
+ }
+
+ seq_printf(m, " cached: %cEAX=0x%08x %cEBX=0x%08x %cECX=0x%08x %cEDX=0x%08x\n",
+ cached[j].eax == regs.eax ? ' ' : '*', cached[j].eax,
+ cached[j].ebx == regs.ebx ? ' ' : '*', cached[j].ebx,
+ cached[j].ecx == regs.ecx ? ' ' : '*', cached[j].ecx,
+ cached[j].edx == regs.edx ? ' ' : '*', cached[j].edx);
+ seq_printf(m, " actual: EAX=0x%08x EBX=0x%08x ECX=0x%08x EDX=0x%08x\n",
+ regs.eax, regs.ebx, regs.ecx, regs.edx);
+ }
+}
+
+static void __cpuid_debug_show(struct seq_file *m, uintptr_t cpu_id,
+ const struct cpuid_parse_entry *entry, int nr_entries)
+{
+ const struct cpuinfo_x86 *c = per_cpu_ptr(&cpu_info, cpu_id);
+ const struct cpuid_table *t = &c->cpuid;
+
+ for (int i = 0; i < nr_entries; i++, entry++) {
+ const struct leaf_parse_info *qi = cpuid_table_info_p(t, entry->info_offs);
+ const struct cpuid_regs *qr = cpuid_table_regs_p(t, entry->regs_offs);
+
+ cpuid_show_leaf(m, cpu_id, entry, qi, qr);
+ }
+}
+
+static int cpuid_debug_show(struct seq_file *m, void *p)
+{
+ uintptr_t cpu_id = (uintptr_t)m->private;
+
+ for (int i = 0; i < cpuid_nphases; i++)
+ __cpuid_debug_show(m, cpu_id, cpuid_phases[i].table, cpuid_phases[i].nr_entries);
+
+ return 0;
+}
+
+static int cpuid_debug_open(struct inode *inode, struct file *file)
+{
+ return single_open(file, cpuid_debug_show, inode->i_private);
+}
+
+static const struct file_operations cpuid_ops = {
+ .open = cpuid_debug_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = single_release,
+};
+
+static __init int cpuid_init_debugfs(void)
+{
+ struct dentry *dir;
+ uintptr_t cpu_id;
+ char cpu_name[24];
+
+ dir = debugfs_create_dir("cpuid", arch_debugfs_dir);
+
+ for_each_possible_cpu(cpu_id) {
+ scnprintf(cpu_name, sizeof(cpu_name), "%lu", cpu_id);
+ debugfs_create_file(cpu_name, 0444, dir, (void *)cpu_id, &cpuid_ops);
+ }
+
+ return 0;
+}
+late_initcall(cpuid_init_debugfs);
diff --git a/arch/x86/kernel/cpu/cpuid_parser.c b/arch/x86/kernel/cpu/cpuid_parser.c
index 97b7f296df03..ab736f03051e 100644
--- a/arch/x86/kernel/cpu/cpuid_parser.c
+++ b/arch/x86/kernel/cpu/cpuid_parser.c
@@ -74,14 +74,13 @@ static const struct cpuid_parse_entry cpuid_common_entries[] = {
CPUID_COMMON_ENTRIES
};
-static const struct {
- const struct cpuid_parse_entry *table;
- int nr_entries;
-} cpuid_phases[] = {
+const struct cpuid_phase cpuid_phases[] = {
{ cpuid_early_entries, ARRAY_SIZE(cpuid_early_entries) },
{ cpuid_common_entries, ARRAY_SIZE(cpuid_common_entries) },
};
+const int cpuid_nphases = ARRAY_SIZE(cpuid_phases);
+
/*
* Leaf-independent parser code:
*/
@@ -189,7 +188,7 @@ cpuid_fill_table(struct cpuid_table *t, const struct cpuid_parse_entry entries[]
static void __cpuid_scan_cpu_full(struct cpuinfo_x86 *c, bool early_boot)
{
- int nphases = early_boot ? 1 : ARRAY_SIZE(cpuid_phases);
+ int nphases = early_boot ? 1 : cpuid_nphases;
struct cpuid_table *table = &c->cpuid;
for (int i = 0; i < nphases; i++)
diff --git a/arch/x86/kernel/cpu/cpuid_parser.h b/arch/x86/kernel/cpu/cpuid_parser.h
index a3f7dcc6c03f..8b0d44b745c5 100644
--- a/arch/x86/kernel/cpu/cpuid_parser.h
+++ b/arch/x86/kernel/cpu/cpuid_parser.h
@@ -149,6 +149,18 @@ struct cpuid_parse_entry {
CPUID_PARSE_ENTRY ( 0x80000003, 0, generic ), \
CPUID_PARSE_ENTRY ( 0x80000004, 0, generic ), \
+/*
+ * CPUID parser phases:
+ */
+
+struct cpuid_phase {
+ const struct cpuid_parse_entry *table;
+ int nr_entries;
+};
+
+extern const struct cpuid_phase cpuid_phases[];
+extern const int cpuid_nphases;
+
/*
* CPUID leaf vendor table:
*/
--
2.53.0
^ permalink raw reply related [flat|nested] 101+ messages in thread
* [PATCH v6 23/90] x86/cpuid: Parse CPUID(0x16)
2026-03-27 2:15 [PATCH v6 00/90] x86: Introduce a centralized CPUID data model Ahmed S. Darwish
` (21 preceding siblings ...)
2026-03-27 2:15 ` [PATCH v6 22/90] x86/cpuid: Introduce a parser debugfs interface Ahmed S. Darwish
@ 2026-03-27 2:15 ` Ahmed S. Darwish
2026-03-27 2:15 ` [PATCH v6 24/90] x86/tsc: Use parsed CPUID(0x16) Ahmed S. Darwish
` (68 subsequent siblings)
91 siblings, 0 replies; 101+ messages in thread
From: Ahmed S. Darwish @ 2026-03-27 2:15 UTC (permalink / raw)
To: Borislav Petkov, Dave Hansen, Ingo Molnar
Cc: Thomas Gleixner, Andrew Cooper, H. Peter Anvin,
Sean Christopherson, David Woodhouse, Peter Zijlstra,
Christian Ludloff, Sohil Mehta, John Ogness, x86, x86-cpuid, LKML,
Ahmed S. Darwish
Add CPUID(0x16) support to the CPUID parser. The leaf enumerates the
CPU's frequency information and is only supported on Intel machines.
This allows converting CPUID(0x16) call sites to the CPUID APIs next.
Signed-off-by: Ahmed S. Darwish <darwi@linutronix.de>
---
arch/x86/include/asm/cpuid/types.h | 1 +
arch/x86/kernel/cpu/cpuid_parser.h | 2 ++
2 files changed, 3 insertions(+)
diff --git a/arch/x86/include/asm/cpuid/types.h b/arch/x86/include/asm/cpuid/types.h
index 8be2c2ba874a..2939ad095f6c 100644
--- a/arch/x86/include/asm/cpuid/types.h
+++ b/arch/x86/include/asm/cpuid/types.h
@@ -206,6 +206,7 @@ struct cpuid_leaves {
/* Leaf Subleaf number (or max number of subleaves) */
CPUID_LEAF ( 0x0, 0 );
CPUID_LEAF ( 0x1, 0 );
+ CPUID_LEAF ( 0x16, 0 );
CPUID_LEAF ( 0x80000000, 0 );
CPUID_LEAF ( 0x80000002, 0 );
CPUID_LEAF ( 0x80000003, 0 );
diff --git a/arch/x86/kernel/cpu/cpuid_parser.h b/arch/x86/kernel/cpu/cpuid_parser.h
index 8b0d44b745c5..ee1958f3d369 100644
--- a/arch/x86/kernel/cpu/cpuid_parser.h
+++ b/arch/x86/kernel/cpu/cpuid_parser.h
@@ -144,6 +144,7 @@ struct cpuid_parse_entry {
*/
#define CPUID_COMMON_ENTRIES \
/* Leaf Subleaf Reader function */ \
+ CPUID_PARSE_ENTRY ( 0x16, 0, generic ), \
CPUID_PARSE_ENTRY ( 0x80000000, 0, 0x80000000 ), \
CPUID_PARSE_ENTRY ( 0x80000002, 0, generic ), \
CPUID_PARSE_ENTRY ( 0x80000003, 0, generic ), \
@@ -180,5 +181,6 @@ struct cpuid_vendor_entry {
#define CPUID_VENDOR_ENTRIES \
/* Leaf Vendor list */ \
+ CPUID_VENDOR_ENTRY(0x16, X86_VENDOR_INTEL), \
#endif /* _ARCH_X86_CPUID_PARSER_H */
--
2.53.0
^ permalink raw reply related [flat|nested] 101+ messages in thread
* [PATCH v6 24/90] x86/tsc: Use parsed CPUID(0x16)
2026-03-27 2:15 [PATCH v6 00/90] x86: Introduce a centralized CPUID data model Ahmed S. Darwish
` (22 preceding siblings ...)
2026-03-27 2:15 ` [PATCH v6 23/90] x86/cpuid: Parse CPUID(0x16) Ahmed S. Darwish
@ 2026-03-27 2:15 ` Ahmed S. Darwish
2026-03-27 2:15 ` [PATCH v6 25/90] x86/cpuid: Parse Transmeta and Centaur extended ranges Ahmed S. Darwish
` (67 subsequent siblings)
91 siblings, 0 replies; 101+ messages in thread
From: Ahmed S. Darwish @ 2026-03-27 2:15 UTC (permalink / raw)
To: Borislav Petkov, Dave Hansen, Ingo Molnar
Cc: Thomas Gleixner, Andrew Cooper, H. Peter Anvin,
Sean Christopherson, David Woodhouse, Peter Zijlstra,
Christian Ludloff, Sohil Mehta, John Ogness, x86, x86-cpuid, LKML,
Ahmed S. Darwish
At the x86 timestamp counter code, use parsed CPUID(0x16) access instead of
a direct CPUID query.
Beside the CPUID parser centralization benefits, this allows using the
auto-generated <asm/cpuid/leaf_types.h> data types, and their full C99
bitfields, instead of doing ugly bitwise operations on CPUID output.
Remove the "max standard level >= CPUID_LEVEL_FREQ" check since the CPUID
parser API's NULL check is equivalent.
Remove the Intel vendor check since the CPUID parser does a similar check
before caching CPUID(0x16) output. Thus the CPUID API's NULL check is also
equivalent.
Signed-off-by: Ahmed S. Darwish <darwi@linutronix.de>
---
arch/x86/kernel/tsc.c | 24 +++++-------------------
1 file changed, 5 insertions(+), 19 deletions(-)
diff --git a/arch/x86/kernel/tsc.c b/arch/x86/kernel/tsc.c
index d9aa694e43f3..bc2838d69b19 100644
--- a/arch/x86/kernel/tsc.c
+++ b/arch/x86/kernel/tsc.c
@@ -671,6 +671,7 @@ static unsigned long quick_pit_calibrate(void)
*/
unsigned long native_calibrate_tsc(void)
{
+ const struct leaf_0x16_0 *l16 = cpuid_leaf(&boot_cpu_data, 0x16);
unsigned int eax_denominator, ebx_numerator, ecx_hz, edx;
unsigned int crystal_khz;
@@ -712,13 +713,8 @@ unsigned long native_calibrate_tsc(void)
* clock, but we can easily calculate it to a high degree of accuracy
* by considering the crystal ratio and the CPU speed.
*/
- if (crystal_khz == 0 && boot_cpu_data.cpuid_level >= CPUID_LEAF_FREQ) {
- unsigned int eax_base_mhz, ebx, ecx, edx;
-
- cpuid(CPUID_LEAF_FREQ, &eax_base_mhz, &ebx, &ecx, &edx);
- crystal_khz = eax_base_mhz * 1000 *
- eax_denominator / ebx_numerator;
- }
+ if (crystal_khz == 0 && l16)
+ crystal_khz = l16->cpu_base_mhz * 1000 * eax_denominator / ebx_numerator;
if (crystal_khz == 0)
return 0;
@@ -745,19 +741,9 @@ unsigned long native_calibrate_tsc(void)
static unsigned long cpu_khz_from_cpuid(void)
{
- unsigned int eax_base_mhz, ebx_max_mhz, ecx_bus_mhz, edx;
-
- if (boot_cpu_data.x86_vendor != X86_VENDOR_INTEL)
- return 0;
-
- if (boot_cpu_data.cpuid_level < CPUID_LEAF_FREQ)
- return 0;
-
- eax_base_mhz = ebx_max_mhz = ecx_bus_mhz = edx = 0;
-
- cpuid(CPUID_LEAF_FREQ, &eax_base_mhz, &ebx_max_mhz, &ecx_bus_mhz, &edx);
+ const struct leaf_0x16_0 *l16 = cpuid_leaf(&boot_cpu_data, 0x16);
- return eax_base_mhz * 1000;
+ return l16 ? (l16->cpu_base_mhz * 1000) : 0;
}
/*
--
2.53.0
^ permalink raw reply related [flat|nested] 101+ messages in thread
* [PATCH v6 25/90] x86/cpuid: Parse Transmeta and Centaur extended ranges
2026-03-27 2:15 [PATCH v6 00/90] x86: Introduce a centralized CPUID data model Ahmed S. Darwish
` (23 preceding siblings ...)
2026-03-27 2:15 ` [PATCH v6 24/90] x86/tsc: Use parsed CPUID(0x16) Ahmed S. Darwish
@ 2026-03-27 2:15 ` Ahmed S. Darwish
2026-03-27 2:15 ` [PATCH v6 26/90] x86/cpu: transmeta: Use parsed CPUID(0x80860000)->CPUID(0x80860006) Ahmed S. Darwish
` (66 subsequent siblings)
91 siblings, 0 replies; 101+ messages in thread
From: Ahmed S. Darwish @ 2026-03-27 2:15 UTC (permalink / raw)
To: Borislav Petkov, Dave Hansen, Ingo Molnar
Cc: Thomas Gleixner, Andrew Cooper, H. Peter Anvin,
Sean Christopherson, David Woodhouse, Peter Zijlstra,
Christian Ludloff, Sohil Mehta, John Ogness, x86, x86-cpuid, LKML,
Ahmed S. Darwish
Parse the Transmeta extended CPUID(0x80860000)->CPUID(0x80860006) range.
Reuse the CPUID(0x80000000) read function and its safety guards against
CPUs repeating the output of the highest standard CPUID leaf. Transmeta's
code at early_init_transmeta() already carries a similar guard.
Parse Centaur/Zhaoxin extended CPUID(0xc0000000) and CPUID(0xc0000001).
Add x86 vendor tags for the Transmeta and Centaur/Zhaoxin CPUID leaves so
that they are not parsed on other vendors.
Signed-off-by: Ahmed S. Darwish <darwi@linutronix.de>
---
arch/x86/include/asm/cpuid/types.h | 13 ++++++++
arch/x86/kernel/cpu/cpuid_parser.c | 48 +++++++++++++++++++-----------
arch/x86/kernel/cpu/cpuid_parser.h | 18 +++++++++++
3 files changed, 61 insertions(+), 18 deletions(-)
diff --git a/arch/x86/include/asm/cpuid/types.h b/arch/x86/include/asm/cpuid/types.h
index 2939ad095f6c..8cc9f81e9526 100644
--- a/arch/x86/include/asm/cpuid/types.h
+++ b/arch/x86/include/asm/cpuid/types.h
@@ -37,9 +37,13 @@ enum cpuid_regs_idx {
#define CPUID_BASE_START 0x00000000
#define CPUID_EXT_START 0x80000000
+#define CPUID_TMX_START 0x80860000
+#define CPUID_CTR_START 0xc0000000
#define CPUID_BASE_END CPUID_RANGE_MAX(CPUID_BASE_START)
#define CPUID_EXT_END CPUID_RANGE_MAX(CPUID_EXT_START)
+#define CPUID_TMX_END CPUID_RANGE_MAX(CPUID_TMX_START)
+#define CPUID_CTR_END CPUID_RANGE_MAX(CPUID_CTR_START)
/*
* Types for CPUID(0x2) parsing:
@@ -211,6 +215,15 @@ struct cpuid_leaves {
CPUID_LEAF ( 0x80000002, 0 );
CPUID_LEAF ( 0x80000003, 0 );
CPUID_LEAF ( 0x80000004, 0 );
+ CPUID_LEAF ( 0x80860000, 0 );
+ CPUID_LEAF ( 0x80860001, 0 );
+ CPUID_LEAF ( 0x80860002, 0 );
+ CPUID_LEAF ( 0x80860003, 0 );
+ CPUID_LEAF ( 0x80860004, 0 );
+ CPUID_LEAF ( 0x80860005, 0 );
+ CPUID_LEAF ( 0x80860006, 0 );
+ CPUID_LEAF ( 0xc0000000, 0 );
+ CPUID_LEAF ( 0xc0000001, 0 );
};
/*
diff --git a/arch/x86/kernel/cpu/cpuid_parser.c b/arch/x86/kernel/cpu/cpuid_parser.c
index ab736f03051e..a7e6692f767b 100644
--- a/arch/x86/kernel/cpu/cpuid_parser.c
+++ b/arch/x86/kernel/cpu/cpuid_parser.c
@@ -42,24 +42,30 @@ cpuid_read_generic(const struct cpuid_parse_entry *e, const struct cpuid_read_ou
cpuid_read_subleaf(e->leaf, e->subleaf + i, regs);
}
-static void
-cpuid_read_0x80000000(const struct cpuid_parse_entry *e, const struct cpuid_read_output *output)
-{
- struct leaf_0x80000000_0 *el0 = (struct leaf_0x80000000_0 *)output->regs;
-
- cpuid_read_subleaf(e->leaf, e->subleaf, el0);
-
- /*
- * Protect against Intel 32-bit CPUs lacking an extended CPUID range. A
- * CPUID(0x80000000) query on such machines will repeat the output of the
- * highest standard CPUID leaf instead.
- */
- if (CPUID_RANGE(el0->max_ext_leaf) != CPUID_EXT_START)
- return;
-
- output->info->nr_entries = 1;
+/*
+ * Define an extended range CPUID read function
+ *
+ * Guard against CPUs lacking the passed range leaf; e.g. Intel 32-bit CPUs lacking
+ * CPUID(0x80000000). A query on such machines will just repeat the output of the
+ * highest standard CPUID leaf.
+ */
+#define define_cpuid_range_read_function(_range, _name) \
+static void \
+cpuid_read_##_range(const struct cpuid_parse_entry *e, const struct cpuid_read_output *output) \
+{ \
+ struct leaf_##_range##_0 *l = (struct leaf_##_range##_0 *)output->regs; \
+ \
+ cpuid_read_subleaf(e->leaf, e->subleaf, l); \
+ if (CPUID_RANGE(l->max_##_name##_leaf) != _range) \
+ return; \
+ \
+ output->info->nr_entries = 1; \
}
+define_cpuid_range_read_function(0x80000000, ext);
+define_cpuid_range_read_function(0x80860000, tra);
+define_cpuid_range_read_function(0xc0000000, cntr);
+
/*
* CPUID parser tables:
*
@@ -115,10 +121,14 @@ static unsigned int cpuid_range_max_leaf(const struct cpuid_table *t, unsigned i
{
const struct leaf_0x0_0 *l0 = __cpuid_table_subleaf(t, 0x0, 0);
const struct leaf_0x80000000_0 *el0 = __cpuid_table_subleaf(t, 0x80000000, 0);
+ const struct leaf_0x80860000_0 *tl0 = __cpuid_table_subleaf(t, 0x80860000, 0);
+ const struct leaf_0xc0000000_0 *cl0 = __cpuid_table_subleaf(t, 0xc0000000, 0);
switch (range) {
- case CPUID_BASE_START: return l0 ? l0->max_std_leaf : 0;
- case CPUID_EXT_START: return el0 ? el0->max_ext_leaf : 0;
+ case CPUID_BASE_START: return l0 ? l0->max_std_leaf : 0;
+ case CPUID_EXT_START: return el0 ? el0->max_ext_leaf : 0;
+ case CPUID_TMX_START: return tl0 ? tl0->max_tra_leaf : 0;
+ case CPUID_CTR_START: return cl0 ? cl0->max_cntr_leaf : 0;
default: return 0;
}
}
@@ -180,6 +190,8 @@ cpuid_fill_table(struct cpuid_table *t, const struct cpuid_parse_entry entries[]
} ranges[] = {
{ CPUID_BASE_START, CPUID_BASE_END },
{ CPUID_EXT_START, CPUID_EXT_END },
+ { CPUID_TMX_START, CPUID_TMX_END },
+ { CPUID_CTR_START, CPUID_CTR_END },
};
for (unsigned int i = 0; i < ARRAY_SIZE(ranges); i++)
diff --git a/arch/x86/kernel/cpu/cpuid_parser.h b/arch/x86/kernel/cpu/cpuid_parser.h
index ee1958f3d369..76a87a71b430 100644
--- a/arch/x86/kernel/cpu/cpuid_parser.h
+++ b/arch/x86/kernel/cpu/cpuid_parser.h
@@ -149,6 +149,15 @@ struct cpuid_parse_entry {
CPUID_PARSE_ENTRY ( 0x80000002, 0, generic ), \
CPUID_PARSE_ENTRY ( 0x80000003, 0, generic ), \
CPUID_PARSE_ENTRY ( 0x80000004, 0, generic ), \
+ CPUID_PARSE_ENTRY ( 0x80860000, 0, 0x80860000 ), \
+ CPUID_PARSE_ENTRY ( 0x80860001, 0, generic ), \
+ CPUID_PARSE_ENTRY ( 0x80860002, 0, generic ), \
+ CPUID_PARSE_ENTRY ( 0x80860003, 0, generic ), \
+ CPUID_PARSE_ENTRY ( 0x80860004, 0, generic ), \
+ CPUID_PARSE_ENTRY ( 0x80860005, 0, generic ), \
+ CPUID_PARSE_ENTRY ( 0x80860006, 0, generic ), \
+ CPUID_PARSE_ENTRY ( 0xc0000000, 0, 0xc0000000 ), \
+ CPUID_PARSE_ENTRY ( 0xc0000001, 0, generic ), \
/*
* CPUID parser phases:
@@ -182,5 +191,14 @@ struct cpuid_vendor_entry {
#define CPUID_VENDOR_ENTRIES \
/* Leaf Vendor list */ \
CPUID_VENDOR_ENTRY(0x16, X86_VENDOR_INTEL), \
+ CPUID_VENDOR_ENTRY(0x80860000, X86_VENDOR_TRANSMETA), \
+ CPUID_VENDOR_ENTRY(0x80860001, X86_VENDOR_TRANSMETA), \
+ CPUID_VENDOR_ENTRY(0x80860002, X86_VENDOR_TRANSMETA), \
+ CPUID_VENDOR_ENTRY(0x80860003, X86_VENDOR_TRANSMETA), \
+ CPUID_VENDOR_ENTRY(0x80860004, X86_VENDOR_TRANSMETA), \
+ CPUID_VENDOR_ENTRY(0x80860005, X86_VENDOR_TRANSMETA), \
+ CPUID_VENDOR_ENTRY(0x80860006, X86_VENDOR_TRANSMETA), \
+ CPUID_VENDOR_ENTRY(0xc0000000, X86_VENDOR_CENTAUR, X86_VENDOR_ZHAOXIN), \
+ CPUID_VENDOR_ENTRY(0xc0000001, X86_VENDOR_CENTAUR, X86_VENDOR_ZHAOXIN), \
#endif /* _ARCH_X86_CPUID_PARSER_H */
--
2.53.0
^ permalink raw reply related [flat|nested] 101+ messages in thread
* [PATCH v6 26/90] x86/cpu: transmeta: Use parsed CPUID(0x80860000)->CPUID(0x80860006)
2026-03-27 2:15 [PATCH v6 00/90] x86: Introduce a centralized CPUID data model Ahmed S. Darwish
` (24 preceding siblings ...)
2026-03-27 2:15 ` [PATCH v6 25/90] x86/cpuid: Parse Transmeta and Centaur extended ranges Ahmed S. Darwish
@ 2026-03-27 2:15 ` Ahmed S. Darwish
2026-03-27 2:15 ` [PATCH v6 27/90] x86/cpu: transmeta: Refactor CPU information printing Ahmed S. Darwish
` (65 subsequent siblings)
91 siblings, 0 replies; 101+ messages in thread
From: Ahmed S. Darwish @ 2026-03-27 2:15 UTC (permalink / raw)
To: Borislav Petkov, Dave Hansen, Ingo Molnar
Cc: Thomas Gleixner, Andrew Cooper, H. Peter Anvin,
Sean Christopherson, David Woodhouse, Peter Zijlstra,
Christian Ludloff, Sohil Mehta, John Ogness, x86, x86-cpuid, LKML,
Ahmed S. Darwish
Use parsed CPUID(0x80860000) to CPUID(0x80860006).
Beside the CPUID parser centralization benefits, this allows using the
auto-generated x86-cpuid-db data types, and their full C99 bitfields,
instead of doing ugly bitwise operations on the CPUID output.
Keep the x86_capability[] CPUID(0x80860001).EDX assignment. It will be
removed when X86_FEATURE translation is integrated into the CPUID table.
Signed-off-by: Ahmed S. Darwish <darwi@linutronix.de>
---
arch/x86/kernel/cpu/transmeta.c | 102 ++++++++++++++------------------
1 file changed, 44 insertions(+), 58 deletions(-)
diff --git a/arch/x86/kernel/cpu/transmeta.c b/arch/x86/kernel/cpu/transmeta.c
index d9e0edb379b8..4b77dc1a7d9e 100644
--- a/arch/x86/kernel/cpu/transmeta.c
+++ b/arch/x86/kernel/cpu/transmeta.c
@@ -12,77 +12,63 @@
static void early_init_transmeta(struct cpuinfo_x86 *c)
{
- u32 xlvl;
+ const struct leaf_0x80860000_0 *l = cpuid_leaf(c, 0x80860000);
- /* Transmeta-defined flags: level 0x80860001 */
- xlvl = cpuid_eax(0x80860000);
- if ((xlvl & 0xffff0000) == 0x80860000) {
- if (xlvl >= 0x80860001)
- c->x86_capability[CPUID_8086_0001_EDX] = cpuid_edx(0x80860001);
- }
+ if (l && l->max_tra_leaf >= 0x80860001)
+ c->x86_capability[CPUID_8086_0001_EDX] = cpuid_edx(0x80860001);
+}
+
+/*
+ * If CPU revision is 0x02000000, then CPUID(0x80860002) should be used instead.
+ */
+static bool is_legacy_revision(const struct leaf_0x80860001_0 *l1)
+{
+ return !(l1->cpu_rev_major == 2 && l1->cpu_rev_minor == 0 &&
+ l1->cpu_rev_mask_major == 0 && l1->cpu_rev_mask_minor == 0);
}
static void init_transmeta(struct cpuinfo_x86 *c)
{
- unsigned int cap_mask, uk, max, dummy;
- unsigned int cms_rev1, cms_rev2;
- unsigned int cpu_rev, cpu_freq = 0, cpu_flags, new_cpu_rev;
- char cpu_info[65];
+ const struct leaf_0x80860001_0 *l1 = cpuid_leaf(c, 0x80860001);
+ const struct leaf_0x80860002_0 *l2 = cpuid_leaf(c, 0x80860002);
+ const struct leaf_0x80860003_0 *l3 = cpuid_leaf(c, 0x80860003);
+ const struct leaf_0x80860004_0 *l4 = cpuid_leaf(c, 0x80860004);
+ const struct leaf_0x80860005_0 *l5 = cpuid_leaf(c, 0x80860005);
+ const struct leaf_0x80860006_0 *l6 = cpuid_leaf(c, 0x80860006);
+ unsigned int cap_mask, uk;
early_init_transmeta(c);
cpu_detect_cache_sizes(c);
- /* Print CMS and CPU revision */
- max = cpuid_eax(0x80860000);
- cpu_rev = 0;
- if (max >= 0x80860001) {
- cpuid(0x80860001, &dummy, &cpu_rev, &cpu_freq, &cpu_flags);
- if (cpu_rev != 0x02000000) {
- pr_info("CPU: Processor revision %u.%u.%u.%u, %u MHz\n",
- (cpu_rev >> 24) & 0xff,
- (cpu_rev >> 16) & 0xff,
- (cpu_rev >> 8) & 0xff,
- cpu_rev & 0xff,
- cpu_freq);
- }
+ if (l1 && is_legacy_revision(l1)) {
+ pr_info("CPU: Processor revision %u.%u.%u.%u, %u MHz\n",
+ l1->cpu_rev_major, l1->cpu_rev_minor,
+ l1->cpu_rev_mask_major, l1->cpu_rev_mask_minor,
+ l1->cpu_base_mhz);
}
- if (max >= 0x80860002) {
- cpuid(0x80860002, &new_cpu_rev, &cms_rev1, &cms_rev2, &dummy);
- if (cpu_rev == 0x02000000) {
- pr_info("CPU: Processor revision %08X, %u MHz\n",
- new_cpu_rev, cpu_freq);
- }
+
+ if (l1 && l2 && !is_legacy_revision(l1)) {
+ pr_info("CPU: Processor revision %08X, %u MHz\n",
+ l2->cpu_rev_id, l1->cpu_base_mhz);
+ }
+
+ if (l2) {
pr_info("CPU: Code Morphing Software revision %u.%u.%u-%u-%u\n",
- (cms_rev1 >> 24) & 0xff,
- (cms_rev1 >> 16) & 0xff,
- (cms_rev1 >> 8) & 0xff,
- cms_rev1 & 0xff,
- cms_rev2);
+ l2->cms_rev_major, l2->cms_rev_minor,
+ l2->cms_rev_mask_1, l2->cms_rev_mask_2,
+ l2->cms_rev_mask_3);
}
- if (max >= 0x80860006) {
- cpuid(0x80860003,
- (void *)&cpu_info[0],
- (void *)&cpu_info[4],
- (void *)&cpu_info[8],
- (void *)&cpu_info[12]);
- cpuid(0x80860004,
- (void *)&cpu_info[16],
- (void *)&cpu_info[20],
- (void *)&cpu_info[24],
- (void *)&cpu_info[28]);
- cpuid(0x80860005,
- (void *)&cpu_info[32],
- (void *)&cpu_info[36],
- (void *)&cpu_info[40],
- (void *)&cpu_info[44]);
- cpuid(0x80860006,
- (void *)&cpu_info[48],
- (void *)&cpu_info[52],
- (void *)&cpu_info[56],
- (void *)&cpu_info[60]);
- cpu_info[64] = '\0';
- pr_info("CPU: %s\n", cpu_info);
+
+ if (l3 && l4 && l5 && l6) {
+ u32 info[] = {
+ l3->cpu_info_0, l3->cpu_info_1, l3->cpu_info_2, l3->cpu_info_3,
+ l4->cpu_info_4, l4->cpu_info_5, l4->cpu_info_6, l4->cpu_info_7,
+ l5->cpu_info_8, l5->cpu_info_9, l5->cpu_info_10, l5->cpu_info_11,
+ l6->cpu_info_12, l6->cpu_info_13, l6->cpu_info_14, l6->cpu_info_15,
+ 0 /* Null terminator */,
+ };
+ pr_info("CPU: %s\n", (char *)info);
}
/* Unhide possibly hidden capability flags */
--
2.53.0
^ permalink raw reply related [flat|nested] 101+ messages in thread
* [PATCH v6 27/90] x86/cpu: transmeta: Refactor CPU information printing
2026-03-27 2:15 [PATCH v6 00/90] x86: Introduce a centralized CPUID data model Ahmed S. Darwish
` (25 preceding siblings ...)
2026-03-27 2:15 ` [PATCH v6 26/90] x86/cpu: transmeta: Use parsed CPUID(0x80860000)->CPUID(0x80860006) Ahmed S. Darwish
@ 2026-03-27 2:15 ` Ahmed S. Darwish
2026-03-27 2:15 ` [PATCH v6 28/90] x86/cpu: centaur: Use parsed CPUID(0xc0000001) Ahmed S. Darwish
` (64 subsequent siblings)
91 siblings, 0 replies; 101+ messages in thread
From: Ahmed S. Darwish @ 2026-03-27 2:15 UTC (permalink / raw)
To: Borislav Petkov, Dave Hansen, Ingo Molnar
Cc: Thomas Gleixner, Andrew Cooper, H. Peter Anvin,
Sean Christopherson, David Woodhouse, Peter Zijlstra,
Christian Ludloff, Sohil Mehta, John Ogness, x86, x86-cpuid, LKML,
Ahmed S. Darwish
Now that the Transmeta init code has been converted to the CPUID API,
refactor it into two separate functions for readability.
No functional change.
Signed-off-by: Ahmed S. Darwish <darwi@linutronix.de>
---
arch/x86/kernel/cpu/transmeta.c | 30 ++++++++++++++++++++----------
1 file changed, 20 insertions(+), 10 deletions(-)
diff --git a/arch/x86/kernel/cpu/transmeta.c b/arch/x86/kernel/cpu/transmeta.c
index 4b77dc1a7d9e..991e11d5c28a 100644
--- a/arch/x86/kernel/cpu/transmeta.c
+++ b/arch/x86/kernel/cpu/transmeta.c
@@ -27,19 +27,10 @@ static bool is_legacy_revision(const struct leaf_0x80860001_0 *l1)
l1->cpu_rev_mask_major == 0 && l1->cpu_rev_mask_minor == 0);
}
-static void init_transmeta(struct cpuinfo_x86 *c)
+static void print_cpu_revision(struct cpuinfo_x86 *c)
{
const struct leaf_0x80860001_0 *l1 = cpuid_leaf(c, 0x80860001);
const struct leaf_0x80860002_0 *l2 = cpuid_leaf(c, 0x80860002);
- const struct leaf_0x80860003_0 *l3 = cpuid_leaf(c, 0x80860003);
- const struct leaf_0x80860004_0 *l4 = cpuid_leaf(c, 0x80860004);
- const struct leaf_0x80860005_0 *l5 = cpuid_leaf(c, 0x80860005);
- const struct leaf_0x80860006_0 *l6 = cpuid_leaf(c, 0x80860006);
- unsigned int cap_mask, uk;
-
- early_init_transmeta(c);
-
- cpu_detect_cache_sizes(c);
if (l1 && is_legacy_revision(l1)) {
pr_info("CPU: Processor revision %u.%u.%u.%u, %u MHz\n",
@@ -59,6 +50,14 @@ static void init_transmeta(struct cpuinfo_x86 *c)
l2->cms_rev_mask_1, l2->cms_rev_mask_2,
l2->cms_rev_mask_3);
}
+}
+
+static void print_cpu_info_string(struct cpuinfo_x86 *c)
+{
+ const struct leaf_0x80860003_0 *l3 = cpuid_leaf(c, 0x80860003);
+ const struct leaf_0x80860004_0 *l4 = cpuid_leaf(c, 0x80860004);
+ const struct leaf_0x80860005_0 *l5 = cpuid_leaf(c, 0x80860005);
+ const struct leaf_0x80860006_0 *l6 = cpuid_leaf(c, 0x80860006);
if (l3 && l4 && l5 && l6) {
u32 info[] = {
@@ -70,6 +69,17 @@ static void init_transmeta(struct cpuinfo_x86 *c)
};
pr_info("CPU: %s\n", (char *)info);
}
+}
+
+static void init_transmeta(struct cpuinfo_x86 *c)
+{
+ unsigned int cap_mask, uk;
+
+ early_init_transmeta(c);
+ cpu_detect_cache_sizes(c);
+
+ print_cpu_revision(c);
+ print_cpu_info_string(c);
/* Unhide possibly hidden capability flags */
rdmsr(0x80860004, cap_mask, uk);
--
2.53.0
^ permalink raw reply related [flat|nested] 101+ messages in thread
* [PATCH v6 28/90] x86/cpu: centaur: Use parsed CPUID(0xc0000001)
2026-03-27 2:15 [PATCH v6 00/90] x86: Introduce a centralized CPUID data model Ahmed S. Darwish
` (26 preceding siblings ...)
2026-03-27 2:15 ` [PATCH v6 27/90] x86/cpu: transmeta: Refactor CPU information printing Ahmed S. Darwish
@ 2026-03-27 2:15 ` Ahmed S. Darwish
2026-03-27 2:15 ` [PATCH v6 29/90] x86/cpu: zhaoxin: " Ahmed S. Darwish
` (63 subsequent siblings)
91 siblings, 0 replies; 101+ messages in thread
From: Ahmed S. Darwish @ 2026-03-27 2:15 UTC (permalink / raw)
To: Borislav Petkov, Dave Hansen, Ingo Molnar
Cc: Thomas Gleixner, Andrew Cooper, H. Peter Anvin,
Sean Christopherson, David Woodhouse, Peter Zijlstra,
Christian Ludloff, Sohil Mehta, John Ogness, x86, x86-cpuid, LKML,
Ahmed S. Darwish
Use parsed CPUID(0xc0000001).
Beside the CPUID parser centralization benefits, this allows using the
auto-generated x86-cpuid-db data types, and their full C99 bitfields,
instead of doing ugly bitwise operations on the CPUID output.
Keep the x86_capability[] CPUID(0xc0000001).EDX assignment. It will be
removed once X86_FEATURE translation is integrated into the CPUID model.
Signed-off-by: Ahmed S. Darwish <darwi@linutronix.de>
---
arch/x86/kernel/cpu/centaur.c | 25 +++++++++----------------
1 file changed, 9 insertions(+), 16 deletions(-)
diff --git a/arch/x86/kernel/cpu/centaur.c b/arch/x86/kernel/cpu/centaur.c
index a97e38fa6a9f..5f09bce3aaa7 100644
--- a/arch/x86/kernel/cpu/centaur.c
+++ b/arch/x86/kernel/cpu/centaur.c
@@ -12,34 +12,27 @@
#include "cpu.h"
-#define ACE_PRESENT (1 << 6)
-#define ACE_ENABLED (1 << 7)
#define ACE_FCR (1 << 28) /* MSR_VIA_FCR */
-
-#define RNG_PRESENT (1 << 2)
-#define RNG_ENABLED (1 << 3)
#define RNG_ENABLE (1 << 6) /* MSR_VIA_RNG */
static void init_c3(struct cpuinfo_x86 *c)
{
- u32 lo, hi;
-
- /* Test for Centaur Extended Feature Flags presence */
- if (cpuid_eax(0xC0000000) >= 0xC0000001) {
- u32 tmp = cpuid_edx(0xC0000001);
+ const struct leaf_0xc0000001_0 *l1 = cpuid_leaf(c, 0xc0000001);
+ u32 lo, hi;
- /* enable ACE unit, if present and disabled */
- if ((tmp & (ACE_PRESENT | ACE_ENABLED)) == ACE_PRESENT) {
+ if (l1) {
+ /* Enable ACE unit, if present and disabled */
+ if (l1->ace && !l1->ace_en) {
rdmsr(MSR_VIA_FCR, lo, hi);
- lo |= ACE_FCR; /* enable ACE unit */
+ lo |= ACE_FCR;
wrmsr(MSR_VIA_FCR, lo, hi);
pr_info("CPU: Enabled ACE h/w crypto\n");
}
- /* enable RNG unit, if present and disabled */
- if ((tmp & (RNG_PRESENT | RNG_ENABLED)) == RNG_PRESENT) {
+ /* Enable RNG unit, if present and disabled */
+ if (l1->rng && !l1->rng_en) {
rdmsr(MSR_VIA_RNG, lo, hi);
- lo |= RNG_ENABLE; /* enable RNG unit */
+ lo |= RNG_ENABLE;
wrmsr(MSR_VIA_RNG, lo, hi);
pr_info("CPU: Enabled h/w RNG\n");
}
--
2.53.0
^ permalink raw reply related [flat|nested] 101+ messages in thread
* [PATCH v6 29/90] x86/cpu: zhaoxin: Use parsed CPUID(0xc0000001)
2026-03-27 2:15 [PATCH v6 00/90] x86: Introduce a centralized CPUID data model Ahmed S. Darwish
` (27 preceding siblings ...)
2026-03-27 2:15 ` [PATCH v6 28/90] x86/cpu: centaur: Use parsed CPUID(0xc0000001) Ahmed S. Darwish
@ 2026-03-27 2:15 ` Ahmed S. Darwish
2026-03-27 2:15 ` [PATCH v6 30/90] x86/cpuid: Parse CPUID(0x2) Ahmed S. Darwish
` (62 subsequent siblings)
91 siblings, 0 replies; 101+ messages in thread
From: Ahmed S. Darwish @ 2026-03-27 2:15 UTC (permalink / raw)
To: Borislav Petkov, Dave Hansen, Ingo Molnar
Cc: Thomas Gleixner, Andrew Cooper, H. Peter Anvin,
Sean Christopherson, David Woodhouse, Peter Zijlstra,
Christian Ludloff, Sohil Mehta, John Ogness, x86, x86-cpuid, LKML,
Ahmed S. Darwish
Use parsed CPUID(0xc0000001).
Beside the CPUID parser centralization benefits, this allows using the
auto-generated x86-cpuid-db data types, and their full C99 bitfields,
instead of doing ugly bitwise operations on the CPUID output.
Keep the x86_capability[] CPUID(0xc0000001).EDX assignment. It will be
removed once X86_FEATURE translation is integrated into the CPUID model.
Signed-off-by: Ahmed S. Darwish <darwi@linutronix.de>
---
arch/x86/kernel/cpu/zhaoxin.c | 19 +++++--------------
1 file changed, 5 insertions(+), 14 deletions(-)
diff --git a/arch/x86/kernel/cpu/zhaoxin.c b/arch/x86/kernel/cpu/zhaoxin.c
index 55bc656aaa95..ea76e9594453 100644
--- a/arch/x86/kernel/cpu/zhaoxin.c
+++ b/arch/x86/kernel/cpu/zhaoxin.c
@@ -11,35 +11,26 @@
#define MSR_ZHAOXIN_FCR57 0x00001257
-#define ACE_PRESENT (1 << 6)
-#define ACE_ENABLED (1 << 7)
#define ACE_FCR (1 << 7) /* MSR_ZHAOXIN_FCR */
-
-#define RNG_PRESENT (1 << 2)
-#define RNG_ENABLED (1 << 3)
#define RNG_ENABLE (1 << 8) /* MSR_ZHAOXIN_RNG */
static void init_zhaoxin_cap(struct cpuinfo_x86 *c)
{
- u32 lo, hi;
-
- /* Test for Extended Feature Flags presence */
- if (cpuid_eax(0xC0000000) >= 0xC0000001) {
- u32 tmp = cpuid_edx(0xC0000001);
+ const struct leaf_0xc0000001_0 *l1 = cpuid_leaf(c, 0xc0000001);
+ u32 lo, hi;
+ if (l1) {
/* Enable ACE unit, if present and disabled */
- if ((tmp & (ACE_PRESENT | ACE_ENABLED)) == ACE_PRESENT) {
+ if (l1->ace && !l1->ace_en) {
rdmsr(MSR_ZHAOXIN_FCR57, lo, hi);
- /* Enable ACE unit */
lo |= ACE_FCR;
wrmsr(MSR_ZHAOXIN_FCR57, lo, hi);
pr_info("CPU: Enabled ACE h/w crypto\n");
}
/* Enable RNG unit, if present and disabled */
- if ((tmp & (RNG_PRESENT | RNG_ENABLED)) == RNG_PRESENT) {
+ if (l1->rng && !l1->rng_en) {
rdmsr(MSR_ZHAOXIN_FCR57, lo, hi);
- /* Enable RNG unit */
lo |= RNG_ENABLE;
wrmsr(MSR_ZHAOXIN_FCR57, lo, hi);
pr_info("CPU: Enabled h/w RNG\n");
--
2.53.0
^ permalink raw reply related [flat|nested] 101+ messages in thread
* [PATCH v6 30/90] x86/cpuid: Parse CPUID(0x2)
2026-03-27 2:15 [PATCH v6 00/90] x86: Introduce a centralized CPUID data model Ahmed S. Darwish
` (28 preceding siblings ...)
2026-03-27 2:15 ` [PATCH v6 29/90] x86/cpu: zhaoxin: " Ahmed S. Darwish
@ 2026-03-27 2:15 ` Ahmed S. Darwish
2026-03-27 2:15 ` [PATCH v6 31/90] x86/cpuid: Warn once on invalid CPUID(0x2) iteration count Ahmed S. Darwish
` (61 subsequent siblings)
91 siblings, 0 replies; 101+ messages in thread
From: Ahmed S. Darwish @ 2026-03-27 2:15 UTC (permalink / raw)
To: Borislav Petkov, Dave Hansen, Ingo Molnar
Cc: Thomas Gleixner, Andrew Cooper, H. Peter Anvin,
Sean Christopherson, David Woodhouse, Peter Zijlstra,
Christian Ludloff, Sohil Mehta, John Ogness, x86, x86-cpuid, LKML,
Ahmed S. Darwish
Parse CPUID(0x2).
Query it only for Intel, Centaur, and Zhaoxin, given that
kernel/cpu/cacheinfo.c :: init_intel_cacheinfo()
is called by:
kernel/cpu/intel.c cpu_dev.c_x86_vendor = X86_VENDOR_INTEL
kernel/cpu/centaur.c cpu_dev.c_x86_vendor = X86_VENDOR_CENTAUR
kernel/cpu/zhaoxin.c cpu_dev.c_x86_vendor = X86_VENDOR_ZHAOXIN
At the CPUID tables, keep CPUID(0x2) marked as invalid if the whole leaf,
or all of its output registers separately, were malformed.
Note, cpuid_leaf_0x2() at <asm/cpuid/api.h> will be removed once all call
sites are transformed to new CPUID APIs.
References: fe78079ec07f ("x86/cpu: Introduce and use CPUID leaf 0x2 parsing helpers")
Signed-off-by: Ahmed S. Darwish <darwi@linutronix.de>
---
arch/x86/include/asm/cpuid/types.h | 1 +
arch/x86/kernel/cpu/cpuid_parser.c | 36 ++++++++++++++++++++++++++++++
arch/x86/kernel/cpu/cpuid_parser.h | 2 ++
3 files changed, 39 insertions(+)
diff --git a/arch/x86/include/asm/cpuid/types.h b/arch/x86/include/asm/cpuid/types.h
index 8cc9f81e9526..c35de721f652 100644
--- a/arch/x86/include/asm/cpuid/types.h
+++ b/arch/x86/include/asm/cpuid/types.h
@@ -210,6 +210,7 @@ struct cpuid_leaves {
/* Leaf Subleaf number (or max number of subleaves) */
CPUID_LEAF ( 0x0, 0 );
CPUID_LEAF ( 0x1, 0 );
+ CPUID_LEAF ( 0x2, 0 );
CPUID_LEAF ( 0x16, 0 );
CPUID_LEAF ( 0x80000000, 0 );
CPUID_LEAF ( 0x80000002, 0 );
diff --git a/arch/x86/kernel/cpu/cpuid_parser.c b/arch/x86/kernel/cpu/cpuid_parser.c
index a7e6692f767b..be340b202182 100644
--- a/arch/x86/kernel/cpu/cpuid_parser.c
+++ b/arch/x86/kernel/cpu/cpuid_parser.c
@@ -42,6 +42,42 @@ cpuid_read_generic(const struct cpuid_parse_entry *e, const struct cpuid_read_ou
cpuid_read_subleaf(e->leaf, e->subleaf + i, regs);
}
+static void
+cpuid_read_0x2(const struct cpuid_parse_entry *e, const struct cpuid_read_output *output)
+{
+ union leaf_0x2_regs *regs = (union leaf_0x2_regs *)output->regs;
+ struct leaf_0x2_0 *l = (struct leaf_0x2_0 *)output->regs;
+ int invalid_regs = 0;
+
+ /*
+ * All Intel CPUs must report an iteration count of 1. For broken hardware,
+ * keep the leaf marked as invalid at the CPUID table.
+ */
+ cpuid_read_subleaf(e->leaf, e->subleaf, l);
+ if (l->iteration_count != 0x01)
+ return;
+
+ /*
+ * The most significant bit (MSB) of each CPUID(0x2) register must be clear.
+ * If a register is malformed, replace its 1-byte descriptors with NULL.
+ */
+ for (int i = 0; i < 4; i++) {
+ if (regs->reg[i].invalid) {
+ regs->regv[i] = 0;
+ invalid_regs++;
+ }
+ }
+
+ /*
+ * If all of the CPUID(0x2) output registers were malformed, keep the leaf
+ * marked as invalid at the CPUID table.
+ */
+ if (invalid_regs == 4)
+ return;
+
+ output->info->nr_entries = 1;
+}
+
/*
* Define an extended range CPUID read function
*
diff --git a/arch/x86/kernel/cpu/cpuid_parser.h b/arch/x86/kernel/cpu/cpuid_parser.h
index 76a87a71b430..1de239370652 100644
--- a/arch/x86/kernel/cpu/cpuid_parser.h
+++ b/arch/x86/kernel/cpu/cpuid_parser.h
@@ -144,6 +144,7 @@ struct cpuid_parse_entry {
*/
#define CPUID_COMMON_ENTRIES \
/* Leaf Subleaf Reader function */ \
+ CPUID_PARSE_ENTRY ( 0x2, 0, 0x2 ), \
CPUID_PARSE_ENTRY ( 0x16, 0, generic ), \
CPUID_PARSE_ENTRY ( 0x80000000, 0, 0x80000000 ), \
CPUID_PARSE_ENTRY ( 0x80000002, 0, generic ), \
@@ -190,6 +191,7 @@ struct cpuid_vendor_entry {
#define CPUID_VENDOR_ENTRIES \
/* Leaf Vendor list */ \
+ CPUID_VENDOR_ENTRY(0x2, X86_VENDOR_INTEL, X86_VENDOR_CENTAUR, X86_VENDOR_ZHAOXIN),\
CPUID_VENDOR_ENTRY(0x16, X86_VENDOR_INTEL), \
CPUID_VENDOR_ENTRY(0x80860000, X86_VENDOR_TRANSMETA), \
CPUID_VENDOR_ENTRY(0x80860001, X86_VENDOR_TRANSMETA), \
--
2.53.0
^ permalink raw reply related [flat|nested] 101+ messages in thread
* [PATCH v6 31/90] x86/cpuid: Warn once on invalid CPUID(0x2) iteration count
2026-03-27 2:15 [PATCH v6 00/90] x86: Introduce a centralized CPUID data model Ahmed S. Darwish
` (29 preceding siblings ...)
2026-03-27 2:15 ` [PATCH v6 30/90] x86/cpuid: Parse CPUID(0x2) Ahmed S. Darwish
@ 2026-03-27 2:15 ` Ahmed S. Darwish
2026-03-27 2:15 ` [PATCH v6 32/90] x86/cpuid: Introduce parsed CPUID(0x2) API Ahmed S. Darwish
` (60 subsequent siblings)
91 siblings, 0 replies; 101+ messages in thread
From: Ahmed S. Darwish @ 2026-03-27 2:15 UTC (permalink / raw)
To: Borislav Petkov, Dave Hansen, Ingo Molnar
Cc: Thomas Gleixner, Andrew Cooper, H. Peter Anvin,
Sean Christopherson, David Woodhouse, Peter Zijlstra,
Christian Ludloff, Sohil Mehta, John Ogness, x86, x86-cpuid, LKML,
Ahmed S. Darwish
CPUID(0x2) output includes a "query count" byte. That byte was supposed to
specify the number of repeated CPUID(0x2) subleaf 0 queries needed to
extract all of the CPU's cache and TLB descriptors.
Per current Intel manuals, all CPUs supporting this leaf "will always"
return an iteration count of 1.
Since the CPUID parser ignores any CPUID(0x2) output with an invalid
iteration count, lightly warn about this once in the kernel log.
Do not emit a warning if some of the CPUID(0x2) output registers, or even
all of them, are invalid. This is an architecturally-defined response.
Suggested-by: Ingo Molnar <mingo@kernel.org>
Signed-off-by: Ahmed S. Darwish <darwi@linutronix.de>
References: b5969494c8d8 ("x86/cpu: Remove CPUID leaf 0x2 parsing loop")
Link: https://lore.kernel.org/lkml/aBnmy_Bmf-H0wxqz@gmail.com
---
arch/x86/kernel/cpu/cpuid_parser.c | 7 ++++++-
1 file changed, 6 insertions(+), 1 deletion(-)
diff --git a/arch/x86/kernel/cpu/cpuid_parser.c b/arch/x86/kernel/cpu/cpuid_parser.c
index be340b202182..bddd9937bb2b 100644
--- a/arch/x86/kernel/cpu/cpuid_parser.c
+++ b/arch/x86/kernel/cpu/cpuid_parser.c
@@ -3,6 +3,8 @@
* CPUID parser; for populating the system's CPUID tables.
*/
+#define pr_fmt(fmt) "x86/cpuid: " fmt
+
#include <linux/kernel.h>
#include <asm/cpuid/api.h>
@@ -54,8 +56,11 @@ cpuid_read_0x2(const struct cpuid_parse_entry *e, const struct cpuid_read_output
* keep the leaf marked as invalid at the CPUID table.
*/
cpuid_read_subleaf(e->leaf, e->subleaf, l);
- if (l->iteration_count != 0x01)
+ if (l->iteration_count != 0x01) {
+ pr_warn_once("Ignoring CPUID(0x2) due to invalid iteration count = %d",
+ l->iteration_count);
return;
+ }
/*
* The most significant bit (MSB) of each CPUID(0x2) register must be clear.
--
2.53.0
^ permalink raw reply related [flat|nested] 101+ messages in thread
* [PATCH v6 32/90] x86/cpuid: Introduce parsed CPUID(0x2) API
2026-03-27 2:15 [PATCH v6 00/90] x86: Introduce a centralized CPUID data model Ahmed S. Darwish
` (30 preceding siblings ...)
2026-03-27 2:15 ` [PATCH v6 31/90] x86/cpuid: Warn once on invalid CPUID(0x2) iteration count Ahmed S. Darwish
@ 2026-03-27 2:15 ` Ahmed S. Darwish
2026-03-27 2:15 ` [PATCH v6 33/90] x86/cpu: Use parsed CPUID(0x2) Ahmed S. Darwish
` (59 subsequent siblings)
91 siblings, 0 replies; 101+ messages in thread
From: Ahmed S. Darwish @ 2026-03-27 2:15 UTC (permalink / raw)
To: Borislav Petkov, Dave Hansen, Ingo Molnar
Cc: Thomas Gleixner, Andrew Cooper, H. Peter Anvin,
Sean Christopherson, David Woodhouse, Peter Zijlstra,
Christian Ludloff, Sohil Mehta, John Ogness, x86, x86-cpuid, LKML,
Ahmed S. Darwish
Add a new iterator, for_each_parsed_cpuid_0x2_desc(), for retrieving parsed
CPUID(0x2) entries as 1-byte descriptors.
This new macro is aimed to replace for_each_cpuid_0x2_desc(), which
operates on directly queried CPUID data instead.
Assert that the passed "regs" are the same size as "union leaf_0x2_regs".
Use a size equivalence check, instead of a typeof() check, to give callers
the freedom to either pass a "struct cpuid_regs" pointer or a "struct
leaf_0x2_0" pointer; where both can returned by the parsed CPUID API at
<asm/cpuid/api.h>. This size comparison matches what other kernel CPUID
APIs do; e.g. cpuid_read() and cpuid_read_subleaf() at <asm/cpuid/api.h>.
Put the size equivalence check inside a GNU statement expression, ({..})
so that it can be placed inside the macro's loop initialization.
Signed-off-by: Ahmed S. Darwish <darwi@linutronix.de>
---
arch/x86/include/asm/cpuid/api.h | 43 ++++++++++++++++++++++++++++++++
1 file changed, 43 insertions(+)
diff --git a/arch/x86/include/asm/cpuid/api.h b/arch/x86/include/asm/cpuid/api.h
index 3d5a0d4918cc..a55a28e9f0f6 100644
--- a/arch/x86/include/asm/cpuid/api.h
+++ b/arch/x86/include/asm/cpuid/api.h
@@ -528,6 +528,49 @@ static inline bool cpuid_amd_hygon_has_l3_cache(void)
__cpuid_table_nr_filled_subleaves(&(_cpuinfo)->cpuid, _leaf, n); \
})
+/*
+ * Convenience leaf-specific functions (using parsed CPUID data):
+ */
+
+/*
+ * CPUID(0x2)
+ */
+
+/**
+ * for_each_parsed_cpuid_0x2_desc() - Iterator for parsed CPUID(0x2) descriptors
+ * @_regs: Leaf 0x2 register output, as returned by cpuid_leaf_raw()
+ * @_ptr: u8 pointer, for macro internal use only
+ * @_desc: Pointer to parsed descriptor information at each iteration
+ *
+ * Loop over the 1-byte descriptors in the passed CPUID(0x2) output registers
+ * @_regs. Provide the parsed information for each descriptor through @_desc.
+ *
+ * To handle cache-specific descriptors, switch on @_desc->c_type. For TLB
+ * descriptors, switch on @_desc->t_type.
+ *
+ * Example usage for cache descriptors::
+ *
+ * const struct leaf_0x2_table *desc;
+ * const struct cpuid_regs *regs;
+ * const u8 *ptr;
+ *
+ * regs = cpuid_leaf_raw(c, 0x2);
+ * if (!regs) {
+ * // Handle error
+ * }
+ *
+ * for_each_parsed_cpuid_0x2_desc(regs, ptr, desc) {
+ * switch (desc->c_type) {
+ * ...
+ * }
+ * }
+ */
+#define for_each_parsed_cpuid_0x2_desc(_regs, _ptr, _desc) \
+ for (({ static_assert(sizeof(*_regs) == sizeof(union leaf_0x2_regs)); }), \
+ _ptr = &((const union leaf_0x2_regs *)(_regs))->desc[1]; \
+ _ptr < &((const union leaf_0x2_regs *)(_regs))->desc[16] && (_desc = &cpuid_0x2_table[*_ptr]);\
+ _ptr++)
+
/*
* CPUID parser exported APIs:
*/
--
2.53.0
^ permalink raw reply related [flat|nested] 101+ messages in thread
* [PATCH v6 33/90] x86/cpu: Use parsed CPUID(0x2)
2026-03-27 2:15 [PATCH v6 00/90] x86: Introduce a centralized CPUID data model Ahmed S. Darwish
` (31 preceding siblings ...)
2026-03-27 2:15 ` [PATCH v6 32/90] x86/cpuid: Introduce parsed CPUID(0x2) API Ahmed S. Darwish
@ 2026-03-27 2:15 ` Ahmed S. Darwish
2026-03-27 2:15 ` [PATCH v6 34/90] x86/cacheinfo: " Ahmed S. Darwish
` (58 subsequent siblings)
91 siblings, 0 replies; 101+ messages in thread
From: Ahmed S. Darwish @ 2026-03-27 2:15 UTC (permalink / raw)
To: Borislav Petkov, Dave Hansen, Ingo Molnar
Cc: Thomas Gleixner, Andrew Cooper, H. Peter Anvin,
Sean Christopherson, David Woodhouse, Peter Zijlstra,
Christian Ludloff, Sohil Mehta, John Ogness, x86, x86-cpuid, LKML,
Ahmed S. Darwish
At the Intel cacheinfo code, use parsed CPUID(0x2) access instead of a
direct CPUID query.
Remove the "maximum standard CPUID level >= 0x2" check as the parsed
CPUID API output NULL check is equivalent.
Signed-off-by: Ahmed S. Darwish <darwi@linutronix.de>
---
arch/x86/kernel/cpu/intel.c | 10 +++++-----
1 file changed, 5 insertions(+), 5 deletions(-)
diff --git a/arch/x86/kernel/cpu/intel.c b/arch/x86/kernel/cpu/intel.c
index 08869fecdf30..cad66ca14ca4 100644
--- a/arch/x86/kernel/cpu/intel.c
+++ b/arch/x86/kernel/cpu/intel.c
@@ -722,14 +722,14 @@ static void intel_tlb_lookup(const struct leaf_0x2_table *desc)
static void intel_detect_tlb(struct cpuinfo_x86 *c)
{
const struct leaf_0x2_table *desc;
- union leaf_0x2_regs regs;
- u8 *ptr;
+ const struct cpuid_regs *regs;
+ const u8 *ptr;
- if (c->cpuid_level < 2)
+ regs = cpuid_leaf_raw(c, 0x2);
+ if (!regs)
return;
- cpuid_leaf_0x2(®s);
- for_each_cpuid_0x2_desc(regs, ptr, desc)
+ for_each_parsed_cpuid_0x2_desc(regs, ptr, desc)
intel_tlb_lookup(desc);
}
--
2.53.0
^ permalink raw reply related [flat|nested] 101+ messages in thread
* [PATCH v6 34/90] x86/cacheinfo: Use parsed CPUID(0x2)
2026-03-27 2:15 [PATCH v6 00/90] x86: Introduce a centralized CPUID data model Ahmed S. Darwish
` (32 preceding siblings ...)
2026-03-27 2:15 ` [PATCH v6 33/90] x86/cpu: Use parsed CPUID(0x2) Ahmed S. Darwish
@ 2026-03-27 2:15 ` Ahmed S. Darwish
2026-03-27 2:15 ` [PATCH v6 35/90] x86/cpuid: Remove direct CPUID(0x2) query helpers Ahmed S. Darwish
` (57 subsequent siblings)
91 siblings, 0 replies; 101+ messages in thread
From: Ahmed S. Darwish @ 2026-03-27 2:15 UTC (permalink / raw)
To: Borislav Petkov, Dave Hansen, Ingo Molnar
Cc: Thomas Gleixner, Andrew Cooper, H. Peter Anvin,
Sean Christopherson, David Woodhouse, Peter Zijlstra,
Christian Ludloff, Sohil Mehta, John Ogness, x86, x86-cpuid, LKML,
Ahmed S. Darwish
Use parsed CPUID(0x2) instead of directly invoking CPUID queries.
Remove the max CPUID level check; checking cpuid_leaf_raw()'s result for
NULL is enough.
Signed-off-by: Ahmed S. Darwish <darwi@linutronix.de>
---
arch/x86/kernel/cpu/cacheinfo.c | 10 +++++-----
1 file changed, 5 insertions(+), 5 deletions(-)
diff --git a/arch/x86/kernel/cpu/cacheinfo.c b/arch/x86/kernel/cpu/cacheinfo.c
index 51a95b07831f..6fded356f2ee 100644
--- a/arch/x86/kernel/cpu/cacheinfo.c
+++ b/arch/x86/kernel/cpu/cacheinfo.c
@@ -391,14 +391,14 @@ static void intel_cacheinfo_0x2(struct cpuinfo_x86 *c)
{
unsigned int l1i = 0, l1d = 0, l2 = 0, l3 = 0;
const struct leaf_0x2_table *desc;
- union leaf_0x2_regs regs;
- u8 *ptr;
+ const struct cpuid_regs *regs;
+ const u8 *ptr;
- if (c->cpuid_level < 2)
+ regs = cpuid_leaf_raw(c, 0x2);
+ if (!regs)
return;
- cpuid_leaf_0x2(®s);
- for_each_cpuid_0x2_desc(regs, ptr, desc) {
+ for_each_parsed_cpuid_0x2_desc(regs, ptr, desc) {
switch (desc->c_type) {
case CACHE_L1_INST: l1i += desc->c_size; break;
case CACHE_L1_DATA: l1d += desc->c_size; break;
--
2.53.0
^ permalink raw reply related [flat|nested] 101+ messages in thread
* [PATCH v6 35/90] x86/cpuid: Remove direct CPUID(0x2) query helpers
2026-03-27 2:15 [PATCH v6 00/90] x86: Introduce a centralized CPUID data model Ahmed S. Darwish
` (33 preceding siblings ...)
2026-03-27 2:15 ` [PATCH v6 34/90] x86/cacheinfo: " Ahmed S. Darwish
@ 2026-03-27 2:15 ` Ahmed S. Darwish
2026-03-27 2:15 ` [PATCH v6 36/90] x86/cpuid: Parse deterministic cache parameters CPUID leaves Ahmed S. Darwish
` (56 subsequent siblings)
91 siblings, 0 replies; 101+ messages in thread
From: Ahmed S. Darwish @ 2026-03-27 2:15 UTC (permalink / raw)
To: Borislav Petkov, Dave Hansen, Ingo Molnar
Cc: Thomas Gleixner, Andrew Cooper, H. Peter Anvin,
Sean Christopherson, David Woodhouse, Peter Zijlstra,
Christian Ludloff, Sohil Mehta, John Ogness, x86, x86-cpuid, LKML,
Ahmed S. Darwish
All call sites at x86/cpu and x86/cacheinfo have been converted from
directly invoking CPUID(0x2) queries to parsed CPUID access.
Remove the direct CPUID(0x2) query helpers
cpuid_leaf_0x2()
for_each_cpuid_0x2_desc()
And rename the parsed CPUID(0x2) iterator macro
for_each_parsed_cpuid_0x2_desc()
back to
for_each_cpuid_0x2_desc()
since by now only parsed CPUID(0x2) access is allowed.
Signed-off-by: Ahmed S. Darwish <darwi@linutronix.de>
---
arch/x86/include/asm/cpuid/api.h | 75 ++------------------------------
arch/x86/kernel/cpu/cacheinfo.c | 2 +-
arch/x86/kernel/cpu/intel.c | 2 +-
3 files changed, 5 insertions(+), 74 deletions(-)
diff --git a/arch/x86/include/asm/cpuid/api.h b/arch/x86/include/asm/cpuid/api.h
index a55a28e9f0f6..f4bdfe3c9325 100644
--- a/arch/x86/include/asm/cpuid/api.h
+++ b/arch/x86/include/asm/cpuid/api.h
@@ -212,75 +212,6 @@ static inline u32 cpuid_base_hypervisor(const char *sig, u32 leaves)
return 0;
}
-/*
- * CPUID(0x2) parsing:
- */
-
-/**
- * cpuid_leaf_0x2() - Return sanitized CPUID(0x2) register output
- * @regs: Output parameter
- *
- * Query CPUID(0x2) and store its output in @regs. Force set any
- * invalid 1-byte descriptor returned by the hardware to zero (the NULL
- * cache/TLB descriptor) before returning it to the caller.
- *
- * Use for_each_cpuid_0x2_desc() to iterate over the register output in
- * parsed form.
- */
-static inline void cpuid_leaf_0x2(union leaf_0x2_regs *regs)
-{
- cpuid_read(0x2, regs);
-
- /*
- * All Intel CPUs must report an iteration count of 1. In case
- * of bogus hardware, treat all returned descriptors as NULL.
- */
- if (regs->desc[0] != 0x01) {
- for (int i = 0; i < 4; i++)
- regs->regv[i] = 0;
- return;
- }
-
- /*
- * The most significant bit (MSB) of each register must be clear.
- * If a register is invalid, replace its descriptors with NULL.
- */
- for (int i = 0; i < 4; i++) {
- if (regs->reg[i].invalid)
- regs->regv[i] = 0;
- }
-}
-
-/**
- * for_each_cpuid_0x2_desc() - Iterator for parsed CPUID(0x2) descriptors
- * @_regs: CPUID(0x2) register output, as returned by cpuid_leaf_0x2()
- * @_ptr: u8 pointer, for macro internal use only
- * @_desc: Pointer to the parsed CPUID(0x2) descriptor at each iteration
- *
- * Loop over the 1-byte descriptors in the passed CPUID(0x2) output registers
- * @_regs. Provide the parsed information for each descriptor through @_desc.
- *
- * To handle cache-specific descriptors, switch on @_desc->c_type. For TLB
- * descriptors, switch on @_desc->t_type.
- *
- * Example usage for cache descriptors::
- *
- * const struct leaf_0x2_table *desc;
- * union leaf_0x2_regs regs;
- * u8 *ptr;
- *
- * cpuid_leaf_0x2(®s);
- * for_each_cpuid_0x2_desc(regs, ptr, desc) {
- * switch (desc->c_type) {
- * ...
- * }
- * }
- */
-#define for_each_cpuid_0x2_desc(_regs, _ptr, _desc) \
- for (_ptr = &(_regs).desc[1]; \
- _ptr < &(_regs).desc[16] && (_desc = &cpuid_0x2_table[*_ptr]); \
- _ptr++)
-
/*
* CPUID(0x80000006) parsing:
*/
@@ -537,7 +468,7 @@ static inline bool cpuid_amd_hygon_has_l3_cache(void)
*/
/**
- * for_each_parsed_cpuid_0x2_desc() - Iterator for parsed CPUID(0x2) descriptors
+ * for_each_cpuid_0x2_desc() - Iterator for parsed CPUID(0x2) descriptors
* @_regs: Leaf 0x2 register output, as returned by cpuid_leaf_raw()
* @_ptr: u8 pointer, for macro internal use only
* @_desc: Pointer to parsed descriptor information at each iteration
@@ -559,13 +490,13 @@ static inline bool cpuid_amd_hygon_has_l3_cache(void)
* // Handle error
* }
*
- * for_each_parsed_cpuid_0x2_desc(regs, ptr, desc) {
+ * for_each_cpuid_0x2_desc(regs, ptr, desc) {
* switch (desc->c_type) {
* ...
* }
* }
*/
-#define for_each_parsed_cpuid_0x2_desc(_regs, _ptr, _desc) \
+#define for_each_cpuid_0x2_desc(_regs, _ptr, _desc) \
for (({ static_assert(sizeof(*_regs) == sizeof(union leaf_0x2_regs)); }), \
_ptr = &((const union leaf_0x2_regs *)(_regs))->desc[1]; \
_ptr < &((const union leaf_0x2_regs *)(_regs))->desc[16] && (_desc = &cpuid_0x2_table[*_ptr]);\
diff --git a/arch/x86/kernel/cpu/cacheinfo.c b/arch/x86/kernel/cpu/cacheinfo.c
index 6fded356f2ee..d933d58a5a61 100644
--- a/arch/x86/kernel/cpu/cacheinfo.c
+++ b/arch/x86/kernel/cpu/cacheinfo.c
@@ -398,7 +398,7 @@ static void intel_cacheinfo_0x2(struct cpuinfo_x86 *c)
if (!regs)
return;
- for_each_parsed_cpuid_0x2_desc(regs, ptr, desc) {
+ for_each_cpuid_0x2_desc(regs, ptr, desc) {
switch (desc->c_type) {
case CACHE_L1_INST: l1i += desc->c_size; break;
case CACHE_L1_DATA: l1d += desc->c_size; break;
diff --git a/arch/x86/kernel/cpu/intel.c b/arch/x86/kernel/cpu/intel.c
index cad66ca14ca4..615e3a4872b7 100644
--- a/arch/x86/kernel/cpu/intel.c
+++ b/arch/x86/kernel/cpu/intel.c
@@ -729,7 +729,7 @@ static void intel_detect_tlb(struct cpuinfo_x86 *c)
if (!regs)
return;
- for_each_parsed_cpuid_0x2_desc(regs, ptr, desc)
+ for_each_cpuid_0x2_desc(regs, ptr, desc)
intel_tlb_lookup(desc);
}
--
2.53.0
^ permalink raw reply related [flat|nested] 101+ messages in thread
* [PATCH v6 36/90] x86/cpuid: Parse deterministic cache parameters CPUID leaves
2026-03-27 2:15 [PATCH v6 00/90] x86: Introduce a centralized CPUID data model Ahmed S. Darwish
` (34 preceding siblings ...)
2026-03-27 2:15 ` [PATCH v6 35/90] x86/cpuid: Remove direct CPUID(0x2) query helpers Ahmed S. Darwish
@ 2026-03-27 2:15 ` Ahmed S. Darwish
2026-03-27 2:15 ` [PATCH v6 37/90] x86/cacheinfo: Pass a 'struct cpuinfo_x86' refrence to CPUID(0x4) code Ahmed S. Darwish
` (55 subsequent siblings)
91 siblings, 0 replies; 101+ messages in thread
From: Ahmed S. Darwish @ 2026-03-27 2:15 UTC (permalink / raw)
To: Borislav Petkov, Dave Hansen, Ingo Molnar
Cc: Thomas Gleixner, Andrew Cooper, H. Peter Anvin,
Sean Christopherson, David Woodhouse, Peter Zijlstra,
Christian Ludloff, Sohil Mehta, John Ogness, x86, x86-cpuid, LKML,
Ahmed S. Darwish
Parse CPUID(0x4) and CPUID(0x8000001d).
Query CPUID(0x4) only for Intel, Centaur, and Zhaoxin as these are the x86
vendors where it is supported. Query CPUID(0x8000001d) for AMD and Hygon.
Define a single CPUID parser read function for both leaves, as they have
the same subleaf cache enumeration logic.
Introduce the macro
define_cpuid_read_function()
to avoid code duplication between the CPUID parser default read function,
cpuid_read_generic(), and the new CPUID(0x4)/CPUID(0x8000001d) logic.
Signed-off-by: Ahmed S. Darwish <darwi@linutronix.de>
---
arch/x86/include/asm/cpuid/types.h | 2 ++
arch/x86/kernel/cpu/cpuid_parser.c | 40 +++++++++++++++++++++++-------
arch/x86/kernel/cpu/cpuid_parser.h | 4 +++
3 files changed, 37 insertions(+), 9 deletions(-)
diff --git a/arch/x86/include/asm/cpuid/types.h b/arch/x86/include/asm/cpuid/types.h
index c35de721f652..f77659303569 100644
--- a/arch/x86/include/asm/cpuid/types.h
+++ b/arch/x86/include/asm/cpuid/types.h
@@ -211,11 +211,13 @@ struct cpuid_leaves {
CPUID_LEAF ( 0x0, 0 );
CPUID_LEAF ( 0x1, 0 );
CPUID_LEAF ( 0x2, 0 );
+ CPUID_LEAF_N ( 0x4, 8 );
CPUID_LEAF ( 0x16, 0 );
CPUID_LEAF ( 0x80000000, 0 );
CPUID_LEAF ( 0x80000002, 0 );
CPUID_LEAF ( 0x80000003, 0 );
CPUID_LEAF ( 0x80000004, 0 );
+ CPUID_LEAF_N ( 0x8000001d, 8 );
CPUID_LEAF ( 0x80860000, 0 );
CPUID_LEAF ( 0x80860001, 0 );
CPUID_LEAF ( 0x80860002, 0 );
diff --git a/arch/x86/kernel/cpu/cpuid_parser.c b/arch/x86/kernel/cpu/cpuid_parser.c
index bddd9937bb2b..99507e99d8d9 100644
--- a/arch/x86/kernel/cpu/cpuid_parser.c
+++ b/arch/x86/kernel/cpu/cpuid_parser.c
@@ -31,18 +31,34 @@ static const struct cpuid_vendor_entry cpuid_vendor_entries[] = {
* Leaf read functions:
*/
+/**
+ * define_cpuid_read_function() - Generate a CPUID parser read function
+ * @suffix: Generated function name suffix (full name becomes: cpuid_read_@suffix())
+ * @_leaf_t: Type to cast the CPUID output storage pointer
+ * @_leaf: Name of the CPUID output storage pointer
+ * @_break_c: Condition to break the CPUID parsing loop, which may reference @_leaf,
+ * and where @_leaf stores each iteration's CPUID output.
+ *
+ * Define a CPUID parser read function according to the requirements stated at
+ * 'struct cpuid_parse_entry'->read().
+ */
+#define define_cpuid_read_function(suffix, _leaf_t, _leaf, _break_c) \
+static void \
+cpuid_read_##suffix(const struct cpuid_parse_entry *e, const struct cpuid_read_output *output) \
+{ \
+ struct _leaf_t *_leaf = (struct _leaf_t *)output->regs; \
+ \
+ for (int i = 0; i < e->maxcnt; i++, _leaf++, output->info->nr_entries++) { \
+ cpuid_read_subleaf(e->leaf, e->subleaf + i, _leaf); \
+ if (_break_c) \
+ break; \
+ } \
+}
+
/*
* Default CPUID read function
- * Satisfies the requirements stated at 'struct cpuid_parse_entry'->read().
*/
-static void
-cpuid_read_generic(const struct cpuid_parse_entry *e, const struct cpuid_read_output *output)
-{
- struct cpuid_regs *regs = output->regs;
-
- for (int i = 0; i < e->maxcnt; i++, regs++, output->info->nr_entries++)
- cpuid_read_subleaf(e->leaf, e->subleaf + i, regs);
-}
+define_cpuid_read_function(generic, cpuid_regs, ignored, false);
static void
cpuid_read_0x2(const struct cpuid_parse_entry *e, const struct cpuid_read_output *output)
@@ -83,6 +99,12 @@ cpuid_read_0x2(const struct cpuid_parse_entry *e, const struct cpuid_read_output
output->info->nr_entries = 1;
}
+/*
+ * Shared read function for Intel CPUID(0x4) and AMD CPUID(0x8000001d), as both have
+ * the same subleaf enumeration logic and register output format.
+ */
+define_cpuid_read_function(deterministic_cache, leaf_0x4_n, l, l->cache_type == 0);
+
/*
* Define an extended range CPUID read function
*
diff --git a/arch/x86/kernel/cpu/cpuid_parser.h b/arch/x86/kernel/cpu/cpuid_parser.h
index 1de239370652..25ca9b19e8cf 100644
--- a/arch/x86/kernel/cpu/cpuid_parser.h
+++ b/arch/x86/kernel/cpu/cpuid_parser.h
@@ -145,11 +145,13 @@ struct cpuid_parse_entry {
#define CPUID_COMMON_ENTRIES \
/* Leaf Subleaf Reader function */ \
CPUID_PARSE_ENTRY ( 0x2, 0, 0x2 ), \
+ CPUID_PARSE_ENTRY_N ( 0x4, deterministic_cache ), \
CPUID_PARSE_ENTRY ( 0x16, 0, generic ), \
CPUID_PARSE_ENTRY ( 0x80000000, 0, 0x80000000 ), \
CPUID_PARSE_ENTRY ( 0x80000002, 0, generic ), \
CPUID_PARSE_ENTRY ( 0x80000003, 0, generic ), \
CPUID_PARSE_ENTRY ( 0x80000004, 0, generic ), \
+ CPUID_PARSE_ENTRY_N ( 0x8000001d, deterministic_cache ), \
CPUID_PARSE_ENTRY ( 0x80860000, 0, 0x80860000 ), \
CPUID_PARSE_ENTRY ( 0x80860001, 0, generic ), \
CPUID_PARSE_ENTRY ( 0x80860002, 0, generic ), \
@@ -192,7 +194,9 @@ struct cpuid_vendor_entry {
#define CPUID_VENDOR_ENTRIES \
/* Leaf Vendor list */ \
CPUID_VENDOR_ENTRY(0x2, X86_VENDOR_INTEL, X86_VENDOR_CENTAUR, X86_VENDOR_ZHAOXIN),\
+ CPUID_VENDOR_ENTRY(0x4, X86_VENDOR_INTEL, X86_VENDOR_CENTAUR, X86_VENDOR_ZHAOXIN),\
CPUID_VENDOR_ENTRY(0x16, X86_VENDOR_INTEL), \
+ CPUID_VENDOR_ENTRY(0x8000001d, X86_VENDOR_AMD, X86_VENDOR_HYGON), \
CPUID_VENDOR_ENTRY(0x80860000, X86_VENDOR_TRANSMETA), \
CPUID_VENDOR_ENTRY(0x80860001, X86_VENDOR_TRANSMETA), \
CPUID_VENDOR_ENTRY(0x80860002, X86_VENDOR_TRANSMETA), \
--
2.53.0
^ permalink raw reply related [flat|nested] 101+ messages in thread
* [PATCH v6 37/90] x86/cacheinfo: Pass a 'struct cpuinfo_x86' refrence to CPUID(0x4) code
2026-03-27 2:15 [PATCH v6 00/90] x86: Introduce a centralized CPUID data model Ahmed S. Darwish
` (35 preceding siblings ...)
2026-03-27 2:15 ` [PATCH v6 36/90] x86/cpuid: Parse deterministic cache parameters CPUID leaves Ahmed S. Darwish
@ 2026-03-27 2:15 ` Ahmed S. Darwish
2026-03-27 2:15 ` [PATCH v6 38/90] x86/cacheinfo: Use parsed CPUID(0x4) Ahmed S. Darwish
` (54 subsequent siblings)
91 siblings, 0 replies; 101+ messages in thread
From: Ahmed S. Darwish @ 2026-03-27 2:15 UTC (permalink / raw)
To: Borislav Petkov, Dave Hansen, Ingo Molnar
Cc: Thomas Gleixner, Andrew Cooper, H. Peter Anvin,
Sean Christopherson, David Woodhouse, Peter Zijlstra,
Christian Ludloff, Sohil Mehta, John Ogness, x86, x86-cpuid, LKML,
Ahmed S. Darwish
Prepare the CPUID(0x4) cache topology code for using the parsed CPUID API
instead of invoking direct CPUID queries.
Since the CPUID API requires a 'struct cpuinfo_x86' reference, trickle it
from <linux/cacheinfo.h>'s populate_cache_leaves() x86 implementation down
to fill_cpuid4_info() and its Intel-specific CPUID(0x4) code.
No functional change intended.
Suggested-by: Ingo Molnar <mingo@kernel.org>
Signed-off-by: Ahmed S. Darwish <darwi@linutronix.de>
Link: https://lore.kernel.org/lkml/aBnEBbDATdE2LTGU@gmail.com
---
arch/x86/kernel/cpu/cacheinfo.c | 14 +++++++-------
1 file changed, 7 insertions(+), 7 deletions(-)
diff --git a/arch/x86/kernel/cpu/cacheinfo.c b/arch/x86/kernel/cpu/cacheinfo.c
index d933d58a5a61..07f7e7b667ed 100644
--- a/arch/x86/kernel/cpu/cacheinfo.c
+++ b/arch/x86/kernel/cpu/cacheinfo.c
@@ -252,7 +252,7 @@ static int amd_fill_cpuid4_info(int index, struct _cpuid4_info *id4)
return cpuid4_info_fill_done(id4, eax, ebx, ecx);
}
-static int intel_fill_cpuid4_info(int index, struct _cpuid4_info *id4)
+static int intel_fill_cpuid4_info(struct cpuinfo_x86 *unused, int index, struct _cpuid4_info *id4)
{
union _cpuid4_leaf_eax eax;
union _cpuid4_leaf_ebx ebx;
@@ -264,13 +264,13 @@ static int intel_fill_cpuid4_info(int index, struct _cpuid4_info *id4)
return cpuid4_info_fill_done(id4, eax, ebx, ecx);
}
-static int fill_cpuid4_info(int index, struct _cpuid4_info *id4)
+static int fill_cpuid4_info(struct cpuinfo_x86 *c, int index, struct _cpuid4_info *id4)
{
u8 cpu_vendor = boot_cpu_data.x86_vendor;
return (cpu_vendor == X86_VENDOR_AMD || cpu_vendor == X86_VENDOR_HYGON) ?
amd_fill_cpuid4_info(index, id4) :
- intel_fill_cpuid4_info(index, id4);
+ intel_fill_cpuid4_info(c, index, id4);
}
static int find_num_cache_leaves(struct cpuinfo_x86 *c)
@@ -443,7 +443,7 @@ static bool intel_cacheinfo_0x4(struct cpuinfo_x86 *c)
struct _cpuid4_info id4 = {};
int ret;
- ret = intel_fill_cpuid4_info(i, &id4);
+ ret = intel_fill_cpuid4_info(c, i, &id4);
if (ret < 0)
continue;
@@ -612,17 +612,17 @@ int populate_cache_leaves(unsigned int cpu)
struct cpu_cacheinfo *this_cpu_ci = get_cpu_cacheinfo(cpu);
struct cacheinfo *ci = this_cpu_ci->info_list;
u8 cpu_vendor = boot_cpu_data.x86_vendor;
- u32 apicid = cpu_data(cpu).topo.apicid;
+ struct cpuinfo_x86 *c = &cpu_data(cpu);
struct amd_northbridge *nb = NULL;
struct _cpuid4_info id4 = {};
int idx, ret;
for (idx = 0; idx < this_cpu_ci->num_leaves; idx++) {
- ret = fill_cpuid4_info(idx, &id4);
+ ret = fill_cpuid4_info(c, idx, &id4);
if (ret)
return ret;
- id4.id = get_cache_id(apicid, &id4);
+ id4.id = get_cache_id(c->topo.apicid, &id4);
if (cpu_vendor == X86_VENDOR_AMD || cpu_vendor == X86_VENDOR_HYGON)
nb = amd_init_l3_cache(idx);
--
2.53.0
^ permalink raw reply related [flat|nested] 101+ messages in thread
* [PATCH v6 38/90] x86/cacheinfo: Use parsed CPUID(0x4)
2026-03-27 2:15 [PATCH v6 00/90] x86: Introduce a centralized CPUID data model Ahmed S. Darwish
` (36 preceding siblings ...)
2026-03-27 2:15 ` [PATCH v6 37/90] x86/cacheinfo: Pass a 'struct cpuinfo_x86' refrence to CPUID(0x4) code Ahmed S. Darwish
@ 2026-03-27 2:15 ` Ahmed S. Darwish
2026-03-27 2:15 ` [PATCH v6 39/90] x86/cacheinfo: Use parsed CPUID(0x8000001d) Ahmed S. Darwish
` (53 subsequent siblings)
91 siblings, 0 replies; 101+ messages in thread
From: Ahmed S. Darwish @ 2026-03-27 2:15 UTC (permalink / raw)
To: Borislav Petkov, Dave Hansen, Ingo Molnar
Cc: Thomas Gleixner, Andrew Cooper, H. Peter Anvin,
Sean Christopherson, David Woodhouse, Peter Zijlstra,
Christian Ludloff, Sohil Mehta, John Ogness, x86, x86-cpuid, LKML,
Ahmed S. Darwish
For Intel cacheinfo, use parsed CPUID(0x4) instead of a direct CPUID query.
Use the CPUID API
cpuid_subleaf_count(c, 0x4)
to determine the number of CPUID(0x4) cache subleaves instead of calling
find_num_cache_leaves(). The latter function internally invokes direct
CPUID(0x4) queries.
Since find_num_cache_leaves() is no longer needed for Intel code paths,
make its name and implementation AMD-specific. Adjust the AMD code paths
accordingly.
At intel_cacheinfo_0x4(), remove the max CPUID level check since
cpuid_subleaf_count(c, 0x4) will return zero if CPUID(0x4) is not valid.
Signed-off-by: Ahmed S. Darwish <darwi@linutronix.de>
---
arch/x86/kernel/cpu/cacheinfo.c | 40 ++++++++++++++-------------------
1 file changed, 17 insertions(+), 23 deletions(-)
diff --git a/arch/x86/kernel/cpu/cacheinfo.c b/arch/x86/kernel/cpu/cacheinfo.c
index 07f7e7b667ed..91020f85c000 100644
--- a/arch/x86/kernel/cpu/cacheinfo.c
+++ b/arch/x86/kernel/cpu/cacheinfo.c
@@ -252,16 +252,17 @@ static int amd_fill_cpuid4_info(int index, struct _cpuid4_info *id4)
return cpuid4_info_fill_done(id4, eax, ebx, ecx);
}
-static int intel_fill_cpuid4_info(struct cpuinfo_x86 *unused, int index, struct _cpuid4_info *id4)
+static int intel_fill_cpuid4_info(struct cpuinfo_x86 *c, int index, struct _cpuid4_info *id4)
{
- union _cpuid4_leaf_eax eax;
- union _cpuid4_leaf_ebx ebx;
- union _cpuid4_leaf_ecx ecx;
- u32 ignored;
+ const struct cpuid_regs *regs = cpuid_subleaf_n_raw(c, 0x4, index);
- cpuid_count(4, index, &eax.full, &ebx.full, &ecx.full, &ignored);
+ if (!regs)
+ return -EIO;
- return cpuid4_info_fill_done(id4, eax, ebx, ecx);
+ return cpuid4_info_fill_done(id4,
+ (union _cpuid4_leaf_eax)(regs->eax),
+ (union _cpuid4_leaf_ebx)(regs->ebx),
+ (union _cpuid4_leaf_ecx)(regs->ecx));
}
static int fill_cpuid4_info(struct cpuinfo_x86 *c, int index, struct _cpuid4_info *id4)
@@ -273,17 +274,16 @@ static int fill_cpuid4_info(struct cpuinfo_x86 *c, int index, struct _cpuid4_inf
intel_fill_cpuid4_info(c, index, id4);
}
-static int find_num_cache_leaves(struct cpuinfo_x86 *c)
+static int amd_find_num_cache_leaves(struct cpuinfo_x86 *c)
{
- unsigned int eax, ebx, ecx, edx, op;
union _cpuid4_leaf_eax cache_eax;
+ unsigned int eax, ebx, ecx, edx;
int i = -1;
- /* Do a CPUID(op) loop to calculate num_cache_leaves */
- op = (c->x86_vendor == X86_VENDOR_AMD || c->x86_vendor == X86_VENDOR_HYGON) ? 0x8000001d : 4;
+ /* Do a CPUID(0x8000001d) loop to calculate num_cache_leaves */
do {
++i;
- cpuid_count(op, i, &eax, &ebx, &ecx, &edx);
+ cpuid_count(0x8000001d, i, &eax, &ebx, &ecx, &edx);
cache_eax.full = eax;
} while (cache_eax.split.type != CTYPE_NULL);
return i;
@@ -328,7 +328,7 @@ void cacheinfo_amd_init_llc_id(struct cpuinfo_x86 *c, u16 die_id)
* Newer families: LLC ID is calculated from the number
* of threads sharing the L3 cache.
*/
- u32 llc_index = find_num_cache_leaves(c) - 1;
+ u32 llc_index = amd_find_num_cache_leaves(c) - 1;
struct _cpuid4_info id4 = {};
if (!amd_fill_cpuid4_info(llc_index, &id4))
@@ -353,7 +353,7 @@ void init_amd_cacheinfo(struct cpuinfo_x86 *c)
struct cpu_cacheinfo *ci = get_cpu_cacheinfo(c->cpu_index);
if (boot_cpu_has(X86_FEATURE_TOPOEXT))
- ci->num_leaves = find_num_cache_leaves(c);
+ ci->num_leaves = amd_find_num_cache_leaves(c);
else if (c->extended_cpuid_level >= 0x80000006)
ci->num_leaves = (cpuid_edx(0x80000006) & 0xf000) ? 4 : 3;
}
@@ -362,7 +362,7 @@ void init_hygon_cacheinfo(struct cpuinfo_x86 *c)
{
struct cpu_cacheinfo *ci = get_cpu_cacheinfo(c->cpu_index);
- ci->num_leaves = find_num_cache_leaves(c);
+ ci->num_leaves = amd_find_num_cache_leaves(c);
}
static void intel_cacheinfo_done(struct cpuinfo_x86 *c, unsigned int l3,
@@ -426,15 +426,9 @@ static bool intel_cacheinfo_0x4(struct cpuinfo_x86 *c)
unsigned int l2_id = BAD_APICID, l3_id = BAD_APICID;
unsigned int l1d = 0, l1i = 0, l2 = 0, l3 = 0;
- if (c->cpuid_level < 4)
- return false;
-
- /*
- * There should be at least one leaf. A non-zero value means
- * that the number of leaves has been previously initialized.
- */
+ /* Non-zero means that it has been previously initialized */
if (!ci->num_leaves)
- ci->num_leaves = find_num_cache_leaves(c);
+ ci->num_leaves = cpuid_subleaf_count(c, 0x4);
if (!ci->num_leaves)
return false;
--
2.53.0
^ permalink raw reply related [flat|nested] 101+ messages in thread
* [PATCH v6 39/90] x86/cacheinfo: Use parsed CPUID(0x8000001d)
2026-03-27 2:15 [PATCH v6 00/90] x86: Introduce a centralized CPUID data model Ahmed S. Darwish
` (37 preceding siblings ...)
2026-03-27 2:15 ` [PATCH v6 38/90] x86/cacheinfo: Use parsed CPUID(0x4) Ahmed S. Darwish
@ 2026-03-27 2:15 ` Ahmed S. Darwish
2026-03-27 2:15 ` [PATCH v6 40/90] x86/cpuid: Parse CPUID(0x80000005), CPUID(0x80000006), CPUID(0x80000008) Ahmed S. Darwish
` (52 subsequent siblings)
91 siblings, 0 replies; 101+ messages in thread
From: Ahmed S. Darwish @ 2026-03-27 2:15 UTC (permalink / raw)
To: Borislav Petkov, Dave Hansen, Ingo Molnar
Cc: Thomas Gleixner, Andrew Cooper, H. Peter Anvin,
Sean Christopherson, David Woodhouse, Peter Zijlstra,
Christian Ludloff, Sohil Mehta, John Ogness, x86, x86-cpuid, LKML,
Ahmed S. Darwish
For AMD cacheinfo, use parsed CPUID(0x8000001d) instead of CPUID queries.
Beside the CPUID parser centralization benefits, this allows using the
auto-generated x86-cpuid-db data types, and their C99 bitfields, instead of
doing ugly bitwise operations on the CPUID output.
Trickle down a 'struct cpuinfo_x86' reference to the relevant functions as
the CPUID APIs require it.
Use the parsed CPUID API
cpuid_subleaf_count(c, 0x8000001d)
instead of calling amd_find_num_cache_leaves() and its direct CPUID
queries. Remove the latter function as it is no longer used.
Keep using the 'union _cpuid4_leaf_eax/ebx/ecx' data types as they are
required by the AMD CPUID(0x4) emulation code. A follow up commit will
replace them with their auto-generated x86-cpuid-db equivalents.
Signed-off-by: Ahmed S. Darwish <darwi@linutronix.de>
---
arch/x86/kernel/cpu/cacheinfo.c | 41 +++++++++++++--------------------
1 file changed, 16 insertions(+), 25 deletions(-)
diff --git a/arch/x86/kernel/cpu/cacheinfo.c b/arch/x86/kernel/cpu/cacheinfo.c
index 91020f85c000..86a8e1dad935 100644
--- a/arch/x86/kernel/cpu/cacheinfo.c
+++ b/arch/x86/kernel/cpu/cacheinfo.c
@@ -237,16 +237,22 @@ static int cpuid4_info_fill_done(struct _cpuid4_info *id4, union _cpuid4_leaf_ea
return 0;
}
-static int amd_fill_cpuid4_info(int index, struct _cpuid4_info *id4)
+static int amd_fill_cpuid4_info(struct cpuinfo_x86 *c, int index, struct _cpuid4_info *id4)
{
union _cpuid4_leaf_eax eax;
union _cpuid4_leaf_ebx ebx;
union _cpuid4_leaf_ecx ecx;
- u32 ignored;
- if (boot_cpu_has(X86_FEATURE_TOPOEXT) || boot_cpu_data.x86_vendor == X86_VENDOR_HYGON)
- cpuid_count(0x8000001d, index, &eax.full, &ebx.full, &ecx.full, &ignored);
- else
+ if (boot_cpu_has(X86_FEATURE_TOPOEXT) || boot_cpu_data.x86_vendor == X86_VENDOR_HYGON) {
+ const struct cpuid_regs *regs = cpuid_subleaf_n_raw(c, 0x8000001d, index);
+
+ if (!regs)
+ return -EIO;
+
+ eax.full = regs->eax;
+ ebx.full = regs->ebx;
+ ecx.full = regs->ecx;
+ } else
legacy_amd_cpuid4(index, &eax, &ebx, &ecx);
return cpuid4_info_fill_done(id4, eax, ebx, ecx);
@@ -270,25 +276,10 @@ static int fill_cpuid4_info(struct cpuinfo_x86 *c, int index, struct _cpuid4_inf
u8 cpu_vendor = boot_cpu_data.x86_vendor;
return (cpu_vendor == X86_VENDOR_AMD || cpu_vendor == X86_VENDOR_HYGON) ?
- amd_fill_cpuid4_info(index, id4) :
+ amd_fill_cpuid4_info(c, index, id4) :
intel_fill_cpuid4_info(c, index, id4);
}
-static int amd_find_num_cache_leaves(struct cpuinfo_x86 *c)
-{
- union _cpuid4_leaf_eax cache_eax;
- unsigned int eax, ebx, ecx, edx;
- int i = -1;
-
- /* Do a CPUID(0x8000001d) loop to calculate num_cache_leaves */
- do {
- ++i;
- cpuid_count(0x8000001d, i, &eax, &ebx, &ecx, &edx);
- cache_eax.full = eax;
- } while (cache_eax.split.type != CTYPE_NULL);
- return i;
-}
-
/*
* The max shared threads number comes from CPUID(0x4) EAX[25-14] with input
* ECX as cache index. Then right shift apicid by the number's order to get
@@ -328,10 +319,10 @@ void cacheinfo_amd_init_llc_id(struct cpuinfo_x86 *c, u16 die_id)
* Newer families: LLC ID is calculated from the number
* of threads sharing the L3 cache.
*/
- u32 llc_index = amd_find_num_cache_leaves(c) - 1;
+ u32 llc_index = cpuid_subleaf_count(c, 0x8000001d) - 1;
struct _cpuid4_info id4 = {};
- if (!amd_fill_cpuid4_info(llc_index, &id4))
+ if (!amd_fill_cpuid4_info(c, llc_index, &id4))
c->topo.llc_id = get_cache_id(c->topo.apicid, &id4);
}
}
@@ -353,7 +344,7 @@ void init_amd_cacheinfo(struct cpuinfo_x86 *c)
struct cpu_cacheinfo *ci = get_cpu_cacheinfo(c->cpu_index);
if (boot_cpu_has(X86_FEATURE_TOPOEXT))
- ci->num_leaves = amd_find_num_cache_leaves(c);
+ ci->num_leaves = cpuid_subleaf_count(c, 0x8000001d);
else if (c->extended_cpuid_level >= 0x80000006)
ci->num_leaves = (cpuid_edx(0x80000006) & 0xf000) ? 4 : 3;
}
@@ -362,7 +353,7 @@ void init_hygon_cacheinfo(struct cpuinfo_x86 *c)
{
struct cpu_cacheinfo *ci = get_cpu_cacheinfo(c->cpu_index);
- ci->num_leaves = amd_find_num_cache_leaves(c);
+ ci->num_leaves = cpuid_subleaf_count(c, 0x8000001d);
}
static void intel_cacheinfo_done(struct cpuinfo_x86 *c, unsigned int l3,
--
2.53.0
^ permalink raw reply related [flat|nested] 101+ messages in thread
* [PATCH v6 40/90] x86/cpuid: Parse CPUID(0x80000005), CPUID(0x80000006), CPUID(0x80000008)
2026-03-27 2:15 [PATCH v6 00/90] x86: Introduce a centralized CPUID data model Ahmed S. Darwish
` (38 preceding siblings ...)
2026-03-27 2:15 ` [PATCH v6 39/90] x86/cacheinfo: Use parsed CPUID(0x8000001d) Ahmed S. Darwish
@ 2026-03-27 2:15 ` Ahmed S. Darwish
2026-03-27 2:15 ` [PATCH v6 41/90] x86/cacheinfo: Use auto-generated data types Ahmed S. Darwish
` (51 subsequent siblings)
91 siblings, 0 replies; 101+ messages in thread
From: Ahmed S. Darwish @ 2026-03-27 2:15 UTC (permalink / raw)
To: Borislav Petkov, Dave Hansen, Ingo Molnar
Cc: Thomas Gleixner, Andrew Cooper, H. Peter Anvin,
Sean Christopherson, David Woodhouse, Peter Zijlstra,
Christian Ludloff, Sohil Mehta, John Ogness, x86, x86-cpuid, LKML,
Ahmed S. Darwish
Parse AMD cacheinfo CPUID(0x80000005) and CPUID(0x80000006).
Also parse the CPU capacity parameters at CPUID(0x80000008).
This allows converting their call sites to parsed CPUID access instead of
issuing CPUID queries.
Signed-off-by: Ahmed S. Darwish <darwi@linutronix.de>
---
arch/x86/include/asm/cpuid/types.h | 3 +++
arch/x86/kernel/cpu/cpuid_parser.h | 3 +++
2 files changed, 6 insertions(+)
diff --git a/arch/x86/include/asm/cpuid/types.h b/arch/x86/include/asm/cpuid/types.h
index f77659303569..f50e54bfb514 100644
--- a/arch/x86/include/asm/cpuid/types.h
+++ b/arch/x86/include/asm/cpuid/types.h
@@ -217,6 +217,9 @@ struct cpuid_leaves {
CPUID_LEAF ( 0x80000002, 0 );
CPUID_LEAF ( 0x80000003, 0 );
CPUID_LEAF ( 0x80000004, 0 );
+ CPUID_LEAF ( 0x80000005, 0 );
+ CPUID_LEAF ( 0x80000006, 0 );
+ CPUID_LEAF ( 0x80000008, 0 );
CPUID_LEAF_N ( 0x8000001d, 8 );
CPUID_LEAF ( 0x80860000, 0 );
CPUID_LEAF ( 0x80860001, 0 );
diff --git a/arch/x86/kernel/cpu/cpuid_parser.h b/arch/x86/kernel/cpu/cpuid_parser.h
index 25ca9b19e8cf..ab391de03a92 100644
--- a/arch/x86/kernel/cpu/cpuid_parser.h
+++ b/arch/x86/kernel/cpu/cpuid_parser.h
@@ -151,6 +151,9 @@ struct cpuid_parse_entry {
CPUID_PARSE_ENTRY ( 0x80000002, 0, generic ), \
CPUID_PARSE_ENTRY ( 0x80000003, 0, generic ), \
CPUID_PARSE_ENTRY ( 0x80000004, 0, generic ), \
+ CPUID_PARSE_ENTRY ( 0x80000005, 0, generic ), \
+ CPUID_PARSE_ENTRY ( 0x80000006, 0, generic ), \
+ CPUID_PARSE_ENTRY ( 0x80000008, 0, generic ), \
CPUID_PARSE_ENTRY_N ( 0x8000001d, deterministic_cache ), \
CPUID_PARSE_ENTRY ( 0x80860000, 0, 0x80860000 ), \
CPUID_PARSE_ENTRY ( 0x80860001, 0, generic ), \
--
2.53.0
^ permalink raw reply related [flat|nested] 101+ messages in thread
* [PATCH v6 41/90] x86/cacheinfo: Use auto-generated data types
2026-03-27 2:15 [PATCH v6 00/90] x86: Introduce a centralized CPUID data model Ahmed S. Darwish
` (39 preceding siblings ...)
2026-03-27 2:15 ` [PATCH v6 40/90] x86/cpuid: Parse CPUID(0x80000005), CPUID(0x80000006), CPUID(0x80000008) Ahmed S. Darwish
@ 2026-03-27 2:15 ` Ahmed S. Darwish
2026-03-27 2:15 ` [PATCH v6 42/90] x86/cacheinfo: Use parsed CPUID(0x80000005) and CPUID(0x80000006) Ahmed S. Darwish
` (50 subsequent siblings)
91 siblings, 0 replies; 101+ messages in thread
From: Ahmed S. Darwish @ 2026-03-27 2:15 UTC (permalink / raw)
To: Borislav Petkov, Dave Hansen, Ingo Molnar
Cc: Thomas Gleixner, Andrew Cooper, H. Peter Anvin,
Sean Christopherson, David Woodhouse, Peter Zijlstra,
Christian Ludloff, Sohil Mehta, John Ogness, x86, x86-cpuid, LKML,
Ahmed S. Darwish
For the AMD CPUID(0x4) emulation logic, use the auto-generated
<asm/cpuid/leaf_types.h> data type:
struct leaf_0x4_n
instead of the manually-defined:
union _cpuid4_leaf_{eax,ebx,ecx}
ones. Remove such unions entirely as they are no longer used.
Signed-off-by: Ahmed S. Darwish <darwi@linutronix.de>
Link: https://gitlab.com/x86-cpuid.org/x86-cpuid-db
---
arch/x86/kernel/cpu/cacheinfo.c | 127 +++++++++++---------------------
1 file changed, 42 insertions(+), 85 deletions(-)
diff --git a/arch/x86/kernel/cpu/cacheinfo.c b/arch/x86/kernel/cpu/cacheinfo.c
index 86a8e1dad935..209a0c708213 100644
--- a/arch/x86/kernel/cpu/cacheinfo.c
+++ b/arch/x86/kernel/cpu/cacheinfo.c
@@ -41,39 +41,8 @@ enum _cache_type {
CTYPE_UNIFIED = 3
};
-union _cpuid4_leaf_eax {
- struct {
- enum _cache_type type :5;
- unsigned int level :3;
- unsigned int is_self_initializing :1;
- unsigned int is_fully_associative :1;
- unsigned int reserved :4;
- unsigned int num_threads_sharing :12;
- unsigned int num_cores_on_die :6;
- } split;
- u32 full;
-};
-
-union _cpuid4_leaf_ebx {
- struct {
- unsigned int coherency_line_size :12;
- unsigned int physical_line_partition :10;
- unsigned int ways_of_associativity :10;
- } split;
- u32 full;
-};
-
-union _cpuid4_leaf_ecx {
- struct {
- unsigned int number_of_sets :32;
- } split;
- u32 full;
-};
-
struct _cpuid4_info {
- union _cpuid4_leaf_eax eax;
- union _cpuid4_leaf_ebx ebx;
- union _cpuid4_leaf_ecx ecx;
+ struct leaf_0x4_n regs;
unsigned int id;
unsigned long size;
};
@@ -148,17 +117,14 @@ static const unsigned short assocs[] = {
static const unsigned char levels[] = { 1, 1, 2, 3 };
static const unsigned char types[] = { 1, 2, 3, 3 };
-static void legacy_amd_cpuid4(int index, union _cpuid4_leaf_eax *eax,
- union _cpuid4_leaf_ebx *ebx, union _cpuid4_leaf_ecx *ecx)
+static void legacy_amd_cpuid4(int index, struct leaf_0x4_n *regs)
{
unsigned int dummy, line_size, lines_per_tag, assoc, size_in_kb;
union l1_cache l1i, l1d, *l1;
union l2_cache l2;
union l3_cache l3;
- eax->full = 0;
- ebx->full = 0;
- ecx->full = 0;
+ *regs = (struct leaf_0x4_n){ };
cpuid(0x80000005, &dummy, &dummy, &l1d.val, &l1i.val);
cpuid(0x80000006, &dummy, &dummy, &l2.val, &l3.val);
@@ -204,71 +170,62 @@ static void legacy_amd_cpuid4(int index, union _cpuid4_leaf_eax *eax,
return;
}
- eax->split.is_self_initializing = 1;
- eax->split.type = types[index];
- eax->split.level = levels[index];
- eax->split.num_threads_sharing = 0;
- eax->split.num_cores_on_die = topology_num_cores_per_package();
+ regs->cache_self_init = 1;
+ regs->cache_type = types[index];
+ regs->cache_level = levels[index];
+ regs->num_threads_sharing = 0;
+ regs->num_cores_on_die = topology_num_cores_per_package();
if (assoc == AMD_CPUID4_FULLY_ASSOCIATIVE)
- eax->split.is_fully_associative = 1;
+ regs->fully_associative = 1;
- ebx->split.coherency_line_size = line_size - 1;
- ebx->split.ways_of_associativity = assoc - 1;
- ebx->split.physical_line_partition = lines_per_tag - 1;
- ecx->split.number_of_sets = (size_in_kb * 1024) / line_size /
- (ebx->split.ways_of_associativity + 1) - 1;
+ regs->cache_linesize = line_size - 1;
+ regs->cache_nways = assoc - 1;
+ regs->cache_npartitions = lines_per_tag - 1;
+ regs->cache_nsets = (size_in_kb * 1024) / line_size /
+ (regs->cache_nways + 1) - 1;
}
-static int cpuid4_info_fill_done(struct _cpuid4_info *id4, union _cpuid4_leaf_eax eax,
- union _cpuid4_leaf_ebx ebx, union _cpuid4_leaf_ecx ecx)
+static int cpuid4_info_fill_done(struct _cpuid4_info *id4, const struct leaf_0x4_n *regs)
{
- if (eax.split.type == CTYPE_NULL)
+ if (regs->cache_type == CTYPE_NULL)
return -EIO;
- id4->eax = eax;
- id4->ebx = ebx;
- id4->ecx = ecx;
- id4->size = (ecx.split.number_of_sets + 1) *
- (ebx.split.coherency_line_size + 1) *
- (ebx.split.physical_line_partition + 1) *
- (ebx.split.ways_of_associativity + 1);
+ id4->regs = *regs;
+ id4->size = (regs->cache_nsets + 1) *
+ (regs->cache_linesize + 1) *
+ (regs->cache_npartitions + 1) *
+ (regs->cache_nways + 1);
return 0;
}
static int amd_fill_cpuid4_info(struct cpuinfo_x86 *c, int index, struct _cpuid4_info *id4)
{
- union _cpuid4_leaf_eax eax;
- union _cpuid4_leaf_ebx ebx;
- union _cpuid4_leaf_ecx ecx;
+ struct leaf_0x4_n l_0x4_regs;
if (boot_cpu_has(X86_FEATURE_TOPOEXT) || boot_cpu_data.x86_vendor == X86_VENDOR_HYGON) {
- const struct cpuid_regs *regs = cpuid_subleaf_n_raw(c, 0x8000001d, index);
+ const struct leaf_0x8000001d_n *regs = cpuid_subleaf_n(c, 0x8000001d, index);
if (!regs)
return -EIO;
- eax.full = regs->eax;
- ebx.full = regs->ebx;
- ecx.full = regs->ecx;
+ /* CPUID(0x8000001d) and CPUID(0x4) have the same bitfields */
+ l_0x4_regs = *(struct leaf_0x4_n *)regs;
} else
- legacy_amd_cpuid4(index, &eax, &ebx, &ecx);
+ legacy_amd_cpuid4(index, &l_0x4_regs);
- return cpuid4_info_fill_done(id4, eax, ebx, ecx);
+ return cpuid4_info_fill_done(id4, &l_0x4_regs);
}
static int intel_fill_cpuid4_info(struct cpuinfo_x86 *c, int index, struct _cpuid4_info *id4)
{
- const struct cpuid_regs *regs = cpuid_subleaf_n_raw(c, 0x4, index);
+ const struct leaf_0x4_n *regs = cpuid_subleaf_n(c, 0x4, index);
if (!regs)
return -EIO;
- return cpuid4_info_fill_done(id4,
- (union _cpuid4_leaf_eax)(regs->eax),
- (union _cpuid4_leaf_ebx)(regs->ebx),
- (union _cpuid4_leaf_ecx)(regs->ecx));
+ return cpuid4_info_fill_done(id4, regs);
}
static int fill_cpuid4_info(struct cpuinfo_x86 *c, int index, struct _cpuid4_info *id4)
@@ -290,7 +247,7 @@ static unsigned int get_cache_id(u32 apicid, const struct _cpuid4_info *id4)
unsigned long num_threads_sharing;
int index_msb;
- num_threads_sharing = 1 + id4->eax.split.num_threads_sharing;
+ num_threads_sharing = 1 + id4->regs.num_threads_sharing;
index_msb = get_count_order(num_threads_sharing);
return apicid >> index_msb;
@@ -406,7 +363,7 @@ static unsigned int calc_cache_topo_id(struct cpuinfo_x86 *c, const struct _cpui
unsigned int num_threads_sharing;
int index_msb;
- num_threads_sharing = 1 + id4->eax.split.num_threads_sharing;
+ num_threads_sharing = 1 + id4->regs.num_threads_sharing;
index_msb = get_count_order(num_threads_sharing);
return c->topo.apicid & ~((1 << index_msb) - 1);
}
@@ -432,11 +389,11 @@ static bool intel_cacheinfo_0x4(struct cpuinfo_x86 *c)
if (ret < 0)
continue;
- switch (id4.eax.split.level) {
+ switch (id4.regs.cache_level) {
case 1:
- if (id4.eax.split.type == CTYPE_DATA)
+ if (id4.regs.cache_type == CTYPE_DATA)
l1d = id4.size / 1024;
- else if (id4.eax.split.type == CTYPE_INST)
+ else if (id4.regs.cache_type == CTYPE_INST)
l1i = id4.size / 1024;
break;
case 2:
@@ -497,7 +454,7 @@ static int __cache_amd_cpumap_setup(unsigned int cpu, int index,
} else if (boot_cpu_has(X86_FEATURE_TOPOEXT)) {
unsigned int apicid, nshared, first, last;
- nshared = id4->eax.split.num_threads_sharing + 1;
+ nshared = id4->regs.num_threads_sharing + 1;
apicid = cpu_data(cpu).topo.apicid;
first = apicid - (apicid % nshared);
last = first + nshared - 1;
@@ -544,7 +501,7 @@ static void __cache_cpumap_setup(unsigned int cpu, int index,
}
ci = this_cpu_ci->info_list + index;
- num_threads_sharing = 1 + id4->eax.split.num_threads_sharing;
+ num_threads_sharing = 1 + id4->regs.num_threads_sharing;
cpumask_set_cpu(cpu, &ci->shared_cpu_map);
if (num_threads_sharing == 1)
@@ -571,13 +528,13 @@ static void ci_info_init(struct cacheinfo *ci, const struct _cpuid4_info *id4,
{
ci->id = id4->id;
ci->attributes = CACHE_ID;
- ci->level = id4->eax.split.level;
- ci->type = cache_type_map[id4->eax.split.type];
- ci->coherency_line_size = id4->ebx.split.coherency_line_size + 1;
- ci->ways_of_associativity = id4->ebx.split.ways_of_associativity + 1;
+ ci->level = id4->regs.cache_level;
+ ci->type = cache_type_map[id4->regs.cache_type];
+ ci->coherency_line_size = id4->regs.cache_linesize + 1;
+ ci->ways_of_associativity = id4->regs.cache_nways + 1;
ci->size = id4->size;
- ci->number_of_sets = id4->ecx.split.number_of_sets + 1;
- ci->physical_line_partition = id4->ebx.split.physical_line_partition + 1;
+ ci->number_of_sets = id4->regs.cache_nsets + 1;
+ ci->physical_line_partition = id4->regs.cache_npartitions + 1;
ci->priv = nb;
}
--
2.53.0
^ permalink raw reply related [flat|nested] 101+ messages in thread
* [PATCH v6 42/90] x86/cacheinfo: Use parsed CPUID(0x80000005) and CPUID(0x80000006)
2026-03-27 2:15 [PATCH v6 00/90] x86: Introduce a centralized CPUID data model Ahmed S. Darwish
` (40 preceding siblings ...)
2026-03-27 2:15 ` [PATCH v6 41/90] x86/cacheinfo: Use auto-generated data types Ahmed S. Darwish
@ 2026-03-27 2:15 ` Ahmed S. Darwish
2026-03-27 2:15 ` [PATCH v6 43/90] x86/cacheinfo: Use parsed CPUID(0x80000006) Ahmed S. Darwish
` (49 subsequent siblings)
91 siblings, 0 replies; 101+ messages in thread
From: Ahmed S. Darwish @ 2026-03-27 2:15 UTC (permalink / raw)
To: Borislav Petkov, Dave Hansen, Ingo Molnar
Cc: Thomas Gleixner, Andrew Cooper, H. Peter Anvin,
Sean Christopherson, David Woodhouse, Peter Zijlstra,
Christian Ludloff, Sohil Mehta, John Ogness, x86, x86-cpuid, LKML,
Ahmed S. Darwish
For AMD CPUID(0x4)-emulation logic, use parsed CPUID(0x80000005) and
CPUID(0x80000006) instead of invoking CPUID queries.
Beside the CPUID parser centralization benefits, this allows using the auto
generated x86-cpuid-db data types, and their C99 bitfields, instead of
doing ugly bitwise operations or defining custom call site types.
Remove the 'union l[123]_cache' data types as they are no longer needed.
Replace the expression:
ci->num_leaves = (cpuid_edx(0x80000006) & 0xf000) ? 4 : 3;
with:
ci->num_leaves = cpuid_leaf(c, 0x80000006)->l3_assoc ? 4 : 3;
since per AMD manuals, an L3 associativity level of zero implies the
absence of a CPU L3 cache.
While at it, separate the "Fallback AMD CPUID(0x4) emulation" comment from
the "AMD_L2_L3_INVALID_ASSOC" one. The former is as a code section header.
Signed-off-by: Ahmed S. Darwish <darwi@linutronix.de>
---
arch/x86/kernel/cpu/cacheinfo.c | 103 +++++++++++++-------------------
1 file changed, 40 insertions(+), 63 deletions(-)
diff --git a/arch/x86/kernel/cpu/cacheinfo.c b/arch/x86/kernel/cpu/cacheinfo.c
index 209a0c708213..7dab0d7152cc 100644
--- a/arch/x86/kernel/cpu/cacheinfo.c
+++ b/arch/x86/kernel/cpu/cacheinfo.c
@@ -56,47 +56,17 @@ static const enum cache_type cache_type_map[] = {
};
/*
- * Fallback AMD CPUID(0x4) emulation
+ * Fallback AMD CPUID(0x4) emulation:
* AMD CPUs with TOPOEXT can just use CPUID(0x8000001d)
- *
+ */
+
+/*
* @AMD_L2_L3_INVALID_ASSOC: cache info for the respective L2/L3 cache should
* be determined from CPUID(0x8000001d) instead of CPUID(0x80000006).
*/
-
#define AMD_CPUID4_FULLY_ASSOCIATIVE 0xffff
#define AMD_L2_L3_INVALID_ASSOC 0x9
-union l1_cache {
- struct {
- unsigned line_size :8;
- unsigned lines_per_tag :8;
- unsigned assoc :8;
- unsigned size_in_kb :8;
- };
- unsigned int val;
-};
-
-union l2_cache {
- struct {
- unsigned line_size :8;
- unsigned lines_per_tag :4;
- unsigned assoc :4;
- unsigned size_in_kb :16;
- };
- unsigned int val;
-};
-
-union l3_cache {
- struct {
- unsigned line_size :8;
- unsigned lines_per_tag :4;
- unsigned assoc :4;
- unsigned res :2;
- unsigned size_encoded :14;
- };
- unsigned int val;
-};
-
/* L2/L3 associativity mapping */
static const unsigned short assocs[] = {
[1] = 1,
@@ -117,50 +87,52 @@ static const unsigned short assocs[] = {
static const unsigned char levels[] = { 1, 1, 2, 3 };
static const unsigned char types[] = { 1, 2, 3, 3 };
-static void legacy_amd_cpuid4(int index, struct leaf_0x4_n *regs)
+static void legacy_amd_cpuid4(struct cpuinfo_x86 *c, int index, struct leaf_0x4_n *regs)
{
- unsigned int dummy, line_size, lines_per_tag, assoc, size_in_kb;
- union l1_cache l1i, l1d, *l1;
- union l2_cache l2;
- union l3_cache l3;
+ const struct leaf_0x80000005_0 *el5 = cpuid_leaf(c, 0x80000005);
+ const struct leaf_0x80000006_0 *el6 = cpuid_leaf(c, 0x80000006);
+ const struct cpuid_regs *el5_raw = cpuid_leaf_raw(c, 0x80000005);
+ unsigned int line_size, lines_per_tag, assoc, size_in_kb;
*regs = (struct leaf_0x4_n){ };
- cpuid(0x80000005, &dummy, &dummy, &l1d.val, &l1i.val);
- cpuid(0x80000006, &dummy, &dummy, &l2.val, &l3.val);
-
- l1 = &l1d;
switch (index) {
- case 1:
- l1 = &l1i;
- fallthrough;
case 0:
- if (!l1->val)
+ if (!el5 || !el5_raw->ecx)
return;
- assoc = (l1->assoc == 0xff) ? AMD_CPUID4_FULLY_ASSOCIATIVE : l1->assoc;
- line_size = l1->line_size;
- lines_per_tag = l1->lines_per_tag;
- size_in_kb = l1->size_in_kb;
+ assoc = el5->l1_dcache_assoc;
+ line_size = el5->l1_dcache_line_size;
+ lines_per_tag = el5->l1_dcache_nlines;
+ size_in_kb = el5->l1_dcache_size_kb;
+ break;
+ case 1:
+ if (!el5 || !el5_raw->edx)
+ return;
+
+ assoc = el5->l1_icache_assoc;
+ line_size = el5->l1_icache_line_size;
+ lines_per_tag = el5->l1_icache_nlines;
+ size_in_kb = el5->l1_icache_size_kb;
break;
case 2:
- if (!l2.assoc || l2.assoc == AMD_L2_L3_INVALID_ASSOC)
+ if (!el6 || !el6->l2_assoc || el6->l2_assoc == AMD_L2_L3_INVALID_ASSOC)
return;
/* Use x86_cache_size as it might have K7 errata fixes */
- assoc = assocs[l2.assoc];
- line_size = l2.line_size;
- lines_per_tag = l2.lines_per_tag;
+ assoc = assocs[el6->l2_assoc];
+ line_size = el6->l2_line_size;
+ lines_per_tag = el6->l2_nlines;
size_in_kb = __this_cpu_read(cpu_info.x86_cache_size);
break;
case 3:
- if (!l3.assoc || l3.assoc == AMD_L2_L3_INVALID_ASSOC)
+ if (!el6 || !el6->l3_assoc || el6->l3_assoc == AMD_L2_L3_INVALID_ASSOC)
return;
- assoc = assocs[l3.assoc];
- line_size = l3.line_size;
- lines_per_tag = l3.lines_per_tag;
- size_in_kb = l3.size_encoded * 512;
+ assoc = assocs[el6->l3_assoc];
+ line_size = el6->l3_line_size;
+ lines_per_tag = el6->l3_nlines;
+ size_in_kb = el6->l3_size_range * 512;
if (boot_cpu_has(X86_FEATURE_AMD_DCM)) {
size_in_kb = size_in_kb >> 1;
assoc = assoc >> 1;
@@ -170,6 +142,10 @@ static void legacy_amd_cpuid4(int index, struct leaf_0x4_n *regs)
return;
}
+ /* For L1d and L1i caches, 0xff is the full associativity marker */
+ if ((index == 0 || index == 1) && assoc == 0xff)
+ assoc = AMD_CPUID4_FULLY_ASSOCIATIVE;
+
regs->cache_self_init = 1;
regs->cache_type = types[index];
regs->cache_level = levels[index];
@@ -213,7 +189,7 @@ static int amd_fill_cpuid4_info(struct cpuinfo_x86 *c, int index, struct _cpuid4
/* CPUID(0x8000001d) and CPUID(0x4) have the same bitfields */
l_0x4_regs = *(struct leaf_0x4_n *)regs;
} else
- legacy_amd_cpuid4(index, &l_0x4_regs);
+ legacy_amd_cpuid4(c, index, &l_0x4_regs);
return cpuid4_info_fill_done(id4, &l_0x4_regs);
}
@@ -298,12 +274,13 @@ void cacheinfo_hygon_init_llc_id(struct cpuinfo_x86 *c)
void init_amd_cacheinfo(struct cpuinfo_x86 *c)
{
+ const struct leaf_0x80000006_0 *el6 = cpuid_leaf(c, 0x80000006);
struct cpu_cacheinfo *ci = get_cpu_cacheinfo(c->cpu_index);
if (boot_cpu_has(X86_FEATURE_TOPOEXT))
ci->num_leaves = cpuid_subleaf_count(c, 0x8000001d);
- else if (c->extended_cpuid_level >= 0x80000006)
- ci->num_leaves = (cpuid_edx(0x80000006) & 0xf000) ? 4 : 3;
+ else if (el6)
+ ci->num_leaves = (el6->l3_assoc) ? 4 : 3;
}
void init_hygon_cacheinfo(struct cpuinfo_x86 *c)
--
2.53.0
^ permalink raw reply related [flat|nested] 101+ messages in thread
* [PATCH v6 43/90] x86/cacheinfo: Use parsed CPUID(0x80000006)
2026-03-27 2:15 [PATCH v6 00/90] x86: Introduce a centralized CPUID data model Ahmed S. Darwish
` (41 preceding siblings ...)
2026-03-27 2:15 ` [PATCH v6 42/90] x86/cacheinfo: Use parsed CPUID(0x80000005) and CPUID(0x80000006) Ahmed S. Darwish
@ 2026-03-27 2:15 ` Ahmed S. Darwish
2026-03-27 2:15 ` [PATCH v6 44/90] x86/cpu: Use parsed CPUID(0x80000005) and CPUID(0x80000006) Ahmed S. Darwish
` (48 subsequent siblings)
91 siblings, 0 replies; 101+ messages in thread
From: Ahmed S. Darwish @ 2026-03-27 2:15 UTC (permalink / raw)
To: Borislav Petkov, Dave Hansen, Ingo Molnar
Cc: Thomas Gleixner, Andrew Cooper, H. Peter Anvin,
Sean Christopherson, David Woodhouse, Peter Zijlstra,
Christian Ludloff, Sohil Mehta, John Ogness, x86, x86-cpuid, LKML,
Ahmed S. Darwish
For AMD cacheinfo, use parsed CPUID(0x80000006) instead of issuing a direct
CPUID query.
Beside the CPUID parser centralization benefits, this allows using the
auto-generated x86-cpuid-db data types, and their C99 bitfields, instead of
doing ugly bitwise operations on CPUID output.
For enumerating L3 cache availability, check if CPUID(0x80000006).EDX
l3_assoc output is not zero. Per AMD manuals, an L3 associativity of zero
implies the absence of a CPU L3 cache.
Since cpuid_amd_hygon_has_l3_cache() is now using the CPUID parser APIs,
move its definition under the section: "Convenience leaf-specific functions
(using parsed CPUID)."
Signed-off-by: Ahmed S. Darwish <darwi@linutronix.de>
---
arch/x86/include/asm/cpuid/api.h | 20 +++++++++++---------
arch/x86/kernel/amd_nb.c | 3 ++-
arch/x86/kernel/cpu/cacheinfo.c | 6 +++---
3 files changed, 16 insertions(+), 13 deletions(-)
diff --git a/arch/x86/include/asm/cpuid/api.h b/arch/x86/include/asm/cpuid/api.h
index f4bdfe3c9325..611ee8596115 100644
--- a/arch/x86/include/asm/cpuid/api.h
+++ b/arch/x86/include/asm/cpuid/api.h
@@ -212,15 +212,6 @@ static inline u32 cpuid_base_hypervisor(const char *sig, u32 leaves)
return 0;
}
-/*
- * CPUID(0x80000006) parsing:
- */
-
-static inline bool cpuid_amd_hygon_has_l3_cache(void)
-{
- return cpuid_edx(0x80000006);
-}
-
/*
* 'struct cpuid_leaves' accessors (without sanity checks):
*
@@ -502,6 +493,17 @@ static inline bool cpuid_amd_hygon_has_l3_cache(void)
_ptr < &((const union leaf_0x2_regs *)(_regs))->desc[16] && (_desc = &cpuid_0x2_table[*_ptr]);\
_ptr++)
+/*
+ * CPUID(0x80000006)
+ */
+
+static inline bool cpuid_amd_hygon_has_l3_cache(struct cpuinfo_x86 *c)
+{
+ const struct leaf_0x80000006_0 *el6 = cpuid_leaf(c, 0x80000006);
+
+ return el6 && el6->l3_assoc;
+}
+
/*
* CPUID parser exported APIs:
*/
diff --git a/arch/x86/kernel/amd_nb.c b/arch/x86/kernel/amd_nb.c
index 5d364540673d..06ebbd564945 100644
--- a/arch/x86/kernel/amd_nb.c
+++ b/arch/x86/kernel/amd_nb.c
@@ -16,6 +16,7 @@
#include <asm/amd/nb.h>
#include <asm/cpuid/api.h>
+#include <asm/processor.h>
static u32 *flush_words;
@@ -93,7 +94,7 @@ static int amd_cache_northbridges(void)
if (amd_gart_present())
amd_northbridges.flags |= AMD_NB_GART;
- if (!cpuid_amd_hygon_has_l3_cache())
+ if (!cpuid_amd_hygon_has_l3_cache(&boot_cpu_data))
return 0;
/*
diff --git a/arch/x86/kernel/cpu/cacheinfo.c b/arch/x86/kernel/cpu/cacheinfo.c
index 7dab0d7152cc..3e40bcca1c3b 100644
--- a/arch/x86/kernel/cpu/cacheinfo.c
+++ b/arch/x86/kernel/cpu/cacheinfo.c
@@ -235,7 +235,7 @@ static unsigned int get_cache_id(u32 apicid, const struct _cpuid4_info *id4)
void cacheinfo_amd_init_llc_id(struct cpuinfo_x86 *c, u16 die_id)
{
- if (!cpuid_amd_hygon_has_l3_cache())
+ if (!cpuid_amd_hygon_has_l3_cache(c))
return;
if (c->x86 < 0x17) {
@@ -262,7 +262,7 @@ void cacheinfo_amd_init_llc_id(struct cpuinfo_x86 *c, u16 die_id)
void cacheinfo_hygon_init_llc_id(struct cpuinfo_x86 *c)
{
- if (!cpuid_amd_hygon_has_l3_cache())
+ if (!cpuid_amd_hygon_has_l3_cache(c))
return;
/*
@@ -280,7 +280,7 @@ void init_amd_cacheinfo(struct cpuinfo_x86 *c)
if (boot_cpu_has(X86_FEATURE_TOPOEXT))
ci->num_leaves = cpuid_subleaf_count(c, 0x8000001d);
else if (el6)
- ci->num_leaves = (el6->l3_assoc) ? 4 : 3;
+ ci->num_leaves = cpuid_amd_hygon_has_l3_cache(c) ? 4 : 3;
}
void init_hygon_cacheinfo(struct cpuinfo_x86 *c)
--
2.53.0
^ permalink raw reply related [flat|nested] 101+ messages in thread
* [PATCH v6 44/90] x86/cpu: Use parsed CPUID(0x80000005) and CPUID(0x80000006)
2026-03-27 2:15 [PATCH v6 00/90] x86: Introduce a centralized CPUID data model Ahmed S. Darwish
` (42 preceding siblings ...)
2026-03-27 2:15 ` [PATCH v6 43/90] x86/cacheinfo: Use parsed CPUID(0x80000006) Ahmed S. Darwish
@ 2026-03-27 2:15 ` Ahmed S. Darwish
2026-03-27 2:15 ` [PATCH v6 45/90] x86/cpu/amd: Use parsed CPUID(0x80000005) Ahmed S. Darwish
` (47 subsequent siblings)
91 siblings, 0 replies; 101+ messages in thread
From: Ahmed S. Darwish @ 2026-03-27 2:15 UTC (permalink / raw)
To: Borislav Petkov, Dave Hansen, Ingo Molnar
Cc: Thomas Gleixner, Andrew Cooper, H. Peter Anvin,
Sean Christopherson, David Woodhouse, Peter Zijlstra,
Christian Ludloff, Sohil Mehta, John Ogness, x86, x86-cpuid, LKML,
Ahmed S. Darwish
Use parsed CPUID(0x80000005) and CPUID(0x80000006) instead of issuing CPUID
queries and doing ugly bitwise operations.
Signed-off-by: Ahmed S. Darwish <darwi@linutronix.de>
---
arch/x86/kernel/cpu/common.c | 22 +++++++++++-----------
1 file changed, 11 insertions(+), 11 deletions(-)
diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c
index f7372833dd50..5fa5463686ac 100644
--- a/arch/x86/kernel/cpu/common.c
+++ b/arch/x86/kernel/cpu/common.c
@@ -857,27 +857,26 @@ static void get_model_name(struct cpuinfo_x86 *c)
void cpu_detect_cache_sizes(struct cpuinfo_x86 *c)
{
- unsigned int n, dummy, ebx, ecx, edx, l2size;
+ const struct leaf_0x80000005_0 *el5 = cpuid_leaf(c, 0x80000005);
+ const struct leaf_0x80000006_0 *el6 = cpuid_leaf(c, 0x80000006);
+ unsigned int l2size;
- n = c->extended_cpuid_level;
-
- if (n >= 0x80000005) {
- cpuid(0x80000005, &dummy, &ebx, &ecx, &edx);
- c->x86_cache_size = (ecx>>24) + (edx>>24);
+ if (el5) {
+ c->x86_cache_size = el5->l1_dcache_size_kb + el5->l1_icache_size_kb;
#ifdef CONFIG_X86_64
/* On K8 L1 TLB is inclusive, so don't count it */
c->x86_tlbsize = 0;
#endif
}
- if (n < 0x80000006) /* Some chips just has a large L1. */
+ /* Some chips only have a large L1 */
+ if (!el6)
return;
- cpuid(0x80000006, &dummy, &ebx, &ecx, &edx);
- l2size = ecx >> 16;
+ l2size = el6->l2_size_kb;
#ifdef CONFIG_X86_64
- c->x86_tlbsize += ((ebx >> 16) & 0xfff) + (ebx & 0xfff);
+ c->x86_tlbsize += el6->l2_dtlb_4k_nentries + el6->l2_itlb_4k_nentries;
#else
/* do processor-specific cache resizing */
if (this_cpu->legacy_cache_size)
@@ -887,8 +886,9 @@ void cpu_detect_cache_sizes(struct cpuinfo_x86 *c)
if (cachesize_override != -1)
l2size = cachesize_override;
+ /* Again, no L2 cache is possible */
if (l2size == 0)
- return; /* Again, no L2 cache is possible */
+ return;
#endif
c->x86_cache_size = l2size;
--
2.53.0
^ permalink raw reply related [flat|nested] 101+ messages in thread
* [PATCH v6 45/90] x86/cpu/amd: Use parsed CPUID(0x80000005)
2026-03-27 2:15 [PATCH v6 00/90] x86: Introduce a centralized CPUID data model Ahmed S. Darwish
` (43 preceding siblings ...)
2026-03-27 2:15 ` [PATCH v6 44/90] x86/cpu: Use parsed CPUID(0x80000005) and CPUID(0x80000006) Ahmed S. Darwish
@ 2026-03-27 2:15 ` Ahmed S. Darwish
2026-03-27 2:16 ` [PATCH v6 46/90] x86/cpu/amd: Refactor TLB detection code Ahmed S. Darwish
` (46 subsequent siblings)
91 siblings, 0 replies; 101+ messages in thread
From: Ahmed S. Darwish @ 2026-03-27 2:15 UTC (permalink / raw)
To: Borislav Petkov, Dave Hansen, Ingo Molnar
Cc: Thomas Gleixner, Andrew Cooper, H. Peter Anvin,
Sean Christopherson, David Woodhouse, Peter Zijlstra,
Christian Ludloff, Sohil Mehta, John Ogness, x86, x86-cpuid, LKML,
Ahmed S. Darwish
For AMD BSP init, use parsed CPUID(0x80000005) instead of issuing a direct
CPUID query and doing ugly bitwise operations.
Signed-off-by: Ahmed S. Darwish <darwi@linutronix.de>
---
arch/x86/kernel/cpu/amd.c | 12 +++++-------
1 file changed, 5 insertions(+), 7 deletions(-)
diff --git a/arch/x86/kernel/cpu/amd.c b/arch/x86/kernel/cpu/amd.c
index 224420f53ea9..67c983fd8d67 100644
--- a/arch/x86/kernel/cpu/amd.c
+++ b/arch/x86/kernel/cpu/amd.c
@@ -1,6 +1,7 @@
// SPDX-License-Identifier: GPL-2.0-only
#include <linux/export.h>
#include <linux/bitops.h>
+#include <linux/sizes.h>
#include <linux/elf.h>
#include <linux/mm.h>
#include <linux/kvm_types.h>
@@ -421,6 +422,8 @@ static void tsa_init(struct cpuinfo_x86 *c)
static void bsp_init_amd(struct cpuinfo_x86 *c)
{
+ const struct leaf_0x80000005_0 *el5 = cpuid_leaf(c, 0x80000005);
+
if (cpu_has(c, X86_FEATURE_CONSTANT_TSC)) {
if (c->x86 > 0x10 ||
@@ -433,13 +436,8 @@ static void bsp_init_amd(struct cpuinfo_x86 *c)
}
}
- if (c->x86 == 0x15) {
- unsigned long upperbit;
- u32 cpuid, assoc;
-
- cpuid = cpuid_edx(0x80000005);
- assoc = cpuid >> 16 & 0xff;
- upperbit = ((cpuid >> 24) << 10) / assoc;
+ if (c->x86 == 0x15 && el5) {
+ unsigned long upperbit = (el5->l1_icache_size_kb * SZ_1K) / el5->l1_icache_assoc;
va_align.mask = (upperbit - 1) & PAGE_MASK;
va_align.flags = ALIGN_VA_32 | ALIGN_VA_64;
--
2.53.0
^ permalink raw reply related [flat|nested] 101+ messages in thread
* [PATCH v6 46/90] x86/cpu/amd: Refactor TLB detection code
2026-03-27 2:15 [PATCH v6 00/90] x86: Introduce a centralized CPUID data model Ahmed S. Darwish
` (44 preceding siblings ...)
2026-03-27 2:15 ` [PATCH v6 45/90] x86/cpu/amd: Use parsed CPUID(0x80000005) Ahmed S. Darwish
@ 2026-03-27 2:16 ` Ahmed S. Darwish
2026-03-27 2:16 ` [PATCH v6 47/90] x86/cpu/amd: Use parsed CPUID(CPUID(0x80000005) and CPUID(0x80000006) Ahmed S. Darwish
` (45 subsequent siblings)
91 siblings, 0 replies; 101+ messages in thread
From: Ahmed S. Darwish @ 2026-03-27 2:16 UTC (permalink / raw)
To: Borislav Petkov, Dave Hansen, Ingo Molnar
Cc: Thomas Gleixner, Andrew Cooper, H. Peter Anvin,
Sean Christopherson, David Woodhouse, Peter Zijlstra,
Christian Ludloff, Sohil Mehta, John Ogness, x86, x86-cpuid, LKML,
Ahmed S. Darwish
AMD's TLB init code fills below global variables:
- tlb_lld_4k, tlb_lli_4k
- tlb_lld_2m, tlb_lli_2m
- tlb_lld_4m, tlb_lli_4m
CPUID(0x80000006) reports these DTLB/ITLB numbers for L2, while
CPUID(0x80000005) reports such numbers for L1.
The code sets these variables with the L2 numbers by default. If the
latter is not available, then the L1 numbers are used as a fallback.
Refactor the TLB init logic before converting it to the parsed CPUID API.
Signed-off-by: Ahmed S. Darwish <darwi@linutronix.de>
---
arch/x86/kernel/cpu/amd.c | 54 ++++++++++++++++-----------------------
1 file changed, 22 insertions(+), 32 deletions(-)
diff --git a/arch/x86/kernel/cpu/amd.c b/arch/x86/kernel/cpu/amd.c
index 67c983fd8d67..e13f5d05d7cf 100644
--- a/arch/x86/kernel/cpu/amd.c
+++ b/arch/x86/kernel/cpu/amd.c
@@ -1179,50 +1179,40 @@ static unsigned int amd_size_cache(struct cpuinfo_x86 *c, unsigned int size)
static void cpu_detect_tlb_amd(struct cpuinfo_x86 *c)
{
- u32 ebx, eax, ecx, edx;
- u16 mask = 0xfff;
+ u32 l2_tlb_eax, l2_tlb_ebx, l1_tlb_eax;
+ u16 l2_mask = 0xfff, l1_mask = 0xff;
- if (c->x86 < 0xf)
+ if (c->x86 < 0xf || c->extended_cpuid_level < 0x80000006)
return;
- if (c->extended_cpuid_level < 0x80000006)
- return;
-
- cpuid(0x80000006, &eax, &ebx, &ecx, &edx);
+ l2_tlb_eax = cpuid_eax(0x80000006);
+ l2_tlb_ebx = cpuid_ebx(0x80000006);
+ l1_tlb_eax = cpuid_eax(0x80000005);
- tlb_lld_4k = (ebx >> 16) & mask;
- tlb_lli_4k = ebx & mask;
+ tlb_lld_4k = (l2_tlb_ebx >> 16) & l2_mask;
+ tlb_lli_4k = l2_tlb_ebx & l2_mask;
/*
- * K8 doesn't have 2M/4M entries in the L2 TLB so read out the L1 TLB
- * characteristics from the CPUID function 0x80000005 instead.
+ * K8 does not report 2M/4M entries in the L2 TLB, so always use
+ * the L1 TLB information there. On later CPUs, fall back to L1
+ * when the L2 entry count is zero.
*/
- if (c->x86 == 0xf) {
- cpuid(0x80000005, &eax, &ebx, &ecx, &edx);
- mask = 0xff;
- }
- /* Handle DTLB 2M and 4M sizes, fall back to L1 if L2 is disabled */
- if (!((eax >> 16) & mask))
- tlb_lld_2m = (cpuid_eax(0x80000005) >> 16) & 0xff;
- else
- tlb_lld_2m = (eax >> 16) & mask;
-
- /* a 4M entry uses two 2M entries */
- tlb_lld_4m = tlb_lld_2m >> 1;
+ tlb_lld_2m = (l2_tlb_eax >> 16) & l2_mask;
+ if (c->x86 == 0xf || !tlb_lld_2m)
+ tlb_lld_2m = (l1_tlb_eax >> 16) & l1_mask;
- /* Handle ITLB 2M and 4M sizes, fall back to L1 if L2 is disabled */
- if (!(eax & mask)) {
+ tlb_lli_2m = l2_tlb_eax & l2_mask;
+ if (c->x86 == 0xf || !tlb_lli_2m) {
/* Erratum 658 */
- if (c->x86 == 0x15 && c->x86_model <= 0x1f) {
+ if (c->x86 == 0x15 && c->x86_model <= 0x1f)
tlb_lli_2m = 1024;
- } else {
- cpuid(0x80000005, &eax, &ebx, &ecx, &edx);
- tlb_lli_2m = eax & 0xff;
- }
- } else
- tlb_lli_2m = eax & mask;
+ else
+ tlb_lli_2m = l1_tlb_eax & l1_mask;
+ }
+ /* A 4M entry uses two 2M entries */
+ tlb_lld_4m = tlb_lld_2m >> 1;
tlb_lli_4m = tlb_lli_2m >> 1;
/* Max number of pages INVLPGB can invalidate in one shot */
--
2.53.0
^ permalink raw reply related [flat|nested] 101+ messages in thread
* [PATCH v6 47/90] x86/cpu/amd: Use parsed CPUID(CPUID(0x80000005) and CPUID(0x80000006)
2026-03-27 2:15 [PATCH v6 00/90] x86: Introduce a centralized CPUID data model Ahmed S. Darwish
` (45 preceding siblings ...)
2026-03-27 2:16 ` [PATCH v6 46/90] x86/cpu/amd: Refactor TLB detection code Ahmed S. Darwish
@ 2026-03-27 2:16 ` Ahmed S. Darwish
2026-03-27 2:16 ` [PATCH v6 48/90] x86/cpu/hygon: Use parsed CPUID(0x80000005) " Ahmed S. Darwish
` (44 subsequent siblings)
91 siblings, 0 replies; 101+ messages in thread
From: Ahmed S. Darwish @ 2026-03-27 2:16 UTC (permalink / raw)
To: Borislav Petkov, Dave Hansen, Ingo Molnar
Cc: Thomas Gleixner, Andrew Cooper, H. Peter Anvin,
Sean Christopherson, David Woodhouse, Peter Zijlstra,
Christian Ludloff, Sohil Mehta, John Ogness, x86, x86-cpuid, LKML,
Ahmed S. Darwish
For AMD TLB detection, use parsed CPUID(0x80000005) and CPUID(0x80000006)
instead of direct CPUID queries and ugly bitwise operations.
Signed-off-by: Ahmed S. Darwish <darwi@linutronix.de>
---
arch/x86/kernel/cpu/amd.c | 22 +++++++++-------------
1 file changed, 9 insertions(+), 13 deletions(-)
diff --git a/arch/x86/kernel/cpu/amd.c b/arch/x86/kernel/cpu/amd.c
index e13f5d05d7cf..5fd7f34fa284 100644
--- a/arch/x86/kernel/cpu/amd.c
+++ b/arch/x86/kernel/cpu/amd.c
@@ -1179,18 +1179,14 @@ static unsigned int amd_size_cache(struct cpuinfo_x86 *c, unsigned int size)
static void cpu_detect_tlb_amd(struct cpuinfo_x86 *c)
{
- u32 l2_tlb_eax, l2_tlb_ebx, l1_tlb_eax;
- u16 l2_mask = 0xfff, l1_mask = 0xff;
+ const struct leaf_0x80000005_0 *el5 = cpuid_leaf(c, 0x80000005);
+ const struct leaf_0x80000006_0 *el6 = cpuid_leaf(c, 0x80000006);
- if (c->x86 < 0xf || c->extended_cpuid_level < 0x80000006)
+ if (c->x86 < 0xf || !el5 || !el6)
return;
- l2_tlb_eax = cpuid_eax(0x80000006);
- l2_tlb_ebx = cpuid_ebx(0x80000006);
- l1_tlb_eax = cpuid_eax(0x80000005);
-
- tlb_lld_4k = (l2_tlb_ebx >> 16) & l2_mask;
- tlb_lli_4k = l2_tlb_ebx & l2_mask;
+ tlb_lld_4k = el6->l2_dtlb_4k_nentries;
+ tlb_lli_4k = el6->l2_itlb_4k_nentries;
/*
* K8 does not report 2M/4M entries in the L2 TLB, so always use
@@ -1198,17 +1194,17 @@ static void cpu_detect_tlb_amd(struct cpuinfo_x86 *c)
* when the L2 entry count is zero.
*/
- tlb_lld_2m = (l2_tlb_eax >> 16) & l2_mask;
+ tlb_lld_2m = el6->l2_dtlb_2m_4m_nentries;
if (c->x86 == 0xf || !tlb_lld_2m)
- tlb_lld_2m = (l1_tlb_eax >> 16) & l1_mask;
+ tlb_lld_2m = el5->l1_dtlb_2m_4m_nentries;
- tlb_lli_2m = l2_tlb_eax & l2_mask;
+ tlb_lli_2m = el6->l2_itlb_2m_4m_nentries;
if (c->x86 == 0xf || !tlb_lli_2m) {
/* Erratum 658 */
if (c->x86 == 0x15 && c->x86_model <= 0x1f)
tlb_lli_2m = 1024;
else
- tlb_lli_2m = l1_tlb_eax & l1_mask;
+ tlb_lli_2m = el5->l1_itlb_2m_4m_nentries;
}
/* A 4M entry uses two 2M entries */
--
2.53.0
^ permalink raw reply related [flat|nested] 101+ messages in thread
* [PATCH v6 48/90] x86/cpu/hygon: Use parsed CPUID(0x80000005) and CPUID(0x80000006)
2026-03-27 2:15 [PATCH v6 00/90] x86: Introduce a centralized CPUID data model Ahmed S. Darwish
` (46 preceding siblings ...)
2026-03-27 2:16 ` [PATCH v6 47/90] x86/cpu/amd: Use parsed CPUID(CPUID(0x80000005) and CPUID(0x80000006) Ahmed S. Darwish
@ 2026-03-27 2:16 ` Ahmed S. Darwish
2026-03-27 2:16 ` [PATCH v6 49/90] x86/cpu/centaur: Use parsed CPUID(0x80000005) Ahmed S. Darwish
` (43 subsequent siblings)
91 siblings, 0 replies; 101+ messages in thread
From: Ahmed S. Darwish @ 2026-03-27 2:16 UTC (permalink / raw)
To: Borislav Petkov, Dave Hansen, Ingo Molnar
Cc: Thomas Gleixner, Andrew Cooper, H. Peter Anvin,
Sean Christopherson, David Woodhouse, Peter Zijlstra,
Christian Ludloff, Sohil Mehta, John Ogness, x86, x86-cpuid, LKML,
Ahmed S. Darwish
For Hygon init, use parsed CPUID(0x80000005) and CPUID(0x80000006) instead
of direct CPUID queries and ugly bitwise operations.
Consolidate all comments; the code has now clear logic and bitfield names.
Signed-off-by: Ahmed S. Darwish <darwi@linutronix.de>
---
arch/x86/kernel/cpu/hygon.c | 35 ++++++++++++++++-------------------
1 file changed, 16 insertions(+), 19 deletions(-)
diff --git a/arch/x86/kernel/cpu/hygon.c b/arch/x86/kernel/cpu/hygon.c
index 3e8891a9caf2..4a63538c2b3f 100644
--- a/arch/x86/kernel/cpu/hygon.c
+++ b/arch/x86/kernel/cpu/hygon.c
@@ -229,35 +229,32 @@ static void init_hygon(struct cpuinfo_x86 *c)
clear_cpu_cap(c, X86_FEATURE_APIC_MSRS_FENCE);
}
+/*
+ * For DTLB/ITLB 2M-4M detection, fall back to L1 if L2 is disabled
+ */
static void cpu_detect_tlb_hygon(struct cpuinfo_x86 *c)
{
- u32 ebx, eax, ecx, edx;
- u16 mask = 0xfff;
+ const struct leaf_0x80000005_0 *el5 = cpuid_leaf(c, 0x80000005);
+ const struct leaf_0x80000006_0 *el6 = cpuid_leaf(c, 0x80000006);
- if (c->extended_cpuid_level < 0x80000006)
+ if (!el5 || !el6)
return;
- cpuid(0x80000006, &eax, &ebx, &ecx, &edx);
+ tlb_lld_4k = el6->l2_dtlb_4k_nentries;
+ tlb_lli_4k = el6->l2_itlb_4k_nentries;
- tlb_lld_4k = (ebx >> 16) & mask;
- tlb_lli_4k = ebx & mask;
+ if (el6->l2_dtlb_2m_4m_nentries)
+ tlb_lld_2m = el6->l2_dtlb_2m_4m_nentries;
+ else
+ tlb_lld_2m = el5->l1_dtlb_2m_4m_nentries;
- /* Handle DTLB 2M and 4M sizes, fall back to L1 if L2 is disabled */
- if (!((eax >> 16) & mask))
- tlb_lld_2m = (cpuid_eax(0x80000005) >> 16) & 0xff;
+ if (el6->l2_itlb_2m_4m_nentries)
+ tlb_lli_2m = el6->l2_itlb_2m_4m_nentries;
else
- tlb_lld_2m = (eax >> 16) & mask;
+ tlb_lli_2m = el5->l1_itlb_2m_4m_nentries;
- /* a 4M entry uses two 2M entries */
+ /* A 4M TLB entry uses two 2M entries */
tlb_lld_4m = tlb_lld_2m >> 1;
-
- /* Handle ITLB 2M and 4M sizes, fall back to L1 if L2 is disabled */
- if (!(eax & mask)) {
- cpuid(0x80000005, &eax, &ebx, &ecx, &edx);
- tlb_lli_2m = eax & 0xff;
- } else
- tlb_lli_2m = eax & mask;
-
tlb_lli_4m = tlb_lli_2m >> 1;
}
--
2.53.0
^ permalink raw reply related [flat|nested] 101+ messages in thread
* [PATCH v6 49/90] x86/cpu/centaur: Use parsed CPUID(0x80000005)
2026-03-27 2:15 [PATCH v6 00/90] x86: Introduce a centralized CPUID data model Ahmed S. Darwish
` (47 preceding siblings ...)
2026-03-27 2:16 ` [PATCH v6 48/90] x86/cpu/hygon: Use parsed CPUID(0x80000005) " Ahmed S. Darwish
@ 2026-03-27 2:16 ` Ahmed S. Darwish
2026-03-27 2:16 ` [PATCH v6 50/90] x86/cpu: Use parsed CPUID(0x80000008) Ahmed S. Darwish
` (42 subsequent siblings)
91 siblings, 0 replies; 101+ messages in thread
From: Ahmed S. Darwish @ 2026-03-27 2:16 UTC (permalink / raw)
To: Borislav Petkov, Dave Hansen, Ingo Molnar
Cc: Thomas Gleixner, Andrew Cooper, H. Peter Anvin,
Sean Christopherson, David Woodhouse, Peter Zijlstra,
Christian Ludloff, Sohil Mehta, John Ogness, x86, x86-cpuid, LKML,
Ahmed S. Darwish
Use parsed CPUID(0x80000005) instead of issuing a CPUID query and doing
ugly bitwise operations.
Signed-off-by: Ahmed S. Darwish <darwi@linutronix.de>
---
arch/x86/kernel/cpu/centaur.c | 15 +++++----------
1 file changed, 5 insertions(+), 10 deletions(-)
diff --git a/arch/x86/kernel/cpu/centaur.c b/arch/x86/kernel/cpu/centaur.c
index 5f09bce3aaa7..895cf00919d3 100644
--- a/arch/x86/kernel/cpu/centaur.c
+++ b/arch/x86/kernel/cpu/centaur.c
@@ -107,11 +107,11 @@ static void early_init_centaur(struct cpuinfo_x86 *c)
static void init_centaur(struct cpuinfo_x86 *c)
{
#ifdef CONFIG_X86_32
- char *name;
+ const struct leaf_0x80000005_0 *el5 = cpuid_leaf(c, 0x80000005);
+ u32 lo, hi, newlo;
u32 fcr_set = 0;
u32 fcr_clr = 0;
- u32 lo, hi, newlo;
- u32 aa, bb, cc, dd;
+ char *name;
#endif
early_init_centaur(c);
init_intel_cacheinfo(c);
@@ -181,13 +181,8 @@ static void init_centaur(struct cpuinfo_x86 *c)
/* Set 3DNow! on Winchip 2 and above. */
if (c->x86_model >= 8)
set_cpu_cap(c, X86_FEATURE_3DNOW);
- /* See if we can find out some more. */
- if (cpuid_eax(0x80000000) >= 0x80000005) {
- /* Yes, we can. */
- cpuid(0x80000005, &aa, &bb, &cc, &dd);
- /* Add L1 data and code cache sizes. */
- c->x86_cache_size = (cc>>24)+(dd>>24);
- }
+ if (el5)
+ c->x86_cache_size = el5->l1_dcache_size_kb + el5->l1_icache_size_kb;
sprintf(c->x86_model_id, "WinChip %s", name);
}
#endif
--
2.53.0
^ permalink raw reply related [flat|nested] 101+ messages in thread
* [PATCH v6 50/90] x86/cpu: Use parsed CPUID(0x80000008)
2026-03-27 2:15 [PATCH v6 00/90] x86: Introduce a centralized CPUID data model Ahmed S. Darwish
` (48 preceding siblings ...)
2026-03-27 2:16 ` [PATCH v6 49/90] x86/cpu/centaur: Use parsed CPUID(0x80000005) Ahmed S. Darwish
@ 2026-03-27 2:16 ` Ahmed S. Darwish
2026-03-27 2:16 ` [PATCH v6 51/90] x86/cpuid: Parse CPUID(0xa) and CPUID(0x1c) Ahmed S. Darwish
` (41 subsequent siblings)
91 siblings, 0 replies; 101+ messages in thread
From: Ahmed S. Darwish @ 2026-03-27 2:16 UTC (permalink / raw)
To: Borislav Petkov, Dave Hansen, Ingo Molnar
Cc: Thomas Gleixner, Andrew Cooper, H. Peter Anvin,
Sean Christopherson, David Woodhouse, Peter Zijlstra,
Christian Ludloff, Sohil Mehta, John Ogness, x86, x86-cpuid, LKML,
Ahmed S. Darwish
Use parsed CPUID(0x80000008) instead of issuing a direct CPUID query and
doing ugly bitwise operations.
Signed-off-by: Ahmed S. Darwish <darwi@linutronix.de>
---
arch/x86/kernel/cpu/common.c | 11 ++++-------
1 file changed, 4 insertions(+), 7 deletions(-)
diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c
index 5fa5463686ac..2beb53f6bed7 100644
--- a/arch/x86/kernel/cpu/common.c
+++ b/arch/x86/kernel/cpu/common.c
@@ -1100,10 +1100,9 @@ void get_cpu_cap(struct cpuinfo_x86 *c)
void get_cpu_address_sizes(struct cpuinfo_x86 *c)
{
- u32 eax, ebx, ecx, edx;
+ const struct leaf_0x80000008_0 *el8 = cpuid_leaf(c, 0x80000008);
- if (!cpu_has(c, X86_FEATURE_CPUID) ||
- (c->extended_cpuid_level < 0x80000008)) {
+ if (!cpu_has(c, X86_FEATURE_CPUID) || !el8) {
if (IS_ENABLED(CONFIG_X86_64)) {
c->x86_clflush_size = 64;
c->x86_phys_bits = 36;
@@ -1118,10 +1117,8 @@ void get_cpu_address_sizes(struct cpuinfo_x86 *c)
c->x86_phys_bits = 36;
}
} else {
- cpuid(0x80000008, &eax, &ebx, &ecx, &edx);
-
- c->x86_virt_bits = (eax >> 8) & 0xff;
- c->x86_phys_bits = eax & 0xff;
+ c->x86_virt_bits = el8->virt_addr_bits;
+ c->x86_phys_bits = el8->phys_addr_bits;
/* Provide a sane default if not enumerated: */
if (!c->x86_clflush_size)
--
2.53.0
^ permalink raw reply related [flat|nested] 101+ messages in thread
* [PATCH v6 51/90] x86/cpuid: Parse CPUID(0xa) and CPUID(0x1c)
2026-03-27 2:15 [PATCH v6 00/90] x86: Introduce a centralized CPUID data model Ahmed S. Darwish
` (49 preceding siblings ...)
2026-03-27 2:16 ` [PATCH v6 50/90] x86/cpu: Use parsed CPUID(0x80000008) Ahmed S. Darwish
@ 2026-03-27 2:16 ` Ahmed S. Darwish
2026-03-27 2:16 ` [PATCH v6 52/90] x86/cpu/intel: Use parsed CPUID(0xa) Ahmed S. Darwish
` (40 subsequent siblings)
91 siblings, 0 replies; 101+ messages in thread
From: Ahmed S. Darwish @ 2026-03-27 2:16 UTC (permalink / raw)
To: Borislav Petkov, Dave Hansen, Ingo Molnar
Cc: Thomas Gleixner, Andrew Cooper, H. Peter Anvin,
Sean Christopherson, David Woodhouse, Peter Zijlstra,
Christian Ludloff, Sohil Mehta, John Ogness, x86, x86-cpuid, LKML,
Ahmed S. Darwish
Parse CPUID(0xa) and CPUID(0x1c).
This allows their call sites to be converted to the CPUID APIs next.
Signed-off-by: Ahmed S. Darwish <darwi@linutronix.de>
---
arch/x86/include/asm/cpuid/types.h | 2 ++
arch/x86/kernel/cpu/cpuid_parser.h | 4 ++++
2 files changed, 6 insertions(+)
diff --git a/arch/x86/include/asm/cpuid/types.h b/arch/x86/include/asm/cpuid/types.h
index f50e54bfb514..128898d4434b 100644
--- a/arch/x86/include/asm/cpuid/types.h
+++ b/arch/x86/include/asm/cpuid/types.h
@@ -212,6 +212,8 @@ struct cpuid_leaves {
CPUID_LEAF ( 0x1, 0 );
CPUID_LEAF ( 0x2, 0 );
CPUID_LEAF_N ( 0x4, 8 );
+ CPUID_LEAF ( 0xa, 0 );
+ CPUID_LEAF ( 0x1c, 0 );
CPUID_LEAF ( 0x16, 0 );
CPUID_LEAF ( 0x80000000, 0 );
CPUID_LEAF ( 0x80000002, 0 );
diff --git a/arch/x86/kernel/cpu/cpuid_parser.h b/arch/x86/kernel/cpu/cpuid_parser.h
index ab391de03a92..8e147e7223e0 100644
--- a/arch/x86/kernel/cpu/cpuid_parser.h
+++ b/arch/x86/kernel/cpu/cpuid_parser.h
@@ -146,6 +146,8 @@ struct cpuid_parse_entry {
/* Leaf Subleaf Reader function */ \
CPUID_PARSE_ENTRY ( 0x2, 0, 0x2 ), \
CPUID_PARSE_ENTRY_N ( 0x4, deterministic_cache ), \
+ CPUID_PARSE_ENTRY ( 0xa, 0, generic ), \
+ CPUID_PARSE_ENTRY ( 0x1c, 0, generic ), \
CPUID_PARSE_ENTRY ( 0x16, 0, generic ), \
CPUID_PARSE_ENTRY ( 0x80000000, 0, 0x80000000 ), \
CPUID_PARSE_ENTRY ( 0x80000002, 0, generic ), \
@@ -198,7 +200,9 @@ struct cpuid_vendor_entry {
/* Leaf Vendor list */ \
CPUID_VENDOR_ENTRY(0x2, X86_VENDOR_INTEL, X86_VENDOR_CENTAUR, X86_VENDOR_ZHAOXIN),\
CPUID_VENDOR_ENTRY(0x4, X86_VENDOR_INTEL, X86_VENDOR_CENTAUR, X86_VENDOR_ZHAOXIN),\
+ CPUID_VENDOR_ENTRY(0xa, X86_VENDOR_INTEL, X86_VENDOR_CENTAUR, X86_VENDOR_ZHAOXIN),\
CPUID_VENDOR_ENTRY(0x16, X86_VENDOR_INTEL), \
+ CPUID_VENDOR_ENTRY(0x1c, X86_VENDOR_INTEL), \
CPUID_VENDOR_ENTRY(0x8000001d, X86_VENDOR_AMD, X86_VENDOR_HYGON), \
CPUID_VENDOR_ENTRY(0x80860000, X86_VENDOR_TRANSMETA), \
CPUID_VENDOR_ENTRY(0x80860001, X86_VENDOR_TRANSMETA), \
--
2.53.0
^ permalink raw reply related [flat|nested] 101+ messages in thread
* [PATCH v6 52/90] x86/cpu/intel: Use parsed CPUID(0xa)
2026-03-27 2:15 [PATCH v6 00/90] x86: Introduce a centralized CPUID data model Ahmed S. Darwish
` (50 preceding siblings ...)
2026-03-27 2:16 ` [PATCH v6 51/90] x86/cpuid: Parse CPUID(0xa) and CPUID(0x1c) Ahmed S. Darwish
@ 2026-03-27 2:16 ` Ahmed S. Darwish
2026-03-27 2:16 ` [PATCH v6 53/90] x86/cpu/centaur: " Ahmed S. Darwish
` (39 subsequent siblings)
91 siblings, 0 replies; 101+ messages in thread
From: Ahmed S. Darwish @ 2026-03-27 2:16 UTC (permalink / raw)
To: Borislav Petkov, Dave Hansen, Ingo Molnar
Cc: Thomas Gleixner, Andrew Cooper, H. Peter Anvin,
Sean Christopherson, David Woodhouse, Peter Zijlstra,
Christian Ludloff, Sohil Mehta, John Ogness, x86, x86-cpuid, LKML,
Ahmed S. Darwish
For Intel's PMU enumeration, use parsed CPUID(0xa) instead of a CPUID query
and ugly bitwise operations.
Remove comments; the generated bitfield names already make everything clear.
Signed-off-by: Ahmed S. Darwish <darwi@linutronix.de>
---
arch/x86/kernel/cpu/intel.c | 10 ++++------
1 file changed, 4 insertions(+), 6 deletions(-)
diff --git a/arch/x86/kernel/cpu/intel.c b/arch/x86/kernel/cpu/intel.c
index 615e3a4872b7..7f186c68d701 100644
--- a/arch/x86/kernel/cpu/intel.c
+++ b/arch/x86/kernel/cpu/intel.c
@@ -547,18 +547,16 @@ static const struct x86_cpu_id zmm_exclusion_list[] = {
static void init_intel(struct cpuinfo_x86 *c)
{
+ const struct leaf_0xa_0 *la = cpuid_leaf(c, 0xa);
+
early_init_intel(c);
intel_workarounds(c);
init_intel_cacheinfo(c);
- if (c->cpuid_level > 9) {
- unsigned eax = cpuid_eax(10);
- /* Check for version and the number of counters */
- if ((eax & 0xff) && (((eax>>8) & 0xff) > 1))
- set_cpu_cap(c, X86_FEATURE_ARCH_PERFMON);
- }
+ if (la && la->pmu_version && la->num_counters_gp > 1)
+ set_cpu_cap(c, X86_FEATURE_ARCH_PERFMON);
if (cpu_has(c, X86_FEATURE_XMM2))
set_cpu_cap(c, X86_FEATURE_LFENCE_RDTSC);
--
2.53.0
^ permalink raw reply related [flat|nested] 101+ messages in thread
* [PATCH v6 53/90] x86/cpu/centaur: Use parsed CPUID(0xa)
2026-03-27 2:15 [PATCH v6 00/90] x86: Introduce a centralized CPUID data model Ahmed S. Darwish
` (51 preceding siblings ...)
2026-03-27 2:16 ` [PATCH v6 52/90] x86/cpu/intel: Use parsed CPUID(0xa) Ahmed S. Darwish
@ 2026-03-27 2:16 ` Ahmed S. Darwish
2026-03-27 2:16 ` [PATCH v6 54/90] x86/cpu/zhaoxin: " Ahmed S. Darwish
` (38 subsequent siblings)
91 siblings, 0 replies; 101+ messages in thread
From: Ahmed S. Darwish @ 2026-03-27 2:16 UTC (permalink / raw)
To: Borislav Petkov, Dave Hansen, Ingo Molnar
Cc: Thomas Gleixner, Andrew Cooper, H. Peter Anvin,
Sean Christopherson, David Woodhouse, Peter Zijlstra,
Christian Ludloff, Sohil Mehta, John Ogness, x86, x86-cpuid, LKML,
Ahmed S. Darwish
For Centaur's PMU enumeration, use parsed CPUID(0xa) instead of a direct
CPUID query and ugly bitwise operations.
Remove comments; the generated bitfield names already make everything clear.
Signed-off-by: Ahmed S. Darwish <darwi@linutronix.de>
---
arch/x86/kernel/cpu/centaur.c | 14 +++-----------
1 file changed, 3 insertions(+), 11 deletions(-)
diff --git a/arch/x86/kernel/cpu/centaur.c b/arch/x86/kernel/cpu/centaur.c
index 895cf00919d3..86cbe4427453 100644
--- a/arch/x86/kernel/cpu/centaur.c
+++ b/arch/x86/kernel/cpu/centaur.c
@@ -106,6 +106,7 @@ static void early_init_centaur(struct cpuinfo_x86 *c)
static void init_centaur(struct cpuinfo_x86 *c)
{
+ const struct leaf_0xa_0 *la = cpuid_leaf(c, 0xa);
#ifdef CONFIG_X86_32
const struct leaf_0x80000005_0 *el5 = cpuid_leaf(c, 0x80000005);
u32 lo, hi, newlo;
@@ -116,17 +117,8 @@ static void init_centaur(struct cpuinfo_x86 *c)
early_init_centaur(c);
init_intel_cacheinfo(c);
- if (c->cpuid_level > 9) {
- unsigned int eax = cpuid_eax(10);
-
- /*
- * Check for version and the number of counters
- * Version(eax[7:0]) can't be 0;
- * Counters(eax[15:8]) should be greater than 1;
- */
- if ((eax & 0xff) && (((eax >> 8) & 0xff) > 1))
- set_cpu_cap(c, X86_FEATURE_ARCH_PERFMON);
- }
+ if (la && la->pmu_version && la->num_counters_gp > 1)
+ set_cpu_cap(c, X86_FEATURE_ARCH_PERFMON);
#ifdef CONFIG_X86_32
if (c->x86 == 5) {
--
2.53.0
^ permalink raw reply related [flat|nested] 101+ messages in thread
* [PATCH v6 54/90] x86/cpu/zhaoxin: Use parsed CPUID(0xa)
2026-03-27 2:15 [PATCH v6 00/90] x86: Introduce a centralized CPUID data model Ahmed S. Darwish
` (52 preceding siblings ...)
2026-03-27 2:16 ` [PATCH v6 53/90] x86/cpu/centaur: " Ahmed S. Darwish
@ 2026-03-27 2:16 ` Ahmed S. Darwish
2026-03-27 2:16 ` [PATCH v6 55/90] perf/x86/intel: " Ahmed S. Darwish
` (37 subsequent siblings)
91 siblings, 0 replies; 101+ messages in thread
From: Ahmed S. Darwish @ 2026-03-27 2:16 UTC (permalink / raw)
To: Borislav Petkov, Dave Hansen, Ingo Molnar
Cc: Thomas Gleixner, Andrew Cooper, H. Peter Anvin,
Sean Christopherson, David Woodhouse, Peter Zijlstra,
Christian Ludloff, Sohil Mehta, John Ogness, x86, x86-cpuid, LKML,
Ahmed S. Darwish
For Zhaoxin's PMU enumeration, use parsed CPUID(0xa) instead of a direct
CPUID query and ugly bitwise operations.
Remove comments; the generated bitfield names already make everything clear.
Signed-off-by: Ahmed S. Darwish <darwi@linutronix.de>
---
arch/x86/kernel/cpu/zhaoxin.c | 15 ++++-----------
1 file changed, 4 insertions(+), 11 deletions(-)
diff --git a/arch/x86/kernel/cpu/zhaoxin.c b/arch/x86/kernel/cpu/zhaoxin.c
index ea76e9594453..b068922efed9 100644
--- a/arch/x86/kernel/cpu/zhaoxin.c
+++ b/arch/x86/kernel/cpu/zhaoxin.c
@@ -61,20 +61,13 @@ static void early_init_zhaoxin(struct cpuinfo_x86 *c)
static void init_zhaoxin(struct cpuinfo_x86 *c)
{
+ const struct leaf_0xa_0 *la = cpuid_leaf(c, 0xa);
+
early_init_zhaoxin(c);
init_intel_cacheinfo(c);
- if (c->cpuid_level > 9) {
- unsigned int eax = cpuid_eax(10);
-
- /*
- * Check for version and the number of counters
- * Version(eax[7:0]) can't be 0;
- * Counters(eax[15:8]) should be greater than 1;
- */
- if ((eax & 0xff) && (((eax >> 8) & 0xff) > 1))
- set_cpu_cap(c, X86_FEATURE_ARCH_PERFMON);
- }
+ if (la && la->pmu_version && la->num_counters_gp > 1)
+ set_cpu_cap(c, X86_FEATURE_ARCH_PERFMON);
if (c->x86 >= 0x6)
init_zhaoxin_cap(c);
--
2.53.0
^ permalink raw reply related [flat|nested] 101+ messages in thread
* [PATCH v6 55/90] perf/x86/intel: Use parsed CPUID(0xa)
2026-03-27 2:15 [PATCH v6 00/90] x86: Introduce a centralized CPUID data model Ahmed S. Darwish
` (53 preceding siblings ...)
2026-03-27 2:16 ` [PATCH v6 54/90] x86/cpu/zhaoxin: " Ahmed S. Darwish
@ 2026-03-27 2:16 ` Ahmed S. Darwish
2026-03-27 2:16 ` [PATCH v6 56/90] perf/x86/zhaoxin: " Ahmed S. Darwish
` (36 subsequent siblings)
91 siblings, 0 replies; 101+ messages in thread
From: Ahmed S. Darwish @ 2026-03-27 2:16 UTC (permalink / raw)
To: Borislav Petkov, Dave Hansen, Ingo Molnar
Cc: Thomas Gleixner, Andrew Cooper, H. Peter Anvin,
Sean Christopherson, David Woodhouse, Peter Zijlstra,
Christian Ludloff, Sohil Mehta, John Ogness, x86, x86-cpuid, LKML,
Ahmed S. Darwish
For Intel perfmon, use parsed CPUID(0xa) instead of issuing CPUID queries
and defining custom CPUID output data types.
Signed-off-by: Ahmed S. Darwish <darwi@linutronix.de>
---
arch/x86/events/intel/core.c | 41 ++++++++++++++++++------------------
1 file changed, 21 insertions(+), 20 deletions(-)
diff --git a/arch/x86/events/intel/core.c b/arch/x86/events/intel/core.c
index d1107129d5ad..20dece48b994 100644
--- a/arch/x86/events/intel/core.c
+++ b/arch/x86/events/intel/core.c
@@ -6577,10 +6577,11 @@ static __init void intel_arch_events_quirk(void)
static __init void intel_nehalem_quirk(void)
{
- union cpuid10_ebx ebx;
+ struct leaf_0xa_0 l = { };
+ struct cpuid_regs *regs = (struct cpuid_regs *)&l;
- ebx.full = x86_pmu.events_maskl;
- if (ebx.split.no_branch_misses_retired) {
+ regs->ebx = x86_pmu.events_maskl;
+ if (l.no_br_misses_retired) {
/*
* Erratum AAJ80 detected, we work it around by using
* the BR_MISP_EXEC.ANY event. This will over-count
@@ -6588,8 +6589,8 @@ static __init void intel_nehalem_quirk(void)
* architectural event which is often completely bogus:
*/
intel_perfmon_event_map[PERF_COUNT_HW_BRANCH_MISSES] = 0x7f89;
- ebx.split.no_branch_misses_retired = 0;
- x86_pmu.events_maskl = ebx.full;
+ l.no_br_misses_retired = 0;
+ x86_pmu.events_maskl = regs->ebx;
pr_info("CPU erratum AAJ80 worked around\n");
}
}
@@ -7522,15 +7523,13 @@ static __always_inline void intel_pmu_init_arw(struct pmu *pmu)
__init int intel_pmu_init(void)
{
+ const struct cpuid_regs *regs = cpuid_leaf_raw(&boot_cpu_data, 0xa);
+ const struct leaf_0xa_0 *leaf = cpuid_leaf(&boot_cpu_data, 0xa);
struct attribute **extra_skl_attr = &empty_attrs;
struct attribute **extra_attr = &empty_attrs;
struct attribute **td_attr = &empty_attrs;
struct attribute **mem_attr = &empty_attrs;
struct attribute **tsx_attr = &empty_attrs;
- union cpuid10_edx edx;
- union cpuid10_eax eax;
- union cpuid10_ebx ebx;
- unsigned int fixed_mask;
bool pmem = false;
int version, i;
char *name;
@@ -7554,27 +7553,29 @@ __init int intel_pmu_init(void)
return -ENODEV;
}
+ if (!leaf || !regs)
+ return -ENODEV;
+
/*
* Check whether the Architectural PerfMon supports
* Branch Misses Retired hw_event or not.
*/
- cpuid(10, &eax.full, &ebx.full, &fixed_mask, &edx.full);
- if (eax.split.mask_length < ARCH_PERFMON_EVENTS_COUNT)
+ if (leaf->events_mask_len < ARCH_PERFMON_EVENTS_COUNT)
return -ENODEV;
- version = eax.split.version_id;
+ version = leaf->pmu_version;
if (version < 2)
x86_pmu = core_pmu;
else
x86_pmu = intel_pmu;
x86_pmu.version = version;
- x86_pmu.cntr_mask64 = GENMASK_ULL(eax.split.num_counters - 1, 0);
- x86_pmu.cntval_bits = eax.split.bit_width;
- x86_pmu.cntval_mask = (1ULL << eax.split.bit_width) - 1;
+ x86_pmu.cntr_mask64 = GENMASK_ULL(leaf->num_counters_gp - 1, 0);
+ x86_pmu.cntval_bits = leaf->bit_width_gp;
+ x86_pmu.cntval_mask = (1ULL << leaf->bit_width_gp) - 1;
- x86_pmu.events_maskl = ebx.full;
- x86_pmu.events_mask_len = eax.split.mask_length;
+ x86_pmu.events_maskl = regs->ebx;
+ x86_pmu.events_mask_len = leaf->events_mask_len;
x86_pmu.pebs_events_mask = intel_pmu_pebs_mask(x86_pmu.cntr_mask64);
x86_pmu.pebs_capable = PEBS_COUNTER_MASK;
@@ -7588,9 +7589,9 @@ __init int intel_pmu_init(void)
int assume = 3 * !boot_cpu_has(X86_FEATURE_HYPERVISOR);
x86_pmu.fixed_cntr_mask64 =
- GENMASK_ULL(max((int)edx.split.num_counters_fixed, assume) - 1, 0);
+ GENMASK_ULL(max((int)leaf->num_counters_fixed, assume) - 1, 0);
} else if (version >= 5)
- x86_pmu.fixed_cntr_mask64 = fixed_mask;
+ x86_pmu.fixed_cntr_mask64 = leaf->pmu_fcounters_bitmap;
if (boot_cpu_has(X86_FEATURE_PDCM)) {
u64 capabilities;
@@ -7612,7 +7613,7 @@ __init int intel_pmu_init(void)
x86_add_quirk(intel_arch_events_quirk); /* Install first, so it runs last */
if (version >= 5) {
- x86_pmu.intel_cap.anythread_deprecated = edx.split.anythread_deprecated;
+ x86_pmu.intel_cap.anythread_deprecated = leaf->anythread_deprecation;
if (x86_pmu.intel_cap.anythread_deprecated)
pr_cont(" AnyThread deprecated, ");
}
--
2.53.0
^ permalink raw reply related [flat|nested] 101+ messages in thread
* [PATCH v6 56/90] perf/x86/zhaoxin: Use parsed CPUID(0xa)
2026-03-27 2:15 [PATCH v6 00/90] x86: Introduce a centralized CPUID data model Ahmed S. Darwish
` (54 preceding siblings ...)
2026-03-27 2:16 ` [PATCH v6 55/90] perf/x86/intel: " Ahmed S. Darwish
@ 2026-03-27 2:16 ` Ahmed S. Darwish
2026-03-27 2:16 ` [PATCH v6 57/90] x86/xen: " Ahmed S. Darwish
` (35 subsequent siblings)
91 siblings, 0 replies; 101+ messages in thread
From: Ahmed S. Darwish @ 2026-03-27 2:16 UTC (permalink / raw)
To: Borislav Petkov, Dave Hansen, Ingo Molnar
Cc: Thomas Gleixner, Andrew Cooper, H. Peter Anvin,
Sean Christopherson, David Woodhouse, Peter Zijlstra,
Christian Ludloff, Sohil Mehta, John Ogness, x86, x86-cpuid, LKML,
Ahmed S. Darwish
For Zhaoxin perfmon, use parsed CPUID(0xa) instead of issuing CPUID queries
and defining custom CPUID output data types.
Signed-off-by: Ahmed S. Darwish <darwi@linutronix.de>
---
arch/x86/events/zhaoxin/core.c | 32 ++++++++++++++------------------
1 file changed, 14 insertions(+), 18 deletions(-)
diff --git a/arch/x86/events/zhaoxin/core.c b/arch/x86/events/zhaoxin/core.c
index 6ed644fe89aa..1c487d09f65c 100644
--- a/arch/x86/events/zhaoxin/core.c
+++ b/arch/x86/events/zhaoxin/core.c
@@ -505,39 +505,36 @@ static __init void zhaoxin_arch_events_quirk(void)
__init int zhaoxin_pmu_init(void)
{
- union cpuid10_edx edx;
- union cpuid10_eax eax;
- union cpuid10_ebx ebx;
+ const struct cpuid_regs *regs = cpuid_leaf_raw(&boot_cpu_data, 0xa);
+ const struct leaf_0xa_0 *leaf = cpuid_leaf(&boot_cpu_data, 0xa);
struct event_constraint *c;
- unsigned int unused;
- int version;
pr_info("Welcome to zhaoxin pmu!\n");
+ if (!leaf || !regs)
+ return -ENODEV;
+
/*
* Check whether the Architectural PerfMon supports
* hw_event or not.
*/
- cpuid(10, &eax.full, &ebx.full, &unused, &edx.full);
-
- if (eax.split.mask_length < ARCH_PERFMON_EVENTS_COUNT - 1)
+ if (leaf->events_mask_len < ARCH_PERFMON_EVENTS_COUNT - 1)
return -ENODEV;
- version = eax.split.version_id;
- if (version != 2)
+ if (leaf->pmu_version != 2)
return -ENODEV;
x86_pmu = zhaoxin_pmu;
pr_info("Version check pass!\n");
- x86_pmu.version = version;
- x86_pmu.cntr_mask64 = GENMASK_ULL(eax.split.num_counters - 1, 0);
- x86_pmu.cntval_bits = eax.split.bit_width;
- x86_pmu.cntval_mask = (1ULL << eax.split.bit_width) - 1;
- x86_pmu.events_maskl = ebx.full;
- x86_pmu.events_mask_len = eax.split.mask_length;
+ x86_pmu.version = leaf->pmu_version;
+ x86_pmu.cntr_mask64 = GENMASK_ULL(leaf->num_counters_gp - 1, 0);
+ x86_pmu.cntval_bits = leaf->bit_width_gp;
+ x86_pmu.cntval_mask = (1ULL << leaf->bit_width_gp) - 1;
+ x86_pmu.events_maskl = regs->ebx;
+ x86_pmu.events_mask_len = leaf->events_mask_len;
- x86_pmu.fixed_cntr_mask64 = GENMASK_ULL(edx.split.num_counters_fixed - 1, 0);
+ x86_pmu.fixed_cntr_mask64 = GENMASK_ULL(leaf->num_counters_fixed - 1, 0);
x86_add_quirk(zhaoxin_arch_events_quirk);
switch (boot_cpu_data.x86) {
@@ -617,4 +614,3 @@ __init int zhaoxin_pmu_init(void)
return 0;
}
-
--
2.53.0
^ permalink raw reply related [flat|nested] 101+ messages in thread
* [PATCH v6 57/90] x86/xen: Use parsed CPUID(0xa)
2026-03-27 2:15 [PATCH v6 00/90] x86: Introduce a centralized CPUID data model Ahmed S. Darwish
` (55 preceding siblings ...)
2026-03-27 2:16 ` [PATCH v6 56/90] perf/x86/zhaoxin: " Ahmed S. Darwish
@ 2026-03-27 2:16 ` Ahmed S. Darwish
2026-03-27 2:16 ` [PATCH v6 58/90] KVM: x86: Use standard CPUID(0xa) types Ahmed S. Darwish
` (34 subsequent siblings)
91 siblings, 0 replies; 101+ messages in thread
From: Ahmed S. Darwish @ 2026-03-27 2:16 UTC (permalink / raw)
To: Borislav Petkov, Dave Hansen, Ingo Molnar
Cc: Thomas Gleixner, Andrew Cooper, H. Peter Anvin,
Sean Christopherson, David Woodhouse, Peter Zijlstra,
Christian Ludloff, Sohil Mehta, John Ogness, x86, x86-cpuid, LKML,
Ahmed S. Darwish
For Xen PMU, use parsed CPUID(0xa) instead of a direct CPUID query and ugly
bitwise operations.
Remove the PMU_{GENERAL,FIXED}_NR macros as they are no longer needed.
Signed-off-by: Ahmed S. Darwish <darwi@linutronix.de>
---
arch/x86/xen/pmu.c | 26 +++++---------------------
1 file changed, 5 insertions(+), 21 deletions(-)
diff --git a/arch/x86/xen/pmu.c b/arch/x86/xen/pmu.c
index 5f50a3ee08f5..b0ef35f2bad3 100644
--- a/arch/x86/xen/pmu.c
+++ b/arch/x86/xen/pmu.c
@@ -48,18 +48,6 @@ static __read_mostly int amd_num_counters;
#define MSR_TYPE_ARCH_COUNTER 3
#define MSR_TYPE_ARCH_CTRL 4
-/* Number of general pmu registers (CPUID.EAX[0xa].EAX[8..15]) */
-#define PMU_GENERAL_NR_SHIFT 8
-#define PMU_GENERAL_NR_BITS 8
-#define PMU_GENERAL_NR_MASK (((1 << PMU_GENERAL_NR_BITS) - 1) \
- << PMU_GENERAL_NR_SHIFT)
-
-/* Number of fixed pmu registers (CPUID.EDX[0xa].EDX[0..4]) */
-#define PMU_FIXED_NR_SHIFT 0
-#define PMU_FIXED_NR_BITS 5
-#define PMU_FIXED_NR_MASK (((1 << PMU_FIXED_NR_BITS) - 1) \
- << PMU_FIXED_NR_SHIFT)
-
/* Alias registers (0x4c1) for full-width writes to PMCs */
#define MSR_PMC_ALIAS_MASK (~(MSR_IA32_PERFCTR0 ^ MSR_IA32_PMC0))
@@ -70,6 +58,8 @@ static __read_mostly int intel_num_arch_counters, intel_num_fixed_counters;
static void xen_pmu_arch_init(void)
{
+ const struct leaf_0xa_0 *leaf_a = cpuid_leaf(&boot_cpu_data, 0xa);
+
if (boot_cpu_data.x86_vendor == X86_VENDOR_AMD) {
switch (boot_cpu_data.x86) {
@@ -98,15 +88,9 @@ static void xen_pmu_arch_init(void)
amd_ctrls_base = MSR_K7_EVNTSEL0;
amd_msr_step = 1;
k7_counters_mirrored = 0;
- } else {
- uint32_t eax, ebx, ecx, edx;
-
- cpuid(0xa, &eax, &ebx, &ecx, &edx);
-
- intel_num_arch_counters = (eax & PMU_GENERAL_NR_MASK) >>
- PMU_GENERAL_NR_SHIFT;
- intel_num_fixed_counters = (edx & PMU_FIXED_NR_MASK) >>
- PMU_FIXED_NR_SHIFT;
+ } else if (leaf_a) {
+ intel_num_arch_counters = leaf_a->num_counters_gp;
+ intel_num_fixed_counters = leaf_a->num_counters_fixed;
}
}
--
2.53.0
^ permalink raw reply related [flat|nested] 101+ messages in thread
* [PATCH v6 58/90] KVM: x86: Use standard CPUID(0xa) types
2026-03-27 2:15 [PATCH v6 00/90] x86: Introduce a centralized CPUID data model Ahmed S. Darwish
` (56 preceding siblings ...)
2026-03-27 2:16 ` [PATCH v6 57/90] x86/xen: " Ahmed S. Darwish
@ 2026-03-27 2:16 ` Ahmed S. Darwish
2026-03-27 2:16 ` [PATCH v6 59/90] KVM: x86/pmu: " Ahmed S. Darwish
` (33 subsequent siblings)
91 siblings, 0 replies; 101+ messages in thread
From: Ahmed S. Darwish @ 2026-03-27 2:16 UTC (permalink / raw)
To: Borislav Petkov, Dave Hansen, Ingo Molnar
Cc: Thomas Gleixner, Andrew Cooper, H. Peter Anvin,
Sean Christopherson, David Woodhouse, Peter Zijlstra,
Christian Ludloff, Sohil Mehta, John Ogness, x86, x86-cpuid, LKML,
Ahmed S. Darwish
For KVM guest CPUID build-up, use the auto-generated CPUID(0xa) types from
x86-cpuid-db instead of relying on the custom perf types.
The latter types are in process of getting removed from the kernel.
Signed-off-by: Ahmed S. Darwish <darwi@linutronix.de>
---
arch/x86/kvm/cpuid.c | 22 +++++++++++-----------
1 file changed, 11 insertions(+), 11 deletions(-)
diff --git a/arch/x86/kvm/cpuid.c b/arch/x86/kvm/cpuid.c
index 8137927e7387..16ed4c001c79 100644
--- a/arch/x86/kvm/cpuid.c
+++ b/arch/x86/kvm/cpuid.c
@@ -1503,28 +1503,28 @@ static inline int __do_cpuid_func(struct kvm_cpuid_array *array, u32 function)
}
break;
case 0xa: { /* Architectural Performance Monitoring */
- union cpuid10_eax eax = { };
- union cpuid10_edx edx = { };
+ struct leaf_0xa_0 l = { };
+ struct cpuid_regs *regs = (struct cpuid_regs *)&l;
if (!enable_pmu || !static_cpu_has(X86_FEATURE_ARCH_PERFMON)) {
entry->eax = entry->ebx = entry->ecx = entry->edx = 0;
break;
}
- eax.split.version_id = kvm_pmu_cap.version;
- eax.split.num_counters = kvm_pmu_cap.num_counters_gp;
- eax.split.bit_width = kvm_pmu_cap.bit_width_gp;
- eax.split.mask_length = kvm_pmu_cap.events_mask_len;
- edx.split.num_counters_fixed = kvm_pmu_cap.num_counters_fixed;
- edx.split.bit_width_fixed = kvm_pmu_cap.bit_width_fixed;
+ l.pmu_version = kvm_pmu_cap.version;
+ l.num_counters_gp = kvm_pmu_cap.num_counters_gp;
+ l.bit_width_gp = kvm_pmu_cap.bit_width_gp;
+ l.events_mask_len = kvm_pmu_cap.events_mask_len;
+ l.num_counters_fixed = kvm_pmu_cap.num_counters_fixed;
+ l.bitwidth_fixed = kvm_pmu_cap.bit_width_fixed;
if (kvm_pmu_cap.version)
- edx.split.anythread_deprecated = 1;
+ l.anythread_deprecation = 1;
- entry->eax = eax.full;
+ entry->eax = regs->eax;
entry->ebx = kvm_pmu_cap.events_mask;
entry->ecx = 0;
- entry->edx = edx.full;
+ entry->edx = regs->edx;
break;
}
case 0x1f:
--
2.53.0
^ permalink raw reply related [flat|nested] 101+ messages in thread
* [PATCH v6 59/90] KVM: x86/pmu: Use standard CPUID(0xa) types
2026-03-27 2:15 [PATCH v6 00/90] x86: Introduce a centralized CPUID data model Ahmed S. Darwish
` (57 preceding siblings ...)
2026-03-27 2:16 ` [PATCH v6 58/90] KVM: x86: Use standard CPUID(0xa) types Ahmed S. Darwish
@ 2026-03-27 2:16 ` Ahmed S. Darwish
2026-03-27 2:16 ` [PATCH v6 60/90] perf/x86: Remove custom " Ahmed S. Darwish
` (32 subsequent siblings)
91 siblings, 0 replies; 101+ messages in thread
From: Ahmed S. Darwish @ 2026-03-27 2:16 UTC (permalink / raw)
To: Borislav Petkov, Dave Hansen, Ingo Molnar
Cc: Thomas Gleixner, Andrew Cooper, H. Peter Anvin,
Sean Christopherson, David Woodhouse, Peter Zijlstra,
Christian Ludloff, Sohil Mehta, John Ogness, x86, x86-cpuid, LKML,
Ahmed S. Darwish
For KVM PMU refresh, use the auto-generated CPUID(0xa) types from
x86-cpuid-db instead of relying on the custom perf types.
The latter types are in process of getting removed from the kernel.
Signed-off-by: Ahmed S. Darwish <darwi@linutronix.de>
---
arch/x86/kvm/vmx/pmu_intel.c | 31 +++++++++++++------------------
1 file changed, 13 insertions(+), 18 deletions(-)
diff --git a/arch/x86/kvm/vmx/pmu_intel.c b/arch/x86/kvm/vmx/pmu_intel.c
index 74e0b01185b8..e0aeb1bc04ca 100644
--- a/arch/x86/kvm/vmx/pmu_intel.c
+++ b/arch/x86/kvm/vmx/pmu_intel.c
@@ -493,8 +493,8 @@ static void intel_pmu_refresh(struct kvm_vcpu *vcpu)
struct kvm_pmu *pmu = vcpu_to_pmu(vcpu);
struct lbr_desc *lbr_desc = vcpu_to_lbr_desc(vcpu);
struct kvm_cpuid_entry2 *entry;
- union cpuid10_eax eax;
- union cpuid10_edx edx;
+ struct leaf_0xa_0 l = { };
+ struct cpuid_regs *regs = (struct cpuid_regs *)&l;
u64 perf_capabilities;
u64 counter_rsvd;
@@ -515,21 +515,18 @@ static void intel_pmu_refresh(struct kvm_vcpu *vcpu)
if (!entry)
return;
- eax.full = entry->eax;
- edx.full = entry->edx;
+ regs->eax = entry->eax;
+ regs->edx = entry->edx;
- pmu->version = eax.split.version_id;
+ pmu->version = l.pmu_version;
if (!pmu->version)
return;
- pmu->nr_arch_gp_counters = min_t(int, eax.split.num_counters,
- kvm_pmu_cap.num_counters_gp);
- eax.split.bit_width = min_t(int, eax.split.bit_width,
- kvm_pmu_cap.bit_width_gp);
- pmu->counter_bitmask[KVM_PMC_GP] = BIT_ULL(eax.split.bit_width) - 1;
- eax.split.mask_length = min_t(int, eax.split.mask_length,
- kvm_pmu_cap.events_mask_len);
- pmu->available_event_types = ~entry->ebx & (BIT_ULL(eax.split.mask_length) - 1);
+ pmu->nr_arch_gp_counters = min_t(int, l.num_counters_gp, kvm_pmu_cap.num_counters_gp);
+ l.bit_width_gp = min_t(int, l.bit_width_gp, kvm_pmu_cap.bit_width_gp);
+ pmu->counter_bitmask[KVM_PMC_GP]= BIT_ULL(l.bit_width_gp) - 1;
+ l.events_mask_len = min_t(int, l.events_mask_len, kvm_pmu_cap.events_mask_len);
+ pmu->available_event_types = ~entry->ebx & (BIT_ULL(l.events_mask_len) - 1);
entry = kvm_find_cpuid_entry_index(vcpu, 7, 0);
if (entry &&
@@ -552,11 +549,9 @@ static void intel_pmu_refresh(struct kvm_vcpu *vcpu)
if (pmu->version == 1)
return;
- pmu->nr_arch_fixed_counters = min_t(int, edx.split.num_counters_fixed,
- kvm_pmu_cap.num_counters_fixed);
- edx.split.bit_width_fixed = min_t(int, edx.split.bit_width_fixed,
- kvm_pmu_cap.bit_width_fixed);
- pmu->counter_bitmask[KVM_PMC_FIXED] = BIT_ULL(edx.split.bit_width_fixed) - 1;
+ pmu->nr_arch_fixed_counters = min_t(int, l.num_counters_fixed, kvm_pmu_cap.num_counters_fixed);
+ l.bitwidth_fixed = min_t(int, l.bitwidth_fixed, kvm_pmu_cap.bit_width_fixed);
+ pmu->counter_bitmask[KVM_PMC_FIXED] = BIT_ULL(l.bitwidth_fixed) - 1;
intel_pmu_enable_fixed_counter_bits(pmu, INTEL_FIXED_0_KERNEL |
INTEL_FIXED_0_USER |
--
2.53.0
^ permalink raw reply related [flat|nested] 101+ messages in thread
* [PATCH v6 60/90] perf/x86: Remove custom CPUID(0xa) types
2026-03-27 2:15 [PATCH v6 00/90] x86: Introduce a centralized CPUID data model Ahmed S. Darwish
` (58 preceding siblings ...)
2026-03-27 2:16 ` [PATCH v6 59/90] KVM: x86/pmu: " Ahmed S. Darwish
@ 2026-03-27 2:16 ` Ahmed S. Darwish
2026-03-27 2:16 ` [PATCH v6 61/90] perf/x86/lbr: Use parsed CPUID(0x1c) Ahmed S. Darwish
` (31 subsequent siblings)
91 siblings, 0 replies; 101+ messages in thread
From: Ahmed S. Darwish @ 2026-03-27 2:16 UTC (permalink / raw)
To: Borislav Petkov, Dave Hansen, Ingo Molnar
Cc: Thomas Gleixner, Andrew Cooper, H. Peter Anvin,
Sean Christopherson, David Woodhouse, Peter Zijlstra,
Christian Ludloff, Sohil Mehta, John Ogness, x86, x86-cpuid, LKML,
Ahmed S. Darwish
All CPUID(0xa) sites have been transformed from direct CPUID queries to the
CPUID parser APIs.
Pure users of perf's custom CPUID(0xa) types have also been converted to
the auto generated x86-cpuid-db data types.
Remove the now-unused CPUID(0xa) types from <asm/perf_event.h>.
Signed-off-by: Ahmed S. Darwish <darwi@linutronix.de>
---
arch/x86/include/asm/perf_event.h | 38 -------------------------------
1 file changed, 38 deletions(-)
diff --git a/arch/x86/include/asm/perf_event.h b/arch/x86/include/asm/perf_event.h
index ff5acb8b199b..23caaba1e104 100644
--- a/arch/x86/include/asm/perf_event.h
+++ b/arch/x86/include/asm/perf_event.h
@@ -157,44 +157,6 @@
/* Steal the highest bit of pebs_data_cfg for SW usage */
#define PEBS_UPDATE_DS_SW BIT_ULL(63)
-/*
- * Intel "Architectural Performance Monitoring" CPUID
- * detection/enumeration details:
- */
-union cpuid10_eax {
- struct {
- unsigned int version_id:8;
- unsigned int num_counters:8;
- unsigned int bit_width:8;
- unsigned int mask_length:8;
- } split;
- unsigned int full;
-};
-
-union cpuid10_ebx {
- struct {
- unsigned int no_unhalted_core_cycles:1;
- unsigned int no_instructions_retired:1;
- unsigned int no_unhalted_reference_cycles:1;
- unsigned int no_llc_reference:1;
- unsigned int no_llc_misses:1;
- unsigned int no_branch_instruction_retired:1;
- unsigned int no_branch_misses_retired:1;
- } split;
- unsigned int full;
-};
-
-union cpuid10_edx {
- struct {
- unsigned int num_counters_fixed:5;
- unsigned int bit_width_fixed:8;
- unsigned int reserved1:2;
- unsigned int anythread_deprecated:1;
- unsigned int reserved2:16;
- } split;
- unsigned int full;
-};
-
/*
* Intel "Architectural Performance Monitoring extension" CPUID
* detection/enumeration details:
--
2.53.0
^ permalink raw reply related [flat|nested] 101+ messages in thread
* [PATCH v6 61/90] perf/x86/lbr: Use parsed CPUID(0x1c)
2026-03-27 2:15 [PATCH v6 00/90] x86: Introduce a centralized CPUID data model Ahmed S. Darwish
` (59 preceding siblings ...)
2026-03-27 2:16 ` [PATCH v6 60/90] perf/x86: Remove custom " Ahmed S. Darwish
@ 2026-03-27 2:16 ` Ahmed S. Darwish
2026-03-27 2:16 ` [PATCH v6 62/90] perf/x86/lbr: Remove custom CPUID(0x1c) types Ahmed S. Darwish
` (30 subsequent siblings)
91 siblings, 0 replies; 101+ messages in thread
From: Ahmed S. Darwish @ 2026-03-27 2:16 UTC (permalink / raw)
To: Borislav Petkov, Dave Hansen, Ingo Molnar
Cc: Thomas Gleixner, Andrew Cooper, H. Peter Anvin,
Sean Christopherson, David Woodhouse, Peter Zijlstra,
Christian Ludloff, Sohil Mehta, John Ogness, x86, x86-cpuid, LKML,
Ahmed S. Darwish
Use parsed CPUID(0x1c) instead of a direct CPUID query and custom perf
CPUID(0x1c) data types.
Signed-off-by: Ahmed S. Darwish <darwi@linutronix.de>
---
arch/x86/events/intel/lbr.c | 33 +++++++++++++++------------------
1 file changed, 15 insertions(+), 18 deletions(-)
diff --git a/arch/x86/events/intel/lbr.c b/arch/x86/events/intel/lbr.c
index cae2e02fe6cc..7bc48f5e5e52 100644
--- a/arch/x86/events/intel/lbr.c
+++ b/arch/x86/events/intel/lbr.c
@@ -1587,19 +1587,16 @@ static bool is_arch_lbr_xsave_available(void)
void __init intel_pmu_arch_lbr_init(void)
{
+ const struct leaf_0x1c_0 *l = cpuid_leaf(&boot_cpu_data, 0x1c);
struct pmu *pmu = x86_get_pmu(smp_processor_id());
- union cpuid28_eax eax;
- union cpuid28_ebx ebx;
- union cpuid28_ecx ecx;
- unsigned int unused_edx;
bool arch_lbr_xsave;
size_t size;
u64 lbr_nr;
- /* Arch LBR Capabilities */
- cpuid(28, &eax.full, &ebx.full, &ecx.full, &unused_edx);
+ if (!l)
+ goto clear_arch_lbr;
- lbr_nr = fls(eax.split.lbr_depth_mask) * 8;
+ lbr_nr = fls(l->lbr_depth_mask) * 8;
if (!lbr_nr)
goto clear_arch_lbr;
@@ -1607,17 +1604,17 @@ void __init intel_pmu_arch_lbr_init(void)
if (wrmsrq_safe(MSR_ARCH_LBR_DEPTH, lbr_nr))
goto clear_arch_lbr;
- x86_pmu.lbr_depth_mask = eax.split.lbr_depth_mask;
- x86_pmu.lbr_deep_c_reset = eax.split.lbr_deep_c_reset;
- x86_pmu.lbr_lip = eax.split.lbr_lip;
- x86_pmu.lbr_cpl = ebx.split.lbr_cpl;
- x86_pmu.lbr_filter = ebx.split.lbr_filter;
- x86_pmu.lbr_call_stack = ebx.split.lbr_call_stack;
- x86_pmu.lbr_mispred = ecx.split.lbr_mispred;
- x86_pmu.lbr_timed_lbr = ecx.split.lbr_timed_lbr;
- x86_pmu.lbr_br_type = ecx.split.lbr_br_type;
- x86_pmu.lbr_counters = ecx.split.lbr_counters;
- x86_pmu.lbr_nr = lbr_nr;
+ x86_pmu.lbr_depth_mask = l->lbr_depth_mask;
+ x86_pmu.lbr_deep_c_reset = l->lbr_deep_c_reset;
+ x86_pmu.lbr_lip = l->lbr_ip_is_lip;
+ x86_pmu.lbr_cpl = l->lbr_cpl;
+ x86_pmu.lbr_filter = l->lbr_branch_filter;
+ x86_pmu.lbr_call_stack = l->lbr_call_stack;
+ x86_pmu.lbr_mispred = l->lbr_mispredict;
+ x86_pmu.lbr_timed_lbr = l->lbr_timed_lbr;
+ x86_pmu.lbr_br_type = l->lbr_branch_type;
+ x86_pmu.lbr_counters = l->lbr_events_gpc_bmp;
+ x86_pmu.lbr_nr = lbr_nr;
if (!!x86_pmu.lbr_counters)
x86_pmu.flags |= PMU_FL_BR_CNTR | PMU_FL_DYN_CONSTRAINT;
--
2.53.0
^ permalink raw reply related [flat|nested] 101+ messages in thread
* [PATCH v6 62/90] perf/x86/lbr: Remove custom CPUID(0x1c) types
2026-03-27 2:15 [PATCH v6 00/90] x86: Introduce a centralized CPUID data model Ahmed S. Darwish
` (60 preceding siblings ...)
2026-03-27 2:16 ` [PATCH v6 61/90] perf/x86/lbr: Use parsed CPUID(0x1c) Ahmed S. Darwish
@ 2026-03-27 2:16 ` Ahmed S. Darwish
2026-03-27 2:16 ` [PATCH v6 63/90] x86/cpuid: Parse CPUID(0x23) Ahmed S. Darwish
` (29 subsequent siblings)
91 siblings, 0 replies; 101+ messages in thread
From: Ahmed S. Darwish @ 2026-03-27 2:16 UTC (permalink / raw)
To: Borislav Petkov, Dave Hansen, Ingo Molnar
Cc: Thomas Gleixner, Andrew Cooper, H. Peter Anvin,
Sean Christopherson, David Woodhouse, Peter Zijlstra,
Christian Ludloff, Sohil Mehta, John Ogness, x86, x86-cpuid, LKML,
Ahmed S. Darwish
All CPUID(0x1c) call sites have been converted from direct CPUID queries to
the CPUID API and its x86-cpuid-db auto generated types.
Remove the custom CPUID(0x1c) types from <asm/perf_event.h>.
Signed-off-by: Ahmed S. Darwish <darwi@linutronix.de>
---
arch/x86/include/asm/perf_event.h | 43 -------------------------------
1 file changed, 43 deletions(-)
diff --git a/arch/x86/include/asm/perf_event.h b/arch/x86/include/asm/perf_event.h
index 23caaba1e104..c57e6c9231aa 100644
--- a/arch/x86/include/asm/perf_event.h
+++ b/arch/x86/include/asm/perf_event.h
@@ -197,49 +197,6 @@ union cpuid35_ebx {
unsigned int full;
};
-/*
- * Intel Architectural LBR CPUID detection/enumeration details:
- */
-union cpuid28_eax {
- struct {
- /* Supported LBR depth values */
- unsigned int lbr_depth_mask:8;
- unsigned int reserved:22;
- /* Deep C-state Reset */
- unsigned int lbr_deep_c_reset:1;
- /* IP values contain LIP */
- unsigned int lbr_lip:1;
- } split;
- unsigned int full;
-};
-
-union cpuid28_ebx {
- struct {
- /* CPL Filtering Supported */
- unsigned int lbr_cpl:1;
- /* Branch Filtering Supported */
- unsigned int lbr_filter:1;
- /* Call-stack Mode Supported */
- unsigned int lbr_call_stack:1;
- } split;
- unsigned int full;
-};
-
-union cpuid28_ecx {
- struct {
- /* Mispredict Bit Supported */
- unsigned int lbr_mispred:1;
- /* Timed LBRs Supported */
- unsigned int lbr_timed_lbr:1;
- /* Branch Type Field Supported */
- unsigned int lbr_br_type:1;
- unsigned int reserved:13;
- /* Branch counters (Event Logging) Supported */
- unsigned int lbr_counters:4;
- } split;
- unsigned int full;
-};
-
/*
* AMD "Extended Performance Monitoring and Debug" CPUID
* detection/enumeration details:
--
2.53.0
^ permalink raw reply related [flat|nested] 101+ messages in thread
* [PATCH v6 63/90] x86/cpuid: Parse CPUID(0x23)
2026-03-27 2:15 [PATCH v6 00/90] x86: Introduce a centralized CPUID data model Ahmed S. Darwish
` (61 preceding siblings ...)
2026-03-27 2:16 ` [PATCH v6 62/90] perf/x86/lbr: Remove custom CPUID(0x1c) types Ahmed S. Darwish
@ 2026-03-27 2:16 ` Ahmed S. Darwish
2026-03-27 2:16 ` [PATCH v6 64/90] perf/x86/intel: Use parsed per-CPU CPUID(0x23) Ahmed S. Darwish
` (28 subsequent siblings)
91 siblings, 0 replies; 101+ messages in thread
From: Ahmed S. Darwish @ 2026-03-27 2:16 UTC (permalink / raw)
To: Borislav Petkov, Dave Hansen, Ingo Molnar
Cc: Thomas Gleixner, Andrew Cooper, H. Peter Anvin,
Sean Christopherson, David Woodhouse, Peter Zijlstra,
Christian Ludloff, Sohil Mehta, John Ogness, x86, x86-cpuid, LKML,
Ahmed S. Darwish
Parse Intel PMU CPUID(0x23), and all its known subleaves.
This allows converting their call sites to the CPUID API next.
Note, for all subleaves, make sure that subleaf 0 declares their support
beforehand.
Signed-off-by: Ahmed S. Darwish <darwi@linutronix.de>
---
arch/x86/include/asm/cpuid/types.h | 6 +++++
arch/x86/kernel/cpu/cpuid_parser.c | 37 ++++++++++++++++++++++++++++++
arch/x86/kernel/cpu/cpuid_parser.h | 7 ++++++
3 files changed, 50 insertions(+)
diff --git a/arch/x86/include/asm/cpuid/types.h b/arch/x86/include/asm/cpuid/types.h
index 128898d4434b..70ccd52a6848 100644
--- a/arch/x86/include/asm/cpuid/types.h
+++ b/arch/x86/include/asm/cpuid/types.h
@@ -215,6 +215,12 @@ struct cpuid_leaves {
CPUID_LEAF ( 0xa, 0 );
CPUID_LEAF ( 0x1c, 0 );
CPUID_LEAF ( 0x16, 0 );
+ CPUID_LEAF ( 0x23, 0 );
+ CPUID_LEAF ( 0x23, 1 );
+ CPUID_LEAF ( 0x23, 2 );
+ CPUID_LEAF ( 0x23, 3 );
+ CPUID_LEAF ( 0x23, 4 );
+ CPUID_LEAF ( 0x23, 5 );
CPUID_LEAF ( 0x80000000, 0 );
CPUID_LEAF ( 0x80000002, 0 );
CPUID_LEAF ( 0x80000003, 0 );
diff --git a/arch/x86/kernel/cpu/cpuid_parser.c b/arch/x86/kernel/cpu/cpuid_parser.c
index 99507e99d8d9..de11fb4116f2 100644
--- a/arch/x86/kernel/cpu/cpuid_parser.c
+++ b/arch/x86/kernel/cpu/cpuid_parser.c
@@ -105,6 +105,43 @@ cpuid_read_0x2(const struct cpuid_parse_entry *e, const struct cpuid_read_output
*/
define_cpuid_read_function(deterministic_cache, leaf_0x4_n, l, l->cache_type == 0);
+static bool cpuid_0x23_has_subleaf(u32 subleaf)
+{
+ struct leaf_0x23_0 l;
+
+ cpuid_read_subleaf(0x23, 0, &l);
+
+ if (subleaf == 1)
+ return l.counters_subleaf;
+ if (subleaf == 2)
+ return l.acr_subleaf;
+ if (subleaf == 3)
+ return l.events_subleaf;
+ if (subleaf == 4)
+ return l.pebs_caps_subleaf;
+ if (subleaf == 5)
+ return l.pebs_subleaf;
+
+ return false;
+}
+
+#define define_cpuid_0x23_subleaf_read_function(subl) \
+static void \
+cpuid_read_0x23_##subl(const struct cpuid_parse_entry *e, const struct cpuid_read_output *output) \
+{ \
+ if (!cpuid_0x23_has_subleaf(subl)) \
+ return; \
+ \
+ cpuid_read_subleaf(e->leaf, e->subleaf, output->regs); \
+ output->info->nr_entries = 1; \
+}
+
+define_cpuid_0x23_subleaf_read_function(1);
+define_cpuid_0x23_subleaf_read_function(2);
+define_cpuid_0x23_subleaf_read_function(3);
+define_cpuid_0x23_subleaf_read_function(4);
+define_cpuid_0x23_subleaf_read_function(5);
+
/*
* Define an extended range CPUID read function
*
diff --git a/arch/x86/kernel/cpu/cpuid_parser.h b/arch/x86/kernel/cpu/cpuid_parser.h
index 8e147e7223e0..46f06792afb1 100644
--- a/arch/x86/kernel/cpu/cpuid_parser.h
+++ b/arch/x86/kernel/cpu/cpuid_parser.h
@@ -149,6 +149,12 @@ struct cpuid_parse_entry {
CPUID_PARSE_ENTRY ( 0xa, 0, generic ), \
CPUID_PARSE_ENTRY ( 0x1c, 0, generic ), \
CPUID_PARSE_ENTRY ( 0x16, 0, generic ), \
+ CPUID_PARSE_ENTRY ( 0x23, 0, generic ), \
+ CPUID_PARSE_ENTRY ( 0x23, 1, 0x23_1 ), \
+ CPUID_PARSE_ENTRY ( 0x23, 2, 0x23_2 ), \
+ CPUID_PARSE_ENTRY ( 0x23, 3, 0x23_3 ), \
+ CPUID_PARSE_ENTRY ( 0x23, 4, 0x23_4 ), \
+ CPUID_PARSE_ENTRY ( 0x23, 5, 0x23_5 ), \
CPUID_PARSE_ENTRY ( 0x80000000, 0, 0x80000000 ), \
CPUID_PARSE_ENTRY ( 0x80000002, 0, generic ), \
CPUID_PARSE_ENTRY ( 0x80000003, 0, generic ), \
@@ -203,6 +209,7 @@ struct cpuid_vendor_entry {
CPUID_VENDOR_ENTRY(0xa, X86_VENDOR_INTEL, X86_VENDOR_CENTAUR, X86_VENDOR_ZHAOXIN),\
CPUID_VENDOR_ENTRY(0x16, X86_VENDOR_INTEL), \
CPUID_VENDOR_ENTRY(0x1c, X86_VENDOR_INTEL), \
+ CPUID_VENDOR_ENTRY(0x23, X86_VENDOR_INTEL), \
CPUID_VENDOR_ENTRY(0x8000001d, X86_VENDOR_AMD, X86_VENDOR_HYGON), \
CPUID_VENDOR_ENTRY(0x80860000, X86_VENDOR_TRANSMETA), \
CPUID_VENDOR_ENTRY(0x80860001, X86_VENDOR_TRANSMETA), \
--
2.53.0
^ permalink raw reply related [flat|nested] 101+ messages in thread
* [PATCH v6 64/90] perf/x86/intel: Use parsed per-CPU CPUID(0x23)
2026-03-27 2:15 [PATCH v6 00/90] x86: Introduce a centralized CPUID data model Ahmed S. Darwish
` (62 preceding siblings ...)
2026-03-27 2:16 ` [PATCH v6 63/90] x86/cpuid: Parse CPUID(0x23) Ahmed S. Darwish
@ 2026-03-27 2:16 ` Ahmed S. Darwish
2026-03-27 2:16 ` [PATCH v6 65/90] perf/x86/intel: Remove custom CPUID(0x23) types Ahmed S. Darwish
` (27 subsequent siblings)
91 siblings, 0 replies; 101+ messages in thread
From: Ahmed S. Darwish @ 2026-03-27 2:16 UTC (permalink / raw)
To: Borislav Petkov, Dave Hansen, Ingo Molnar
Cc: Thomas Gleixner, Andrew Cooper, H. Peter Anvin,
Sean Christopherson, David Woodhouse, Peter Zijlstra,
Christian Ludloff, Sohil Mehta, John Ogness, x86, x86-cpuid, LKML,
Ahmed S. Darwish
For Intel PMU capabilities, use parsed CPUID(0x23) instead of direct CPUID
queries and custom perf CPUID(0x23) data types.
Replace manual subleaves availability checks with checking whether the
CPUID APIs return NULL. This is sufficient since the CPUID parser
validates all the leaves and subleaves beforehand.
Signed-off-by: Ahmed S. Darwish <darwi@linutronix.de>
---
arch/x86/events/intel/core.c | 62 +++++++++++++++++-------------------
1 file changed, 30 insertions(+), 32 deletions(-)
diff --git a/arch/x86/events/intel/core.c b/arch/x86/events/intel/core.c
index 20dece48b994..6eee7fbcef9e 100644
--- a/arch/x86/events/intel/core.c
+++ b/arch/x86/events/intel/core.c
@@ -5891,51 +5891,49 @@ static inline void __intel_update_large_pebs_flags(struct pmu *pmu)
#define counter_mask(_gp, _fixed) ((_gp) | ((u64)(_fixed) << INTEL_PMC_IDX_FIXED))
-static void update_pmu_cap(struct pmu *pmu)
-{
- unsigned int eax, ebx, ecx, edx;
- union cpuid35_eax eax_0;
- union cpuid35_ebx ebx_0;
+static void update_pmu_cap(struct pmu *pmu, int cpu)
+{
+ struct cpuinfo_x86 *cpuinfo = is_hybrid() ? &cpu_data(cpu) : &boot_cpu_data;
+ const struct leaf_0x23_0 *sl0 = cpuid_subleaf(cpuinfo, 0x23, 0);
+ const struct leaf_0x23_1 *sl1 = cpuid_subleaf(cpuinfo, 0x23, 1);
+ const struct leaf_0x23_2 *sl2 = cpuid_subleaf(cpuinfo, 0x23, 2);
+ const struct leaf_0x23_4 *sl4 = cpuid_subleaf(cpuinfo, 0x23, 4);
+ const struct leaf_0x23_5 *sl5 = cpuid_subleaf(cpuinfo, 0x23, 5);
+ u64 pdists_mask = 0;
u64 cntrs_mask = 0;
u64 pebs_mask = 0;
- u64 pdists_mask = 0;
- cpuid(ARCH_PERFMON_EXT_LEAF, &eax_0.full, &ebx_0.full, &ecx, &edx);
+ if (!sl0)
+ return;
- if (ebx_0.split.umask2)
+ if (sl0->unitmask2)
hybrid(pmu, config_mask) |= ARCH_PERFMON_EVENTSEL_UMASK2;
- if (ebx_0.split.eq)
+ if (sl0->eq)
hybrid(pmu, config_mask) |= ARCH_PERFMON_EVENTSEL_EQ;
- if (ebx_0.split.rdpmc_user_disable)
+ if (sl0->rdpmc_user_disable)
hybrid(pmu, config_mask) |= ARCH_PERFMON_EVENTSEL_RDPMC_USER_DISABLE;
- if (eax_0.split.cntr_subleaf) {
- cpuid_count(ARCH_PERFMON_EXT_LEAF, ARCH_PERFMON_NUM_COUNTER_LEAF,
- &eax, &ebx, &ecx, &edx);
- hybrid(pmu, cntr_mask64) = eax;
- hybrid(pmu, fixed_cntr_mask64) = ebx;
- cntrs_mask = counter_mask(eax, ebx);
+ if (sl1) {
+ hybrid(pmu, cntr_mask64) = sl1->gp_counters;
+ hybrid(pmu, fixed_cntr_mask64) = sl1->fixed_counters;
+ cntrs_mask = counter_mask(sl1->gp_counters, sl1->fixed_counters);
}
- if (eax_0.split.acr_subleaf) {
- cpuid_count(ARCH_PERFMON_EXT_LEAF, ARCH_PERFMON_ACR_LEAF,
- &eax, &ebx, &ecx, &edx);
+ if (sl2) {
/* The mask of the counters which can be reloaded */
- hybrid(pmu, acr_cntr_mask64) = counter_mask(eax, ebx);
+ hybrid(pmu, acr_cntr_mask64) = counter_mask(sl2->acr_gp_reload, sl2->acr_fixed_reload);
/* The mask of the counters which can cause a reload of reloadable counters */
- hybrid(pmu, acr_cause_mask64) = counter_mask(ecx, edx);
+ hybrid(pmu, acr_cause_mask64) = counter_mask(sl2->acr_gp_trigger, sl2->acr_fixed_trigger);
}
- /* Bits[5:4] should be set simultaneously if arch-PEBS is supported */
- if (eax_0.split.pebs_caps_subleaf && eax_0.split.pebs_cnts_subleaf) {
- cpuid_count(ARCH_PERFMON_EXT_LEAF, ARCH_PERFMON_PEBS_CAP_LEAF,
- &eax, &ebx, &ecx, &edx);
- hybrid(pmu, arch_pebs_cap).caps = (u64)ebx << 32;
+ /* Both subleaves should be available if arch-PEBS is supported */
+ if (sl4 && sl5) {
+ const struct cpuid_regs *sl4_regs = (const struct cpuid_regs *)sl4;
+
+ hybrid(pmu, arch_pebs_cap).caps = (u64)sl4_regs->ebx << 32;
- cpuid_count(ARCH_PERFMON_EXT_LEAF, ARCH_PERFMON_PEBS_COUNTER_LEAF,
- &eax, &ebx, &ecx, &edx);
- pebs_mask = counter_mask(eax, ecx);
- pdists_mask = counter_mask(ebx, edx);
+ pebs_mask = counter_mask(sl5->pebs_gp, sl5->pebs_fixed);
+ pdists_mask = counter_mask(sl5->pebs_pdist_gp, sl5->pebs_pdist_fixed);
hybrid(pmu, arch_pebs_cap).counters = pebs_mask;
hybrid(pmu, arch_pebs_cap).pdists = pdists_mask;
@@ -6038,7 +6036,7 @@ static bool init_hybrid_pmu(int cpu)
goto end;
if (this_cpu_has(X86_FEATURE_ARCH_PERFMON_EXT))
- update_pmu_cap(&pmu->pmu);
+ update_pmu_cap(&pmu->pmu, cpu);
intel_pmu_check_hybrid_pmus(pmu);
@@ -8452,7 +8450,7 @@ __init int intel_pmu_init(void)
* when a new type is online.
*/
if (!is_hybrid() && boot_cpu_has(X86_FEATURE_ARCH_PERFMON_EXT))
- update_pmu_cap(NULL);
+ update_pmu_cap(NULL, 0);
if (x86_pmu.arch_pebs) {
static_call_update(intel_pmu_disable_event_ext,
--
2.53.0
^ permalink raw reply related [flat|nested] 101+ messages in thread
* [PATCH v6 65/90] perf/x86/intel: Remove custom CPUID(0x23) types
2026-03-27 2:15 [PATCH v6 00/90] x86: Introduce a centralized CPUID data model Ahmed S. Darwish
` (63 preceding siblings ...)
2026-03-27 2:16 ` [PATCH v6 64/90] perf/x86/intel: Use parsed per-CPU CPUID(0x23) Ahmed S. Darwish
@ 2026-03-27 2:16 ` Ahmed S. Darwish
2026-03-27 2:16 ` [PATCH v6 66/90] x86/cpuid: Parse CPUID(0x80000022) Ahmed S. Darwish
` (26 subsequent siblings)
91 siblings, 0 replies; 101+ messages in thread
From: Ahmed S. Darwish @ 2026-03-27 2:16 UTC (permalink / raw)
To: Borislav Petkov, Dave Hansen, Ingo Molnar
Cc: Thomas Gleixner, Andrew Cooper, H. Peter Anvin,
Sean Christopherson, David Woodhouse, Peter Zijlstra,
Christian Ludloff, Sohil Mehta, John Ogness, x86, x86-cpuid, LKML,
Ahmed S. Darwish
All CPUID(0x23) call sites have been converted to the CPUID API and its
auto generated x86-cpuid-db data types.
Remove the custom CPUID(0x23) types from perf.
Signed-off-by: Ahmed S. Darwish <darwi@linutronix.de>
---
arch/x86/include/asm/perf_event.h | 38 +------------------------------
1 file changed, 1 insertion(+), 37 deletions(-)
diff --git a/arch/x86/include/asm/perf_event.h b/arch/x86/include/asm/perf_event.h
index c57e6c9231aa..5aa07710af12 100644
--- a/arch/x86/include/asm/perf_event.h
+++ b/arch/x86/include/asm/perf_event.h
@@ -157,46 +157,10 @@
/* Steal the highest bit of pebs_data_cfg for SW usage */
#define PEBS_UPDATE_DS_SW BIT_ULL(63)
-/*
- * Intel "Architectural Performance Monitoring extension" CPUID
- * detection/enumeration details:
- */
-#define ARCH_PERFMON_EXT_LEAF 0x00000023
-#define ARCH_PERFMON_NUM_COUNTER_LEAF 0x1
-#define ARCH_PERFMON_ACR_LEAF 0x2
+// _CPUID_TODO_: Remove subleaf 4 and 5 after defining them
#define ARCH_PERFMON_PEBS_CAP_LEAF 0x4
#define ARCH_PERFMON_PEBS_COUNTER_LEAF 0x5
-union cpuid35_eax {
- struct {
- unsigned int leaf0:1;
- /* Counters Sub-Leaf */
- unsigned int cntr_subleaf:1;
- /* Auto Counter Reload Sub-Leaf */
- unsigned int acr_subleaf:1;
- /* Events Sub-Leaf */
- unsigned int events_subleaf:1;
- /* arch-PEBS Sub-Leaves */
- unsigned int pebs_caps_subleaf:1;
- unsigned int pebs_cnts_subleaf:1;
- unsigned int reserved:26;
- } split;
- unsigned int full;
-};
-
-union cpuid35_ebx {
- struct {
- /* UnitMask2 Supported */
- unsigned int umask2:1;
- /* EQ-bit Supported */
- unsigned int eq:1;
- /* rdpmc user disable Supported */
- unsigned int rdpmc_user_disable:1;
- unsigned int reserved:29;
- } split;
- unsigned int full;
-};
-
/*
* AMD "Extended Performance Monitoring and Debug" CPUID
* detection/enumeration details:
--
2.53.0
^ permalink raw reply related [flat|nested] 101+ messages in thread
* [PATCH v6 66/90] x86/cpuid: Parse CPUID(0x80000022)
2026-03-27 2:15 [PATCH v6 00/90] x86: Introduce a centralized CPUID data model Ahmed S. Darwish
` (64 preceding siblings ...)
2026-03-27 2:16 ` [PATCH v6 65/90] perf/x86/intel: Remove custom CPUID(0x23) types Ahmed S. Darwish
@ 2026-03-27 2:16 ` Ahmed S. Darwish
2026-03-27 2:16 ` [PATCH v6 67/90] perf/x86/amd/lbr: Use parsed CPUID(0x80000022) Ahmed S. Darwish
` (25 subsequent siblings)
91 siblings, 0 replies; 101+ messages in thread
From: Ahmed S. Darwish @ 2026-03-27 2:16 UTC (permalink / raw)
To: Borislav Petkov, Dave Hansen, Ingo Molnar
Cc: Thomas Gleixner, Andrew Cooper, H. Peter Anvin,
Sean Christopherson, David Woodhouse, Peter Zijlstra,
Christian Ludloff, Sohil Mehta, John Ogness, x86, x86-cpuid, LKML,
Ahmed S. Darwish
Parse CPUID(0x80000022).
Add AMD and Hygon vendor tags as it is only supported on these CPUs.
Signed-off-by: Ahmed S. Darwish <darwi@linutronix.de>
---
arch/x86/include/asm/cpuid/types.h | 1 +
arch/x86/kernel/cpu/cpuid_parser.h | 2 ++
2 files changed, 3 insertions(+)
diff --git a/arch/x86/include/asm/cpuid/types.h b/arch/x86/include/asm/cpuid/types.h
index 70ccd52a6848..deddb534486a 100644
--- a/arch/x86/include/asm/cpuid/types.h
+++ b/arch/x86/include/asm/cpuid/types.h
@@ -229,6 +229,7 @@ struct cpuid_leaves {
CPUID_LEAF ( 0x80000006, 0 );
CPUID_LEAF ( 0x80000008, 0 );
CPUID_LEAF_N ( 0x8000001d, 8 );
+ CPUID_LEAF ( 0x80000022, 0 );
CPUID_LEAF ( 0x80860000, 0 );
CPUID_LEAF ( 0x80860001, 0 );
CPUID_LEAF ( 0x80860002, 0 );
diff --git a/arch/x86/kernel/cpu/cpuid_parser.h b/arch/x86/kernel/cpu/cpuid_parser.h
index 46f06792afb1..59a4d562320a 100644
--- a/arch/x86/kernel/cpu/cpuid_parser.h
+++ b/arch/x86/kernel/cpu/cpuid_parser.h
@@ -163,6 +163,7 @@ struct cpuid_parse_entry {
CPUID_PARSE_ENTRY ( 0x80000006, 0, generic ), \
CPUID_PARSE_ENTRY ( 0x80000008, 0, generic ), \
CPUID_PARSE_ENTRY_N ( 0x8000001d, deterministic_cache ), \
+ CPUID_PARSE_ENTRY ( 0x80000022, 0, generic ), \
CPUID_PARSE_ENTRY ( 0x80860000, 0, 0x80860000 ), \
CPUID_PARSE_ENTRY ( 0x80860001, 0, generic ), \
CPUID_PARSE_ENTRY ( 0x80860002, 0, generic ), \
@@ -211,6 +212,7 @@ struct cpuid_vendor_entry {
CPUID_VENDOR_ENTRY(0x1c, X86_VENDOR_INTEL), \
CPUID_VENDOR_ENTRY(0x23, X86_VENDOR_INTEL), \
CPUID_VENDOR_ENTRY(0x8000001d, X86_VENDOR_AMD, X86_VENDOR_HYGON), \
+ CPUID_VENDOR_ENTRY(0x80000022, X86_VENDOR_AMD, X86_VENDOR_HYGON), \
CPUID_VENDOR_ENTRY(0x80860000, X86_VENDOR_TRANSMETA), \
CPUID_VENDOR_ENTRY(0x80860001, X86_VENDOR_TRANSMETA), \
CPUID_VENDOR_ENTRY(0x80860002, X86_VENDOR_TRANSMETA), \
--
2.53.0
^ permalink raw reply related [flat|nested] 101+ messages in thread
* [PATCH v6 67/90] perf/x86/amd/lbr: Use parsed CPUID(0x80000022)
2026-03-27 2:15 [PATCH v6 00/90] x86: Introduce a centralized CPUID data model Ahmed S. Darwish
` (65 preceding siblings ...)
2026-03-27 2:16 ` [PATCH v6 66/90] x86/cpuid: Parse CPUID(0x80000022) Ahmed S. Darwish
@ 2026-03-27 2:16 ` Ahmed S. Darwish
2026-03-27 2:16 ` [PATCH v6 68/90] perf/x86/amd: " Ahmed S. Darwish
` (24 subsequent siblings)
91 siblings, 0 replies; 101+ messages in thread
From: Ahmed S. Darwish @ 2026-03-27 2:16 UTC (permalink / raw)
To: Borislav Petkov, Dave Hansen, Ingo Molnar
Cc: Thomas Gleixner, Andrew Cooper, H. Peter Anvin,
Sean Christopherson, David Woodhouse, Peter Zijlstra,
Christian Ludloff, Sohil Mehta, John Ogness, x86, x86-cpuid, LKML,
Ahmed S. Darwish
For AMD LBR, use parsed CPUID(0x80000022) instead of a direct CPUID query
and custom perf data types.
Signed-off-by: Ahmed S. Darwish <darwi@linutronix.de>
---
arch/x86/events/amd/lbr.c | 7 +++----
1 file changed, 3 insertions(+), 4 deletions(-)
diff --git a/arch/x86/events/amd/lbr.c b/arch/x86/events/amd/lbr.c
index 5b437dc8e4ce..e5a16266545f 100644
--- a/arch/x86/events/amd/lbr.c
+++ b/arch/x86/events/amd/lbr.c
@@ -423,14 +423,13 @@ void amd_pmu_lbr_disable_all(void)
__init int amd_pmu_lbr_init(void)
{
- union cpuid_0x80000022_ebx ebx;
+ const struct leaf_0x80000022_0 *l = cpuid_leaf(&boot_cpu_data, 0x80000022);
- if (x86_pmu.version < 2 || !boot_cpu_has(X86_FEATURE_AMD_LBR_V2))
+ if (!l || x86_pmu.version < 2 || !boot_cpu_has(X86_FEATURE_AMD_LBR_V2))
return -EOPNOTSUPP;
/* Set number of entries */
- ebx.full = cpuid_ebx(EXT_PERFMON_DEBUG_FEATURES);
- x86_pmu.lbr_nr = ebx.split.lbr_v2_stack_sz;
+ x86_pmu.lbr_nr = l->lbr_v2_stack_size;
pr_cont("%d-deep LBR, ", x86_pmu.lbr_nr);
--
2.53.0
^ permalink raw reply related [flat|nested] 101+ messages in thread
* [PATCH v6 68/90] perf/x86/amd: Use parsed CPUID(0x80000022)
2026-03-27 2:15 [PATCH v6 00/90] x86: Introduce a centralized CPUID data model Ahmed S. Darwish
` (66 preceding siblings ...)
2026-03-27 2:16 ` [PATCH v6 67/90] perf/x86/amd/lbr: Use parsed CPUID(0x80000022) Ahmed S. Darwish
@ 2026-03-27 2:16 ` Ahmed S. Darwish
2026-03-27 2:16 ` [PATCH v6 69/90] KVM: x86: Use standard CPUID(0x80000022) types Ahmed S. Darwish
` (23 subsequent siblings)
91 siblings, 0 replies; 101+ messages in thread
From: Ahmed S. Darwish @ 2026-03-27 2:16 UTC (permalink / raw)
To: Borislav Petkov, Dave Hansen, Ingo Molnar
Cc: Thomas Gleixner, Andrew Cooper, H. Peter Anvin,
Sean Christopherson, David Woodhouse, Peter Zijlstra,
Christian Ludloff, Sohil Mehta, John Ogness, x86, x86-cpuid, LKML,
Ahmed S. Darwish
For AMD perf, use parsed CPUID(0x80000022) instead of direct CPUID queries
and custom perf data types.
For the uncore CPU hotplug callbacks, ensure that the correct per-CPU CPUID
table is queried.
Signed-off-by: Ahmed S. Darwish <darwi@linutronix.de>
---
arch/x86/events/amd/core.c | 8 +++-----
arch/x86/events/amd/uncore.c | 18 +++++++-----------
2 files changed, 10 insertions(+), 16 deletions(-)
diff --git a/arch/x86/events/amd/core.c b/arch/x86/events/amd/core.c
index d66a357f219d..b070d0be36c4 100644
--- a/arch/x86/events/amd/core.c
+++ b/arch/x86/events/amd/core.c
@@ -1410,7 +1410,7 @@ static const struct attribute_group *amd_attr_update[] = {
static int __init amd_core_pmu_init(void)
{
- union cpuid_0x80000022_ebx ebx;
+ const struct leaf_0x80000022_0 *leaf = cpuid_leaf(&boot_cpu_data, 0x80000022);
u64 even_ctr_mask = 0ULL;
int i;
@@ -1430,14 +1430,12 @@ static int __init amd_core_pmu_init(void)
x86_pmu.cntr_mask64 = GENMASK_ULL(AMD64_NUM_COUNTERS_CORE - 1, 0);
/* Check for Performance Monitoring v2 support */
- if (boot_cpu_has(X86_FEATURE_PERFMON_V2)) {
- ebx.full = cpuid_ebx(EXT_PERFMON_DEBUG_FEATURES);
-
+ if (leaf && boot_cpu_has(X86_FEATURE_PERFMON_V2)) {
/* Update PMU version for later usage */
x86_pmu.version = 2;
/* Find the number of available Core PMCs */
- x86_pmu.cntr_mask64 = GENMASK_ULL(ebx.split.num_core_pmc - 1, 0);
+ x86_pmu.cntr_mask64 = GENMASK_ULL(leaf->n_pmc_core - 1, 0);
amd_pmu_global_cntr_mask = x86_pmu.cntr_mask64;
diff --git a/arch/x86/events/amd/uncore.c b/arch/x86/events/amd/uncore.c
index 05cff39968ec..6a5d8f8cfbc0 100644
--- a/arch/x86/events/amd/uncore.c
+++ b/arch/x86/events/amd/uncore.c
@@ -692,7 +692,7 @@ static int amd_uncore_df_add(struct perf_event *event, int flags)
static
void amd_uncore_df_ctx_scan(struct amd_uncore *uncore, unsigned int cpu)
{
- union cpuid_0x80000022_ebx ebx;
+ const struct leaf_0x80000022_0 *leaf = cpuid_leaf(&cpu_data(cpu), 0x80000022);
union amd_uncore_info info;
if (!boot_cpu_has(X86_FEATURE_PERFCTR_NB))
@@ -703,10 +703,8 @@ void amd_uncore_df_ctx_scan(struct amd_uncore *uncore, unsigned int cpu)
info.split.gid = 0;
info.split.cid = topology_logical_package_id(cpu);
- if (pmu_version >= 2) {
- ebx.full = cpuid_ebx(EXT_PERFMON_DEBUG_FEATURES);
- info.split.num_pmcs = ebx.split.num_df_pmc;
- }
+ if (leaf && pmu_version >= 2)
+ info.split.num_pmcs = leaf->n_pmc_northbridge;
*per_cpu_ptr(uncore->info, cpu) = info;
}
@@ -990,16 +988,14 @@ static void amd_uncore_umc_read(struct perf_event *event)
static
void amd_uncore_umc_ctx_scan(struct amd_uncore *uncore, unsigned int cpu)
{
- union cpuid_0x80000022_ebx ebx;
+ const struct leaf_0x80000022_0 *leaf = cpuid_leaf(&cpu_data(cpu), 0x80000022);
union amd_uncore_info info;
- unsigned int eax, ecx, edx;
- if (pmu_version < 2)
+ if (!leaf || pmu_version < 2)
return;
- cpuid(EXT_PERFMON_DEBUG_FEATURES, &eax, &ebx.full, &ecx, &edx);
- info.split.aux_data = ecx; /* stash active mask */
- info.split.num_pmcs = ebx.split.num_umc_pmc;
+ info.split.aux_data = leaf->active_umc_bitmask;
+ info.split.num_pmcs = leaf->n_pmc_umc;
info.split.gid = topology_logical_package_id(cpu);
info.split.cid = topology_logical_package_id(cpu);
*per_cpu_ptr(uncore->info, cpu) = info;
--
2.53.0
^ permalink raw reply related [flat|nested] 101+ messages in thread
* [PATCH v6 69/90] KVM: x86: Use standard CPUID(0x80000022) types
2026-03-27 2:15 [PATCH v6 00/90] x86: Introduce a centralized CPUID data model Ahmed S. Darwish
` (67 preceding siblings ...)
2026-03-27 2:16 ` [PATCH v6 68/90] perf/x86/amd: " Ahmed S. Darwish
@ 2026-03-27 2:16 ` Ahmed S. Darwish
2026-03-27 2:16 ` [PATCH v6 70/90] perf/x86: Remove custom " Ahmed S. Darwish
` (22 subsequent siblings)
91 siblings, 0 replies; 101+ messages in thread
From: Ahmed S. Darwish @ 2026-03-27 2:16 UTC (permalink / raw)
To: Borislav Petkov, Dave Hansen, Ingo Molnar
Cc: Thomas Gleixner, Andrew Cooper, H. Peter Anvin,
Sean Christopherson, David Woodhouse, Peter Zijlstra,
Christian Ludloff, Sohil Mehta, John Ogness, x86, x86-cpuid, LKML,
Ahmed S. Darwish
Use standard CPUID(0x80000022) types from x86-cpuid-db instead of relying
on custom perf types.
The latter are in process of getting removed from the kernel.
Signed-off-by: Ahmed S. Darwish <darwi@linutronix.de>
---
arch/x86/kvm/cpuid.c | 7 ++++---
arch/x86/kvm/svm/pmu.c | 7 ++++---
2 files changed, 8 insertions(+), 6 deletions(-)
diff --git a/arch/x86/kvm/cpuid.c b/arch/x86/kvm/cpuid.c
index 16ed4c001c79..ca769e390e62 100644
--- a/arch/x86/kvm/cpuid.c
+++ b/arch/x86/kvm/cpuid.c
@@ -1870,7 +1870,8 @@ static inline int __do_cpuid_func(struct kvm_cpuid_array *array, u32 function)
break;
/* AMD Extended Performance Monitoring and Debug */
case 0x80000022: {
- union cpuid_0x80000022_ebx ebx = { };
+ struct leaf_0x80000022_0 leaf = { };
+ struct cpuid_regs *regs = (struct cpuid_regs *)&leaf;
entry->ecx = entry->edx = 0;
if (!enable_pmu || !kvm_cpu_cap_has(X86_FEATURE_PERFMON_V2)) {
@@ -1880,8 +1881,8 @@ static inline int __do_cpuid_func(struct kvm_cpuid_array *array, u32 function)
cpuid_entry_override(entry, CPUID_8000_0022_EAX);
- ebx.split.num_core_pmc = kvm_pmu_cap.num_counters_gp;
- entry->ebx = ebx.full;
+ leaf.n_pmc_core = kvm_pmu_cap.num_counters_gp;
+ entry->ebx = regs->ebx;
break;
}
/*Add support for Centaur's CPUID instruction*/
diff --git a/arch/x86/kvm/svm/pmu.c b/arch/x86/kvm/svm/pmu.c
index 7aa298eeb072..7c89b330fb73 100644
--- a/arch/x86/kvm/svm/pmu.c
+++ b/arch/x86/kvm/svm/pmu.c
@@ -179,7 +179,8 @@ static int amd_pmu_set_msr(struct kvm_vcpu *vcpu, struct msr_data *msr_info)
static void amd_pmu_refresh(struct kvm_vcpu *vcpu)
{
struct kvm_pmu *pmu = vcpu_to_pmu(vcpu);
- union cpuid_0x80000022_ebx ebx;
+ struct leaf_0x80000022_0 leaf = { };
+ struct cpuid_regs *regs = (struct cpuid_regs *)&leaf;
pmu->version = 1;
if (guest_cpu_cap_has(vcpu, X86_FEATURE_PERFMON_V2)) {
@@ -190,8 +191,8 @@ static void amd_pmu_refresh(struct kvm_vcpu *vcpu)
*/
BUILD_BUG_ON(x86_feature_cpuid(X86_FEATURE_PERFMON_V2).function != 0x80000022 ||
x86_feature_cpuid(X86_FEATURE_PERFMON_V2).index);
- ebx.full = kvm_find_cpuid_entry_index(vcpu, 0x80000022, 0)->ebx;
- pmu->nr_arch_gp_counters = ebx.split.num_core_pmc;
+ regs->ebx = kvm_find_cpuid_entry_index(vcpu, 0x80000022, 0)->ebx;
+ pmu->nr_arch_gp_counters = leaf.n_pmc_core;
} else if (guest_cpu_cap_has(vcpu, X86_FEATURE_PERFCTR_CORE)) {
pmu->nr_arch_gp_counters = AMD64_NUM_COUNTERS_CORE;
} else {
--
2.53.0
^ permalink raw reply related [flat|nested] 101+ messages in thread
* [PATCH v6 70/90] perf/x86: Remove custom CPUID(0x80000022) types
2026-03-27 2:15 [PATCH v6 00/90] x86: Introduce a centralized CPUID data model Ahmed S. Darwish
` (68 preceding siblings ...)
2026-03-27 2:16 ` [PATCH v6 69/90] KVM: x86: Use standard CPUID(0x80000022) types Ahmed S. Darwish
@ 2026-03-27 2:16 ` Ahmed S. Darwish
2026-03-27 2:16 ` [PATCH v6 71/90] x86/cpuid: Parse CPUID(0x80000007) Ahmed S. Darwish
` (21 subsequent siblings)
91 siblings, 0 replies; 101+ messages in thread
From: Ahmed S. Darwish @ 2026-03-27 2:16 UTC (permalink / raw)
To: Borislav Petkov, Dave Hansen, Ingo Molnar
Cc: Thomas Gleixner, Andrew Cooper, H. Peter Anvin,
Sean Christopherson, David Woodhouse, Peter Zijlstra,
Christian Ludloff, Sohil Mehta, John Ogness, x86, x86-cpuid, LKML,
Ahmed S. Darwish
All CPUID(0x80000022) call sites have been converted to the CPUID API and
its auto generated x86-cpuid-db data types.
Remove the custom CPUID(0x80000022) types from perf.
Signed-off-by: Ahmed S. Darwish <darwi@linutronix.de>
---
arch/x86/include/asm/perf_event.h | 23 -----------------------
1 file changed, 23 deletions(-)
diff --git a/arch/x86/include/asm/perf_event.h b/arch/x86/include/asm/perf_event.h
index 5aa07710af12..e90c79424c70 100644
--- a/arch/x86/include/asm/perf_event.h
+++ b/arch/x86/include/asm/perf_event.h
@@ -161,24 +161,6 @@
#define ARCH_PERFMON_PEBS_CAP_LEAF 0x4
#define ARCH_PERFMON_PEBS_COUNTER_LEAF 0x5
-/*
- * AMD "Extended Performance Monitoring and Debug" CPUID
- * detection/enumeration details:
- */
-union cpuid_0x80000022_ebx {
- struct {
- /* Number of Core Performance Counters */
- unsigned int num_core_pmc:4;
- /* Number of available LBR Stack Entries */
- unsigned int lbr_v2_stack_sz:6;
- /* Number of Data Fabric Counters */
- unsigned int num_df_pmc:6;
- /* Number of Unified Memory Controller Counters */
- unsigned int num_umc_pmc:6;
- } split;
- unsigned int full;
-};
-
struct x86_pmu_capability {
int version;
int num_counters_gp;
@@ -498,11 +480,6 @@ struct arch_pebs_cntr_header {
u32 reserved;
};
-/*
- * AMD Extended Performance Monitoring and Debug cpuid feature detection
- */
-#define EXT_PERFMON_DEBUG_FEATURES 0x80000022
-
/*
* IBS cpuid feature detection
*/
--
2.53.0
^ permalink raw reply related [flat|nested] 101+ messages in thread
* [PATCH v6 71/90] x86/cpuid: Parse CPUID(0x80000007)
2026-03-27 2:15 [PATCH v6 00/90] x86: Introduce a centralized CPUID data model Ahmed S. Darwish
` (69 preceding siblings ...)
2026-03-27 2:16 ` [PATCH v6 70/90] perf/x86: Remove custom " Ahmed S. Darwish
@ 2026-03-27 2:16 ` Ahmed S. Darwish
2026-03-27 2:16 ` [PATCH v6 72/90] x86/cpu: Use parsed CPUID(0x80000007) Ahmed S. Darwish
` (20 subsequent siblings)
91 siblings, 0 replies; 101+ messages in thread
From: Ahmed S. Darwish @ 2026-03-27 2:16 UTC (permalink / raw)
To: Borislav Petkov, Dave Hansen, Ingo Molnar
Cc: Thomas Gleixner, Andrew Cooper, H. Peter Anvin,
Sean Christopherson, David Woodhouse, Peter Zijlstra,
Christian Ludloff, Sohil Mehta, John Ogness, x86, x86-cpuid, LKML,
Ahmed S. Darwish
Parse CPUID(0x80000007).
This allows the cpuinfo_x86::x86_power call sites to be converted to the
CPUID APIs next.
Signed-off-by: Ahmed S. Darwish <darwi@linutronix.de>
---
arch/x86/include/asm/cpuid/types.h | 1 +
arch/x86/kernel/cpu/cpuid_parser.h | 1 +
2 files changed, 2 insertions(+)
diff --git a/arch/x86/include/asm/cpuid/types.h b/arch/x86/include/asm/cpuid/types.h
index deddb534486a..6180acd35f59 100644
--- a/arch/x86/include/asm/cpuid/types.h
+++ b/arch/x86/include/asm/cpuid/types.h
@@ -227,6 +227,7 @@ struct cpuid_leaves {
CPUID_LEAF ( 0x80000004, 0 );
CPUID_LEAF ( 0x80000005, 0 );
CPUID_LEAF ( 0x80000006, 0 );
+ CPUID_LEAF ( 0x80000007, 0 );
CPUID_LEAF ( 0x80000008, 0 );
CPUID_LEAF_N ( 0x8000001d, 8 );
CPUID_LEAF ( 0x80000022, 0 );
diff --git a/arch/x86/kernel/cpu/cpuid_parser.h b/arch/x86/kernel/cpu/cpuid_parser.h
index 59a4d562320a..c81f76c1c077 100644
--- a/arch/x86/kernel/cpu/cpuid_parser.h
+++ b/arch/x86/kernel/cpu/cpuid_parser.h
@@ -161,6 +161,7 @@ struct cpuid_parse_entry {
CPUID_PARSE_ENTRY ( 0x80000004, 0, generic ), \
CPUID_PARSE_ENTRY ( 0x80000005, 0, generic ), \
CPUID_PARSE_ENTRY ( 0x80000006, 0, generic ), \
+ CPUID_PARSE_ENTRY ( 0x80000007, 0, generic ), \
CPUID_PARSE_ENTRY ( 0x80000008, 0, generic ), \
CPUID_PARSE_ENTRY_N ( 0x8000001d, deterministic_cache ), \
CPUID_PARSE_ENTRY ( 0x80000022, 0, generic ), \
--
2.53.0
^ permalink raw reply related [flat|nested] 101+ messages in thread
* [PATCH v6 72/90] x86/cpu: Use parsed CPUID(0x80000007)
2026-03-27 2:15 [PATCH v6 00/90] x86: Introduce a centralized CPUID data model Ahmed S. Darwish
` (70 preceding siblings ...)
2026-03-27 2:16 ` [PATCH v6 71/90] x86/cpuid: Parse CPUID(0x80000007) Ahmed S. Darwish
@ 2026-03-27 2:16 ` Ahmed S. Darwish
2026-03-27 2:16 ` [PATCH v6 73/90] x86/cpu: amd/hygon: " Ahmed S. Darwish
` (19 subsequent siblings)
91 siblings, 0 replies; 101+ messages in thread
From: Ahmed S. Darwish @ 2026-03-27 2:16 UTC (permalink / raw)
To: Borislav Petkov, Dave Hansen, Ingo Molnar
Cc: Thomas Gleixner, Andrew Cooper, H. Peter Anvin,
Sean Christopherson, David Woodhouse, Peter Zijlstra,
Christian Ludloff, Sohil Mehta, John Ogness, x86, x86-cpuid, LKML,
Ahmed S. Darwish
For Intel, Centar, and Zhaoxin early init, use parsed CPUID(0x80000007)
instead of doing ugly bitwise operations on cpuinfo_x86::x86_power.
The latter is backed by a direct CPUID query and will be later removed.
Signed-off-by: Ahmed S. Darwish <darwi@linutronix.de>
---
arch/x86/kernel/cpu/centaur.c | 4 +++-
arch/x86/kernel/cpu/intel.c | 13 +++++++------
arch/x86/kernel/cpu/zhaoxin.c | 4 +++-
3 files changed, 13 insertions(+), 8 deletions(-)
diff --git a/arch/x86/kernel/cpu/centaur.c b/arch/x86/kernel/cpu/centaur.c
index 86cbe4427453..29688aec2231 100644
--- a/arch/x86/kernel/cpu/centaur.c
+++ b/arch/x86/kernel/cpu/centaur.c
@@ -89,6 +89,8 @@ enum {
static void early_init_centaur(struct cpuinfo_x86 *c)
{
+ const struct leaf_0x80000007_0 *el7 = cpuid_leaf(c, 0x80000007);
+
#ifdef CONFIG_X86_32
/* Emulate MTRRs using Centaur's MCR. */
if (c->x86 == 5)
@@ -98,7 +100,7 @@ static void early_init_centaur(struct cpuinfo_x86 *c)
(c->x86 >= 7))
set_cpu_cap(c, X86_FEATURE_CONSTANT_TSC);
- if (c->x86_power & (1 << 8)) {
+ if (el7 && el7->constant_tsc) {
set_cpu_cap(c, X86_FEATURE_CONSTANT_TSC);
set_cpu_cap(c, X86_FEATURE_NONSTOP_TSC);
}
diff --git a/arch/x86/kernel/cpu/intel.c b/arch/x86/kernel/cpu/intel.c
index 7f186c68d701..e84042d1bbca 100644
--- a/arch/x86/kernel/cpu/intel.c
+++ b/arch/x86/kernel/cpu/intel.c
@@ -215,6 +215,7 @@ void intel_unlock_cpuid_leafs(struct cpuinfo_x86 *c)
static void early_init_intel(struct cpuinfo_x86 *c)
{
+ const struct leaf_0x80000007_0 *el7 = cpuid_leaf(c, 0x80000007);
u64 misc_enable;
if (c->x86 >= 6 && !cpu_has(c, X86_FEATURE_IA64))
@@ -262,16 +263,16 @@ static void early_init_intel(struct cpuinfo_x86 *c)
c->x86_phys_bits = 36;
/*
- * c->x86_power is 8000_0007 edx. Bit 8 is TSC runs at constant rate
- * with P/T states and does not stop in deep C-states.
+ * CPUID(0x80000007).constant_tsc implies that TSC runs at constant
+ * rate with P/T states and does not stop in deep C-states
*
- * It is also reliable across cores and sockets. (but not across
- * cabinets - we turn it off in that case explicitly.)
+ * It is also reliable across cores and sockets, but not across
+ * cabinets; disable it explicitly in that case.
*
* Use a model-specific check for some older CPUs that have invariant
- * TSC but may not report it architecturally via 8000_0007.
+ * TSC but may not report it architecturally via CPUID(0x80000007).
*/
- if (c->x86_power & (1 << 8)) {
+ if (el7 && el7->constant_tsc) {
set_cpu_cap(c, X86_FEATURE_CONSTANT_TSC);
set_cpu_cap(c, X86_FEATURE_NONSTOP_TSC);
} else if ((c->x86_vfm >= INTEL_P4_PRESCOTT && c->x86_vfm <= INTEL_P4_CEDARMILL) ||
diff --git a/arch/x86/kernel/cpu/zhaoxin.c b/arch/x86/kernel/cpu/zhaoxin.c
index b068922efed9..5918f9387c87 100644
--- a/arch/x86/kernel/cpu/zhaoxin.c
+++ b/arch/x86/kernel/cpu/zhaoxin.c
@@ -50,10 +50,12 @@ static void init_zhaoxin_cap(struct cpuinfo_x86 *c)
static void early_init_zhaoxin(struct cpuinfo_x86 *c)
{
+ const struct leaf_0x80000007_0 *el7 = cpuid_leaf(c, 0x80000007);
+
if (c->x86 >= 0x6)
set_cpu_cap(c, X86_FEATURE_CONSTANT_TSC);
- if (c->x86_power & (1 << 8)) {
+ if (el7 && el7->constant_tsc) {
set_cpu_cap(c, X86_FEATURE_CONSTANT_TSC);
set_cpu_cap(c, X86_FEATURE_NONSTOP_TSC);
}
--
2.53.0
^ permalink raw reply related [flat|nested] 101+ messages in thread
* [PATCH v6 73/90] x86/cpu: amd/hygon: Use parsed CPUID(0x80000007)
2026-03-27 2:15 [PATCH v6 00/90] x86: Introduce a centralized CPUID data model Ahmed S. Darwish
` (71 preceding siblings ...)
2026-03-27 2:16 ` [PATCH v6 72/90] x86/cpu: Use parsed CPUID(0x80000007) Ahmed S. Darwish
@ 2026-03-27 2:16 ` Ahmed S. Darwish
2026-03-27 2:16 ` [PATCH v6 74/90] x86/cpu: cpuinfo: " Ahmed S. Darwish
` (18 subsequent siblings)
91 siblings, 0 replies; 101+ messages in thread
From: Ahmed S. Darwish @ 2026-03-27 2:16 UTC (permalink / raw)
To: Borislav Petkov, Dave Hansen, Ingo Molnar
Cc: Thomas Gleixner, Andrew Cooper, H. Peter Anvin,
Sean Christopherson, David Woodhouse, Peter Zijlstra,
Christian Ludloff, Sohil Mehta, John Ogness, x86, x86-cpuid, LKML,
Ahmed S. Darwish
Use parsed CPUID(0x80000007) instead of doing ugly bitwise operations on
cpuinfo_x86::x86_power. The latter is backed by a direct CPUID query and
will be later removed.
Signed-off-by: Ahmed S. Darwish <darwi@linutronix.de>
---
arch/x86/kernel/cpu/amd.c | 25 +++++++++++--------------
arch/x86/kernel/cpu/hygon.c | 25 +++++++++++--------------
2 files changed, 22 insertions(+), 28 deletions(-)
diff --git a/arch/x86/kernel/cpu/amd.c b/arch/x86/kernel/cpu/amd.c
index 5fd7f34fa284..96b67b8b694c 100644
--- a/arch/x86/kernel/cpu/amd.c
+++ b/arch/x86/kernel/cpu/amd.c
@@ -611,6 +611,7 @@ static void early_detect_mem_encrypt(struct cpuinfo_x86 *c)
static void early_init_amd(struct cpuinfo_x86 *c)
{
+ const struct leaf_0x80000007_0 *el7 = cpuid_leaf(c, 0x80000007);
u32 dummy;
if (c->x86 >= 0xf)
@@ -618,22 +619,18 @@ static void early_init_amd(struct cpuinfo_x86 *c)
rdmsr_safe(MSR_AMD64_PATCH_LEVEL, &c->microcode, &dummy);
- /*
- * c->x86_power is 8000_0007 edx. Bit 8 is TSC runs at constant rate
- * with P/T states and does not stop in deep C-states
- */
- if (c->x86_power & (1 << 8)) {
- set_cpu_cap(c, X86_FEATURE_CONSTANT_TSC);
- set_cpu_cap(c, X86_FEATURE_NONSTOP_TSC);
- }
+ if (el7) {
+ if (el7->constant_tsc) {
+ set_cpu_cap(c, X86_FEATURE_CONSTANT_TSC);
+ set_cpu_cap(c, X86_FEATURE_NONSTOP_TSC);
+ }
- /* Bit 12 of 8000_0007 edx is accumulated power mechanism. */
- if (c->x86_power & BIT(12))
- set_cpu_cap(c, X86_FEATURE_ACC_POWER);
+ if (el7->proc_power_reporting)
+ set_cpu_cap(c, X86_FEATURE_ACC_POWER);
- /* Bit 14 indicates the Runtime Average Power Limit interface. */
- if (c->x86_power & BIT(14))
- set_cpu_cap(c, X86_FEATURE_RAPL);
+ if (el7->rapl_interface)
+ set_cpu_cap(c, X86_FEATURE_RAPL);
+ }
#ifdef CONFIG_X86_64
set_cpu_cap(c, X86_FEATURE_SYSCALL32);
diff --git a/arch/x86/kernel/cpu/hygon.c b/arch/x86/kernel/cpu/hygon.c
index 4a63538c2b3f..8f31005bc802 100644
--- a/arch/x86/kernel/cpu/hygon.c
+++ b/arch/x86/kernel/cpu/hygon.c
@@ -125,28 +125,25 @@ static void bsp_init_hygon(struct cpuinfo_x86 *c)
static void early_init_hygon(struct cpuinfo_x86 *c)
{
+ const struct leaf_0x80000007_0 *el7 = cpuid_leaf(c, 0x80000007);
u32 dummy;
set_cpu_cap(c, X86_FEATURE_K8);
rdmsr_safe(MSR_AMD64_PATCH_LEVEL, &c->microcode, &dummy);
- /*
- * c->x86_power is 8000_0007 edx. Bit 8 is TSC runs at constant rate
- * with P/T states and does not stop in deep C-states
- */
- if (c->x86_power & (1 << 8)) {
- set_cpu_cap(c, X86_FEATURE_CONSTANT_TSC);
- set_cpu_cap(c, X86_FEATURE_NONSTOP_TSC);
- }
+ if (el7) {
+ if (el7->constant_tsc) {
+ set_cpu_cap(c, X86_FEATURE_CONSTANT_TSC);
+ set_cpu_cap(c, X86_FEATURE_NONSTOP_TSC);
+ }
- /* Bit 12 of 8000_0007 edx is accumulated power mechanism. */
- if (c->x86_power & BIT(12))
- set_cpu_cap(c, X86_FEATURE_ACC_POWER);
+ if (el7->proc_power_reporting)
+ set_cpu_cap(c, X86_FEATURE_ACC_POWER);
- /* Bit 14 indicates the Runtime Average Power Limit interface. */
- if (c->x86_power & BIT(14))
- set_cpu_cap(c, X86_FEATURE_RAPL);
+ if (el7->rapl_interface)
+ set_cpu_cap(c, X86_FEATURE_RAPL);
+ }
#ifdef CONFIG_X86_64
set_cpu_cap(c, X86_FEATURE_SYSCALL32);
--
2.53.0
^ permalink raw reply related [flat|nested] 101+ messages in thread
* [PATCH v6 74/90] x86/cpu: cpuinfo: Use parsed CPUID(0x80000007)
2026-03-27 2:15 [PATCH v6 00/90] x86: Introduce a centralized CPUID data model Ahmed S. Darwish
` (72 preceding siblings ...)
2026-03-27 2:16 ` [PATCH v6 73/90] x86/cpu: amd/hygon: " Ahmed S. Darwish
@ 2026-03-27 2:16 ` Ahmed S. Darwish
2026-03-27 2:16 ` [PATCH v6 75/90] KVM: x86: " Ahmed S. Darwish
` (17 subsequent siblings)
91 siblings, 0 replies; 101+ messages in thread
From: Ahmed S. Darwish @ 2026-03-27 2:16 UTC (permalink / raw)
To: Borislav Petkov, Dave Hansen, Ingo Molnar
Cc: Thomas Gleixner, Andrew Cooper, H. Peter Anvin,
Sean Christopherson, David Woodhouse, Peter Zijlstra,
Christian Ludloff, Sohil Mehta, John Ogness, x86, x86-cpuid, LKML,
Ahmed S. Darwish
For /proc/cpuinfo "power management" line, use parsed CPUID(0x80000007)
instead of poking at cpuinfo_x86::x86_power. The latter is backed by a
direct CPUID query and will be later removed.
Remove the x86_power_flags[] strings table as it has no more users.
Signed-off-by: Ahmed S. Darwish <darwi@linutronix.de>
---
arch/x86/include/asm/cpufeature.h | 1 -
arch/x86/kernel/cpu/Makefile | 2 +-
arch/x86/kernel/cpu/powerflags.c | 24 ------------
arch/x86/kernel/cpu/proc.c | 61 ++++++++++++++++++++++++-------
4 files changed, 49 insertions(+), 39 deletions(-)
delete mode 100644 arch/x86/kernel/cpu/powerflags.c
diff --git a/arch/x86/include/asm/cpufeature.h b/arch/x86/include/asm/cpufeature.h
index 3ddc1d33399b..520949560138 100644
--- a/arch/x86/include/asm/cpufeature.h
+++ b/arch/x86/include/asm/cpufeature.h
@@ -39,7 +39,6 @@ enum cpuid_leafs
};
extern const char * const x86_cap_flags[NCAPINTS*32];
-extern const char * const x86_power_flags[32];
/*
* In order to save room, we index into this array by doing
diff --git a/arch/x86/kernel/cpu/Makefile b/arch/x86/kernel/cpu/Makefile
index d62e2d60a965..5c091d9fc9ee 100644
--- a/arch/x86/kernel/cpu/Makefile
+++ b/arch/x86/kernel/cpu/Makefile
@@ -27,7 +27,7 @@ obj-y += bugs.o
obj-y += aperfmperf.o
obj-y += cpuid-deps.o cpuid_0x2_table.o
obj-y += umwait.o
-obj-y += capflags.o powerflags.o
+obj-y += capflags.o
obj-$(CONFIG_X86_LOCAL_APIC) += topology.o
diff --git a/arch/x86/kernel/cpu/powerflags.c b/arch/x86/kernel/cpu/powerflags.c
deleted file mode 100644
index fd6ec2aa0303..000000000000
--- a/arch/x86/kernel/cpu/powerflags.c
+++ /dev/null
@@ -1,24 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * Strings for the various x86 power flags
- *
- * This file must not contain any executable code.
- */
-
-#include <asm/cpufeature.h>
-
-const char *const x86_power_flags[32] = {
- "ts", /* temperature sensor */
- "fid", /* frequency id control */
- "vid", /* voltage id control */
- "ttp", /* thermal trip */
- "tm", /* hardware thermal control */
- "stc", /* software thermal control */
- "100mhzsteps", /* 100 MHz multiplier control */
- "hwpstate", /* hardware P-state control */
- "", /* tsc invariant mapped to constant_tsc */
- "cpb", /* core performance boost */
- "eff_freq_ro", /* Readonly aperf/mperf */
- "proc_feedback", /* processor feedback interface */
- "acc_power", /* accumulated power mechanism */
-};
diff --git a/arch/x86/kernel/cpu/proc.c b/arch/x86/kernel/cpu/proc.c
index 6571d432cbe3..89471bcfcc32 100644
--- a/arch/x86/kernel/cpu/proc.c
+++ b/arch/x86/kernel/cpu/proc.c
@@ -4,9 +4,11 @@
#include <linux/string.h>
#include <linux/seq_file.h>
#include <linux/cpufreq.h>
-#include <asm/prctl.h>
#include <linux/proc_fs.h>
+#include <asm/cpuid/api.h>
+#include <asm/prctl.h>
+
#include "cpu.h"
#ifdef CONFIG_X86_VMX_FEATURE_NAMES
@@ -60,6 +62,50 @@ static void show_cpuinfo_misc(struct seq_file *m, struct cpuinfo_x86 *c)
}
#endif
+static void show_cpuinfo_power(struct cpuinfo_x86 *c, struct seq_file *m)
+{
+ const struct cpuid_regs *el7_regs = cpuid_leaf_raw(c, 0x80000007);
+ const struct leaf_0x80000007_0 *el7 = cpuid_leaf(c, 0x80000007);
+
+ seq_puts(m, "power management:");
+
+ if (!el7_regs || !el7)
+ return;
+
+ if (el7->digital_temp)
+ seq_puts(m, " ts");
+ if (el7->powernow_freq_id)
+ seq_puts(m, " fid");
+ if (el7->powernow_volt_id)
+ seq_puts(m, " vid");
+ if (el7->thermal_trip)
+ seq_puts(m, " ttp");
+ if (el7->hw_thermal_control)
+ seq_puts(m, " tm");
+ if (el7->sw_thermal_control)
+ seq_puts(m, " stc");
+ if (el7->_100mhz_steps)
+ seq_puts(m, " 100mhzsteps");
+ if (el7->hw_pstate)
+ seq_puts(m, " hwpstate");
+
+ /* Keep constant_tsc off the power management line */
+
+ if (el7->core_perf_boost)
+ seq_puts(m, " cpb");
+ if (el7->eff_freq_ro)
+ seq_puts(m, " eff_freq_ro");
+ if (el7->proc_feedback)
+ seq_puts(m, " proc_feedback");
+ if (el7->proc_power_reporting)
+ seq_puts(m, " acc_power");
+
+ /* Afterwards, just output the offsets of set bits */
+ for (int i = 13; i < 32; i++)
+ if (el7_regs->edx & BIT(i))
+ seq_printf(m, " [%d]", i);
+}
+
static int show_cpuinfo(struct seq_file *m, void *v)
{
struct cpuinfo_x86 *c = v;
@@ -138,18 +184,7 @@ static int show_cpuinfo(struct seq_file *m, void *v)
seq_printf(m, "address sizes\t: %u bits physical, %u bits virtual\n",
c->x86_phys_bits, c->x86_virt_bits);
- seq_puts(m, "power management:");
- for (i = 0; i < 32; i++) {
- if (c->x86_power & (1 << i)) {
- if (i < ARRAY_SIZE(x86_power_flags) &&
- x86_power_flags[i])
- seq_printf(m, "%s%s",
- x86_power_flags[i][0] ? " " : "",
- x86_power_flags[i]);
- else
- seq_printf(m, " [%d]", i);
- }
- }
+ show_cpuinfo_power(c, m);
seq_puts(m, "\n\n");
--
2.53.0
^ permalink raw reply related [flat|nested] 101+ messages in thread
* [PATCH v6 75/90] KVM: x86: Use parsed CPUID(0x80000007)
2026-03-27 2:15 [PATCH v6 00/90] x86: Introduce a centralized CPUID data model Ahmed S. Darwish
` (73 preceding siblings ...)
2026-03-27 2:16 ` [PATCH v6 74/90] x86/cpu: cpuinfo: " Ahmed S. Darwish
@ 2026-03-27 2:16 ` Ahmed S. Darwish
2026-03-27 2:16 ` [PATCH v6 76/90] x86/microcode: Allocate cpuinfo_x86 snapshots on the heap Ahmed S. Darwish
` (16 subsequent siblings)
91 siblings, 0 replies; 101+ messages in thread
From: Ahmed S. Darwish @ 2026-03-27 2:16 UTC (permalink / raw)
To: Borislav Petkov, Dave Hansen, Ingo Molnar
Cc: Thomas Gleixner, Andrew Cooper, H. Peter Anvin,
Sean Christopherson, David Woodhouse, Peter Zijlstra,
Christian Ludloff, Sohil Mehta, John Ogness, x86, x86-cpuid, LKML,
Ahmed S. Darwish
For KVM cpuid, use parsed CPUID(0x80000007) instead of poking at x86_power.
The latter is backed by a direct CPUID query and will be removed later.
Signed-off-by: Ahmed S. Darwish <darwi@linutronix.de>
---
arch/x86/kvm/cpuid.c | 11 ++++++++---
1 file changed, 8 insertions(+), 3 deletions(-)
diff --git a/arch/x86/kvm/cpuid.c b/arch/x86/kvm/cpuid.c
index ca769e390e62..efc155e1da10 100644
--- a/arch/x86/kvm/cpuid.c
+++ b/arch/x86/kvm/cpuid.c
@@ -1763,13 +1763,18 @@ static inline int __do_cpuid_func(struct kvm_cpuid_array *array, u32 function)
/* Drop reserved bits, pass host L2 cache and TLB info. */
entry->edx &= ~GENMASK(17, 16);
break;
- case 0x80000007: /* Advanced power management */
+ case 0x80000007: { /* Advanced power management */
+ const struct cpuid_regs *el7 = cpuid_leaf_raw(&boot_cpu_data, 0x80000007);
+
cpuid_entry_override(entry, CPUID_8000_0007_EDX);
- /* mask against host */
- entry->edx &= boot_cpu_data.x86_power;
+ /* Mask against host */
+ if (el7)
+ entry->edx &= el7->edx;
+
entry->eax = entry->ebx = entry->ecx = 0;
break;
+ }
case 0x80000008: {
/*
* GuestPhysAddrSize (EAX[23:16]) is intended for software
--
2.53.0
^ permalink raw reply related [flat|nested] 101+ messages in thread
* [PATCH v6 76/90] x86/microcode: Allocate cpuinfo_x86 snapshots on the heap
2026-03-27 2:15 [PATCH v6 00/90] x86: Introduce a centralized CPUID data model Ahmed S. Darwish
` (74 preceding siblings ...)
2026-03-27 2:16 ` [PATCH v6 75/90] KVM: x86: " Ahmed S. Darwish
@ 2026-03-27 2:16 ` Ahmed S. Darwish
2026-03-27 2:16 ` [PATCH v6 77/90] x86/cpuid: Parse leaves backing X86_FEATURE words Ahmed S. Darwish
` (15 subsequent siblings)
91 siblings, 0 replies; 101+ messages in thread
From: Ahmed S. Darwish @ 2026-03-27 2:16 UTC (permalink / raw)
To: Borislav Petkov, Dave Hansen, Ingo Molnar
Cc: Thomas Gleixner, Andrew Cooper, H. Peter Anvin,
Sean Christopherson, David Woodhouse, Peter Zijlstra,
Christian Ludloff, Sohil Mehta, John Ogness, x86, x86-cpuid, LKML,
Ahmed S. Darwish
load_late_stop_cpus() snapshots CPU capabilities before a late microcode
update, while microcode_check() snapshots the capabilities again after the
update.
Both functions allocate their struct cpuinfo_x86 snapshots on the stack.
Meanwhile, cpuinfo_x86 contains the parsed CPUID tables where more leaves
will be added; resulting in "stack frame length exceeded" warnings.
Allocate the before/after cpuinfo_x86 snapshots on the heap.
For load_late_stop_cpus(), do the memory allocation before the microcode
staging step. This leaves no leaked or stale microcode state in -ENOMEM
failure modes.
Signed-off-by: Ahmed S. Darwish <darwi@linutronix.de>
---
arch/x86/kernel/cpu/common.c | 11 ++++++++---
arch/x86/kernel/cpu/microcode/core.c | 9 ++++++---
2 files changed, 14 insertions(+), 6 deletions(-)
diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c
index 2beb53f6bed7..ece5a59124f5 100644
--- a/arch/x86/kernel/cpu/common.c
+++ b/arch/x86/kernel/cpu/common.c
@@ -2543,15 +2543,20 @@ void store_cpu_caps(struct cpuinfo_x86 *curr_info)
*/
void microcode_check(struct cpuinfo_x86 *prev_info)
{
- struct cpuinfo_x86 curr_info;
+ struct cpuinfo_x86 *curr_info __free(kfree) = kmalloc_obj(*curr_info);
perf_check_microcode();
amd_check_microcode();
- store_cpu_caps(&curr_info);
+ if (!curr_info) {
+ pr_warn("x86/CPU: Microcode update CPU capability changes check was skipped (ENOMEM)\n");
+ return;
+ }
+
+ store_cpu_caps(curr_info);
- if (!memcmp(&prev_info->x86_capability, &curr_info.x86_capability,
+ if (!memcmp(&prev_info->x86_capability, &curr_info->x86_capability,
sizeof(prev_info->x86_capability)))
return;
diff --git a/arch/x86/kernel/cpu/microcode/core.c b/arch/x86/kernel/cpu/microcode/core.c
index 56d791aeac4e..7a00671540bc 100644
--- a/arch/x86/kernel/cpu/microcode/core.c
+++ b/arch/x86/kernel/cpu/microcode/core.c
@@ -588,16 +588,19 @@ static int load_cpus_stopped(void *unused)
static int load_late_stop_cpus(bool is_safe)
{
+ struct cpuinfo_x86 *prev_info __free(kfree) = kmalloc_obj(*prev_info);
unsigned int cpu, updated = 0, failed = 0, timedout = 0, siblings = 0;
unsigned int nr_offl, offline = 0;
int old_rev = boot_cpu_data.microcode;
- struct cpuinfo_x86 prev_info;
if (!is_safe) {
pr_err("Late microcode loading without minimal revision check.\n");
pr_err("You should switch to early loading, if possible.\n");
}
+ if (!prev_info)
+ return -ENOMEM;
+
/*
* Pre-load the microcode image into a staging device. This
* process is preemptible and does not require stopping CPUs.
@@ -617,7 +620,7 @@ static int load_late_stop_cpus(bool is_safe)
* Take a snapshot before the microcode update in order to compare and
* check whether any bits changed after an update.
*/
- store_cpu_caps(&prev_info);
+ store_cpu_caps(prev_info);
if (microcode_ops->use_nmi)
static_branch_enable_cpuslocked(µcode_nmi_handler_enable);
@@ -666,7 +669,7 @@ static int load_late_stop_cpus(bool is_safe)
num_online_cpus() - (updated + siblings));
}
pr_info("revision: 0x%x -> 0x%x\n", old_rev, boot_cpu_data.microcode);
- microcode_check(&prev_info);
+ microcode_check(prev_info);
return updated + siblings == num_online_cpus() ? 0 : -EIO;
}
--
2.53.0
^ permalink raw reply related [flat|nested] 101+ messages in thread
* [PATCH v6 77/90] x86/cpuid: Parse leaves backing X86_FEATURE words
2026-03-27 2:15 [PATCH v6 00/90] x86: Introduce a centralized CPUID data model Ahmed S. Darwish
` (75 preceding siblings ...)
2026-03-27 2:16 ` [PATCH v6 76/90] x86/microcode: Allocate cpuinfo_x86 snapshots on the heap Ahmed S. Darwish
@ 2026-03-27 2:16 ` Ahmed S. Darwish
2026-03-27 2:16 ` [PATCH v6 78/90] x86/cpuid: Parse Linux synthetic CPUID leaves Ahmed S. Darwish
` (14 subsequent siblings)
91 siblings, 0 replies; 101+ messages in thread
From: Ahmed S. Darwish @ 2026-03-27 2:16 UTC (permalink / raw)
To: Borislav Petkov, Dave Hansen, Ingo Molnar
Cc: Thomas Gleixner, Andrew Cooper, H. Peter Anvin,
Sean Christopherson, David Woodhouse, Peter Zijlstra,
Christian Ludloff, Sohil Mehta, John Ogness, x86, x86-cpuid, LKML,
Ahmed S. Darwish
Add CPUID parser support for:
CPUID(0x6)
CPUID(0x7)
CPUID(0x7).1
CPUID(0xd).1
CPUID(0x80000001)
CPUID(0x8000000a)
CPUID(0x8000001f)
CPUID(0x80000021)
where one or more of these leaves output registers back the X86_FEATURE
words at <asm/cpufeatures.h>.
Handle CPUID(0x7).1 via a custom reader. Its availability depends on the
subleaf count reported by CPUID(0x7).0, so check that first.
Do not use a custom reader for CPUID(0xd).1. Per the Intel SDM regarding
CPUID(0xd)'s subleaf availability: "sub-leafs 0 and 1 are always valid".
Note, this prepares for later changes that will route X86_FEATURE queries
from cpuinfo_x86::x86_capability[] to the system's CPUID tables.
Signed-off-by: Ahmed S. Darwish <darwi@linutronix.de>
---
arch/x86/include/asm/cpuid/types.h | 8 ++++++++
arch/x86/kernel/cpu/cpuid_parser.c | 13 +++++++++++++
arch/x86/kernel/cpu/cpuid_parser.h | 8 ++++++++
3 files changed, 29 insertions(+)
diff --git a/arch/x86/include/asm/cpuid/types.h b/arch/x86/include/asm/cpuid/types.h
index 6180acd35f59..204d6277c8cd 100644
--- a/arch/x86/include/asm/cpuid/types.h
+++ b/arch/x86/include/asm/cpuid/types.h
@@ -212,7 +212,11 @@ struct cpuid_leaves {
CPUID_LEAF ( 0x1, 0 );
CPUID_LEAF ( 0x2, 0 );
CPUID_LEAF_N ( 0x4, 8 );
+ CPUID_LEAF ( 0x6, 0 );
+ CPUID_LEAF ( 0x7, 0 );
+ CPUID_LEAF ( 0x7, 1 );
CPUID_LEAF ( 0xa, 0 );
+ CPUID_LEAF ( 0xd, 1 );
CPUID_LEAF ( 0x1c, 0 );
CPUID_LEAF ( 0x16, 0 );
CPUID_LEAF ( 0x23, 0 );
@@ -222,6 +226,7 @@ struct cpuid_leaves {
CPUID_LEAF ( 0x23, 4 );
CPUID_LEAF ( 0x23, 5 );
CPUID_LEAF ( 0x80000000, 0 );
+ CPUID_LEAF ( 0x80000001, 0 );
CPUID_LEAF ( 0x80000002, 0 );
CPUID_LEAF ( 0x80000003, 0 );
CPUID_LEAF ( 0x80000004, 0 );
@@ -229,7 +234,10 @@ struct cpuid_leaves {
CPUID_LEAF ( 0x80000006, 0 );
CPUID_LEAF ( 0x80000007, 0 );
CPUID_LEAF ( 0x80000008, 0 );
+ CPUID_LEAF ( 0x8000000a, 0 );
CPUID_LEAF_N ( 0x8000001d, 8 );
+ CPUID_LEAF ( 0x8000001f, 0 );
+ CPUID_LEAF ( 0x80000021, 0 );
CPUID_LEAF ( 0x80000022, 0 );
CPUID_LEAF ( 0x80860000, 0 );
CPUID_LEAF ( 0x80860001, 0 );
diff --git a/arch/x86/kernel/cpu/cpuid_parser.c b/arch/x86/kernel/cpu/cpuid_parser.c
index de11fb4116f2..b3bf4141db15 100644
--- a/arch/x86/kernel/cpu/cpuid_parser.c
+++ b/arch/x86/kernel/cpu/cpuid_parser.c
@@ -99,6 +99,19 @@ cpuid_read_0x2(const struct cpuid_parse_entry *e, const struct cpuid_read_output
output->info->nr_entries = 1;
}
+static void
+cpuid_read_0x7_1(const struct cpuid_parse_entry *e, const struct cpuid_read_output *output)
+{
+ struct leaf_0x7_0 l7;
+
+ cpuid_read_subleaf(0x7, 0, &l7);
+ if (l7.leaf7_n_subleaves == 0)
+ return;
+
+ cpuid_read_subleaf(e->leaf, e->subleaf, output->regs);
+ output->info->nr_entries = 1;
+}
+
/*
* Shared read function for Intel CPUID(0x4) and AMD CPUID(0x8000001d), as both have
* the same subleaf enumeration logic and register output format.
diff --git a/arch/x86/kernel/cpu/cpuid_parser.h b/arch/x86/kernel/cpu/cpuid_parser.h
index c81f76c1c077..f6a620a03312 100644
--- a/arch/x86/kernel/cpu/cpuid_parser.h
+++ b/arch/x86/kernel/cpu/cpuid_parser.h
@@ -146,7 +146,11 @@ struct cpuid_parse_entry {
/* Leaf Subleaf Reader function */ \
CPUID_PARSE_ENTRY ( 0x2, 0, 0x2 ), \
CPUID_PARSE_ENTRY_N ( 0x4, deterministic_cache ), \
+ CPUID_PARSE_ENTRY ( 0x6, 0, generic ), \
+ CPUID_PARSE_ENTRY ( 0x7, 0, generic ), \
+ CPUID_PARSE_ENTRY ( 0x7, 1, 0x7_1 ), \
CPUID_PARSE_ENTRY ( 0xa, 0, generic ), \
+ CPUID_PARSE_ENTRY ( 0xd, 1, generic ), \
CPUID_PARSE_ENTRY ( 0x1c, 0, generic ), \
CPUID_PARSE_ENTRY ( 0x16, 0, generic ), \
CPUID_PARSE_ENTRY ( 0x23, 0, generic ), \
@@ -156,6 +160,7 @@ struct cpuid_parse_entry {
CPUID_PARSE_ENTRY ( 0x23, 4, 0x23_4 ), \
CPUID_PARSE_ENTRY ( 0x23, 5, 0x23_5 ), \
CPUID_PARSE_ENTRY ( 0x80000000, 0, 0x80000000 ), \
+ CPUID_PARSE_ENTRY ( 0x80000001, 0, generic ), \
CPUID_PARSE_ENTRY ( 0x80000002, 0, generic ), \
CPUID_PARSE_ENTRY ( 0x80000003, 0, generic ), \
CPUID_PARSE_ENTRY ( 0x80000004, 0, generic ), \
@@ -163,7 +168,10 @@ struct cpuid_parse_entry {
CPUID_PARSE_ENTRY ( 0x80000006, 0, generic ), \
CPUID_PARSE_ENTRY ( 0x80000007, 0, generic ), \
CPUID_PARSE_ENTRY ( 0x80000008, 0, generic ), \
+ CPUID_PARSE_ENTRY ( 0x8000000a, 0, generic ), \
CPUID_PARSE_ENTRY_N ( 0x8000001d, deterministic_cache ), \
+ CPUID_PARSE_ENTRY ( 0x8000001f, 0, generic ), \
+ CPUID_PARSE_ENTRY ( 0x80000021, 0, generic ), \
CPUID_PARSE_ENTRY ( 0x80000022, 0, generic ), \
CPUID_PARSE_ENTRY ( 0x80860000, 0, 0x80860000 ), \
CPUID_PARSE_ENTRY ( 0x80860001, 0, generic ), \
--
2.53.0
^ permalink raw reply related [flat|nested] 101+ messages in thread
* [PATCH v6 78/90] x86/cpuid: Parse Linux synthetic CPUID leaves
2026-03-27 2:15 [PATCH v6 00/90] x86: Introduce a centralized CPUID data model Ahmed S. Darwish
` (76 preceding siblings ...)
2026-03-27 2:16 ` [PATCH v6 77/90] x86/cpuid: Parse leaves backing X86_FEATURE words Ahmed S. Darwish
@ 2026-03-27 2:16 ` Ahmed S. Darwish
2026-03-27 2:16 ` [PATCH v6 79/90] x86/cpuid: Introduce a compile-time X86_FEATURE word map Ahmed S. Darwish
` (13 subsequent siblings)
91 siblings, 0 replies; 101+ messages in thread
From: Ahmed S. Darwish @ 2026-03-27 2:16 UTC (permalink / raw)
To: Borislav Petkov, Dave Hansen, Ingo Molnar
Cc: Thomas Gleixner, Andrew Cooper, H. Peter Anvin,
Sean Christopherson, David Woodhouse, Peter Zijlstra,
Christian Ludloff, Sohil Mehta, John Ogness, x86, x86-cpuid, LKML,
Ahmed S. Darwish
The X86_FEATURE words at <asm/cpufeatures.h> contain both hardware-defined
CPUID register bits and Linux-defined synthetic bits.
The hardware-defined bits already map naturally into the parsed CPUID
tables, but the synthetic bits do not. This gets feature enumeration split
between the CPUID parser and the <asm/cpufeature.h> feature APIs.
For this, the x86-cpuid-db project provides a 1:1 bitfield mapping for the
synthetic X86_FEATURE words using the CPUID range 0x4c780000. The range
prefix 0x4c78 is for Linux in its shorthand ASCII form Lx, where Linux
becomes a virtual vendor mirroring hardware vendors like AMD and Intel.
Cover all the synthetic feature and bug words by parsing CPUID(0x4c780001),
CPUID(0x4c780001).1, and CPUID(0x4c780002).
Skip these synthetic CPUID leaves in the debugfs code which compares each
cached CPUID value against its actual hardware backing.
Signed-off-by: Ahmed S. Darwish <darwi@linutronix.de>
Link: https://lore.kernel.org/lkml/874ixernra.ffs@tglx
Link: https://gitlab.com/x86-cpuid.org/x86-cpuid-db/-/blob/v3.0/CHANGELOG.rst
---
arch/x86/include/asm/cpuid/types.h | 5 +++++
arch/x86/kernel/cpu/cpuid_debugfs.c | 4 ++++
arch/x86/kernel/cpu/cpuid_parser.c | 17 +++++++++++++++++
arch/x86/kernel/cpu/cpuid_parser.h | 3 +++
4 files changed, 29 insertions(+)
diff --git a/arch/x86/include/asm/cpuid/types.h b/arch/x86/include/asm/cpuid/types.h
index 204d6277c8cd..263e82e89f70 100644
--- a/arch/x86/include/asm/cpuid/types.h
+++ b/arch/x86/include/asm/cpuid/types.h
@@ -39,11 +39,13 @@ enum cpuid_regs_idx {
#define CPUID_EXT_START 0x80000000
#define CPUID_TMX_START 0x80860000
#define CPUID_CTR_START 0xc0000000
+#define CPUID_LNX_START 0x4c780000
#define CPUID_BASE_END CPUID_RANGE_MAX(CPUID_BASE_START)
#define CPUID_EXT_END CPUID_RANGE_MAX(CPUID_EXT_START)
#define CPUID_TMX_END CPUID_RANGE_MAX(CPUID_TMX_START)
#define CPUID_CTR_END CPUID_RANGE_MAX(CPUID_CTR_START)
+#define CPUID_LNX_END CPUID_RANGE_MAX(CPUID_LNX_START)
/*
* Types for CPUID(0x2) parsing:
@@ -225,6 +227,9 @@ struct cpuid_leaves {
CPUID_LEAF ( 0x23, 3 );
CPUID_LEAF ( 0x23, 4 );
CPUID_LEAF ( 0x23, 5 );
+ CPUID_LEAF ( 0x4c780001, 0 );
+ CPUID_LEAF ( 0x4c780001, 1 );
+ CPUID_LEAF ( 0x4c780002, 0 );
CPUID_LEAF ( 0x80000000, 0 );
CPUID_LEAF ( 0x80000001, 0 );
CPUID_LEAF ( 0x80000002, 0 );
diff --git a/arch/x86/kernel/cpu/cpuid_debugfs.c b/arch/x86/kernel/cpu/cpuid_debugfs.c
index 4bd874bffffc..c1ae9d7449cc 100644
--- a/arch/x86/kernel/cpu/cpuid_debugfs.c
+++ b/arch/x86/kernel/cpu/cpuid_debugfs.c
@@ -36,6 +36,10 @@ cpuid_show_leaf(struct seq_file *m, uintptr_t cpu_id, const struct cpuid_parse_e
};
int ret;
+ /* Ignore synthetic ranges as they have no hardware backing */
+ if (CPUID_RANGE(entry->leaf) == CPUID_LNX_START)
+ continue;
+
seq_printf(m, "Leaf 0x%08x, subleaf %u:\n", entry->leaf, subleaf);
ret = smp_call_function_single(cpu_id, cpuid_this_cpu, ®s, true);
diff --git a/arch/x86/kernel/cpu/cpuid_parser.c b/arch/x86/kernel/cpu/cpuid_parser.c
index b3bf4141db15..9e22081f649d 100644
--- a/arch/x86/kernel/cpu/cpuid_parser.c
+++ b/arch/x86/kernel/cpu/cpuid_parser.c
@@ -155,6 +155,21 @@ define_cpuid_0x23_subleaf_read_function(3);
define_cpuid_0x23_subleaf_read_function(4);
define_cpuid_0x23_subleaf_read_function(5);
+/*
+ * Synthetic CPUID leaves read function
+ *
+ * These leaves do not exist in hardware. They reserve slots in the per-CPU
+ * CPUID tables for the synthetic Linux-defined X86_FEATURE and X86_BUG words.
+ *
+ * Always mark the read as successful; the actual bits will be populated via
+ * the X86_FEATURE bit update helpers at <asm/cpufeature.h>.
+ */
+static void
+cpuid_read_synthetic(const struct cpuid_parse_entry *e, const struct cpuid_read_output *output)
+{
+ output->info->nr_entries = 1;
+}
+
/*
* Define an extended range CPUID read function
*
@@ -242,6 +257,7 @@ static unsigned int cpuid_range_max_leaf(const struct cpuid_table *t, unsigned i
case CPUID_EXT_START: return el0 ? el0->max_ext_leaf : 0;
case CPUID_TMX_START: return tl0 ? tl0->max_tra_leaf : 0;
case CPUID_CTR_START: return cl0 ? cl0->max_cntr_leaf : 0;
+ case CPUID_LNX_START: return CPUID_LNX_END;
default: return 0;
}
}
@@ -305,6 +321,7 @@ cpuid_fill_table(struct cpuid_table *t, const struct cpuid_parse_entry entries[]
{ CPUID_EXT_START, CPUID_EXT_END },
{ CPUID_TMX_START, CPUID_TMX_END },
{ CPUID_CTR_START, CPUID_CTR_END },
+ { CPUID_LNX_START, CPUID_LNX_END },
};
for (unsigned int i = 0; i < ARRAY_SIZE(ranges); i++)
diff --git a/arch/x86/kernel/cpu/cpuid_parser.h b/arch/x86/kernel/cpu/cpuid_parser.h
index f6a620a03312..e7c07346452e 100644
--- a/arch/x86/kernel/cpu/cpuid_parser.h
+++ b/arch/x86/kernel/cpu/cpuid_parser.h
@@ -159,6 +159,9 @@ struct cpuid_parse_entry {
CPUID_PARSE_ENTRY ( 0x23, 3, 0x23_3 ), \
CPUID_PARSE_ENTRY ( 0x23, 4, 0x23_4 ), \
CPUID_PARSE_ENTRY ( 0x23, 5, 0x23_5 ), \
+ CPUID_PARSE_ENTRY ( 0x4c780001, 0, synthetic ), \
+ CPUID_PARSE_ENTRY ( 0x4c780001, 1, synthetic ), \
+ CPUID_PARSE_ENTRY ( 0x4c780002, 0, synthetic ), \
CPUID_PARSE_ENTRY ( 0x80000000, 0, 0x80000000 ), \
CPUID_PARSE_ENTRY ( 0x80000001, 0, generic ), \
CPUID_PARSE_ENTRY ( 0x80000002, 0, generic ), \
--
2.53.0
^ permalink raw reply related [flat|nested] 101+ messages in thread
* [PATCH v6 79/90] x86/cpuid: Introduce a compile-time X86_FEATURE word map
2026-03-27 2:15 [PATCH v6 00/90] x86: Introduce a centralized CPUID data model Ahmed S. Darwish
` (77 preceding siblings ...)
2026-03-27 2:16 ` [PATCH v6 78/90] x86/cpuid: Parse Linux synthetic CPUID leaves Ahmed S. Darwish
@ 2026-03-27 2:16 ` Ahmed S. Darwish
2026-03-27 2:16 ` [PATCH v6 80/90] x86/cpuid: Introduce X86_FEATURE and CPUID word APIs Ahmed S. Darwish
` (12 subsequent siblings)
91 siblings, 0 replies; 101+ messages in thread
From: Ahmed S. Darwish @ 2026-03-27 2:16 UTC (permalink / raw)
To: Borislav Petkov, Dave Hansen, Ingo Molnar
Cc: Thomas Gleixner, Andrew Cooper, H. Peter Anvin,
Sean Christopherson, David Woodhouse, Peter Zijlstra,
Christian Ludloff, Sohil Mehta, John Ogness, x86, x86-cpuid, LKML,
Ahmed S. Darwish
Prepare for routing X86_FEATURE queries to the CPUID tables instead of to
cpuinfo_x86::x86_capability[]. The latter will be later removed to make
the CPUID tables a "single source of Truth" for all x86 feature state.
Build a compile time map from an <asm/cpufeatures.h> X86_FEATURE word to
its cached CPUID leaf/subleaf register output.
Use a compile time table to preserve the feature querying optimizations at
<asm/cpufeature.h>.
Signed-off-by: Ahmed S. Darwish <darwi@linutronix.de>
---
arch/x86/include/asm/cpuid/types.h | 59 +++++++++++++++++++++++++++++-
1 file changed, 57 insertions(+), 2 deletions(-)
diff --git a/arch/x86/include/asm/cpuid/types.h b/arch/x86/include/asm/cpuid/types.h
index 263e82e89f70..6b0790408b85 100644
--- a/arch/x86/include/asm/cpuid/types.h
+++ b/arch/x86/include/asm/cpuid/types.h
@@ -168,9 +168,12 @@ struct leaf_parse_info {
* Use an array of storage entries to accommodate CPUID leaves with multiple subleaves
* having the same output format. This is common for hierarchical enumeration; e.g.,
* CPUID(0x4), CPUID(0x12), and CPUID(0x8000001d).
+ *
+ * Align all CPUID outputs to unsigned long. They're passed to bitops for X86_FEATURE
+ * queries, which require the alignment.
*/
#define __CPUID_LEAF(_name, _count) \
- struct _name _name[_count]; \
+ struct _name _name[_count] __aligned(sizeof(unsigned long));\
struct leaf_parse_info _name##_info
/**
@@ -267,9 +270,61 @@ struct cpuid_leaves {
*
* This is to be embedded inside 'struct cpuinfo_x86' to provide parsed and
* sanitized CPUID data per CPU.
+ *
+ * Align the leaves to unsigned long since their elements are passed to bitops
+ * for X86_FEATURE querying.
*/
struct cpuid_table {
- struct cpuid_leaves leaves;
+ struct cpuid_leaves leaves __aligned(sizeof(unsigned long));
+};
+
+/*
+ * X86_FEATURE word mappings:
+ *
+ * Build a compile-time mapping table from an <asm/cpufeatures.h> X86_FEATURE
+ * word to its corresponding cached entry in a CPUID table.
+ */
+
+#define __BUG(n) (NCAPINTS + (n))
+
+struct cpuid_cpufeature {
+ unsigned int leaves_offset; /* Offset from a struct cpuid_leaves instance */
+ unsigned int cpuid_reg; /* Output register: CPUID_EAX -> CPUID_EDX */
};
+#define __cpu_feature_word(_word, _leaf, _subleaf, _reg) \
+ [_word] = { \
+ .leaves_offset = offsetof(struct cpuid_leaves, leaf_##_leaf##_##_subleaf),\
+ .cpuid_reg = _reg, \
+ }
+
+#define CPUID_FEATURE_WORDS_MAP \
+{ \
+ /* X86_FEATURE word, Leaf, Subleaf, Output reg */ \
+ __cpu_feature_word(0, 0x1, 0, CPUID_EDX), \
+ __cpu_feature_word(1, 0x80000001, 0, CPUID_EDX), \
+ __cpu_feature_word(2, 0x80860001, 0, CPUID_EDX), \
+ __cpu_feature_word(3, 0x4c780001, 0, CPUID_EAX), \
+ __cpu_feature_word(4, 0x1, 0, CPUID_ECX), \
+ __cpu_feature_word(5, 0xc0000001, 0, CPUID_EDX), \
+ __cpu_feature_word(6, 0x80000001, 0, CPUID_ECX), \
+ __cpu_feature_word(7, 0x4c780001, 0, CPUID_EBX), \
+ __cpu_feature_word(8, 0x4c780001, 0, CPUID_ECX), \
+ __cpu_feature_word(9, 0x7, 0, CPUID_EBX), \
+ __cpu_feature_word(10, 0xd, 1, CPUID_EAX), \
+ __cpu_feature_word(11, 0x4c780001, 0, CPUID_EDX), \
+ __cpu_feature_word(12, 0x7, 1, CPUID_EAX), \
+ __cpu_feature_word(13, 0x80000008, 0, CPUID_EBX), \
+ __cpu_feature_word(14, 0x6, 0, CPUID_EAX), \
+ __cpu_feature_word(15, 0x8000000a, 0, CPUID_EDX), \
+ __cpu_feature_word(16, 0x7, 0, CPUID_ECX), \
+ __cpu_feature_word(17, 0x4c780001, 1, CPUID_EAX), \
+ __cpu_feature_word(18, 0x7, 0, CPUID_EDX), \
+ __cpu_feature_word(19, 0x8000001f, 0, CPUID_EAX), \
+ __cpu_feature_word(20, 0x80000021, 0, CPUID_EAX), \
+ __cpu_feature_word(21, 0x4c780001, 1, CPUID_EBX), \
+ __cpu_feature_word(__BUG(0), 0x4c780002, 0, CPUID_EAX), \
+ __cpu_feature_word(__BUG(1), 0x4c780002, 0, CPUID_EBX), \
+}
+
#endif /* _ASM_X86_CPUID_TYPES_H */
--
2.53.0
^ permalink raw reply related [flat|nested] 101+ messages in thread
* [PATCH v6 80/90] x86/cpuid: Introduce X86_FEATURE and CPUID word APIs
2026-03-27 2:15 [PATCH v6 00/90] x86: Introduce a centralized CPUID data model Ahmed S. Darwish
` (78 preceding siblings ...)
2026-03-27 2:16 ` [PATCH v6 79/90] x86/cpuid: Introduce a compile-time X86_FEATURE word map Ahmed S. Darwish
@ 2026-03-27 2:16 ` Ahmed S. Darwish
2026-03-27 2:16 ` [PATCH v6 81/90] x86/percpu: Add offset argument to x86_this_cpu_test_bit() Ahmed S. Darwish
` (11 subsequent siblings)
91 siblings, 0 replies; 101+ messages in thread
From: Ahmed S. Darwish @ 2026-03-27 2:16 UTC (permalink / raw)
To: Borislav Petkov, Dave Hansen, Ingo Molnar
Cc: Thomas Gleixner, Andrew Cooper, H. Peter Anvin,
Sean Christopherson, David Woodhouse, Peter Zijlstra,
Christian Ludloff, Sohil Mehta, John Ogness, x86, x86-cpuid, LKML,
Ahmed S. Darwish
Introduce helper APIs to translate:
- X86_FEATURE symbols from <asm/cpufeatures.h>
- CPUID word indices from <asm/cpufeature.h>
into offsets within the cached CPUID tables.
These helpers will be used to route all X86_FEATURE and CPUID word querying
into the centralized CPUID tables, instead of their current routing to
cpuinfo_x86::x86_capability[]. Thus removing the latter from the kernel.
Signed-off-by: Ahmed S. Darwish <darwi@linutronix.de>
---
arch/x86/include/asm/cpuid/api.h | 125 +++++++++++++++++++++++++++++++
1 file changed, 125 insertions(+)
diff --git a/arch/x86/include/asm/cpuid/api.h b/arch/x86/include/asm/cpuid/api.h
index 611ee8596115..b60a408c8fec 100644
--- a/arch/x86/include/asm/cpuid/api.h
+++ b/arch/x86/include/asm/cpuid/api.h
@@ -504,6 +504,131 @@ static inline bool cpuid_amd_hygon_has_l3_cache(struct cpuinfo_x86 *c)
return el6 && el6->l3_assoc;
}
+/*
+ * X86_FEATURE mapping:
+ *
+ * These macros are for the internal <asm/cpufeature.h> X86_FEATURE querying.
+ * Do everything at compile-time to preserve that header's query optimizations.
+ *
+ * @_feature: <asm/cpufeatures.h> X86_FEATURE symbol
+ */
+
+#define __feature_word(_feature) ((_feature) / 32)
+#define __feature_word_bit(_feature) ((_feature) % 32)
+
+/*
+ * Return cached CPUID output offset for @_feature; within 'struct cpuid_leaves'.
+ */
+#define __feature_byte_offset(_feature) \
+({ \
+ struct cpuid_cpufeature ____map[] = CPUID_FEATURE_WORDS_MAP; \
+ unsigned int ____word = __feature_word(_feature); \
+ \
+ ____map[____word].leaves_offset; \
+})
+
+/*
+ * Return CPUID output register for @_feature; i.e., CPUID_EAX -> CPUID_EDX.
+ */
+#define __feature_register(_feature) \
+({ \
+ struct cpuid_cpufeature ____map[] = CPUID_FEATURE_WORDS_MAP; \
+ unsigned int ____word = __feature_word(_feature); \
+ \
+ ____map[____word].cpuid_reg; \
+})
+
+/*
+ * Return bit offset for @_feature. This is for bitops, where the offset is
+ * relative to ((u8 *)&cpuid_leaves + __feature_byte_offset(@_feature)).
+ */
+#define __feature_bit_offset(_feature) \
+({ \
+ 32 * __feature_register(_feature) + __feature_word_bit(_feature); \
+})
+
+/**
+ * cpuid_feature_byte_offset() - Return X86_FEATURE byte offset
+ * @_feature: X86_FEATURE symbol from <asm/cpufeatures.h>
+ *
+ * Return CPUID table 'struct cpuid_leaves' byte offset, for @_feature.
+ */
+#define cpuid_feature_byte_offset(_feature) __feature_byte_offset(_feature)
+
+/**
+ * cpuid_feature_bitmap() - Return X86_FEATURE bitmap
+ * @_cpuinfo: CPU capability structure ('struct cpuinfo_x86')
+ * @_feature: X86_FEATURE symbol from <asm/cpufeatures.h>
+ *
+ * Return CPUID table bitmap, within @_cpuinfo, for @_feature. The returned
+ * bitmap is unsigned long aligned, for bitops access.
+ */
+#define cpuid_feature_bitmap(_cpuinfo, _feature) \
+ (unsigned long *)((u8 *)&(_cpuinfo)->cpuid.leaves + __feature_byte_offset(_feature))
+
+/**
+ * cpuid_feature_bit_offset()
+ * @_feature: X86_FEATURE symbol from <asm/cpufeatures.h>
+ *
+ * Return CPUID table bit offset, for @_feature, within the bitmap returned by
+ * cpuid_feature_bitmap().
+ */
+#define cpuid_feature_bit_offset(_feature) __feature_bit_offset(_feature)
+
+/*
+ * CPUID word mapping:
+ */
+
+static inline u32 *__cpuid_word_address(struct cpuinfo_x86 *c, u16 word)
+{
+ u16 feature = word * 32;
+
+ return (u32 *)cpuid_feature_bitmap(c, feature) + __feature_register(feature);
+}
+
+/**
+ * cpuid_word() - Return the CPUID word's raw u32 value
+ * @c: CPU capability structure ('struct cpuinfo_x86')
+ * @word: CPUID word number as defined at "enum cpuid_leafs"
+ */
+static inline u32 cpuid_word(struct cpuinfo_x86 *c, u16 word)
+{
+ return *__cpuid_word_address(c, word);
+}
+
+/**
+ * cpuid_word_set() - Set the CPUID word's raw u32 value
+ * @c: CPU capability structure ('struct cpuinfo_x86')
+ * @word: CPUID word number as defined at "enum cpuid_leafs"
+ * @val: Raw u32 value to set the word to
+ */
+static inline void cpuid_word_set(struct cpuinfo_x86 *c, u16 word, u32 val)
+{
+ *__cpuid_word_address(c, word) = val;
+}
+
+/**
+ * cpuid_word_set_bits() - Set bits at CPUID word according to passed map
+ * @c: CPU capability structure ('struct cpuinfo_x86')
+ * @word: CPUID word number as defined at "enum cpuid_leafs"
+ * @map: Map of bits to be set
+ */
+static inline void cpuid_word_set_bits(struct cpuinfo_x86 *c, u16 word, u32 map)
+{
+ *__cpuid_word_address(c, word) |= map;
+}
+
+/**
+ * cpuid_word_clear_bits() - Clear bits at CPUID word according to passed map
+ * @c: CPU capability structure ('struct cpuinfo_x86')
+ * @word: CPUID word number as defined at "enum cpuid_leafs"
+ * @map: Map of bits to be cleared
+ */
+static inline void cpuid_word_clear_bits(struct cpuinfo_x86 *c, u16 word, u32 map)
+{
+ *__cpuid_word_address(c, word) &= ~map;
+}
+
/*
* CPUID parser exported APIs:
*/
--
2.53.0
^ permalink raw reply related [flat|nested] 101+ messages in thread
* [PATCH v6 81/90] x86/percpu: Add offset argument to x86_this_cpu_test_bit()
2026-03-27 2:15 [PATCH v6 00/90] x86: Introduce a centralized CPUID data model Ahmed S. Darwish
` (79 preceding siblings ...)
2026-03-27 2:16 ` [PATCH v6 80/90] x86/cpuid: Introduce X86_FEATURE and CPUID word APIs Ahmed S. Darwish
@ 2026-03-27 2:16 ` Ahmed S. Darwish
2026-03-27 2:16 ` [PATCH v6 82/90] x86/cpufeature: Factor out a __static_cpu_has() helper Ahmed S. Darwish
` (10 subsequent siblings)
91 siblings, 0 replies; 101+ messages in thread
From: Ahmed S. Darwish @ 2026-03-27 2:16 UTC (permalink / raw)
To: Borislav Petkov, Dave Hansen, Ingo Molnar
Cc: Thomas Gleixner, Andrew Cooper, H. Peter Anvin,
Sean Christopherson, David Woodhouse, Peter Zijlstra,
Christian Ludloff, Sohil Mehta, John Ogness, x86, x86-cpuid, LKML,
Ahmed S. Darwish
x86_this_cpu_test_bit() assumes that the queried bitmap starts at the base
address of the percpu object. For X86_FEATURE bitops, this matches the
current cpuinfo_x86::x86_capability[] layout.
Upcoming changes though will route all X86_FEATURE queries to the CPUID
tables, where the bitmap resides at the per-CPU CPUID table plus an offset.
Add an offset argument to x86_this_cpu_test_bit().
Signed-off-by: Ahmed S. Darwish <darwi@linutronix.de>
---
arch/x86/include/asm/cpufeature.h | 2 +-
arch/x86/include/asm/percpu.h | 34 ++++++++++++++++++-------------
2 files changed, 21 insertions(+), 15 deletions(-)
diff --git a/arch/x86/include/asm/cpufeature.h b/arch/x86/include/asm/cpufeature.h
index 520949560138..b12bde4986b5 100644
--- a/arch/x86/include/asm/cpufeature.h
+++ b/arch/x86/include/asm/cpufeature.h
@@ -56,7 +56,7 @@ extern const char * const x86_bug_flags[NBUGINTS*32];
#define this_cpu_has(bit) \
(__builtin_constant_p(bit) && REQUIRED_MASK_BIT_SET(bit) ? 1 : \
- x86_this_cpu_test_bit(bit, cpu_info.x86_capability))
+ x86_this_cpu_test_bit(bit, cpu_info.x86_capability, 0))
/*
* This is the default CPU features testing macro to use in code.
diff --git a/arch/x86/include/asm/percpu.h b/arch/x86/include/asm/percpu.h
index 409981468cba..8a36f0bb979d 100644
--- a/arch/x86/include/asm/percpu.h
+++ b/arch/x86/include/asm/percpu.h
@@ -89,15 +89,17 @@
#endif /* CONFIG_SMP */
#if defined(CONFIG_USE_X86_SEG_SUPPORT) && defined(USE_TYPEOF_UNQUAL)
-# define __my_cpu_type(var) typeof(var)
-# define __my_cpu_ptr(ptr) (ptr)
-# define __my_cpu_var(var) (var)
+# define __my_cpu_type(var) typeof(var)
+# define __my_cpu_ptr(ptr) (ptr)
+# define __my_cpu_ptr_off(ptr, off) (typeof(ptr))((uintptr_t)(ptr) + (off))
+# define __my_cpu_var(var) (var)
-# define __percpu_qual __percpu_seg_override
+# define __percpu_qual __percpu_seg_override
#else
-# define __my_cpu_type(var) typeof(var) __percpu_seg_override
-# define __my_cpu_ptr(ptr) (__my_cpu_type(*(ptr))*)(__force uintptr_t)(ptr)
-# define __my_cpu_var(var) (*__my_cpu_ptr(&(var)))
+# define __my_cpu_type(var) typeof(var) __percpu_seg_override
+# define __my_cpu_ptr(ptr) (__my_cpu_type(*(ptr))*)(__force uintptr_t)(ptr)
+# define __my_cpu_ptr_off(ptr, off) (__my_cpu_type(*(ptr))*)((__force uintptr_t)(ptr) + (off))
+# define __my_cpu_var(var) (*__my_cpu_ptr(&(var)))
#endif
#define __force_percpu_arg(x) __force_percpu_prefix "%" #x
@@ -570,29 +572,33 @@ do { \
*/
#define this_cpu_read_stable(pcp) __pcpu_size_call_return(this_cpu_read_stable_, pcp)
-#define x86_this_cpu_constant_test_bit(_nr, _var) \
+#define x86_this_cpu_constant_test_bit(_nr, _var, _offset) \
({ \
unsigned long __percpu *addr__ = \
- (unsigned long __percpu *)&(_var) + BIT_WORD(_nr); \
+ (unsigned long __percpu *)((u8 __percpu *)&(_var) + (_offset)) +\
+ BIT_WORD(_nr); \
+ \
+ /* Ensure bitops safety */ \
+ BUILD_BUG_ON(!IS_ALIGNED((unsigned long)(_offset), sizeof(unsigned long)));\
\
!!(BIT_MASK(_nr) & raw_cpu_read(*addr__)); \
})
-#define x86_this_cpu_variable_test_bit(_nr, _var) \
+#define x86_this_cpu_variable_test_bit(_nr, _var, _offset) \
({ \
bool oldbit; \
\
asm volatile("btl %[nr], " __percpu_arg([var]) \
: "=@ccc" (oldbit) \
- : [var] "m" (__my_cpu_var(_var)), \
+ : [var] "m" (*__my_cpu_ptr_off(&(_var), _offset)), \
[nr] "rI" (_nr)); \
oldbit; \
})
-#define x86_this_cpu_test_bit(_nr, _var) \
+#define x86_this_cpu_test_bit(_nr, _var, _offset) \
(__builtin_constant_p(_nr) \
- ? x86_this_cpu_constant_test_bit(_nr, _var) \
- : x86_this_cpu_variable_test_bit(_nr, _var))
+ ? x86_this_cpu_constant_test_bit(_nr, _var, _offset) \
+ : x86_this_cpu_variable_test_bit(_nr, _var, _offset))
#include <asm-generic/percpu.h>
--
2.53.0
^ permalink raw reply related [flat|nested] 101+ messages in thread
* [PATCH v6 82/90] x86/cpufeature: Factor out a __static_cpu_has() helper
2026-03-27 2:15 [PATCH v6 00/90] x86: Introduce a centralized CPUID data model Ahmed S. Darwish
` (80 preceding siblings ...)
2026-03-27 2:16 ` [PATCH v6 81/90] x86/percpu: Add offset argument to x86_this_cpu_test_bit() Ahmed S. Darwish
@ 2026-03-27 2:16 ` Ahmed S. Darwish
2026-03-27 2:16 ` [PATCH v6 83/90] x86/asm/32: Cache CPUID(0x1).EDX in cpuid_table Ahmed S. Darwish
` (9 subsequent siblings)
91 siblings, 0 replies; 101+ messages in thread
From: Ahmed S. Darwish @ 2026-03-27 2:16 UTC (permalink / raw)
To: Borislav Petkov, Dave Hansen, Ingo Molnar
Cc: Thomas Gleixner, Andrew Cooper, H. Peter Anvin,
Sean Christopherson, David Woodhouse, Peter Zijlstra,
Christian Ludloff, Sohil Mehta, John Ogness, x86, x86-cpuid, LKML,
Ahmed S. Darwish
Later changes will route X86_FEATURE querying to centralized CPUID tables.
In that case, the X86_FEATURE's bit value from <asm/cpufeatures.h> is
different from the bitmap's own bit value to be checked by the fallback
capability-byte "testb" check.
Factor the asm goto fallback code out of _static_cpu_has() and into
__static_cpu_has(). Pass the X86_FEATURE bit, and the bitmap offset bit,
separately.
No functional change intended.
Signed-off-by: Ahmed S. Darwish <darwi@linutronix.de>
---
arch/x86/include/asm/cpufeature.h | 44 +++++++++++++++++--------------
1 file changed, 24 insertions(+), 20 deletions(-)
diff --git a/arch/x86/include/asm/cpufeature.h b/arch/x86/include/asm/cpufeature.h
index b12bde4986b5..48643b4b1e24 100644
--- a/arch/x86/include/asm/cpufeature.h
+++ b/arch/x86/include/asm/cpufeature.h
@@ -90,29 +90,33 @@ void check_cpufeature_deps(struct cpuinfo_x86 *c);
#define setup_force_cpu_bug(bit) setup_force_cpu_cap(bit)
/*
- * Do not use an "m" constraint for [cap_byte] here: gcc doesn't know
- * that this is only used on a fallback path and will sometimes cause
- * it to manifest the address of boot_cpu_data in a register, fouling
- * the mainline (post-initialization) code.
+ * Helper macro for CPU feature detection with alternative instructions.
+ *
+ * Do not use an "m" constraint for [cap_byte]: GCC does not know that this is
+ * only used on a fallback path and will sometimes manifest the address of
+ * boot_cpu_data in a register, fouling the mainline post-initialization code.
*/
+#define __static_cpu_has(_feature_bit, _bitmap, _bitmap_bit) \
+ asm goto(ALTERNATIVE_TERNARY("jmp 6f", %c[feature], "", "jmp %l[t_no]") \
+ ".pushsection .altinstr_aux,\"ax\"\n" \
+ "6:\n" \
+ ANNOTATE_DATA_SPECIAL "\n" \
+ " testb %[bitnum], %a[cap_byte]\n" \
+ " jnz %l[t_yes]\n" \
+ " jmp %l[t_no]\n" \
+ ".popsection\n" \
+ : : [feature] "i" (_feature_bit), \
+ [bitnum] "i" (1 << ((_bitmap_bit) & 7)), \
+ [cap_byte] "i" (&((const char *)(_bitmap))[(_bitmap_bit) >> 3]) \
+ : : t_yes, t_no); \
+ t_yes: \
+ return true; \
+ t_no: \
+ return false \
+
static __always_inline bool _static_cpu_has(u16 bit)
{
- asm goto(ALTERNATIVE_TERNARY("jmp 6f", %c[feature], "", "jmp %l[t_no]")
- ".pushsection .altinstr_aux,\"ax\"\n"
- "6:\n"
- ANNOTATE_DATA_SPECIAL "\n"
- " testb %[bitnum], %a[cap_byte]\n"
- " jnz %l[t_yes]\n"
- " jmp %l[t_no]\n"
- ".popsection\n"
- : : [feature] "i" (bit),
- [bitnum] "i" (1 << (bit & 7)),
- [cap_byte] "i" (&((const char *)boot_cpu_data.x86_capability)[bit >> 3])
- : : t_yes, t_no);
-t_yes:
- return true;
-t_no:
- return false;
+ __static_cpu_has(bit, &boot_cpu_data.x86_capability, bit);
}
#define static_cpu_has(bit) \
--
2.53.0
^ permalink raw reply related [flat|nested] 101+ messages in thread
* [PATCH v6 83/90] x86/asm/32: Cache CPUID(0x1).EDX in cpuid_table
2026-03-27 2:15 [PATCH v6 00/90] x86: Introduce a centralized CPUID data model Ahmed S. Darwish
` (81 preceding siblings ...)
2026-03-27 2:16 ` [PATCH v6 82/90] x86/cpufeature: Factor out a __static_cpu_has() helper Ahmed S. Darwish
@ 2026-03-27 2:16 ` Ahmed S. Darwish
2026-03-27 2:16 ` [PATCH v6 84/90] x86: Route all feature queries to the CPUID tables Ahmed S. Darwish
` (8 subsequent siblings)
91 siblings, 0 replies; 101+ messages in thread
From: Ahmed S. Darwish @ 2026-03-27 2:16 UTC (permalink / raw)
To: Borislav Petkov, Dave Hansen, Ingo Molnar
Cc: Thomas Gleixner, Andrew Cooper, H. Peter Anvin,
Sean Christopherson, David Woodhouse, Peter Zijlstra,
Christian Ludloff, Sohil Mehta, John Ogness, x86, x86-cpuid, LKML,
Ahmed S. Darwish
The x86-32 early boot code initializes new_cpu_data from the boot CPU and
stores CPUID(0x1).EDX in cpuinfo_x86::x86_capability[].
Introduce the CPUINFO_CPUID_0x1_EDX asm-offset, and store %edx in the
cached CPUID table entry for new_cpu_data. This prepares for the removal
of cpuinfo_x86::x86_capability[].
Note that the definition of CPUINFO_CPUID_0x1_EDX is much more complex than
X86_CAPABILITY, even though both are used as:
movl $1,%eax
cpuid
...
movl %edx,X86_CAPABILITY
movl %edx,CPUINFO_CPUID_0x1_EDX
This is because CPUID(0x1).EDX is conveniently the first word of
cpuinfo_x86::x86_capability[], but not of cpuinfo_x86::cpuid_table.
Signed-off-by: Ahmed S. Darwish <darwi@linutronix.de>
---
arch/x86/kernel/asm-offsets.c | 5 +++++
arch/x86/kernel/head_32.S | 2 ++
2 files changed, 7 insertions(+)
diff --git a/arch/x86/kernel/asm-offsets.c b/arch/x86/kernel/asm-offsets.c
index 081816888f7a..0bc36d617801 100644
--- a/arch/x86/kernel/asm-offsets.c
+++ b/arch/x86/kernel/asm-offsets.c
@@ -40,6 +40,11 @@ static void __used common(void)
OFFSET(CPUINFO_cpuid_level, cpuinfo_x86, cpuid_level);
OFFSET(CPUINFO_x86_capability, cpuinfo_x86, x86_capability);
OFFSET(CPUINFO_x86_vendor_id, cpuinfo_x86, x86_vendor_id);
+ DEFINE(CPUINFO_CPUID_0x1_EDX,
+ offsetof(struct cpuinfo_x86, cpuid) +
+ offsetof(struct cpuid_table, leaves) +
+ offsetof(struct cpuid_leaves, leaf_0x1_0) +
+ offsetof(struct cpuid_regs, edx));
BLANK();
OFFSET(TASK_threadsp, task_struct, thread.sp);
diff --git a/arch/x86/kernel/head_32.S b/arch/x86/kernel/head_32.S
index 80ef5d386b03..6dcc27014641 100644
--- a/arch/x86/kernel/head_32.S
+++ b/arch/x86/kernel/head_32.S
@@ -43,6 +43,7 @@
#define X86_CPUID new_cpu_data+CPUINFO_cpuid_level
#define X86_CAPABILITY new_cpu_data+CPUINFO_x86_capability
#define X86_VENDOR_ID new_cpu_data+CPUINFO_x86_vendor_id
+#define X86_FEATUREFLAG new_cpu_data+CPUINFO_CPUID_0x1_EDX
/*
* Worst-case size of the kernel mapping we need to make:
@@ -263,6 +264,7 @@ SYM_FUNC_START(startup_32_smp)
andb $0x0f,%cl # mask mask revision
movb %cl,X86_STEPPING
movl %edx,X86_CAPABILITY
+ movl %edx,X86_FEATUREFLAG
.Lis486:
movl $0x50022,%ecx # set AM, WP, NE and MP
--
2.53.0
^ permalink raw reply related [flat|nested] 101+ messages in thread
* [PATCH v6 84/90] x86: Route all feature queries to the CPUID tables
2026-03-27 2:15 [PATCH v6 00/90] x86: Introduce a centralized CPUID data model Ahmed S. Darwish
` (82 preceding siblings ...)
2026-03-27 2:16 ` [PATCH v6 83/90] x86/asm/32: Cache CPUID(0x1).EDX in cpuid_table Ahmed S. Darwish
@ 2026-03-27 2:16 ` Ahmed S. Darwish
2026-03-27 2:16 ` [PATCH v6 85/90] x86/cpu: Remove x86_capability[] and x86_power initialization Ahmed S. Darwish
` (7 subsequent siblings)
91 siblings, 0 replies; 101+ messages in thread
From: Ahmed S. Darwish @ 2026-03-27 2:16 UTC (permalink / raw)
To: Borislav Petkov, Dave Hansen, Ingo Molnar
Cc: Thomas Gleixner, Andrew Cooper, H. Peter Anvin,
Sean Christopherson, David Woodhouse, Peter Zijlstra,
Christian Ludloff, Sohil Mehta, John Ogness, x86, x86-cpuid, LKML,
Ahmed S. Darwish
Use the CPUID API's cpuid_feature_*() and cpuid_word_*() helpers to route
all feature querying to the CPUID tables instead of to x86_capability[].
This allows the CPUID tables to act as a single source of truth for x86
feature state; both hardware-backed and synthetic.
Do this routing in one shot, not to fragment x86 state tracking between
CPUID tables and x86_capability[]. The latter will be fully removed.
Signed-off-by: Ahmed S. Darwish <darwi@linutronix.de>
---
arch/x86/include/asm/cpufeature.h | 12 ++++++---
arch/x86/include/asm/elf.h | 2 +-
arch/x86/kernel/cpu/common.c | 41 +++++++++++++++++--------------
arch/x86/kernel/cpu/cpuid-deps.c | 2 +-
arch/x86/kernel/mpparse.c | 2 +-
arch/x86/kvm/cpuid.c | 3 +--
6 files changed, 34 insertions(+), 28 deletions(-)
diff --git a/arch/x86/include/asm/cpufeature.h b/arch/x86/include/asm/cpufeature.h
index 48643b4b1e24..58d5e4f3891c 100644
--- a/arch/x86/include/asm/cpufeature.h
+++ b/arch/x86/include/asm/cpufeature.h
@@ -10,6 +10,7 @@
#include <linux/bitops.h>
#include <asm/alternative.h>
#include <asm/cpufeaturemasks.h>
+#include <asm/cpuid/api.h>
enum cpuid_leafs
{
@@ -48,7 +49,7 @@ extern const char * const x86_bug_flags[NBUGINTS*32];
#define x86_bug_flag(flag) x86_bug_flags[flag]
#define test_cpu_cap(c, bit) \
- arch_test_bit(bit, (unsigned long *)((c)->x86_capability))
+ arch_test_bit(cpuid_feature_bit_offset(bit), cpuid_feature_bitmap(c, bit))
#define cpu_has(c, bit) \
(__builtin_constant_p(bit) && REQUIRED_MASK_BIT_SET(bit) ? 1 : \
@@ -56,7 +57,7 @@ extern const char * const x86_bug_flags[NBUGINTS*32];
#define this_cpu_has(bit) \
(__builtin_constant_p(bit) && REQUIRED_MASK_BIT_SET(bit) ? 1 : \
- x86_this_cpu_test_bit(bit, cpu_info.x86_capability, 0))
+ x86_this_cpu_test_bit(cpuid_feature_bit_offset(bit), cpu_info.cpuid.leaves, cpuid_feature_byte_offset(bit)))
/*
* This is the default CPU features testing macro to use in code.
@@ -72,7 +73,8 @@ extern const char * const x86_bug_flags[NBUGINTS*32];
#define boot_cpu_has(bit) cpu_has(&boot_cpu_data, bit)
-#define set_cpu_cap(c, bit) set_bit(bit, (unsigned long *)((c)->x86_capability))
+#define set_cpu_cap(c, bit) \
+ set_bit(cpuid_feature_bit_offset(bit), cpuid_feature_bitmap(c, bit))
extern void setup_clear_cpu_cap(unsigned int bit);
extern void clear_cpu_cap(struct cpuinfo_x86 *c, unsigned int bit);
@@ -116,7 +118,9 @@ void check_cpufeature_deps(struct cpuinfo_x86 *c);
static __always_inline bool _static_cpu_has(u16 bit)
{
- __static_cpu_has(bit, &boot_cpu_data.x86_capability, bit);
+ __static_cpu_has(bit,
+ cpuid_feature_bitmap(&boot_cpu_data, bit),
+ cpuid_feature_bit_offset(bit));
}
#define static_cpu_has(bit) \
diff --git a/arch/x86/include/asm/elf.h b/arch/x86/include/asm/elf.h
index 2ba5f166e58f..33deebdde48a 100644
--- a/arch/x86/include/asm/elf.h
+++ b/arch/x86/include/asm/elf.h
@@ -239,7 +239,7 @@ extern int force_personality32;
instruction set this CPU supports. This could be done in user space,
but it's not easy, and we've already done it here. */
-#define ELF_HWCAP (boot_cpu_data.x86_capability[CPUID_1_EDX])
+#define ELF_HWCAP cpuid_word(&boot_cpu_data, CPUID_1_EDX)
extern u32 elf_hwcap2;
diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c
index ece5a59124f5..98e53f5aa41d 100644
--- a/arch/x86/kernel/cpu/common.c
+++ b/arch/x86/kernel/cpu/common.c
@@ -968,11 +968,9 @@ void cpu_detect(struct cpuinfo_x86 *c)
static void apply_forced_caps(struct cpuinfo_x86 *c)
{
- int i;
-
- for (i = 0; i < NCAPINTS + NBUGINTS; i++) {
- c->x86_capability[i] &= ~cpu_caps_cleared[i];
- c->x86_capability[i] |= cpu_caps_set[i];
+ for (int i = 0; i < NCAPINTS + NBUGINTS; i++) {
+ cpuid_word_clear_bits(c, i, cpu_caps_cleared[i]);
+ cpuid_word_set_bits(c, i, cpu_caps_set[i]);
}
}
@@ -2002,8 +2000,6 @@ static void generic_identify(struct cpuinfo_x86 *c)
*/
static void identify_cpu(struct cpuinfo_x86 *c)
{
- int i;
-
c->loops_per_jiffy = loops_per_jiffy;
c->x86_cache_size = 0;
c->x86_vendor = X86_VENDOR_UNKNOWN;
@@ -2112,13 +2108,13 @@ static void identify_cpu(struct cpuinfo_x86 *c)
* executed, c == &boot_cpu_data.
*/
if (c != &boot_cpu_data) {
- /* AND the already accumulated flags with these */
- for (i = 0; i < NCAPINTS; i++)
- boot_cpu_data.x86_capability[i] &= c->x86_capability[i];
+ /* Clear boot_cpu_data features that are not on this CPU */
+ for (int i = 0; i < NCAPINTS; i++)
+ cpuid_word_clear_bits(&boot_cpu_data, i, ~cpuid_word(c, i));
- /* OR, i.e. replicate the bug flags */
- for (i = NCAPINTS; i < NCAPINTS + NBUGINTS; i++)
- c->x86_capability[i] |= boot_cpu_data.x86_capability[i];
+ /* Replicate boot_cpu_data's bug flags to this CPU */
+ for (int i = NCAPINTS; i < NCAPINTS + NBUGINTS; i++)
+ cpuid_word_set_bits(c, i, cpuid_word(&boot_cpu_data, i));
}
ppin_init(c);
@@ -2521,12 +2517,17 @@ void cpu_init(void)
*/
void store_cpu_caps(struct cpuinfo_x86 *curr_info)
{
+ const struct leaf_0x0_0 *l0;
+
/* Reload CPUID max function as it might've changed. */
- curr_info->cpuid_level = cpuid_eax(0);
+ cpuid_refresh_leaf(curr_info, 0x0);
+ l0 = cpuid_leaf(curr_info, 0x0);
+ if (l0)
+ curr_info->cpuid_level = l0->max_std_leaf;
/* Copy all capability leafs and pick up the synthetic ones. */
- memcpy(&curr_info->x86_capability, &boot_cpu_data.x86_capability,
- sizeof(curr_info->x86_capability));
+ for (int i = 0; i < NCAPINTS + NBUGINTS; i++)
+ cpuid_word_set(curr_info, i, cpuid_word(&boot_cpu_data, i));
/* Get the hardware CPUID leafs */
get_cpu_cap(curr_info);
@@ -2556,10 +2557,12 @@ void microcode_check(struct cpuinfo_x86 *prev_info)
store_cpu_caps(curr_info);
- if (!memcmp(&prev_info->x86_capability, &curr_info->x86_capability,
- sizeof(prev_info->x86_capability)))
- return;
+ for (int i = 0; i < NCAPINTS + NBUGINTS; i++)
+ if (cpuid_word(prev_info, i) != cpuid_word(curr_info, i))
+ goto err;
+ return;
+err:
pr_warn("x86/CPU: CPU features have changed after loading microcode, but might not take effect.\n");
pr_warn("x86/CPU: Please consider either early loading through initrd/built-in or a potential BIOS update.\n");
}
diff --git a/arch/x86/kernel/cpu/cpuid-deps.c b/arch/x86/kernel/cpu/cpuid-deps.c
index 146f6f8b0650..78374450374a 100644
--- a/arch/x86/kernel/cpu/cpuid-deps.c
+++ b/arch/x86/kernel/cpu/cpuid-deps.c
@@ -106,7 +106,7 @@ static inline void clear_feature(struct cpuinfo_x86 *c, unsigned int feature)
clear_cpu_cap(&boot_cpu_data, feature);
set_bit(feature, (unsigned long *)cpu_caps_cleared);
} else {
- clear_bit(feature, (unsigned long *)c->x86_capability);
+ clear_bit(cpuid_feature_bit_offset(feature), cpuid_feature_bitmap(c, feature));
}
}
diff --git a/arch/x86/kernel/mpparse.c b/arch/x86/kernel/mpparse.c
index 4a1b1b28abf9..a66f22db640f 100644
--- a/arch/x86/kernel/mpparse.c
+++ b/arch/x86/kernel/mpparse.c
@@ -384,7 +384,7 @@ static inline void __init construct_default_ISA_mptable(int mpc_default_type)
processor.cpuflag = CPU_ENABLED;
processor.cpufeature = (boot_cpu_data.x86 << 8) |
(boot_cpu_data.x86_model << 4) | boot_cpu_data.x86_stepping;
- processor.featureflag = boot_cpu_data.x86_capability[CPUID_1_EDX];
+ processor.featureflag = cpuid_word(&boot_cpu_data, CPUID_1_EDX);
processor.reserved[0] = 0;
processor.reserved[1] = 0;
for (i = 0; i < 2; i++) {
diff --git a/arch/x86/kvm/cpuid.c b/arch/x86/kvm/cpuid.c
index efc155e1da10..161fa2b23bdb 100644
--- a/arch/x86/kvm/cpuid.c
+++ b/arch/x86/kvm/cpuid.c
@@ -704,7 +704,6 @@ static __always_inline u32 raw_cpuid_get(struct cpuid_reg cpuid)
do { \
const struct cpuid_reg cpuid = x86_feature_cpuid(leaf * 32); \
const u32 __maybe_unused kvm_cpu_cap_init_in_progress = leaf; \
- const u32 *kernel_cpu_caps = boot_cpu_data.x86_capability; \
u32 kvm_cpu_cap_passthrough = 0; \
u32 kvm_cpu_cap_synthesized = 0; \
u32 kvm_cpu_cap_emulated = 0; \
@@ -715,7 +714,7 @@ do { \
kvm_cpu_caps[leaf] = kvm_cpu_cap_features; \
\
if (leaf < NCAPINTS) \
- kvm_cpu_caps[leaf] &= kernel_cpu_caps[leaf]; \
+ kvm_cpu_caps[leaf] &= cpuid_word(&boot_cpu_data, leaf);\
\
kvm_cpu_caps[leaf] |= kvm_cpu_cap_passthrough; \
kvm_cpu_caps[leaf] &= (raw_cpuid_get(cpuid) | \
--
2.53.0
^ permalink raw reply related [flat|nested] 101+ messages in thread
* [PATCH v6 85/90] x86/cpu: Remove x86_capability[] and x86_power initialization
2026-03-27 2:15 [PATCH v6 00/90] x86: Introduce a centralized CPUID data model Ahmed S. Darwish
` (83 preceding siblings ...)
2026-03-27 2:16 ` [PATCH v6 84/90] x86: Route all feature queries to the CPUID tables Ahmed S. Darwish
@ 2026-03-27 2:16 ` Ahmed S. Darwish
2026-03-27 2:16 ` [PATCH v6 86/90] x86/cpu/transmeta: Remove x86_capability[] CPUID initialization Ahmed S. Darwish
` (6 subsequent siblings)
91 siblings, 0 replies; 101+ messages in thread
From: Ahmed S. Darwish @ 2026-03-27 2:16 UTC (permalink / raw)
To: Borislav Petkov, Dave Hansen, Ingo Molnar
Cc: Thomas Gleixner, Andrew Cooper, H. Peter Anvin,
Sean Christopherson, David Woodhouse, Peter Zijlstra,
Christian Ludloff, Sohil Mehta, John Ogness, x86, x86-cpuid, LKML,
Ahmed S. Darwish
X86_FEATURE queries are now routed to the CPUID tables instead of to
x86_capability[].
x86_power call sites have all been converted to parsed CPUID(0x80000007)
access.
Remove all direct CPUID queries which populate x86_capability[] and
x86_power.
Signed-off-by: Ahmed S. Darwish <darwi@linutronix.de>
---
arch/x86/kernel/cpu/common.c | 58 ------------------------------------
1 file changed, 58 deletions(-)
diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c
index 98e53f5aa41d..4c2739f31e3d 100644
--- a/arch/x86/kernel/cpu/common.c
+++ b/arch/x86/kernel/cpu/common.c
@@ -1018,70 +1018,12 @@ static void init_speculation_control(struct cpuinfo_x86 *c)
void get_cpu_cap(struct cpuinfo_x86 *c)
{
const struct leaf_0x80000000_0 *el0;
- u32 eax, ebx, ecx, edx;
cpuid_scan_cpu(c);
- /* Intel-defined flags: level 0x00000001 */
- if (c->cpuid_level >= 0x00000001) {
- cpuid(0x00000001, &eax, &ebx, &ecx, &edx);
-
- c->x86_capability[CPUID_1_ECX] = ecx;
- c->x86_capability[CPUID_1_EDX] = edx;
- }
-
- /* Thermal and Power Management Leaf: level 0x00000006 (eax) */
- if (c->cpuid_level >= 0x00000006)
- c->x86_capability[CPUID_6_EAX] = cpuid_eax(0x00000006);
-
- /* Additional Intel-defined flags: level 0x00000007 */
- if (c->cpuid_level >= 0x00000007) {
- cpuid_count(0x00000007, 0, &eax, &ebx, &ecx, &edx);
- c->x86_capability[CPUID_7_0_EBX] = ebx;
- c->x86_capability[CPUID_7_ECX] = ecx;
- c->x86_capability[CPUID_7_EDX] = edx;
-
- /* Check valid sub-leaf index before accessing it */
- if (eax >= 1) {
- cpuid_count(0x00000007, 1, &eax, &ebx, &ecx, &edx);
- c->x86_capability[CPUID_7_1_EAX] = eax;
- }
- }
-
- /* Extended state features: level 0x0000000d */
- if (c->cpuid_level >= 0x0000000d) {
- cpuid_count(0x0000000d, 1, &eax, &ebx, &ecx, &edx);
-
- c->x86_capability[CPUID_D_1_EAX] = eax;
- }
-
el0 = cpuid_leaf(c, 0x80000000);
c->extended_cpuid_level = el0 ? el0->max_ext_leaf : 0;
- if (c->extended_cpuid_level >= 0x80000001) {
- cpuid(0x80000001, &eax, &ebx, &ecx, &edx);
-
- c->x86_capability[CPUID_8000_0001_ECX] = ecx;
- c->x86_capability[CPUID_8000_0001_EDX] = edx;
- }
-
- if (c->extended_cpuid_level >= 0x80000007)
- c->x86_power = cpuid_edx(0x80000007);
-
- if (c->extended_cpuid_level >= 0x80000008) {
- cpuid(0x80000008, &eax, &ebx, &ecx, &edx);
- c->x86_capability[CPUID_8000_0008_EBX] = ebx;
- }
-
- if (c->extended_cpuid_level >= 0x8000000a)
- c->x86_capability[CPUID_8000_000A_EDX] = cpuid_edx(0x8000000a);
-
- if (c->extended_cpuid_level >= 0x8000001f)
- c->x86_capability[CPUID_8000_001F_EAX] = cpuid_eax(0x8000001f);
-
- if (c->extended_cpuid_level >= 0x80000021)
- c->x86_capability[CPUID_8000_0021_EAX] = cpuid_eax(0x80000021);
-
init_scattered_cpuid_features(c);
init_speculation_control(c);
--
2.53.0
^ permalink raw reply related [flat|nested] 101+ messages in thread
* [PATCH v6 86/90] x86/cpu/transmeta: Remove x86_capability[] CPUID initialization
2026-03-27 2:15 [PATCH v6 00/90] x86: Introduce a centralized CPUID data model Ahmed S. Darwish
` (84 preceding siblings ...)
2026-03-27 2:16 ` [PATCH v6 85/90] x86/cpu: Remove x86_capability[] and x86_power initialization Ahmed S. Darwish
@ 2026-03-27 2:16 ` Ahmed S. Darwish
2026-03-27 20:35 ` kernel test robot
` (2 more replies)
2026-03-27 2:16 ` [PATCH v6 87/90] x86/cpu: centaur/zhaoxin: Remove x86_capability[] initialization Ahmed S. Darwish
` (5 subsequent siblings)
91 siblings, 3 replies; 101+ messages in thread
From: Ahmed S. Darwish @ 2026-03-27 2:16 UTC (permalink / raw)
To: Borislav Petkov, Dave Hansen, Ingo Molnar
Cc: Thomas Gleixner, Andrew Cooper, H. Peter Anvin,
Sean Christopherson, David Woodhouse, Peter Zijlstra,
Christian Ludloff, Sohil Mehta, John Ogness, x86, x86-cpuid, LKML,
Ahmed S. Darwish
X86_FEATURE queries are now routed to the CPUID tables instead of to
x86_capability[].
Remove all direct CPUID queries which populate x86_capability[].
Signed-off-by: Ahmed S. Darwish <darwi@linutronix.de>
---
arch/x86/kernel/cpu/transmeta.c | 10 ----------
1 file changed, 10 deletions(-)
diff --git a/arch/x86/kernel/cpu/transmeta.c b/arch/x86/kernel/cpu/transmeta.c
index 991e11d5c28a..47964f43a740 100644
--- a/arch/x86/kernel/cpu/transmeta.c
+++ b/arch/x86/kernel/cpu/transmeta.c
@@ -10,14 +10,6 @@
#include "cpu.h"
-static void early_init_transmeta(struct cpuinfo_x86 *c)
-{
- const struct leaf_0x80860000_0 *l = cpuid_leaf(c, 0x80860000);
-
- if (l && l->max_tra_leaf >= 0x80860001)
- c->x86_capability[CPUID_8086_0001_EDX] = cpuid_edx(0x80860001);
-}
-
/*
* If CPU revision is 0x02000000, then CPUID(0x80860002) should be used instead.
*/
@@ -85,7 +77,6 @@ static void init_transmeta(struct cpuinfo_x86 *c)
rdmsr(0x80860004, cap_mask, uk);
wrmsr(0x80860004, ~0, uk);
cpuid_refresh_leaf(c, 0x1);
- c->x86_capability[CPUID_1_EDX] = cpuid_edx(0x00000001);
wrmsr(0x80860004, cap_mask, uk);
/* All Transmeta CPUs have a constant TSC */
@@ -103,7 +94,6 @@ static void init_transmeta(struct cpuinfo_x86 *c)
static const struct cpu_dev transmeta_cpu_dev = {
.c_vendor = "Transmeta",
.c_ident = { "GenuineTMx86", "TransmetaCPU" },
- .c_early_init = early_init_transmeta,
.c_init = init_transmeta,
.c_x86_vendor = X86_VENDOR_TRANSMETA,
};
--
2.53.0
^ permalink raw reply related [flat|nested] 101+ messages in thread
* [PATCH v6 87/90] x86/cpu: centaur/zhaoxin: Remove x86_capability[] initialization
2026-03-27 2:15 [PATCH v6 00/90] x86: Introduce a centralized CPUID data model Ahmed S. Darwish
` (85 preceding siblings ...)
2026-03-27 2:16 ` [PATCH v6 86/90] x86/cpu/transmeta: Remove x86_capability[] CPUID initialization Ahmed S. Darwish
@ 2026-03-27 2:16 ` Ahmed S. Darwish
2026-03-27 2:16 ` [PATCH v6 88/90] KVM: x86: Remove BUILD_BUG_ON() x86_capability[] check Ahmed S. Darwish
` (4 subsequent siblings)
91 siblings, 0 replies; 101+ messages in thread
From: Ahmed S. Darwish @ 2026-03-27 2:16 UTC (permalink / raw)
To: Borislav Petkov, Dave Hansen, Ingo Molnar
Cc: Thomas Gleixner, Andrew Cooper, H. Peter Anvin,
Sean Christopherson, David Woodhouse, Peter Zijlstra,
Christian Ludloff, Sohil Mehta, John Ogness, x86, x86-cpuid, LKML,
Ahmed S. Darwish
X86_FEATURE queries are now routed to the CPUID tables instead of to
x86_capability[].
Remove all direct CPUID queries which populate x86_capability[].
Signed-off-by: Ahmed S. Darwish <darwi@linutronix.de>
---
arch/x86/kernel/cpu/centaur.c | 1 -
arch/x86/kernel/cpu/zhaoxin.c | 1 -
2 files changed, 2 deletions(-)
diff --git a/arch/x86/kernel/cpu/centaur.c b/arch/x86/kernel/cpu/centaur.c
index 29688aec2231..8f614003d82c 100644
--- a/arch/x86/kernel/cpu/centaur.c
+++ b/arch/x86/kernel/cpu/centaur.c
@@ -42,7 +42,6 @@ static void init_c3(struct cpuinfo_x86 *c)
* EDX feature bits. Refresh the leaf.
*/
cpuid_refresh_leaf(c, 0xc0000001);
- c->x86_capability[CPUID_C000_0001_EDX] = cpuid_edx(0xC0000001);
}
#ifdef CONFIG_X86_32
/* Cyrix III family needs CX8 & PGE explicitly enabled. */
diff --git a/arch/x86/kernel/cpu/zhaoxin.c b/arch/x86/kernel/cpu/zhaoxin.c
index 5918f9387c87..7f576f0296b7 100644
--- a/arch/x86/kernel/cpu/zhaoxin.c
+++ b/arch/x86/kernel/cpu/zhaoxin.c
@@ -41,7 +41,6 @@ static void init_zhaoxin_cap(struct cpuinfo_x86 *c)
* EDX feature bits. Refresh the leaf.
*/
cpuid_refresh_leaf(c, 0xc0000001);
- c->x86_capability[CPUID_C000_0001_EDX] = cpuid_edx(0xC0000001);
}
if (c->x86 >= 0x6)
--
2.53.0
^ permalink raw reply related [flat|nested] 101+ messages in thread
* [PATCH v6 88/90] KVM: x86: Remove BUILD_BUG_ON() x86_capability[] check
2026-03-27 2:15 [PATCH v6 00/90] x86: Introduce a centralized CPUID data model Ahmed S. Darwish
` (86 preceding siblings ...)
2026-03-27 2:16 ` [PATCH v6 87/90] x86/cpu: centaur/zhaoxin: Remove x86_capability[] initialization Ahmed S. Darwish
@ 2026-03-27 2:16 ` Ahmed S. Darwish
2026-03-27 2:16 ` [PATCH v6 89/90] x86/cpu: Remove x86_capability[] and x86_power Ahmed S. Darwish
` (3 subsequent siblings)
91 siblings, 0 replies; 101+ messages in thread
From: Ahmed S. Darwish @ 2026-03-27 2:16 UTC (permalink / raw)
To: Borislav Petkov, Dave Hansen, Ingo Molnar
Cc: Thomas Gleixner, Andrew Cooper, H. Peter Anvin,
Sean Christopherson, David Woodhouse, Peter Zijlstra,
Christian Ludloff, Sohil Mehta, John Ogness, x86, x86-cpuid, LKML,
Ahmed S. Darwish
KVM's direct access to cpuinfo_x86::x86_capability[] has been replaced with
the cpuid_word_*() APIs. The former is getting removed from the kernel.
Adjust the kvm_cpu_caps[] alignment comment accordingly.
Remove BUILD_BUG_ON() related to x86_capability[] as it does not matte
anymore.
Signed-off-by: Ahmed S. Darwish <darwi@linutronix.de>
---
arch/x86/kvm/cpuid.c | 7 ++-----
1 file changed, 2 insertions(+), 5 deletions(-)
diff --git a/arch/x86/kvm/cpuid.c b/arch/x86/kvm/cpuid.c
index 161fa2b23bdb..dac12dfdf47a 100644
--- a/arch/x86/kvm/cpuid.c
+++ b/arch/x86/kvm/cpuid.c
@@ -30,8 +30,8 @@
#include "xen.h"
/*
- * Unlike "struct cpuinfo_x86.x86_capability", kvm_cpu_caps doesn't need to be
- * aligned to sizeof(unsigned long) because it's not accessed via bitops.
+ * No unsigned long alignment is needed. The CPUID tables X86_FEATURE
+ * words are accessed by bitops, but this table is not.
*/
u32 kvm_cpu_caps[NR_KVM_CPU_CAPS] __read_mostly;
EXPORT_SYMBOL_FOR_KVM_INTERNAL(kvm_cpu_caps);
@@ -838,9 +838,6 @@ void kvm_initialize_cpu_caps(void)
WARN_ON_ONCE(kvm_is_configuring_cpu_caps);
kvm_is_configuring_cpu_caps = true;
- BUILD_BUG_ON(sizeof(kvm_cpu_caps) - (NKVMCAPINTS * sizeof(*kvm_cpu_caps)) >
- sizeof(boot_cpu_data.x86_capability));
-
kvm_cpu_cap_init(CPUID_1_ECX,
F(XMM3),
F(PCLMULQDQ),
--
2.53.0
^ permalink raw reply related [flat|nested] 101+ messages in thread
* [PATCH v6 89/90] x86/cpu: Remove x86_capability[] and x86_power
2026-03-27 2:15 [PATCH v6 00/90] x86: Introduce a centralized CPUID data model Ahmed S. Darwish
` (87 preceding siblings ...)
2026-03-27 2:16 ` [PATCH v6 88/90] KVM: x86: Remove BUILD_BUG_ON() x86_capability[] check Ahmed S. Darwish
@ 2026-03-27 2:16 ` Ahmed S. Darwish
2026-03-27 2:16 ` [PATCH v6 90/90] MAINTAINERS: Extend x86 CPUID DATABASE file coverage Ahmed S. Darwish
` (2 subsequent siblings)
91 siblings, 0 replies; 101+ messages in thread
From: Ahmed S. Darwish @ 2026-03-27 2:16 UTC (permalink / raw)
To: Borislav Petkov, Dave Hansen, Ingo Molnar
Cc: Thomas Gleixner, Andrew Cooper, H. Peter Anvin,
Sean Christopherson, David Woodhouse, Peter Zijlstra,
Christian Ludloff, Sohil Mehta, John Ogness, x86, x86-cpuid, LKML,
Ahmed S. Darwish
X86_FEATURE queries are now routed to the CPUID tables instead of to
x86_capability[].
x86_power call sites have all been converted to parsed CPUID(0x80000007)
access.
Remove x86_capability[] and x86_power from struct cpuinfo_x86.
Signed-off-by: Ahmed S. Darwish <darwi@linutronix.de>
---
arch/x86/include/asm/processor.h | 10 ----------
arch/x86/kernel/asm-offsets.c | 1 -
arch/x86/kernel/cpu/common.c | 5 -----
arch/x86/kernel/head_32.S | 2 --
4 files changed, 18 deletions(-)
diff --git a/arch/x86/include/asm/processor.h b/arch/x86/include/asm/processor.h
index 5ee0dcbd548c..b5c89229d9a2 100644
--- a/arch/x86/include/asm/processor.h
+++ b/arch/x86/include/asm/processor.h
@@ -153,15 +153,6 @@ struct cpuinfo_x86 {
__u32 extended_cpuid_level;
/* Maximum supported CPUID level, -1=no CPUID: */
int cpuid_level;
- /*
- * Align to size of unsigned long because the x86_capability array
- * is passed to bitops which require the alignment. Use unnamed
- * union to enforce the array is aligned to size of unsigned long.
- */
- union {
- __u32 x86_capability[NCAPINTS + NBUGINTS];
- unsigned long x86_capability_alignment;
- };
char x86_vendor_id[16];
char x86_model_id[64];
struct cpuinfo_topology topo;
@@ -173,7 +164,6 @@ struct cpuinfo_x86 {
int x86_cache_max_rmid; /* max index */
int x86_cache_occ_scale; /* scale to bytes */
int x86_cache_mbm_width_offset;
- int x86_power;
unsigned long loops_per_jiffy;
/* protected processor identification number */
u64 ppin;
diff --git a/arch/x86/kernel/asm-offsets.c b/arch/x86/kernel/asm-offsets.c
index 0bc36d617801..98d2cd03d0af 100644
--- a/arch/x86/kernel/asm-offsets.c
+++ b/arch/x86/kernel/asm-offsets.c
@@ -38,7 +38,6 @@ static void __used common(void)
OFFSET(CPUINFO_x86_model, cpuinfo_x86, x86_model);
OFFSET(CPUINFO_x86_stepping, cpuinfo_x86, x86_stepping);
OFFSET(CPUINFO_cpuid_level, cpuinfo_x86, cpuid_level);
- OFFSET(CPUINFO_x86_capability, cpuinfo_x86, x86_capability);
OFFSET(CPUINFO_x86_vendor_id, cpuinfo_x86, x86_vendor_id);
DEFINE(CPUINFO_CPUID_0x1_EDX,
offsetof(struct cpuinfo_x86, cpuid) +
diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c
index 4c2739f31e3d..a5e94f09c5dd 100644
--- a/arch/x86/kernel/cpu/common.c
+++ b/arch/x86/kernel/cpu/common.c
@@ -1727,7 +1727,6 @@ static void __init cpu_parse_early_param(void)
*/
static void __init early_identify_cpu(struct cpuinfo_x86 *c)
{
- memset(&c->x86_capability, 0, sizeof(c->x86_capability));
memset(&c->cpuid, 0, sizeof(c->cpuid));
c->extended_cpuid_level = 0;
@@ -1959,7 +1958,6 @@ static void identify_cpu(struct cpuinfo_x86 *c)
c->x86_virt_bits = 32;
#endif
c->x86_cache_alignment = c->x86_clflush_size;
- memset(&c->x86_capability, 0, sizeof(c->x86_capability));
memset(&c->cpuid, 0, sizeof(c->cpuid));
#ifdef CONFIG_X86_VMX_FEATURE_NAMES
memset(&c->vmx_capability, 0, sizeof(c->vmx_capability));
@@ -1987,9 +1985,6 @@ static void identify_cpu(struct cpuinfo_x86 *c)
* features a certain CPU supports which CPUID doesn't
* tell us, CPUID claiming incorrect flags, or other bugs,
* we handle them here.
- *
- * At the end of this section, c->x86_capability better
- * indicate the features this CPU genuinely supports!
*/
if (this_cpu->c_init)
this_cpu->c_init(c);
diff --git a/arch/x86/kernel/head_32.S b/arch/x86/kernel/head_32.S
index 6dcc27014641..7f38331ee083 100644
--- a/arch/x86/kernel/head_32.S
+++ b/arch/x86/kernel/head_32.S
@@ -41,7 +41,6 @@
#define X86_STEPPING new_cpu_data+CPUINFO_x86_stepping
#define X86_HARD_MATH new_cpu_data+CPUINFO_hard_math
#define X86_CPUID new_cpu_data+CPUINFO_cpuid_level
-#define X86_CAPABILITY new_cpu_data+CPUINFO_x86_capability
#define X86_VENDOR_ID new_cpu_data+CPUINFO_x86_vendor_id
#define X86_FEATUREFLAG new_cpu_data+CPUINFO_CPUID_0x1_EDX
@@ -263,7 +262,6 @@ SYM_FUNC_START(startup_32_smp)
movb %al,X86_MODEL
andb $0x0f,%cl # mask mask revision
movb %cl,X86_STEPPING
- movl %edx,X86_CAPABILITY
movl %edx,X86_FEATUREFLAG
.Lis486:
--
2.53.0
^ permalink raw reply related [flat|nested] 101+ messages in thread
* [PATCH v6 90/90] MAINTAINERS: Extend x86 CPUID DATABASE file coverage
2026-03-27 2:15 [PATCH v6 00/90] x86: Introduce a centralized CPUID data model Ahmed S. Darwish
` (88 preceding siblings ...)
2026-03-27 2:16 ` [PATCH v6 89/90] x86/cpu: Remove x86_capability[] and x86_power Ahmed S. Darwish
@ 2026-03-27 2:16 ` Ahmed S. Darwish
2026-03-27 15:23 ` [PATCH v6 00/90] x86: Introduce a centralized CPUID data model Borislav Petkov
2026-04-07 10:09 ` Maciej Wieczor-Retman
91 siblings, 0 replies; 101+ messages in thread
From: Ahmed S. Darwish @ 2026-03-27 2:16 UTC (permalink / raw)
To: Borislav Petkov, Dave Hansen, Ingo Molnar
Cc: Thomas Gleixner, Andrew Cooper, H. Peter Anvin,
Sean Christopherson, David Woodhouse, Peter Zijlstra,
Christian Ludloff, Sohil Mehta, John Ogness, x86, x86-cpuid, LKML,
Ahmed S. Darwish
Add
arch/x86/include/asm/cpuid/
to the x86 CPUID DATABASE entry since the newly-added CPUID APIs are now at
<asm/cpuid/types.h> and <asm/cpuid/api.h>. The auto generated x86-cpuid-db
CPUID C99 bitfields header is also under that added folder.
Add
arch/x86/include/asm/cpufeature.h
since it has the X86_FEATURE word names listing, along with the X86_FEATURE
APIs, which are now both routed to the CPUID tables.
Add
arch/x86/include/asm/cpufeatures.h
since it has the X86_FEATURE bit listings, where by now new feature bits
should only be appended to; never modified in-place.
Adding these files ensures that myself and the x86-cpuid mailing list are
CCed on related patches.
Signed-off-by: Ahmed S. Darwish <darwi@linutronix.de>
---
MAINTAINERS | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/MAINTAINERS b/MAINTAINERS
index 8cb3b9fcface..6cd8d0e4fb99 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -28564,7 +28564,8 @@ R: Ahmed S. Darwish <darwi@linutronix.de>
L: x86-cpuid@lists.linux.dev
S: Maintained
W: https://x86-cpuid.org
-F: arch/x86/include/asm/cpuid/leaf_types.h
+F: arch/x86/include/asm/cpufeature*.h
+F: arch/x86/include/asm/cpuid/
F: tools/arch/x86/kcpuid/
X86 ENTRY CODE
--
2.53.0
^ permalink raw reply related [flat|nested] 101+ messages in thread
* Re: [PATCH v6 02/90] ASoC: Intel: avs: Include CPUID header at file scope
2026-03-27 2:15 ` [PATCH v6 02/90] ASoC: Intel: avs: Include CPUID header at file scope Ahmed S. Darwish
@ 2026-03-27 9:25 ` Cezary Rojewski
0 siblings, 0 replies; 101+ messages in thread
From: Cezary Rojewski @ 2026-03-27 9:25 UTC (permalink / raw)
To: Ahmed S. Darwish
Cc: Thomas Gleixner, Andrew Cooper, H. Peter Anvin,
Sean Christopherson, David Woodhouse, Peter Zijlstra,
Christian Ludloff, Sohil Mehta, John Ogness, x86, x86-cpuid, LKML,
Borislav Petkov, Dave Hansen, Ingo Molnar
On 2026-03-27 3:15 AM, Ahmed S. Darwish wrote:
> Commit
>
> cbe37a4d2b3c ("ASoC: Intel: avs: Configure basefw on TGL-based platforms")
>
> includes the main CPUID header from within a C function. This works by
> luck and forbids valid refactorings inside that header.
>
> Include the CPUID header at file scope instead.
>
> Remove the COMPILE_TEST build flag so that the CONFIG_X86 conditionals can
> be removed. The driver gets enough compilation testing already on x86.
>
> For clarity, refactor the CPUID(0x15) code into its own function without
> changing any of the driver's logic.
>
> Suggested-by: Borislav Petkov <bp@alien8.de> # CONFIG_X86 removal
> Signed-off-by: Ahmed S. Darwish <darwi@linutronix.de>
> Fixes: cbe37a4d2b3c ("ASoC: Intel: avs: Configure basefw on TGL-based platforms")
> References: 47a1886a610a ("ASoC: Intel: avs: Enable AVS driver only on x86 platforms")
> Link: https://lore.kernel.org/r/20251016105514.GCaPDPEu016XyDocfY@fat_crate.local
> Link: https://lore.kernel.org/r/da5bf77b-5bdb-440f-92b5-db35d8687987@intel.com
Thank you for sorting this out, looks good.
Acked-by: Cezary Rojewski <cezary.rojewski@intel.com>
^ permalink raw reply [flat|nested] 101+ messages in thread
* Re: [PATCH v6 01/90] ASoC: Intel: avs: Check maximum valid CPUID leaf
2026-03-27 2:15 ` [PATCH v6 01/90] ASoC: Intel: avs: Check maximum valid CPUID leaf Ahmed S. Darwish
@ 2026-03-27 9:26 ` Cezary Rojewski
2026-03-27 23:52 ` [tip: x86/cpu] " tip-bot2 for Ahmed S. Darwish
1 sibling, 0 replies; 101+ messages in thread
From: Cezary Rojewski @ 2026-03-27 9:26 UTC (permalink / raw)
To: Ahmed S. Darwish
Cc: Thomas Gleixner, Andrew Cooper, H. Peter Anvin,
Sean Christopherson, David Woodhouse, Peter Zijlstra,
Christian Ludloff, Sohil Mehta, John Ogness, x86, x86-cpuid, LKML,
Borislav Petkov, Dave Hansen, Ingo Molnar
On 2026-03-27 3:15 AM, Ahmed S. Darwish wrote:
> The Intel AVS driver queries CPUID(0x15) before checking if the CPUID leaf
> is available. Check the maximum-valid CPU standard leaf beforehand.
>
> Use the CPUID_LEAF_TSC macro instead of defining a custom local one for the
> CPUID(0x15) leaf number.
>
> Note, the inclusion of a header file from within a C function will be fixed
> in a separate commit next.
>
> Fixes: cbe37a4d2b3c ("ASoC: Intel: avs: Configure basefw on TGL-based platforms")
> Signed-off-by: Ahmed S. Darwish <darwi@linutronix.de>
Acked-by: Cezary Rojewski <cezary.rojewski@intel.com>
^ permalink raw reply [flat|nested] 101+ messages in thread
* Re: [PATCH v6 00/90] x86: Introduce a centralized CPUID data model
2026-03-27 2:15 [PATCH v6 00/90] x86: Introduce a centralized CPUID data model Ahmed S. Darwish
` (89 preceding siblings ...)
2026-03-27 2:16 ` [PATCH v6 90/90] MAINTAINERS: Extend x86 CPUID DATABASE file coverage Ahmed S. Darwish
@ 2026-03-27 15:23 ` Borislav Petkov
2026-03-30 18:29 ` Ahmed S. Darwish
2026-04-07 10:09 ` Maciej Wieczor-Retman
91 siblings, 1 reply; 101+ messages in thread
From: Borislav Petkov @ 2026-03-27 15:23 UTC (permalink / raw)
To: Ahmed S. Darwish
Cc: Dave Hansen, Ingo Molnar, Thomas Gleixner, Andrew Cooper,
H. Peter Anvin, Sean Christopherson, David Woodhouse,
Peter Zijlstra, Christian Ludloff, Sohil Mehta, John Ogness, x86,
x86-cpuid, LKML
On Fri, Mar 27, 2026 at 03:15:14AM +0100, Ahmed S. Darwish wrote:
> For the Linux-synthetic feature words, only x86_capability[] defines them
> as they have no hardware backing. Unify their handling by defining them in
> x86-cpuid-db as a synthetic CPUID leaf:
>
> <leaf id="0x4c780001">
> <desc>Linux-defined synthetic feature flags</desc>
Hmm, this makes me wonder: we have cases where we take a x86_capability
element which mirrors a real CPUID reg and then turn it into a synthetic word
because we end up using only a handful of the real bits and there's no need to
have almost unused word.
Example:
ddde4abaa0ec ("x86/cpufeatures: Make X86_FEATURE leaf 17 Linux-specific")
I guess I'll see what happens when I reach the end of the patchset - I'm just
pointing this out now, before I forget so that we don't shoot ourselves in the
foot ABI-wise and for no good reason.
Thx.
--
Regards/Gruss,
Boris.
https://people.kernel.org/tglx/notes-about-netiquette
^ permalink raw reply [flat|nested] 101+ messages in thread
* Re: [PATCH v6 86/90] x86/cpu/transmeta: Remove x86_capability[] CPUID initialization
2026-03-27 2:16 ` [PATCH v6 86/90] x86/cpu/transmeta: Remove x86_capability[] CPUID initialization Ahmed S. Darwish
@ 2026-03-27 20:35 ` kernel test robot
2026-03-27 20:58 ` kernel test robot
2026-03-27 22:56 ` kernel test robot
2 siblings, 0 replies; 101+ messages in thread
From: kernel test robot @ 2026-03-27 20:35 UTC (permalink / raw)
To: Ahmed S. Darwish, Borislav Petkov, Dave Hansen, Ingo Molnar
Cc: oe-kbuild-all, Thomas Gleixner, Andrew Cooper, H. Peter Anvin,
Sean Christopherson, David Woodhouse, Peter Zijlstra,
Christian Ludloff, Sohil Mehta, John Ogness, x86, x86-cpuid, LKML,
Ahmed S. Darwish
Hi Ahmed,
kernel test robot noticed the following build errors:
[auto build test ERROR on c369299895a591d96745d6492d4888259b004a9e]
url: https://github.com/intel-lab-lkp/linux/commits/Ahmed-S-Darwish/ASoC-Intel-avs-Check-maximum-valid-CPUID-leaf/20260327-215933
base: c369299895a591d96745d6492d4888259b004a9e
patch link: https://lore.kernel.org/r/20260327021645.555257-87-darwi%40linutronix.de
patch subject: [PATCH v6 86/90] x86/cpu/transmeta: Remove x86_capability[] CPUID initialization
config: i386-buildonly-randconfig-006-20260328 (https://download.01.org/0day-ci/archive/20260328/202603280449.C5WZiJry-lkp@intel.com/config)
compiler: gcc-14 (Debian 14.2.0-19) 14.2.0
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20260328/202603280449.C5WZiJry-lkp@intel.com/reproduce)
If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202603280449.C5WZiJry-lkp@intel.com/
All errors (new ones prefixed by >>):
arch/x86/kernel/cpu/transmeta.c: In function 'init_transmeta':
>> arch/x86/kernel/cpu/transmeta.c:70:9: error: implicit declaration of function 'early_init_transmeta'; did you mean 'init_transmeta'? [-Wimplicit-function-declaration]
70 | early_init_transmeta(c);
| ^~~~~~~~~~~~~~~~~~~~
| init_transmeta
vim +70 arch/x86/kernel/cpu/transmeta.c
fe8a36b887f719 arch/x86/kernel/cpu/transmeta.c Ahmed S. Darwish 2026-03-27 65
fe8a36b887f719 arch/x86/kernel/cpu/transmeta.c Ahmed S. Darwish 2026-03-27 66 static void init_transmeta(struct cpuinfo_x86 *c)
fe8a36b887f719 arch/x86/kernel/cpu/transmeta.c Ahmed S. Darwish 2026-03-27 67 {
fe8a36b887f719 arch/x86/kernel/cpu/transmeta.c Ahmed S. Darwish 2026-03-27 68 unsigned int cap_mask, uk;
fe8a36b887f719 arch/x86/kernel/cpu/transmeta.c Ahmed S. Darwish 2026-03-27 69
fe8a36b887f719 arch/x86/kernel/cpu/transmeta.c Ahmed S. Darwish 2026-03-27 @70 early_init_transmeta(c);
fe8a36b887f719 arch/x86/kernel/cpu/transmeta.c Ahmed S. Darwish 2026-03-27 71 cpu_detect_cache_sizes(c);
fe8a36b887f719 arch/x86/kernel/cpu/transmeta.c Ahmed S. Darwish 2026-03-27 72
fe8a36b887f719 arch/x86/kernel/cpu/transmeta.c Ahmed S. Darwish 2026-03-27 73 print_cpu_revision(c);
fe8a36b887f719 arch/x86/kernel/cpu/transmeta.c Ahmed S. Darwish 2026-03-27 74 print_cpu_info_string(c);
^1da177e4c3f41 arch/i386/kernel/cpu/transmeta.c Linus Torvalds 2005-04-16 75
^1da177e4c3f41 arch/i386/kernel/cpu/transmeta.c Linus Torvalds 2005-04-16 76 /* Unhide possibly hidden capability flags */
^1da177e4c3f41 arch/i386/kernel/cpu/transmeta.c Linus Torvalds 2005-04-16 77 rdmsr(0x80860004, cap_mask, uk);
^1da177e4c3f41 arch/i386/kernel/cpu/transmeta.c Linus Torvalds 2005-04-16 78 wrmsr(0x80860004, ~0, uk);
3ad602b4fa9f92 arch/x86/kernel/cpu/transmeta.c Ahmed S. Darwish 2026-03-27 79 cpuid_refresh_leaf(c, 0x1);
^1da177e4c3f41 arch/i386/kernel/cpu/transmeta.c Linus Torvalds 2005-04-16 80 wrmsr(0x80860004, cap_mask, uk);
^1da177e4c3f41 arch/i386/kernel/cpu/transmeta.c Linus Torvalds 2005-04-16 81
30b82ea08c3365 arch/i386/kernel/cpu/transmeta.c H. Peter Anvin 2007-02-13 82 /* All Transmeta CPUs have a constant TSC */
10cd5a1e5403d7 arch/x86/kernel/cpu/transmeta.c Ingo Molnar 2008-02-26 83 set_cpu_cap(c, X86_FEATURE_CONSTANT_TSC);
30b82ea08c3365 arch/i386/kernel/cpu/transmeta.c H. Peter Anvin 2007-02-13 84
--
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki
^ permalink raw reply [flat|nested] 101+ messages in thread
* Re: [PATCH v6 86/90] x86/cpu/transmeta: Remove x86_capability[] CPUID initialization
2026-03-27 2:16 ` [PATCH v6 86/90] x86/cpu/transmeta: Remove x86_capability[] CPUID initialization Ahmed S. Darwish
2026-03-27 20:35 ` kernel test robot
@ 2026-03-27 20:58 ` kernel test robot
2026-03-27 22:56 ` kernel test robot
2 siblings, 0 replies; 101+ messages in thread
From: kernel test robot @ 2026-03-27 20:58 UTC (permalink / raw)
To: Ahmed S. Darwish, Borislav Petkov, Dave Hansen, Ingo Molnar
Cc: oe-kbuild-all, Thomas Gleixner, Andrew Cooper, H. Peter Anvin,
Sean Christopherson, David Woodhouse, Peter Zijlstra,
Christian Ludloff, Sohil Mehta, John Ogness, x86, x86-cpuid, LKML,
Ahmed S. Darwish
Hi Ahmed,
kernel test robot noticed the following build errors:
[auto build test ERROR on c369299895a591d96745d6492d4888259b004a9e]
url: https://github.com/intel-lab-lkp/linux/commits/Ahmed-S-Darwish/ASoC-Intel-avs-Check-maximum-valid-CPUID-leaf/20260327-215933
base: c369299895a591d96745d6492d4888259b004a9e
patch link: https://lore.kernel.org/r/20260327021645.555257-87-darwi%40linutronix.de
patch subject: [PATCH v6 86/90] x86/cpu/transmeta: Remove x86_capability[] CPUID initialization
config: i386-allnoconfig-bpf (https://download.01.org/0day-ci/archive/20260327/202603272110.n460HyzQ-lkp@intel.com/config)
compiler: gcc-14 (Debian 14.2.0-19) 14.2.0
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20260327/202603272110.n460HyzQ-lkp@intel.com/reproduce)
If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202603272110.n460HyzQ-lkp@intel.com/
All errors (new ones prefixed by >>):
arch/x86/kernel/cpu/transmeta.c: In function 'init_transmeta':
>> arch/x86/kernel/cpu/transmeta.c:70:9: error: implicit declaration of function 'early_init_transmeta'; did you mean 'init_transmeta'? [-Wimplicit-function-declaration]
70 | early_init_transmeta(c);
| ^~~~~~~~~~~~~~~~~~~~
| init_transmeta
vim +70 arch/x86/kernel/cpu/transmeta.c
fe8a36b887f719 arch/x86/kernel/cpu/transmeta.c Ahmed S. Darwish 2026-03-27 65
fe8a36b887f719 arch/x86/kernel/cpu/transmeta.c Ahmed S. Darwish 2026-03-27 66 static void init_transmeta(struct cpuinfo_x86 *c)
fe8a36b887f719 arch/x86/kernel/cpu/transmeta.c Ahmed S. Darwish 2026-03-27 67 {
fe8a36b887f719 arch/x86/kernel/cpu/transmeta.c Ahmed S. Darwish 2026-03-27 68 unsigned int cap_mask, uk;
fe8a36b887f719 arch/x86/kernel/cpu/transmeta.c Ahmed S. Darwish 2026-03-27 69
fe8a36b887f719 arch/x86/kernel/cpu/transmeta.c Ahmed S. Darwish 2026-03-27 @70 early_init_transmeta(c);
fe8a36b887f719 arch/x86/kernel/cpu/transmeta.c Ahmed S. Darwish 2026-03-27 71 cpu_detect_cache_sizes(c);
fe8a36b887f719 arch/x86/kernel/cpu/transmeta.c Ahmed S. Darwish 2026-03-27 72
fe8a36b887f719 arch/x86/kernel/cpu/transmeta.c Ahmed S. Darwish 2026-03-27 73 print_cpu_revision(c);
fe8a36b887f719 arch/x86/kernel/cpu/transmeta.c Ahmed S. Darwish 2026-03-27 74 print_cpu_info_string(c);
^1da177e4c3f41 arch/i386/kernel/cpu/transmeta.c Linus Torvalds 2005-04-16 75
^1da177e4c3f41 arch/i386/kernel/cpu/transmeta.c Linus Torvalds 2005-04-16 76 /* Unhide possibly hidden capability flags */
^1da177e4c3f41 arch/i386/kernel/cpu/transmeta.c Linus Torvalds 2005-04-16 77 rdmsr(0x80860004, cap_mask, uk);
^1da177e4c3f41 arch/i386/kernel/cpu/transmeta.c Linus Torvalds 2005-04-16 78 wrmsr(0x80860004, ~0, uk);
3ad602b4fa9f92 arch/x86/kernel/cpu/transmeta.c Ahmed S. Darwish 2026-03-27 79 cpuid_refresh_leaf(c, 0x1);
^1da177e4c3f41 arch/i386/kernel/cpu/transmeta.c Linus Torvalds 2005-04-16 80 wrmsr(0x80860004, cap_mask, uk);
^1da177e4c3f41 arch/i386/kernel/cpu/transmeta.c Linus Torvalds 2005-04-16 81
30b82ea08c3365 arch/i386/kernel/cpu/transmeta.c H. Peter Anvin 2007-02-13 82 /* All Transmeta CPUs have a constant TSC */
10cd5a1e5403d7 arch/x86/kernel/cpu/transmeta.c Ingo Molnar 2008-02-26 83 set_cpu_cap(c, X86_FEATURE_CONSTANT_TSC);
30b82ea08c3365 arch/i386/kernel/cpu/transmeta.c H. Peter Anvin 2007-02-13 84
--
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki
^ permalink raw reply [flat|nested] 101+ messages in thread
* Re: [PATCH v6 86/90] x86/cpu/transmeta: Remove x86_capability[] CPUID initialization
2026-03-27 2:16 ` [PATCH v6 86/90] x86/cpu/transmeta: Remove x86_capability[] CPUID initialization Ahmed S. Darwish
2026-03-27 20:35 ` kernel test robot
2026-03-27 20:58 ` kernel test robot
@ 2026-03-27 22:56 ` kernel test robot
2 siblings, 0 replies; 101+ messages in thread
From: kernel test robot @ 2026-03-27 22:56 UTC (permalink / raw)
To: Ahmed S. Darwish, Borislav Petkov, Dave Hansen, Ingo Molnar
Cc: llvm, oe-kbuild-all, Thomas Gleixner, Andrew Cooper,
H. Peter Anvin, Sean Christopherson, David Woodhouse,
Peter Zijlstra, Christian Ludloff, Sohil Mehta, John Ogness, x86,
x86-cpuid, LKML, Ahmed S. Darwish
Hi Ahmed,
kernel test robot noticed the following build errors:
[auto build test ERROR on c369299895a591d96745d6492d4888259b004a9e]
url: https://github.com/intel-lab-lkp/linux/commits/Ahmed-S-Darwish/ASoC-Intel-avs-Check-maximum-valid-CPUID-leaf/20260327-215933
base: c369299895a591d96745d6492d4888259b004a9e
patch link: https://lore.kernel.org/r/20260327021645.555257-87-darwi%40linutronix.de
patch subject: [PATCH v6 86/90] x86/cpu/transmeta: Remove x86_capability[] CPUID initialization
config: i386-buildonly-randconfig-001-20260328 (https://download.01.org/0day-ci/archive/20260328/202603280640.96anZ0BA-lkp@intel.com/config)
compiler: clang version 20.1.8 (https://github.com/llvm/llvm-project 87f0227cb60147a26a1eeb4fb06e3b505e9c7261)
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20260328/202603280640.96anZ0BA-lkp@intel.com/reproduce)
If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202603280640.96anZ0BA-lkp@intel.com/
All errors (new ones prefixed by >>):
>> arch/x86/kernel/cpu/transmeta.c:70:2: error: call to undeclared function 'early_init_transmeta'; ISO C99 and later do not support implicit function declarations [-Wimplicit-function-declaration]
70 | early_init_transmeta(c);
| ^
arch/x86/kernel/cpu/transmeta.c:70:2: note: did you mean 'init_transmeta'?
arch/x86/kernel/cpu/transmeta.c:66:13: note: 'init_transmeta' declared here
66 | static void init_transmeta(struct cpuinfo_x86 *c)
| ^
67 | {
68 | unsigned int cap_mask, uk;
69 |
70 | early_init_transmeta(c);
| ~~~~~~~~~~~~~~~~~~~~
| init_transmeta
1 error generated.
vim +/early_init_transmeta +70 arch/x86/kernel/cpu/transmeta.c
fe8a36b887f719b arch/x86/kernel/cpu/transmeta.c Ahmed S. Darwish 2026-03-27 65
fe8a36b887f719b arch/x86/kernel/cpu/transmeta.c Ahmed S. Darwish 2026-03-27 66 static void init_transmeta(struct cpuinfo_x86 *c)
fe8a36b887f719b arch/x86/kernel/cpu/transmeta.c Ahmed S. Darwish 2026-03-27 67 {
fe8a36b887f719b arch/x86/kernel/cpu/transmeta.c Ahmed S. Darwish 2026-03-27 68 unsigned int cap_mask, uk;
fe8a36b887f719b arch/x86/kernel/cpu/transmeta.c Ahmed S. Darwish 2026-03-27 69
fe8a36b887f719b arch/x86/kernel/cpu/transmeta.c Ahmed S. Darwish 2026-03-27 @70 early_init_transmeta(c);
fe8a36b887f719b arch/x86/kernel/cpu/transmeta.c Ahmed S. Darwish 2026-03-27 71 cpu_detect_cache_sizes(c);
fe8a36b887f719b arch/x86/kernel/cpu/transmeta.c Ahmed S. Darwish 2026-03-27 72
fe8a36b887f719b arch/x86/kernel/cpu/transmeta.c Ahmed S. Darwish 2026-03-27 73 print_cpu_revision(c);
fe8a36b887f719b arch/x86/kernel/cpu/transmeta.c Ahmed S. Darwish 2026-03-27 74 print_cpu_info_string(c);
^1da177e4c3f415 arch/i386/kernel/cpu/transmeta.c Linus Torvalds 2005-04-16 75
^1da177e4c3f415 arch/i386/kernel/cpu/transmeta.c Linus Torvalds 2005-04-16 76 /* Unhide possibly hidden capability flags */
^1da177e4c3f415 arch/i386/kernel/cpu/transmeta.c Linus Torvalds 2005-04-16 77 rdmsr(0x80860004, cap_mask, uk);
^1da177e4c3f415 arch/i386/kernel/cpu/transmeta.c Linus Torvalds 2005-04-16 78 wrmsr(0x80860004, ~0, uk);
3ad602b4fa9f922 arch/x86/kernel/cpu/transmeta.c Ahmed S. Darwish 2026-03-27 79 cpuid_refresh_leaf(c, 0x1);
^1da177e4c3f415 arch/i386/kernel/cpu/transmeta.c Linus Torvalds 2005-04-16 80 wrmsr(0x80860004, cap_mask, uk);
^1da177e4c3f415 arch/i386/kernel/cpu/transmeta.c Linus Torvalds 2005-04-16 81
30b82ea08c3365a arch/i386/kernel/cpu/transmeta.c H. Peter Anvin 2007-02-13 82 /* All Transmeta CPUs have a constant TSC */
10cd5a1e5403d79 arch/x86/kernel/cpu/transmeta.c Ingo Molnar 2008-02-26 83 set_cpu_cap(c, X86_FEATURE_CONSTANT_TSC);
30b82ea08c3365a arch/i386/kernel/cpu/transmeta.c H. Peter Anvin 2007-02-13 84
--
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki
^ permalink raw reply [flat|nested] 101+ messages in thread
* [tip: x86/cpu] ASoC: Intel: avs: Check maximum valid CPUID leaf
2026-03-27 2:15 ` [PATCH v6 01/90] ASoC: Intel: avs: Check maximum valid CPUID leaf Ahmed S. Darwish
2026-03-27 9:26 ` Cezary Rojewski
@ 2026-03-27 23:52 ` tip-bot2 for Ahmed S. Darwish
1 sibling, 0 replies; 101+ messages in thread
From: tip-bot2 for Ahmed S. Darwish @ 2026-03-27 23:52 UTC (permalink / raw)
To: linux-tip-commits
Cc: Ahmed S. Darwish, Borislav Petkov (AMD), Cezary Rojewski, x86,
linux-kernel
The following commit has been merged into the x86/cpu branch of tip:
Commit-ID: 93a1f0e61329f538cfc7122d7fa0e7a1803e326d
Gitweb: https://git.kernel.org/tip/93a1f0e61329f538cfc7122d7fa0e7a1803e326d
Author: Ahmed S. Darwish <darwi@linutronix.de>
AuthorDate: Fri, 27 Mar 2026 03:15:15 +01:00
Committer: Borislav Petkov (AMD) <bp@alien8.de>
CommitterDate: Sat, 28 Mar 2026 00:27:11 +01:00
ASoC: Intel: avs: Check maximum valid CPUID leaf
The Intel AVS driver queries CPUID(0x15) before checking if the CPUID leaf
is available. Check the maximum-valid CPU standard leaf beforehand.
Use the CPUID_LEAF_TSC macro instead of the custom local one for the
CPUID(0x15) leaf number.
Fixes: cbe37a4d2b3c ("ASoC: Intel: avs: Configure basefw on TGL-based platforms")
Signed-off-by: Ahmed S. Darwish <darwi@linutronix.de>
Signed-off-by: Borislav Petkov (AMD) <bp@alien8.de>
Acked-by: Cezary Rojewski <cezary.rojewski@intel.com>
Link: https://patch.msgid.link/20260327021645.555257-2-darwi@linutronix.de
---
sound/soc/intel/avs/tgl.c | 9 ++++++---
1 file changed, 6 insertions(+), 3 deletions(-)
diff --git a/sound/soc/intel/avs/tgl.c b/sound/soc/intel/avs/tgl.c
index afb0665..4649d74 100644
--- a/sound/soc/intel/avs/tgl.c
+++ b/sound/soc/intel/avs/tgl.c
@@ -11,8 +11,6 @@
#include "debug.h"
#include "messages.h"
-#define CPUID_TSC_LEAF 0x15
-
static int avs_tgl_dsp_core_power(struct avs_dev *adev, u32 core_mask, bool power)
{
core_mask &= AVS_MAIN_CORE_MASK;
@@ -49,7 +47,11 @@ static int avs_tgl_config_basefw(struct avs_dev *adev)
unsigned int ecx;
#include <asm/cpuid/api.h>
- ecx = cpuid_ecx(CPUID_TSC_LEAF);
+
+ if (boot_cpu_data.cpuid_level < CPUID_LEAF_TSC)
+ goto no_cpuid;
+
+ ecx = cpuid_ecx(CPUID_LEAF_TSC);
if (ecx) {
ret = avs_ipc_set_fw_config(adev, 1, AVS_FW_CFG_XTAL_FREQ_HZ, sizeof(ecx), &ecx);
if (ret)
@@ -57,6 +59,7 @@ static int avs_tgl_config_basefw(struct avs_dev *adev)
}
#endif
+no_cpuid:
hwid.device = pci->device;
hwid.subsystem = pci->subsystem_vendor | (pci->subsystem_device << 16);
hwid.revision = pci->revision;
^ permalink raw reply related [flat|nested] 101+ messages in thread
* Re: [PATCH v6 00/90] x86: Introduce a centralized CPUID data model
2026-03-27 15:23 ` [PATCH v6 00/90] x86: Introduce a centralized CPUID data model Borislav Petkov
@ 2026-03-30 18:29 ` Ahmed S. Darwish
2026-03-30 23:08 ` Borislav Petkov
0 siblings, 1 reply; 101+ messages in thread
From: Ahmed S. Darwish @ 2026-03-30 18:29 UTC (permalink / raw)
To: Borislav Petkov
Cc: Dave Hansen, Ingo Molnar, Thomas Gleixner, Andrew Cooper,
H. Peter Anvin, Sean Christopherson, David Woodhouse,
Peter Zijlstra, Christian Ludloff, Sohil Mehta, John Ogness, x86,
x86-cpuid, LKML
Hi Boris,
On Fri, 27 Mar 2026, Borislav Petkov wrote:
>
> Hmm, this makes me wonder: we have cases where we take a x86_capability
> element which mirrors a real CPUID reg and then turn it into a synthetic
> word because we end up using only a handful of the real bits and there's
> no need to have almost unused word.
>
> Example:
>
> ddde4abaa0ec ("x86/cpufeatures: Make X86_FEATURE leaf 17 Linux-specific")
>
> I guess I'll see what happens when I reach the end of the patchset - I'm
> just pointing this out now, before I forget so that we don't shoot
> ourselves in the foot ABI-wise and for no good reason.
>
That commit got my attention indeed, and it is referenced below:
https://gitlab.com/x86-cpuid.org/x86-cpuid-db/-/blob/v3.0/db/xml/leaf_4c780001.xml#L360
There is an important difference with this series though: all hardware
backed X86_FEATURE words do not consume extra space. They are redirected,
at compile-time, to their respective entries in the CPUID tables.
It is the synthetic X86_FEATURE words which now consume extra space, as a
unique 4-byte entry in the CPUID tables is required for them.
Now that I'm thinking deeper about this, I guess I should revert that
commit above at this point in the patch queue:
76 x86/microcode: Allocate cpuinfo_x86 snapshots on the heap
==> NN Revert "x86/cpufeatures: Make X86_FEATURE leaf 17 Linux-specific"
77 x86/cpuid: Parse leaves backing X86_FEATURE words
78 x86/cpuid: Parse Linux synthetic CPUID leaves
Then we let X86_FEATURE word 17 be redirected to CPUID(0x80000007).EBX, as
it was before, and save the CPUID table 4-byte entry for a future synthetic
word. I'll have to update the XML accordingly, but it's no big deal.
Thanks,
Ahmed
^ permalink raw reply [flat|nested] 101+ messages in thread
* Re: [PATCH v6 00/90] x86: Introduce a centralized CPUID data model
2026-03-30 18:29 ` Ahmed S. Darwish
@ 2026-03-30 23:08 ` Borislav Petkov
0 siblings, 0 replies; 101+ messages in thread
From: Borislav Petkov @ 2026-03-30 23:08 UTC (permalink / raw)
To: Ahmed S. Darwish
Cc: Dave Hansen, Ingo Molnar, Thomas Gleixner, Andrew Cooper,
H. Peter Anvin, Sean Christopherson, David Woodhouse,
Peter Zijlstra, Christian Ludloff, Sohil Mehta, John Ogness, x86,
x86-cpuid, LKML
On Mon, Mar 30, 2026 at 08:29:24PM +0200, Ahmed S. Darwish wrote:
> There is an important difference with this series though: all hardware
> backed X86_FEATURE words do not consume extra space. They are redirected,
> at compile-time, to their respective entries in the CPUID tables.
>
> It is the synthetic X86_FEATURE words which now consume extra space, as a
> unique 4-byte entry in the CPUID tables is required for them.
Well, since the goal is to have *all* CPUID leaves available to the kernel,
then we *technically* don't need the synthetic ones anymore with the exception
of a handful ones which we defined for ourselves, like X86_FEATURE_ALWAYS, for
example.
But *all* synthetic bits which have correspondence to real CPUID leaves - and
they're synthetic because we wanted to save space... i.e., all those bits in
arch/x86/kernel/cpu/scattered.c, they don't need synthetic flags anymore
because the corresponding full leafs (damn spelling of Blätter eh!) are there.
Then, I'm thinking, we can reorder all the remaining really-synthetic ones
into the unique 4-byte entries and then not even expose them in any db and not
make them available in anything because we will have to cast them in stone
then.
But we don't have to - they're kernel-only and no one needs to know which bits
they occupy.
Something to that effect I'd say...
But we'll get to it eventually.
Thx.
--
Regards/Gruss,
Boris.
https://people.kernel.org/tglx/notes-about-netiquette
^ permalink raw reply [flat|nested] 101+ messages in thread
* Re: [PATCH v6 00/90] x86: Introduce a centralized CPUID data model
2026-03-27 2:15 [PATCH v6 00/90] x86: Introduce a centralized CPUID data model Ahmed S. Darwish
` (90 preceding siblings ...)
2026-03-27 15:23 ` [PATCH v6 00/90] x86: Introduce a centralized CPUID data model Borislav Petkov
@ 2026-04-07 10:09 ` Maciej Wieczor-Retman
91 siblings, 0 replies; 101+ messages in thread
From: Maciej Wieczor-Retman @ 2026-04-07 10:09 UTC (permalink / raw)
To: Ahmed S. Darwish
Cc: Borislav Petkov, Dave Hansen, Ingo Molnar, Thomas Gleixner,
Andrew Cooper, H. Peter Anvin, Sean Christopherson,
David Woodhouse, Peter Zijlstra, Christian Ludloff, Sohil Mehta,
John Ogness, x86, x86-cpuid, LKML
Hi, very cool rework! So far I didn't notice any problems while testing.
Buy anyway I wanted to ask if you thought about including the cpuid_deps[] or
cpuid_dependent_features[] into the new cpuid API ecosystem?
Or if not (since this patchset is quite long already :b ), then do you have any
idea where best it could fit in? During discussion on [1] you mentioned the
feature depenedency should be encoded in x86-cpuid-db. I assume you meant it
would need to be first patched into there, then parsed by Kconfig?
[1] https://lore.kernel.org/all/acruJf-pyld-fTh1@lx-t490/
(resending the email as the in-reply-to got lost somehow and I wanted to correct
top posting)
--
Kind regards
Maciej Wieczór-Retman
^ permalink raw reply [flat|nested] 101+ messages in thread
end of thread, other threads:[~2026-04-07 10:09 UTC | newest]
Thread overview: 101+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-03-27 2:15 [PATCH v6 00/90] x86: Introduce a centralized CPUID data model Ahmed S. Darwish
2026-03-27 2:15 ` [PATCH v6 01/90] ASoC: Intel: avs: Check maximum valid CPUID leaf Ahmed S. Darwish
2026-03-27 9:26 ` Cezary Rojewski
2026-03-27 23:52 ` [tip: x86/cpu] " tip-bot2 for Ahmed S. Darwish
2026-03-27 2:15 ` [PATCH v6 02/90] ASoC: Intel: avs: Include CPUID header at file scope Ahmed S. Darwish
2026-03-27 9:25 ` Cezary Rojewski
2026-03-27 2:15 ` [PATCH v6 03/90] tools/x86/kcpuid: Update bitfields to x86-cpuid-db v3.0 Ahmed S. Darwish
2026-03-27 2:15 ` [PATCH v6 04/90] treewide: Explicitly include the x86 CPUID headers Ahmed S. Darwish
2026-03-27 2:15 ` [PATCH v6 05/90] x86/cpu: <asm/processor.h>: Do not include the CPUID API header Ahmed S. Darwish
2026-03-27 2:15 ` [PATCH v6 06/90] x86/cpuid: Rename cpuid_leaf()/cpuid_subleaf() APIs Ahmed S. Darwish
2026-03-27 2:15 ` [PATCH v6 07/90] x86/cpuid: Introduce <asm/cpuid/leaf_types.h> Ahmed S. Darwish
2026-03-27 2:15 ` [PATCH v6 08/90] x86: Introduce a centralized CPUID data model Ahmed S. Darwish
2026-03-27 2:15 ` [PATCH v6 09/90] x86/cpuid: Introduce a centralized CPUID parser Ahmed S. Darwish
2026-03-27 2:15 ` [PATCH v6 10/90] x86/cpu: Rescan CPUID table after disabling PSN Ahmed S. Darwish
2026-03-27 2:15 ` [PATCH v6 11/90] x86/cpu: centaur/zhaoxin: Rescan CPUID(0xc0000001) after MSR writes Ahmed S. Darwish
2026-03-27 2:15 ` [PATCH v6 12/90] x86/cpu/transmeta: Rescan CPUID(0x1) after capability unhide Ahmed S. Darwish
2026-03-27 2:15 ` [PATCH v6 13/90] x86/cpu/intel: Rescan CPUID table after leaf unlock Ahmed S. Darwish
2026-03-27 2:15 ` [PATCH v6 14/90] x86/cpu: Use parsed CPUID(0x0) Ahmed S. Darwish
2026-03-27 2:15 ` [PATCH v6 15/90] x86/lib: Add CPUID(0x1) family and model calculation Ahmed S. Darwish
2026-03-27 2:15 ` [PATCH v6 16/90] x86/cpu: Use parsed CPUID(0x1) Ahmed S. Darwish
2026-03-27 2:15 ` [PATCH v6 17/90] x86/cpuid: Parse CPUID(0x80000000) Ahmed S. Darwish
2026-03-27 2:15 ` [PATCH v6 18/90] x86/cpu: Use parsed CPUID(0x80000000) Ahmed S. Darwish
2026-03-27 2:15 ` [PATCH v6 19/90] x86/cpuid: Parse CPUID(0x80000002) to CPUID(0x80000004) Ahmed S. Darwish
2026-03-27 2:15 ` [PATCH v6 20/90] x86/cpu: Use parsed " Ahmed S. Darwish
2026-03-27 2:15 ` [PATCH v6 21/90] x86/cpuid: Split parser tables and add vendor-qualified parsing Ahmed S. Darwish
2026-03-27 2:15 ` [PATCH v6 22/90] x86/cpuid: Introduce a parser debugfs interface Ahmed S. Darwish
2026-03-27 2:15 ` [PATCH v6 23/90] x86/cpuid: Parse CPUID(0x16) Ahmed S. Darwish
2026-03-27 2:15 ` [PATCH v6 24/90] x86/tsc: Use parsed CPUID(0x16) Ahmed S. Darwish
2026-03-27 2:15 ` [PATCH v6 25/90] x86/cpuid: Parse Transmeta and Centaur extended ranges Ahmed S. Darwish
2026-03-27 2:15 ` [PATCH v6 26/90] x86/cpu: transmeta: Use parsed CPUID(0x80860000)->CPUID(0x80860006) Ahmed S. Darwish
2026-03-27 2:15 ` [PATCH v6 27/90] x86/cpu: transmeta: Refactor CPU information printing Ahmed S. Darwish
2026-03-27 2:15 ` [PATCH v6 28/90] x86/cpu: centaur: Use parsed CPUID(0xc0000001) Ahmed S. Darwish
2026-03-27 2:15 ` [PATCH v6 29/90] x86/cpu: zhaoxin: " Ahmed S. Darwish
2026-03-27 2:15 ` [PATCH v6 30/90] x86/cpuid: Parse CPUID(0x2) Ahmed S. Darwish
2026-03-27 2:15 ` [PATCH v6 31/90] x86/cpuid: Warn once on invalid CPUID(0x2) iteration count Ahmed S. Darwish
2026-03-27 2:15 ` [PATCH v6 32/90] x86/cpuid: Introduce parsed CPUID(0x2) API Ahmed S. Darwish
2026-03-27 2:15 ` [PATCH v6 33/90] x86/cpu: Use parsed CPUID(0x2) Ahmed S. Darwish
2026-03-27 2:15 ` [PATCH v6 34/90] x86/cacheinfo: " Ahmed S. Darwish
2026-03-27 2:15 ` [PATCH v6 35/90] x86/cpuid: Remove direct CPUID(0x2) query helpers Ahmed S. Darwish
2026-03-27 2:15 ` [PATCH v6 36/90] x86/cpuid: Parse deterministic cache parameters CPUID leaves Ahmed S. Darwish
2026-03-27 2:15 ` [PATCH v6 37/90] x86/cacheinfo: Pass a 'struct cpuinfo_x86' refrence to CPUID(0x4) code Ahmed S. Darwish
2026-03-27 2:15 ` [PATCH v6 38/90] x86/cacheinfo: Use parsed CPUID(0x4) Ahmed S. Darwish
2026-03-27 2:15 ` [PATCH v6 39/90] x86/cacheinfo: Use parsed CPUID(0x8000001d) Ahmed S. Darwish
2026-03-27 2:15 ` [PATCH v6 40/90] x86/cpuid: Parse CPUID(0x80000005), CPUID(0x80000006), CPUID(0x80000008) Ahmed S. Darwish
2026-03-27 2:15 ` [PATCH v6 41/90] x86/cacheinfo: Use auto-generated data types Ahmed S. Darwish
2026-03-27 2:15 ` [PATCH v6 42/90] x86/cacheinfo: Use parsed CPUID(0x80000005) and CPUID(0x80000006) Ahmed S. Darwish
2026-03-27 2:15 ` [PATCH v6 43/90] x86/cacheinfo: Use parsed CPUID(0x80000006) Ahmed S. Darwish
2026-03-27 2:15 ` [PATCH v6 44/90] x86/cpu: Use parsed CPUID(0x80000005) and CPUID(0x80000006) Ahmed S. Darwish
2026-03-27 2:15 ` [PATCH v6 45/90] x86/cpu/amd: Use parsed CPUID(0x80000005) Ahmed S. Darwish
2026-03-27 2:16 ` [PATCH v6 46/90] x86/cpu/amd: Refactor TLB detection code Ahmed S. Darwish
2026-03-27 2:16 ` [PATCH v6 47/90] x86/cpu/amd: Use parsed CPUID(CPUID(0x80000005) and CPUID(0x80000006) Ahmed S. Darwish
2026-03-27 2:16 ` [PATCH v6 48/90] x86/cpu/hygon: Use parsed CPUID(0x80000005) " Ahmed S. Darwish
2026-03-27 2:16 ` [PATCH v6 49/90] x86/cpu/centaur: Use parsed CPUID(0x80000005) Ahmed S. Darwish
2026-03-27 2:16 ` [PATCH v6 50/90] x86/cpu: Use parsed CPUID(0x80000008) Ahmed S. Darwish
2026-03-27 2:16 ` [PATCH v6 51/90] x86/cpuid: Parse CPUID(0xa) and CPUID(0x1c) Ahmed S. Darwish
2026-03-27 2:16 ` [PATCH v6 52/90] x86/cpu/intel: Use parsed CPUID(0xa) Ahmed S. Darwish
2026-03-27 2:16 ` [PATCH v6 53/90] x86/cpu/centaur: " Ahmed S. Darwish
2026-03-27 2:16 ` [PATCH v6 54/90] x86/cpu/zhaoxin: " Ahmed S. Darwish
2026-03-27 2:16 ` [PATCH v6 55/90] perf/x86/intel: " Ahmed S. Darwish
2026-03-27 2:16 ` [PATCH v6 56/90] perf/x86/zhaoxin: " Ahmed S. Darwish
2026-03-27 2:16 ` [PATCH v6 57/90] x86/xen: " Ahmed S. Darwish
2026-03-27 2:16 ` [PATCH v6 58/90] KVM: x86: Use standard CPUID(0xa) types Ahmed S. Darwish
2026-03-27 2:16 ` [PATCH v6 59/90] KVM: x86/pmu: " Ahmed S. Darwish
2026-03-27 2:16 ` [PATCH v6 60/90] perf/x86: Remove custom " Ahmed S. Darwish
2026-03-27 2:16 ` [PATCH v6 61/90] perf/x86/lbr: Use parsed CPUID(0x1c) Ahmed S. Darwish
2026-03-27 2:16 ` [PATCH v6 62/90] perf/x86/lbr: Remove custom CPUID(0x1c) types Ahmed S. Darwish
2026-03-27 2:16 ` [PATCH v6 63/90] x86/cpuid: Parse CPUID(0x23) Ahmed S. Darwish
2026-03-27 2:16 ` [PATCH v6 64/90] perf/x86/intel: Use parsed per-CPU CPUID(0x23) Ahmed S. Darwish
2026-03-27 2:16 ` [PATCH v6 65/90] perf/x86/intel: Remove custom CPUID(0x23) types Ahmed S. Darwish
2026-03-27 2:16 ` [PATCH v6 66/90] x86/cpuid: Parse CPUID(0x80000022) Ahmed S. Darwish
2026-03-27 2:16 ` [PATCH v6 67/90] perf/x86/amd/lbr: Use parsed CPUID(0x80000022) Ahmed S. Darwish
2026-03-27 2:16 ` [PATCH v6 68/90] perf/x86/amd: " Ahmed S. Darwish
2026-03-27 2:16 ` [PATCH v6 69/90] KVM: x86: Use standard CPUID(0x80000022) types Ahmed S. Darwish
2026-03-27 2:16 ` [PATCH v6 70/90] perf/x86: Remove custom " Ahmed S. Darwish
2026-03-27 2:16 ` [PATCH v6 71/90] x86/cpuid: Parse CPUID(0x80000007) Ahmed S. Darwish
2026-03-27 2:16 ` [PATCH v6 72/90] x86/cpu: Use parsed CPUID(0x80000007) Ahmed S. Darwish
2026-03-27 2:16 ` [PATCH v6 73/90] x86/cpu: amd/hygon: " Ahmed S. Darwish
2026-03-27 2:16 ` [PATCH v6 74/90] x86/cpu: cpuinfo: " Ahmed S. Darwish
2026-03-27 2:16 ` [PATCH v6 75/90] KVM: x86: " Ahmed S. Darwish
2026-03-27 2:16 ` [PATCH v6 76/90] x86/microcode: Allocate cpuinfo_x86 snapshots on the heap Ahmed S. Darwish
2026-03-27 2:16 ` [PATCH v6 77/90] x86/cpuid: Parse leaves backing X86_FEATURE words Ahmed S. Darwish
2026-03-27 2:16 ` [PATCH v6 78/90] x86/cpuid: Parse Linux synthetic CPUID leaves Ahmed S. Darwish
2026-03-27 2:16 ` [PATCH v6 79/90] x86/cpuid: Introduce a compile-time X86_FEATURE word map Ahmed S. Darwish
2026-03-27 2:16 ` [PATCH v6 80/90] x86/cpuid: Introduce X86_FEATURE and CPUID word APIs Ahmed S. Darwish
2026-03-27 2:16 ` [PATCH v6 81/90] x86/percpu: Add offset argument to x86_this_cpu_test_bit() Ahmed S. Darwish
2026-03-27 2:16 ` [PATCH v6 82/90] x86/cpufeature: Factor out a __static_cpu_has() helper Ahmed S. Darwish
2026-03-27 2:16 ` [PATCH v6 83/90] x86/asm/32: Cache CPUID(0x1).EDX in cpuid_table Ahmed S. Darwish
2026-03-27 2:16 ` [PATCH v6 84/90] x86: Route all feature queries to the CPUID tables Ahmed S. Darwish
2026-03-27 2:16 ` [PATCH v6 85/90] x86/cpu: Remove x86_capability[] and x86_power initialization Ahmed S. Darwish
2026-03-27 2:16 ` [PATCH v6 86/90] x86/cpu/transmeta: Remove x86_capability[] CPUID initialization Ahmed S. Darwish
2026-03-27 20:35 ` kernel test robot
2026-03-27 20:58 ` kernel test robot
2026-03-27 22:56 ` kernel test robot
2026-03-27 2:16 ` [PATCH v6 87/90] x86/cpu: centaur/zhaoxin: Remove x86_capability[] initialization Ahmed S. Darwish
2026-03-27 2:16 ` [PATCH v6 88/90] KVM: x86: Remove BUILD_BUG_ON() x86_capability[] check Ahmed S. Darwish
2026-03-27 2:16 ` [PATCH v6 89/90] x86/cpu: Remove x86_capability[] and x86_power Ahmed S. Darwish
2026-03-27 2:16 ` [PATCH v6 90/90] MAINTAINERS: Extend x86 CPUID DATABASE file coverage Ahmed S. Darwish
2026-03-27 15:23 ` [PATCH v6 00/90] x86: Introduce a centralized CPUID data model Borislav Petkov
2026-03-30 18:29 ` Ahmed S. Darwish
2026-03-30 23:08 ` Borislav Petkov
2026-04-07 10:09 ` Maciej Wieczor-Retman
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox