aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2014-12-10 18:01:43 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2014-12-10 18:01:43 -0500
commit3a5dc1fafb016560315fe45bb4ef8bde259dd1bc (patch)
tree6de33857df82f8b7f2200345192cf58939cb5823
parent3100e448e7d74489a96cb7b45d88fe6962774eaa (diff)
parent25cdb9c86826f8d035d8aaa07fc36832e76bd8a0 (diff)
Merge branch 'x86-microcode-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
Pull x86 microcode loading updates from Ingo Molnar: "The main changes in this cycle are: - Reload microcode when resuming and the case when only the early loader has been utilized. (Borislav Petkov) - Also, do not load the driver on paravirt guests. (Boris Ostrovsky)" * 'x86-microcode-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: x86/microcode/intel: Fish out the stashed microcode for the BSP x86, microcode: Reload microcode on resume x86, microcode: Don't initialize microcode code on paravirt x86, microcode, intel: Drop unused parameter x86, microcode, AMD: Do not use smp_processor_id() in preemtible context
-rw-r--r--arch/x86/include/asm/microcode.h2
-rw-r--r--arch/x86/include/asm/microcode_amd.h4
-rw-r--r--arch/x86/include/asm/microcode_intel.h2
-rw-r--r--arch/x86/kernel/cpu/microcode/amd.c8
-rw-r--r--arch/x86/kernel/cpu/microcode/amd_early.c20
-rw-r--r--arch/x86/kernel/cpu/microcode/core.c12
-rw-r--r--arch/x86/kernel/cpu/microcode/core_early.c21
-rw-r--r--arch/x86/kernel/cpu/microcode/intel_early.c42
8 files changed, 87 insertions, 24 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 b7b10b82d3e5..af935397e053 100644
--- a/arch/x86/include/asm/microcode_amd.h
+++ b/arch/x86/include/asm/microcode_amd.h
@@ -59,7 +59,7 @@ static inline u16 find_equiv_id(struct equiv_cpu_entry *equiv_cpu_table,
59 59
60extern int __apply_microcode_amd(struct microcode_amd *mc_amd); 60extern int __apply_microcode_amd(struct microcode_amd *mc_amd);
61extern int apply_microcode_amd(int cpu); 61extern int apply_microcode_amd(int cpu);
62extern enum ucode_state load_microcode_amd(u8 family, const u8 *data, size_t size); 62extern enum ucode_state load_microcode_amd(int cpu, u8 family, const u8 *data, size_t size);
63 63
64#define PATCH_MAX_SIZE PAGE_SIZE 64#define PATCH_MAX_SIZE PAGE_SIZE
65extern u8 amd_ucode_patch[PATCH_MAX_SIZE]; 65extern u8 amd_ucode_patch[PATCH_MAX_SIZE];
@@ -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.c b/arch/x86/kernel/cpu/microcode/amd.c
index 8fffd845e22b..bfbbe6195e2d 100644
--- a/arch/x86/kernel/cpu/microcode/amd.c
+++ b/arch/x86/kernel/cpu/microcode/amd.c
@@ -376,7 +376,7 @@ static enum ucode_state __load_microcode_amd(u8 family, const u8 *data,
376 return UCODE_OK; 376 return UCODE_OK;
377} 377}
378 378
379enum ucode_state load_microcode_amd(u8 family, const u8 *data, size_t size) 379enum ucode_state load_microcode_amd(int cpu, u8 family, const u8 *data, size_t size)
380{ 380{
381 enum ucode_state ret; 381 enum ucode_state ret;
382 382
@@ -390,8 +390,8 @@ enum ucode_state load_microcode_amd(u8 family, const u8 *data, size_t size)
390 390
391#if defined(CONFIG_MICROCODE_AMD_EARLY) && defined(CONFIG_X86_32) 391#if defined(CONFIG_MICROCODE_AMD_EARLY) && defined(CONFIG_X86_32)
392 /* save BSP's matching patch for early load */ 392 /* save BSP's matching patch for early load */
393 if (cpu_data(smp_processor_id()).cpu_index == boot_cpu_data.cpu_index) { 393 if (cpu_data(cpu).cpu_index == boot_cpu_data.cpu_index) {
394 struct ucode_patch *p = find_patch(smp_processor_id()); 394 struct ucode_patch *p = find_patch(cpu);
395 if (p) { 395 if (p) {
396 memset(amd_ucode_patch, 0, PATCH_MAX_SIZE); 396 memset(amd_ucode_patch, 0, PATCH_MAX_SIZE);
397 memcpy(amd_ucode_patch, p->data, min_t(u32, ksize(p->data), 397 memcpy(amd_ucode_patch, p->data, min_t(u32, ksize(p->data),
@@ -444,7 +444,7 @@ static enum ucode_state request_microcode_amd(int cpu, struct device *device,
444 goto fw_release; 444 goto fw_release;
445 } 445 }
446 446
447 ret = load_microcode_amd(c->x86, fw->data, fw->size); 447 ret = load_microcode_amd(cpu, c->x86, fw->data, fw->size);
448 448
449 fw_release: 449 fw_release:
450 release_firmware(fw); 450 release_firmware(fw);
diff --git a/arch/x86/kernel/cpu/microcode/amd_early.c b/arch/x86/kernel/cpu/microcode/amd_early.c
index 06674473b0e6..737737edbd1e 100644
--- a/arch/x86/kernel/cpu/microcode/amd_early.c
+++ b/arch/x86/kernel/cpu/microcode/amd_early.c
@@ -389,7 +389,7 @@ int __init save_microcode_in_initrd_amd(void)
389 eax = cpuid_eax(0x00000001); 389 eax = cpuid_eax(0x00000001);
390 eax = ((eax >> 8) & 0xf) + ((eax >> 20) & 0xff); 390 eax = ((eax >> 8) & 0xf) + ((eax >> 20) & 0xff);
391 391
392 ret = load_microcode_amd(eax, container, container_size); 392 ret = load_microcode_amd(smp_processor_id(), eax, container, container_size);
393 if (ret != UCODE_OK) 393 if (ret != UCODE_OK)
394 retval = -EINVAL; 394 retval = -EINVAL;
395 395
@@ -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 08fe6e8a726e..15c29096136b 100644
--- 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)
465 465
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#ifdef CONFIG_X86_64
469 else if (!uci->mc) 468 else if (!uci->mc)
470 /* 469 reload_early_microcode();
471 * We might resume and not have applied late microcode but still
472 * have a newer patch stashed from the early loader. We don't
473 * have it in uci->mc so we have to load it the same way we're
474 * applying patches early on the APs.
475 */
476 load_ucode_ap();
477#endif
478} 470}
479 471
480static struct syscore_ops mc_syscore_ops = { 472static struct syscore_ops mc_syscore_ops = {
@@ -559,7 +551,7 @@ static int __init microcode_init(void)
559 struct cpuinfo_x86 *c = &cpu_data(0); 551 struct cpuinfo_x86 *c = &cpu_data(0);
560 int error; 552 int error;
561 553
562 if (dis_ucode_ldr) 554 if (paravirt_enabled() || dis_ucode_ldr)
563 return 0; 555 return 0;
564 556
565 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
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 b88343f7a3b3..ec9df6f9cd47 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)
650} 650}
651#endif 651#endif
652 652
653static int apply_microcode_early(struct mc_saved_data *mc_saved_data, 653static int apply_microcode_early(struct ucode_cpu_info *uci, bool early)
654 struct ucode_cpu_info *uci)
655{ 654{
656 struct microcode_intel *mc_intel; 655 struct microcode_intel *mc_intel;
657 unsigned int val[2]; 656 unsigned int val[2];
@@ -680,7 +679,10 @@ static int apply_microcode_early(struct mc_saved_data *mc_saved_data,
680#endif 679#endif
681 uci->cpu_sig.rev = val[1]; 680 uci->cpu_sig.rev = val[1];
682 681
683 print_ucode(uci); 682 if (early)
683 print_ucode(uci);
684 else
685 print_ucode_info(uci, mc_intel->hdr.date);
684 686
685 return 0; 687 return 0;
686} 688}
@@ -715,12 +717,17 @@ _load_ucode_intel_bsp(struct mc_saved_data *mc_saved_data,
715 unsigned long initrd_end_early, 717 unsigned long initrd_end_early,
716 struct ucode_cpu_info *uci) 718 struct ucode_cpu_info *uci)
717{ 719{
720 enum ucode_state ret;
721
718 collect_cpu_info_early(uci); 722 collect_cpu_info_early(uci);
719 scan_microcode(initrd_start_early, initrd_end_early, mc_saved_data, 723 scan_microcode(initrd_start_early, initrd_end_early, mc_saved_data,
720 mc_saved_in_initrd, uci); 724 mc_saved_in_initrd, uci);
721 load_microcode(mc_saved_data, mc_saved_in_initrd, 725
722 initrd_start_early, uci); 726 ret = load_microcode(mc_saved_data, mc_saved_in_initrd,
723 apply_microcode_early(mc_saved_data, uci); 727 initrd_start_early, uci);
728
729 if (ret == UCODE_OK)
730 apply_microcode_early(uci, true);
724} 731}
725 732
726void __init 733void __init
@@ -749,7 +756,8 @@ load_ucode_intel_bsp(void)
749 initrd_end_early = initrd_start_early + ramdisk_size; 756 initrd_end_early = initrd_start_early + ramdisk_size;
750 757
751 _load_ucode_intel_bsp(&mc_saved_data, mc_saved_in_initrd, 758 _load_ucode_intel_bsp(&mc_saved_data, mc_saved_in_initrd,
752 initrd_start_early, initrd_end_early, &uci); 759 initrd_start_early, initrd_end_early,
760 &uci);
753#endif 761#endif
754} 762}
755 763
@@ -783,5 +791,23 @@ void load_ucode_intel_ap(void)
783 collect_cpu_info_early(&uci); 791 collect_cpu_info_early(&uci);
784 load_microcode(mc_saved_data_p, mc_saved_in_initrd_p, 792 load_microcode(mc_saved_data_p, mc_saved_in_initrd_p,
785 initrd_start_addr, &uci); 793 initrd_start_addr, &uci);
786 apply_microcode_early(mc_saved_data_p, &uci); 794 apply_microcode_early(&uci, true);
795}
796
797void reload_ucode_intel(void)
798{
799 struct ucode_cpu_info uci;
800 enum ucode_state ret;
801
802 if (!mc_saved_data.mc_saved_count)
803 return;
804
805 collect_cpu_info_early(&uci);
806
807 ret = generic_load_microcode_early(mc_saved_data.mc_saved,
808 mc_saved_data.mc_saved_count, &uci);
809 if (ret != UCODE_OK)
810 return;
811
812 apply_microcode_early(&uci, false);
787} 813}