2024-02-13 21:04:13

by Thomas Gleixner

[permalink] [raw]
Subject: [patch V6 01/19] x86/cpu: Provide cpuid_read() et al.

From: Thomas Gleixner <[email protected]>

Provide a few helper functions to read CPUID leafs or individual registers
into a data structure without requiring unions.

Signed-off-by: Thomas Gleixner <[email protected]>
Tested-by: Juergen Gross <[email protected]>
Tested-by: Sohil Mehta <[email protected]>
Tested-by: Michael Kelley <[email protected]>
Tested-by: Peter Zijlstra (Intel) <[email protected]>
Tested-by: Zhang Rui <[email protected]>
Tested-by: Wang Wendy <[email protected]>
Acked-by: Peter Zijlstra (Intel) <[email protected]>



---
arch/x86/include/asm/cpuid.h | 36 ++++++++++++++++++++++++++++++++++++
1 file changed, 36 insertions(+)
---

--- a/arch/x86/include/asm/cpuid.h
+++ b/arch/x86/include/asm/cpuid.h
@@ -127,6 +127,42 @@ static inline unsigned int cpuid_edx(uns
return edx;
}

+static inline void __cpuid_read(unsigned int leaf, unsigned int subleaf, u32 *regs)
+{
+ regs[CPUID_EAX] = leaf;
+ regs[CPUID_ECX] = subleaf;
+ __cpuid(regs, regs + 1, regs + 2, regs + 3);
+}
+
+#define cpuid_subleaf(leaf, subleaf, regs) { \
+ BUILD_BUG_ON(sizeof(*(regs)) != 16); \
+ __cpuid_read(leaf, subleaf, (u32 *)(regs)); \
+}
+
+#define cpuid_leaf(leaf, regs) { \
+ BUILD_BUG_ON(sizeof(*(regs)) != 16); \
+ __cpuid_read(leaf, 0, (u32 *)(regs)); \
+}
+
+static inline void __cpuid_read_reg(unsigned int leaf, unsigned int subleaf,
+ enum cpuid_regs_idx regidx, u32 *reg)
+{
+ u32 regs[4];
+
+ __cpuid_read(leaf, subleaf, regs);
+ *reg = regs[regidx];
+}
+
+#define cpuid_subleaf_reg(leaf, subleaf, regidx, reg) { \
+ BUILD_BUG_ON(sizeof(*(reg)) != 4); \
+ __cpuid_read_reg(leaf, subleaf, regidx, (u32 *)(reg)); \
+}
+
+#define cpuid_leaf_reg(leaf, regidx, reg) { \
+ BUILD_BUG_ON(sizeof(*(reg)) != 4); \
+ __cpuid_read_reg(leaf, 0, regidx, (u32 *)(reg)); \
+}
+
static __always_inline bool cpuid_function_is_indexed(u32 function)
{
switch (function) {





2024-02-13 21:37:53

by Borislav Petkov

[permalink] [raw]
Subject: Re: [patch V6 01/19] x86/cpu: Provide cpuid_read() et al.

On Tue, Feb 13, 2024 at 10:04:00PM +0100, Thomas Gleixner wrote:
> +static inline void __cpuid_read(unsigned int leaf, unsigned int subleaf, u32 *regs)
> +{
> + regs[CPUID_EAX] = leaf;
> + regs[CPUID_ECX] = subleaf;
> + __cpuid(regs, regs + 1, regs + 2, regs + 3);

Yeah,

__cpuid(regs, regs + CPUID_EBX, regs + CPUID_ECX, regs + CPUID_EDX);

explains what those numbers are.

Thx.

--
Regards/Gruss,
Boris.

https://people.kernel.org/tglx/notes-about-netiquette

2024-02-13 23:32:15

by Thomas Gleixner

[permalink] [raw]
Subject: Re: [patch V6 01/19] x86/cpu: Provide cpuid_read() et al.

On Tue, Feb 13 2024 at 22:36, Borislav Petkov wrote:

> On Tue, Feb 13, 2024 at 10:04:00PM +0100, Thomas Gleixner wrote:
>> +static inline void __cpuid_read(unsigned int leaf, unsigned int subleaf, u32 *regs)
>> +{
>> + regs[CPUID_EAX] = leaf;
>> + regs[CPUID_ECX] = subleaf;
>> + __cpuid(regs, regs + 1, regs + 2, regs + 3);
>
> Yeah,
>
> __cpuid(regs, regs + CPUID_EBX, regs + CPUID_ECX, regs + CPUID_EDX);
>
> explains what those numbers are.

Oops. Sorry, I missed that part of your previous reply and just
responded to the u32 *regs part. I'll send an update tomorrow.

Thanks,

tglx

2024-02-14 20:30:32

by Thomas Gleixner

[permalink] [raw]
Subject: [patch V6a 01/19] x86/cpu: Provide cpuid_read() et al.

Provide a few helper functions to read CPUID leafs or individual registers
into a data structure without requiring unions.

Signed-off-by: Thomas Gleixner <[email protected]>
Tested-by: Juergen Gross <[email protected]>
Tested-by: Sohil Mehta <[email protected]>
Tested-by: Michael Kelley <[email protected]>
Tested-by: Peter Zijlstra (Intel) <[email protected]>
Tested-by: Zhang Rui <[email protected]>
Tested-by: Wang Wendy <[email protected]>
Acked-by: Peter Zijlstra (Intel) <[email protected]>
---
V6a: Use CPUID_E*X instead of hardcoded numbers - Borislav
---
arch/x86/include/asm/cpuid.h | 36 ++++++++++++++++++++++++++++++++++++
1 file changed, 36 insertions(+)
---

--- a/arch/x86/include/asm/cpuid.h
+++ b/arch/x86/include/asm/cpuid.h
@@ -127,6 +127,42 @@ static inline unsigned int cpuid_edx(uns
return edx;
}

+static inline void __cpuid_read(unsigned int leaf, unsigned int subleaf, u32 *regs)
+{
+ regs[CPUID_EAX] = leaf;
+ regs[CPUID_ECX] = subleaf;
+ __cpuid(regs + CPUID_EAX, regs + CPUID_EBX, regs + CPUID_ECX, regs + CPUID_EDX);
+}
+
+#define cpuid_subleaf(leaf, subleaf, regs) { \
+ BUILD_BUG_ON(sizeof(*(regs)) != 16); \
+ __cpuid_read(leaf, subleaf, (u32 *)(regs)); \
+}
+
+#define cpuid_leaf(leaf, regs) { \
+ BUILD_BUG_ON(sizeof(*(regs)) != 16); \
+ __cpuid_read(leaf, 0, (u32 *)(regs)); \
+}
+
+static inline void __cpuid_read_reg(unsigned int leaf, unsigned int subleaf,
+ enum cpuid_regs_idx regidx, u32 *reg)
+{
+ u32 regs[4];
+
+ __cpuid_read(leaf, subleaf, regs);
+ *reg = regs[regidx];
+}
+
+#define cpuid_subleaf_reg(leaf, subleaf, regidx, reg) { \
+ BUILD_BUG_ON(sizeof(*(reg)) != 4); \
+ __cpuid_read_reg(leaf, subleaf, regidx, (u32 *)(reg)); \
+}
+
+#define cpuid_leaf_reg(leaf, regidx, reg) { \
+ BUILD_BUG_ON(sizeof(*(reg)) != 4); \
+ __cpuid_read_reg(leaf, 0, regidx, (u32 *)(reg)); \
+}
+
static __always_inline bool cpuid_function_is_indexed(u32 function)
{
switch (function) {

2024-02-15 08:49:49

by Andy Shevchenko

[permalink] [raw]
Subject: Re: [patch V6a 01/19] x86/cpu: Provide cpuid_read() et al.

On Wed, Feb 14, 2024 at 10:29 PM Thomas Gleixner <[email protected]> wrote:
>
> Provide a few helper functions to read CPUID leafs or individual registers
> into a data structure without requiring unions.

..

> +#define cpuid_subleaf(leaf, subleaf, regs) { \
> + BUILD_BUG_ON(sizeof(*(regs)) != 16); \
> + __cpuid_read(leaf, subleaf, (u32 *)(regs)); \
> +}
> +
> +#define cpuid_leaf(leaf, regs) { \
> + BUILD_BUG_ON(sizeof(*(regs)) != 16); \
> + __cpuid_read(leaf, 0, (u32 *)(regs)); \
> +}

