Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings
forked fromtorvalds/linux

Commitbb8c13d

Browse files
suryasaimadhuKAGA-KOKO
authored andcommitted
x86/microcode: Fix CPU synchronization routine
Emanuel reported an issue with a hang during microcode update because mydumb idea to use one atomic synchronization variable for both rendezvous- before and after update - was simply bollocks: microcode: microcode_reload_late: late_cpus: 4 microcode: __reload_late: cpu 2 entered microcode: __reload_late: cpu 1 entered microcode: __reload_late: cpu 3 entered microcode: __reload_late: cpu 0 entered microcode: __reload_late: cpu 1 left microcode: Timeout while waiting for CPUs rendezvous, remaining: 1CPU1 above would finish, leave and the others will still spin waiting forit to join.So do two synchronization atomics instead, which makes the code a lot morestraightforward.Also, since the update is serialized and it also takes quite some time permicrocode engine, increase the exit timeout by the number of CPUs on thesystem.That's ok because the moment all CPUs are done, that timeout will be cutshort.Furthermore, panic when some of the CPUs timeout when returning from amicrocode update: we can't allow a system with not all cores updated.Also, as an optimization, do not do the exit sync if microcode wasn'tupdated.Reported-by: Emanuel Czirai <xftroxgpx@protonmail.com>Signed-off-by: Borislav Petkov <bp@suse.de>Signed-off-by: Thomas Gleixner <tglx@linutronix.de>Tested-by: Emanuel Czirai <xftroxgpx@protonmail.com>Tested-by: Ashok Raj <ashok.raj@intel.com>Tested-by: Tom Lendacky <thomas.lendacky@amd.com>Link:https://lkml.kernel.org/r/20180314183615.17629-2-bp@alien8.de
1 parent2613f36 commitbb8c13d

File tree

1 file changed

+41
-27
lines changed
  • arch/x86/kernel/cpu/microcode

1 file changed

+41
-27
lines changed

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

Lines changed: 41 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -517,7 +517,29 @@ static int check_online_cpus(void)
517517
return-EINVAL;
518518
}
519519

520-
staticatomic_tlate_cpus;
520+
staticatomic_tlate_cpus_in;
521+
staticatomic_tlate_cpus_out;
522+
523+
staticint__wait_for_cpus(atomic_t*t,long longtimeout)
524+
{
525+
intall_cpus=num_online_cpus();
526+
527+
atomic_inc(t);
528+
529+
while (atomic_read(t)<all_cpus) {
530+
if (timeout<SPINUNIT) {
531+
pr_err("Timeout while waiting for CPUs rendezvous, remaining: %d\n",
532+
all_cpus-atomic_read(t));
533+
return1;
534+
}
535+
536+
ndelay(SPINUNIT);
537+
timeout-=SPINUNIT;
538+
539+
touch_nmi_watchdog();
540+
}
541+
return0;
542+
}
521543

522544
/*
523545
* Returns:
@@ -527,46 +549,39 @@ static atomic_t late_cpus;
527549
*/
528550
staticint__reload_late(void*info)
529551
{
530-
unsignedinttimeout=NSEC_PER_SEC;
531-
intall_cpus=num_online_cpus();
532552
intcpu=smp_processor_id();
533553
enumucode_stateerr;
534554
intret=0;
535555

536-
atomic_dec(&late_cpus);
537-
538556
/*
539557
* Wait for all CPUs to arrive. A load will not be attempted unless all
540558
* CPUs show up.
541559
* */
542-
while (atomic_read(&late_cpus)) {
543-
if (timeout<SPINUNIT) {
544-
pr_err("Timeout while waiting for CPUs rendezvous, remaining: %d\n",
545-
atomic_read(&late_cpus));
546-
return-1;
547-
}
548-
549-
ndelay(SPINUNIT);
550-
timeout-=SPINUNIT;
551-
552-
touch_nmi_watchdog();
553-
}
560+
if (__wait_for_cpus(&late_cpus_in,NSEC_PER_SEC))
561+
return-1;
554562

555563
spin_lock(&update_lock);
556564
apply_microcode_local(&err);
557565
spin_unlock(&update_lock);
558566

559567
if (err>UCODE_NFOUND) {
560568
pr_warn("Error reloading microcode on CPU %d\n",cpu);
561-
ret=-1;
562-
}elseif (err==UCODE_UPDATED) {
569+
return-1;
570+
/* siblings return UCODE_OK because their engine got updated already */
571+
}elseif (err==UCODE_UPDATED||err==UCODE_OK) {
563572
ret=1;
573+
}else {
574+
returnret;
564575
}
565576

566-
atomic_inc(&late_cpus);
567-
568-
while (atomic_read(&late_cpus)!=all_cpus)
569-
cpu_relax();
577+
/*
578+
* Increase the wait timeout to a safe value here since we're
579+
* serializing the microcode update and that could take a while on a
580+
* large number of CPUs. And that is fine as the *actual* timeout will
581+
* be determined by the last CPU finished updating and thus cut short.
582+
*/
583+
if (__wait_for_cpus(&late_cpus_out,NSEC_PER_SEC*num_online_cpus()))
584+
panic("Timeout during microcode update!\n");
570585

571586
returnret;
572587
}
@@ -579,12 +594,11 @@ static int microcode_reload_late(void)
579594
{
580595
intret;
581596

582-
atomic_set(&late_cpus,num_online_cpus());
597+
atomic_set(&late_cpus_in,0);
598+
atomic_set(&late_cpus_out,0);
583599

584600
ret=stop_machine_cpuslocked(__reload_late,NULL,cpu_online_mask);
585-
if (ret<0)
586-
returnret;
587-
elseif (ret>0)
601+
if (ret>0)
588602
microcode_check();
589603

590604
returnret;

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp