From be7ab6893a23631415e0462ce677b05471c61e62 Mon Sep 17 00:00:00 2001 From: Shiji Yang Date: Thu, 1 May 2025 10:18:52 +0800 Subject: [PATCH] generic: fix MIPS -mno-long-calls patchset for 6.12 kernel It seems that we need to override all execmem alloc/free callbacks, not just for module. This is the default patch behavior in the 6.6 kernel. Fix the warning when the module is loaded: root@OpenWrt:~# insmod mtd-rw i_want_a_brick=1 [ 1404.954813] mtd-rw: mtd0: setting writeable flag [ 1404.959643] mtd-rw: mtd5: setting writeable flag [ 1404.966396] ------------[ cut here ]------------ [ 1404.971119] WARNING: CPU: 0 PID: 8 at mm/vmalloc.c:3361 vfree+0x1ac/0x2c4 [ 1404.978146] Trying to vfree() nonexistent vm area (74cc6c73) [ 1404.983901] Modules linked in: mtd_rw(O) ath9k(O) ath9k_common(O)... [ 1405.043696] CPU: 0 UID: 0 PID: 8 Comm: kworker/0:1 Tainted: G W O 6.12.25 #0 [ 1405.052118] Tainted: [W]=WARN, [O]=OOT_MODULE [ 1405.056536] Hardware name: [ 1405.061222] Workqueue: events do_free_init [ 1405.065408] Stack : 807865d8 80850000 81823f80 81857df8 00000000 00000d21 81823fd0 800ca130 [ 1405.073924] 81839e48 807865d8 808d20bf 807865d8 81857d1c 00000001 81857ce8 4951640f [ 1405.082434] 00000000 00000000 807865d8 81857bf8 ffffefff 00000000 ffffffea 00000b5d [ 1405.090944] 81857c04 00000b5d 808537b0 ffffffff 00000001 00000000 807865d8 81857df8 [ 1405.099453] 00000000 00000d21 81823fd0 8085119c 00000018 803f4828 00000000 80a00000 [ 1405.107963] ... [ 1405.110454] Call Trace: [ 1405.112935] [<80066910>] show_stack+0x28/0xf0 [ 1405.117392] [<8069f340>] dump_stack_lvl+0x48/0x7c [ 1405.122186] [<80084ab8>] __warn+0x9c/0x118 [ 1405.126357] [<80084bc0>] warn_slowpath_fmt+0x8c/0xac [ 1405.131399] [<801f02ec>] vfree+0x1ac/0x2c4 [ 1405.135570] [<800dde54>] do_free_init+0x50/0x84 [ 1405.140172] [<8009f4a0>] process_one_work+0x1b0/0x3dc [ 1405.145312] [<800a022c>] worker_thread+0x308/0x478 [ 1405.150178] [<800a81c0>] kthread+0xf4/0x11c [ 1405.154455] [<80061b58>] ret_from_kernel_thread+0x14/0x1c [ 1405.159938] [ 1405.161772] ---[ end trace 0000000000000000 ]--- Fixes: a9c0f28951fd ("generic: 6.12: move MIPS reloc patch from pending to hack and rework") Ref: https://lore.kernel.org/all/20240505160628.2323363-1-rppt@kernel.org/ Signed-off-by: Shiji Yang Tested-by: Tony Ambardar Link: https://github.com/openwrt/openwrt/pull/18721 Signed-off-by: Robert Marko --- ...lare-custom-execmem-alloc-free-funct.patch | 62 ++++++++++++ ...-declare-custom-module-alloc-free-fu.patch | 99 ------------------- ...ng-calls-with-mno-long-calls-if-poss.patch | 41 ++++---- 3 files changed, 85 insertions(+), 117 deletions(-) create mode 100644 target/linux/generic/hack-6.12/301-01-mm-permit-to-declare-custom-execmem-alloc-free-funct.patch delete mode 100644 target/linux/generic/hack-6.12/301-01-module-permit-to-declare-custom-module-alloc-free-fu.patch diff --git a/target/linux/generic/hack-6.12/301-01-mm-permit-to-declare-custom-execmem-alloc-free-funct.patch b/target/linux/generic/hack-6.12/301-01-mm-permit-to-declare-custom-execmem-alloc-free-funct.patch new file mode 100644 index 00000000000..3128ed3a68f --- /dev/null +++ b/target/linux/generic/hack-6.12/301-01-mm-permit-to-declare-custom-execmem-alloc-free-funct.patch @@ -0,0 +1,62 @@ +From: Christian Marangi +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 +Co-authored-by: Shiji Yang +--- + 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]; diff --git a/target/linux/generic/hack-6.12/301-01-module-permit-to-declare-custom-module-alloc-free-fu.patch b/target/linux/generic/hack-6.12/301-01-module-permit-to-declare-custom-module-alloc-free-fu.patch deleted file mode 100644 index 611c203cbd8..00000000000 --- a/target/linux/generic/hack-6.12/301-01-module-permit-to-declare-custom-module-alloc-free-fu.patch +++ /dev/null @@ -1,99 +0,0 @@ -From fec97dbb51697148ba881611f2b780a8d8a15885 Mon Sep 17 00:00:00 2001 -From: Christian Marangi -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 ---- - 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) diff --git a/target/linux/generic/hack-6.12/301-02-mips-replace-mlong-calls-with-mno-long-calls-if-poss.patch b/target/linux/generic/hack-6.12/301-02-mips-replace-mlong-calls-with-mno-long-calls-if-poss.patch index 58a03148246..eaf4de1e896 100644 --- a/target/linux/generic/hack-6.12/301-02-mips-replace-mlong-calls-with-mno-long-calls-if-poss.patch +++ b/target/linux/generic/hack-6.12/301-02-mips-replace-mlong-calls-with-mno-long-calls-if-poss.patch @@ -1,4 +1,3 @@ -From 92ecd205bc5ab96b08295bf344c794da063a6f04 Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Mon, 14 Apr 2025 18:05:45 +0200 Subject: [PATCH 2/2] mips: replace -mlong-calls with -mno-long-calls if @@ -25,8 +24,8 @@ Signed-off-by: Christian Marangi --- 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 @@ -65,7 +64,15 @@ Signed-off-by: Christian Marangi 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 + #include + #include + #include +@@ -19,6 +20,7 @@ #include #include #include @@ -73,7 +80,7 @@ Signed-off-by: Christian Marangi #include 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); @@ -177,7 +184,6 @@ Signed-off-by: Christian Marangi + + return page_address(page); +} -+#endif + +static void free_phys(void *ptr) +{ @@ -192,19 +198,18 @@ Signed-off-by: Christian Marangi + } 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; +} @@ -216,17 +221,17 @@ Signed-off-by: Christian Marangi + 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 + @@ -330,7 +335,7 @@ Signed-off-by: Christian Marangi 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)) { @@ -352,7 +357,7 @@ Signed-off-by: Christian Marangi 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); } -- 2.47.2