mirror of
https://github.com/torvalds/linux.git
synced 2026-09-22 20:54:03 +02:00
Merge branch 'bpf-riscv-add-timed-may_goto-support'
Feng Jiang says:
====================
bpf, riscv: add timed may_goto support
This series adds RISC-V JIT support for the timed may_goto loop bound.
Patch 1 implements arch_bpf_timed_may_goto() and enables
bpf_jit_supports_timed_may_goto() so the verifier uses the timed
expansion path.
Patch 2 adds a test that checks R0-R5 are preserved across
arch_bpf_timed_may_goto() calls.
Patch 3 enables the verifier_may_goto_1, stream_cond_break, and
may_goto_interaction fastcall tests on riscv64.
Tested on riscv64 QEMU (rva23s64): may_goto programs load and JIT
correctly, and the 250ms timeout path works as expected.
Signed-off-by: Feng Jiang <jiangfeng@kylinos.cn>
Tested-by: Pu Lehui <pulehui@huawei.com>
Reviewed-by: Björn Töpel <bjorn@kernel.org>
Acked-by: Björn Töpel <bjorn@kernel.org>
---
Changes in v5:
- Use REG_S/REG_L/SZREG in arch_bpf_timed_may_goto assembly. (Pu Lehui)
- Add __arch_s390x to the timed_may_goto_preserves_regs test. (Pu Lehui)
- Switch the preserves-regs test to SEC("syscall") to fix
bpf_prog_test_run() EINVAL.
- Link to v4: https://lore.kernel.org/r/20260722-riscv-bpf-timed-may-goto-v4-0-e117e6337bc7@kylinos.cn
Changes in v4:
- Add 'bpf-next' prefix to match the BPF kernel tree workflow.
- Add a test checking that R0-R5 are preserved across
arch_bpf_timed_may_goto() calls. Use bpf_get_prandom_u32() to
prevent the verifier from removing the checks via DCE.
- Rename may_goto_interaction_arm64() to may_goto_interaction().
- Wrap the arch_bpf_timed_may_goto address check to a single line.
- Link to v3: https://lore.kernel.org/r/20260715-riscv-bpf-timed-may-goto-v3-0-cf2a9c3d843f@kylinos.cn
Changes in v3:
- Set up the frame pointer in arch_bpf_timed_may_goto() so the function
does not break stack unwinding under CONFIG_FRAME_POINTER.
Changes in v2:
- Fix BPF_REG_0 being clobbered after arch_bpf_timed_may_goto() calls.
- Enable the may_goto_interaction fastcall test on riscv64.
---
====================
Link: https://patch.msgid.link/20260723-riscv-bpf-timed-may-goto-v5-0-86acb54e5642@kylinos.cn
Signed-off-by: Kumar Kartikeya Dwivedi <memxor@gmail.com>
This commit is contained in:
commit
159d4fbb6c
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -1841,7 +1841,12 @@ int bpf_jit_emit_insn(const struct bpf_insn *insn, struct rv_jit_context *ctx,
|
|||
if (aux->tail_call_reachable && insn->src_reg == BPF_PSEUDO_CALL)
|
||||
emit_sd(RV_REG_SP, ctx->tcc_offset, RV_REG_TCC, ctx);
|
||||
|
||||
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;
|
||||
}
|
||||
|
|
@ -2161,3 +2166,8 @@ bool bpf_jit_supports_subprog_tailcalls(void)
|
|||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
bool bpf_jit_supports_timed_may_goto(void)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
|
|
|||
47
arch/riscv/net/bpf_timed_may_goto.S
Normal file
47
arch/riscv/net/bpf_timed_may_goto.S
Normal file
|
|
@ -0,0 +1,47 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/* Copyright (c) 2026 Feng Jiang <jiangfeng@kylinos.cn> */
|
||||
|
||||
#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, -(8*SZREG)
|
||||
REG_S ra, 7*SZREG(sp)
|
||||
REG_S s0, 6*SZREG(sp)
|
||||
addi s0, sp, 8*SZREG
|
||||
|
||||
/* Save BPF registers R0-R5 (a5, a0-a4) */
|
||||
REG_S a5, 5*SZREG(sp)
|
||||
REG_S a0, 4*SZREG(sp)
|
||||
REG_S a1, 3*SZREG(sp)
|
||||
REG_S a2, 2*SZREG(sp)
|
||||
REG_S a3, 1*SZREG(sp)
|
||||
REG_S a4, 0*SZREG(sp)
|
||||
|
||||
add a0, t0, s5
|
||||
call bpf_check_timed_may_goto
|
||||
mv t0, a0
|
||||
|
||||
/* Restore BPF registers R0-R5 */
|
||||
REG_L a4, 0*SZREG(sp)
|
||||
REG_L a3, 1*SZREG(sp)
|
||||
REG_L a2, 2*SZREG(sp)
|
||||
REG_L a1, 3*SZREG(sp)
|
||||
REG_L a0, 4*SZREG(sp)
|
||||
REG_L a5, 5*SZREG(sp)
|
||||
|
||||
REG_L s0, 6*SZREG(sp)
|
||||
REG_L ra, 7*SZREG(sp)
|
||||
addi sp, sp, 8*SZREG
|
||||
ret
|
||||
SYM_FUNC_END(arch_bpf_timed_may_goto)
|
||||
|
|
@ -64,6 +64,7 @@ SEC("syscall")
|
|||
__arch_x86_64
|
||||
__arch_arm64
|
||||
__arch_s390x
|
||||
__arch_riscv64
|
||||
__success __retval(0)
|
||||
__stderr("ERROR: Timeout detected for may_goto instruction")
|
||||
__stderr("CPU: {{[0-9]+}} UID: 0 PID: {{[0-9]+}} Comm: {{.*}}")
|
||||
|
|
|
|||
|
|
@ -660,6 +660,7 @@ __naked void may_goto_interaction_x86_64(void)
|
|||
|
||||
SEC("raw_tp")
|
||||
__arch_arm64
|
||||
__arch_riscv64
|
||||
__log_level(4) __msg("stack depth 24")
|
||||
/* may_goto counter at -24 */
|
||||
__xlated("0: *(u64 *)(r10 -24) =")
|
||||
|
|
@ -679,7 +680,7 @@ __xlated("10: *(u64 *)(r10 -24) = r12")
|
|||
__xlated("11: *(u64 *)(r10 -8) = r1")
|
||||
__xlated("12: exit")
|
||||
__success
|
||||
__naked void may_goto_interaction_arm64(void)
|
||||
__naked void may_goto_interaction(void)
|
||||
{
|
||||
asm volatile (
|
||||
"r1 = 1;"
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@ __description("may_goto 0")
|
|||
__arch_x86_64
|
||||
__arch_s390x
|
||||
__arch_arm64
|
||||
__arch_riscv64
|
||||
__xlated("0: r0 = 1")
|
||||
__xlated("1: exit")
|
||||
__success
|
||||
|
|
@ -31,6 +32,7 @@ __description("batch 2 of may_goto 0")
|
|||
__arch_x86_64
|
||||
__arch_s390x
|
||||
__arch_arm64
|
||||
__arch_riscv64
|
||||
__xlated("0: r0 = 1")
|
||||
__xlated("1: exit")
|
||||
__success
|
||||
|
|
@ -53,6 +55,7 @@ __description("may_goto batch with offsets 2/1/0")
|
|||
__arch_x86_64
|
||||
__arch_s390x
|
||||
__arch_arm64
|
||||
__arch_riscv64
|
||||
__xlated("0: r0 = 1")
|
||||
__xlated("1: exit")
|
||||
__success
|
||||
|
|
@ -79,6 +82,7 @@ __description("may_goto batch with offsets 2/0")
|
|||
__arch_x86_64
|
||||
__arch_s390x
|
||||
__arch_arm64
|
||||
__arch_riscv64
|
||||
__xlated("0: *(u64 *)(r10 -16) = 65535")
|
||||
__xlated("1: *(u64 *)(r10 -8) = 0")
|
||||
__xlated("2: r12 = *(u64 *)(r10 -16)")
|
||||
|
|
@ -106,4 +110,62 @@ __naked void may_goto_batch_2(void)
|
|||
: __clobber_all);
|
||||
}
|
||||
|
||||
/*
|
||||
* Use bpf_get_prandom_u32() to prevent DCE from removing the checks.
|
||||
* retval: 0=all ok, 1-6=R0-R5 clobbered.
|
||||
*/
|
||||
SEC("syscall")
|
||||
__description("timed may_goto preserves R0-R5")
|
||||
__arch_x86_64
|
||||
__arch_s390x
|
||||
__arch_arm64
|
||||
__arch_riscv64
|
||||
__success
|
||||
__retval(0)
|
||||
__naked void timed_may_goto_preserves_regs(void)
|
||||
{
|
||||
asm volatile (
|
||||
"call %[bpf_get_prandom_u32];"
|
||||
"r6 = r0;"
|
||||
"r0 = 0x1111;"
|
||||
"r0 += r6;"
|
||||
"r1 = 0x2222;"
|
||||
"r1 += r6;"
|
||||
"r2 = 0x3333;"
|
||||
"r2 += r6;"
|
||||
"r3 = 0x4444;"
|
||||
"r3 += r6;"
|
||||
"r4 = 0x5555;"
|
||||
"r4 += r6;"
|
||||
"r5 = 0x6666;"
|
||||
"r5 += r6;"
|
||||
".8byte %[may_goto];"
|
||||
".8byte %[loop];"
|
||||
"r0 -= r6;"
|
||||
"r1 -= r6;"
|
||||
"r2 -= r6;"
|
||||
"r3 -= r6;"
|
||||
"r4 -= r6;"
|
||||
"r5 -= r6;"
|
||||
"if r0 != 0x1111 goto 1f;"
|
||||
"if r1 != 0x2222 goto 2f;"
|
||||
"if r2 != 0x3333 goto 3f;"
|
||||
"if r3 != 0x4444 goto 4f;"
|
||||
"if r4 != 0x5555 goto 5f;"
|
||||
"if r5 != 0x6666 goto 6f;"
|
||||
"r0 = 0;"
|
||||
"exit;"
|
||||
"1: r0 = 1; exit;"
|
||||
"2: r0 = 2; exit;"
|
||||
"3: r0 = 3; exit;"
|
||||
"4: r0 = 4; exit;"
|
||||
"5: r0 = 5; exit;"
|
||||
"6: r0 = 6; exit;"
|
||||
:
|
||||
: __imm(bpf_get_prandom_u32),
|
||||
__imm_insn(may_goto, BPF_RAW_INSN(BPF_JMP | BPF_JCOND, 0, 0, 1, 0)),
|
||||
__imm_insn(loop, BPF_RAW_INSN(BPF_JMP | BPF_JA, 0, 0, -2, 0))
|
||||
: __clobber_all);
|
||||
}
|
||||
|
||||
char _license[] SEC("license") = "GPL";
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user