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

Commit 757885e9 authored by Jacob Shin's avatar Jacob Shin Committed by H. Peter Anvin
Browse files

x86, microcode, amd: Early microcode patch loading support for AMD



Add early microcode patch loading support for AMD.

Signed-off-by: default avatarJacob Shin <jacob.shin@amd.com>
Link: http://lkml.kernel.org/r/1369940959-2077-5-git-send-email-jacob.shin@amd.com


Signed-off-by: default avatarH. Peter Anvin <hpa@linux.intel.com>
Cc: Fenghua Yu <fenghua.yu@intel.com>
parent a76096a6
Loading
Loading
Loading
Loading
+5 −6
Original line number Diff line number Diff line
@@ -11,7 +11,8 @@ file and loaded to CPUs during boot time.
The format of the combined initrd image is microcode in cpio format followed by
the initrd image (maybe compressed). Kernel parses the combined initrd image
during boot time. The microcode file in cpio name space is:
kernel/x86/microcode/GenuineIntel.bin
on Intel: kernel/x86/microcode/GenuineIntel.bin
on AMD  : kernel/x86/microcode/AuthenticAMD.bin

During BSP boot (before SMP starts), if the kernel finds the microcode file in
the initrd file, it parses the microcode and saves matching microcode in memory.
@@ -34,10 +35,8 @@ original initrd image /boot/initrd-3.5.0.img.

mkdir initrd
cd initrd
mkdir kernel
mkdir kernel/x86
mkdir kernel/x86/microcode
cp ../microcode.bin kernel/x86/microcode/GenuineIntel.bin
find .|cpio -oc >../ucode.cpio
mkdir -p kernel/x86/microcode
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
+9 −5
Original line number Diff line number Diff line
@@ -1058,8 +1058,16 @@ config MICROCODE_INTEL_LIB
	depends on MICROCODE_INTEL

config MICROCODE_INTEL_EARLY
	def_bool n

config MICROCODE_AMD_EARLY
	def_bool n

config MICROCODE_EARLY
	bool "Early load microcode"
	depends on MICROCODE_INTEL && BLK_DEV_INITRD
	depends on (MICROCODE_INTEL || MICROCODE_AMD) && 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
@@ -1067,10 +1075,6 @@ config MICROCODE_INTEL_EARLY
	  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 MICROCODE_EARLY
	def_bool y
	depends on MICROCODE_INTEL_EARLY

config X86_MSR
	tristate "/dev/cpu/*/msr - Model-specific register support"
	---help---
+14 −0
Original line number Diff line number Diff line
@@ -61,4 +61,18 @@ extern int __apply_microcode_amd(struct microcode_amd *mc_amd);
extern int apply_microcode_amd(int cpu);
extern enum ucode_state load_microcode_amd(int cpu, const u8 *data, size_t size);

#ifdef CONFIG_MICROCODE_AMD_EARLY
#ifdef CONFIG_X86_32
#define MPB_MAX_SIZE PAGE_SIZE
extern u8 __cpuinitdata amd_bsp_mpb[MPB_MAX_SIZE];
#endif
extern void __init load_ucode_amd_bsp(void);
extern void __cpuinit load_ucode_amd_ap(void);
extern int __init save_microcode_in_initrd_amd(void);
#else
static inline void __init load_ucode_amd_bsp(void) {}
static inline void __cpuinit load_ucode_amd_ap(void) {}
static inline int __init save_microcode_in_initrd_amd(void) { return -EINVAL; }
#endif

#endif /* _ASM_X86_MICROCODE_AMD_H */
+1 −0
Original line number Diff line number Diff line
@@ -93,6 +93,7 @@ obj-$(CONFIG_MICROCODE_INTEL_LIB) += microcode_intel_lib.o
microcode-y				:= microcode_core.o
microcode-$(CONFIG_MICROCODE_INTEL)	+= microcode_intel.o
microcode-$(CONFIG_MICROCODE_AMD)	+= microcode_amd.o
obj-$(CONFIG_MICROCODE_AMD_EARLY)	+= microcode_amd_early.o
obj-$(CONFIG_MICROCODE)			+= microcode.o

obj-$(CONFIG_X86_CHECK_BIOS_CORRUPTION) += check.o
+22 −0
Original line number Diff line number Diff line
@@ -126,9 +126,20 @@ static struct ucode_patch *find_patch(unsigned int cpu)
static int collect_cpu_info_amd(int cpu, struct cpu_signature *csig)
{
	struct cpuinfo_x86 *c = &cpu_data(cpu);
	struct ucode_cpu_info *uci = ucode_cpu_info + cpu;
	struct ucode_patch *p;

	csig->sig = cpuid_eax(0x00000001);
	csig->rev = c->microcode;

	/*
	 * a patch could have been loaded early, set uci->mc so that
	 * mc_bp_resume() can call apply_microcode()
	 */
	p = find_patch(cpu);
	if (p && (p->patch_id == csig->rev))
		uci->mc = p->data;

	pr_info("CPU%d: patch_level=0x%08x\n", cpu, csig->rev);

	return 0;
@@ -373,6 +384,17 @@ enum ucode_state load_microcode_amd(int cpu, const u8 *data, size_t size)
	if (ret != UCODE_OK)
		cleanup();

#if defined(CONFIG_MICROCODE_AMD_EARLY) && defined(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);
		if (p) {
			memset(amd_bsp_mpb, 0, MPB_MAX_SIZE);
			memcpy(amd_bsp_mpb, p->data, min_t(u32, ksize(p->data),
							   MPB_MAX_SIZE));
		}
	}
#endif
	return ret;
}

Loading