x86/microcode: Merge the early microcode loader
authorBorislav Petkov <bp@suse.de>
Tue, 20 Oct 2015 09:54:45 +0000 (11:54 +0200)
committerIngo Molnar <mingo@kernel.org>
Wed, 21 Oct 2015 09:22:12 +0000 (11:22 +0200)
Merge the early loader functionality into the driver proper. The
diff is huge but logically, it is simply moving code from the
_early.c files into the main driver.

Signed-off-by: Borislav Petkov <bp@suse.de>
Cc: Andy Lutomirski <luto@amacapital.net>
Cc: Arjan van de Ven <arjan@linux.intel.com>
Cc: Borislav Petkov <bp@alien8.de>
Cc: Brian Gerst <brgerst@gmail.com>
Cc: Dave Jones <davej@codemonkey.org.uk>
Cc: Denys Vlasenko <dvlasenk@redhat.com>
Cc: H. Peter Anvin <hpa@zytor.com>
Cc: Len Brown <len.brown@intel.com>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: Tony Luck <tony.luck@intel.com>
Link: http://lkml.kernel.org/r/1445334889-300-3-git-send-email-bp@alien8.de
Signed-off-by: Ingo Molnar <mingo@kernel.org>
13 files changed:
arch/x86/Kconfig
arch/x86/include/asm/microcode.h
arch/x86/include/asm/microcode_amd.h
arch/x86/include/asm/microcode_intel.h
arch/x86/kernel/cpu/microcode/Makefile
arch/x86/kernel/cpu/microcode/amd.c
arch/x86/kernel/cpu/microcode/amd_early.c [deleted file]
arch/x86/kernel/cpu/microcode/core.c
arch/x86/kernel/cpu/microcode/core_early.c [deleted file]
arch/x86/kernel/cpu/microcode/intel.c
arch/x86/kernel/cpu/microcode/intel_early.c [deleted file]
arch/x86/kernel/head_32.S
arch/x86/mm/init.c

index fdf1f0cdf6b673d181f1fe05cf8374d1c330c31e..255ea22ccbec509ead6325098863a50587ecae99 100644 (file)
@@ -1126,6 +1126,7 @@ config MICROCODE
        bool "CPU microcode loading support"
        default y
        depends on CPU_SUP_AMD || CPU_SUP_INTEL
+       depends on BLK_DEV_INITRD
        select FW_LOADER
        ---help---
 
@@ -1167,24 +1168,6 @@ config MICROCODE_OLD_INTERFACE
        def_bool y
        depends on MICROCODE
 
-config MICROCODE_INTEL_EARLY
-       bool
-
-config MICROCODE_AMD_EARLY
-       bool
-
-config MICROCODE_EARLY
-       bool "Early load microcode"
-       depends on MICROCODE && 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
-         at the beginning of initrd image. The data tells kernel to load
-         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 X86_MSR
        tristate "/dev/cpu/*/msr - Model-specific register support"
        ---help---
index d1ff724f352bcc1d87787612532399848d88b1ab..9f953f7851bb608fa5980854fc51f2805fd0204c 100644 (file)
@@ -81,7 +81,6 @@ static inline struct microcode_ops * __init init_amd_microcode(void)
 static inline void __exit exit_amd_microcode(void) {}
 #endif
 
-#ifdef CONFIG_MICROCODE_EARLY
 #define MAX_UCODE_COUNT 128
 
 #define QCHAR(a, b, c, d) ((a) + ((b) << 8) + ((c) << 16) + ((d) << 24))
@@ -156,22 +155,18 @@ static inline unsigned int x86_model(unsigned int sig)
        return model;
 }
 
+#ifdef CONFIG_MICROCODE
 extern void __init load_ucode_bsp(void);
 extern void load_ucode_ap(void);
 extern int __init save_microcode_in_initrd(void);
 void reload_early_microcode(void);
 extern bool get_builtin_firmware(struct cpio_data *cd, const char *name);
 #else
-static inline void __init load_ucode_bsp(void) {}
-static inline void load_ucode_ap(void) {}
-static inline int __init save_microcode_in_initrd(void)
-{
-       return 0;
-}
-static inline void reload_early_microcode(void) {}
-static inline bool get_builtin_firmware(struct cpio_data *cd, const char *name)
-{
-       return false;
-}
+static inline void __init load_ucode_bsp(void)                 { }
+static inline void load_ucode_ap(void)                         { }
+static inline int __init save_microcode_in_initrd(void)                { return 0; }
+static inline void reload_early_microcode(void)                        { }
+static inline bool
+get_builtin_firmware(struct cpio_data *cd, const char *name)   { return false; }
 #endif
 #endif /* _ASM_X86_MICROCODE_H */
