From d496a002ae1f02425168e5211c237abee588651a Mon Sep 17 00:00:00 2001 From: Quentin Casasnovas Date: Thu, 26 Feb 2015 18:03:59 +0100 Subject: [PATCH 01/15] x86/microcode/intel: Fix out of bounds memory access to the extended header Improper pointer arithmetics when calculating the address of the extended header could lead to an out of bounds memory read and kernel panic. Signed-off-by: Quentin Casasnovas Link: http://lkml.kernel.org/r/20150225094125.GB30434@chrystal.uk.oracle.com Signed-off-by: Borislav Petkov --- arch/x86/kernel/cpu/microcode/intel_early.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/arch/x86/kernel/cpu/microcode/intel_early.c b/arch/x86/kernel/cpu/microcode/intel_early.c index 420eb933189ca..3a6c6136c9da0 100644 --- a/arch/x86/kernel/cpu/microcode/intel_early.c +++ b/arch/x86/kernel/cpu/microcode/intel_early.c @@ -180,8 +180,7 @@ matching_model_microcode(struct microcode_header_intel *mc_header, if (total_size <= data_size + MC_HEADER_SIZE) return UCODE_NFOUND; - ext_header = (struct extended_sigtable *) - mc_header + data_size + MC_HEADER_SIZE; + ext_header = (void *) mc_header + data_size + MC_HEADER_SIZE; ext_sigcount = ext_header->count; ext_sig = (void *)ext_header + EXT_HEADER_SIZE; @@ -457,8 +456,7 @@ static void __ref show_saved_mc(void) if (total_size <= data_size + MC_HEADER_SIZE) continue; - ext_header = (struct extended_sigtable *) - mc_saved_header + data_size + MC_HEADER_SIZE; + ext_header = (void *) mc_saved_header + data_size + MC_HEADER_SIZE; ext_sigcount = ext_header->count; ext_sig = (void *)ext_header + EXT_HEADER_SIZE; From 776d3cdc93d83808bf5929d716a56c69bbe01d2f Mon Sep 17 00:00:00 2001 From: Borislav Petkov Date: Thu, 5 Feb 2015 19:35:19 +0100 Subject: [PATCH 02/15] x86/microcode/intel: Check if microcode was found before applying We should check the return value of the routines fishing out the proper microcode and not try to apply if we haven't found a suitable blob. Signed-off-by: Borislav Petkov --- arch/x86/kernel/cpu/microcode/intel_early.c | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/arch/x86/kernel/cpu/microcode/intel_early.c b/arch/x86/kernel/cpu/microcode/intel_early.c index 3a6c6136c9da0..d515ff3feb8bd 100644 --- a/arch/x86/kernel/cpu/microcode/intel_early.c +++ b/arch/x86/kernel/cpu/microcode/intel_early.c @@ -727,9 +727,10 @@ _load_ucode_intel_bsp(struct mc_saved_data *mc_saved_data, ret = load_microcode(mc_saved_data, mc_saved_in_initrd, initrd_start_early, uci); + if (ret != UCODE_OK) + return; - if (ret == UCODE_OK) - apply_microcode_early(uci, true); + apply_microcode_early(uci, true); } void __init @@ -769,6 +770,7 @@ void load_ucode_intel_ap(void) struct ucode_cpu_info uci; unsigned long *mc_saved_in_initrd_p; unsigned long initrd_start_addr; + enum ucode_state ret; #ifdef CONFIG_X86_32 unsigned long *initrd_start_p; @@ -791,8 +793,12 @@ void load_ucode_intel_ap(void) return; collect_cpu_info_early(&uci); - load_microcode(mc_saved_data_p, mc_saved_in_initrd_p, - initrd_start_addr, &uci); + ret = load_microcode(mc_saved_data_p, mc_saved_in_initrd_p, + initrd_start_addr, &uci); + + if (ret != UCODE_OK) + return; + apply_microcode_early(&uci, true); } From f9524e6f5447277e238b419afc3d0712941fa2a5 Mon Sep 17 00:00:00 2001 From: Borislav Petkov Date: Thu, 5 Feb 2015 20:11:41 +0100 Subject: [PATCH 03/15] x86/microcode/intel: Do the mc_saved_src NULL check first ... and only then deref it. Also, shorten some variable names and rename others so as to diminish the ubiquitous presence of the "mc_" prefix everywhere and make it a bit more readable. Use kcalloc so that we don't kfree() uninitialized memory on the unwind path, as suggested by Quentin. Signed-off-by: Borislav Petkov Cc: Quentin Casasnovas --- arch/x86/kernel/cpu/microcode/intel_early.c | 38 ++++++++++++--------- 1 file changed, 22 insertions(+), 16 deletions(-) diff --git a/arch/x86/kernel/cpu/microcode/intel_early.c b/arch/x86/kernel/cpu/microcode/intel_early.c index d515ff3feb8bd..95516006958d0 100644 --- a/arch/x86/kernel/cpu/microcode/intel_early.c +++ b/arch/x86/kernel/cpu/microcode/intel_early.c @@ -203,7 +203,7 @@ save_microcode(struct mc_saved_data *mc_saved_data, unsigned int mc_saved_count) { int i, j; - struct microcode_intel **mc_saved_p; + struct microcode_intel **saved_ptr; int ret; if (!mc_saved_count) @@ -212,39 +212,45 @@ save_microcode(struct mc_saved_data *mc_saved_data, /* * Copy new microcode data. */ - mc_saved_p = kmalloc(mc_saved_count*sizeof(struct microcode_intel *), - GFP_KERNEL); - if (!mc_saved_p) + saved_ptr = kcalloc(mc_saved_count, sizeof(struct microcode_intel *), GFP_KERNEL); + if (!saved_ptr) return -ENOMEM; for (i = 0; i < mc_saved_count; i++) { - struct microcode_intel *mc = mc_saved_src[i]; - struct microcode_header_intel *mc_header = &mc->hdr; - unsigned long mc_size = get_totalsize(mc_header); - mc_saved_p[i] = kmalloc(mc_size, GFP_KERNEL); - if (!mc_saved_p[i]) { - ret = -ENOMEM; - goto err; - } + struct microcode_header_intel *mc_hdr; + struct microcode_intel *mc; + unsigned long size; + if (!mc_saved_src[i]) { ret = -EINVAL; goto err; } - memcpy(mc_saved_p[i], mc, mc_size); + + mc = mc_saved_src[i]; + mc_hdr = &mc->hdr; + size = get_totalsize(mc_hdr); + + saved_ptr[i] = kmalloc(size, GFP_KERNEL); + if (!saved_ptr[i]) { + ret = -ENOMEM; + goto err; + } + + memcpy(saved_ptr[i], mc, size); } /* * Point to newly saved microcode. */ - mc_saved_data->mc_saved = mc_saved_p; + mc_saved_data->mc_saved = saved_ptr; mc_saved_data->mc_saved_count = mc_saved_count; return 0; err: for (j = 0; j <= i; j++) - kfree(mc_saved_p[j]); - kfree(mc_saved_p); + kfree(saved_ptr[j]); + kfree(saved_ptr); return ret; } From 2d48bb9b6ec6fb0f28e5135fd080edc23152ae45 Mon Sep 17 00:00:00 2001 From: Borislav Petkov Date: Mon, 9 Feb 2015 17:40:03 +0100 Subject: [PATCH 04/15] x86/microcode/intel: Get rid of last arg to load_ucode_intel_bsp() Allocate it on the helper's _load_ucode_intel_bsp() stack instead and do not hand it down. Signed-off-by: Borislav Petkov --- arch/x86/kernel/cpu/microcode/intel_early.c | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/arch/x86/kernel/cpu/microcode/intel_early.c b/arch/x86/kernel/cpu/microcode/intel_early.c index 95516006958d0..ed30bc77dd385 100644 --- a/arch/x86/kernel/cpu/microcode/intel_early.c +++ b/arch/x86/kernel/cpu/microcode/intel_early.c @@ -722,21 +722,21 @@ static void __init _load_ucode_intel_bsp(struct mc_saved_data *mc_saved_data, unsigned long *mc_saved_in_initrd, unsigned long initrd_start_early, - unsigned long initrd_end_early, - struct ucode_cpu_info *uci) + unsigned long initrd_end_early) { + struct ucode_cpu_info uci; enum ucode_state ret; - collect_cpu_info_early(uci); + collect_cpu_info_early(&uci); scan_microcode(initrd_start_early, initrd_end_early, mc_saved_data, - mc_saved_in_initrd, uci); + mc_saved_in_initrd, &uci); ret = load_microcode(mc_saved_data, mc_saved_in_initrd, - initrd_start_early, uci); + initrd_start_early, &uci); if (ret != UCODE_OK) return; - apply_microcode_early(uci, true); + apply_microcode_early(&uci, true); } void __init @@ -744,7 +744,6 @@ load_ucode_intel_bsp(void) { u64 ramdisk_image, ramdisk_size; unsigned long initrd_start_early, initrd_end_early; - struct ucode_cpu_info uci; #ifdef CONFIG_X86_32 struct boot_params *boot_params_p; @@ -757,7 +756,7 @@ load_ucode_intel_bsp(void) _load_ucode_intel_bsp( (struct mc_saved_data *)__pa_nodebug(&mc_saved_data), (unsigned long *)__pa_nodebug(&mc_saved_in_initrd), - initrd_start_early, initrd_end_early, &uci); + initrd_start_early, initrd_end_early); #else ramdisk_image = boot_params.hdr.ramdisk_image; ramdisk_size = boot_params.hdr.ramdisk_size; @@ -765,8 +764,7 @@ load_ucode_intel_bsp(void) initrd_end_early = initrd_start_early + ramdisk_size; _load_ucode_intel_bsp(&mc_saved_data, mc_saved_in_initrd, - initrd_start_early, initrd_end_early, - &uci); + initrd_start_early, initrd_end_early); #endif } From 02f35177fb00ee0d73f9af2d6006af6b75b58c11 Mon Sep 17 00:00:00 2001 From: Borislav Petkov Date: Mon, 9 Feb 2015 22:59:51 +0100 Subject: [PATCH 05/15] x86/microcode/intel: Simplify load_ucode_intel_bsp() Don't compute start and end from start and size in order to compute size again down the path in scan_microcode(). So pass size directly instead and simplify a bunch. Shorten variable names and remove useless ones. Signed-off-by: Borislav Petkov --- arch/x86/kernel/cpu/microcode/intel_early.c | 49 ++++++++------------- 1 file changed, 18 insertions(+), 31 deletions(-) diff --git a/arch/x86/kernel/cpu/microcode/intel_early.c b/arch/x86/kernel/cpu/microcode/intel_early.c index ed30bc77dd385..34a2ff9217f89 100644 --- a/arch/x86/kernel/cpu/microcode/intel_early.c +++ b/arch/x86/kernel/cpu/microcode/intel_early.c @@ -552,12 +552,10 @@ EXPORT_SYMBOL_GPL(save_mc_for_early); static __initdata char ucode_name[] = "kernel/x86/microcode/GenuineIntel.bin"; static __init enum ucode_state -scan_microcode(unsigned long start, unsigned long end, - struct mc_saved_data *mc_saved_data, - unsigned long *mc_saved_in_initrd, - struct ucode_cpu_info *uci) +scan_microcode(unsigned long start, unsigned long size, + struct mc_saved_data *mc_saved_data, + unsigned long *mc_saved_in_initrd, struct ucode_cpu_info *uci) { - unsigned int size = end - start + 1; struct cpio_data cd; long offset = 0; #ifdef CONFIG_X86_32 @@ -573,7 +571,6 @@ scan_microcode(unsigned long start, unsigned long end, if (!cd.data) return UCODE_ERROR; - return get_matching_model_microcode(0, start, cd.data, cd.size, mc_saved_data, mc_saved_in_initrd, uci); @@ -721,50 +718,40 @@ int __init save_microcode_in_initrd_intel(void) static void __init _load_ucode_intel_bsp(struct mc_saved_data *mc_saved_data, unsigned long *mc_saved_in_initrd, - unsigned long initrd_start_early, - unsigned long initrd_end_early) + unsigned long start, unsigned long size) { struct ucode_cpu_info uci; enum ucode_state ret; collect_cpu_info_early(&uci); - scan_microcode(initrd_start_early, initrd_end_early, mc_saved_data, - mc_saved_in_initrd, &uci); + scan_microcode(start, size, mc_saved_data, mc_saved_in_initrd, &uci); - ret = load_microcode(mc_saved_data, mc_saved_in_initrd, - initrd_start_early, &uci); + ret = load_microcode(mc_saved_data, mc_saved_in_initrd, start, &uci); if (ret != UCODE_OK) return; apply_microcode_early(&uci, true); } -void __init -load_ucode_intel_bsp(void) +void __init load_ucode_intel_bsp(void) { - u64 ramdisk_image, ramdisk_size; - unsigned long initrd_start_early, initrd_end_early; + u64 start, size; #ifdef CONFIG_X86_32 - struct boot_params *boot_params_p; + struct boot_params *p; - boot_params_p = (struct boot_params *)__pa_nodebug(&boot_params); - ramdisk_image = boot_params_p->hdr.ramdisk_image; - ramdisk_size = boot_params_p->hdr.ramdisk_size; - initrd_start_early = ramdisk_image; - initrd_end_early = initrd_start_early + ramdisk_size; + p = (struct boot_params *)__pa_nodebug(&boot_params); + start = p->hdr.ramdisk_image; + size = p->hdr.ramdisk_size; _load_ucode_intel_bsp( - (struct mc_saved_data *)__pa_nodebug(&mc_saved_data), - (unsigned long *)__pa_nodebug(&mc_saved_in_initrd), - initrd_start_early, initrd_end_early); + (struct mc_saved_data *)__pa_nodebug(&mc_saved_data), + (unsigned long *)__pa_nodebug(&mc_saved_in_initrd), + start, size); #else - ramdisk_image = boot_params.hdr.ramdisk_image; - ramdisk_size = boot_params.hdr.ramdisk_size; - initrd_start_early = ramdisk_image + PAGE_OFFSET; - initrd_end_early = initrd_start_early + ramdisk_size; + start = boot_params.hdr.ramdisk_image + PAGE_OFFSET; + size = boot_params.hdr.ramdisk_size; - _load_ucode_intel_bsp(&mc_saved_data, mc_saved_in_initrd, - initrd_start_early, initrd_end_early); + _load_ucode_intel_bsp(&mc_saved_data, mc_saved_in_initrd, start, size); #endif } From a5de5e242b80c085913041e99ab245408083f273 Mon Sep 17 00:00:00 2001 From: Borislav Petkov Date: Mon, 9 Feb 2015 17:49:43 +0100 Subject: [PATCH 06/15] x86/microcode/intel: Make _save_mc() return the updated saved count ... of microcode patches instead of handing in a pointer which is used for I/O in an otherwise void function. Signed-off-by: Borislav Petkov --- arch/x86/kernel/cpu/microcode/intel_early.c | 29 ++++++++++----------- 1 file changed, 14 insertions(+), 15 deletions(-) diff --git a/arch/x86/kernel/cpu/microcode/intel_early.c b/arch/x86/kernel/cpu/microcode/intel_early.c index 34a2ff9217f89..f1d9a321d4248 100644 --- a/arch/x86/kernel/cpu/microcode/intel_early.c +++ b/arch/x86/kernel/cpu/microcode/intel_early.c @@ -262,17 +262,18 @@ save_microcode(struct mc_saved_data *mc_saved_data, * - or if it is a newly discovered microcode patch. * * The microcode patch should have matching model with CPU. + * + * Returns: The updated number @num_saved of saved microcode patches. */ -static void _save_mc(struct microcode_intel **mc_saved, u8 *ucode_ptr, - unsigned int *mc_saved_count_p) +static unsigned int _save_mc(struct microcode_intel **mc_saved, + u8 *ucode_ptr, unsigned int num_saved) { - int i; - int found = 0; - unsigned int mc_saved_count = *mc_saved_count_p; struct microcode_header_intel *mc_header; + int found = 0, i; mc_header = (struct microcode_header_intel *)ucode_ptr; - for (i = 0; i < mc_saved_count; i++) { + + for (i = 0; i < num_saved; i++) { unsigned int sig, pf; unsigned int new_rev; struct microcode_header_intel *mc_saved_header = @@ -289,21 +290,20 @@ static void _save_mc(struct microcode_intel **mc_saved, u8 *ucode_ptr, * Replace the older one with this newer * one. */ - mc_saved[i] = - (struct microcode_intel *)ucode_ptr; + mc_saved[i] = (struct microcode_intel *)ucode_ptr; break; } } } - if (i >= mc_saved_count && !found) + + if (i >= num_saved && !found) /* * This ucode is first time discovered in ucode file. * Save it to memory. */ - mc_saved[mc_saved_count++] = - (struct microcode_intel *)ucode_ptr; + mc_saved[num_saved++] = (struct microcode_intel *)ucode_ptr; - *mc_saved_count_p = mc_saved_count; + return num_saved; } /* @@ -351,7 +351,7 @@ get_matching_model_microcode(int cpu, unsigned long start, continue; } - _save_mc(mc_saved_tmp, ucode_ptr, &mc_saved_count); + mc_saved_count = _save_mc(mc_saved_tmp, ucode_ptr, mc_saved_count); ucode_ptr += mc_size; } @@ -519,8 +519,7 @@ int save_mc_for_early(u8 *mc) * Save the microcode patch mc in mc_save_tmp structure if it's a newer * version. */ - - _save_mc(mc_saved_tmp, mc, &mc_saved_count); + mc_saved_count = _save_mc(mc_saved_tmp, mc, mc_saved_count); /* * Save the mc_save_tmp in global mc_saved_data. From c868570e745781736366b83191aae2ccb9de2d1c Mon Sep 17 00:00:00 2001 From: Borislav Petkov Date: Mon, 9 Feb 2015 17:59:01 +0100 Subject: [PATCH 07/15] x86/microcode/intel: Sanitize _save_mc() Shorten local variable names for better readability and flatten loop indentation levels. No functionality change. Signed-off-by: Borislav Petkov --- arch/x86/kernel/cpu/microcode/intel_early.c | 49 ++++++++++----------- 1 file changed, 23 insertions(+), 26 deletions(-) diff --git a/arch/x86/kernel/cpu/microcode/intel_early.c b/arch/x86/kernel/cpu/microcode/intel_early.c index f1d9a321d4248..94ec304b7af3a 100644 --- a/arch/x86/kernel/cpu/microcode/intel_early.c +++ b/arch/x86/kernel/cpu/microcode/intel_early.c @@ -268,39 +268,36 @@ save_microcode(struct mc_saved_data *mc_saved_data, static unsigned int _save_mc(struct microcode_intel **mc_saved, u8 *ucode_ptr, unsigned int num_saved) { - struct microcode_header_intel *mc_header; + struct microcode_header_intel *mc_hdr, *mc_saved_hdr; + unsigned int sig, pf, new_rev; int found = 0, i; - mc_header = (struct microcode_header_intel *)ucode_ptr; + mc_hdr = (struct microcode_header_intel *)ucode_ptr; for (i = 0; i < num_saved; i++) { - unsigned int sig, pf; - unsigned int new_rev; - struct microcode_header_intel *mc_saved_header = - (struct microcode_header_intel *)mc_saved[i]; - sig = mc_saved_header->sig; - pf = mc_saved_header->pf; - new_rev = mc_header->rev; - - if (get_matching_sig(sig, pf, ucode_ptr, new_rev)) { - found = 1; - if (update_match_revision(mc_header, new_rev)) { - /* - * Found an older ucode saved before. - * Replace the older one with this newer - * one. - */ - mc_saved[i] = (struct microcode_intel *)ucode_ptr; - break; - } - } - } + mc_saved_hdr = (struct microcode_header_intel *)mc_saved[i]; + sig = mc_saved_hdr->sig; + pf = mc_saved_hdr->pf; + new_rev = mc_hdr->rev; + + if (!get_matching_sig(sig, pf, ucode_ptr, new_rev)) + continue; + + found = 1; + + if (!update_match_revision(mc_hdr, new_rev)) + continue; - if (i >= num_saved && !found) /* - * This ucode is first time discovered in ucode file. - * Save it to memory. + * Found an older ucode saved earlier. Replace it with + * this newer one. */ + mc_saved[i] = (struct microcode_intel *)ucode_ptr; + break; + } + + /* Newly detected microcode, save it to memory. */ + if (i >= num_saved && !found) mc_saved[num_saved++] = (struct microcode_intel *)ucode_ptr; return num_saved; From 4f5e5f2b574804ed330e20456d5b86a4259544ad Mon Sep 17 00:00:00 2001 From: Borislav Petkov Date: Mon, 9 Feb 2015 18:10:29 +0100 Subject: [PATCH 08/15] x86/microcode/intel: Rename update_match_revision() ... to revision_is_newer() and push it up into the header and make it an inline function. Signed-off-by: Borislav Petkov --- arch/x86/include/asm/microcode_intel.h | 8 ++++++-- arch/x86/kernel/cpu/microcode/intel_early.c | 2 +- arch/x86/kernel/cpu/microcode/intel_lib.c | 8 +------- 3 files changed, 8 insertions(+), 10 deletions(-) diff --git a/arch/x86/include/asm/microcode_intel.h b/arch/x86/include/asm/microcode_intel.h index dd4c20043ce75..a6b753a131cd8 100644 --- a/arch/x86/include/asm/microcode_intel.h +++ b/arch/x86/include/asm/microcode_intel.h @@ -60,8 +60,12 @@ extern int get_matching_microcode(unsigned int csig, int cpf, void *mc, int rev); extern int microcode_sanity_check(void *mc, int print_err); extern int get_matching_sig(unsigned int csig, int cpf, void *mc, int rev); -extern int -update_match_revision(struct microcode_header_intel *mc_header, int rev); + +static inline int +revision_is_newer(struct microcode_header_intel *mc_header, int rev) +{ + return (mc_header->rev <= rev) ? 0 : 1; +} #ifdef CONFIG_MICROCODE_INTEL_EARLY extern void __init load_ucode_intel_bsp(void); diff --git a/arch/x86/kernel/cpu/microcode/intel_early.c b/arch/x86/kernel/cpu/microcode/intel_early.c index 94ec304b7af3a..cd42b3a55897c 100644 --- a/arch/x86/kernel/cpu/microcode/intel_early.c +++ b/arch/x86/kernel/cpu/microcode/intel_early.c @@ -285,7 +285,7 @@ static unsigned int _save_mc(struct microcode_intel **mc_saved, found = 1; - if (!update_match_revision(mc_hdr, new_rev)) + if (!revision_is_newer(mc_hdr, new_rev)) continue; /* diff --git a/arch/x86/kernel/cpu/microcode/intel_lib.c b/arch/x86/kernel/cpu/microcode/intel_lib.c index ce69320d01790..7e259d99b0aa0 100644 --- a/arch/x86/kernel/cpu/microcode/intel_lib.c +++ b/arch/x86/kernel/cpu/microcode/intel_lib.c @@ -38,12 +38,6 @@ update_match_cpu(unsigned int csig, unsigned int cpf, return (!sigmatch(sig, csig, pf, cpf)) ? 0 : 1; } -int -update_match_revision(struct microcode_header_intel *mc_header, int rev) -{ - return (mc_header->rev <= rev) ? 0 : 1; -} - int microcode_sanity_check(void *mc, int print_err) { unsigned long total_size, data_size, ext_table_size; @@ -166,7 +160,7 @@ int get_matching_microcode(unsigned int csig, int cpf, void *mc, int rev) { struct microcode_header_intel *mc_header = mc; - if (!update_match_revision(mc_header, rev)) + if (!revision_is_newer(mc_header, rev)) return 0; return get_matching_sig(csig, cpf, mc, rev); From 58ce8d6d3a7616014dc70fd8d8f945176d74957c Mon Sep 17 00:00:00 2001 From: Borislav Petkov Date: Mon, 9 Feb 2015 21:42:34 +0100 Subject: [PATCH 09/15] x86/microcode: Consolidate family,model, ... code ... to the header. Split the family acquiring function into a main one, doing CPUID and a helper which computes the extended family and is used in multiple places. Get rid of the locally-grown get_x86_{family,model}(). While at it, rename local variables to something more descriptive and vertically align assignments for better readability. There should be no functionality change resulting from this patch. Signed-off-by: Borislav Petkov --- arch/x86/include/asm/microcode.h | 73 ++++++++++++++++++++ arch/x86/kernel/cpu/microcode/core_early.c | 75 ++++----------------- arch/x86/kernel/cpu/microcode/intel_early.c | 58 +++++----------- 3 files changed, 101 insertions(+), 105 deletions(-) diff --git a/arch/x86/include/asm/microcode.h b/arch/x86/include/asm/microcode.h index 201b520521ed7..2fb20d6f7e23b 100644 --- a/arch/x86/include/asm/microcode.h +++ b/arch/x86/include/asm/microcode.h @@ -75,6 +75,79 @@ static inline void __exit exit_amd_microcode(void) {} #ifdef CONFIG_MICROCODE_EARLY #define MAX_UCODE_COUNT 128 + +#define QCHAR(a, b, c, d) ((a) + ((b) << 8) + ((c) << 16) + ((d) << 24)) +#define CPUID_INTEL1 QCHAR('G', 'e', 'n', 'u') +#define CPUID_INTEL2 QCHAR('i', 'n', 'e', 'I') +#define CPUID_INTEL3 QCHAR('n', 't', 'e', 'l') +#define CPUID_AMD1 QCHAR('A', 'u', 't', 'h') +#define CPUID_AMD2 QCHAR('e', 'n', 't', 'i') +#define CPUID_AMD3 QCHAR('c', 'A', 'M', 'D') + +#define CPUID_IS(a, b, c, ebx, ecx, edx) \ + (!((ebx ^ (a))|(edx ^ (b))|(ecx ^ (c)))) + +/* + * In early loading microcode phase on BSP, boot_cpu_data is not set up yet. + * x86_vendor() gets vendor id for BSP. + * + * In 32 bit AP case, accessing boot_cpu_data needs linear address. To simplify + * coding, we still use x86_vendor() to get vendor id for AP. + * + * x86_vendor() gets vendor information directly from CPUID. + */ +static inline int x86_vendor(void) +{ + u32 eax = 0x00000000; + u32 ebx, ecx = 0, edx; + + native_cpuid(&eax, &ebx, &ecx, &edx); + + if (CPUID_IS(CPUID_INTEL1, CPUID_INTEL2, CPUID_INTEL3, ebx, ecx, edx)) + return X86_VENDOR_INTEL; + + if (CPUID_IS(CPUID_AMD1, CPUID_AMD2, CPUID_AMD3, ebx, ecx, edx)) + return X86_VENDOR_AMD; + + return X86_VENDOR_UNKNOWN; +} + +static inline unsigned int __x86_family(unsigned int sig) +{ + unsigned int x86; + + x86 = (sig >> 8) & 0xf; + + if (x86 == 0xf) + x86 += (sig >> 20) & 0xff; + + return x86; +} + +static inline unsigned int x86_family(void) +{ + u32 eax = 0x00000001; + u32 ebx, ecx = 0, edx; + + native_cpuid(&eax, &ebx, &ecx, &edx); + + return __x86_family(eax); +} + +static inline unsigned int x86_model(unsigned int sig) +{ + unsigned int x86, model; + + x86 = __x86_family(sig); + + model = (sig >> 4) & 0xf; + + if (x86 == 0x6 || x86 == 0xf) + model += ((sig >> 16) & 0xf) << 4; + + return model; +} + extern void __init load_ucode_bsp(void); extern void load_ucode_ap(void); extern int __init save_microcode_in_initrd(void); diff --git a/arch/x86/kernel/cpu/microcode/core_early.c b/arch/x86/kernel/cpu/microcode/core_early.c index d45df4bd16abe..a413a69cbd744 100644 --- a/arch/x86/kernel/cpu/microcode/core_early.c +++ b/arch/x86/kernel/cpu/microcode/core_early.c @@ -23,57 +23,6 @@ #include #include -#define QCHAR(a, b, c, d) ((a) + ((b) << 8) + ((c) << 16) + ((d) << 24)) -#define CPUID_INTEL1 QCHAR('G', 'e', 'n', 'u') -#define CPUID_INTEL2 QCHAR('i', 'n', 'e', 'I') -#define CPUID_INTEL3 QCHAR('n', 't', 'e', 'l') -#define CPUID_AMD1 QCHAR('A', 'u', 't', 'h') -#define CPUID_AMD2 QCHAR('e', 'n', 't', 'i') -#define CPUID_AMD3 QCHAR('c', 'A', 'M', 'D') - -#define CPUID_IS(a, b, c, ebx, ecx, edx) \ - (!((ebx ^ (a))|(edx ^ (b))|(ecx ^ (c)))) - -/* - * In early loading microcode phase on BSP, boot_cpu_data is not set up yet. - * x86_vendor() gets vendor id for BSP. - * - * In 32 bit AP case, accessing boot_cpu_data needs linear address. To simplify - * coding, we still use x86_vendor() to get vendor id for AP. - * - * x86_vendor() gets vendor information directly through cpuid. - */ -static int x86_vendor(void) -{ - u32 eax = 0x00000000; - u32 ebx, ecx = 0, edx; - - native_cpuid(&eax, &ebx, &ecx, &edx); - - if (CPUID_IS(CPUID_INTEL1, CPUID_INTEL2, CPUID_INTEL3, ebx, ecx, edx)) - return X86_VENDOR_INTEL; - - if (CPUID_IS(CPUID_AMD1, CPUID_AMD2, CPUID_AMD3, ebx, ecx, edx)) - return X86_VENDOR_AMD; - - return X86_VENDOR_UNKNOWN; -} - -static int x86_family(void) -{ - u32 eax = 0x00000001; - u32 ebx, ecx = 0, edx; - int x86; - - native_cpuid(&eax, &ebx, &ecx, &edx); - - x86 = (eax >> 8) & 0xf; - if (x86 == 15) - x86 += (eax >> 20) & 0xff; - - return x86; -} - static bool __init check_loader_disabled_bsp(void) { #ifdef CONFIG_X86_32 @@ -96,7 +45,7 @@ static bool __init check_loader_disabled_bsp(void) void __init load_ucode_bsp(void) { - int vendor, x86; + int vendor, family; if (check_loader_disabled_bsp()) return; @@ -105,15 +54,15 @@ void __init load_ucode_bsp(void) return; vendor = x86_vendor(); - x86 = x86_family(); + family = x86_family(); switch (vendor) { case X86_VENDOR_INTEL: - if (x86 >= 6) + if (family >= 6) load_ucode_intel_bsp(); break; case X86_VENDOR_AMD: - if (x86 >= 0x10) + if (family >= 0x10) load_ucode_amd_bsp(); break; default: @@ -132,7 +81,7 @@ static bool check_loader_disabled_ap(void) void load_ucode_ap(void) { - int vendor, x86; + int vendor, family; if (check_loader_disabled_ap()) return; @@ -141,15 +90,15 @@ void load_ucode_ap(void) return; vendor = x86_vendor(); - x86 = x86_family(); + family = x86_family(); switch (vendor) { case X86_VENDOR_INTEL: - if (x86 >= 6) + if (family >= 6) load_ucode_intel_ap(); break; case X86_VENDOR_AMD: - if (x86 >= 0x10) + if (family >= 0x10) load_ucode_amd_ap(); break; default: @@ -179,18 +128,18 @@ int __init save_microcode_in_initrd(void) void reload_early_microcode(void) { - int vendor, x86; + int vendor, family; vendor = x86_vendor(); - x86 = x86_family(); + family = x86_family(); switch (vendor) { case X86_VENDOR_INTEL: - if (x86 >= 6) + if (family >= 6) reload_ucode_intel(); break; case X86_VENDOR_AMD: - if (x86 >= 0x10) + if (family >= 0x10) reload_ucode_amd(); break; default: diff --git a/arch/x86/kernel/cpu/microcode/intel_early.c b/arch/x86/kernel/cpu/microcode/intel_early.c index cd42b3a55897c..5c7896bf0e4d8 100644 --- a/arch/x86/kernel/cpu/microcode/intel_early.c +++ b/arch/x86/kernel/cpu/microcode/intel_early.c @@ -126,31 +126,6 @@ load_microcode(struct mc_saved_data *mc_saved_data, } } -static u8 get_x86_family(unsigned long sig) -{ - u8 x86; - - x86 = (sig >> 8) & 0xf; - - if (x86 == 0xf) - x86 += (sig >> 20) & 0xff; - - return x86; -} - -static u8 get_x86_model(unsigned long sig) -{ - u8 x86, x86_model; - - x86 = get_x86_family(sig); - x86_model = (sig >> 4) & 0xf; - - if (x86 == 0x6 || x86 == 0xf) - x86_model += ((sig >> 16) & 0xf) << 4; - - return x86_model; -} - /* * Given CPU signature and a microcode patch, this function finds if the * microcode patch has matching family and model with the CPU. @@ -159,41 +134,40 @@ static enum ucode_state matching_model_microcode(struct microcode_header_intel *mc_header, unsigned long sig) { - u8 x86, x86_model; - u8 x86_ucode, x86_model_ucode; + unsigned int fam, model; + unsigned int fam_ucode, model_ucode; struct extended_sigtable *ext_header; unsigned long total_size = get_totalsize(mc_header); unsigned long data_size = get_datasize(mc_header); int ext_sigcount, i; struct extended_signature *ext_sig; - x86 = get_x86_family(sig); - x86_model = get_x86_model(sig); + fam = __x86_family(sig); + model = x86_model(sig); - x86_ucode = get_x86_family(mc_header->sig); - x86_model_ucode = get_x86_model(mc_header->sig); + fam_ucode = __x86_family(mc_header->sig); + model_ucode = x86_model(mc_header->sig); - if (x86 == x86_ucode && x86_model == x86_model_ucode) + if (fam == fam_ucode && model == model_ucode) return UCODE_OK; /* Look for ext. headers: */ if (total_size <= data_size + MC_HEADER_SIZE) return UCODE_NFOUND; - ext_header = (void *) mc_header + data_size + MC_HEADER_SIZE; + ext_header = (void *) mc_header + data_size + MC_HEADER_SIZE; + ext_sig = (void *)ext_header + EXT_HEADER_SIZE; ext_sigcount = ext_header->count; - ext_sig = (void *)ext_header + EXT_HEADER_SIZE; for (i = 0; i < ext_sigcount; i++) { - x86_ucode = get_x86_family(ext_sig->sig); - x86_model_ucode = get_x86_model(ext_sig->sig); + fam_ucode = __x86_family(ext_sig->sig); + model_ucode = x86_model(ext_sig->sig); - if (x86 == x86_ucode && x86_model == x86_model_ucode) + if (fam == fam_ucode && model == model_ucode) return UCODE_OK; ext_sig++; } - return UCODE_NFOUND; } @@ -374,7 +348,7 @@ get_matching_model_microcode(int cpu, unsigned long start, static int collect_cpu_info_early(struct ucode_cpu_info *uci) { unsigned int val[2]; - u8 x86, x86_model; + unsigned int family, model; struct cpu_signature csig; unsigned int eax, ebx, ecx, edx; @@ -389,10 +363,10 @@ static int collect_cpu_info_early(struct ucode_cpu_info *uci) native_cpuid(&eax, &ebx, &ecx, &edx); csig.sig = eax; - x86 = get_x86_family(csig.sig); - x86_model = get_x86_model(csig.sig); + family = __x86_family(csig.sig); + model = x86_model(csig.sig); - if ((x86_model >= 5) || (x86 > 6)) { + if ((model >= 5) || (family > 6)) { /* get processor flags from MSR 0x17 */ native_rdmsr(MSR_IA32_PLATFORM_ID, val[0], val[1]); csig.pf = 1 << ((val[1] >> 18) & 7); From 9e02bb46d366b3635da966e29c5a53920ee7fde8 Mon Sep 17 00:00:00 2001 From: Borislav Petkov Date: Tue, 10 Feb 2015 10:56:37 +0100 Subject: [PATCH 10/15] x86/microcode/intel: Simplify generic_load_microcode_early() * remove state variable and out label * get rid of completely unused mc_size * shorten variable names * get rid of local variables * don't do assignments in local var declarations for less cluttered code * finally rename it to the shorter and perfectly fine load_microcode_early() No functionality change. Signed-off-by: Borislav Petkov --- arch/x86/kernel/cpu/microcode/intel_early.c | 55 ++++++++++----------- 1 file changed, 26 insertions(+), 29 deletions(-) diff --git a/arch/x86/kernel/cpu/microcode/intel_early.c b/arch/x86/kernel/cpu/microcode/intel_early.c index 5c7896bf0e4d8..d7192124f50b4 100644 --- a/arch/x86/kernel/cpu/microcode/intel_early.c +++ b/arch/x86/kernel/cpu/microcode/intel_early.c @@ -35,38 +35,35 @@ static struct mc_saved_data { } mc_saved_data; static enum ucode_state -generic_load_microcode_early(struct microcode_intel **mc_saved_p, - unsigned int mc_saved_count, - struct ucode_cpu_info *uci) +load_microcode_early(struct microcode_intel **saved, + unsigned int num_saved, struct ucode_cpu_info *uci) { struct microcode_intel *ucode_ptr, *new_mc = NULL; - int new_rev = uci->cpu_sig.rev; - enum ucode_state state = UCODE_OK; - unsigned int mc_size; - struct microcode_header_intel *mc_header; - unsigned int csig = uci->cpu_sig.sig; - unsigned int cpf = uci->cpu_sig.pf; - int i; + struct microcode_header_intel *mc_hdr; + int new_rev, ret, i; - for (i = 0; i < mc_saved_count; i++) { - ucode_ptr = mc_saved_p[i]; + new_rev = uci->cpu_sig.rev; - mc_header = (struct microcode_header_intel *)ucode_ptr; - mc_size = get_totalsize(mc_header); - if (get_matching_microcode(csig, cpf, ucode_ptr, new_rev)) { - new_rev = mc_header->rev; - new_mc = ucode_ptr; - } - } + for (i = 0; i < num_saved; i++) { + ucode_ptr = saved[i]; + mc_hdr = (struct microcode_header_intel *)ucode_ptr; + + ret = get_matching_microcode(uci->cpu_sig.sig, + uci->cpu_sig.pf, + ucode_ptr, + new_rev); + if (!ret) + continue; - if (!new_mc) { - state = UCODE_NFOUND; - goto out; + new_rev = mc_hdr->rev; + new_mc = ucode_ptr; } + if (!new_mc) + return UCODE_NFOUND; + uci->mc = (struct microcode_intel *)new_mc; -out: - return state; + return UCODE_OK; } static void @@ -114,13 +111,13 @@ load_microcode(struct mc_saved_data *mc_saved_data, microcode_pointer(mc_saved_tmp, mc_saved_in_initrd, initrd_start, count); - return generic_load_microcode_early(mc_saved_tmp, count, uci); + return load_microcode_early(mc_saved_tmp, count, uci); } else { #ifdef CONFIG_X86_32 microcode_phys(mc_saved_tmp, mc_saved_data); - return generic_load_microcode_early(mc_saved_tmp, count, uci); + return load_microcode_early(mc_saved_tmp, count, uci); #else - return generic_load_microcode_early(mc_saved_data->mc_saved, + return load_microcode_early(mc_saved_data->mc_saved, count, uci); #endif } @@ -773,8 +770,8 @@ void reload_ucode_intel(void) collect_cpu_info_early(&uci); - ret = generic_load_microcode_early(mc_saved_data.mc_saved, - mc_saved_data.mc_saved_count, &uci); + ret = load_microcode_early(mc_saved_data.mc_saved, + mc_saved_data.mc_saved_count, &uci); if (ret != UCODE_OK) return; From e3d8f6747663b468ccedb8af0f38f2be82874c63 Mon Sep 17 00:00:00 2001 From: Borislav Petkov Date: Tue, 10 Feb 2015 11:28:23 +0100 Subject: [PATCH 11/15] x86/microcode/intel: Move mc arg last in get_matching_{microcode|sig} ... arguments list so that it comes more natural for those functions to have the signature, processor flags and revision together, before the rest of the args. No functionality change. Signed-off-by: Borislav Petkov --- arch/x86/include/asm/microcode_intel.h | 5 ++--- arch/x86/kernel/cpu/microcode/intel.c | 4 ++-- arch/x86/kernel/cpu/microcode/intel_early.c | 6 +++--- arch/x86/kernel/cpu/microcode/intel_lib.c | 16 +++++++--------- 4 files changed, 14 insertions(+), 17 deletions(-) diff --git a/arch/x86/include/asm/microcode_intel.h b/arch/x86/include/asm/microcode_intel.h index a6b753a131cd8..2b9209c46ca93 100644 --- a/arch/x86/include/asm/microcode_intel.h +++ b/arch/x86/include/asm/microcode_intel.h @@ -56,10 +56,9 @@ struct extended_sigtable { #define exttable_size(et) ((et)->count * EXT_SIGNATURE_SIZE + EXT_HEADER_SIZE) -extern int -get_matching_microcode(unsigned int csig, int cpf, void *mc, int rev); +extern int get_matching_microcode(unsigned int csig, int cpf, int rev, void *mc); extern int microcode_sanity_check(void *mc, int print_err); -extern int get_matching_sig(unsigned int csig, int cpf, void *mc, int rev); +extern int get_matching_sig(unsigned int csig, int cpf, int rev, void *mc); static inline int revision_is_newer(struct microcode_header_intel *mc_header, int rev) diff --git a/arch/x86/kernel/cpu/microcode/intel.c b/arch/x86/kernel/cpu/microcode/intel.c index 746e7fd08aad7..a41beadb3db9a 100644 --- a/arch/x86/kernel/cpu/microcode/intel.c +++ b/arch/x86/kernel/cpu/microcode/intel.c @@ -124,7 +124,7 @@ static int get_matching_mc(struct microcode_intel *mc_intel, int cpu) cpf = cpu_sig.pf; crev = cpu_sig.rev; - return get_matching_microcode(csig, cpf, mc_intel, crev); + return get_matching_microcode(csig, cpf, crev, mc_intel); } static int apply_microcode_intel(int cpu) @@ -226,7 +226,7 @@ static enum ucode_state generic_load_microcode(int cpu, void *data, size_t size, csig = uci->cpu_sig.sig; cpf = uci->cpu_sig.pf; - if (get_matching_microcode(csig, cpf, mc, new_rev)) { + if (get_matching_microcode(csig, cpf, new_rev, mc)) { vfree(new_mc); new_rev = mc_header.rev; new_mc = mc; diff --git a/arch/x86/kernel/cpu/microcode/intel_early.c b/arch/x86/kernel/cpu/microcode/intel_early.c index d7192124f50b4..844c758951609 100644 --- a/arch/x86/kernel/cpu/microcode/intel_early.c +++ b/arch/x86/kernel/cpu/microcode/intel_early.c @@ -50,8 +50,8 @@ load_microcode_early(struct microcode_intel **saved, ret = get_matching_microcode(uci->cpu_sig.sig, uci->cpu_sig.pf, - ucode_ptr, - new_rev); + new_rev, + ucode_ptr); if (!ret) continue; @@ -251,7 +251,7 @@ static unsigned int _save_mc(struct microcode_intel **mc_saved, pf = mc_saved_hdr->pf; new_rev = mc_hdr->rev; - if (!get_matching_sig(sig, pf, ucode_ptr, new_rev)) + if (!get_matching_sig(sig, pf, new_rev, ucode_ptr)) continue; found = 1; diff --git a/arch/x86/kernel/cpu/microcode/intel_lib.c b/arch/x86/kernel/cpu/microcode/intel_lib.c index 7e259d99b0aa0..cd47a510a3f17 100644 --- a/arch/x86/kernel/cpu/microcode/intel_lib.c +++ b/arch/x86/kernel/cpu/microcode/intel_lib.c @@ -122,10 +122,9 @@ int microcode_sanity_check(void *mc, int print_err) EXPORT_SYMBOL_GPL(microcode_sanity_check); /* - * return 0 - no update found - * return 1 - found update + * Returns 1 if update has been found, 0 otherwise. */ -int get_matching_sig(unsigned int csig, int cpf, void *mc, int rev) +int get_matching_sig(unsigned int csig, int cpf, int rev, void *mc) { struct microcode_header_intel *mc_header = mc; struct extended_sigtable *ext_header; @@ -153,16 +152,15 @@ int get_matching_sig(unsigned int csig, int cpf, void *mc, int rev) } /* - * return 0 - no update found - * return 1 - found update + * Returns 1 if update has been found, 0 otherwise. */ -int get_matching_microcode(unsigned int csig, int cpf, void *mc, int rev) +int get_matching_microcode(unsigned int csig, int cpf, int rev, void *mc) { - struct microcode_header_intel *mc_header = mc; + struct microcode_header_intel *mc_hdr = mc; - if (!revision_is_newer(mc_header, rev)) + if (!revision_is_newer(mc_hdr, rev)) return 0; - return get_matching_sig(csig, cpf, mc, rev); + return get_matching_sig(csig, cpf, rev, mc); } EXPORT_SYMBOL_GPL(get_matching_microcode); From 140f74fcedbfc862178c082c50b5f54dd52c1ce4 Mon Sep 17 00:00:00 2001 From: Borislav Petkov Date: Tue, 10 Feb 2015 12:00:56 +0100 Subject: [PATCH 12/15] x86/microcode/intel: Sanitize microcode_pointer() Shorten variable names and rename it to what it does. No functionality change. Signed-off-by: Borislav Petkov --- arch/x86/kernel/cpu/microcode/intel_early.c | 23 ++++++++------------- 1 file changed, 9 insertions(+), 14 deletions(-) diff --git a/arch/x86/kernel/cpu/microcode/intel_early.c b/arch/x86/kernel/cpu/microcode/intel_early.c index 844c758951609..7bcad1aacce35 100644 --- a/arch/x86/kernel/cpu/microcode/intel_early.c +++ b/arch/x86/kernel/cpu/microcode/intel_early.c @@ -66,16 +66,14 @@ load_microcode_early(struct microcode_intel **saved, return UCODE_OK; } -static void -microcode_pointer(struct microcode_intel **mc_saved, - unsigned long *mc_saved_in_initrd, - unsigned long initrd_start, int mc_saved_count) +static inline void +copy_initrd_ptrs(struct microcode_intel **mc_saved, unsigned long *initrd, + unsigned long off, int num_saved) { int i; - for (i = 0; i < mc_saved_count; i++) - mc_saved[i] = (struct microcode_intel *) - (mc_saved_in_initrd[i] + initrd_start); + for (i = 0; i < num_saved; i++) + mc_saved[i] = (struct microcode_intel *)(initrd[i] + off); } #ifdef CONFIG_X86_32 @@ -99,17 +97,14 @@ microcode_phys(struct microcode_intel **mc_saved_tmp, #endif static enum ucode_state -load_microcode(struct mc_saved_data *mc_saved_data, - unsigned long *mc_saved_in_initrd, - unsigned long initrd_start, - struct ucode_cpu_info *uci) +load_microcode(struct mc_saved_data *mc_saved_data, unsigned long *initrd, + unsigned long initrd_start, struct ucode_cpu_info *uci) { struct microcode_intel *mc_saved_tmp[MAX_UCODE_COUNT]; unsigned int count = mc_saved_data->mc_saved_count; if (!mc_saved_data->mc_saved) { - microcode_pointer(mc_saved_tmp, mc_saved_in_initrd, - initrd_start, count); + copy_initrd_ptrs(mc_saved_tmp, initrd, initrd_start, count); return load_microcode_early(mc_saved_tmp, count, uci); } else { @@ -672,7 +667,7 @@ int __init save_microcode_in_initrd_intel(void) if (count == 0) return ret; - microcode_pointer(mc_saved, mc_saved_in_initrd, initrd_start, count); + copy_initrd_ptrs(mc_saved, mc_saved_in_initrd, initrd_start, count); ret = save_microcode(&mc_saved_data, mc_saved, count); if (ret) pr_err("Cannot save microcode patches from initrd.\n"); From 4f1f605cfe3046c4c9f07920c47d3f801d31c0ba Mon Sep 17 00:00:00 2001 From: Borislav Petkov Date: Tue, 10 Feb 2015 12:45:16 +0100 Subject: [PATCH 13/15] x86/microcode/intel: Check scan_microcode()'s retval ... and do not attempt to load anything in case of error. Signed-off-by: Borislav Petkov --- arch/x86/kernel/cpu/microcode/intel_early.c | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/arch/x86/kernel/cpu/microcode/intel_early.c b/arch/x86/kernel/cpu/microcode/intel_early.c index 7bcad1aacce35..88a0348f455c0 100644 --- a/arch/x86/kernel/cpu/microcode/intel_early.c +++ b/arch/x86/kernel/cpu/microcode/intel_early.c @@ -514,9 +514,9 @@ EXPORT_SYMBOL_GPL(save_mc_for_early); static __initdata char ucode_name[] = "kernel/x86/microcode/GenuineIntel.bin"; static __init enum ucode_state -scan_microcode(unsigned long start, unsigned long size, - struct mc_saved_data *mc_saved_data, - unsigned long *mc_saved_in_initrd, struct ucode_cpu_info *uci) +scan_microcode(struct mc_saved_data *mc_saved_data, unsigned long *initrd, + unsigned long start, unsigned long size, + struct ucode_cpu_info *uci) { struct cpio_data cd; long offset = 0; @@ -534,8 +534,7 @@ scan_microcode(unsigned long start, unsigned long size, return UCODE_ERROR; return get_matching_model_microcode(0, start, cd.data, cd.size, - mc_saved_data, mc_saved_in_initrd, - uci); + mc_saved_data, initrd, uci); } /* @@ -679,16 +678,19 @@ int __init save_microcode_in_initrd_intel(void) static void __init _load_ucode_intel_bsp(struct mc_saved_data *mc_saved_data, - unsigned long *mc_saved_in_initrd, + unsigned long *initrd, unsigned long start, unsigned long size) { struct ucode_cpu_info uci; enum ucode_state ret; collect_cpu_info_early(&uci); - scan_microcode(start, size, mc_saved_data, mc_saved_in_initrd, &uci); - ret = load_microcode(mc_saved_data, mc_saved_in_initrd, start, &uci); + ret = scan_microcode(mc_saved_data, initrd, start, size, &uci); + if (ret != UCODE_OK) + return; + + ret = load_microcode(mc_saved_data, initrd, start, &uci); if (ret != UCODE_OK) return; From a858b5e50442579a73112c7c79bf6096e96de535 Mon Sep 17 00:00:00 2001 From: Borislav Petkov Date: Wed, 11 Feb 2015 14:54:42 +0100 Subject: [PATCH 14/15] x86/microcode/intel: Fix printing of microcode blobs in show_saved_mc() When doing echo 1 > /sys/devices/system/cpu/microcode/reload in order to reload microcode, I get: microcode: Total microcode saved: 1 BUG: using smp_processor_id() in preemptible [00000000] code: bash/2606 caller is debug_smp_processor_id+0x17/0x20 CPU: 1 PID: 2606 Comm: bash Not tainted 3.19.0-rc7+ #9 Hardware name: LENOVO 2320CTO/2320CTO, BIOS G2ET86WW (2.06 ) 11/13/2012 ffffffff81a4266d ffff8802131db808 ffffffff81666588 0000000000000007 0000000000000001 ffff8802131db838 ffffffff812e6eef ffff8802131db868 00000000000306a9 0000000000000010 0000000000000015 ffff8802131db848 Call Trace: dump_stack check_preemption_disabled debug_smp_processor_id show_saved_mc ? save_microcode.constprop.8 save_mc_for_early ? print_context_stack ? dump_trace ? __bfs ? mark_held_locks ? get_page_from_freelist ? trace_hardirqs_on_caller ? trace_hardirqs_on ? __alloc_pages_nodemask ? __get_vm_area_node ? map_vm_area ? __vmalloc_node_range ? generic_load_microcode generic_load_microcode ? microcode_fini_cpu request_microcode_fw reload_store dev_attr_store sysfs_kf_write kernfs_fop_write vfs_write ? sysret_check SyS_write system_call_fastpath microcode: CPU1: sig=0x306a9, pf=0x10, rev=0x15 microcode: mc_saved[0]: sig=0x306a9, pf=0x12, rev=0x1b, toal size=0x3000, date = 2014-05-29 because we're using smp_processor_id() in preemtible context. And we don't really need to use it there because the microcode container we're dumping is global and CPU-specific info is irrelevant. While at it, make pr_* stuff use "microcode: " prefix for easier grepping and document how to enable the DEBUG build. Signed-off-by: Borislav Petkov --- arch/x86/kernel/cpu/microcode/intel_early.c | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/arch/x86/kernel/cpu/microcode/intel_early.c b/arch/x86/kernel/cpu/microcode/intel_early.c index 88a0348f455c0..2f49ab4ac0ae1 100644 --- a/arch/x86/kernel/cpu/microcode/intel_early.c +++ b/arch/x86/kernel/cpu/microcode/intel_early.c @@ -16,6 +16,14 @@ * as published by the Free Software Foundation; either version * 2 of the License, or (at your option) any later version. */ + +/* + * This needs to be before all headers so that pr_debug in printk.h doesn't turn + * printk calls into no_printk(). + * + *#define DEBUG + */ + #include #include #include @@ -28,6 +36,9 @@ #include #include +#undef pr_fmt +#define pr_fmt(fmt) "microcode: " fmt + static unsigned long mc_saved_in_initrd[MAX_UCODE_COUNT]; static struct mc_saved_data { unsigned int mc_saved_count; @@ -397,8 +408,7 @@ static void __ref show_saved_mc(void) sig = uci.cpu_sig.sig; pf = uci.cpu_sig.pf; rev = uci.cpu_sig.rev; - pr_debug("CPU%d: sig=0x%x, pf=0x%x, rev=0x%x\n", - smp_processor_id(), sig, pf, rev); + pr_debug("CPU: sig=0x%x, pf=0x%x, rev=0x%x\n", sig, pf, rev); for (i = 0; i < mc_saved_data.mc_saved_count; i++) { struct microcode_header_intel *mc_saved_header; From 46423ffaf45c2494626841238d8bf75123a28caa Mon Sep 17 00:00:00 2001 From: "Michael S. Tsirkin" Date: Sun, 29 Mar 2015 15:43:09 +0200 Subject: [PATCH 15/15] x86/microcode/amd: Drop the pci_ids.h dependency This file doesn't use any macros from pci_ids.h anymore, drop the include. Signed-off-by: Michael S. Tsirkin Signed-off-by: Borislav Petkov Cc: Andreas Herrmann Cc: H. Peter Anvin Cc: Thomas Gleixner Link: http://lkml.kernel.org/r/1427635734-24786-80-git-send-email-mst@redhat.com Signed-off-by: Ingo Molnar --- arch/x86/kernel/cpu/microcode/amd.c | 1 - 1 file changed, 1 deletion(-) diff --git a/arch/x86/kernel/cpu/microcode/amd.c b/arch/x86/kernel/cpu/microcode/amd.c index bfbbe6195e2da..12829c3ced3c5 100644 --- a/arch/x86/kernel/cpu/microcode/amd.c +++ b/arch/x86/kernel/cpu/microcode/amd.c @@ -21,7 +21,6 @@ #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt #include -#include #include #include #include