* [PATCH bpf-next] bpf, x86: Use global buffer for trampoline size generation
@ 2026-09-07 16:05 Jiri Olsa
2026-09-07 16:20 ` sashiko-bot
2026-09-07 19:56 ` Alexei Starovoitov
0 siblings, 2 replies; 8+ messages in thread
From: Jiri Olsa @ 2026-09-07 16:05 UTC (permalink / raw)
To: Alexei Starovoitov, Daniel Borkmann, Andrii Nakryiko
Cc: bpf, Martin KaFai Lau, Eduard Zingerman, Song Liu, Yonghong Song,
Mike Rapoport
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>
---
was "bpf, x86: Add support for jit dry run",
- doing this by having single scratch page instead as suggested by Alexei
arch/x86/net/bpf_jit_comp.c | 30 +++++++++++++++---------------
1 file changed, 15 insertions(+), 15 deletions(-)
diff --git a/arch/x86/net/bpf_jit_comp.c b/arch/x86/net/bpf_jit_comp.c
index bba351944202..13ef0d53ca29 100644
--- a/arch/x86/net/bpf_jit_comp.c
+++ b/arch/x86/net/bpf_jit_comp.c
@@ -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,15 @@ 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)
+{
+ 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)
@@ -4000,24 +4010,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)
--
2.54.0
^ permalink raw reply related [flat|nested] 8+ messages in thread
* Re: [PATCH bpf-next] bpf, x86: Use global buffer for trampoline size generation
2026-09-07 16:05 [PATCH bpf-next] bpf, x86: Use global buffer for trampoline size generation Jiri Olsa
@ 2026-09-07 16:20 ` sashiko-bot
2026-09-07 19:56 ` Alexei Starovoitov
1 sibling, 0 replies; 8+ messages in thread
From: sashiko-bot @ 2026-09-07 16:20 UTC (permalink / raw)
To: Jiri Olsa; +Cc: bpf
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [Medium] Concurrent BPF trampoline size calculations cause data races and severe cacheline bouncing on the globally shared `trampoline_size_image` buffer.
--
commit d4cd8458939c8e8adafba04b2627a4ef1338ac21
Author: Jiri Olsa <jolsa@kernel.org>
Subject: bpf, x86: Use global buffer for trampoline size generation
This commit replaces the per-invocation allocation of a temporary
trampoline buffer in arch_bpf_trampoline_size() with a globally shared
buffer allocated during initialization. This reduces the time it takes
to calculate the required size by reusing the writable scratch page.
> diff --git a/arch/x86/net/bpf_jit_comp.c b/arch/x86/net/bpf_jit_comp.c
> index bba351944202c..13ef0d53ca296 100644
> --- a/arch/x86/net/bpf_jit_comp.c
> +++ b/arch/x86/net/bpf_jit_comp.c
[ ... ]
> @@ -4000,24 +4010,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);
> }
[Severity: Medium]
Can this lead to concurrent modifications of the shared scratch buffer?
If multiple threads attach trampolines or load BPF struct_ops programs
simultaneously, they might both invoke arch_bpf_trampoline_size() and
execute lockless writes into trampoline_size_image (such as inside
emit_code()).
For example, bpf_struct_ops_map_update_elem() calls into the trampoline size
calculation while holding only a per-map lock, allowing parallel updates
across different maps.
While the generated bytes are ultimately discarded and the calculation
depends on local pointer arithmetic rather than the buffer's contents, do
these concurrent lockless writes risk severe cacheline bouncing? This could
degrade concurrent attachment performance and will likely trigger KCSAN data
race warnings.
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260907160538.922450-1-jolsa@kernel.org?part=1
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH bpf-next] bpf, x86: Use global buffer for trampoline size generation
2026-09-07 16:05 [PATCH bpf-next] bpf, x86: Use global buffer for trampoline size generation Jiri Olsa
2026-09-07 16:20 ` sashiko-bot
@ 2026-09-07 19:56 ` Alexei Starovoitov
2026-09-07 20:26 ` Jiri Olsa
1 sibling, 1 reply; 8+ messages in thread
From: Alexei Starovoitov @ 2026-09-07 19:56 UTC (permalink / raw)
To: Jiri Olsa, Alexei Starovoitov, Daniel Borkmann, Andrii Nakryiko
Cc: bpf, Martin KaFai Lau, Eduard Zingerman, Song Liu, Yonghong Song,
Mike Rapoport
On Mon Sep 7, 2026 at 9:05 AM PDT, Jiri Olsa wrote:
> 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>
> ---
> was "bpf, x86: Add support for jit dry run",
> - doing this by having single scratch page instead as suggested by Alexei
>
> arch/x86/net/bpf_jit_comp.c | 30 +++++++++++++++---------------
> 1 file changed, 15 insertions(+), 15 deletions(-)
>
> diff --git a/arch/x86/net/bpf_jit_comp.c b/arch/x86/net/bpf_jit_comp.c
> index bba351944202..13ef0d53ca29 100644
> --- a/arch/x86/net/bpf_jit_comp.c
> +++ b/arch/x86/net/bpf_jit_comp.c
> @@ -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,15 @@ 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)
> +{
> + trampoline_size_image = execmem_alloc(EXECMEM_MODULE_DATA, PAGE_SIZE);
I think I asked it earlier... why does it have to be execmem ?
Can it be normal page?
If so then alloc it and free it every time. No need to keep one page in reserve.
pw-bot: cr
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH bpf-next] bpf, x86: Use global buffer for trampoline size generation
2026-09-07 19:56 ` Alexei Starovoitov
@ 2026-09-07 20:26 ` Jiri Olsa
2026-09-08 0:13 ` Alexei Starovoitov
0 siblings, 1 reply; 8+ messages in thread
From: Jiri Olsa @ 2026-09-07 20:26 UTC (permalink / raw)
To: Alexei Starovoitov
Cc: Alexei Starovoitov, Daniel Borkmann, Andrii Nakryiko, bpf,
Martin KaFai Lau, Eduard Zingerman, Song Liu, Yonghong Song,
Mike Rapoport
On Mon, Sep 07, 2026 at 12:56:33PM -0700, Alexei Starovoitov wrote:
> On Mon Sep 7, 2026 at 9:05 AM PDT, Jiri Olsa wrote:
> > 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>
> > ---
> > was "bpf, x86: Add support for jit dry run",
> > - doing this by having single scratch page instead as suggested by Alexei
> >
> > arch/x86/net/bpf_jit_comp.c | 30 +++++++++++++++---------------
> > 1 file changed, 15 insertions(+), 15 deletions(-)
> >
> > diff --git a/arch/x86/net/bpf_jit_comp.c b/arch/x86/net/bpf_jit_comp.c
> > index bba351944202..13ef0d53ca29 100644
> > --- a/arch/x86/net/bpf_jit_comp.c
> > +++ b/arch/x86/net/bpf_jit_comp.c
> > @@ -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,15 @@ 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)
> > +{
> > + trampoline_size_image = execmem_alloc(EXECMEM_MODULE_DATA, PAGE_SIZE);
>
> I think I asked it earlier... why does it have to be execmem ?
> Can it be normal page?
ugh sorry I forgot.. the page/image needs to be in execmem range
for emitting call/jmp otherwise the delta won't fit in 4 bytes
and it fails on emit_patch is_simm32 check
>
> If so then alloc it and free it every time. No need to keep one page in reserve.
hum, you mean drop the change then?
jirka
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH bpf-next] bpf, x86: Use global buffer for trampoline size generation
2026-09-07 20:26 ` Jiri Olsa
@ 2026-09-08 0:13 ` Alexei Starovoitov
2026-09-08 12:25 ` Jiri Olsa
0 siblings, 1 reply; 8+ messages in thread
From: Alexei Starovoitov @ 2026-09-08 0:13 UTC (permalink / raw)
To: Jiri Olsa
Cc: Alexei Starovoitov, Daniel Borkmann, Andrii Nakryiko, bpf,
Martin KaFai Lau, Eduard Zingerman, Song Liu, Yonghong Song,
Mike Rapoport
On Mon, Sep 7, 2026 at 1:26 PM Jiri Olsa <olsajiri@gmail.com> wrote:
>
> On Mon, Sep 07, 2026 at 12:56:33PM -0700, Alexei Starovoitov wrote:
> > On Mon Sep 7, 2026 at 9:05 AM PDT, Jiri Olsa wrote:
> > > 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>
> > > ---
> > > was "bpf, x86: Add support for jit dry run",
> > > - doing this by having single scratch page instead as suggested by Alexei
> > >
> > > arch/x86/net/bpf_jit_comp.c | 30 +++++++++++++++---------------
> > > 1 file changed, 15 insertions(+), 15 deletions(-)
> > >
> > > diff --git a/arch/x86/net/bpf_jit_comp.c b/arch/x86/net/bpf_jit_comp.c
> > > index bba351944202..13ef0d53ca29 100644
> > > --- a/arch/x86/net/bpf_jit_comp.c
> > > +++ b/arch/x86/net/bpf_jit_comp.c
> > > @@ -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,15 @@ 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)
> > > +{
> > > + trampoline_size_image = execmem_alloc(EXECMEM_MODULE_DATA, PAGE_SIZE);
> >
> > I think I asked it earlier... why does it have to be execmem ?
> > Can it be normal page?
>
> ugh sorry I forgot.. the page/image needs to be in execmem range
> for emitting call/jmp otherwise the delta won't fit in 4 bytes
> and it fails on emit_patch is_simm32 check
ahh. I see. Please mention it in the comment and
also use bpf_jit_alloc_exec(PAGE_SIZE).
execmem_alloc(EXECMEM_MODULE_DATA...) was working by accident.
The VM ranges could have been different.
> >
> > If so then alloc it and free it every time. No need to keep one page in reserve.
>
> hum, you mean drop the change then?
Since it needs to be execmem preallocating one page for this is fine.
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH bpf-next] bpf, x86: Use global buffer for trampoline size generation
2026-09-08 0:13 ` Alexei Starovoitov
@ 2026-09-08 12:25 ` Jiri Olsa
2026-09-08 15:19 ` Mike Rapoport
0 siblings, 1 reply; 8+ messages in thread
From: Jiri Olsa @ 2026-09-08 12:25 UTC (permalink / raw)
To: Alexei Starovoitov
Cc: Jiri Olsa, Alexei Starovoitov, Daniel Borkmann, Andrii Nakryiko,
bpf, Martin KaFai Lau, Eduard Zingerman, Song Liu, Yonghong Song,
Mike Rapoport
On Mon, Sep 07, 2026 at 05:13:29PM -0700, Alexei Starovoitov wrote:
> On Mon, Sep 7, 2026 at 1:26 PM Jiri Olsa <olsajiri@gmail.com> wrote:
> >
> > On Mon, Sep 07, 2026 at 12:56:33PM -0700, Alexei Starovoitov wrote:
> > > On Mon Sep 7, 2026 at 9:05 AM PDT, Jiri Olsa wrote:
> > > > 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>
> > > > ---
> > > > was "bpf, x86: Add support for jit dry run",
> > > > - doing this by having single scratch page instead as suggested by Alexei
> > > >
> > > > arch/x86/net/bpf_jit_comp.c | 30 +++++++++++++++---------------
> > > > 1 file changed, 15 insertions(+), 15 deletions(-)
> > > >
> > > > diff --git a/arch/x86/net/bpf_jit_comp.c b/arch/x86/net/bpf_jit_comp.c
> > > > index bba351944202..13ef0d53ca29 100644
> > > > --- a/arch/x86/net/bpf_jit_comp.c
> > > > +++ b/arch/x86/net/bpf_jit_comp.c
> > > > @@ -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,15 @@ 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)
> > > > +{
> > > > + trampoline_size_image = execmem_alloc(EXECMEM_MODULE_DATA, PAGE_SIZE);
> > >
> > > I think I asked it earlier... why does it have to be execmem ?
> > > Can it be normal page?
> >
> > ugh sorry I forgot.. the page/image needs to be in execmem range
> > for emitting call/jmp otherwise the delta won't fit in 4 bytes
> > and it fails on emit_patch is_simm32 check
>
> ahh. I see. Please mention it in the comment and
> also use bpf_jit_alloc_exec(PAGE_SIZE).
>
> execmem_alloc(EXECMEM_MODULE_DATA...) was working by accident.
> The VM ranges could have been different.
bpf_jit_alloc_exec returns read only page so I'd use bpf_jit_alloc_exec_rw,
but it was recently removed in:
c7a2a3618290 x86/bpf: Make arch_bpf_trampoline_size allocate from EXECMEM_MODULE_DATA
so I ended up with:
trampoline_size_image = execmem_alloc_rw(EXECMEM_BPF, PAGE_SIZE);
>
> > >
> > > If so then alloc it and free it every time. No need to keep one page in reserve.
> >
> > hum, you mean drop the change then?
>
> Since it needs to be execmem preallocating one page for this is fine.
ok, great
jirka
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH bpf-next] bpf, x86: Use global buffer for trampoline size generation
2026-09-08 12:25 ` Jiri Olsa
@ 2026-09-08 15:19 ` Mike Rapoport
2026-09-09 9:49 ` Jiri Olsa
0 siblings, 1 reply; 8+ messages in thread
From: Mike Rapoport @ 2026-09-08 15:19 UTC (permalink / raw)
To: Jiri Olsa
Cc: Alexei Starovoitov, Alexei Starovoitov, Daniel Borkmann,
Andrii Nakryiko, bpf, Martin KaFai Lau, Eduard Zingerman,
Song Liu, Yonghong Song
On Tue, Sep 08, 2026 at 02:25:24PM +0200, Jiri Olsa wrote:
> On Mon, Sep 07, 2026 at 05:13:29PM -0700, Alexei Starovoitov wrote:
>
> > > > > +static void *trampoline_size_image;
> > > > > +
> > > > > +static int __init init_trampoline_size_image(void)
> > > > > +{
> > > > > + trampoline_size_image = execmem_alloc(EXECMEM_MODULE_DATA, PAGE_SIZE);
> > > >
> > > > I think I asked it earlier... why does it have to be execmem ?
> > > > Can it be normal page?
> > >
> > > ugh sorry I forgot.. the page/image needs to be in execmem range
> > > for emitting call/jmp otherwise the delta won't fit in 4 bytes
> > > and it fails on emit_patch is_simm32 check
> >
> > ahh. I see. Please mention it in the comment and
> > also use bpf_jit_alloc_exec(PAGE_SIZE).
> >
> > execmem_alloc(EXECMEM_MODULE_DATA...) was working by accident.
> > The VM ranges could have been different.
On x86 it's not an accident ;-)
But would be a surprise if this is copied to another architecture.
> bpf_jit_alloc_exec returns read only page so I'd use bpf_jit_alloc_exec_rw,
> but it was recently removed in:
>
> c7a2a3618290 x86/bpf: Make arch_bpf_trampoline_size allocate from EXECMEM_MODULE_DATA
>
> so I ended up with:
>
> trampoline_size_image = execmem_alloc_rw(EXECMEM_BPF, PAGE_SIZE);
This will work, but it will permanently damage 2M mapping in the module
address space.
execmem_alloc_rw() takes a page out of the ROX cache and resets that page
permissions to RW. This splits the large mapping of the 2M cache page and
since this is a permanent allocation, that chunk will be forever mapped
with 4k pages.
execmem_alloc(EXECMEM_MODULE_DATA...) does not use ROX cache, so it won't
take a page out of ROX cache and reset it's permissions.
Since this is anyway x86 code and on x86 the ranges for data and code are
*always* the same, I'd keep execmem_alloc(EXECMEM_MODULE_DATA...) and add a
comment.
> jirka
--
Sincerely yours,
Mike.
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH bpf-next] bpf, x86: Use global buffer for trampoline size generation
2026-09-08 15:19 ` Mike Rapoport
@ 2026-09-09 9:49 ` Jiri Olsa
0 siblings, 0 replies; 8+ messages in thread
From: Jiri Olsa @ 2026-09-09 9:49 UTC (permalink / raw)
To: Mike Rapoport
Cc: Jiri Olsa, Alexei Starovoitov, Alexei Starovoitov,
Daniel Borkmann, Andrii Nakryiko, bpf, Martin KaFai Lau,
Eduard Zingerman, Song Liu, Yonghong Song
On Tue, Sep 08, 2026 at 06:19:17PM +0300, Mike Rapoport wrote:
> On Tue, Sep 08, 2026 at 02:25:24PM +0200, Jiri Olsa wrote:
> > On Mon, Sep 07, 2026 at 05:13:29PM -0700, Alexei Starovoitov wrote:
> >
> > > > > > +static void *trampoline_size_image;
> > > > > > +
> > > > > > +static int __init init_trampoline_size_image(void)
> > > > > > +{
> > > > > > + trampoline_size_image = execmem_alloc(EXECMEM_MODULE_DATA, PAGE_SIZE);
> > > > >
> > > > > I think I asked it earlier... why does it have to be execmem ?
> > > > > Can it be normal page?
> > > >
> > > > ugh sorry I forgot.. the page/image needs to be in execmem range
> > > > for emitting call/jmp otherwise the delta won't fit in 4 bytes
> > > > and it fails on emit_patch is_simm32 check
> > >
> > > ahh. I see. Please mention it in the comment and
> > > also use bpf_jit_alloc_exec(PAGE_SIZE).
> > >
> > > execmem_alloc(EXECMEM_MODULE_DATA...) was working by accident.
> > > The VM ranges could have been different.
>
> On x86 it's not an accident ;-)
> But would be a surprise if this is copied to another architecture.
>
> > bpf_jit_alloc_exec returns read only page so I'd use bpf_jit_alloc_exec_rw,
> > but it was recently removed in:
> >
> > c7a2a3618290 x86/bpf: Make arch_bpf_trampoline_size allocate from EXECMEM_MODULE_DATA
> >
> > so I ended up with:
> >
> > trampoline_size_image = execmem_alloc_rw(EXECMEM_BPF, PAGE_SIZE);
>
> This will work, but it will permanently damage 2M mapping in the module
> address space.
>
> execmem_alloc_rw() takes a page out of the ROX cache and resets that page
> permissions to RW. This splits the large mapping of the 2M cache page and
> since this is a permanent allocation, that chunk will be forever mapped
> with 4k pages.
>
> execmem_alloc(EXECMEM_MODULE_DATA...) does not use ROX cache, so it won't
> take a page out of ROX cache and reset it's permissions.
>
> Since this is anyway x86 code and on x86 the ranges for data and code are
> *always* the same, I'd keep execmem_alloc(EXECMEM_MODULE_DATA...) and add a
> comment.
sgtm, if there's no objection I'll add comment to init_trampoline_size_image
and send new version
thanks,
jirka
^ permalink raw reply [flat|nested] 8+ messages in thread
end of thread, other threads:[~2026-09-09 9:49 UTC | newest]
Thread overview: 8+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-09-07 16:05 [PATCH bpf-next] bpf, x86: Use global buffer for trampoline size generation Jiri Olsa
2026-09-07 16:20 ` sashiko-bot
2026-09-07 19:56 ` Alexei Starovoitov
2026-09-07 20:26 ` Jiri Olsa
2026-09-08 0:13 ` Alexei Starovoitov
2026-09-08 12:25 ` Jiri Olsa
2026-09-08 15:19 ` Mike Rapoport
2026-09-09 9:49 ` Jiri Olsa
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox