Skip to content

Commit 89d21e2

Browse files
chleroympe
authored andcommitted
powerpc/bpf/32: Fix Oops on tail call tests
test_bpf tail call tests end up as: test_bpf: #0 Tail call leaf jited:1 85 PASS test_bpf: #1 Tail call 2 jited:1 111 PASS test_bpf: #2 Tail call 3 jited:1 145 PASS test_bpf: #3 Tail call 4 jited:1 170 PASS test_bpf: #4 Tail call load/store leaf jited:1 190 PASS test_bpf: #5 Tail call load/store jited:1 BUG: Unable to handle kernel data access on write at 0xf1b4e000 Faulting instruction address: 0xbe86b710 Oops: Kernel access of bad area, sig: 11 [#1] BE PAGE_SIZE=4K MMU=Hash PowerMac Modules linked in: test_bpf(+) CPU: 0 PID: 97 Comm: insmod Not tainted 6.1.0-rc4+ #195 Hardware name: PowerMac3,1 750CL 0x87210 PowerMac NIP: be86b710 LR: be857e88 CTR: be86b704 REGS: f1b4df20 TRAP: 0300 Not tainted (6.1.0-rc4+) MSR: 00009032 <EE,ME,IR,DR,RI> CR: 28008242 XER: 00000000 DAR: f1b4e000 DSISR: 42000000 GPR00: 00000001 f1b4dfe0 c11d2280 00000000 00000000 00000000 00000002 00000000 GPR08: f1b4e000 be86b704 f1b4e000 00000000 00000000 100d816a f2440000 fe73baa8 GPR16: f2458000 00000000 c1941ae4 f1fe2248 00000045 c0de0000 f2458030 00000000 GPR24: 000003e8 0000000f f2458000 f1b4dc90 3e584b46 00000000 f24466a0 c1941a00 NIP [be86b710] 0xbe86b710 LR [be857e88] __run_one+0xec/0x264 [test_bpf] Call Trace: [f1b4dfe0] [00000002] 0x2 (unreliable) Instruction dump: XXXXXXXX XXXXXXXX XXXXXXXX XXXXXXXX XXXXXXXX XXXXXXXX XXXXXXXX XXXXXXXX XXXXXXXX XXXXXXXX XXXXXXXX XXXXXXXX XXXXXXXX XXXXXXXX XXXXXXXX XXXXXXXX ---[ end trace 0000000000000000 ]--- This is a tentative to write above the stack. The problem is encoutered with tests added by commit 38608ee ("bpf, tests: Add load store test case for tail call") This happens because tail call is done to a BPF prog with a different stack_depth. At the time being, the stack is kept as is when the caller tail calls its callee. But at exit, the callee restores the stack based on its own properties. Therefore here, at each run, r1 is erroneously increased by 32 - 16 = 16 bytes. This was done that way in order to pass the tail call count from caller to callee through the stack. As powerpc32 doesn't have a red zone in the stack, it was necessary the maintain the stack as is for the tail call. But it was not anticipated that the BPF frame size could be different. Let's take a new approach. Use register r4 to carry the tail call count during the tail call, and save it into the stack at function entry if required. This means the input parameter must be in r3, which is more correct as it is a 32 bits parameter, then tail call better match with normal BPF function entry, the down side being that we move that input parameter back and forth between r3 and r4. That can be optimised later. Doing that also has the advantage of maximising the common parts between tail calls and a normal function exit. With the fix, tail call tests are now successfull: test_bpf: #0 Tail call leaf jited:1 53 PASS test_bpf: #1 Tail call 2 jited:1 115 PASS test_bpf: #2 Tail call 3 jited:1 154 PASS test_bpf: #3 Tail call 4 jited:1 165 PASS test_bpf: #4 Tail call load/store leaf jited:1 101 PASS test_bpf: #5 Tail call load/store jited:1 141 PASS test_bpf: #6 Tail call error path, max count reached jited:1 994 PASS test_bpf: #7 Tail call count preserved across function calls jited:1 140975 PASS test_bpf: #8 Tail call error path, NULL target jited:1 110 PASS test_bpf: #9 Tail call error path, index out of range jited:1 69 PASS test_bpf: test_tail_calls: Summary: 10 PASSED, 0 FAILED, [10/10 JIT'ed] Suggested-by: Naveen N. Rao <naveen.n.rao@linux.vnet.ibm.com> Fixes: 51c66ad ("powerpc/bpf: Implement extended BPF on PPC32") Cc: stable@vger.kernel.org Signed-off-by: Christophe Leroy <christophe.leroy@csgroup.eu> Tested-by: Naveen N. Rao <naveen.n.rao@linux.vnet.ibm.com Signed-off-by: Michael Ellerman <mpe@ellerman.id.au> Link: https://lore.kernel.org/r/757acccb7fbfc78efa42dcf3c974b46678198905.1669278887.git.christophe.leroy@csgroup.eu
1 parent eb761a1 commit 89d21e2

File tree

1 file changed

+21
-31
lines changed

1 file changed

+21
-31
lines changed

arch/powerpc/net/bpf_jit_comp32.c

