aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBorislav Petkov <bp@suse.de>2015-03-18 14:28:56 -0400
committerIngo Molnar <mingo@kernel.org>2015-05-06 05:24:53 -0400
commit760d765b2bb662be177d4b5b271ced8debc803ac (patch)
treeae71bf65b3e8b389062a4988da7c8e821fa19a34
parentda9b50765e6ea3e9113df3a14a63700e47a670b7 (diff)
x86/microcode: Parse built-in microcode early
Apparently, people do build microcode into the kernel image, i.e. CONFIG_FIRMWARE_IN_KERNEL=y. Make that work in the early loader which is where microcode should be preferably loaded anyway. Note that you need to specify the microcode filename with the path relative to the toplevel firmware directory (the same like the late loading method) in CONFIG_EXTRA_FIRMWARE=y so that early loader can find it. I.e., something like this (Intel variant): CONFIG_FIRMWARE_IN_KERNEL=y CONFIG_EXTRA_FIRMWARE="intel-ucode/06-3a-09" CONFIG_EXTRA_FIRMWARE_DIR="/lib/firmware/" While at it, add me to the loader copyright boilerplate. Signed-off-by: Borislav Petkov <bp@suse.de> Cc: Borislav Petkov <bp@alien8.de> Cc: Daniel J Blueman <daniel@numascale.com> Cc: H. Peter Anvin <hpa@zytor.com> Cc: Thomas Gleixner <tglx@linutronix.de> Signed-off-by: Ingo Molnar <mingo@kernel.org>
-rw-r--r--arch/x86/include/asm/microcode.h8
-rw-r--r--arch/x86/include/asm/microcode_amd.h4
-rw-r--r--arch/x86/kernel/cpu/microcode/amd_early.c19
-rw-r--r--arch/x86/kernel/cpu/microcode/core_early.c23
-rw-r--r--arch/x86/kernel/cpu/microcode/intel_early.c23
5 files changed, 68 insertions, 9 deletions
diff --git a/arch/x86/include/asm/microcode.h b/arch/x86/include/asm/microcode.h
index 2fb20d6f7e23..9e6278c7140e 100644
--- a/arch/x86/include/asm/microcode.h
+++ b/arch/x86/include/asm/microcode.h
@@ -1,6 +1,8 @@
1#ifndef _ASM_X86_MICROCODE_H 1#ifndef _ASM_X86_MICROCODE_H
2#define _ASM_X86_MICROCODE_H 2#define _ASM_X86_MICROCODE_H
3 3
4#include <linux/earlycpio.h>
5
4#define native_rdmsr(msr, val1, val2) \ 6#define native_rdmsr(msr, val1, val2) \
5do { \ 7do { \
6 u64 __val = native_read_msr((msr)); \ 8 u64 __val = native_read_msr((msr)); \
@@ -152,6 +154,7 @@ extern void __init load_ucode_bsp(void);
152extern void load_ucode_ap(void); 154extern void load_ucode_ap(void);
153extern int __init save_microcode_in_initrd(void); 155extern int __init save_microcode_in_initrd(void);
154void reload_early_microcode(void); 156void reload_early_microcode(void);
157extern bool get_builtin_firmware(struct cpio_data *cd, const char *name);
155#else 158#else
156static inline void __init load_ucode_bsp(void) {} 159static inline void __init load_ucode_bsp(void) {}
157static inline void load_ucode_ap(void) {} 160static inline void load_ucode_ap(void) {}
@@ -160,6 +163,9 @@ static inline int __init save_microcode_in_initrd(void)
160 return 0; 163 return 0;
161} 164}
162static inline void reload_early_microcode(void) {} 165static inline void reload_early_microcode(void) {}
166static inline bool get_builtin_firmware(struct cpio_data *cd, const char *name)
167{
168 return false;
169}
163#endif 170#endif
164
165#endif /* _ASM_X86_MICROCODE_H */ 171#endif /* _ASM_X86_MICROCODE_H */
diff --git a/arch/x86/include/asm/microcode_amd.h b/arch/x86/include/asm/microcode_amd.h
index af935397e053..b8438543f340 100644
--- a/arch/x86/include/asm/microcode_amd.h
+++ b/arch/x86/include/asm/microcode_amd.h
@@ -65,12 +65,12 @@ extern enum ucode_state load_microcode_amd(int cpu, u8 family, const u8 *data, s
65extern u8 amd_ucode_patch[PATCH_MAX_SIZE]; 65extern u8 amd_ucode_patch[PATCH_MAX_SIZE];
66 66
67#ifdef CONFIG_MICROCODE_AMD_EARLY 67#ifdef CONFIG_MICROCODE_AMD_EARLY
68extern void __init load_ucode_amd_bsp(void); 68extern void __init load_ucode_amd_bsp(int family);
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); 71void reload_ucode_amd(void);
72#else 72#else
73static inline void __init load_ucode_amd_bsp(void) {} 73static inline void __init load_ucode_amd_bsp(int family) {}
74static inline void load_ucode_amd_ap(void) {} 74static inline void load_ucode_amd_ap(void) {}
75static 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) {} 76void reload_ucode_amd(void) {}
diff --git a/arch/x86/kernel/cpu/microcode/amd_early.c b/arch/x86/kernel/cpu/microcode/amd_early.c
index 737737edbd1e..9208a36d0f03 100644
--- a/arch/x86/kernel/cpu/microcode/amd_early.c
+++ b/arch/x86/kernel/cpu/microcode/amd_early.c
@@ -228,7 +228,18 @@ static void apply_ucode_in_initrd(void *ucode, size_t size, bool save_patch)
228 } 228 }
229} 229}
230 230
231void __init load_ucode_amd_bsp(void) 231static bool __init load_builtin_amd_microcode(struct cpio_data *cp, int family)
232{
233 char fw_name[36] = "amd-ucode/microcode_amd.bin";
234
235 if (family >= 0x15)
236 snprintf(fw_name, sizeof(fw_name),
237 "amd-ucode/microcode_amd_fam%.2xh.bin", family);
238
239 return get_builtin_firmware(cp, fw_name);
240}
241
242void __init load_ucode_amd_bsp(int family)
232{ 243{
233 struct cpio_data cp; 244 struct cpio_data cp;
234 void **data; 245 void **data;
@@ -243,8 +254,10 @@ void __init load_ucode_amd_bsp(void)
243#endif 254#endif
244 255
245 cp = find_ucode_in_initrd(); 256 cp = find_ucode_in_initrd();
246 if (!cp.data) 257 if (!cp.data) {
247 return; 258 if (!load_builtin_amd_microcode(&cp, family))
259 return;
260 }
248 261
249 *data = cp.data; 262 *data = cp.data;
250 *size = cp.size; 263 *size = cp.size;
diff --git a/arch/x86/kernel/cpu/microcode/core_early.c b/arch/x86/kernel/cpu/microcode/core_early.c
index a413a69cbd74..979ca78b1561 100644
--- a/arch/x86/kernel/cpu/microcode/core_early.c
+++ b/arch/x86/kernel/cpu/microcode/core_early.c
@@ -3,6 +3,7 @@
3 * 3 *
4 * Copyright (C) 2012 Fenghua Yu <fenghua.yu@intel.com> 4 * Copyright (C) 2012 Fenghua Yu <fenghua.yu@intel.com>
5 * H Peter Anvin" <hpa@zytor.com> 5 * H Peter Anvin" <hpa@zytor.com>
6 * (C) 2015 Borislav Petkov <bp@alien8.de>
6 * 7 *
7 * This driver allows to early upgrade microcode on Intel processors 8 * This driver allows to early upgrade microcode on Intel processors
8 * belonging to IA-32 family - PentiumPro, Pentium II, 9 * belonging to IA-32 family - PentiumPro, Pentium II,
@@ -17,6 +18,7 @@
17 * 2 of the License, or (at your option) any later version. 18 * 2 of the License, or (at your option) any later version.
18 */ 19 */
19#include <linux/module.h> 20#include <linux/module.h>
21#include <linux/firmware.h>
20#include <asm/microcode.h> 22#include <asm/microcode.h>
21#include <asm/microcode_intel.h> 23#include <asm/microcode_intel.h>
22#include <asm/microcode_amd.h> 24#include <asm/microcode_amd.h>
@@ -43,6 +45,25 @@ static bool __init check_loader_disabled_bsp(void)
43 return *res; 45 return *res;
44} 46}
45 47
48extern struct builtin_fw __start_builtin_fw[];
49extern struct builtin_fw __end_builtin_fw[];
50
51bool get_builtin_firmware(struct cpio_data *cd, const char *name)
52{
53#ifdef CONFIG_FW_LOADER
54 struct builtin_fw *b_fw;
55
56 for (b_fw = __start_builtin_fw; b_fw != __end_builtin_fw; b_fw++) {
57 if (!strcmp(name, b_fw->name)) {
58 cd->size = b_fw->size;
59 cd->data = b_fw->data;
60 return true;
61 }
62 }
63#endif
64 return false;
65}
66
46void __init load_ucode_bsp(void) 67void __init load_ucode_bsp(void)
47{ 68{
48 int vendor, family; 69 int vendor, family;
@@ -63,7 +84,7 @@ void __init load_ucode_bsp(void)
63 break; 84 break;
64 case X86_VENDOR_AMD: 85 case X86_VENDOR_AMD:
65 if (family >= 0x10) 86 if (family >= 0x10)
66 load_ucode_amd_bsp(); 87 load_ucode_amd_bsp(family);
67 break; 88 break;
68 default: 89 default:
69 break; 90 break;
diff --git a/arch/x86/kernel/cpu/microcode/intel_early.c b/arch/x86/kernel/cpu/microcode/intel_early.c
index 45881e92f1be..ccd474a7a59e 100644
--- a/arch/x86/kernel/cpu/microcode/intel_early.c
+++ b/arch/x86/kernel/cpu/microcode/intel_early.c
@@ -521,6 +521,23 @@ out:
521EXPORT_SYMBOL_GPL(save_mc_for_early); 521EXPORT_SYMBOL_GPL(save_mc_for_early);
522#endif 522#endif
523 523
524static bool __init load_builtin_intel_microcode(struct cpio_data *cp)
525{
526 u32 eax = 0x00000001, ebx, ecx = 0, edx;
527 int family, model, stepping;
528 char name[30];
529
530 native_cpuid(&eax, &ebx, &ecx, &edx);
531
532 family = __x86_family(eax);
533 model = x86_model(eax);
534 stepping = eax & 0xf;
535
536 sprintf(name, "intel-ucode/%02x-%02x-%02x", family, model, stepping);
537
538 return get_builtin_firmware(cp, name);
539}
540
524static __initdata char ucode_name[] = "kernel/x86/microcode/GenuineIntel.bin"; 541static __initdata char ucode_name[] = "kernel/x86/microcode/GenuineIntel.bin";
525static __init enum ucode_state 542static __init enum ucode_state
526scan_microcode(struct mc_saved_data *mc_saved_data, unsigned long *initrd, 543scan_microcode(struct mc_saved_data *mc_saved_data, unsigned long *initrd,
@@ -539,8 +556,10 @@ scan_microcode(struct mc_saved_data *mc_saved_data, unsigned long *initrd,
539 cd.size = 0; 556 cd.size = 0;
540 557
541 cd = find_cpio_data(p, (void *)start, size, &offset); 558 cd = find_cpio_data(p, (void *)start, size, &offset);
542 if (!cd.data) 559 if (!cd.data) {
543 return UCODE_ERROR; 560 if (!load_builtin_intel_microcode(&cd))
561 return UCODE_ERROR;
562 }
544 563
545 return get_matching_model_microcode(0, start, cd.data, cd.size, 564 return get_matching_model_microcode(0, start, cd.data, cd.size,
546 mc_saved_data, initrd, uci); 565 mc_saved_data, initrd, uci);