Skip to content

Commit adc5742

Browse files
Ahmed S. DarwishIngo Molnar
authored andcommitted
x86/cpuid: Refactor <asm/cpuid.h>
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 <[email protected]> Signed-off-by: Ahmed S. Darwish <[email protected]> Signed-off-by: Ingo Molnar <[email protected]> Cc: Andrew Cooper <[email protected]> Cc: "H. Peter Anvin" <[email protected]> Cc: John Ogness <[email protected]> Cc: "Ahmed S. Darwish" <[email protected]> Cc: [email protected] Link: https://lore.kernel.org/r/[email protected]
1 parent 82070bc commit adc5742

File tree

3 files changed

+238
-216
lines changed

3 files changed

+238
-216
lines changed

arch/x86/include/asm/cpuid.h

Lines changed: 1 addition & 216 deletions
Original file line numberDiff line numberDiff line change
@@ -1,223 +1,8 @@
11
/* SPDX-License-Identifier: GPL-2.0 */
2-
/*
3-
* CPUID-related helpers/definitions
4-
*/
52

63
#ifndef _ASM_X86_CPUID_H
74
#define _ASM_X86_CPUID_H
85

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

2238
#endif /* _ASM_X86_CPUID_H */

0 commit comments

Comments
 (0)