From: Nikita Panov <panov.nikita@huawei.com>
To: <catalin.marinas@arm.com>, <akpm@linux-foundation.org>,
<david@kernel.org>, <ljs@kernel.org>, <vbabka@kernel.org>,
<cl@gentwo.org>, <linux@armlinux.org.uk>, <will@kernel.org>,
<mark.rutland@arm.com>, <liam@infradead.org>, <rppt@kernel.org>,
<surenb@google.com>, <mhocko@suse.com>
Cc: <linux-mm@kvack.org>, <linux-kernel@vger.kernel.org>,
<linux-arm-kernel@lists.infradead.org>,
<wangkefeng.wang@huawei.com>, <artem.kuzin@huawei.com>,
<panov.nikita@huawei.com>
Subject: [RFC PATCH 13/18] arm64: make kernel text patching aware about replicas
Date: Fri, 28 Aug 2026 00:11:53 +0800 [thread overview]
Message-ID: <20260827161158.3618409-14-panov.nikita@huawei.com> (raw)
In-Reply-To: <20260827161158.3618409-1-panov.nikita@huawei.com>
Acked-by: Artem Kuzin <artem.kuzin@huawei.com>
Acked-by: Alexander Grubnikov <alexander.grubnikov@huawei.com>
Acked-by: Ilya Hanov <ilya.hanov@huawei-partners.com>
Acked-by: Denis Darvish <darvish.denis@huawei.com>
Signed-off-by: Nikita Panov <panov.nikita@huawei.com>
---
arch/arm64/kernel/alternative.c | 33 +++++++++++-
arch/arm64/kernel/patching.c | 96 +++++++++++++++++++++++++++++++++
2 files changed, 128 insertions(+), 1 deletion(-)
diff --git a/arch/arm64/kernel/alternative.c b/arch/arm64/kernel/alternative.c
index f5ec7e7c1d3f..e85644d64bbd 100644
--- a/arch/arm64/kernel/alternative.c
+++ b/arch/arm64/kernel/alternative.c
@@ -10,6 +10,7 @@
#include <linux/init.h>
#include <linux/cpu.h>
+#include <linux/numa_kernel_replication.h>
#include <linux/elf.h>
#include <asm/cacheflush.h>
#include <asm/alternative.h>
@@ -139,6 +140,36 @@ static noinstr void clean_dcache_range_nopatch(u64 start, u64 end)
} while (cur += d_size, cur < end);
}
+#ifdef CONFIG_KERNEL_REPLICATION
+static void __write_alternatives(struct alt_instr *alt,
+ alternative_cb_t alt_cb,
+ __le32 *origptr, __le32 *updptr,
+ int nr_inst)
+{
+ if (is_text_replicated() && is_kernel_text((unsigned long)origptr)) {
+ int nid;
+
+ for_each_memory_node(nid) {
+ __le32 *ptr = numa_get_replica(origptr, nid);
+
+ alt_cb(alt, origptr, ptr, nr_inst);
+ clean_dcache_range_nopatch((u64)ptr,
+ (u64)(ptr + nr_inst));
+ }
+ } else {
+ alt_cb(alt, origptr, updptr, nr_inst);
+ }
+}
+#else
+static void __write_alternatives(struct alt_instr *alt,
+ alternative_cb_t alt_cb,
+ __le32 *origptr, __le32 *updptr,
+ int nr_inst)
+{
+ alt_cb(alt, origptr, updptr, nr_inst);
+}
+#endif /* CONFIG_KERNEL_REPLICATION */
+
static int __apply_alternatives(const struct alt_region *region,
bool is_module,
unsigned long *cpucap_mask)
@@ -174,7 +205,7 @@ static int __apply_alternatives(const struct alt_region *region,
alt_cb = patch_alternative;
}
- alt_cb(alt, origptr, updptr, nr_inst);
+ __write_alternatives(alt, alt_cb, origptr, updptr, nr_inst);
if (!is_module) {
clean_dcache_range_nopatch((u64)origptr,
diff --git a/arch/arm64/kernel/patching.c b/arch/arm64/kernel/patching.c
index 09f019c6547a..8bac14198459 100644
--- a/arch/arm64/kernel/patching.c
+++ b/arch/arm64/kernel/patching.c
@@ -5,6 +5,7 @@
#include <linux/spinlock.h>
#include <linux/stop_machine.h>
#include <linux/uaccess.h>
+#include <linux/numa_kernel_replication.h>
#include <asm/cacheflush.h>
#include <asm/fixmap.h>
@@ -15,6 +16,7 @@
static DEFINE_RAW_SPINLOCK(patch_lock);
+#ifndef CONFIG_KERNEL_REPLICATION
static bool is_exit_text(unsigned long addr)
{
/* discarded with init text/data */
@@ -42,6 +44,17 @@ static void __kprobes *patch_map(void *addr, int fixmap)
return (void *)set_fixmap_offset(fixmap, phys);
}
+#else
+static void __kprobes *patch_map(void *addr, int fixmap, int nid)
+{
+ struct page *page;
+
+ page = walk_to_page_node(nid, addr);
+ BUG_ON(!page);
+
+ return (void *)set_fixmap_offset(fixmap, page_to_phys(page) + offset_in_page(addr));
+}
+#endif /* CONFIG_KERNEL_REPLICATION */
static void __kprobes patch_unmap(int fixmap)
{
@@ -63,6 +76,28 @@ int __kprobes aarch64_insn_read(void *addr, u32 *insnp)
return ret;
}
+#ifdef CONFIG_KERNEL_REPLICATION
+static int __kprobes __aarch64_insn_write(void *addr, __le32 insn)
+{
+ int nid;
+ void *waddr = addr;
+ unsigned long flags = 0;
+ int ret;
+
+ raw_spin_lock_irqsave(&patch_lock, flags);
+ for_each_memory_node(nid) {
+ waddr = patch_map(addr, FIX_TEXT_POKE0, nid);
+ ret = copy_to_kernel_nofault(waddr, &insn, AARCH64_INSN_SIZE);
+ patch_unmap(FIX_TEXT_POKE0);
+
+ if (ret || !is_text_replicated())
+ break;
+ }
+ raw_spin_unlock_irqrestore(&patch_lock, flags);
+
+ return ret;
+}
+#else
static int __kprobes __aarch64_insn_write(void *addr, __le32 insn)
{
void *waddr = addr;
@@ -79,12 +114,37 @@ static int __kprobes __aarch64_insn_write(void *addr, __le32 insn)
return ret;
}
+#endif /* CONFIG_KERNEL_REPLICATION */
int __kprobes aarch64_insn_write(void *addr, u32 insn)
{
return __aarch64_insn_write(addr, cpu_to_le32(insn));
}
+#ifdef CONFIG_KERNEL_REPLICATION
+noinstr int aarch64_insn_write_literal_u64(void *addr, u64 val)
+{
+ int nid;
+ u64 *waddr;
+ unsigned long flags;
+ int ret;
+
+ raw_spin_lock_irqsave(&patch_lock, flags);
+ for_each_memory_node(nid) {
+ waddr = patch_map(addr, FIX_TEXT_POKE0, nid);
+
+ ret = copy_to_kernel_nofault(waddr, &val, sizeof(val));
+
+ patch_unmap(FIX_TEXT_POKE0);
+
+ if (ret || !is_text_replicated())
+ break;
+ }
+ raw_spin_unlock_irqrestore(&patch_lock, flags);
+
+ return ret;
+}
+#else
noinstr int aarch64_insn_write_literal_u64(void *addr, u64 val)
{
u64 *waddr;
@@ -101,9 +161,44 @@ noinstr int aarch64_insn_write_literal_u64(void *addr, u64 val)
return ret;
}
+#endif /* CONFIG_KERNEL_REPLICATION */
typedef void text_poke_f(void *dst, void *src, size_t patched, size_t len);
+#ifdef CONFIG_KERNEL_REPLICATION
+static void *__text_poke(text_poke_f func, void *addr, void *src, size_t len)
+{
+ unsigned long flags;
+ size_t patched = 0;
+ size_t size;
+ void *waddr;
+ void *ptr;
+
+ raw_spin_lock_irqsave(&patch_lock, flags);
+
+ while (patched < len) {
+ int nid;
+
+ ptr = addr + patched;
+ size = min(PAGE_SIZE - offset_in_page(ptr), len - patched);
+
+ for_each_memory_node(nid) {
+ waddr = patch_map(ptr, FIX_TEXT_POKE0, nid);
+ func(waddr, src, patched, size);
+ patch_unmap(FIX_TEXT_POKE0);
+
+ if (!is_text_replicated())
+ break;
+ }
+ patched += size;
+ }
+ raw_spin_unlock_irqrestore(&patch_lock, flags);
+
+ flush_icache_range((uintptr_t)addr, (uintptr_t)addr + len);
+
+ return addr;
+}
+#else
static void *__text_poke(text_poke_f func, void *addr, void *src, size_t len)
{
unsigned long flags;
@@ -130,6 +225,7 @@ static void *__text_poke(text_poke_f func, void *addr, void *src, size_t len)
return addr;
}
+#endif
static void text_poke_memcpy(void *dst, void *src, size_t patched, size_t len)
{
--
2.34.1
next prev parent reply other threads:[~2026-08-27 16:26 UTC|newest]
Thread overview: 29+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-08-27 16:11 [RFC PATCH 00/18] mm: arm64: Add kernel replication feature Nikita Panov
2026-08-27 16:11 ` [RFC PATCH 01/18] mm: arm64 add Kconfig option for kernel replication Nikita Panov
2026-08-27 16:11 ` [RFC PATCH 02/18] arm64: align kernel text and rodata Nikita Panov
2026-08-27 17:35 ` Lorenzo Stoakes (ARM)
2026-08-28 13:00 ` Nikita Panov
2026-08-27 16:11 ` [RFC PATCH 03/18] mm: allow per-NUMA node local P4D/PUD/PMD/PTE allocation Nikita Panov
2026-08-27 16:11 ` [RFC PATCH 04/18] arm64: add arch callbacks for kernel replication Nikita Panov
2026-08-27 16:11 ` [RFC PATCH 05/18] mm: per-NUMA node replication core infrastructure Nikita Panov
2026-08-27 16:11 ` [RFC PATCH 06/18] mm: add support of memory protection for NUMA replicas Nikita Panov
2026-08-27 16:11 ` [RFC PATCH 07/18] arm64: " Nikita Panov
2026-08-27 16:11 ` [RFC PATCH 08/18] mm: set memory permissions for BPF handlers replicas Nikita Panov
2026-08-27 16:11 ` [RFC PATCH 09/18] mm: add replicas allocation support for vmalloc Nikita Panov
2026-08-27 16:11 ` [RFC PATCH 10/18] arm64: enable per-NUMA node kernel text and rodata replication Nikita Panov
2026-08-27 16:11 ` [RFC PATCH 11/18] mm: " Nikita Panov
2026-08-27 16:11 ` [RFC PATCH 12/18] arm64: make power management aware about kernel replication Nikita Panov
2026-08-27 16:11 ` Nikita Panov [this message]
2026-08-27 16:11 ` [RFC PATCH 14/18] arm64: add correct alignment to kimage in efi code Nikita Panov
2026-08-27 16:11 ` [RFC PATCH 15/18] arm64: add support of NUMA replication for ptdump Nikita Panov
2026-08-27 16:11 ` [RFC PATCH 16/18] arm64: add kernel modules text and rodata replication support Nikita Panov
2026-08-27 16:11 ` [RFC PATCH 17/18] mm: init kernel modules with " Nikita Panov
2026-08-27 16:11 ` [RFC PATCH 18/18] mm: introduce kernel cmdline option "kernel_replication=" Nikita Panov
2026-08-27 17:25 ` [RFC PATCH 00/18] mm: arm64: Add kernel replication feature Lorenzo Stoakes (ARM)
2026-08-27 19:04 ` David Hildenbrand (Arm)
2026-08-28 15:05 ` Artem Kuzin
2026-08-28 13:03 ` Nikita Panov
2026-08-27 19:11 ` Matthew Wilcox
2026-08-28 13:35 ` Nikita Panov
2026-08-28 17:58 ` Christoph Lameter (Ampere)
2026-08-28 20:58 ` Yang Shi
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=20260827161158.3618409-14-panov.nikita@huawei.com \
--to=panov.nikita@huawei.com \
--cc=akpm@linux-foundation.org \
--cc=artem.kuzin@huawei.com \
--cc=catalin.marinas@arm.com \
--cc=cl@gentwo.org \
--cc=david@kernel.org \
--cc=liam@infradead.org \
--cc=linux-arm-kernel@lists.infradead.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-mm@kvack.org \
--cc=linux@armlinux.org.uk \
--cc=ljs@kernel.org \
--cc=mark.rutland@arm.com \
--cc=mhocko@suse.com \
--cc=rppt@kernel.org \
--cc=surenb@google.com \
--cc=vbabka@kernel.org \
--cc=wangkefeng.wang@huawei.com \
--cc=will@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