+21-31
Original file line numberDiff line numberDiff line change
@@ -113,23 +113,19 @@ void bpf_jit_build_prologue(u32 *image, struct codegen_context *ctx)
113113
{
114114
int i;
115115

116-
/* First arg comes in as a 32 bits pointer. */
117-
EMIT(PPC_RAW_MR(bpf_to_ppc(BPF_REG_1), _R3));
118-
EMIT(PPC_RAW_LI(bpf_to_ppc(BPF_REG_1) - 1, 0));
116+
/* Initialize tail_call_cnt, to be skipped if we do tail calls. */
117+
EMIT(PPC_RAW_LI(_R4, 0));
118+
119+
#define BPF_TAILCALL_PROLOGUE_SIZE 4
120+
119121
EMIT(PPC_RAW_STWU(_R1, _R1, -BPF_PPC_STACKFRAME(ctx)));
120122

121-
/*
122-
* Initialize tail_call_cnt in stack frame if we do tail calls.
123-
* Otherwise, put in NOPs so that it can be skipped when we are
124-
* invoked through a tail call.
125-
*/
126123
if (ctx->seen & SEEN_TAILCALL)
127-
EMIT(PPC_RAW_STW(bpf_to_ppc(BPF_REG_1) - 1, _R1,
128-
bpf_jit_stack_offsetof(ctx, BPF_PPC_TC)));
129-
else
130-
EMIT(PPC_RAW_NOP());
124+
EMIT(PPC_RAW_STW(_R4, _R1, bpf_jit_stack_offsetof(ctx, BPF_PPC_TC)));
131125

132-
#define BPF_TAILCALL_PROLOGUE_SIZE 16
126+
/* First arg comes in as a 32 bits pointer. */
127+
EMIT(PPC_RAW_MR(bpf_to_ppc(BPF_REG_1), _R3));
128+
EMIT(PPC_RAW_LI(bpf_to_ppc(BPF_REG_1) - 1, 0));
133129

134130
/*
135131
* We need a stack frame, but we don't necessarily need to
@@ -170,24 +166,24 @@ static void bpf_jit_emit_common_epilogue(u32 *image, struct codegen_context *ctx
170166
for (i = BPF_PPC_NVR_MIN; i <= 31; i++)
171167
if (bpf_is_seen_register(ctx, i))
172168
EMIT(PPC_RAW_LWZ(i, _R1, bpf_jit_stack_offsetof(ctx, i)));
173-
}
174-
175-
void bpf_jit_build_epilogue(u32 *image, struct codegen_context *ctx)
176-
{
177-
EMIT(PPC_RAW_MR(_R3, bpf_to_ppc(BPF_REG_0)));
178-
179-
bpf_jit_emit_common_epilogue(image, ctx);
180-
181-
/* Tear down our stack frame */
182169

183170
if (ctx->seen & SEEN_FUNC)
184171
EMIT(PPC_RAW_LWZ(_R0, _R1, BPF_PPC_STACKFRAME(ctx) + PPC_LR_STKOFF));
185172

173+
/* Tear down our stack frame */
186174
EMIT(PPC_RAW_ADDI(_R1, _R1, BPF_PPC_STACKFRAME(ctx)));
187175

188176
if (ctx->seen & SEEN_FUNC)
189177
EMIT(PPC_RAW_MTLR(_R0));
190178

179+
}
180+
181+
void bpf_jit_build_epilogue(u32 *image, struct codegen_context *ctx)
182+
{
183+
EMIT(PPC_RAW_MR(_R3, bpf_to_ppc(BPF_REG_0)));
184+
185+
bpf_jit_emit_common_epilogue(image, ctx);
186+
191187
EMIT(PPC_RAW_BLR());
192188
}
193189

@@ -244,7 +240,6 @@ static int bpf_jit_emit_tail_call(u32 *image, struct codegen_context *ctx, u32 o
244240
EMIT(PPC_RAW_RLWINM(_R3, b2p_index, 2, 0, 29));
245241
EMIT(PPC_RAW_ADD(_R3, _R3, b2p_bpf_array));
246242
EMIT(PPC_RAW_LWZ(_R3, _R3, offsetof(struct bpf_array, ptrs)));
247-
EMIT(PPC_RAW_STW(_R0, _R1, bpf_jit_stack_offsetof(ctx, BPF_PPC_TC)));
248243

249244
/*
250245
* if (prog == NULL)
@@ -255,19 +250,14 @@ static int bpf_jit_emit_tail_call(u32 *image, struct codegen_context *ctx, u32 o
255250

256251
/* goto *(prog->bpf_func + prologue_size); */
257252
EMIT(PPC_RAW_LWZ(_R3, _R3, offsetof(struct bpf_prog, bpf_func)));
258-
259-
if (ctx->seen & SEEN_FUNC)
260-
EMIT(PPC_RAW_LWZ(_R0, _R1, BPF_PPC_STACKFRAME(ctx) + PPC_LR_STKOFF));
261-
262253
EMIT(PPC_RAW_ADDIC(_R3, _R3, BPF_TAILCALL_PROLOGUE_SIZE));
263-
264-
if (ctx->seen & SEEN_FUNC)
265-
EMIT(PPC_RAW_MTLR(_R0));
266-
267254
EMIT(PPC_RAW_MTCTR(_R3));
268255

269256
EMIT(PPC_RAW_MR(_R3, bpf_to_ppc(BPF_REG_1)));
270257

258+
/* Put tail_call_cnt in r4 */
259+
EMIT(PPC_RAW_MR(_R4, _R0));
260+
271261
/* tear restore NVRs, ... */
272262
bpf_jit_emit_common_epilogue(image, ctx);
273263

0 commit comments

Comments
 (0)