1090 lines · 24.2 KB · C
RawDownload
// SPDX-License-Identifier: GPL-2.0-only/* *  AMD CPU Microcode Update Driver for Linux * *  This driver allows to upgrade microcode on F10h AMD *  CPUs and later. * *  Copyright (C) 2008-2011 Advanced Micro Devices Inc. *	          2013-2018 Borislav Petkov <bp@alien8.de> * *  Author: Peter Oruba <peter.oruba@amd.com> * *  Based on work by: *  Tigran Aivazian <aivazian.tigran@gmail.com> * *  early loader: *  Copyright (C) 2013 Advanced Micro Devices, Inc. * *  Author: Jacob Shin <jacob.shin@amd.com> *  Fixes: Borislav Petkov <bp@suse.de> */#define pr_fmt(fmt) "microcode: " fmt #include <linux/earlycpio.h>#include <linux/firmware.h>#include <linux/uaccess.h>#include <linux/vmalloc.h>#include <linux/initrd.h>#include <linux/kernel.h>#include <linux/pci.h> #include <asm/microcode.h>#include <asm/processor.h>#include <asm/setup.h>#include <asm/cpu.h>#include <asm/msr.h>#include <asm/tlb.h> #include "internal.h" struct ucode_patch {	struct list_head plist;	void *data;	unsigned int size;	u32 patch_id;	u16 equiv_cpu;}; static LIST_HEAD(microcode_cache); #define UCODE_MAGIC			0x00414d44#define UCODE_EQUIV_CPU_TABLE_TYPE	0x00000000#define UCODE_UCODE_TYPE		0x00000001 #define SECTION_HDR_SIZE		8#define CONTAINER_HDR_SZ		12 struct equiv_cpu_entry {	u32	installed_cpu;	u32	fixed_errata_mask;	u32	fixed_errata_compare;	u16	equiv_cpu;	u16	res;} __packed; struct microcode_header_amd {	u32	data_code;	u32	patch_id;	u16	mc_patch_data_id;	u8	mc_patch_data_len;	u8	init_flag;	u32	mc_patch_data_checksum;	u32	nb_dev_id;	u32	sb_dev_id;	u16	processor_rev_id;	u8	nb_rev_id;	u8	sb_rev_id;	u8	bios_api_rev;	u8	reserved1[3];	u32	match_reg[8];} __packed; struct microcode_amd {	struct microcode_header_amd	hdr;	unsigned int			mpb[];}; static struct equiv_cpu_table {	unsigned int num_entries;	struct equiv_cpu_entry *entry;} equiv_table; union zen_patch_rev {	struct {		__u32 rev	 : 8,		      stepping	 : 4,		      model	 : 4,		      __reserved : 4,		      ext_model	 : 4,		      ext_fam	 : 8;	};	__u32 ucode_rev;}; union cpuid_1_eax {	struct {		__u32 stepping    : 4,		      model	  : 4,		      family	  : 4,		      __reserved0 : 4,		      ext_model   : 4,		      ext_fam     : 8,		      __reserved1 : 4;	};	__u32 full;}; /* * This points to the current valid container of microcode patches which we will * save from the initrd/builtin before jettisoning its contents. @mc is the * microcode patch we found to match. */struct cont_desc {	struct microcode_amd *mc;	u32		     psize;	u8		     *data;	size_t		     size;}; /* * Microcode patch container file is prepended to the initrd in cpio * format. See Documentation/arch/x86/microcode.rst */static const charucode_path[] __maybe_unused = "kernel/x86/microcode/AuthenticAMD.bin"; /* * This is CPUID(1).EAX on the BSP. It is used in two ways: * * 1. To ignore the equivalence table on Zen1 and newer. * * 2. To match which patches to load because the patch revision ID *    already contains the f/m/s for which the microcode is destined *    for. */static u32 bsp_cpuid_1_eax __ro_after_init; static union cpuid_1_eax ucode_rev_to_cpuid(unsigned int val){	union zen_patch_rev p;	union cpuid_1_eax c; 	p.ucode_rev = val;	c.full = 0; 	c.stepping  = p.stepping;	c.model     = p.model;	c.ext_model = p.ext_model;	c.family    = 0xf;	c.ext_fam   = p.ext_fam; 	return c;} static u16 find_equiv_id(struct equiv_cpu_table *et, u32 sig){	unsigned int i; 	/* Zen and newer do not need an equivalence table. */	if (x86_family(bsp_cpuid_1_eax) >= 0x17)		return 0; 	if (!et || !et->num_entries)		return 0; 	for (i = 0; i < et->num_entries; i++) {		struct equiv_cpu_entry *e = &et->entry[i]; 		if (sig == e->installed_cpu)			return e->equiv_cpu;	}	return 0;} /* * Check whether there is a valid microcode container file at the beginning * of @buf of size @buf_size. */static bool verify_container(const u8 *buf, size_t buf_size){	u32 cont_magic; 	if (buf_size <= CONTAINER_HDR_SZ) {		pr_debug("Truncated microcode container header.\n");		return false;	} 	cont_magic = *(const u32 *)buf;	if (cont_magic != UCODE_MAGIC) {		pr_debug("Invalid magic value (0x%08x).\n", cont_magic);		return false;	} 	return true;} /* * Check whether there is a valid, non-truncated CPU equivalence table at the * beginning of @buf of size @buf_size. */static bool verify_equivalence_table(const u8 *buf, size_t buf_size){	const u32 *hdr = (const u32 *)buf;	u32 cont_type, equiv_tbl_len; 	if (!verify_container(buf, buf_size))		return false; 	/* Zen and newer do not need an equivalence table. */	if (x86_family(bsp_cpuid_1_eax) >= 0x17)		return true; 	cont_type = hdr[1];	if (cont_type != UCODE_EQUIV_CPU_TABLE_TYPE) {		pr_debug("Wrong microcode container equivalence table type: %u.\n",			 cont_type);		return false;	} 	buf_size -= CONTAINER_HDR_SZ; 	equiv_tbl_len = hdr[2];	if (equiv_tbl_len < sizeof(struct equiv_cpu_entry) ||	    buf_size < equiv_tbl_len) {		pr_debug("Truncated equivalence table.\n");		return false;	} 	return true;} /* * Check whether there is a valid, non-truncated microcode patch section at the * beginning of @buf of size @buf_size. * * On success, @sh_psize returns the patch size according to the section header, * to the caller. */static bool__verify_patch_section(const u8 *buf, size_t buf_size, u32 *sh_psize){	u32 p_type, p_size;	const u32 *hdr; 	if (buf_size < SECTION_HDR_SIZE) {		pr_debug("Truncated patch section.\n");		return false;	} 	hdr = (const u32 *)buf;	p_type = hdr[0];	p_size = hdr[1]; 	if (p_type != UCODE_UCODE_TYPE) {		pr_debug("Invalid type field (0x%x) in container file section header.\n",			 p_type);		return false;	} 	if (p_size < sizeof(struct microcode_header_amd)) {		pr_debug("Patch of size %u too short.\n", p_size);		return false;	} 	*sh_psize = p_size; 	return true;} /* * Check whether the passed remaining file @buf_size is large enough to contain * a patch of the indicated @sh_psize (and also whether this size does not * exceed the per-family maximum). @sh_psize is the size read from the section * header. */static unsigned int __verify_patch_size(u32 sh_psize, size_t buf_size){	u8 family = x86_family(bsp_cpuid_1_eax);	u32 max_size; 	if (family >= 0x15)		return min_t(u32, sh_psize, buf_size); #define F1XH_MPB_MAX_SIZE 2048#define F14H_MPB_MAX_SIZE 1824 	switch (family) {	case 0x10 ... 0x12:		max_size = F1XH_MPB_MAX_SIZE;		break;	case 0x14:		max_size = F14H_MPB_MAX_SIZE;		break;	default:		WARN(1, "%s: WTF family: 0x%x\n", __func__, family);		return 0;	} 	if (sh_psize > min_t(u32, buf_size, max_size))		return 0; 	return sh_psize;} /* * Verify the patch in @buf. * * Returns: * negative: on error * positive: patch is not for this family, skip it * 0: success */static int verify_patch(const u8 *buf, size_t buf_size, u32 *patch_size){	u8 family = x86_family(bsp_cpuid_1_eax);	struct microcode_header_amd *mc_hdr;	unsigned int ret;	u32 sh_psize;	u16 proc_id;	u8 patch_fam; 	if (!__verify_patch_section(buf, buf_size, &sh_psize))		return -1; 	/*	 * The section header length is not included in this indicated size	 * but is present in the leftover file length so we need to subtract	 * it before passing this value to the function below.	 */	buf_size -= SECTION_HDR_SIZE; 	/*	 * Check if the remaining buffer is big enough to contain a patch of	 * size sh_psize, as the section claims.	 */	if (buf_size < sh_psize) {		pr_debug("Patch of size %u truncated.\n", sh_psize);		return -1;	} 	ret = __verify_patch_size(sh_psize, buf_size);	if (!ret) {		pr_debug("Per-family patch size mismatch.\n");		return -1;	} 	*patch_size = sh_psize; 	mc_hdr	= (struct microcode_header_amd *)(buf + SECTION_HDR_SIZE);	if (mc_hdr->nb_dev_id || mc_hdr->sb_dev_id) {		pr_err("Patch-ID 0x%08x: chipset-specific code unsupported.\n", mc_hdr->patch_id);		return -1;	} 	proc_id	= mc_hdr->processor_rev_id;	patch_fam = 0xf + (proc_id >> 12);	if (patch_fam != family)		return 1; 	return 0;} static bool mc_patch_matches(struct microcode_amd *mc, u16 eq_id){	/* Zen and newer do not need an equivalence table. */	if (x86_family(bsp_cpuid_1_eax) >= 0x17)		return ucode_rev_to_cpuid(mc->hdr.patch_id).full == bsp_cpuid_1_eax;	else		return eq_id == mc->hdr.processor_rev_id;} /* * This scans the ucode blob for the proper container as we can have multiple * containers glued together. Returns the equivalence ID from the equivalence * table or 0 if none found. * Returns the amount of bytes consumed while scanning. @desc contains all the * data we're going to use in later stages of the application. */static size_t parse_container(u8 *ucode, size_t size, struct cont_desc *desc){	struct equiv_cpu_table table;	size_t orig_size = size;	u32 *hdr = (u32 *)ucode;	u16 eq_id;	u8 *buf; 	if (!verify_equivalence_table(ucode, size))		return 0; 	buf = ucode; 	table.entry = (struct equiv_cpu_entry *)(buf + CONTAINER_HDR_SZ);	table.num_entries = hdr[2] / sizeof(struct equiv_cpu_entry); 	/*	 * Find the equivalence ID of our CPU in this table. Even if this table	 * doesn't contain a patch for the CPU, scan through the whole container	 * so that it can be skipped in case there are other containers appended.	 */	eq_id = find_equiv_id(&table, bsp_cpuid_1_eax); 	buf  += hdr[2] + CONTAINER_HDR_SZ;	size -= hdr[2] + CONTAINER_HDR_SZ; 	/*	 * Scan through the rest of the container to find where it ends. We do	 * some basic sanity-checking too.	 */	while (size > 0) {		struct microcode_amd *mc;		u32 patch_size;		int ret; 		ret = verify_patch(buf, size, &patch_size);		if (ret < 0) {			/*			 * Patch verification failed, skip to the next container, if			 * there is one. Before exit, check whether that container has			 * found a patch already. If so, use it.			 */			goto out;		} else if (ret > 0) {			goto skip;		} 		mc = (struct microcode_amd *)(buf + SECTION_HDR_SIZE);		if (mc_patch_matches(mc, eq_id)) {			desc->psize = patch_size;			desc->mc = mc;		} skip:		/* Skip patch section header too: */		buf  += patch_size + SECTION_HDR_SIZE;		size -= patch_size + SECTION_HDR_SIZE;	} out:	/*	 * If we have found a patch (desc->mc), it means we're looking at the	 * container which has a patch for this CPU so return 0 to mean, @ucode	 * already points to the proper container. Otherwise, we return the size	 * we scanned so that we can advance to the next container in the	 * buffer.	 */	if (desc->mc) {		desc->data = ucode;		desc->size = orig_size - size; 		return 0;	} 	return orig_size - size;} /* * Scan the ucode blob for the proper container as we can have multiple * containers glued together. */static void scan_containers(u8 *ucode, size_t size, struct cont_desc *desc){	while (size) {		size_t s = parse_container(ucode, size, desc);		if (!s)			return; 		/* catch wraparound */		if (size >= s) {			ucode += s;			size  -= s;		} else {			return;		}	}} static int __apply_microcode_amd(struct microcode_amd *mc, unsigned int psize){	unsigned long p_addr = (unsigned long)&mc->hdr.data_code;	u32 rev, dummy; 	native_wrmsrl(MSR_AMD64_PATCH_LOADER, p_addr); 	if (x86_family(bsp_cpuid_1_eax) == 0x17) {		unsigned long p_addr_end = p_addr + psize - 1; 		invlpg(p_addr); 		/*		 * Flush next page too if patch image is crossing a page

Lines 1–500 of 1090.