aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86/kernel/cpu/microcode/intel.c
diff options
context:
space:
mode:
authorBorislav Petkov <bp@suse.de>2016-10-25 05:55:20 -0400
committerIngo Molnar <mingo@kernel.org>2016-10-25 06:28:59 -0400
commit8027923ab4df9b2bdb9d642b7dceeb135c032f5e (patch)
tree14edc0f87034e5b93a33482daa88628854203a26 /arch/x86/kernel/cpu/microcode/intel.c
parent76bd11c23aaa5c4bed504bfc4cf690240759598d (diff)
x86/microcode/intel: Remove intel_lib.c
Its functions are used in intel.c only now, so get rid of it. Make functions static. No functionality change. Signed-off-by: Borislav Petkov <bp@suse.de> Cc: Andy Lutomirski <luto@kernel.org> Cc: Borislav Petkov <bp@alien8.de> Cc: Brian Gerst <brgerst@gmail.com> Cc: Denys Vlasenko <dvlasenk@redhat.com> Cc: H. Peter Anvin <hpa@zytor.com> Cc: Josh Poimboeuf <jpoimboe@redhat.com> Cc: Linus Torvalds <torvalds@linux-foundation.org> Cc: Peter Zijlstra <peterz@infradead.org> Cc: Thomas Gleixner <tglx@linutronix.de> Link: http://lkml.kernel.org/r/20161025095522.11964-11-bp@alien8.de Signed-off-by: Ingo Molnar <mingo@kernel.org>
Diffstat (limited to 'arch/x86/kernel/cpu/microcode/intel.c')
-rw-r--r--arch/x86/kernel/cpu/microcode/intel.c154
1 files changed, 153 insertions, 1 deletions
diff --git a/arch/x86/kernel/cpu/microcode/intel.c b/arch/x86/kernel/cpu/microcode/intel.c
index b84288e08098..5e631d2cf37f 100644
--- a/arch/x86/kernel/cpu/microcode/intel.c
+++ b/arch/x86/kernel/cpu/microcode/intel.c
@@ -61,6 +61,61 @@ static struct ucode_blobs {
61 bool valid; 61 bool valid;
62} blobs; 62} blobs;
63 63
64static inline bool cpu_signatures_match(unsigned int s1, unsigned int p1,
65 unsigned int s2, unsigned int p2)
66{
67 if (s1 != s2)
68 return false;
69
70 /* Processor flags are either both 0 ... */
71 if (!p1 && !p2)
72 return true;
73
74 /* ... or they intersect. */
75 return p1 & p2;
76}
77
78/*
79 * Returns 1 if update has been found, 0 otherwise.
80 */
81static int find_matching_signature(void *mc, unsigned int csig, int cpf)
82{
83 struct microcode_header_intel *mc_hdr = mc;
84 struct extended_sigtable *ext_hdr;
85 struct extended_signature *ext_sig;
86 int i;
87
88 if (cpu_signatures_match(csig, cpf, mc_hdr->sig, mc_hdr->pf))
89 return 1;
90
91 /* Look for ext. headers: */
92 if (get_totalsize(mc_hdr) <= get_datasize(mc_hdr) + MC_HEADER_SIZE)
93 return 0;
94
95 ext_hdr = mc + get_datasize(mc_hdr) + MC_HEADER_SIZE;
96 ext_sig = (void *)ext_hdr + EXT_HEADER_SIZE;
97
98 for (i = 0; i < ext_hdr->count; i++) {
99 if (cpu_signatures_match(csig, cpf, ext_sig->sig, ext_sig->pf))
100 return 1;
101 ext_sig++;
102 }
103 return 0;
104}
105
106/*
107 * Returns 1 if update has been found, 0 otherwise.
108 */
109static int has_newer_microcode(void *mc, unsigned int csig, int cpf, int new_rev)
110{
111 struct microcode_header_intel *mc_hdr = mc;
112
113 if (mc_hdr->rev <= new_rev)
114 return 0;
115
116 return find_matching_signature(mc, csig, cpf);
117}
118
64/* Go through saved patches and find the one suitable for the current CPU. */ 119/* Go through saved patches and find the one suitable for the current CPU. */
65static enum ucode_state 120static enum ucode_state
66find_microcode_patch(struct microcode_intel **saved, 121find_microcode_patch(struct microcode_intel **saved,
@@ -291,6 +346,104 @@ static unsigned int _save_mc(struct microcode_intel **mc_saved,
291 return num_saved; 346 return num_saved;
292} 347}
293 348
349static int microcode_sanity_check(void *mc, int print_err)
350{
351 unsigned long total_size, data_size, ext_table_size;
352 struct microcode_header_intel *mc_header = mc;
353 struct extended_sigtable *ext_header = NULL;
354 u32 sum, orig_sum, ext_sigcount = 0, i;
355 struct extended_signature *ext_sig;
356
357 total_size = get_totalsize(mc_header);
358 data_size = get_datasize(mc_header);
359
360 if (data_size + MC_HEADER_SIZE > total_size) {
361 if (print_err)
362 pr_err("Error: bad microcode data file size.\n");
363 return -EINVAL;
364 }
365
366 if (mc_header->ldrver != 1 || mc_header->hdrver != 1) {
367 if (print_err)
368 pr_err("Error: invalid/unknown microcode update format.\n");
369 return -EINVAL;
370 }
371
372 ext_table_size = total_size - (MC_HEADER_SIZE + data_size);
373 if (ext_table_size) {
374 u32 ext_table_sum = 0;
375 u32 *ext_tablep;
376
377 if ((ext_table_size < EXT_HEADER_SIZE)
378 || ((ext_table_size - EXT_HEADER_SIZE) % EXT_SIGNATURE_SIZE)) {
379 if (print_err)
380 pr_err("Error: truncated extended signature table.\n");
381 return -EINVAL;
382 }
383
384 ext_header = mc + MC_HEADER_SIZE + data_size;
385 if (ext_table_size != exttable_size(ext_header)) {
386 if (print_err)
387 pr_err("Error: extended signature table size mismatch.\n");
388 return -EFAULT;
389 }
390
391 ext_sigcount = ext_header->count;
392
393 /*
394 * Check extended table checksum: the sum of all dwords that
395 * comprise a valid table must be 0.
396 */
397 ext_tablep = (u32 *)ext_header;
398
399 i = ext_table_size / sizeof(u32);
400 while (i--)
401 ext_table_sum += ext_tablep[i];
402
403 if (ext_table_sum) {
404 if (print_err)
405 pr_warn("Bad extended signature table checksum, aborting.\n");
406 return -EINVAL;
407 }
408 }
409
410 /*
411 * Calculate the checksum of update data and header. The checksum of
412 * valid update data and header including the extended signature table
413 * must be 0.
414 */
415 orig_sum = 0;
416 i = (MC_HEADER_SIZE + data_size) / sizeof(u32);
417 while (i--)
418 orig_sum += ((u32 *)mc)[i];
419
420 if (orig_sum) {
421 if (print_err)
422 pr_err("Bad microcode data checksum, aborting.\n");
423 return -EINVAL;
424 }
425
426 if (!ext_table_size)
427 return 0;
428
429 /*
430 * Check extended signature checksum: 0 => valid.
431 */
432 for (i = 0; i < ext_sigcount; i++) {
433 ext_sig = (void *)ext_header + EXT_HEADER_SIZE +
434 EXT_SIGNATURE_SIZE * i;
435
436 sum = (mc_header->sig + mc_header->pf + mc_header->cksum) -
437 (ext_sig->sig + ext_sig->pf + ext_sig->cksum);
438 if (sum) {
439 if (print_err)
440 pr_err("Bad extended signature checksum, aborting.\n");
441 return -EINVAL;
442 }
443 }
444 return 0;
445}
446
294/* 447/*
295 * Get microcode matching with BSP's model. Only CPUs with the same model as 448 * Get microcode matching with BSP's model. Only CPUs with the same model as
296 * BSP can stay in the platform. 449 * BSP can stay in the platform.
@@ -1105,4 +1258,3 @@ struct microcode_ops * __init init_intel_microcode(void)
1105 1258
1106 return &microcode_intel_ops; 1259 return &microcode_intel_ops;
1107} 1260}
1108