diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2016-07-30 16:18:33 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2016-07-30 16:18:33 -0400 |
commit | d761f3ed6e71bcca724a6e9e39efcac65b7b4ac1 (patch) | |
tree | f7730c261782da30e402e396a1c87e15dbf68c3c | |
parent | b325e04ea21081439f0f3e7fe1117e883a9031d8 (diff) | |
parent | 4a1a8e1b8f9f37bdbba416eb0a5ff3f47d31cb28 (diff) |
Merge branch 'x86-microcode-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
Pull x86 microcode updates from Thomas Gleixner:
- more work to make the microcode loader robust
- a fix for the micro code load precedence
- fixes for initrd loading with randomized memory
- less printk noise on SMP machines
* 'x86-microcode-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip:
x86/asm, x86/microcode: Add __PAGE_OFFSET_BASE define on 32-bit
x86/microcode/intel: Fix initrd loading with CONFIG_RANDOMIZE_MEMORY=y
x86/microcode: Remove unused symbol exports
x86/microcode/intel: Do not issue microcode updates messages on each CPU
Documentation/microcode: Document some aspects for more clarity
x86/microcode/AMD: Make amd_ucode_patch[] static
x86/microcode/intel: Unexport save_mc_for_early()
x86/microcode/intel: Rename load_microcode_early() to find_microcode_patch()
x86/microcode: Propagate save_microcode_in_initrd() retval
x86/microcode: Get rid of find_cpio_data()'s dummy offset arg
lib/cpio: Make find_cpio_data()'s offset arg optional
x86/microcode: Fix suspend to RAM with builtin microcode
x86/microcode: Fix loading precedence
-rw-r--r-- | Documentation/x86/early-microcode.txt | 5 | ||||
-rw-r--r-- | arch/x86/include/asm/microcode.h | 26 | ||||
-rw-r--r-- | arch/x86/include/asm/microcode_amd.h | 1 | ||||
-rw-r--r-- | arch/x86/include/asm/microcode_intel.h | 5 | ||||
-rw-r--r-- | arch/x86/include/asm/page_32_types.h | 3 | ||||
-rw-r--r-- | arch/x86/kernel/cpu/microcode/amd.c | 33 | ||||
-rw-r--r-- | arch/x86/kernel/cpu/microcode/core.c | 10 | ||||
-rw-r--r-- | arch/x86/kernel/cpu/microcode/intel.c | 261 | ||||
-rw-r--r-- | arch/x86/kernel/cpu/microcode/intel_lib.c | 2 | ||||
-rw-r--r-- | arch/x86/mm/init.c | 7 | ||||
-rw-r--r-- | lib/earlycpio.c | 5 |
11 files changed, 198 insertions, 160 deletions
diff --git a/Documentation/x86/early-microcode.txt b/Documentation/x86/early-microcode.txt index c956d99cf1de..07749e7f3d50 100644 --- a/Documentation/x86/early-microcode.txt +++ b/Documentation/x86/early-microcode.txt | |||
@@ -45,7 +45,10 @@ Builtin microcode | |||
45 | ================= | 45 | ================= |
46 | 46 | ||
47 | We can also load builtin microcode supplied through the regular firmware | 47 | We can also load builtin microcode supplied through the regular firmware |
48 | builtin method CONFIG_FIRMWARE_IN_KERNEL. Here's an example: | 48 | builtin method CONFIG_FIRMWARE_IN_KERNEL. Only 64-bit is currently |
49 | supported. | ||
50 | |||
51 | Here's an example: | ||
49 | 52 | ||
50 | CONFIG_FIRMWARE_IN_KERNEL=y | 53 | CONFIG_FIRMWARE_IN_KERNEL=y |
51 | CONFIG_EXTRA_FIRMWARE="intel-ucode/06-3a-09 amd-ucode/microcode_amd_fam15h.bin" | 54 | CONFIG_EXTRA_FIRMWARE="intel-ucode/06-3a-09 amd-ucode/microcode_amd_fam15h.bin" |
diff --git a/arch/x86/include/asm/microcode.h b/arch/x86/include/asm/microcode.h index 9d3a96c4da78..da0d81fa0b54 100644 --- a/arch/x86/include/asm/microcode.h +++ b/arch/x86/include/asm/microcode.h | |||
@@ -133,40 +133,14 @@ static inline unsigned int x86_cpuid_family(void) | |||
133 | #ifdef CONFIG_MICROCODE | 133 | #ifdef CONFIG_MICROCODE |
134 | extern void __init load_ucode_bsp(void); | 134 | extern void __init load_ucode_bsp(void); |
135 | extern void load_ucode_ap(void); | 135 | extern void load_ucode_ap(void); |
136 | extern int __init save_microcode_in_initrd(void); | ||
137 | void reload_early_microcode(void); | 136 | void reload_early_microcode(void); |
138 | extern bool get_builtin_firmware(struct cpio_data *cd, const char *name); | 137 | extern bool get_builtin_firmware(struct cpio_data *cd, const char *name); |
139 | #else | 138 | #else |
140 | static inline void __init load_ucode_bsp(void) { } | 139 | static inline void __init load_ucode_bsp(void) { } |
141 | static inline void load_ucode_ap(void) { } | 140 | static inline void load_ucode_ap(void) { } |
142 | static inline int __init save_microcode_in_initrd(void) { return 0; } | ||
143 | static inline void reload_early_microcode(void) { } | 141 | static inline void reload_early_microcode(void) { } |
144 | static inline bool | 142 | static inline bool |
145 | get_builtin_firmware(struct cpio_data *cd, const char *name) { return false; } | 143 | get_builtin_firmware(struct cpio_data *cd, const char *name) { return false; } |
146 | #endif | 144 | #endif |
147 | 145 | ||
148 | static inline unsigned long get_initrd_start(void) | ||
149 | { | ||
150 | #ifdef CONFIG_BLK_DEV_INITRD | ||
151 | return initrd_start; | ||
152 | #else | ||
153 | return 0; | ||
154 | #endif | ||
155 | } | ||
156 | |||
157 | static inline unsigned long get_initrd_start_addr(void) | ||
158 | { | ||
159 | #ifdef CONFIG_BLK_DEV_INITRD | ||
160 | #ifdef CONFIG_X86_32 | ||
161 | unsigned long *initrd_start_p = (unsigned long *)__pa_nodebug(&initrd_start); | ||
162 | |||
163 | return (unsigned long)__pa_nodebug(*initrd_start_p); | ||
164 | #else | ||
165 | return get_initrd_start(); | ||
166 | #endif | ||
167 | #else /* CONFIG_BLK_DEV_INITRD */ | ||
168 | return 0; | ||
169 | #endif | ||
170 | } | ||
171 | |||
172 | #endif /* _ASM_X86_MICROCODE_H */ | 146 | #endif /* _ASM_X86_MICROCODE_H */ |
diff --git a/arch/x86/include/asm/microcode_amd.h b/arch/x86/include/asm/microcode_amd.h index adfc847a395e..15eb75484cc0 100644 --- a/arch/x86/include/asm/microcode_amd.h +++ b/arch/x86/include/asm/microcode_amd.h | |||
@@ -62,7 +62,6 @@ extern int apply_microcode_amd(int cpu); | |||
62 | extern enum ucode_state load_microcode_amd(int cpu, u8 family, const u8 *data, size_t size); | 62 | extern 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 |
65 | extern u8 amd_ucode_patch[PATCH_MAX_SIZE]; | ||
66 | 65 | ||
67 | #ifdef CONFIG_MICROCODE_AMD | 66 | #ifdef CONFIG_MICROCODE_AMD |
68 | extern void __init load_ucode_amd_bsp(unsigned int family); | 67 | extern void __init load_ucode_amd_bsp(unsigned int family); |
diff --git a/arch/x86/include/asm/microcode_intel.h b/arch/x86/include/asm/microcode_intel.h index 603417f8dd6c..5e69154c9f07 100644 --- a/arch/x86/include/asm/microcode_intel.h +++ b/arch/x86/include/asm/microcode_intel.h | |||
@@ -70,9 +70,4 @@ static inline int __init save_microcode_in_initrd_intel(void) { return -EINVAL; | |||
70 | static inline void reload_ucode_intel(void) {} | 70 | static inline void reload_ucode_intel(void) {} |
71 | #endif | 71 | #endif |
72 | 72 | ||
73 | #ifdef CONFIG_HOTPLUG_CPU | ||
74 | extern int save_mc_for_early(u8 *mc); | ||
75 | #else | ||
76 | static inline int save_mc_for_early(u8 *mc) { return 0; } | ||
77 | #endif | ||
78 | #endif /* _ASM_X86_MICROCODE_INTEL_H */ | 73 | #endif /* _ASM_X86_MICROCODE_INTEL_H */ |
diff --git a/arch/x86/include/asm/page_32_types.h b/arch/x86/include/asm/page_32_types.h index 3a52ee0e726d..3bae4969ac65 100644 --- a/arch/x86/include/asm/page_32_types.h +++ b/arch/x86/include/asm/page_32_types.h | |||
@@ -13,7 +13,8 @@ | |||
13 | * If you want more physical memory than this then see the CONFIG_HIGHMEM4G | 13 | * If you want more physical memory than this then see the CONFIG_HIGHMEM4G |
14 | * and CONFIG_HIGHMEM64G options in the kernel configuration. | 14 | * and CONFIG_HIGHMEM64G options in the kernel configuration. |
15 | */ | 15 | */ |
16 | #define __PAGE_OFFSET _AC(CONFIG_PAGE_OFFSET, UL) | 16 | #define __PAGE_OFFSET_BASE _AC(CONFIG_PAGE_OFFSET, UL) |
17 | #define __PAGE_OFFSET __PAGE_OFFSET_BASE | ||
17 | 18 | ||
18 | #define __START_KERNEL_map __PAGE_OFFSET | 19 | #define __START_KERNEL_map __PAGE_OFFSET |
19 | 20 | ||
diff --git a/arch/x86/kernel/cpu/microcode/amd.c b/arch/x86/kernel/cpu/microcode/amd.c index 8581963894c7..27a0228c9cae 100644 --- a/arch/x86/kernel/cpu/microcode/amd.c +++ b/arch/x86/kernel/cpu/microcode/amd.c | |||
@@ -56,24 +56,24 @@ static u8 *container; | |||
56 | static size_t container_size; | 56 | static size_t container_size; |
57 | 57 | ||
58 | static u32 ucode_new_rev; | 58 | static u32 ucode_new_rev; |
59 | u8 amd_ucode_patch[PATCH_MAX_SIZE]; | 59 | static u8 amd_ucode_patch[PATCH_MAX_SIZE]; |
60 | static u16 this_equiv_id; | 60 | static u16 this_equiv_id; |
61 | 61 | ||
62 | static struct cpio_data ucode_cpio; | 62 | static struct cpio_data ucode_cpio; |
63 | 63 | ||
64 | /* | ||
65 | * Microcode patch container file is prepended to the initrd in cpio format. | ||
66 | * See Documentation/x86/early-microcode.txt | ||
67 | */ | ||
68 | static __initdata char ucode_path[] = "kernel/x86/microcode/AuthenticAMD.bin"; | ||
69 | |||
70 | static struct cpio_data __init find_ucode_in_initrd(void) | 64 | static struct cpio_data __init find_ucode_in_initrd(void) |
71 | { | 65 | { |
72 | long offset = 0; | 66 | #ifdef CONFIG_BLK_DEV_INITRD |
73 | char *path; | 67 | char *path; |
74 | void *start; | 68 | void *start; |
75 | size_t size; | 69 | size_t size; |
76 | 70 | ||
71 | /* | ||
72 | * Microcode patch container file is prepended to the initrd in cpio | ||
73 | * format. See Documentation/x86/early-microcode.txt | ||
74 | */ | ||
75 | static __initdata char ucode_path[] = "kernel/x86/microcode/AuthenticAMD.bin"; | ||
76 | |||
77 | #ifdef CONFIG_X86_32 | 77 | #ifdef CONFIG_X86_32 |
78 | struct boot_params *p; | 78 | struct boot_params *p; |
79 | 79 | ||
@@ -89,9 +89,12 @@ static struct cpio_data __init find_ucode_in_initrd(void) | |||
89 | path = ucode_path; | 89 | path = ucode_path; |
90 | start = (void *)(boot_params.hdr.ramdisk_image + PAGE_OFFSET); | 90 | start = (void *)(boot_params.hdr.ramdisk_image + PAGE_OFFSET); |
91 | size = boot_params.hdr.ramdisk_size; | 91 | size = boot_params.hdr.ramdisk_size; |
92 | #endif | 92 | #endif /* !CONFIG_X86_32 */ |
93 | 93 | ||
94 | return find_cpio_data(path, start, size, &offset); | 94 | return find_cpio_data(path, start, size, NULL); |
95 | #else | ||
96 | return (struct cpio_data){ NULL, 0, "" }; | ||
97 | #endif | ||
95 | } | 98 | } |
96 | 99 | ||
97 | static size_t compute_container_size(u8 *data, u32 total_size) | 100 | static size_t compute_container_size(u8 *data, u32 total_size) |
@@ -289,11 +292,11 @@ void __init load_ucode_amd_bsp(unsigned int family) | |||
289 | size = &ucode_cpio.size; | 292 | size = &ucode_cpio.size; |
290 | #endif | 293 | #endif |
291 | 294 | ||
292 | cp = find_ucode_in_initrd(); | 295 | if (!load_builtin_amd_microcode(&cp, family)) |
293 | if (!cp.data) { | 296 | cp = find_ucode_in_initrd(); |
294 | if (!load_builtin_amd_microcode(&cp, family)) | 297 | |
295 | return; | 298 | if (!(cp.data && cp.size)) |
296 | } | 299 | return; |
297 | 300 | ||
298 | *data = cp.data; | 301 | *data = cp.data; |
299 | *size = cp.size; | 302 | *size = cp.size; |
diff --git a/arch/x86/kernel/cpu/microcode/core.c b/arch/x86/kernel/cpu/microcode/core.c index ac360bfbbdb6..df04b2d033f6 100644 --- a/arch/x86/kernel/cpu/microcode/core.c +++ b/arch/x86/kernel/cpu/microcode/core.c | |||
@@ -60,7 +60,6 @@ static bool dis_ucode_ldr; | |||
60 | static DEFINE_MUTEX(microcode_mutex); | 60 | static DEFINE_MUTEX(microcode_mutex); |
61 | 61 | ||
62 | struct ucode_cpu_info ucode_cpu_info[NR_CPUS]; | 62 | struct ucode_cpu_info ucode_cpu_info[NR_CPUS]; |
63 | EXPORT_SYMBOL_GPL(ucode_cpu_info); | ||
64 | 63 | ||
65 | /* | 64 | /* |
66 | * Operations that are run on a target cpu: | 65 | * Operations that are run on a target cpu: |
@@ -175,24 +174,24 @@ void load_ucode_ap(void) | |||
175 | } | 174 | } |
176 | } | 175 | } |
177 | 176 | ||
178 | int __init save_microcode_in_initrd(void) | 177 | static int __init save_microcode_in_initrd(void) |
179 | { | 178 | { |
180 | struct cpuinfo_x86 *c = &boot_cpu_data; | 179 | struct cpuinfo_x86 *c = &boot_cpu_data; |
181 | 180 | ||
182 | switch (c->x86_vendor) { | 181 | switch (c->x86_vendor) { |
183 | case X86_VENDOR_INTEL: | 182 | case X86_VENDOR_INTEL: |
184 | if (c->x86 >= 6) | 183 | if (c->x86 >= 6) |
185 | save_microcode_in_initrd_intel(); | 184 | return save_microcode_in_initrd_intel(); |
186 | break; | 185 | break; |
187 | case X86_VENDOR_AMD: | 186 | case X86_VENDOR_AMD: |
188 | if (c->x86 >= 0x10) | 187 | if (c->x86 >= 0x10) |
189 | save_microcode_in_initrd_amd(); | 188 | return save_microcode_in_initrd_amd(); |
190 | break; | 189 | break; |
191 | default: | 190 | default: |
192 | break; | 191 | break; |
193 | } | 192 | } |
194 | 193 | ||
195 | return 0; | 194 | return -EINVAL; |
196 | } | 195 | } |
197 | 196 | ||
198 | void reload_early_microcode(void) | 197 | void reload_early_microcode(void) |
@@ -691,4 +690,5 @@ int __init microcode_init(void) | |||
691 | return error; | 690 | return error; |
692 | 691 | ||
693 | } | 692 | } |
693 | fs_initcall(save_microcode_in_initrd); | ||
694 | late_initcall(microcode_init); | 694 | late_initcall(microcode_init); |
diff --git a/arch/x86/kernel/cpu/microcode/intel.c b/arch/x86/kernel/cpu/microcode/intel.c index 65cbbcd48fe4..cdc0deab00c9 100644 --- a/arch/x86/kernel/cpu/microcode/intel.c +++ b/arch/x86/kernel/cpu/microcode/intel.c | |||
@@ -40,9 +40,13 @@ | |||
40 | #include <asm/msr.h> | 40 | #include <asm/msr.h> |
41 | 41 | ||
42 | /* | 42 | /* |
43 | * Temporary microcode blobs pointers storage. We note here the pointers to | 43 | * Temporary microcode blobs pointers storage. We note here during early load |
44 | * microcode blobs we've got from whatever storage (detached initrd, builtin). | 44 | * the pointers to microcode blobs we've got from whatever storage (detached |
45 | * Later on, we put those into final storage mc_saved_data.mc_saved. | 45 | * initrd, builtin). Later on, we put those into final storage |
46 | * mc_saved_data.mc_saved. | ||
47 | * | ||
48 | * Important: those are offsets from the beginning of initrd or absolute | ||
49 | * addresses within the kernel image when built-in. | ||
46 | */ | 50 | */ |
47 | static unsigned long mc_tmp_ptrs[MAX_UCODE_COUNT]; | 51 | static unsigned long mc_tmp_ptrs[MAX_UCODE_COUNT]; |
48 | 52 | ||
@@ -51,8 +55,15 @@ static struct mc_saved_data { | |||
51 | struct microcode_intel **mc_saved; | 55 | struct microcode_intel **mc_saved; |
52 | } mc_saved_data; | 56 | } mc_saved_data; |
53 | 57 | ||
58 | /* Microcode blobs within the initrd. 0 if builtin. */ | ||
59 | static struct ucode_blobs { | ||
60 | unsigned long start; | ||
61 | bool valid; | ||
62 | } blobs; | ||
63 | |||
64 | /* Go through saved patches and find the one suitable for the current CPU. */ | ||
54 | static enum ucode_state | 65 | static enum ucode_state |
55 | load_microcode_early(struct microcode_intel **saved, | 66 | find_microcode_patch(struct microcode_intel **saved, |
56 | unsigned int num_saved, struct ucode_cpu_info *uci) | 67 | unsigned int num_saved, struct ucode_cpu_info *uci) |
57 | { | 68 | { |
58 | struct microcode_intel *ucode_ptr, *new_mc = NULL; | 69 | struct microcode_intel *ucode_ptr, *new_mc = NULL; |
@@ -121,13 +132,13 @@ load_microcode(struct mc_saved_data *mcs, unsigned long *mc_ptrs, | |||
121 | if (!mcs->mc_saved) { | 132 | if (!mcs->mc_saved) { |
122 | copy_ptrs(mc_saved_tmp, mc_ptrs, offset, count); | 133 | copy_ptrs(mc_saved_tmp, mc_ptrs, offset, count); |
123 | 134 | ||
124 | return load_microcode_early(mc_saved_tmp, count, uci); | 135 | return find_microcode_patch(mc_saved_tmp, count, uci); |
125 | } else { | 136 | } else { |
126 | #ifdef CONFIG_X86_32 | 137 | #ifdef CONFIG_X86_32 |
127 | microcode_phys(mc_saved_tmp, mcs); | 138 | microcode_phys(mc_saved_tmp, mcs); |
128 | return load_microcode_early(mc_saved_tmp, count, uci); | 139 | return find_microcode_patch(mc_saved_tmp, count, uci); |
129 | #else | 140 | #else |
130 | return load_microcode_early(mcs->mc_saved, count, uci); | 141 | return find_microcode_patch(mcs->mc_saved, count, uci); |
131 | #endif | 142 | #endif |
132 | } | 143 | } |
133 | } | 144 | } |
@@ -450,8 +461,6 @@ static void show_saved_mc(void) | |||
450 | #endif | 461 | #endif |
451 | } | 462 | } |
452 | 463 | ||
453 | #ifdef CONFIG_HOTPLUG_CPU | ||
454 | static DEFINE_MUTEX(x86_cpu_microcode_mutex); | ||
455 | /* | 464 | /* |
456 | * Save this mc into mc_saved_data. So it will be loaded early when a CPU is | 465 | * Save this mc into mc_saved_data. So it will be loaded early when a CPU is |
457 | * hot added or resumes. | 466 | * hot added or resumes. |
@@ -459,19 +468,18 @@ static DEFINE_MUTEX(x86_cpu_microcode_mutex); | |||
459 | * Please make sure this mc should be a valid microcode patch before calling | 468 | * Please make sure this mc should be a valid microcode patch before calling |
460 | * this function. | 469 | * this function. |
461 | */ | 470 | */ |
462 | int save_mc_for_early(u8 *mc) | 471 | static void save_mc_for_early(u8 *mc) |
463 | { | 472 | { |
473 | #ifdef CONFIG_HOTPLUG_CPU | ||
474 | /* Synchronization during CPU hotplug. */ | ||
475 | static DEFINE_MUTEX(x86_cpu_microcode_mutex); | ||
476 | |||
464 | struct microcode_intel *mc_saved_tmp[MAX_UCODE_COUNT]; | 477 | struct microcode_intel *mc_saved_tmp[MAX_UCODE_COUNT]; |
465 | unsigned int mc_saved_count_init; | 478 | unsigned int mc_saved_count_init; |
466 | unsigned int num_saved; | 479 | unsigned int num_saved; |
467 | struct microcode_intel **mc_saved; | 480 | struct microcode_intel **mc_saved; |
468 | int ret = 0; | 481 | int ret, i; |
469 | int i; | ||
470 | 482 | ||
471 | /* | ||
472 | * Hold hotplug lock so mc_saved_data is not accessed by a CPU in | ||
473 | * hotplug. | ||
474 | */ | ||
475 | mutex_lock(&x86_cpu_microcode_mutex); | 483 | mutex_lock(&x86_cpu_microcode_mutex); |
476 | 484 | ||
477 | mc_saved_count_init = mc_saved_data.num_saved; | 485 | mc_saved_count_init = mc_saved_data.num_saved; |
@@ -509,11 +517,8 @@ int save_mc_for_early(u8 *mc) | |||
509 | 517 | ||
510 | out: | 518 | out: |
511 | mutex_unlock(&x86_cpu_microcode_mutex); | 519 | mutex_unlock(&x86_cpu_microcode_mutex); |
512 | |||
513 | return ret; | ||
514 | } | ||
515 | EXPORT_SYMBOL_GPL(save_mc_for_early); | ||
516 | #endif | 520 | #endif |
521 | } | ||
517 | 522 | ||
518 | static bool __init load_builtin_intel_microcode(struct cpio_data *cp) | 523 | static bool __init load_builtin_intel_microcode(struct cpio_data *cp) |
519 | { | 524 | { |
@@ -532,37 +537,6 @@ static bool __init load_builtin_intel_microcode(struct cpio_data *cp) | |||
532 | #endif | 537 | #endif |
533 | } | 538 | } |
534 | 539 | ||
535 | static __initdata char ucode_name[] = "kernel/x86/microcode/GenuineIntel.bin"; | ||
536 | static __init enum ucode_state | ||
537 | scan_microcode(struct mc_saved_data *mcs, unsigned long *mc_ptrs, | ||
538 | unsigned long start, unsigned long size, | ||
539 | struct ucode_cpu_info *uci) | ||
540 | { | ||
541 | struct cpio_data cd; | ||
542 | long offset = 0; | ||
543 | #ifdef CONFIG_X86_32 | ||
544 | char *p = (char *)__pa_nodebug(ucode_name); | ||
545 | #else | ||
546 | char *p = ucode_name; | ||
547 | #endif | ||
548 | |||
549 | cd.data = NULL; | ||
550 | cd.size = 0; | ||
551 | |||
552 | /* try built-in microcode if no initrd */ | ||
553 | if (!size) { | ||
554 | if (!load_builtin_intel_microcode(&cd)) | ||
555 | return UCODE_ERROR; | ||
556 | } else { | ||
557 | cd = find_cpio_data(p, (void *)start, size, &offset); | ||
558 | if (!cd.data) | ||
559 | return UCODE_ERROR; | ||
560 | } | ||
561 | |||
562 | return get_matching_model_microcode(start, cd.data, cd.size, | ||
563 | mcs, mc_ptrs, uci); | ||
564 | } | ||
565 | |||
566 | /* | 540 | /* |
567 | * Print ucode update info. | 541 | * Print ucode update info. |
568 | */ | 542 | */ |
@@ -680,38 +654,117 @@ static int apply_microcode_early(struct ucode_cpu_info *uci, bool early) | |||
680 | */ | 654 | */ |
681 | int __init save_microcode_in_initrd_intel(void) | 655 | int __init save_microcode_in_initrd_intel(void) |
682 | { | 656 | { |
683 | unsigned int count = mc_saved_data.num_saved; | ||
684 | struct microcode_intel *mc_saved[MAX_UCODE_COUNT]; | 657 | struct microcode_intel *mc_saved[MAX_UCODE_COUNT]; |
685 | int ret = 0; | 658 | unsigned int count = mc_saved_data.num_saved; |
659 | unsigned long offset = 0; | ||
660 | int ret; | ||
686 | 661 | ||
687 | if (!count) | 662 | if (!count) |
688 | return ret; | 663 | return 0; |
664 | |||
665 | /* | ||
666 | * We have found a valid initrd but it might've been relocated in the | ||
667 | * meantime so get its updated address. | ||
668 | */ | ||
669 | if (IS_ENABLED(CONFIG_BLK_DEV_INITRD) && blobs.valid) | ||
670 | offset = initrd_start; | ||
689 | 671 | ||
690 | copy_ptrs(mc_saved, mc_tmp_ptrs, get_initrd_start(), count); | 672 | copy_ptrs(mc_saved, mc_tmp_ptrs, offset, count); |
691 | 673 | ||
692 | ret = save_microcode(&mc_saved_data, mc_saved, count); | 674 | ret = save_microcode(&mc_saved_data, mc_saved, count); |
693 | if (ret) | 675 | if (ret) |
694 | pr_err("Cannot save microcode patches from initrd.\n"); | 676 | pr_err("Cannot save microcode patches from initrd.\n"); |
695 | 677 | else | |
696 | show_saved_mc(); | 678 | show_saved_mc(); |
697 | 679 | ||
698 | return ret; | 680 | return ret; |
699 | } | 681 | } |
700 | 682 | ||
683 | static __init enum ucode_state | ||
684 | __scan_microcode_initrd(struct cpio_data *cd, struct ucode_blobs *blbp) | ||
685 | { | ||
686 | #ifdef CONFIG_BLK_DEV_INITRD | ||
687 | static __initdata char ucode_name[] = "kernel/x86/microcode/GenuineIntel.bin"; | ||
688 | char *p = IS_ENABLED(CONFIG_X86_32) ? (char *)__pa_nodebug(ucode_name) | ||
689 | : ucode_name; | ||
690 | # ifdef CONFIG_X86_32 | ||
691 | unsigned long start = 0, size; | ||
692 | struct boot_params *params; | ||
693 | |||
694 | params = (struct boot_params *)__pa_nodebug(&boot_params); | ||
695 | size = params->hdr.ramdisk_size; | ||
696 | |||
697 | /* | ||
698 | * Set start only if we have an initrd image. We cannot use initrd_start | ||
699 | * because it is not set that early yet. | ||
700 | */ | ||
701 | start = (size ? params->hdr.ramdisk_image : 0); | ||
702 | |||
703 | # else /* CONFIG_X86_64 */ | ||
704 | unsigned long start = 0, size; | ||
705 | |||
706 | size = (u64)boot_params.ext_ramdisk_size << 32; | ||
707 | size |= boot_params.hdr.ramdisk_size; | ||
708 | |||
709 | if (size) { | ||
710 | start = (u64)boot_params.ext_ramdisk_image << 32; | ||
711 | start |= boot_params.hdr.ramdisk_image; | ||
712 | |||
713 | start += PAGE_OFFSET; | ||
714 | } | ||
715 | # endif | ||
716 | |||
717 | *cd = find_cpio_data(p, (void *)start, size, NULL); | ||
718 | if (cd->data) { | ||
719 | blbp->start = start; | ||
720 | blbp->valid = true; | ||
721 | |||
722 | return UCODE_OK; | ||
723 | } else | ||
724 | #endif /* CONFIG_BLK_DEV_INITRD */ | ||
725 | return UCODE_ERROR; | ||
726 | } | ||
727 | |||
728 | static __init enum ucode_state | ||
729 | scan_microcode(struct mc_saved_data *mcs, unsigned long *mc_ptrs, | ||
730 | struct ucode_cpu_info *uci, struct ucode_blobs *blbp) | ||
731 | { | ||
732 | struct cpio_data cd = { NULL, 0, "" }; | ||
733 | enum ucode_state ret; | ||
734 | |||
735 | /* try built-in microcode first */ | ||
736 | if (load_builtin_intel_microcode(&cd)) | ||
737 | /* | ||
738 | * Invalidate blobs as we might've gotten an initrd too, | ||
739 | * supplied by the boot loader, by mistake or simply forgotten | ||
740 | * there. That's fine, we ignore it since we've found builtin | ||
741 | * microcode already. | ||
742 | */ | ||
743 | blbp->valid = false; | ||
744 | else { | ||
745 | ret = __scan_microcode_initrd(&cd, blbp); | ||
746 | if (ret != UCODE_OK) | ||
747 | return ret; | ||
748 | } | ||
749 | |||
750 | return get_matching_model_microcode(blbp->start, cd.data, cd.size, | ||
751 | mcs, mc_ptrs, uci); | ||
752 | } | ||
753 | |||
701 | static void __init | 754 | static void __init |
702 | _load_ucode_intel_bsp(struct mc_saved_data *mcs, unsigned long *mc_ptrs, | 755 | _load_ucode_intel_bsp(struct mc_saved_data *mcs, unsigned long *mc_ptrs, |
703 | unsigned long start, unsigned long size) | 756 | struct ucode_blobs *blbp) |
704 | { | 757 | { |
705 | struct ucode_cpu_info uci; | 758 | struct ucode_cpu_info uci; |
706 | enum ucode_state ret; | 759 | enum ucode_state ret; |
707 | 760 | ||
708 | collect_cpu_info_early(&uci); | 761 | collect_cpu_info_early(&uci); |
709 | 762 | ||
710 | ret = scan_microcode(mcs, mc_ptrs, start, size, &uci); | 763 | ret = scan_microcode(mcs, mc_ptrs, &uci, blbp); |
711 | if (ret != UCODE_OK) | 764 | if (ret != UCODE_OK) |
712 | return; | 765 | return; |
713 | 766 | ||
714 | ret = load_microcode(mcs, mc_ptrs, start, &uci); | 767 | ret = load_microcode(mcs, mc_ptrs, blbp->start, &uci); |
715 | if (ret != UCODE_OK) | 768 | if (ret != UCODE_OK) |
716 | return; | 769 | return; |
717 | 770 | ||
@@ -720,54 +773,60 @@ _load_ucode_intel_bsp(struct mc_saved_data *mcs, unsigned long *mc_ptrs, | |||
720 | 773 | ||
721 | void __init load_ucode_intel_bsp(void) | 774 | void __init load_ucode_intel_bsp(void) |
722 | { | 775 | { |
723 | u64 start, size; | 776 | struct ucode_blobs *blobs_p; |
724 | #ifdef CONFIG_X86_32 | 777 | struct mc_saved_data *mcs; |
725 | struct boot_params *p; | 778 | unsigned long *ptrs; |
726 | |||
727 | p = (struct boot_params *)__pa_nodebug(&boot_params); | ||
728 | size = p->hdr.ramdisk_size; | ||
729 | 779 | ||
730 | /* | 780 | #ifdef CONFIG_X86_32 |
731 | * Set start only if we have an initrd image. We cannot use initrd_start | 781 | mcs = (struct mc_saved_data *)__pa_nodebug(&mc_saved_data); |
732 | * because it is not set that early yet. | 782 | ptrs = (unsigned long *)__pa_nodebug(&mc_tmp_ptrs); |
733 | */ | 783 | blobs_p = (struct ucode_blobs *)__pa_nodebug(&blobs); |
734 | start = (size ? p->hdr.ramdisk_image : 0); | ||
735 | |||
736 | _load_ucode_intel_bsp((struct mc_saved_data *)__pa_nodebug(&mc_saved_data), | ||
737 | (unsigned long *)__pa_nodebug(&mc_tmp_ptrs), | ||
738 | start, size); | ||
739 | #else | 784 | #else |
740 | size = boot_params.hdr.ramdisk_size; | 785 | mcs = &mc_saved_data; |
741 | start = (size ? boot_params.hdr.ramdisk_image + PAGE_OFFSET : 0); | 786 | ptrs = mc_tmp_ptrs; |
742 | 787 | blobs_p = &blobs; | |
743 | _load_ucode_intel_bsp(&mc_saved_data, mc_tmp_ptrs, start, size); | ||
744 | #endif | 788 | #endif |
789 | |||
790 | _load_ucode_intel_bsp(mcs, ptrs, blobs_p); | ||
745 | } | 791 | } |
746 | 792 | ||
747 | void load_ucode_intel_ap(void) | 793 | void load_ucode_intel_ap(void) |
748 | { | 794 | { |
749 | unsigned long *mcs_tmp_p; | 795 | struct ucode_blobs *blobs_p; |
750 | struct mc_saved_data *mcs_p; | 796 | unsigned long *ptrs, start = 0; |
797 | struct mc_saved_data *mcs; | ||
751 | struct ucode_cpu_info uci; | 798 | struct ucode_cpu_info uci; |
752 | enum ucode_state ret; | 799 | enum ucode_state ret; |
753 | #ifdef CONFIG_X86_32 | ||
754 | 800 | ||
755 | mcs_tmp_p = (unsigned long *)__pa_nodebug(mc_tmp_ptrs); | 801 | #ifdef CONFIG_X86_32 |
756 | mcs_p = (struct mc_saved_data *)__pa_nodebug(&mc_saved_data); | 802 | mcs = (struct mc_saved_data *)__pa_nodebug(&mc_saved_data); |
803 | ptrs = (unsigned long *)__pa_nodebug(mc_tmp_ptrs); | ||
804 | blobs_p = (struct ucode_blobs *)__pa_nodebug(&blobs); | ||
757 | #else | 805 | #else |
758 | mcs_tmp_p = mc_tmp_ptrs; | 806 | mcs = &mc_saved_data; |
759 | mcs_p = &mc_saved_data; | 807 | ptrs = mc_tmp_ptrs; |
808 | blobs_p = &blobs; | ||
760 | #endif | 809 | #endif |
761 | 810 | ||
762 | /* | 811 | /* |
763 | * If there is no valid ucode previously saved in memory, no need to | 812 | * If there is no valid ucode previously saved in memory, no need to |
764 | * update ucode on this AP. | 813 | * update ucode on this AP. |
765 | */ | 814 | */ |
766 | if (!mcs_p->num_saved) | 815 | if (!mcs->num_saved) |
767 | return; | 816 | return; |
768 | 817 | ||
818 | if (blobs_p->valid) { | ||
819 | start = blobs_p->start; | ||
820 | |||
821 | /* | ||
822 | * Pay attention to CONFIG_RANDOMIZE_MEMORY=y as it shuffles | ||
823 | * physmem mapping too and there we have the initrd. | ||
824 | */ | ||
825 | start += PAGE_OFFSET - __PAGE_OFFSET_BASE; | ||
826 | } | ||
827 | |||
769 | collect_cpu_info_early(&uci); | 828 | collect_cpu_info_early(&uci); |
770 | ret = load_microcode(mcs_p, mcs_tmp_p, get_initrd_start_addr(), &uci); | 829 | ret = load_microcode(mcs, ptrs, start, &uci); |
771 | if (ret != UCODE_OK) | 830 | if (ret != UCODE_OK) |
772 | return; | 831 | return; |
773 | 832 | ||
@@ -784,7 +843,7 @@ void reload_ucode_intel(void) | |||
784 | 843 | ||
785 | collect_cpu_info_early(&uci); | 844 | collect_cpu_info_early(&uci); |
786 | 845 | ||
787 | ret = load_microcode_early(mc_saved_data.mc_saved, | 846 | ret = find_microcode_patch(mc_saved_data.mc_saved, |
788 | mc_saved_data.num_saved, &uci); | 847 | mc_saved_data.num_saved, &uci); |
789 | if (ret != UCODE_OK) | 848 | if (ret != UCODE_OK) |
790 | return; | 849 | return; |
@@ -794,6 +853,7 @@ void reload_ucode_intel(void) | |||
794 | 853 | ||
795 | static int collect_cpu_info(int cpu_num, struct cpu_signature *csig) | 854 | static int collect_cpu_info(int cpu_num, struct cpu_signature *csig) |
796 | { | 855 | { |
856 | static struct cpu_signature prev; | ||
797 | struct cpuinfo_x86 *c = &cpu_data(cpu_num); | 857 | struct cpuinfo_x86 *c = &cpu_data(cpu_num); |
798 | unsigned int val[2]; | 858 | unsigned int val[2]; |
799 | 859 | ||
@@ -808,8 +868,13 @@ static int collect_cpu_info(int cpu_num, struct cpu_signature *csig) | |||
808 | } | 868 | } |
809 | 869 | ||
810 | csig->rev = c->microcode; | 870 | csig->rev = c->microcode; |
811 | pr_info("CPU%d sig=0x%x, pf=0x%x, revision=0x%x\n", | 871 | |
812 | cpu_num, csig->sig, csig->pf, csig->rev); | 872 | /* No extra locking on prev, races are harmless. */ |
873 | if (csig->sig != prev.sig || csig->pf != prev.pf || csig->rev != prev.rev) { | ||
874 | pr_info("sig=0x%x, pf=0x%x, revision=0x%x\n", | ||
875 | csig->sig, csig->pf, csig->rev); | ||
876 | prev = *csig; | ||
877 | } | ||
813 | 878 | ||
814 | return 0; | 879 | return 0; |
815 | } | 880 | } |
@@ -838,6 +903,7 @@ static int apply_microcode_intel(int cpu) | |||
838 | struct ucode_cpu_info *uci; | 903 | struct ucode_cpu_info *uci; |
839 | struct cpuinfo_x86 *c; | 904 | struct cpuinfo_x86 *c; |
840 | unsigned int val[2]; | 905 | unsigned int val[2]; |
906 | static int prev_rev; | ||
841 | 907 | ||
842 | /* We should bind the task to the CPU */ | 908 | /* We should bind the task to the CPU */ |
843 | if (WARN_ON(raw_smp_processor_id() != cpu)) | 909 | if (WARN_ON(raw_smp_processor_id() != cpu)) |
@@ -872,11 +938,14 @@ static int apply_microcode_intel(int cpu) | |||
872 | return -1; | 938 | return -1; |
873 | } | 939 | } |
874 | 940 | ||
875 | pr_info("CPU%d updated to revision 0x%x, date = %04x-%02x-%02x\n", | 941 | if (val[1] != prev_rev) { |
876 | cpu, val[1], | 942 | pr_info("updated to revision 0x%x, date = %04x-%02x-%02x\n", |
877 | mc->hdr.date & 0xffff, | 943 | val[1], |
878 | mc->hdr.date >> 24, | 944 | mc->hdr.date & 0xffff, |
879 | (mc->hdr.date >> 16) & 0xff); | 945 | mc->hdr.date >> 24, |
946 | (mc->hdr.date >> 16) & 0xff); | ||
947 | prev_rev = val[1]; | ||
948 | } | ||
880 | 949 | ||
881 | c = &cpu_data(cpu); | 950 | c = &cpu_data(cpu); |
882 | 951 | ||
diff --git a/arch/x86/kernel/cpu/microcode/intel_lib.c b/arch/x86/kernel/cpu/microcode/intel_lib.c index 2ce1a7dc45b7..406cb6c0d9dd 100644 --- a/arch/x86/kernel/cpu/microcode/intel_lib.c +++ b/arch/x86/kernel/cpu/microcode/intel_lib.c | |||
@@ -141,7 +141,6 @@ int microcode_sanity_check(void *mc, int print_err) | |||
141 | } | 141 | } |
142 | return 0; | 142 | return 0; |
143 | } | 143 | } |
144 | EXPORT_SYMBOL_GPL(microcode_sanity_check); | ||
145 | 144 | ||
146 | /* | 145 | /* |
147 | * Returns 1 if update has been found, 0 otherwise. | 146 | * Returns 1 if update has been found, 0 otherwise. |
@@ -183,4 +182,3 @@ int has_newer_microcode(void *mc, unsigned int csig, int cpf, int new_rev) | |||
183 | 182 | ||
184 | return find_matching_signature(mc, csig, cpf); | 183 | return find_matching_signature(mc, csig, cpf); |
185 | } | 184 | } |
186 | EXPORT_SYMBOL_GPL(has_newer_microcode); | ||
diff --git a/arch/x86/mm/init.c b/arch/x86/mm/init.c index cc82830bc8c4..fb4c1b42fc7e 100644 --- a/arch/x86/mm/init.c +++ b/arch/x86/mm/init.c | |||
@@ -700,13 +700,6 @@ void free_initmem(void) | |||
700 | void __init free_initrd_mem(unsigned long start, unsigned long end) | 700 | void __init free_initrd_mem(unsigned long start, unsigned long end) |
701 | { | 701 | { |
702 | /* | 702 | /* |
703 | * Remember, initrd memory may contain microcode or other useful things. | ||
704 | * Before we lose initrd mem, we need to find a place to hold them | ||
705 | * now that normal virtual memory is enabled. | ||
706 | */ | ||
707 | save_microcode_in_initrd(); | ||
708 | |||
709 | /* | ||
710 | * end could be not aligned, and We can not align that, | 703 | * end could be not aligned, and We can not align that, |
711 | * decompresser could be confused by aligned initrd_end | 704 | * decompresser could be confused by aligned initrd_end |
712 | * We already reserve the end partial page before in | 705 | * We already reserve the end partial page before in |
diff --git a/lib/earlycpio.c b/lib/earlycpio.c index 3eb3e4722b8e..db283ba4d2c1 100644 --- a/lib/earlycpio.c +++ b/lib/earlycpio.c | |||
@@ -125,7 +125,10 @@ struct cpio_data find_cpio_data(const char *path, void *data, | |||
125 | if ((ch[C_MODE] & 0170000) == 0100000 && | 125 | if ((ch[C_MODE] & 0170000) == 0100000 && |
126 | ch[C_NAMESIZE] >= mypathsize && | 126 | ch[C_NAMESIZE] >= mypathsize && |
127 | !memcmp(p, path, mypathsize)) { | 127 | !memcmp(p, path, mypathsize)) { |
128 | *nextoff = (long)nptr - (long)data; | 128 | |
129 | if (nextoff) | ||
130 | *nextoff = (long)nptr - (long)data; | ||
131 | |||
129 | if (ch[C_NAMESIZE] - mypathsize >= MAX_CPIO_FILE_NAME) { | 132 | if (ch[C_NAMESIZE] - mypathsize >= MAX_CPIO_FILE_NAME) { |
130 | pr_warn( | 133 | pr_warn( |
131 | "File %s exceeding MAX_CPIO_FILE_NAME [%d]\n", | 134 | "File %s exceeding MAX_CPIO_FILE_NAME [%d]\n", |