From: "Mike Rapoport (Microsoft)" Jiri Olsa reports slowdown of tracing_multi benchmark that allocates huge number of trampolines [1]. The slowdown caused by extra protection changes in execmem_alloc_rw() and execmem_free(). With ROX caches enabled, all execmem allocations except EXECMEM_MODULE_DATA are ROX after the allocation. execmem_alloc_rw() temporarily sets them to W+NX and execmem_free() resets them back to ROX. The only user of bpf_jit_alloc_exec_rw() is x86::arch_bpf_trampoline_size() that only needs a temporary writable buffer in the modules address space. On x86 executable memory and module data are constrained to the same address range, so x86::arch_bpf_trampoline_size() can directly use execmem_alloc(EXECMEM_MODULE_DATA) Replace the call to bpf_jit_alloc_exec_rw() with a call to execmem_alloc(EXECMEM_MODULE_DATA) in x86::arch_bpf_trampoline_size() and drop bpf_jit_alloc_exec_rw() helper. Reported-by: Jiri Olsa Link: https://lore.kernel.org/all/an8r7EODLIL-bZM3@krava Fixes: f0334294a428 ("bpf, x86: make sure allocation in arch_bpf_trampoline_size() is writable") Signed-off-by: Mike Rapoport (Microsoft) --- arch/x86/net/bpf_jit_comp.c | 8 +++++--- include/linux/filter.h | 1 - kernel/bpf/core.c | 5 ----- 3 files changed, 5 insertions(+), 9 deletions(-) diff --git a/arch/x86/net/bpf_jit_comp.c b/arch/x86/net/bpf_jit_comp.c index b2feec81e231..7d064d3e2788 100644 --- a/arch/x86/net/bpf_jit_comp.c +++ b/arch/x86/net/bpf_jit_comp.c @@ -13,6 +13,7 @@ #include #include #include +#include #include #include #include @@ -3706,15 +3707,16 @@ int arch_bpf_trampoline_size(const struct btf_func_model *m, u32 flags, * * We cannot use kvmalloc here, because we need image to be in * module memory range. - * Since it must be writable use bpf_jit_alloc_exec_rw(). + * Since it must be writable use execmem_alloc(EXECMEM_MODULE_DATA) + * that returns writable memory in the module address space. */ - image = bpf_jit_alloc_exec_rw(PAGE_SIZE); + image = execmem_alloc(EXECMEM_MODULE_DATA, PAGE_SIZE); if (!image) return -ENOMEM; ret = __arch_prepare_bpf_trampoline(&im, image, image + PAGE_SIZE, image, m, flags, tnodes, func_addr); - bpf_jit_free_exec(image); + execmem_free(image); return ret; } diff --git a/include/linux/filter.h b/include/linux/filter.h index 32d5297c557e..14acb2455746 100644 --- a/include/linux/filter.h +++ b/include/linux/filter.h @@ -1333,7 +1333,6 @@ bpf_jit_binary_alloc(unsigned int proglen, u8 **image_ptr, void bpf_jit_binary_free(struct bpf_binary_header *hdr); u64 bpf_jit_alloc_exec_limit(void); void *bpf_jit_alloc_exec(unsigned long size); -void *bpf_jit_alloc_exec_rw(unsigned long size); void bpf_jit_free_exec(void *addr); void bpf_jit_free(struct bpf_prog *fp); struct bpf_binary_header * diff --git a/kernel/bpf/core.c b/kernel/bpf/core.c index e2076667b245..1b89c18cf246 100644 --- a/kernel/bpf/core.c +++ b/kernel/bpf/core.c @@ -1128,11 +1128,6 @@ void *bpf_jit_alloc_exec(unsigned long size) return execmem_alloc(EXECMEM_BPF, size); } -void *bpf_jit_alloc_exec_rw(unsigned long size) -{ - return execmem_alloc_rw(EXECMEM_BPF, size); -} - void bpf_jit_free_exec(void *addr) { execmem_free(addr); base-commit: 07edbd8fe6416f45e9ba6b0edcd3e40770601ebc -- 2.53.0