856 lines · 21.5 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/platform_device.h>#include <linux/stop_machine.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/perf_event.h>#include <asm/processor.h>#include <asm/cmdline.h>#include <asm/setup.h> #include "internal.h" static struct microcode_ops	*microcode_ops;bool dis_ucode_ldr = true; bool force_minrev = IS_ENABLED(CONFIG_MICROCODE_LATE_FORCE_MINREV);module_param(force_minrev, bool, S_IRUSR | S_IWUSR); /* * 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; 	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;} static bool __init check_loader_disabled_bsp(void){	static const char *__dis_opt_str = "dis_ucode_ldr";	const char *cmdline = boot_command_line;	const char *option  = __dis_opt_str; 	/*	 * CPUID(1).ECX[31]: 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.	 */	if (native_cpuid_ecx(1) & BIT(31))		return true; 	if (x86_cpuid_vendor() == X86_VENDOR_AMD) {		if (amd_check_current_patch_level())			return true;	} 	if (cmdline_find_option_bool(cmdline, option) <= 0)		dis_ucode_ldr = false; 	return dis_ucode_ldr;} void __init load_ucode_bsp(void){	unsigned int cpuid_1_eax;	bool intel = true; 	if (!have_cpuid_p())		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 (check_loader_disabled_bsp())		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; 	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 platform_device	*microcode_pdev; #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;} static void load_primary(unsigned int cpu){	unsigned int nr_offl = cpumask_weight(&cpu_offline_mask);	bool proceed = true; 	/* Kick soft-offlined SMT siblings if required */	if (!cpu && nr_offl)		proceed = kick_offline_cpus(nr_offl); 	/* If the soft-offlined CPUs did not respond, abort */	if (proceed)		__load_primary(cpu); 	/* Unconditionally release soft-offlined SMT siblings if required */	if (!cpu && nr_offl)		release_offline_cpus();} /* * Minimal stub rendezvous handler for soft-offlined CPUs which participate * in the NMI rendezvous to protect against a concurrent NMI on affected * CPUs. */void noinstr microcode_offline_nmi_handler(void){	if (!raw_cpu_read(ucode_ctrl.nmi_enabled))		return;	raw_cpu_write(ucode_ctrl.nmi_enabled, false);	raw_cpu_write(ucode_ctrl.result, UCODE_OFFLINE);	raw_atomic_inc(&offline_in_nmi);	wait_for_ctrl();} static noinstr bool microcode_update_handler(void){	unsigned int cpu = raw_smp_processor_id(); 	if (raw_cpu_read(ucode_ctrl.ctrl_cpu) == cpu) {		instrumentation_begin();		load_primary(cpu);		instrumentation_end();	} else {		load_secondary(cpu);	} 	instrumentation_begin();	touch_nmi_watchdog();	instrumentation_end(); 	return true;} /* * Protection against instrumentation is required for CPUs which are not * safe against an NMI which is delivered to the secondary SMT sibling

Lines 1–500 of 856.