Skip to contentSkip to conversation

x86/microcode changes for v4.6

GIT PULL Ingo Molnar 1 participant 1 message Mar 14, 2016

Subsystems (3)
lore
Share & tools
lore
#0 lore raw

Linus,

Please pull the latest x86-microcode-for-linus git tree from:

git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip.git x86-microcode-for-linus

# HEAD: 4ace2e7a48ab426eaa9745ace4c50c6a7adb3992 x86/microcode/intel: Drop orig_sum from ext signature checksum

The biggest change in this cycle was the separation of the microcode loading mechanism from the initrd code plus the support of built-in microcode images. There were also lots cleanups and general restructuring. (by Borislav Petkov)

Thanks,

Ingo

------------------>
Andrzej Hajda (1):
x86/microcode: Use kmemdup() rather than duplicating its implementation

Boris Ostrovsky (1):
x86/microcode: Remove unnecessary paravirt_enabled check

Borislav Petkov (20):
x86/microcode: Untangle from BLK_DEV_INITRD x86/microcode/intel: Make early loader look for builtin microcode too x86/microcode: Remove redundant __setup() param parsing x86/microcode: Issue update message only once x86/microcode/AMD: Drop redundant printk prefix x86/microcode/intel: Rename local variables of type struct mc_saved_data x86/microcode/intel: Rename mc_saved_count to num_saved x86/microcode/intel: Rename mc_intel variable to mc x86/microcode/intel: Move the BUG_ON up and turn it into WARN_ON x86/microcode/intel: Cleanup apply_microcode_intel() x86/microcode/intel: Use *wrmsrl variants x86/microcode/intel: Rename mc_saved_in_initrd x86/microcode/intel: Remove unused arg of get_matching_model_microcode() x86/microcode/intel: Cleanup get_matching_model_microcode() x86/microcode/AMD: Issue microcode updated message later x86/microcode: Document builtin microcode loading method x86/microcode/intel: Get rid of DWSIZE
x86/microcode/intel: Merge two consecutive if-statements x86/microcode/intel: Improve microcode sanity-checking error messages x86/microcode/intel: Drop orig_sum from ext signature checksum

Chris Bainbridge (1):
x86/microcode/intel: Change checksum variables to u32

Dan Carpenter (1):
x86/microcode: Remove an unneeded NULL check

 Documentation/x86/early-microcode.txt     |  25 +++
 arch/x86/Kconfig                          |  27 +--
 arch/x86/include/asm/microcode.h          |  26 +++
 arch/x86/include/asm/microcode_intel.h    |   1 -
 arch/x86/kernel/cpu/microcode/amd.c       |  15 +-
 arch/x86/kernel/cpu/microcode/core.c      |  19 +-
 arch/x86/kernel/cpu/microcode/intel.c     | 285 +++++++++++++++---------------
 arch/x86/kernel/cpu/microcode/intel_lib.c |  58 +++---
 8 files changed, 253 insertions(+), 203 deletions(-)
Documentation/x86/early-microcode.txt +25 -0
index d62bea6796da..c956d99cf1de 100644
@@ -40,3 +40,28 @@ cp ../microcode.bin kernel/x86/microcode/GenuineIntel.bin (or AuthenticAMD.bin)
 find . | cpio -o -H newc >../ucode.cpio
 cd ..
 cat ucode.cpio /boot/initrd-3.5.0.img >/boot/initrd-3.5.0.ucode.img
