x86/microcode: Untangle from BLK_DEV_INITRD
authorBorislav Petkov <bp@suse.de>
Wed, 3 Feb 2016 11:33:29 +0000 (12:33 +0100)
committerIngo Molnar <mingo@kernel.org>
Tue, 9 Feb 2016 10:41:15 +0000 (11:41 +0100)
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 <tv@lio96.de>
Tested-by: Thomas Voegtle <tv@lio96.de>
Signed-off-by: Borislav Petkov <bp@suse.de>
Cc: <stable@vger.kernel.org> # 4.4
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Thomas Gleixner <tglx@linutronix.de>
Link: http://lkml.kernel.org/r/1454499225-21544-2-git-send-email-bp@alien8.de
Signed-off-by: Ingo Molnar <mingo@kernel.org>
arch/x86/Kconfig
arch/x86/include/asm/microcode.h
arch/x86/kernel/cpu/microcode/intel.c

index 9af2e63384005002bc99c762f8a61fdd1bbbb3ca..405b1858134b005af48526947fa24621764ce573 100644 (file)
@@ -1159,22 +1159,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.
-
-         This option selects the general module only, you need to select
-         at least one vendor specific module as well.
-
-         To compile this driver as a module, choose M here: the module
-         will be called microcode.
+         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.
+
+         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.
+
+         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"
index 1e1b07a5a7388d45eaaf46e032efd8ee14569662..9d3a96c4da789230f9aeb523e6af35e4fe4a8db3 100644 (file)
@@ -3,6 +3,7 @@
 
 #include <asm/cpu.h>
 #include <linux/earlycpio.h>
+#include <linux/initrd.h>
 
 #define native_rdmsr(msr, val1, val2)                  \
 do {                                                   \
@@ -143,4 +144,29 @@ static inline void reload_early_microcode(void)                    { }
 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 */
index ee81c544ee0daa8f6d8f35569463ba3b9f444f06..044bbbbcbaf167494bb5f3ebacbf2c6b392cab89 100644 (file)
@@ -690,7 +690,7 @@ int __init save_microcode_in_initrd_intel(void)
        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");
@@ -748,20 +748,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
 
        /*
@@ -773,7 +767,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;