Skip to content

Commit 520e02e

Browse files
author
Fox Snowpatch
committed
1 parent 5c2c0ba commit 520e02e

4 files changed

Lines changed: 111 additions & 12 deletions

File tree

arch/powerpc/net/Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,4 @@
22
#
33
# Arch-specific network modules
44
#
5-
obj-$(CONFIG_BPF_JIT) += bpf_jit_comp.o bpf_jit_comp$(BITS).o
5+
obj-$(CONFIG_BPF_JIT) += bpf_jit_comp.o bpf_jit_comp$(BITS).o bpf_timed_may_goto.o

arch/powerpc/net/bpf_jit_comp.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -537,6 +537,11 @@ bool bpf_jit_supports_subprog_tailcalls(void)
537537
return IS_ENABLED(CONFIG_PPC64);
538538
}
539539

540+
bool bpf_jit_supports_timed_may_goto(void)
541+
{
542+
return IS_ENABLED(CONFIG_PPC64);
543+
}
544+
540545
bool bpf_jit_supports_kfunc_call(void)
541546
{
542547
return IS_ENABLED(CONFIG_PPC64);

arch/powerpc/net/bpf_jit_comp64.c

Lines changed: 48 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -451,10 +451,28 @@ void arch_bpf_stack_walk(bool (*consume_fn)(void *, u64, u64, u64), void *cookie
451451
}
452452
}
453453

