[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <20251013143444.3999-36-david.kaplan@amd.com>
Date: Mon, 13 Oct 2025 09:34:23 -0500
From: David Kaplan <david.kaplan@....com>
To: Thomas Gleixner <tglx@...utronix.de>, Borislav Petkov <bp@...en8.de>,
Peter Zijlstra <peterz@...radead.org>, Josh Poimboeuf <jpoimboe@...nel.org>,
Pawan Gupta <pawan.kumar.gupta@...ux.intel.com>, Ingo Molnar
<mingo@...hat.com>, Dave Hansen <dave.hansen@...ux.intel.com>,
<x86@...nel.org>, "H . Peter Anvin" <hpa@...or.com>
CC: Alexander Graf <graf@...zon.com>, Boris Ostrovsky
<boris.ostrovsky@...cle.com>, <linux-kernel@...r.kernel.org>
Subject: [RFC PATCH 35/56] x86/alternative: Save old bytes for retpolines
Similar to alternatives, save the original bytes when patching retpolines
the first time.
Signed-off-by: David Kaplan <david.kaplan@....com>
---
arch/x86/include/asm/alternative.h | 5 ++++
arch/x86/include/asm/module.h | 2 ++
arch/x86/kernel/alternative.c | 37 +++++++++++++++++++++++++++++-
3 files changed, 43 insertions(+), 1 deletion(-)
diff --git a/arch/x86/include/asm/alternative.h b/arch/x86/include/asm/alternative.h
index 3ee781d61927..24a4afbf163b 100644
--- a/arch/x86/include/asm/alternative.h
+++ b/arch/x86/include/asm/alternative.h
@@ -102,6 +102,11 @@ struct alt_site {
u8 len;
};
+struct retpoline_site {
+ u8 bytes[6];
+ u8 len;
+} __packed;
+
extern void alternative_instructions(void);
extern void apply_alternatives(struct alt_instr *start, struct alt_instr *end,
struct module *mod);
diff --git a/arch/x86/include/asm/module.h b/arch/x86/include/asm/module.h
index 2bb602f99154..d0c39b921408 100644
--- a/arch/x86/include/asm/module.h
+++ b/arch/x86/include/asm/module.h
@@ -21,6 +21,8 @@ struct mod_arch_specific {
struct its_array its_pages;
#ifdef CONFIG_DYNAMIC_MITIGATIONS
struct alt_site *alt_sites;
+ struct retpoline_site *retpoline_sites;
+ int num_retpoline_sites;
#endif
};
diff --git a/arch/x86/kernel/alternative.c b/arch/x86/kernel/alternative.c
index 8037076e9301..a02dc6bfb696 100644
--- a/arch/x86/kernel/alternative.c
+++ b/arch/x86/kernel/alternative.c
@@ -302,6 +302,8 @@ static bool __maybe_unused repatch_in_progress;
#ifdef CONFIG_DYNAMIC_MITIGATIONS
static struct alt_site *alt_sites;
+static struct retpoline_site *retpoline_sites;
+static int num_retpoline_sites;
/* Do not patch __init text addresses when repatching */
static bool should_patch(void *addr, struct module *mod)
@@ -1036,8 +1038,36 @@ static int patch_retpoline(void *addr, struct insn *insn, u8 *bytes)
void __init_or_module noinline apply_retpolines(s32 *start, s32 *end, struct module *mod)
{
s32 *s;
+ u32 idx = 0;
+ struct retpoline_site *save_site = NULL;
- for (s = start; s < end; s++) {
+#ifdef CONFIG_DYNAMIC_MITIGATIONS
+ u32 size = ((u64)end - (u64)start)/4;
+
+ /* ITS code needs the save_site pointer even on re-patch. */
+ if (!mod) {
+ if (!retpoline_sites) {
+ retpoline_sites = kcalloc(size, sizeof(struct retpoline_site), GFP_KERNEL);
+ if (WARN_ON(!retpoline_sites))
+ return;
+ }
+
+ save_site = retpoline_sites;
+ num_retpoline_sites = size;
+ } else {
+ if (!mod->arch.retpoline_sites) {
+ mod->arch.retpoline_sites = kcalloc(size, sizeof(struct retpoline_site),
+ GFP_KERNEL);
+ if (WARN_ON(!mod->arch.retpoline_sites))
+ return;
+ }
+
+ save_site = mod->arch.retpoline_sites;
+ mod->arch.num_retpoline_sites = size;
+ }
+#endif
+
+ for (s = start; s < end; s++, idx++) {
void *addr = (void *)s + *s;
struct insn insn;
int len, ret;
@@ -1085,6 +1115,11 @@ void __init_or_module noinline apply_retpolines(s32 *start, s32 *end, struct mod
addr, addr, insn.length,
addr + insn.length + insn.immediate.value);
+ if (IS_ENABLED(CONFIG_DYNAMIC_MITIGATIONS) && save_site) {
+ save_site[idx].len = insn.length;
+ memcpy(save_site[idx].bytes, addr, insn.length);
+ }
+
len = patch_retpoline(addr, &insn, bytes);
if (len == insn.length) {
optimize_nops(addr, bytes, len);
--
2.34.1
Powered by blists - more mailing lists