The following patchset adds early microcode patch loading support on
AMD systems, on top of the framework introduced by:
https://lkml.org/lkml/2012/12/21/193
V3:
* Moved early logic to microcode_amd_early.c
* Revised x86 vendor detection in microcode_core_early.c to use switch
statement.
* Added AMD blurb to Documentation/x86/early-microcode.txt
V2:
* Fixed warnings when compiling without early loading
* Picked up a typo fix [PATCH 1/4] from Boris
Borislav Petkov (1):
x86, microcode, intel: Correct typo in printk
Jacob Shin (3):
x86/microcode: vendor abstract out save_microcode_in_initrd()
x86/microcode/amd: refactor functions to prepare for early loading
microcode/x86/amd: early microcode patch loading support for AMD
Documentation/x86/early-microcode.txt | 11 +-
arch/x86/Kconfig | 14 +-
arch/x86/include/asm/microcode_amd.h | 78 +++++++++++
arch/x86/include/asm/microcode_intel.h | 2 +
arch/x86/kernel/Makefile | 1 +
arch/x86/kernel/microcode_amd.c | 133 +++++++++---------
arch/x86/kernel/microcode_amd_early.c | 222 +++++++++++++++++++++++++++++++
arch/x86/kernel/microcode_core_early.c | 49 ++++++-
arch/x86/kernel/microcode_intel_early.c | 6 +-
9 files changed, 429 insertions(+), 87 deletions(-)
create mode 100644 arch/x86/include/asm/microcode_amd.h
create mode 100644 arch/x86/kernel/microcode_amd_early.c
--
1.7.9.5
From: Borislav Petkov <[email protected]>
User-visible so correct it.
Signed-off-by: Borislav Petkov <[email protected]>
Signed-off-by: Jacob Shin <[email protected]>
---
arch/x86/kernel/microcode_intel_early.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/arch/x86/kernel/microcode_intel_early.c b/arch/x86/kernel/microcode_intel_early.c
index 2e9e128..a07f0a0 100644
--- a/arch/x86/kernel/microcode_intel_early.c
+++ b/arch/x86/kernel/microcode_intel_early.c
@@ -529,7 +529,7 @@ int save_mc_for_early(u8 *mc)
*/
ret = save_microcode(&mc_saved_data, mc_saved_tmp, mc_saved_count);
if (ret) {
- pr_err("Can not save microcode patch.\n");
+ pr_err("Cannot save microcode patch.\n");
goto out;
}
@@ -711,7 +711,7 @@ int __init save_microcode_in_initrd(void)
microcode_pointer(mc_saved, mc_saved_in_initrd, initrd_start, count);
ret = save_microcode(&mc_saved_data, mc_saved, count);
if (ret)
- pr_err("Can not save microcod patches from initrd");
+ pr_err("Cannot save microcode patches from initrd.\n");
show_saved_mc();
--
1.7.9.5
Currently save_microcode_in_initrd() is declared in vendor neutural
microcode.h file, but defined in vendor specific
microcode_intel_early.c file. Vendor abstract it out to
microcode_core_early.c with a wrapper function.
Signed-off-by: Jacob Shin <[email protected]>
---
arch/x86/include/asm/microcode_intel.h | 2 ++
arch/x86/kernel/microcode_core_early.c | 10 ++++++++++
arch/x86/kernel/microcode_intel_early.c | 2 +-
3 files changed, 13 insertions(+), 1 deletion(-)
diff --git a/arch/x86/include/asm/microcode_intel.h b/arch/x86/include/asm/microcode_intel.h
index 5356f92..87a0853 100644
--- a/arch/x86/include/asm/microcode_intel.h
+++ b/arch/x86/include/asm/microcode_intel.h
@@ -67,10 +67,12 @@ update_match_revision(struct microcode_header_intel *mc_header, int rev);
extern void __init load_ucode_intel_bsp(void);
extern void __cpuinit load_ucode_intel_ap(void);
extern void show_ucode_info_early(void);
+extern int __init save_microcode_in_initrd_intel(void);
#else
static inline __init void load_ucode_intel_bsp(void) {}
static inline __cpuinit void load_ucode_intel_ap(void) {}
static inline void show_ucode_info_early(void) {}
+static inline int __init save_microcode_in_initrd_intel(void) { return -EINVAL; }
#endif
#if defined(CONFIG_MICROCODE_INTEL_EARLY) && defined(CONFIG_HOTPLUG_CPU)
diff --git a/arch/x86/kernel/microcode_core_early.c b/arch/x86/kernel/microcode_core_early.c
index 833d51d..0d19ac5 100644
--- a/arch/x86/kernel/microcode_core_early.c
+++ b/arch/x86/kernel/microcode_core_early.c
@@ -98,3 +98,13 @@ void __cpuinit load_ucode_ap(void)
if (vendor == X86_VENDOR_INTEL && x86 >= 6)
load_ucode_intel_ap();
}
+
+int __init save_microcode_in_initrd(void)
+{
+ struct cpuinfo_x86 *c = &boot_cpu_data;
+
+ if (c->x86_vendor == X86_VENDOR_INTEL && c->x86 >= 6)
+ return save_microcode_in_initrd_intel();
+
+ return 0;
+}
diff --git a/arch/x86/kernel/microcode_intel_early.c b/arch/x86/kernel/microcode_intel_early.c
index a07f0a0..dabef95 100644
--- a/arch/x86/kernel/microcode_intel_early.c
+++ b/arch/x86/kernel/microcode_intel_early.c
@@ -699,7 +699,7 @@ static int __cpuinit apply_microcode_early(struct mc_saved_data *mc_saved_data,
* This function converts microcode patch offsets previously stored in
* mc_saved_in_initrd to pointers and stores the pointers in mc_saved_data.
*/
-int __init save_microcode_in_initrd(void)
+int __init save_microcode_in_initrd_intel(void)
{
unsigned int count = mc_saved_data.mc_saved_count;
struct microcode_intel *mc_saved[MAX_UCODE_COUNT];
--
1.7.9.5
Add early microcode patch loading support for AMD.
Signed-off-by: Jacob Shin <[email protected]>
---
Documentation/x86/early-microcode.txt | 11 +-
arch/x86/Kconfig | 14 +-
arch/x86/include/asm/microcode_amd.h | 14 ++
arch/x86/kernel/Makefile | 1 +
arch/x86/kernel/microcode_amd.c | 22 ++++
arch/x86/kernel/microcode_amd_early.c | 222 ++++++++++++++++++++++++++++++++
arch/x86/kernel/microcode_core_early.c | 43 ++++++-
7 files changed, 310 insertions(+), 17 deletions(-)
create mode 100644 arch/x86/kernel/microcode_amd_early.c
diff --git a/Documentation/x86/early-microcode.txt b/Documentation/x86/early-microcode.txt
index 4aaf0df..d62bea6 100644
--- a/Documentation/x86/early-microcode.txt
+++ b/Documentation/x86/early-microcode.txt
@@ -11,7 +11,8 @@ file and loaded to CPUs during boot time.
The format of the combined initrd image is microcode in cpio format followed by
the initrd image (maybe compressed). Kernel parses the combined initrd image
during boot time. The microcode file in cpio name space is:
-kernel/x86/microcode/GenuineIntel.bin
+on Intel: kernel/x86/microcode/GenuineIntel.bin
+on AMD : kernel/x86/microcode/AuthenticAMD.bin
During BSP boot (before SMP starts), if the kernel finds the microcode file in
the initrd file, it parses the microcode and saves matching microcode in memory.
@@ -34,10 +35,8 @@ original initrd image /boot/initrd-3.5.0.img.
mkdir initrd
cd initrd
-mkdir kernel
-mkdir kernel/x86
-mkdir kernel/x86/microcode
-cp ../microcode.bin kernel/x86/microcode/GenuineIntel.bin
-find .|cpio -oc >../ucode.cpio
+mkdir -p kernel/x86/microcode
+cp ../microcode.bin kernel/x86/microcode/GenuineIntel.bin (or AuthenticAMD.bin)
+find . | cpio -o -H newc >../ucode.cpio
cd ..
cat ucode.cpio /boot/initrd-3.5.0.img >/boot/initrd-3.5.0.ucode.img
diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
index 3a5bced..7c74ae3 100644
--- a/arch/x86/Kconfig
+++ b/arch/x86/Kconfig
@@ -1090,8 +1090,16 @@ config MICROCODE_INTEL_LIB
depends on MICROCODE_INTEL
config MICROCODE_INTEL_EARLY
+ def_bool n
+
+config MICROCODE_AMD_EARLY
+ def_bool n
+
+config MICROCODE_EARLY
bool "Early load microcode"
- depends on MICROCODE_INTEL && BLK_DEV_INITRD
+ depends on (MICROCODE_INTEL || MICROCODE_AMD) && BLK_DEV_INITRD
+ select MICROCODE_INTEL_EARLY if MICROCODE_INTEL
+ select MICROCODE_AMD_EARLY if MICROCODE_AMD
default y
help
This option provides functionality to read additional microcode data
@@ -1099,10 +1107,6 @@ config MICROCODE_INTEL_EARLY
microcode to CPU's as early as possible. No functional change if no
microcode data is glued to the initrd, therefore it's safe to say Y.
-config MICROCODE_EARLY
- def_bool y
- depends on MICROCODE_INTEL_EARLY
-
config X86_MSR
tristate "/dev/cpu/*/msr - Model-specific register support"
---help---
diff --git a/arch/x86/include/asm/microcode_amd.h b/arch/x86/include/asm/microcode_amd.h
index a57d9b7..24254aa 100644
--- a/arch/x86/include/asm/microcode_amd.h
+++ b/arch/x86/include/asm/microcode_amd.h
@@ -61,4 +61,18 @@ extern int __apply_microcode_amd(struct microcode_amd *mc_amd);
extern int apply_microcode_amd(int cpu);
extern enum ucode_state load_microcode_amd(int cpu, const u8 *data, size_t size);
+#ifdef CONFIG_MICROCODE_AMD_EARLY
+#ifdef CONFIG_X86_32
+#define MPB_MAX_SIZE PAGE_SIZE
+extern u8 __cpuinitdata amd_bsp_mpb[MPB_MAX_SIZE];
+#endif
+extern void __init load_ucode_amd_bsp(void);
+extern void __cpuinit load_ucode_amd_ap(void);
+extern int __init save_microcode_in_initrd_amd(void);
+#else
+static inline void __init load_ucode_amd_bsp(void) {}
+static inline void __cpuinit load_ucode_amd_ap(void) {}
+static inline int __init save_microcode_in_initrd_amd(void) { return -EINVAL; }
+#endif
+
#endif /* _ASM_X86_MICROCODE_AMD_H */
diff --git a/arch/x86/kernel/Makefile b/arch/x86/kernel/Makefile
index 4ce822e..612ed34 100644
--- a/arch/x86/kernel/Makefile
+++ b/arch/x86/kernel/Makefile
@@ -93,6 +93,7 @@ obj-$(CONFIG_MICROCODE_INTEL_LIB) += microcode_intel_lib.o
microcode-y := microcode_core.o
microcode-$(CONFIG_MICROCODE_INTEL) += microcode_intel.o
microcode-$(CONFIG_MICROCODE_AMD) += microcode_amd.o
+obj-$(CONFIG_MICROCODE_AMD_EARLY) += microcode_amd_early.o
obj-$(CONFIG_MICROCODE) += microcode.o
obj-$(CONFIG_X86_CHECK_BIOS_CORRUPTION) += check.o
diff --git a/arch/x86/kernel/microcode_amd.c b/arch/x86/kernel/microcode_amd.c
index 8f11f8f..47ebb1d 100644
--- a/arch/x86/kernel/microcode_amd.c
+++ b/arch/x86/kernel/microcode_amd.c
@@ -126,9 +126,20 @@ static struct ucode_patch *find_patch(unsigned int cpu)
static int collect_cpu_info_amd(int cpu, struct cpu_signature *csig)
{
struct cpuinfo_x86 *c = &cpu_data(cpu);
+ struct ucode_cpu_info *uci = ucode_cpu_info + cpu;
+ struct ucode_patch *p;
csig->sig = cpuid_eax(0x00000001);
csig->rev = c->microcode;
+
+ /*
+ * a patch could have been loaded early, set uci->mc so that
+ * mc_bp_resume() can call apply_microcode()
+ */
+ p = find_patch(cpu);
+ if (p && (p->patch_id == csig->rev))
+ uci->mc = p->data;
+
pr_info("CPU%d: patch_level=0x%08x\n", cpu, csig->rev);
return 0;
@@ -373,6 +384,17 @@ enum ucode_state load_microcode_amd(int cpu, const u8 *data, size_t size)
if (ret != UCODE_OK)
cleanup();
+#if defined(CONFIG_MICROCODE_AMD_EARLY) && defined(CONFIG_X86_32)
+ /* save BSP's matching patch for early load */
+ if (cpu_data(cpu).cpu_index == boot_cpu_data.cpu_index) {
+ struct ucode_patch *p = find_patch(cpu);
+ if (p) {
+ memset(amd_bsp_mpb, 0, MPB_MAX_SIZE);
+ memcpy(amd_bsp_mpb, p->data, min_t(u32, ksize(p->data),
+ MPB_MAX_SIZE));
+ }
+ }
+#endif
return ret;
}
diff --git a/arch/x86/kernel/microcode_amd_early.c b/arch/x86/kernel/microcode_amd_early.c
new file mode 100644
index 0000000..7e54d97
--- /dev/null
+++ b/arch/x86/kernel/microcode_amd_early.c
@@ -0,0 +1,222 @@
+/*
+ * Copyright (C) 2013 Advanced Micro Devices, Inc.
+ *
+ * Author: Jacob Shin <[email protected]>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/earlycpio.h>
+
+#include <asm/cpu.h>
+#include <asm/setup.h>
+#include <asm/microcode_amd.h>
+
+static bool ucode_loaded;
+static u32 ucode_new_rev;
+
+/*
+ * Microcode patch container file is prepended to the initrd in cpio format.
+ * See Documentation/x86/early-microcode.txt
+ */
+static __initdata char ucode_path[] = "kernel/x86/microcode/AuthenticAMD.bin";
+
+static struct cpio_data __init find_ucode_in_initrd(void)
+{
+ long offset = 0;
+ struct cpio_data cd;
+
+#ifdef CONFIG_X86_32
+ /*
+ * On 32-bit, early load occurs before paging is turned on so we need
+ * to use physical addresses.
+ */
+ if (!(read_cr0() & X86_CR0_PG)) {
+ struct boot_params *p;
+ p = (struct boot_params *)__pa_nodebug(&boot_params);
+ cd = find_cpio_data((char *)__pa_nodebug(ucode_path),
+ (void *)p->hdr.ramdisk_image, p->hdr.ramdisk_size,
+ &offset);
+ } else
+#endif
+ cd = find_cpio_data(ucode_path,
+ (void *)(boot_params.hdr.ramdisk_image + PAGE_OFFSET),
+ boot_params.hdr.ramdisk_size, &offset);
+
+ if (*(u32 *)cd.data != UCODE_MAGIC) {
+ cd.data = NULL;
+ cd.size = 0;
+ }
+
+ return cd;
+}
+
+/*
+ * Early load occurs before we can vmalloc(). So we look for the microcode
+ * patch container file in initrd, traverse equivalent cpu table, look for a
+ * matching microcode patch, and update, all in initrd memory in place.
+ * When vmalloc() is available for use later -- on 64-bit during first AP load,
+ * and on 32-bit during save_microcode_in_initrd_amd() -- we can call
+ * load_microcode_amd() to save equivalent cpu table and microcode patches in
+ * kernel heap memory.
+ */
+static void __init apply_ucode_in_initrd(void)
+{
+ struct cpio_data cd;
+ struct equiv_cpu_entry *eq;
+ u32 *header;
+ u8 *data;
+ u16 eq_id;
+ int offset, left;
+ u32 rev, dummy;
+ u32 *new_rev;
+
+#ifdef CONFIG_X86_32
+ new_rev = (u32 *)__pa_nodebug(&ucode_new_rev);
+#else
+ new_rev = &ucode_new_rev;
+#endif
+ cd = find_ucode_in_initrd();
+ if (!cd.data)
+ return;
+
+ data = cd.data;
+ left = cd.size;
+ header = (u32 *)data;
+
+ /* find equiv cpu table */
+
+ if (header[1] != UCODE_EQUIV_CPU_TABLE_TYPE || /* type */
+ header[2] == 0) /* size */
+ return;
+
+ eq = (struct equiv_cpu_entry *)(data + CONTAINER_HDR_SZ);
+ offset = header[2] + CONTAINER_HDR_SZ;
+ data += offset;
+ left -= offset;
+
+ eq_id = find_equiv_id(eq, cpuid_eax(0x00000001));
+ if (!eq_id)
+ return;
+
+ /* find ucode and update if needed */
+
+ rdmsr(MSR_AMD64_PATCH_LEVEL, rev, dummy);
+
+ while (left > 0) {
+ struct microcode_amd *mc;
+
+ header = (u32 *)data;
+ if (header[0] != UCODE_UCODE_TYPE || /* type */
+ header[1] == 0) /* size */
+ break;
+
+ mc = (struct microcode_amd *)(data + SECTION_HDR_SIZE);
+ if (eq_id == mc->hdr.processor_rev_id && rev < mc->hdr.patch_id)
+ if (__apply_microcode_amd(mc) == 0) {
+ if (!(*new_rev))
+ *new_rev = mc->hdr.patch_id;
+ break;
+ }
+
+ offset = header[1] + SECTION_HDR_SIZE;
+ data += offset;
+ left -= offset;
+ }
+}
+
+void __init load_ucode_amd_bsp(void)
+{
+ apply_ucode_in_initrd();
+}
+
+#ifdef CONFIG_X86_32
+u8 __cpuinitdata amd_bsp_mpb[MPB_MAX_SIZE];
+
+/*
+ * On 32-bit, since AP's early load occurs before paging is turned on, we
+ * cannot traverse cpu_equiv_table and pcache in kernel heap memory. So during
+ * cold boot, AP will apply_ucode_in_initrd() just like the BSP. During
+ * save_microcode_in_initrd_amd() BSP's patch is copied to amd_bsp_mpb, which
+ * is used upon resume from suspend.
+ */
+void __cpuinit load_ucode_amd_ap(void)
+{
+ struct microcode_amd *mc;
+
+ mc = (struct microcode_amd *)__pa_nodebug(amd_bsp_mpb);
+ if (mc->hdr.patch_id && mc->hdr.processor_rev_id)
+ __apply_microcode_amd(mc);
+ else
+ apply_ucode_in_initrd();
+}
+
+static void __init collect_cpu_sig_on_bsp(void *arg)
+{
+ unsigned int cpu = smp_processor_id();
+ struct ucode_cpu_info *uci = ucode_cpu_info + cpu;
+ uci->cpu_sig.sig = cpuid_eax(0x00000001);
+}
+#else
+static void __cpuinit collect_cpu_info_amd_early(struct cpuinfo_x86 *c,
+ struct ucode_cpu_info *uci)
+{
+ u32 rev, eax;
+
+ rdmsr(MSR_AMD64_PATCH_LEVEL, rev, eax);
+ eax = cpuid_eax(0x00000001);
+
+ uci->cpu_sig.sig = eax;
+ uci->cpu_sig.rev = rev;
+ c->microcode = rev;
+ c->x86 = ((eax >> 8) & 0xf) + ((eax >> 20) & 0xff);
+}
+
+void __cpuinit load_ucode_amd_ap(void)
+{
+ unsigned int cpu = smp_processor_id();
+
+ collect_cpu_info_amd_early(&cpu_data(cpu), ucode_cpu_info + cpu);
+
+ if (cpu && !ucode_loaded) {
+ struct cpio_data cd = find_ucode_in_initrd();
+ if (load_microcode_amd(0, cd.data, cd.size) != UCODE_OK)
+ return;
+ ucode_loaded = true;
+ }
+
+ apply_microcode_amd(cpu);
+}
+#endif
+
+int __init save_microcode_in_initrd_amd(void)
+{
+ enum ucode_state ret;
+ struct cpio_data cd;
+#ifdef CONFIG_X86_32
+ unsigned int bsp = boot_cpu_data.cpu_index;
+ struct ucode_cpu_info *uci = ucode_cpu_info + bsp;
+
+ if (!uci->cpu_sig.sig)
+ smp_call_function_single(bsp, collect_cpu_sig_on_bsp, NULL, 1);
+#endif
+ if (ucode_new_rev)
+ pr_info("microcode: updated early to new patch_level=0x%08x\n",
+ ucode_new_rev);
+
+ if (ucode_loaded)
+ return 0;
+
+ cd = find_ucode_in_initrd();
+ if (!cd.data)
+ return -EINVAL;
+
+ ret = load_microcode_amd(0, cd.data, cd.size);
+ if (ret != UCODE_OK)
+ return -EINVAL;
+
+ ucode_loaded = true;
+ return 0;
+}
diff --git a/arch/x86/kernel/microcode_core_early.c b/arch/x86/kernel/microcode_core_early.c
index 0d19ac5..86119f6 100644
--- a/arch/x86/kernel/microcode_core_early.c
+++ b/arch/x86/kernel/microcode_core_early.c
@@ -18,6 +18,7 @@
*/
#include <linux/module.h>
#include <asm/microcode_intel.h>
+#include <asm/microcode_amd.h>
#include <asm/processor.h>
#define QCHAR(a, b, c, d) ((a) + ((b) << 8) + ((c) << 16) + ((d) << 24))
@@ -81,8 +82,18 @@ void __init load_ucode_bsp(void)
vendor = x86_vendor();
x86 = x86_family();
- if (vendor == X86_VENDOR_INTEL && x86 >= 6)
- load_ucode_intel_bsp();
+ switch (vendor) {
+ case X86_VENDOR_INTEL:
+ if (x86 >= 6)
+ load_ucode_intel_bsp();
+ break;
+ case X86_VENDOR_AMD:
+ if (x86 >= 0x10)
+ load_ucode_amd_bsp();
+ break;
+ default:
+ break;
+ }
}
void __cpuinit load_ucode_ap(void)
@@ -95,16 +106,36 @@ void __cpuinit load_ucode_ap(void)
vendor = x86_vendor();
x86 = x86_family();
- if (vendor == X86_VENDOR_INTEL && x86 >= 6)
- load_ucode_intel_ap();
+ switch (vendor) {
+ case X86_VENDOR_INTEL:
+ if (x86 >= 6)
+ load_ucode_intel_ap();
+ break;
+ case X86_VENDOR_AMD:
+ if (x86 >= 0x10)
+ load_ucode_amd_ap();
+ break;
+ default:
+ break;
+ }
}
int __init save_microcode_in_initrd(void)
{
struct cpuinfo_x86 *c = &boot_cpu_data;
- if (c->x86_vendor == X86_VENDOR_INTEL && c->x86 >= 6)
- return save_microcode_in_initrd_intel();
+ switch (c->x86_vendor) {
+ case X86_VENDOR_INTEL:
+ if (c->x86 >= 6)
+ save_microcode_in_initrd_intel();
+ break;
+ case X86_VENDOR_AMD:
+ if (c->x86 >= 0x10)
+ save_microcode_in_initrd_amd();
+ break;
+ default:
+ break;
+ }
return 0;
}
--
1.7.9.5
In preparation work for early loading, refactor some common functions
that will be shared, and move some struct defines to a common header file.
Signed-off-by: Jacob Shin <[email protected]>
---
arch/x86/include/asm/microcode_amd.h | 64 ++++++++++++++++++++
arch/x86/kernel/microcode_amd.c | 111 +++++++++++++---------------------
2 files changed, 106 insertions(+), 69 deletions(-)
create mode 100644 arch/x86/include/asm/microcode_amd.h
diff --git a/arch/x86/include/asm/microcode_amd.h b/arch/x86/include/asm/microcode_amd.h
new file mode 100644
index 0000000..a57d9b7
--- /dev/null
+++ b/arch/x86/include/asm/microcode_amd.h
@@ -0,0 +1,64 @@
+#ifndef _ASM_X86_MICROCODE_AMD_H
+#define _ASM_X86_MICROCODE_AMD_H
+
+#include <asm/microcode.h>
+
+#define UCODE_MAGIC 0x00414d44
+#define UCODE_EQUIV_CPU_TABLE_TYPE 0x00000000
+#define UCODE_UCODE_TYPE 0x00000001
+
+#define SECTION_HDR_SIZE 8
+#define CONTAINER_HDR_SZ 12
+
+struct equiv_cpu_entry {
+ u32 installed_cpu;
+ u32 fixed_errata_mask;
+ u32 fixed_errata_compare;
+ u16 equiv_cpu;
+ u16 res;
+} __attribute__((packed));
+
+struct microcode_header_amd {
+ u32 data_code;
+ u32 patch_id;
+ u16 mc_patch_data_id;
+ u8 mc_patch_data_len;
+ u8 init_flag;
+ u32 mc_patch_data_checksum;
+ u32 nb_dev_id;
+ u32 sb_dev_id;
+ u16 processor_rev_id;
+ u8 nb_rev_id;
+ u8 sb_rev_id;
+ u8 bios_api_rev;
+ u8 reserved1[3];
+ u32 match_reg[8];
+} __attribute__((packed));
+
+struct microcode_amd {
+ struct microcode_header_amd hdr;
+ unsigned int mpb[0];
+};
+
+static inline u16 find_equiv_id(struct equiv_cpu_entry *equiv_cpu_table,
+ unsigned int sig)
+{
+ int i = 0;
+
+ if (!equiv_cpu_table)
+ return 0;
+
+ while (equiv_cpu_table[i].installed_cpu != 0) {
+ if (sig == equiv_cpu_table[i].installed_cpu)
+ return equiv_cpu_table[i].equiv_cpu;
+
+ i++;
+ }
+ return 0;
+}
+
+extern int __apply_microcode_amd(struct microcode_amd *mc_amd);
+extern int apply_microcode_amd(int cpu);
+extern enum ucode_state load_microcode_amd(int cpu, const u8 *data, size_t size);
+
+#endif /* _ASM_X86_MICROCODE_AMD_H */
diff --git a/arch/x86/kernel/microcode_amd.c b/arch/x86/kernel/microcode_amd.c
index efdec7c..8f11f8f 100644
--- a/arch/x86/kernel/microcode_amd.c
+++ b/arch/x86/kernel/microcode_amd.c
@@ -31,48 +31,12 @@
#include <asm/microcode.h>
#include <asm/processor.h>
#include <asm/msr.h>
+#include <asm/microcode_amd.h>
MODULE_DESCRIPTION("AMD Microcode Update Driver");
MODULE_AUTHOR("Peter Oruba");
MODULE_LICENSE("GPL v2");
-#define UCODE_MAGIC 0x00414d44
-#define UCODE_EQUIV_CPU_TABLE_TYPE 0x00000000
-#define UCODE_UCODE_TYPE 0x00000001
-
-struct equiv_cpu_entry {
- u32 installed_cpu;
- u32 fixed_errata_mask;
- u32 fixed_errata_compare;
- u16 equiv_cpu;
- u16 res;
-} __attribute__((packed));
-
-struct microcode_header_amd {
- u32 data_code;
- u32 patch_id;
- u16 mc_patch_data_id;
- u8 mc_patch_data_len;
- u8 init_flag;
- u32 mc_patch_data_checksum;
- u32 nb_dev_id;
- u32 sb_dev_id;
- u16 processor_rev_id;
- u8 nb_rev_id;
- u8 sb_rev_id;
- u8 bios_api_rev;
- u8 reserved1[3];
- u32 match_reg[8];
-} __attribute__((packed));
-
-struct microcode_amd {
- struct microcode_header_amd hdr;
- unsigned int mpb[0];
-};
-
-#define SECTION_HDR_SIZE 8
-#define CONTAINER_HDR_SZ 12
-
static struct equiv_cpu_entry *equiv_cpu_table;
struct ucode_patch {
@@ -84,21 +48,10 @@ struct ucode_patch {
static LIST_HEAD(pcache);
-static u16 find_equiv_id(unsigned int cpu)
+static u16 __find_equiv_id(unsigned int cpu)
{
struct ucode_cpu_info *uci = ucode_cpu_info + cpu;
- int i = 0;
-
- if (!equiv_cpu_table)
- return 0;
-
- while (equiv_cpu_table[i].installed_cpu != 0) {
- if (uci->cpu_sig.sig == equiv_cpu_table[i].installed_cpu)
- return equiv_cpu_table[i].equiv_cpu;
-
- i++;
- }
- return 0;
+ return find_equiv_id(equiv_cpu_table, uci->cpu_sig.sig);
}
static u32 find_cpu_family_by_equiv_cpu(u16 equiv_cpu)
@@ -163,7 +116,7 @@ static struct ucode_patch *find_patch(unsigned int cpu)
{
u16 equiv_id;
- equiv_id = find_equiv_id(cpu);
+ equiv_id = __find_equiv_id(cpu);
if (!equiv_id)
return NULL;
@@ -215,7 +168,21 @@ static unsigned int verify_patch_size(int cpu, u32 patch_size,
return patch_size;
}
-static int apply_microcode_amd(int cpu)
+int __apply_microcode_amd(struct microcode_amd *mc_amd)
+{
+ u32 rev, dummy;
+
+ wrmsrl(MSR_AMD64_PATCH_LOADER, (u64)(long)&mc_amd->hdr.data_code);
+
+ /* verify patch application was successful */
+ rdmsr(MSR_AMD64_PATCH_LEVEL, rev, dummy);
+ if (rev != mc_amd->hdr.patch_id)
+ return -1;
+
+ return 0;
+}
+
+int apply_microcode_amd(int cpu)
{
struct cpuinfo_x86 *c = &cpu_data(cpu);
struct microcode_amd *mc_amd;
@@ -242,19 +209,15 @@ static int apply_microcode_amd(int cpu)
return 0;
}
- wrmsrl(MSR_AMD64_PATCH_LOADER, (u64)(long)&mc_amd->hdr.data_code);
-
- /* verify patch application was successful */
- rdmsr(MSR_AMD64_PATCH_LEVEL, rev, dummy);
- if (rev != mc_amd->hdr.patch_id) {
+ if (__apply_microcode_amd(mc_amd))
pr_err("CPU%d: update failed for patch_level=0x%08x\n",
- cpu, mc_amd->hdr.patch_id);
- return -1;
- }
+ cpu, mc_amd->hdr.patch_id);
+ else
+ pr_info("CPU%d: new patch_level=0x%08x\n", cpu,
+ mc_amd->hdr.patch_id);
- pr_info("CPU%d: new patch_level=0x%08x\n", cpu, rev);
- uci->cpu_sig.rev = rev;
- c->microcode = rev;
+ uci->cpu_sig.rev = mc_amd->hdr.patch_id;
+ c->microcode = mc_amd->hdr.patch_id;
return 0;
}
@@ -364,7 +327,7 @@ static int verify_and_add_patch(unsigned int cpu, u8 *fw, unsigned int leftover)
return crnt_size;
}
-static enum ucode_state load_microcode_amd(int cpu, const u8 *data, size_t size)
+static enum ucode_state __load_microcode_amd(int cpu, const u8 *data, size_t size)
{
enum ucode_state ret = UCODE_ERROR;
unsigned int leftover;
@@ -398,6 +361,21 @@ static enum ucode_state load_microcode_amd(int cpu, const u8 *data, size_t size)
return UCODE_OK;
}
+enum ucode_state load_microcode_amd(int cpu, const u8 *data, size_t size)
+{
+ enum ucode_state ret;
+
+ /* free old equiv table */
+ free_equiv_cpu_table();
+
+ ret = __load_microcode_amd(cpu, data, size);
+
+ if (ret != UCODE_OK)
+ cleanup();
+
+ return ret;
+}
+
/*
* AMD microcode firmware naming convention, up to family 15h they are in
* the legacy file:
@@ -440,12 +418,7 @@ static enum ucode_state request_microcode_amd(int cpu, struct device *device,
goto fw_release;
}
- /* free old equiv table */
- free_equiv_cpu_table();
-
ret = load_microcode_amd(cpu, fw->data, fw->size);
- if (ret != UCODE_OK)
- cleanup();
fw_release:
release_firmware(fw);
--
1.7.9.5
Commit-ID: 83b325f1b4d00035494bc18a7a131b2197b3c718
Gitweb: http://git.kernel.org/tip/83b325f1b4d00035494bc18a7a131b2197b3c718
Author: Borislav Petkov <[email protected]>
AuthorDate: Thu, 30 May 2013 14:09:16 -0500
Committer: H. Peter Anvin <[email protected]>
CommitDate: Thu, 30 May 2013 20:19:25 -0700
x86, microcode, intel: Correct typo in printk
User-visible so correct it.
Signed-off-by: Borislav Petkov <[email protected]>
Link: http://lkml.kernel.org/r/[email protected]
Signed-off-by: Jacob Shin <[email protected]>
Signed-off-by: H. Peter Anvin <[email protected]>
Cc: Fenghua Yu <[email protected]>
---
arch/x86/kernel/microcode_intel_early.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/arch/x86/kernel/microcode_intel_early.c b/arch/x86/kernel/microcode_intel_early.c
index 2e9e128..a07f0a0 100644
--- a/arch/x86/kernel/microcode_intel_early.c
+++ b/arch/x86/kernel/microcode_intel_early.c
@@ -529,7 +529,7 @@ int save_mc_for_early(u8 *mc)
*/
ret = save_microcode(&mc_saved_data, mc_saved_tmp, mc_saved_count);
if (ret) {
- pr_err("Can not save microcode patch.\n");
+ pr_err("Cannot save microcode patch.\n");
goto out;
}
@@ -711,7 +711,7 @@ int __init save_microcode_in_initrd(void)
microcode_pointer(mc_saved, mc_saved_in_initrd, initrd_start, count);
ret = save_microcode(&mc_saved_data, mc_saved, count);
if (ret)
- pr_err("Can not save microcod patches from initrd");
+ pr_err("Cannot save microcode patches from initrd.\n");
show_saved_mc();
Commit-ID: f2b3ee820a9f2368d7f8842ad7da062dfe86e199
Gitweb: http://git.kernel.org/tip/f2b3ee820a9f2368d7f8842ad7da062dfe86e199
Author: Jacob Shin <[email protected]>
AuthorDate: Thu, 30 May 2013 14:09:17 -0500
Committer: H. Peter Anvin <[email protected]>
CommitDate: Thu, 30 May 2013 20:19:25 -0700
x86, microcode: Vendor abstract out save_microcode_in_initrd()
Currently save_microcode_in_initrd() is declared in vendor neutural
microcode.h file, but defined in vendor specific
microcode_intel_early.c file. Vendor abstract it out to
microcode_core_early.c with a wrapper function.
Signed-off-by: Jacob Shin <[email protected]>
Link: http://lkml.kernel.org/r/[email protected]
Signed-off-by: H. Peter Anvin <[email protected]>
Cc: Fenghua Yu <[email protected]>
---
arch/x86/include/asm/microcode_intel.h | 2 ++
arch/x86/kernel/microcode_core_early.c | 10 ++++++++++
arch/x86/kernel/microcode_intel_early.c | 2 +-
3 files changed, 13 insertions(+), 1 deletion(-)
diff --git a/arch/x86/include/asm/microcode_intel.h b/arch/x86/include/asm/microcode_intel.h
index 5356f92..87a0853 100644
--- a/arch/x86/include/asm/microcode_intel.h
+++ b/arch/x86/include/asm/microcode_intel.h
@@ -67,10 +67,12 @@ update_match_revision(struct microcode_header_intel *mc_header, int rev);
extern void __init load_ucode_intel_bsp(void);
extern void __cpuinit load_ucode_intel_ap(void);
extern void show_ucode_info_early(void);
+extern int __init save_microcode_in_initrd_intel(void);
#else
static inline __init void load_ucode_intel_bsp(void) {}
static inline __cpuinit void load_ucode_intel_ap(void) {}
static inline void show_ucode_info_early(void) {}
+static inline int __init save_microcode_in_initrd_intel(void) { return -EINVAL; }
#endif
#if defined(CONFIG_MICROCODE_INTEL_EARLY) && defined(CONFIG_HOTPLUG_CPU)
diff --git a/arch/x86/kernel/microcode_core_early.c b/arch/x86/kernel/microcode_core_early.c
index 833d51d..0d19ac5 100644
--- a/arch/x86/kernel/microcode_core_early.c
+++ b/arch/x86/kernel/microcode_core_early.c
@@ -98,3 +98,13 @@ void __cpuinit load_ucode_ap(void)
if (vendor == X86_VENDOR_INTEL && x86 >= 6)
load_ucode_intel_ap();
}
+
+int __init save_microcode_in_initrd(void)
+{
+ struct cpuinfo_x86 *c = &boot_cpu_data;
+
+ if (c->x86_vendor == X86_VENDOR_INTEL && c->x86 >= 6)
+ return save_microcode_in_initrd_intel();
+
+ return 0;
+}
diff --git a/arch/x86/kernel/microcode_intel_early.c b/arch/x86/kernel/microcode_intel_early.c
index a07f0a0..dabef95 100644
--- a/arch/x86/kernel/microcode_intel_early.c
+++ b/arch/x86/kernel/microcode_intel_early.c
@@ -699,7 +699,7 @@ static int __cpuinit apply_microcode_early(struct mc_saved_data *mc_saved_data,
* This function converts microcode patch offsets previously stored in
* mc_saved_in_initrd to pointers and stores the pointers in mc_saved_data.
*/
-int __init save_microcode_in_initrd(void)
+int __init save_microcode_in_initrd_intel(void)
{
unsigned int count = mc_saved_data.mc_saved_count;
struct microcode_intel *mc_saved[MAX_UCODE_COUNT];
Commit-ID: a76096a6571d5389376753c2e18b30a9791fa072
Gitweb: http://git.kernel.org/tip/a76096a6571d5389376753c2e18b30a9791fa072
Author: Jacob Shin <[email protected]>
AuthorDate: Thu, 30 May 2013 14:09:18 -0500
Committer: H. Peter Anvin <[email protected]>
CommitDate: Thu, 30 May 2013 20:19:25 -0700
x86, microcode, amd: Refactor functions to prepare for early loading
In preparation work for early loading, refactor some common functions
that will be shared, and move some struct defines to a common header file.
Signed-off-by: Jacob Shin <[email protected]>
Link: http://lkml.kernel.org/r/[email protected]
Signed-off-by: H. Peter Anvin <[email protected]>
Cc: Fenghua Yu <[email protected]>
---
arch/x86/include/asm/microcode_amd.h | 64 ++++++++++++++++++++
arch/x86/kernel/microcode_amd.c | 111 +++++++++++++----------------------
2 files changed, 106 insertions(+), 69 deletions(-)
diff --git a/arch/x86/include/asm/microcode_amd.h b/arch/x86/include/asm/microcode_amd.h
new file mode 100644
index 0000000..a57d9b7
--- /dev/null
+++ b/arch/x86/include/asm/microcode_amd.h
@@ -0,0 +1,64 @@
+#ifndef _ASM_X86_MICROCODE_AMD_H
+#define _ASM_X86_MICROCODE_AMD_H
+
+#include <asm/microcode.h>
+
+#define UCODE_MAGIC 0x00414d44
+#define UCODE_EQUIV_CPU_TABLE_TYPE 0x00000000
+#define UCODE_UCODE_TYPE 0x00000001
+
+#define SECTION_HDR_SIZE 8
+#define CONTAINER_HDR_SZ 12
+
+struct equiv_cpu_entry {
+ u32 installed_cpu;
+ u32 fixed_errata_mask;
+ u32 fixed_errata_compare;
+ u16 equiv_cpu;
+ u16 res;
+} __attribute__((packed));
+
+struct microcode_header_amd {
+ u32 data_code;
+ u32 patch_id;
+ u16 mc_patch_data_id;
+ u8 mc_patch_data_len;
+ u8 init_flag;
+ u32 mc_patch_data_checksum;
+ u32 nb_dev_id;
+ u32 sb_dev_id;
+ u16 processor_rev_id;
+ u8 nb_rev_id;
+ u8 sb_rev_id;
+ u8 bios_api_rev;
+ u8 reserved1[3];
+ u32 match_reg[8];
+} __attribute__((packed));
+
+struct microcode_amd {
+ struct microcode_header_amd hdr;
+ unsigned int mpb[0];
+};
+
+static inline u16 find_equiv_id(struct equiv_cpu_entry *equiv_cpu_table,
+ unsigned int sig)
+{
+ int i = 0;
+
+ if (!equiv_cpu_table)
+ return 0;
+
+ while (equiv_cpu_table[i].installed_cpu != 0) {
+ if (sig == equiv_cpu_table[i].installed_cpu)
+ return equiv_cpu_table[i].equiv_cpu;
+
+ i++;
+ }
+ return 0;
+}
+
+extern int __apply_microcode_amd(struct microcode_amd *mc_amd);
+extern int apply_microcode_amd(int cpu);
+extern enum ucode_state load_microcode_amd(int cpu, const u8 *data, size_t size);
+
+#endif /* _ASM_X86_MICROCODE_AMD_H */
diff --git a/arch/x86/kernel/microcode_amd.c b/arch/x86/kernel/microcode_amd.c
index efdec7c..8f11f8f 100644
--- a/arch/x86/kernel/microcode_amd.c
+++ b/arch/x86/kernel/microcode_amd.c
@@ -31,48 +31,12 @@
#include <asm/microcode.h>
#include <asm/processor.h>
#include <asm/msr.h>
+#include <asm/microcode_amd.h>
MODULE_DESCRIPTION("AMD Microcode Update Driver");
MODULE_AUTHOR("Peter Oruba");
MODULE_LICENSE("GPL v2");
-#define UCODE_MAGIC 0x00414d44
-#define UCODE_EQUIV_CPU_TABLE_TYPE 0x00000000
-#define UCODE_UCODE_TYPE 0x00000001
-
-struct equiv_cpu_entry {
- u32 installed_cpu;
- u32 fixed_errata_mask;
- u32 fixed_errata_compare;
- u16 equiv_cpu;
- u16 res;
-} __attribute__((packed));
-
-struct microcode_header_amd {
- u32 data_code;
- u32 patch_id;
- u16 mc_patch_data_id;
- u8 mc_patch_data_len;
- u8 init_flag;
- u32 mc_patch_data_checksum;
- u32 nb_dev_id;
- u32 sb_dev_id;
- u16 processor_rev_id;
- u8 nb_rev_id;
- u8 sb_rev_id;
- u8 bios_api_rev;
- u8 reserved1[3];
- u32 match_reg[8];
-} __attribute__((packed));
-
-struct microcode_amd {
- struct microcode_header_amd hdr;
- unsigned int mpb[0];
-};
-
-#define SECTION_HDR_SIZE 8
-#define CONTAINER_HDR_SZ 12
-
static struct equiv_cpu_entry *equiv_cpu_table;
struct ucode_patch {
@@ -84,21 +48,10 @@ struct ucode_patch {
static LIST_HEAD(pcache);
-static u16 find_equiv_id(unsigned int cpu)
+static u16 __find_equiv_id(unsigned int cpu)
{
struct ucode_cpu_info *uci = ucode_cpu_info + cpu;
- int i = 0;
-
- if (!equiv_cpu_table)
- return 0;
-
- while (equiv_cpu_table[i].installed_cpu != 0) {
- if (uci->cpu_sig.sig == equiv_cpu_table[i].installed_cpu)
- return equiv_cpu_table[i].equiv_cpu;
-
- i++;
- }
- return 0;
+ return find_equiv_id(equiv_cpu_table, uci->cpu_sig.sig);
}
static u32 find_cpu_family_by_equiv_cpu(u16 equiv_cpu)
@@ -163,7 +116,7 @@ static struct ucode_patch *find_patch(unsigned int cpu)
{
u16 equiv_id;
- equiv_id = find_equiv_id(cpu);
+ equiv_id = __find_equiv_id(cpu);
if (!equiv_id)
return NULL;
@@ -215,7 +168,21 @@ static unsigned int verify_patch_size(int cpu, u32 patch_size,
return patch_size;
}
-static int apply_microcode_amd(int cpu)
+int __apply_microcode_amd(struct microcode_amd *mc_amd)
+{
+ u32 rev, dummy;
+
+ wrmsrl(MSR_AMD64_PATCH_LOADER, (u64)(long)&mc_amd->hdr.data_code);
+
+ /* verify patch application was successful */
+ rdmsr(MSR_AMD64_PATCH_LEVEL, rev, dummy);
+ if (rev != mc_amd->hdr.patch_id)
+ return -1;
+
+ return 0;
+}
+
+int apply_microcode_amd(int cpu)
{
struct cpuinfo_x86 *c = &cpu_data(cpu);
struct microcode_amd *mc_amd;
@@ -242,19 +209,15 @@ static int apply_microcode_amd(int cpu)
return 0;
}
- wrmsrl(MSR_AMD64_PATCH_LOADER, (u64)(long)&mc_amd->hdr.data_code);
-
- /* verify patch application was successful */
- rdmsr(MSR_AMD64_PATCH_LEVEL, rev, dummy);
- if (rev != mc_amd->hdr.patch_id) {
+ if (__apply_microcode_amd(mc_amd))
pr_err("CPU%d: update failed for patch_level=0x%08x\n",
- cpu, mc_amd->hdr.patch_id);
- return -1;
- }
+ cpu, mc_amd->hdr.patch_id);
+ else
+ pr_info("CPU%d: new patch_level=0x%08x\n", cpu,
+ mc_amd->hdr.patch_id);
- pr_info("CPU%d: new patch_level=0x%08x\n", cpu, rev);
- uci->cpu_sig.rev = rev;
- c->microcode = rev;
+ uci->cpu_sig.rev = mc_amd->hdr.patch_id;
+ c->microcode = mc_amd->hdr.patch_id;
return 0;
}
@@ -364,7 +327,7 @@ static int verify_and_add_patch(unsigned int cpu, u8 *fw, unsigned int leftover)
return crnt_size;
}
-static enum ucode_state load_microcode_amd(int cpu, const u8 *data, size_t size)
+static enum ucode_state __load_microcode_amd(int cpu, const u8 *data, size_t size)
{
enum ucode_state ret = UCODE_ERROR;
unsigned int leftover;
@@ -398,6 +361,21 @@ static enum ucode_state load_microcode_amd(int cpu, const u8 *data, size_t size)
return UCODE_OK;
}
+enum ucode_state load_microcode_amd(int cpu, const u8 *data, size_t size)
+{
+ enum ucode_state ret;
+
+ /* free old equiv table */
+ free_equiv_cpu_table();
+
+ ret = __load_microcode_amd(cpu, data, size);
+
+ if (ret != UCODE_OK)
+ cleanup();
+
+ return ret;
+}
+
/*
* AMD microcode firmware naming convention, up to family 15h they are in
* the legacy file:
@@ -440,12 +418,7 @@ static enum ucode_state request_microcode_amd(int cpu, struct device *device,
goto fw_release;
}
- /* free old equiv table */
- free_equiv_cpu_table();
-
ret = load_microcode_amd(cpu, fw->data, fw->size);
- if (ret != UCODE_OK)
- cleanup();
fw_release:
release_firmware(fw);
Commit-ID: 757885e94a22bcc82beb9b1445c95218cb20ceab
Gitweb: http://git.kernel.org/tip/757885e94a22bcc82beb9b1445c95218cb20ceab
Author: Jacob Shin <[email protected]>
AuthorDate: Thu, 30 May 2013 14:09:19 -0500
Committer: H. Peter Anvin <[email protected]>
CommitDate: Thu, 30 May 2013 20:19:25 -0700
x86, microcode, amd: Early microcode patch loading support for AMD
Add early microcode patch loading support for AMD.
Signed-off-by: Jacob Shin <[email protected]>
Link: http://lkml.kernel.org/r/[email protected]
Signed-off-by: H. Peter Anvin <[email protected]>
Cc: Fenghua Yu <[email protected]>
---
Documentation/x86/early-microcode.txt | 11 +-
arch/x86/Kconfig | 14 ++-
arch/x86/include/asm/microcode_amd.h | 14 +++
arch/x86/kernel/Makefile | 1 +
arch/x86/kernel/microcode_amd.c | 22 ++++
arch/x86/kernel/microcode_amd_early.c | 222 +++++++++++++++++++++++++++++++++
arch/x86/kernel/microcode_core_early.c | 43 ++++++-
7 files changed, 310 insertions(+), 17 deletions(-)
diff --git a/Documentation/x86/early-microcode.txt b/Documentation/x86/early-microcode.txt
index 4aaf0df..d62bea6 100644
--- a/Documentation/x86/early-microcode.txt
+++ b/Documentation/x86/early-microcode.txt
@@ -11,7 +11,8 @@ file and loaded to CPUs during boot time.
The format of the combined initrd image is microcode in cpio format followed by
the initrd image (maybe compressed). Kernel parses the combined initrd image
during boot time. The microcode file in cpio name space is:
-kernel/x86/microcode/GenuineIntel.bin
+on Intel: kernel/x86/microcode/GenuineIntel.bin
+on AMD : kernel/x86/microcode/AuthenticAMD.bin
During BSP boot (before SMP starts), if the kernel finds the microcode file in
the initrd file, it parses the microcode and saves matching microcode in memory.
@@ -34,10 +35,8 @@ original initrd image /boot/initrd-3.5.0.img.
mkdir initrd
cd initrd
-mkdir kernel
-mkdir kernel/x86
-mkdir kernel/x86/microcode
-cp ../microcode.bin kernel/x86/microcode/GenuineIntel.bin
-find .|cpio -oc >../ucode.cpio
+mkdir -p kernel/x86/microcode
+cp ../microcode.bin kernel/x86/microcode/GenuineIntel.bin (or AuthenticAMD.bin)
+find . | cpio -o -H newc >../ucode.cpio
cd ..
cat ucode.cpio /boot/initrd-3.5.0.img >/boot/initrd-3.5.0.ucode.img
diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
index 685692c..28dba52 100644
--- a/arch/x86/Kconfig
+++ b/arch/x86/Kconfig
@@ -1058,8 +1058,16 @@ config MICROCODE_INTEL_LIB
depends on MICROCODE_INTEL
config MICROCODE_INTEL_EARLY
+ def_bool n
+
+config MICROCODE_AMD_EARLY
+ def_bool n
+
+config MICROCODE_EARLY
bool "Early load microcode"
- depends on MICROCODE_INTEL && BLK_DEV_INITRD
+ depends on (MICROCODE_INTEL || MICROCODE_AMD) && BLK_DEV_INITRD
+ select MICROCODE_INTEL_EARLY if MICROCODE_INTEL
+ select MICROCODE_AMD_EARLY if MICROCODE_AMD
default y
help
This option provides functionality to read additional microcode data
@@ -1067,10 +1075,6 @@ config MICROCODE_INTEL_EARLY
microcode to CPU's as early as possible. No functional change if no
microcode data is glued to the initrd, therefore it's safe to say Y.
-config MICROCODE_EARLY
- def_bool y
- depends on MICROCODE_INTEL_EARLY
-
config X86_MSR
tristate "/dev/cpu/*/msr - Model-specific register support"
---help---
diff --git a/arch/x86/include/asm/microcode_amd.h b/arch/x86/include/asm/microcode_amd.h
index a57d9b7..24254aa 100644
--- a/arch/x86/include/asm/microcode_amd.h
+++ b/arch/x86/include/asm/microcode_amd.h
@@ -61,4 +61,18 @@ extern int __apply_microcode_amd(struct microcode_amd *mc_amd);
extern int apply_microcode_amd(int cpu);
extern enum ucode_state load_microcode_amd(int cpu, const u8 *data, size_t size);
+#ifdef CONFIG_MICROCODE_AMD_EARLY
+#ifdef CONFIG_X86_32
+#define MPB_MAX_SIZE PAGE_SIZE
+extern u8 __cpuinitdata amd_bsp_mpb[MPB_MAX_SIZE];
+#endif
+extern void __init load_ucode_amd_bsp(void);
+extern void __cpuinit load_ucode_amd_ap(void);
+extern int __init save_microcode_in_initrd_amd(void);
+#else
+static inline void __init load_ucode_amd_bsp(void) {}
+static inline void __cpuinit load_ucode_amd_ap(void) {}
+static inline int __init save_microcode_in_initrd_amd(void) { return -EINVAL; }
+#endif
+
#endif /* _ASM_X86_MICROCODE_AMD_H */
diff --git a/arch/x86/kernel/Makefile b/arch/x86/kernel/Makefile
index 7bd3bd3..6c3fcea 100644
--- a/arch/x86/kernel/Makefile
+++ b/arch/x86/kernel/Makefile
@@ -93,6 +93,7 @@ obj-$(CONFIG_MICROCODE_INTEL_LIB) += microcode_intel_lib.o
microcode-y := microcode_core.o
microcode-$(CONFIG_MICROCODE_INTEL) += microcode_intel.o
microcode-$(CONFIG_MICROCODE_AMD) += microcode_amd.o
+obj-$(CONFIG_MICROCODE_AMD_EARLY) += microcode_amd_early.o
obj-$(CONFIG_MICROCODE) += microcode.o
obj-$(CONFIG_X86_CHECK_BIOS_CORRUPTION) += check.o
diff --git a/arch/x86/kernel/microcode_amd.c b/arch/x86/kernel/microcode_amd.c
index 8f11f8f..47ebb1d 100644
--- a/arch/x86/kernel/microcode_amd.c
+++ b/arch/x86/kernel/microcode_amd.c
@@ -126,9 +126,20 @@ static struct ucode_patch *find_patch(unsigned int cpu)
static int collect_cpu_info_amd(int cpu, struct cpu_signature *csig)
{
struct cpuinfo_x86 *c = &cpu_data(cpu);
+ struct ucode_cpu_info *uci = ucode_cpu_info + cpu;
+ struct ucode_patch *p;
csig->sig = cpuid_eax(0x00000001);
csig->rev = c->microcode;
+
+ /*
+ * a patch could have been loaded early, set uci->mc so that
+ * mc_bp_resume() can call apply_microcode()
+ */
+ p = find_patch(cpu);
+ if (p && (p->patch_id == csig->rev))
+ uci->mc = p->data;
+
pr_info("CPU%d: patch_level=0x%08x\n", cpu, csig->rev);
return 0;
@@ -373,6 +384,17 @@ enum ucode_state load_microcode_amd(int cpu, const u8 *data, size_t size)
if (ret != UCODE_OK)
cleanup();
+#if defined(CONFIG_MICROCODE_AMD_EARLY) && defined(CONFIG_X86_32)
+ /* save BSP's matching patch for early load */
+ if (cpu_data(cpu).cpu_index == boot_cpu_data.cpu_index) {
+ struct ucode_patch *p = find_patch(cpu);
+ if (p) {
+ memset(amd_bsp_mpb, 0, MPB_MAX_SIZE);
+ memcpy(amd_bsp_mpb, p->data, min_t(u32, ksize(p->data),
+ MPB_MAX_SIZE));
+ }
+ }
+#endif
return ret;
}
diff --git a/arch/x86/kernel/microcode_amd_early.c b/arch/x86/kernel/microcode_amd_early.c
new file mode 100644
index 0000000..7e54d97
--- /dev/null
+++ b/arch/x86/kernel/microcode_amd_early.c
@@ -0,0 +1,222 @@
+/*
+ * Copyright (C) 2013 Advanced Micro Devices, Inc.
+ *
+ * Author: Jacob Shin <[email protected]>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/earlycpio.h>
+
+#include <asm/cpu.h>
+#include <asm/setup.h>
+#include <asm/microcode_amd.h>
+
+static bool ucode_loaded;
+static u32 ucode_new_rev;
+
+/*
+ * Microcode patch container file is prepended to the initrd in cpio format.
+ * See Documentation/x86/early-microcode.txt
+ */
+static __initdata char ucode_path[] = "kernel/x86/microcode/AuthenticAMD.bin";
+
+static struct cpio_data __init find_ucode_in_initrd(void)
+{
+ long offset = 0;
+ struct cpio_data cd;
+
+#ifdef CONFIG_X86_32
+ /*
+ * On 32-bit, early load occurs before paging is turned on so we need
+ * to use physical addresses.
+ */
+ if (!(read_cr0() & X86_CR0_PG)) {
+ struct boot_params *p;
+ p = (struct boot_params *)__pa_nodebug(&boot_params);
+ cd = find_cpio_data((char *)__pa_nodebug(ucode_path),
+ (void *)p->hdr.ramdisk_image, p->hdr.ramdisk_size,
+ &offset);
+ } else
+#endif
+ cd = find_cpio_data(ucode_path,
+ (void *)(boot_params.hdr.ramdisk_image + PAGE_OFFSET),
+ boot_params.hdr.ramdisk_size, &offset);
+
+ if (*(u32 *)cd.data != UCODE_MAGIC) {
+ cd.data = NULL;
+ cd.size = 0;
+ }
+
+ return cd;
+}
+
+/*
+ * Early load occurs before we can vmalloc(). So we look for the microcode
+ * patch container file in initrd, traverse equivalent cpu table, look for a
+ * matching microcode patch, and update, all in initrd memory in place.
+ * When vmalloc() is available for use later -- on 64-bit during first AP load,
+ * and on 32-bit during save_microcode_in_initrd_amd() -- we can call
+ * load_microcode_amd() to save equivalent cpu table and microcode patches in
+ * kernel heap memory.
+ */
+static void __init apply_ucode_in_initrd(void)
+{
+ struct cpio_data cd;
+ struct equiv_cpu_entry *eq;
+ u32 *header;
+ u8 *data;
+ u16 eq_id;
+ int offset, left;
+ u32 rev, dummy;
+ u32 *new_rev;
+
+#ifdef CONFIG_X86_32
+ new_rev = (u32 *)__pa_nodebug(&ucode_new_rev);
+#else
+ new_rev = &ucode_new_rev;
+#endif
+ cd = find_ucode_in_initrd();
+ if (!cd.data)
+ return;
+
+ data = cd.data;
+ left = cd.size;
+ header = (u32 *)data;
+
+ /* find equiv cpu table */
+
+ if (header[1] != UCODE_EQUIV_CPU_TABLE_TYPE || /* type */
+ header[2] == 0) /* size */
+ return;
+
+ eq = (struct equiv_cpu_entry *)(data + CONTAINER_HDR_SZ);
+ offset = header[2] + CONTAINER_HDR_SZ;
+ data += offset;
+ left -= offset;
+
+ eq_id = find_equiv_id(eq, cpuid_eax(0x00000001));
+ if (!eq_id)
+ return;
+
+ /* find ucode and update if needed */
+
+ rdmsr(MSR_AMD64_PATCH_LEVEL, rev, dummy);
+
+ while (left > 0) {
+ struct microcode_amd *mc;
+
+ header = (u32 *)data;
+ if (header[0] != UCODE_UCODE_TYPE || /* type */
+ header[1] == 0) /* size */
+ break;
+
+ mc = (struct microcode_amd *)(data + SECTION_HDR_SIZE);
+ if (eq_id == mc->hdr.processor_rev_id && rev < mc->hdr.patch_id)
+ if (__apply_microcode_amd(mc) == 0) {
+ if (!(*new_rev))
+ *new_rev = mc->hdr.patch_id;
+ break;
+ }
+
+ offset = header[1] + SECTION_HDR_SIZE;
+ data += offset;
+ left -= offset;
+ }
+}
+
+void __init load_ucode_amd_bsp(void)
+{
+ apply_ucode_in_initrd();
+}
+
+#ifdef CONFIG_X86_32
+u8 __cpuinitdata amd_bsp_mpb[MPB_MAX_SIZE];
+
+/*
+ * On 32-bit, since AP's early load occurs before paging is turned on, we
+ * cannot traverse cpu_equiv_table and pcache in kernel heap memory. So during
+ * cold boot, AP will apply_ucode_in_initrd() just like the BSP. During
+ * save_microcode_in_initrd_amd() BSP's patch is copied to amd_bsp_mpb, which
+ * is used upon resume from suspend.
+ */
+void __cpuinit load_ucode_amd_ap(void)
+{
+ struct microcode_amd *mc;
+
+ mc = (struct microcode_amd *)__pa_nodebug(amd_bsp_mpb);
+ if (mc->hdr.patch_id && mc->hdr.processor_rev_id)
+ __apply_microcode_amd(mc);
+ else
+ apply_ucode_in_initrd();
+}
+
+static void __init collect_cpu_sig_on_bsp(void *arg)
+{
+ unsigned int cpu = smp_processor_id();
+ struct ucode_cpu_info *uci = ucode_cpu_info + cpu;
+ uci->cpu_sig.sig = cpuid_eax(0x00000001);
+}
+#else
+static void __cpuinit collect_cpu_info_amd_early(struct cpuinfo_x86 *c,
+ struct ucode_cpu_info *uci)
+{
+ u32 rev, eax;
+
+ rdmsr(MSR_AMD64_PATCH_LEVEL, rev, eax);
+ eax = cpuid_eax(0x00000001);
+
+ uci->cpu_sig.sig = eax;
+ uci->cpu_sig.rev = rev;
+ c->microcode = rev;
+ c->x86 = ((eax >> 8) & 0xf) + ((eax >> 20) & 0xff);
+}
+
+void __cpuinit load_ucode_amd_ap(void)
+{
+ unsigned int cpu = smp_processor_id();
+
+ collect_cpu_info_amd_early(&cpu_data(cpu), ucode_cpu_info + cpu);
+
+ if (cpu && !ucode_loaded) {
+ struct cpio_data cd = find_ucode_in_initrd();
+ if (load_microcode_amd(0, cd.data, cd.size) != UCODE_OK)
+ return;
+ ucode_loaded = true;
+ }
+
+ apply_microcode_amd(cpu);
+}
+#endif
+
+int __init save_microcode_in_initrd_amd(void)
+{
+ enum ucode_state ret;
+ struct cpio_data cd;
+#ifdef CONFIG_X86_32
+ unsigned int bsp = boot_cpu_data.cpu_index;
+ struct ucode_cpu_info *uci = ucode_cpu_info + bsp;
+
+ if (!uci->cpu_sig.sig)
+ smp_call_function_single(bsp, collect_cpu_sig_on_bsp, NULL, 1);
+#endif
+ if (ucode_new_rev)
+ pr_info("microcode: updated early to new patch_level=0x%08x\n",
+ ucode_new_rev);
+
+ if (ucode_loaded)
+ return 0;
+
+ cd = find_ucode_in_initrd();
+ if (!cd.data)
+ return -EINVAL;
+
+ ret = load_microcode_amd(0, cd.data, cd.size);
+ if (ret != UCODE_OK)
+ return -EINVAL;
+
+ ucode_loaded = true;
+ return 0;
+}
diff --git a/arch/x86/kernel/microcode_core_early.c b/arch/x86/kernel/microcode_core_early.c
index 0d19ac5..86119f6 100644
--- a/arch/x86/kernel/microcode_core_early.c
+++ b/arch/x86/kernel/microcode_core_early.c
@@ -18,6 +18,7 @@
*/
#include <linux/module.h>
#include <asm/microcode_intel.h>
+#include <asm/microcode_amd.h>
#include <asm/processor.h>
#define QCHAR(a, b, c, d) ((a) + ((b) << 8) + ((c) << 16) + ((d) << 24))
@@ -81,8 +82,18 @@ void __init load_ucode_bsp(void)
vendor = x86_vendor();
x86 = x86_family();
- if (vendor == X86_VENDOR_INTEL && x86 >= 6)
- load_ucode_intel_bsp();
+ switch (vendor) {
+ case X86_VENDOR_INTEL:
+ if (x86 >= 6)
+ load_ucode_intel_bsp();
+ break;
+ case X86_VENDOR_AMD:
+ if (x86 >= 0x10)
+ load_ucode_amd_bsp();
+ break;
+ default:
+ break;
+ }
}
void __cpuinit load_ucode_ap(void)
@@ -95,16 +106,36 @@ void __cpuinit load_ucode_ap(void)
vendor = x86_vendor();
x86 = x86_family();
- if (vendor == X86_VENDOR_INTEL && x86 >= 6)
- load_ucode_intel_ap();
+ switch (vendor) {
+ case X86_VENDOR_INTEL:
+ if (x86 >= 6)
+ load_ucode_intel_ap();
+ break;
+ case X86_VENDOR_AMD:
+ if (x86 >= 0x10)
+ load_ucode_amd_ap();
+ break;
+ default:
+ break;
+ }
}
int __init save_microcode_in_initrd(void)
{
struct cpuinfo_x86 *c = &boot_cpu_data;
- if (c->x86_vendor == X86_VENDOR_INTEL && c->x86 >= 6)
- return save_microcode_in_initrd_intel();
+ switch (c->x86_vendor) {
+ case X86_VENDOR_INTEL:
+ if (c->x86 >= 6)
+ save_microcode_in_initrd_intel();
+ break;
+ case X86_VENDOR_AMD:
+ if (c->x86 >= 0x10)
+ save_microcode_in_initrd_amd();
+ break;
+ default:
+ break;
+ }
return 0;
}
On Thu, 30 May 2013, Jacob Shin wrote:
> mkdir initrd
> cd initrd
> -mkdir kernel
> -mkdir kernel/x86
> -mkdir kernel/x86/microcode
> -cp ../microcode.bin kernel/x86/microcode/GenuineIntel.bin
> -find .|cpio -oc >../ucode.cpio
> +mkdir -p kernel/x86/microcode
> +cp ../microcode.bin kernel/x86/microcode/GenuineIntel.bin (or AuthenticAMD.bin)
Can I just
'cat /lib/firmware/amd-ucode/*bin >kernel/x86/microcode/AuthenticAMD.bin'
to get a valid microcode container for all amd processors?
The answer for Intel is "yes". I sure hope it is the same for AMD...
--
"One disk to rule them all, One disk to find them. One disk to bring
them all and in the darkness grind them. In the Land of Redmond
where the shadows lie." -- The Silicon Valley Tarot
Henrique Holschuh
On Thu, May 30, 2013 at 8:31 PM, tip-bot for Jacob Shin
<[email protected]> wrote:
> Commit-ID: 757885e94a22bcc82beb9b1445c95218cb20ceab
> Gitweb: http://git.kernel.org/tip/757885e94a22bcc82beb9b1445c95218cb20ceab
> Author: Jacob Shin <[email protected]>
> AuthorDate: Thu, 30 May 2013 14:09:19 -0500
> Committer: H. Peter Anvin <[email protected]>
> CommitDate: Thu, 30 May 2013 20:19:25 -0700
>
> x86, microcode, amd: Early microcode patch loading support for AMD
>
> Add early microcode patch loading support for AMD.
>
> Signed-off-by: Jacob Shin <[email protected]>
> Link: http://lkml.kernel.org/r/[email protected]
> Signed-off-by: H. Peter Anvin <[email protected]>
> Cc: Fenghua Yu <[email protected]>
> ---
> Documentation/x86/early-microcode.txt | 11 +-
> arch/x86/Kconfig | 14 ++-
> arch/x86/include/asm/microcode_amd.h | 14 +++
> arch/x86/kernel/Makefile | 1 +
> arch/x86/kernel/microcode_amd.c | 22 ++++
> arch/x86/kernel/microcode_amd_early.c | 222 +++++++++++++++++++++++++++++++++
> arch/x86/kernel/microcode_core_early.c | 43 ++++++-
> 7 files changed, 310 insertions(+), 17 deletions(-)
>
WARNING: arch/x86/kernel/built-in.o(.cpuinit.text+0x7115): Section
mismatch in reference from the function load_ucode_amd_ap() to the
function .init.text:find_ucode_in_initrd()
The function __cpuinit load_ucode_amd_ap() references
a function __init find_ucode_in_initrd().
If find_ucode_in_initrd is only used by load_ucode_amd_ap then
annotate find_ucode_in_initrd with a matching annotation.
On Thu, May 30, 2013 at 11:10:23PM -0700, Yinghai Lu wrote:
> On Thu, May 30, 2013 at 8:31 PM, tip-bot for Jacob Shin
> <[email protected]> wrote:
> > Commit-ID: 757885e94a22bcc82beb9b1445c95218cb20ceab
> > Gitweb: http://git.kernel.org/tip/757885e94a22bcc82beb9b1445c95218cb20ceab
> > Author: Jacob Shin <[email protected]>
> > AuthorDate: Thu, 30 May 2013 14:09:19 -0500
> > Committer: H. Peter Anvin <[email protected]>
> > CommitDate: Thu, 30 May 2013 20:19:25 -0700
> >
> > x86, microcode, amd: Early microcode patch loading support for AMD
> >
> > Add early microcode patch loading support for AMD.
> >
> > Signed-off-by: Jacob Shin <[email protected]>
> > Link: http://lkml.kernel.org/r/[email protected]
> > Signed-off-by: H. Peter Anvin <[email protected]>
> > Cc: Fenghua Yu <[email protected]>
> > ---
> > Documentation/x86/early-microcode.txt | 11 +-
> > arch/x86/Kconfig | 14 ++-
> > arch/x86/include/asm/microcode_amd.h | 14 +++
> > arch/x86/kernel/Makefile | 1 +
> > arch/x86/kernel/microcode_amd.c | 22 ++++
> > arch/x86/kernel/microcode_amd_early.c | 222 +++++++++++++++++++++++++++++++++
> > arch/x86/kernel/microcode_core_early.c | 43 ++++++-
> > 7 files changed, 310 insertions(+), 17 deletions(-)
> >
>
> WARNING: arch/x86/kernel/built-in.o(.cpuinit.text+0x7115): Section
> mismatch in reference from the function load_ucode_amd_ap() to the
> function .init.text:find_ucode_in_initrd()
> The function __cpuinit load_ucode_amd_ap() references
> a function __init find_ucode_in_initrd().
> If find_ucode_in_initrd is only used by load_ucode_amd_ap then
> annotate find_ucode_in_initrd with a matching annotation.
Sorry about that, should have turned on CONFIG_DEBUG_SECTION_MISMATCH=y
This should fix the warnings:
>From 5c7ec96f218f08db25e449d7d5789ee2f66f2f92 Mon Sep 17 00:00:00 2001
From: Jacob Shin <[email protected]>
Date: Fri, 31 May 2013 01:53:24 -0500
Subject: [PATCH 1/1] x86/microcode/amd: fix section mismatch warnings on
microcode_amd_early.c
Fix section mismatch warnings on microcode_amd_early.c
Signed-off-by: Jacob Shin <[email protected]>
---
arch/x86/include/asm/microcode_amd.h | 2 +-
arch/x86/kernel/microcode_amd_early.c | 8 ++++----
2 files changed, 5 insertions(+), 5 deletions(-)
diff --git a/arch/x86/include/asm/microcode_amd.h b/arch/x86/include/asm/microcode_amd.h
index 24254aa..c6b043f 100644
--- a/arch/x86/include/asm/microcode_amd.h
+++ b/arch/x86/include/asm/microcode_amd.h
@@ -64,7 +64,7 @@ extern enum ucode_state load_microcode_amd(int cpu, const u8 *data, size_t size)
#ifdef CONFIG_MICROCODE_AMD_EARLY
#ifdef CONFIG_X86_32
#define MPB_MAX_SIZE PAGE_SIZE
-extern u8 __cpuinitdata amd_bsp_mpb[MPB_MAX_SIZE];
+extern u8 amd_bsp_mpb[MPB_MAX_SIZE];
#endif
extern void __init load_ucode_amd_bsp(void);
extern void __cpuinit load_ucode_amd_ap(void);
diff --git a/arch/x86/kernel/microcode_amd_early.c b/arch/x86/kernel/microcode_amd_early.c
index 7e54d97..9618805 100644
--- a/arch/x86/kernel/microcode_amd_early.c
+++ b/arch/x86/kernel/microcode_amd_early.c
@@ -21,9 +21,9 @@ static u32 ucode_new_rev;
* Microcode patch container file is prepended to the initrd in cpio format.
* See Documentation/x86/early-microcode.txt
*/
-static __initdata char ucode_path[] = "kernel/x86/microcode/AuthenticAMD.bin";
+static __cpuinitdata char ucode_path[] = "kernel/x86/microcode/AuthenticAMD.bin";
-static struct cpio_data __init find_ucode_in_initrd(void)
+static struct cpio_data __cpuinit find_ucode_in_initrd(void)
{
long offset = 0;
struct cpio_data cd;
@@ -62,7 +62,7 @@ static struct cpio_data __init find_ucode_in_initrd(void)
* load_microcode_amd() to save equivalent cpu table and microcode patches in
* kernel heap memory.
*/
-static void __init apply_ucode_in_initrd(void)
+static void __cpuinit apply_ucode_in_initrd(void)
{
struct cpio_data cd;
struct equiv_cpu_entry *eq;
@@ -133,7 +133,7 @@ void __init load_ucode_amd_bsp(void)
}
#ifdef CONFIG_X86_32
-u8 __cpuinitdata amd_bsp_mpb[MPB_MAX_SIZE];
+u8 amd_bsp_mpb[MPB_MAX_SIZE];
/*
* On 32-bit, since AP's early load occurs before paging is turned on, we
--
1.7.9.5
On Thu, May 30, 2013 at 08:31:08PM -0700, tip-bot for Jacob Shin wrote:
> Commit-ID: 757885e94a22bcc82beb9b1445c95218cb20ceab
> Gitweb: http://git.kernel.org/tip/757885e94a22bcc82beb9b1445c95218cb20ceab
> Author: Jacob Shin <[email protected]>
> AuthorDate: Thu, 30 May 2013 14:09:19 -0500
> Committer: H. Peter Anvin <[email protected]>
> CommitDate: Thu, 30 May 2013 20:19:25 -0700
>
> x86, microcode, amd: Early microcode patch loading support for AMD
>
> Add early microcode patch loading support for AMD.
>
> Signed-off-by: Jacob Shin <[email protected]>
> Link: http://lkml.kernel.org/r/[email protected]
> Signed-off-by: H. Peter Anvin <[email protected]>
> Cc: Fenghua Yu <[email protected]>
> ---
...
> diff --git a/arch/x86/kernel/Makefile b/arch/x86/kernel/Makefile
> index 7bd3bd3..6c3fcea 100644
> --- a/arch/x86/kernel/Makefile
> +++ b/arch/x86/kernel/Makefile
> @@ -93,6 +93,7 @@ obj-$(CONFIG_MICROCODE_INTEL_LIB) += microcode_intel_lib.o
> microcode-y := microcode_core.o
> microcode-$(CONFIG_MICROCODE_INTEL) += microcode_intel.o
> microcode-$(CONFIG_MICROCODE_AMD) += microcode_amd.o
> +obj-$(CONFIG_MICROCODE_AMD_EARLY) += microcode_amd_early.o
> obj-$(CONFIG_MICROCODE) += microcode.o
This can't be right:
WARNING: modpost: Found 1 section mismatch(es).
To see full details build your kernel with:
'make CONFIG_DEBUG_SECTION_MISMATCH=y'
arch/x86/built-in.o: In function `apply_ucode_in_initrd':
/home/boris/kernel/linux-2.6/arch/x86/kernel/microcode_amd_early.c:118: undefined reference to `__apply_microcode_amd'
arch/x86/built-in.o: In function `save_microcode_in_initrd_amd':
/home/boris/kernel/linux-2.6/arch/x86/kernel/microcode_amd_early.c:216: undefined reference to `load_microcode_amd'
arch/x86/built-in.o: In function `collect_cpu_info_amd_early':
/home/boris/kernel/linux-2.6/arch/x86/kernel/microcode_amd_early.c:171: undefined reference to `ucode_cpu_info'
/home/boris/kernel/linux-2.6/arch/x86/kernel/microcode_amd_early.c:172: undefined reference to `ucode_cpu_info'
arch/x86/built-in.o: In function `load_ucode_amd_ap':
/home/boris/kernel/linux-2.6/arch/x86/kernel/microcode_amd_early.c:185: undefined reference to `load_microcode_amd'
/home/boris/kernel/linux-2.6/arch/x86/kernel/microcode_amd_early.c:190: undefined reference to `apply_microcode_amd'
make: *** [vmlinux] Error 1
$ grep MICROCODE .config
CONFIG_MICROCODE=m
CONFIG_MICROCODE_INTEL=y
CONFIG_MICROCODE_AMD=y
CONFIG_MICROCODE_OLD_INTERFACE=y
CONFIG_MICROCODE_INTEL_LIB=y
CONFIG_MICROCODE_INTEL_EARLY=y
CONFIG_MICROCODE_AMD_EARLY=y
CONFIG_MICROCODE_EARLY=y
Jacob, as a tip for you: before sending out patches, always do a
for ARCH in "i386" "x86_64"
do
for cfg in "defconfig" "allnoconfig" "allyesconfig" "allmodconfig"
do
make -j<something> $ARCH $cfg
done
done
to smoke-test your patches. I'm not saying this should catch all build
errors but still...
Thanks.
On Fri, May 31, 2013 at 10:41:33AM +0200, Borislav Petkov wrote:
> On Thu, May 30, 2013 at 08:31:08PM -0700, tip-bot for Jacob Shin wrote:
> > Commit-ID: 757885e94a22bcc82beb9b1445c95218cb20ceab
> > Gitweb: http://git.kernel.org/tip/757885e94a22bcc82beb9b1445c95218cb20ceab
> > Author: Jacob Shin <[email protected]>
> > AuthorDate: Thu, 30 May 2013 14:09:19 -0500
> > Committer: H. Peter Anvin <[email protected]>
> > CommitDate: Thu, 30 May 2013 20:19:25 -0700
> >
> > x86, microcode, amd: Early microcode patch loading support for AMD
> >
> > Add early microcode patch loading support for AMD.
> >
> > Signed-off-by: Jacob Shin <[email protected]>
> > Link: http://lkml.kernel.org/r/[email protected]
> > Signed-off-by: H. Peter Anvin <[email protected]>
> > Cc: Fenghua Yu <[email protected]>
> > ---
>
> ...
>
> > diff --git a/arch/x86/kernel/Makefile b/arch/x86/kernel/Makefile
> > index 7bd3bd3..6c3fcea 100644
> > --- a/arch/x86/kernel/Makefile
> > +++ b/arch/x86/kernel/Makefile
> > @@ -93,6 +93,7 @@ obj-$(CONFIG_MICROCODE_INTEL_LIB) += microcode_intel_lib.o
> > microcode-y := microcode_core.o
> > microcode-$(CONFIG_MICROCODE_INTEL) += microcode_intel.o
> > microcode-$(CONFIG_MICROCODE_AMD) += microcode_amd.o
> > +obj-$(CONFIG_MICROCODE_AMD_EARLY) += microcode_amd_early.o
> > obj-$(CONFIG_MICROCODE) += microcode.o
>
> This can't be right:
>
> WARNING: modpost: Found 1 section mismatch(es).
> To see full details build your kernel with:
> 'make CONFIG_DEBUG_SECTION_MISMATCH=y'
> arch/x86/built-in.o: In function `apply_ucode_in_initrd':
> /home/boris/kernel/linux-2.6/arch/x86/kernel/microcode_amd_early.c:118: undefined reference to `__apply_microcode_amd'
> arch/x86/built-in.o: In function `save_microcode_in_initrd_amd':
> /home/boris/kernel/linux-2.6/arch/x86/kernel/microcode_amd_early.c:216: undefined reference to `load_microcode_amd'
> arch/x86/built-in.o: In function `collect_cpu_info_amd_early':
> /home/boris/kernel/linux-2.6/arch/x86/kernel/microcode_amd_early.c:171: undefined reference to `ucode_cpu_info'
> /home/boris/kernel/linux-2.6/arch/x86/kernel/microcode_amd_early.c:172: undefined reference to `ucode_cpu_info'
> arch/x86/built-in.o: In function `load_ucode_amd_ap':
> /home/boris/kernel/linux-2.6/arch/x86/kernel/microcode_amd_early.c:185: undefined reference to `load_microcode_amd'
> /home/boris/kernel/linux-2.6/arch/x86/kernel/microcode_amd_early.c:190: undefined reference to `apply_microcode_amd'
> make: *** [vmlinux] Error 1
>
> $ grep MICROCODE .config
> CONFIG_MICROCODE=m
> CONFIG_MICROCODE_INTEL=y
> CONFIG_MICROCODE_AMD=y
> CONFIG_MICROCODE_OLD_INTERFACE=y
> CONFIG_MICROCODE_INTEL_LIB=y
> CONFIG_MICROCODE_INTEL_EARLY=y
> CONFIG_MICROCODE_AMD_EARLY=y
> CONFIG_MICROCODE_EARLY=y
>
> Jacob, as a tip for you: before sending out patches, always do a
>
> for ARCH in "i386" "x86_64"
> do
> for cfg in "defconfig" "allnoconfig" "allyesconfig" "allmodconfig"
> do
> make -j<something> $ARCH $cfg
> done
> done
>
> to smoke-test your patches. I'm not saying this should catch all build
> errors but still...
So sorry .. lesson learned, will do.
Fix below. Yinghai, I appended this randconfig error fix to the
section mismatch fix I sent you earlier:
https://lkml.org/lkml/2013/5/31/51
>From bdb3e0c8cde1a7cd12946a3be5e2ebf22421f462 Mon Sep 17 00:00:00 2001
From: Jacob Shin <[email protected]>
Date: Fri, 31 May 2013 01:53:24 -0500
Subject: [PATCH 1/1] x86/microcode/amd: fix warnings and errors on randconfig
Fix section mismatch warnings on microcode_amd_early.
Compile error occurs when CONFIG_MICROCODE=m, change so that early
loading depends on microcode_core.
Reported-by: Yinghai Lu <[email protected]>
Reported-by: Borislav Petkov <[email protected]>
Signed-off-by: Jacob Shin <[email protected]>
---
arch/x86/Kconfig | 2 +-
arch/x86/include/asm/microcode_amd.h | 2 +-
arch/x86/kernel/microcode_amd_early.c | 8 ++++----
3 files changed, 6 insertions(+), 6 deletions(-)
diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
index 28dba52..2705532 100644
--- a/arch/x86/Kconfig
+++ b/arch/x86/Kconfig
@@ -1065,7 +1065,7 @@ config MICROCODE_AMD_EARLY
config MICROCODE_EARLY
bool "Early load microcode"
- depends on (MICROCODE_INTEL || MICROCODE_AMD) && BLK_DEV_INITRD
+ depends on MICROCODE=y && BLK_DEV_INITRD
select MICROCODE_INTEL_EARLY if MICROCODE_INTEL
select MICROCODE_AMD_EARLY if MICROCODE_AMD
default y
diff --git a/arch/x86/include/asm/microcode_amd.h b/arch/x86/include/asm/microcode_amd.h
index 24254aa..c6b043f 100644
--- a/arch/x86/include/asm/microcode_amd.h
+++ b/arch/x86/include/asm/microcode_amd.h
@@ -64,7 +64,7 @@ extern enum ucode_state load_microcode_amd(int cpu, const u8 *data, size_t size)
#ifdef CONFIG_MICROCODE_AMD_EARLY
#ifdef CONFIG_X86_32
#define MPB_MAX_SIZE PAGE_SIZE
-extern u8 __cpuinitdata amd_bsp_mpb[MPB_MAX_SIZE];
+extern u8 amd_bsp_mpb[MPB_MAX_SIZE];
#endif
extern void __init load_ucode_amd_bsp(void);
extern void __cpuinit load_ucode_amd_ap(void);
diff --git a/arch/x86/kernel/microcode_amd_early.c b/arch/x86/kernel/microcode_amd_early.c
index 7e54d97..9618805 100644
--- a/arch/x86/kernel/microcode_amd_early.c
+++ b/arch/x86/kernel/microcode_amd_early.c
@@ -21,9 +21,9 @@ static u32 ucode_new_rev;
* Microcode patch container file is prepended to the initrd in cpio format.
* See Documentation/x86/early-microcode.txt
*/
-static __initdata char ucode_path[] = "kernel/x86/microcode/AuthenticAMD.bin";
+static __cpuinitdata char ucode_path[] = "kernel/x86/microcode/AuthenticAMD.bin";
-static struct cpio_data __init find_ucode_in_initrd(void)
+static struct cpio_data __cpuinit find_ucode_in_initrd(void)
{
long offset = 0;
struct cpio_data cd;
@@ -62,7 +62,7 @@ static struct cpio_data __init find_ucode_in_initrd(void)
* load_microcode_amd() to save equivalent cpu table and microcode patches in
* kernel heap memory.
*/
-static void __init apply_ucode_in_initrd(void)
+static void __cpuinit apply_ucode_in_initrd(void)
{
struct cpio_data cd;
struct equiv_cpu_entry *eq;
@@ -133,7 +133,7 @@ void __init load_ucode_amd_bsp(void)
}
#ifdef CONFIG_X86_32
-u8 __cpuinitdata amd_bsp_mpb[MPB_MAX_SIZE];
+u8 amd_bsp_mpb[MPB_MAX_SIZE];
/*
* On 32-bit, since AP's early load occurs before paging is turned on, we
--
1.7.9.5
If you send a patch with text above the patch, please include a scissor
line:
---8<---
... above the patch so that git tools can process it.
-hpa
On Fri, May 31, 2013 at 08:13:09AM -0700, H. Peter Anvin wrote:
> If you send a patch with text above the patch, please include a scissor
> line:
>
> ---8<---
>
> ... above the patch so that git tools can process it.
Ah okay, sorry about that, will do so from now on.
Yinghai, Boris, sorry if you have to hand snip my previous fix email,
but please do let me know if I can add your Tested-by's
Thanks!
On Fri, May 31, 2013 at 01:26:49AM -0300, Henrique de Moraes Holschuh wrote:
> On Thu, 30 May 2013, Jacob Shin wrote:
> > mkdir initrd
> > cd initrd
> > -mkdir kernel
> > -mkdir kernel/x86
> > -mkdir kernel/x86/microcode
> > -cp ../microcode.bin kernel/x86/microcode/GenuineIntel.bin
> > -find .|cpio -oc >../ucode.cpio
> > +mkdir -p kernel/x86/microcode
> > +cp ../microcode.bin kernel/x86/microcode/GenuineIntel.bin (or AuthenticAMD.bin)
>
> Can I just
> 'cat /lib/firmware/amd-ucode/*bin >kernel/x86/microcode/AuthenticAMD.bin'
> to get a valid microcode container for all amd processors?
>
> The answer for Intel is "yes". I sure hope it is the same for AMD...
Hm. I have not thought about that, I will investigate and follow up
with a patch if needed.
Thanks,
On Fri, May 31, 2013 at 01:26:49AM -0300, Henrique de Moraes Holschuh wrote:
> On Thu, 30 May 2013, Jacob Shin wrote:
> > mkdir initrd
> > cd initrd
> > -mkdir kernel
> > -mkdir kernel/x86
> > -mkdir kernel/x86/microcode
> > -cp ../microcode.bin kernel/x86/microcode/GenuineIntel.bin
> > -find .|cpio -oc >../ucode.cpio
> > +mkdir -p kernel/x86/microcode
> > +cp ../microcode.bin kernel/x86/microcode/GenuineIntel.bin (or AuthenticAMD.bin)
>
> Can I just
> 'cat /lib/firmware/amd-ucode/*bin >kernel/x86/microcode/AuthenticAMD.bin'
> to get a valid microcode container for all amd processors?
>
> The answer for Intel is "yes". I sure hope it is the same for AMD...
No, this doesn't work for AMD.
The container file includes a header section with information how to
map CPU F/M/S to microcode revisions provided with a container
file. Concatenating several container files will not create an
all-embracing header section.
More details were available on the amd64.org web pages. But it seems
that the web site is not available anymore ...
Andreas
On Fri, 31 May 2013, Andreas Herrmann wrote:
> On Fri, May 31, 2013 at 01:26:49AM -0300, Henrique de Moraes Holschuh wrote:
> > On Thu, 30 May 2013, Jacob Shin wrote:
> > > mkdir initrd
> > > cd initrd
> > > -mkdir kernel
> > > -mkdir kernel/x86
> > > -mkdir kernel/x86/microcode
> > > -cp ../microcode.bin kernel/x86/microcode/GenuineIntel.bin
> > > -find .|cpio -oc >../ucode.cpio
> > > +mkdir -p kernel/x86/microcode
> > > +cp ../microcode.bin kernel/x86/microcode/GenuineIntel.bin (or AuthenticAMD.bin)
> >
> > Can I just
> > 'cat /lib/firmware/amd-ucode/*bin >kernel/x86/microcode/AuthenticAMD.bin'
> > to get a valid microcode container for all amd processors?
> >
> > The answer for Intel is "yes". I sure hope it is the same for AMD...
>
> No, this doesn't work for AMD.
>
> The container file includes a header section with information how to
> map CPU F/M/S to microcode revisions provided with a container
> file. Concatenating several container files will not create an
> all-embracing header section.
>
> More details were available on the amd64.org web pages. But it seems
> that the web site is not available anymore ...
Well, this is a problem for userspace. Maybe the easier solution would be
to make kernel/x86/microcode/AuthenticAMD a folder, and look for files there
with names we can derivate from the ones used by the firmware interface (or
even the same names)?
The early-initramfs API easily allows this to be implemented...
--
"One disk to rule them all, One disk to find them. One disk to bring
them all and in the darkness grind them. In the Land of Redmond
where the shadows lie." -- The Silicon Valley Tarot
Henrique Holschuh
Commit-ID: 6b3389ac21b5e557b957f1497d0ff22bf733e8c3
Gitweb: http://git.kernel.org/tip/6b3389ac21b5e557b957f1497d0ff22bf733e8c3
Author: Jacob Shin <[email protected]>
AuthorDate: Fri, 31 May 2013 01:53:24 -0500
Committer: H. Peter Anvin <[email protected]>
CommitDate: Fri, 31 May 2013 13:56:58 -0700
x86, microcode, amd: Fix warnings and errors on with CONFIG_MICROCODE=m
Fix section mismatch warnings on microcode_amd_early.
Compile error occurs when CONFIG_MICROCODE=m, change so that early
loading depends on microcode_core.
Reported-by: Yinghai Lu <[email protected]>
Reported-by: Borislav Petkov <[email protected]>
Signed-off-by: Jacob Shin <[email protected]>
Link: http://lkml.kernel.org/r/20130531150241.GA12006@jshin-Toonie
Signed-off-by: H. Peter Anvin <[email protected]>
---
arch/x86/Kconfig | 2 +-
arch/x86/include/asm/microcode_amd.h | 2 +-
arch/x86/kernel/microcode_amd_early.c | 8 ++++----
3 files changed, 6 insertions(+), 6 deletions(-)
diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
index 28dba52..2705532 100644
--- a/arch/x86/Kconfig
+++ b/arch/x86/Kconfig
@@ -1065,7 +1065,7 @@ config MICROCODE_AMD_EARLY
config MICROCODE_EARLY
bool "Early load microcode"
- depends on (MICROCODE_INTEL || MICROCODE_AMD) && BLK_DEV_INITRD
+ depends on MICROCODE=y && BLK_DEV_INITRD
select MICROCODE_INTEL_EARLY if MICROCODE_INTEL
select MICROCODE_AMD_EARLY if MICROCODE_AMD
default y
diff --git a/arch/x86/include/asm/microcode_amd.h b/arch/x86/include/asm/microcode_amd.h
index 24254aa..c6b043f 100644
--- a/arch/x86/include/asm/microcode_amd.h
+++ b/arch/x86/include/asm/microcode_amd.h
@@ -64,7 +64,7 @@ extern enum ucode_state load_microcode_amd(int cpu, const u8 *data, size_t size)
#ifdef CONFIG_MICROCODE_AMD_EARLY
#ifdef CONFIG_X86_32
#define MPB_MAX_SIZE PAGE_SIZE
-extern u8 __cpuinitdata amd_bsp_mpb[MPB_MAX_SIZE];
+extern u8 amd_bsp_mpb[MPB_MAX_SIZE];
#endif
extern void __init load_ucode_amd_bsp(void);
extern void __cpuinit load_ucode_amd_ap(void);
diff --git a/arch/x86/kernel/microcode_amd_early.c b/arch/x86/kernel/microcode_amd_early.c
index 7e54d97..9618805 100644
--- a/arch/x86/kernel/microcode_amd_early.c
+++ b/arch/x86/kernel/microcode_amd_early.c
@@ -21,9 +21,9 @@ static u32 ucode_new_rev;
* Microcode patch container file is prepended to the initrd in cpio format.
* See Documentation/x86/early-microcode.txt
*/
-static __initdata char ucode_path[] = "kernel/x86/microcode/AuthenticAMD.bin";
+static __cpuinitdata char ucode_path[] = "kernel/x86/microcode/AuthenticAMD.bin";
-static struct cpio_data __init find_ucode_in_initrd(void)
+static struct cpio_data __cpuinit find_ucode_in_initrd(void)
{
long offset = 0;
struct cpio_data cd;
@@ -62,7 +62,7 @@ static struct cpio_data __init find_ucode_in_initrd(void)
* load_microcode_amd() to save equivalent cpu table and microcode patches in
* kernel heap memory.
*/
-static void __init apply_ucode_in_initrd(void)
+static void __cpuinit apply_ucode_in_initrd(void)
{
struct cpio_data cd;
struct equiv_cpu_entry *eq;
@@ -133,7 +133,7 @@ void __init load_ucode_amd_bsp(void)
}
#ifdef CONFIG_X86_32
-u8 __cpuinitdata amd_bsp_mpb[MPB_MAX_SIZE];
+u8 amd_bsp_mpb[MPB_MAX_SIZE];
/*
* On 32-bit, since AP's early load occurs before paging is turned on, we
On Fri, May 31, 2013 at 06:30:39PM -0300, Henrique de Moraes Holschuh wrote:
> On Fri, 31 May 2013, Andreas Herrmann wrote:
> > On Fri, May 31, 2013 at 01:26:49AM -0300, Henrique de Moraes Holschuh wrote:
> > > On Thu, 30 May 2013, Jacob Shin wrote:
> > > > mkdir initrd
> > > > cd initrd
> > > > -mkdir kernel
> > > > -mkdir kernel/x86
> > > > -mkdir kernel/x86/microcode
> > > > -cp ../microcode.bin kernel/x86/microcode/GenuineIntel.bin
> > > > -find .|cpio -oc >../ucode.cpio
> > > > +mkdir -p kernel/x86/microcode
> > > > +cp ../microcode.bin kernel/x86/microcode/GenuineIntel.bin (or AuthenticAMD.bin)
> > >
> > > Can I just
> > > 'cat /lib/firmware/amd-ucode/*bin >kernel/x86/microcode/AuthenticAMD.bin'
> > > to get a valid microcode container for all amd processors?
> > >
> > > The answer for Intel is "yes". I sure hope it is the same for AMD...
> >
> > No, this doesn't work for AMD.
> >
> > The container file includes a header section with information how to
> > map CPU F/M/S to microcode revisions provided with a container
> > file. Concatenating several container files will not create an
> > all-embracing header section.
> >
> > More details were available on the amd64.org web pages. But it seems
> > that the web site is not available anymore ...
>
> Well, this is a problem for userspace. Maybe the easier solution would be
> to make kernel/x86/microcode/AuthenticAMD a folder, and look for files there
> with names we can derivate from the ones used by the firmware interface (or
> even the same names)?
>
> The early-initramfs API easily allows this to be implemented...
Yeah, but since that will break symmetry with Intel's GenuineIntel.bin
file path, so I decided to add some more logic to early loading code
to be able to parse through multiple containers files concatanated
together.
Any thoughts on this Boris?
Patch below:
---8<---
>From 40ba7f578e2abb83897f218e6577396a3852ad00 Mon Sep 17 00:00:00 2001
From: Jacob Shin <[email protected]>
Date: Fri, 31 May 2013 13:57:02 -0500
Subject: [PATCH 1/1] x86/microcode/amd: allow multiple family's bin files
appended together
Add support for parsing through multiple family's microcode patch
container binary files appended together when early loading. This is
already supported on Intel.
Reported-by: Henrique de Moraes Holschuh <[email protected]>
Signed-off-by: Jacob Shin <[email protected]>
---
arch/x86/kernel/microcode_amd_early.c | 63 +++++++++++++++++++++++++++------
1 file changed, 53 insertions(+), 10 deletions(-)
diff --git a/arch/x86/kernel/microcode_amd_early.c b/arch/x86/kernel/microcode_amd_early.c
index 9618805..2426dab 100644
--- a/arch/x86/kernel/microcode_amd_early.c
+++ b/arch/x86/kernel/microcode_amd_early.c
@@ -16,6 +16,7 @@
static bool ucode_loaded;
static u32 ucode_new_rev;
+static int family_offset;
/*
* Microcode patch container file is prepended to the initrd in cpio format.
@@ -27,6 +28,7 @@ static struct cpio_data __cpuinit find_ucode_in_initrd(void)
{
long offset = 0;
struct cpio_data cd;
+ int *fam_offset = &family_offset;
#ifdef CONFIG_X86_32
/*
@@ -39,12 +41,18 @@ static struct cpio_data __cpuinit find_ucode_in_initrd(void)
cd = find_cpio_data((char *)__pa_nodebug(ucode_path),
(void *)p->hdr.ramdisk_image, p->hdr.ramdisk_size,
&offset);
+ fam_offset = (int *)__pa_nodebug(&family_offset);
} else
#endif
cd = find_cpio_data(ucode_path,
(void *)(boot_params.hdr.ramdisk_image + PAGE_OFFSET),
boot_params.hdr.ramdisk_size, &offset);
+ if (*fam_offset) {
+ cd.data = (u8 *)cd.data + *fam_offset;
+ cd.size -= *fam_offset;
+ }
+
if (*(u32 *)cd.data != UCODE_MAGIC) {
cd.data = NULL;
cd.size = 0;
@@ -68,15 +76,18 @@ static void __cpuinit apply_ucode_in_initrd(void)
struct equiv_cpu_entry *eq;
u32 *header;
u8 *data;
- u16 eq_id;
+ u16 eq_id = 0;
int offset, left;
- u32 rev, dummy;
+ u32 rev, eax;
u32 *new_rev;
+ int *fam_off;
#ifdef CONFIG_X86_32
new_rev = (u32 *)__pa_nodebug(&ucode_new_rev);
+ fam_off = (int *)__pa_nodebug(&family_offset);
#else
new_rev = &ucode_new_rev;
+ fam_off = &family_offset;
#endif
cd = find_ucode_in_initrd();
if (!cd.data)
@@ -92,18 +103,44 @@ static void __cpuinit apply_ucode_in_initrd(void)
header[2] == 0) /* size */
return;
- eq = (struct equiv_cpu_entry *)(data + CONTAINER_HDR_SZ);
- offset = header[2] + CONTAINER_HDR_SZ;
- data += offset;
- left -= offset;
+ eax = cpuid_eax(0x00000001);
+
+ while (left > 0) {
+ eq = (struct equiv_cpu_entry *)(data + CONTAINER_HDR_SZ);
+
+ offset = header[2] + CONTAINER_HDR_SZ;
+ data += offset;
+ left -= offset;
+
+ eq_id = find_equiv_id(eq, eax);
+ if (eq_id)
+ break;
+
+ /*
+ * support multiple container files appended together. if this
+ * one does not have a matching equivalent cpu entry, we fast
+ * forward to the next container file.
+ */
+ while (left > 0) {
+ header = (u32 *)data;
+ if (header[0] == UCODE_MAGIC &&
+ header[1] == UCODE_EQUIV_CPU_TABLE_TYPE)
+ break;
+
+ offset = header[1] + SECTION_HDR_SIZE;
+ data += offset;
+ left -= offset;
+ }
+
+ *fam_off = data - (u8 *)cd.data;
+ }
- eq_id = find_equiv_id(eq, cpuid_eax(0x00000001));
if (!eq_id)
return;
/* find ucode and update if needed */
- rdmsr(MSR_AMD64_PATCH_LEVEL, rev, dummy);
+ rdmsr(MSR_AMD64_PATCH_LEVEL, rev, eax);
while (left > 0) {
struct microcode_amd *mc;
@@ -116,8 +153,11 @@ static void __cpuinit apply_ucode_in_initrd(void)
mc = (struct microcode_amd *)(data + SECTION_HDR_SIZE);
if (eq_id == mc->hdr.processor_rev_id && rev < mc->hdr.patch_id)
if (__apply_microcode_amd(mc) == 0) {
- if (!(*new_rev))
- *new_rev = mc->hdr.patch_id;
+#ifdef CONFIG_X86_32
+ u8 *mpb = (u8 *)__pa_nodebug(&amd_bsp_mpb);
+ memcpy(mpb, mc, header[1]);
+#endif
+ *new_rev = mc->hdr.patch_id;
break;
}
@@ -182,6 +222,9 @@ void __cpuinit load_ucode_amd_ap(void)
if (cpu && !ucode_loaded) {
struct cpio_data cd = find_ucode_in_initrd();
+ if (!cd.data)
+ return;
+
if (load_microcode_amd(0, cd.data, cd.size) != UCODE_OK)
return;
ucode_loaded = true;
--
1.7.9.5
On Fri, May 31, 2013 at 02:59:20PM -0700, tip-bot for Jacob Shin wrote:
> Commit-ID: 6b3389ac21b5e557b957f1497d0ff22bf733e8c3
> Gitweb: http://git.kernel.org/tip/6b3389ac21b5e557b957f1497d0ff22bf733e8c3
> Author: Jacob Shin <[email protected]>
> AuthorDate: Fri, 31 May 2013 01:53:24 -0500
> Committer: H. Peter Anvin <[email protected]>
> CommitDate: Fri, 31 May 2013 13:56:58 -0700
>
> x86, microcode, amd: Fix warnings and errors on with CONFIG_MICROCODE=m
>
> Fix section mismatch warnings on microcode_amd_early.
> Compile error occurs when CONFIG_MICROCODE=m, change so that early
> loading depends on microcode_core.
>
> Reported-by: Yinghai Lu <[email protected]>
> Reported-by: Borislav Petkov <[email protected]>
> Signed-off-by: Jacob Shin <[email protected]>
> Link: http://lkml.kernel.org/r/20130531150241.GA12006@jshin-Toonie
> Signed-off-by: H. Peter Anvin <[email protected]>
> ---
> arch/x86/Kconfig | 2 +-
> arch/x86/include/asm/microcode_amd.h | 2 +-
> arch/x86/kernel/microcode_amd_early.c | 8 ++++----
> 3 files changed, 6 insertions(+), 6 deletions(-)
>
> diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
> index 28dba52..2705532 100644
> --- a/arch/x86/Kconfig
> +++ b/arch/x86/Kconfig
> @@ -1065,7 +1065,7 @@ config MICROCODE_AMD_EARLY
>
> config MICROCODE_EARLY
> bool "Early load microcode"
> - depends on (MICROCODE_INTEL || MICROCODE_AMD) && BLK_DEV_INITRD
> + depends on MICROCODE=y && BLK_DEV_INITRD
This means now though, distros will have to build in microcode support
(not a module anymore) in order to get early ucode loading support.
I'm not saying this is necessarily a bad thing - actually, I even think
we want to make the microcode glue in the kernel not be a module anymore
because it doesn't hurt and modern CPUs will definitely rather need
microcode than not, so we'd need that functionality unconditionally...
Thanks.
On Fri, May 31, 2013 at 2:59 PM, tip-bot for Jacob Shin
<[email protected]> wrote:
> Commit-ID: 6b3389ac21b5e557b957f1497d0ff22bf733e8c3
> Gitweb: http://git.kernel.org/tip/6b3389ac21b5e557b957f1497d0ff22bf733e8c3
> Author: Jacob Shin <[email protected]>
> AuthorDate: Fri, 31 May 2013 01:53:24 -0500
> Committer: H. Peter Anvin <[email protected]>
> CommitDate: Fri, 31 May 2013 13:56:58 -0700
>
> x86, microcode, amd: Fix warnings and errors on with CONFIG_MICROCODE=m
>
> Fix section mismatch warnings on microcode_amd_early.
> Compile error occurs when CONFIG_MICROCODE=m, change so that early
> loading depends on microcode_core.
>
> Reported-by: Yinghai Lu <[email protected]>
> Reported-by: Borislav Petkov <[email protected]>
> Signed-off-by: Jacob Shin <[email protected]>
> Link: http://lkml.kernel.org/r/20130531150241.GA12006@jshin-Toonie
> Signed-off-by: H. Peter Anvin <[email protected]>
> ---
> arch/x86/Kconfig | 2 +-
> arch/x86/include/asm/microcode_amd.h | 2 +-
> arch/x86/kernel/microcode_amd_early.c | 8 ++++----
> 3 files changed, 6 insertions(+), 6 deletions(-)
>
> diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
> index 28dba52..2705532 100644
> --- a/arch/x86/Kconfig
> +++ b/arch/x86/Kconfig
> @@ -1065,7 +1065,7 @@ config MICROCODE_AMD_EARLY
>
> config MICROCODE_EARLY
> bool "Early load microcode"
> - depends on (MICROCODE_INTEL || MICROCODE_AMD) && BLK_DEV_INITRD
> + depends on MICROCODE=y && BLK_DEV_INITRD
> select MICROCODE_INTEL_EARLY if MICROCODE_INTEL
> select MICROCODE_AMD_EARLY if MICROCODE_AMD
> default y
> diff --git a/arch/x86/include/asm/microcode_amd.h b/arch/x86/include/asm/microcode_amd.h
> index 24254aa..c6b043f 100644
> --- a/arch/x86/include/asm/microcode_amd.h
> +++ b/arch/x86/include/asm/microcode_amd.h
> @@ -64,7 +64,7 @@ extern enum ucode_state load_microcode_amd(int cpu, const u8 *data, size_t size)
> #ifdef CONFIG_MICROCODE_AMD_EARLY
> #ifdef CONFIG_X86_32
> #define MPB_MAX_SIZE PAGE_SIZE
> -extern u8 __cpuinitdata amd_bsp_mpb[MPB_MAX_SIZE];
> +extern u8 amd_bsp_mpb[MPB_MAX_SIZE];
> #endif
> extern void __init load_ucode_amd_bsp(void);
> extern void __cpuinit load_ucode_amd_ap(void);
> diff --git a/arch/x86/kernel/microcode_amd_early.c b/arch/x86/kernel/microcode_amd_early.c
> index 7e54d97..9618805 100644
> --- a/arch/x86/kernel/microcode_amd_early.c
> +++ b/arch/x86/kernel/microcode_amd_early.c
> @@ -21,9 +21,9 @@ static u32 ucode_new_rev;
> * Microcode patch container file is prepended to the initrd in cpio format.
> * See Documentation/x86/early-microcode.txt
> */
> -static __initdata char ucode_path[] = "kernel/x86/microcode/AuthenticAMD.bin";
> +static __cpuinitdata char ucode_path[] = "kernel/x86/microcode/AuthenticAMD.bin";
>
> -static struct cpio_data __init find_ucode_in_initrd(void)
> +static struct cpio_data __cpuinit find_ucode_in_initrd(void)
> {
> long offset = 0;
> struct cpio_data cd;
does not like right fix.
find_ucode_in_initrd should be __init.
> @@ -62,7 +62,7 @@ static struct cpio_data __init find_ucode_in_initrd(void)
> * load_microcode_amd() to save equivalent cpu table and microcode patches in
> * kernel heap memory.
> */
> -static void __init apply_ucode_in_initrd(void)
> +static void __cpuinit apply_ucode_in_initrd(void)
> {
> struct cpio_data cd;
> struct equiv_cpu_entry *eq;
it should not call find_ucode_in_initrd or
it should be __init.
> @@ -133,7 +133,7 @@ void __init load_ucode_amd_bsp(void)
> }
>
> #ifdef CONFIG_X86_32
> -u8 __cpuinitdata amd_bsp_mpb[MPB_MAX_SIZE];
> +u8 amd_bsp_mpb[MPB_MAX_SIZE];
>
> /*
> * On 32-bit, since AP's early load occurs before paging is turned on, we
On Tue, Jun 04, 2013 at 02:02:43PM -0700, Yinghai Lu wrote:
> On Fri, May 31, 2013 at 2:59 PM, tip-bot for Jacob Shin
> <[email protected]> wrote:
> > Commit-ID: 6b3389ac21b5e557b957f1497d0ff22bf733e8c3
> > Gitweb: http://git.kernel.org/tip/6b3389ac21b5e557b957f1497d0ff22bf733e8c3
> > Author: Jacob Shin <[email protected]>
> > AuthorDate: Fri, 31 May 2013 01:53:24 -0500
> > Committer: H. Peter Anvin <[email protected]>
> > CommitDate: Fri, 31 May 2013 13:56:58 -0700
> >
> > x86, microcode, amd: Fix warnings and errors on with CONFIG_MICROCODE=m
> >
> > Fix section mismatch warnings on microcode_amd_early.
> > Compile error occurs when CONFIG_MICROCODE=m, change so that early
> > loading depends on microcode_core.
> >
> > Reported-by: Yinghai Lu <[email protected]>
> > Reported-by: Borislav Petkov <[email protected]>
> > Signed-off-by: Jacob Shin <[email protected]>
> > Link: http://lkml.kernel.org/r/20130531150241.GA12006@jshin-Toonie
> > Signed-off-by: H. Peter Anvin <[email protected]>
> > ---
> > arch/x86/Kconfig | 2 +-
> > arch/x86/include/asm/microcode_amd.h | 2 +-
> > arch/x86/kernel/microcode_amd_early.c | 8 ++++----
> > 3 files changed, 6 insertions(+), 6 deletions(-)
> >
> > diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
> > index 28dba52..2705532 100644
> > --- a/arch/x86/Kconfig
> > +++ b/arch/x86/Kconfig
> > @@ -1065,7 +1065,7 @@ config MICROCODE_AMD_EARLY
> >
> > config MICROCODE_EARLY
> > bool "Early load microcode"
> > - depends on (MICROCODE_INTEL || MICROCODE_AMD) && BLK_DEV_INITRD
> > + depends on MICROCODE=y && BLK_DEV_INITRD
> > select MICROCODE_INTEL_EARLY if MICROCODE_INTEL
> > select MICROCODE_AMD_EARLY if MICROCODE_AMD
> > default y
> > diff --git a/arch/x86/include/asm/microcode_amd.h b/arch/x86/include/asm/microcode_amd.h
> > index 24254aa..c6b043f 100644
> > --- a/arch/x86/include/asm/microcode_amd.h
> > +++ b/arch/x86/include/asm/microcode_amd.h
> > @@ -64,7 +64,7 @@ extern enum ucode_state load_microcode_amd(int cpu, const u8 *data, size_t size)
> > #ifdef CONFIG_MICROCODE_AMD_EARLY
> > #ifdef CONFIG_X86_32
> > #define MPB_MAX_SIZE PAGE_SIZE
> > -extern u8 __cpuinitdata amd_bsp_mpb[MPB_MAX_SIZE];
> > +extern u8 amd_bsp_mpb[MPB_MAX_SIZE];
> > #endif
> > extern void __init load_ucode_amd_bsp(void);
> > extern void __cpuinit load_ucode_amd_ap(void);
> > diff --git a/arch/x86/kernel/microcode_amd_early.c b/arch/x86/kernel/microcode_amd_early.c
> > index 7e54d97..9618805 100644
> > --- a/arch/x86/kernel/microcode_amd_early.c
> > +++ b/arch/x86/kernel/microcode_amd_early.c
> > @@ -21,9 +21,9 @@ static u32 ucode_new_rev;
> > * Microcode patch container file is prepended to the initrd in cpio format.
> > * See Documentation/x86/early-microcode.txt
> > */
> > -static __initdata char ucode_path[] = "kernel/x86/microcode/AuthenticAMD.bin";
> > +static __cpuinitdata char ucode_path[] = "kernel/x86/microcode/AuthenticAMD.bin";
> >
> > -static struct cpio_data __init find_ucode_in_initrd(void)
> > +static struct cpio_data __cpuinit find_ucode_in_initrd(void)
> > {
> > long offset = 0;
> > struct cpio_data cd;
>
> does not like right fix.
>
> find_ucode_in_initrd should be __init.
>
> > @@ -62,7 +62,7 @@ static struct cpio_data __init find_ucode_in_initrd(void)
> > * load_microcode_amd() to save equivalent cpu table and microcode patches in
> > * kernel heap memory.
> > */
> > -static void __init apply_ucode_in_initrd(void)
> > +static void __cpuinit apply_ucode_in_initrd(void)
> > {
> > struct cpio_data cd;
> > struct equiv_cpu_entry *eq;
>
> it should not call find_ucode_in_initrd or
> it should be __init.
It's because the load_ucode_amd_ap() (which is __cpuinit because it
can be called during CPU hotplug on).
Hm.. but yes, I do agree with you, I'm waiting for feedback on this
follow up patch to allow multiple concatanated microcode files:
https://lkml.org/lkml/2013/5/31/664
I'll submit multi-patch patchset to address your feedback as well.
Thank you,
On Tue, Jun 04, 2013 at 04:36:00PM -0500, Jacob Shin wrote:
> On Tue, Jun 04, 2013 at 02:02:43PM -0700, Yinghai Lu wrote:
> > On Fri, May 31, 2013 at 2:59 PM, tip-bot for Jacob Shin
> > <[email protected]> wrote:
> > > Commit-ID: 6b3389ac21b5e557b957f1497d0ff22bf733e8c3
> > > Gitweb: http://git.kernel.org/tip/6b3389ac21b5e557b957f1497d0ff22bf733e8c3
> > > Author: Jacob Shin <[email protected]>
> > > AuthorDate: Fri, 31 May 2013 01:53:24 -0500
> > > Committer: H. Peter Anvin <[email protected]>
> > > CommitDate: Fri, 31 May 2013 13:56:58 -0700
> > >
> > > x86, microcode, amd: Fix warnings and errors on with CONFIG_MICROCODE=m
> > >
> > > Fix section mismatch warnings on microcode_amd_early.
> > > Compile error occurs when CONFIG_MICROCODE=m, change so that early
> > > loading depends on microcode_core.
> > >
> > > Reported-by: Yinghai Lu <[email protected]>
> > > Reported-by: Borislav Petkov <[email protected]>
> > > Signed-off-by: Jacob Shin <[email protected]>
> > > Link: http://lkml.kernel.org/r/20130531150241.GA12006@jshin-Toonie
> > > Signed-off-by: H. Peter Anvin <[email protected]>
> > > ---
> > > arch/x86/Kconfig | 2 +-
> > > arch/x86/include/asm/microcode_amd.h | 2 +-
> > > arch/x86/kernel/microcode_amd_early.c | 8 ++++----
> > > 3 files changed, 6 insertions(+), 6 deletions(-)
> > >
> > > diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
> > > index 28dba52..2705532 100644
> > > --- a/arch/x86/Kconfig
> > > +++ b/arch/x86/Kconfig
> > > @@ -1065,7 +1065,7 @@ config MICROCODE_AMD_EARLY
> > >
> > > config MICROCODE_EARLY
> > > bool "Early load microcode"
> > > - depends on (MICROCODE_INTEL || MICROCODE_AMD) && BLK_DEV_INITRD
> > > + depends on MICROCODE=y && BLK_DEV_INITRD
> > > select MICROCODE_INTEL_EARLY if MICROCODE_INTEL
> > > select MICROCODE_AMD_EARLY if MICROCODE_AMD
> > > default y
> > > diff --git a/arch/x86/include/asm/microcode_amd.h b/arch/x86/include/asm/microcode_amd.h
> > > index 24254aa..c6b043f 100644
> > > --- a/arch/x86/include/asm/microcode_amd.h
> > > +++ b/arch/x86/include/asm/microcode_amd.h
> > > @@ -64,7 +64,7 @@ extern enum ucode_state load_microcode_amd(int cpu, const u8 *data, size_t size)
> > > #ifdef CONFIG_MICROCODE_AMD_EARLY
> > > #ifdef CONFIG_X86_32
> > > #define MPB_MAX_SIZE PAGE_SIZE
> > > -extern u8 __cpuinitdata amd_bsp_mpb[MPB_MAX_SIZE];
> > > +extern u8 amd_bsp_mpb[MPB_MAX_SIZE];
> > > #endif
> > > extern void __init load_ucode_amd_bsp(void);
> > > extern void __cpuinit load_ucode_amd_ap(void);
> > > diff --git a/arch/x86/kernel/microcode_amd_early.c b/arch/x86/kernel/microcode_amd_early.c
> > > index 7e54d97..9618805 100644
> > > --- a/arch/x86/kernel/microcode_amd_early.c
> > > +++ b/arch/x86/kernel/microcode_amd_early.c
> > > @@ -21,9 +21,9 @@ static u32 ucode_new_rev;
> > > * Microcode patch container file is prepended to the initrd in cpio format.
> > > * See Documentation/x86/early-microcode.txt
> > > */
> > > -static __initdata char ucode_path[] = "kernel/x86/microcode/AuthenticAMD.bin";
> > > +static __cpuinitdata char ucode_path[] = "kernel/x86/microcode/AuthenticAMD.bin";
> > >
> > > -static struct cpio_data __init find_ucode_in_initrd(void)
> > > +static struct cpio_data __cpuinit find_ucode_in_initrd(void)
> > > {
> > > long offset = 0;
> > > struct cpio_data cd;
> >
> > does not like right fix.
> >
> > find_ucode_in_initrd should be __init.
> >
> > > @@ -62,7 +62,7 @@ static struct cpio_data __init find_ucode_in_initrd(void)
> > > * load_microcode_amd() to save equivalent cpu table and microcode patches in
> > > * kernel heap memory.
> > > */
> > > -static void __init apply_ucode_in_initrd(void)
> > > +static void __cpuinit apply_ucode_in_initrd(void)
> > > {
> > > struct cpio_data cd;
> > > struct equiv_cpu_entry *eq;
> >
> > it should not call find_ucode_in_initrd or
> > it should be __init.
>
> It's because the load_ucode_amd_ap() (which is __cpuinit because it
> can be called during CPU hotplug on).
Sorry, let me clarify. find_ucode_in_initrd() is called by
load_ucode_amd_ap() during cold boot. However, since
load_ucode_amd_ap() is also called during suspend/resume (CPU hotplug)
it has to be __cpuinit. Of course during suspend/resume code path,
find_ucode_in_initrd() is not called, since it is no longer there in memory.
>
> Hm.. but yes, I do agree with you, I'm waiting for feedback on this
> follow up patch to allow multiple concatanated microcode files:
>
> https://lkml.org/lkml/2013/5/31/664
>
> I'll submit multi-patch patchset to address your feedback as well.
>
> Thank you,
On Tue, Jun 4, 2013 at 2:55 PM, Jacob Shin <[email protected]> wrote:
> On Tue, Jun 04, 2013 at 04:36:00PM -0500, Jacob Shin wrote:
>>
>> It's because the load_ucode_amd_ap() (which is __cpuinit because it
>> can be called during CPU hotplug on).
>
> Sorry, let me clarify. find_ucode_in_initrd() is called by
> load_ucode_amd_ap() during cold boot. However, since
> load_ucode_amd_ap() is also called during suspend/resume (CPU hotplug)
> it has to be __cpuinit. Of course during suspend/resume code path,
> find_ucode_in_initrd() is not called, since it is no longer there in memory.
>
>>
>> Hm.. but yes, I do agree with you, I'm waiting for feedback on this
>> follow up patch to allow multiple concatanated microcode files:
>>
>> https://lkml.org/lkml/2013/5/31/664
>>
>> I'll submit multi-patch patchset to address your feedback as well.
Those microcode should be with initrd.
During first BP finding and apply it, it is still with initrd that is loaded by
bootloader.
then kernel may move the initrd to mapped range.
then AP will use those moved blob or saved blob during booting path and
hot-add path.
so the find_.._in_initrd should be __init and you just need one pointer
to the blob original or moved.
Thanks
Yinghai
On Fri, May 31, 2013 at 08:15:12PM -0500, Jacob Shin wrote:
> Any thoughts on this Boris?
Looks ok to me - I'm assuming you're testing all this new code on all
families...?
Thanks.
--
Regards/Gruss,
Boris.
Sent from a fat crate under my desk. Formatting is fine.
--
On Thu, Jun 06, 2013 at 12:10:42AM +0200, Borislav Petkov wrote:
> On Fri, May 31, 2013 at 08:15:12PM -0500, Jacob Shin wrote:
> > Any thoughts on this Boris?
>
> Looks ok to me - I'm assuming you're testing all this new code on all
> families...?
Thanks, I have sent out a V2 of this patch. This time I remembered to
CC you on it :-) (sorry about V1)
Yes the new early load bits have been tested on variety of families,
and also 32 vs 64 bits, loading on cold boot vs suspend/resume, single
family container file vs multiple container files appended together,
.. etc.