index d3e86cfd08fe607818955c7b5ec7a84c4e3f9fe0..adfc847a395ec2d94e4d46993379a0a7a77f59e0 100644 (file)
@@ -64,7 +64,7 @@ extern enum ucode_state load_microcode_amd(int cpu, u8 family, const u8 *data, s
 #define PATCH_MAX_SIZE PAGE_SIZE
 extern u8 amd_ucode_patch[PATCH_MAX_SIZE];
 
-#ifdef CONFIG_MICROCODE_AMD_EARLY
+#ifdef CONFIG_MICROCODE_AMD
 extern void __init load_ucode_amd_bsp(unsigned int family);
 extern void load_ucode_amd_ap(void);
 extern int __init save_microcode_in_initrd_amd(void);
index 7991c606125d01b137a6f0e1ed16f1e8c1d86015..8559b0102ea1f14dfc840c28df6e1fcc0f813965 100644 (file)
@@ -57,7 +57,7 @@ extern int has_newer_microcode(void *mc, unsigned int csig, int cpf, int rev);
 extern int microcode_sanity_check(void *mc, int print_err);
 extern int find_matching_signature(void *mc, unsigned int csig, int cpf);
 
-#ifdef CONFIG_MICROCODE_INTEL_EARLY
+#ifdef CONFIG_MICROCODE_INTEL
 extern void __init load_ucode_intel_bsp(void);
 extern void load_ucode_intel_ap(void);
 extern void show_ucode_info_early(void);
@@ -71,13 +71,9 @@ static inline int __init save_microcode_in_initrd_intel(void) { return -EINVAL;
 static inline void reload_ucode_intel(void) {}
 #endif
 
-#if defined(CONFIG_MICROCODE_INTEL_EARLY) && defined(CONFIG_HOTPLUG_CPU)
+#ifdef CONFIG_HOTPLUG_CPU
 extern int save_mc_for_early(u8 *mc);
 #else
-static inline int save_mc_for_early(u8 *mc)
-{
-       return 0;
-}
+static inline int save_mc_for_early(u8 *mc) { return 0; }
 #endif
-
 #endif /* _ASM_X86_MICROCODE_INTEL_H */
index 285c85427c323c8e33abc8a4dfc0436123143de7..220b1a50851345632c3f5c1ca4f0e3cbb40d02a0 100644 (file)
@@ -2,6 +2,3 @@ microcode-y                             := core.o
 obj-$(CONFIG_MICROCODE)                        += microcode.o
 microcode-$(CONFIG_MICROCODE_INTEL)    += intel.o intel_lib.o
 microcode-$(CONFIG_MICROCODE_AMD)      += amd.o
-obj-$(CONFIG_MICROCODE_EARLY)          += core_early.o
-obj-$(CONFIG_MICROCODE_INTEL_EARLY)    += intel_early.o
-obj-$(CONFIG_MICROCODE_AMD_EARLY)      += amd_early.o
index 5dcce5dc39b9e21124104c5d40a250c4f2c53749..20297fbb7355f42a5d72822e455ca9d0cb5c1e04 100644 (file)
@@ -1,5 +1,9 @@
 /*
  *  AMD CPU Microcode Update Driver for Linux
+ *
+ *  This driver allows to upgrade microcode on F10h AMD
+ *  CPUs and later.
+ *
  *  Copyright (C) 2008-2011 Advanced Micro Devices Inc.
  *
  *  Author: Peter Oruba <peter.oruba@amd.com>
  *  Andreas Herrmann <herrmann.der.user@googlemail.com>
  *  Borislav Petkov <bp@alien8.de>
  *
- *  This driver allows to upgrade microcode on F10h AMD
- *  CPUs and later.
+ *  early loader:
+ *  Copyright (C) 2013 Advanced Micro Devices, Inc.
+ *
+ *  Author: Jacob Shin <jacob.shin@amd.com>
+ *  Fixes: Borislav Petkov <bp@suse.de>
  *
  *  Licensed under the terms of the GNU General Public
  *  License version 2. See file COPYING for details.
  */
-
 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
 
+#include <linux/earlycpio.h>
 #include <linux/firmware.h>
 #include <linux/uaccess.h>
 #include <linux/vmalloc.h>
+#include <linux/initrd.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/pci.h>
 
+#include <asm/microcode_amd.h>
 #include <asm/microcode.h>
 #include <asm/processor.h>
+#include <asm/setup.h>
+#include <asm/cpu.h>
 #include <asm/msr.h>
-#include <asm/microcode_amd.h>
 
 MODULE_DESCRIPTION("AMD Microcode Update Driver");
 MODULE_AUTHOR("Peter Oruba");
@@ -47,6 +57,432 @@ struct ucode_patch {
 
 static LIST_HEAD(pcache);
 
+/*
+ * This points to the current valid container of microcode patches which we will
+ * save from the initrd before jettisoning its contents.
+ */
+static u8 *container;
+static size_t container_size;
+
+static u32 ucode_new_rev;
+u8 amd_ucode_patch[PATCH_MAX_SIZE];
+static u16 this_equiv_id;
+
+static struct cpio_data ucode_cpio;
+
+/*
+ * 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;
+       char *path;
+       void *start;
+       size_t size;
+
+#ifdef CONFIG_X86_32
+       struct boot_params *p;
+
+       /*
+        * On 32-bit, early load occurs before paging is turned on so we need
+        * to use physical addresses.
+        */
+       p       = (struct boot_params *)__pa_nodebug(&boot_params);
+       path    = (char *)__pa_nodebug(ucode_path);
+       start   = (void *)p->hdr.ramdisk_image;
+       size    = p->hdr.ramdisk_size;
+#else
+       path    = ucode_path;
+       start   = (void *)(boot_params.hdr.ramdisk_image + PAGE_OFFSET);
+       size    = boot_params.hdr.ramdisk_size;
+#endif
+
+       return find_cpio_data(path, start, size, &offset);
+}
+
+static size_t compute_container_size(u8 *data, u32 total_size)
+{
+       size_t size = 0;
+       u32 *header = (u32 *)data;
+
+       if (header[0] != UCODE_MAGIC ||
+           header[1] != UCODE_EQUIV_CPU_TABLE_TYPE || /* type */
+           header[2] == 0)                            /* size */
+               return size;
+
+       size = header[2] + CONTAINER_HDR_SZ;
+       total_size -= size;
+       data += size;
+
+       while (total_size) {
+               u16 patch_size;
+
+               header = (u32 *)data;
+
+               if (header[0] != UCODE_UCODE_TYPE)
+                       break;
+
+               /*
+                * Sanity-check patch size.
+                */
+               patch_size = header[1];
+               if (patch_size > PATCH_MAX_SIZE)
+                       break;
+
+               size       += patch_size + SECTION_HDR_SIZE;
+               data       += patch_size + SECTION_HDR_SIZE;
+               total_size -= patch_size + SECTION_HDR_SIZE;
+       }
+
+       return size;
+}
+
+/*
+ * 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 apply_ucode_in_initrd(void *ucode, size_t size, bool save_patch)
+{
+       struct equiv_cpu_entry *eq;
+       size_t *cont_sz;
+       u32 *header;
+       u8  *data, **cont;
+       u8 (*patch)[PATCH_MAX_SIZE];
+       u16 eq_id = 0;
+       int offset, left;
+       u32 rev, eax, ebx, ecx, edx;
+       u32 *new_rev;
+
+#ifdef CONFIG_X86_32
+       new_rev = (u32 *)__pa_nodebug(&ucode_new_rev);
+       cont_sz = (size_t *)__pa_nodebug(&container_size);
+       cont    = (u8 **)__pa_nodebug(&container);
+       patch   = (u8 (*)[PATCH_MAX_SIZE])__pa_nodebug(&amd_ucode_patch);
+#else
+       new_rev = &ucode_new_rev;
+       cont_sz = &container_size;
+       cont    = &container;
+       patch   = &amd_ucode_patch;
+#endif
+
+       data   = ucode;
+       left   = size;
+       header = (u32 *)data;
+
+       /* find equiv cpu table */
+       if (header[0] != UCODE_MAGIC ||
+           header[1] != UCODE_EQUIV_CPU_TABLE_TYPE || /* type */
+           header[2] == 0)                            /* size */
+               return;
+
+       eax = 0x00000001;
+       ecx = 0;
+       native_cpuid(&eax, &ebx, &ecx, &edx);
+
+       while (left > 0) {
+               eq = (struct equiv_cpu_entry *)(data + CONTAINER_HDR_SZ);
+
+               *cont = data;
+
+               /* Advance past the container header */
+               offset = header[2] + CONTAINER_HDR_SZ;
+               data  += offset;
+               left  -= offset;
+
+               eq_id = find_equiv_id(eq, eax);
+               if (eq_id) {
+                       this_equiv_id = eq_id;
+                       *cont_sz = compute_container_size(*cont, left + offset);
+
+                       /*
+                        * truncate how much we need to iterate over in the
+                        * ucode update loop below
+                        */
+                       left = *cont_sz - offset;
+                       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;
+               }
+
+               /* mark where the next microcode container file starts */
+               offset    = data - (u8 *)ucode;
+               ucode     = data;
+       }
+
+       if (!eq_id) {
+               *cont = NULL;
+               *cont_sz = 0;
+               return;
+       }
+
+       if (check_current_patch_level(&rev, true))
+               return;
+
+       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)) {
+                               rev = mc->hdr.patch_id;
+                               *new_rev = rev;
+
+                               if (save_patch)
+                                       memcpy(patch, mc,
+                                              min_t(u32, header[1], PATCH_MAX_SIZE));
+                       }
+               }
+
+               offset  = header[1] + SECTION_HDR_SIZE;
+               data   += offset;
+               left   -= offset;
+       }
+}
+
+static bool __init load_builtin_amd_microcode(struct cpio_data *cp,
+                                             unsigned int family)
+{
+#ifdef CONFIG_X86_64
+       char fw_name[36] = "amd-ucode/microcode_amd.bin";
+
+       if (family >= 0x15)
+               snprintf(fw_name, sizeof(fw_name),
+                        "amd-ucode/microcode_amd_fam%.2xh.bin", family);
+
+       return get_builtin_firmware(cp, fw_name);
+#else
+       return false;
+#endif
+}
+
+void __init load_ucode_amd_bsp(unsigned int family)
+{
+       struct cpio_data cp;
+       void **data;
+       size_t *size;
+
+#ifdef CONFIG_X86_32
+       data =  (void **)__pa_nodebug(&ucode_cpio.data);
+       size = (size_t *)__pa_nodebug(&ucode_cpio.size);
+#else
+       data = &ucode_cpio.data;
+       size = &ucode_cpio.size;
+#endif
+
+       cp = find_ucode_in_initrd();
+       if (!cp.data) {
+               if (!load_builtin_amd_microcode(&cp, family))
+                       return;
+       }
+
+       *data = cp.data;
+       *size = cp.size;
+
+       apply_ucode_in_initrd(cp.data, cp.size, true);
+}
+
+#ifdef CONFIG_X86_32
+/*
+ * 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_ucode_patch,
+ * which is used upon resume from suspend.
+ */
+void load_ucode_amd_ap(void)
+{
+       struct microcode_amd *mc;
+       size_t *usize;
+       void **ucode;
+
+       mc = (struct microcode_amd *)__pa_nodebug(amd_ucode_patch);
+       if (mc->hdr.patch_id && mc->hdr.processor_rev_id) {
+               __apply_microcode_amd(mc);
+               return;
+       }
+
+       ucode = (void *)__pa_nodebug(&container);
+       usize = (size_t *)__pa_nodebug(&container_size);
+
+       if (!*ucode || !*usize)
+               return;
+
+       apply_ucode_in_initrd(*ucode, *usize, false);
+}
+
+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);
+}
+
+static void __init get_bsp_sig(void)
+{
+       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);
+}
+#else
+void load_ucode_amd_ap(void)
+{
+       unsigned int cpu = smp_processor_id();
+       struct equiv_cpu_entry *eq;
+       struct microcode_amd *mc;
+       u32 rev, eax;
+       u16 eq_id;
+
+       /* Exit if called on the BSP. */
+       if (!cpu)
+               return;
+
+       if (!container)
+               return;
+
+       /*
+        * 64-bit runs with paging enabled, thus early==false.
+        */
+       if (check_current_patch_level(&rev, false))
+               return;
+
+       eax = cpuid_eax(0x00000001);
+       eq  = (struct equiv_cpu_entry *)(container + CONTAINER_HDR_SZ);
+
+       eq_id = find_equiv_id(eq, eax);
+       if (!eq_id)
+               return;
+
+       if (eq_id == this_equiv_id) {
+               mc = (struct microcode_amd *)amd_ucode_patch;
+
+               if (mc && rev < mc->hdr.patch_id) {
+                       if (!__apply_microcode_amd(mc))
+                               ucode_new_rev = mc->hdr.patch_id;
+               }
+
+       } else {
+               if (!ucode_cpio.data)
+                       return;
+
+               /*
+                * AP has a different equivalence ID than BSP, looks like
+                * mixed-steppings silicon so go through the ucode blob anew.
+                */
+               apply_ucode_in_initrd(ucode_cpio.data, ucode_cpio.size, false);
+       }
+}
+#endif
+
+int __init save_microcode_in_initrd_amd(void)
+{
+       unsigned long cont;
+       int retval = 0;
+       enum ucode_state ret;
+       u8 *cont_va;
+       u32 eax;
+
+       if (!container)
+               return -EINVAL;
+
+#ifdef CONFIG_X86_32
+       get_bsp_sig();
+       cont    = (unsigned long)container;
+       cont_va = __va(container);
+#else
+       /*
+        * We need the physical address of the container for both bitness since
+        * boot_params.hdr.ramdisk_image is a physical address.
+        */
+       cont    = __pa(container);
+       cont_va = container;
+#endif
+
+       /*
+        * Take into account the fact that the ramdisk might get relocated and
+        * therefore we need to recompute the container's position in virtual
+        * memory space.
+        */
+       if (relocated_ramdisk)
+               container = (u8 *)(__va(relocated_ramdisk) +
+                            (cont - boot_params.hdr.ramdisk_image));
+       else
+               container = cont_va;
+
+       if (ucode_new_rev)
+               pr_info("microcode: updated early to new patch_level=0x%08x\n",
+                       ucode_new_rev);
+
+       eax   = cpuid_eax(0x00000001);
+       eax   = ((eax >> 8) & 0xf) + ((eax >> 20) & 0xff);
+
+       ret = load_microcode_amd(smp_processor_id(), eax, container, container_size);
+       if (ret != UCODE_OK)
+               retval = -EINVAL;
+
+       /*
+        * This will be freed any msec now, stash patches for the current
+        * family and switch to patch cache for cpu hotplug, etc later.
+        */
+       container = NULL;
+       container_size = 0;
+
+       return retval;
+}
+
+void reload_ucode_amd(void)
+{
+       struct microcode_amd *mc;
+       u32 rev;
+
+       /*
+        * early==false because this is a syscore ->resume path and by
+        * that time paging is long enabled.
+        */
+       if (check_current_patch_level(&rev, false))
+               return;
+
+       mc = (struct microcode_amd *)amd_ucode_patch;
+
+       if (mc && rev < mc->hdr.patch_id) {
+               if (!__apply_microcode_amd(mc)) {
+                       ucode_new_rev = mc->hdr.patch_id;
+                       pr_info("microcode: reload patch_level=0x%08x\n",
+                               ucode_new_rev);
+               }
+       }
+}
 static u16 __find_equiv_id(unsigned int cpu)
 {
        struct ucode_cpu_info *uci = ucode_cpu_info + cpu;
@@ -435,7 +871,7 @@ enum ucode_state load_microcode_amd(int cpu, u8 family, const u8 *data, size_t s
        if (ret != UCODE_OK)
                cleanup();
 
-#if defined(CONFIG_MICROCODE_AMD_EARLY) && defined(CONFIG_X86_32)
+#ifdef 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);
diff --git a/arch/x86/kernel/cpu/microcode/amd_early.c b/arch/x86/kernel/cpu/microcode/amd_early.c
deleted file mode 100644 (file)
index a54a47b..0000000
+++ /dev/null
@@ -1,444 +0,0 @@
-/*
- * Copyright (C) 2013 Advanced Micro Devices, Inc.
- *
- * Author: Jacob Shin <jacob.shin@amd.com>
- * Fixes: Borislav Petkov <bp@suse.de>
- *
- * 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 <linux/initrd.h>
-
-#include <asm/cpu.h>
-#include <asm/setup.h>
-#include <asm/microcode_amd.h>
-
-/*
- * This points to the current valid container of microcode patches which we will
- * save from the initrd before jettisoning its contents.
- */
-static u8 *container;
-static size_t container_size;
-
-static u32 ucode_new_rev;
-u8 amd_ucode_patch[PATCH_MAX_SIZE];
-static u16 this_equiv_id;
-
-static struct cpio_data ucode_cpio;
-
-/*
- * 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;
-       char *path;
-       void *start;
-       size_t size;
-
-#ifdef CONFIG_X86_32
-       struct boot_params *p;
-
-       /*
-        * On 32-bit, early load occurs before paging is turned on so we need
-        * to use physical addresses.
-        */
-       p       = (struct boot_params *)__pa_nodebug(&boot_params);
-       path    = (char *)__pa_nodebug(ucode_path);
-       start   = (void *)p->hdr.ramdisk_image;
-       size    = p->hdr.ramdisk_size;
-#else
-       path    = ucode_path;
-       start   = (void *)(boot_params.hdr.ramdisk_image + PAGE_OFFSET);
-       size    = boot_params.hdr.ramdisk_size;
-#endif
-
-       return find_cpio_data(path, start, size, &offset);
-}
-
-static size_t compute_container_size(u8 *data, u32 total_size)
-{
-       size_t size = 0;
-       u32 *header = (u32 *)data;
-
-       if (header[0] != UCODE_MAGIC ||
-           header[1] != UCODE_EQUIV_CPU_TABLE_TYPE || /* type */
-           header[2] == 0)                            /* size */
-               return size;
-
-       size = header[2] + CONTAINER_HDR_SZ;
-       total_size -= size;
-       data += size;
-
-       while (total_size) {
-               u16 patch_size;
-
-               header = (u32 *)data;
-
-               if (header[0] != UCODE_UCODE_TYPE)
-                       break;
-
-               /*
-                * Sanity-check patch size.
-                */
-               patch_size = header[1];
-               if (patch_size > PATCH_MAX_SIZE)
-                       break;
-
-               size       += patch_size + SECTION_HDR_SIZE;
-               data       += patch_size + SECTION_HDR_SIZE;
-               total_size -= patch_size + SECTION_HDR_SIZE;
-       }
-
-       return size;
-}
-
-/*
- * 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 apply_ucode_in_initrd(void *ucode, size_t size, bool save_patch)
-{
-       struct equiv_cpu_entry *eq;
-       size_t *cont_sz;
-       u32 *header;
-       u8  *data, **cont;
-       u8 (*patch)[PATCH_MAX_SIZE];
-       u16 eq_id = 0;
-       int offset, left;
-       u32 rev, eax, ebx, ecx, edx;
-       u32 *new_rev;
-
-#ifdef CONFIG_X86_32
-       new_rev = (u32 *)__pa_nodebug(&ucode_new_rev);
-       cont_sz = (size_t *)__pa_nodebug(&container_size);
-       cont    = (u8 **)__pa_nodebug(&container);
-       patch   = (u8 (*)[PATCH_MAX_SIZE])__pa_nodebug(&amd_ucode_patch);
-#else
-       new_rev = &ucode_new_rev;
-       cont_sz = &container_size;
-       cont    = &container;
-       patch   = &amd_ucode_patch;
-#endif
-
-       data   = ucode;
-       left   = size;
-       header = (u32 *)data;
-
-       /* find equiv cpu table */
-       if (header[0] != UCODE_MAGIC ||
-           header[1] != UCODE_EQUIV_CPU_TABLE_TYPE || /* type */
-           header[2] == 0)                            /* size */
-               return;
-
-       eax = 0x00000001;
-       ecx = 0;
-       native_cpuid(&eax, &ebx, &ecx, &edx);
-
-       while (left > 0) {
-               eq = (struct equiv_cpu_entry *)(data + CONTAINER_HDR_SZ);
-
-               *cont = data;
-
-               /* Advance past the container header */
-               offset = header[2] + CONTAINER_HDR_SZ;
-               data  += offset;
-               left  -= offset;
-
-               eq_id = find_equiv_id(eq, eax);
-               if (eq_id) {
-                       this_equiv_id = eq_id;
-                       *cont_sz = compute_container_size(*cont, left + offset);
-
-                       /*
-                        * truncate how much we need to iterate over in the
-                        * ucode update loop below
-                        */
-                       left = *cont_sz - offset;
-                       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;
-               }
-
-               /* mark where the next microcode container file starts */
-               offset    = data - (u8 *)ucode;
-               ucode     = data;
-       }
-
-       if (!eq_id) {
-               *cont = NULL;
-               *cont_sz = 0;
-               return;
-       }
-
-       if (check_current_patch_level(&rev, true))
-               return;
-
-       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)) {
-                               rev = mc->hdr.patch_id;
-                               *new_rev = rev;
-
-                               if (save_patch)
-                                       memcpy(patch, mc,
-                                              min_t(u32, header[1], PATCH_MAX_SIZE));
-                       }
-               }
-
-               offset  = header[1] + SECTION_HDR_SIZE;
-               data   += offset;
-               left   -= offset;
-       }
-}
-
-static bool __init load_builtin_amd_microcode(struct cpio_data *cp,
-                                             unsigned int family)
-{
-#ifdef CONFIG_X86_64
-       char fw_name[36] = "amd-ucode/microcode_amd.bin";
-
-       if (family >= 0x15)
-               snprintf(fw_name, sizeof(fw_name),
-                        "amd-ucode/microcode_amd_fam%.2xh.bin", family);
-
-       return get_builtin_firmware(cp, fw_name);
-#else
-       return false;
-#endif
-}
-
-void __init load_ucode_amd_bsp(unsigned int family)
-{
-       struct cpio_data cp;
-       void **data;
-       size_t *size;
-
-#ifdef CONFIG_X86_32
-       data =  (void **)__pa_nodebug(&ucode_cpio.data);
-       size = (size_t *)__pa_nodebug(&ucode_cpio.size);
-#else
-       data = &ucode_cpio.data;
-       size = &ucode_cpio.size;
-#endif
-
-       cp = find_ucode_in_initrd();
-       if (!cp.data) {
-               if (!load_builtin_amd_microcode(&cp, family))
-                       return;
-       }
-
-       *data = cp.data;
-       *size = cp.size;
-
-       apply_ucode_in_initrd(cp.data, cp.size, true);
-}
-
-#ifdef CONFIG_X86_32
-/*
- * 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_ucode_patch,
- * which is used upon resume from suspend.
- */
-void load_ucode_amd_ap(void)
-{
-       struct microcode_amd *mc;
-       size_t *usize;
-       void **ucode;
-
-       mc = (struct microcode_amd *)__pa_nodebug(amd_ucode_patch);
-       if (mc->hdr.patch_id && mc->hdr.processor_rev_id) {
-               __apply_microcode_amd(mc);
-               return;
-       }
-
-       ucode = (void *)__pa_nodebug(&container);
-       usize = (size_t *)__pa_nodebug(&container_size);
-
-       if (!*ucode || !*usize)
-               return;
-
-       apply_ucode_in_initrd(*ucode, *usize, false);
-}
-
-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);
-}
-
-static void __init get_bsp_sig(void)
-{
-       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);
-}
-#else
-void load_ucode_amd_ap(void)
-{
-       unsigned int cpu = smp_processor_id();
-       struct equiv_cpu_entry *eq;
-       struct microcode_amd *mc;
-       u32 rev, eax;
-       u16 eq_id;
-
-       /* Exit if called on the BSP. */
-       if (!cpu)
-               return;
-
-       if (!container)
-               return;
-
-       /*
-        * 64-bit runs with paging enabled, thus early==false.
-        */
-       if (check_current_patch_level(&rev, false))
-               return;
-
-       eax = cpuid_eax(0x00000001);
-       eq  = (struct equiv_cpu_entry *)(container + CONTAINER_HDR_SZ);
-
-       eq_id = find_equiv_id(eq, eax);
-       if (!eq_id)
-               return;
-
-       if (eq_id == this_equiv_id) {
-               mc = (struct microcode_amd *)amd_ucode_patch;
-
-               if (mc && rev < mc->hdr.patch_id) {
-                       if (!__apply_microcode_amd(mc))
-                               ucode_new_rev = mc->hdr.patch_id;
-               }
-
-       } else {
-               if (!ucode_cpio.data)
-                       return;
-
-               /*
-                * AP has a different equivalence ID than BSP, looks like
-                * mixed-steppings silicon so go through the ucode blob anew.
-                */
-               apply_ucode_in_initrd(ucode_cpio.data, ucode_cpio.size, false);
-       }
-}
-#endif
-
-int __init save_microcode_in_initrd_amd(void)
-{
-       unsigned long cont;
-       int retval = 0;
-       enum ucode_state ret;
-       u8 *cont_va;
-       u32 eax;
-
-       if (!container)
-               return -EINVAL;
-
-#ifdef CONFIG_X86_32
-       get_bsp_sig();
-       cont    = (unsigned long)container;
-       cont_va = __va(container);
-#else
-       /*
-        * We need the physical address of the container for both bitness since
-        * boot_params.hdr.ramdisk_image is a physical address.
-        */
-       cont    = __pa(container);
-       cont_va = container;
-#endif
-
-       /*
-        * Take into account the fact that the ramdisk might get relocated and
-        * therefore we need to recompute the container's position in virtual
-        * memory space.
-        */
-       if (relocated_ramdisk)
-               container = (u8 *)(__va(relocated_ramdisk) +
-                            (cont - boot_params.hdr.ramdisk_image));
-       else
-               container = cont_va;
-
-       if (ucode_new_rev)
-               pr_info("microcode: updated early to new patch_level=0x%08x\n",
-                       ucode_new_rev);
-
-       eax   = cpuid_eax(0x00000001);
-       eax   = ((eax >> 8) & 0xf) + ((eax >> 20) & 0xff);
-
-       ret = load_microcode_amd(smp_processor_id(), eax, container, container_size);
-       if (ret != UCODE_OK)
-               retval = -EINVAL;
-
-       /*
-        * This will be freed any msec now, stash patches for the current
-        * family and switch to patch cache for cpu hotplug, etc later.
-        */
-       container = NULL;
-       container_size = 0;
-
-       return retval;
-}
-
-void reload_ucode_amd(void)
-{
-       struct microcode_amd *mc;
-       u32 rev;
-
-       /*
-        * early==false because this is a syscore ->resume path and by
-        * that time paging is long enabled.
-        */
-       if (check_current_patch_level(&rev, false))
-               return;
-
-       mc = (struct microcode_amd *)amd_ucode_patch;
-
-       if (mc && rev < mc->hdr.patch_id) {
-               if (!__apply_microcode_amd(mc)) {
-                       ucode_new_rev = mc->hdr.patch_id;
-                       pr_info("microcode: reload patch_level=0x%08x\n",
-                               ucode_new_rev);
-               }
-       }
-}
index 15491dd3131e6b68490186826f4d1e7b1b647381..18848c7de058f78d324867c95d71563d4d90c600 100644 (file)
@@ -5,6 +5,12 @@
  *           2006      Shaohua Li <shaohua.li@intel.com>
  *           2013-2015 Borislav Petkov <bp@alien8.de>
  *
