1 /* SPDX-License-Identifier: GPL-2.0 */
3 * CPUID-related helpers/definitions
6 #ifndef _ASM_X86_CPUID_H
7 #define _ASM_X86_CPUID_H
9 #include <asm/string.h>
12 u32 eax, ebx, ecx, edx;
23 extern int have_cpuid_p(void);
25 static inline int have_cpuid_p(void)
30 static inline void native_cpuid(unsigned int *eax, unsigned int *ebx,
31 unsigned int *ecx, unsigned int *edx)
33 /* ecx is often an input as well as an output. */
39 : "0" (*eax), "2" (*ecx)
43 #define native_cpuid_reg(reg) \
44 static inline unsigned int native_cpuid_##reg(unsigned int op) \
46 unsigned int eax = op, ebx, ecx = 0, edx; \
48 native_cpuid(&eax, &ebx, &ecx, &edx); \
54 * Native CPUID functions returning a single datum.
61 #ifdef CONFIG_PARAVIRT_XXL
62 #include <asm/paravirt.h>
64 #define __cpuid native_cpuid
68 * Generic CPUID function
69 * clear %ecx since some cpus (Cyrix MII) do not set or clear %ecx
70 * resulting in stale register contents being returned.
72 static inline void cpuid(unsigned int op,
73 unsigned int *eax, unsigned int *ebx,
74 unsigned int *ecx, unsigned int *edx)
78 __cpuid(eax, ebx, ecx, edx);
81 /* Some CPUID calls want 'count' to be placed in ecx */
82 static inline void cpuid_count(unsigned int op, int count,
83 unsigned int *eax, unsigned int *ebx,
84 unsigned int *ecx, unsigned int *edx)
88 __cpuid(eax, ebx, ecx, edx);
92 * CPUID functions returning a single datum
94 static inline unsigned int cpuid_eax(unsigned int op)
96 unsigned int eax, ebx, ecx, edx;
98 cpuid(op, &eax, &ebx, &ecx, &edx);
103 static inline unsigned int cpuid_ebx(unsigned int op)
105 unsigned int eax, ebx, ecx, edx;
107 cpuid(op, &eax, &ebx, &ecx, &edx);
112 static inline unsigned int cpuid_ecx(unsigned int op)
114 unsigned int eax, ebx, ecx, edx;
116 cpuid(op, &eax, &ebx, &ecx, &edx);
121 static inline unsigned int cpuid_edx(unsigned int op)
123 unsigned int eax, ebx, ecx, edx;
125 cpuid(op, &eax, &ebx, &ecx, &edx);
130 static inline void __cpuid_read(unsigned int leaf, unsigned int subleaf, u32 *regs)
132 regs[CPUID_EAX] = leaf;
133 regs[CPUID_ECX] = subleaf;
134 __cpuid(regs + CPUID_EAX, regs + CPUID_EBX, regs + CPUID_ECX, regs + CPUID_EDX);
137 #define cpuid_subleaf(leaf, subleaf, regs) { \
138 static_assert(sizeof(*(regs)) == 16); \
139 __cpuid_read(leaf, subleaf, (u32 *)(regs)); \
142 #define cpuid_leaf(leaf, regs) { \
143 static_assert(sizeof(*(regs)) == 16); \
144 __cpuid_read(leaf, 0, (u32 *)(regs)); \
147 static inline void __cpuid_read_reg(unsigned int leaf, unsigned int subleaf,
148 enum cpuid_regs_idx regidx, u32 *reg)
152 __cpuid_read(leaf, subleaf, regs);
156 #define cpuid_subleaf_reg(leaf, subleaf, regidx, reg) { \
157 static_assert(sizeof(*(reg)) == 4); \
158 __cpuid_read_reg(leaf, subleaf, regidx, (u32 *)(reg)); \
161 #define cpuid_leaf_reg(leaf, regidx, reg) { \
162 static_assert(sizeof(*(reg)) == 4); \
163 __cpuid_read_reg(leaf, 0, regidx, (u32 *)(reg)); \
166 static __always_inline bool cpuid_function_is_indexed(u32 function)
189 #define for_each_possible_hypervisor_cpuid_base(function) \
190 for (function = 0x40000000; function < 0x40010000; function += 0x100)
192 static inline uint32_t hypervisor_cpuid_base(const char *sig, uint32_t leaves)
194 uint32_t base, eax, signature[3];
196 for_each_possible_hypervisor_cpuid_base(base) {
197 cpuid(base, &eax, &signature[0], &signature[1], &signature[2]);
199 if (!memcmp(sig, signature, 12) &&
200 (leaves == 0 || ((eax - base) >= leaves)))
207 #endif /* _ASM_X86_CPUID_H */