1309 lines · 29.1 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/bsearch.h>#include <linux/uaccess.h>#include <linux/vmalloc.h>#include <linux/initrd.h>#include <linux/kernel.h>#include <linux/pci.h> #include <crypto/sha2.h> #include <asm/microcode.h>#include <asm/processor.h>#include <asm/cpuid/api.h>#include <asm/cmdline.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 bool sha_check = true; struct patch_digest {	u32 patch_id;	u8 sha256[SHA256_DIGEST_SIZE];}; #include "amd_shas.c" static int cmp_id(const void *key, const void *elem){	struct patch_digest *pd = (struct patch_digest *)elem;	u32 patch_id = *(u32 *)key; 	if (patch_id == pd->patch_id)		return 0;	else if (patch_id < pd->patch_id)		return -1;	else		return 1;} static u32 cpuid_to_ucode_rev(unsigned int val){	union zen_patch_rev p = {};	union cpuid_1_eax c; 	c.full = val; 	p.stepping  = c.stepping;	p.model     = c.model;	p.ext_model = c.ext_model;	p.ext_fam   = c.ext_fam; 	return p.ucode_rev;} static u32 get_cutoff_revision(u32 rev){	switch (rev >> 8) {	case 0x80012: return 0x8001277; break;	case 0x80082: return 0x800820f; break;	case 0x83010: return 0x830107c; break;	case 0x86001: return 0x860010e; break;	case 0x86081: return 0x8608108; break;	case 0x87010: return 0x8701034; break;	case 0x8a000: return 0x8a0000a; break;	case 0xa0010: return 0xa00107a; break;	case 0xa0011: return 0xa0011da; break;	case 0xa0012: return 0xa001243; break;	case 0xa0082: return 0xa00820e; break;	case 0xa1011: return 0xa101153; break;	case 0xa1012: return 0xa10124e; break;	case 0xa1081: return 0xa108109; break;	case 0xa2010: return 0xa20102f; break;	case 0xa2012: return 0xa201212; break;	case 0xa4041: return 0xa404109; break;	case 0xa5000: return 0xa500013; break;	case 0xa6012: return 0xa60120a; break;	case 0xa7041: return 0xa704109; break;	case 0xa7052: return 0xa705208; break;	case 0xa7080: return 0xa708009; break;	case 0xa70c0: return 0xa70C009; break;	case 0xaa001: return 0xaa00116; break;	case 0xaa002: return 0xaa00218; break;	case 0xb0021: return 0xb002146; break;	case 0xb0081: return 0xb008111; break;	case 0xb1010: return 0xb101046; break;	case 0xb2040: return 0xb204031; break;	case 0xb4040: return 0xb404031; break;	case 0xb4041: return 0xb404101; break;	case 0xb6000: return 0xb600031; break;	case 0xb6080: return 0xb608031; break;	case 0xb7000: return 0xb700031; break;	default: break; 	}	return 0;} static bool need_sha_check(u32 cur_rev){	u32 cutoff; 	cutoff = get_cutoff_revision(cur_rev);	if (cutoff)		return cur_rev <= cutoff; 	pr_info("You should not be seeing this. Please send the following couple of lines to x86-<at>-kernel.org\n");	pr_info("CPUID(1).EAX: 0x%x, current revision: 0x%x\n", bsp_cpuid_1_eax, cur_rev);	return true;} static bool cpu_has_entrysign(void){	unsigned int fam   = x86_family(bsp_cpuid_1_eax);	unsigned int model = x86_model(bsp_cpuid_1_eax); 	if (fam == 0x17 || fam == 0x19)		return true; 	if (fam == 0x1a) {		if (model <= 0x2f ||		    (0x40 <= model && model <= 0x4f) ||		    (0x60 <= model && model <= 0x7f))			return true;	} 	return false;} static bool verify_sha256_digest(u32 patch_id, u32 cur_rev, const u8 *data, unsigned int len){	struct patch_digest *pd = NULL;	u8 digest[SHA256_DIGEST_SIZE];	int i; 	if (!cpu_has_entrysign())		return true; 	if (!need_sha_check(cur_rev))		return true; 	if (!sha_check)		return true; 	pd = bsearch(&patch_id, phashes, ARRAY_SIZE(phashes), sizeof(struct patch_digest), cmp_id);	if (!pd) {		pr_err("No sha256 digest for patch ID: 0x%x found\n", patch_id);		return false;	} 	sha256(data, len, digest); 	if (memcmp(digest, pd->sha256, sizeof(digest))) {		pr_err("Patch 0x%x SHA256 digest mismatch!\n", patch_id); 		for (i = 0; i < SHA256_DIGEST_SIZE; i++)			pr_cont("0x%x ", digest[i]);		pr_info("\n"); 		return false;	} 	return true;} 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 u32 get_patch_level(void){	u32 rev, dummy __always_unused; 	if (IS_ENABLED(CONFIG_MICROCODE_DBG) && x86_hypervisor_present) {		int cpu = smp_processor_id(); 		if (!microcode_rev[cpu]) {			if (!base_rev)				base_rev = cpuid_to_ucode_rev(bsp_cpuid_1_eax); 			microcode_rev[cpu] = base_rev; 			ucode_dbg("CPU%d, base_rev: 0x%x\n", cpu, base_rev);		} 		return microcode_rev[cpu];	} 	native_rdmsr(MSR_AMD64_PATCH_LEVEL, rev, dummy);	if (!rev) {		if (x86_family(bsp_cpuid_1_eax) < 0x17)			return rev; 		rev = cpuid_to_ucode_rev(bsp_cpuid_1_eax);		pr_info_once("No current revision, generating the lowest one: 0x%x\n", rev);	} 	return rev;} 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) {		ucode_dbg("Truncated microcode container header.\n");		return false;	} 	cont_magic = *(const u32 *)buf;	if (cont_magic != UCODE_MAGIC) {		ucode_dbg("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) {		ucode_dbg("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) {		ucode_dbg("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) {		ucode_dbg("Truncated patch section.\n");		return false;	} 	hdr = (const u32 *)buf;	p_type = hdr[0];	p_size = hdr[1]; 	if (p_type != UCODE_UCODE_TYPE) {		ucode_dbg("Invalid type field (0x%x) in container file section header.\n",			  p_type);		return false;	} 	if (p_size < sizeof(struct microcode_header_amd)) {		ucode_dbg("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 bool __verify_patch_size(u32 sh_psize, size_t buf_size){	u8 family = x86_family(bsp_cpuid_1_eax);	u32 max_size; 	if (family >= 0x15)		goto ret; #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 false;	} 	if (sh_psize > max_size)		return false; ret:	/* Working with the whole buffer so < is ok. */	return sh_psize <= buf_size;} /* * Verify the patch in @buf.

Lines 1–500 of 1309.