+ * X86 CPU microcode early update for Linux:
+ *
+ *     Copyright (C) 2012 Fenghua Yu <fenghua.yu@intel.com>
+ *                        H Peter Anvin" <hpa@zytor.com>
+ *               (C) 2015 Borislav Petkov <bp@alien8.de>
+ *
  * This driver allows to upgrade microcode on x86 processors.
  *
  * This program is free software; you can redistribute it and/or
 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
 
 #include <linux/platform_device.h>
+#include <linux/syscore_ops.h>
 #include <linux/miscdevice.h>
 #include <linux/capability.h>
+#include <linux/firmware.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/mutex.h>
 #include <linux/cpu.h>
 #include <linux/fs.h>
 #include <linux/mm.h>
-#include <linux/syscore_ops.h>
 
-#include <asm/microcode.h>
-#include <asm/processor.h>
+#include <asm/microcode_intel.h>
 #include <asm/cpu_device_id.h>
+#include <asm/microcode_amd.h>
 #include <asm/perf_event.h>
+#include <asm/microcode.h>
+#include <asm/processor.h>
+#include <asm/cmdline.h>
 
 MODULE_DESCRIPTION("Microcode Update Driver");
 MODULE_AUTHOR("Tigran Aivazian <tigran@aivazian.fsnet.co.uk>");
@@ -68,6 +78,150 @@ struct cpu_info_ctx {
        int                     err;
 };
 
