generic: 6.12: move MIPS reloc patch from pending to hack and rework
Move MIPS reloc patch from pending to hack and rework it to adapt to new kernel 6.12 version. This required an additional patch. While at it also improve the text with the original info without cut. Link: https://github.com/openwrt/openwrt/pull/16547 Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
This commit is contained in:
parent
be6753dda0
commit
a9c0f28951
2 changed files with 149 additions and 29 deletions
|
@ -0,0 +1,99 @@
|
||||||
|
From fec97dbb51697148ba881611f2b780a8d8a15885 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Christian Marangi <ansuelsmth@gmail.com>
|
||||||
|
Date: Mon, 14 Apr 2025 18:04:25 +0200
|
||||||
|
Subject: [PATCH 1/2] module: permit to declare custom module alloc/free
|
||||||
|
function
|
||||||
|
|
||||||
|
Permit to declare custom module alloc/free function that bypass the
|
||||||
|
execmem API. This works by making the alloc/free function weak
|
||||||
|
permitting an arch to declare a replacement for them.
|
||||||
|
|
||||||
|
Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
|
||||||
|
---
|
||||||
|
include/linux/moduleloader.h | 5 +++++
|
||||||
|
kernel/module/main.c | 33 ++++++++++++++++++++++++---------
|
||||||
|
2 files changed, 33 insertions(+), 9 deletions(-)
|
||||||
|
|
||||||
|
--- a/include/linux/moduleloader.h
|
||||||
|
+++ b/include/linux/moduleloader.h
|
||||||
|
@@ -122,4 +122,9 @@ void module_arch_cleanup(struct module *
|
||||||
|
/* Any cleanup before freeing mod->module_init */
|
||||||
|
void module_arch_freeing_init(struct module *mod);
|
||||||
|
|
||||||
|
+void *module_arch_mem_alloc(struct module_memory *mem,
|
||||||
|
+ enum mod_mem_type type);
|
||||||
|
+
|
||||||
|
+void module_arch_mem_free(struct module_memory *mem);
|
||||||
|
+
|
||||||
|
#endif
|
||||||
|
--- a/kernel/module/main.c
|
||||||
|
+++ b/kernel/module/main.c
|
||||||
|
@@ -1191,22 +1191,20 @@ void __weak module_arch_freeing_init(str
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
-static int module_memory_alloc(struct module *mod, enum mod_mem_type type)
|
||||||
|
+void *__weak module_arch_mem_alloc(struct module_memory *mem,
|
||||||
|
+ enum mod_mem_type type)
|
||||||
|
{
|
||||||
|
- unsigned int size = PAGE_ALIGN(mod->mem[type].size);
|
||||||
|
enum execmem_type execmem_type;
|
||||||
|
void *ptr;
|
||||||
|
|
||||||
|
- mod->mem[type].size = size;
|
||||||
|
-
|
||||||
|
if (mod_mem_type_is_data(type))
|
||||||
|
execmem_type = EXECMEM_MODULE_DATA;
|
||||||
|
else
|
||||||
|
execmem_type = EXECMEM_MODULE_TEXT;
|
||||||
|
|
||||||
|
- ptr = execmem_alloc(execmem_type, size);
|
||||||
|
+ ptr = execmem_alloc(execmem_type, mem->size);
|
||||||
|
if (!ptr)
|
||||||
|
- return -ENOMEM;
|
||||||
|
+ return ERR_PTR(-ENOMEM);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The pointer to these blocks of memory are stored on the module
|
||||||
|
@@ -1221,21 +1219,38 @@ static int module_memory_alloc(struct mo
|
||||||
|
*/
|
||||||
|
kmemleak_not_leak(ptr);
|
||||||
|
|
||||||
|
+ return ptr;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static int module_memory_alloc(struct module *mod, enum mod_mem_type type)
|
||||||
|
+{
|
||||||
|
+ unsigned int size = PAGE_ALIGN(mod->mem[type].size);
|
||||||
|
+ void *ptr;
|
||||||
|
+
|
||||||
|
+ mod->mem[type].size = size;
|
||||||
|
+
|
||||||
|
+ ptr = module_arch_mem_alloc(&mod->mem[type], type);
|
||||||
|
+ if (IS_ERR(ptr))
|
||||||
|
+ return PTR_ERR(ptr);
|
||||||
|
+
|
||||||
|
memset(ptr, 0, size);
|
||||||
|
mod->mem[type].base = ptr;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
+void __weak module_arch_mem_free(struct module_memory *mem)
|
||||||
|
+{
|
||||||
|
+ execmem_free(mem->base);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
static void module_memory_free(struct module *mod, enum mod_mem_type type,
|
||||||
|
bool unload_codetags)
|
||||||
|
{
|
||||||
|
- void *ptr = mod->mem[type].base;
|
||||||
|
-
|
||||||
|
if (!unload_codetags && mod_mem_type_is_core_data(type))
|
||||||
|
return;
|
||||||
|
|
||||||
|
- execmem_free(ptr);
|
||||||
|
+ module_arch_mem_free(&mod->mem[type]);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void free_mod_mem(struct module *mod, bool unload_codetags)
|
|
@ -1,13 +1,32 @@
|
||||||
|
From 92ecd205bc5ab96b08295bf344c794da063a6f04 Mon Sep 17 00:00:00 2001
|
||||||
From: Felix Fietkau <nbd@nbd.name>
|
From: Felix Fietkau <nbd@nbd.name>
|
||||||
Subject: mips: replace -mlong-calls with -mno-long-calls to make function calls faster in kernel modules to achieve this, try to
|
Date: Mon, 14 Apr 2025 18:05:45 +0200
|
||||||
|
Subject: [PATCH 2/2] mips: replace -mlong-calls with -mno-long-calls if
|
||||||
|
possible
|
||||||
|
|
||||||
|
This is a really old patch ported from MikroTik. It needs a an
|
||||||
|
additional patch to actually be implemented and both this and the old
|
||||||
|
one are considered HACK as they bypass normal kernel linux to make it
|
||||||
|
work.
|
||||||
|
|
||||||
|
The original message quote:
|
||||||
|
|
||||||
|
replace -mlong-calls with -mno-long-calls to make function
|
||||||
|
calls faster in kernel modules to achieve this, try to load
|
||||||
|
kernel modules to KSEG0 and if that doesn't work, use vmalloc
|
||||||
|
and fix up relocations with a jump table based on code from a
|
||||||
|
kernel patch by MikroTik.
|
||||||
|
|
||||||
|
SVN-Revision: 16772
|
||||||
|
|
||||||
lede-commit: 3b3d64743ba2a874df9d70cd19e242205b0a788c
|
lede-commit: 3b3d64743ba2a874df9d70cd19e242205b0a788c
|
||||||
Signed-off-by: Felix Fietkau <nbd@nbd.name>
|
Signed-off-by: Felix Fietkau <nbd@nbd.name>
|
||||||
|
Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
|
||||||
---
|
---
|
||||||
arch/mips/Makefile | 5 +
|
arch/mips/Makefile | 10 ++
|
||||||
arch/mips/include/asm/module.h | 5 +
|
arch/mips/include/asm/module.h | 5 +
|
||||||
arch/mips/kernel/module.c | 279 ++++++++++++++++++++++++++++++++++++++++-
|
arch/mips/kernel/module.c | 282 ++++++++++++++++++++++++++++++++-
|
||||||
3 files changed, 284 insertions(+), 5 deletions(-)
|
3 files changed, 293 insertions(+), 4 deletions(-)
|
||||||
|
|
||||||
--- a/arch/mips/Makefile
|
--- a/arch/mips/Makefile
|
||||||
+++ b/arch/mips/Makefile
|
+++ b/arch/mips/Makefile
|
||||||
|
@ -46,11 +65,18 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
|
||||||
typedef uint8_t Elf64_Byte; /* Type for a 8-bit quantity. */
|
typedef uint8_t Elf64_Byte; /* Type for a 8-bit quantity. */
|
||||||
--- a/arch/mips/kernel/module.c
|
--- a/arch/mips/kernel/module.c
|
||||||
+++ b/arch/mips/kernel/module.c
|
+++ b/arch/mips/kernel/module.c
|
||||||
@@ -32,23 +32,261 @@ struct mips_hi16 {
|
@@ -19,6 +19,7 @@
|
||||||
|
#include <linux/kernel.h>
|
||||||
|
#include <linux/spinlock.h>
|
||||||
|
#include <linux/jump_label.h>
|
||||||
|
+#include <linux/vmalloc.h>
|
||||||
|
#include <asm/jump_label.h>
|
||||||
|
|
||||||
|
struct mips_hi16 {
|
||||||
|
@@ -30,14 +31,256 @@ struct mips_hi16 {
|
||||||
static LIST_HEAD(dbe_list);
|
static LIST_HEAD(dbe_list);
|
||||||
static DEFINE_SPINLOCK(dbe_lock);
|
static DEFINE_SPINLOCK(dbe_lock);
|
||||||
|
|
||||||
-#ifdef MODULE_START
|
|
||||||
+/*
|
+/*
|
||||||
+ * Get the potential max trampolines size required of the init and
|
+ * Get the potential max trampolines size required of the init and
|
||||||
+ * non-init sections. Only used if we cannot find enough contiguous
|
+ * non-init sections. Only used if we cannot find enough contiguous
|
||||||
|
@ -125,7 +151,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
|
||||||
+ return ret;
|
+ return ret;
|
||||||
+}
|
+}
|
||||||
+
|
+
|
||||||
+#ifndef MODULE_START
|
+#ifndef MODULES_VADDR
|
||||||
+static void *alloc_phys(unsigned long size)
|
+static void *alloc_phys(unsigned long size)
|
||||||
+{
|
+{
|
||||||
+ unsigned order;
|
+ unsigned order;
|
||||||
|
@ -166,30 +192,23 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
|
||||||
+ } while (free);
|
+ } while (free);
|
||||||
+}
|
+}
|
||||||
+
|
+
|
||||||
+
|
+#ifndef MODULES_VADDR
|
||||||
void *module_alloc(unsigned long size)
|
+void *module_arch_mem_alloc(struct module_memory *mem,
|
||||||
{
|
+ enum mod_mem_type type)
|
||||||
+#ifdef MODULE_START
|
+{
|
||||||
return __vmalloc_node_range(size, 1, MODULE_START, MODULE_END,
|
|
||||||
GFP_KERNEL, PAGE_KERNEL, 0, NUMA_NO_NODE,
|
|
||||||
__builtin_return_address(0));
|
|
||||||
+#else
|
|
||||||
+ void *ptr;
|
+ void *ptr;
|
||||||
+
|
+
|
||||||
+ if (size == 0)
|
+ ptr = alloc_phys(mem->size);
|
||||||
+ return NULL;
|
|
||||||
+
|
|
||||||
+ ptr = alloc_phys(size);
|
|
||||||
+
|
+
|
||||||
+ /* If we failed to allocate physically contiguous memory,
|
+ /* If we failed to allocate physically contiguous memory,
|
||||||
+ * fall back to regular vmalloc. The module loader code will
|
+ * fall back to regular vmalloc. The module loader code will
|
||||||
+ * create jump tables to handle long jumps */
|
+ * create jump tables to handle long jumps */
|
||||||
+ if (!ptr)
|
+ if (!ptr)
|
||||||
+ return vmalloc(size);
|
+ return vmalloc(mem->size);
|
||||||
+
|
+
|
||||||
+ return ptr;
|
+ return ptr;
|
||||||
|
+}
|
||||||
+#endif
|
+#endif
|
||||||
}
|
|
||||||
+
|
+
|
||||||
+static inline bool is_phys_addr(void *ptr)
|
+static inline bool is_phys_addr(void *ptr)
|
||||||
+{
|
+{
|
||||||
|
@ -197,17 +216,19 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
|
||||||
+ return (KSEGX((unsigned long)ptr) == CKSEG0);
|
+ return (KSEGX((unsigned long)ptr) == CKSEG0);
|
||||||
+#else
|
+#else
|
||||||
+ return (KSEGX(ptr) == KSEG0);
|
+ return (KSEGX(ptr) == KSEG0);
|
||||||
#endif
|
+ #endif
|
||||||
+}
|
+}
|
||||||
+
|
+
|
||||||
|
+#ifndef MODULES_VADDR
|
||||||
+/* Free memory returned from module_alloc */
|
+/* Free memory returned from module_alloc */
|
||||||
+void module_memfree(void *module_region)
|
+void module_arch_mem_free(struct module_memory *mem)
|
||||||
+{
|
+{
|
||||||
+ if (is_phys_addr(module_region))
|
+ if (is_phys_addr(mem->base))
|
||||||
+ free_phys(module_region);
|
+ free_phys(mem->base);
|
||||||
+ else
|
+ else
|
||||||
+ vfree(module_region);
|
+ vfree(mem->base);
|
||||||
+}
|
+}
|
||||||
|
+#endif
|
||||||
+
|
+
|
||||||
+static void *__module_alloc(int size, bool phys)
|
+static void *__module_alloc(int size, bool phys)
|
||||||
+{
|
+{
|
||||||
|
@ -266,7 +287,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
|
||||||
+
|
+
|
||||||
+ return 0;
|
+ return 0;
|
||||||
+}
|
+}
|
||||||
|
+
|
||||||
static void apply_r_mips_32(u32 *location, u32 base, Elf_Addr v)
|
static void apply_r_mips_32(u32 *location, u32 base, Elf_Addr v)
|
||||||
{
|
{
|
||||||
*location = base + v;
|
*location = base + v;
|
||||||
|
@ -309,7 +330,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
|
||||||
if (v % 4) {
|
if (v % 4) {
|
||||||
pr_err("module %s: dangerous R_MIPS_26 relocation\n",
|
pr_err("module %s: dangerous R_MIPS_26 relocation\n",
|
||||||
me->name);
|
me->name);
|
||||||
@@ -56,13 +294,17 @@ static int apply_r_mips_26(struct module
|
@@ -45,13 +288,17 @@ static int apply_r_mips_26(struct module
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((v & 0xf0000000) != (((unsigned long)location + 4) & 0xf0000000)) {
|
if ((v & 0xf0000000) != (((unsigned long)location + 4) & 0xf0000000)) {
|
||||||
|
@ -331,7 +352,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -442,9 +684,36 @@ int module_finalize(const Elf_Ehdr *hdr,
|
@@ -431,9 +678,36 @@ int module_finalize(const Elf_Ehdr *hdr,
|
||||||
list_add(&me->arch.dbe_list, &dbe_list);
|
list_add(&me->arch.dbe_list, &dbe_list);
|
||||||
spin_unlock_irq(&dbe_lock);
|
spin_unlock_irq(&dbe_lock);
|
||||||
}
|
}
|
Loading…
Reference in a new issue