Re: [PATCH] x86: Unbreak early processor microcode loading

From: Borislav Petkov
Date: Wed Mar 18 2015 - 14:44:32 EST


On Wed, Mar 18, 2015 at 11:02:27AM +0100, Borislav Petkov wrote:
> I don't like the ifdeffery in your solution and would like to try to fix
> it in a cleaner way. Unless you come up with a better solution first.

Ok, how about this below? It is more involved but finds and loads the
microcode built-in into the kernel in the early loader which is when
you want to load microcode anyway. Only AMD for now but that should be
enough for testing.

---
From: Borislav Petkov <bp@xxxxxxx>
Date: Wed, 18 Mar 2015 19:28:56 +0100
Subject: [RFC PATCH] x86/microcode: Parse built-in microcode early

Only AMD for now, WIP.

Not-yet-signed-off-by: Borislav Petkov <bp@xxxxxxx>
---
arch/x86/include/asm/microcode.h | 8 +++++++-
arch/x86/include/asm/microcode_amd.h | 4 ++--
arch/x86/kernel/cpu/microcode/amd_early.c | 13 ++++++++++---
arch/x86/kernel/cpu/microcode/core_early.c | 23 ++++++++++++++++++++++-
4 files changed, 41 insertions(+), 7 deletions(-)

diff --git a/arch/x86/include/asm/microcode.h b/arch/x86/include/asm/microcode.h
index 2fb20d6f7e23..8924b9a65603 100644
--- a/arch/x86/include/asm/microcode.h
+++ b/arch/x86/include/asm/microcode.h
@@ -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 bool get_builtin_firmware(struct cpio_data *cd, const char *name)
+{
+ return false;
+}
#endif
-
#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
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) {}
diff --git a/arch/x86/kernel/cpu/microcode/amd_early.c b/arch/x86/kernel/cpu/microcode/amd_early.c
index 737737edbd1e..10d9068ca4f6 100644
--- a/arch/x86/kernel/cpu/microcode/amd_early.c
+++ b/arch/x86/kernel/cpu/microcode/amd_early.c
@@ -228,8 +228,9 @@ static void apply_ucode_in_initrd(void *ucode, size_t size, bool save_patch)
}
}

-void __init load_ucode_amd_bsp(void)
+void __init load_ucode_amd_bsp(int family)
{
+ char fw_name[26] = "microcode_amd.bin";
struct cpio_data cp;
void **data;
size_t *size;
@@ -243,8 +244,14 @@ void __init load_ucode_amd_bsp(void)
#endif

cp = find_ucode_in_initrd();
- if (!cp.data)
- return;
+ if (!cp.data) {
+ if (family >= 0x15)
+ snprintf(fw_name, sizeof(fw_name),
+ "microcode_amd_fam%.2xh.bin", family);
+
+ if (!get_builtin_firmware(&cp, fw_name))
+ return;
+ }

*data = cp.data;
*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..beda0ea2409e 100644
--- a/arch/x86/kernel/cpu/microcode/core_early.c
+++ b/arch/x86/kernel/cpu/microcode/core_early.c
@@ -3,6 +3,7 @@
*
* Copyright (C) 2012 Fenghua Yu <fenghua.yu@xxxxxxxxx>
* H Peter Anvin" <hpa@xxxxxxxxx>
+ * (C) 2015 Borislav Petkov <bp@xxxxxxx>
*
* 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;
--
2.3.3

--
Regards/Gruss,
Boris.

ECO tip #101: Trim your mails when you reply.
--
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/