summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRussell King (Oracle) <rmk+kernel@armlinux.org.uk>2022-05-16 10:24:35 +0100
committerRussell King (Oracle) <rmk+kernel@armlinux.org.uk>2023-10-30 12:55:58 +0000
commitf06e4de16b57e425a1a9f27b07495dedb29d06e1 (patch)
treede57b817153c45a5e8aa6f63834b29c71907e22d
parent04d79b59295624ca50691ba4c45d1eda6c4db80f (diff)
arm64: text replication: copy initial kernel text
Allocate memory on the appropriate node for the per-node copies of the kernel text, and copy the kernel text to that memory. Clean and invalidate the caches to the point of unification so that the copied text is correctly visible to the target node. Signed-off-by: Russell King (Oracle) <rmk+kernel@armlinux.org.uk>
-rw-r--r--arch/arm64/mm/ktext.c21
1 files changed, 21 insertions, 0 deletions
diff --git a/arch/arm64/mm/ktext.c b/arch/arm64/mm/ktext.c
index 901f159c65e6..4c803b89fcfe 100644
--- a/arch/arm64/mm/ktext.c
+++ b/arch/arm64/mm/ktext.c
@@ -4,14 +4,23 @@
*/
#include <linux/kernel.h>
+#include <linux/memblock.h>
+#include <linux/numa.h>
#include <linux/pgtable.h>
+#include <linux/string.h>
+#include <asm/cacheflush.h>
#include <asm/ktext.h>
#include <asm/memory.h>
+static void *kernel_texts[MAX_NUMNODES];
+
+/* Allocate memory for the replicated kernel texts. */
void __init ktext_replication_init(void)
{
+ size_t size = _etext - _stext;
int kidx = pgd_index((phys_addr_t)KERNEL_START);
+ int nid;
/*
* If we've messed up and the kernel shares a L0 entry with the
@@ -26,4 +35,16 @@ void __init ktext_replication_init(void)
pr_warn("Kernel is located in the same L0 index as vmalloc - text replication disabled\n");
return;
}
+
+ for_each_node(nid) {
+ /* Nothing to do for node 0 */
+ if (!nid)
+ continue;
+
+ /* Allocate and copy initial kernel text for this node */
+ kernel_texts[nid] = memblock_alloc_node(size, PAGE_SIZE, nid);
+ memcpy(kernel_texts[nid], _stext, size);
+ caches_clean_inval_pou((u64)kernel_texts[nid],
+ (u64)kernel_texts[nid] + size);
+ }
}