diff options
Diffstat (limited to 'arch/x86/kernel/cpu/microcode')
| -rw-r--r-- | arch/x86/kernel/cpu/microcode/amd.c | 4 | ||||
| -rw-r--r-- | arch/x86/kernel/cpu/microcode/core.c | 36 | ||||
| -rw-r--r-- | arch/x86/kernel/cpu/microcode/intel.c | 5 | 
3 files changed, 26 insertions, 19 deletions
diff --git a/arch/x86/kernel/cpu/microcode/amd.c b/arch/x86/kernel/cpu/microcode/amd.c index a0e52bd00ecc..3f6b137ef4e6 100644 --- a/arch/x86/kernel/cpu/microcode/amd.c +++ b/arch/x86/kernel/cpu/microcode/amd.c @@ -567,7 +567,7 @@ int __init save_microcode_in_initrd_amd(unsigned int cpuid_1_eax)  void reload_ucode_amd(void)  {  	struct microcode_amd *mc; -	u32 rev, dummy; +	u32 rev, dummy __always_unused;  	mc = (struct microcode_amd *)amd_ucode_patch; @@ -673,7 +673,7 @@ static enum ucode_state apply_microcode_amd(int cpu)  	struct ucode_cpu_info *uci;  	struct ucode_patch *p;  	enum ucode_state ret; -	u32 rev, dummy; +	u32 rev, dummy __always_unused;  	BUG_ON(raw_smp_processor_id() != cpu); diff --git a/arch/x86/kernel/cpu/microcode/core.c b/arch/x86/kernel/cpu/microcode/core.c index cb0fdcaf1415..7019d4b2df0c 100644 --- a/arch/x86/kernel/cpu/microcode/core.c +++ b/arch/x86/kernel/cpu/microcode/core.c @@ -63,11 +63,6 @@ LIST_HEAD(microcode_cache);   */  static DEFINE_MUTEX(microcode_mutex); -/* - * Serialize late loading so that CPUs get updated one-by-one. - */ -static DEFINE_RAW_SPINLOCK(update_lock); -  struct ucode_cpu_info		ucode_cpu_info[NR_CPUS];  struct cpu_info_ctx { @@ -566,11 +561,18 @@ static int __reload_late(void *info)  	if (__wait_for_cpus(&late_cpus_in, NSEC_PER_SEC))  		return -1; -	raw_spin_lock(&update_lock); -	apply_microcode_local(&err); -	raw_spin_unlock(&update_lock); +	/* +	 * On an SMT system, it suffices to load the microcode on one sibling of +	 * the core because the microcode engine is shared between the threads. +	 * Synchronization still needs to take place so that no concurrent +	 * loading attempts happen on multiple threads of an SMT core. See +	 * below. +	 */ +	if (cpumask_first(topology_sibling_cpumask(cpu)) == cpu) +		apply_microcode_local(&err); +	else +		goto wait_for_siblings; -	/* siblings return UCODE_OK because their engine got updated already */  	if (err > UCODE_NFOUND) {  		pr_warn("Error reloading microcode on CPU %d\n", cpu);  		ret = -1; @@ -578,14 +580,18 @@ static int __reload_late(void *info)  		ret = 1;  	} +wait_for_siblings: +	if (__wait_for_cpus(&late_cpus_out, NSEC_PER_SEC)) +		panic("Timeout during microcode update!\n"); +  	/* -	 * Increase the wait timeout to a safe value here since we're -	 * serializing the microcode update and that could take a while on a -	 * large number of CPUs. And that is fine as the *actual* timeout will -	 * be determined by the last CPU finished updating and thus cut short. +	 * At least one thread has completed update on each core. +	 * For others, simply call the update to make sure the +	 * per-cpu cpuinfo can be updated with right microcode +	 * revision.  	 */ -	if (__wait_for_cpus(&late_cpus_out, NSEC_PER_SEC * num_online_cpus())) -		panic("Timeout during microcode update!\n"); +	if (cpumask_first(topology_sibling_cpumask(cpu)) != cpu) +		apply_microcode_local(&err);  	return ret;  } diff --git a/arch/x86/kernel/cpu/microcode/intel.c b/arch/x86/kernel/cpu/microcode/intel.c index ce799cfe9434..6a99535d7f37 100644 --- a/arch/x86/kernel/cpu/microcode/intel.c +++ b/arch/x86/kernel/cpu/microcode/intel.c @@ -791,6 +791,7 @@ static enum ucode_state apply_microcode_intel(int cpu)  {  	struct ucode_cpu_info *uci = ucode_cpu_info + cpu;  	struct cpuinfo_x86 *c = &cpu_data(cpu); +	bool bsp = c->cpu_index == boot_cpu_data.cpu_index;  	struct microcode_intel *mc;  	enum ucode_state ret;  	static int prev_rev; @@ -836,7 +837,7 @@ static enum ucode_state apply_microcode_intel(int cpu)  		return UCODE_ERROR;  	} -	if (rev != prev_rev) { +	if (bsp && rev != prev_rev) {  		pr_info("updated to revision 0x%x, date = %04x-%02x-%02x\n",  			rev,  			mc->hdr.date & 0xffff, @@ -852,7 +853,7 @@ out:  	c->microcode	 = rev;  	/* Update boot_cpu_data's revision too, if we're on the BSP: */ -	if (c->cpu_index == boot_cpu_data.cpu_index) +	if (bsp)  		boot_cpu_data.microcode = rev;  	return ret;  |