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