Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 9cf8d636 authored by Linus Torvalds's avatar Linus Torvalds
Browse files

Merge branch 'x86-microcode-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip

Pull x86 microcode updates from Ingo Molnar:
 "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)"

* 'x86-microcode-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: (24 commits)
  x86/microcode/intel: Drop orig_sum from ext signature checksum
  x86/microcode/intel: Improve microcode sanity-checking error messages
  x86/microcode/intel: Merge two consecutive if-statements
  x86/microcode/intel: Get rid of DWSIZE
  x86/microcode/intel: Change checksum variables to u32
  x86/microcode: Use kmemdup() rather than duplicating its implementation
  x86/microcode: Remove unnecessary paravirt_enabled check
  x86/microcode: Document builtin microcode loading method
  x86/microcode/AMD: Issue microcode updated message later
  x86/microcode/intel: Cleanup get_matching_model_microcode()
  x86/microcode/intel: Remove unused arg of get_matching_model_microcode()
  x86/microcode/intel: Rename mc_saved_in_initrd
  x86/microcode/intel: Use *wrmsrl variants
  x86/microcode/intel: Cleanup apply_microcode_intel()
  x86/microcode/intel: Move the BUG_ON up and turn it into WARN_ON
  x86/microcode/intel: Rename mc_intel variable to mc
  x86/microcode/intel: Rename mc_saved_count to num_saved
  x86/microcode/intel: Rename local variables of type struct mc_saved_data
  x86/microcode/AMD: Drop redundant printk prefix
  x86/microcode: Issue update message only once
  ...
parents ecc026bf 4ace2e7a
Loading
Loading
Loading
Loading
+25 −0
Original line number Diff line number Diff line
@@ -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.
+14 −13
Original line number Diff line number Diff line
@@ -1163,22 +1163,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"
+26 −0
Original line number Diff line number Diff line
@@ -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 */
+0 −1
Original line number Diff line number Diff line
@@ -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 ? \
+6 −9
Original line number Diff line number Diff line
@@ -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;
}

Loading