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

Hari Bathini hbathini at linux.ibm.com
Wed Mar 4 00:46:20 AEDT 2026



On 23/02/26 2:33 pm, adubey wrote:
> 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 at kernel.org
>> Closes:
>> https://lore.kernel.org/ 
>> bpf/2a310e86a59eb4c44c3ac9e5647814469d9c955580c9c0f1b3d9ca4a44717a34 at mail.kernel.org/
>> Fixes: 11d45eee9f42 ("powerpc64/bpf: Additional NVR handling for 
>> bpf_throw")
>> Signed-off-by: Hari Bathini <hbathini at linux.ibm.com>
>> ---
>>
>> Changes since v1:
>> * Fixed incorrect use of PPC_RAW_SUB() as pointed out by
>>   bot+bpf-ci at 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?

Did think about it but went with this approach to keep the tearing down
of the stack consistent for all cases. Addressed the other comments
and posted v3.

- Hari


More information about the Linuxppc-dev mailing list