1/* SPDX-License-Identifier: GPL-2.0 */
2/*
3 * CPUID-related helpers/definitions
4 */
5
6#ifndef _ASM_X86_CPUID_H
7#define _ASM_X86_CPUID_H
8
9#include <asm/string.h>
10
11struct cpuid_regs {
12 u32 eax, ebx, ecx, edx;
13};
14
15enum cpuid_regs_idx {
16 CPUID_EAX = 0,
17 CPUID_EBX,
18 CPUID_ECX,
19 CPUID_EDX,
20};
21
22#ifdef CONFIG_X86_32
23extern int have_cpuid_p(void);
24#else
25static inline int have_cpuid_p(void)
26{
27 return 1;
28}
29#endif
30static inline void native_cpuid(unsigned int *eax, unsigned int *ebx,
31 unsigned int *ecx, unsigned int *edx)
32{
33 /* ecx is often an input as well as an output. */
34 asm volatile("cpuid"
35 : "=a" (*eax),
36 "=b" (*ebx),
37 "=c" (*ecx),
38 "=d" (*edx)
39 : "0" (*eax), "2" (*ecx)
40 : "memory");
41}
42
43#define native_cpuid_reg(reg) \
44static inline unsigned int native_cpuid_##reg(unsigned int op) \
45{ \
46 unsigned int eax = op, ebx, ecx = 0, edx; \
47 \
48 native_cpuid(&eax, &ebx, &ecx, &edx); \
49 \
50 return reg; \
51}
52
53/*
54 * Native CPUID functions returning a single datum.
55 */
56native_cpuid_reg(eax)
57native_cpuid_reg(ebx)
58native_cpuid_reg(ecx)
59native_cpuid_reg(edx)
60
61#ifdef CONFIG_PARAVIRT_XXL
62#include <asm/paravirt.h>
63#else
64#define __cpuid native_cpuid
65#endif
66
67/*
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.
71 */
72static inline void cpuid(unsigned int op,
73 unsigned int *eax, unsigned int *ebx,
74 unsigned int *ecx, unsigned int *edx)
75{
76 *eax = op;
77 *ecx = 0;
78 __cpuid(eax, ebx, ecx, edx);
79}
80
81/* Some CPUID calls want 'count' to be placed in ecx */
82static inline void cpuid_count(unsigned int op, int count,
83 unsigned int *eax, unsigned int *ebx,
84 unsigned int *ecx, unsigned int *edx)
85{
86 *eax = op;
87 *ecx = count;
88 __cpuid(eax, ebx, ecx, edx);
89}
90
91/*
92 * CPUID functions returning a single datum
93 */
94static inline unsigned int cpuid_eax(unsigned int op)
95{
96 unsigned int eax, ebx, ecx, edx;
97
98 cpuid(op, eax: &eax, ebx: &ebx, ecx: &ecx, edx: &edx);
99
100 return eax;
101}
102
103static inline unsigned int cpuid_ebx(unsigned int op)
104{
105 unsigned int eax, ebx, ecx, edx;
106
107 cpuid(op, eax: &eax, ebx: &ebx, ecx: &ecx, edx: &edx);
108
109 return ebx;
110}
111
112static inline unsigned int cpuid_ecx(unsigned int op)
113{
114 unsigned int eax, ebx, ecx, edx;
115
116 cpuid(op, eax: &eax, ebx: &ebx, ecx: &ecx, edx: &edx);
117
118 return ecx;
119}
120
121static inline unsigned int cpuid_edx(unsigned int op)
122{
123 unsigned int eax, ebx, ecx, edx;
124
125 cpuid(op, eax: &eax, ebx: &ebx, ecx: &ecx, edx: &edx);
126
127 return edx;
128}
129
130static __always_inline bool cpuid_function_is_indexed(u32 function)
131{
132 switch (function) {
133 case 4:
134 case 7:
135 case 0xb:
136 case 0xd:
137 case 0xf:
138 case 0x10:
139 case 0x12:
140 case 0x14:
141 case 0x17:
142 case 0x18:
143 case 0x1d:
144 case 0x1e:
145 case 0x1f:
146 case 0x8000001d:
147 return true;
148 }
149
150 return false;
151}
152
153#define for_each_possible_hypervisor_cpuid_base(function) \
154 for (function = 0x40000000; function < 0x40010000; function += 0x100)
155
156static inline uint32_t hypervisor_cpuid_base(const char *sig, uint32_t leaves)
157{
158 uint32_t base, eax, signature[3];
159
160 for_each_possible_hypervisor_cpuid_base(base) {
161 cpuid(op: base, eax: &eax, ebx: &signature[0], ecx: &signature[1], edx: &signature[2]);
162
163 if (!memcmp(p: sig, q: signature, size: 12) &&
164 (leaves == 0 || ((eax - base) >= leaves)))
165 return base;
166 }
167
168 return 0;
169}
170
171#endif /* _ASM_X86_CPUID_H */
172

source code of linux/arch/x86/include/asm/cpuid.h