From: Ashok Raj <ashok.raj@intel.com>
To: gregkh@linuxfoundation.org, tglx@linutronix.de
Cc: Borislav Petkov <bp@suse.de>,
linux-kernel@vger.kernel.org, stable@vger.kernel.org,
thomas.lendacky@amd.com, arjan.van.de.ven@intel.com,
asit.k.mallick@intel.com
Subject: [4.15 & 4.14 stable 12/12] x86/microcode: Fix CPU synchronization routine
Date: Fri, 6 Apr 2018 11:30:26 -0700 [thread overview]
Message-ID: <1523039426-3938-13-git-send-email-ashok.raj@intel.com> (raw)
In-Reply-To: <1523039426-3938-1-git-send-email-ashok.raj@intel.com>
From: Borislav Petkov <bp@suse.de>
commit bb8c13d61a629276a162c1d2b1a20a815cbcfbb7 upstream
Emanuel reported an issue with a hang during microcode update because my
dumb 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: 1
CPU1 above would finish, leave and the others will still spin waiting for
it to join.
So do two synchronization atomics instead, which makes the code a lot more
straightforward.
Also, since the update is serialized and it also takes quite some time per
microcode engine, increase the exit timeout by the number of CPUs on the
system.
That's ok because the moment all CPUs are done, that timeout will be cut
short.
Furthermore, panic when some of the CPUs timeout when returning from a
microcode 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't
updated.
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>
Cc: Asit K Mallick <asit.k.mallick@intel.com>
Cc: stable@vger.kernel.org
Link: https://lkml.kernel.org/r/20180314183615.17629-2-bp@alien8.de
---
arch/x86/kernel/cpu/microcode/core.c | 68 ++++++++++++++++++++++--------------
1 file changed, 41 insertions(+), 27 deletions(-)
diff --git a/arch/x86/kernel/cpu/microcode/core.c b/arch/x86/kernel/cpu/microcode/core.c
index e6d5caa..021c904 100644
--- a/arch/x86/kernel/cpu/microcode/core.c
+++ b/arch/x86/kernel/cpu/microcode/core.c
@@ -517,7 +517,29 @@ static int check_online_cpus(void)
return -EINVAL;
}
-static atomic_t late_cpus;
+static atomic_t late_cpus_in;
+static atomic_t late_cpus_out;
+
+static int __wait_for_cpus(atomic_t *t, long long timeout)
+{
+ int all_cpus = num_online_cpus();
+
+ atomic_inc(t);
+
+ while (atomic_read(t) < all_cpus) {
+ if (timeout < SPINUNIT) {
+ pr_err("Timeout while waiting for CPUs rendezvous, remaining: %d\n",
+ all_cpus - atomic_read(t));
+ return 1;
+ }
+
+ ndelay(SPINUNIT);
+ timeout -= SPINUNIT;
+
+ touch_nmi_watchdog();
+ }
+ return 0;
+}
/*
* Returns:
@@ -527,30 +549,16 @@ static atomic_t late_cpus;
*/
static int __reload_late(void *info)
{
- unsigned int timeout = NSEC_PER_SEC;
- int all_cpus = num_online_cpus();
int cpu = smp_processor_id();
enum ucode_state err;
int ret = 0;
- atomic_dec(&late_cpus);
-
/*
* Wait for all CPUs to arrive. A load will not be attempted unless all
* CPUs show up.
* */
- while (atomic_read(&late_cpus)) {
- if (timeout < SPINUNIT) {
- pr_err("Timeout while waiting for CPUs rendezvous, remaining: %d\n",
- atomic_read(&late_cpus));
- return -1;
- }
-
- ndelay(SPINUNIT);
- timeout -= SPINUNIT;
-
- touch_nmi_watchdog();
- }
+ if (__wait_for_cpus(&late_cpus_in, NSEC_PER_SEC))
+ return -1;
spin_lock(&update_lock);
apply_microcode_local(&err);
@@ -558,15 +566,22 @@ static int __reload_late(void *info)
if (err > UCODE_NFOUND) {
pr_warn("Error reloading microcode on CPU %d\n", cpu);
- ret = -1;
- } else if (err == UCODE_UPDATED) {
+ return -1;
+ /* siblings return UCODE_OK because their engine got updated already */
+ } else if (err == UCODE_UPDATED || err == UCODE_OK) {
ret = 1;
+ } else {
+ return ret;
}
- atomic_inc(&late_cpus);
-
- while (atomic_read(&late_cpus) != all_cpus)
- cpu_relax();
+ /*
+ * 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.
+ */
+ if (__wait_for_cpus(&late_cpus_out, NSEC_PER_SEC * num_online_cpus()))
+ panic("Timeout during microcode update!\n");
return ret;
}
@@ -579,12 +594,11 @@ static int microcode_reload_late(void)
{
int ret;
- atomic_set(&late_cpus, num_online_cpus());
+ atomic_set(&late_cpus_in, 0);
+ atomic_set(&late_cpus_out, 0);
ret = stop_machine_cpuslocked(__reload_late, NULL, cpu_online_mask);
- if (ret < 0)
- return ret;
- else if (ret > 0)
+ if (ret > 0)
microcode_check();
return ret;
--
2.7.4
next prev parent reply other threads:[~2018-04-06 18:32 UTC|newest]
Thread overview: 14+ messages / expand[flat|nested] mbox.gz Atom feed top
2018-04-06 18:30 [4.15 & 4.14 stable 00/12] Series to update microcode loading Ashok Raj
2018-04-06 18:30 ` [4.15 & 4.14 stable 01/12] x86/microcode: Propagate return value from updating functions Ashok Raj
2018-04-06 18:30 ` [4.15 & 4.14 stable 02/12] x86/CPU: Add a microcode loader callback Ashok Raj
2018-04-06 18:30 ` [4.15 & 4.14 stable 03/12] x86/CPU: Check CPU feature bits after microcode upgrade Ashok Raj
2018-04-06 18:30 ` [4.15 & 4.14 stable 04/12] x86/microcode: Get rid of struct apply_microcode_ctx Ashok Raj
2018-04-06 18:30 ` [4.15 & 4.14 stable 05/12] x86/microcode/intel: Check microcode revision before updating sibling threads Ashok Raj
2018-04-06 18:30 ` [4.15 & 4.14 stable 06/12] x86/microcode/intel: Writeback and invalidate caches before updating microcode Ashok Raj
2018-04-06 18:30 ` [4.15 & 4.14 stable 07/12] x86/microcode: Do not upload microcode if CPUs are offline Ashok Raj
2018-04-06 18:30 ` [4.15 & 4.14 stable 08/12] x86/microcode/intel: Look into the patch cache first Ashok Raj
2018-04-06 18:30 ` [4.15 & 4.14 stable 09/12] x86/microcode: Request microcode on the BSP Ashok Raj
2018-04-06 18:30 ` [4.15 & 4.14 stable 10/12] x86/microcode: Synchronize late microcode loading Ashok Raj
2018-04-06 18:30 ` [4.15 & 4.14 stable 11/12] x86/microcode: Attempt late loading only when new microcode is present Ashok Raj
2018-04-06 18:30 ` Ashok Raj [this message]
2018-04-10 15:47 ` [4.15 & 4.14 stable 00/12] Series to update microcode loading Greg KH
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1523039426-3938-13-git-send-email-ashok.raj@intel.com \
--to=ashok.raj@intel.com \
--cc=arjan.van.de.ven@intel.com \
--cc=asit.k.mallick@intel.com \
--cc=bp@suse.de \
--cc=gregkh@linuxfoundation.org \
--cc=linux-kernel@vger.kernel.org \
--cc=stable@vger.kernel.org \
--cc=tglx@linutronix.de \
--cc=thomas.lendacky@amd.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®