// 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 pageLines 1–500 of 1090. 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/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 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 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