* + mm-execmem-arch-convert-simple-overrides-of-module_alloc-to-execmem.patch added to mm-unstable branch
@ 2023-09-18 15:51 Andrew Morton
0 siblings, 0 replies; only message in thread
From: Andrew Morton @ 2023-09-18 15:51 UTC (permalink / raw)
To: mm-commits, will, tsbogend, tglx, song, rostedt, rick.p.edgecombe,
puranjay12, palmer, naveen.n.rao, nadav.amit, mpe, mcgrof,
mark.rutland, linux, kent.overstreet, hca, dinguyen, deller,
davem, christophe.leroy, chenhuacai, catalin.marinas, bjorn, rppt,
akpm
[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1: Type: text/plain, Size: 15788 bytes --]
The patch titled
Subject: mm/execmem, arch: convert simple overrides of module_alloc to execmem
has been added to the -mm mm-unstable branch. Its filename is
mm-execmem-arch-convert-simple-overrides-of-module_alloc-to-execmem.patch
This patch will shortly appear at
https://git.kernel.org/pub/scm/linux/kernel/git/akpm/25-new.git/tree/patches/mm-execmem-arch-convert-simple-overrides-of-module_alloc-to-execmem.patch
This patch will later appear in the mm-unstable branch at
git://git.kernel.org/pub/scm/linux/kernel/git/akpm/mm
Before you just go and hit "reply", please:
a) Consider who else should be cc'ed
b) Prefer to cc a suitable mailing list as well
c) Ideally: find the original patch on the mailing list and do a
reply-to-all to that, adding suitable additional cc's
*** Remember to use Documentation/process/submit-checklist.rst when testing your code ***
The -mm tree is included into linux-next via the mm-everything
branch at git://git.kernel.org/pub/scm/linux/kernel/git/akpm/mm
and is updated there every 2-3 working days
------------------------------------------------------
From: "Mike Rapoport (IBM)" <rppt@kernel.org>
Subject: mm/execmem, arch: convert simple overrides of module_alloc to execmem
Date: Mon, 18 Sep 2023 10:29:45 +0300
Several architectures override module_alloc() only to define address range
for code allocations different than VMALLOC address space.
Provide a generic implementation in execmem that uses the parameters for
address space ranges, required alignment and page protections provided by
architectures.
The architectures must fill execmem_params structure and implement
execmem_arch_params() that returns a pointer to that structure. This way
the execmem initialization won't be called from every architecture, but
rather from a central place, namely initialization of the core memory
management.
The execmem provides execmem_text_alloc() API that wraps
__vmalloc_node_range() with the parameters defined by the architectures.
If an architecture does not implement execmem_arch_params(),
execmem_text_alloc() will fall back to module_alloc().
The name execmem_text_alloc() emphasizes that the allocated memory is for
executable code, the allocations of the associated data, like data
sections of a module will use execmem_data_alloc() interface that will be
added later.
Link: https://lkml.kernel.org/r/20230918072955.2507221-4-rppt@kernel.org
Signed-off-by: Mike Rapoport (IBM) <rppt@kernel.org>
Cc: Björn Töpel <bjorn@kernel.org>
Cc: Catalin Marinas <catalin.marinas@arm.com>
Cc: Christophe Leroy <christophe.leroy@csgroup.eu>
Cc: David S. Miller <davem@davemloft.net>
Cc: Dinh Nguyen <dinguyen@kernel.org>
Cc: Heiko Carstens <hca@linux.ibm.com>
Cc: Helge Deller <deller@gmx.de>
Cc: Huacai Chen <chenhuacai@kernel.org>
Cc: Kent Overstreet <kent.overstreet@linux.dev>
Cc: Luis Chamberlain <mcgrof@kernel.org>
Cc: Mark Rutland <mark.rutland@arm.com>
Cc: Michael Ellerman <mpe@ellerman.id.au>
Cc: Nadav Amit <nadav.amit@gmail.com>
Cc: "Naveen N. Rao" <naveen.n.rao@linux.ibm.com>
Cc: Palmer Dabbelt <palmer@dabbelt.com>
Cc: Puranjay Mohan <puranjay12@gmail.com>
Cc: Rick Edgecombe <rick.p.edgecombe@intel.com>
Cc: Russell King (Oracle) <linux@armlinux.org.uk>
Cc: Song Liu <song@kernel.org>
Cc: Steven Rostedt (Google) <rostedt@goodmis.org>
Cc: Thomas Bogendoerfer <tsbogend@alpha.franken.de>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: Will Deacon <will@kernel.org>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
---
arch/loongarch/kernel/module.c | 18 +++++++-
arch/mips/kernel/module.c | 19 +++++++-
arch/nios2/kernel/module.c | 19 ++++++--
arch/parisc/kernel/module.c | 23 +++++++---
arch/riscv/kernel/module.c | 20 +++++++--
arch/sparc/kernel/module.c | 42 ++++++++-----------
include/linux/execmem.h | 44 ++++++++++++++++++++
mm/execmem.c | 66 +++++++++++++++++++++++++++++--
mm/mm_init.c | 2
9 files changed, 202 insertions(+), 51 deletions(-)
--- a/arch/loongarch/kernel/module.c~mm-execmem-arch-convert-simple-overrides-of-module_alloc-to-execmem
+++ a/arch/loongarch/kernel/module.c
@@ -18,6 +18,7 @@
#include <linux/ftrace.h>
#include <linux/string.h>
#include <linux/kernel.h>
+#include <linux/execmem.h>
#include <asm/alternative.h>
#include <asm/inst.h>
@@ -469,10 +470,21 @@ int apply_relocate_add(Elf_Shdr *sechdrs
return 0;
}
-void *module_alloc(unsigned long size)
+static struct execmem_params execmem_params __ro_after_init = {
+ .ranges = {
+ [EXECMEM_DEFAULT] = {
+ .pgprot = PAGE_KERNEL,
+ .alignment = 1,
+ },
+ },
+};
+
+struct execmem_params __init *execmem_arch_params(void)
{
- return __vmalloc_node_range(size, 1, MODULES_VADDR, MODULES_END,
- GFP_KERNEL, PAGE_KERNEL, 0, NUMA_NO_NODE, __builtin_return_address(0));
+ execmem_params.ranges[EXECMEM_DEFAULT].start = MODULES_VADDR;
+ execmem_params.ranges[EXECMEM_DEFAULT].end = MODULES_END;
+
+ return &execmem_params;
}
static void module_init_ftrace_plt(const Elf_Ehdr *hdr,
--- a/arch/mips/kernel/module.c~mm-execmem-arch-convert-simple-overrides-of-module_alloc-to-execmem
+++ a/arch/mips/kernel/module.c
@@ -20,6 +20,7 @@
#include <linux/kernel.h>
#include <linux/spinlock.h>
#include <linux/jump_label.h>
+#include <linux/execmem.h>
extern void jump_label_apply_nops(struct module *mod);
@@ -33,11 +34,21 @@ static LIST_HEAD(dbe_list);
static DEFINE_SPINLOCK(dbe_lock);
#ifdef MODULE_START
-void *module_alloc(unsigned long size)
+static struct execmem_params execmem_params __ro_after_init = {
+ .ranges = {
+ [EXECMEM_DEFAULT] = {
+ .start = MODULE_START,
+ .end = MODULE_END,
+ .alignment = 1,
+ },
+ },
+};
+
+struct execmem_params __init *execmem_arch_params(void)
{
- return __vmalloc_node_range(size, 1, MODULE_START, MODULE_END,
- GFP_KERNEL, PAGE_KERNEL, 0, NUMA_NO_NODE,
- __builtin_return_address(0));
+ execmem_params.ranges[EXECMEM_DEFAULT].pgprot = PAGE_KERNEL;
+
+ return &execmem_params;
}
#endif
--- a/arch/nios2/kernel/module.c~mm-execmem-arch-convert-simple-overrides-of-module_alloc-to-execmem
+++ a/arch/nios2/kernel/module.c
@@ -18,15 +18,24 @@
#include <linux/fs.h>
#include <linux/string.h>
#include <linux/kernel.h>
+#include <linux/execmem.h>
#include <asm/cacheflush.h>
-void *module_alloc(unsigned long size)
+static struct execmem_params execmem_params __ro_after_init = {
+ .ranges = {
+ [EXECMEM_DEFAULT] = {
+ .start = MODULES_VADDR,
+ .end = MODULES_END,
+ .pgprot = PAGE_KERNEL_EXEC,
+ .alignment = 1,
+ },
+ },
+};
+
+struct execmem_params __init *execmem_arch_params(void)
{
- return __vmalloc_node_range(size, 1, MODULES_VADDR, MODULES_END,
- GFP_KERNEL, PAGE_KERNEL_EXEC,
- VM_FLUSH_RESET_PERMS, NUMA_NO_NODE,
- __builtin_return_address(0));
+ return &execmem_params;
}
int apply_relocate_add(Elf32_Shdr *sechdrs, const char *strtab,
--- a/arch/parisc/kernel/module.c~mm-execmem-arch-convert-simple-overrides-of-module_alloc-to-execmem
+++ a/arch/parisc/kernel/module.c
@@ -49,6 +49,7 @@
#include <linux/bug.h>
#include <linux/mm.h>
#include <linux/slab.h>
+#include <linux/execmem.h>
#include <asm/unwind.h>
#include <asm/sections.h>
@@ -173,15 +174,21 @@ static inline int reassemble_22(int as22
((as22 & 0x0003ff) << 3));
}
-void *module_alloc(unsigned long size)
+static struct execmem_params execmem_params __ro_after_init = {
+ .ranges = {
+ [EXECMEM_DEFAULT] = {
+ .pgprot = PAGE_KERNEL_RWX,
+ .alignment = 1,
+ },
+ },
+};
+
+struct execmem_params __init *execmem_arch_params(void)
{
- /* using RWX means less protection for modules, but it's
- * easier than trying to map the text, data, init_text and
- * init_data correctly */
- return __vmalloc_node_range(size, 1, VMALLOC_START, VMALLOC_END,
- GFP_KERNEL,
- PAGE_KERNEL_RWX, 0, NUMA_NO_NODE,
- __builtin_return_address(0));
+ execmem_params.ranges[EXECMEM_DEFAULT].start = VMALLOC_START;
+ execmem_params.ranges[EXECMEM_DEFAULT].end = VMALLOC_END;
+
+ return &execmem_params;
}
#ifndef CONFIG_64BIT
--- a/arch/riscv/kernel/module.c~mm-execmem-arch-convert-simple-overrides-of-module_alloc-to-execmem
+++ a/arch/riscv/kernel/module.c
@@ -11,6 +11,7 @@
#include <linux/vmalloc.h>
#include <linux/sizes.h>
#include <linux/pgtable.h>
+#include <linux/execmem.h>
#include <asm/alternative.h>
#include <asm/sections.h>
@@ -436,12 +437,21 @@ int apply_relocate_add(Elf_Shdr *sechdrs
}
#if defined(CONFIG_MMU) && defined(CONFIG_64BIT)
-void *module_alloc(unsigned long size)
+static struct execmem_params execmem_params __ro_after_init = {
+ .ranges = {
+ [EXECMEM_DEFAULT] = {
+ .pgprot = PAGE_KERNEL,
+ .alignment = 1,
+ },
+ },
+};
+
+struct execmem_params __init *execmem_arch_params(void)
{
- return __vmalloc_node_range(size, 1, MODULES_VADDR,
- MODULES_END, GFP_KERNEL,
- PAGE_KERNEL, 0, NUMA_NO_NODE,
- __builtin_return_address(0));
+ execmem_params.ranges[EXECMEM_DEFAULT].start = MODULES_VADDR;
+ execmem_params.ranges[EXECMEM_DEFAULT].end = MODULES_END;
+
+ return &execmem_params;
}
#endif
--- a/arch/sparc/kernel/module.c~mm-execmem-arch-convert-simple-overrides-of-module_alloc-to-execmem
+++ a/arch/sparc/kernel/module.c
@@ -14,6 +14,10 @@
#include <linux/string.h>
#include <linux/ctype.h>
#include <linux/mm.h>
+#include <linux/execmem.h>
+#ifdef CONFIG_SPARC64
+#include <linux/jump_label.h>
+#endif
#include <asm/processor.h>
#include <asm/spitfire.h>
@@ -21,34 +25,26 @@
#include "entry.h"
+static struct execmem_params execmem_params __ro_after_init = {
+ .ranges = {
+ [EXECMEM_DEFAULT] = {
#ifdef CONFIG_SPARC64
-
-#include <linux/jump_label.h>
-
-static void *module_map(unsigned long size)
-{
- if (PAGE_ALIGN(size) > MODULES_LEN)
- return NULL;
- return __vmalloc_node_range(size, 1, MODULES_VADDR, MODULES_END,
- GFP_KERNEL, PAGE_KERNEL, 0, NUMA_NO_NODE,
- __builtin_return_address(0));
-}
+ .start = MODULES_VADDR,
+ .end = MODULES_END,
#else
-static void *module_map(unsigned long size)
-{
- return vmalloc(size);
-}
-#endif /* CONFIG_SPARC64 */
+ .start = VMALLOC_START,
+ .end = VMALLOC_END,
+#endif
+ .alignment = 1,
+ },
+ },
+};
-void *module_alloc(unsigned long size)
+struct execmem_params __init *execmem_arch_params(void)
{
- void *ret;
-
- ret = module_map(size);
- if (ret)
- memset(ret, 0, size);
+ execmem_params.ranges[EXECMEM_DEFAULT].pgprot = PAGE_KERNEL;
- return ret;
+ return &execmem_params;
}
/* Make generic code ignore STT_REGISTER dummy undefined symbols. */
--- a/include/linux/execmem.h~mm-execmem-arch-convert-simple-overrides-of-module_alloc-to-execmem
+++ a/include/linux/execmem.h
@@ -33,6 +33,44 @@ enum execmem_type {
};
/**
+ * struct execmem_range - definition of a memory range suitable for code and
+ * related data allocations
+ * @start: address space start
+ * @end: address space end (inclusive)
+ * @pgprot: permissions for memory in this address space
+ * @alignment: alignment required for text allocations
+ */
+struct execmem_range {
+ unsigned long start;
+ unsigned long end;
+ pgprot_t pgprot;
+ unsigned int alignment;
+};
+
+/**
+ * struct execmem_params - architecture parameters for code allocations
+ * @ranges: array of ranges defining architecture specific parameters for
+ * each type of executable memory allocations
+ */
+struct execmem_params {
+ struct execmem_range ranges[EXECMEM_TYPE_MAX];
+};
+
+/**
+ * execmem_arch_params - supply parameters for allocations of executable memory
+ *
+ * A hook for architectures to define parameters for allocations of
+ * executable memory described by struct execmem_params
+ *
+ * For architectures that do not implement this method a default set of
+ * parameters will be used
+ *
+ * Return: a structure defining architecture parameters and restrictions
+ * for allocations of executable memory
+ */
+struct execmem_params *execmem_arch_params(void);
+
+/**
* execmem_text_alloc - allocate executable memory
* @type: type of the allocation
* @size: how many bytes of memory are required
@@ -53,4 +91,10 @@ void *execmem_text_alloc(enum execmem_ty
*/
void execmem_free(void *ptr);
+#ifdef CONFIG_EXECMEM
+void execmem_init(void);
+#else
+static inline void execmem_init(void) {}
+#endif
+
#endif /* _LINUX_EXECMEM_ALLOC_H */
--- a/mm/execmem.c~mm-execmem-arch-convert-simple-overrides-of-module_alloc-to-execmem
+++ a/mm/execmem.c
@@ -5,14 +5,26 @@
#include <linux/execmem.h>
#include <linux/moduleloader.h>
-static void *execmem_alloc(size_t size)
+static struct execmem_params execmem_params;
+
+static void *execmem_alloc(size_t size, struct execmem_range *range)
{
- return module_alloc(size);
+ unsigned long start = range->start;
+ unsigned long end = range->end;
+ unsigned int align = range->alignment;
+ pgprot_t pgprot = range->pgprot;
+
+ return __vmalloc_node_range(size, align, start, end,
+ GFP_KERNEL, pgprot, VM_FLUSH_RESET_PERMS,
+ NUMA_NO_NODE, __builtin_return_address(0));
}
void *execmem_text_alloc(enum execmem_type type, size_t size)
{
- return execmem_alloc(size);
+ if (!execmem_params.ranges[type].start)
+ return module_alloc(size);
+
+ return execmem_alloc(size, &execmem_params.ranges[type]);
}
void execmem_free(void *ptr)
@@ -24,3 +36,51 @@ void execmem_free(void *ptr)
WARN_ON(in_interrupt());
vfree(ptr);
}
+
+struct execmem_params * __weak execmem_arch_params(void)
+{
+ return NULL;
+}
+
+static bool execmem_validate_params(struct execmem_params *p)
+{
+ struct execmem_range *r = &p->ranges[EXECMEM_DEFAULT];
+
+ if (!r->alignment || !r->start || !r->end || !pgprot_val(r->pgprot)) {
+ pr_crit("Invalid parameters for execmem allocator, module loading will fail");
+ return false;
+ }
+
+ return true;
+}
+
+static void execmem_init_missing(struct execmem_params *p)
+{
+ struct execmem_range *default_range = &p->ranges[EXECMEM_DEFAULT];
+
+ for (int i = EXECMEM_DEFAULT + 1; i < EXECMEM_TYPE_MAX; i++) {
+ struct execmem_range *r = &p->ranges[i];
+
+ if (!r->start) {
+ r->pgprot = default_range->pgprot;
+ r->alignment = default_range->alignment;
+ r->start = default_range->start;
+ r->end = default_range->end;
+ }
+ }
+}
+
+void __init execmem_init(void)
+{
+ struct execmem_params *p = execmem_arch_params();
+
+ if (!p)
+ return;
+
+ if (!execmem_validate_params(p))
+ return;
+
+ execmem_init_missing(p);
+
+ execmem_params = *p;
+}
--- a/mm/mm_init.c~mm-execmem-arch-convert-simple-overrides-of-module_alloc-to-execmem
+++ a/mm/mm_init.c
@@ -26,6 +26,7 @@
#include <linux/pgtable.h>
#include <linux/swap.h>
#include <linux/cma.h>
+#include <linux/execmem.h>
#include "internal.h"
#include "slab.h"
#include "shuffle.h"
@@ -2795,4 +2796,5 @@ void __init mm_core_init(void)
pti_init();
kmsan_init_runtime();
mm_cache_init();
+ execmem_init();
}
_
Patches currently in -mm which might be from rppt@kernel.org are
nios2-define-virtual-address-space-for-modules.patch
mm-introduce-execmem_text_alloc-and-execmem_free.patch
mm-execmem-arch-convert-simple-overrides-of-module_alloc-to-execmem.patch
mm-execmem-arch-convert-remaining-overrides-of-module_alloc-to-execmem.patch
modules-execmem-drop-module_alloc.patch
mm-execmem-introduce-execmem_data_alloc.patch
arm64-execmem-extend-execmem_params-for-generated-code-allocations.patch
riscv-extend-execmem_params-for-generated-code-allocations.patch
powerpc-extend-execmem_params-for-kprobes-allocations.patch
arch-make-execmem-setup-available-regardless-of-config_modules.patch
x86-ftrace-enable-dynamic-ftrace-without-config_modules.patch
kprobes-remove-dependency-on-config_modules.patch
bpf-remove-config_bpf_jit-dependency-on-config_modules-of.patch
^ permalink raw reply [flat|nested] only message in thread
only message in thread, other threads:[~2023-09-18 16:10 UTC | newest]
Thread overview: (only message) (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2023-09-18 15:51 + mm-execmem-arch-convert-simple-overrides-of-module_alloc-to-execmem.patch added to mm-unstable branch Andrew Morton
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.