Re: [PATCH v6 00/90] x86: Introduce a centralized CPUID data model

Maciej Wieczor-Retman <[email protected]> Tue, 07 Apr 2026 08:55:07 +0000
Newsgroups dev.linux.lists.x86-cpuid,org.kernel.vger.linux-kernel
Message-ID <[email protected]>
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?

Kind regards
Maciej Wieczór-Retman

[1] https://lore.kernel.org/all/acruJf-pyld-fTh1@lx-t490/

On 2026-03-27 at 03:15:14 +0100, Ahmed S. Darwish wrote:
>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/[email protected]
>
>The cover letter there details the v1-v5 progression in full.
>
>Thank you!
>Ahmed
>
>8<-----
>
>base-commit: c369299895a591d96745d6492d4888259b004a9e
>-- 
>2.53.0