| From 2f96e88c6d7730169a67b23cafabf8a0c8599f1d Mon Sep 17 00:00:00 2001 |
| From: Sasha Levin <sashal@kernel.org> |
| Date: Wed, 1 Feb 2023 11:04:25 +0100 |
| Subject: powerpc/bpf/32: Only set a stack frame when necessary |
| |
| From: Christophe Leroy <christophe.leroy@csgroup.eu> |
| |
| [ Upstream commit d084dcf256bc4565b4b1af9b00297ac7b51c7049 ] |
| |
| Until now a stack frame was set at all time due to the need |
| to keep tail call counter in the stack. |
| |
| But since commit 89d21e259a94 ("powerpc/bpf/32: Fix Oops on tail call |
| tests") the tail call counter is passed via register r4. It is therefore |
| not necessary anymore to have a stack frame for that. |
| |
| Just like PPC64, implement bpf_has_stack_frame() and only sets the frame |
| when needed. |
| |
| The difference with PPC64 is that PPC32 doesn't have a redzone, so |
| the stack is required as soon as non volatile registers are used or |
| when tail call count is set up. |
| |
| Signed-off-by: Christophe Leroy <christophe.leroy@csgroup.eu> |
| [mpe: Fix commit reference in change log] |
| Signed-off-by: Michael Ellerman <mpe@ellerman.id.au> |
| Link: https://lore.kernel.org/r/62d7b654a3cfe73d998697cb29bbc5ffd89bfdb1.1675245773.git.christophe.leroy@csgroup.eu |
| Signed-off-by: Sasha Levin <sashal@kernel.org> |
| --- |
| arch/powerpc/net/bpf_jit_comp32.c | 20 ++++++++++++++++++-- |
| 1 file changed, 18 insertions(+), 2 deletions(-) |
| |
| diff --git a/arch/powerpc/net/bpf_jit_comp32.c b/arch/powerpc/net/bpf_jit_comp32.c |
| index a379b0ce19ffa..8643b2c8b76ef 100644 |
| --- a/arch/powerpc/net/bpf_jit_comp32.c |
| +++ b/arch/powerpc/net/bpf_jit_comp32.c |
| @@ -79,6 +79,20 @@ static int bpf_jit_stack_offsetof(struct codegen_context *ctx, int reg) |
| #define SEEN_NVREG_FULL_MASK 0x0003ffff /* Non volatile registers r14-r31 */ |
| #define SEEN_NVREG_TEMP_MASK 0x00001e01 /* BPF_REG_5, BPF_REG_AX, TMP_REG */ |
| |
| +static inline bool bpf_has_stack_frame(struct codegen_context *ctx) |
| +{ |
| + /* |
| + * We only need a stack frame if: |
| + * - we call other functions (kernel helpers), or |
| + * - we use non volatile registers, or |
| + * - we use tail call counter |
| + * - the bpf program uses its stack area |
| + * The latter condition is deduced from the usage of BPF_REG_FP |
| + */ |
| + return ctx->seen & (SEEN_FUNC | SEEN_TAILCALL | SEEN_NVREG_FULL_MASK) || |
| + bpf_is_seen_register(ctx, bpf_to_ppc(BPF_REG_FP)); |
| +} |
| + |
| void bpf_jit_realloc_regs(struct codegen_context *ctx) |
| { |
| unsigned int nvreg_mask; |
| @@ -118,7 +132,8 @@ void bpf_jit_build_prologue(u32 *image, struct codegen_context *ctx) |
| |
| #define BPF_TAILCALL_PROLOGUE_SIZE 4 |
| |
| - EMIT(PPC_RAW_STWU(_R1, _R1, -BPF_PPC_STACKFRAME(ctx))); |
| + if (bpf_has_stack_frame(ctx)) |
| + EMIT(PPC_RAW_STWU(_R1, _R1, -BPF_PPC_STACKFRAME(ctx))); |
| |
| if (ctx->seen & SEEN_TAILCALL) |
| EMIT(PPC_RAW_STW(_R4, _R1, bpf_jit_stack_offsetof(ctx, BPF_PPC_TC))); |
| @@ -171,7 +186,8 @@ static void bpf_jit_emit_common_epilogue(u32 *image, struct codegen_context *ctx |
| EMIT(PPC_RAW_LWZ(_R0, _R1, BPF_PPC_STACKFRAME(ctx) + PPC_LR_STKOFF)); |
| |
| /* Tear down our stack frame */ |
| - EMIT(PPC_RAW_ADDI(_R1, _R1, BPF_PPC_STACKFRAME(ctx))); |
| + if (bpf_has_stack_frame(ctx)) |
| + EMIT(PPC_RAW_ADDI(_R1, _R1, BPF_PPC_STACKFRAME(ctx))); |
| |
| if (ctx->seen & SEEN_FUNC) |
| EMIT(PPC_RAW_MTLR(_R0)); |
| -- |
| 2.39.2 |
| |