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