..

> +#define cpuid_subleaf_reg(leaf, subleaf, regidx, reg) { \
> + BUILD_BUG_ON(sizeof(*(reg)) != 4); \
> + __cpuid_read_reg(leaf, subleaf, regidx, (u32 *)(reg)); \
> +}
> +
> +#define cpuid_leaf_reg(leaf, regidx, reg) { \
> + BUILD_BUG_ON(sizeof(*(reg)) != 4); \
> + __cpuid_read_reg(leaf, 0, regidx, (u32 *)(reg)); \
> +}

I'm wondering if we can use static_assert() instead of BUILD_BUG_ON()
in the above macros.

--
With Best Regards,
Andy Shevchenko

2024-02-15 15:07:25

by Thomas Gleixner

[permalink] [raw]
Subject: Re: [patch V6a 01/19] x86/cpu: Provide cpuid_read() et al.

On Thu, Feb 15 2024 at 10:49, Andy Shevchenko wrote:

> On Wed, Feb 14, 2024 at 10:29 PM Thomas Gleixner <tglx@linutronixde> wrote:
>>
>> Provide a few helper functions to read CPUID leafs or individual registers
>> into a data structure without requiring unions.
>
> ...
>
>> +#define cpuid_subleaf(leaf, subleaf, regs) { \
>> + BUILD_BUG_ON(sizeof(*(regs)) != 16); \
>> + __cpuid_read(leaf, subleaf, (u32 *)(regs)); \
>> +}
>> +
>> +#define cpuid_leaf(leaf, regs) { \
>> + BUILD_BUG_ON(sizeof(*(regs)) != 16); \
>> + __cpuid_read(leaf, 0, (u32 *)(regs)); \
>> +}
>
> ...
>
>> +#define cpuid_subleaf_reg(leaf, subleaf, regidx, reg) { \
>> + BUILD_BUG_ON(sizeof(*(reg)) != 4); \
>> + __cpuid_read_reg(leaf, subleaf, regidx, (u32 *)(reg)); \
>> +}
>> +
>> +#define cpuid_leaf_reg(leaf, regidx, reg) { \
>> + BUILD_BUG_ON(sizeof(*(reg)) != 4); \
>> + __cpuid_read_reg(leaf, 0, regidx, (u32 *)(reg)); \
>> +}
>
> I'm wondering if we can use static_assert() instead of BUILD_BUG_ON()
> in the above macros.

