From: Thomas Gleixner <tglx@linutronix.de>
To: LKML <linux-kernel@vger.kernel.org>
Cc: x86@kernel.org, Borislav Petkov <bp@alien8.de>
Subject: [patch V5 30/39] x86/microcode: Add per CPU result state
Date: Tue, 17 Oct 2023 23:24:05 +0200 (CEST) [thread overview]
Message-ID: <20231017211723.632681010@linutronix.de> (raw)
In-Reply-To: 20231017200758.877560658@linutronix.de
From: Thomas Gleixner <tglx@linutronix.de>
The microcode rendezvous is purely acting on global state, which does
not allow to analyze fails in a coherent way.
Introduce per CPU state where the results are written into, which allows to
analyze the return codes of the individual CPUs.
Initialize the state when walking the cpu_present_mask in the online check
to avoid another for_each_cpu() loop.
Enhance the result print out with that.
The structure is intentionally named ucode_ctrl as it will gain control
fields in subsequent changes.
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
---
arch/x86/kernel/cpu/microcode/core.c | 112 ++++++++++++++++++-------------
arch/x86/kernel/cpu/microcode/internal.h | 1
2 files changed, 67 insertions(+), 46 deletions(-)
---
--- a/arch/x86/kernel/cpu/microcode/core.c
+++ b/arch/x86/kernel/cpu/microcode/core.c
@@ -252,6 +252,11 @@ static struct platform_device *microcode
* requirement can be relaxed in the future. Right now, this is conservative
* and good.
*/
+struct microcode_ctrl {
+ enum ucode_state result;
+};
+
+static DEFINE_PER_CPU(struct microcode_ctrl, ucode_ctrl);
static atomic_t late_cpus_in, late_cpus_out;
static bool wait_for_cpus(atomic_t *cnt)
@@ -274,23 +279,19 @@ static bool wait_for_cpus(atomic_t *cnt)
return false;
}
-/*
- * Returns:
- * < 0 - on error
- * 0 - success (no update done or microcode was updated)
- */
-static int __reload_late(void *info)
+static int load_cpus_stopped(void *unused)
{
int cpu = smp_processor_id();
- enum ucode_state err;
- int ret = 0;
+ enum ucode_state ret;
/*
* Wait for all CPUs to arrive. A load will not be attempted unless all
* CPUs show up.
* */
- if (!wait_for_cpus(&late_cpus_in))
- return -1;
+ if (!wait_for_cpus(&late_cpus_in)) {
+ this_cpu_write(ucode_ctrl.result, UCODE_TIMEOUT);
+ return 0;
+ }
/*
* On an SMT system, it suffices to load the microcode on one sibling of
@@ -299,17 +300,11 @@ static int __reload_late(void *info)
* loading attempts happen on multiple threads of an SMT core. See
* below.
*/
- if (cpumask_first(topology_sibling_cpumask(cpu)) == cpu)
- err = microcode_ops->apply_microcode(cpu);
- else
+ if (cpumask_first(topology_sibling_cpumask(cpu)) != cpu)
goto wait_for_siblings;
- if (err >= UCODE_NFOUND) {
- if (err == UCODE_ERROR) {
- pr_warn("Error reloading microcode on CPU %d\n", cpu);
- ret = -1;
- }
- }
+ ret = microcode_ops->apply_microcode(cpu);
+ this_cpu_write(ucode_ctrl.result, ret);
wait_for_siblings:
if (!wait_for_cpus(&late_cpus_out))
@@ -321,19 +316,18 @@ static int __reload_late(void *info)
* per-cpu cpuinfo can be updated with right microcode
* revision.
*/
- if (cpumask_first(topology_sibling_cpumask(cpu)) != cpu)
- err = microcode_ops->apply_microcode(cpu);
+ if (cpumask_first(topology_sibling_cpumask(cpu)) == cpu)
+ return 0;
- return ret;
+ ret = microcode_ops->apply_microcode(cpu);
+ this_cpu_write(ucode_ctrl.result, ret);
+ return 0;
}
-/*
- * Reload microcode late on all CPUs. Wait for a sec until they
- * all gather together.
- */
-static int microcode_reload_late(void)
+static int load_late_stop_cpus(void)
{
- int old = boot_cpu_data.microcode, ret;
+ unsigned int cpu, updated = 0, failed = 0, timedout = 0, siblings = 0;
+ int old_rev = boot_cpu_data.microcode;
struct cpuinfo_x86 prev_info;
pr_err("Attempting late microcode loading - it is dangerous and taints the kernel.\n");
@@ -348,26 +342,47 @@ static int microcode_reload_late(void)
*/
store_cpu_caps(&prev_info);
- ret = stop_machine_cpuslocked(__reload_late, NULL, cpu_online_mask);
+ stop_machine_cpuslocked(load_cpus_stopped, NULL, cpu_online_mask);
+
+ /* Analyze the results */
+ for_each_cpu_and(cpu, cpu_present_mask, &cpus_booted_once_mask) {
+ switch (per_cpu(ucode_ctrl.result, cpu)) {
+ case UCODE_UPDATED: updated++; break;
+ case UCODE_TIMEOUT: timedout++; break;
+ case UCODE_OK: siblings++; break;
+ default: failed++; break;
+ }
+ }
if (microcode_ops->finalize_late_load)
- microcode_ops->finalize_late_load(ret);
+ microcode_ops->finalize_late_load(!updated);
- if (!ret) {
- pr_info("Reload succeeded, microcode revision: 0x%x -> 0x%x\n",
- old, boot_cpu_data.microcode);
- microcode_check(&prev_info);
- add_taint(TAINT_CPU_OUT_OF_SPEC, LOCKDEP_STILL_OK);
- } else {
- pr_info("Reload failed, current microcode revision: 0x%x\n",
- boot_cpu_data.microcode);
+ if (!updated) {
+ /* Nothing changed. */
+ if (!failed && !timedout)
+ return 0;
+ pr_err("update failed: %u CPUs failed %u CPUs timed out\n",
+ failed, timedout);
+ return -EIO;
}
- return ret;
+
+ add_taint(TAINT_CPU_OUT_OF_SPEC, LOCKDEP_STILL_OK);
+ pr_info("load: updated on %u primary CPUs with %u siblings\n", updated, siblings);
+ if (failed || timedout) {
+ pr_err("load incomplete. %u CPUs timed out or failed\n",
+ num_online_cpus() - (updated + siblings));
+ }
+ pr_info("revision: 0x%x -> 0x%x\n", old_rev, boot_cpu_data.microcode);
+ microcode_check(&prev_info);
+
+ return updated + siblings == num_online_cpus() ? 0 : -EIO;
}
/*
- * Ensure that all required CPUs which are present and have been booted
- * once are online.
+ * This function does two things:
+ *
+ * 1) Ensure that all required CPUs which are present and have been booted
+ * once are online.
*
* To pass this check, all primary threads must be online.
*
@@ -378,9 +393,12 @@ static int microcode_reload_late(void)
* behaviour is undefined. The default play_dead() implementation on
* modern CPUs uses MWAIT, which is also not guaranteed to be safe
* against a microcode update which affects MWAIT.
+ *
+ * 2) Initialize the per CPU control structure
*/
-static bool ensure_cpus_are_online(void)
+static bool setup_cpus(void)
{
+ struct microcode_ctrl ctrl = { .result = -1, };
unsigned int cpu;
for_each_cpu_and(cpu, cpu_present_mask, &cpus_booted_once_mask) {
@@ -390,18 +408,20 @@ static bool ensure_cpus_are_online(void)
return false;
}
}
+ /* Initialize the per CPU state */
+ per_cpu(ucode_ctrl, cpu) = ctrl;
}
return true;
}
-static int ucode_load_late_locked(void)
+static int load_late_locked(void)
{
- if (!ensure_cpus_are_online())
+ if (!setup_cpus())
return -EBUSY;
switch (microcode_ops->request_microcode_fw(0, µcode_pdev->dev)) {
case UCODE_NEW:
- return microcode_reload_late();
+ return load_late_stop_cpus();
case UCODE_NFOUND:
return -ENOENT;
default:
@@ -421,7 +441,7 @@ static ssize_t reload_store(struct devic
return -EINVAL;
cpus_read_lock();
- ret = ucode_load_late_locked();
+ ret = load_late_locked();
cpus_read_unlock();
return ret ? : size;
--- a/arch/x86/kernel/cpu/microcode/internal.h
+++ b/arch/x86/kernel/cpu/microcode/internal.h
@@ -16,6 +16,7 @@ enum ucode_state {
UCODE_UPDATED,
UCODE_NFOUND,
UCODE_ERROR,
+ UCODE_TIMEOUT,
};
struct microcode_ops {
next prev parent reply other threads:[~2023-10-17 21:25 UTC|newest]
Thread overview: 70+ messages / expand[flat|nested] mbox.gz Atom feed top
2023-10-17 21:23 [patch V5 00/39] x86/microcode: Cleanup and late loading enhancements Thomas Gleixner
2023-10-17 21:23 ` [patch V5 01/39] x86/boot/32: Disable stackprotector and tracing for mk_early_pgtbl_32() Thomas Gleixner
2023-10-17 21:23 ` [patch V5 02/39] x86/boot: Use __pa_nodebug() in mk_early_pgtbl_32() Thomas Gleixner
2023-10-20 11:38 ` [tip: x86/microcode] " tip-bot2 for Thomas Gleixner
2023-10-17 21:23 ` [patch V5 03/39] x86/boot/32: De-uglify the 2/3 level paging difference " Thomas Gleixner
2023-10-18 10:00 ` Borislav Petkov
2023-10-18 13:20 ` Thomas Gleixner
2023-10-18 16:28 ` Borislav Petkov
2023-10-20 11:38 ` [tip: x86/microcode] " tip-bot2 for Thomas Gleixner
2023-10-17 21:23 ` [patch V5 04/39] x86/boot/32: Restructure mk_early_pgtbl_32() Thomas Gleixner
2023-10-20 11:38 ` [tip: x86/microcode] " tip-bot2 for Thomas Gleixner
2023-10-17 21:23 ` [patch V5 05/39] x86/microcode: Provide CONFIG_MICROCODE_INITRD32 Thomas Gleixner
2023-10-20 11:38 ` [tip: x86/microcode] " tip-bot2 for Thomas Gleixner
2023-10-17 21:23 ` [patch V5 06/39] x86/boot/32: Temporarily map initrd for microcode loading Thomas Gleixner
2023-10-20 11:38 ` [tip: x86/microcode] " tip-bot2 for Thomas Gleixner
2023-10-17 21:23 ` [patch V5 07/39] x86/microcode/32: Move early loading after paging enable Thomas Gleixner
2023-10-20 11:38 ` [tip: x86/microcode] " tip-bot2 for Thomas Gleixner
2023-10-17 21:23 ` [patch V5 08/39] x86/microcode/intel: Rip out mixed stepping support for Intel CPUs Thomas Gleixner
2023-10-20 11:38 ` [tip: x86/microcode] " tip-bot2 for Ashok Raj
2023-10-17 21:23 ` [patch V5 09/39] x86/microcode/intel: Simplify scan_microcode() Thomas Gleixner
2023-10-17 21:23 ` [patch V5 10/39] x86/microcode/intel: Simplify and rename generic_load_microcode() Thomas Gleixner
2023-10-17 21:23 ` [patch V5 11/39] x86/microcode/intel: Cleanup code further Thomas Gleixner
2023-10-17 21:23 ` [patch V5 12/39] x86/microcode/intel: Simplify early loading Thomas Gleixner
2023-10-20 11:38 ` [tip: x86/microcode] " tip-bot2 for Thomas Gleixner
2023-10-24 13:21 ` tip-bot2 for Thomas Gleixner
2023-10-17 21:23 ` [patch V5 13/39] x86/microcode/intel: Save the microcode only after a successful late-load Thomas Gleixner
2023-10-17 21:23 ` [patch V5 14/39] x86/microcode/intel: Switch to kvmalloc() Thomas Gleixner
2023-10-17 21:23 ` [patch V5 15/39] x86/microcode/intel: Unify microcode apply() functions Thomas Gleixner
2023-10-20 11:37 ` [tip: x86/microcode] " tip-bot2 for Thomas Gleixner
2023-10-24 13:21 ` tip-bot2 for Thomas Gleixner
2023-10-17 21:23 ` [patch V5 16/39] x86/microcode/intel: Rework intel_cpu_collect_info() Thomas Gleixner
2023-10-20 11:37 ` [tip: x86/microcode] " tip-bot2 for Thomas Gleixner
2023-10-24 13:21 ` tip-bot2 for Thomas Gleixner
2023-10-17 21:23 ` [patch V5 17/39] x86/microcode/intel: Reuse intel_cpu_collect_info() Thomas Gleixner
2023-10-17 21:23 ` [patch V5 18/39] x86/microcode/intel: Rework intel_find_matching_signature() Thomas Gleixner
2023-10-17 21:23 ` [patch V5 19/39] x86/microcode: Remove pointless apply() invocation Thomas Gleixner
2023-10-20 11:37 ` [tip: x86/microcode] " tip-bot2 for Thomas Gleixner
2023-10-24 13:21 ` tip-bot2 for Thomas Gleixner
2023-10-17 21:23 ` [patch V5 20/39] x86/microcode/amd: Use correct per CPU ucode_cpu_info Thomas Gleixner
2023-10-17 21:23 ` [patch V5 21/39] x86/microcode/amd: Cache builtin microcode too Thomas Gleixner
2023-10-17 21:23 ` [patch V5 22/39] x86/microcode/amd: Cache builtin/initrd microcode early Thomas Gleixner
2023-10-20 11:37 ` [tip: x86/microcode] " tip-bot2 for Thomas Gleixner
2023-10-24 13:21 ` tip-bot2 for Thomas Gleixner
2023-10-17 21:23 ` [patch V5 23/39] x86/microcode/amd: Use cached microcode for AP load Thomas Gleixner
2023-10-20 11:37 ` [tip: x86/microcode] " tip-bot2 for Thomas Gleixner
2023-10-24 13:21 ` tip-bot2 for Thomas Gleixner
2023-10-17 21:23 ` [patch V5 24/39] x86/microcode: Mop up early loading leftovers Thomas Gleixner
2023-10-20 11:37 ` [tip: x86/microcode] " tip-bot2 for Thomas Gleixner
2023-10-24 13:20 ` tip-bot2 for Thomas Gleixner
2023-10-17 21:23 ` [patch V5 25/39] x86/microcode: Get rid of the schedule work indirection Thomas Gleixner
2023-10-20 11:37 ` [tip: x86/microcode] " tip-bot2 for Thomas Gleixner
2023-10-24 13:20 ` tip-bot2 for Thomas Gleixner
2023-10-17 21:23 ` [patch V5 26/39] x86/microcode: Clean up mc_cpu_down_prep() Thomas Gleixner
2023-10-17 21:24 ` [patch V5 27/39] x86/microcode: Handle "nosmt" correctly Thomas Gleixner
2023-10-17 21:24 ` [patch V5 28/39] x86/microcode: Clarify the late load logic Thomas Gleixner
2023-10-17 21:24 ` [patch V5 29/39] x86/microcode: Sanitize __wait_for_cpus() Thomas Gleixner
2023-10-17 21:24 ` Thomas Gleixner [this message]
2023-10-20 11:37 ` [tip: x86/microcode] x86/microcode: Add per CPU result state tip-bot2 for Thomas Gleixner
2023-10-24 13:20 ` tip-bot2 for Thomas Gleixner
2023-10-17 21:24 ` [patch V5 31/39] x86/microcode: Add per CPU control field Thomas Gleixner
2023-10-17 21:24 ` [patch V5 32/39] x86/microcode: Provide new control functions Thomas Gleixner
2023-10-17 21:24 ` [patch V5 33/39] x86/microcode: Replace the all-in-one rendevous handler Thomas Gleixner
2023-10-17 21:24 ` [patch V5 34/39] x86/microcode: Rendezvous and load in NMI Thomas Gleixner
2023-10-17 21:24 ` [patch V5 35/39] x86/microcode: Protect against instrumentation Thomas Gleixner
2023-10-17 21:24 ` [patch V5 36/39] x86/apic: Provide apic_force_nmi_on_cpu() Thomas Gleixner
2023-10-17 21:24 ` [patch V5 37/39] x86/microcode: Handle "offline" CPUs correctly Thomas Gleixner
2023-10-17 21:24 ` [patch V5 38/39] x86/microcode: Prepare for minimal revision check Thomas Gleixner
2023-10-20 11:37 ` [tip: x86/microcode] " tip-bot2 for Thomas Gleixner
2023-10-24 13:20 ` tip-bot2 for Thomas Gleixner
2023-10-17 21:24 ` [patch V5 39/39] x86/microcode/intel: Add a minimum required revision for late loading Thomas Gleixner
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=20231017211723.632681010@linutronix.de \
--to=tglx@linutronix.de \
--cc=bp@alien8.de \
--cc=linux-kernel@vger.kernel.org \
--cc=x86@kernel.org \
/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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.