4.4-stable review patch.  If anyone has any objections, please let me know.

------------------

From: Borislav Petkov <[email protected]>

commit 5f9c01aa7c49a2d74474d6d879a797b8badf29e6 upstream.

Thomas Voegtle reported that doing oldconfig with a .config which has
CONFIG_MICROCODE enabled but BLK_DEV_INITRD disabled prevents the
microcode loading mechanism from being built.

So untangle it from the BLK_DEV_INITRD dependency so that oldconfig
doesn't turn it off and add an explanatory text to its Kconfig help what
the supported methods for supplying microcode are.

Reported-by: Thomas Voegtle <[email protected]>
Tested-by: Thomas Voegtle <[email protected]>
Signed-off-by: Borislav Petkov <[email protected]>
Cc: Linus Torvalds <[email protected]>
Cc: Peter Zijlstra <[email protected]>
Cc: Thomas Gleixner <[email protected]>
Link: http://lkml.kernel.org/r/[email protected]
Signed-off-by: Ingo Molnar <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>

---
 arch/x86/Kconfig                      |   23 ++++++++++++-----------
 arch/x86/include/asm/microcode.h      |   26 ++++++++++++++++++++++++++
 arch/x86/kernel/cpu/microcode/intel.c |   14 ++++----------
 3 files changed, 42 insertions(+), 21 deletions(-)

--- a/arch/x86/Kconfig
+++ b/arch/x86/Kconfig
@@ -1126,22 +1126,23 @@ 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---
-
          If you say Y here, you will be able to update the microcode on
-         certain Intel and AMD processors. The Intel support is for the
-         IA32 family, e.g. Pentium Pro, Pentium II, Pentium III, Pentium 4,
-         Xeon etc. The AMD support is for families 0x10 and later. You will
-         obviously need the actual microcode binary data itself which is not
-         shipped with the Linux kernel.
+         Intel and AMD processors. The Intel support is for the IA32 family,
+         e.g. Pentium Pro, Pentium II, Pentium III, Pentium 4, Xeon etc. The
+         AMD support is for families 0x10 and later. You will obviously need
+         the actual microcode binary data itself which is not shipped with
+         the Linux kernel.
 
-         This option selects the general module only, you need to select
-         at least one vendor specific module as well.
+         The preferred method to load microcode from a detached initrd is 
described
+         in Documentation/x86/early-microcode.txt. For that you need to enable
+         CONFIG_BLK_DEV_INITRD in order for the loader to be able to scan the
+         initrd for microcode blobs.
 
-         To compile this driver as a module, choose M here: the module
-         will be called microcode.
+         In addition, you can build-in the microcode into the kernel. For that 
you
+         need to enable FIRMWARE_IN_KERNEL and add the vendor-supplied 
microcode
+         to the CONFIG_EXTRA_FIRMWARE config option.
 
 config MICROCODE_INTEL
        bool "Intel microcode loading support"
--- a/arch/x86/include/asm/microcode.h
+++ b/arch/x86/include/asm/microcode.h
@@ -2,6 +2,7 @@
 #define _ASM_X86_MICROCODE_H
 
 #include <linux/earlycpio.h>
+#include <linux/initrd.h>
 
 #define native_rdmsr(msr, val1, val2)                  \
 do {                                                   \
@@ -168,4 +169,29 @@ static inline void reload_early_microcod
 static inline bool
 get_builtin_firmware(struct cpio_data *cd, const char *name)   { return false; 
}
 #endif
+
+static inline unsigned long get_initrd_start(void)
+{
+#ifdef CONFIG_BLK_DEV_INITRD
+       return initrd_start;
+#else
+       return 0;
+#endif
+}
+
+static inline unsigned long get_initrd_start_addr(void)
+{
+#ifdef CONFIG_BLK_DEV_INITRD
+#ifdef CONFIG_X86_32
+       unsigned long *initrd_start_p = (unsigned long 
*)__pa_nodebug(&initrd_start);
+
+       return (unsigned long)__pa_nodebug(*initrd_start_p);
+#else
+       return get_initrd_start();
+#endif
+#else /* CONFIG_BLK_DEV_INITRD */
+       return 0;
+#endif
+}
+
 #endif /* _ASM_X86_MICROCODE_H */
--- a/arch/x86/kernel/cpu/microcode/intel.c
+++ b/arch/x86/kernel/cpu/microcode/intel.c
@@ -698,7 +698,7 @@ int __init save_microcode_in_initrd_inte
        if (count == 0)
                return ret;
 
-       copy_initrd_ptrs(mc_saved, mc_saved_in_initrd, initrd_start, count);
+       copy_initrd_ptrs(mc_saved, mc_saved_in_initrd, get_initrd_start(), 
count);
        ret = save_microcode(&mc_saved_data, mc_saved, count);
        if (ret)
                pr_err("Cannot save microcode patches from initrd.\n");
@@ -760,20 +760,14 @@ 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_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;
+       mc_saved_data_p = &mc_saved_data;
 #endif
 
        /*
@@ -785,7 +779,7 @@ void load_ucode_intel_ap(void)
 
        collect_cpu_info_early(&uci);
        ret = load_microcode(mc_saved_data_p, mc_saved_in_initrd_p,
-                            initrd_start_addr, &uci);
+                            get_initrd_start_addr(), &uci);
 
        if (ret != UCODE_OK)
                return;


Reply via email to