linux/arch/x86/kernel/cpu/microcode/amd.c

// 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)
{}