1fc01b568SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only 2bad5fa63SBorislav Petkov /* 3bad5fa63SBorislav Petkov * AMD CPU Microcode Update Driver for Linux 4fe055896SBorislav Petkov * 5fe055896SBorislav Petkov * This driver allows to upgrade microcode on F10h AMD 6fe055896SBorislav Petkov * CPUs and later. 7fe055896SBorislav Petkov * 8bad5fa63SBorislav Petkov * Copyright (C) 2008-2011 Advanced Micro Devices Inc. 92ffcbce3SBorislav Petkov * 2013-2018 Borislav Petkov <[email protected]> 10bad5fa63SBorislav Petkov * 11bad5fa63SBorislav Petkov * Author: Peter Oruba <[email protected]> 12bad5fa63SBorislav Petkov * 13bad5fa63SBorislav Petkov * Based on work by: 14cea58224SAndrew Morton * Tigran Aivazian <[email protected]> 15bad5fa63SBorislav Petkov * 16fe055896SBorislav Petkov * early loader: 17fe055896SBorislav Petkov * Copyright (C) 2013 Advanced Micro Devices, Inc. 18fe055896SBorislav Petkov * 19fe055896SBorislav Petkov * Author: Jacob Shin <[email protected]> 20fe055896SBorislav Petkov * Fixes: Borislav Petkov <[email protected]> 21bad5fa63SBorislav Petkov */ 226b26e1bfSBorislav Petkov #define pr_fmt(fmt) "microcode: " fmt 23bad5fa63SBorislav Petkov 24fe055896SBorislav Petkov #include <linux/earlycpio.h> 25bad5fa63SBorislav Petkov #include <linux/firmware.h> 26bad5fa63SBorislav Petkov #include <linux/uaccess.h> 27bad5fa63SBorislav Petkov #include <linux/vmalloc.h> 28fe055896SBorislav Petkov #include <linux/initrd.h> 29bad5fa63SBorislav Petkov #include <linux/kernel.h> 30bad5fa63SBorislav Petkov #include <linux/pci.h> 31bad5fa63SBorislav Petkov 32bad5fa63SBorislav Petkov #include <asm/microcode.h> 33bad5fa63SBorislav Petkov #include <asm/processor.h> 34fe055896SBorislav Petkov #include <asm/setup.h> 35fe055896SBorislav Petkov #include <asm/cpu.h> 36bad5fa63SBorislav Petkov #include <asm/msr.h> 37c809b0d0SBorislav Petkov (AMD) #include <asm/tlb.h> 38bad5fa63SBorislav Petkov 39d02a0efdSThomas Gleixner #include "internal.h" 40d02a0efdSThomas Gleixner 41ae76d951SAshok Raj struct ucode_patch { 42ae76d951SAshok Raj struct list_head plist; 43ae76d951SAshok Raj void *data; 44ae76d951SAshok Raj unsigned int size; 45ae76d951SAshok Raj u32 patch_id; 46ae76d951SAshok Raj u16 equiv_cpu; 47ae76d951SAshok Raj }; 48ae76d951SAshok Raj 49ae76d951SAshok Raj static LIST_HEAD(microcode_cache); 50ae76d951SAshok Raj 51d02a0efdSThomas Gleixner #define UCODE_MAGIC 0x00414d44 52d02a0efdSThomas Gleixner #define UCODE_EQUIV_CPU_TABLE_TYPE 0x00000000 53d02a0efdSThomas Gleixner #define UCODE_UCODE_TYPE 0x00000001 54d02a0efdSThomas Gleixner 55d02a0efdSThomas Gleixner #define SECTION_HDR_SIZE 8 56d02a0efdSThomas Gleixner #define CONTAINER_HDR_SZ 12 57d02a0efdSThomas Gleixner 58d02a0efdSThomas Gleixner struct equiv_cpu_entry { 59d02a0efdSThomas Gleixner u32 installed_cpu; 60d02a0efdSThomas Gleixner u32 fixed_errata_mask; 61d02a0efdSThomas Gleixner u32 fixed_errata_compare; 62d02a0efdSThomas Gleixner u16 equiv_cpu; 63d02a0efdSThomas Gleixner u16 res; 64d02a0efdSThomas Gleixner } __packed; 65d02a0efdSThomas Gleixner 66d02a0efdSThomas Gleixner struct microcode_header_amd { 67d02a0efdSThomas Gleixner u32 data_code; 68d02a0efdSThomas Gleixner u32 patch_id; 69d02a0efdSThomas Gleixner u16 mc_patch_data_id; 70d02a0efdSThomas Gleixner u8 mc_patch_data_len; 71d02a0efdSThomas Gleixner u8 init_flag; 72d02a0efdSThomas Gleixner u32 mc_patch_data_checksum; 73d02a0efdSThomas Gleixner u32 nb_dev_id; 74d02a0efdSThomas Gleixner u32 sb_dev_id; 75d02a0efdSThomas Gleixner u16 processor_rev_id; 76d02a0efdSThomas Gleixner u8 nb_rev_id; 77d02a0efdSThomas Gleixner u8 sb_rev_id; 78d02a0efdSThomas Gleixner u8 bios_api_rev; 79d02a0efdSThomas Gleixner u8 reserved1[3]; 80d02a0efdSThomas Gleixner u32 match_reg[8]; 81d02a0efdSThomas Gleixner } __packed; 82d02a0efdSThomas Gleixner 83d02a0efdSThomas Gleixner struct microcode_amd { 84d02a0efdSThomas Gleixner struct microcode_header_amd hdr; 85d02a0efdSThomas Gleixner unsigned int mpb[]; 86d02a0efdSThomas Gleixner }; 87d02a0efdSThomas Gleixner 8839cd7c17SMaciej S. Szmigiero static struct equiv_cpu_table { 89413c8915SMaciej S. Szmigiero unsigned int num_entries; 9039cd7c17SMaciej S. Szmigiero struct equiv_cpu_entry *entry; 9139cd7c17SMaciej S. Szmigiero } equiv_table; 92bad5fa63SBorislav Petkov 9394838d23SBorislav Petkov union zen_patch_rev { 9494838d23SBorislav Petkov struct { 9594838d23SBorislav Petkov __u32 rev : 8, 9694838d23SBorislav Petkov stepping : 4, 9794838d23SBorislav Petkov model : 4, 9894838d23SBorislav Petkov __reserved : 4, 9994838d23SBorislav Petkov ext_model : 4, 10094838d23SBorislav Petkov ext_fam : 8; 10194838d23SBorislav Petkov }; 10294838d23SBorislav Petkov __u32 ucode_rev; 10394838d23SBorislav Petkov }; 10494838d23SBorislav Petkov 10594838d23SBorislav Petkov union cpuid_1_eax { 10694838d23SBorislav Petkov struct { 10794838d23SBorislav Petkov __u32 stepping : 4, 10894838d23SBorislav Petkov model : 4, 10994838d23SBorislav Petkov family : 4, 11094838d23SBorislav Petkov __reserved0 : 4, 11194838d23SBorislav Petkov ext_model : 4, 11294838d23SBorislav Petkov ext_fam : 8, 11394838d23SBorislav Petkov __reserved1 : 4; 11494838d23SBorislav Petkov }; 11594838d23SBorislav Petkov __u32 full; 11694838d23SBorislav Petkov }; 11794838d23SBorislav Petkov 118fe055896SBorislav Petkov /* 119fe055896SBorislav Petkov * This points to the current valid container of microcode patches which we will 120f454177fSBorislav Petkov * save from the initrd/builtin before jettisoning its contents. @mc is the 121f454177fSBorislav Petkov * microcode patch we found to match. 122fe055896SBorislav Petkov */ 12369f5f983SBorislav Petkov struct cont_desc { 124f454177fSBorislav Petkov struct microcode_amd *mc; 125f454177fSBorislav Petkov u32 psize; 12606b8534cSBorislav Petkov u8 *data; 12706b8534cSBorislav Petkov size_t size; 12869f5f983SBorislav Petkov }; 129fe055896SBorislav Petkov 1306c545647SBorislav Petkov /* 1316c545647SBorislav Petkov * Microcode patch container file is prepended to the initrd in cpio 132ff61f079SJonathan Corbet * format. See Documentation/arch/x86/microcode.rst 1336c545647SBorislav Petkov */ 13406b8534cSBorislav Petkov static const char 13506b8534cSBorislav Petkov ucode_path[] __maybe_unused = "kernel/x86/microcode/AuthenticAMD.bin"; 136fe055896SBorislav Petkov 13794838d23SBorislav Petkov /* 13894838d23SBorislav Petkov * This is CPUID(1).EAX on the BSP. It is used in two ways: 13994838d23SBorislav Petkov * 14094838d23SBorislav Petkov * 1. To ignore the equivalence table on Zen1 and newer. 14194838d23SBorislav Petkov * 14294838d23SBorislav Petkov * 2. To match which patches to load because the patch revision ID 14394838d23SBorislav Petkov * already contains the f/m/s for which the microcode is destined 14494838d23SBorislav Petkov * for. 14594838d23SBorislav Petkov */ 14694838d23SBorislav Petkov static u32 bsp_cpuid_1_eax __ro_after_init; 14794838d23SBorislav Petkov 14894838d23SBorislav Petkov static union cpuid_1_eax ucode_rev_to_cpuid(unsigned int val) 14994838d23SBorislav Petkov { 15094838d23SBorislav Petkov union zen_patch_rev p; 15194838d23SBorislav Petkov union cpuid_1_eax c; 15294838d23SBorislav Petkov 15394838d23SBorislav Petkov p.ucode_rev = val; 15494838d23SBorislav Petkov c.full = 0; 15594838d23SBorislav Petkov 15694838d23SBorislav Petkov c.stepping = p.stepping; 15794838d23SBorislav Petkov c.model = p.model; 15894838d23SBorislav Petkov c.ext_model = p.ext_model; 15994838d23SBorislav Petkov c.family = 0xf; 16094838d23SBorislav Petkov c.ext_fam = p.ext_fam; 16194838d23SBorislav Petkov 16294838d23SBorislav Petkov return c; 16394838d23SBorislav Petkov } 16494838d23SBorislav Petkov 16539cd7c17SMaciej S. Szmigiero static u16 find_equiv_id(struct equiv_cpu_table *et, u32 sig) 16676bd11c2SBorislav Petkov { 167413c8915SMaciej S. Szmigiero unsigned int i; 16839cd7c17SMaciej S. Szmigiero 16994838d23SBorislav Petkov /* Zen and newer do not need an equivalence table. */ 17094838d23SBorislav Petkov if (x86_family(bsp_cpuid_1_eax) >= 0x17) 17194838d23SBorislav Petkov return 0; 17294838d23SBorislav Petkov 173413c8915SMaciej S. Szmigiero if (!et || !et->num_entries) 174413c8915SMaciej S. Szmigiero return 0; 175413c8915SMaciej S. Szmigiero 176413c8915SMaciej S. Szmigiero for (i = 0; i < et->num_entries; i++) { 177413c8915SMaciej S. Szmigiero struct equiv_cpu_entry *e = &et->entry[i]; 178413c8915SMaciej S. Szmigiero 179413c8915SMaciej S. Szmigiero if (sig == e->installed_cpu) 180413c8915SMaciej S. Szmigiero return e->equiv_cpu; 18176bd11c2SBorislav Petkov } 18276bd11c2SBorislav Petkov return 0; 18376bd11c2SBorislav Petkov } 18476bd11c2SBorislav Petkov 18506b8534cSBorislav Petkov /* 186f4ff2591SMaciej S. Szmigiero * Check whether there is a valid microcode container file at the beginning 1870b62f6cbSThomas Gleixner * of @buf of size @buf_size. 188f4ff2591SMaciej S. Szmigiero */ 1890b62f6cbSThomas Gleixner static bool verify_container(const u8 *buf, size_t buf_size) 190f4ff2591SMaciej S. Szmigiero { 191f4ff2591SMaciej S. Szmigiero u32 cont_magic; 192f4ff2591SMaciej S. Szmigiero 193f4ff2591SMaciej S. Szmigiero if (buf_size <= CONTAINER_HDR_SZ) { 194f4ff2591SMaciej S. Szmigiero pr_debug("Truncated microcode container header.\n"); 195f4ff2591SMaciej S. Szmigiero return false; 196f4ff2591SMaciej S. Szmigiero } 197f4ff2591SMaciej S. Szmigiero 198f4ff2591SMaciej S. Szmigiero cont_magic = *(const u32 *)buf; 199f4ff2591SMaciej S. Szmigiero if (cont_magic != UCODE_MAGIC) { 200f4ff2591SMaciej S. Szmigiero pr_debug("Invalid magic value (0x%08x).\n", cont_magic); 201f4ff2591SMaciej S. Szmigiero return false; 202f4ff2591SMaciej S. Szmigiero } 203f4ff2591SMaciej S. Szmigiero 204f4ff2591SMaciej S. Szmigiero return true; 205f4ff2591SMaciej S. Szmigiero } 206f4ff2591SMaciej S. Szmigiero 207f4ff2591SMaciej S. Szmigiero /* 208f4ff2591SMaciej S. Szmigiero * Check whether there is a valid, non-truncated CPU equivalence table at the 2090b62f6cbSThomas Gleixner * beginning of @buf of size @buf_size. 210f4ff2591SMaciej S. Szmigiero */ 2110b62f6cbSThomas Gleixner static bool verify_equivalence_table(const u8 *buf, size_t buf_size) 212f4ff2591SMaciej S. Szmigiero { 213f4ff2591SMaciej S. Szmigiero const u32 *hdr = (const u32 *)buf; 214f4ff2591SMaciej S. Szmigiero u32 cont_type, equiv_tbl_len; 215f4ff2591SMaciej S. Szmigiero 2160b62f6cbSThomas Gleixner if (!verify_container(buf, buf_size)) 217f4ff2591SMaciej S. Szmigiero return false; 218f4ff2591SMaciej S. Szmigiero 21994838d23SBorislav Petkov /* Zen and newer do not need an equivalence table. */ 22094838d23SBorislav Petkov if (x86_family(bsp_cpuid_1_eax) >= 0x17) 22194838d23SBorislav Petkov return true; 22294838d23SBorislav Petkov 223f4ff2591SMaciej S. Szmigiero cont_type = hdr[1]; 224f4ff2591SMaciej S. Szmigiero if (cont_type != UCODE_EQUIV_CPU_TABLE_TYPE) { 225f4ff2591SMaciej S. Szmigiero pr_debug("Wrong microcode container equivalence table type: %u.\n", 226f4ff2591SMaciej S. Szmigiero cont_type); 227f4ff2591SMaciej S. Szmigiero return false; 228f4ff2591SMaciej S. Szmigiero } 229f4ff2591SMaciej S. Szmigiero 230f4ff2591SMaciej S. Szmigiero buf_size -= CONTAINER_HDR_SZ; 231f4ff2591SMaciej S. Szmigiero 232f4ff2591SMaciej S. Szmigiero equiv_tbl_len = hdr[2]; 233f4ff2591SMaciej S. Szmigiero if (equiv_tbl_len < sizeof(struct equiv_cpu_entry) || 234f4ff2591SMaciej S. Szmigiero buf_size < equiv_tbl_len) { 235f4ff2591SMaciej S. Szmigiero pr_debug("Truncated equivalence table.\n"); 236f4ff2591SMaciej S. Szmigiero return false; 237f4ff2591SMaciej S. Szmigiero } 238f4ff2591SMaciej S. Szmigiero 239f4ff2591SMaciej S. Szmigiero return true; 240f4ff2591SMaciej S. Szmigiero } 241f4ff2591SMaciej S. Szmigiero 242f4ff2591SMaciej S. Szmigiero /* 243f4ff2591SMaciej S. Szmigiero * Check whether there is a valid, non-truncated microcode patch section at the 2440b62f6cbSThomas Gleixner * beginning of @buf of size @buf_size. 2452b8d34b1SBorislav Petkov * 2462b8d34b1SBorislav Petkov * On success, @sh_psize returns the patch size according to the section header, 2472b8d34b1SBorislav Petkov * to the caller. 248f4ff2591SMaciej S. Szmigiero */ 2492b8d34b1SBorislav Petkov static bool 2500b62f6cbSThomas Gleixner __verify_patch_section(const u8 *buf, size_t buf_size, u32 *sh_psize) 251f4ff2591SMaciej S. Szmigiero { 2522b8d34b1SBorislav Petkov u32 p_type, p_size; 253f4ff2591SMaciej S. Szmigiero const u32 *hdr; 254f4ff2591SMaciej S. Szmigiero 255f4ff2591SMaciej S. Szmigiero if (buf_size < SECTION_HDR_SIZE) { 256f4ff2591SMaciej S. Szmigiero pr_debug("Truncated patch section.\n"); 257f4ff2591SMaciej S. Szmigiero return false; 258f4ff2591SMaciej S. Szmigiero } 259f4ff2591SMaciej S. Szmigiero 260f4ff2591SMaciej S. Szmigiero hdr = (const u32 *)buf; 2612b8d34b1SBorislav Petkov p_type = hdr[0]; 2622b8d34b1SBorislav Petkov p_size = hdr[1]; 263f4ff2591SMaciej S. Szmigiero 2642b8d34b1SBorislav Petkov if (p_type != UCODE_UCODE_TYPE) { 265f4ff2591SMaciej S. Szmigiero pr_debug("Invalid type field (0x%x) in container file section header.\n", 2662b8d34b1SBorislav Petkov p_type); 267f4ff2591SMaciej S. Szmigiero return false; 268f4ff2591SMaciej S. Szmigiero } 269f4ff2591SMaciej S. Szmigiero 2702b8d34b1SBorislav Petkov if (p_size < sizeof(struct microcode_header_amd)) { 2712b8d34b1SBorislav Petkov pr_debug("Patch of size %u too short.\n", p_size); 272f4ff2591SMaciej S. Szmigiero return false; 273f4ff2591SMaciej S. Szmigiero } 274f4ff2591SMaciej S. Szmigiero 2752b8d34b1SBorislav Petkov *sh_psize = p_size; 2762b8d34b1SBorislav Petkov 277f4ff2591SMaciej S. Szmigiero return true; 278f4ff2591SMaciej S. Szmigiero } 279f4ff2591SMaciej S. Szmigiero 280f4ff2591SMaciej S. Szmigiero /* 28170887cb2SBorislav Petkov * Check whether the passed remaining file @buf_size is large enough to contain 28270887cb2SBorislav Petkov * a patch of the indicated @sh_psize (and also whether this size does not 28370887cb2SBorislav Petkov * exceed the per-family maximum). @sh_psize is the size read from the section 28470887cb2SBorislav Petkov * header. 2853974b681SBorislav Petkov */ 286*d8317f3dSNikolay Borisov static bool __verify_patch_size(u32 sh_psize, size_t buf_size) 2873974b681SBorislav Petkov { 28894838d23SBorislav Petkov u8 family = x86_family(bsp_cpuid_1_eax); 2893974b681SBorislav Petkov u32 max_size; 2903974b681SBorislav Petkov 291cfffbfebSBorislav Petkov if (family >= 0x15) 292*d8317f3dSNikolay Borisov goto ret; 293cfffbfebSBorislav Petkov 2943974b681SBorislav Petkov #define F1XH_MPB_MAX_SIZE 2048 2953974b681SBorislav Petkov #define F14H_MPB_MAX_SIZE 1824 2963974b681SBorislav Petkov 2973974b681SBorislav Petkov switch (family) { 298cfffbfebSBorislav Petkov case 0x10 ... 0x12: 299cfffbfebSBorislav Petkov max_size = F1XH_MPB_MAX_SIZE; 300cfffbfebSBorislav Petkov break; 3013974b681SBorislav Petkov case 0x14: 3023974b681SBorislav Petkov max_size = F14H_MPB_MAX_SIZE; 3033974b681SBorislav Petkov break; 3043974b681SBorislav Petkov default: 305cfffbfebSBorislav Petkov WARN(1, "%s: WTF family: 0x%x\n", __func__, family); 306*d8317f3dSNikolay Borisov return false; 3073974b681SBorislav Petkov } 3083974b681SBorislav Petkov 309*d8317f3dSNikolay Borisov if (sh_psize > max_size) 310*d8317f3dSNikolay Borisov return false; 3113974b681SBorislav Petkov 312*d8317f3dSNikolay Borisov ret: 313*d8317f3dSNikolay Borisov /* Working with the whole buffer so < is ok. */ 314*d8317f3dSNikolay Borisov return sh_psize <= buf_size; 3153974b681SBorislav Petkov } 3163974b681SBorislav Petkov 317d430a305SBorislav Petkov /* 318d430a305SBorislav Petkov * Verify the patch in @buf. 319d430a305SBorislav Petkov * 320d430a305SBorislav Petkov * Returns: 321d430a305SBorislav Petkov * negative: on error 322d430a305SBorislav Petkov * positive: patch is not for this family, skip it 323d430a305SBorislav Petkov * 0: success 324d430a305SBorislav Petkov */ 32594838d23SBorislav Petkov static int verify_patch(const u8 *buf, size_t buf_size, u32 *patch_size) 3262b8d34b1SBorislav Petkov { 32794838d23SBorislav Petkov u8 family = x86_family(bsp_cpuid_1_eax); 32851776fb8SBorislav Petkov struct microcode_header_amd *mc_hdr; 3292b8d34b1SBorislav Petkov u32 sh_psize; 33051776fb8SBorislav Petkov u16 proc_id; 33151776fb8SBorislav Petkov u8 patch_fam; 3322b8d34b1SBorislav Petkov 3330b62f6cbSThomas Gleixner if (!__verify_patch_section(buf, buf_size, &sh_psize)) 334d430a305SBorislav Petkov return -1; 335d430a305SBorislav Petkov 3362b8d34b1SBorislav Petkov /* 3372b8d34b1SBorislav Petkov * The section header length is not included in this indicated size 3382b8d34b1SBorislav Petkov * but is present in the leftover file length so we need to subtract 3392b8d34b1SBorislav Petkov * it before passing this value to the function below. 3402b8d34b1SBorislav Petkov */ 3412b8d34b1SBorislav Petkov buf_size -= SECTION_HDR_SIZE; 3422b8d34b1SBorislav Petkov 3432b8d34b1SBorislav Petkov /* 3442b8d34b1SBorislav Petkov * Check if the remaining buffer is big enough to contain a patch of 3452b8d34b1SBorislav Petkov * size sh_psize, as the section claims. 3462b8d34b1SBorislav Petkov */ 3472b8d34b1SBorislav Petkov if (buf_size < sh_psize) { 3482b8d34b1SBorislav Petkov pr_debug("Patch of size %u truncated.\n", sh_psize); 349d430a305SBorislav Petkov return -1; 3502b8d34b1SBorislav Petkov } 3512b8d34b1SBorislav Petkov 352*d8317f3dSNikolay Borisov if (!__verify_patch_size(sh_psize, buf_size)) { 353d430a305SBorislav Petkov pr_debug("Per-family patch size mismatch.\n"); 354d430a305SBorislav Petkov return -1; 355d430a305SBorislav Petkov } 35651776fb8SBorislav Petkov 357d430a305SBorislav Petkov *patch_size = sh_psize; 358d430a305SBorislav Petkov 359d430a305SBorislav Petkov mc_hdr = (struct microcode_header_amd *)(buf + SECTION_HDR_SIZE); 360c7957020SBorislav Petkov if (mc_hdr->nb_dev_id || mc_hdr->sb_dev_id) { 361c7957020SBorislav Petkov pr_err("Patch-ID 0x%08x: chipset-specific code unsupported.\n", mc_hdr->patch_id); 362d430a305SBorislav Petkov return -1; 363c7957020SBorislav Petkov } 364c7957020SBorislav Petkov 365d430a305SBorislav Petkov proc_id = mc_hdr->processor_rev_id; 36651776fb8SBorislav Petkov patch_fam = 0xf + (proc_id >> 12); 36751776fb8SBorislav Petkov if (patch_fam != family) 368d430a305SBorislav Petkov return 1; 36951776fb8SBorislav Petkov 370d430a305SBorislav Petkov return 0; 3712b8d34b1SBorislav Petkov } 3722b8d34b1SBorislav Petkov 37394838d23SBorislav Petkov static bool mc_patch_matches(struct microcode_amd *mc, u16 eq_id) 37494838d23SBorislav Petkov { 37594838d23SBorislav Petkov /* Zen and newer do not need an equivalence table. */ 37694838d23SBorislav Petkov if (x86_family(bsp_cpuid_1_eax) >= 0x17) 37794838d23SBorislav Petkov return ucode_rev_to_cpuid(mc->hdr.patch_id).full == bsp_cpuid_1_eax; 37894838d23SBorislav Petkov else 37994838d23SBorislav Petkov return eq_id == mc->hdr.processor_rev_id; 38094838d23SBorislav Petkov } 38194838d23SBorislav Petkov 3823974b681SBorislav Petkov /* 38306b8534cSBorislav Petkov * This scans the ucode blob for the proper container as we can have multiple 384db80b2efSNikolay Borisov * containers glued together. 385db80b2efSNikolay Borisov * 3868801b3fcSBorislav Petkov * Returns the amount of bytes consumed while scanning. @desc contains all the 3878801b3fcSBorislav Petkov * data we're going to use in later stages of the application. 38806b8534cSBorislav Petkov */ 38972dc571aSBorislav Petkov static size_t parse_container(u8 *ucode, size_t size, struct cont_desc *desc) 39006b8534cSBorislav Petkov { 39139cd7c17SMaciej S. Szmigiero struct equiv_cpu_table table; 39272dc571aSBorislav Petkov size_t orig_size = size; 3938801b3fcSBorislav Petkov u32 *hdr = (u32 *)ucode; 3948801b3fcSBorislav Petkov u16 eq_id; 3958801b3fcSBorislav Petkov u8 *buf; 39606b8534cSBorislav Petkov 3970b62f6cbSThomas Gleixner if (!verify_equivalence_table(ucode, size)) 398c45e8035SBorislav Petkov return 0; 39906b8534cSBorislav Petkov 4008801b3fcSBorislav Petkov buf = ucode; 40106b8534cSBorislav Petkov 40239cd7c17SMaciej S. Szmigiero table.entry = (struct equiv_cpu_entry *)(buf + CONTAINER_HDR_SZ); 403413c8915SMaciej S. Szmigiero table.num_entries = hdr[2] / sizeof(struct equiv_cpu_entry); 40406b8534cSBorislav Petkov 405c45e8035SBorislav Petkov /* 406c45e8035SBorislav Petkov * Find the equivalence ID of our CPU in this table. Even if this table 407c45e8035SBorislav Petkov * doesn't contain a patch for the CPU, scan through the whole container 408c45e8035SBorislav Petkov * so that it can be skipped in case there are other containers appended. 409c45e8035SBorislav Petkov */ 41094838d23SBorislav Petkov eq_id = find_equiv_id(&table, bsp_cpuid_1_eax); 4118801b3fcSBorislav Petkov 4128801b3fcSBorislav Petkov buf += hdr[2] + CONTAINER_HDR_SZ; 4138801b3fcSBorislav Petkov size -= hdr[2] + CONTAINER_HDR_SZ; 41406b8534cSBorislav Petkov 41506b8534cSBorislav Petkov /* 4168801b3fcSBorislav Petkov * Scan through the rest of the container to find where it ends. We do 4178801b3fcSBorislav Petkov * some basic sanity-checking too. 41806b8534cSBorislav Petkov */ 4198801b3fcSBorislav Petkov while (size > 0) { 4208801b3fcSBorislav Petkov struct microcode_amd *mc; 4218801b3fcSBorislav Petkov u32 patch_size; 422c45e8035SBorislav Petkov int ret; 4238feaa64aSBorislav Petkov 42494838d23SBorislav Petkov ret = verify_patch(buf, size, &patch_size); 425c45e8035SBorislav Petkov if (ret < 0) { 426c45e8035SBorislav Petkov /* 427ba73e369SBorislav Petkov * Patch verification failed, skip to the next container, if 428ba73e369SBorislav Petkov * there is one. Before exit, check whether that container has 429ba73e369SBorislav Petkov * found a patch already. If so, use it. 430c45e8035SBorislav Petkov */ 431c45e8035SBorislav Petkov goto out; 432c45e8035SBorislav Petkov } else if (ret > 0) { 433c45e8035SBorislav Petkov goto skip; 434c45e8035SBorislav Petkov } 43506b8534cSBorislav Petkov 436c45e8035SBorislav Petkov mc = (struct microcode_amd *)(buf + SECTION_HDR_SIZE); 43794838d23SBorislav Petkov if (mc_patch_matches(mc, eq_id)) { 4388801b3fcSBorislav Petkov desc->psize = patch_size; 4398801b3fcSBorislav Petkov desc->mc = mc; 44006b8534cSBorislav Petkov } 44106b8534cSBorislav Petkov 442c45e8035SBorislav Petkov skip: 443c45e8035SBorislav Petkov /* Skip patch section header too: */ 444c45e8035SBorislav Petkov buf += patch_size + SECTION_HDR_SIZE; 445c45e8035SBorislav Petkov size -= patch_size + SECTION_HDR_SIZE; 44606b8534cSBorislav Petkov } 44706b8534cSBorislav Petkov 448ba73e369SBorislav Petkov out: 4498801b3fcSBorislav Petkov /* 4508801b3fcSBorislav Petkov * If we have found a patch (desc->mc), it means we're looking at the 4518801b3fcSBorislav Petkov * container which has a patch for this CPU so return 0 to mean, @ucode 4528801b3fcSBorislav Petkov * already points to the proper container. Otherwise, we return the size 4538801b3fcSBorislav Petkov * we scanned so that we can advance to the next container in the 4548801b3fcSBorislav Petkov * buffer. 4558801b3fcSBorislav Petkov */ 4568801b3fcSBorislav Petkov if (desc->mc) { 4578801b3fcSBorislav Petkov desc->data = ucode; 4588801b3fcSBorislav Petkov desc->size = orig_size - size; 4598801b3fcSBorislav Petkov 4608801b3fcSBorislav Petkov return 0; 4618801b3fcSBorislav Petkov } 4628801b3fcSBorislav Petkov 4638801b3fcSBorislav Petkov return orig_size - size; 4648801b3fcSBorislav Petkov } 4658801b3fcSBorislav Petkov 4668801b3fcSBorislav Petkov /* 4678801b3fcSBorislav Petkov * Scan the ucode blob for the proper container as we can have multiple 4688801b3fcSBorislav Petkov * containers glued together. 4698801b3fcSBorislav Petkov */ 4708801b3fcSBorislav Petkov static void scan_containers(u8 *ucode, size_t size, struct cont_desc *desc) 4718801b3fcSBorislav Petkov { 47272dc571aSBorislav Petkov while (size) { 47372dc571aSBorislav Petkov size_t s = parse_container(ucode, size, desc); 4748801b3fcSBorislav Petkov if (!s) 4758801b3fcSBorislav Petkov return; 4768801b3fcSBorislav Petkov 47772dc571aSBorislav Petkov /* catch wraparound */ 47872dc571aSBorislav Petkov if (size >= s) { 4798801b3fcSBorislav Petkov ucode += s; 48072dc571aSBorislav Petkov size -= s; 48172dc571aSBorislav Petkov } else { 48272dc571aSBorislav Petkov return; 48372dc571aSBorislav Petkov } 4848801b3fcSBorislav Petkov } 48506b8534cSBorislav Petkov } 48606b8534cSBorislav Petkov 487c809b0d0SBorislav Petkov (AMD) static int __apply_microcode_amd(struct microcode_amd *mc, unsigned int psize) 48876bd11c2SBorislav Petkov { 489c809b0d0SBorislav Petkov (AMD) unsigned long p_addr = (unsigned long)&mc->hdr.data_code; 49076bd11c2SBorislav Petkov u32 rev, dummy; 49176bd11c2SBorislav Petkov 492c809b0d0SBorislav Petkov (AMD) native_wrmsrl(MSR_AMD64_PATCH_LOADER, p_addr); 493c809b0d0SBorislav Petkov (AMD) 494c809b0d0SBorislav Petkov (AMD) if (x86_family(bsp_cpuid_1_eax) == 0x17) { 495c809b0d0SBorislav Petkov (AMD) unsigned long p_addr_end = p_addr + psize - 1; 496c809b0d0SBorislav Petkov (AMD) 497c809b0d0SBorislav Petkov (AMD) invlpg(p_addr); 498c809b0d0SBorislav Petkov (AMD) 499c809b0d0SBorislav Petkov (AMD) /* 500c809b0d0SBorislav Petkov (AMD) * Flush next page too if patch image is crossing a page 501c809b0d0SBorislav Petkov (AMD) * boundary. 502c809b0d0SBorislav Petkov (AMD) */ 503c809b0d0SBorislav Petkov (AMD) if (p_addr >> PAGE_SHIFT != p_addr_end >> PAGE_SHIFT) 504c809b0d0SBorislav Petkov (AMD) invlpg(p_addr_end); 505c809b0d0SBorislav Petkov (AMD) } 50676bd11c2SBorislav Petkov 50776bd11c2SBorislav Petkov /* verify patch application was successful */ 50876bd11c2SBorislav Petkov native_rdmsr(MSR_AMD64_PATCH_LEVEL, rev, dummy); 50994838d23SBorislav Petkov 510ef901dc3SBorislav Petkov if (rev != mc->hdr.patch_id) 51176bd11c2SBorislav Petkov return -1; 51276bd11c2SBorislav Petkov 51376bd11c2SBorislav Petkov return 0; 51476bd11c2SBorislav Petkov } 51576bd11c2SBorislav Petkov 516fe055896SBorislav Petkov /* 517fe055896SBorislav Petkov * Early load occurs before we can vmalloc(). So we look for the microcode 518fe055896SBorislav Petkov * patch container file in initrd, traverse equivalent cpu table, look for a 519fe055896SBorislav Petkov * matching microcode patch, and update, all in initrd memory in place. 520fe055896SBorislav Petkov * When vmalloc() is available for use later -- on 64-bit during first AP load, 521fe055896SBorislav Petkov * and on 32-bit during save_microcode_in_initrd_amd() -- we can call 522fe055896SBorislav Petkov * load_microcode_amd() to save equivalent cpu table and microcode patches in 523fe055896SBorislav Petkov * kernel heap memory. 524200d3553SBorislav Petkov * 5258801b3fcSBorislav Petkov * Returns true if container found (sets @desc), false otherwise. 526fe055896SBorislav Petkov */ 52794838d23SBorislav Petkov static bool early_apply_microcode(u32 old_rev, void *ucode, size_t size) 528fe055896SBorislav Petkov { 5298801b3fcSBorislav Petkov struct cont_desc desc = { 0 }; 5308801b3fcSBorislav Petkov struct microcode_amd *mc; 5318801b3fcSBorislav Petkov bool ret = false; 532fe055896SBorislav Petkov 5338801b3fcSBorislav Petkov scan_containers(ucode, size, &desc); 53406b8534cSBorislav Petkov 5358801b3fcSBorislav Petkov mc = desc.mc; 5368801b3fcSBorislav Petkov if (!mc) 5378801b3fcSBorislav Petkov return ret; 538fe055896SBorislav Petkov 539e7ad18d1SBorislav Petkov /* 540e7ad18d1SBorislav Petkov * Allow application of the same revision to pick up SMT-specific 541e7ad18d1SBorislav Petkov * changes even if the revision of the other SMT thread is already 542e7ad18d1SBorislav Petkov * up-to-date. 543e7ad18d1SBorislav Petkov */ 544080990aaSBorislav Petkov (AMD) if (old_rev > mc->hdr.patch_id) 5458801b3fcSBorislav Petkov return ret; 546fe055896SBorislav Petkov 547c809b0d0SBorislav Petkov (AMD) return !__apply_microcode_amd(mc, desc.psize); 548fe055896SBorislav Petkov } 549fe055896SBorislav Petkov 55094838d23SBorislav Petkov static bool get_builtin_microcode(struct cpio_data *cp) 551fe055896SBorislav Petkov { 552fe055896SBorislav Petkov char fw_name[36] = "amd-ucode/microcode_amd.bin"; 55394838d23SBorislav Petkov u8 family = x86_family(bsp_cpuid_1_eax); 5549d489604SBorislav Petkov struct firmware fw; 5559d489604SBorislav Petkov 5569d489604SBorislav Petkov if (IS_ENABLED(CONFIG_X86_32)) 5579d489604SBorislav Petkov return false; 558fe055896SBorislav Petkov 559fe055896SBorislav Petkov if (family >= 0x15) 560fe055896SBorislav Petkov snprintf(fw_name, sizeof(fw_name), 5612e9064faSPaolo Bonzini "amd-ucode/microcode_amd_fam%02hhxh.bin", family); 562fe055896SBorislav Petkov 5639d489604SBorislav Petkov if (firmware_request_builtin(&fw, fw_name)) { 5649d489604SBorislav Petkov cp->size = fw.size; 5659d489604SBorislav Petkov cp->data = (void *)fw.data; 5669d489604SBorislav Petkov return true; 5679d489604SBorislav Petkov } 5689d489604SBorislav Petkov 569fe055896SBorislav Petkov return false; 570fe055896SBorislav Petkov } 571fe055896SBorislav Petkov 572a85c08aaSNikolay Borisov static bool __init find_blobs_in_containers(struct cpio_data *ret) 573fe055896SBorislav Petkov { 574fe055896SBorislav Petkov struct cpio_data cp; 575a85c08aaSNikolay Borisov bool found; 576fe055896SBorislav Petkov 57794838d23SBorislav Petkov if (!get_builtin_microcode(&cp)) 5780b62f6cbSThomas Gleixner cp = find_microcode_in_initrd(ucode_path); 5796c545647SBorislav Petkov 580a85c08aaSNikolay Borisov found = cp.data && cp.size; 581a85c08aaSNikolay Borisov if (found) 582e71bb4ecSBorislav Petkov *ret = cp; 583a85c08aaSNikolay Borisov 584a85c08aaSNikolay Borisov return found; 585fe055896SBorislav Petkov } 586fe055896SBorislav Petkov 587080990aaSBorislav Petkov (AMD) void __init load_ucode_amd_bsp(struct early_load_data *ed, unsigned int cpuid_1_eax) 588fe055896SBorislav Petkov { 589e71bb4ecSBorislav Petkov struct cpio_data cp = { }; 590080990aaSBorislav Petkov (AMD) u32 dummy; 591080990aaSBorislav Petkov (AMD) 59294838d23SBorislav Petkov bsp_cpuid_1_eax = cpuid_1_eax; 59394838d23SBorislav Petkov 594080990aaSBorislav Petkov (AMD) native_rdmsr(MSR_AMD64_PATCH_LEVEL, ed->old_rev, dummy); 595fe055896SBorislav Petkov 596ecfd4108SThomas Gleixner /* Needed in load_microcode_amd() */ 5975af05b8dSThomas Gleixner ucode_cpu_info[0].cpu_sig.sig = cpuid_1_eax; 598ecfd4108SThomas Gleixner 599a85c08aaSNikolay Borisov if (!find_blobs_in_containers(&cp)) 600fe055896SBorislav Petkov return; 601fe055896SBorislav Petkov 60294838d23SBorislav Petkov if (early_apply_microcode(ed->old_rev, cp.data, cp.size)) 603080990aaSBorislav Petkov (AMD) native_rdmsr(MSR_AMD64_PATCH_LEVEL, ed->new_rev, dummy); 604fe055896SBorislav Petkov } 605e71bb4ecSBorislav Petkov 6061d81d85dSBorislav Petkov (AMD) static enum ucode_state _load_microcode_amd(u8 family, const u8 *data, size_t size); 60776bd11c2SBorislav Petkov 608a7939f01SThomas Gleixner static int __init save_microcode_in_initrd(void) 609fe055896SBorislav Petkov { 610a7939f01SThomas Gleixner unsigned int cpuid_1_eax = native_cpuid_eax(1); 611a7939f01SThomas Gleixner struct cpuinfo_x86 *c = &boot_cpu_data; 61272edfe95SBorislav Petkov struct cont_desc desc = { 0 }; 613fe055896SBorislav Petkov enum ucode_state ret; 6148cc26e0bSBorislav Petkov struct cpio_data cp; 615fe055896SBorislav Petkov 616a7939f01SThomas Gleixner if (dis_ucode_ldr || c->x86_vendor != X86_VENDOR_AMD || c->x86 < 0x10) 617a7939f01SThomas Gleixner return 0; 618a7939f01SThomas Gleixner 619a85c08aaSNikolay Borisov if (!find_blobs_in_containers(&cp)) 62006b8534cSBorislav Petkov return -EINVAL; 621fe055896SBorislav Petkov 62272edfe95SBorislav Petkov scan_containers(cp.data, cp.size, &desc); 623da0aa3ddSBorislav Petkov if (!desc.mc) 62406b8534cSBorislav Petkov return -EINVAL; 62588b2f634SBorislav Petkov 6261d81d85dSBorislav Petkov (AMD) ret = _load_microcode_amd(x86_family(cpuid_1_eax), desc.data, desc.size); 6272613f36eSBorislav Petkov if (ret > UCODE_UPDATED) 62872edfe95SBorislav Petkov return -EINVAL; 629fe055896SBorislav Petkov 63072edfe95SBorislav Petkov return 0; 631fe055896SBorislav Petkov } 632a7939f01SThomas Gleixner early_initcall(save_microcode_in_initrd); 633fe055896SBorislav Petkov 634d1744a4cSBorislav Petkov (AMD) static inline bool patch_cpus_equivalent(struct ucode_patch *p, 635d1744a4cSBorislav Petkov (AMD) struct ucode_patch *n, 636d1744a4cSBorislav Petkov (AMD) bool ignore_stepping) 63794838d23SBorislav Petkov { 63894838d23SBorislav Petkov /* Zen and newer hardcode the f/m/s in the patch ID */ 63994838d23SBorislav Petkov if (x86_family(bsp_cpuid_1_eax) >= 0x17) { 64094838d23SBorislav Petkov union cpuid_1_eax p_cid = ucode_rev_to_cpuid(p->patch_id); 64194838d23SBorislav Petkov union cpuid_1_eax n_cid = ucode_rev_to_cpuid(n->patch_id); 64294838d23SBorislav Petkov 643d1744a4cSBorislav Petkov (AMD) if (ignore_stepping) { 64494838d23SBorislav Petkov p_cid.stepping = 0; 64594838d23SBorislav Petkov n_cid.stepping = 0; 646d1744a4cSBorislav Petkov (AMD) } 64794838d23SBorislav Petkov 64894838d23SBorislav Petkov return p_cid.full == n_cid.full; 64994838d23SBorislav Petkov } else { 65094838d23SBorislav Petkov return p->equiv_cpu == n->equiv_cpu; 65194838d23SBorislav Petkov } 65294838d23SBorislav Petkov } 65394838d23SBorislav Petkov 654bad5fa63SBorislav Petkov /* 655bad5fa63SBorislav Petkov * a small, trivial cache of per-family ucode patches 656bad5fa63SBorislav Petkov */ 65794838d23SBorislav Petkov static struct ucode_patch *cache_find_patch(struct ucode_cpu_info *uci, u16 equiv_cpu) 658bad5fa63SBorislav Petkov { 659bad5fa63SBorislav Petkov struct ucode_patch *p; 66094838d23SBorislav Petkov struct ucode_patch n; 66194838d23SBorislav Petkov 66294838d23SBorislav Petkov n.equiv_cpu = equiv_cpu; 66394838d23SBorislav Petkov n.patch_id = uci->cpu_sig.rev; 66494838d23SBorislav Petkov 66594838d23SBorislav Petkov WARN_ON_ONCE(!n.patch_id); 666bad5fa63SBorislav Petkov 667058dc498SBorislav Petkov list_for_each_entry(p, µcode_cache, plist) 668d1744a4cSBorislav Petkov (AMD) if (patch_cpus_equivalent(p, &n, false)) 669bad5fa63SBorislav Petkov return p; 67094838d23SBorislav Petkov 671bad5fa63SBorislav Petkov return NULL; 672bad5fa63SBorislav Petkov } 673bad5fa63SBorislav Petkov 674d1744a4cSBorislav Petkov (AMD) static inline int patch_newer(struct ucode_patch *p, struct ucode_patch *n) 67594838d23SBorislav Petkov { 67694838d23SBorislav Petkov /* Zen and newer hardcode the f/m/s in the patch ID */ 67794838d23SBorislav Petkov if (x86_family(bsp_cpuid_1_eax) >= 0x17) { 67894838d23SBorislav Petkov union zen_patch_rev zp, zn; 67994838d23SBorislav Petkov 68094838d23SBorislav Petkov zp.ucode_rev = p->patch_id; 68194838d23SBorislav Petkov zn.ucode_rev = n->patch_id; 68294838d23SBorislav Petkov 683d1744a4cSBorislav Petkov (AMD) if (zn.stepping != zp.stepping) 684d1744a4cSBorislav Petkov (AMD) return -1; 685d1744a4cSBorislav Petkov (AMD) 68694838d23SBorislav Petkov return zn.rev > zp.rev; 68794838d23SBorislav Petkov } else { 68894838d23SBorislav Petkov return n->patch_id > p->patch_id; 68994838d23SBorislav Petkov } 69094838d23SBorislav Petkov } 69194838d23SBorislav Petkov 692bad5fa63SBorislav Petkov static void update_cache(struct ucode_patch *new_patch) 693bad5fa63SBorislav Petkov { 694bad5fa63SBorislav Petkov struct ucode_patch *p; 695d1744a4cSBorislav Petkov (AMD) int ret; 696bad5fa63SBorislav Petkov 697058dc498SBorislav Petkov list_for_each_entry(p, µcode_cache, plist) { 698d1744a4cSBorislav Petkov (AMD) if (patch_cpus_equivalent(p, new_patch, true)) { 699d1744a4cSBorislav Petkov (AMD) ret = patch_newer(p, new_patch); 700d1744a4cSBorislav Petkov (AMD) if (ret < 0) 701d1744a4cSBorislav Petkov (AMD) continue; 702d1744a4cSBorislav Petkov (AMD) else if (!ret) { 703bad5fa63SBorislav Petkov /* we already have the latest patch */ 704a99f0342SShu Wang kfree(new_patch->data); 705a99f0342SShu Wang kfree(new_patch); 706bad5fa63SBorislav Petkov return; 707a99f0342SShu Wang } 708bad5fa63SBorislav Petkov 709bad5fa63SBorislav Petkov list_replace(&p->plist, &new_patch->plist); 710bad5fa63SBorislav Petkov kfree(p->data); 711bad5fa63SBorislav Petkov kfree(p); 712bad5fa63SBorislav Petkov return; 713bad5fa63SBorislav Petkov } 714bad5fa63SBorislav Petkov } 715bad5fa63SBorislav Petkov /* no patch found, add it */ 716058dc498SBorislav Petkov list_add_tail(&new_patch->plist, µcode_cache); 717bad5fa63SBorislav Petkov } 718bad5fa63SBorislav Petkov 719bad5fa63SBorislav Petkov static void free_cache(void) 720bad5fa63SBorislav Petkov { 721bad5fa63SBorislav Petkov struct ucode_patch *p, *tmp; 722bad5fa63SBorislav Petkov 723058dc498SBorislav Petkov list_for_each_entry_safe(p, tmp, µcode_cache, plist) { 724bad5fa63SBorislav Petkov __list_del(p->plist.prev, p->plist.next); 725bad5fa63SBorislav Petkov kfree(p->data); 726bad5fa63SBorislav Petkov kfree(p); 727bad5fa63SBorislav Petkov } 728bad5fa63SBorislav Petkov } 729bad5fa63SBorislav Petkov 730bad5fa63SBorislav Petkov static struct ucode_patch *find_patch(unsigned int cpu) 731bad5fa63SBorislav Petkov { 73237a19366SBorislav Petkov (AMD) struct ucode_cpu_info *uci = ucode_cpu_info + cpu; 73394838d23SBorislav Petkov u32 rev, dummy __always_unused; 7345343558aSBorislav Petkov (AMD) u16 equiv_id = 0; 735bad5fa63SBorislav Petkov 73694838d23SBorislav Petkov /* fetch rev if not populated yet: */ 73794838d23SBorislav Petkov if (!uci->cpu_sig.rev) { 73894838d23SBorislav Petkov rdmsr(MSR_AMD64_PATCH_LEVEL, rev, dummy); 73994838d23SBorislav Petkov uci->cpu_sig.rev = rev; 74094838d23SBorislav Petkov } 74194838d23SBorislav Petkov 74294838d23SBorislav Petkov if (x86_family(bsp_cpuid_1_eax) < 0x17) { 74337a19366SBorislav Petkov (AMD) equiv_id = find_equiv_id(&equiv_table, uci->cpu_sig.sig); 744bad5fa63SBorislav Petkov if (!equiv_id) 745bad5fa63SBorislav Petkov return NULL; 74694838d23SBorislav Petkov } 747bad5fa63SBorislav Petkov 74894838d23SBorislav Petkov return cache_find_patch(uci, equiv_id); 749bad5fa63SBorislav Petkov } 750bad5fa63SBorislav Petkov 75105e91e72SBorislav Petkov (AMD) void reload_ucode_amd(unsigned int cpu) 75205e91e72SBorislav Petkov (AMD) { 75305e91e72SBorislav Petkov (AMD) u32 rev, dummy __always_unused; 75405e91e72SBorislav Petkov (AMD) struct microcode_amd *mc; 75505e91e72SBorislav Petkov (AMD) struct ucode_patch *p; 75605e91e72SBorislav Petkov (AMD) 75705e91e72SBorislav Petkov (AMD) p = find_patch(cpu); 75805e91e72SBorislav Petkov (AMD) if (!p) 75905e91e72SBorislav Petkov (AMD) return; 76005e91e72SBorislav Petkov (AMD) 76105e91e72SBorislav Petkov (AMD) mc = p->data; 76205e91e72SBorislav Petkov (AMD) 76305e91e72SBorislav Petkov (AMD) rdmsr(MSR_AMD64_PATCH_LEVEL, rev, dummy); 76405e91e72SBorislav Petkov (AMD) 76505e91e72SBorislav Petkov (AMD) if (rev < mc->hdr.patch_id) { 766c809b0d0SBorislav Petkov (AMD) if (!__apply_microcode_amd(mc, p->size)) 767080990aaSBorislav Petkov (AMD) pr_info_once("reload revision: 0x%08x\n", mc->hdr.patch_id); 76805e91e72SBorislav Petkov (AMD) } 76905e91e72SBorislav Petkov (AMD) } 77005e91e72SBorislav Petkov (AMD) 771bad5fa63SBorislav Petkov static int collect_cpu_info_amd(int cpu, struct cpu_signature *csig) 772bad5fa63SBorislav Petkov { 773bad5fa63SBorislav Petkov struct cpuinfo_x86 *c = &cpu_data(cpu); 774bad5fa63SBorislav Petkov struct ucode_cpu_info *uci = ucode_cpu_info + cpu; 775bad5fa63SBorislav Petkov struct ucode_patch *p; 776bad5fa63SBorislav Petkov 777bad5fa63SBorislav Petkov csig->sig = cpuid_eax(0x00000001); 778bad5fa63SBorislav Petkov csig->rev = c->microcode; 779bad5fa63SBorislav Petkov 780bad5fa63SBorislav Petkov /* 781bad5fa63SBorislav Petkov * a patch could have been loaded early, set uci->mc so that 782bad5fa63SBorislav Petkov * mc_bp_resume() can call apply_microcode() 783bad5fa63SBorislav Petkov */ 784bad5fa63SBorislav Petkov p = find_patch(cpu); 785bad5fa63SBorislav Petkov if (p && (p->patch_id == csig->rev)) 786bad5fa63SBorislav Petkov uci->mc = p->data; 787bad5fa63SBorislav Petkov 788bad5fa63SBorislav Petkov return 0; 789bad5fa63SBorislav Petkov } 790bad5fa63SBorislav Petkov 7913f1f576aSBorislav Petkov static enum ucode_state apply_microcode_amd(int cpu) 792bad5fa63SBorislav Petkov { 793bad5fa63SBorislav Petkov struct cpuinfo_x86 *c = &cpu_data(cpu); 794bad5fa63SBorislav Petkov struct microcode_amd *mc_amd; 795bad5fa63SBorislav Petkov struct ucode_cpu_info *uci; 796bad5fa63SBorislav Petkov struct ucode_patch *p; 7978da38ebaSFilippo Sironi enum ucode_state ret; 79894838d23SBorislav Petkov u32 rev; 799bad5fa63SBorislav Petkov 800bad5fa63SBorislav Petkov BUG_ON(raw_smp_processor_id() != cpu); 801bad5fa63SBorislav Petkov 802bad5fa63SBorislav Petkov uci = ucode_cpu_info + cpu; 803bad5fa63SBorislav Petkov 804bad5fa63SBorislav Petkov p = find_patch(cpu); 805bad5fa63SBorislav Petkov if (!p) 8063f1f576aSBorislav Petkov return UCODE_NFOUND; 807bad5fa63SBorislav Petkov 80894838d23SBorislav Petkov rev = uci->cpu_sig.rev; 80994838d23SBorislav Petkov 810bad5fa63SBorislav Petkov mc_amd = p->data; 811bad5fa63SBorislav Petkov uci->mc = p->data; 812bad5fa63SBorislav Petkov 813bad5fa63SBorislav Petkov /* need to apply patch? */ 814a32b0f0dSBorislav Petkov (AMD) if (rev > mc_amd->hdr.patch_id) { 8158da38ebaSFilippo Sironi ret = UCODE_OK; 8168da38ebaSFilippo Sironi goto out; 817bad5fa63SBorislav Petkov } 818bad5fa63SBorislav Petkov 819c809b0d0SBorislav Petkov (AMD) if (__apply_microcode_amd(mc_amd, p->size)) { 820bad5fa63SBorislav Petkov pr_err("CPU%d: update failed for patch_level=0x%08x\n", 821bad5fa63SBorislav Petkov cpu, mc_amd->hdr.patch_id); 8223f1f576aSBorislav Petkov return UCODE_ERROR; 823bad5fa63SBorislav Petkov } 824bad5fa63SBorislav Petkov 8258da38ebaSFilippo Sironi rev = mc_amd->hdr.patch_id; 8268da38ebaSFilippo Sironi ret = UCODE_UPDATED; 8278da38ebaSFilippo Sironi 8288da38ebaSFilippo Sironi out: 8298da38ebaSFilippo Sironi uci->cpu_sig.rev = rev; 8308da38ebaSFilippo Sironi c->microcode = rev; 831bad5fa63SBorislav Petkov 832370a132bSPrarit Bhargava /* Update boot_cpu_data's revision too, if we're on the BSP: */ 833370a132bSPrarit Bhargava if (c->cpu_index == boot_cpu_data.cpu_index) 8348da38ebaSFilippo Sironi boot_cpu_data.microcode = rev; 835370a132bSPrarit Bhargava 8368da38ebaSFilippo Sironi return ret; 837bad5fa63SBorislav Petkov } 838bad5fa63SBorislav Petkov 8395af05b8dSThomas Gleixner void load_ucode_amd_ap(unsigned int cpuid_1_eax) 8405af05b8dSThomas Gleixner { 8415af05b8dSThomas Gleixner unsigned int cpu = smp_processor_id(); 8425af05b8dSThomas Gleixner 8435af05b8dSThomas Gleixner ucode_cpu_info[cpu].cpu_sig.sig = cpuid_1_eax; 8445af05b8dSThomas Gleixner apply_microcode_amd(cpu); 8455af05b8dSThomas Gleixner } 8465af05b8dSThomas Gleixner 84738673f62SMaciej S. Szmigiero static size_t install_equiv_cpu_table(const u8 *buf, size_t buf_size) 848bad5fa63SBorislav Petkov { 84938673f62SMaciej S. Szmigiero u32 equiv_tbl_len; 85038673f62SMaciej S. Szmigiero const u32 *hdr; 851bad5fa63SBorislav Petkov 8520b62f6cbSThomas Gleixner if (!verify_equivalence_table(buf, buf_size)) 85338673f62SMaciej S. Szmigiero return 0; 854bad5fa63SBorislav Petkov 85538673f62SMaciej S. Szmigiero hdr = (const u32 *)buf; 85638673f62SMaciej S. Szmigiero equiv_tbl_len = hdr[2]; 85738673f62SMaciej S. Szmigiero 85894838d23SBorislav Petkov /* Zen and newer do not need an equivalence table. */ 85994838d23SBorislav Petkov if (x86_family(bsp_cpuid_1_eax) >= 0x17) 86094838d23SBorislav Petkov goto out; 86194838d23SBorislav Petkov 86239cd7c17SMaciej S. Szmigiero equiv_table.entry = vmalloc(equiv_tbl_len); 86339cd7c17SMaciej S. Szmigiero if (!equiv_table.entry) { 864bad5fa63SBorislav Petkov pr_err("failed to allocate equivalent CPU table\n"); 86538673f62SMaciej S. Szmigiero return 0; 866bad5fa63SBorislav Petkov } 867bad5fa63SBorislav Petkov 86839cd7c17SMaciej S. Szmigiero memcpy(equiv_table.entry, buf + CONTAINER_HDR_SZ, equiv_tbl_len); 869413c8915SMaciej S. Szmigiero equiv_table.num_entries = equiv_tbl_len / sizeof(struct equiv_cpu_entry); 870bad5fa63SBorislav Petkov 87194838d23SBorislav Petkov out: 872bad5fa63SBorislav Petkov /* add header length */ 87338673f62SMaciej S. Szmigiero return equiv_tbl_len + CONTAINER_HDR_SZ; 874bad5fa63SBorislav Petkov } 875bad5fa63SBorislav Petkov 876bad5fa63SBorislav Petkov static void free_equiv_cpu_table(void) 877bad5fa63SBorislav Petkov { 87894838d23SBorislav Petkov if (x86_family(bsp_cpuid_1_eax) >= 0x17) 87994838d23SBorislav Petkov return; 88094838d23SBorislav Petkov 88139cd7c17SMaciej S. Szmigiero vfree(equiv_table.entry); 882413c8915SMaciej S. Szmigiero memset(&equiv_table, 0, sizeof(equiv_table)); 883bad5fa63SBorislav Petkov } 884bad5fa63SBorislav Petkov 885bad5fa63SBorislav Petkov static void cleanup(void) 886bad5fa63SBorislav Petkov { 887bad5fa63SBorislav Petkov free_equiv_cpu_table(); 888bad5fa63SBorislav Petkov free_cache(); 889bad5fa63SBorislav Petkov } 890bad5fa63SBorislav Petkov 891bad5fa63SBorislav Petkov /* 8922b8d34b1SBorislav Petkov * Return a non-negative value even if some of the checks failed so that 893bad5fa63SBorislav Petkov * we can skip over the next patch. If we return a negative value, we 894bad5fa63SBorislav Petkov * signal a grave error like a memory allocation has failed and the 895bad5fa63SBorislav Petkov * driver cannot continue functioning normally. In such cases, we tear 896bad5fa63SBorislav Petkov * down everything we've used up so far and exit. 897bad5fa63SBorislav Petkov */ 898d430a305SBorislav Petkov static int verify_and_add_patch(u8 family, u8 *fw, unsigned int leftover, 899d430a305SBorislav Petkov unsigned int *patch_size) 900bad5fa63SBorislav Petkov { 901bad5fa63SBorislav Petkov struct microcode_header_amd *mc_hdr; 902bad5fa63SBorislav Petkov struct ucode_patch *patch; 903bad5fa63SBorislav Petkov u16 proc_id; 904d430a305SBorislav Petkov int ret; 905bad5fa63SBorislav Petkov 90694838d23SBorislav Petkov ret = verify_patch(fw, leftover, patch_size); 907d430a305SBorislav Petkov if (ret) 908d430a305SBorislav Petkov return ret; 909bad5fa63SBorislav Petkov 910bad5fa63SBorislav Petkov patch = kzalloc(sizeof(*patch), GFP_KERNEL); 911bad5fa63SBorislav Petkov if (!patch) { 912bad5fa63SBorislav Petkov pr_err("Patch allocation failure.\n"); 913bad5fa63SBorislav Petkov return -EINVAL; 914bad5fa63SBorislav Petkov } 915bad5fa63SBorislav Petkov 916d430a305SBorislav Petkov patch->data = kmemdup(fw + SECTION_HDR_SIZE, *patch_size, GFP_KERNEL); 917bad5fa63SBorislav Petkov if (!patch->data) { 918bad5fa63SBorislav Petkov pr_err("Patch data allocation failure.\n"); 919bad5fa63SBorislav Petkov kfree(patch); 920bad5fa63SBorislav Petkov return -EINVAL; 921bad5fa63SBorislav Petkov } 922712f210aSKees Cook patch->size = *patch_size; 923bad5fa63SBorislav Petkov 924d430a305SBorislav Petkov mc_hdr = (struct microcode_header_amd *)(fw + SECTION_HDR_SIZE); 925d430a305SBorislav Petkov proc_id = mc_hdr->processor_rev_id; 926d430a305SBorislav Petkov 927bad5fa63SBorislav Petkov INIT_LIST_HEAD(&patch->plist); 928bad5fa63SBorislav Petkov patch->patch_id = mc_hdr->patch_id; 929bad5fa63SBorislav Petkov patch->equiv_cpu = proc_id; 930bad5fa63SBorislav Petkov 93194838d23SBorislav Petkov pr_debug("%s: Adding patch_id: 0x%08x, proc_id: 0x%04x\n", 932bad5fa63SBorislav Petkov __func__, patch->patch_id, proc_id); 933bad5fa63SBorislav Petkov 934bad5fa63SBorislav Petkov /* ... and add to cache. */ 935bad5fa63SBorislav Petkov update_cache(patch); 936bad5fa63SBorislav Petkov 937d430a305SBorislav Petkov return 0; 938bad5fa63SBorislav Petkov } 939bad5fa63SBorislav Petkov 94061de9b70SBorislav Petkov /* Scan the blob in @data and add microcode patches to the cache. */ 941bad5fa63SBorislav Petkov static enum ucode_state __load_microcode_amd(u8 family, const u8 *data, 942bad5fa63SBorislav Petkov size_t size) 943bad5fa63SBorislav Petkov { 944bad5fa63SBorislav Petkov u8 *fw = (u8 *)data; 94538673f62SMaciej S. Szmigiero size_t offset; 946bad5fa63SBorislav Petkov 94738673f62SMaciej S. Szmigiero offset = install_equiv_cpu_table(data, size); 94838673f62SMaciej S. Szmigiero if (!offset) 949d430a305SBorislav Petkov return UCODE_ERROR; 95038673f62SMaciej S. Szmigiero 951bad5fa63SBorislav Petkov fw += offset; 952d430a305SBorislav Petkov size -= offset; 953bad5fa63SBorislav Petkov 954bad5fa63SBorislav Petkov if (*(u32 *)fw != UCODE_UCODE_TYPE) { 955bad5fa63SBorislav Petkov pr_err("invalid type field in container file section header\n"); 956bad5fa63SBorislav Petkov free_equiv_cpu_table(); 957d430a305SBorislav Petkov return UCODE_ERROR; 958bad5fa63SBorislav Petkov } 959bad5fa63SBorislav Petkov 960d430a305SBorislav Petkov while (size > 0) { 961d430a305SBorislav Petkov unsigned int crnt_size = 0; 962d430a305SBorislav Petkov int ret; 963bad5fa63SBorislav Petkov 964d430a305SBorislav Petkov ret = verify_and_add_patch(family, fw, size, &crnt_size); 965d430a305SBorislav Petkov if (ret < 0) 966d430a305SBorislav Petkov return UCODE_ERROR; 967d430a305SBorislav Petkov 968d430a305SBorislav Petkov fw += crnt_size + SECTION_HDR_SIZE; 969d430a305SBorislav Petkov size -= (crnt_size + SECTION_HDR_SIZE); 970bad5fa63SBorislav Petkov } 971bad5fa63SBorislav Petkov 972bad5fa63SBorislav Petkov return UCODE_OK; 973bad5fa63SBorislav Petkov } 974bad5fa63SBorislav Petkov 9751d81d85dSBorislav Petkov (AMD) static enum ucode_state _load_microcode_amd(u8 family, const u8 *data, size_t size) 9761d81d85dSBorislav Petkov (AMD) { 9771d81d85dSBorislav Petkov (AMD) enum ucode_state ret; 9781d81d85dSBorislav Petkov (AMD) 9791d81d85dSBorislav Petkov (AMD) /* free old equiv table */ 9801d81d85dSBorislav Petkov (AMD) free_equiv_cpu_table(); 9811d81d85dSBorislav Petkov (AMD) 9821d81d85dSBorislav Petkov (AMD) ret = __load_microcode_amd(family, data, size); 9831d81d85dSBorislav Petkov (AMD) if (ret != UCODE_OK) 9841d81d85dSBorislav Petkov (AMD) cleanup(); 9851d81d85dSBorislav Petkov (AMD) 9861d81d85dSBorislav Petkov (AMD) return ret; 9871d81d85dSBorislav Petkov (AMD) } 9881d81d85dSBorislav Petkov (AMD) 9892355370cSBorislav Petkov (AMD) static enum ucode_state load_microcode_amd(u8 family, const u8 *data, size_t size) 990bad5fa63SBorislav Petkov { 9917ff6edf4SBorislav Petkov (AMD) struct cpuinfo_x86 *c; 9927ff6edf4SBorislav Petkov (AMD) unsigned int nid, cpu; 9932613f36eSBorislav Petkov struct ucode_patch *p; 994bad5fa63SBorislav Petkov enum ucode_state ret; 995bad5fa63SBorislav Petkov 9961d81d85dSBorislav Petkov (AMD) ret = _load_microcode_amd(family, data, size); 9971d81d85dSBorislav Petkov (AMD) if (ret != UCODE_OK) 9982613f36eSBorislav Petkov return ret; 999bad5fa63SBorislav Petkov 10007ff6edf4SBorislav Petkov (AMD) for_each_node(nid) { 10017ff6edf4SBorislav Petkov (AMD) cpu = cpumask_first(cpumask_of_node(nid)); 10027ff6edf4SBorislav Petkov (AMD) c = &cpu_data(cpu); 10037ff6edf4SBorislav Petkov (AMD) 10047ff6edf4SBorislav Petkov (AMD) p = find_patch(cpu); 10057ff6edf4SBorislav Petkov (AMD) if (!p) 10067ff6edf4SBorislav Petkov (AMD) continue; 10077ff6edf4SBorislav Petkov (AMD) 10087ff6edf4SBorislav Petkov (AMD) if (c->microcode >= p->patch_id) 10097ff6edf4SBorislav Petkov (AMD) continue; 10102613f36eSBorislav Petkov 10112613f36eSBorislav Petkov ret = UCODE_NEW; 10127ff6edf4SBorislav Petkov (AMD) } 10132613f36eSBorislav Petkov 1014bad5fa63SBorislav Petkov return ret; 1015bad5fa63SBorislav Petkov } 1016bad5fa63SBorislav Petkov 1017bad5fa63SBorislav Petkov /* 1018bad5fa63SBorislav Petkov * AMD microcode firmware naming convention, up to family 15h they are in 1019bad5fa63SBorislav Petkov * the legacy file: 1020bad5fa63SBorislav Petkov * 1021bad5fa63SBorislav Petkov * amd-ucode/microcode_amd.bin 1022bad5fa63SBorislav Petkov * 1023bad5fa63SBorislav Petkov * This legacy file is always smaller than 2K in size. 1024bad5fa63SBorislav Petkov * 1025bad5fa63SBorislav Petkov * Beginning with family 15h, they are in family-specific firmware files: 1026bad5fa63SBorislav Petkov * 1027bad5fa63SBorislav Petkov * amd-ucode/microcode_amd_fam15h.bin 1028bad5fa63SBorislav Petkov * amd-ucode/microcode_amd_fam16h.bin 1029bad5fa63SBorislav Petkov * ... 1030bad5fa63SBorislav Petkov * 1031bad5fa63SBorislav Petkov * These might be larger than 2K. 1032bad5fa63SBorislav Petkov */ 1033a61ac80aSBorislav Petkov static enum ucode_state request_microcode_amd(int cpu, struct device *device) 1034bad5fa63SBorislav Petkov { 1035bad5fa63SBorislav Petkov char fw_name[36] = "amd-ucode/microcode_amd.bin"; 1036bad5fa63SBorislav Petkov struct cpuinfo_x86 *c = &cpu_data(cpu); 1037bad5fa63SBorislav Petkov enum ucode_state ret = UCODE_NFOUND; 1038bad5fa63SBorislav Petkov const struct firmware *fw; 1039bad5fa63SBorislav Petkov 10409407bda8SThomas Gleixner if (force_minrev) 10419407bda8SThomas Gleixner return UCODE_NFOUND; 10429407bda8SThomas Gleixner 1043bad5fa63SBorislav Petkov if (c->x86 >= 0x15) 1044bad5fa63SBorislav Petkov snprintf(fw_name, sizeof(fw_name), "amd-ucode/microcode_amd_fam%.2xh.bin", c->x86); 1045bad5fa63SBorislav Petkov 1046d3bad75aSLinus Torvalds if (request_firmware_direct(&fw, (const char *)fw_name, device)) { 1047bad5fa63SBorislav Petkov pr_debug("failed to load file %s\n", fw_name); 1048bad5fa63SBorislav Petkov goto out; 1049bad5fa63SBorislav Petkov } 1050bad5fa63SBorislav Petkov 1051bad5fa63SBorislav Petkov ret = UCODE_ERROR; 10520b62f6cbSThomas Gleixner if (!verify_container(fw->data, fw->size)) 1053bad5fa63SBorislav Petkov goto fw_release; 1054bad5fa63SBorislav Petkov 10552355370cSBorislav Petkov (AMD) ret = load_microcode_amd(c->x86, fw->data, fw->size); 1056bad5fa63SBorislav Petkov 1057bad5fa63SBorislav Petkov fw_release: 1058bad5fa63SBorislav Petkov release_firmware(fw); 1059bad5fa63SBorislav Petkov 1060bad5fa63SBorislav Petkov out: 1061bad5fa63SBorislav Petkov return ret; 1062bad5fa63SBorislav Petkov } 1063bad5fa63SBorislav Petkov 1064bad5fa63SBorislav Petkov static void microcode_fini_cpu_amd(int cpu) 1065bad5fa63SBorislav Petkov { 1066bad5fa63SBorislav Petkov struct ucode_cpu_info *uci = ucode_cpu_info + cpu; 1067bad5fa63SBorislav Petkov 1068bad5fa63SBorislav Petkov uci->mc = NULL; 1069bad5fa63SBorislav Petkov } 1070bad5fa63SBorislav Petkov 1071bad5fa63SBorislav Petkov static struct microcode_ops microcode_amd_ops = { 1072bad5fa63SBorislav Petkov .request_microcode_fw = request_microcode_amd, 1073bad5fa63SBorislav Petkov .collect_cpu_info = collect_cpu_info_amd, 1074bad5fa63SBorislav Petkov .apply_microcode = apply_microcode_amd, 1075bad5fa63SBorislav Petkov .microcode_fini_cpu = microcode_fini_cpu_amd, 1076634ac23aSThomas Gleixner .nmi_safe = true, 1077bad5fa63SBorislav Petkov }; 1078bad5fa63SBorislav Petkov 1079bad5fa63SBorislav Petkov struct microcode_ops * __init init_amd_microcode(void) 1080bad5fa63SBorislav Petkov { 10819a2bc335SBorislav Petkov struct cpuinfo_x86 *c = &boot_cpu_data; 1082bad5fa63SBorislav Petkov 1083bad5fa63SBorislav Petkov if (c->x86_vendor != X86_VENDOR_AMD || c->x86 < 0x10) { 10841b74dde7SChen Yucong pr_warn("AMD CPU family 0x%x not supported\n", c->x86); 1085bad5fa63SBorislav Petkov return NULL; 1086bad5fa63SBorislav Petkov } 1087bad5fa63SBorislav Petkov return µcode_amd_ops; 1088bad5fa63SBorislav Petkov } 1089bad5fa63SBorislav Petkov 1090bad5fa63SBorislav Petkov void __exit exit_amd_microcode(void) 1091bad5fa63SBorislav Petkov { 1092bad5fa63SBorislav Petkov cleanup(); 1093bad5fa63SBorislav Petkov } 1094