Implement arch_bpf_timed_may_goto() for the RV64 JIT. The argument and return value are carried in BPF_REG_AX, and BPF R0-R5 are preserved across the call to the generic bpf_check_timed_may_goto().
Enable bpf_jit_supports_timed_may_goto() so the verifier uses the timed expansion path. Signed-off-by: Feng Jiang <[email protected]> --- arch/riscv/net/Makefile | 2 +- arch/riscv/net/bpf_jit_comp64.c | 13 ++++++++++- arch/riscv/net/bpf_timed_may_goto.S | 44 +++++++++++++++++++++++++++++++++++++ 3 files changed, 57 insertions(+), 2 deletions(-) diff --git a/arch/riscv/net/Makefile b/arch/riscv/net/Makefile index 9a1e5f0a94e5..6458d4d51990 100644 --- a/arch/riscv/net/Makefile +++ b/arch/riscv/net/Makefile @@ -3,7 +3,7 @@ obj-$(CONFIG_BPF_JIT) += bpf_jit_core.o ifeq ($(CONFIG_ARCH_RV64I),y) - obj-$(CONFIG_BPF_JIT) += bpf_jit_comp64.o + obj-$(CONFIG_BPF_JIT) += bpf_jit_comp64.o bpf_timed_may_goto.o else obj-$(CONFIG_BPF_JIT) += bpf_jit_comp32.o endif diff --git a/arch/riscv/net/bpf_jit_comp64.c b/arch/riscv/net/bpf_jit_comp64.c index c03c1de16b79..4f88a446278a 100644 --- a/arch/riscv/net/bpf_jit_comp64.c +++ b/arch/riscv/net/bpf_jit_comp64.c @@ -1841,7 +1841,13 @@ int bpf_jit_emit_insn(const struct bpf_insn *insn, struct rv_jit_context *ctx, if (ret) return ret; - if (insn->src_reg != BPF_PSEUDO_CALL) + /* + * arch_bpf_timed_may_goto() is emitted by the verifier and + * returns its result in BPF_REG_AX instead of BPF_REG_0, so + * skip the normal "move return register into R0". + */ + if (insn->src_reg != BPF_PSEUDO_CALL && + addr != (u64)arch_bpf_timed_may_goto) emit_mv(bpf_to_rv_reg(BPF_REG_0, ctx), RV_REG_A0, ctx); break; } @@ -2157,3 +2163,8 @@ bool bpf_jit_supports_fsession(void) { return true; } + +bool bpf_jit_supports_timed_may_goto(void) +{ + return true; +} diff --git a/arch/riscv/net/bpf_timed_may_goto.S b/arch/riscv/net/bpf_timed_may_goto.S new file mode 100644 index 000000000000..f54f389d921e --- /dev/null +++ b/arch/riscv/net/bpf_timed_may_goto.S @@ -0,0 +1,44 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* Copyright (c) 2026 Feng Jiang <[email protected]> */ + +#include <linux/linkage.h> +#include <asm/asm.h> + +/* + * Trampoline for the BPF timed may_goto loop bound. Custom calling convention: + * - input: stack offset in BPF_REG_AX (t0) + * - output: updated count in BPF_REG_AX (t0) + * + * Calls bpf_check_timed_may_goto(ptr) with the standard RISC-V ABI, where + * ptr = BPF_REG_FP (s5) + BPF_REG_AX (t0). BPF R0-R5 (a5, a0-a4) are saved + * across the call; BPF_REG_FP (s5) is callee-saved and needs no saving. + */ + +SYM_FUNC_START(arch_bpf_timed_may_goto) + addi sp, sp, -64 + sd ra, 56(sp) + + /* Save BPF registers R0-R5 (a5, a0-a4) */ + sd a5, 48(sp) + sd a0, 40(sp) + sd a1, 32(sp) + sd a2, 24(sp) + sd a3, 16(sp) + sd a4, 8(sp) + + add a0, t0, s5 + call bpf_check_timed_may_goto + mv t0, a0 + + /* Restore BPF registers R0-R5 */ + ld a4, 8(sp) + ld a3, 16(sp) + ld a2, 24(sp) + ld a1, 32(sp) + ld a0, 40(sp) + ld a5, 48(sp) + + ld ra, 56(sp) + addi sp, sp, 64 + ret +SYM_FUNC_END(arch_bpf_timed_may_goto) -- 2.25.1

