Commit | Line | Data |
---|---|---|
2874c5fd | 1 | // SPDX-License-Identifier: GPL-2.0-or-later |
1da177e4 | 2 | /* |
6b44e72a | 3 | * Intel CPU Microcode Update Driver for Linux |
1da177e4 | 4 | * |
cea58224 | 5 | * Copyright (C) 2000-2006 Tigran Aivazian <aivazian.tigran@gmail.com> |
6b44e72a | 6 | * 2006 Shaohua Li <shaohua.li@intel.com> |
1da177e4 | 7 | * |
fe055896 BP |
8 | * Intel CPU microcode early update for Linux |
9 | * | |
10 | * Copyright (C) 2012 Fenghua Yu <fenghua.yu@intel.com> | |
11 | * H Peter Anvin" <hpa@zytor.com> | |
1da177e4 | 12 | */ |
6b26e1bf | 13 | #define pr_fmt(fmt) "microcode: " fmt |
fe055896 | 14 | #include <linux/earlycpio.h> |
4bae1967 | 15 | #include <linux/firmware.h> |
4bae1967 | 16 | #include <linux/uaccess.h> |
fe055896 | 17 | #include <linux/initrd.h> |
4bae1967 | 18 | #include <linux/kernel.h> |
fe055896 BP |
19 | #include <linux/slab.h> |
20 | #include <linux/cpu.h> | |
7e94a7b6 | 21 | #include <linux/uio.h> |
fe055896 | 22 | #include <linux/mm.h> |
1da177e4 | 23 | |
723f2828 | 24 | #include <asm/intel-family.h> |
4bae1967 | 25 | #include <asm/processor.h> |
fe055896 BP |
26 | #include <asm/tlbflush.h> |
27 | #include <asm/setup.h> | |
4bae1967 | 28 | #include <asm/msr.h> |
1da177e4 | 29 | |
d02a0efd TG |
30 | #include "internal.h" |
31 | ||
06b8534c | 32 | static const char ucode_path[] = "kernel/x86/microcode/GenuineIntel.bin"; |
fe055896 | 33 | |
dd5e3e3c TG |
34 | #define UCODE_BSP_LOADED ((struct microcode_intel *)0x1UL) |
35 | ||
c26665ab | 36 | /* Current microcode patch used in early patching on the APs. */ |
dd5e3e3c | 37 | static struct microcode_intel *ucode_patch_va __read_mostly; |
2a1dada3 | 38 | static struct microcode_intel *ucode_patch_late __read_mostly; |
6c545647 | 39 | |
7e702d17 | 40 | /* last level cache size per core */ |
0177669e | 41 | static unsigned int llc_size_per_core __ro_after_init; |
7e702d17 | 42 | |
4da2131f TG |
43 | /* microcode format is extended from prescott processors */ |
44 | struct extended_signature { | |
45 | unsigned int sig; | |
46 | unsigned int pf; | |
47 | unsigned int cksum; | |
48 | }; | |
49 | ||
50 | struct extended_sigtable { | |
51 | unsigned int count; | |
52 | unsigned int cksum; | |
53 | unsigned int reserved[3]; | |
54 | struct extended_signature sigs[]; | |
55 | }; | |
56 | ||
57 | #define DEFAULT_UCODE_TOTALSIZE (DEFAULT_UCODE_DATASIZE + MC_HEADER_SIZE) | |
58 | #define EXT_HEADER_SIZE (sizeof(struct extended_sigtable)) | |
59 | #define EXT_SIGNATURE_SIZE (sizeof(struct extended_signature)) | |
60 | ||
61 | static inline unsigned int get_totalsize(struct microcode_header_intel *hdr) | |
62 | { | |
63 | return hdr->datasize ? hdr->totalsize : DEFAULT_UCODE_TOTALSIZE; | |
64 | } | |
65 | ||
66 | static inline unsigned int exttable_size(struct extended_sigtable *et) | |
67 | { | |
68 | return et->count * EXT_SIGNATURE_SIZE + EXT_HEADER_SIZE; | |
69 | } | |
70 | ||
164aa1ca | 71 | void intel_collect_cpu_info(struct cpu_signature *sig) |
4da2131f | 72 | { |
164aa1ca TG |
73 | sig->sig = cpuid_eax(1); |
74 | sig->pf = 0; | |
75 | sig->rev = intel_get_microcode_revision(); | |
4da2131f | 76 | |
164aa1ca TG |
77 | if (x86_model(sig->sig) >= 5 || x86_family(sig->sig) > 6) { |
78 | unsigned int val[2]; | |
4da2131f | 79 | |
4da2131f TG |
80 | /* get processor flags from MSR 0x17 */ |
81 | native_rdmsr(MSR_IA32_PLATFORM_ID, val[0], val[1]); | |
164aa1ca | 82 | sig->pf = 1 << ((val[1] >> 18) & 7); |
4da2131f | 83 | } |
4da2131f | 84 | } |
164aa1ca | 85 | EXPORT_SYMBOL_GPL(intel_collect_cpu_info); |
4da2131f | 86 | |
b7fcd995 TG |
87 | static inline bool cpu_signatures_match(struct cpu_signature *s1, unsigned int sig2, |
88 | unsigned int pf2) | |
89 | { | |
90 | if (s1->sig != sig2) | |
91 | return false; | |
92 | ||
93 | /* Processor flags are either both 0 or they intersect. */ | |
94 | return ((!s1->pf && !pf2) || (s1->pf & pf2)); | |
95 | } | |
96 | ||
97 | bool intel_find_matching_signature(void *mc, struct cpu_signature *sig) | |
4da2131f TG |
98 | { |
99 | struct microcode_header_intel *mc_hdr = mc; | |
4da2131f | 100 | struct extended_signature *ext_sig; |
b7fcd995 | 101 | struct extended_sigtable *ext_hdr; |
4da2131f TG |
102 | int i; |
103 | ||
b7fcd995 TG |
104 | if (cpu_signatures_match(sig, mc_hdr->sig, mc_hdr->pf)) |
105 | return true; | |
4da2131f TG |
106 | |
107 | /* Look for ext. headers: */ | |
b0e67db1 | 108 | if (get_totalsize(mc_hdr) <= intel_microcode_get_datasize(mc_hdr) + MC_HEADER_SIZE) |
b7fcd995 | 109 | return false; |
4da2131f | 110 | |
b0e67db1 | 111 | ext_hdr = mc + intel_microcode_get_datasize(mc_hdr) + MC_HEADER_SIZE; |
4da2131f TG |
112 | ext_sig = (void *)ext_hdr + EXT_HEADER_SIZE; |
113 | ||
114 | for (i = 0; i < ext_hdr->count; i++) { | |
b7fcd995 TG |
115 | if (cpu_signatures_match(sig, ext_sig->sig, ext_sig->pf)) |
116 | return true; | |
4da2131f TG |
117 | ext_sig++; |
118 | } | |
119 | return 0; | |
120 | } | |
121 | EXPORT_SYMBOL_GPL(intel_find_matching_signature); | |
122 | ||
123 | /** | |
124 | * intel_microcode_sanity_check() - Sanity check microcode file. | |
125 | * @mc: Pointer to the microcode file contents. | |
126 | * @print_err: Display failure reason if true, silent if false. | |
127 | * @hdr_type: Type of file, i.e. normal microcode file or In Field Scan file. | |
128 | * Validate if the microcode header type matches with the type | |
129 | * specified here. | |
130 | * | |
131 | * Validate certain header fields and verify if computed checksum matches | |
132 | * with the one specified in the header. | |
133 | * | |
134 | * Return: 0 if the file passes all the checks, -EINVAL if any of the checks | |
135 | * fail. | |
136 | */ | |
137 | int intel_microcode_sanity_check(void *mc, bool print_err, int hdr_type) | |
138 | { | |
139 | unsigned long total_size, data_size, ext_table_size; | |
140 | struct microcode_header_intel *mc_header = mc; | |
141 | struct extended_sigtable *ext_header = NULL; | |
142 | u32 sum, orig_sum, ext_sigcount = 0, i; | |
143 | struct extended_signature *ext_sig; | |
144 | ||
145 | total_size = get_totalsize(mc_header); | |
b0e67db1 | 146 | data_size = intel_microcode_get_datasize(mc_header); |
4da2131f TG |
147 | |
148 | if (data_size + MC_HEADER_SIZE > total_size) { | |
149 | if (print_err) | |
150 | pr_err("Error: bad microcode data file size.\n"); | |
151 | return -EINVAL; | |
152 | } | |
153 | ||
154 | if (mc_header->ldrver != 1 || mc_header->hdrver != hdr_type) { | |
155 | if (print_err) | |
156 | pr_err("Error: invalid/unknown microcode update format. Header type %d\n", | |
157 | mc_header->hdrver); | |
158 | return -EINVAL; | |
159 | } | |
160 | ||
161 | ext_table_size = total_size - (MC_HEADER_SIZE + data_size); | |
162 | if (ext_table_size) { | |
163 | u32 ext_table_sum = 0; | |
164 | u32 *ext_tablep; | |
165 | ||
166 | if (ext_table_size < EXT_HEADER_SIZE || | |
167 | ((ext_table_size - EXT_HEADER_SIZE) % EXT_SIGNATURE_SIZE)) { | |
168 | if (print_err) | |
169 | pr_err("Error: truncated extended signature table.\n"); | |
170 | return -EINVAL; | |
171 | } | |
172 | ||
173 | ext_header = mc + MC_HEADER_SIZE + data_size; | |
174 | if (ext_table_size != exttable_size(ext_header)) { | |
175 | if (print_err) | |
176 | pr_err("Error: extended signature table size mismatch.\n"); | |
177 | return -EFAULT; | |
178 | } | |
179 | ||
180 | ext_sigcount = ext_header->count; | |
181 | ||
182 | /* | |
183 | * Check extended table checksum: the sum of all dwords that | |
184 | * comprise a valid table must be 0. | |
185 | */ | |
186 | ext_tablep = (u32 *)ext_header; | |
187 | ||
188 | i = ext_table_size / sizeof(u32); | |
189 | while (i--) | |
190 | ext_table_sum += ext_tablep[i]; | |
191 | ||
192 | if (ext_table_sum) { | |
193 | if (print_err) | |
194 | pr_warn("Bad extended signature table checksum, aborting.\n"); | |
195 | return -EINVAL; | |
196 | } | |
197 | } | |
198 | ||
199 | /* | |
200 | * Calculate the checksum of update data and header. The checksum of | |
201 | * valid update data and header including the extended signature table | |
202 | * must be 0. | |
203 | */ | |
204 | orig_sum = 0; | |
205 | i = (MC_HEADER_SIZE + data_size) / sizeof(u32); | |
206 | while (i--) | |
207 | orig_sum += ((u32 *)mc)[i]; | |
208 | ||
209 | if (orig_sum) { | |
210 | if (print_err) | |
211 | pr_err("Bad microcode data checksum, aborting.\n"); | |
212 | return -EINVAL; | |
213 | } | |
214 | ||
215 | if (!ext_table_size) | |
216 | return 0; | |
217 | ||
218 | /* | |
219 | * Check extended signature checksum: 0 => valid. | |
220 | */ | |
221 | for (i = 0; i < ext_sigcount; i++) { | |
222 | ext_sig = (void *)ext_header + EXT_HEADER_SIZE + | |
223 | EXT_SIGNATURE_SIZE * i; | |
224 | ||
225 | sum = (mc_header->sig + mc_header->pf + mc_header->cksum) - | |
226 | (ext_sig->sig + ext_sig->pf + ext_sig->cksum); | |
227 | if (sum) { | |
228 | if (print_err) | |
229 | pr_err("Bad extended signature checksum, aborting.\n"); | |
230 | return -EINVAL; | |
231 | } | |
232 | } | |
233 | return 0; | |
234 | } | |
235 | EXPORT_SYMBOL_GPL(intel_microcode_sanity_check); | |
236 | ||
dd5e3e3c | 237 | static void update_ucode_pointer(struct microcode_intel *mc) |
fe055896 | 238 | { |
f24f2044 | 239 | kvfree(ucode_patch_va); |
dd5e3e3c TG |
240 | |
241 | /* | |
242 | * Save the virtual address for early loading and for eventual free | |
243 | * on late loading. | |
244 | */ | |
245 | ucode_patch_va = mc; | |
246 | } | |
bd207330 | 247 | |
dd5e3e3c TG |
248 | static void save_microcode_patch(struct microcode_intel *patch) |
249 | { | |
f24f2044 | 250 | unsigned int size = get_totalsize(&patch->hdr); |
dd5e3e3c | 251 | struct microcode_intel *mc; |
aa78c1cc | 252 | |
f24f2044 | 253 | mc = kvmemdup(patch, size, GFP_KERNEL); |
dd5e3e3c TG |
254 | if (mc) |
255 | update_ucode_pointer(mc); | |
f24f2044 TG |
256 | else |
257 | pr_err("Unable to allocate microcode memory size: %u\n", size); | |
fe055896 BP |
258 | } |
259 | ||
dd5e3e3c TG |
260 | /* Scan blob for microcode matching the boot CPUs family, model, stepping */ |
261 | static __init struct microcode_intel *scan_microcode(void *data, size_t size, | |
262 | struct ucode_cpu_info *uci, | |
263 | bool save) | |
fe055896 | 264 | { |
f96fde53 | 265 | struct microcode_header_intel *mc_header; |
06b8534c | 266 | struct microcode_intel *patch = NULL; |
ae76d951 | 267 | u32 cur_rev = uci->cpu_sig.rev; |
f96fde53 | 268 | unsigned int mc_size; |
fe055896 | 269 | |
b0f0bf5e | 270 | for (; size >= sizeof(struct microcode_header_intel); size -= mc_size, data += mc_size) { |
06b8534c | 271 | mc_header = (struct microcode_header_intel *)data; |
fe055896 BP |
272 | |
273 | mc_size = get_totalsize(mc_header); | |
ae76d951 | 274 | if (!mc_size || mc_size > size || |
e0788c32 | 275 | intel_microcode_sanity_check(data, false, MC_HEADER_TYPE_MICROCODE) < 0) |
fe055896 BP |
276 | break; |
277 | ||
b7fcd995 | 278 | if (!intel_find_matching_signature(data, &uci->cpu_sig)) |
fe055896 | 279 | continue; |
fe055896 | 280 | |
dd5e3e3c TG |
281 | /* |
282 | * For saving the early microcode, find the matching revision which | |
283 | * was loaded on the BSP. | |
284 | * | |
285 | * On the BSP during early boot, find a newer revision than | |
286 | * actually loaded in the CPU. | |
287 | */ | |
288 | if (save) { | |
289 | if (cur_rev != mc_header->rev) | |
290 | continue; | |
291 | } else if (cur_rev >= mc_header->rev) { | |
b0f0bf5e | 292 | continue; |
dd5e3e3c | 293 | } |
fe055896 | 294 | |
06b8534c | 295 | patch = data; |
ae76d951 | 296 | cur_rev = mc_header->rev; |
06b8534c | 297 | } |
f96fde53 | 298 | |
dd5e3e3c | 299 | return size ? NULL : patch; |
fe055896 BP |
300 | } |
301 | ||
3973718c TG |
302 | static enum ucode_state __apply_microcode(struct ucode_cpu_info *uci, |
303 | struct microcode_intel *mc, | |
304 | u32 *cur_rev) | |
fe055896 | 305 | { |
3973718c | 306 | u32 rev; |
fe055896 | 307 | |
de778275 | 308 | if (!mc) |
dd5e3e3c | 309 | return UCODE_NFOUND; |
fe055896 | 310 | |
c182d2b7 AR |
311 | /* |
312 | * Save us the MSR write below - which is a particular expensive | |
313 | * operation - when the other hyperthread has updated the microcode | |
314 | * already. | |
315 | */ | |
3973718c TG |
316 | *cur_rev = intel_get_microcode_revision(); |
317 | if (*cur_rev >= mc->hdr.rev) { | |
318 | uci->cpu_sig.rev = *cur_rev; | |
c182d2b7 AR |
319 | return UCODE_OK; |
320 | } | |
321 | ||
91df9fdf AR |
322 | /* |
323 | * Writeback and invalidate caches before updating microcode to avoid | |
324 | * internal issues depending on what the microcode is updating. | |
325 | */ | |
326 | native_wbinvd(); | |
327 | ||
fe055896 | 328 | /* write microcode via MSR 0x79 */ |
c416e611 | 329 | native_wrmsrl(MSR_IA32_UCODE_WRITE, (unsigned long)mc->bits); |
fe055896 | 330 | |
4167709b BP |
331 | rev = intel_get_microcode_revision(); |
332 | if (rev != mc->hdr.rev) | |
dd5e3e3c | 333 | return UCODE_ERROR; |
fe055896 | 334 | |
4167709b | 335 | uci->cpu_sig.rev = rev; |
dd5e3e3c | 336 | return UCODE_UPDATED; |
fe055896 BP |
337 | } |
338 | ||
3973718c TG |
339 | static enum ucode_state apply_microcode_early(struct ucode_cpu_info *uci) |
340 | { | |
341 | struct microcode_intel *mc = uci->mc; | |
080990aa BPA |
342 | u32 cur_rev; |
343 | ||
344 | return __apply_microcode(uci, mc, &cur_rev); | |
3973718c TG |
345 | } |
346 | ||
dd5e3e3c | 347 | static __init bool load_builtin_intel_microcode(struct cpio_data *cp) |
0177669e TG |
348 | { |
349 | unsigned int eax = 1, ebx, ecx = 0, edx; | |
350 | struct firmware fw; | |
351 | char name[30]; | |
352 | ||
353 | if (IS_ENABLED(CONFIG_X86_32)) | |
354 | return false; | |
355 | ||
356 | native_cpuid(&eax, &ebx, &ecx, &edx); | |
357 | ||
358 | sprintf(name, "intel-ucode/%02x-%02x-%02x", | |
359 | x86_family(eax), x86_model(eax), x86_stepping(eax)); | |
360 | ||
361 | if (firmware_request_builtin(&fw, name)) { | |
362 | cp->size = fw.size; | |
363 | cp->data = (void *)fw.data; | |
364 | return true; | |
365 | } | |
366 | return false; | |
367 | } | |
368 | ||
dd5e3e3c | 369 | static __init struct microcode_intel *get_microcode_blob(struct ucode_cpu_info *uci, bool save) |
fe055896 | 370 | { |
06b8534c | 371 | struct cpio_data cp; |
fe055896 | 372 | |
9c21ea53 BPA |
373 | intel_collect_cpu_info(&uci->cpu_sig); |
374 | ||
06b8534c | 375 | if (!load_builtin_intel_microcode(&cp)) |
0b62f6cb | 376 | cp = find_microcode_in_initrd(ucode_path); |
fe055896 | 377 | |
06b8534c | 378 | if (!(cp.data && cp.size)) |
dd5e3e3c | 379 | return NULL; |
fe055896 | 380 | |
dd5e3e3c | 381 | return scan_microcode(cp.data, cp.size, uci, save); |
06b8534c | 382 | } |
6c545647 | 383 | |
06b8534c | 384 | /* |
dd5e3e3c TG |
385 | * Invoked from an early init call to save the microcode blob which was |
386 | * selected during early boot when mm was not usable. The microcode must be | |
387 | * saved because initrd is going away. It's an early init call so the APs | |
388 | * just can use the pointer and do not have to scan initrd/builtin firmware | |
389 | * again. | |
06b8534c | 390 | */ |
dd5e3e3c | 391 | static int __init save_builtin_microcode(void) |
06b8534c | 392 | { |
dd5e3e3c | 393 | struct ucode_cpu_info uci; |
6c545647 | 394 | |
dd5e3e3c TG |
395 | if (xchg(&ucode_patch_va, NULL) != UCODE_BSP_LOADED) |
396 | return 0; | |
6c545647 | 397 | |
dd5e3e3c TG |
398 | if (dis_ucode_ldr || boot_cpu_data.x86_vendor != X86_VENDOR_INTEL) |
399 | return 0; | |
6c545647 | 400 | |
dd5e3e3c TG |
401 | uci.mc = get_microcode_blob(&uci, true); |
402 | if (uci.mc) | |
403 | save_microcode_patch(uci.mc); | |
404 | return 0; | |
6c545647 | 405 | } |
dd5e3e3c | 406 | early_initcall(save_builtin_microcode); |
6c545647 | 407 | |
dd5e3e3c | 408 | /* Load microcode on BSP from initrd or builtin blobs */ |
080990aa | 409 | void __init load_ucode_intel_bsp(struct early_load_data *ed) |
fe055896 BP |
410 | { |
411 | struct ucode_cpu_info uci; | |
fe055896 | 412 | |
dd5e3e3c | 413 | uci.mc = get_microcode_blob(&uci, false); |
9c21ea53 | 414 | ed->old_rev = uci.cpu_sig.rev; |
080990aa | 415 | |
9c21ea53 BPA |
416 | if (uci.mc && apply_microcode_early(&uci) == UCODE_UPDATED) { |
417 | ucode_patch_va = UCODE_BSP_LOADED; | |
418 | ed->new_rev = uci.cpu_sig.rev; | |
419 | } | |
fe055896 BP |
420 | } |
421 | ||
06b8534c | 422 | void load_ucode_intel_ap(void) |
fe055896 | 423 | { |
06b8534c | 424 | struct ucode_cpu_info uci; |
264285ac | 425 | |
dd5e3e3c TG |
426 | uci.mc = ucode_patch_va; |
427 | if (uci.mc) | |
428 | apply_microcode_early(&uci); | |
fe055896 BP |
429 | } |
430 | ||
dd5e3e3c | 431 | /* Reload microcode on resume */ |
fe055896 BP |
432 | void reload_ucode_intel(void) |
433 | { | |
dd5e3e3c | 434 | struct ucode_cpu_info uci = { .mc = ucode_patch_va, }; |
fe055896 | 435 | |
dd5e3e3c TG |
436 | if (uci.mc) |
437 | apply_microcode_early(&uci); | |
fe055896 BP |
438 | } |
439 | ||
d45de409 | 440 | static int collect_cpu_info(int cpu_num, struct cpu_signature *csig) |
1da177e4 | 441 | { |
11f96ac4 | 442 | intel_collect_cpu_info(csig); |
d45de409 | 443 | return 0; |
1da177e4 LT |
444 | } |
445 | ||
3973718c | 446 | static enum ucode_state apply_microcode_late(int cpu) |
1da177e4 | 447 | { |
d8c3b52c | 448 | struct ucode_cpu_info *uci = ucode_cpu_info + cpu; |
3973718c | 449 | struct microcode_intel *mc = ucode_patch_late; |
8da38eba | 450 | enum ucode_state ret; |
3973718c | 451 | u32 cur_rev; |
4bae1967 | 452 | |
3973718c | 453 | if (WARN_ON_ONCE(smp_processor_id() != cpu)) |
3f1f576a | 454 | return UCODE_ERROR; |
9a3110bf | 455 | |
3973718c TG |
456 | ret = __apply_microcode(uci, mc, &cur_rev); |
457 | if (ret != UCODE_UPDATED && ret != UCODE_OK) | |
458 | return ret; | |
9cd4d78e | 459 | |
3973718c TG |
460 | cpu_data(cpu).microcode = uci->cpu_sig.rev; |
461 | if (!cpu) | |
462 | boot_cpu_data.microcode = uci->cpu_sig.rev; | |
370a132b | 463 | |
8da38eba | 464 | return ret; |
1da177e4 LT |
465 | } |
466 | ||
cf5ab01c AR |
467 | static bool ucode_validate_minrev(struct microcode_header_intel *mc_header) |
468 | { | |
469 | int cur_rev = boot_cpu_data.microcode; | |
470 | ||
471 | /* | |
472 | * When late-loading, ensure the header declares a minimum revision | |
473 | * required to perform a late-load. The previously reserved field | |
474 | * is 0 in older microcode blobs. | |
475 | */ | |
476 | if (!mc_header->min_req_ver) { | |
477 | pr_info("Unsafe microcode update: Microcode header does not specify a required min version\n"); | |
478 | return false; | |
479 | } | |
480 | ||
481 | /* | |
482 | * Check whether the current revision is either greater or equal to | |
483 | * to the minimum revision specified in the header. | |
484 | */ | |
485 | if (cur_rev < mc_header->min_req_ver) { | |
486 | pr_info("Unsafe microcode update: Current revision 0x%x too old\n", cur_rev); | |
487 | pr_info("Current should be at 0x%x or higher. Use early loading instead\n", mc_header->min_req_ver); | |
488 | return false; | |
489 | } | |
490 | return true; | |
491 | } | |
492 | ||
6b072022 | 493 | static enum ucode_state parse_microcode_blobs(int cpu, struct iov_iter *iter) |
9a3110bf | 494 | { |
a0a29b62 | 495 | struct ucode_cpu_info *uci = ucode_cpu_info + cpu; |
cf5ab01c | 496 | bool is_safe, new_is_safe = false; |
6b072022 | 497 | int cur_rev = uci->cpu_sig.rev; |
dd5e3e3c | 498 | unsigned int curr_mc_size = 0; |
7e94a7b6 | 499 | u8 *new_mc = NULL, *mc = NULL; |
9a3110bf | 500 | |
7e94a7b6 | 501 | while (iov_iter_count(iter)) { |
a0a29b62 | 502 | struct microcode_header_intel mc_header; |
7e94a7b6 JH |
503 | unsigned int mc_size, data_size; |
504 | u8 *data; | |
9a3110bf | 505 | |
7e94a7b6 JH |
506 | if (!copy_from_iter_full(&mc_header, sizeof(mc_header), iter)) { |
507 | pr_err("error! Truncated or inaccessible header in microcode data file\n"); | |
f24f2044 | 508 | goto fail; |
35a9ff4e QC |
509 | } |
510 | ||
a0a29b62 | 511 | mc_size = get_totalsize(&mc_header); |
7e94a7b6 JH |
512 | if (mc_size < sizeof(mc_header)) { |
513 | pr_err("error! Bad data in microcode data file (totalsize too small)\n"); | |
f24f2044 | 514 | goto fail; |
7e94a7b6 JH |
515 | } |
516 | data_size = mc_size - sizeof(mc_header); | |
517 | if (data_size > iov_iter_count(iter)) { | |
518 | pr_err("error! Bad data in microcode data file (truncated file?)\n"); | |
f24f2044 | 519 | goto fail; |
a0a29b62 | 520 | } |
a30a6a2c | 521 | |
938179b4 DS |
522 | /* For performance reasons, reuse mc area when possible */ |
523 | if (!mc || mc_size > curr_mc_size) { | |
f24f2044 TG |
524 | kvfree(mc); |
525 | mc = kvmalloc(mc_size, GFP_KERNEL); | |
938179b4 | 526 | if (!mc) |
f24f2044 | 527 | goto fail; |
938179b4 DS |
528 | curr_mc_size = mc_size; |
529 | } | |
a0a29b62 | 530 | |
7e94a7b6 JH |
531 | memcpy(mc, &mc_header, sizeof(mc_header)); |
532 | data = mc + sizeof(mc_header); | |
533 | if (!copy_from_iter_full(data, data_size, iter) || | |
f24f2044 TG |
534 | intel_microcode_sanity_check(mc, true, MC_HEADER_TYPE_MICROCODE) < 0) |
535 | goto fail; | |
a0a29b62 | 536 | |
6b072022 TG |
537 | if (cur_rev >= mc_header.rev) |
538 | continue; | |
539 | ||
b7fcd995 | 540 | if (!intel_find_matching_signature(mc, &uci->cpu_sig)) |
6b072022 TG |
541 | continue; |
542 | ||
cf5ab01c AR |
543 | is_safe = ucode_validate_minrev(&mc_header); |
544 | if (force_minrev && !is_safe) | |
545 | continue; | |
546 | ||
f24f2044 | 547 | kvfree(new_mc); |
6b072022 TG |
548 | cur_rev = mc_header.rev; |
549 | new_mc = mc; | |
cf5ab01c | 550 | new_is_safe = is_safe; |
6b072022 | 551 | mc = NULL; |
a30a6a2c SL |
552 | } |
553 | ||
f24f2044 TG |
554 | if (iov_iter_count(iter)) |
555 | goto fail; | |
4bae1967 | 556 | |
f24f2044 | 557 | kvfree(mc); |
f61337d9 BP |
558 | if (!new_mc) |
559 | return UCODE_NFOUND; | |
a0a29b62 | 560 | |
2a1dada3 | 561 | ucode_patch_late = (struct microcode_intel *)new_mc; |
cf5ab01c | 562 | return new_is_safe ? UCODE_NEW_SAFE : UCODE_NEW; |
f24f2044 TG |
563 | |
564 | fail: | |
565 | kvfree(mc); | |
566 | kvfree(new_mc); | |
567 | return UCODE_ERROR; | |
a30a6a2c SL |
568 | } |
569 | ||
723f2828 BP |
570 | static bool is_blacklisted(unsigned int cpu) |
571 | { | |
572 | struct cpuinfo_x86 *c = &cpu_data(cpu); | |
573 | ||
b94b7373 JZ |
574 | /* |
575 | * Late loading on model 79 with microcode revision less than 0x0b000021 | |
7e702d17 JZ |
576 | * and LLC size per core bigger than 2.5MB may result in a system hang. |
577 | * This behavior is documented in item BDF90, #334165 (Intel Xeon | |
578 | * Processor E7-8800/4800 v4 Product Family). | |
b94b7373 JZ |
579 | */ |
580 | if (c->x86 == 6 && | |
581 | c->x86_model == INTEL_FAM6_BROADWELL_X && | |
b399151c | 582 | c->x86_stepping == 0x01 && |
7e702d17 | 583 | llc_size_per_core > 2621440 && |
b94b7373 JZ |
584 | c->microcode < 0x0b000021) { |
585 | pr_err_once("Erratum BDF90: late loading with revision < 0x0b000021 (0x%x) disabled.\n", c->microcode); | |
586 | pr_err_once("Please consider either early loading through initrd/built-in or a potential BIOS update.\n"); | |
723f2828 BP |
587 | return true; |
588 | } | |
589 | ||
590 | return false; | |
591 | } | |
592 | ||
a61ac80a | 593 | static enum ucode_state request_microcode_fw(int cpu, struct device *device) |
a30a6a2c | 594 | { |
92cb7612 | 595 | struct cpuinfo_x86 *c = &cpu_data(cpu); |
a30a6a2c | 596 | const struct firmware *firmware; |
7e94a7b6 | 597 | struct iov_iter iter; |
871b72dd | 598 | enum ucode_state ret; |
7e94a7b6 JH |
599 | struct kvec kvec; |
600 | char name[30]; | |
a30a6a2c | 601 | |
723f2828 BP |
602 | if (is_blacklisted(cpu)) |
603 | return UCODE_NFOUND; | |
604 | ||
3e135d88 | 605 | sprintf(name, "intel-ucode/%02x-%02x-%02x", |
b399151c | 606 | c->x86, c->x86_model, c->x86_stepping); |
871b72dd | 607 | |
75da02b2 | 608 | if (request_firmware_direct(&firmware, name, device)) { |
f58e1f53 | 609 | pr_debug("data file %s load failed\n", name); |
871b72dd | 610 | return UCODE_NFOUND; |
a30a6a2c | 611 | } |
a0a29b62 | 612 | |
7e94a7b6 JH |
613 | kvec.iov_base = (void *)firmware->data; |
614 | kvec.iov_len = firmware->size; | |
de4eda9d | 615 | iov_iter_kvec(&iter, ITER_SOURCE, &kvec, 1, firmware->size); |
6b072022 | 616 | ret = parse_microcode_blobs(cpu, &iter); |
a0a29b62 | 617 | |
a30a6a2c SL |
618 | release_firmware(firmware); |
619 | ||
a0a29b62 DA |
620 | return ret; |
621 | } | |
622 | ||
2a1dada3 TG |
623 | static void finalize_late_load(int result) |
624 | { | |
625 | if (!result) | |
f24f2044 TG |
626 | update_ucode_pointer(ucode_patch_late); |
627 | else | |
628 | kvfree(ucode_patch_late); | |
2a1dada3 TG |
629 | ucode_patch_late = NULL; |
630 | } | |
631 | ||
4db646b1 | 632 | static struct microcode_ops microcode_intel_ops = { |
0177669e TG |
633 | .request_microcode_fw = request_microcode_fw, |
634 | .collect_cpu_info = collect_cpu_info, | |
3973718c | 635 | .apply_microcode = apply_microcode_late, |
2a1dada3 | 636 | .finalize_late_load = finalize_late_load, |
7eb314a2 | 637 | .use_nmi = IS_ENABLED(CONFIG_X86_64), |
8d86f390 PO |
638 | }; |
639 | ||
0177669e | 640 | static __init void calc_llc_size_per_core(struct cpuinfo_x86 *c) |
7e702d17 | 641 | { |
24dbc600 | 642 | u64 llc_size = c->x86_cache_size * 1024ULL; |
7e702d17 JZ |
643 | |
644 | do_div(llc_size, c->x86_max_cores); | |
0177669e | 645 | llc_size_per_core = (unsigned int)llc_size; |
7e702d17 JZ |
646 | } |
647 | ||
18dbc916 | 648 | struct microcode_ops * __init init_intel_microcode(void) |
8d86f390 | 649 | { |
9a2bc335 | 650 | struct cpuinfo_x86 *c = &boot_cpu_data; |
7164b3f5 SB |
651 | |
652 | if (c->x86_vendor != X86_VENDOR_INTEL || c->x86 < 6 || | |
653 | cpu_has(c, X86_FEATURE_IA64)) { | |
654 | pr_err("Intel CPU family 0x%x not supported\n", c->x86); | |
655 | return NULL; | |
656 | } | |
657 | ||
0177669e | 658 | calc_llc_size_per_core(c); |
7e702d17 | 659 | |
18dbc916 | 660 | return µcode_intel_ops; |
8d86f390 | 661 | } |