Linux Audio

Check our new training course

Loading...
Note: File does not exist in v4.6.
  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, &ebx, &ecx, &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, &ebx, &ecx, &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, &ebx, &ecx, &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, &ebx, &ecx, &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(base, &eax, &signature[0], &signature[1], &signature[2]);
162
163		if (!memcmp(sig, signature, 12) &&
164		    (leaves == 0 || ((eax - base) >= leaves)))
165			return base;
166	}
167
168	return 0;
169}
170
171#endif /* _ASM_X86_CPUID_H */