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 11 struct cpuid_regs { 12 u32 eax, ebx, ecx, edx; 13 }; 14 15 enum cpuid_regs_idx { 16 CPUID_EAX = 0, 17 CPUID_EBX, 18 CPUID_ECX, 19 CPUID_EDX, 20 }; 21 22 #ifdef CONFIG_X86_32 23 extern int have_cpuid_p(void); 24 #else 25 static inline int have_cpuid_p(void) 26 { 27 return 1; 28 } 29 #endif 30 static 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) \ 44 static 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 */ 56 native_cpuid_reg(eax) 57 native_cpuid_reg(ebx) 58 native_cpuid_reg(ecx) 59 native_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 */ 72 static 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 */ 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) 85 { 86 *eax = op; 87 *ecx = count; 88 __cpuid(eax, ebx, ecx, edx); 89 } 90 91 /* 92 * CPUID functions returning a single datum 93 */ 94 static 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 103 static 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 112 static 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 121 static 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 130 static __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 156 static 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 */ 172