+
+Builtin microcode
+=================
+
+We can also load builtin microcode supplied through the regular firmware
+builtin method CONFIG_FIRMWARE_IN_KERNEL. Here's an example:
+
+CONFIG_FIRMWARE_IN_KERNEL=y
+CONFIG_EXTRA_FIRMWARE="intel-ucode/06-3a-09 amd-ucode/microcode_amd_fam15h.bin"
+CONFIG_EXTRA_FIRMWARE_DIR="/lib/firmware"
+
+This basically means, you have the following tree structure locally:
+
+/lib/firmware/
+|-- amd-ucode
+...
+|   |-- microcode_amd_fam15h.bin
+...
+|-- intel-ucode
+...
+|   |-- 06-3a-09
+...
+
+so that the build system can find those files and integrate them into
+the final kernel image. The early loader finds them and applies them.
arch/x86/Kconfig +14 -13
index 9af2e6338400..405b1858134b 100644
@@ -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"
arch/x86/include/asm/microcode.h +26 -0
index 1e1b07a5a738..9d3a96c4da78 100644
@@ -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 */
arch/x86/include/asm/microcode_intel.h +0 -1
index 8559b0102ea1..603417f8dd6c 100644
@@ -40,7 +40,6 @@ struct extended_sigtable {
 #define DEFAULT_UCODE_TOTALSIZE (DEFAULT_UCODE_DATASIZE + MC_HEADER_SIZE)
 #define EXT_HEADER_SIZE		(sizeof(struct extended_sigtable))
 #define EXT_SIGNATURE_SIZE	(sizeof(struct extended_signature))
-#define DWSIZE			(sizeof(u32))
 
 #define get_totalsize(mc) \
 	(((struct microcode_intel *)mc)->hdr.datasize ? \
arch/x86/kernel/cpu/microcode/amd.c +6 -9
index 2233f8a76615..e397fc160b05 100644
@@ -431,10 +431,6 @@ int __init save_microcode_in_initrd_amd(void)
 	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);
 
@@ -469,8 +465,7 @@ void reload_ucode_amd(void)
 	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);
+			pr_info("reload patch_level=0x%08x\n", ucode_new_rev);
 		}
 	}
 }
@@ -793,15 +788,13 @@ static int verify_and_add_patch(u8 family, u8 *fw, unsigned int leftover)
 		return -EINVAL;
 	}
 
-	patch->data = kzalloc(patch_size, GFP_KERNEL);
+	patch->data = kmemdup(fw + SECTION_HDR_SIZE, patch_size, GFP_KERNEL);
 	if (!patch->data) {
 		pr_err("Patch data allocation failure.\n");
 		kfree(patch);
 		return -EINVAL;
 	}
 
-	/* All looks ok, copy patch... */
-	memcpy(patch->data, fw + SECTION_HDR_SIZE, patch_size);
 	INIT_LIST_HEAD(&patch->plist);
 	patch->patch_id  = mc_hdr->patch_id;
 	patch->equiv_cpu = proc_id;
@@ -957,6 +950,10 @@ struct microcode_ops * __init init_amd_microcode(void)
 		return NULL;
 	}
 
+	if (ucode_new_rev)
+		pr_info_once("microcode updated early to new patch_level=0x%08x\n",
+			     ucode_new_rev);
+
 	return &microcode_amd_ops;
 }
 
arch/x86/kernel/cpu/microcode/core.c +6 -13
index faec7120c508..ac360bfbbdb6 100644
@@ -43,16 +43,8 @@
 #define MICROCODE_VERSION	"2.01"
 
 static struct microcode_ops	*microcode_ops;
-
 static bool dis_ucode_ldr;
 
-static int __init disable_loader(char *str)
-{
-	dis_ucode_ldr = true;
-	return 1;
-}
-__setup("dis_ucode_ldr", disable_loader);
-
 /*
  * Synchronization.
  *
@@ -81,15 +73,16 @@ struct cpu_info_ctx {
 
 static bool __init check_loader_disabled_bsp(void)
 {
+	static const char *__dis_opt_str = "dis_ucode_ldr";
+
 #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);
+	const char *option  = (const char *)__pa_nodebug(__dis_opt_str);
 	bool *res = (bool *)__pa_nodebug(&dis_ucode_ldr);
 
 #else /* CONFIG_X86_64 */
 	const char *cmdline = boot_command_line;
-	const char *option  = "dis_ucode_ldr";
+	const char *option  = __dis_opt_str;
 	bool *res = &dis_ucode_ldr;
 #endif
 
@@ -479,7 +472,7 @@ static enum ucode_state microcode_init_cpu(int cpu, bool refresh_fw)
 	enum ucode_state ustate;
 	struct ucode_cpu_info *uci = ucode_cpu_info + cpu;
 
-	if (uci && uci->valid)
+	if (uci->valid)
 		return UCODE_OK;
 
 	if (collect_cpu_info(cpu))
@@ -630,7 +623,7 @@ int __init microcode_init(void)
 	struct cpuinfo_x86 *c = &boot_cpu_data;
 	int error;
 
-	if (paravirt_enabled() || dis_ucode_ldr)
+	if (dis_ucode_ldr)
 		return -EINVAL;
 
 	if (c->x86_vendor == X86_VENDOR_INTEL)
arch/x86/kernel/cpu/microcode/intel.c +139 -146

618 lines not on this page · raw message

arch/x86/kernel/cpu/microcode/intel_lib.c +37 -21

113 lines not on this page · raw message