11965aae3SH. Peter Anvin #ifndef _ASM_X86_MICROCODE_H 21965aae3SH. Peter Anvin #define _ASM_X86_MICROCODE_H 3bb898558SAl Viro 4e1b43e3fSBorislav Petkov #define native_rdmsr(msr, val1, val2) \ 5e1b43e3fSBorislav Petkov do { \ 6e1b43e3fSBorislav Petkov u64 __val = native_read_msr((msr)); \ 7e1b43e3fSBorislav Petkov (void)((val1) = (u32)__val); \ 8e1b43e3fSBorislav Petkov (void)((val2) = (u32)(__val >> 32)); \ 9e1b43e3fSBorislav Petkov } while (0) 10e1b43e3fSBorislav Petkov 11e1b43e3fSBorislav Petkov #define native_wrmsr(msr, low, high) \ 12e1b43e3fSBorislav Petkov native_write_msr(msr, low, high) 13e1b43e3fSBorislav Petkov 14e1b43e3fSBorislav Petkov #define native_wrmsrl(msr, val) \ 15e1b43e3fSBorislav Petkov native_write_msr((msr), \ 16e1b43e3fSBorislav Petkov (u32)((u64)(val)), \ 17e1b43e3fSBorislav Petkov (u32)((u64)(val) >> 32)) 18e1b43e3fSBorislav Petkov 19bb898558SAl Viro struct cpu_signature { 20bb898558SAl Viro unsigned int sig; 21bb898558SAl Viro unsigned int pf; 22bb898558SAl Viro unsigned int rev; 23bb898558SAl Viro }; 24bb898558SAl Viro 25bb898558SAl Viro struct device; 26bb898558SAl Viro 27871b72ddSDmitry Adamushko enum ucode_state { UCODE_ERROR, UCODE_OK, UCODE_NFOUND }; 2865cef131SBorislav Petkov extern bool dis_ucode_ldr; 29871b72ddSDmitry Adamushko 30bb898558SAl Viro struct microcode_ops { 31871b72ddSDmitry Adamushko enum ucode_state (*request_microcode_user) (int cpu, 32871b72ddSDmitry Adamushko const void __user *buf, size_t size); 33bb898558SAl Viro 3448e30685SBorislav Petkov enum ucode_state (*request_microcode_fw) (int cpu, struct device *, 3548e30685SBorislav Petkov bool refresh_fw); 36bb898558SAl Viro 37bb898558SAl Viro void (*microcode_fini_cpu) (int cpu); 38871b72ddSDmitry Adamushko 39871b72ddSDmitry Adamushko /* 40871b72ddSDmitry Adamushko * The generic 'microcode_core' part guarantees that 41871b72ddSDmitry Adamushko * the callbacks below run on a target cpu when they 42871b72ddSDmitry Adamushko * are being called. 43871b72ddSDmitry Adamushko * See also the "Synchronization" section in microcode_core.c. 44871b72ddSDmitry Adamushko */ 45871b72ddSDmitry Adamushko int (*apply_microcode) (int cpu); 46871b72ddSDmitry Adamushko int (*collect_cpu_info) (int cpu, struct cpu_signature *csig); 47bb898558SAl Viro }; 48bb898558SAl Viro 49bb898558SAl Viro struct ucode_cpu_info { 50bb898558SAl Viro struct cpu_signature cpu_sig; 51bb898558SAl Viro int valid; 52bb898558SAl Viro void *mc; 53bb898558SAl Viro }; 54bb898558SAl Viro extern struct ucode_cpu_info ucode_cpu_info[]; 55bb898558SAl Viro 56bb898558SAl Viro #ifdef CONFIG_MICROCODE_INTEL 57bb898558SAl Viro extern struct microcode_ops * __init init_intel_microcode(void); 58bb898558SAl Viro #else 59bb898558SAl Viro static inline struct microcode_ops * __init init_intel_microcode(void) 60bb898558SAl Viro { 61bb898558SAl Viro return NULL; 62bb898558SAl Viro } 63bb898558SAl Viro #endif /* CONFIG_MICROCODE_INTEL */ 64bb898558SAl Viro 65bb898558SAl Viro #ifdef CONFIG_MICROCODE_AMD 66bb898558SAl Viro extern struct microcode_ops * __init init_amd_microcode(void); 67f72c1a57SBorislav Petkov extern void __exit exit_amd_microcode(void); 68bb898558SAl Viro #else 69bb898558SAl Viro static inline struct microcode_ops * __init init_amd_microcode(void) 70bb898558SAl Viro { 71bb898558SAl Viro return NULL; 72bb898558SAl Viro } 73f72c1a57SBorislav Petkov static inline void __exit exit_amd_microcode(void) {} 74bb898558SAl Viro #endif 75bb898558SAl Viro 76a8ebf6d1SFenghua Yu #ifdef CONFIG_MICROCODE_EARLY 77a8ebf6d1SFenghua Yu #define MAX_UCODE_COUNT 128 78*58ce8d6dSBorislav Petkov 79*58ce8d6dSBorislav Petkov #define QCHAR(a, b, c, d) ((a) + ((b) << 8) + ((c) << 16) + ((d) << 24)) 80*58ce8d6dSBorislav Petkov #define CPUID_INTEL1 QCHAR('G', 'e', 'n', 'u') 81*58ce8d6dSBorislav Petkov #define CPUID_INTEL2 QCHAR('i', 'n', 'e', 'I') 82*58ce8d6dSBorislav Petkov #define CPUID_INTEL3 QCHAR('n', 't', 'e', 'l') 83*58ce8d6dSBorislav Petkov #define CPUID_AMD1 QCHAR('A', 'u', 't', 'h') 84*58ce8d6dSBorislav Petkov #define CPUID_AMD2 QCHAR('e', 'n', 't', 'i') 85*58ce8d6dSBorislav Petkov #define CPUID_AMD3 QCHAR('c', 'A', 'M', 'D') 86*58ce8d6dSBorislav Petkov 87*58ce8d6dSBorislav Petkov #define CPUID_IS(a, b, c, ebx, ecx, edx) \ 88*58ce8d6dSBorislav Petkov (!((ebx ^ (a))|(edx ^ (b))|(ecx ^ (c)))) 89*58ce8d6dSBorislav Petkov 90*58ce8d6dSBorislav Petkov /* 91*58ce8d6dSBorislav Petkov * In early loading microcode phase on BSP, boot_cpu_data is not set up yet. 92*58ce8d6dSBorislav Petkov * x86_vendor() gets vendor id for BSP. 93*58ce8d6dSBorislav Petkov * 94*58ce8d6dSBorislav Petkov * In 32 bit AP case, accessing boot_cpu_data needs linear address. To simplify 95*58ce8d6dSBorislav Petkov * coding, we still use x86_vendor() to get vendor id for AP. 96*58ce8d6dSBorislav Petkov * 97*58ce8d6dSBorislav Petkov * x86_vendor() gets vendor information directly from CPUID. 98*58ce8d6dSBorislav Petkov */ 99*58ce8d6dSBorislav Petkov static inline int x86_vendor(void) 100*58ce8d6dSBorislav Petkov { 101*58ce8d6dSBorislav Petkov u32 eax = 0x00000000; 102*58ce8d6dSBorislav Petkov u32 ebx, ecx = 0, edx; 103*58ce8d6dSBorislav Petkov 104*58ce8d6dSBorislav Petkov native_cpuid(&eax, &ebx, &ecx, &edx); 105*58ce8d6dSBorislav Petkov 106*58ce8d6dSBorislav Petkov if (CPUID_IS(CPUID_INTEL1, CPUID_INTEL2, CPUID_INTEL3, ebx, ecx, edx)) 107*58ce8d6dSBorislav Petkov return X86_VENDOR_INTEL; 108*58ce8d6dSBorislav Petkov 109*58ce8d6dSBorislav Petkov if (CPUID_IS(CPUID_AMD1, CPUID_AMD2, CPUID_AMD3, ebx, ecx, edx)) 110*58ce8d6dSBorislav Petkov return X86_VENDOR_AMD; 111*58ce8d6dSBorislav Petkov 112*58ce8d6dSBorislav Petkov return X86_VENDOR_UNKNOWN; 113*58ce8d6dSBorislav Petkov } 114*58ce8d6dSBorislav Petkov 115*58ce8d6dSBorislav Petkov static inline unsigned int __x86_family(unsigned int sig) 116*58ce8d6dSBorislav Petkov { 117*58ce8d6dSBorislav Petkov unsigned int x86; 118*58ce8d6dSBorislav Petkov 119*58ce8d6dSBorislav Petkov x86 = (sig >> 8) & 0xf; 120*58ce8d6dSBorislav Petkov 121*58ce8d6dSBorislav Petkov if (x86 == 0xf) 122*58ce8d6dSBorislav Petkov x86 += (sig >> 20) & 0xff; 123*58ce8d6dSBorislav Petkov 124*58ce8d6dSBorislav Petkov return x86; 125*58ce8d6dSBorislav Petkov } 126*58ce8d6dSBorislav Petkov 127*58ce8d6dSBorislav Petkov static inline unsigned int x86_family(void) 128*58ce8d6dSBorislav Petkov { 129*58ce8d6dSBorislav Petkov u32 eax = 0x00000001; 130*58ce8d6dSBorislav Petkov u32 ebx, ecx = 0, edx; 131*58ce8d6dSBorislav Petkov 132*58ce8d6dSBorislav Petkov native_cpuid(&eax, &ebx, &ecx, &edx); 133*58ce8d6dSBorislav Petkov 134*58ce8d6dSBorislav Petkov return __x86_family(eax); 135*58ce8d6dSBorislav Petkov } 136*58ce8d6dSBorislav Petkov 137*58ce8d6dSBorislav Petkov static inline unsigned int x86_model(unsigned int sig) 138*58ce8d6dSBorislav Petkov { 139*58ce8d6dSBorislav Petkov unsigned int x86, model; 140*58ce8d6dSBorislav Petkov 141*58ce8d6dSBorislav Petkov x86 = __x86_family(sig); 142*58ce8d6dSBorislav Petkov 143*58ce8d6dSBorislav Petkov model = (sig >> 4) & 0xf; 144*58ce8d6dSBorislav Petkov 145*58ce8d6dSBorislav Petkov if (x86 == 0x6 || x86 == 0xf) 146*58ce8d6dSBorislav Petkov model += ((sig >> 16) & 0xf) << 4; 147*58ce8d6dSBorislav Petkov 148*58ce8d6dSBorislav Petkov return model; 149*58ce8d6dSBorislav Petkov } 150*58ce8d6dSBorislav Petkov 151a8ebf6d1SFenghua Yu extern void __init load_ucode_bsp(void); 152148f9bb8SPaul Gortmaker extern void load_ucode_ap(void); 153a8ebf6d1SFenghua Yu extern int __init save_microcode_in_initrd(void); 154fbae4ba8SBorislav Petkov void reload_early_microcode(void); 155a8ebf6d1SFenghua Yu #else 156a8ebf6d1SFenghua Yu static inline void __init load_ucode_bsp(void) {} 157148f9bb8SPaul Gortmaker static inline void load_ucode_ap(void) {} 158a8ebf6d1SFenghua Yu static inline int __init save_microcode_in_initrd(void) 159a8ebf6d1SFenghua Yu { 160a8ebf6d1SFenghua Yu return 0; 161a8ebf6d1SFenghua Yu } 162fbae4ba8SBorislav Petkov static inline void reload_early_microcode(void) {} 163a8ebf6d1SFenghua Yu #endif 164a8ebf6d1SFenghua Yu 1651965aae3SH. Peter Anvin #endif /* _ASM_X86_MICROCODE_H */ 166