LoongArch: BPF: Add timed may_goto implementation

Implement arch_bpf_timed_may_goto() support and advertise it through
bpf_jit_supports_timed_may_goto() so the verifier lowers may_goto into
the timed variant: instead of a fixed iteration counter, the loop is
bounded by a wall-clock timeout maintained in a per-loop stack slot.

arch_bpf_timed_may_goto() uses a custom calling convention: the verifier
passes the count/timestamp stack offset in BPF_REG_AX and expects the
updated count back in the same register. The JIT call path therefore can
skip the usual 'BPF_REG_0 = C return value' move for this helper.

Acked-by: Tiezhu Yang <yangtiezhu@loongson.cn>
Tested-by: Tiezhu Yang <yangtiezhu@loongson.cn>
Signed-off-by: George Guo <guodongtai@kylinos.cn>
Signed-off-by: Huacai Chen <chenhuacai@loongson.cn>
This commit is contained in:
George Guo 2026-08-17 22:07:40 +08:00 committed by Huacai Chen
parent 1db6d003e9
commit 3fbf3534c2
3 changed files with 60 additions and 2 deletions

View File

@ -4,4 +4,4 @@
#
# Copyright (C) 2022 Loongson Technology Corporation Limited
#
obj-$(CONFIG_BPF_JIT) += bpf_jit.o
obj-$(CONFIG_BPF_JIT) += bpf_jit.o bpf_timed_may_goto.o

View File

@ -1192,7 +1192,13 @@ static int build_insn(const struct bpf_insn *insn, struct jit_ctx *ctx, bool ext
move_addr(ctx, t1, func_addr);
emit_insn(ctx, jirl, LOONGARCH_GPR_RA, t1, 0);
if (insn->src_reg != BPF_PSEUDO_CALL)
/*
* Call to arch_bpf_timed_may_goto() uses a custom calling
* convention with the argument and return value in BPF_REG_AX,
* so skip moving the C return value into BPF_REG_0.
*/
if (insn->src_reg != BPF_PSEUDO_CALL &&
func_addr != (u64)arch_bpf_timed_may_goto)
move_reg(ctx, regmap[BPF_REG_0], LOONGARCH_GPR_A0);
break;
@ -2396,6 +2402,11 @@ bool bpf_jit_supports_subprog_tailcalls(void)
return true;
}
bool bpf_jit_supports_timed_may_goto(void)
{
return true;
}
bool bpf_jit_inlines_helper_call(s32 imm)
{
switch (imm) {

View File

@ -0,0 +1,47 @@
/* SPDX-License-Identifier: GPL-2.0 */
/*
* Author: George Guo <guodongtai@kylinos.cn>
* Copyright (C) 2026 KylinSoft Corporation.
*/
#include <asm/asmmacro.h>
#include <asm/regdef.h>
#include <linux/export.h>
#include <linux/linkage.h>
SYM_FUNC_START(arch_bpf_timed_may_goto)
addi.d sp, sp, -64
st.d ra, sp, 56
/* Save BPF registers R0 - R5 (a5, a0 - a4) */
st.d a5, sp, 8
st.d a0, sp, 16
st.d a1, sp, 24
st.d a2, sp, 32
st.d a3, sp, 40
st.d a4, sp, 48
/*
* BPF_REG_AX (t0) holds the offset passed in by the verifier;
* add it to BPF_REG_FP (s4) to get the pointer to the count and
* timestamp, then pass it as the first argument in a0.
*
* The verifier emits a load using FP right before this call,
* so BPF_REG_FP (s4) is always set up by the JIT in this case.
*/
add.d a0, t0, s4
bl bpf_check_timed_may_goto
/* BPF_REG_AX (t0) will be stored into count, so move the return value to it. */
move t0, a0
ld.d ra, sp, 56
ld.d a5, sp, 8
ld.d a0, sp, 16
ld.d a1, sp, 24
ld.d a2, sp, 32
ld.d a3, sp, 40
ld.d a4, sp, 48
addi.d sp, sp, 64
jr ra
SYM_FUNC_END(arch_bpf_timed_may_goto)