]> git.kernelconcepts.de Git - karo-tx-linux.git/commitdiff
x86/microcode: Parse built-in microcode early
authorBorislav Petkov <bp@suse.de>
Wed, 18 Mar 2015 18:28:56 +0000 (19:28 +0100)
committerIngo Molnar <mingo@kernel.org>
Wed, 6 May 2015 09:24:53 +0000 (11:24 +0200)
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>
arch/x86/include/asm/microcode.h
arch/x86/include/asm/microcode_amd.h
arch/x86/kernel/cpu/microcode/amd_early.c
arch/x86/kernel/cpu/microcode/core_early.c
arch/x86/kernel/cpu/microcode/intel_early.c

index 2fb20d6f7e23b0ccace549901dacf89b51e9c381..9e6278c7140eac3cac2e5841002300c3b903e457 100644 (file)
@@ -1,6 +1,8 @@
 #ifndef _ASM_X86_MICROCODE_H
 #define _ASM_X86_MICROCODE_H
 
+#include <linux/earlycpio.h>
+
 #define native_rdmsr(msr, val1, val2)                  \
 do {                                                   \
        u64 __val = native_read_msr((msr));             \
@@ -152,6 +154,7 @@ extern void __init load_ucode_bsp(void);
 extern void load_ucode_ap(void);
 extern int __init save_microcode_in_initrd(void);
 void reload_early_microcode(void);
+extern bool get_builtin_firmware(struct cpio_data *cd, const char *name);
 #else
 static inline void __init load_ucode_bsp(void) {}
 static inline void load_ucode_ap(void) {}
@@ -160,6 +163,9 @@ static inline int __init save_microcode_in_initrd(void)
        return 0;
 }
 static inline void reload_early_microcode(void) {}
+static inline bool get_builtin_firmware(struct cpio_data *cd, const char *name)
+{
+       return false;
+}
 #endif
-
 #endif /* _ASM_X86_MICROCODE_H */
index af935397e053e4a504daed8c14cfc06686a08794..b8438543f340a78091e6c3063f0ac76a694c91d0 100644 (file)
@@ -65,12 +65,12 @@ extern enum ucode_state load_microcode_amd(int cpu, u8 family, const u8 *data, s
 extern u8 amd_ucode_patch[PATCH_MAX_SIZE];
 
 #ifdef CONFIG_MICROCODE_AMD_EARLY
-extern void __init load_ucode_amd_bsp(void);
+extern void __init load_ucode_amd_bsp(int family);
 extern void load_ucode_amd_ap(void);
 extern int __init save_microcode_in_initrd_amd(void);
 void reload_ucode_amd(void);
 #else
-static inline void __init load_ucode_amd_bsp(void) {}
+static inline void __init load_ucode_amd_bsp(int family) {}
 static inline void load_ucode_amd_ap(void) {}
 static inline int __init save_microcode_in_initrd_amd(void) { return -EINVAL; }
 void reload_ucode_amd(void) {}
index 737737edbd1ef5bbc478cf2b6f898f25c231ea81..9208a36d0f030571a8972793064532a9f81bf7d8 100644 (file)
@@ -228,7 +228,18 @@ static void apply_ucode_in_initrd(void *ucode, size_t size, bool save_patch)
        }
 }
 
-void __init load_ucode_amd_bsp(void)
+static bool __init load_builtin_amd_microcode(struct cpio_data *cp, int family)
+{
+       char fw_name[36] = "amd-ucode/microcode_amd.bin";
+
+       if (family >= 0x15)
+               snprintf(fw_name, sizeof(fw_name),
+                        "amd-ucode/microcode_amd_fam%.2xh.bin", family);
+
+       return get_builtin_firmware(cp, fw_name);
+}
+
+void __init load_ucode_amd_bsp(int family)
 {
        struct cpio_data cp;
        void **data;
@@ -243,8 +254,10 @@ void __init load_ucode_amd_bsp(void)
 #endif
 
        cp = find_ucode_in_initrd();
-       if (!cp.data)
-               return;
+       if (!cp.data) {
+               if (!load_builtin_amd_microcode(&cp, family))
+                       return;
+       }
 
        *data = cp.data;
        *size = cp.size;
index a413a69cbd744f2e2873434ee20b66e86fb466dd..979ca78b15612fe2ec9938c6aed0c95b65056cfb 100644 (file)
@@ -3,6 +3,7 @@
  *
  *     Copyright (C) 2012 Fenghua Yu <fenghua.yu@intel.com>
  *                        H Peter Anvin" <hpa@zytor.com>
+ *               (C) 2015 Borislav Petkov <bp@alien8.de>
  *
  *     This driver allows to early upgrade microcode on Intel processors
  *     belonging to IA-32 family - PentiumPro, Pentium II,
@@ -17,6 +18,7 @@
  *     2 of the License, or (at your option) any later version.
  */
 #include <linux/module.h>
+#include <linux/firmware.h>
 #include <asm/microcode.h>
 #include <asm/microcode_intel.h>
 #include <asm/microcode_amd.h>
@@ -43,6 +45,25 @@ static bool __init check_loader_disabled_bsp(void)
        return *res;
 }
 
+extern struct builtin_fw __start_builtin_fw[];
+extern struct builtin_fw __end_builtin_fw[];
+
+bool get_builtin_firmware(struct cpio_data *cd, const char *name)
+{
+#ifdef CONFIG_FW_LOADER
+       struct builtin_fw *b_fw;
+
+       for (b_fw = __start_builtin_fw; b_fw != __end_builtin_fw; b_fw++) {
+               if (!strcmp(name, b_fw->name)) {
+                       cd->size = b_fw->size;
+                       cd->data = b_fw->data;
+                       return true;
+               }
+       }
+#endif
+       return false;
+}
+
 void __init load_ucode_bsp(void)
 {
        int vendor, family;
@@ -63,7 +84,7 @@ void __init load_ucode_bsp(void)
                break;
        case X86_VENDOR_AMD:
                if (family >= 0x10)
-                       load_ucode_amd_bsp();
+                       load_ucode_amd_bsp(family);
                break;
        default:
                break;
index 45881e92f1bec84857ed4751e1aaf6733f69d083..ccd474a7a59eef36406103140141ee89130633d4 100644 (file)
@@ -521,6 +521,23 @@ out:
 EXPORT_SYMBOL_GPL(save_mc_for_early);
 #endif
 
+static bool __init load_builtin_intel_microcode(struct cpio_data *cp)
+{
+       u32 eax = 0x00000001, ebx, ecx = 0, edx;
+       int family, model, stepping;
+       char name[30];
+
+       native_cpuid(&eax, &ebx, &ecx, &edx);
+
+       family   = __x86_family(eax);
+       model    = x86_model(eax);
+       stepping = eax & 0xf;
+
+       sprintf(name, "intel-ucode/%02x-%02x-%02x", family, model, stepping);
+
+       return get_builtin_firmware(cp, name);
+}
+
 static __initdata char ucode_name[] = "kernel/x86/microcode/GenuineIntel.bin";
 static __init enum ucode_state
 scan_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,
        cd.size = 0;
 
        cd = find_cpio_data(p, (void *)start, size, &offset);
-       if (!cd.data)
-               return UCODE_ERROR;
+       if (!cd.data) {
+               if (!load_builtin_intel_microcode(&cd))
+                       return UCODE_ERROR;
+       }
 
        return get_matching_model_microcode(0, start, cd.data, cd.size,
                                            mc_saved_data, initrd, uci);