]> www.infradead.org Git - users/jedix/linux-maple.git/commitdiff
x86/cpuid: Refactor <asm/cpuid.h>
authorAhmed S. Darwish <darwi@linutronix.de>
Mon, 17 Mar 2025 22:18:20 +0000 (23:18 +0100)
committerIngo Molnar <mingo@kernel.org>
Wed, 19 Mar 2025 10:19:22 +0000 (11:19 +0100)
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: "Ahmed S. Darwish" <darwi@linutronix.de>
Cc: x86-cpuid@lists.linux.dev
Link: https://lore.kernel.org/r/20250317221824.3738853-2-mingo@kernel.org
arch/x86/include/asm/cpuid.h
arch/x86/include/asm/cpuid/api.h [new file with mode: 0644]
arch/x86/include/asm/cpuid/types.h [new file with mode: 0644]

index a92e4b08820adc26402e6dcb77b6688baabc8a43..d5749b25fa10c6480c2084c1c0d4c04800430d79 100644 (file)
@@ -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 (file)
index 0000000..4d1da9c
--- /dev/null
@@ -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 (file)
index 0000000..724002a
--- /dev/null
@@ -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 */