This is a note to let you know that I've just added the patch titled x86, microcode: Reload microcode on resume to the 3.18-stable tree which can be found at: http://www.kernel.org/git/?p=linux/kernel/git/stable/stable-queue.git;a=summary The filename of the patch is: x86-microcode-reload-microcode-on-resume.patch and it can be found in the queue-3.18 subdirectory. If you, or anyone else, feels it should not be added to the stable tree, please let <stable@xxxxxxxxxxxxxxx> know about it. >From fbae4ba8c4a387e306adc9c710e5c225cece7678 Mon Sep 17 00:00:00 2001 From: Borislav Petkov <bp@xxxxxxx> Date: Wed, 3 Dec 2014 17:21:41 +0100 Subject: x86, microcode: Reload microcode on resume From: Borislav Petkov <bp@xxxxxxx> commit fbae4ba8c4a387e306adc9c710e5c225cece7678 upstream. 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 <bp@xxxxxxx> Signed-off-by: Greg Kroah-Hartman <gregkh@xxxxxxxxxxxxxxxxxxx> --- arch/x86/include/asm/microcode.h | 2 + arch/x86/include/asm/microcode_amd.h | 2 + arch/x86/include/asm/microcode_intel.h | 2 + arch/x86/kernel/cpu/microcode/amd_early.c | 18 ++++++++++ arch/x86/kernel/cpu/microcode/core.c | 10 ----- arch/x86/kernel/cpu/microcode/core_early.c | 21 ++++++++++++ arch/x86/kernel/cpu/microcode/intel_early.c | 47 ++++++++++++++++++++++------ 7 files changed, 84 insertions(+), 18 deletions(-) --- a/arch/x86/include/asm/microcode.h +++ b/arch/x86/include/asm/microcode.h @@ -78,6 +78,7 @@ static inline void __exit exit_amd_micro extern void __init load_ucode_bsp(void); extern void load_ucode_ap(void); extern int __init save_microcode_in_initrd(void); +void reload_early_microcode(void); #else static inline void __init load_ucode_bsp(void) {} static inline void load_ucode_ap(void) {} @@ -85,6 +86,7 @@ static inline int __init save_microcode_ { return 0; } +static inline void reload_early_microcode(void) {} #endif #endif /* _ASM_X86_MICROCODE_H */ --- a/arch/x86/include/asm/microcode_amd.h +++ b/arch/x86/include/asm/microcode_amd.h @@ -68,10 +68,12 @@ extern u8 amd_ucode_patch[PATCH_MAX_SIZE extern void __init load_ucode_amd_bsp(void); extern void load_ucode_amd_ap(void); extern int __init save_microcode_in_initrd_amd(void); +void reload_ucode_amd(void); #else static inline void __init load_ucode_amd_bsp(void) {} static inline void load_ucode_amd_ap(void) {} static inline int __init save_microcode_in_initrd_amd(void) { return -EINVAL; } +void reload_ucode_amd(void) {} #endif #endif /* _ASM_X86_MICROCODE_AMD_H */ --- a/arch/x86/include/asm/microcode_intel.h +++ b/arch/x86/include/asm/microcode_intel.h @@ -68,11 +68,13 @@ extern void __init load_ucode_intel_bsp( extern void load_ucode_intel_ap(void); extern void show_ucode_info_early(void); extern int __init save_microcode_in_initrd_intel(void); +void reload_ucode_intel(void); #else static inline __init void load_ucode_intel_bsp(void) {} static inline void load_ucode_intel_ap(void) {} static inline void show_ucode_info_early(void) {} static inline int __init save_microcode_in_initrd_intel(void) { return -EINVAL; } +static inline void reload_ucode_intel(void) {} #endif #if defined(CONFIG_MICROCODE_INTEL_EARLY) && defined(CONFIG_HOTPLUG_CPU) --- 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( 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); + } + } +} --- a/arch/x86/kernel/cpu/microcode/core.c +++ b/arch/x86/kernel/cpu/microcode/core.c @@ -465,16 +465,8 @@ static void mc_bp_resume(void) if (uci->valid && uci->mc) microcode_ops->apply_microcode(cpu); -#ifdef CONFIG_X86_64 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(); -#endif + reload_early_microcode(); } static struct syscore_ops mc_syscore_ops = { --- 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; + } +} --- 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 uc } #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 #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_da 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); } Patches currently in stable-queue which might be from bp@xxxxxxx are queue-3.18/x86-microcode-intel-drop-unused-parameter.patch queue-3.18/x86-microcode-intel-fish-out-the-stashed-microcode-for-the-bsp.patch queue-3.18/x86-microcode-reload-microcode-on-resume.patch queue-3.18/x86-microcode-amd-do-not-use-smp_processor_id-in-preemtible-context.patch queue-3.18/x86-microcode-don-t-initialize-microcode-code-on-paravirt.patch -- To unsubscribe from this list: send the line "unsubscribe stable" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html