From 47768626c6db42cd06ff077ba12dd2cb10ab818b Mon Sep 17 00:00:00 2001 From: Borislav Petkov Date: Mon, 1 Dec 2014 17:50:16 +0100 Subject: x86, microcode, intel: Drop unused parameter apply_microcode_early() doesn't use mc_saved_data, kill it. Signed-off-by: Borislav Petkov --- arch/x86/kernel/cpu/microcode/intel_early.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) (limited to 'arch/x86/kernel/cpu/microcode') diff --git a/arch/x86/kernel/cpu/microcode/intel_early.c b/arch/x86/kernel/cpu/microcode/intel_early.c index b88343f7a3b3..31e7576a123c 100644 --- a/arch/x86/kernel/cpu/microcode/intel_early.c +++ b/arch/x86/kernel/cpu/microcode/intel_early.c @@ -650,8 +650,7 @@ static inline void print_ucode(struct ucode_cpu_info *uci) } #endif -static int apply_microcode_early(struct mc_saved_data *mc_saved_data, - struct ucode_cpu_info *uci) +static int apply_microcode_early(struct ucode_cpu_info *uci) { struct microcode_intel *mc_intel; unsigned int val[2]; @@ -720,7 +719,7 @@ _load_ucode_intel_bsp(struct mc_saved_data *mc_saved_data, mc_saved_in_initrd, uci); load_microcode(mc_saved_data, mc_saved_in_initrd, initrd_start_early, uci); - apply_microcode_early(mc_saved_data, uci); + apply_microcode_early(uci); } void __init @@ -783,5 +782,5 @@ void load_ucode_intel_ap(void) collect_cpu_info_early(&uci); load_microcode(mc_saved_data_p, mc_saved_in_initrd_p, initrd_start_addr, &uci); - apply_microcode_early(mc_saved_data_p, &uci); + apply_microcode_early(&uci); } -- cgit v1.2.2 From a18a0f6850d4b286a5ebf02cd5b22fe496b86349 Mon Sep 17 00:00:00 2001 From: Boris Ostrovsky Date: Mon, 1 Dec 2014 16:27:44 -0500 Subject: x86, microcode: Don't initialize microcode code on paravirt Paravirtual guests are not expected to load microcode into processors and therefore it is not necessary to initialize microcode loading logic. In fact, under certain circumstances initializing this logic may cause the guest to crash. Specifically, 32-bit kernels use __pa_nodebug() macro which does not work in Xen (the code path that leads to this macro happens during resume when we call mc_bp_resume()->load_ucode_ap() ->check_loader_disabled_ap()) Signed-off-by: Boris Ostrovsky Link: http://lkml.kernel.org/r/1417469264-31470-1-git-send-email-boris.ostrovsky@oracle.com Signed-off-by: Borislav Petkov --- arch/x86/kernel/cpu/microcode/core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch/x86/kernel/cpu/microcode') diff --git a/arch/x86/kernel/cpu/microcode/core.c b/arch/x86/kernel/cpu/microcode/core.c index 2ce9051174e6..ebd232d7de4d 100644 --- a/arch/x86/kernel/cpu/microcode/core.c +++ b/arch/x86/kernel/cpu/microcode/core.c @@ -557,7 +557,7 @@ static int __init microcode_init(void) struct cpuinfo_x86 *c = &cpu_data(0); int error; - if (dis_ucode_ldr) + if (paravirt_enabled() || dis_ucode_ldr) return 0; if (c->x86_vendor == X86_VENDOR_INTEL) -- cgit v1.2.2 From fbae4ba8c4a387e306adc9c710e5c225cece7678 Mon Sep 17 00:00:00 2001 From: Borislav Petkov Date: Wed, 3 Dec 2014 17:21:41 +0100 Subject: x86, microcode: Reload microcode on resume Normally, we do reapply microcode on resume. However, in the cases where that microcode comes from the early loader and the late loader hasn't been utilized yet, there's no easy way for us to go and apply the patch applied during boot by the early loader. Thus, reuse the patch stashed by the early loader for the BSP. Signed-off-by: Borislav Petkov --- arch/x86/kernel/cpu/microcode/amd_early.c | 18 +++++++++++ arch/x86/kernel/cpu/microcode/core.c | 8 +---- arch/x86/kernel/cpu/microcode/core_early.c | 21 +++++++++++++ arch/x86/kernel/cpu/microcode/intel_early.c | 47 +++++++++++++++++++++++------ 4 files changed, 78 insertions(+), 16 deletions(-) (limited to 'arch/x86/kernel/cpu/microcode') diff --git a/arch/x86/kernel/cpu/microcode/amd_early.c b/arch/x86/kernel/cpu/microcode/amd_early.c index 3d988a30a21d..737737edbd1e 100644 --- a/arch/x86/kernel/cpu/microcode/amd_early.c +++ b/arch/x86/kernel/cpu/microcode/amd_early.c @@ -402,3 +402,21 @@ int __init save_microcode_in_initrd_amd(void) return retval; } + +void reload_ucode_amd(void) +{ + struct microcode_amd *mc; + u32 rev, eax; + + rdmsr(MSR_AMD64_PATCH_LEVEL, rev, eax); + + mc = (struct microcode_amd *)amd_ucode_patch; + + if (mc && rev < mc->hdr.patch_id) { + if (!__apply_microcode_amd(mc)) { + ucode_new_rev = mc->hdr.patch_id; + pr_info("microcode: reload patch_level=0x%08x\n", + ucode_new_rev); + } + } +} diff --git a/arch/x86/kernel/cpu/microcode/core.c b/arch/x86/kernel/cpu/microcode/core.c index ebd232d7de4d..15c29096136b 100644 --- a/arch/x86/kernel/cpu/microcode/core.c +++ b/arch/x86/kernel/cpu/microcode/core.c @@ -466,13 +466,7 @@ static void mc_bp_resume(void) if (uci->valid && uci->mc) microcode_ops->apply_microcode(cpu); else if (!uci->mc) - /* - * We might resume and not have applied late microcode but still - * have a newer patch stashed from the early loader. We don't - * have it in uci->mc so we have to load it the same way we're - * applying patches early on the APs. - */ - load_ucode_ap(); + reload_early_microcode(); } static struct syscore_ops mc_syscore_ops = { diff --git a/arch/x86/kernel/cpu/microcode/core_early.c b/arch/x86/kernel/cpu/microcode/core_early.c index 2c017f242a78..d45df4bd16ab 100644 --- a/arch/x86/kernel/cpu/microcode/core_early.c +++ b/arch/x86/kernel/cpu/microcode/core_early.c @@ -176,3 +176,24 @@ int __init save_microcode_in_initrd(void) return 0; } + +void reload_early_microcode(void) +{ + int vendor, x86; + + vendor = x86_vendor(); + x86 = x86_family(); + + switch (vendor) { + case X86_VENDOR_INTEL: + if (x86 >= 6) + reload_ucode_intel(); + break; + case X86_VENDOR_AMD: + if (x86 >= 0x10) + reload_ucode_amd(); + break; + default: + break; + } +} diff --git a/arch/x86/kernel/cpu/microcode/intel_early.c b/arch/x86/kernel/cpu/microcode/intel_early.c index 31e7576a123c..f04d0d6638ca 100644 --- a/arch/x86/kernel/cpu/microcode/intel_early.c +++ b/arch/x86/kernel/cpu/microcode/intel_early.c @@ -34,6 +34,8 @@ static struct mc_saved_data { struct microcode_intel **mc_saved; } mc_saved_data; +static struct microcode_intel bsp_patch; + static enum ucode_state generic_load_microcode_early(struct microcode_intel **mc_saved_p, unsigned int mc_saved_count, @@ -650,7 +652,7 @@ static inline void print_ucode(struct ucode_cpu_info *uci) } #endif -static int apply_microcode_early(struct ucode_cpu_info *uci) +static int apply_microcode_early(struct ucode_cpu_info *uci, bool early) { struct microcode_intel *mc_intel; unsigned int val[2]; @@ -679,7 +681,10 @@ static int apply_microcode_early(struct ucode_cpu_info *uci) #endif uci->cpu_sig.rev = val[1]; - print_ucode(uci); + if (early) + print_ucode(uci); + else + print_ucode_info(uci, mc_intel->hdr.date); return 0; } @@ -712,14 +717,22 @@ _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) + struct ucode_cpu_info *uci, + struct microcode_intel *bsp) { + 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); - load_microcode(mc_saved_data, mc_saved_in_initrd, - initrd_start_early, uci); - apply_microcode_early(uci); + + ret = load_microcode(mc_saved_data, mc_saved_in_initrd, + initrd_start_early, uci); + + if (ret == UCODE_OK) { + apply_microcode_early(uci, true); + memcpy(bsp, uci->mc, sizeof(*bsp)); + } } void __init @@ -728,10 +741,12 @@ load_ucode_intel_bsp(void) u64 ramdisk_image, ramdisk_size; unsigned long initrd_start_early, initrd_end_early; struct ucode_cpu_info uci; + struct microcode_intel *bsp_p; #ifdef CONFIG_X86_32 struct boot_params *boot_params_p; boot_params_p = (struct boot_params *)__pa_nodebug(&boot_params); + bsp_p = (struct microcode_intel *)__pa_nodebug(&bsp_patch); ramdisk_image = boot_params_p->hdr.ramdisk_image; ramdisk_size = boot_params_p->hdr.ramdisk_size; initrd_start_early = ramdisk_image; @@ -740,15 +755,17 @@ 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, &uci, bsp_p); #else + bsp_p = &bsp_patch; 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; _load_ucode_intel_bsp(&mc_saved_data, mc_saved_in_initrd, - initrd_start_early, initrd_end_early, &uci); + initrd_start_early, initrd_end_early, + &uci, bsp_p); #endif } @@ -782,5 +799,17 @@ void load_ucode_intel_ap(void) collect_cpu_info_early(&uci); load_microcode(mc_saved_data_p, mc_saved_in_initrd_p, initrd_start_addr, &uci); - apply_microcode_early(&uci); + apply_microcode_early(&uci, true); +} + +void reload_ucode_intel(void) +{ + struct ucode_cpu_info uci; + + if (!bsp_patch.hdr.rev) + return; + + uci.mc = &bsp_patch; + + apply_microcode_early(&uci, false); } -- cgit v1.2.2