The Linux Kernel Mailing List
 help / color / mirror / Atom feed
From: "Ahmed S. Darwish" <darwi@linutronix.de>
To: Sean Christopherson <seanjc@google.com>
Cc: Borislav Petkov <bp@alien8.de>, Ingo Molnar <mingo@redhat.com>,
	Dave Hansen <dave.hansen@linux.intel.com>,
	Thomas Gleixner <tglx@linutronix.de>,
	Andrew Cooper <andrew.cooper3@citrix.com>,
	"H. Peter Anvin" <hpa@zytor.com>,
	David Woodhouse <dwmw2@infradead.org>,
	Peter Zijlstra <peterz@infradead.org>,
	Sohil Mehta <sohil.mehta@intel.com>,
	John Ogness <john.ogness@linutronix.de>,
	x86@kernel.org, x86-cpuid@lists.linux.dev,
	LKML <linux-kernel@vger.kernel.org>
Subject: Re: [PATCH v4 07/34] x86/cpuid: Introduce a centralized CPUID data model
Date: Mon, 18 Aug 2025 15:49:02 +0200	[thread overview]
Message-ID: <aKMvTrrKYgJNWX8L@lx-t490> (raw)
In-Reply-To: <aJ9TbaNMgaplKSbH@google.com>

Hi!

