xref: /linux/arch/x86/include/asm/cpuid.h (revision f96a974170b749e3a56844e25b31d46a7233b6f6)
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 <linux/types.h>
10 
11 #include <asm/string.h>
12 
13 struct cpuid_regs {
14 	u32 eax, ebx, ecx, edx;
15 };
16 
17 enum cpuid_regs_idx {
18 	CPUID_EAX = 0,
19 	CPUID_EBX,
20 	CPUID_ECX,
21 	CPUID_EDX,
22 };
23 
24 #define CPUID_LEAF_MWAIT	0x5
25 #define CPUID_LEAF_DCA		0x9
26 #define CPUID_LEAF_XSTATE	0x0d
27 #define CPUID_LEAF_TSC		0x15
28 #define CPUID_LEAF_FREQ		0x16
29 #define CPUID_LEAF_TILE		0x1d
30 
31 #ifdef CONFIG_X86_32
32 bool have_cpuid_p(void);
33 #else
34 static inline bool have_cpuid_p(void)
35 {
36 	return true;
37 }
38 #endif
39 static inline void native_cpuid(unsigned int *eax, unsigned int *ebx,
40 				unsigned int *ecx, unsigned int *edx)
41 {
42 	/* ecx is often an input as well as an output. */
43 	asm volatile("cpuid"
44 	    : "=a" (*eax),
45 	      "=b" (*ebx),
46 	      "=c" (*ecx),
47 	      "=d" (*edx)
48 	    : "0" (*eax), "2" (*ecx)
49 	    : "memory");
50 }
51 
52 #define native_cpuid_reg(reg)					\
53 static inline unsigned int native_cpuid_##reg(unsigned int op)	\
54 {								\
55 	unsigned int eax = op, ebx, ecx = 0, edx;		\
56 								\
57 	native_cpuid(&eax, &ebx, &ecx, &edx);			\
58 								\
59 	return reg;						\
60 }
61 
62 /*
63  * Native CPUID functions returning a single datum.
64  */
65 native_cpuid_reg(eax)
66 native_cpuid_reg(ebx)
67 native_cpuid_reg(ecx)
68 native_cpuid_reg(edx)
69 
70 #ifdef CONFIG_PARAVIRT_XXL
71 #include <asm/paravirt.h>
72 #else
73 #define __cpuid			native_cpuid
74 #endif
75 
76 /*
77  * Generic CPUID function
78  * clear %ecx since some cpus (Cyrix MII) do not set or clear %ecx
79  * resulting in stale register contents being returned.
80  */
81 static inline void cpuid(unsigned int op,
82 			 unsigned int *eax, unsigned int *ebx,
83 			 unsigned int *ecx, unsigned int *edx)
84 {
85 	*eax = op;
86 	*ecx = 0;
87 	__cpuid(eax, ebx, ecx, edx);
88 }
89 
90 /* Some CPUID calls want 'count' to be placed in ecx */
91 static inline void cpuid_count(unsigned int op, int count,
92 			       unsigned int *eax, unsigned int *ebx,
93 			       unsigned int *ecx, unsigned int *edx)
94 {
95 	*eax = op;
96 	*ecx = count;
97 	__cpuid(eax, ebx, ecx, edx);
98 }
99 
100 /*
101  * CPUID functions returning a single datum
102  */
103 static inline unsigned int cpuid_eax(unsigned int op)
104 {
105 	unsigned int eax, ebx, ecx, edx;
106 
107 	cpuid(op, &eax, &ebx, &ecx, &edx);
108 
109 	return eax;
110 }
111 
112 static inline unsigned int cpuid_ebx(unsigned int op)
113 {
114 	unsigned int eax, ebx, ecx, edx;
115 
116 	cpuid(op, &eax, &ebx, &ecx, &edx);
117 
118 	return ebx;
119 }
120 
121 static inline unsigned int cpuid_ecx(unsigned int op)
122 {
123 	unsigned int eax, ebx, ecx, edx;
124 
125 	cpuid(op, &eax, &ebx, &ecx, &edx);
126 
127 	return ecx;
128 }
129 
130 static inline unsigned int cpuid_edx(unsigned int op)
131 {
132 	unsigned int eax, ebx, ecx, edx;
133 
134 	cpuid(op, &eax, &ebx, &ecx, &edx);
135 
136 	return edx;
137 }
138 
139 static inline void __cpuid_read(unsigned int leaf, unsigned int subleaf, u32 *regs)
140 {
141 	regs[CPUID_EAX] = leaf;
142 	regs[CPUID_ECX] = subleaf;
143 	__cpuid(regs + CPUID_EAX, regs + CPUID_EBX, regs + CPUID_ECX, regs + CPUID_EDX);
144 }
145 
146 #define cpuid_subleaf(leaf, subleaf, regs) {		\
147 	static_assert(sizeof(*(regs)) == 16);		\
148 	__cpuid_read(leaf, subleaf, (u32 *)(regs));	\
149 }
150 
151 #define cpuid_leaf(leaf, regs) {			\
152 	static_assert(sizeof(*(regs)) == 16);		\
153 	__cpuid_read(leaf, 0, (u32 *)(regs));		\
154 }
155 
156 static inline void __cpuid_read_reg(unsigned int leaf, unsigned int subleaf,
157 				    enum cpuid_regs_idx regidx, u32 *reg)
158 {
159 	u32 regs[4];
160 
161 	__cpuid_read(leaf, subleaf, regs);
162 	*reg = regs[regidx];
163 }
164 
165 #define cpuid_subleaf_reg(leaf, subleaf, regidx, reg) {		\
166 	static_assert(sizeof(*(reg)) == 4);			\
167 	__cpuid_read_reg(leaf, subleaf, regidx, (u32 *)(reg));	\
168 }
169 
170 #define cpuid_leaf_reg(leaf, regidx, reg) {			\
171 	static_assert(sizeof(*(reg)) == 4);			\
172 	__cpuid_read_reg(leaf, 0, regidx, (u32 *)(reg));	\
173 }
174 
175 static __always_inline bool cpuid_function_is_indexed(u32 function)
176 {
177 	switch (function) {
178 	case 4:
179 	case 7:
180 	case 0xb:
181 	case 0xd:
182 	case 0xf:
183 	case 0x10:
184 	case 0x12:
185 	case 0x14:
186 	case 0x17:
187 	case 0x18:
188 	case 0x1d:
189 	case 0x1e:
190 	case 0x1f:
191 	case 0x24:
192 	case 0x8000001d:
193 		return true;
194 	}
195 
196 	return false;
197 }
198 
199 #define for_each_possible_hypervisor_cpuid_base(function) \
200 	for (function = 0x40000000; function < 0x40010000; function += 0x100)
201 
202 static inline uint32_t hypervisor_cpuid_base(const char *sig, uint32_t leaves)
203 {
204 	uint32_t base, eax, signature[3];
205 
206 	for_each_possible_hypervisor_cpuid_base(base) {
207 		cpuid(base, &eax, &signature[0], &signature[1], &signature[2]);
208 
209 		/*
210 		 * This must not compile to "call memcmp" because it's called
211 		 * from PVH early boot code before instrumentation is set up
212 		 * and memcmp() itself may be instrumented.
213 		 */
214 		if (!__builtin_memcmp(sig, signature, 12) &&
215 		    (leaves == 0 || ((eax - base) >= leaves)))
216 			return base;
217 	}
218 
219 	return 0;
220 }
221 
222 #endif /* _ASM_X86_CPUID_H */
223