454+
static int bpf_jit_emit_func_call(u32 *image, struct codegen_context *ctx, u64 func_addr, int reg)
455+
{
456+
long reladdr;
457+
458+
reladdr = func_addr - kernel_toc_addr();
459+
if (reladdr > 0x7FFFFFFF || reladdr < -(0x80000000L)) {
460+
pr_err("eBPF: address of %ps out of range of kernel_toc.\n", (void *)func_addr);
461+
return -ERANGE;
462+
}
463+
464+
EMIT(PPC_RAW_ADDIS(reg, _R2, PPC_HA(reladdr)));
465+
EMIT(PPC_RAW_ADDI(reg, reg, PPC_LO(reladdr)));
466+
EMIT(PPC_RAW_MTCTR(reg));
467+
EMIT(PPC_RAW_BCTRL());
468+
469+
return 0;
470+
}
471+
454472
int bpf_jit_emit_func_call_rel(u32 *image, u32 *fimage, struct codegen_context *ctx, u64 func)
455473
{
456474
unsigned long func_addr = func ? ppc_function_entry((void *)func) : 0;
457-
long reladdr;
475+
int ret;
458476

459477
/* bpf to bpf call, func is not known in the initial pass. Emit 5 nops as a placeholder */
460478
if (!func) {
@@ -469,6 +487,7 @@ int bpf_jit_emit_func_call_rel(u32 *image, u32 *fimage, struct codegen_context *
469487
}
470488

471489
#ifdef CONFIG_PPC_KERNEL_PCREL
490+
long reladdr;
472491
reladdr = func_addr - local_paca->kernelbase;
473492

474493
/*
@@ -507,16 +526,9 @@ int bpf_jit_emit_func_call_rel(u32 *image, u32 *fimage, struct codegen_context *
507526
EMIT(PPC_RAW_BCTRL());
508527
#else
509528
if (core_kernel_text(func_addr)) {
510-
reladdr = func_addr - kernel_toc_addr();
511-
if (reladdr > 0x7FFFFFFF || reladdr < -(0x80000000L)) {
512-
pr_err("eBPF: address of %ps out of range of kernel_toc.\n", (void *)func);
513-
return -ERANGE;
514-
}
515-
516-
EMIT(PPC_RAW_ADDIS(_R12, _R2, PPC_HA(reladdr)));
517-
EMIT(PPC_RAW_ADDI(_R12, _R12, PPC_LO(reladdr)));
518-
EMIT(PPC_RAW_MTCTR(_R12));
519-
EMIT(PPC_RAW_BCTRL());
529+
ret = bpf_jit_emit_func_call(image, ctx, func_addr, _R12);
530+
if (ret)
531+
return ret;
520532
} else {
521533
if (IS_ENABLED(CONFIG_PPC64_ELF_ABI_V1)) {
522534
/* func points to the function descriptor */
@@ -1755,6 +1767,31 @@ int bpf_jit_build_body(struct bpf_prog *fp, u32 *image, u32 *fimage, struct code
17551767
if (ret < 0)
17561768
return ret;
17571769

1770+
/*
1771+
* Call to arch_bpf_timed_may_goto() is emitted by the
1772+
* verifier and called with custom calling convention with
1773+
* first argument and return value in BPF_REG_AX (_R12).
1774+
*
1775+
* The generic helper or bpf function call emission path
1776+
* may use the same scratch register as BPF_REG_AX to
1777+
* materialize the target address. This would clobber AX
1778+
* and break timed may_goto semantics.
1779+
*
1780+
* Emit a minimal indirect call sequence here using a temp
1781+
* register and skip the normal post-call return-value move.
1782+
*/
1783+
1784+
if (func_addr == (u64)arch_bpf_timed_may_goto) {
1785+
#ifdef CONFIG_PPC_KERNEL_PCREL
1786+
PPC_LI_ADDR(tmp1_reg, func_addr);
1787+
EMIT(PPC_RAW_MTCTR(tmp1_reg));
1788+
EMIT(PPC_RAW_BCTRL());
1789+
#else
1790+
bpf_jit_emit_func_call(image, ctx, func_addr, tmp1_reg);
1791+
#endif
1792+
break;
1793+
}
1794+
17581795
/* Take care of powerpc ABI requirements before kfunc call */
17591796
if (insn[i].src_reg == BPF_PSEUDO_KFUNC_CALL) {
17601797
if (prepare_for_kfunc_call(fp, image, ctx, &insn[i]))
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
/* SPDX-License-Identifier: GPL-2.0 */
2+
/* Copyright (c) 2025 IBM Corporation, Saket Kumar Bhaskar <skb99@linux.ibm.com> */
3+
4+
#include <linux/linkage.h>
5+
#include <asm/ppc_asm.h>
6+
7+
/*
8+
* arch_bpf_timed_may_goto() trampoline for powerpc64
9+
*
10+
* Custom BPF convention (verifier/JIT):
11+
* - input: stack offset in BPF_REG_AX (r12)
12+
* - output: updated count in BPF_REG_AX (r12)
13+
*
14+
* Call bpf_check_timed_may_goto(ptr) with normal powerpc64 ABI:
15+
* - r3 = ptr, return in r3
16+
*
17+
* Preserve BPF regs R0-R5 (mapping: r8, r3-r7).
18+
*/
19+
20+
SYM_FUNC_START(arch_bpf_timed_may_goto)
21+
/* Prologue: save LR, allocate frame */
22+
mflr r0
23+
std r0, 16(r1)
24+
stdu r1, -112(r1)
25+
26+
/* Save BPF registers R0 - R5 (r8, r3-r7) */
27+
std r3, 24(r1)
28+
std r4, 32(r1)
29+
std r5, 40(r1)
30+
std r6, 48(r1)
31+
std r7, 56(r1)
32+
std r8, 64(r1)
33+
34+
/*
35+
* r3 = BPF_REG_FP + BPF_REG_AX
36+
* BPF_REG_FP is r31; BPF_REG_AX is r12 (stack offset in bytes).
37+
*/
38+
add r3, r31, r12
39+
bl bpf_check_timed_may_goto
40+
41+
/* Put return value back into AX */
42+
mr r12, r3
43+
44+
/* Restore BPF registers R0 - R5 (r8, r3-r7) */
45+
ld r3, 24(r1)
46+
ld r4, 32(r1)
47+
ld r5, 40(r1)
48+
ld r6, 48(r1)
49+
ld r7, 56(r1)
50+
ld r8, 64(r1)
51+
52+
/* Epilogue: pop frame, restore LR, return */
53+
addi r1, r1, 112
54+
ld r0, 16(r1)
55+
mtlr r0
56+
blr
57+
SYM_FUNC_END(arch_bpf_timed_may_goto)

0 commit comments

Comments
 (0)