diff options
author | Borislav Petkov <bp@suse.de> | 2016-10-25 05:55:20 -0400 |
---|---|---|
committer | Ingo Molnar <mingo@kernel.org> | 2016-10-25 06:28:59 -0400 |
commit | 8027923ab4df9b2bdb9d642b7dceeb135c032f5e (patch) | |
tree | 14edc0f87034e5b93a33482daa88628854203a26 /arch/x86/kernel/cpu/microcode/intel.c | |
parent | 76bd11c23aaa5c4bed504bfc4cf690240759598d (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.c | 154 |
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 | ||
64 | static 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 | */ | ||
81 | static 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 | */ | ||
109 | static 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. */ |
65 | static enum ucode_state | 120 | static enum ucode_state |
66 | find_microcode_patch(struct microcode_intel **saved, | 121 | find_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 | ||
349 | static 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 µcode_intel_ops; | 1259 | return µcode_intel_ops; |
1107 | } | 1260 | } |
1108 | |||