Commit | Line | Data |
---|---|---|
1965aae3 PA |
1 | #ifndef _ASM_X86_MICROCODE_H |
2 | #define _ASM_X86_MICROCODE_H | |
d45de409 | 3 | |
760d765b BP |
4 | #include <linux/earlycpio.h> |
5 | ||
e1b43e3f BP |
6 | #define native_rdmsr(msr, val1, val2) \ |
7 | do { \ | |
8 | u64 __val = native_read_msr((msr)); \ | |
9 | (void)((val1) = (u32)__val); \ | |
10 | (void)((val2) = (u32)(__val >> 32)); \ | |
11 | } while (0) | |
12 | ||
13 | #define native_wrmsr(msr, low, high) \ | |
14 | native_write_msr(msr, low, high) | |
15 | ||
16 | #define native_wrmsrl(msr, val) \ | |
17 | native_write_msr((msr), \ | |
18 | (u32)((u64)(val)), \ | |
19 | (u32)((u64)(val) >> 32)) | |
20 | ||
18dbc916 DA |
21 | struct cpu_signature { |
22 | unsigned int sig; | |
23 | unsigned int pf; | |
24 | unsigned int rev; | |
25 | }; | |
8d86f390 | 26 | |
a0a29b62 | 27 | struct device; |
d45de409 | 28 | |
871b72dd | 29 | enum ucode_state { UCODE_ERROR, UCODE_OK, UCODE_NFOUND }; |
65cef131 | 30 | extern bool dis_ucode_ldr; |
871b72dd | 31 | |
26bf7a48 | 32 | struct microcode_ops { |
871b72dd DA |
33 | enum ucode_state (*request_microcode_user) (int cpu, |
34 | const void __user *buf, size_t size); | |
a0a29b62 | 35 | |
48e30685 BP |
36 | enum ucode_state (*request_microcode_fw) (int cpu, struct device *, |
37 | bool refresh_fw); | |
a0a29b62 | 38 | |
a0a29b62 | 39 | void (*microcode_fini_cpu) (int cpu); |
871b72dd DA |
40 | |
41 | /* | |
42 | * The generic 'microcode_core' part guarantees that | |
43 | * the callbacks below run on a target cpu when they | |
44 | * are being called. | |
45 | * See also the "Synchronization" section in microcode_core.c. | |
46 | */ | |
47 | int (*apply_microcode) (int cpu); | |
48 | int (*collect_cpu_info) (int cpu, struct cpu_signature *csig); | |
26bf7a48 PO |
49 | }; |
50 | ||
d45de409 | 51 | struct ucode_cpu_info { |
871b72dd DA |
52 | struct cpu_signature cpu_sig; |
53 | int valid; | |
54 | void *mc; | |
c3b71bce | 55 | }; |
d45de409 DA |
56 | extern struct ucode_cpu_info ucode_cpu_info[]; |
57 | ||
18dbc916 DA |
58 | #ifdef CONFIG_MICROCODE_INTEL |
59 | extern struct microcode_ops * __init init_intel_microcode(void); | |
60 | #else | |
61 | static inline struct microcode_ops * __init init_intel_microcode(void) | |
62 | { | |
63 | return NULL; | |
64 | } | |
65 | #endif /* CONFIG_MICROCODE_INTEL */ | |
66 | ||
67 | #ifdef CONFIG_MICROCODE_AMD | |
68 | extern struct microcode_ops * __init init_amd_microcode(void); | |
f72c1a57 | 69 | extern void __exit exit_amd_microcode(void); |
18dbc916 DA |
70 | #else |
71 | static inline struct microcode_ops * __init init_amd_microcode(void) | |
72 | { | |
73 | return NULL; | |
74 | } | |
f72c1a57 | 75 | static inline void __exit exit_amd_microcode(void) {} |
18dbc916 DA |
76 | #endif |
77 | ||
a8ebf6d1 FY |
78 | #ifdef CONFIG_MICROCODE_EARLY |
79 | #define MAX_UCODE_COUNT 128 | |
58ce8d6d BP |
80 | |
81 | #define QCHAR(a, b, c, d) ((a) + ((b) << 8) + ((c) << 16) + ((d) << 24)) | |
82 | #define CPUID_INTEL1 QCHAR('G', 'e', 'n', 'u') | |
83 | #define CPUID_INTEL2 QCHAR('i', 'n', 'e', 'I') | |
84 | #define CPUID_INTEL3 QCHAR('n', 't', 'e', 'l') | |
85 | #define CPUID_AMD1 QCHAR('A', 'u', 't', 'h') | |
86 | #define CPUID_AMD2 QCHAR('e', 'n', 't', 'i') | |
87 | #define CPUID_AMD3 QCHAR('c', 'A', 'M', 'D') | |
88 | ||
89 | #define CPUID_IS(a, b, c, ebx, ecx, edx) \ | |
90 | (!((ebx ^ (a))|(edx ^ (b))|(ecx ^ (c)))) | |
91 | ||
92 | /* | |
93 | * In early loading microcode phase on BSP, boot_cpu_data is not set up yet. | |
94 | * x86_vendor() gets vendor id for BSP. | |
95 | * | |
96 | * In 32 bit AP case, accessing boot_cpu_data needs linear address. To simplify | |
97 | * coding, we still use x86_vendor() to get vendor id for AP. | |
98 | * | |
99 | * x86_vendor() gets vendor information directly from CPUID. | |
100 | */ | |
101 | static inline int x86_vendor(void) | |
102 | { | |
103 | u32 eax = 0x00000000; | |
104 | u32 ebx, ecx = 0, edx; | |
105 | ||
106 | native_cpuid(&eax, &ebx, &ecx, &edx); | |
107 | ||
108 | if (CPUID_IS(CPUID_INTEL1, CPUID_INTEL2, CPUID_INTEL3, ebx, ecx, edx)) | |
109 | return X86_VENDOR_INTEL; | |
110 | ||
111 | if (CPUID_IS(CPUID_AMD1, CPUID_AMD2, CPUID_AMD3, ebx, ecx, edx)) | |
112 | return X86_VENDOR_AMD; | |
113 | ||
114 | return X86_VENDOR_UNKNOWN; | |
115 | } | |
116 | ||
117 | static inline unsigned int __x86_family(unsigned int sig) | |
118 | { | |
119 | unsigned int x86; | |
120 | ||
121 | x86 = (sig >> 8) & 0xf; | |
122 | ||
123 | if (x86 == 0xf) | |
124 | x86 += (sig >> 20) & 0xff; | |
125 | ||
126 | return x86; | |
127 | } | |
128 | ||
129 | static inline unsigned int x86_family(void) | |
130 | { | |
131 | u32 eax = 0x00000001; | |
132 | u32 ebx, ecx = 0, edx; | |
133 | ||
134 | native_cpuid(&eax, &ebx, &ecx, &edx); | |
135 | ||
136 | return __x86_family(eax); | |
137 | } | |
138 | ||
139 | static inline unsigned int x86_model(unsigned int sig) | |
140 | { | |
141 | unsigned int x86, model; | |
142 | ||
143 | x86 = __x86_family(sig); | |
144 | ||
145 | model = (sig >> 4) & 0xf; | |
146 | ||
147 | if (x86 == 0x6 || x86 == 0xf) | |
148 | model += ((sig >> 16) & 0xf) << 4; | |
149 | ||
150 | return model; | |
151 | } | |
152 | ||
a8ebf6d1 | 153 | extern void __init load_ucode_bsp(void); |
148f9bb8 | 154 | extern void load_ucode_ap(void); |
a8ebf6d1 | 155 | extern int __init save_microcode_in_initrd(void); |
fbae4ba8 | 156 | void reload_early_microcode(void); |
760d765b | 157 | extern bool get_builtin_firmware(struct cpio_data *cd, const char *name); |
a8ebf6d1 FY |
158 | #else |
159 | static inline void __init load_ucode_bsp(void) {} | |
148f9bb8 | 160 | static inline void load_ucode_ap(void) {} |
a8ebf6d1 FY |
161 | static inline int __init save_microcode_in_initrd(void) |
162 | { | |
163 | return 0; | |
164 | } | |
fbae4ba8 | 165 | static inline void reload_early_microcode(void) {} |
760d765b BP |
166 | static inline bool get_builtin_firmware(struct cpio_data *cd, const char *name) |
167 | { | |
168 | return false; | |
169 | } | |
a8ebf6d1 | 170 | #endif |
1965aae3 | 171 | #endif /* _ASM_X86_MICROCODE_H */ |