Path: blob/master/arch/x86/kernel/cpu/microcode/intel.c
26515 views
// SPDX-License-Identifier: GPL-2.0-or-later1/*2* Intel CPU Microcode Update Driver for Linux3*4* Copyright (C) 2000-2006 Tigran Aivazian <[email protected]>5* 2006 Shaohua Li <[email protected]>6*7* Intel CPU microcode early update for Linux8*9* Copyright (C) 2012 Fenghua Yu <[email protected]>10* H Peter Anvin" <[email protected]>11*/12#define pr_fmt(fmt) "microcode: " fmt13#include <linux/earlycpio.h>14#include <linux/firmware.h>15#include <linux/uaccess.h>16#include <linux/initrd.h>17#include <linux/kernel.h>18#include <linux/slab.h>19#include <linux/cpu.h>20#include <linux/uio.h>21#include <linux/mm.h>2223#include <asm/cpu_device_id.h>24#include <asm/processor.h>25#include <asm/tlbflush.h>26#include <asm/setup.h>27#include <asm/msr.h>2829#include "internal.h"3031static const char ucode_path[] = "kernel/x86/microcode/GenuineIntel.bin";3233#define UCODE_BSP_LOADED ((struct microcode_intel *)0x1UL)3435/* Current microcode patch used in early patching on the APs. */36static struct microcode_intel *ucode_patch_va __read_mostly;37static struct microcode_intel *ucode_patch_late __read_mostly;3839/* last level cache size per core */40static unsigned int llc_size_per_core __ro_after_init;4142/* microcode format is extended from prescott processors */43struct extended_signature {44unsigned int sig;45unsigned int pf;46unsigned int cksum;47};4849struct extended_sigtable {50unsigned int count;51unsigned int cksum;52unsigned int reserved[3];53struct extended_signature sigs[];54};5556#define DEFAULT_UCODE_TOTALSIZE (DEFAULT_UCODE_DATASIZE + MC_HEADER_SIZE)57#define EXT_HEADER_SIZE (sizeof(struct extended_sigtable))58#define EXT_SIGNATURE_SIZE (sizeof(struct extended_signature))5960static inline unsigned int get_totalsize(struct microcode_header_intel *hdr)61{62return hdr->datasize ? hdr->totalsize : DEFAULT_UCODE_TOTALSIZE;63}6465static inline unsigned int exttable_size(struct extended_sigtable *et)66{67return et->count * EXT_SIGNATURE_SIZE + EXT_HEADER_SIZE;68}6970void intel_collect_cpu_info(struct cpu_signature *sig)71{72sig->sig = cpuid_eax(1);73sig->pf = 0;74sig->rev = intel_get_microcode_revision();7576if (IFM(x86_family(sig->sig), x86_model(sig->sig)) >= INTEL_PENTIUM_III_DESCHUTES) {77unsigned int val[2];7879/* get processor flags from MSR 0x17 */80native_rdmsr(MSR_IA32_PLATFORM_ID, val[0], val[1]);81sig->pf = 1 << ((val[1] >> 18) & 7);82}83}84EXPORT_SYMBOL_GPL(intel_collect_cpu_info);8586static inline bool cpu_signatures_match(struct cpu_signature *s1, unsigned int sig2,87unsigned int pf2)88{89if (s1->sig != sig2)90return false;9192/* Processor flags are either both 0 or they intersect. */93return ((!s1->pf && !pf2) || (s1->pf & pf2));94}9596bool intel_find_matching_signature(void *mc, struct cpu_signature *sig)97{98struct microcode_header_intel *mc_hdr = mc;99struct extended_signature *ext_sig;100struct extended_sigtable *ext_hdr;101int i;102103if (cpu_signatures_match(sig, mc_hdr->sig, mc_hdr->pf))104return true;105106/* Look for ext. headers: */107if (get_totalsize(mc_hdr) <= intel_microcode_get_datasize(mc_hdr) + MC_HEADER_SIZE)108return false;109110ext_hdr = mc + intel_microcode_get_datasize(mc_hdr) + MC_HEADER_SIZE;111ext_sig = (void *)ext_hdr + EXT_HEADER_SIZE;112113for (i = 0; i < ext_hdr->count; i++) {114if (cpu_signatures_match(sig, ext_sig->sig, ext_sig->pf))115return true;116ext_sig++;117}118return 0;119}120EXPORT_SYMBOL_GPL(intel_find_matching_signature);121122/**123* intel_microcode_sanity_check() - Sanity check microcode file.124* @mc: Pointer to the microcode file contents.125* @print_err: Display failure reason if true, silent if false.126* @hdr_type: Type of file, i.e. normal microcode file or In Field Scan file.127* Validate if the microcode header type matches with the type128* specified here.129*130* Validate certain header fields and verify if computed checksum matches131* with the one specified in the header.132*133* Return: 0 if the file passes all the checks, -EINVAL if any of the checks134* fail.135*/136int intel_microcode_sanity_check(void *mc, bool print_err, int hdr_type)137{138unsigned long total_size, data_size, ext_table_size;139struct microcode_header_intel *mc_header = mc;140struct extended_sigtable *ext_header = NULL;141u32 sum, orig_sum, ext_sigcount = 0, i;142struct extended_signature *ext_sig;143144total_size = get_totalsize(mc_header);145data_size = intel_microcode_get_datasize(mc_header);146147if (data_size + MC_HEADER_SIZE > total_size) {148if (print_err)149pr_err("Error: bad microcode data file size.\n");150return -EINVAL;151}152153if (mc_header->ldrver != 1 || mc_header->hdrver != hdr_type) {154if (print_err)155pr_err("Error: invalid/unknown microcode update format. Header type %d\n",156mc_header->hdrver);157return -EINVAL;158}159160ext_table_size = total_size - (MC_HEADER_SIZE + data_size);161if (ext_table_size) {162u32 ext_table_sum = 0;163u32 *ext_tablep;164165if (ext_table_size < EXT_HEADER_SIZE ||166((ext_table_size - EXT_HEADER_SIZE) % EXT_SIGNATURE_SIZE)) {167if (print_err)168pr_err("Error: truncated extended signature table.\n");169return -EINVAL;170}171172ext_header = mc + MC_HEADER_SIZE + data_size;173if (ext_table_size != exttable_size(ext_header)) {174if (print_err)175pr_err("Error: extended signature table size mismatch.\n");176return -EFAULT;177}178179ext_sigcount = ext_header->count;180181/*182* Check extended table checksum: the sum of all dwords that183* comprise a valid table must be 0.184*/185ext_tablep = (u32 *)ext_header;186187i = ext_table_size / sizeof(u32);188while (i--)189ext_table_sum += ext_tablep[i];190191if (ext_table_sum) {192if (print_err)193pr_warn("Bad extended signature table checksum, aborting.\n");194return -EINVAL;195}196}197198/*199* Calculate the checksum of update data and header. The checksum of200* valid update data and header including the extended signature table201* must be 0.202*/203orig_sum = 0;204i = (MC_HEADER_SIZE + data_size) / sizeof(u32);205while (i--)206orig_sum += ((u32 *)mc)[i];207208if (orig_sum) {209if (print_err)210pr_err("Bad microcode data checksum, aborting.\n");211return -EINVAL;212}213214if (!ext_table_size)215return 0;216217/*218* Check extended signature checksum: 0 => valid.219*/220for (i = 0; i < ext_sigcount; i++) {221ext_sig = (void *)ext_header + EXT_HEADER_SIZE +222EXT_SIGNATURE_SIZE * i;223224sum = (mc_header->sig + mc_header->pf + mc_header->cksum) -225(ext_sig->sig + ext_sig->pf + ext_sig->cksum);226if (sum) {227if (print_err)228pr_err("Bad extended signature checksum, aborting.\n");229return -EINVAL;230}231}232return 0;233}234EXPORT_SYMBOL_GPL(intel_microcode_sanity_check);235236static void update_ucode_pointer(struct microcode_intel *mc)237{238kvfree(ucode_patch_va);239240/*241* Save the virtual address for early loading and for eventual free242* on late loading.243*/244ucode_patch_va = mc;245}246247static void save_microcode_patch(struct microcode_intel *patch)248{249unsigned int size = get_totalsize(&patch->hdr);250struct microcode_intel *mc;251252mc = kvmemdup(patch, size, GFP_KERNEL);253if (mc)254update_ucode_pointer(mc);255else256pr_err("Unable to allocate microcode memory size: %u\n", size);257}258259/* Scan blob for microcode matching the boot CPUs family, model, stepping */260static __init struct microcode_intel *scan_microcode(void *data, size_t size,261struct ucode_cpu_info *uci,262bool save)263{264struct microcode_header_intel *mc_header;265struct microcode_intel *patch = NULL;266u32 cur_rev = uci->cpu_sig.rev;267unsigned int mc_size;268269for (; size >= sizeof(struct microcode_header_intel); size -= mc_size, data += mc_size) {270mc_header = (struct microcode_header_intel *)data;271272mc_size = get_totalsize(mc_header);273if (!mc_size || mc_size > size ||274intel_microcode_sanity_check(data, false, MC_HEADER_TYPE_MICROCODE) < 0)275break;276277if (!intel_find_matching_signature(data, &uci->cpu_sig))278continue;279280/*281* For saving the early microcode, find the matching revision which282* was loaded on the BSP.283*284* On the BSP during early boot, find a newer revision than285* actually loaded in the CPU.286*/287if (save) {288if (cur_rev != mc_header->rev)289continue;290} else if (cur_rev >= mc_header->rev) {291continue;292}293294patch = data;295cur_rev = mc_header->rev;296}297298return size ? NULL : patch;299}300301static enum ucode_state __apply_microcode(struct ucode_cpu_info *uci,302struct microcode_intel *mc,303u32 *cur_rev)304{305u32 rev;306307if (!mc)308return UCODE_NFOUND;309310/*311* Save us the MSR write below - which is a particular expensive312* operation - when the other hyperthread has updated the microcode313* already.314*/315*cur_rev = intel_get_microcode_revision();316if (*cur_rev >= mc->hdr.rev) {317uci->cpu_sig.rev = *cur_rev;318return UCODE_OK;319}320321/* write microcode via MSR 0x79 */322native_wrmsrq(MSR_IA32_UCODE_WRITE, (unsigned long)mc->bits);323324rev = intel_get_microcode_revision();325if (rev != mc->hdr.rev)326return UCODE_ERROR;327328uci->cpu_sig.rev = rev;329return UCODE_UPDATED;330}331332static enum ucode_state apply_microcode_early(struct ucode_cpu_info *uci)333{334struct microcode_intel *mc = uci->mc;335u32 cur_rev;336337return __apply_microcode(uci, mc, &cur_rev);338}339340static __init bool load_builtin_intel_microcode(struct cpio_data *cp)341{342unsigned int eax = 1, ebx, ecx = 0, edx;343struct firmware fw;344char name[30];345346if (IS_ENABLED(CONFIG_X86_32))347return false;348349native_cpuid(&eax, &ebx, &ecx, &edx);350351sprintf(name, "intel-ucode/%02x-%02x-%02x",352x86_family(eax), x86_model(eax), x86_stepping(eax));353354if (firmware_request_builtin(&fw, name)) {355cp->size = fw.size;356cp->data = (void *)fw.data;357return true;358}359return false;360}361362static __init struct microcode_intel *get_microcode_blob(struct ucode_cpu_info *uci, bool save)363{364struct cpio_data cp;365366intel_collect_cpu_info(&uci->cpu_sig);367368if (!load_builtin_intel_microcode(&cp))369cp = find_microcode_in_initrd(ucode_path);370371if (!(cp.data && cp.size))372return NULL;373374return scan_microcode(cp.data, cp.size, uci, save);375}376377/*378* Invoked from an early init call to save the microcode blob which was379* selected during early boot when mm was not usable. The microcode must be380* saved because initrd is going away. It's an early init call so the APs381* just can use the pointer and do not have to scan initrd/builtin firmware382* again.383*/384static int __init save_builtin_microcode(void)385{386struct ucode_cpu_info uci;387388if (xchg(&ucode_patch_va, NULL) != UCODE_BSP_LOADED)389return 0;390391if (microcode_loader_disabled() || boot_cpu_data.x86_vendor != X86_VENDOR_INTEL)392return 0;393394uci.mc = get_microcode_blob(&uci, true);395if (uci.mc)396save_microcode_patch(uci.mc);397return 0;398}399early_initcall(save_builtin_microcode);400401/* Load microcode on BSP from initrd or builtin blobs */402void __init load_ucode_intel_bsp(struct early_load_data *ed)403{404struct ucode_cpu_info uci;405406uci.mc = get_microcode_blob(&uci, false);407ed->old_rev = uci.cpu_sig.rev;408409if (uci.mc && apply_microcode_early(&uci) == UCODE_UPDATED) {410ucode_patch_va = UCODE_BSP_LOADED;411ed->new_rev = uci.cpu_sig.rev;412}413}414415void load_ucode_intel_ap(void)416{417struct ucode_cpu_info uci;418419uci.mc = ucode_patch_va;420if (uci.mc)421apply_microcode_early(&uci);422}423424/* Reload microcode on resume */425void reload_ucode_intel(void)426{427struct ucode_cpu_info uci = { .mc = ucode_patch_va, };428429if (uci.mc)430apply_microcode_early(&uci);431}432433static int collect_cpu_info(int cpu_num, struct cpu_signature *csig)434{435intel_collect_cpu_info(csig);436return 0;437}438439static enum ucode_state apply_microcode_late(int cpu)440{441struct ucode_cpu_info *uci = ucode_cpu_info + cpu;442struct microcode_intel *mc = ucode_patch_late;443enum ucode_state ret;444u32 cur_rev;445446if (WARN_ON_ONCE(smp_processor_id() != cpu))447return UCODE_ERROR;448449ret = __apply_microcode(uci, mc, &cur_rev);450if (ret != UCODE_UPDATED && ret != UCODE_OK)451return ret;452453cpu_data(cpu).microcode = uci->cpu_sig.rev;454if (!cpu)455boot_cpu_data.microcode = uci->cpu_sig.rev;456457return ret;458}459460static bool ucode_validate_minrev(struct microcode_header_intel *mc_header)461{462int cur_rev = boot_cpu_data.microcode;463464/*465* When late-loading, ensure the header declares a minimum revision466* required to perform a late-load. The previously reserved field467* is 0 in older microcode blobs.468*/469if (!mc_header->min_req_ver) {470pr_info("Unsafe microcode update: Microcode header does not specify a required min version\n");471return false;472}473474/*475* Check whether the current revision is either greater or equal to476* to the minimum revision specified in the header.477*/478if (cur_rev < mc_header->min_req_ver) {479pr_info("Unsafe microcode update: Current revision 0x%x too old\n", cur_rev);480pr_info("Current should be at 0x%x or higher. Use early loading instead\n", mc_header->min_req_ver);481return false;482}483return true;484}485486static enum ucode_state parse_microcode_blobs(int cpu, struct iov_iter *iter)487{488struct ucode_cpu_info *uci = ucode_cpu_info + cpu;489bool is_safe, new_is_safe = false;490int cur_rev = uci->cpu_sig.rev;491unsigned int curr_mc_size = 0;492u8 *new_mc = NULL, *mc = NULL;493494while (iov_iter_count(iter)) {495struct microcode_header_intel mc_header;496unsigned int mc_size, data_size;497u8 *data;498499if (!copy_from_iter_full(&mc_header, sizeof(mc_header), iter)) {500pr_err("error! Truncated or inaccessible header in microcode data file\n");501goto fail;502}503504mc_size = get_totalsize(&mc_header);505if (mc_size < sizeof(mc_header)) {506pr_err("error! Bad data in microcode data file (totalsize too small)\n");507goto fail;508}509data_size = mc_size - sizeof(mc_header);510if (data_size > iov_iter_count(iter)) {511pr_err("error! Bad data in microcode data file (truncated file?)\n");512goto fail;513}514515/* For performance reasons, reuse mc area when possible */516if (!mc || mc_size > curr_mc_size) {517kvfree(mc);518mc = kvmalloc(mc_size, GFP_KERNEL);519if (!mc)520goto fail;521curr_mc_size = mc_size;522}523524memcpy(mc, &mc_header, sizeof(mc_header));525data = mc + sizeof(mc_header);526if (!copy_from_iter_full(data, data_size, iter) ||527intel_microcode_sanity_check(mc, true, MC_HEADER_TYPE_MICROCODE) < 0)528goto fail;529530if (cur_rev >= mc_header.rev)531continue;532533if (!intel_find_matching_signature(mc, &uci->cpu_sig))534continue;535536is_safe = ucode_validate_minrev(&mc_header);537if (force_minrev && !is_safe)538continue;539540kvfree(new_mc);541cur_rev = mc_header.rev;542new_mc = mc;543new_is_safe = is_safe;544mc = NULL;545}546547if (iov_iter_count(iter))548goto fail;549550kvfree(mc);551if (!new_mc)552return UCODE_NFOUND;553554ucode_patch_late = (struct microcode_intel *)new_mc;555return new_is_safe ? UCODE_NEW_SAFE : UCODE_NEW;556557fail:558kvfree(mc);559kvfree(new_mc);560return UCODE_ERROR;561}562563static bool is_blacklisted(unsigned int cpu)564{565struct cpuinfo_x86 *c = &cpu_data(cpu);566567/*568* Late loading on model 79 with microcode revision less than 0x0b000021569* and LLC size per core bigger than 2.5MB may result in a system hang.570* This behavior is documented in item BDX90, #334165 (Intel Xeon571* Processor E7-8800/4800 v4 Product Family).572*/573if (c->x86_vfm == INTEL_BROADWELL_X &&574c->x86_stepping == 0x01 &&575llc_size_per_core > 2621440 &&576c->microcode < 0x0b000021) {577pr_err_once("Erratum BDX90: late loading with revision < 0x0b000021 (0x%x) disabled.\n", c->microcode);578pr_err_once("Please consider either early loading through initrd/built-in or a potential BIOS update.\n");579return true;580}581582return false;583}584585static enum ucode_state request_microcode_fw(int cpu, struct device *device)586{587struct cpuinfo_x86 *c = &cpu_data(cpu);588const struct firmware *firmware;589struct iov_iter iter;590enum ucode_state ret;591struct kvec kvec;592char name[30];593594if (is_blacklisted(cpu))595return UCODE_NFOUND;596597sprintf(name, "intel-ucode/%02x-%02x-%02x",598c->x86, c->x86_model, c->x86_stepping);599600if (request_firmware_direct(&firmware, name, device)) {601pr_debug("data file %s load failed\n", name);602return UCODE_NFOUND;603}604605kvec.iov_base = (void *)firmware->data;606kvec.iov_len = firmware->size;607iov_iter_kvec(&iter, ITER_SOURCE, &kvec, 1, firmware->size);608ret = parse_microcode_blobs(cpu, &iter);609610release_firmware(firmware);611612return ret;613}614615static void finalize_late_load(int result)616{617if (!result)618update_ucode_pointer(ucode_patch_late);619else620kvfree(ucode_patch_late);621ucode_patch_late = NULL;622}623624static struct microcode_ops microcode_intel_ops = {625.request_microcode_fw = request_microcode_fw,626.collect_cpu_info = collect_cpu_info,627.apply_microcode = apply_microcode_late,628.finalize_late_load = finalize_late_load,629.use_nmi = IS_ENABLED(CONFIG_X86_64),630};631632static __init void calc_llc_size_per_core(struct cpuinfo_x86 *c)633{634u64 llc_size = c->x86_cache_size * 1024ULL;635636do_div(llc_size, topology_num_cores_per_package());637llc_size_per_core = (unsigned int)llc_size;638}639640struct microcode_ops * __init init_intel_microcode(void)641{642struct cpuinfo_x86 *c = &boot_cpu_data;643644if (c->x86_vendor != X86_VENDOR_INTEL || c->x86 < 6 ||645cpu_has(c, X86_FEATURE_IA64)) {646pr_err("Intel CPU family 0x%x not supported\n", c->x86);647return NULL;648}649650calc_llc_size_per_core(c);651652return µcode_intel_ops;653}654655656