Skip to content

Commit 01c74b4

Browse files
ashok-rajSomasundaram Krishnasamy
authored andcommitted
x86/microcode: Update late microcode in parallel
Microcode update was changed to be serialized due to restrictions after Spectre days. Updating serially on a large multi-socket system can be painful since it is being done on one CPU at a time. Cloud customers have expressed discontent as services disappear for a prolonged time. Currently, only one core (or only one thread of a core in the case of an SMT system) goes through the update while other cores (or respectively, SMT threads) are quiesced. Do the microcode update only on the first thread of each core while other siblings simply wait for this to complete. [ bp: Simplify, massage, cleanup comments. ] Signed-off-by: Ashok Raj <[email protected]> Signed-off-by: Mihai Carabas <[email protected]> Signed-off-by: Borislav Petkov <[email protected]> Cc: Boris Ostrovsky <[email protected]> Cc: "H. Peter Anvin" <[email protected]> Cc: Ingo Molnar <[email protected]> Cc: Jon Grimm <[email protected]> Cc: [email protected] Cc: [email protected] Cc: [email protected] Cc: Thomas Gleixner <[email protected]> Cc: Tom Lendacky <[email protected]> Cc: x86-ml <[email protected]> Link: https://urldefense.proofpoint.com/v2/url?u=https-3A__lkml.kernel.org_r_1566506627-2D16536-2D2-2Dgit-2Dsend-2Demail-2Dmihai.carabas-40oracle.com&d=DwIBaQ&c=RoP1YumCXCgaWHvlZYR8PZh8Bv7qIrMUB65eapI_JnE&r=IOMTUEJr06tE0LeEzvwr_907ba6u9S5iDf7M8ZYjbGY&m=HQnUvxzYcAft4TQU6i2cgOnDcqXRq5HNmQfXDCW0mCc&s=keMggB0XGOzj8kyM47xUQK9t3GboAzk3sKUx-FUXPBM&e= Orabug: 30297345 JIRA: LINUX-1612 Patch has not been committed to any tree yet so (1) there is no SHA1 to reference and (2) commit message will probably change. Signed-off-by: Mihai Carabas <[email protected]> Reviewed-by: Boris Ostrovsky <[email protected]> Signed-off-by: Somasundaram Krishnasamy <[email protected]>
1 parent 93e4dba commit 01c74b4

File tree

1 file changed

+21
-15
lines changed
  • arch/x86/kernel/cpu/microcode

1 file changed

+21
-15
lines changed

arch/x86/kernel/cpu/microcode/core.c

Lines changed: 21 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -70,11 +70,6 @@ LIST_HEAD(microcode_cache);
7070
*/
7171
static DEFINE_MUTEX(microcode_mutex);
7272

73-
/*
74-
* Serialize late loading so that CPUs get updated one-by-one.
75-
*/
76-
static DEFINE_RAW_SPINLOCK(update_lock);
77-
7873
struct ucode_cpu_info ucode_cpu_info[NR_CPUS];
7974

8075
struct cpu_info_ctx {
@@ -579,11 +574,18 @@ static int __reload_late(void *info)
579574
if (__wait_for_cpus(&late_cpus_in, NSEC_PER_SEC))
580575
return -1;
581576

582-
raw_spin_lock(&update_lock);
583-
apply_microcode_local(&err);
584-
raw_spin_unlock(&update_lock);
577+
/*
578+
* On an SMT system, it suffices to load the microcode on one sibling of
579+
* the core because the microcode engine is shared between the threads.
580+
* Synchronization still needs to take place so that no concurrent
581+
* loading attempts happen on multiple threads of an SMT core. See
582+
* below.
583+
*/
584+
if (cpumask_first(topology_sibling_cpumask(cpu)) == cpu)
585+
apply_microcode_local(&err);
586+
else
587+
goto wait_for_siblings;
585588

586-
/* siblings return UCODE_OK because their engine got updated already */
587589
if (err > UCODE_NFOUND) {
588590
pr_warn("Error reloading microcode on CPU %d\n", cpu);
589591
ret = -1;
@@ -597,14 +599,18 @@ static int __reload_late(void *info)
597599
memcpy(&boot_cpu_data, c, sizeof(boot_cpu_data));
598600
}
599601

602+
wait_for_siblings:
603+
if (__wait_for_cpus(&late_cpus_out, NSEC_PER_SEC))
604+
panic("Timeout during microcode update!\n");
605+
600606
/*
601-
* Increase the wait timeout to a safe value here since we're
602-
* serializing the microcode update and that could take a while on a
603-
* large number of CPUs. And that is fine as the *actual* timeout will
604-
* be determined by the last CPU finished updating and thus cut short.
607+
* At least one thread has completed update on each core.
608+
* For others, simply call the update to make sure the
609+
* per-cpu cpuinfo can be updated with right microcode
610+
* revision.
605611
*/
606-
if (__wait_for_cpus(&late_cpus_out, NSEC_PER_SEC * num_online_cpus()))
607-
panic("Timeout during microcode update!\n");
612+
if (cpumask_first(topology_sibling_cpumask(cpu)) != cpu)
613+
apply_microcode_local(&err);
608614

609615
return ret;
610616
}

0 commit comments

Comments
 (0)