Commit 12af2b83 authored by Mike Rapoport (IBM)'s avatar Mike Rapoport (IBM) Committed by Luis Chamberlain
Browse files

mm: introduce execmem_alloc() and execmem_free()



module_alloc() is used everywhere as a mean to allocate memory for code.

Beside being semantically wrong, this unnecessarily ties all subsystems
that need to allocate code, such as ftrace, kprobes and BPF to modules and
puts the burden of code allocation to the modules code.

Several architectures override module_alloc() because of various
constraints where the executable memory can be located and this causes
additional obstacles for improvements of code allocation.

Start splitting code allocation from modules by introducing execmem_alloc()
and execmem_free() APIs.

Initially, execmem_alloc() is a wrapper for module_alloc() and
execmem_free() is a replacement of module_memfree() to allow updating all
call sites to use the new APIs.

Since architectures define different restrictions on placement,
permissions, alignment and other parameters for memory that can be used by
different subsystems that allocate executable memory, execmem_alloc() takes
a type argument, that will be used to identify the calling subsystem and to
allow architectures define parameters for ranges suitable for that
subsystem.

No functional changes.

Signed-off-by: default avatarMike Rapoport (IBM) <rppt@kernel.org>
Acked-by: default avatarMasami Hiramatsu (Google) <mhiramat@kernel.org>
Acked-by: default avatarSong Liu <song@kernel.org>
Acked-by: default avatarSteven Rostedt (Google) <rostedt@goodmis.org>
Signed-off-by: default avatarLuis Chamberlain <mcgrof@kernel.org>
parent bc6b94d3
Loading
Loading
Loading
Loading
+3 −3
Original line number Diff line number Diff line
@@ -19,8 +19,8 @@
#include <linux/extable.h>
#include <linux/kdebug.h>
#include <linux/slab.h>
#include <linux/moduleloader.h>
#include <linux/set_memory.h>
#include <linux/execmem.h>
#include <asm/code-patching.h>
#include <asm/cacheflush.h>
#include <asm/sstep.h>
@@ -130,7 +130,7 @@ void *alloc_insn_page(void)
{
	void *page;

	page = module_alloc(PAGE_SIZE);
	page = execmem_alloc(EXECMEM_KPROBES, PAGE_SIZE);
	if (!page)
		return NULL;

@@ -142,7 +142,7 @@ void *alloc_insn_page(void)
	}
	return page;
error:
	module_memfree(page);
	execmem_free(page);
	return NULL;
}

+2 −2
Original line number Diff line number Diff line
@@ -7,13 +7,13 @@
 *   Author(s): Martin Schwidefsky <schwidefsky@de.ibm.com>
 */

#include <linux/moduleloader.h>
#include <linux/hardirq.h>
#include <linux/uaccess.h>
#include <linux/ftrace.h>
#include <linux/kernel.h>
#include <linux/types.h>
#include <linux/kprobes.h>
#include <linux/execmem.h>
#include <trace/syscall.h>
#include <asm/asm-offsets.h>
#include <asm/text-patching.h>
@@ -220,7 +220,7 @@ static int __init ftrace_plt_init(void)
{
	const char *start, *end;

	ftrace_plt = module_alloc(PAGE_SIZE);
	ftrace_plt = execmem_alloc(EXECMEM_FTRACE, PAGE_SIZE);
	if (!ftrace_plt)
		panic("cannot allocate ftrace plt\n");

+2 −2
Original line number Diff line number Diff line
@@ -9,7 +9,6 @@

#define pr_fmt(fmt) "kprobes: " fmt

#include <linux/moduleloader.h>
#include <linux/kprobes.h>
#include <linux/ptrace.h>
#include <linux/preempt.h>
@@ -21,6 +20,7 @@
#include <linux/slab.h>
#include <linux/hardirq.h>
#include <linux/ftrace.h>
#include <linux/execmem.h>
#include <asm/set_memory.h>
#include <asm/sections.h>
#include <asm/dis.h>
@@ -38,7 +38,7 @@ void *alloc_insn_page(void)
{
	void *page;

	page = module_alloc(PAGE_SIZE);
	page = execmem_alloc(EXECMEM_KPROBES, PAGE_SIZE);
	if (!page)
		return NULL;
	set_memory_rox((unsigned long)page, 1);
+3 −2
Original line number Diff line number Diff line
@@ -21,6 +21,7 @@
#include <linux/moduleloader.h>
#include <linux/bug.h>
#include <linux/memory.h>
#include <linux/execmem.h>
#include <asm/alternative.h>
#include <asm/nospec-branch.h>
#include <asm/facility.h>
@@ -76,7 +77,7 @@ void *module_alloc(unsigned long size)
#ifdef CONFIG_FUNCTION_TRACER
void module_arch_cleanup(struct module *mod)
{
	module_memfree(mod->arch.trampolines_start);
	execmem_free(mod->arch.trampolines_start);
}
#endif

@@ -510,7 +511,7 @@ static int module_alloc_ftrace_hotpatch_trampolines(struct module *me,

	size = FTRACE_HOTPATCH_TRAMPOLINES_SIZE(s->sh_size);
	numpages = DIV_ROUND_UP(size, PAGE_SIZE);
	start = module_alloc(numpages * PAGE_SIZE);
	start = execmem_alloc(EXECMEM_FTRACE, numpages * PAGE_SIZE);
	if (!start)
		return -ENOMEM;
	set_memory_rox((unsigned long)start, numpages);
+4 −4
Original line number Diff line number Diff line
// SPDX-License-Identifier: GPL-2.0
#include <linux/moduleloader.h>
#include <linux/workqueue.h>
#include <linux/netdevice.h>
#include <linux/filter.h>
#include <linux/cache.h>
#include <linux/if_vlan.h>
#include <linux/execmem.h>

#include <asm/cacheflush.h>
#include <asm/ptrace.h>
@@ -713,7 +713,7 @@ cond_branch: f_offset = addrs[i + filter[i].jf];
				if (unlikely(proglen + ilen > oldproglen)) {
					pr_err("bpb_jit_compile fatal error\n");
					kfree(addrs);
					module_memfree(image);
					execmem_free(image);
					return;
				}
				memcpy(image + proglen, temp, ilen);
@@ -736,7 +736,7 @@ cond_branch: f_offset = addrs[i + filter[i].jf];
			break;
		}
		if (proglen == oldproglen) {
			image = module_alloc(proglen);
			image = execmem_alloc(EXECMEM_BPF, proglen);
			if (!image)
				goto out;
		}
@@ -758,7 +758,7 @@ cond_branch: f_offset = addrs[i + filter[i].jf];
void bpf_jit_free(struct bpf_prog *fp)
{
	if (fp->jited)
		module_memfree(fp->bpf_func);
		execmem_free(fp->bpf_func);

	bpf_prog_unlock_free(fp);
}
Loading