--- /dev/null
+From: Christian Marangi <ansuelsmth@gmail.com>
+Date: Mon, 14 Apr 2025 18:04:25 +0200
+Subject: [PATCH 1/2] mm: permit to declare custom execmem alloc/free function
+
+Permit to declare custom execmem 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>
+Co-authored-by: Shiji Yang <yangshiji66@outlook.com>
+---
+ include/linux/moduleloader.h | 4 ++++
+ mm/execmem.c | 14 ++++++++++++--
+ 2 files changed, 16 insertions(+), 2 deletions(-)
+
+--- a/include/linux/moduleloader.h
++++ b/include/linux/moduleloader.h
+@@ -122,4 +122,8 @@ void module_arch_cleanup(struct module *
+ /* Any cleanup before freeing mod->module_init */
+ void module_arch_freeing_init(struct module *mod);
+
++enum execmem_type;
++void *arch_execmem_alloc(enum execmem_type type, size_t size);
++void arch_execmem_free(void *ptr);
++
+ #endif
+--- a/mm/execmem.c
++++ b/mm/execmem.c
+@@ -52,14 +52,19 @@ static void *__execmem_alloc(struct exec
+ return kasan_reset_tag(p);
+ }
+
+-void *execmem_alloc(enum execmem_type type, size_t size)
++void *__weak arch_execmem_alloc(enum execmem_type type, size_t size)
+ {
+ struct execmem_range *range = &execmem_info->ranges[type];
+
+ return __execmem_alloc(range, size);
+ }
+
+-void execmem_free(void *ptr)
++void *execmem_alloc(enum execmem_type type, size_t size)
++{
++ return arch_execmem_alloc(type, size);
++}
++
++void __weak arch_execmem_free(void *ptr)
+ {
+ /*
+ * This memory may be RO, and freeing RO memory in an interrupt is not
+@@ -69,6 +74,11 @@ void execmem_free(void *ptr)
+ vfree(ptr);
+ }
+
++void execmem_free(void *ptr)
++{
++ arch_execmem_free(ptr);
++}
++
+ static bool execmem_validate(struct execmem_info *info)
+ {
+ struct execmem_range *r = &info->ranges[EXECMEM_DEFAULT];
+++ /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>
Date: Mon, 14 Apr 2025 18:05:45 +0200
Subject: [PATCH 2/2] mips: replace -mlong-calls with -mno-long-calls if
---
arch/mips/Makefile | 10 ++
arch/mips/include/asm/module.h | 5 +
- arch/mips/kernel/module.c | 282 ++++++++++++++++++++++++++++++++-
- 3 files changed, 293 insertions(+), 4 deletions(-)
+ arch/mips/kernel/module.c | 281 ++++++++++++++++++++++++++++++++-
+ 3 files changed, 292 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
-@@ -19,6 +19,7 @@
+@@ -8,6 +8,7 @@
+
+ #undef DEBUG
+
++#include <linux/execmem.h>
+ #include <linux/extable.h>
+ #include <linux/moduleloader.h>
+ #include <linux/elf.h>
+@@ -19,6 +20,7 @@
#include <linux/kernel.h>
#include <linux/spinlock.h>
#include <linux/jump_label.h>
#include <asm/jump_label.h>
struct mips_hi16 {
-@@ -30,14 +31,256 @@ struct mips_hi16 {
+@@ -30,14 +32,254 @@ struct mips_hi16 {
static LIST_HEAD(dbe_list);
static DEFINE_SPINLOCK(dbe_lock);
+
+ return page_address(page);
+}
-+#endif
+
+static void free_phys(void *ptr)
+{
+ } while (free);
+}
+
-+#ifndef MODULES_VADDR
-+void *module_arch_mem_alloc(struct module_memory *mem,
-+ enum mod_mem_type type)
++void *arch_execmem_alloc(enum execmem_type type,
++ size_t size)
+{
+ void *ptr;
+
-+ ptr = alloc_phys(mem->size);
++ ptr = alloc_phys(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(mem->size);
++ return vmalloc(size);
+
+ return 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_arch_mem_free(struct module_memory *mem)
++void arch_execmem_free(void *ptr)
+{
-+ if (is_phys_addr(mem->base))
-+ free_phys(mem->base);
++ if (is_phys_addr(ptr))
++ free_phys(ptr);
+ else
-+ vfree(mem->base);
++ vfree(ptr);
+}
+#endif
+
if (v % 4) {
pr_err("module %s: dangerous R_MIPS_26 relocation\n",
me->name);
-@@ -45,13 +288,17 @@ static int apply_r_mips_26(struct module
+@@ -45,13 +287,17 @@ static int apply_r_mips_26(struct module
}
if ((v & 0xf0000000) != (((unsigned long)location + 4) & 0xf0000000)) {
return 0;
}
-@@ -431,9 +678,36 @@ int module_finalize(const Elf_Ehdr *hdr,
+@@ -431,9 +677,36 @@ int module_finalize(const Elf_Ehdr *hdr,
list_add(&me->arch.dbe_list, &dbe_list);
spin_unlock_irq(&dbe_lock);
}