+static bool __init check_loader_disabled_bsp(void)
+{
+#ifdef CONFIG_X86_32
+       const char *cmdline = (const char *)__pa_nodebug(boot_command_line);
+       const char *opt     = "dis_ucode_ldr";
+       const char *option  = (const char *)__pa_nodebug(opt);
+       bool *res = (bool *)__pa_nodebug(&dis_ucode_ldr);
+
+#else /* CONFIG_X86_64 */
+       const char *cmdline = boot_command_line;
+       const char *option  = "dis_ucode_ldr";
+       bool *res = &dis_ucode_ldr;
+#endif
+
+       if (cmdline_find_option_bool(cmdline, option))
+               *res = true;
+
+       return *res;
+}
+
+extern struct builtin_fw __start_builtin_fw[];
+extern struct builtin_fw __end_builtin_fw[];
+
+bool get_builtin_firmware(struct cpio_data *cd, const char *name)
+{
+#ifdef CONFIG_FW_LOADER
+       struct builtin_fw *b_fw;
+
+       for (b_fw = __start_builtin_fw; b_fw != __end_builtin_fw; b_fw++) {
+               if (!strcmp(name, b_fw->name)) {
+                       cd->size = b_fw->size;
+                       cd->data = b_fw->data;
+                       return true;
+               }
+       }
+#endif
+       return false;
+}
+
+void __init load_ucode_bsp(void)
+{
+       int vendor;
+       unsigned int family;
+
+       if (check_loader_disabled_bsp())
+               return;
+
+       if (!have_cpuid_p())
+               return;
+
+       vendor = x86_vendor();
+       family = x86_family();
+
+       switch (vendor) {
+       case X86_VENDOR_INTEL:
+               if (family >= 6)
+                       load_ucode_intel_bsp();
+               break;
+       case X86_VENDOR_AMD:
+               if (family >= 0x10)
+                       load_ucode_amd_bsp(family);
+               break;
+       default:
+               break;
+       }
+}
+
+static bool check_loader_disabled_ap(void)
+{
+#ifdef CONFIG_X86_32
+       return *((bool *)__pa_nodebug(&dis_ucode_ldr));
+#else
+       return dis_ucode_ldr;
+#endif
+}
+
+void load_ucode_ap(void)
+{
+       int vendor, family;
+
+       if (check_loader_disabled_ap())
+               return;
+
+       if (!have_cpuid_p())
+               return;
+
+       vendor = x86_vendor();
+       family = x86_family();
+
+       switch (vendor) {
+       case X86_VENDOR_INTEL:
+               if (family >= 6)
+                       load_ucode_intel_ap();
+               break;
+       case X86_VENDOR_AMD:
+               if (family >= 0x10)
+                       load_ucode_amd_ap();
+               break;
+       default:
+               break;
+       }
+}
+
+int __init save_microcode_in_initrd(void)
+{
+       struct cpuinfo_x86 *c = &boot_cpu_data;
+
+       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;
+}
+
+void reload_early_microcode(void)
+{
+       int vendor, family;
+
+       vendor = x86_vendor();
+       family = x86_family();
+
+       switch (vendor) {
+       case X86_VENDOR_INTEL:
+               if (family >= 6)
+                       reload_ucode_intel();
+               break;
+       case X86_VENDOR_AMD:
+               if (family >= 0x10)
+                       reload_ucode_amd();
+               break;
+       default:
+               break;
+       }
+}
+
 static void collect_cpu_info_local(void *arg)
 {
        struct cpu_info_ctx *ctx = arg;
diff --git a/arch/x86/kernel/cpu/microcode/core_early.c b/arch/x86/kernel/cpu/microcode/core_early.c
deleted file mode 100644 (file)
index 8ebc421..0000000
+++ /dev/null
@@ -1,170 +0,0 @@
-/*
- *     X86 CPU microcode early update for Linux
- *
- *     Copyright (C) 2012 Fenghua Yu <fenghua.yu@intel.com>
- *                        H Peter Anvin" <hpa@zytor.com>
- *               (C) 2015 Borislav Petkov <bp@alien8.de>
- *
- *     This driver allows to early upgrade microcode on Intel processors
- *     belonging to IA-32 family - PentiumPro, Pentium II,
- *     Pentium III, Xeon, Pentium 4, etc.
- *
- *     Reference: Section 9.11 of Volume 3, IA-32 Intel Architecture
- *     Software Developer's Manual.
- *
- *     This program is free software; you can redistribute it and/or
- *     modify it under the terms of the GNU General Public License
- *     as published by the Free Software Foundation; either version
- *     2 of the License, or (at your option) any later version.
- */
-#include <linux/module.h>
-#include <linux/firmware.h>
-#include <asm/microcode.h>
-#include <asm/microcode_intel.h>
-#include <asm/microcode_amd.h>
-#include <asm/processor.h>
-#include <asm/cmdline.h>
-
-static bool __init check_loader_disabled_bsp(void)
-{
-#ifdef CONFIG_X86_32
-       const char *cmdline = (const char *)__pa_nodebug(boot_command_line);
-       const char *opt     = "dis_ucode_ldr";
-       const char *option  = (const char *)__pa_nodebug(opt);
-       bool *res = (bool *)__pa_nodebug(&dis_ucode_ldr);
-
-#else /* CONFIG_X86_64 */
-       const char *cmdline = boot_command_line;
-       const char *option  = "dis_ucode_ldr";
-       bool *res = &dis_ucode_ldr;
-#endif
-
-       if (cmdline_find_option_bool(cmdline, option))
-               *res = true;
-
-       return *res;
-}
-
-extern struct builtin_fw __start_builtin_fw[];
-extern struct builtin_fw __end_builtin_fw[];
-
-bool get_builtin_firmware(struct cpio_data *cd, const char *name)
-{
-#ifdef CONFIG_FW_LOADER
-       struct builtin_fw *b_fw;
-
-       for (b_fw = __start_builtin_fw; b_fw != __end_builtin_fw; b_fw++) {
-               if (!strcmp(name, b_fw->name)) {
-                       cd->size = b_fw->size;
-                       cd->data = b_fw->data;
-                       return true;
-               }
-       }
-#endif
-       return false;
-}
-
-void __init load_ucode_bsp(void)
-{
-       int vendor;
-       unsigned int family;
-
-       if (check_loader_disabled_bsp())
-               return;
-
-       if (!have_cpuid_p())
-               return;
-
-       vendor = x86_vendor();
-       family = x86_family();
-
-       switch (vendor) {
-       case X86_VENDOR_INTEL:
-               if (family >= 6)
-                       load_ucode_intel_bsp();
-               break;
-       case X86_VENDOR_AMD:
-               if (family >= 0x10)
-                       load_ucode_amd_bsp(family);
-               break;
-       default:
-               break;
-       }
-}
-
-static bool check_loader_disabled_ap(void)
-{
-#ifdef CONFIG_X86_32
-       return *((bool *)__pa_nodebug(&dis_ucode_ldr));
-#else
-       return dis_ucode_ldr;
-#endif
-}
-
-void load_ucode_ap(void)
-{
-       int vendor, family;
-
-       if (check_loader_disabled_ap())
-               return;
-
-       if (!have_cpuid_p())
-               return;
-
-       vendor = x86_vendor();
-       family = x86_family();
-
-       switch (vendor) {
-       case X86_VENDOR_INTEL:
-               if (family >= 6)
-                       load_ucode_intel_ap();
-               break;
-       case X86_VENDOR_AMD:
-               if (family >= 0x10)
-                       load_ucode_amd_ap();
-               break;
-       default:
-               break;
-       }
-}
-
-int __init save_microcode_in_initrd(void)
-{
-       struct cpuinfo_x86 *c = &boot_cpu_data;
-
-       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;
-}
-
-void reload_early_microcode(void)
-{
-       int vendor, family;
-
-       vendor = x86_vendor();
-       family = x86_family();
-
-       switch (vendor) {
-       case X86_VENDOR_INTEL:
-               if (family >= 6)
-                       reload_ucode_intel();
-               break;
-       case X86_VENDOR_AMD:
-               if (family >= 0x10)
-                       reload_ucode_amd();
-               break;
-       default:
-               break;
-       }
-}
index bfd6fcd242ea666fbb4a78863c4bd1f218b6745d..2e09171e53382b96e5e1c74e1b8cf1c9650871f0 100644 (file)
  * Copyright (C) 2000-2006 Tigran Aivazian <tigran@aivazian.fsnet.co.uk>
  *              2006 Shaohua Li <shaohua.li@intel.com>
  *
+ * Intel CPU microcode early update for Linux
+ *
+ * Copyright (C) 2012 Fenghua Yu <fenghua.yu@intel.com>
+ *                   H Peter Anvin" <hpa@zytor.com>
+ *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License
  * as published by the Free Software Foundation; either version
  * 2 of the License, or (at your option) any later version.
  */
 
+/*
+ * This needs to be before all headers so that pr_debug in printk.h doesn't turn
+ * printk calls into no_printk().
+ *
+ *#define DEBUG
+ */
 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
 
+#include <linux/earlycpio.h>
 #include <linux/firmware.h>
 #include <linux/uaccess.h>
+#include <linux/vmalloc.h>
+#include <linux/initrd.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
-#include <linux/vmalloc.h>
+#include <linux/slab.h>
+#include <linux/cpu.h>
+#include <linux/mm.h>
 
 #include <asm/microcode_intel.h>
 #include <asm/processor.h>
+#include <asm/tlbflush.h>
+#include <asm/setup.h>
 #include <asm/msr.h>
 
 MODULE_DESCRIPTION("Microcode Update Driver");
 MODULE_AUTHOR("Tigran Aivazian <tigran@aivazian.fsnet.co.uk>");
 MODULE_LICENSE("GPL");
 
+static unsigned long mc_saved_in_initrd[MAX_UCODE_COUNT];
+static struct mc_saved_data {
+       unsigned int mc_saved_count;
+       struct microcode_intel **mc_saved;
+} mc_saved_data;
+
+static enum ucode_state
+load_microcode_early(struct microcode_intel **saved,
+                    unsigned int num_saved, struct ucode_cpu_info *uci)
+{
+       struct microcode_intel *ucode_ptr, *new_mc = NULL;
+       struct microcode_header_intel *mc_hdr;
+       int new_rev, ret, i;
+
+       new_rev = uci->cpu_sig.rev;
+
+       for (i = 0; i < num_saved; i++) {
+               ucode_ptr = saved[i];
+               mc_hdr    = (struct microcode_header_intel *)ucode_ptr;
+
+               ret = has_newer_microcode(ucode_ptr,
+                                         uci->cpu_sig.sig,
+                                         uci->cpu_sig.pf,
+                                         new_rev);
+               if (!ret)
+                       continue;
+
+               new_rev = mc_hdr->rev;
+               new_mc  = ucode_ptr;
+       }
+
+       if (!new_mc)
+               return UCODE_NFOUND;
+
+       uci->mc = (struct microcode_intel *)new_mc;
+       return UCODE_OK;
+}
+
+static inline void
+copy_initrd_ptrs(struct microcode_intel **mc_saved, unsigned long *initrd,
+                 unsigned long off, int num_saved)
+{
+       int i;
+
+       for (i = 0; i < num_saved; i++)
+               mc_saved[i] = (struct microcode_intel *)(initrd[i] + off);
+}
+
+#ifdef CONFIG_X86_32
+static void
+microcode_phys(struct microcode_intel **mc_saved_tmp,
+              struct mc_saved_data *mc_saved_data)
+{
+       int i;
+       struct microcode_intel ***mc_saved;
+
+       mc_saved = (struct microcode_intel ***)
+                  __pa_nodebug(&mc_saved_data->mc_saved);
+       for (i = 0; i < mc_saved_data->mc_saved_count; i++) {
+               struct microcode_intel *p;
+
+               p = *(struct microcode_intel **)
+                       __pa_nodebug(mc_saved_data->mc_saved + i);
+               mc_saved_tmp[i] = (struct microcode_intel *)__pa_nodebug(p);
+       }
+}
+#endif
+
+static enum ucode_state
+load_microcode(struct mc_saved_data *mc_saved_data, unsigned long *initrd,
+              unsigned long initrd_start, struct ucode_cpu_info *uci)
+{
+       struct microcode_intel *mc_saved_tmp[MAX_UCODE_COUNT];
+       unsigned int count = mc_saved_data->mc_saved_count;
+
+       if (!mc_saved_data->mc_saved) {
+               copy_initrd_ptrs(mc_saved_tmp, initrd, initrd_start, count);
+
+               return load_microcode_early(mc_saved_tmp, count, uci);
+       } else {
+#ifdef CONFIG_X86_32
+               microcode_phys(mc_saved_tmp, mc_saved_data);
+               return load_microcode_early(mc_saved_tmp, count, uci);
+#else
+               return load_microcode_early(mc_saved_data->mc_saved,
+                                                   count, uci);
+#endif
+       }
+}
+
+/*
+ * Given CPU signature and a microcode patch, this function finds if the
+ * microcode patch has matching family and model with the CPU.
+ */
+static enum ucode_state
+matching_model_microcode(struct microcode_header_intel *mc_header,
+                       unsigned long sig)
+{
+       unsigned int fam, model;
+       unsigned int fam_ucode, model_ucode;
+       struct extended_sigtable *ext_header;
+       unsigned long total_size = get_totalsize(mc_header);
+       unsigned long data_size = get_datasize(mc_header);
+       int ext_sigcount, i;
+       struct extended_signature *ext_sig;
+
+       fam   = __x86_family(sig);
+       model = x86_model(sig);
+
+       fam_ucode   = __x86_family(mc_header->sig);
+       model_ucode = x86_model(mc_header->sig);
+
+       if (fam == fam_ucode && model == model_ucode)
+               return UCODE_OK;
+
+       /* Look for ext. headers: */
+       if (total_size <= data_size + MC_HEADER_SIZE)
+               return UCODE_NFOUND;
+
+       ext_header   = (void *) mc_header + data_size + MC_HEADER_SIZE;
+       ext_sig      = (void *)ext_header + EXT_HEADER_SIZE;
+       ext_sigcount = ext_header->count;
+
+       for (i = 0; i < ext_sigcount; i++) {
+               fam_ucode   = __x86_family(ext_sig->sig);
+               model_ucode = x86_model(ext_sig->sig);
+
+               if (fam == fam_ucode && model == model_ucode)
+                       return UCODE_OK;
+
+               ext_sig++;
+       }
+       return UCODE_NFOUND;
+}
+
+static int
+save_microcode(struct mc_saved_data *mc_saved_data,
+              struct microcode_intel **mc_saved_src,
+              unsigned int mc_saved_count)
+{
+       int i, j;
+       struct microcode_intel **saved_ptr;
+       int ret;
+
+       if (!mc_saved_count)
+               return -EINVAL;
+
+       /*
+        * Copy new microcode data.
+        */
+       saved_ptr = kcalloc(mc_saved_count, sizeof(struct microcode_intel *), GFP_KERNEL);
+       if (!saved_ptr)
+               return -ENOMEM;
+
+       for (i = 0; i < mc_saved_count; i++) {
+               struct microcode_header_intel *mc_hdr;
+               struct microcode_intel *mc;
+               unsigned long size;
+
+               if (!mc_saved_src[i]) {
+                       ret = -EINVAL;
+                       goto err;
+               }
+
+               mc     = mc_saved_src[i];
+               mc_hdr = &mc->hdr;
+               size   = get_totalsize(mc_hdr);
+
+               saved_ptr[i] = kmalloc(size, GFP_KERNEL);
+               if (!saved_ptr[i]) {
+                       ret = -ENOMEM;
+                       goto err;
+               }
+
+               memcpy(saved_ptr[i], mc, size);
+       }
+
+       /*
+        * Point to newly saved microcode.
+        */
+       mc_saved_data->mc_saved = saved_ptr;
+       mc_saved_data->mc_saved_count = mc_saved_count;
+
+       return 0;
+
+err:
+       for (j = 0; j <= i; j++)
+               kfree(saved_ptr[j]);
+       kfree(saved_ptr);
+
+       return ret;
+}
+
+/*
+ * A microcode patch in ucode_ptr is saved into mc_saved
+ * - if it has matching signature and newer revision compared to an existing
+ *   patch mc_saved.
+ * - or if it is a newly discovered microcode patch.
+ *
+ * The microcode patch should have matching model with CPU.
+ *
+ * Returns: The updated number @num_saved of saved microcode patches.
+ */
+static unsigned int _save_mc(struct microcode_intel **mc_saved,
+                            u8 *ucode_ptr, unsigned int num_saved)
+{
+       struct microcode_header_intel *mc_hdr, *mc_saved_hdr;
+       unsigned int sig, pf;
+       int found = 0, i;
+
+       mc_hdr = (struct microcode_header_intel *)ucode_ptr;
+
+       for (i = 0; i < num_saved; i++) {
+               mc_saved_hdr = (struct microcode_header_intel *)mc_saved[i];
+               sig          = mc_saved_hdr->sig;
+               pf           = mc_saved_hdr->pf;
+
+               if (!find_matching_signature(ucode_ptr, sig, pf))
+                       continue;
+
+               found = 1;
+
+               if (mc_hdr->rev <= mc_saved_hdr->rev)
+                       continue;
+
+               /*
+                * Found an older ucode saved earlier. Replace it with
+                * this newer one.
+                */
+               mc_saved[i] = (struct microcode_intel *)ucode_ptr;
+               break;
+       }
+
+       /* Newly detected microcode, save it to memory. */
+       if (i >= num_saved && !found)
+               mc_saved[num_saved++] = (struct microcode_intel *)ucode_ptr;
+
+       return num_saved;
+}
+
+/*
+ * Get microcode matching with BSP's model. Only CPUs with the same model as
+ * BSP can stay in the platform.
+ */
+static enum ucode_state __init
+get_matching_model_microcode(int cpu, unsigned long start,
+                            void *data, size_t size,
+                            struct mc_saved_data *mc_saved_data,
+                            unsigned long *mc_saved_in_initrd,
+                            struct ucode_cpu_info *uci)
+{
+       u8 *ucode_ptr = data;
+       unsigned int leftover = size;
+       enum ucode_state state = UCODE_OK;
+       unsigned int mc_size;
+       struct microcode_header_intel *mc_header;
+       struct microcode_intel *mc_saved_tmp[MAX_UCODE_COUNT];
+       unsigned int mc_saved_count = mc_saved_data->mc_saved_count;
+       int i;
+
+       while (leftover && mc_saved_count < ARRAY_SIZE(mc_saved_tmp)) {
+
+               if (leftover < sizeof(mc_header))
+                       break;
+
+               mc_header = (struct microcode_header_intel *)ucode_ptr;
+
+               mc_size = get_totalsize(mc_header);
+               if (!mc_size || mc_size > leftover ||
+                       microcode_sanity_check(ucode_ptr, 0) < 0)
+                       break;
+
+               leftover -= mc_size;
+
+               /*
+                * Since APs with same family and model as the BSP may boot in
+                * the platform, we need to find and save microcode patches
+                * with the same family and model as the BSP.
+                */
+               if (matching_model_microcode(mc_header, uci->cpu_sig.sig) !=
+                        UCODE_OK) {
+                       ucode_ptr += mc_size;
+                       continue;
+               }
+
+               mc_saved_count = _save_mc(mc_saved_tmp, ucode_ptr, mc_saved_count);
+
+               ucode_ptr += mc_size;
+       }
+
+       if (leftover) {
+               state = UCODE_ERROR;
+               goto out;
+       }
+
+       if (mc_saved_count == 0) {
+               state = UCODE_NFOUND;
+               goto out;
+       }
+
+       for (i = 0; i < mc_saved_count; i++)
+               mc_saved_in_initrd[i] = (unsigned long)mc_saved_tmp[i] - start;
+
+       mc_saved_data->mc_saved_count = mc_saved_count;
+out:
+       return state;
+}
+
+static int collect_cpu_info_early(struct ucode_cpu_info *uci)
+{
+       unsigned int val[2];
+       unsigned int family, model;
+       struct cpu_signature csig;
+       unsigned int eax, ebx, ecx, edx;
+
+       csig.sig = 0;
+       csig.pf = 0;
+       csig.rev = 0;
+
+       memset(uci, 0, sizeof(*uci));
+
+       eax = 0x00000001;
+       ecx = 0;
+       native_cpuid(&eax, &ebx, &ecx, &edx);
+       csig.sig = eax;
+
+       family = __x86_family(csig.sig);
+       model  = x86_model(csig.sig);
+
+       if ((model >= 5) || (family > 6)) {
+               /* get processor flags from MSR 0x17 */
+               native_rdmsr(MSR_IA32_PLATFORM_ID, val[0], val[1]);
+               csig.pf = 1 << ((val[1] >> 18) & 7);
+       }
+       native_wrmsr(MSR_IA32_UCODE_REV, 0, 0);
+
+       /* As documented in the SDM: Do a CPUID 1 here */
+       sync_core();
+
+       /* get the current revision from MSR 0x8B */
+       native_rdmsr(MSR_IA32_UCODE_REV, val[0], val[1]);
+
+       csig.rev = val[1];
+
+       uci->cpu_sig = csig;
+       uci->valid = 1;
+
+       return 0;
+}
+
+#ifdef DEBUG
+static void show_saved_mc(void)
+{
+       int i, j;
+       unsigned int sig, pf, rev, total_size, data_size, date;
+       struct ucode_cpu_info uci;
+
+       if (mc_saved_data.mc_saved_count == 0) {
+               pr_debug("no microcode data saved.\n");
+               return;
+       }
+       pr_debug("Total microcode saved: %d\n", mc_saved_data.mc_saved_count);
+
+       collect_cpu_info_early(&uci);
+
+       sig = uci.cpu_sig.sig;
+       pf = uci.cpu_sig.pf;
+       rev = uci.cpu_sig.rev;
+       pr_debug("CPU: sig=0x%x, pf=0x%x, rev=0x%x\n", sig, pf, rev);
+
+       for (i = 0; i < mc_saved_data.mc_saved_count; i++) {
+               struct microcode_header_intel *mc_saved_header;
+               struct extended_sigtable *ext_header;
+               int ext_sigcount;
+               struct extended_signature *ext_sig;
+
+               mc_saved_header = (struct microcode_header_intel *)
+                                 mc_saved_data.mc_saved[i];
+               sig = mc_saved_header->sig;
+               pf = mc_saved_header->pf;
+               rev = mc_saved_header->rev;
+               total_size = get_totalsize(mc_saved_header);
+               data_size = get_datasize(mc_saved_header);
+               date = mc_saved_header->date;
+
+               pr_debug("mc_saved[%d]: sig=0x%x, pf=0x%x, rev=0x%x, toal size=0x%x, date = %04x-%02x-%02x\n",
+                        i, sig, pf, rev, total_size,
+                        date & 0xffff,
+                        date >> 24,
+                        (date >> 16) & 0xff);
+
+               /* Look for ext. headers: */
+               if (total_size <= data_size + MC_HEADER_SIZE)
+                       continue;
+
+               ext_header = (void *) mc_saved_header + data_size + MC_HEADER_SIZE;
+               ext_sigcount = ext_header->count;
+               ext_sig = (void *)ext_header + EXT_HEADER_SIZE;
+
+               for (j = 0; j < ext_sigcount; j++) {
+                       sig = ext_sig->sig;
+                       pf = ext_sig->pf;
+
+                       pr_debug("\tExtended[%d]: sig=0x%x, pf=0x%x\n",
+                                j, sig, pf);
+
+                       ext_sig++;
+               }
+
+       }
+}
+#else
+static inline void show_saved_mc(void)
+{
+}
+#endif
+
+#ifdef CONFIG_HOTPLUG_CPU
+static DEFINE_MUTEX(x86_cpu_microcode_mutex);
+/*
+ * Save this mc into mc_saved_data. So it will be loaded early when a CPU is
+ * hot added or resumes.
+ *
+ * Please make sure this mc should be a valid microcode patch before calling
+ * this function.
+ */
+int save_mc_for_early(u8 *mc)
+{
+       struct microcode_intel *mc_saved_tmp[MAX_UCODE_COUNT];
+       unsigned int mc_saved_count_init;
+       unsigned int mc_saved_count;
+       struct microcode_intel **mc_saved;
+       int ret = 0;
+       int i;
+
+       /*
+        * Hold hotplug lock so mc_saved_data is not accessed by a CPU in
+        * hotplug.
+        */
+       mutex_lock(&x86_cpu_microcode_mutex);
+
+       mc_saved_count_init = mc_saved_data.mc_saved_count;
+       mc_saved_count = mc_saved_data.mc_saved_count;
+       mc_saved = mc_saved_data.mc_saved;
+
+       if (mc_saved && mc_saved_count)
+               memcpy(mc_saved_tmp, mc_saved,
+                      mc_saved_count * sizeof(struct microcode_intel *));
+       /*
+        * Save the microcode patch mc in mc_save_tmp structure if it's a newer
+        * version.
+        */
+       mc_saved_count = _save_mc(mc_saved_tmp, mc, mc_saved_count);
+
+       /*
+        * Save the mc_save_tmp in global mc_saved_data.
+        */
+       ret = save_microcode(&mc_saved_data, mc_saved_tmp, mc_saved_count);
+       if (ret) {
+               pr_err("Cannot save microcode patch.\n");
+               goto out;
+       }
+
+       show_saved_mc();
+
+       /*
+        * Free old saved microcode data.
+        */
+       if (mc_saved) {
+               for (i = 0; i < mc_saved_count_init; i++)
+                       kfree(mc_saved[i]);
+               kfree(mc_saved);
+       }
+
+out:
+       mutex_unlock(&x86_cpu_microcode_mutex);
+
+       return ret;
+}
+EXPORT_SYMBOL_GPL(save_mc_for_early);
+#endif
+
+static bool __init load_builtin_intel_microcode(struct cpio_data *cp)
+{
+#ifdef CONFIG_X86_64
+       unsigned int eax = 0x00000001, ebx, ecx = 0, edx;
+       unsigned int family, model, stepping;
+       char name[30];
+
+       native_cpuid(&eax, &ebx, &ecx, &edx);
+
+       family   = __x86_family(eax);
+       model    = x86_model(eax);
+       stepping = eax & 0xf;
+
+       sprintf(name, "intel-ucode/%02x-%02x-%02x", family, model, stepping);
+
+       return get_builtin_firmware(cp, name);
+#else
+       return false;
+#endif
+}
+
+static __initdata char ucode_name[] = "kernel/x86/microcode/GenuineIntel.bin";
+static __init enum ucode_state
+scan_microcode(struct mc_saved_data *mc_saved_data, unsigned long *initrd,
+              unsigned long start, unsigned long size,
+              struct ucode_cpu_info *uci)
+{
+       struct cpio_data cd;
+       long offset = 0;
+#ifdef CONFIG_X86_32
+       char *p = (char *)__pa_nodebug(ucode_name);
+#else
+       char *p = ucode_name;
+#endif
+
+       cd.data = NULL;
+       cd.size = 0;
+
+       cd = find_cpio_data(p, (void *)start, size, &offset);
+       if (!cd.data) {
+               if (!load_builtin_intel_microcode(&cd))
+                       return UCODE_ERROR;
+       }
+
+       return get_matching_model_microcode(0, start, cd.data, cd.size,
+                                           mc_saved_data, initrd, uci);
+}
+
+/*
+ * Print ucode update info.
+ */
+static void
+print_ucode_info(struct ucode_cpu_info *uci, unsigned int date)
+{
+       int cpu = smp_processor_id();
+
+       pr_info("CPU%d microcode updated early to revision 0x%x, date = %04x-%02x-%02x\n",
+               cpu,
+               uci->cpu_sig.rev,
+               date & 0xffff,
+               date >> 24,
+               (date >> 16) & 0xff);
+}
+
+#ifdef CONFIG_X86_32
+
+static int delay_ucode_info;
+static int current_mc_date;
+
+/*
+ * Print early updated ucode info after printk works. This is delayed info dump.
+ */
+void show_ucode_info_early(void)
+{
+       struct ucode_cpu_info uci;
+
+       if (delay_ucode_info) {
+               collect_cpu_info_early(&uci);
+               print_ucode_info(&uci, current_mc_date);
+               delay_ucode_info = 0;
+       }
+}
+
+/*
+ * At this point, we can not call printk() yet. Keep microcode patch number in
+ * mc_saved_data.mc_saved and delay printing microcode info in
+ * show_ucode_info_early() until printk() works.
+ */
+static void print_ucode(struct ucode_cpu_info *uci)
+{
+       struct microcode_intel *mc_intel;
+       int *delay_ucode_info_p;
+       int *current_mc_date_p;
+
+       mc_intel = uci->mc;
+       if (mc_intel == NULL)
+               return;
+
+       delay_ucode_info_p = (int *)__pa_nodebug(&delay_ucode_info);
+       current_mc_date_p = (int *)__pa_nodebug(&current_mc_date);
+
+       *delay_ucode_info_p = 1;
+       *current_mc_date_p = mc_intel->hdr.date;
+}
+#else
+
+/*
+ * Flush global tlb. We only do this in x86_64 where paging has been enabled
+ * already and PGE should be enabled as well.
+ */
+static inline void flush_tlb_early(void)
+{
+       __native_flush_tlb_global_irq_disabled();
+}
+
+static inline void print_ucode(struct ucode_cpu_info *uci)
+{
+       struct microcode_intel *mc_intel;
+
+       mc_intel = uci->mc;
+       if (mc_intel == NULL)
+               return;
+
+       print_ucode_info(uci, mc_intel->hdr.date);
+}
+#endif
+
+static int apply_microcode_early(struct ucode_cpu_info *uci, bool early)
+{
+       struct microcode_intel *mc_intel;
+       unsigned int val[2];
+
+       mc_intel = uci->mc;
+       if (mc_intel == NULL)
+               return 0;
+
+       /* write microcode via MSR 0x79 */
+       native_wrmsr(MSR_IA32_UCODE_WRITE,
+             (unsigned long) mc_intel->bits,
+             (unsigned long) mc_intel->bits >> 16 >> 16);
+       native_wrmsr(MSR_IA32_UCODE_REV, 0, 0);
+
+       /* As documented in the SDM: Do a CPUID 1 here */
+       sync_core();
+
+       /* get the current revision from MSR 0x8B */
+       native_rdmsr(MSR_IA32_UCODE_REV, val[0], val[1]);
+       if (val[1] != mc_intel->hdr.rev)
+               return -1;
+
+#ifdef CONFIG_X86_64
+       /* Flush global tlb. This is precaution. */
+       flush_tlb_early();
+#endif
+       uci->cpu_sig.rev = val[1];
+
+       if (early)
+               print_ucode(uci);
+       else
+               print_ucode_info(uci, mc_intel->hdr.date);
+
+       return 0;
+}
+
+/*
+ * 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_intel(void)
+{
+       unsigned int count = mc_saved_data.mc_saved_count;
+       struct microcode_intel *mc_saved[MAX_UCODE_COUNT];
+       int ret = 0;
+
+       if (count == 0)
+               return ret;
+
+       copy_initrd_ptrs(mc_saved, mc_saved_in_initrd, initrd_start, count);
+       ret = save_microcode(&mc_saved_data, mc_saved, count);
+       if (ret)
+               pr_err("Cannot save microcode patches from initrd.\n");
+
+       show_saved_mc();
+
+       return ret;
+}
+
+static void __init
+_load_ucode_intel_bsp(struct mc_saved_data *mc_saved_data,
+                     unsigned long *initrd,
+                     unsigned long start, unsigned long size)
+{
+       struct ucode_cpu_info uci;
+       enum ucode_state ret;
+
+       collect_cpu_info_early(&uci);
+
+       ret = scan_microcode(mc_saved_data, initrd, start, size, &uci);
+       if (ret != UCODE_OK)
+               return;
+
+       ret = load_microcode(mc_saved_data, initrd, start, &uci);
+       if (ret != UCODE_OK)
+               return;
+
+       apply_microcode_early(&uci, true);
+}
+
+void __init load_ucode_intel_bsp(void)
+{
+       u64 start, size;
+#ifdef CONFIG_X86_32
+       struct boot_params *p;
+
+       p       = (struct boot_params *)__pa_nodebug(&boot_params);
+       start   = p->hdr.ramdisk_image;
+       size    = p->hdr.ramdisk_size;
+
+       _load_ucode_intel_bsp(
+                       (struct mc_saved_data *)__pa_nodebug(&mc_saved_data),
+                       (unsigned long *)__pa_nodebug(&mc_saved_in_initrd),
+                       start, size);
+#else
+       start   = boot_params.hdr.ramdisk_image + PAGE_OFFSET;
+       size    = boot_params.hdr.ramdisk_size;
+
+       _load_ucode_intel_bsp(&mc_saved_data, mc_saved_in_initrd, start, size);
+#endif
+}
+
+void load_ucode_intel_ap(void)
+{
+       struct mc_saved_data *mc_saved_data_p;
+       struct ucode_cpu_info uci;
+       unsigned long *mc_saved_in_initrd_p;
+       unsigned long initrd_start_addr;
+       enum ucode_state ret;
+#ifdef CONFIG_X86_32
+       unsigned long *initrd_start_p;
+
+       mc_saved_in_initrd_p =
+               (unsigned long *)__pa_nodebug(mc_saved_in_initrd);
+       mc_saved_data_p = (struct mc_saved_data *)__pa_nodebug(&mc_saved_data);
+       initrd_start_p = (unsigned long *)__pa_nodebug(&initrd_start);
+       initrd_start_addr = (unsigned long)__pa_nodebug(*initrd_start_p);
+#else
+       mc_saved_data_p = &mc_saved_data;
+       mc_saved_in_initrd_p = mc_saved_in_initrd;
+       initrd_start_addr = initrd_start;
+#endif
+
+       /*
+        * If there is no valid ucode previously saved in memory, no need to
+        * update ucode on this AP.
+        */
+       if (mc_saved_data_p->mc_saved_count == 0)
+               return;
+
+       collect_cpu_info_early(&uci);
+       ret = load_microcode(mc_saved_data_p, mc_saved_in_initrd_p,
+                            initrd_start_addr, &uci);
+
+       if (ret != UCODE_OK)
+               return;
+
+       apply_microcode_early(&uci, true);
+}
+
+void reload_ucode_intel(void)
+{
+       struct ucode_cpu_info uci;
+       enum ucode_state ret;
+
+       if (!mc_saved_data.mc_saved_count)
+               return;
+
+       collect_cpu_info_early(&uci);
+
+       ret = load_microcode_early(mc_saved_data.mc_saved,
+                                  mc_saved_data.mc_saved_count, &uci);
+       if (ret != UCODE_OK)
+               return;
+
+       apply_microcode_early(&uci, false);
+}
+
 static int collect_cpu_info(int cpu_num, struct cpu_signature *csig)
 {
        struct cpuinfo_x86 *c = &cpu_data(cpu_num);
diff --git a/arch/x86/kernel/cpu/microcode/intel_early.c b/arch/x86/kernel/cpu/microcode/intel_early.c
deleted file mode 100644 (file)
index 37ea89c..0000000
+++ /dev/null
@@ -1,808 +0,0 @@
-/*
- *     Intel CPU microcode early update for Linux
- *
- *     Copyright (C) 2012 Fenghua Yu <fenghua.yu@intel.com>
- *                        H Peter Anvin" <hpa@zytor.com>
- *
- *     This allows to early upgrade microcode on Intel processors
- *     belonging to IA-32 family - PentiumPro, Pentium II,
- *     Pentium III, Xeon, Pentium 4, etc.
- *
- *     Reference: Section 9.11 of Volume 3, IA-32 Intel Architecture
- *     Software Developer's Manual.
- *
- *     This program is free software; you can redistribute it and/or
- *     modify it under the terms of the GNU General Public License
- *     as published by the Free Software Foundation; either version
- *     2 of the License, or (at your option) any later version.
- */
-
-/*
- * This needs to be before all headers so that pr_debug in printk.h doesn't turn
- * printk calls into no_printk().
- *
- *#define DEBUG
- */
-
-#include <linux/module.h>
-#include <linux/mm.h>
-#include <linux/slab.h>
-#include <linux/earlycpio.h>
-#include <linux/initrd.h>
-#include <linux/cpu.h>
-#include <asm/msr.h>
-#include <asm/microcode_intel.h>
-#include <asm/processor.h>
-#include <asm/tlbflush.h>
-#include <asm/setup.h>
-
-#undef pr_fmt
-#define pr_fmt(fmt)    "microcode: " fmt
-
-static unsigned long mc_saved_in_initrd[MAX_UCODE_COUNT];
-static struct mc_saved_data {
-       unsigned int mc_saved_count;
-       struct microcode_intel **mc_saved;
-} mc_saved_data;
-
-static enum ucode_state
-load_microcode_early(struct microcode_intel **saved,
-                    unsigned int num_saved, struct ucode_cpu_info *uci)
-{
-       struct microcode_intel *ucode_ptr, *new_mc = NULL;
-       struct microcode_header_intel *mc_hdr;
-       int new_rev, ret, i;
-
-       new_rev = uci->cpu_sig.rev;
-
-       for (i = 0; i < num_saved; i++) {
-               ucode_ptr = saved[i];
-               mc_hdr    = (struct microcode_header_intel *)ucode_ptr;
-
-               ret = has_newer_microcode(ucode_ptr,
-                                         uci->cpu_sig.sig,
-                                         uci->cpu_sig.pf,
-                                         new_rev);
-               if (!ret)
-                       continue;
-
-               new_rev = mc_hdr->rev;
-               new_mc  = ucode_ptr;
-       }
-
-       if (!new_mc)
-               return UCODE_NFOUND;
-
-       uci->mc = (struct microcode_intel *)new_mc;
-       return UCODE_OK;
-}
-
-static inline void
-copy_initrd_ptrs(struct microcode_intel **mc_saved, unsigned long *initrd,
-                 unsigned long off, int num_saved)
-{
-       int i;
-
-       for (i = 0; i < num_saved; i++)
-               mc_saved[i] = (struct microcode_intel *)(initrd[i] + off);
-}
-
-#ifdef CONFIG_X86_32
-static void
-microcode_phys(struct microcode_intel **mc_saved_tmp,
-              struct mc_saved_data *mc_saved_data)
-{
-       int i;
-       struct microcode_intel ***mc_saved;
-
-       mc_saved = (struct microcode_intel ***)
-                  __pa_nodebug(&mc_saved_data->mc_saved);
-       for (i = 0; i < mc_saved_data->mc_saved_count; i++) {
-               struct microcode_intel *p;
-
-               p = *(struct microcode_intel **)
-                       __pa_nodebug(mc_saved_data->mc_saved + i);
-               mc_saved_tmp[i] = (struct microcode_intel *)__pa_nodebug(p);
-       }
-}
-#endif
-
-static enum ucode_state
-load_microcode(struct mc_saved_data *mc_saved_data, unsigned long *initrd,
-              unsigned long initrd_start, struct ucode_cpu_info *uci)
-{
-       struct microcode_intel *mc_saved_tmp[MAX_UCODE_COUNT];
-       unsigned int count = mc_saved_data->mc_saved_count;
-
-       if (!mc_saved_data->mc_saved) {
-               copy_initrd_ptrs(mc_saved_tmp, initrd, initrd_start, count);
-
-               return load_microcode_early(mc_saved_tmp, count, uci);
-       } else {
-#ifdef CONFIG_X86_32
-               microcode_phys(mc_saved_tmp, mc_saved_data);
-               return load_microcode_early(mc_saved_tmp, count, uci);
-#else
-               return load_microcode_early(mc_saved_data->mc_saved,
-                                                   count, uci);
-#endif
-       }
-}
-
-/*
- * Given CPU signature and a microcode patch, this function finds if the
- * microcode patch has matching family and model with the CPU.
- */
-static enum ucode_state
-matching_model_microcode(struct microcode_header_intel *mc_header,
-                       unsigned long sig)
-{
-       unsigned int fam, model;
-       unsigned int fam_ucode, model_ucode;
-       struct extended_sigtable *ext_header;
-       unsigned long total_size = get_totalsize(mc_header);
-       unsigned long data_size = get_datasize(mc_header);
-       int ext_sigcount, i;
-       struct extended_signature *ext_sig;
-
-       fam   = __x86_family(sig);
-       model = x86_model(sig);
-
-       fam_ucode   = __x86_family(mc_header->sig);
-       model_ucode = x86_model(mc_header->sig);
-
-       if (fam == fam_ucode && model == model_ucode)
-               return UCODE_OK;
-
-       /* Look for ext. headers: */
-       if (total_size <= data_size + MC_HEADER_SIZE)
-               return UCODE_NFOUND;
-
-       ext_header   = (void *) mc_header + data_size + MC_HEADER_SIZE;
-       ext_sig      = (void *)ext_header + EXT_HEADER_SIZE;
-       ext_sigcount = ext_header->count;
-
-       for (i = 0; i < ext_sigcount; i++) {
-               fam_ucode   = __x86_family(ext_sig->sig);
-               model_ucode = x86_model(ext_sig->sig);
-
-               if (fam == fam_ucode && model == model_ucode)
-                       return UCODE_OK;
-
-               ext_sig++;
-       }
-       return UCODE_NFOUND;
-}
-
-static int
-save_microcode(struct mc_saved_data *mc_saved_data,
-              struct microcode_intel **mc_saved_src,
-              unsigned int mc_saved_count)
-{
-       int i, j;
-       struct microcode_intel **saved_ptr;
-       int ret;
-
-       if (!mc_saved_count)
-               return -EINVAL;
-
-       /*
-        * Copy new microcode data.
-        */
-       saved_ptr = kcalloc(mc_saved_count, sizeof(struct microcode_intel *), GFP_KERNEL);
-       if (!saved_ptr)
-               return -ENOMEM;
-
-       for (i = 0; i < mc_saved_count; i++) {
-               struct microcode_header_intel *mc_hdr;
-               struct microcode_intel *mc;
-               unsigned long size;
-
-               if (!mc_saved_src[i]) {
-                       ret = -EINVAL;
-                       goto err;
-               }
-
-               mc     = mc_saved_src[i];
-               mc_hdr = &mc->hdr;
-               size   = get_totalsize(mc_hdr);
-
-               saved_ptr[i] = kmalloc(size, GFP_KERNEL);
-               if (!saved_ptr[i]) {
-                       ret = -ENOMEM;
-                       goto err;
-               }
-
-               memcpy(saved_ptr[i], mc, size);
-       }
-
-       /*
-        * Point to newly saved microcode.
-        */
-       mc_saved_data->mc_saved = saved_ptr;
-       mc_saved_data->mc_saved_count = mc_saved_count;
-
-       return 0;
-
-err:
-       for (j = 0; j <= i; j++)
-               kfree(saved_ptr[j]);
-       kfree(saved_ptr);
-
-       return ret;
-}
-
-/*
- * A microcode patch in ucode_ptr is saved into mc_saved
- * - if it has matching signature and newer revision compared to an existing
- *   patch mc_saved.
- * - or if it is a newly discovered microcode patch.
- *
- * The microcode patch should have matching model with CPU.
- *
- * Returns: The updated number @num_saved of saved microcode patches.
- */
-static unsigned int _save_mc(struct microcode_intel **mc_saved,
-                            u8 *ucode_ptr, unsigned int num_saved)
-{
-       struct microcode_header_intel *mc_hdr, *mc_saved_hdr;
-       unsigned int sig, pf;
-       int found = 0, i;
-
-       mc_hdr = (struct microcode_header_intel *)ucode_ptr;
-
-       for (i = 0; i < num_saved; i++) {
-               mc_saved_hdr = (struct microcode_header_intel *)mc_saved[i];
-               sig          = mc_saved_hdr->sig;
-               pf           = mc_saved_hdr->pf;
-
-               if (!find_matching_signature(ucode_ptr, sig, pf))
-                       continue;
-
-               found = 1;
-
-               if (mc_hdr->rev <= mc_saved_hdr->rev)
-                       continue;
-
-               /*
-                * Found an older ucode saved earlier. Replace it with
-                * this newer one.
-                */
-               mc_saved[i] = (struct microcode_intel *)ucode_ptr;
-               break;
-       }
-
-       /* Newly detected microcode, save it to memory. */
-       if (i >= num_saved && !found)
-               mc_saved[num_saved++] = (struct microcode_intel *)ucode_ptr;
-
-       return num_saved;
-}
-
-/*
- * Get microcode matching with BSP's model. Only CPUs with the same model as
- * BSP can stay in the platform.
- */
-static enum ucode_state __init
-get_matching_model_microcode(int cpu, unsigned long start,
-                            void *data, size_t size,
-                            struct mc_saved_data *mc_saved_data,
-                            unsigned long *mc_saved_in_initrd,
-                            struct ucode_cpu_info *uci)
-{
-       u8 *ucode_ptr = data;
-       unsigned int leftover = size;
-       enum ucode_state state = UCODE_OK;
-       unsigned int mc_size;
-       struct microcode_header_intel *mc_header;
-       struct microcode_intel *mc_saved_tmp[MAX_UCODE_COUNT];
-       unsigned int mc_saved_count = mc_saved_data->mc_saved_count;
-       int i;
-
-       while (leftover && mc_saved_count < ARRAY_SIZE(mc_saved_tmp)) {
-
-               if (leftover < sizeof(mc_header))
-                       break;
-
-               mc_header = (struct microcode_header_intel *)ucode_ptr;
-
-               mc_size = get_totalsize(mc_header);
-               if (!mc_size || mc_size > leftover ||
-                       microcode_sanity_check(ucode_ptr, 0) < 0)
-                       break;
-
-               leftover -= mc_size;
-
-               /*
-                * Since APs with same family and model as the BSP may boot in
-                * the platform, we need to find and save microcode patches
-                * with the same family and model as the BSP.
-                */
-               if (matching_model_microcode(mc_header, uci->cpu_sig.sig) !=
-                        UCODE_OK) {
-                       ucode_ptr += mc_size;
-                       continue;
-               }
-
-               mc_saved_count = _save_mc(mc_saved_tmp, ucode_ptr, mc_saved_count);
-
-               ucode_ptr += mc_size;
-       }
-
-       if (leftover) {
-               state = UCODE_ERROR;
-               goto out;
-       }
-
-       if (mc_saved_count == 0) {
-               state = UCODE_NFOUND;
-               goto out;
-       }
-
-       for (i = 0; i < mc_saved_count; i++)
-               mc_saved_in_initrd[i] = (unsigned long)mc_saved_tmp[i] - start;
-
-       mc_saved_data->mc_saved_count = mc_saved_count;
-out:
-       return state;
-}
-
-static int collect_cpu_info_early(struct ucode_cpu_info *uci)
-{
-       unsigned int val[2];
-       unsigned int family, model;
-       struct cpu_signature csig;
-       unsigned int eax, ebx, ecx, edx;
-
-       csig.sig = 0;
-       csig.pf = 0;
-       csig.rev = 0;
-
-       memset(uci, 0, sizeof(*uci));
-
-       eax = 0x00000001;
-       ecx = 0;
-       native_cpuid(&eax, &ebx, &ecx, &edx);
-       csig.sig = eax;
-
-       family = __x86_family(csig.sig);
-       model  = x86_model(csig.sig);
-
-       if ((model >= 5) || (family > 6)) {
-               /* get processor flags from MSR 0x17 */
-               native_rdmsr(MSR_IA32_PLATFORM_ID, val[0], val[1]);
-               csig.pf = 1 << ((val[1] >> 18) & 7);
-       }
-       native_wrmsr(MSR_IA32_UCODE_REV, 0, 0);
-
-       /* As documented in the SDM: Do a CPUID 1 here */
-       sync_core();
-
-       /* get the current revision from MSR 0x8B */
-       native_rdmsr(MSR_IA32_UCODE_REV, val[0], val[1]);
-
-       csig.rev = val[1];
-
-       uci->cpu_sig = csig;
-       uci->valid = 1;
-
-       return 0;
-}
-
-#ifdef DEBUG
-static void show_saved_mc(void)
-{
-       int i, j;
-       unsigned int sig, pf, rev, total_size, data_size, date;
-       struct ucode_cpu_info uci;
-
-       if (mc_saved_data.mc_saved_count == 0) {
-               pr_debug("no microcode data saved.\n");
-               return;
-       }
-       pr_debug("Total microcode saved: %d\n", mc_saved_data.mc_saved_count);
-
-       collect_cpu_info_early(&uci);
-
-       sig = uci.cpu_sig.sig;
-       pf = uci.cpu_sig.pf;
-       rev = uci.cpu_sig.rev;
-       pr_debug("CPU: sig=0x%x, pf=0x%x, rev=0x%x\n", sig, pf, rev);
-
-       for (i = 0; i < mc_saved_data.mc_saved_count; i++) {
-               struct microcode_header_intel *mc_saved_header;
-               struct extended_sigtable *ext_header;
-               int ext_sigcount;
-               struct extended_signature *ext_sig;
-
-               mc_saved_header = (struct microcode_header_intel *)
-                                 mc_saved_data.mc_saved[i];
-               sig = mc_saved_header->sig;
-               pf = mc_saved_header->pf;
-               rev = mc_saved_header->rev;
-               total_size = get_totalsize(mc_saved_header);
-               data_size = get_datasize(mc_saved_header);
-               date = mc_saved_header->date;
-
-               pr_debug("mc_saved[%d]: sig=0x%x, pf=0x%x, rev=0x%x, toal size=0x%x, date = %04x-%02x-%02x\n",
-                        i, sig, pf, rev, total_size,
-                        date & 0xffff,
-                        date >> 24,
-                        (date >> 16) & 0xff);
-
-               /* Look for ext. headers: */
-               if (total_size <= data_size + MC_HEADER_SIZE)
-                       continue;
-
-               ext_header = (void *) mc_saved_header + data_size + MC_HEADER_SIZE;
-               ext_sigcount = ext_header->count;
-               ext_sig = (void *)ext_header + EXT_HEADER_SIZE;
-
-               for (j = 0; j < ext_sigcount; j++) {
-                       sig = ext_sig->sig;
-                       pf = ext_sig->pf;
-
-                       pr_debug("\tExtended[%d]: sig=0x%x, pf=0x%x\n",
-                                j, sig, pf);
-
-                       ext_sig++;
-               }
-
-       }
-}
-#else
-static inline void show_saved_mc(void)
-{
-}
-#endif
-
-#if defined(CONFIG_MICROCODE_INTEL_EARLY) && defined(CONFIG_HOTPLUG_CPU)
-static DEFINE_MUTEX(x86_cpu_microcode_mutex);
-/*
- * Save this mc into mc_saved_data. So it will be loaded early when a CPU is
- * hot added or resumes.
- *
- * Please make sure this mc should be a valid microcode patch before calling
- * this function.
- */
-int save_mc_for_early(u8 *mc)
-{
-       struct microcode_intel *mc_saved_tmp[MAX_UCODE_COUNT];
-       unsigned int mc_saved_count_init;
-       unsigned int mc_saved_count;
-       struct microcode_intel **mc_saved;
-       int ret = 0;
-       int i;
-
-       /*
-        * Hold hotplug lock so mc_saved_data is not accessed by a CPU in
-        * hotplug.
-        */
-       mutex_lock(&x86_cpu_microcode_mutex);
-
-       mc_saved_count_init = mc_saved_data.mc_saved_count;
-       mc_saved_count = mc_saved_data.mc_saved_count;
-       mc_saved = mc_saved_data.mc_saved;
-
-       if (mc_saved && mc_saved_count)
-               memcpy(mc_saved_tmp, mc_saved,
-                      mc_saved_count * sizeof(struct microcode_intel *));
-       /*
-        * Save the microcode patch mc in mc_save_tmp structure if it's a newer
-        * version.
-        */
-       mc_saved_count = _save_mc(mc_saved_tmp, mc, mc_saved_count);
-
-       /*
-        * Save the mc_save_tmp in global mc_saved_data.
-        */
-       ret = save_microcode(&mc_saved_data, mc_saved_tmp, mc_saved_count);
-       if (ret) {
-               pr_err("Cannot save microcode patch.\n");
-               goto out;
-       }
-
-       show_saved_mc();
-
-       /*
-        * Free old saved microcode data.
-        */
-       if (mc_saved) {
-               for (i = 0; i < mc_saved_count_init; i++)
-                       kfree(mc_saved[i]);
-               kfree(mc_saved);
-       }
-
-out:
-       mutex_unlock(&x86_cpu_microcode_mutex);
-
-       return ret;
-}
-EXPORT_SYMBOL_GPL(save_mc_for_early);
-#endif
-
-static bool __init load_builtin_intel_microcode(struct cpio_data *cp)
-{
-#ifdef CONFIG_X86_64
-       unsigned int eax = 0x00000001, ebx, ecx = 0, edx;
-       unsigned int family, model, stepping;
-       char name[30];
-
-       native_cpuid(&eax, &ebx, &ecx, &edx);
-
-       family   = __x86_family(eax);
-       model    = x86_model(eax);
-       stepping = eax & 0xf;
-
-       sprintf(name, "intel-ucode/%02x-%02x-%02x", family, model, stepping);
-
-       return get_builtin_firmware(cp, name);
-#else
-       return false;
-#endif
-}
-
-static __initdata char ucode_name[] = "kernel/x86/microcode/GenuineIntel.bin";
-static __init enum ucode_state
-scan_microcode(struct mc_saved_data *mc_saved_data, unsigned long *initrd,
-              unsigned long start, unsigned long size,
-              struct ucode_cpu_info *uci)
-{
-       struct cpio_data cd;
-       long offset = 0;
-#ifdef CONFIG_X86_32
-       char *p = (char *)__pa_nodebug(ucode_name);
-#else
-       char *p = ucode_name;
-#endif
-
-       cd.data = NULL;
-       cd.size = 0;
-
-       cd = find_cpio_data(p, (void *)start, size, &offset);
-       if (!cd.data) {
-               if (!load_builtin_intel_microcode(&cd))
-                       return UCODE_ERROR;
-       }
-
-       return get_matching_model_microcode(0, start, cd.data, cd.size,
-                                           mc_saved_data, initrd, uci);
-}
-
-/*
- * Print ucode update info.
- */
-static void
-print_ucode_info(struct ucode_cpu_info *uci, unsigned int date)
-{
-       int cpu = smp_processor_id();
-
-       pr_info("CPU%d microcode updated early to revision 0x%x, date = %04x-%02x-%02x\n",
-               cpu,
-               uci->cpu_sig.rev,
-               date & 0xffff,
-               date >> 24,
-               (date >> 16) & 0xff);
-}
-
-#ifdef CONFIG_X86_32
-
-static int delay_ucode_info;
-static int current_mc_date;
-
-/*
- * Print early updated ucode info after printk works. This is delayed info dump.
- */
-void show_ucode_info_early(void)
-{
-       struct ucode_cpu_info uci;
-
-       if (delay_ucode_info) {
-               collect_cpu_info_early(&uci);
-               print_ucode_info(&uci, current_mc_date);
-               delay_ucode_info = 0;
-       }
-}
-
-/*
- * At this point, we can not call printk() yet. Keep microcode patch number in
- * mc_saved_data.mc_saved and delay printing microcode info in
- * show_ucode_info_early() until printk() works.
- */
-static void print_ucode(struct ucode_cpu_info *uci)
-{
-       struct microcode_intel *mc_intel;
-       int *delay_ucode_info_p;
-       int *current_mc_date_p;
-
-       mc_intel = uci->mc;
-       if (mc_intel == NULL)
-               return;
-
-       delay_ucode_info_p = (int *)__pa_nodebug(&delay_ucode_info);
-       current_mc_date_p = (int *)__pa_nodebug(&current_mc_date);
-
-       *delay_ucode_info_p = 1;
-       *current_mc_date_p = mc_intel->hdr.date;
-}
-#else
-
-/*
- * Flush global tlb. We only do this in x86_64 where paging has been enabled
- * already and PGE should be enabled as well.
- */
-static inline void flush_tlb_early(void)
-{
-       __native_flush_tlb_global_irq_disabled();
-}
-
-static inline void print_ucode(struct ucode_cpu_info *uci)
-{
-       struct microcode_intel *mc_intel;
-
-       mc_intel = uci->mc;
-       if (mc_intel == NULL)
-               return;
-
-       print_ucode_info(uci, mc_intel->hdr.date);
-}
-#endif
-
-static int apply_microcode_early(struct ucode_cpu_info *uci, bool early)
-{
-       struct microcode_intel *mc_intel;
-       unsigned int val[2];
-
-       mc_intel = uci->mc;
-       if (mc_intel == NULL)
-               return 0;
-
-       /* write microcode via MSR 0x79 */
-       native_wrmsr(MSR_IA32_UCODE_WRITE,
-             (unsigned long) mc_intel->bits,
-             (unsigned long) mc_intel->bits >> 16 >> 16);
-       native_wrmsr(MSR_IA32_UCODE_REV, 0, 0);
-
-       /* As documented in the SDM: Do a CPUID 1 here */
-       sync_core();
-
-       /* get the current revision from MSR 0x8B */
-       native_rdmsr(MSR_IA32_UCODE_REV, val[0], val[1]);
-       if (val[1] != mc_intel->hdr.rev)
-               return -1;
-
-#ifdef CONFIG_X86_64
-       /* Flush global tlb. This is precaution. */
-       flush_tlb_early();
-#endif
-       uci->cpu_sig.rev = val[1];
-
-       if (early)
-               print_ucode(uci);
-       else
-               print_ucode_info(uci, mc_intel->hdr.date);
-
-       return 0;
-}
-
-/*
- * 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_intel(void)
-{
-       unsigned int count = mc_saved_data.mc_saved_count;
-       struct microcode_intel *mc_saved[MAX_UCODE_COUNT];
-       int ret = 0;
-
-       if (count == 0)
-               return ret;
-
-       copy_initrd_ptrs(mc_saved, mc_saved_in_initrd, initrd_start, count);
-       ret = save_microcode(&mc_saved_data, mc_saved, count);
-       if (ret)
-               pr_err("Cannot save microcode patches from initrd.\n");
-
-       show_saved_mc();
-
-       return ret;
-}
-
-static void __init
-_load_ucode_intel_bsp(struct mc_saved_data *mc_saved_data,
-                     unsigned long *initrd,
-                     unsigned long start, unsigned long size)
-{
-       struct ucode_cpu_info uci;
-       enum ucode_state ret;
-
-       collect_cpu_info_early(&uci);
-
-       ret = scan_microcode(mc_saved_data, initrd, start, size, &uci);
-       if (ret != UCODE_OK)
-               return;
-
-       ret = load_microcode(mc_saved_data, initrd, start, &uci);
-       if (ret != UCODE_OK)
-               return;
-
-       apply_microcode_early(&uci, true);
-}
-
-void __init load_ucode_intel_bsp(void)
-{
-       u64 start, size;
-#ifdef CONFIG_X86_32
-       struct boot_params *p;
-
-       p       = (struct boot_params *)__pa_nodebug(&boot_params);
-       start   = p->hdr.ramdisk_image;
-       size    = p->hdr.ramdisk_size;
-
-       _load_ucode_intel_bsp(
-                       (struct mc_saved_data *)__pa_nodebug(&mc_saved_data),
-                       (unsigned long *)__pa_nodebug(&mc_saved_in_initrd),
-                       start, size);
-#else
-       start   = boot_params.hdr.ramdisk_image + PAGE_OFFSET;
-       size    = boot_params.hdr.ramdisk_size;
-
-       _load_ucode_intel_bsp(&mc_saved_data, mc_saved_in_initrd, start, size);
-#endif
-}
-
-void load_ucode_intel_ap(void)
-{
-       struct mc_saved_data *mc_saved_data_p;
-       struct ucode_cpu_info uci;
-       unsigned long *mc_saved_in_initrd_p;
-       unsigned long initrd_start_addr;
-       enum ucode_state ret;
-#ifdef CONFIG_X86_32
-       unsigned long *initrd_start_p;
-
-       mc_saved_in_initrd_p =
-               (unsigned long *)__pa_nodebug(mc_saved_in_initrd);
-       mc_saved_data_p = (struct mc_saved_data *)__pa_nodebug(&mc_saved_data);
-       initrd_start_p = (unsigned long *)__pa_nodebug(&initrd_start);
-       initrd_start_addr = (unsigned long)__pa_nodebug(*initrd_start_p);
-#else
-       mc_saved_data_p = &mc_saved_data;
-       mc_saved_in_initrd_p = mc_saved_in_initrd;
-       initrd_start_addr = initrd_start;
-#endif
-
-       /*
-        * If there is no valid ucode previously saved in memory, no need to
-        * update ucode on this AP.
-        */
-       if (mc_saved_data_p->mc_saved_count == 0)
-               return;
-
-       collect_cpu_info_early(&uci);
-       ret = load_microcode(mc_saved_data_p, mc_saved_in_initrd_p,
-                            initrd_start_addr, &uci);
-
-       if (ret != UCODE_OK)
-               return;
-
-       apply_microcode_early(&uci, true);
-}
-
-void reload_ucode_intel(void)
-{
-       struct ucode_cpu_info uci;
-       enum ucode_state ret;
-
-       if (!mc_saved_data.mc_saved_count)
-               return;
-
-       collect_cpu_info_early(&uci);
-
-       ret = load_microcode_early(mc_saved_data.mc_saved,
-                                  mc_saved_data.mc_saved_count, &uci);
-       if (ret != UCODE_OK)
-               return;
-
-       apply_microcode_early(&uci, false);
-}
index 0e2d96ffd158d0e5f4c1d355040cd9b285ef84d6..6bc9ae24b6d2a74930701c0c6ea60fe090a3ebbc 100644 (file)
@@ -152,7 +152,7 @@ ENTRY(startup_32)
        movl %eax, pa(olpc_ofw_pgd)
 #endif
 
