aboutsummaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
Diffstat (limited to 'arch')
-rw-r--r--arch/x86/include/asm/microcode.h2
-rw-r--r--arch/x86/include/asm/microcode_amd.h2
-rw-r--r--arch/x86/include/asm/microcode_intel.h2
-rw-r--r--arch/x86/kernel/cpu/microcode/amd_early.c18
-rw-r--r--arch/x86/kernel/cpu/microcode/core.c8
-rw-r--r--arch/x86/kernel/cpu/microcode/core_early.c21
-rw-r--r--arch/x86/kernel/cpu/microcode/intel_early.c47
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) {}
78extern void __init load_ucode_bsp(void); 78extern void __init load_ucode_bsp(void);
79extern void load_ucode_ap(void); 79extern void load_ucode_ap(void);
80extern int __init save_microcode_in_initrd(void); 80extern int __init save_microcode_in_initrd(void);
81void reload_early_microcode(void);
81#else 82#else
82static inline void __init load_ucode_bsp(void) {} 83static inline void __init load_ucode_bsp(void) {}
83static inline void load_ucode_ap(void) {} 84static 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}
89static 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];
68extern void __init load_ucode_amd_bsp(void); 68extern void __init load_ucode_amd_bsp(void);
69extern void load_ucode_amd_ap(void); 69extern void load_ucode_amd_ap(void);
70extern int __init save_microcode_in_initrd_amd(void); 70extern int __init save_microcode_in_initrd_amd(void);
71void reload_ucode_amd(void);
71#else 72#else
72static inline void __init load_ucode_amd_bsp(void) {} 73static inline void __init load_ucode_amd_bsp(void) {}
73static inline void load_ucode_amd_ap(void) {} 74static inline void load_ucode_amd_ap(void) {}
74static inline int __init save_microcode_in_initrd_amd(void) { return -EINVAL; } 75static inline int __init save_microcode_in_initrd_amd(void) { return -EINVAL; }
76void 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);
68extern void load_ucode_intel_ap(void); 68extern void load_ucode_intel_ap(void);
69extern void show_ucode_info_early(void); 69extern void show_ucode_info_early(void);
70extern int __init save_microcode_in_initrd_intel(void); 70extern int __init save_microcode_in_initrd_intel(void);
71void reload_ucode_intel(void);
71#else 72#else
72static inline __init void load_ucode_intel_bsp(void) {} 73static inline __init void load_ucode_intel_bsp(void) {}
73static inline void load_ucode_intel_ap(void) {} 74static inline void load_ucode_intel_ap(void) {}
74static inline void show_ucode_info_early(void) {} 75static inline void show_ucode_info_early(void) {}
75static inline int __init save_microcode_in_initrd_intel(void) { return -EINVAL; } 76static inline int __init save_microcode_in_initrd_intel(void) { return -EINVAL; }
77static 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
406void 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
478static struct syscore_ops mc_syscore_ops = { 472static 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
180void 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
37static struct microcode_intel bsp_patch;
38
37static enum ucode_state 39static enum ucode_state
38generic_load_microcode_early(struct microcode_intel **mc_saved_p, 40generic_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
653static int apply_microcode_early(struct ucode_cpu_info *uci) 655static 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
725void __init 738void __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
805void 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}