summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRussell King (Oracle) <rmk+kernel@armlinux.org.uk>2023-10-11 18:12:53 +0100
committerRussell King (Oracle) <rmk+kernel@armlinux.org.uk>2023-10-11 18:14:57 +0100
commit6188e1f71bf3f1000eb5b404ec62c17cd336b23d (patch)
treef3796e8341da5c4c2c2847025d20498e4a206501
parent97fcdb1b9798ac74f001a1baeb4f5e561cc658d3 (diff)
arm64: text replication: handle aarch64_insn_write_literal_u64()
aarch64_insn_write_literal_u64() was introduced in v6.3-rc1 for updating ftrace ops pointers in the kernel text. This needs to be fixed up for kernel text replication, so provide a version that will update the mapping. Signed-off-by: Russell King (Oracle) <rmk+kernel@armlinux.org.uk>
-rw-r--r--arch/arm64/include/asm/ktext.h1
-rw-r--r--arch/arm64/kernel/patching.c2
-rw-r--r--arch/arm64/mm/ktext.c21
3 files changed, 24 insertions, 0 deletions
diff --git a/arch/arm64/include/asm/ktext.h b/arch/arm64/include/asm/ktext.h
index 289e11289c06..def0c894ed46 100644
--- a/arch/arm64/include/asm/ktext.h
+++ b/arch/arm64/include/asm/ktext.h
@@ -10,6 +10,7 @@
#ifdef CONFIG_REPLICATE_KTEXT
void ktext_replication_init(void);
+void ktext_replication_write(void *addr, void *data, size_t size);
void __kprobes ktext_replication_patch(u32 *tp, __le32 insn);
void ktext_replication_patch_alternative(__le32 *src, int nr_inst);
diff --git a/arch/arm64/kernel/patching.c b/arch/arm64/kernel/patching.c
index 627fff6ddda2..b670e159a766 100644
--- a/arch/arm64/kernel/patching.c
+++ b/arch/arm64/kernel/patching.c
@@ -103,6 +103,8 @@ noinstr int aarch64_insn_write_literal_u64(void *addr, u64 val)
patch_unmap(FIX_TEXT_POKE0);
raw_spin_unlock_irqrestore(&patch_lock, flags);
+ ktext_replication_write(addr, &val, sizeof(val));
+
return ret;
}
diff --git a/arch/arm64/mm/ktext.c b/arch/arm64/mm/ktext.c
index 04b5ceddae4e..0017e7760d36 100644
--- a/arch/arm64/mm/ktext.c
+++ b/arch/arm64/mm/ktext.c
@@ -17,6 +17,27 @@
static void *kernel_texts[MAX_NUMNODES];
+noinstr void ktext_replication_write(void *addr, void *data, size_t size)
+{
+ unsigned long offset;
+ void *ptr;
+ int nid;
+
+ if (!is_kernel_text((unsigned long)addr))
+ return;
+
+ offset = (unsigned long)addr - (unsigned long)_stext;
+
+ for_each_node(nid) {
+ if (!kernel_texts[nid] || !nid)
+ continue;
+
+ ptr = kernel_texts[nid] + offset;
+
+ memcpy(ptr, data, size);
+ }
+}
+
void __kprobes ktext_replication_patch(u32 *tp, __le32 insn)
{
unsigned long offset;