From: David Kaplan <david.kaplan@amd.com>
To: Thomas Gleixner <tglx@linutronix.de>,
Borislav Petkov <bp@alien8.de>,
Peter Zijlstra <peterz@infradead.org>,
Josh Poimboeuf <jpoimboe@kernel.org>,
Pawan Gupta <pawan.kumar.gupta@linux.intel.com>,
Ingo Molnar <mingo@redhat.com>,
Dave Hansen <dave.hansen@linux.intel.com>, <x86@kernel.org>,
"H . Peter Anvin" <hpa@zytor.com>
Cc: Alexander Graf <graf@amazon.com>,
Boris Ostrovsky <boris.ostrovsky@oracle.com>,
<linux-kernel@vger.kernel.org>
Subject: [RFC PATCH 50/56] x86/alternative: Add re-patch support
Date: Mon, 13 Oct 2025 09:34:38 -0500 [thread overview]
Message-ID: <20251013143444.3999-51-david.kaplan@amd.com> (raw)
In-Reply-To: <20251013143444.3999-1-david.kaplan@amd.com>
Updating alternatives is done under the biggest hammers possible. The
freezer is used to freeze all processes and kernel threads at safe
points to ensure they are not in the middle of a sequence we're about to
patch. Then stop_machine_nmi() synchronizes all CPUs and puts them into
a tight spin loop while re-patching occurs. The actual patching is done
using simple memcpy, just like during boot.
Signed-off-by: David Kaplan <david.kaplan@amd.com>
---
arch/x86/include/asm/alternative.h | 6 ++
arch/x86/kernel/alternative.c | 131 +++++++++++++++++++++++++++++
2 files changed, 137 insertions(+)
diff --git a/arch/x86/include/asm/alternative.h b/arch/x86/include/asm/alternative.h
index 61ce8a4b1aa6..f0b863292c3c 100644
--- a/arch/x86/include/asm/alternative.h
+++ b/arch/x86/include/asm/alternative.h
@@ -19,6 +19,7 @@
#ifndef __ASSEMBLER__
#include <linux/stddef.h>
+#include <linux/static_call_types.h>
/*
* Alternative inline assembly for SMP.
@@ -89,6 +90,9 @@ extern s32 __cfi_sites[], __cfi_sites_end[];
extern s32 __ibt_endbr_seal[], __ibt_endbr_seal_end[];
extern s32 __smp_locks[], __smp_locks_end[];
+extern struct static_call_site __start_static_call_sites[],
+ __stop_static_call_sites[];
+
/*
* Debug flag that can be tested to see whether alternative
* instructions were patched in already:
@@ -98,6 +102,8 @@ extern int alternatives_patched;
struct module;
#ifdef CONFIG_DYNAMIC_MITIGATIONS
+extern void cpu_update_alternatives(void);
+extern void cpu_prepare_repatch_alternatives(void);
extern void reset_retpolines(s32 *start, s32 *end, struct module *mod);
extern void reset_returns(s32 *start, s32 *end, struct module *mod);
extern void reset_alternatives(struct alt_instr *start, struct alt_instr *end,
diff --git a/arch/x86/kernel/alternative.c b/arch/x86/kernel/alternative.c
index 23bb3386ec5e..613cb645bd9f 100644
--- a/arch/x86/kernel/alternative.c
+++ b/arch/x86/kernel/alternative.c
@@ -6,12 +6,15 @@
#include <linux/vmalloc.h>
#include <linux/memory.h>
#include <linux/execmem.h>
+#include <linux/stop_machine.h>
+#include <linux/freezer.h>
#include <asm/text-patching.h>
#include <asm/insn.h>
#include <asm/ibt.h>
#include <asm/set_memory.h>
#include <asm/nmi.h>
+#include <asm/bugs.h>
int __read_mostly alternatives_patched;
@@ -3468,4 +3471,132 @@ void its_free_all(struct module *mod)
its_page = NULL;
}
#endif
+static atomic_t thread_ack;
+
+/*
+ * This function is called by ALL online CPUs but only CPU0 will do the
+ * re-patching. It is important that all other cores spin in the tight loop
+ * below (and not in multi_cpu_stop) because they cannot safely do return
+ * instructions while returns are being patched. Therefore, spin them here
+ * (with interrupts disabled) until CPU0 has finished its work.
+ */
+static int __cpu_update_alternatives(void *__unused)
+{
+ if (smp_processor_id()) {
+ atomic_dec(&thread_ack);
+ while (!READ_ONCE(alternatives_patched))
+ cpu_relax();
+
+ cpu_bugs_update_speculation_msrs();
+ } else {
+ repatch_in_progress = true;
+
+ /* Wait for all cores to enter this function. */
+ while (atomic_read(&thread_ack))
+ cpu_relax();
+
+ /* These must be un-done in the opposite order in which they were applied. */
+ reset_alternatives(__alt_instructions, __alt_instructions_end, NULL);
+ reset_builtin_callthunks();
+ reset_returns(__return_sites, __return_sites_end, NULL);
+ reset_retpolines(__retpoline_sites, __retpoline_sites_end, NULL);
+
+ apply_retpolines(__retpoline_sites, __retpoline_sites_end, NULL);
+ apply_returns(__return_sites, __return_sites_end, NULL);
+ callthunks_patch_builtin_calls();
+ apply_alternatives(__alt_instructions, __alt_instructions_end, NULL);
+
+ update_all_static_calls(__start_static_call_sites,
+ __stop_static_call_sites, NULL);
+ modules_update_alternatives();
+ cpu_bugs_update_speculation_msrs();
+ repatch_in_progress = false;
+
+ /* This will wake the other CPUs. */
+ WRITE_ONCE(alternatives_patched, 1);
+ }
+ return 0;
+}
+
+void cpu_prepare_repatch_alternatives(void)
+{
+ alternatives_patched = 0;
+ /* Reset the synchronization barrier. */
+ atomic_set(&thread_ack, num_online_cpus() - 1);
+}
+
+static void make_all_text_writeable(void)
+{
+ unsigned long start = PFN_ALIGN(_text);
+ unsigned long end = PFN_ALIGN(_etext);
+
+ set_memory_rw(start, (end - start) >> PAGE_SHIFT);
+ modules_prepare_repatch();
+}
+
+static void make_all_text_readonly(void)
+{
+ unsigned long start = PFN_ALIGN(_text);
+ unsigned long end = PFN_ALIGN(_etext);
+
+ set_memory_ro(start, (end - start) >> PAGE_SHIFT);
+ modules_post_repatch();
+}
+
+void cpu_update_alternatives(void)
+{
+ /*
+ * Re-patching is not supported under Xen PV because it uses MOV-CR2
+ * for synchronization (see sync_core_nmi_safe()).
+ */
+ if (cpu_feature_enabled(X86_FEATURE_XENPV)) {
+ pr_err("Xen PV does not support dynamic mitigations!\n");
+ alternatives_patched = 1;
+ return;
+ }
+
+ pr_info("Re-patching alternatives\n");
+
+ /*
+ * ITS mitigation requires dynamic memory allocation and changing memory
+ * permissions. These are not possible under NMI context.
+ *
+ * Therefore, pre-allocate ITS pages if needed. If previous ITS pages
+ * exist, those will be used instead.
+ */
+ its_prealloc(__retpoline_sites, __retpoline_sites_end, NULL);
+ modules_pre_update_alternatives();
+
+ /*
+ * Freeze everything because we cannot have a thread be in the middle of
+ * something we're about to change when we issue stop_machine.
+ *
+ * Therefore, use the freezer to get all tasks to a safe place before we
+ * re-patch.
+ */
+ if (freeze_processes()) {
+ pr_err("Unable to freeze processes for re-patching!\n");
+ return;
+ }
+
+ if (freeze_kernel_threads()) {
+ pr_err("Unable to freeze tasks for re-patching!\n");
+ thaw_processes();
+ return;
+ }
+
+ make_all_text_writeable();
+ stop_machine_nmi(__cpu_update_alternatives, NULL, cpu_online_mask);
+ make_all_text_readonly();
+
+ cpu_bugs_smt_update();
+
+ /* Free un-needed ITS pages. This cannot happen in NMI context. */
+ its_free_all(NULL);
+ modules_post_update_alternatives();
+
+ thaw_kernel_threads();
+ thaw_processes();
+ pr_info("Finished re-patching alternatives\n");
+}
#endif
--
2.34.1
next prev parent reply other threads:[~2025-10-13 14:36 UTC|newest]
Thread overview: 175+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-10-13 14:33 [RFC PATCH 00/56] Dynamic mitigations David Kaplan
2025-10-13 14:33 ` [RFC PATCH 01/56] Documentation/admin-guide: Add documentation David Kaplan
2025-10-16 21:24 ` Josh Poimboeuf
2025-10-17 14:04 ` Kaplan, David
2025-10-18 13:39 ` Borislav Petkov
2025-10-20 13:53 ` Kaplan, David
2025-10-22 11:43 ` Borislav Petkov
2025-10-13 14:33 ` [RFC PATCH 02/56] x86/Kconfig: Add CONFIG_DYNAMIC_MITIGATIONS David Kaplan
2025-10-16 21:20 ` Josh Poimboeuf
2025-10-17 13:57 ` Kaplan, David
2025-10-13 14:33 ` [RFC PATCH 03/56] cpu: Reset global mitigations David Kaplan
2025-10-16 21:34 ` Josh Poimboeuf
2025-10-17 14:05 ` Kaplan, David
2025-10-17 14:19 ` Kaplan, David
2025-10-17 16:03 ` Josh Poimboeuf
2025-10-17 16:36 ` Borislav Petkov
2025-10-13 14:33 ` [RFC PATCH 04/56] x86/bugs: Reset spectre_v1 mitigations David Kaplan
2025-10-14 18:37 ` Dave Hansen
2025-10-14 19:16 ` Kaplan, David
2025-10-29 11:57 ` Borislav Petkov
2025-10-29 13:48 ` Kaplan, David
2025-11-03 18:24 ` Borislav Petkov
2025-10-13 14:33 ` [RFC PATCH 05/56] x86/bugs: Reset spectre_v2 mitigations David Kaplan
2025-11-03 19:31 ` Borislav Petkov
2025-11-03 20:10 ` Kaplan, David
2025-11-03 20:28 ` Borislav Petkov
2025-11-05 2:29 ` Josh Poimboeuf
2025-11-05 11:03 ` Borislav Petkov
2025-11-05 17:06 ` Josh Poimboeuf
2025-11-05 20:04 ` Borislav Petkov
2025-11-05 20:21 ` Kaplan, David
2025-11-05 20:52 ` Josh Poimboeuf
2025-11-14 17:14 ` [PATCH] x86/bugs: Get rid of the forward declarations Borislav Petkov
2025-11-14 19:19 ` Josh Poimboeuf
2025-11-14 19:31 ` Borislav Petkov
2025-11-14 20:04 ` Pawan Gupta
2025-10-13 14:33 ` [RFC PATCH 06/56] x86/bugs: Reset retbleed mitigations David Kaplan
2025-10-13 14:33 ` [RFC PATCH 07/56] x86/bugs: Reset spectre_v2_user mitigations David Kaplan
2025-10-16 12:54 ` Brendan Jackman
2025-10-16 14:06 ` Kaplan, David
2025-10-16 14:56 ` Brendan Jackman
2025-10-16 15:26 ` Kaplan, David
2025-10-16 16:13 ` Brendan Jackman
2025-11-26 11:23 ` Borislav Petkov
2025-12-01 16:53 ` Kaplan, David
2025-12-03 12:31 ` Borislav Petkov
2025-12-03 17:02 ` Kaplan, David
2025-12-03 17:35 ` Borislav Petkov
2025-12-03 20:14 ` Kaplan, David
2025-12-04 15:07 ` Borislav Petkov
2025-10-13 14:33 ` [RFC PATCH 08/56] x86/bugs: Reset SSB mitigations David Kaplan
2025-10-17 15:13 ` Nikolay Borisov
2025-10-17 15:56 ` Kaplan, David
2026-01-20 13:07 ` Borislav Petkov
2025-10-13 14:33 ` [RFC PATCH 09/56] x86/bugs: Reset L1TF mitigations David Kaplan
2025-10-13 14:33 ` [RFC PATCH 10/56] x86/bugs: Reset MDS mitigations David Kaplan
2025-10-13 14:33 ` [RFC PATCH 11/56] x86/bugs: Reset MMIO mitigations David Kaplan
2026-01-26 13:05 ` Borislav Petkov
2026-01-26 14:51 ` Kaplan, David
2025-10-13 14:34 ` [RFC PATCH 12/56] x86/bugs: Reset SRBDS mitigations David Kaplan
2025-10-13 14:34 ` [RFC PATCH 13/56] x86/bugs: Reset SRSO mitigations David Kaplan
2025-10-13 14:34 ` [RFC PATCH 14/56] x86/bugs: Reset GDS mitigations David Kaplan
2025-10-24 2:40 ` Pawan Gupta
2025-10-24 14:43 ` Kaplan, David
2025-10-13 14:34 ` [RFC PATCH 15/56] x86/bugs: Reset BHI mitigations David Kaplan
2025-10-24 2:49 ` Pawan Gupta
2025-10-24 15:02 ` Kaplan, David
2025-10-13 14:34 ` [RFC PATCH 16/56] x86/bugs: Reset ITS mitigation David Kaplan
2025-10-13 14:34 ` [RFC PATCH 17/56] x86/bugs: Reset TSA mitigations David Kaplan
2025-10-13 14:34 ` [RFC PATCH 18/56] x86/bugs: Reset VMSCAPE mitigations David Kaplan
2025-10-13 14:34 ` [RFC PATCH 19/56] x86/bugs: Define bugs_smt_disable() David Kaplan
2025-10-13 14:34 ` [RFC PATCH 20/56] x86/bugs: Move bugs.c logic out of .init section David Kaplan
2025-10-16 12:31 ` Brendan Jackman
2025-10-16 13:46 ` Kaplan, David
2025-10-16 14:33 ` Brendan Jackman
2025-10-13 14:34 ` [RFC PATCH 21/56] x86/callthunks: Move logic out of .init David Kaplan
2025-10-13 14:34 ` [RFC PATCH 22/56] cpu: Move mitigation " David Kaplan
2025-10-13 14:34 ` [RFC PATCH 23/56] x86/vmlinux.lds: Move alternative sections David Kaplan
2025-10-13 14:34 ` [RFC PATCH 24/56] x86/vmlinux.lds: Move altinstr_aux conditionally David Kaplan
2025-10-13 14:34 ` [RFC PATCH 25/56] x86/vmlinux.lds: Define __init_alt_end David Kaplan
2025-10-13 14:34 ` [RFC PATCH 26/56] module: Save module ELF info David Kaplan
2025-10-13 14:34 ` [RFC PATCH 27/56] x86/mm: Conditionally free alternative sections David Kaplan
2025-10-13 14:34 ` [RFC PATCH 28/56] stop_machine: Add stop_machine_nmi() David Kaplan
2026-01-09 22:16 ` Chang S. Bae
2026-01-09 22:19 ` Kaplan, David
2025-10-13 14:34 ` [RFC PATCH 29/56] x86/apic: Add self-NMI support David Kaplan
2025-10-13 14:34 ` [RFC PATCH 30/56] x86/nmi: Add support for stop_machine_nmi() David Kaplan
2025-10-13 14:34 ` [RFC PATCH 31/56] x86/alternative: Prepend nops with retpolines David Kaplan
2025-10-16 10:32 ` Peter Zijlstra
2025-10-16 11:08 ` Peter Zijlstra
2025-10-16 11:07 ` Peter Zijlstra
2025-10-16 11:10 ` Peter Zijlstra
2025-10-16 11:23 ` Peter Zijlstra
2025-10-16 13:27 ` Kaplan, David
2025-10-16 14:07 ` Peter Zijlstra
2025-10-16 14:16 ` Kaplan, David
2025-10-16 14:23 ` Peter Zijlstra
2025-10-22 8:41 ` David Laight
2025-10-22 10:40 ` Peter Zijlstra
2025-10-13 14:34 ` [RFC PATCH 32/56] x86/alternative: Add module param David Kaplan
2025-10-13 14:34 ` [RFC PATCH 33/56] x86/alternative: Avoid re-patching init code David Kaplan
2025-10-13 14:34 ` [RFC PATCH 34/56] x86/alternative: Save old bytes for alternatives David Kaplan
2025-10-15 10:38 ` Juergen Gross
2025-10-15 13:45 ` Kaplan, David
2025-10-27 11:34 ` Nikolay Borisov
2025-10-27 14:19 ` Kaplan, David
2025-10-29 9:37 ` Nikolay Borisov
2025-10-29 16:26 ` Kaplan, David
2025-10-29 22:14 ` David Laight
2025-10-30 14:39 ` Kaplan, David
2025-10-30 15:42 ` Nikolay Borisov
2025-10-30 15:49 ` Kaplan, David
2025-10-13 14:34 ` [RFC PATCH 35/56] x86/alternative: Save old bytes for retpolines David Kaplan
2025-10-13 14:34 ` [RFC PATCH 36/56] x86/alternative: Do not recompute len on re-patch David Kaplan
2025-10-13 14:34 ` [RFC PATCH 37/56] x86/alternative: Reset alternatives David Kaplan
2025-10-13 14:34 ` [RFC PATCH 38/56] x86/callthunks: Reset callthunks David Kaplan
2025-10-13 14:34 ` [RFC PATCH 39/56] x86/sync_core: Add sync_core_nmi_safe() David Kaplan
2025-10-13 14:34 ` [RFC PATCH 40/56] x86/alternative: Use sync_core_nmi_safe() David Kaplan
2025-10-16 10:35 ` Peter Zijlstra
2025-10-16 14:40 ` Kaplan, David
2025-10-16 14:47 ` Peter Zijlstra
2025-10-16 15:34 ` Kaplan, David
2025-10-16 16:15 ` Dave Hansen
2025-10-16 16:27 ` Borislav Petkov
2025-10-16 18:52 ` Peter Zijlstra
2025-10-16 18:56 ` Kaplan, David
2025-10-16 18:58 ` Peter Zijlstra
2025-10-16 21:53 ` Andrew Cooper
2025-10-20 14:49 ` Kaplan, David
2025-10-20 15:01 ` Peter Zijlstra
2025-10-23 18:50 ` Kaplan, David
2025-10-23 19:26 ` Andrew Cooper
2025-10-23 21:23 ` David Laight
2025-10-21 2:13 ` H. Peter Anvin
2025-10-13 14:34 ` [RFC PATCH 41/56] static_call: Add update_all_static_calls() David Kaplan
2025-10-13 14:34 ` [RFC PATCH 42/56] module: Make memory writeable for re-patching David Kaplan
2025-10-13 14:34 ` [RFC PATCH 43/56] module: Update alternatives David Kaplan
2025-10-13 14:34 ` [RFC PATCH 44/56] x86/module: " David Kaplan
2025-10-13 14:34 ` [RFC PATCH 45/56] x86/alternative: Use boot_cpu_has in ITS code David Kaplan
2025-10-13 14:34 ` [RFC PATCH 46/56] x86/alternative: Add ITS re-patching support David Kaplan
2025-10-13 14:34 ` [RFC PATCH 47/56] x86/module: Add ITS re-patch support for modules David Kaplan
2025-10-13 14:34 ` [RFC PATCH 48/56] x86/bugs: Move code for updating speculation MSRs David Kaplan
2025-10-13 14:34 ` [RFC PATCH 49/56] x86/fpu: Qualify warning in os_xsave David Kaplan
2025-10-13 14:34 ` David Kaplan [this message]
2025-10-31 10:22 ` [RFC PATCH 50/56] x86/alternative: Add re-patch support Nikolay Borisov
2025-11-04 16:54 ` Kaplan, David
2025-10-13 14:34 ` [RFC PATCH 51/56] cpu: Parse string of mitigation options David Kaplan
2025-10-13 14:34 ` [RFC PATCH 52/56] x86/bugs: Support parsing " David Kaplan
2025-10-27 11:31 ` Nikolay Borisov
2025-10-27 13:56 ` Kaplan, David
2025-10-13 14:34 ` [RFC PATCH 53/56] drivers/cpu: Re-patch mitigations through sysfs David Kaplan
2025-10-27 12:25 ` Nikolay Borisov
2025-10-27 13:59 ` Kaplan, David
2025-10-13 14:34 ` [RFC PATCH 54/56] x86/debug: Create debugfs interface to x86_capabilities David Kaplan
2025-10-13 14:34 ` [RFC PATCH 55/56] x86/debug: Show return thunk in debugfs David Kaplan
2025-10-27 12:29 ` Nikolay Borisov
2025-10-27 14:24 ` David Laight
2025-10-13 14:34 ` [RFC PATCH 56/56] x86/debug: Show static branch config " David Kaplan
2025-10-14 16:29 ` [RFC PATCH 00/56] Dynamic mitigations Josh Poimboeuf
2025-10-14 18:06 ` Kaplan, David
2025-10-15 9:14 ` Alexander Graf
2025-10-15 23:06 ` Boris Ostrovsky
2025-10-16 12:21 ` Brendan Jackman
2025-10-15 4:10 ` Aaron Rainbolt
2025-10-15 13:53 ` Kaplan, David
2025-10-15 15:43 ` Josh Poimboeuf
2025-10-15 15:51 ` Kaplan, David
2025-10-15 16:02 ` Josh Poimboeuf
2025-10-15 16:10 ` Kaplan, David
2025-10-16 10:00 ` Nicolas Bouchinet
2025-10-16 13:42 ` Kaplan, David
2025-10-16 13:55 ` Nicolas Bouchinet
2025-10-16 13:56 ` Kaplan, David
2025-10-24 5:00 ` Pawan Gupta
2025-10-24 13:41 ` Kaplan, David
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=20251013143444.3999-51-david.kaplan@amd.com \
--to=david.kaplan@amd.com \
--cc=boris.ostrovsky@oracle.com \
--cc=bp@alien8.de \
--cc=dave.hansen@linux.intel.com \
--cc=graf@amazon.com \
--cc=hpa@zytor.com \
--cc=jpoimboe@kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=mingo@redhat.com \
--cc=pawan.kumar.gupta@linux.intel.com \
--cc=peterz@infradead.org \
--cc=tglx@linutronix.de \
--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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox