mirror of
https://github.com/torvalds/linux.git
synced 2026-11-07 06:17:02 +01:00
bpf, x86: Use global buffer for trampoline size generation
Currently arch_bpf_trampoline_size allocates and frees a temporary trampoline buffer on every invocation. The buffer is only used as a scratch space while __arch_prepare_bpf_trampoline() calculates the required size, and the generated trampoline is discarded. Allocating a writable scratch page during kernel initialization and reusing it for all size calculations. This improves tracing_multi attachment time. With current code: # ./test_progs -t tracing_multi_bench_attach -v ... serial_test_tracing_multi_bench_attach: found 55227 functions serial_test_tracing_multi_bench_attach: attached in 1.563s serial_test_tracing_multi_bench_attach: detached in 0.256s With the fix: # ./test_progs -t tracing_multi_bench_attach -v ... serial_test_tracing_multi_bench_attach: found 55235 functions serial_test_tracing_multi_bench_attach: attached in 0.798s serial_test_tracing_multi_bench_attach: detached in 0.258s Signed-off-by: Jiri Olsa <jolsa@kernel.org> Link: https://lore.kernel.org/r/20260910094353.1256316-1-jolsa@kernel.org Signed-off-by: Alexei Starovoitov <ast@kernel.org>
This commit is contained in:
parent
698181b2d5
commit
29fcf9ce4b
|
|
@ -9,6 +9,7 @@
|
|||
#include <linux/filter.h>
|
||||
#include <linux/if_vlan.h>
|
||||
#include <linux/bitfield.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/bpf.h>
|
||||
#include <linux/bpf_verifier.h>
|
||||
#include <linux/memory.h>
|
||||
|
|
@ -35,6 +36,21 @@ void __asan_store8(void *p);
|
|||
|
||||
static bool all_callee_regs_used[4] = {true, true, true, true};
|
||||
|
||||
static void *trampoline_size_image;
|
||||
|
||||
static int __init init_trampoline_size_image(void)
|
||||
{
|
||||
/*
|
||||
* The generated trampoline contains calls and jumps with 32bit relative
|
||||
* offsets, so the scratch image must be in the execmem range.
|
||||
* On x86, module data and executable memory share the same address range,
|
||||
* so using EXECMEM_MODULE_DATA to get writable memory.
|
||||
*/
|
||||
trampoline_size_image = execmem_alloc(EXECMEM_MODULE_DATA, PAGE_SIZE);
|
||||
return trampoline_size_image ? 0 : -ENOMEM;
|
||||
}
|
||||
late_initcall(init_trampoline_size_image);
|
||||
|
||||
static u8 *emit_code(u8 *ptr, u32 bytes, unsigned int len)
|
||||
{
|
||||
if (len == 1)
|
||||
|
|
@ -4067,24 +4083,14 @@ int arch_bpf_trampoline_size(const struct btf_func_model *m, u32 flags,
|
|||
struct bpf_tramp_nodes *tnodes, void *func_addr)
|
||||
{
|
||||
struct bpf_tramp_image im;
|
||||
void *image;
|
||||
int ret;
|
||||
|
||||
/* Allocate a temporary buffer for __arch_prepare_bpf_trampoline().
|
||||
*
|
||||
* We cannot use kvmalloc here, because we need image to be in
|
||||
* module memory range.
|
||||
* Since it must be writable use execmem_alloc(EXECMEM_MODULE_DATA)
|
||||
* that returns writable memory in the module address space.
|
||||
*/
|
||||
image = execmem_alloc(EXECMEM_MODULE_DATA, PAGE_SIZE);
|
||||
if (!image)
|
||||
if (!trampoline_size_image)
|
||||
return -ENOMEM;
|
||||
|
||||
ret = __arch_prepare_bpf_trampoline(&im, image, image + PAGE_SIZE, image,
|
||||
m, flags, tnodes, func_addr);
|
||||
execmem_free(image);
|
||||
return ret;
|
||||
return __arch_prepare_bpf_trampoline(&im, trampoline_size_image,
|
||||
trampoline_size_image + PAGE_SIZE,
|
||||
trampoline_size_image, m, flags,
|
||||
tnodes, func_addr);
|
||||
}
|
||||
|
||||
static int emit_bpf_dispatcher(u8 **pprog, int a, int b, s64 *progs, u8 *image, u8 *buf)
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user