* [RESEND PATCH] powerpc64/bpf: fix JIT code size calculation of bpf trampoline
@ 2025-03-26 14:34 Hari Bathini
2025-03-26 17:21 ` Venkat Rao Bagalkote
2025-04-03 15:45 ` Naveen N Rao
0 siblings, 2 replies; 4+ messages in thread
From: Hari Bathini @ 2025-03-26 14:34 UTC (permalink / raw)
To: linuxppc-dev, bpf
Cc: Madhavan Srinivasan, Venkat Rao Bagalkote, Michael Ellerman,
Naveen N. Rao, Daniel Borkmann, Nicholas Piggin,
Alexei Starovoitov, Andrii Nakryiko, Christophe Leroy, stable
The JIT compile of ldimm instructions can be anywhere between 1-5
instructions long depending on the value being loaded.
arch_bpf_trampoline_size() provides JIT size of the BPF trampoline
before the buffer for JIT'ing it is allocated. BPF trampoline JIT
code has ldimm instructions that need to load the value of pointer
to struct bpf_tramp_image. But this pointer value is not same while
calling arch_bpf_trampoline_size() & arch_prepare_bpf_trampoline().
So, the size arrived at using arch_bpf_trampoline_size() can vary
from the size needed in arch_prepare_bpf_trampoline(). When the
number of ldimm instructions emitted in arch_bpf_trampoline_size()
is less than the number of ldimm instructions emitted during the
actual JIT compile of trampoline, the below warning is produced:
WARNING: CPU: 8 PID: 204190 at arch/powerpc/net/bpf_jit_comp.c:981 __arch_prepare_bpf_trampoline.isra.0+0xd2c/0xdcc
which is:
/* Make sure the trampoline generation logic doesn't overflow */
if (image && WARN_ON_ONCE(&image[ctx->idx] >
(u32 *)rw_image_end - BPF_INSN_SAFETY)) {
Pass NULL as the first argument to __arch_prepare_bpf_trampoline()
call from arch_bpf_trampoline_size() function, to differentiate it
from how arch_prepare_bpf_trampoline() calls it and ensure maximum
possible instructions are emitted in arch_bpf_trampoline_size() for
ldimm instructions that load a different value during the actual JIT
compile of BPF trampoline.
Fixes: d243b62b7bd3 ("powerpc64/bpf: Add support for bpf trampolines")
Reported-by: Venkat Rao Bagalkote <venkat88@linux.ibm.com>
Closes: https://lore.kernel.org/all/6168bfc8-659f-4b5a-a6fb-90a916dde3b3@linux.ibm.com/
Cc: stable@vger.kernel.org # v6.13+
Signed-off-by: Hari Bathini <hbathini@linux.ibm.com>
---
* Removed a redundant '/' accidently added in a comment and resending.
arch/powerpc/net/bpf_jit_comp.c | 29 +++++++++++++++++++++++------
1 file changed, 23 insertions(+), 6 deletions(-)
diff --git a/arch/powerpc/net/bpf_jit_comp.c b/arch/powerpc/net/bpf_jit_comp.c
index 2991bb171a9b..c94717ccb2bd 100644
--- a/arch/powerpc/net/bpf_jit_comp.c
+++ b/arch/powerpc/net/bpf_jit_comp.c
@@ -833,7 +833,12 @@ static int __arch_prepare_bpf_trampoline(struct bpf_tramp_image *im, void *rw_im
EMIT(PPC_RAW_STL(_R26, _R1, nvr_off + SZL));
if (flags & BPF_TRAMP_F_CALL_ORIG) {
- PPC_LI_ADDR(_R3, (unsigned long)im);
+ /*
+ * Emit maximum possible instructions while getting the size of
+ * bpf trampoline to ensure trampoline JIT code doesn't overflow.
+ */
+ PPC_LI_ADDR(_R3, im ? (unsigned long)im :
+ (unsigned long)(~(1UL << (BITS_PER_LONG - 1))));
ret = bpf_jit_emit_func_call_rel(image, ro_image, ctx,
(unsigned long)__bpf_tramp_enter);
if (ret)
@@ -889,7 +894,8 @@ static int __arch_prepare_bpf_trampoline(struct bpf_tramp_image *im, void *rw_im
bpf_trampoline_restore_tail_call_cnt(image, ctx, func_frame_offset, r4_off);
/* Reserve space to patch branch instruction to skip fexit progs */
- im->ip_after_call = &((u32 *)ro_image)[ctx->idx];
+ if (im)
+ im->ip_after_call = &((u32 *)ro_image)[ctx->idx];
EMIT(PPC_RAW_NOP());
}
@@ -912,8 +918,14 @@ static int __arch_prepare_bpf_trampoline(struct bpf_tramp_image *im, void *rw_im
}
if (flags & BPF_TRAMP_F_CALL_ORIG) {
- im->ip_epilogue = &((u32 *)ro_image)[ctx->idx];
- PPC_LI_ADDR(_R3, im);
+ if (im)
+ im->ip_epilogue = &((u32 *)ro_image)[ctx->idx];
+ /*
+ * Emit maximum possible instructions while getting the size of
+ * bpf trampoline to ensure trampoline JIT code doesn't overflow.
+ */
+ PPC_LI_ADDR(_R3, im ? (unsigned long)im :
+ (unsigned long)(~(1UL << (BITS_PER_LONG - 1))));
ret = bpf_jit_emit_func_call_rel(image, ro_image, ctx,
(unsigned long)__bpf_tramp_exit);
if (ret)
@@ -972,7 +984,6 @@ static int __arch_prepare_bpf_trampoline(struct bpf_tramp_image *im, void *rw_im
int arch_bpf_trampoline_size(const struct btf_func_model *m, u32 flags,
struct bpf_tramp_links *tlinks, void *func_addr)
{
- struct bpf_tramp_image im;
void *image;
int ret;
@@ -988,7 +999,13 @@ int arch_bpf_trampoline_size(const struct btf_func_model *m, u32 flags,
if (!image)
return -ENOMEM;
- ret = __arch_prepare_bpf_trampoline(&im, image, image + PAGE_SIZE, image,
+ /*
+ * Pass NULL as bpf_tramp_image pointer to differentiate the intent to get the
+ * buffer size for trampoline here. This differentiation helps in accounting for
+ * maximum possible instructions if the JIT code size is likely to vary during
+ * the actual JIT compile of the trampoline.
+ */
+ ret = __arch_prepare_bpf_trampoline(NULL, image, image + PAGE_SIZE, image,
m, flags, tlinks, func_addr);
bpf_jit_free_exec(image);
--
2.48.1
^ permalink raw reply related [flat|nested] 4+ messages in thread
* Re: [RESEND PATCH] powerpc64/bpf: fix JIT code size calculation of bpf trampoline
2025-03-26 14:34 [RESEND PATCH] powerpc64/bpf: fix JIT code size calculation of bpf trampoline Hari Bathini
@ 2025-03-26 17:21 ` Venkat Rao Bagalkote
2025-04-03 15:45 ` Naveen N Rao
1 sibling, 0 replies; 4+ messages in thread
From: Venkat Rao Bagalkote @ 2025-03-26 17:21 UTC (permalink / raw)
To: Hari Bathini, linuxppc-dev, bpf
Cc: Madhavan Srinivasan, Michael Ellerman, Naveen N. Rao,
Daniel Borkmann, Nicholas Piggin, Alexei Starovoitov,
Andrii Nakryiko, Christophe Leroy, stable
On 26/03/25 8:04 pm, Hari Bathini wrote:
> The JIT compile of ldimm instructions can be anywhere between 1-5
> instructions long depending on the value being loaded.
>
> arch_bpf_trampoline_size() provides JIT size of the BPF trampoline
> before the buffer for JIT'ing it is allocated. BPF trampoline JIT
> code has ldimm instructions that need to load the value of pointer
> to struct bpf_tramp_image. But this pointer value is not same while
> calling arch_bpf_trampoline_size() & arch_prepare_bpf_trampoline().
> So, the size arrived at using arch_bpf_trampoline_size() can vary
> from the size needed in arch_prepare_bpf_trampoline(). When the
> number of ldimm instructions emitted in arch_bpf_trampoline_size()
> is less than the number of ldimm instructions emitted during the
> actual JIT compile of trampoline, the below warning is produced:
>
> WARNING: CPU: 8 PID: 204190 at arch/powerpc/net/bpf_jit_comp.c:981 __arch_prepare_bpf_trampoline.isra.0+0xd2c/0xdcc
>
> which is:
>
> /* Make sure the trampoline generation logic doesn't overflow */
> if (image && WARN_ON_ONCE(&image[ctx->idx] >
> (u32 *)rw_image_end - BPF_INSN_SAFETY)) {
>
> Pass NULL as the first argument to __arch_prepare_bpf_trampoline()
> call from arch_bpf_trampoline_size() function, to differentiate it
> from how arch_prepare_bpf_trampoline() calls it and ensure maximum
> possible instructions are emitted in arch_bpf_trampoline_size() for
> ldimm instructions that load a different value during the actual JIT
> compile of BPF trampoline.
>
> Fixes: d243b62b7bd3 ("powerpc64/bpf: Add support for bpf trampolines")
> Reported-by: Venkat Rao Bagalkote <venkat88@linux.ibm.com>
> Closes: https://lore.kernel.org/all/6168bfc8-659f-4b5a-a6fb-90a916dde3b3@linux.ibm.com/
> Cc: stable@vger.kernel.org # v6.13+
> Signed-off-by: Hari Bathini <hbathini@linux.ibm.com>
> ---
>
> * Removed a redundant '/' accidently added in a comment and resending.
>
> arch/powerpc/net/bpf_jit_comp.c | 29 +++++++++++++++++++++++------
> 1 file changed, 23 insertions(+), 6 deletions(-)
>
> diff --git a/arch/powerpc/net/bpf_jit_comp.c b/arch/powerpc/net/bpf_jit_comp.c
> index 2991bb171a9b..c94717ccb2bd 100644
> --- a/arch/powerpc/net/bpf_jit_comp.c
> +++ b/arch/powerpc/net/bpf_jit_comp.c
> @@ -833,7 +833,12 @@ static int __arch_prepare_bpf_trampoline(struct bpf_tramp_image *im, void *rw_im
> EMIT(PPC_RAW_STL(_R26, _R1, nvr_off + SZL));
>
> if (flags & BPF_TRAMP_F_CALL_ORIG) {
> - PPC_LI_ADDR(_R3, (unsigned long)im);
> + /*
> + * Emit maximum possible instructions while getting the size of
> + * bpf trampoline to ensure trampoline JIT code doesn't overflow.
> + */
> + PPC_LI_ADDR(_R3, im ? (unsigned long)im :
> + (unsigned long)(~(1UL << (BITS_PER_LONG - 1))));
> ret = bpf_jit_emit_func_call_rel(image, ro_image, ctx,
> (unsigned long)__bpf_tramp_enter);
> if (ret)
> @@ -889,7 +894,8 @@ static int __arch_prepare_bpf_trampoline(struct bpf_tramp_image *im, void *rw_im
> bpf_trampoline_restore_tail_call_cnt(image, ctx, func_frame_offset, r4_off);
>
> /* Reserve space to patch branch instruction to skip fexit progs */
> - im->ip_after_call = &((u32 *)ro_image)[ctx->idx];
> + if (im)
> + im->ip_after_call = &((u32 *)ro_image)[ctx->idx];
> EMIT(PPC_RAW_NOP());
> }
>
> @@ -912,8 +918,14 @@ static int __arch_prepare_bpf_trampoline(struct bpf_tramp_image *im, void *rw_im
> }
>
> if (flags & BPF_TRAMP_F_CALL_ORIG) {
> - im->ip_epilogue = &((u32 *)ro_image)[ctx->idx];
> - PPC_LI_ADDR(_R3, im);
> + if (im)
> + im->ip_epilogue = &((u32 *)ro_image)[ctx->idx];
> + /*
> + * Emit maximum possible instructions while getting the size of
> + * bpf trampoline to ensure trampoline JIT code doesn't overflow.
> + */
> + PPC_LI_ADDR(_R3, im ? (unsigned long)im :
> + (unsigned long)(~(1UL << (BITS_PER_LONG - 1))));
> ret = bpf_jit_emit_func_call_rel(image, ro_image, ctx,
> (unsigned long)__bpf_tramp_exit);
> if (ret)
> @@ -972,7 +984,6 @@ static int __arch_prepare_bpf_trampoline(struct bpf_tramp_image *im, void *rw_im
> int arch_bpf_trampoline_size(const struct btf_func_model *m, u32 flags,
> struct bpf_tramp_links *tlinks, void *func_addr)
> {
> - struct bpf_tramp_image im;
> void *image;
> int ret;
>
> @@ -988,7 +999,13 @@ int arch_bpf_trampoline_size(const struct btf_func_model *m, u32 flags,
> if (!image)
> return -ENOMEM;
>
> - ret = __arch_prepare_bpf_trampoline(&im, image, image + PAGE_SIZE, image,
> + /*
> + * Pass NULL as bpf_tramp_image pointer to differentiate the intent to get the
> + * buffer size for trampoline here. This differentiation helps in accounting for
> + * maximum possible instructions if the JIT code size is likely to vary during
> + * the actual JIT compile of the trampoline.
> + */
> + ret = __arch_prepare_bpf_trampoline(NULL, image, image + PAGE_SIZE, image,
> m, flags, tlinks, func_addr);
> bpf_jit_free_exec(image);
Tested this patch by applying on main line kernel, and ran the tests 5
times, and issue is not seen. Hence the reported issue is fixed.
HeadCommit on which this patch was applied:
1e26c5e28ca5821a824e90dd359556f5e9e7b89f.
Please add below tag.
Tested-by: Venkat Rao Bagalkote <venkat88@linux.ibm.com>
Regards,
Venkat.
>
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [RESEND PATCH] powerpc64/bpf: fix JIT code size calculation of bpf trampoline
2025-03-26 14:34 [RESEND PATCH] powerpc64/bpf: fix JIT code size calculation of bpf trampoline Hari Bathini
2025-03-26 17:21 ` Venkat Rao Bagalkote
@ 2025-04-03 15:45 ` Naveen N Rao
2025-04-07 6:38 ` Hari Bathini
1 sibling, 1 reply; 4+ messages in thread
From: Naveen N Rao @ 2025-04-03 15:45 UTC (permalink / raw)
To: Hari Bathini
Cc: linuxppc-dev, bpf, Madhavan Srinivasan, Venkat Rao Bagalkote,
Michael Ellerman, Daniel Borkmann, Nicholas Piggin,
Alexei Starovoitov, Andrii Nakryiko, Christophe Leroy, stable
On Wed, Mar 26, 2025 at 08:04:22PM +0530, Hari Bathini wrote:
> The JIT compile of ldimm instructions can be anywhere between 1-5
> instructions long depending on the value being loaded.
>
> arch_bpf_trampoline_size() provides JIT size of the BPF trampoline
> before the buffer for JIT'ing it is allocated. BPF trampoline JIT
> code has ldimm instructions that need to load the value of pointer
> to struct bpf_tramp_image. But this pointer value is not same while
> calling arch_bpf_trampoline_size() & arch_prepare_bpf_trampoline().
> So, the size arrived at using arch_bpf_trampoline_size() can vary
> from the size needed in arch_prepare_bpf_trampoline(). When the
> number of ldimm instructions emitted in arch_bpf_trampoline_size()
> is less than the number of ldimm instructions emitted during the
> actual JIT compile of trampoline, the below warning is produced:
>
> WARNING: CPU: 8 PID: 204190 at arch/powerpc/net/bpf_jit_comp.c:981 __arch_prepare_bpf_trampoline.isra.0+0xd2c/0xdcc
>
> which is:
>
> /* Make sure the trampoline generation logic doesn't overflow */
> if (image && WARN_ON_ONCE(&image[ctx->idx] >
> (u32 *)rw_image_end - BPF_INSN_SAFETY)) {
>
> Pass NULL as the first argument to __arch_prepare_bpf_trampoline()
> call from arch_bpf_trampoline_size() function, to differentiate it
> from how arch_prepare_bpf_trampoline() calls it and ensure maximum
> possible instructions are emitted in arch_bpf_trampoline_size() for
> ldimm instructions that load a different value during the actual JIT
> compile of BPF trampoline.
>
> Fixes: d243b62b7bd3 ("powerpc64/bpf: Add support for bpf trampolines")
> Reported-by: Venkat Rao Bagalkote <venkat88@linux.ibm.com>
> Closes: https://lore.kernel.org/all/6168bfc8-659f-4b5a-a6fb-90a916dde3b3@linux.ibm.com/
> Cc: stable@vger.kernel.org # v6.13+
> Signed-off-by: Hari Bathini <hbathini@linux.ibm.com>
> ---
>
> * Removed a redundant '/' accidently added in a comment and resending.
>
> arch/powerpc/net/bpf_jit_comp.c | 29 +++++++++++++++++++++++------
> 1 file changed, 23 insertions(+), 6 deletions(-)
>
> diff --git a/arch/powerpc/net/bpf_jit_comp.c b/arch/powerpc/net/bpf_jit_comp.c
> index 2991bb171a9b..c94717ccb2bd 100644
> --- a/arch/powerpc/net/bpf_jit_comp.c
> +++ b/arch/powerpc/net/bpf_jit_comp.c
> @@ -833,7 +833,12 @@ static int __arch_prepare_bpf_trampoline(struct bpf_tramp_image *im, void *rw_im
> EMIT(PPC_RAW_STL(_R26, _R1, nvr_off + SZL));
>
> if (flags & BPF_TRAMP_F_CALL_ORIG) {
> - PPC_LI_ADDR(_R3, (unsigned long)im);
> + /*
> + * Emit maximum possible instructions while getting the size of
> + * bpf trampoline to ensure trampoline JIT code doesn't overflow.
> + */
> + PPC_LI_ADDR(_R3, im ? (unsigned long)im :
> + (unsigned long)(~(1UL << (BITS_PER_LONG - 1))));
We generally rely on a NULL 'image' to detect a dummy pass. See commit
d3921cbb6cd6 ("powerpc/bpf: Only pad length-variable code at initial
pass"), for instance. Have you considered updating PPC_LI64() and
PPC_LI32() to simply emit a fixed number of nops if image is NULL?
- Naveen
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [RESEND PATCH] powerpc64/bpf: fix JIT code size calculation of bpf trampoline
2025-04-03 15:45 ` Naveen N Rao
@ 2025-04-07 6:38 ` Hari Bathini
0 siblings, 0 replies; 4+ messages in thread
From: Hari Bathini @ 2025-04-07 6:38 UTC (permalink / raw)
To: Naveen N Rao
Cc: linuxppc-dev, bpf, Madhavan Srinivasan, Venkat Rao Bagalkote,
Michael Ellerman, Daniel Borkmann, Nicholas Piggin,
Alexei Starovoitov, Andrii Nakryiko, Christophe Leroy, stable
Hi Naveen,
Thanks for the review.
On 03/04/25 9:15 pm, Naveen N Rao wrote:
> On Wed, Mar 26, 2025 at 08:04:22PM +0530, Hari Bathini wrote:
>> The JIT compile of ldimm instructions can be anywhere between 1-5
>> instructions long depending on the value being loaded.
>>
>> arch_bpf_trampoline_size() provides JIT size of the BPF trampoline
>> before the buffer for JIT'ing it is allocated. BPF trampoline JIT
>> code has ldimm instructions that need to load the value of pointer
>> to struct bpf_tramp_image. But this pointer value is not same while
>> calling arch_bpf_trampoline_size() & arch_prepare_bpf_trampoline().
>> So, the size arrived at using arch_bpf_trampoline_size() can vary
>> from the size needed in arch_prepare_bpf_trampoline(). When the
>> number of ldimm instructions emitted in arch_bpf_trampoline_size()
>> is less than the number of ldimm instructions emitted during the
>> actual JIT compile of trampoline, the below warning is produced:
>>
>> WARNING: CPU: 8 PID: 204190 at arch/powerpc/net/bpf_jit_comp.c:981 __arch_prepare_bpf_trampoline.isra.0+0xd2c/0xdcc
>>
>> which is:
>>
>> /* Make sure the trampoline generation logic doesn't overflow */
>> if (image && WARN_ON_ONCE(&image[ctx->idx] >
>> (u32 *)rw_image_end - BPF_INSN_SAFETY)) {
>>
>> Pass NULL as the first argument to __arch_prepare_bpf_trampoline()
>> call from arch_bpf_trampoline_size() function, to differentiate it
>> from how arch_prepare_bpf_trampoline() calls it and ensure maximum
>> possible instructions are emitted in arch_bpf_trampoline_size() for
>> ldimm instructions that load a different value during the actual JIT
>> compile of BPF trampoline.
>>
>> Fixes: d243b62b7bd3 ("powerpc64/bpf: Add support for bpf trampolines")
>> Reported-by: Venkat Rao Bagalkote <venkat88@linux.ibm.com>
>> Closes: https://lore.kernel.org/all/6168bfc8-659f-4b5a-a6fb-90a916dde3b3@linux.ibm.com/
>> Cc: stable@vger.kernel.org # v6.13+
>> Signed-off-by: Hari Bathini <hbathini@linux.ibm.com>
>> ---
>>
>> * Removed a redundant '/' accidently added in a comment and resending.
>>
>> arch/powerpc/net/bpf_jit_comp.c | 29 +++++++++++++++++++++++------
>> 1 file changed, 23 insertions(+), 6 deletions(-)
>>
>> diff --git a/arch/powerpc/net/bpf_jit_comp.c b/arch/powerpc/net/bpf_jit_comp.c
>> index 2991bb171a9b..c94717ccb2bd 100644
>> --- a/arch/powerpc/net/bpf_jit_comp.c
>> +++ b/arch/powerpc/net/bpf_jit_comp.c
>> @@ -833,7 +833,12 @@ static int __arch_prepare_bpf_trampoline(struct bpf_tramp_image *im, void *rw_im
>> EMIT(PPC_RAW_STL(_R26, _R1, nvr_off + SZL));
>>
>> if (flags & BPF_TRAMP_F_CALL_ORIG) {
>> - PPC_LI_ADDR(_R3, (unsigned long)im);
>> + /*
>> + * Emit maximum possible instructions while getting the size of
>> + * bpf trampoline to ensure trampoline JIT code doesn't overflow.
>> + */
>> + PPC_LI_ADDR(_R3, im ? (unsigned long)im :
>> + (unsigned long)(~(1UL << (BITS_PER_LONG - 1))));
>
> We generally rely on a NULL 'image' to detect a dummy pass. See commit
> d3921cbb6cd6 ("powerpc/bpf: Only pad length-variable code at initial
> pass"), for instance. Have you considered updating PPC_LI64() and
> PPC_LI32() to simply emit a fixed number of nops if image is NULL?
Did want to use image as NULL for the dummy pass but decided to do it
as a clean up later with bpf_jit_emit_func_call_rel(), PPC_LI64(),
PPC_LI32() and create_branch() needing it. But on second thoughts,
we are probably better off by accounting for max possible instructions
for all those cases (in the dummy pass) as part of this fix itself.
Will send a V2 soon...
Thanks
Hari
^ permalink raw reply [flat|nested] 4+ messages in thread
end of thread, other threads:[~2025-04-07 6:39 UTC | newest]
Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-03-26 14:34 [RESEND PATCH] powerpc64/bpf: fix JIT code size calculation of bpf trampoline Hari Bathini
2025-03-26 17:21 ` Venkat Rao Bagalkote
2025-04-03 15:45 ` Naveen N Rao
2025-04-07 6:38 ` Hari Bathini
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).