From: "Chang S. Bae" <chang.seok.bae@intel.com>
To: linux-kernel@vger.kernel.org
Cc: x86@kernel.org, tglx@kernel.org, mingo@redhat.com, bp@alien8.de,
dave.hansen@linux.intel.com, peterz@infradead.org,
david.kaplan@amd.com, chang.seok.bae@intel.com
Subject: [PATCH v2 05/11] stop_machine: Introduce stop_machine_nmi_cpuslocked()
Date: Tue, 31 Mar 2026 01:42:43 +0000 [thread overview]
Message-ID: <20260331014251.86353-6-chang.seok.bae@intel.com> (raw)
In-Reply-To: <20260331014251.86353-1-chang.seok.bae@intel.com>
With the NMI control logic in place, introduce an API to run the target
function from NMI context.
Originally-by: David Kaplan <david.kaplan@amd.com>
Suggested-by: Borislav Petkov <bp@alien8.de>
Signed-off-by: Chang S. Bae <chang.seok.bae@intel.com>
Link: https://lore.kernel.org/lkml/20260202105411.GVaYCCUygtEUNrMUtG@fat_crate.local
---
V1 -> V2:
* Support nmi_cpus mask (Boris), including @cpus=NULL cases
* Split out API introduction
* Drop out stop_machine_nmi() [**]
[**] could be added but no user yet in this series
---
include/linux/stop_machine.h | 24 ++++++++++++++++++++
kernel/stop_machine.c | 43 ++++++++++++++++++++++++++++++++++++
2 files changed, 67 insertions(+)
diff --git a/include/linux/stop_machine.h b/include/linux/stop_machine.h
index 9424d363ab38..2da9aa0ec3d3 100644
--- a/include/linux/stop_machine.h
+++ b/include/linux/stop_machine.h
@@ -201,6 +201,30 @@ stop_machine_from_inactive_cpu(cpu_stop_fn_t fn, void *data,
void arch_send_self_nmi(void);
bool noinstr stop_machine_nmi_handler(void);
+/**
+ * stop_machine_nmi_cpuslocked() - Freeze CPUs and run a function in NMI context
+ *
+ * @nmisafe_fn: The function to run
+ * @data: The data pointer for @nmisafe_fn()
+ * @cpus: A cpumask containing the CPUs to run @nmisafe_fn() on. If NULL,
+ * @nmisafe_fn() runs on a single (arbitrary) CPU from
+ * cpu_online_mask.
+ *
+ * Description: This stop_machine() variant runs @nmisafe_fn() from NMI context
+ * to prevent preemption by other NMIs. The callback must be built with noinstr.
+ * Other than that, the semantics match stop_machine_cpuslocked().
+ *
+ * Context: Must be called from within a cpus_read_lock() protected region.
+ * Avoid nested calls to cpus_read_lock().
+ *
+ * Return: 0 if all invocations of @nmisafe_fn return zero, -ENOMEM if cpumask
+ * allocation fails, -EINVAL if any target CPU failed to receive NMI. Otherwise,
+ * an accumulated return value from all invocation of @nmisafe_fn that returned
+ * non-zero.
+ */
+int stop_machine_nmi_cpuslocked(cpu_stop_nmisafe_fn_t nmisafe_fn, void *data,
+ const struct cpumask *cpus);
+
#else
static inline bool stop_machine_nmi_handler(void) { return false; }
#endif /* CONFIG_STOP_MACHINE_NMI */
diff --git a/kernel/stop_machine.c b/kernel/stop_machine.c
index 45ea62f1b2b5..e20e4d3e7b16 100644
--- a/kernel/stop_machine.c
+++ b/kernel/stop_machine.c
@@ -798,6 +798,49 @@ static int multi_stop_run(struct multi_stop_data *msdata)
return msdata->use_nmi ? nmi_stop_run(msdata) : msdata->fn(msdata->data);
}
+int stop_machine_nmi_cpuslocked(cpu_stop_nmisafe_fn_t nmisafe_fn, void *data,
+ const struct cpumask *cpus)
+{
+ struct multi_stop_data msdata = {
+ .nmisafe_fn = nmisafe_fn,
+ .data = data,
+ .num_threads = num_online_cpus(),
+ .active_cpus = cpus,
+ .use_nmi = true,
+ };
+ int ret;
+
+ if (!zalloc_cpumask_var(&msdata.nmi_cpus, GFP_KERNEL))
+ return -ENOMEM;
+
+ /*
+ * NMI CPUs should be exactly those 'active' CPUs executing the
+ * stop function. Follow the selection logic in multi_cpu_stop()
+ * if not provided.
+ */
+ if (!msdata.active_cpus)
+ cpumask_set_cpu(cpumask_first(cpu_online_mask), msdata.nmi_cpus);
+ else
+ cpumask_copy(msdata.nmi_cpus, msdata.active_cpus);
+
+ lockdep_assert_cpus_held();
+
+ ret = stop_multi_cpus(&msdata);
+
+ /*
+ * The NMI handler clears each CPU bit. If any of those NMIs were
+ * ever missed out, return error clearly.
+ */
+ if (!cpumask_empty(msdata.nmi_cpus)) {
+ pr_err("CPUs %*pbl didn't run the stop_machine NMI handler.\n",
+ cpumask_pr_args(msdata.nmi_cpus));
+ ret = -EINVAL;
+ }
+
+ free_cpumask_var(msdata.nmi_cpus);
+ return ret;
+}
+
#else
static int multi_stop_run(struct multi_stop_data *msdata)
--
2.51.0
next prev parent reply other threads:[~2026-03-31 2:14 UTC|newest]
Thread overview: 18+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-03-31 1:42 [PATCH v2 00/11] x86/microcode: Refactor NMI-based rendezvous mechanism to stop-machine Chang S. Bae
2026-03-31 1:42 ` [PATCH v2 01/11] stop_machine: Clarify @cpus == NULL semantics Chang S. Bae
2026-07-23 4:34 ` Borislav Petkov
2026-03-31 1:42 ` [RFC][PATCH v2 02/11] stop_machine: Accumulate error code rather than overwrite Chang S. Bae
2026-08-09 2:04 ` Borislav Petkov
2026-08-11 6:02 ` Chang S. Bae
2026-03-31 1:42 ` [PATCH v2 03/11] stop_machine: Refactor multi-CPU stop glue code Chang S. Bae
2026-03-31 1:42 ` [PATCH v2 04/11] stop_machine: Add NMI-based execution path Chang S. Bae
2026-04-01 2:57 ` Chang S. Bae
2026-03-31 1:42 ` Chang S. Bae [this message]
2026-03-31 1:42 ` [PATCH v2 06/11] x86/apic: Implement self-NMI support Chang S. Bae
2026-03-31 1:42 ` [PATCH v2 07/11] x86/nmi: Support NMI stop-machine handler Chang S. Bae
2026-03-31 1:42 ` [PATCH v2 08/11] x86/microcode: Distinguish NMI control path on stop-machine callback Chang S. Bae
2026-03-31 1:42 ` [PATCH v2 09/11] x86/microcode: Use stop-machine NMI facility Chang S. Bae
2026-03-31 1:42 ` [PATCH v2 10/11] x86/nmi: Simplify offline microcode handler invocation Chang S. Bae
2026-03-31 1:42 ` [PATCH v2 11/11] x86/microcode: Remove microcode_nmi_handler_enable Chang S. Bae
2026-08-09 2:05 ` [PATCH v2 00/11] x86/microcode: Refactor NMI-based rendezvous mechanism to stop-machine Borislav Petkov
2026-08-11 6:02 ` Chang S. Bae
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=20260331014251.86353-6-chang.seok.bae@intel.com \
--to=chang.seok.bae@intel.com \
--cc=bp@alien8.de \
--cc=dave.hansen@linux.intel.com \
--cc=david.kaplan@amd.com \
--cc=linux-kernel@vger.kernel.org \
--cc=mingo@redhat.com \
--cc=peterz@infradead.org \
--cc=tglx@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.