// 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 <[email protected]> * * Author: Peter Oruba <[email protected]> * * Based on work by: * Tigran Aivazian <[email protected]> * * early loader: * Copyright (C) 2013 Advanced Micro Devices, Inc. * * Author: Jacob Shin <[email protected]> * Fixes: Borislav Petkov <[email protected]> */ #define pr_fmt(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 "internal.h" struct ucode_patch { … }; static LIST_HEAD(microcode_cache); #define UCODE_MAGIC … #define UCODE_EQUIV_CPU_TABLE_TYPE … #define UCODE_UCODE_TYPE … #define SECTION_HDR_SIZE … #define CONTAINER_HDR_SZ … struct equiv_cpu_entry { … } __packed; struct microcode_header_amd { … } __packed; struct microcode_amd { … }; static struct equiv_cpu_table { … } equiv_table; zen_patch_rev; cpuid_1_eax; /* * 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 { … }; /* * 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 = …; /* * 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) { … } static u16 find_equiv_id(struct equiv_cpu_table *et, u32 sig) { … } /* * 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) { … } /* * 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) { … } /* * 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) { … } /* * 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) { … } /* * 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) { … } static bool mc_patch_matches(struct microcode_amd *mc, u16 eq_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) { … } /* * 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) { … } static int __apply_microcode_amd(struct microcode_amd *mc) { … } /* * Early load occurs before we can vmalloc(). So we look for the microcode * patch container file in initrd, traverse equivalent cpu table, look for a * matching microcode patch, and update, all in initrd memory in place. * When vmalloc() is available for use later -- on 64-bit during first AP load, * and on 32-bit during save_microcode_in_initrd_amd() -- we can call * load_microcode_amd() to save equivalent cpu table and microcode patches in * kernel heap memory. * * Returns true if container found (sets @desc), false otherwise. */ static bool early_apply_microcode(u32 old_rev, void *ucode, size_t size) { … } static bool get_builtin_microcode(struct cpio_data *cp) { … } static void __init find_blobs_in_containers(struct cpio_data *ret) { … } void __init load_ucode_amd_bsp(struct early_load_data *ed, unsigned int cpuid_1_eax) { … } static enum ucode_state _load_microcode_amd(u8 family, const u8 *data, size_t size); static int __init save_microcode_in_initrd(void) { … } early_initcall(save_microcode_in_initrd); static inline bool patch_cpus_equivalent(struct ucode_patch *p, struct ucode_patch *n, bool ignore_stepping) { … } /* * a small, trivial cache of per-family ucode patches */ static struct ucode_patch *cache_find_patch(struct ucode_cpu_info *uci, u16 equiv_cpu) { … } static inline int patch_newer(struct ucode_patch *p, struct ucode_patch *n) { … } static void update_cache(struct ucode_patch *new_patch) { … } static void free_cache(void) { … } static struct ucode_patch *find_patch(unsigned int cpu) { … } void reload_ucode_amd(unsigned int cpu) { … } static int collect_cpu_info_amd(int cpu, struct cpu_signature *csig) { … } static enum ucode_state apply_microcode_amd(int cpu) { … } void load_ucode_amd_ap(unsigned int cpuid_1_eax) { … } static size_t install_equiv_cpu_table(const u8 *buf, size_t buf_size) { … } static void free_equiv_cpu_table(void) { … } static void cleanup(void) { … } /* * Return a non-negative value even if some of the checks failed so that * we can skip over the next patch. If we return a negative value, we * signal a grave error like a memory allocation has failed and the * driver cannot continue functioning normally. In such cases, we tear * down everything we've used up so far and exit. */ static int verify_and_add_patch(u8 family, u8 *fw, unsigned int leftover, unsigned int *patch_size) { … } /* Scan the blob in @data and add microcode patches to the cache. */ static enum ucode_state __load_microcode_amd(u8 family, const u8 *data, size_t size) { … } static enum ucode_state _load_microcode_amd(u8 family, const u8 *data, size_t size) { … } static enum ucode_state load_microcode_amd(u8 family, const u8 *data, size_t size) { … } /* * AMD microcode firmware naming convention, up to family 15h they are in * the legacy file: * * amd-ucode/microcode_amd.bin * * This legacy file is always smaller than 2K in size. * * Beginning with family 15h, they are in family-specific firmware files: * * amd-ucode/microcode_amd_fam15h.bin * amd-ucode/microcode_amd_fam16h.bin * ... * * These might be larger than 2K. */ static enum ucode_state request_microcode_amd(int cpu, struct device *device) { … } static void microcode_fini_cpu_amd(int cpu) { … } static struct microcode_ops microcode_amd_ops = …; struct microcode_ops * __init init_amd_microcode(void) { … } void __exit exit_amd_microcode(void) { … }