Probably.

Subject: [tip: x86/apic] x86/cpu: Provide cpuid_read() et al.

The following commit has been merged into the x86/apic branch of tip:

Commit-ID: 43d86e3cd9a77912772cf7ad37ad94211bf7351d
Gitweb: https://git.kernel.org/tip/43d86e3cd9a77912772cf7ad37ad94211bf7351d
Author: Thomas Gleixner <[email protected]>
AuthorDate: Wed, 14 Feb 2024 21:29:39 +01:00
Committer: Thomas Gleixner <[email protected]>
CommitterDate: Thu, 15 Feb 2024 22:07:36 +01:00

x86/cpu: Provide cpuid_read() et al.

Provide a few helper functions to read CPUID leafs or individual registers
into a data structure without requiring unions.

Signed-off-by: Thomas Gleixner <[email protected]>
Tested-by: Juergen Gross <[email protected]>
Tested-by: Sohil Mehta <[email protected]>
Tested-by: Michael Kelley <[email protected]>
Tested-by: Peter Zijlstra (Intel) <[email protected]>
Tested-by: Zhang Rui <[email protected]>
Tested-by: Wang Wendy <[email protected]>
Tested-by: K Prateek Nayak <[email protected]>
Acked-by: Peter Zijlstra (Intel) <[email protected]>
Link: https://lore.kernel.org/r/878r3mg570.ffs@tglx

---
arch/x86/include/asm/cpuid.h | 36 +++++++++++++++++++++++++++++++++++-
1 file changed, 36 insertions(+)

diff --git a/arch/x86/include/asm/cpuid.h b/arch/x86/include/asm/cpuid.h
index 9bee3e7..6b122a3 100644
--- a/arch/x86/include/asm/cpuid.h
+++ b/arch/x86/include/asm/cpuid.h
@@ -127,6 +127,42 @@ static inline unsigned int cpuid_edx(unsigned int op)
return edx;
}

+static inline void __cpuid_read(unsigned int leaf, unsigned int subleaf, u32 *regs)
+{
+ regs[CPUID_EAX] = leaf;
+ regs[CPUID_ECX] = subleaf;
+ __cpuid(regs + CPUID_EAX, regs + CPUID_EBX, regs + CPUID_ECX, regs + CPUID_EDX);
+}
+
+#define cpuid_subleaf(leaf, subleaf, regs) { \
+ static_assert(sizeof(*(regs)) == 16); \
+ __cpuid_read(leaf, subleaf, (u32 *)(regs)); \
+}
+
+#define cpuid_leaf(leaf, regs) { \
+ static_assert(sizeof(*(regs)) == 16); \
+ __cpuid_read(leaf, 0, (u32 *)(regs)); \
+}
+
+static inline void __cpuid_read_reg(unsigned int leaf, unsigned int subleaf,
+ enum cpuid_regs_idx regidx, u32 *reg)
+{
+ u32 regs[4];
+
+ __cpuid_read(leaf, subleaf, regs);
+ *reg = regs[regidx];
+}
+
+#define cpuid_subleaf_reg(leaf, subleaf, regidx, reg) { \
+ static_assert(sizeof(*(reg)) == 4); \
+ __cpuid_read_reg(leaf, subleaf, regidx, (u32 *)(reg)); \
+}
+
+#define cpuid_leaf_reg(leaf, regidx, reg) { \
+ static_assert(sizeof(*(reg)) == 4); \
+ __cpuid_read_reg(leaf, 0, regidx, (u32 *)(reg)); \
+}
+
static __always_inline bool cpuid_function_is_indexed(u32 function)
{
switch (function) {