Re: [PATCH v2 5/5] powerpc64/bpf: fix handling of BPF stack in exception callback

adubey
2026-02-23T09:04:20Z

On 2026-02-20 12:09, Hari Bathini wrote:
> Exception callback reuses the stack frame of exception boundary. When
> exception boundary and exception callback programs have different BPF
> stack depth, the current stack unwind in exception callback will fail.
> Adjust the stack frame size of exception callback, in its prologue,
> if its BPF stack depth is different from that of exception boundary.
>
> Reported-by: bot+bpf-ci@kernel.org
> Closes:
> https://lore.kernel.org/bpf/2a310e86a59eb4c44c3ac9e5647814469d9c955580c9c0f1b3d9ca4a44717a34@mail.kernel.org/
> Fixes: 11d45eee9f42 ("powerpc64/bpf: Additional NVR handling for
> bpf_throw")
> Signed-off-by: Hari Bathini <hbathini@linux.ibm.com>
> ---
>
> Changes since v1:
> * Fixed incorrect use of PPC_RAW_SUB() as pointed out by
> bot+bpf-ci@kernel.org.
>
>
> arch/powerpc/net/bpf_jit_comp64.c | 30 ++++++++++++++++++++++--------
> 1 file changed, 22 insertions(+), 8 deletions(-)
>
> diff --git a/arch/powerpc/net/bpf_jit_comp64.c
> b/arch/powerpc/net/bpf_jit_comp64.c
> index 5d4d2bb23cef..33b2a7fd9067 100644
> --- a/arch/powerpc/net/bpf_jit_comp64.c
> +++ b/arch/powerpc/net/bpf_jit_comp64.c
> @@ -32,14 +32,15 @@
> *
> * [ prev sp ] <-------------
> * [ tail_call_info ] 8 |
> - * [ nv gpr save area ] 6*8 + (12*8) |
> + * [ nv gpr save area ] 6*8 |
> + * [ addl. nv gpr save area] (12*8) | <--- exception
> boundary/callback program
> * [ local_tmp_var ] 24 |
> * fp (r31) --> [ ebpf stack space ] upto 512 |
> * [ frame header ] 32/112 |
> * sp (r1) ---> [ stack pointer ] --------------
> *
> * Additional (12*8) in 'nv gpr save area' only in case of
> - * exception boundary.
> + * exception boundary/callback.
> */
>
> /* BPF non-volatile registers save area size */
> @@ -128,12 +129,13 @@ static inline bool bpf_has_stack_frame(struct
> codegen_context *ctx)
> * [ ... ] |
> * sp (r1) ---> [ stack pointer ] --------------
> * [ tail_call_info ] 8
> - * [ nv gpr save area ] 6*8 + (12*8)
> + * [ nv gpr save area ] 6*8
> + * [ addl. nv gpr save area] (12*8) <--- exception boundary/callback
> program
> * [ local_tmp_var ] 24
> * [ unused red zone ] 224
> *
> * Additional (12*8) in 'nv gpr save area' only in case of
> - * exception boundary.
> + * exception boundary/callback.
> */
> static int bpf_jit_stack_local(struct codegen_context *ctx)
> {
> @@ -240,10 +242,6 @@ void bpf_jit_build_prologue(u32 *image, struct
> codegen_context *ctx)
>
> if (bpf_has_stack_frame(ctx) && !ctx->exception_cb) {
> /*
> - * exception_cb uses boundary frame after stack walk.
> - * It can simply use redzone, this optimization reduces
> - * stack walk loop by one level.
> - *
> * We need a stack frame, but we don't necessarily need to
> * save/restore LR unless we call other functions
> */
> @@ -287,6 +285,22 @@ void bpf_jit_build_prologue(u32 *image, struct
> codegen_context *ctx)
> * program(main prog) as third arg
> */
> EMIT(PPC_RAW_MR(_R1, _R5));
> + /*
> + * Exception callback reuses the stack frame of exception boundary.
> + * But BPF stack depth of exception callback and exception boundary
> + * don't have to be same. If BPF stack depth is different, adjust
> the
> + * stack frame size considering BPF stack depth of exception
> callback.
> + * The non-volatile register save area remains unchanged. These non-
> + * volatile registers are restored in exception callback's epilogue.
> + */
> + EMIT(PPC_RAW_LD(bpf_to_ppc(TMP_REG_1), _R5, 0));
> + EMIT(PPC_RAW_SUB(bpf_to_ppc(TMP_REG_2), bpf_to_ppc(TMP_REG_1),
> _R1));
> + EMIT(PPC_RAW_ADDI(bpf_to_ppc(TMP_REG_2), bpf_to_ppc(TMP_REG_2),
> + -BPF_PPC_EXC_STACKFRAME));
> + EMIT(PPC_RAW_CMPLDI(bpf_to_ppc(TMP_REG_2), ctx->stack_size));
> + PPC_BCC_CONST_SHORT(COND_EQ, 12);
Can we avoid resizing when boundary_stack is greater? I think it's safe,
NVR will be intact anyway and any reference within bounds of larger
size.
Any corner case possible?
> + EMIT(PPC_RAW_MR(_R1, bpf_to_ppc(TMP_REG_1)));
> + EMIT(PPC_RAW_STDU(_R1, _R1, -(BPF_PPC_EXC_STACKFRAME +
> ctx->stack_size)));
Do we need to setup FP again? If I get it right, still the FP is
pointing to older frame, any reference in
callback will resolve to old frame.
> }
>
> /*
-Abhishek