--- /dev/null
+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)
+From 92ecd205bc5ab96b08295bf344c794da063a6f04 Mon Sep 17 00:00:00 2001
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
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/kernel/module.c | 279 ++++++++++++++++++++++++++++++++++++++++-
- 3 files changed, 284 insertions(+), 5 deletions(-)
+ arch/mips/kernel/module.c | 282 ++++++++++++++++++++++++++++++++-
+ 3 files changed, 293 insertions(+), 4 deletions(-)
--- a/arch/mips/Makefile
+++ b/arch/mips/Makefile
typedef uint8_t Elf64_Byte; /* Type for a 8-bit quantity. */
--- a/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 DEFINE_SPINLOCK(dbe_lock);
--#ifdef MODULE_START
+/*
+ * Get the potential max trampolines size required of the init and
+ * non-init sections. Only used if we cannot find enough contiguous
+ return ret;
+}
+
-+#ifndef MODULE_START
++#ifndef MODULES_VADDR
+static void *alloc_phys(unsigned long size)
+{
+ unsigned order;
+ } while (free);
+}
+
-+
- void *module_alloc(unsigned long size)
- {
-+#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
++#ifndef MODULES_VADDR
++void *module_arch_mem_alloc(struct module_memory *mem,
++ enum mod_mem_type type)
++{
+ void *ptr;
+
-+ if (size == 0)
-+ return NULL;
-+
-+ ptr = alloc_phys(size);
++ ptr = alloc_phys(mem->size);
+
+ /* If we failed to allocate physically contiguous memory,
+ * fall back to regular vmalloc. The module loader code will
+ * create jump tables to handle long jumps */
+ if (!ptr)
-+ return vmalloc(size);
++ return vmalloc(mem->size);
+
+ return ptr;
++}
+#endif
- }
+
+static inline bool is_phys_addr(void *ptr)
+{
+ return (KSEGX((unsigned long)ptr) == CKSEG0);
+#else
+ return (KSEGX(ptr) == KSEG0);
- #endif
++ #endif
+}
+
++#ifndef MODULES_VADDR
+/* 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))
-+ free_phys(module_region);
++ if (is_phys_addr(mem->base))
++ free_phys(mem->base);
+ else
-+ vfree(module_region);
++ vfree(mem->base);
+}
++#endif
+
+static void *__module_alloc(int size, bool phys)
+{
+
+ return 0;
+}
-
++
static void apply_r_mips_32(u32 *location, u32 base, Elf_Addr v)
{
*location = base + v;
if (v % 4) {
pr_err("module %s: dangerous R_MIPS_26 relocation\n",
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)) {
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);
spin_unlock_irq(&dbe_lock);
}