diff options
Diffstat (limited to 'arch')
-rw-r--r-- | arch/x86/include/asm/microcode.h | 2 | ||||
-rw-r--r-- | arch/x86/include/asm/microcode_amd.h | 2 | ||||
-rw-r--r-- | arch/x86/include/asm/microcode_intel.h | 2 | ||||
-rw-r--r-- | arch/x86/kernel/cpu/microcode/amd_early.c | 18 | ||||
-rw-r--r-- | arch/x86/kernel/cpu/microcode/core.c | 8 | ||||
-rw-r--r-- | arch/x86/kernel/cpu/microcode/core_early.c | 21 | ||||
-rw-r--r-- | arch/x86/kernel/cpu/microcode/intel_early.c | 47 |
7 files changed, 84 insertions, 16 deletions
diff --git a/arch/x86/include/asm/microcode.h b/arch/x86/include/asm/microcode.h index 64dc362506b7..201b520521ed 100644 --- a/arch/x86/include/asm/microcode.h +++ b/arch/x86/include/asm/microcode.h | |||
@@ -78,6 +78,7 @@ static inline void __exit exit_amd_microcode(void) {} | |||
78 | extern void __init load_ucode_bsp(void); | 78 | extern void __init load_ucode_bsp(void); |
79 | extern void load_ucode_ap(void); | 79 | extern void load_ucode_ap(void); |
80 | extern int __init save_microcode_in_initrd(void); | 80 | extern int __init save_microcode_in_initrd(void); |
81 | void reload_early_microcode(void); | ||
81 | #else | 82 | #else |
82 | static inline void __init load_ucode_bsp(void) {} | 83 | static inline void __init load_ucode_bsp(void) {} |
83 | static inline void load_ucode_ap(void) {} | 84 | static inline void load_ucode_ap(void) {} |
@@ -85,6 +86,7 @@ static inline int __init save_microcode_in_initrd(void) | |||
85 | { | 86 | { |
86 | return 0; | 87 | return 0; |
87 | } | 88 | } |
89 | static inline void reload_early_microcode(void) {} | ||
88 | #endif | 90 | #endif |
89 | 91 | ||
90 | #endif /* _ASM_X86_MICROCODE_H */ | 92 | #endif /* _ASM_X86_MICROCODE_H */ |
diff --git a/arch/x86/include/asm/microcode_amd.h b/arch/x86/include/asm/microcode_amd.h index 48a48024ebe4..af935397e053 100644 --- 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]; | |||
68 | extern void __init load_ucode_amd_bsp(void); | 68 | extern void __init load_ucode_amd_bsp(void); |
69 | extern void load_ucode_amd_ap(void); | 69 | extern void load_ucode_amd_ap(void); |
70 | extern int __init save_microcode_in_initrd_amd(void); | 70 | extern int __init save_microcode_in_initrd_amd(void); |
71 | void reload_ucode_amd(void); | ||
71 | #else | 72 | #else |
72 | static inline void __init load_ucode_amd_bsp(void) {} | 73 | static inline void __init load_ucode_amd_bsp(void) {} |
73 | static inline void load_ucode_amd_ap(void) {} | 74 | static inline void load_ucode_amd_ap(void) {} |
74 | static inline int __init save_microcode_in_initrd_amd(void) { return -EINVAL; } | 75 | static inline int __init save_microcode_in_initrd_amd(void) { return -EINVAL; } |
76 | void reload_ucode_amd(void) {} | ||
75 | #endif | 77 | #endif |
76 | 78 | ||
77 | #endif /* _ASM_X86_MICROCODE_AMD_H */ | 79 | #endif /* _ASM_X86_MICROCODE_AMD_H */ |
diff --git a/arch/x86/include/asm/microcode_intel.h b/arch/x86/include/asm/microcode_intel.h index bbe296e0bce1..dd4c20043ce7 100644 --- 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(void); | |||
68 | extern void load_ucode_intel_ap(void); | 68 | extern void load_ucode_intel_ap(void); |
69 | extern void show_ucode_info_early(void); | 69 | extern void show_ucode_info_early(void); |
70 | extern int __init save_microcode_in_initrd_intel(void); | 70 | extern int __init save_microcode_in_initrd_intel(void); |
71 | void reload_ucode_intel(void); | ||
71 | #else | 72 | #else |
72 | static inline __init void load_ucode_intel_bsp(void) {} | 73 | static inline __init void load_ucode_intel_bsp(void) {} |
73 | static inline void load_ucode_intel_ap(void) {} | 74 | static inline void load_ucode_intel_ap(void) {} |
74 | static inline void show_ucode_info_early(void) {} | 75 | static inline void show_ucode_info_early(void) {} |
75 | static inline int __init save_microcode_in_initrd_intel(void) { return -EINVAL; } | 76 | static inline int __init save_microcode_in_initrd_intel(void) { return -EINVAL; } |
77 | static inline void reload_ucode_intel(void) {} | ||
76 | #endif | 78 | #endif |
77 | 79 | ||
78 | #if defined(CONFIG_MICROCODE_INTEL_EARLY) && defined(CONFIG_HOTPLUG_CPU) | 80 | #if defined(CONFIG_MICROCODE_INTEL_EARLY) && defined(CONFIG_HOTPLUG_CPU) |
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 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) | |||
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 = { |
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 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 { | |||
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,7 +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 ucode_cpu_info *uci) | 655 | static int apply_microcode_early(struct ucode_cpu_info *uci, bool early) |
654 | { | 656 | { |
655 | struct microcode_intel *mc_intel; | 657 | struct microcode_intel *mc_intel; |
656 | unsigned int val[2]; | 658 | unsigned int val[2]; |
@@ -679,7 +681,10 @@ static int apply_microcode_early(struct ucode_cpu_info *uci) | |||
679 | #endif | 681 | #endif |
680 | uci->cpu_sig.rev = val[1]; | 682 | uci->cpu_sig.rev = val[1]; |
681 | 683 | ||
682 | print_ucode(uci); | 684 | if (early) |
685 | print_ucode(uci); | ||
686 | else | ||
687 | print_ucode_info(uci, mc_intel->hdr.date); | ||
683 | 688 | ||
684 | return 0; | 689 | return 0; |
685 | } | 690 | } |
@@ -712,14 +717,22 @@ _load_ucode_intel_bsp(struct mc_saved_data *mc_saved_data, | |||
712 | unsigned long *mc_saved_in_initrd, | 717 | unsigned long *mc_saved_in_initrd, |
713 | unsigned long initrd_start_early, | 718 | unsigned long initrd_start_early, |
714 | unsigned long initrd_end_early, | 719 | unsigned long initrd_end_early, |
715 | struct ucode_cpu_info *uci) | 720 | struct ucode_cpu_info *uci, |
721 | struct microcode_intel *bsp) | ||
716 | { | 722 | { |
723 | enum ucode_state ret; | ||
724 | |||
717 | collect_cpu_info_early(uci); | 725 | collect_cpu_info_early(uci); |
718 | scan_microcode(initrd_start_early, initrd_end_early, mc_saved_data, | 726 | scan_microcode(initrd_start_early, initrd_end_early, mc_saved_data, |
719 | mc_saved_in_initrd, uci); | 727 | mc_saved_in_initrd, uci); |
720 | load_microcode(mc_saved_data, mc_saved_in_initrd, | 728 | |
721 | initrd_start_early, uci); | 729 | ret = load_microcode(mc_saved_data, mc_saved_in_initrd, |
722 | apply_microcode_early(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 | } | ||
723 | } | 736 | } |
724 | 737 | ||
725 | void __init | 738 | void __init |
@@ -728,10 +741,12 @@ load_ucode_intel_bsp(void) | |||
728 | u64 ramdisk_image, ramdisk_size; | 741 | u64 ramdisk_image, ramdisk_size; |
729 | unsigned long initrd_start_early, initrd_end_early; | 742 | unsigned long initrd_start_early, initrd_end_early; |
730 | struct ucode_cpu_info uci; | 743 | struct ucode_cpu_info uci; |
744 | struct microcode_intel *bsp_p; | ||
731 | #ifdef CONFIG_X86_32 | 745 | #ifdef CONFIG_X86_32 |
732 | struct boot_params *boot_params_p; | 746 | struct boot_params *boot_params_p; |
733 | 747 | ||
734 | 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); | ||
735 | ramdisk_image = boot_params_p->hdr.ramdisk_image; | 750 | ramdisk_image = boot_params_p->hdr.ramdisk_image; |
736 | ramdisk_size = boot_params_p->hdr.ramdisk_size; | 751 | ramdisk_size = boot_params_p->hdr.ramdisk_size; |
737 | initrd_start_early = ramdisk_image; | 752 | initrd_start_early = ramdisk_image; |
@@ -740,15 +755,17 @@ load_ucode_intel_bsp(void) | |||
740 | _load_ucode_intel_bsp( | 755 | _load_ucode_intel_bsp( |
741 | (struct mc_saved_data *)__pa_nodebug(&mc_saved_data), | 756 | (struct mc_saved_data *)__pa_nodebug(&mc_saved_data), |
742 | (unsigned long *)__pa_nodebug(&mc_saved_in_initrd), | 757 | (unsigned long *)__pa_nodebug(&mc_saved_in_initrd), |
743 | initrd_start_early, initrd_end_early, &uci); | 758 | initrd_start_early, initrd_end_early, &uci, bsp_p); |
744 | #else | 759 | #else |
760 | bsp_p = &bsp_patch; | ||
745 | ramdisk_image = boot_params.hdr.ramdisk_image; | 761 | ramdisk_image = boot_params.hdr.ramdisk_image; |
746 | ramdisk_size = boot_params.hdr.ramdisk_size; | 762 | ramdisk_size = boot_params.hdr.ramdisk_size; |
747 | initrd_start_early = ramdisk_image + PAGE_OFFSET; | 763 | initrd_start_early = ramdisk_image + PAGE_OFFSET; |
748 | initrd_end_early = initrd_start_early + ramdisk_size; | 764 | initrd_end_early = initrd_start_early + ramdisk_size; |
749 | 765 | ||
750 | _load_ucode_intel_bsp(&mc_saved_data, mc_saved_in_initrd, | 766 | _load_ucode_intel_bsp(&mc_saved_data, mc_saved_in_initrd, |
751 | initrd_start_early, initrd_end_early, &uci); | 767 | initrd_start_early, initrd_end_early, |
768 | &uci, bsp_p); | ||
752 | #endif | 769 | #endif |
753 | } | 770 | } |
754 | 771 | ||
@@ -782,5 +799,17 @@ void load_ucode_intel_ap(void) | |||
782 | collect_cpu_info_early(&uci); | 799 | collect_cpu_info_early(&uci); |
783 | load_microcode(mc_saved_data_p, mc_saved_in_initrd_p, | 800 | load_microcode(mc_saved_data_p, mc_saved_in_initrd_p, |
784 | initrd_start_addr, &uci); | 801 | initrd_start_addr, &uci); |
785 | apply_microcode_early(&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); | ||
786 | } | 815 | } |