-#ifdef CONFIG_MICROCODE_EARLY
+#ifdef CONFIG_MICROCODE
        /* Early load ucode on BSP. */
        call load_ucode_bsp
 #endif
@@ -311,12 +311,11 @@ ENTRY(startup_32_smp)
        movl %eax,%ss
        leal -__PAGE_OFFSET(%ecx),%esp
 
-#ifdef CONFIG_MICROCODE_EARLY
+#ifdef CONFIG_MICROCODE
        /* Early load ucode on AP. */
        call load_ucode_ap
 #endif
 
-
 default_entry:
 #define CR0_STATE      (X86_CR0_PE | X86_CR0_MP | X86_CR0_ET | \
                         X86_CR0_NE | X86_CR0_WP | X86_CR0_AM | \
index 1d8a83df153af10a150baf44cd7fd85adf0bbcf4..1f37cb2b56a9938784ba64abb4db0e51de0c70b9 100644 (file)
@@ -693,14 +693,12 @@ void free_initmem(void)
 #ifdef CONFIG_BLK_DEV_INITRD
 void __init free_initrd_mem(unsigned long start, unsigned long end)
 {
-#ifdef CONFIG_MICROCODE_EARLY
        /*
         * Remember, initrd memory may contain microcode or other useful things.
         * Before we lose initrd mem, we need to find a place to hold them
         * now that normal virtual memory is enabled.
         */
        save_microcode_in_initrd();
-#endif
 
        /*
         * end could be not aligned, and We can not align that,