* [PATCH 1/5] x86/cpuid: Refactor <asm/cpuid.h>
2025-03-17 22:30 [PATCH 0/5] x86/cpu: Introduce <asm/cpuid/types.h> and <asm/cpuid/api.h> and clean them up mingo
@ 2025-03-17 22:30 ` mingo
2025-03-17 22:30 ` [PATCH 2/5] x86/cpuid: Clean up <asm/cpuid/types.h> mingo
` (5 subsequent siblings)
6 siblings, 0 replies; 22+ messages in thread
From: mingo @ 2025-03-17 22:30 UTC (permalink / raw)
To: linux-kernel
Cc: Juergen Gross, Stefano Stabellini, Ahmed S . Darwish,
Andrew Cooper, H . Peter Anvin, John Ogness, Linus Torvalds,
Peter Zijlstra, Borislav Petkov, Thomas Gleixner
From: "Ahmed S. Darwish" <darwi@linutronix.de>
In preparation for future commits where CPUID headers will be expanded,
refactor the CPUID header <asm/cpuid.h> into:
asm/cpuid/
├── api.h
└── types.h
Move the CPUID data structures into <asm/cpuid/types.h> and the access
APIs into <asm/cpuid/api.h>. Let <asm/cpuid.h> be just an include of
<asm/cpuid/api.h> so that existing call sites do not break.
Suggested-by: Ingo Molnar <mingo@kernel.org>
Signed-off-by: Ahmed S. Darwish <darwi@linutronix.de>
Signed-off-by: Ingo Molnar <mingo@kernel.org>
Cc: Andrew Cooper <andrew.cooper3@citrix.com>
Cc: "H. Peter Anvin" <hpa@zytor.com>
Cc: John Ogness <john.ogness@linutronix.de>
Cc: x86-cpuid@lists.linux.dev
Link: https://lore.kernel.org/r/20250317164745.4754-3-darwi@linutronix.de
---
arch/x86/include/asm/cpuid.h | 217 +--------------------------------------------------------
arch/x86/include/asm/cpuid/api.h | 208 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
arch/x86/include/asm/cpuid/types.h | 29 ++++++++
3 files changed, 238 insertions(+), 216 deletions(-)
diff --git a/arch/x86/include/asm/cpuid.h b/arch/x86/include/asm/cpuid.h
index a92e4b08820a..d5749b25fa10 100644
--- a/arch/x86/include/asm/cpuid.h
+++ b/arch/x86/include/asm/cpuid.h
@@ -1,223 +1,8 @@
/* SPDX-License-Identifier: GPL-2.0 */
-/*
- * CPUID-related helpers/definitions
- */
#ifndef _ASM_X86_CPUID_H
#define _ASM_X86_CPUID_H
-#include <linux/build_bug.h>
-#include <linux/types.h>
-
-#include <asm/string.h>
-
-struct cpuid_regs {
- u32 eax, ebx, ecx, edx;
-};
-
-enum cpuid_regs_idx {
- CPUID_EAX = 0,
- CPUID_EBX,
- CPUID_ECX,
- CPUID_EDX,
-};
-
-#define CPUID_LEAF_MWAIT 0x5
-#define CPUID_LEAF_DCA 0x9
-#define CPUID_LEAF_XSTATE 0x0d
-#define CPUID_LEAF_TSC 0x15
-#define CPUID_LEAF_FREQ 0x16
-#define CPUID_LEAF_TILE 0x1d
-
-#ifdef CONFIG_X86_32
-bool have_cpuid_p(void);
-#else
-static inline bool have_cpuid_p(void)
-{
- return true;
-}
-#endif
-static inline void native_cpuid(unsigned int *eax, unsigned int *ebx,
- unsigned int *ecx, unsigned int *edx)
-{
- /* ecx is often an input as well as an output. */
- asm volatile("cpuid"
- : "=a" (*eax),
- "=b" (*ebx),
- "=c" (*ecx),
- "=d" (*edx)
- : "0" (*eax), "2" (*ecx)
- : "memory");
-}
-
-#define native_cpuid_reg(reg) \
-static inline unsigned int native_cpuid_##reg(unsigned int op) \
-{ \
- unsigned int eax = op, ebx, ecx = 0, edx; \
- \
- native_cpuid(&eax, &ebx, &ecx, &edx); \
- \
- return reg; \
-}
-
-/*
- * Native CPUID functions returning a single datum.
- */
-native_cpuid_reg(eax)
-native_cpuid_reg(ebx)
-native_cpuid_reg(ecx)
-native_cpuid_reg(edx)
-
-#ifdef CONFIG_PARAVIRT_XXL
-#include <asm/paravirt.h>
-#else
-#define __cpuid native_cpuid
-#endif
-
-/*
- * Generic CPUID function
- * clear %ecx since some cpus (Cyrix MII) do not set or clear %ecx
- * resulting in stale register contents being returned.
- */
-static inline void cpuid(unsigned int op,
- unsigned int *eax, unsigned int *ebx,
- unsigned int *ecx, unsigned int *edx)
-{
- *eax = op;
- *ecx = 0;
- __cpuid(eax, ebx, ecx, edx);
-}
-
-/* Some CPUID calls want 'count' to be placed in ecx */
-static inline void cpuid_count(unsigned int op, int count,
- unsigned int *eax, unsigned int *ebx,
- unsigned int *ecx, unsigned int *edx)
-{
- *eax = op;
- *ecx = count;
- __cpuid(eax, ebx, ecx, edx);
-}
-
-/*
- * CPUID functions returning a single datum
- */
-static inline unsigned int cpuid_eax(unsigned int op)
-{
- unsigned int eax, ebx, ecx, edx;
-
- cpuid(op, &eax, &ebx, &ecx, &edx);
-
- return eax;
-}
-
-static inline unsigned int cpuid_ebx(unsigned int op)
-{
- unsigned int eax, ebx, ecx, edx;
-
- cpuid(op, &eax, &ebx, &ecx, &edx);
-
- return ebx;
-}
-
-static inline unsigned int cpuid_ecx(unsigned int op)
-{
- unsigned int eax, ebx, ecx, edx;
-
- cpuid(op, &eax, &ebx, &ecx, &edx);
-
- return ecx;
-}
-
-static inline unsigned int cpuid_edx(unsigned int op)
-{
- unsigned int eax, ebx, ecx, edx;
-
- cpuid(op, &eax, &ebx, &ecx, &edx);
-
- 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) {
- case 4:
- case 7:
- case 0xb:
- case 0xd:
- case 0xf:
- case 0x10:
- case 0x12:
- case 0x14:
- case 0x17:
- case 0x18:
- case 0x1d:
- case 0x1e:
- case 0x1f:
- case 0x24:
- case 0x8000001d:
- return true;
- }
-
- return false;
-}
-
-#define for_each_possible_hypervisor_cpuid_base(function) \
- for (function = 0x40000000; function < 0x40010000; function += 0x100)
-
-static inline uint32_t hypervisor_cpuid_base(const char *sig, uint32_t leaves)
-{
- uint32_t base, eax, signature[3];
-
- for_each_possible_hypervisor_cpuid_base(base) {
- cpuid(base, &eax, &signature[0], &signature[1], &signature[2]);
-
- /*
- * This must not compile to "call memcmp" because it's called
- * from PVH early boot code before instrumentation is set up
- * and memcmp() itself may be instrumented.
- */
- if (!__builtin_memcmp(sig, signature, 12) &&
- (leaves == 0 || ((eax - base) >= leaves)))
- return base;
- }
-
- return 0;
-}
+#include <asm/cpuid/api.h>
#endif /* _ASM_X86_CPUID_H */
diff --git a/arch/x86/include/asm/cpuid/api.h b/arch/x86/include/asm/cpuid/api.h
new file mode 100644
index 000000000000..4d1da9cc8b6f
--- /dev/null
+++ b/arch/x86/include/asm/cpuid/api.h
@@ -0,0 +1,208 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+
+#ifndef _ASM_X86_CPUID_API_H
+#define _ASM_X86_CPUID_API_H
+
+#include <linux/build_bug.h>
+#include <linux/types.h>
+
+#include <asm/cpuid/types.h>
+#include <asm/string.h>
+
+/*
+ * Raw CPUID accessors
+ */
+
+#ifdef CONFIG_X86_32
+bool have_cpuid_p(void);
+#else
+static inline bool have_cpuid_p(void)
+{
+ return true;
+}
+#endif
+static inline void native_cpuid(unsigned int *eax, unsigned int *ebx,
+ unsigned int *ecx, unsigned int *edx)
+{
+ /* ecx is often an input as well as an output. */
+ asm volatile("cpuid"
+ : "=a" (*eax),
+ "=b" (*ebx),
+ "=c" (*ecx),
+ "=d" (*edx)
+ : "0" (*eax), "2" (*ecx)
+ : "memory");
+}
+
+#define native_cpuid_reg(reg) \
+static inline unsigned int native_cpuid_##reg(unsigned int op) \
+{ \
+ unsigned int eax = op, ebx, ecx = 0, edx; \
+ \
+ native_cpuid(&eax, &ebx, &ecx, &edx); \
+ \
+ return reg; \
+}
+
+/*
+ * Native CPUID functions returning a single datum.
+ */
+native_cpuid_reg(eax)
+native_cpuid_reg(ebx)
+native_cpuid_reg(ecx)
+native_cpuid_reg(edx)
+
+#ifdef CONFIG_PARAVIRT_XXL
+#include <asm/paravirt.h>
+#else
+#define __cpuid native_cpuid
+#endif
+
+/*
+ * Generic CPUID function
+ * clear %ecx since some cpus (Cyrix MII) do not set or clear %ecx
+ * resulting in stale register contents being returned.
+ */
+static inline void cpuid(unsigned int op,
+ unsigned int *eax, unsigned int *ebx,
+ unsigned int *ecx, unsigned int *edx)
+{
+ *eax = op;
+ *ecx = 0;
+ __cpuid(eax, ebx, ecx, edx);
+}
+
+/* Some CPUID calls want 'count' to be placed in ecx */
+static inline void cpuid_count(unsigned int op, int count,
+ unsigned int *eax, unsigned int *ebx,
+ unsigned int *ecx, unsigned int *edx)
+{
+ *eax = op;
+ *ecx = count;
+ __cpuid(eax, ebx, ecx, edx);
+}
+
+/*
+ * CPUID functions returning a single datum
+ */
+
+static inline unsigned int cpuid_eax(unsigned int op)
+{
+ unsigned int eax, ebx, ecx, edx;
+
+ cpuid(op, &eax, &ebx, &ecx, &edx);
+
+ return eax;
+}
+
+static inline unsigned int cpuid_ebx(unsigned int op)
+{
+ unsigned int eax, ebx, ecx, edx;
+
+ cpuid(op, &eax, &ebx, &ecx, &edx);
+
+ return ebx;
+}
+
+static inline unsigned int cpuid_ecx(unsigned int op)
+{
+ unsigned int eax, ebx, ecx, edx;
+
+ cpuid(op, &eax, &ebx, &ecx, &edx);
+
+ return ecx;
+}
+
+static inline unsigned int cpuid_edx(unsigned int op)
+{
+ unsigned int eax, ebx, ecx, edx;
+
+ cpuid(op, &eax, &ebx, &ecx, &edx);
+
+ 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) {
+ case 4:
+ case 7:
+ case 0xb:
+ case 0xd:
+ case 0xf:
+ case 0x10:
+ case 0x12:
+ case 0x14:
+ case 0x17:
+ case 0x18:
+ case 0x1d:
+ case 0x1e:
+ case 0x1f:
+ case 0x24:
+ case 0x8000001d:
+ return true;
+ }
+
+ return false;
+}
+
+#define for_each_possible_hypervisor_cpuid_base(function) \
+ for (function = 0x40000000; function < 0x40010000; function += 0x100)
+
+static inline uint32_t hypervisor_cpuid_base(const char *sig, uint32_t leaves)
+{
+ uint32_t base, eax, signature[3];
+
+ for_each_possible_hypervisor_cpuid_base(base) {
+ cpuid(base, &eax, &signature[0], &signature[1], &signature[2]);
+
+ /*
+ * This must not compile to "call memcmp" because it's called
+ * from PVH early boot code before instrumentation is set up
+ * and memcmp() itself may be instrumented.
+ */
+ if (!__builtin_memcmp(sig, signature, 12) &&
+ (leaves == 0 || ((eax - base) >= leaves)))
+ return base;
+ }
+
+ return 0;
+}
+
+#endif /* _ASM_X86_CPUID_API_H */
diff --git a/arch/x86/include/asm/cpuid/types.h b/arch/x86/include/asm/cpuid/types.h
new file mode 100644
index 000000000000..724002aaff4d
--- /dev/null
+++ b/arch/x86/include/asm/cpuid/types.h
@@ -0,0 +1,29 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef _ASM_X86_CPUID_TYPES_H
+#define _ASM_X86_CPUID_TYPES_H
+
+#include <linux/types.h>
+
+/*
+ * Types for raw CPUID access
+ */
+
+struct cpuid_regs {
+ u32 eax, ebx, ecx, edx;
+};
+
+enum cpuid_regs_idx {
+ CPUID_EAX = 0,
+ CPUID_EBX,
+ CPUID_ECX,
+ CPUID_EDX,
+};
+
+#define CPUID_LEAF_MWAIT 0x5
+#define CPUID_LEAF_DCA 0x9
+#define CPUID_LEAF_XSTATE 0x0d
+#define CPUID_LEAF_TSC 0x15
+#define CPUID_LEAF_FREQ 0x16
+#define CPUID_LEAF_TILE 0x1d
+
+#endif /* _ASM_X86_CPUID_TYPES_H */
--
2.45.2
^ permalink raw reply related [flat|nested] 22+ messages in thread* [PATCH 2/5] x86/cpuid: Clean up <asm/cpuid/types.h>
2025-03-17 22:30 [PATCH 0/5] x86/cpu: Introduce <asm/cpuid/types.h> and <asm/cpuid/api.h> and clean them up mingo
2025-03-17 22:30 ` [PATCH 1/5] x86/cpuid: Refactor <asm/cpuid.h> mingo
@ 2025-03-17 22:30 ` mingo
2025-03-17 22:30 ` [PATCH 3/5] x86/cpuid: Clean up <asm/cpuid/api.h> mingo
` (4 subsequent siblings)
6 siblings, 0 replies; 22+ messages in thread
From: mingo @ 2025-03-17 22:30 UTC (permalink / raw)
To: linux-kernel
Cc: Juergen Gross, Stefano Stabellini, Ahmed S . Darwish,
Andrew Cooper, H . Peter Anvin, John Ogness, Linus Torvalds,
Peter Zijlstra, Borislav Petkov, Thomas Gleixner
From: Ingo Molnar <mingo@kernel.org>
- We have 0x0d, 0x9 and 0x1d as literals for the CPUID_LEAF definitions,
pick a single, consistent style of 0xZZ literals.
- Likewise, harmonize the style of the 'struct cpuid_regs' list of
registers with that of 'enum cpuid_regs_idx'. Because while computers
don't care about unnecessary visual noise, humans do.
Signed-off-by: Ingo Molnar <mingo@kernel.org>
Cc: Ahmed S. Darwish <darwi@linutronix.de>
Cc: Andrew Cooper <andrew.cooper3@citrix.com>
Cc: "H. Peter Anvin" <hpa@zytor.com>
Cc: John Ogness <john.ogness@linutronix.de>
Cc: x86-cpuid@lists.linux.dev
Link: https://lore.kernel.org/r/20250317164745.4754-3-darwi@linutronix.de
---
arch/x86/include/asm/cpuid/types.h | 11 +++++++----
1 file changed, 7 insertions(+), 4 deletions(-)
diff --git a/arch/x86/include/asm/cpuid/types.h b/arch/x86/include/asm/cpuid/types.h
index 724002aaff4d..8582e27e836d 100644
--- a/arch/x86/include/asm/cpuid/types.h
+++ b/arch/x86/include/asm/cpuid/types.h
@@ -5,11 +5,14 @@
#include <linux/types.h>
/*
- * Types for raw CPUID access
+ * Types for raw CPUID access:
*/
struct cpuid_regs {
- u32 eax, ebx, ecx, edx;
+ u32 eax;
+ u32 ebx;
+ u32 ecx;
+ u32 edx;
};
enum cpuid_regs_idx {
@@ -19,8 +22,8 @@ enum cpuid_regs_idx {
CPUID_EDX,
};
-#define CPUID_LEAF_MWAIT 0x5
-#define CPUID_LEAF_DCA 0x9
+#define CPUID_LEAF_MWAIT 0x05
+#define CPUID_LEAF_DCA 0x09
#define CPUID_LEAF_XSTATE 0x0d
#define CPUID_LEAF_TSC 0x15
#define CPUID_LEAF_FREQ 0x16
--
2.45.2
^ permalink raw reply related [flat|nested] 22+ messages in thread* [PATCH 3/5] x86/cpuid: Clean up <asm/cpuid/api.h>
2025-03-17 22:30 [PATCH 0/5] x86/cpu: Introduce <asm/cpuid/types.h> and <asm/cpuid/api.h> and clean them up mingo
2025-03-17 22:30 ` [PATCH 1/5] x86/cpuid: Refactor <asm/cpuid.h> mingo
2025-03-17 22:30 ` [PATCH 2/5] x86/cpuid: Clean up <asm/cpuid/types.h> mingo
@ 2025-03-17 22:30 ` mingo
2025-03-17 22:30 ` [PATCH 4/5] x86/cpuid: Standardize on u32 in <asm/cpuid/api.h> mingo
` (3 subsequent siblings)
6 siblings, 0 replies; 22+ messages in thread
From: mingo @ 2025-03-17 22:30 UTC (permalink / raw)
To: linux-kernel
Cc: Juergen Gross, Stefano Stabellini, Ahmed S . Darwish,
Andrew Cooper, H . Peter Anvin, John Ogness, Linus Torvalds,
Peter Zijlstra, Borislav Petkov, Thomas Gleixner
From: Ingo Molnar <mingo@kernel.org>
- Include <asm/cpuid/types.h> first, as is customary. This also has
the side effect of build-testing the header dependency assumptions
in the types header.
- No newline necessary after the SPDX line
- Newline necessary after inline function definitions
- Rename native_cpuid_reg() to NATIVE_CPUID_REG(): it's a CPP macro,
whose name we capitalize in such cases.
- Prettify the CONFIG_PARAVIRT_XXL inclusion block a bit
- Standardize register references in comments to EAX/EBX/ECX/etc.,
from the hodgepodge of references.
- s/cpus/CPUs because why add noise to common acronyms?
- Use u32 instead of uint32_t in hypervisor_cpuid_base(). Yes, I realize
uint32_t is used in Xen code, but this is a core x86 architecture header
and we should standardize on the type that is being used overwhelmingly
in x86 architecture code. The two types are the same so there should be
no build warnings.
Signed-off-by: Ingo Molnar <mingo@kernel.org>
Cc: Ahmed S. Darwish <darwi@linutronix.de>
Cc: Andrew Cooper <andrew.cooper3@citrix.com>
Cc: "H. Peter Anvin" <hpa@zytor.com>
Cc: John Ogness <john.ogness@linutronix.de>
Cc: x86-cpuid@lists.linux.dev
Link: https://lore.kernel.org/r/20250317164745.4754-3-darwi@linutronix.de
---
arch/x86/include/asm/cpuid/api.h | 30 ++++++++++++++++--------------
1 file changed, 16 insertions(+), 14 deletions(-)
diff --git a/arch/x86/include/asm/cpuid/api.h b/arch/x86/include/asm/cpuid/api.h
index 4d1da9cc8b6f..f26926ba5289 100644
--- a/arch/x86/include/asm/cpuid/api.h
+++ b/arch/x86/include/asm/cpuid/api.h
@@ -1,16 +1,16 @@
/* SPDX-License-Identifier: GPL-2.0 */
-
#ifndef _ASM_X86_CPUID_API_H
#define _ASM_X86_CPUID_API_H
+#include <asm/cpuid/types.h>
+
#include <linux/build_bug.h>
#include <linux/types.h>
-#include <asm/cpuid/types.h>
#include <asm/string.h>
/*
- * Raw CPUID accessors
+ * Raw CPUID accessors:
*/
#ifdef CONFIG_X86_32
@@ -21,6 +21,7 @@ static inline bool have_cpuid_p(void)
return true;
}
#endif
+
static inline void native_cpuid(unsigned int *eax, unsigned int *ebx,
unsigned int *ecx, unsigned int *edx)
{
@@ -34,7 +35,7 @@ static inline void native_cpuid(unsigned int *eax, unsigned int *ebx,
: "memory");
}
-#define native_cpuid_reg(reg) \
+#define NATIVE_CPUID_REG(reg) \
static inline unsigned int native_cpuid_##reg(unsigned int op) \
{ \
unsigned int eax = op, ebx, ecx = 0, edx; \
@@ -45,22 +46,23 @@ static inline unsigned int native_cpuid_##reg(unsigned int op) \
}
/*
- * Native CPUID functions returning a single datum.
+ * Native CPUID functions returning a single datum:
*/
-native_cpuid_reg(eax)
-native_cpuid_reg(ebx)
-native_cpuid_reg(ecx)
-native_cpuid_reg(edx)
+NATIVE_CPUID_REG(eax)
+NATIVE_CPUID_REG(ebx)
+NATIVE_CPUID_REG(ecx)
+NATIVE_CPUID_REG(edx)
#ifdef CONFIG_PARAVIRT_XXL
-#include <asm/paravirt.h>
+# include <asm/paravirt.h>
#else
-#define __cpuid native_cpuid
+# define __cpuid native_cpuid
#endif
/*
* Generic CPUID function
- * clear %ecx since some cpus (Cyrix MII) do not set or clear %ecx
+ *
+ * Clear ECX since some CPUs (Cyrix MII) do not set or clear ECX
* resulting in stale register contents being returned.
*/
static inline void cpuid(unsigned int op,
@@ -72,7 +74,7 @@ static inline void cpuid(unsigned int op,
__cpuid(eax, ebx, ecx, edx);
}
-/* Some CPUID calls want 'count' to be placed in ecx */
+/* Some CPUID calls want 'count' to be placed in ECX */
static inline void cpuid_count(unsigned int op, int count,
unsigned int *eax, unsigned int *ebx,
unsigned int *ecx, unsigned int *edx)
@@ -83,7 +85,7 @@ static inline void cpuid_count(unsigned int op, int count,
}
/*
- * CPUID functions returning a single datum
+ * CPUID functions returning a single datum:
*/
static inline unsigned int cpuid_eax(unsigned int op)
--
2.45.2
^ permalink raw reply related [flat|nested] 22+ messages in thread* [PATCH 4/5] x86/cpuid: Standardize on u32 in <asm/cpuid/api.h>
2025-03-17 22:30 [PATCH 0/5] x86/cpu: Introduce <asm/cpuid/types.h> and <asm/cpuid/api.h> and clean them up mingo
` (2 preceding siblings ...)
2025-03-17 22:30 ` [PATCH 3/5] x86/cpuid: Clean up <asm/cpuid/api.h> mingo
@ 2025-03-17 22:30 ` mingo
2025-03-18 18:48 ` H. Peter Anvin
2025-03-17 22:30 ` [PATCH 5/5] x86/cpuid: Use u32 in instead of uint32_t " mingo
` (2 subsequent siblings)
6 siblings, 1 reply; 22+ messages in thread
From: mingo @ 2025-03-17 22:30 UTC (permalink / raw)
To: linux-kernel
Cc: Juergen Gross, Stefano Stabellini, Ahmed S . Darwish,
Andrew Cooper, H . Peter Anvin, John Ogness, Linus Torvalds,
Peter Zijlstra, Borislav Petkov, Thomas Gleixner
From: Ingo Molnar <mingo@kernel.org>
Convert all uses of 'unsigned int' to 'u32' in <asm/cpuid/api.h>.
This is how a lot of the call sites are doing it, and the two
types are equivalent in the C sense - but 'u32' better expresses
that these are expressions of an immutable hardware ABI.
Signed-off-by: Ingo Molnar <mingo@kernel.org>
Cc: Ahmed S. Darwish <darwi@linutronix.de>
Cc: Andrew Cooper <andrew.cooper3@citrix.com>
Cc: "H. Peter Anvin" <hpa@zytor.com>
Cc: John Ogness <john.ogness@linutronix.de>
Cc: x86-cpuid@lists.linux.dev
Link: https://lore.kernel.org/r/20250317164745.4754-3-darwi@linutronix.de
---
arch/x86/include/asm/cpuid/api.h | 40 ++++++++++++++++++++--------------------
1 file changed, 20 insertions(+), 20 deletions(-)
diff --git a/arch/x86/include/asm/cpuid/api.h b/arch/x86/include/asm/cpuid/api.h
index f26926ba5289..356db1894588 100644
--- a/arch/x86/include/asm/cpuid/api.h
+++ b/arch/x86/include/asm/cpuid/api.h
@@ -22,8 +22,8 @@ static inline bool have_cpuid_p(void)
}
#endif
-static inline void native_cpuid(unsigned int *eax, unsigned int *ebx,
- unsigned int *ecx, unsigned int *edx)
+static inline void native_cpuid(u32 *eax, u32 *ebx,
+ u32 *ecx, u32 *edx)
{
/* ecx is often an input as well as an output. */
asm volatile("cpuid"
@@ -36,9 +36,9 @@ static inline void native_cpuid(unsigned int *eax, unsigned int *ebx,
}
#define NATIVE_CPUID_REG(reg) \
-static inline unsigned int native_cpuid_##reg(unsigned int op) \
+static inline u32 native_cpuid_##reg(u32 op) \
{ \
- unsigned int eax = op, ebx, ecx = 0, edx; \
+ u32 eax = op, ebx, ecx = 0, edx; \
\
native_cpuid(&eax, &ebx, &ecx, &edx); \
\
@@ -65,9 +65,9 @@ NATIVE_CPUID_REG(edx)
* Clear ECX since some CPUs (Cyrix MII) do not set or clear ECX
* resulting in stale register contents being returned.
*/
-static inline void cpuid(unsigned int op,
- unsigned int *eax, unsigned int *ebx,
- unsigned int *ecx, unsigned int *edx)
+static inline void cpuid(u32 op,
+ u32 *eax, u32 *ebx,
+ u32 *ecx, u32 *edx)
{
*eax = op;
*ecx = 0;
@@ -75,9 +75,9 @@ static inline void cpuid(unsigned int op,
}
/* Some CPUID calls want 'count' to be placed in ECX */
-static inline void cpuid_count(unsigned int op, int count,
- unsigned int *eax, unsigned int *ebx,
- unsigned int *ecx, unsigned int *edx)
+static inline void cpuid_count(u32 op, int count,
+ u32 *eax, u32 *ebx,
+ u32 *ecx, u32 *edx)
{
*eax = op;
*ecx = count;
@@ -88,43 +88,43 @@ static inline void cpuid_count(unsigned int op, int count,
* CPUID functions returning a single datum:
*/
-static inline unsigned int cpuid_eax(unsigned int op)
+static inline u32 cpuid_eax(u32 op)
{
- unsigned int eax, ebx, ecx, edx;
+ u32 eax, ebx, ecx, edx;
cpuid(op, &eax, &ebx, &ecx, &edx);
return eax;
}
-static inline unsigned int cpuid_ebx(unsigned int op)
+static inline u32 cpuid_ebx(u32 op)
{
- unsigned int eax, ebx, ecx, edx;
+ u32 eax, ebx, ecx, edx;
cpuid(op, &eax, &ebx, &ecx, &edx);
return ebx;
}
-static inline unsigned int cpuid_ecx(unsigned int op)
+static inline u32 cpuid_ecx(u32 op)
{
- unsigned int eax, ebx, ecx, edx;
+ u32 eax, ebx, ecx, edx;
cpuid(op, &eax, &ebx, &ecx, &edx);
return ecx;
}
-static inline unsigned int cpuid_edx(unsigned int op)
+static inline u32 cpuid_edx(u32 op)
{
- unsigned int eax, ebx, ecx, edx;
+ u32 eax, ebx, ecx, edx;
cpuid(op, &eax, &ebx, &ecx, &edx);
return edx;
}
-static inline void __cpuid_read(unsigned int leaf, unsigned int subleaf, u32 *regs)
+static inline void __cpuid_read(u32 leaf, u32 subleaf, u32 *regs)
{
regs[CPUID_EAX] = leaf;
regs[CPUID_ECX] = subleaf;
@@ -141,7 +141,7 @@ static inline void __cpuid_read(unsigned int leaf, unsigned int subleaf, u32 *re
__cpuid_read(leaf, 0, (u32 *)(regs)); \
}
-static inline void __cpuid_read_reg(unsigned int leaf, unsigned int subleaf,
+static inline void __cpuid_read_reg(u32 leaf, u32 subleaf,
enum cpuid_regs_idx regidx, u32 *reg)
{
u32 regs[4];
--
2.45.2
^ permalink raw reply related [flat|nested] 22+ messages in thread* Re: [PATCH 4/5] x86/cpuid: Standardize on u32 in <asm/cpuid/api.h>
2025-03-17 22:30 ` [PATCH 4/5] x86/cpuid: Standardize on u32 in <asm/cpuid/api.h> mingo
@ 2025-03-18 18:48 ` H. Peter Anvin
2025-03-18 19:08 ` H. Peter Anvin
2025-03-18 19:09 ` Andrew Cooper
0 siblings, 2 replies; 22+ messages in thread
From: H. Peter Anvin @ 2025-03-18 18:48 UTC (permalink / raw)
To: mingo, linux-kernel
Cc: Juergen Gross, Stefano Stabellini, Ahmed S . Darwish,
Andrew Cooper, John Ogness, Linus Torvalds, Peter Zijlstra,
Borislav Petkov, Thomas Gleixner
On March 17, 2025 3:30:38 PM PDT, mingo@kernel.org wrote:
>From: Ingo Molnar <mingo@kernel.org>
>
>Convert all uses of 'unsigned int' to 'u32' in <asm/cpuid/api.h>.
>
>This is how a lot of the call sites are doing it, and the two
>types are equivalent in the C sense - but 'u32' better expresses
>that these are expressions of an immutable hardware ABI.
>
>Signed-off-by: Ingo Molnar <mingo@kernel.org>
>Cc: Ahmed S. Darwish <darwi@linutronix.de>
>Cc: Andrew Cooper <andrew.cooper3@citrix.com>
>Cc: "H. Peter Anvin" <hpa@zytor.com>
>Cc: John Ogness <john.ogness@linutronix.de>
>Cc: x86-cpuid@lists.linux.dev
>Link: https://lore.kernel.org/r/20250317164745.4754-3-darwi@linutronix.de
>---
> arch/x86/include/asm/cpuid/api.h | 40 ++++++++++++++++++++--------------------
> 1 file changed, 20 insertions(+), 20 deletions(-)
>
>diff --git a/arch/x86/include/asm/cpuid/api.h b/arch/x86/include/asm/cpuid/api.h
>index f26926ba5289..356db1894588 100644
>--- a/arch/x86/include/asm/cpuid/api.h
>+++ b/arch/x86/include/asm/cpuid/api.h
>@@ -22,8 +22,8 @@ static inline bool have_cpuid_p(void)
> }
> #endif
>
>-static inline void native_cpuid(unsigned int *eax, unsigned int *ebx,
>- unsigned int *ecx, unsigned int *edx)
>+static inline void native_cpuid(u32 *eax, u32 *ebx,
>+ u32 *ecx, u32 *edx)
> {
> /* ecx is often an input as well as an output. */
> asm volatile("cpuid"
>@@ -36,9 +36,9 @@ static inline void native_cpuid(unsigned int *eax, unsigned int *ebx,
> }
>
> #define NATIVE_CPUID_REG(reg) \
>-static inline unsigned int native_cpuid_##reg(unsigned int op) \
>+static inline u32 native_cpuid_##reg(u32 op) \
> { \
>- unsigned int eax = op, ebx, ecx = 0, edx; \
>+ u32 eax = op, ebx, ecx = 0, edx; \
> \
> native_cpuid(&eax, &ebx, &ecx, &edx); \
> \
>@@ -65,9 +65,9 @@ NATIVE_CPUID_REG(edx)
> * Clear ECX since some CPUs (Cyrix MII) do not set or clear ECX
> * resulting in stale register contents being returned.
> */
>-static inline void cpuid(unsigned int op,
>- unsigned int *eax, unsigned int *ebx,
>- unsigned int *ecx, unsigned int *edx)
>+static inline void cpuid(u32 op,
>+ u32 *eax, u32 *ebx,
>+ u32 *ecx, u32 *edx)
> {
> *eax = op;
> *ecx = 0;
>@@ -75,9 +75,9 @@ static inline void cpuid(unsigned int op,
> }
>
> /* Some CPUID calls want 'count' to be placed in ECX */
>-static inline void cpuid_count(unsigned int op, int count,
>- unsigned int *eax, unsigned int *ebx,
>- unsigned int *ecx, unsigned int *edx)
>+static inline void cpuid_count(u32 op, int count,
>+ u32 *eax, u32 *ebx,
>+ u32 *ecx, u32 *edx)
> {
> *eax = op;
> *ecx = count;
>@@ -88,43 +88,43 @@ static inline void cpuid_count(unsigned int op, int count,
> * CPUID functions returning a single datum:
> */
>
>-static inline unsigned int cpuid_eax(unsigned int op)
>+static inline u32 cpuid_eax(u32 op)
> {
>- unsigned int eax, ebx, ecx, edx;
>+ u32 eax, ebx, ecx, edx;
>
> cpuid(op, &eax, &ebx, &ecx, &edx);
>
> return eax;
> }
>
>-static inline unsigned int cpuid_ebx(unsigned int op)
>+static inline u32 cpuid_ebx(u32 op)
> {
>- unsigned int eax, ebx, ecx, edx;
>+ u32 eax, ebx, ecx, edx;
>
> cpuid(op, &eax, &ebx, &ecx, &edx);
>
> return ebx;
> }
>
>-static inline unsigned int cpuid_ecx(unsigned int op)
>+static inline u32 cpuid_ecx(u32 op)
> {
>- unsigned int eax, ebx, ecx, edx;
>+ u32 eax, ebx, ecx, edx;
>
> cpuid(op, &eax, &ebx, &ecx, &edx);
>
> return ecx;
> }
>
>-static inline unsigned int cpuid_edx(unsigned int op)
>+static inline u32 cpuid_edx(u32 op)
> {
>- unsigned int eax, ebx, ecx, edx;
>+ u32 eax, ebx, ecx, edx;
>
> cpuid(op, &eax, &ebx, &ecx, &edx);
>
> return edx;
> }
>
>-static inline void __cpuid_read(unsigned int leaf, unsigned int subleaf, u32 *regs)
>+static inline void __cpuid_read(u32 leaf, u32 subleaf, u32 *regs)
> {
> regs[CPUID_EAX] = leaf;
> regs[CPUID_ECX] = subleaf;
>@@ -141,7 +141,7 @@ static inline void __cpuid_read(unsigned int leaf, unsigned int subleaf, u32 *re
> __cpuid_read(leaf, 0, (u32 *)(regs)); \
> }
>
>-static inline void __cpuid_read_reg(unsigned int leaf, unsigned int subleaf,
>+static inline void __cpuid_read_reg(u32 leaf, u32 subleaf,
> enum cpuid_regs_idx regidx, u32 *reg)
> {
> u32 regs[4];
So in addition to avoid the in/out pointer hack, I would like to point out that cpuid() is now *exactly* the same as cpuid_count with a count of 0 (which is probably a good idea anyway.)
One more thing is that we ought to be able to make cpuid a const function, allowing the compiler to elide multiple calls. (Slight warning for feature-enabling MSRs changing CPUID), but that would require changing the API to returning a structure, since a pure or const structure can't return values by reference.
^ permalink raw reply [flat|nested] 22+ messages in thread* Re: [PATCH 4/5] x86/cpuid: Standardize on u32 in <asm/cpuid/api.h>
2025-03-18 18:48 ` H. Peter Anvin
@ 2025-03-18 19:08 ` H. Peter Anvin
2025-03-18 19:09 ` Andrew Cooper
1 sibling, 0 replies; 22+ messages in thread
From: H. Peter Anvin @ 2025-03-18 19:08 UTC (permalink / raw)
To: mingo, linux-kernel
Cc: Juergen Gross, Stefano Stabellini, Ahmed S . Darwish,
Andrew Cooper, John Ogness, Linus Torvalds, Peter Zijlstra,
Borislav Petkov, Thomas Gleixner
[-- Attachment #1: Type: text/plain, Size: 516 bytes --]
On 3/18/25 11:48, H. Peter Anvin wrote:
>
> One more thing is that we ought to be able to make cpuid a const
> function, allowing the compiler to elide multiple calls. (Slight warning
> for feature-enabling MSRs changing CPUID), but that would require
> changing the API to returning a structure, since a pure or const
> structure can't return values by reference.
>
So I experimented (test included) and found that gcc 14.2 does not seem
to merge the cpuid calls in this code, whereas clang 19.1 does.
-hpa
[-- Attachment #2: cpuid.c --]
[-- Type: text/x-csrc, Size: 1262 bytes --]
#include <inttypes.h>
#include <stdio.h>
typedef uint32_t u32;
struct cpuid {
u32 ebx;
u32 edx;
u32 ecx;
u32 eax;
};
static inline __attribute__((const)) struct cpuid
cpuid(u32 leaf, u32 subleaf)
{
struct cpuid rv;
asm("cpuid"
: "=a" (rv.eax), "=c" (rv.ecx), "=d" (rv.edx), "=b" (rv.ebx)
: "a" (leaf), "c" (subleaf));
return rv;
}
static inline __attribute__((const)) u32
cpuid_eax(u32 leaf, u32 subleaf)
{
struct cpuid rv = cpuid(leaf, subleaf);
return rv.eax;
}
static inline __attribute__((const)) u32
cpuid_ecx(u32 leaf, u32 subleaf)
{
struct cpuid rv = cpuid(leaf, subleaf);
return rv.ecx;
}
static inline __attribute__((const)) u32
cpuid_edx(u32 leaf, u32 subleaf)
{
struct cpuid rv = cpuid(leaf, subleaf);
return rv.edx;
}
static inline __attribute__((const)) u32
cpuid_ebx(u32 leaf, u32 subleaf)
{
struct cpuid rv = cpuid(leaf, subleaf);
return rv.ebx;
}
u32 eax(u32 leaf, u32 subleaf)
{
return cpuid_eax(leaf, subleaf);
}
struct cpuid _cpuid(u32 leaf, u32 subleaf)
{
return cpuid(leaf, subleaf);
}
int test_cpuid(void)
{
int found = 0;
found += !!(cpuid_edx(1, 0) & (1 << 26)); /* SSE2 */
found += !!(cpuid_ecx(1, 0) & (1 << 0)); /* SSE3 */
found += !!(cpuid(1, 0).ecx & (1 << 9)); /* SSSE3 */
return found;
}
^ permalink raw reply [flat|nested] 22+ messages in thread* Re: [PATCH 4/5] x86/cpuid: Standardize on u32 in <asm/cpuid/api.h>
2025-03-18 18:48 ` H. Peter Anvin
2025-03-18 19:08 ` H. Peter Anvin
@ 2025-03-18 19:09 ` Andrew Cooper
2025-03-18 19:25 ` H. Peter Anvin
1 sibling, 1 reply; 22+ messages in thread
From: Andrew Cooper @ 2025-03-18 19:09 UTC (permalink / raw)
To: H. Peter Anvin, mingo, linux-kernel
Cc: Juergen Gross, Stefano Stabellini, Ahmed S . Darwish, John Ogness,
Linus Torvalds, Peter Zijlstra, Borislav Petkov, Thomas Gleixner
On 18/03/2025 6:48 pm, H. Peter Anvin wrote:
> One more thing is that we ought to be able to make cpuid a const function, allowing the compiler to elide multiple calls. (Slight warning for feature-enabling MSRs changing CPUID), but that would require changing the API to returning a structure, since a pure or const structure can't return values by reference.
It's not only the feature-enabling MSRs. It's also OSXSAVE/OSPKE/etc in
CR4, and on Intel CPUs, the CPUID instruction still has a side effect
for microcode patch revision MSR.
There are a few too many side effects to call it const/pure.
That said, when experimenting with the same in Xen, there was nothing
interesting the compiler could do with const/pure because of how the
existing logic is laid out. Removing volatile and the memory clobber
however did allow the compiler to make slightly better code.
~Andrew
^ permalink raw reply [flat|nested] 22+ messages in thread
* Re: [PATCH 4/5] x86/cpuid: Standardize on u32 in <asm/cpuid/api.h>
2025-03-18 19:09 ` Andrew Cooper
@ 2025-03-18 19:25 ` H. Peter Anvin
2025-03-18 19:44 ` Andrew Cooper
2025-03-19 8:16 ` Ahmed S. Darwish
0 siblings, 2 replies; 22+ messages in thread
From: H. Peter Anvin @ 2025-03-18 19:25 UTC (permalink / raw)
To: Andrew Cooper, mingo, linux-kernel
Cc: Juergen Gross, Stefano Stabellini, Ahmed S . Darwish, John Ogness,
Linus Torvalds, Peter Zijlstra, Borislav Petkov, Thomas Gleixner
On March 18, 2025 12:09:59 PM PDT, Andrew Cooper <andrew.cooper3@citrix.com> wrote:
>On 18/03/2025 6:48 pm, H. Peter Anvin wrote:
>> One more thing is that we ought to be able to make cpuid a const function, allowing the compiler to elide multiple calls. (Slight warning for feature-enabling MSRs changing CPUID), but that would require changing the API to returning a structure, since a pure or const structure can't return values by reference.
>
>It's not only the feature-enabling MSRs. It's also OSXSAVE/OSPKE/etc in
>CR4, and on Intel CPUs, the CPUID instruction still has a side effect
>for microcode patch revision MSR.
>
>There are a few too many side effects to call it const/pure.
>
>That said, when experimenting with the same in Xen, there was nothing
>interesting the compiler could do with const/pure because of how the
>existing logic is laid out. Removing volatile and the memory clobber
>however did allow the compiler to make slightly better code.
>
>~Andrew
Well, I guess I lump CRs, DRs and MSRs together. There is also CPUID for serialization, which is really a totally different use for the same instruction.
tglx has suggested that we should cache or even preload the cpuid data (the latter would have the potential advantage of making the memory data structures a little easier to manage, given the very large potential space.)
The biggest issue is that there is no general mechanism for detecting which cpuid leaves have subleaves, and if they do, how many. I *believe* all existing subleaf sets are dense, but one could at least hypothetically see a vendor or VM define a CPUID leaf with a sparse subleaf set.
^ permalink raw reply [flat|nested] 22+ messages in thread
* Re: [PATCH 4/5] x86/cpuid: Standardize on u32 in <asm/cpuid/api.h>
2025-03-18 19:25 ` H. Peter Anvin
@ 2025-03-18 19:44 ` Andrew Cooper
2025-03-19 8:16 ` Ahmed S. Darwish
1 sibling, 0 replies; 22+ messages in thread
From: Andrew Cooper @ 2025-03-18 19:44 UTC (permalink / raw)
To: H. Peter Anvin, mingo, linux-kernel
Cc: Juergen Gross, Stefano Stabellini, Ahmed S . Darwish, John Ogness,
Linus Torvalds, Peter Zijlstra, Borislav Petkov, Thomas Gleixner
On 18/03/2025 7:25 pm, H. Peter Anvin wrote:
> On March 18, 2025 12:09:59 PM PDT, Andrew Cooper <andrew.cooper3@citrix.com> wrote:
>> On 18/03/2025 6:48 pm, H. Peter Anvin wrote:
>>> One more thing is that we ought to be able to make cpuid a const function, allowing the compiler to elide multiple calls. (Slight warning for feature-enabling MSRs changing CPUID), but that would require changing the API to returning a structure, since a pure or const structure can't return values by reference.
>> It's not only the feature-enabling MSRs. It's also OSXSAVE/OSPKE/etc in
>> CR4, and on Intel CPUs, the CPUID instruction still has a side effect
>> for microcode patch revision MSR.
>>
>> There are a few too many side effects to call it const/pure.
>>
>> That said, when experimenting with the same in Xen, there was nothing
>> interesting the compiler could do with const/pure because of how the
>> existing logic is laid out. Removing volatile and the memory clobber
>> however did allow the compiler to make slightly better code.
>>
>> ~Andrew
> Well, I guess I lump CRs, DRs and MSRs together. There is also CPUID for serialization, which is really a totally different use for the same instruction.
Andy Luto got rid of all CPUID serialisation ages back. It's about the
worst of the available options, even on native. It's IRET-to-self
(doesn't exit under any virt), or SERIALISE on bleeding edge CPUs.
> tglx has suggested that we should cache or even preload the cpuid data (the latter would have the potential advantage of making the memory data structures a little easier to manage, given the very large potential space.)
>
> The biggest issue is that there is no general mechanism for detecting which cpuid leaves have subleaves, and if they do, how many. I *believe* all existing subleaf sets are dense, but one could at least hypothetically see a vendor or VM define a CPUID leaf with a sparse subleaf set.
XSTATE is sparse in general; AVX-512 being the notable absence on
Intel's client line, and AMD has LWP at subleaf 62.
But yes, these are all problems trying to maintain an in-memory copy of
the CPUID state. Maintenance of this in Xen leaves a lot to be desired.
~Andrew
^ permalink raw reply [flat|nested] 22+ messages in thread
* Re: [PATCH 4/5] x86/cpuid: Standardize on u32 in <asm/cpuid/api.h>
2025-03-18 19:25 ` H. Peter Anvin
2025-03-18 19:44 ` Andrew Cooper
@ 2025-03-19 8:16 ` Ahmed S. Darwish
1 sibling, 0 replies; 22+ messages in thread
From: Ahmed S. Darwish @ 2025-03-19 8:16 UTC (permalink / raw)
To: H. Peter Anvin
Cc: Andrew Cooper, mingo, linux-kernel, Juergen Gross,
Stefano Stabellini, John Ogness, Linus Torvalds, Peter Zijlstra,
Borislav Petkov, Thomas Gleixner
On Tue, 18 Mar 2025, H. Peter Anvin wrote:
>
> tglx has suggested that we should cache or even preload the cpuid data
> (the latter would have the potential advantage of making the memory
> data structures a little easier to manage, given the very large
> potential space.)
>
This is indeed in the patch queue that I plan to send after this leaf
cleanups one gets merged. We have a data model and CPUIDs are cached on
early boot. The cache is also refreshed during machine state changes
where the CPUIDs can change; e.g. a microcode update, PSN disable, etc.
Call sites then just do:
a = cpudata_cpuid(c, 0x0)->max_std_leaf;
b = cpudata_cpuid(c, 0x80000000)->max_ext_leaf;
struct leaf_0x1_0 *l1 = cpudata_cpuid(c, 0x1);
x = l0->cpu_vendorid_0;
y = l0->cpu_vendorid_1;
z = l0->cpu_vendorid_2;
and all the data is retrieved auto-magically from the cached tables.
The struct leaf_0xM_N C99 bitfield listings are auto generated by
x86-cpuid-db of course, just like in tools/arch/x86/kcpuid/cpuid.csv.
Thanks,
--
Ahmed S. Darwish
Linutronix GmbH
^ permalink raw reply [flat|nested] 22+ messages in thread
* [PATCH 5/5] x86/cpuid: Use u32 in instead of uint32_t in <asm/cpuid/api.h>
2025-03-17 22:30 [PATCH 0/5] x86/cpu: Introduce <asm/cpuid/types.h> and <asm/cpuid/api.h> and clean them up mingo
` (3 preceding siblings ...)
2025-03-17 22:30 ` [PATCH 4/5] x86/cpuid: Standardize on u32 in <asm/cpuid/api.h> mingo
@ 2025-03-17 22:30 ` mingo
2025-03-17 22:49 ` [PATCH 0/5] x86/cpu: Introduce <asm/cpuid/types.h> and <asm/cpuid/api.h> and clean them up Linus Torvalds
2025-03-18 11:39 ` Ahmed S. Darwish
6 siblings, 0 replies; 22+ messages in thread
From: mingo @ 2025-03-17 22:30 UTC (permalink / raw)
To: linux-kernel
Cc: Juergen Gross, Stefano Stabellini, Ahmed S . Darwish,
Andrew Cooper, H . Peter Anvin, John Ogness, Linus Torvalds,
Peter Zijlstra, Borislav Petkov, Thomas Gleixner
From: Ingo Molnar <mingo@kernel.org>
Use u32 instead of uint32_t in hypervisor_cpuid_base().
Yes, I realize uint32_t is used in Xen code et al, but this is
a core x86 architecture header and we should standardize on the
type that is being used overwhelmingly in related x86 architecture
code.
The two types are the same so there should be no build warnings.
Signed-off-by: Ingo Molnar <mingo@kernel.org>
Cc: Juergen Gross <jgross@suse.com>
Cc: Stefano Stabellini <sstabellini@kernel.org>
Cc: Ahmed S. Darwish <darwi@linutronix.de>
Cc: Andrew Cooper <andrew.cooper3@citrix.com>
Cc: "H. Peter Anvin" <hpa@zytor.com>
Cc: John Ogness <john.ogness@linutronix.de>
Cc: x86-cpuid@lists.linux.dev
Link: https://lore.kernel.org/r/20250317164745.4754-3-darwi@linutronix.de
---
arch/x86/include/asm/cpuid/api.h | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/arch/x86/include/asm/cpuid/api.h b/arch/x86/include/asm/cpuid/api.h
index 356db1894588..9c180c9cc58e 100644
--- a/arch/x86/include/asm/cpuid/api.h
+++ b/arch/x86/include/asm/cpuid/api.h
@@ -187,9 +187,9 @@ static __always_inline bool cpuid_function_is_indexed(u32 function)
#define for_each_possible_hypervisor_cpuid_base(function) \
for (function = 0x40000000; function < 0x40010000; function += 0x100)
-static inline uint32_t hypervisor_cpuid_base(const char *sig, uint32_t leaves)
+static inline u32 hypervisor_cpuid_base(const char *sig, u32 leaves)
{
- uint32_t base, eax, signature[3];
+ u32 base, eax, signature[3];
for_each_possible_hypervisor_cpuid_base(base) {
cpuid(base, &eax, &signature[0], &signature[1], &signature[2]);
--
2.45.2
^ permalink raw reply related [flat|nested] 22+ messages in thread* Re: [PATCH 0/5] x86/cpu: Introduce <asm/cpuid/types.h> and <asm/cpuid/api.h> and clean them up
2025-03-17 22:30 [PATCH 0/5] x86/cpu: Introduce <asm/cpuid/types.h> and <asm/cpuid/api.h> and clean them up mingo
` (4 preceding siblings ...)
2025-03-17 22:30 ` [PATCH 5/5] x86/cpuid: Use u32 in instead of uint32_t " mingo
@ 2025-03-17 22:49 ` Linus Torvalds
2025-03-17 23:00 ` Ingo Molnar
2025-03-18 11:39 ` Ahmed S. Darwish
6 siblings, 1 reply; 22+ messages in thread
From: Linus Torvalds @ 2025-03-17 22:49 UTC (permalink / raw)
To: mingo
Cc: linux-kernel, Juergen Gross, Stefano Stabellini,
Ahmed S . Darwish, Andrew Cooper, H . Peter Anvin, John Ogness,
Peter Zijlstra, Borislav Petkov, Thomas Gleixner
On Mon, 17 Mar 2025 at 15:30, <mingo@kernel.org> wrote:
>
> [ This is a resend with a proper SMTP setup. Apologies for the duplication. ]
Yes, now it looks correct from a DKIM standpoint.
But please still fix your name. Now your "From" line is just this:
From: mingo@kernel.org
rather than your previous series, that had a much more legible
From: Ingo Molnar <mingo@kernel.org>
in it.
No need to re-send, but for next time...
Linus
^ permalink raw reply [flat|nested] 22+ messages in thread* Re: [PATCH 0/5] x86/cpu: Introduce <asm/cpuid/types.h> and <asm/cpuid/api.h> and clean them up
2025-03-17 22:49 ` [PATCH 0/5] x86/cpu: Introduce <asm/cpuid/types.h> and <asm/cpuid/api.h> and clean them up Linus Torvalds
@ 2025-03-17 23:00 ` Ingo Molnar
0 siblings, 0 replies; 22+ messages in thread
From: Ingo Molnar @ 2025-03-17 23:00 UTC (permalink / raw)
To: Linus Torvalds
Cc: linux-kernel, Juergen Gross, Stefano Stabellini,
Ahmed S . Darwish, Andrew Cooper, H . Peter Anvin, John Ogness,
Peter Zijlstra, Borislav Petkov, Thomas Gleixner
* Linus Torvalds <torvalds@linux-foundation.org> wrote:
> On Mon, 17 Mar 2025 at 15:30, <mingo@kernel.org> wrote:
> >
> > [ This is a resend with a proper SMTP setup. Apologies for the duplication. ]
>
> Yes, now it looks correct from a DKIM standpoint.
>
> But please still fix your name. Now your "From" line is just this:
>
> From: mingo@kernel.org
>
> rather than your previous series, that had a much more legible
>
> From: Ingo Molnar <mingo@kernel.org>
>
> in it.
>
> No need to re-send, but for next time...
Oh, that's probably the result of me copy-pasting the documentation:
# https://korg.docs.kernel.org/mail.html
[sendemail]
smtpserver = mail.kernel.org
smtpserverport = 465
smtpencryption = ssl
from = [username]@kernel.org
smtpuser = [username]
Which I did as:
from = mingo@kernel.org
... while it should probably be:
from = Ingo Molnar <mingo@kernel.org>
I just did a test-send to myself, and this appears to have done the
trick.
So maybe the mail.html documentation should be updated to say:
from = "Your Real Name" <[username]@kernel.org>
or so?
Thanks,
Ingo
^ permalink raw reply [flat|nested] 22+ messages in thread
* Re: [PATCH 0/5] x86/cpu: Introduce <asm/cpuid/types.h> and <asm/cpuid/api.h> and clean them up
2025-03-17 22:30 [PATCH 0/5] x86/cpu: Introduce <asm/cpuid/types.h> and <asm/cpuid/api.h> and clean them up mingo
` (5 preceding siblings ...)
2025-03-17 22:49 ` [PATCH 0/5] x86/cpu: Introduce <asm/cpuid/types.h> and <asm/cpuid/api.h> and clean them up Linus Torvalds
@ 2025-03-18 11:39 ` Ahmed S. Darwish
2025-03-18 11:55 ` Ingo Molnar
6 siblings, 1 reply; 22+ messages in thread
From: Ahmed S. Darwish @ 2025-03-18 11:39 UTC (permalink / raw)
To: mingo
Cc: linux-kernel, Juergen Gross, Stefano Stabellini, Andrew Cooper,
H . Peter Anvin, John Ogness, Linus Torvalds, Peter Zijlstra,
Borislav Petkov, Thomas Gleixner
Hi,
On Mon, 17 Mar 2025, mingo@kernel.org wrote:
>
> From: Ingo Molnar <mingo@kernel.org>
>
> This series contains Ahmed S. Darwish's splitting up of <asm/cpuid.h>
> into <asm/cpuid/types.h> and <asm/cpuid/api.h>, followed by a couple
> of cleanups that create a more maintainable base.
>
> [ This is a resend with a proper SMTP setup. Apologies for the duplication. ]
>
Thanks a lot!
Just a small hint that I see this PQ in tip/master, merge commit
b8fefef00c0d ("Merge branch into tip/master: 'x86/cpu'"):
# New commits in x86/cpu:
ba501f14e1e6 ("x86/cpuid: Use u32 in instead of uint32_t in <asm/cpuid/api.h>")
aec28d852ed2 ("x86/cpuid: Standardize on u32 in <asm/cpuid/api.h>")
f2f828b547ab ("x86/cpuid: Clean up <asm/cpuid/api.h>")
67a7ae050e7c ("x86/cpuid: Clean up <asm/cpuid/types.h>")
02b63b33dfc9 ("x86/cpuid: Refactor <asm/cpuid.h>")
But for some reason the above 5 commits are not yet pushed to x86/cpu.
(Sorry if this is expected.)
All the best,
--
Ahmed S. Darwish
Linutronix GmbH
^ permalink raw reply [flat|nested] 22+ messages in thread* Re: [PATCH 0/5] x86/cpu: Introduce <asm/cpuid/types.h> and <asm/cpuid/api.h> and clean them up
2025-03-18 11:39 ` Ahmed S. Darwish
@ 2025-03-18 11:55 ` Ingo Molnar
0 siblings, 0 replies; 22+ messages in thread
From: Ingo Molnar @ 2025-03-18 11:55 UTC (permalink / raw)
To: Ahmed S. Darwish
Cc: linux-kernel, Juergen Gross, Stefano Stabellini, Andrew Cooper,
H . Peter Anvin, John Ogness, Linus Torvalds, Peter Zijlstra,
Borislav Petkov, Thomas Gleixner
* Ahmed S. Darwish <darwi@linutronix.de> wrote:
> Hi,
>
> On Mon, 17 Mar 2025, mingo@kernel.org wrote:
> >
> > From: Ingo Molnar <mingo@kernel.org>
> >
> > This series contains Ahmed S. Darwish's splitting up of <asm/cpuid.h>
> > into <asm/cpuid/types.h> and <asm/cpuid/api.h>, followed by a couple
> > of cleanups that create a more maintainable base.
> >
> > [ This is a resend with a proper SMTP setup. Apologies for the duplication. ]
> >
>
> Thanks a lot!
>
> Just a small hint that I see this PQ in tip/master, merge commit
> b8fefef00c0d ("Merge branch into tip/master: 'x86/cpu'"):
>
> # New commits in x86/cpu:
> ba501f14e1e6 ("x86/cpuid: Use u32 in instead of uint32_t in <asm/cpuid/api.h>")
> aec28d852ed2 ("x86/cpuid: Standardize on u32 in <asm/cpuid/api.h>")
> f2f828b547ab ("x86/cpuid: Clean up <asm/cpuid/api.h>")
> 67a7ae050e7c ("x86/cpuid: Clean up <asm/cpuid/types.h>")
> 02b63b33dfc9 ("x86/cpuid: Refactor <asm/cpuid.h>")
>
> But for some reason the above 5 commits are not yet pushed to x86/cpu.
Yeah, that was a temporary status until a bit more testing could be
done - I've pushed it out now.
Thanks,
Ingo
^ permalink raw reply [flat|nested] 22+ messages in thread