diff options
| author | Ingo Molnar <mingo@kernel.org> | 2014-12-08 04:26:29 -0500 |
|---|---|---|
| committer | Ingo Molnar <mingo@kernel.org> | 2014-12-08 04:26:29 -0500 |
| commit | e913b8cd4548cd0a407b7debd6ec9104e84d050d (patch) | |
| tree | 661e543af2cab13c77b21519d49534e51e319fbd /arch/x86/kernel/cpu/microcode | |
| parent | 2ef84b3bb97f03332f0c1edb4466b1750dcf97b5 (diff) | |
| parent | fbae4ba8c4a387e306adc9c710e5c225cece7678 (diff) | |
Merge tag 'microcode_fixes_for_3.19' of git://git.kernel.org/pub/scm/linux/kernel/git/bp/bp into x86/microcode
Pull x86 microcode fixes from Borislav Petkov:
"Reload microcode when resuming and the case when only the early loader
has been utilized.
Also, do not load the driver on paravirt guests, from Boris Ostrovsky."
Signed-off-by: Ingo Molnar <mingo@kernel.org>
Diffstat (limited to 'arch/x86/kernel/cpu/microcode')
| -rw-r--r-- | arch/x86/kernel/cpu/microcode/amd_early.c | 18 | ||||
| -rw-r--r-- | arch/x86/kernel/cpu/microcode/core.c | 10 | ||||
| -rw-r--r-- | arch/x86/kernel/cpu/microcode/core_early.c | 21 | ||||
| -rw-r--r-- | arch/x86/kernel/cpu/microcode/intel_early.c | 48 |
4 files changed, 79 insertions, 18 deletions
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) | |||
| 402 | 402 | ||
| 403 | return retval; | 403 | return retval; |
| 404 | } | 404 | } |
| 405 | |||
| 406 | void reload_ucode_amd(void) | ||
| 407 | { | ||
| 408 | struct microcode_amd *mc; | ||
| 409 | u32 rev, eax; | ||
| 410 | |||
| 411 | rdmsr(MSR_AMD64_PATCH_LEVEL, rev, eax); | ||
| 412 | |||
| 413 | mc = (struct microcode_amd *)amd_ucode_patch; | ||
| 414 | |||
| 415 | if (mc && rev < mc->hdr.patch_id) { | ||
| 416 | if (!__apply_microcode_amd(mc)) { | ||
| 417 | ucode_new_rev = mc->hdr.patch_id; | ||
| 418 | pr_info("microcode: reload patch_level=0x%08x\n", | ||
| 419 | ucode_new_rev); | ||
| 420 | } | ||
| 421 | } | ||
| 422 | } | ||
diff --git a/arch/x86/kernel/cpu/microcode/core.c b/arch/x86/kernel/cpu/microcode/core.c index 2ce9051174e6..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) | |||
| 466 | if (uci->valid && uci->mc) | 466 | if (uci->valid && uci->mc) |
| 467 | microcode_ops->apply_microcode(cpu); | 467 | microcode_ops->apply_microcode(cpu); |
| 468 | else if (!uci->mc) | 468 | else if (!uci->mc) |
| 469 | /* | 469 | reload_early_microcode(); |
| 470 | * We might resume and not have applied late microcode but still | ||
| 471 | * have a newer patch stashed from the early loader. We don't | ||
| 472 | * have it in uci->mc so we have to load it the same way we're | ||
| 473 | * applying patches early on the APs. | ||
| 474 | */ | ||
| 475 | load_ucode_ap(); | ||
| 476 | } | 470 | } |
| 477 | 471 | ||
| 478 | static struct syscore_ops mc_syscore_ops = { | 472 | static struct syscore_ops mc_syscore_ops = { |
| @@ -557,7 +551,7 @@ static int __init microcode_init(void) | |||
| 557 | struct cpuinfo_x86 *c = &cpu_data(0); | 551 | struct cpuinfo_x86 *c = &cpu_data(0); |
| 558 | int error; | 552 | int error; |
| 559 | 553 | ||
| 560 | if (dis_ucode_ldr) | 554 | if (paravirt_enabled() || dis_ucode_ldr) |
| 561 | return 0; | 555 | return 0; |
| 562 | 556 | ||
| 563 | if (c->x86_vendor == X86_VENDOR_INTEL) | 557 | if (c->x86_vendor == X86_VENDOR_INTEL) |
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) | |||
| 176 | 176 | ||
| 177 | return 0; | 177 | return 0; |
| 178 | } | 178 | } |
| 179 | |||
| 180 | void reload_early_microcode(void) | ||
| 181 | { | ||
| 182 | int vendor, x86; | ||
| 183 | |||
| 184 | vendor = x86_vendor(); | ||
| 185 | x86 = x86_family(); | ||
| 186 | |||
| 187 | switch (vendor) { | ||
| 188 | case X86_VENDOR_INTEL: | ||
| 189 | if (x86 >= 6) | ||
| 190 | reload_ucode_intel(); | ||
| 191 | break; | ||
| 192 | case X86_VENDOR_AMD: | ||
| 193 | if (x86 >= 0x10) | ||
| 194 | reload_ucode_amd(); | ||
| 195 | break; | ||
| 196 | default: | ||
| 197 | break; | ||
| 198 | } | ||
| 199 | } | ||
diff --git a/arch/x86/kernel/cpu/microcode/intel_early.c b/arch/x86/kernel/cpu/microcode/intel_early.c index b88343f7a3b3..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 { | |||
| 34 | struct microcode_intel **mc_saved; | 34 | struct microcode_intel **mc_saved; |
| 35 | } mc_saved_data; | 35 | } mc_saved_data; |
| 36 | 36 | ||
| 37 | static struct microcode_intel bsp_patch; | ||
| 38 | |||
| 37 | static enum ucode_state | 39 | static enum ucode_state |
| 38 | generic_load_microcode_early(struct microcode_intel **mc_saved_p, | 40 | generic_load_microcode_early(struct microcode_intel **mc_saved_p, |
| 39 | unsigned int mc_saved_count, | 41 | unsigned int mc_saved_count, |
| @@ -650,8 +652,7 @@ static inline void print_ucode(struct ucode_cpu_info *uci) | |||
| 650 | } | 652 | } |
| 651 | #endif | 653 | #endif |
| 652 | 654 | ||
| 653 | static int apply_microcode_early(struct mc_saved_data *mc_saved_data, | 655 | static int apply_microcode_early(struct ucode_cpu_info *uci, bool early) |
| 654 | struct ucode_cpu_info *uci) | ||
| 655 | { | 656 | { |
| 656 | struct microcode_intel *mc_intel; | 657 | struct microcode_intel *mc_intel; |
| 657 | unsigned int val[2]; | 658 | unsigned int val[2]; |
| @@ -680,7 +681,10 @@ static int apply_microcode_early(struct mc_saved_data *mc_saved_data, | |||
| 680 | #endif | 681 | #endif |
| 681 | uci->cpu_sig.rev = val[1]; | 682 | uci->cpu_sig.rev = val[1]; |
| 682 | 683 | ||
| 683 | print_ucode(uci); | 684 | if (early) |
| 685 | print_ucode(uci); | ||
| 686 | else | ||
| 687 | print_ucode_info(uci, mc_intel->hdr.date); | ||
| 684 | 688 | ||
| 685 | return 0; | 689 | return 0; |
| 686 | } | 690 | } |
| @@ -713,14 +717,22 @@ _load_ucode_intel_bsp(struct mc_saved_data *mc_saved_data, | |||
| 713 | unsigned long *mc_saved_in_initrd, | 717 | unsigned long *mc_saved_in_initrd, |
| 714 | unsigned long initrd_start_early, | 718 | unsigned long initrd_start_early, |
| 715 | unsigned long initrd_end_early, | 719 | unsigned long initrd_end_early, |
| 716 | struct ucode_cpu_info *uci) | 720 | struct ucode_cpu_info *uci, |
| 721 | struct microcode_intel *bsp) | ||
| 717 | { | 722 | { |
| 723 | enum ucode_state ret; | ||
| 724 | |||
| 718 | collect_cpu_info_early(uci); | 725 | collect_cpu_info_early(uci); |
| 719 | scan_microcode(initrd_start_early, initrd_end_early, mc_saved_data, | 726 | scan_microcode(initrd_start_early, initrd_end_early, mc_saved_data, |
| 720 | mc_saved_in_initrd, uci); | 727 | mc_saved_in_initrd, uci); |
| 721 | load_microcode(mc_saved_data, mc_saved_in_initrd, | 728 | |
| 722 | initrd_start_early, uci); | 729 | ret = load_microcode(mc_saved_data, mc_saved_in_initrd, |
| 723 | apply_microcode_early(mc_saved_data, uci); | 730 | initrd_start_early, uci); |
| 731 | |||
| 732 | if (ret == UCODE_OK) { | ||
| 733 | apply_microcode_early(uci, true); | ||
| 734 | memcpy(bsp, uci->mc, sizeof(*bsp)); | ||
| 735 | } | ||
| 724 | } | 736 | } |
| 725 | 737 | ||
| 726 | void __init | 738 | void __init |
| @@ -729,10 +741,12 @@ load_ucode_intel_bsp(void) | |||
| 729 | u64 ramdisk_image, ramdisk_size; | 741 | u64 ramdisk_image, ramdisk_size; |
| 730 | unsigned long initrd_start_early, initrd_end_early; | 742 | unsigned long initrd_start_early, initrd_end_early; |
| 731 | struct ucode_cpu_info uci; | 743 | struct ucode_cpu_info uci; |
| 744 | struct microcode_intel *bsp_p; | ||
| 732 | #ifdef CONFIG_X86_32 | 745 | #ifdef CONFIG_X86_32 |
| 733 | struct boot_params *boot_params_p; | 746 | struct boot_params *boot_params_p; |
| 734 | 747 | ||
| 735 | boot_params_p = (struct boot_params *)__pa_nodebug(&boot_params); | 748 | boot_params_p = (struct boot_params *)__pa_nodebug(&boot_params); |
| 749 | bsp_p = (struct microcode_intel *)__pa_nodebug(&bsp_patch); | ||
| 736 | ramdisk_image = boot_params_p->hdr.ramdisk_image; | 750 | ramdisk_image = boot_params_p->hdr.ramdisk_image; |
| 737 | ramdisk_size = boot_params_p->hdr.ramdisk_size; | 751 | ramdisk_size = boot_params_p->hdr.ramdisk_size; |
| 738 | initrd_start_early = ramdisk_image; | 752 | initrd_start_early = ramdisk_image; |
| @@ -741,15 +755,17 @@ load_ucode_intel_bsp(void) | |||
| 741 | _load_ucode_intel_bsp( | 755 | _load_ucode_intel_bsp( |
| 742 | (struct mc_saved_data *)__pa_nodebug(&mc_saved_data), | 756 | (struct mc_saved_data *)__pa_nodebug(&mc_saved_data), |
| 743 | (unsigned long *)__pa_nodebug(&mc_saved_in_initrd), | 757 | (unsigned long *)__pa_nodebug(&mc_saved_in_initrd), |
| 744 | initrd_start_early, initrd_end_early, &uci); | 758 | initrd_start_early, initrd_end_early, &uci, bsp_p); |
| 745 | #else | 759 | #else |
| 760 | bsp_p = &bsp_patch; | ||
| 746 | ramdisk_image = boot_params.hdr.ramdisk_image; | 761 | ramdisk_image = boot_params.hdr.ramdisk_image; |
| 747 | ramdisk_size = boot_params.hdr.ramdisk_size; | 762 | ramdisk_size = boot_params.hdr.ramdisk_size; |
| 748 | initrd_start_early = ramdisk_image + PAGE_OFFSET; | 763 | initrd_start_early = ramdisk_image + PAGE_OFFSET; |
| 749 | initrd_end_early = initrd_start_early + ramdisk_size; | 764 | initrd_end_early = initrd_start_early + ramdisk_size; |
| 750 | 765 | ||
| 751 | _load_ucode_intel_bsp(&mc_saved_data, mc_saved_in_initrd, | 766 | _load_ucode_intel_bsp(&mc_saved_data, mc_saved_in_initrd, |
| 752 | initrd_start_early, initrd_end_early, &uci); | 767 | initrd_start_early, initrd_end_early, |
| 768 | &uci, bsp_p); | ||
| 753 | #endif | 769 | #endif |
| 754 | } | 770 | } |
| 755 | 771 | ||
| @@ -783,5 +799,17 @@ void load_ucode_intel_ap(void) | |||
| 783 | collect_cpu_info_early(&uci); | 799 | collect_cpu_info_early(&uci); |
| 784 | load_microcode(mc_saved_data_p, mc_saved_in_initrd_p, | 800 | load_microcode(mc_saved_data_p, mc_saved_in_initrd_p, |
| 785 | initrd_start_addr, &uci); | 801 | initrd_start_addr, &uci); |
| 786 | apply_microcode_early(mc_saved_data_p, &uci); | 802 | apply_microcode_early(&uci, true); |
| 803 | } | ||
| 804 | |||
| 805 | void reload_ucode_intel(void) | ||
| 806 | { | ||
| 807 | struct ucode_cpu_info uci; | ||
| 808 | |||
| 809 | if (!bsp_patch.hdr.rev) | ||
| 810 | return; | ||
| 811 | |||
| 812 | uci.mc = &bsp_patch; | ||
| 813 | |||
| 814 | apply_microcode_early(&uci, false); | ||
| 787 | } | 815 | } |
