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: a9c0f28951
("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 <yangshiji66@outlook.com>
Tested-by: Tony Ambardar <itugrok@yahoo.com>
Link: https://github.com/openwrt/openwrt/pull/18721
Signed-off-by: Robert Marko <robimarko@gmail.com>
This commit is contained in:
parent
2d6f0275f8
commit
be7ab6893a
3 changed files with 85 additions and 117 deletions
|
@ -0,0 +1,62 @@
|
||||||
|
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];
|
|
@ -1,99 +0,0 @@
|
||||||
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,4 +1,3 @@
|
||||||
From 92ecd205bc5ab96b08295bf344c794da063a6f04 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Felix Fietkau <nbd@nbd.name>
|
From: Felix Fietkau <nbd@nbd.name>
|
||||||
Date: Mon, 14 Apr 2025 18:05:45 +0200
|
Date: Mon, 14 Apr 2025 18:05:45 +0200
|
||||||
Subject: [PATCH 2/2] mips: replace -mlong-calls with -mno-long-calls if
|
Subject: [PATCH 2/2] mips: replace -mlong-calls with -mno-long-calls if
|
||||||
|
@ -25,8 +24,8 @@ Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
|
||||||
---
|
---
|
||||||
arch/mips/Makefile | 10 ++
|
arch/mips/Makefile | 10 ++
|
||||||
arch/mips/include/asm/module.h | 5 +
|
arch/mips/include/asm/module.h | 5 +
|
||||||
arch/mips/kernel/module.c | 282 ++++++++++++++++++++++++++++++++-
|
arch/mips/kernel/module.c | 281 ++++++++++++++++++++++++++++++++-
|
||||||
3 files changed, 293 insertions(+), 4 deletions(-)
|
3 files changed, 292 insertions(+), 4 deletions(-)
|
||||||
|
|
||||||
--- a/arch/mips/Makefile
|
--- a/arch/mips/Makefile
|
||||||
+++ b/arch/mips/Makefile
|
+++ b/arch/mips/Makefile
|
||||||
|
@ -65,7 +64,15 @@ Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
|
||||||
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
|
||||||
@@ -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/kernel.h>
|
||||||
#include <linux/spinlock.h>
|
#include <linux/spinlock.h>
|
||||||
#include <linux/jump_label.h>
|
#include <linux/jump_label.h>
|
||||||
|
@ -73,7 +80,7 @@ Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
|
||||||
#include <asm/jump_label.h>
|
#include <asm/jump_label.h>
|
||||||
|
|
||||||
struct mips_hi16 {
|
struct mips_hi16 {
|
||||||
@@ -30,14 +31,256 @@ struct mips_hi16 {
|
@@ -30,14 +32,254 @@ struct mips_hi16 {
|
||||||
static LIST_HEAD(dbe_list);
|
static LIST_HEAD(dbe_list);
|
||||||
static DEFINE_SPINLOCK(dbe_lock);
|
static DEFINE_SPINLOCK(dbe_lock);
|
||||||
|
|
||||||
|
@ -177,7 +184,6 @@ Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
|
||||||
+
|
+
|
||||||
+ return page_address(page);
|
+ return page_address(page);
|
||||||
+}
|
+}
|
||||||
+#endif
|
|
||||||
+
|
+
|
||||||
+static void free_phys(void *ptr)
|
+static void free_phys(void *ptr)
|
||||||
+{
|
+{
|
||||||
|
@ -192,19 +198,18 @@ Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
|
||||||
+ } while (free);
|
+ } while (free);
|
||||||
+}
|
+}
|
||||||
+
|
+
|
||||||
+#ifndef MODULES_VADDR
|
+void *arch_execmem_alloc(enum execmem_type type,
|
||||||
+void *module_arch_mem_alloc(struct module_memory *mem,
|
+ size_t size)
|
||||||
+ enum mod_mem_type type)
|
|
||||||
+{
|
+{
|
||||||
+ void *ptr;
|
+ void *ptr;
|
||||||
+
|
+
|
||||||
+ ptr = alloc_phys(mem->size);
|
+ 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(mem->size);
|
+ return vmalloc(size);
|
||||||
+
|
+
|
||||||
+ return ptr;
|
+ return ptr;
|
||||||
+}
|
+}
|
||||||
|
@ -216,17 +221,17 @@ Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
|
||||||
+ 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
|
+#ifndef MODULES_VADDR
|
||||||
+/* Free memory returned from module_alloc */
|
+/* 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))
|
+ if (is_phys_addr(ptr))
|
||||||
+ free_phys(mem->base);
|
+ free_phys(ptr);
|
||||||
+ else
|
+ else
|
||||||
+ vfree(mem->base);
|
+ vfree(ptr);
|
||||||
+}
|
+}
|
||||||
+#endif
|
+#endif
|
||||||
+
|
+
|
||||||
|
@ -330,7 +335,7 @@ Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
|
||||||
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);
|
||||||
@@ -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)) {
|
if ((v & 0xf0000000) != (((unsigned long)location + 4) & 0xf0000000)) {
|
||||||
|
@ -352,7 +357,7 @@ Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
|
||||||
|
|
||||||
return 0;
|
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);
|
list_add(&me->arch.dbe_list, &dbe_list);
|
||||||
spin_unlock_irq(&dbe_lock);
|
spin_unlock_irq(&dbe_lock);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue