933 lines · 23.4 KB · C
RawDownload
// SPDX-License-Identifier: GPL-2.0-or-later/* * CPU Microcode Update Driver for Linux * * Copyright (C) 2000-2006 Tigran Aivazian <aivazian.tigran@gmail.com> *	      2006	Shaohua Li <shaohua.li@intel.com> *	      2013-2016	Borislav Petkov <bp@alien8.de> * * X86 CPU microcode early update for Linux: * *	Copyright (C) 2012 Fenghua Yu <fenghua.yu@intel.com> *			   H Peter Anvin" <hpa@zytor.com> *		  (C) 2015 Borislav Petkov <bp@alien8.de> * * This driver allows to upgrade microcode on x86 processors. */ #define pr_fmt(fmt) "microcode: " fmt #include <linux/stop_machine.h>#include <linux/device/faux.h>#include <linux/syscore_ops.h>#include <linux/miscdevice.h>#include <linux/capability.h>#include <linux/firmware.h>#include <linux/cpumask.h>#include <linux/kernel.h>#include <linux/delay.h>#include <linux/mutex.h>#include <linux/cpu.h>#include <linux/nmi.h>#include <linux/fs.h>#include <linux/mm.h> #include <asm/apic.h>#include <asm/cpu_device_id.h>#include <asm/cpuid/api.h>#include <asm/perf_event.h>#include <asm/processor.h>#include <asm/cmdline.h>#include <asm/msr.h>#include <asm/setup.h> #include "internal.h" static struct microcode_ops *microcode_ops;static bool dis_ucode_ldr; bool force_minrev = IS_ENABLED(CONFIG_MICROCODE_LATE_FORCE_MINREV); /* * Those below should be behind CONFIG_MICROCODE_DBG ifdeffery but in * order to not uglify the code with ifdeffery and use IS_ENABLED() * instead, leave them in. When microcode debugging is not enabled, * those are meaningless anyway. *//* base microcode revision for debugging */u32 base_rev;u32 microcode_rev[NR_CPUS] = {}; bool __ro_after_init x86_hypervisor_present; /* * Synchronization. * * All non cpu-hotplug-callback call sites use: * * - cpus_read_lock/unlock() to synchronize with *   the cpu-hotplug-callback call sites. * * We guarantee that only a single cpu is being * updated at any particular moment of time. */struct ucode_cpu_info		ucode_cpu_info[NR_CPUS]; /* * Those patch levels cannot be updated to newer ones and thus should be final. */static u32 final_levels[] = {	0x01000098,	0x0100009f,	0x010000af,	0, /* T-101 terminator */}; struct early_load_data early_data; /* * Check the current patch level on this CPU. * * Returns: *  - true: if update should stop *  - false: otherwise */static bool amd_check_current_patch_level(void){	u32 lvl, dummy, i;	u32 *levels; 	if (x86_cpuid_vendor() != X86_VENDOR_AMD)		return false; 	native_rdmsr(MSR_AMD64_PATCH_LEVEL, lvl, dummy); 	levels = final_levels; 	for (i = 0; levels[i]; i++) {		if (lvl == levels[i])			return true;	}	return false;} bool __init microcode_loader_disabled(void){	if (dis_ucode_ldr)		return true; 	/*	 * Disable when:	 *	 * 1) The CPU does not support CPUID, detected below in	 *    load_ucode_bsp().	 *	 * 2) Bit 31 in CPUID[1]:ECX is set	 *    The bit is reserved for hypervisor use. This is still not	 *    completely accurate as XEN PV guests don't see that CPUID bit	 *    set, but that's good enough as they don't land on the BSP	 *    path anyway.	 *	 * 3) Certain AMD patch levels are not allowed to be	 *    overwritten.	 */	if ((x86_hypervisor_present && !IS_ENABLED(CONFIG_MICROCODE_DBG)) ||	    amd_check_current_patch_level())		dis_ucode_ldr = true; 	return dis_ucode_ldr;} static void __init early_parse_cmdline(void){	char cmd_buf[64] = {};	char *s, *p = cmd_buf; 	if (cmdline_find_option(boot_command_line, "microcode", cmd_buf, sizeof(cmd_buf)) > 0) {		while ((s = strsep(&p, ","))) {			if (IS_ENABLED(CONFIG_MICROCODE_DBG)) {				if (strstr(s, "base_rev=")) {					/* advance to the option arg */					strsep(&s, "=");					if (kstrtouint(s, 16, &base_rev)) { ; }				}			} 			if (!strcmp("force_minrev", s))				force_minrev = true; 			if (!strcmp(s, "dis_ucode_ldr"))				dis_ucode_ldr = true;		}	} 	/* old, compat option */	if (cmdline_find_option_bool(boot_command_line, "dis_ucode_ldr") > 0)		dis_ucode_ldr = true;} void __init load_ucode_bsp(void){	unsigned int cpuid_1_eax;	bool intel = true; 	early_parse_cmdline(); 	if (!cpuid_feature())		dis_ucode_ldr = true;	else		x86_hypervisor_present = native_cpuid_ecx(1) & BIT(31); 	if (microcode_loader_disabled())		return; 	cpuid_1_eax = native_cpuid_eax(1); 	switch (x86_cpuid_vendor()) {	case X86_VENDOR_INTEL:		if (x86_family(cpuid_1_eax) < 6)			return;		break; 	case X86_VENDOR_AMD:		if (x86_family(cpuid_1_eax) < 0x10)			return;		intel = false;		break; 	default:		return;	} 	if (intel)		load_ucode_intel_bsp(&early_data);	else		load_ucode_amd_bsp(&early_data, cpuid_1_eax);} void load_ucode_ap(void){	unsigned int cpuid_1_eax; 	/*	 * Can't use microcode_loader_disabled() here - .init section	 * hell. It doesn't have to either - the BSP variant must've	 * parsed cmdline already anyway.	 */	if (dis_ucode_ldr)		return; 	cpuid_1_eax = native_cpuid_eax(1); 	switch (x86_cpuid_vendor()) {	case X86_VENDOR_INTEL:		if (x86_family(cpuid_1_eax) >= 6)			load_ucode_intel_ap();		break;	case X86_VENDOR_AMD:		if (x86_family(cpuid_1_eax) >= 0x10)			load_ucode_amd_ap(cpuid_1_eax);		break;	default:		break;	}} struct cpio_data __init find_microcode_in_initrd(const char *path){#ifdef CONFIG_BLK_DEV_INITRD	unsigned long start = 0;	size_t size; #ifdef CONFIG_X86_32	size = boot_params.hdr.ramdisk_size;	/* Early load on BSP has a temporary mapping. */	if (size)		start = initrd_start_early; #else /* CONFIG_X86_64 */	size  = (unsigned long)boot_params.ext_ramdisk_size << 32;	size |= boot_params.hdr.ramdisk_size; 	if (size) {		start  = (unsigned long)boot_params.ext_ramdisk_image << 32;		start |= boot_params.hdr.ramdisk_image;		start += PAGE_OFFSET;	}#endif 	/*	 * Fixup the start address: after reserve_initrd() runs, initrd_start	 * has the virtual address of the beginning of the initrd. It also	 * possibly relocates the ramdisk. In either case, initrd_start contains	 * the updated address so use that instead.	 */	if (initrd_start)		start = initrd_start; 	return find_cpio_data(path, (void *)start, size, NULL);#else /* !CONFIG_BLK_DEV_INITRD */	return (struct cpio_data){ NULL, 0, "" };#endif} static void reload_early_microcode(unsigned int cpu){	int vendor, family; 	vendor = x86_cpuid_vendor();	family = x86_cpuid_family(); 	switch (vendor) {	case X86_VENDOR_INTEL:		if (family >= 6)			reload_ucode_intel();		break;	case X86_VENDOR_AMD:		if (family >= 0x10)			reload_ucode_amd(cpu);		break;	default:		break;	}} /* fake device for request_firmware */static struct faux_device *microcode_fdev; #ifdef CONFIG_MICROCODE_LATE_LOADING/* * Late loading dance. Why the heavy-handed stomp_machine effort? * * - HT siblings must be idle and not execute other code while the other sibling *   is loading microcode in order to avoid any negative interactions caused by *   the loading. * * - In addition, microcode update on the cores must be serialized until this *   requirement can be relaxed in the future. Right now, this is conservative *   and good. */enum sibling_ctrl {	/* Spinwait with timeout */	SCTRL_WAIT,	/* Invoke the microcode_apply() callback */	SCTRL_APPLY,	/* Proceed without invoking the microcode_apply() callback */	SCTRL_DONE,}; struct microcode_ctrl {	enum sibling_ctrl	ctrl;	enum ucode_state	result;	unsigned int		ctrl_cpu;	bool			nmi_enabled;}; DEFINE_STATIC_KEY_FALSE(microcode_nmi_handler_enable);static DEFINE_PER_CPU(struct microcode_ctrl, ucode_ctrl);static atomic_t late_cpus_in, offline_in_nmi;static unsigned int loops_per_usec;static cpumask_t cpu_offline_mask; static noinstr bool wait_for_cpus(atomic_t *cnt){	unsigned int timeout, loops; 	WARN_ON_ONCE(raw_atomic_dec_return(cnt) < 0); 	for (timeout = 0; timeout < USEC_PER_SEC; timeout++) {		if (!raw_atomic_read(cnt))			return true; 		for (loops = 0; loops < loops_per_usec; loops++)			cpu_relax(); 		/* If invoked directly, tickle the NMI watchdog */		if (!microcode_ops->use_nmi && !(timeout % USEC_PER_MSEC)) {			instrumentation_begin();			touch_nmi_watchdog();			instrumentation_end();		}	}	/* Prevent the late comers from making progress and let them time out */	raw_atomic_inc(cnt);	return false;} static noinstr bool wait_for_ctrl(void){	unsigned int timeout, loops; 	for (timeout = 0; timeout < USEC_PER_SEC; timeout++) {		if (raw_cpu_read(ucode_ctrl.ctrl) != SCTRL_WAIT)			return true; 		for (loops = 0; loops < loops_per_usec; loops++)			cpu_relax(); 		/* If invoked directly, tickle the NMI watchdog */		if (!microcode_ops->use_nmi && !(timeout % USEC_PER_MSEC)) {			instrumentation_begin();			touch_nmi_watchdog();			instrumentation_end();		}	}	return false;} /* * Protected against instrumentation up to the point where the primary * thread completed the update. See microcode_nmi_handler() for details. */static noinstr bool load_secondary_wait(unsigned int ctrl_cpu){	/* Initial rendezvous to ensure that all CPUs have arrived */	if (!wait_for_cpus(&late_cpus_in)) {		raw_cpu_write(ucode_ctrl.result, UCODE_TIMEOUT);		return false;	} 	/*	 * Wait for primary threads to complete. If one of them hangs due	 * to the update, there is no way out. This is non-recoverable	 * because the CPU might hold locks or resources and confuse the	 * scheduler, watchdogs etc. There is no way to safely evacuate the	 * machine.	 */	if (wait_for_ctrl())		return true; 	instrumentation_begin();	panic("Microcode load: Primary CPU %d timed out\n", ctrl_cpu);	instrumentation_end();} /* * Protected against instrumentation up to the point where the primary * thread completed the update. See microcode_nmi_handler() for details. */static noinstr void load_secondary(unsigned int cpu){	unsigned int ctrl_cpu = raw_cpu_read(ucode_ctrl.ctrl_cpu);	enum ucode_state ret; 	if (!load_secondary_wait(ctrl_cpu)) {		instrumentation_begin();		pr_err_once("load: %d CPUs timed out\n",			    atomic_read(&late_cpus_in) - 1);		instrumentation_end();		return;	} 	/* Primary thread completed. Allow to invoke instrumentable code */	instrumentation_begin();	/*	 * If the primary succeeded then invoke the apply() callback,	 * otherwise copy the state from the primary thread.	 */	if (this_cpu_read(ucode_ctrl.ctrl) == SCTRL_APPLY)		ret = microcode_ops->apply_microcode(cpu);	else		ret = per_cpu(ucode_ctrl.result, ctrl_cpu); 	this_cpu_write(ucode_ctrl.result, ret);	this_cpu_write(ucode_ctrl.ctrl, SCTRL_DONE);	instrumentation_end();} static void __load_primary(unsigned int cpu){	struct cpumask *secondaries = topology_sibling_cpumask(cpu);	enum sibling_ctrl ctrl;	enum ucode_state ret;	unsigned int sibling; 	/* Initial rendezvous to ensure that all CPUs have arrived */	if (!wait_for_cpus(&late_cpus_in)) {		this_cpu_write(ucode_ctrl.result, UCODE_TIMEOUT);		pr_err_once("load: %d CPUs timed out\n", atomic_read(&late_cpus_in) - 1);		return;	} 	ret = microcode_ops->apply_microcode(cpu);	this_cpu_write(ucode_ctrl.result, ret);	this_cpu_write(ucode_ctrl.ctrl, SCTRL_DONE); 	/*	 * If the update was successful, let the siblings run the apply()	 * callback. If not, tell them it's done. This also covers the	 * case where the CPU has uniform loading at package or system	 * scope implemented but does not advertise it.	 */	if (ret == UCODE_UPDATED || ret == UCODE_OK)		ctrl = SCTRL_APPLY;	else		ctrl = SCTRL_DONE; 	for_each_cpu(sibling, secondaries) {		if (sibling != cpu)			per_cpu(ucode_ctrl.ctrl, sibling) = ctrl;	}} static bool kick_offline_cpus(unsigned int nr_offl){	unsigned int cpu, timeout; 	for_each_cpu(cpu, &cpu_offline_mask) {		/* Enable the rendezvous handler and send NMI */		per_cpu(ucode_ctrl.nmi_enabled, cpu) = true;		apic_send_nmi_to_offline_cpu(cpu);	} 	/* Wait for them to arrive */	for (timeout = 0; timeout < (USEC_PER_SEC / 2); timeout++) {		if (atomic_read(&offline_in_nmi) == nr_offl)			return true;		udelay(1);	}	/* Let the others time out */	return false;} static void release_offline_cpus(void){	unsigned int cpu; 	for_each_cpu(cpu, &cpu_offline_mask)		per_cpu(ucode_ctrl.ctrl, cpu) = SCTRL_DONE;} 

Lines 1–500 of 933.