// 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. Load more
// 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 char ucode_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.