On Fri, 15 Aug 2025, Sean Christopherson wrote:
>
> IMO, the end result is quite misleading for leaves with "repeated" entries.  0xd
> in particular will be bizarre due to its array starting at ECX=2.  E.g.
> cpuid_subleaf_index() straight up won't work (without lying) due to hardcoding
> '0' as the subleaf.
>
> #define cpuid_subleaf_index(_cpuinfo, _leaf, _idx)			\
> ({									\
> 	__cpuid_assert_leaf_has_dynamic_subleaves(_cpuinfo, _leaf);	\
> 	__cpuid_table_subleaf_idx(&(_cpuinfo)->cpuid, _leaf, 0, _idx);	\
>                                                              ^
>                                                              |
>
> And then the usage would be similarly bizarre, e.g.
>
> 	for (i = XFEATURE_YMM; i < ARRAY_SIZE(xstate_sizes); i++) {
> 		struct cpuid_xstate_sizes *xs = &xstate_sizes[i];
> 		struct cpuid_0xd_2 *c = cpuid_subleaf_index(..., 0xD, i - 2);
>
> 		...
> 	}
>
> Even the cases where the array starts at '0' look weird:
>
> 	const struct leaf_0x4_0 *regs = cpuid_subleaf_index(c, 0x4, index);
>
> because the code is obviously not grabbing CPUID(0x4).0.
>
> And the subleaf_index naming is also weird, because they're essentially the same
> thing, e.g. the SDM refers to "sub-leaf index" for more than just the repeated
> cases.
>
> Rather than define the structures names using an explicit starting subleaf, what
> if the structures and APIs explicitly reference 'n' as the subleaf?  That would
> communicate that the struct represents a repeated subleaf, explicitly tie the API
> to that structure, and would provide macro/function names that don't make the
> reader tease out the subtle usage of "index".
>
> And then instead of just the array size, capture the start:end of the repeated
> subleaf so that the caller doesn't need to manually do the math.
>
> E.g.
>
> 	const struct leaf_0x4_n *regs = cpuid_subleaf_n(c, 0x4, index);
>
> 	struct cpuid_0xd_n *c = cpuid_subleaf_n(..., 0xD, i);
>

Thanks a lot for all these remarks.  I was indeed struggling with good
names for the array indexing case, so the above was really helpful.

In this v4 iteration, I did not add a CPUID parser API for the cases
where the subleaves are repeated but do not start from zero.  Not for any
technical reason, but to avoid having kernel APIs with no call sites.

What I internally have is:

  /**
   * __cpuid_subleaf_index() - Access parsed CPUID data at runtime subleaf index
   * @_cpuinfo:	CPU capability structure reference ('struct cpuinfo_x86')
   * @_leaf:	CPUID leaf in compile-time 0xN format; e.g. 0x4, 0x8000001d
   * @_subleaf:	CPUID subleaf in compile-time decimal format; e.g. 0, 1, 3
   * @_idx:	Index within CPUID(@_leaf).@_subleaf output storage array.
   *		Unlike @_leaf and @_subleaf, this index value can be provided
   *		dynamically.
   * ...
   */
  #define __cpuid_subleaf_index(_cpuinfo, _leaf, _subleaf, @_idx)	\
  ...

Thus, the arch/x86/kvm/cpuid.c loop you quoted would be tokenized as:

    const struct leaf_0xd_2 *ld;
    for (int i = 0; i < ARRAY_SIZE(xstate_sizes) - XFEATURE_YMM; i++) {
        ...
        ld = __cpuid_subleaf_index(c, 0xd, 2, i);
	                           |   |   |  └───────┐
                                   |   |   └────────┐ |
                                   |   └─────────┐  | |
                                   *             *  * v
        ld =                      &c.cpuid.leaf_0xd_2[i];
        ...
    }

I actually agree that, in this case, types like "struct leaf_0xd_2" are
deceiving... Let's divide the problem in two.

Easy case: Subleaves start repeating from subleaf = 0
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

This would be the CPUID leaves:

    x86-cpuid-db/db/xml (tip)> git grep 'id="0" array='
    leaf_04.xml:        <subleaf id="0" array="32">
    leaf_0b.xml:        <subleaf id="0" array="2">
    leaf_18.xml:        <subleaf id="0" array="32">
    leaf_1b.xml:        <subleaf id="0" array="32">
    leaf_1f.xml:        <subleaf id="0" array="6">
    leaf_8000001d.xml:	<subleaf id="0" array="32">
    leaf_80000026.xml:	<subleaf id="0" array="4">

For example, patch 24/34 ("x86/cacheinfo: Use parsed CPUID(0x4)"):

    static int
    intel_fill_cpuid4_info(struct cpuinfo_x86 *c, int index, ...)
    {
	const struct leaf_0x4_0 *regs = cpuid_subleaf_index(c, 0x4, index);
	...
    }

In that case, we might actually generate leaf data types in the form:

    struct leaf_0x4_n { ... };

And have the access macros called cpuid_subleaf_n():

    static int
    intel_fill_cpuid4_info(struct cpuinfo_x86 *c, int index, ...) {
    {
	const struct leaf_0x4_n *regs = cpuid_subleaf_n(c, 0x4, index);
	...
    }

I think this indeed looks much much better.

I will do that for v5 of the model.

Hard case: Subleaves start repeating from subleaf > 0
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

This would be the CPUID leaves:

    x86-cpuid-db/db/xml (tip)> git grep 'id="[1-9][0-9]*" array='

    leaf_0d.xml:    <subleaf id="2" array="62">
    leaf_10.xml:    <subleaf id="1" array="2">
    leaf_12.xml:    <subleaf id="2" array="30">
    leaf_17.xml:    <subleaf id="1" array="3">

For something like CPUID(0xd), I cannot just blindly define a 'struct
cpuid_0xd_n' data type.  We already have:

    struct leaf_0xd_0 { ... };
    struct leaf_0xd_1 { ... };
    struct leaf_0xd_2 { ... };

and they all have different bitfields.  A similar case exist for
CPUID(0x10), CPUID(0x12), and CPUID(0x17).

But, we can still have:

    struct leaf_0xd_0	{ ... };
    struct leaf_0xd_1	{ ... };
    struct leaf_0xd_2_n	{ ... };

With this, the CPUID(0x12) call site at kernel/cpu/sgx/main.c can change
from:

    u32 eax, ebx, ecx, edx;

    for (i = 0; i < ARRAY_SIZE(sgx_epc_sections); i++) {
        ...
	cpuid_count(SGX_CPUID, i + SGX_CPUID_EPC, &eax, ...);
    }

to:

    const struct leaf_0x12_2_n *l;

    for (i = 0; i < ARRAY_SIZE(sgx_epc_sections); i++) {
        ...
	l = __cpuid_subleaf_n(0x12, 2, i);
    }

And the aforementioned KVM snippet would be:

    const struct leaf_0xd_2_n *l;

    for (int i = 0; i < ARRAY_SIZE(xstate_sizes) - XFEATURE_YMM; i++) {
        l = __cpuid_subleaf_n(c, 0xd, 2, i);
    }

I'm open for better names than __cpuid_subleaf_n() for this.  The only
constraint with any suggested name is that I need to have 0xd and 2 both
passed as CPP literals.

API Summary
~~~~~~~~~~~

For CPUID leaves with static subleaves:

    cpuid_leaf(_cpuinfo, _leaf)
    cpuid_subleaf(_cpuinfo, _leaf, _subleaf)

For CPUID leaves with dynamic subleaves:

    cpuid_subleaf_n(_cpuinfo, _leaf, _idx)
    __cpuid_subleaf_n(_cpuinfo, _leaf, _subleaf, _idx)

Sounds good?

>
> Tangentially related, having to manually specific count=1 to CPUID_LEAF() for
> the common case is also ugly.  If a dedicated CPUID_LEAF_N() macro is added to
> specificy the start:end of the range, then CPUID_LEAF() can just hardcode the
> count to '1'.  E.g.
>
> struct cpuid_leaves {
> 	CPUID_LEAF(0x0,		 	0);
> 	CPUID_LEAF(0x1,			0);
> 	CPUID_LEAF(0x2,		 	0);
> 	CPUID_LEAF_N(0x4,		0,	7);
> 	CPUID_LEAF(0xd,			0);
> 	CPUID_LEAF(0xd,			1);
> 	CPUID_LEAF_N(0xd,		2,	63);
> 	CPUID_LEAF(0x16,	 	0);
> 	CPUID_LEAF(0x80000000,		0);
> 	CPUID_LEAF(0x80000005,		0);
> 	CPUID_LEAF(0x80000006,		0);
> 	CPUID_LEAF_N(0x8000001d,	0,	7);
> };
>

This is much better; will do.

Thanks!

--
Ahmed S. Darwish
Linutronix GmbH

  reply	other threads:[~2025-08-18 13:49 UTC|newest]

Thread overview: 55+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2025-08-15  7:01 [PATCH v4 00/34] x86: Introduce a centralized CPUID data model Ahmed S. Darwish
2025-08-15  7:01 ` [PATCH v4 01/34] x86/cpuid: Remove transitional <asm/cpuid.h> header Ahmed S. Darwish
2025-08-15 10:11   ` [tip: x86/urgent] " tip-bot2 for Ahmed S. Darwish
2025-08-15 15:22   ` tip-bot2 for Ahmed S. Darwish
2025-08-15  7:01 ` [PATCH v4 02/34] ASoC: Intel: avs: Include CPUID header at file scope Ahmed S. Darwish
2025-08-18 14:56   ` Borislav Petkov
2025-08-18 15:14     ` Ahmed S. Darwish
2025-08-15  7:01 ` [PATCH v4 03/34] treewide: Explicitly include the x86 CPUID headers Ahmed S. Darwish
2025-08-15  7:01 ` [PATCH v4 04/34] x86/cpu: <asm/processor.h>: Do not include the CPUID API header Ahmed S. Darwish
2025-08-15  7:01 ` [PATCH v4 05/34] x86/cpuid: Rename cpuid_leaf()/cpuid_subleaf() APIs Ahmed S. Darwish
2025-08-15  7:01 ` [PATCH v4 06/34] x86/cpuid: Introduce <asm/cpuid/leaf_types.h> Ahmed S. Darwish
2025-08-25 14:18   ` Borislav Petkov
2025-08-25 14:56     ` Ahmed S. Darwish
2025-08-15  7:02 ` [PATCH v4 07/34] x86/cpuid: Introduce a centralized CPUID data model Ahmed S. Darwish
2025-08-15 15:34   ` Sean Christopherson
2025-08-18 13:49     ` Ahmed S. Darwish [this message]
2025-08-18 18:44       ` Sean Christopherson
2025-08-18 19:54         ` Ahmed S. Darwish
2025-08-18 21:29           ` Sean Christopherson
2025-08-19 13:10             ` Ahmed S. Darwish
2025-08-15  7:02 ` [PATCH v4 08/34] x86/cpuid: Introduce a centralized CPUID parser Ahmed S. Darwish
2025-08-15  7:02 ` [PATCH v4 09/34] x86/cpu: Use parsed CPUID(0x0) Ahmed S. Darwish
2025-08-15  7:02 ` [PATCH v4 10/34] x86/lib: Add CPUID(0x1) CPU family and model calculation Ahmed S. Darwish
2025-08-15  7:02 ` [PATCH v4 11/34] x86/cpu: Use parsed CPUID(0x1) Ahmed S. Darwish
2025-08-15  7:02 ` [PATCH v4 12/34] x86/cpuid: Parse CPUID(0x80000000) Ahmed S. Darwish
2025-08-15  7:02 ` [PATCH v4 13/34] x86/cpu: Use parsed CPUID(0x80000000) Ahmed S. Darwish
2025-08-15  7:02 ` [PATCH v4 14/34] x86/cpuid: Introduce a CPUID leaf x86 vendor table Ahmed S. Darwish
2025-08-15  7:02 ` [PATCH v4 15/34] x86/cpuid: Introduce CPUID parser debugfs interface Ahmed S. Darwish
2025-08-15  7:02 ` [PATCH v4 16/34] x86/cpuid: Parse CPUID(0x2) Ahmed S. Darwish
2025-08-15  7:02 ` [PATCH v4 17/34] x86/cpuid: Warn once on invalid CPUID(0x2) iteration count Ahmed S. Darwish
2025-08-15  7:02 ` [PATCH v4 18/34] x86/cpuid: Introduce parsed CPUID(0x2) API Ahmed S. Darwish
2025-08-15  7:02 ` [PATCH v4 19/34] x86/cpu: Use parsed CPUID(0x2) Ahmed S. Darwish
2025-08-15  7:02 ` [PATCH v4 20/34] x86/cacheinfo: " Ahmed S. Darwish
2025-08-15  7:02 ` [PATCH v4 21/34] x86/cpuid: Remove direct CPUID(0x2) query API Ahmed S. Darwish
2025-08-15  7:02 ` [PATCH v4 22/34] x86/cpuid: Parse 'deterministic cache parameters' CPUID leaves Ahmed S. Darwish
2025-08-15  7:02 ` [PATCH v4 23/34] x86/cacheinfo: Pass a 'struct cpuinfo_x86' refrence to CPUID(0x4) code Ahmed S. Darwish
2025-08-15  7:02 ` [PATCH v4 24/34] x86/cacheinfo: Use parsed CPUID(0x4) Ahmed S. Darwish
2025-08-15  7:02 ` [PATCH v4 25/34] x86/cacheinfo: Use parsed CPUID(0x8000001d) Ahmed S. Darwish
2025-08-15  7:02 ` [PATCH v4 26/34] x86/cpuid: Parse CPUID(0x80000005) and CPUID(0x80000006) Ahmed S. Darwish
2025-08-15  7:02 ` [PATCH v4 27/34] x86/cacheinfo: Use auto-generated data types Ahmed S. Darwish
2025-08-15  7:02 ` [PATCH v4 28/34] x86/cacheinfo: Use parsed CPUID(0x80000005) and CPUID(0x80000006) Ahmed S. Darwish
2025-08-15 15:25   ` Dave Hansen
2025-08-18 15:38     ` Ahmed S. Darwish
2025-08-18 15:52     ` David Woodhouse
2025-08-18 17:00       ` Ahmed S. Darwish
2025-08-15  7:02 ` [PATCH v4 29/34] x86/amd_nb: Trickle down 'struct cpuinfo_x86' reference Ahmed S. Darwish
2025-08-18  2:54   ` kernel test robot
2025-08-18 14:47     ` Ahmed S. Darwish
2025-08-15  7:02 ` [PATCH v4 30/34] x86/cpuid: Use parsed CPUID(0x80000006) Ahmed S. Darwish
2025-08-15  7:02 ` [PATCH v4 31/34] x86/cpu: Rescan CPUID table after PSN disable Ahmed S. Darwish
2025-08-15  7:02 ` [PATCH v4 32/34] x86/cpu: Rescan CPUID table after unlocking full CPUID range Ahmed S. Darwish
2025-08-15  7:02 ` [PATCH v4 33/34] x86/cpuid: Parse CPUID(0x16) Ahmed S. Darwish
2025-08-15  7:02 ` [PATCH v4 34/34] x86/tsc: Use parsed CPUID(0x16) Ahmed S. Darwish
2025-08-16  9:59 ` [PATCH v4 00/34] x86: Introduce a centralized CPUID data model David Woodhouse
2025-08-18 16:37   ` Ahmed S. Darwish

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=aKMvTrrKYgJNWX8L@lx-t490 \
    --to=darwi@linutronix.de \
    --cc=andrew.cooper3@citrix.com \
    --cc=bp@alien8.de \
    --cc=dave.hansen@linux.intel.com \
    --cc=dwmw2@infradead.org \
    --cc=hpa@zytor.com \
    --cc=john.ogness@linutronix.de \
    --cc=linux-kernel@vger.kernel.org \
    --cc=mingo@redhat.com \
    --cc=peterz@infradead.org \
    --cc=seanjc@google.com \
    --cc=sohil.mehta@intel.com \
    --cc=tglx@linutronix.de \
    --cc=x86-cpuid@lists.linux.dev \
    --cc=x86@kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox