* [PATCH bpf-next v5 0/3] Add bpf stack arguments support for RV64
@ 2026-09-05 8:58 Pu Lehui
2026-09-05 8:58 ` [PATCH bpf-next v5 1/3] riscv, bpf: Remap BPF_REG_0 and RV_REG_TCC Pu Lehui
` (4 more replies)
0 siblings, 5 replies; 8+ messages in thread
From: Pu Lehui @ 2026-09-05 8:58 UTC (permalink / raw)
To: bpf, linux-riscv, linux-kernel, Feng Jiang
Cc: Björn Töpel, Alexei Starovoitov, Daniel Borkmann,
Andrii Nakryiko, Eduard Zingerman, Kumar Kartikeya Dwivedi,
Martin KaFai Lau, Song Liu, Yonghong Song, Jiri Olsa,
Emil Tsalapatis, Ihor Solodrai, Puranjay Mohan, Paul Walmsley,
Palmer Dabbelt, Alexandre Ghiti, Pu Lehui
Implement bpf_jit_supports_stack_args() on RV64 JIT to allow bpf
subprogs and kfuncs to pass and receive more than 5 arguments.
Tested on riscv64 QEMU with LLVM main [1]; BPF-to-BPF and kfunc
selftests pass.
[1] https://github.com/llvm/llvm-project/pull/189060
---
Changes in v5:
- Add RV_EXTRA_STK_ARGS macro to represent the exceeding stack args
passed in riscv arg regs. (BPF CI)
- Optimize emit_stack_arg_st() by materializing immediates directly
into destination registers. (BPF CI)
- Update stale comments. (BPF CI and sashiko)
Changes in v4:
- Remap BPF_REG_0 and RV_REG_TCC to align the calling convention of
bpf2bpf and kfunc calls with the riscv abi.
- Adapt the bpf stack arguments implementation based on change 1.
Changes in v3:
- Drop the exceptions.c guard change: the guarded programs use
bpf_throw(), unsupported by the RV64 JIT, so the test is denylisted
on riscv64 and the guard has no effect. (BPF CI)
- Link to v2: https://lore.kernel.org/r/20260813-bpf-riscv-stack-args-v2-0-efea8f9b3fe1@kylinos.cn
Changes in v2:
- Sign-extend 32-bit kfunc arguments passed on the stack (args 9+),
matching the register path and the RISC-V psABI. (Sashiko)
- Restrict the riscv selftest guard to __riscv_xlen == 64 so the
tests are not enabled on RV32. (Sashiko)
- Link to v1: https://lore.kernel.org/r/20260812-bpf-riscv-stack-args-v1-0-67b246806e59@kylinos.cn
Feng Jiang (2):
riscv, bpf: Add BPF stack arguments support for RV64 JIT
selftests/bpf: Enable stack argument tests for RV64
Pu Lehui (1):
riscv, bpf: Remap BPF_REG_0 and RV_REG_TCC
arch/riscv/net/bpf_jit.h | 4 +
arch/riscv/net/bpf_jit_comp64.c | 90 +++++++++++++++----
arch/riscv/net/bpf_jit_core.c | 7 ++
arch/riscv/net/bpf_timed_may_goto.S | 8 +-
.../bpf/progs/btf__stack_arg_precision.c | 3 +-
.../bpf/progs/btf__verifier_stack_arg_order.c | 3 +-
tools/testing/selftests/bpf/progs/stack_arg.c | 3 +-
.../selftests/bpf/progs/stack_arg_kfunc.c | 3 +-
.../selftests/bpf/progs/stack_arg_precision.c | 3 +-
.../selftests/bpf/progs/verifier_jit_inline.c | 2 +-
.../selftests/bpf/progs/verifier_ldsx.c | 6 +-
.../selftests/bpf/progs/verifier_stack_arg.c | 3 +-
.../bpf/progs/verifier_stack_arg_order.c | 3 +-
13 files changed, 108 insertions(+), 30 deletions(-)
--
2.34.1
^ permalink raw reply [flat|nested] 8+ messages in thread
* [PATCH bpf-next v5 1/3] riscv, bpf: Remap BPF_REG_0 and RV_REG_TCC
2026-09-05 8:58 [PATCH bpf-next v5 0/3] Add bpf stack arguments support for RV64 Pu Lehui
@ 2026-09-05 8:58 ` Pu Lehui
2026-09-05 9:42 ` bot+bpf-ci
2026-09-05 8:58 ` [PATCH bpf-next v5 2/3] riscv, bpf: Add BPF stack arguments support for RV64 JIT Pu Lehui
` (3 subsequent siblings)
4 siblings, 1 reply; 8+ messages in thread
From: Pu Lehui @ 2026-09-05 8:58 UTC (permalink / raw)
To: bpf, linux-riscv, linux-kernel, Feng Jiang
Cc: Björn Töpel, Alexei Starovoitov, Daniel Borkmann,
Andrii Nakryiko, Eduard Zingerman, Kumar Kartikeya Dwivedi,
Martin KaFai Lau, Song Liu, Yonghong Song, Jiri Olsa,
Emil Tsalapatis, Ihor Solodrai, Puranjay Mohan, Paul Walmsley,
Palmer Dabbelt, Alexandre Ghiti, Pu Lehui
From: Pu Lehui <pulehui@huawei.com>
To prepare for supporting bpf stack arguments and unifying the calling
convention between bpf2bpf calls and kfunc calls, remap BPF_REG_0 to t6
and RV_REG_TCC to t5.
In the riscv abi, a0-a7 are designated for function argument passing.
Freeing a5 and a6 allows bpf2bpf calls to pass extra arguments (6th to
8th) via a5-a7 consistently with kfuncs.
Signed-off-by: Pu Lehui <pulehui@huawei.com>
---
arch/riscv/net/bpf_jit_comp64.c | 10 +++++-----
arch/riscv/net/bpf_timed_may_goto.S | 8 ++++----
.../testing/selftests/bpf/progs/verifier_jit_inline.c | 2 +-
tools/testing/selftests/bpf/progs/verifier_ldsx.c | 6 +++---
4 files changed, 13 insertions(+), 13 deletions(-)
diff --git a/arch/riscv/net/bpf_jit_comp64.c b/arch/riscv/net/bpf_jit_comp64.c
index e7378be171a9..fc1c8c5480b6 100644
--- a/arch/riscv/net/bpf_jit_comp64.c
+++ b/arch/riscv/net/bpf_jit_comp64.c
@@ -23,11 +23,11 @@
/* fentry and TCC init insns will be skipped on tailcall */
#define RV_TAILCALL_OFFSET ((RV_FENTRY_NINSNS + 1) * 4)
-#define RV_REG_TCC RV_REG_A6
+#define RV_REG_TCC RV_REG_T5
#define RV_REG_ARENA RV_REG_S7 /* For storing arena_vm_start */
static const int regmap[] = {
- [BPF_REG_0] = RV_REG_A5,
+ [BPF_REG_0] = RV_REG_T6,
[BPF_REG_1] = RV_REG_A0,
[BPF_REG_2] = RV_REG_A1,
[BPF_REG_3] = RV_REG_A2,
@@ -47,13 +47,13 @@ static const int pt_regmap[] = {
[RV_REG_A2] = offsetof(struct pt_regs, a2),
[RV_REG_A3] = offsetof(struct pt_regs, a3),
[RV_REG_A4] = offsetof(struct pt_regs, a4),
- [RV_REG_A5] = offsetof(struct pt_regs, a5),
[RV_REG_S1] = offsetof(struct pt_regs, s1),
[RV_REG_S2] = offsetof(struct pt_regs, s2),
[RV_REG_S3] = offsetof(struct pt_regs, s3),
[RV_REG_S4] = offsetof(struct pt_regs, s4),
[RV_REG_S5] = offsetof(struct pt_regs, s5),
[RV_REG_T0] = offsetof(struct pt_regs, t0),
+ [RV_REG_T6] = offsetof(struct pt_regs, t6),
};
enum {
@@ -239,7 +239,7 @@ static void __build_epilogue(bool is_tail_call, struct rv_jit_context *ctx)
emit_addi(RV_REG_SP, RV_REG_SP, stack_adjust, ctx);
/* Set return value. */
if (!is_tail_call)
- emit_addiw(RV_REG_A0, RV_REG_A5, 0, ctx);
+ emit_addiw(RV_REG_A0, regmap[BPF_REG_0], 0, ctx);
emit_jalr(RV_REG_ZERO, is_tail_call ? RV_REG_T3 : RV_REG_RA,
is_tail_call ? RV_TAILCALL_OFFSET : 0, ctx);
}
@@ -1075,7 +1075,7 @@ static int __arch_prepare_bpf_trampoline(struct bpf_tramp_image *im,
save_ret = flags & (BPF_TRAMP_F_CALL_ORIG | BPF_TRAMP_F_RET_FENTRY_RET);
if (save_ret)
- stack_size += 16; /* Save both A5 (BPF R0) and A0 */
+ stack_size += 16; /* Save both RV_REG_T6 (BPF R0) and RV_REG_A0 */
retval_off = stack_size;
stack_size += nr_arg_slots * 8;
diff --git a/arch/riscv/net/bpf_timed_may_goto.S b/arch/riscv/net/bpf_timed_may_goto.S
index 02c637d87420..fcf850f244c9 100644
--- a/arch/riscv/net/bpf_timed_may_goto.S
+++ b/arch/riscv/net/bpf_timed_may_goto.S
@@ -10,7 +10,7 @@
* - 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
+ * ptr = BPF_REG_FP (s5) + BPF_REG_AX (t0). BPF R0-R5 (t6, a0-a4) are saved
* across the call; BPF_REG_FP (s5) is callee-saved and needs no saving.
*/
@@ -20,8 +20,8 @@ SYM_FUNC_START(arch_bpf_timed_may_goto)
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)
+ /* Save BPF registers R0-R5 (t6, a0-a4) */
+ REG_S t6, 5*SZREG(sp)
REG_S a0, 4*SZREG(sp)
REG_S a1, 3*SZREG(sp)
REG_S a2, 2*SZREG(sp)
@@ -38,7 +38,7 @@ SYM_FUNC_START(arch_bpf_timed_may_goto)
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 t6, 5*SZREG(sp)
REG_L s0, 6*SZREG(sp)
REG_L ra, 7*SZREG(sp)
diff --git a/tools/testing/selftests/bpf/progs/verifier_jit_inline.c b/tools/testing/selftests/bpf/progs/verifier_jit_inline.c
index 02e562f56f9d..5b92da2ab75c 100644
--- a/tools/testing/selftests/bpf/progs/verifier_jit_inline.c
+++ b/tools/testing/selftests/bpf/progs/verifier_jit_inline.c
@@ -11,7 +11,7 @@ __jited(" addq %gs:{{.*}}, %rax")
__arch_arm64
__jited(" mrs x8, SP_EL0")
__arch_riscv64
-__jited(" mv a5, tp")
+__jited(" mv t6, tp")
__arch_loongarch
__jited(" move $a5, $tp")
int inline_bpf_get_current_task(void)
diff --git a/tools/testing/selftests/bpf/progs/verifier_ldsx.c b/tools/testing/selftests/bpf/progs/verifier_ldsx.c
index 7e25e1b8cd0b..49e8cd4bb4f9 100644
--- a/tools/testing/selftests/bpf/progs/verifier_ldsx.c
+++ b/tools/testing/selftests/bpf/progs/verifier_ldsx.c
@@ -289,11 +289,11 @@ __jited("ldrsh x22, [x11, #0x18]")
__jited("add x11, x0, x28")
__jited("ldrsb x22, [x11, #0x20]")
__arch_riscv64
-__jited("add t2, a5, s7")
+__jited("add t2, t6, s7")
__jited("lw s3, 0x10(t2)")
-__jited("add t2, a5, s7")
+__jited("add t2, t6, s7")
__jited("lh s3, 0x18(t2)")
-__jited("add t2, a5, s7")
+__jited("add t2, t6, s7")
__jited("lb s3, 0x20(t2)")
__jited("add t2, a0, s7")
__jited("lw s4, 0x10(t2)")
--
2.34.1
^ permalink raw reply [flat|nested] 8+ messages in thread
* [PATCH bpf-next v5 2/3] riscv, bpf: Add BPF stack arguments support for RV64 JIT
2026-09-05 8:58 [PATCH bpf-next v5 0/3] Add bpf stack arguments support for RV64 Pu Lehui
2026-09-05 8:58 ` [PATCH bpf-next v5 1/3] riscv, bpf: Remap BPF_REG_0 and RV_REG_TCC Pu Lehui
@ 2026-09-05 8:58 ` Pu Lehui
2026-09-05 8:58 ` [PATCH bpf-next v5 3/3] selftests/bpf: Enable stack argument tests for RV64 Pu Lehui
` (2 subsequent siblings)
4 siblings, 0 replies; 8+ messages in thread
From: Pu Lehui @ 2026-09-05 8:58 UTC (permalink / raw)
To: bpf, linux-riscv, linux-kernel, Feng Jiang
Cc: Björn Töpel, Alexei Starovoitov, Daniel Borkmann,
Andrii Nakryiko, Eduard Zingerman, Kumar Kartikeya Dwivedi,
Martin KaFai Lau, Song Liu, Yonghong Song, Jiri Olsa,
Emil Tsalapatis, Ihor Solodrai, Puranjay Mohan, Paul Walmsley,
Palmer Dabbelt, Alexandre Ghiti, Pu Lehui
From: Feng Jiang <jiangfeng@kylinos.cn>
Implement bpf_jit_supports_stack_args() on RV64 JIT to allow bpf
subprogs and kfuncs to pass and receive more than 5 arguments.
In the riscv abi, the first 8 arguments are passed in registers a0 to
a7, and arguments 9+ reside on the stack. To align bpf stack arguments
with this calling convention and unify bpf2bpf calls with kfuncs, map
the first 3 bpf stack arguments (6th to 8th) directly to a5 to a7, and
store or load the remaining arguments (9th+) at SP or FP. Reserve
outgoing stack space in the prologue accordingly when stack_arg_cnt
exceeds 3.
In addition, update kfunc argument sign extension to handle all 8
register arguments as well as any arguments passed on the stack.
Co-developed-by: Pu Lehui <pulehui@huawei.com>
Signed-off-by: Feng Jiang <jiangfeng@kylinos.cn>
Signed-off-by: Pu Lehui <pulehui@huawei.com>
---
arch/riscv/net/bpf_jit.h | 4 ++
arch/riscv/net/bpf_jit_comp64.c | 80 ++++++++++++++++++++++++++++-----
arch/riscv/net/bpf_jit_core.c | 7 +++
3 files changed, 81 insertions(+), 10 deletions(-)
diff --git a/arch/riscv/net/bpf_jit.h b/arch/riscv/net/bpf_jit.h
index 419b9d795f2a..5c4f53060c91 100644
--- a/arch/riscv/net/bpf_jit.h
+++ b/arch/riscv/net/bpf_jit.h
@@ -12,6 +12,9 @@
#include <linux/bpf.h>
#include <linux/filter.h>
+#define RV_MAX_REG_ARGS 8
+#define RV_EXTRA_STK_ARGS (RV_MAX_REG_ARGS - MAX_BPF_FUNC_REG_ARGS)
+
/* verify runtime detection extension status */
#define rv_ext_enabled(ext) \
(IS_ENABLED(CONFIG_RISCV_ISA_##ext) && riscv_has_extension_likely(RISCV_ISA_EXT_##ext))
@@ -82,6 +85,7 @@ struct rv_jit_context {
unsigned long flags;
int stack_size;
int tcc_offset;
+ int stack_arg_sz;
u64 arena_vm_start;
u64 user_vm_start;
};
diff --git a/arch/riscv/net/bpf_jit_comp64.c b/arch/riscv/net/bpf_jit_comp64.c
index fc1c8c5480b6..7f84447a31ff 100644
--- a/arch/riscv/net/bpf_jit_comp64.c
+++ b/arch/riscv/net/bpf_jit_comp64.c
@@ -15,7 +15,6 @@
#include <asm/percpu.h>
#include "bpf_jit.h"
-#define RV_MAX_REG_ARGS 8
#define RV_FENTRY_NINSNS 2
#define RV_FENTRY_NBYTES (RV_FENTRY_NINSNS * 4)
/* imm that allows emit_imm to emit max count insns */
@@ -498,6 +497,18 @@ static void emit_ldx(u8 rd, s16 off, u8 rs, u8 size, bool sign_ext,
ctx->ex_jmp_off = ctx->ninsns;
}
+static void emit_stack_arg_ldx(u8 rd, s16 off, struct rv_jit_context *ctx)
+{
+ int idx = off / 8 - 1;
+
+ if (idx < RV_EXTRA_STK_ARGS) {
+ emit_mv(rd, RV_REG_A5 + idx, ctx);
+ return;
+ }
+
+ emit_ldx_insn(rd, (idx - RV_EXTRA_STK_ARGS) * 8, RV_REG_FP, BPF_DW, false, ctx);
+}
+
static void emit_st(u8 rd, s16 off, s32 imm, u8 size, struct rv_jit_context *ctx)
{
emit_imm(RV_REG_T1, imm, ctx);
@@ -515,6 +526,19 @@ static void emit_st(u8 rd, s16 off, s32 imm, u8 size, struct rv_jit_context *ctx
ctx->ex_jmp_off = ctx->ninsns;
}
+static void emit_stack_arg_st(s16 off, s32 imm, struct rv_jit_context *ctx)
+{
+ int idx = -off / 8 - 1;
+
+ if (idx < RV_EXTRA_STK_ARGS) {
+ emit_imm(RV_REG_A5 + idx, imm, ctx);
+ return;
+ }
+
+ emit_imm(RV_REG_T1, imm, ctx);
+ emit_stx_insn(RV_REG_SP, (idx - RV_EXTRA_STK_ARGS) * 8, RV_REG_T1, BPF_DW, ctx);
+}
+
static void emit_stx(u8 rd, s16 off, u8 rs, u8 size, struct rv_jit_context *ctx)
{
if (is_12b_int(off)) {
@@ -531,6 +555,18 @@ static void emit_stx(u8 rd, s16 off, u8 rs, u8 size, struct rv_jit_context *ctx)
ctx->ex_jmp_off = ctx->ninsns;
}
+static void emit_stack_arg_stx(s16 off, u8 rs, struct rv_jit_context *ctx)
+{
+ int idx = -off / 8 - 1;
+
+ if (idx < RV_EXTRA_STK_ARGS) {
+ emit_mv(RV_REG_A5 + idx, rs, ctx);
+ return;
+ }
+
+ emit_stx_insn(RV_REG_SP, (idx - RV_EXTRA_STK_ARGS) * 8, rs, BPF_DW, ctx);
+}
+
static int emit_atomic_ld_st(u8 rd, u8 rs, const struct bpf_insn *insn,
struct rv_jit_context *ctx)
{
@@ -1824,11 +1860,21 @@ int bpf_jit_emit_insn(const struct bpf_insn *insn, struct rv_jit_context *ctx,
return -EINVAL;
for (idx = 0; idx < fm->nr_args; idx++) {
- u8 reg = bpf_to_rv_reg(BPF_REG_1 + idx, ctx);
bool sign = fm->arg_flags[idx] & BTF_FMODEL_SIGNED_ARG;
-
- if (sign_extend(reg, reg, fm->arg_size[idx], sign, ctx))
- return -EINVAL;
+ u8 arg_sz = fm->arg_size[idx];
+
+ if (arg_sz == 8 || (arg_sz != 4 && !sign))
+ continue;
+
+ if (idx < RV_MAX_REG_ARGS) {
+ if (sign_extend(RV_REG_A0 + idx, RV_REG_A0 + idx, arg_sz, sign, ctx))
+ return -EINVAL;
+ } else {
+ emit_ld(RV_REG_T1, (idx - RV_MAX_REG_ARGS) * 8, RV_REG_SP, ctx);
+ if (sign_extend(RV_REG_T1, RV_REG_T1, arg_sz, sign, ctx))
+ return -EINVAL;
+ emit_sd(RV_REG_SP, (idx - RV_MAX_REG_ARGS) * 8, RV_REG_T1, ctx);
+ }
}
}
@@ -1927,7 +1973,10 @@ int bpf_jit_emit_insn(const struct bpf_insn *insn, struct rv_jit_context *ctx,
rs = RV_REG_T2;
}
- emit_ldx(rd, off, rs, BPF_SIZE(code), sign_ext, ctx);
+ if (is_stack_arg_ldx(insn))
+ emit_stack_arg_ldx(rd, off, ctx);
+ else
+ emit_ldx(rd, off, rs, BPF_SIZE(code), sign_ext, ctx);
ret = add_exception_handler(insn, rd, ctx);
if (ret)
@@ -1957,7 +2006,10 @@ int bpf_jit_emit_insn(const struct bpf_insn *insn, struct rv_jit_context *ctx,
rd = RV_REG_T3;
}
- emit_st(rd, off, imm, BPF_SIZE(code), ctx);
+ if (is_stack_arg_st(insn))
+ emit_stack_arg_st(off, imm, ctx);
+ else
+ emit_st(rd, off, imm, BPF_SIZE(code), ctx);
ret = add_exception_handler(insn, REG_DONT_CLEAR_MARKER, ctx);
if (ret)
@@ -1979,7 +2031,10 @@ int bpf_jit_emit_insn(const struct bpf_insn *insn, struct rv_jit_context *ctx,
rd = RV_REG_T2;
}
- emit_stx(rd, off, rs, BPF_SIZE(code), ctx);
+ if (is_stack_arg_stx(insn))
+ emit_stack_arg_stx(off, rs, ctx);
+ else
+ emit_stx(rd, off, rs, BPF_SIZE(code), ctx);
ret = add_exception_handler(insn, REG_DONT_CLEAR_MARKER, ctx);
if (ret)
@@ -2029,9 +2084,9 @@ int bpf_jit_emit_insn(const struct bpf_insn *insn, struct rv_jit_context *ctx,
void bpf_jit_build_prologue(struct rv_jit_context *ctx, bool is_subprog)
{
- int i, stack_adjust = 0, store_offset, bpf_stack_adjust;
+ int i, stack_adjust = 0, store_offset, bpf_stack_adjust = ctx->stack_arg_sz;
- bpf_stack_adjust = round_up(ctx->prog->aux->stack_depth, STACK_ALIGN);
+ bpf_stack_adjust += round_up(ctx->prog->aux->stack_depth, STACK_ALIGN);
if (bpf_stack_adjust)
mark_fp(ctx);
@@ -2190,3 +2245,8 @@ bool bpf_jit_supports_timed_may_goto(void)
{
return true;
}
+
+bool bpf_jit_supports_stack_args(void)
+{
+ return true;
+}
diff --git a/arch/riscv/net/bpf_jit_core.c b/arch/riscv/net/bpf_jit_core.c
index cbfcd287ea16..2fb0b4e198b9 100644
--- a/arch/riscv/net/bpf_jit_core.c
+++ b/arch/riscv/net/bpf_jit_core.c
@@ -48,6 +48,7 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_verifier_env *env, struct bpf_pr
int pass = 0, prev_ninsns = 0, i;
struct rv_jit_data *jit_data;
struct rv_jit_context *ctx;
+ u16 stack_arg_cnt;
if (!prog->jit_requested)
return prog;
@@ -71,6 +72,12 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_verifier_env *env, struct bpf_pr
ctx->arena_vm_start = bpf_arena_get_kern_vm_start(prog->aux->arena);
ctx->user_vm_start = bpf_arena_get_user_vm_start(prog->aux->arena);
+
+ stack_arg_cnt = bpf_out_stack_arg_cnt(env, prog);
+ /* First 3 stack args in regs, rest on stack */
+ ctx->stack_arg_sz = stack_arg_cnt > RV_EXTRA_STK_ARGS ?
+ round_up((stack_arg_cnt - RV_EXTRA_STK_ARGS) * 8, STACK_ALIGN) : 0;
+
ctx->prog = prog;
ctx->offset = kvzalloc_objs(int, prog->len);
if (!ctx->offset)
--
2.34.1
^ permalink raw reply [flat|nested] 8+ messages in thread
* [PATCH bpf-next v5 3/3] selftests/bpf: Enable stack argument tests for RV64
2026-09-05 8:58 [PATCH bpf-next v5 0/3] Add bpf stack arguments support for RV64 Pu Lehui
2026-09-05 8:58 ` [PATCH bpf-next v5 1/3] riscv, bpf: Remap BPF_REG_0 and RV_REG_TCC Pu Lehui
2026-09-05 8:58 ` [PATCH bpf-next v5 2/3] riscv, bpf: Add BPF stack arguments support for RV64 JIT Pu Lehui
@ 2026-09-05 8:58 ` Pu Lehui
2026-09-06 14:22 ` [PATCH bpf-next v5 0/3] Add bpf stack arguments support " Björn Töpel
2026-09-06 14:30 ` patchwork-bot+netdevbpf
4 siblings, 0 replies; 8+ messages in thread
From: Pu Lehui @ 2026-09-05 8:58 UTC (permalink / raw)
To: bpf, linux-riscv, linux-kernel, Feng Jiang
Cc: Björn Töpel, Alexei Starovoitov, Daniel Borkmann,
Andrii Nakryiko, Eduard Zingerman, Kumar Kartikeya Dwivedi,
Martin KaFai Lau, Song Liu, Yonghong Song, Jiri Olsa,
Emil Tsalapatis, Ihor Solodrai, Puranjay Mohan, Paul Walmsley,
Palmer Dabbelt, Alexandre Ghiti, Pu Lehui
From: Feng Jiang <jiangfeng@kylinos.cn>
Enable the stack argument selftests for RV64. The riscv guard is
restricted to __riscv_xlen == 64 since stack arguments are only
supported by the RV64 JIT.
Keep the __BPF_FEATURE_STACK_ARGUMENT gate, defined by clang with
BPF stack argument support [1].
[1] https://github.com/llvm/llvm-project/pull/189060
Signed-off-by: Feng Jiang <jiangfeng@kylinos.cn>
---
tools/testing/selftests/bpf/progs/btf__stack_arg_precision.c | 3 ++-
.../selftests/bpf/progs/btf__verifier_stack_arg_order.c | 3 ++-
tools/testing/selftests/bpf/progs/stack_arg.c | 3 ++-
tools/testing/selftests/bpf/progs/stack_arg_kfunc.c | 3 ++-
tools/testing/selftests/bpf/progs/stack_arg_precision.c | 3 ++-
tools/testing/selftests/bpf/progs/verifier_stack_arg.c | 3 ++-
tools/testing/selftests/bpf/progs/verifier_stack_arg_order.c | 3 ++-
7 files changed, 14 insertions(+), 7 deletions(-)
diff --git a/tools/testing/selftests/bpf/progs/btf__stack_arg_precision.c b/tools/testing/selftests/bpf/progs/btf__stack_arg_precision.c
index 8d38aafe66a2..ab12397a9b52 100644
--- a/tools/testing/selftests/bpf/progs/btf__stack_arg_precision.c
+++ b/tools/testing/selftests/bpf/progs/btf__stack_arg_precision.c
@@ -4,7 +4,8 @@
#include <bpf/bpf_helpers.h>
#include "../test_kmods/bpf_testmod_kfunc.h"
-#if (defined(__TARGET_ARCH_x86) || defined(__TARGET_ARCH_arm64)) && \
+#if (defined(__TARGET_ARCH_x86) || defined(__TARGET_ARCH_arm64) || \
+ (defined(__TARGET_ARCH_riscv) && __riscv_xlen == 64)) && \
defined(__BPF_FEATURE_STACK_ARGUMENT)
long subprog_call_mem_kfunc(long a, long b, long c, long d, long e, long size)
diff --git a/tools/testing/selftests/bpf/progs/btf__verifier_stack_arg_order.c b/tools/testing/selftests/bpf/progs/btf__verifier_stack_arg_order.c
index 99bc115f8380..a980a3a399d3 100644
--- a/tools/testing/selftests/bpf/progs/btf__verifier_stack_arg_order.c
+++ b/tools/testing/selftests/bpf/progs/btf__verifier_stack_arg_order.c
@@ -3,7 +3,8 @@
#include <vmlinux.h>
#include <bpf/bpf_helpers.h>
-#if (defined(__TARGET_ARCH_x86) || defined(__TARGET_ARCH_arm64)) && \
+#if (defined(__TARGET_ARCH_x86) || defined(__TARGET_ARCH_arm64) || \
+ (defined(__TARGET_ARCH_riscv) && __riscv_xlen == 64)) && \
defined(__BPF_FEATURE_STACK_ARGUMENT)
int subprog_bad_order_6args(int a, int b, int c, int d, int e, int f)
diff --git a/tools/testing/selftests/bpf/progs/stack_arg.c b/tools/testing/selftests/bpf/progs/stack_arg.c
index 944e3bb603e7..3e9ed37c57bb 100644
--- a/tools/testing/selftests/bpf/progs/stack_arg.c
+++ b/tools/testing/selftests/bpf/progs/stack_arg.c
@@ -21,7 +21,8 @@ struct {
int timer_result;
-#if (defined(__TARGET_ARCH_x86) || defined(__TARGET_ARCH_arm64)) && \
+#if (defined(__TARGET_ARCH_x86) || defined(__TARGET_ARCH_arm64) || \
+ (defined(__TARGET_ARCH_riscv) && __riscv_xlen == 64)) && \
defined(__BPF_FEATURE_STACK_ARGUMENT)
const volatile bool has_stack_arg = true;
diff --git a/tools/testing/selftests/bpf/progs/stack_arg_kfunc.c b/tools/testing/selftests/bpf/progs/stack_arg_kfunc.c
index 345f2da2e361..b6b1a8aa7f44 100644
--- a/tools/testing/selftests/bpf/progs/stack_arg_kfunc.c
+++ b/tools/testing/selftests/bpf/progs/stack_arg_kfunc.c
@@ -6,7 +6,8 @@
#include "bpf_kfuncs.h"
#include "../test_kmods/bpf_testmod_kfunc.h"
-#if (defined(__TARGET_ARCH_x86) || defined(__TARGET_ARCH_arm64)) && \
+#if (defined(__TARGET_ARCH_x86) || defined(__TARGET_ARCH_arm64) || \
+ (defined(__TARGET_ARCH_riscv) && __riscv_xlen == 64)) && \
defined(__BPF_FEATURE_STACK_ARGUMENT)
const volatile bool has_stack_arg = true;
diff --git a/tools/testing/selftests/bpf/progs/stack_arg_precision.c b/tools/testing/selftests/bpf/progs/stack_arg_precision.c
index ce0301a41fa9..7baa9c1c8e31 100644
--- a/tools/testing/selftests/bpf/progs/stack_arg_precision.c
+++ b/tools/testing/selftests/bpf/progs/stack_arg_precision.c
@@ -6,7 +6,8 @@
#include "../test_kmods/bpf_testmod_kfunc.h"
#include "bpf_misc.h"
-#if (defined(__TARGET_ARCH_x86) || defined(__TARGET_ARCH_arm64)) && \
+#if (defined(__TARGET_ARCH_x86) || defined(__TARGET_ARCH_arm64) || \
+ (defined(__TARGET_ARCH_riscv) && __riscv_xlen == 64)) && \
defined(__BPF_FEATURE_STACK_ARGUMENT)
/* Force kfunc extern BTF generation for inline asm call below.
diff --git a/tools/testing/selftests/bpf/progs/verifier_stack_arg.c b/tools/testing/selftests/bpf/progs/verifier_stack_arg.c
index 51d22faf4559..f6a4a6aa0e61 100644
--- a/tools/testing/selftests/bpf/progs/verifier_stack_arg.c
+++ b/tools/testing/selftests/bpf/progs/verifier_stack_arg.c
@@ -12,7 +12,8 @@ struct {
__type(value, long long);
} map_hash_8b SEC(".maps");
-#if (defined(__TARGET_ARCH_x86) || defined(__TARGET_ARCH_arm64)) && \
+#if (defined(__TARGET_ARCH_x86) || defined(__TARGET_ARCH_arm64) || \
+ (defined(__TARGET_ARCH_riscv) && __riscv_xlen == 64)) && \
defined(__BPF_FEATURE_STACK_ARGUMENT)
__noinline __used
diff --git a/tools/testing/selftests/bpf/progs/verifier_stack_arg_order.c b/tools/testing/selftests/bpf/progs/verifier_stack_arg_order.c
index 8e4325273b3d..57f22691744a 100644
--- a/tools/testing/selftests/bpf/progs/verifier_stack_arg_order.c
+++ b/tools/testing/selftests/bpf/progs/verifier_stack_arg_order.c
@@ -5,7 +5,8 @@
#include <bpf/bpf_helpers.h>
#include "bpf_misc.h"
-#if (defined(__TARGET_ARCH_x86) || defined(__TARGET_ARCH_arm64)) && \
+#if (defined(__TARGET_ARCH_x86) || defined(__TARGET_ARCH_arm64) || \
+ (defined(__TARGET_ARCH_riscv) && __riscv_xlen == 64)) && \
defined(__BPF_FEATURE_STACK_ARGUMENT)
__noinline __used __naked
--
2.34.1
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH bpf-next v5 1/3] riscv, bpf: Remap BPF_REG_0 and RV_REG_TCC
2026-09-05 8:58 ` [PATCH bpf-next v5 1/3] riscv, bpf: Remap BPF_REG_0 and RV_REG_TCC Pu Lehui
@ 2026-09-05 9:42 ` bot+bpf-ci
2026-09-05 9:56 ` Pu Lehui
0 siblings, 1 reply; 8+ messages in thread
From: bot+bpf-ci @ 2026-09-05 9:42 UTC (permalink / raw)
To: pulehui, bpf, linux-riscv, linux-kernel, jiangfeng
Cc: bjorn, ast, daniel, andrii, eddyz87, memxor, martin.lau, song,
yonghong.song, jolsa, emil, ihor.solodrai, puranjay, pjw, palmer,
alex, pulehui, ast, andrii, daniel, martin.lau, eddyz87,
yonghong.song, mason, ihor.solodrai
[-- Attachment #1: Type: text/plain, Size: 2153 bytes --]
> diff --git a/arch/riscv/net/bpf_jit_comp64.c b/arch/riscv/net/bpf_jit_comp64.c
> index e7378be171a9..fc1c8c5480b6 100644
> --- a/arch/riscv/net/bpf_jit_comp64.c
> +++ b/arch/riscv/net/bpf_jit_comp64.c
> @@ -23,11 +23,11 @@
> /* fentry and TCC init insns will be skipped on tailcall */
> #define RV_TAILCALL_OFFSET ((RV_FENTRY_NINSNS + 1) * 4)
>
> -#define RV_REG_TCC RV_REG_A6
> +#define RV_REG_TCC RV_REG_T5
> #define RV_REG_ARENA RV_REG_S7 /* For storing arena_vm_start */
>
> static const int regmap[] = {
> - [BPF_REG_0] = RV_REG_A5,
> + [BPF_REG_0] = RV_REG_T6,
> [BPF_REG_1] = RV_REG_A0,
> [BPF_REG_2] = RV_REG_A1,
> [BPF_REG_3] = RV_REG_A2,
This isn't a bug, but does moving BPF_REG_0 to t6 affect code density?
arch/riscv/net/bpf_jit.h:is_creg() only accepts fp, s1, and a0-a5 for
RVC-compressible forms. With CONFIG_RISCV_ISA_C, every emitter that gates
on is_creg() now falls back to 4-byte instructions whenever BPF R0 is the
destination or base register. Since R0 holds return values and helper
results, could this measurably grow JIT image size for R0-heavy code?
The changelog explains why a5 and a6 needed to be freed, but it doesn't
mention why t6 and t5 were chosen. Could a sentence be added about the
register selection rationale, particularly since t4 appears unused by
the JIT?
> @@ -47,13 +47,13 @@ static const int pt_regmap[] = {
> [RV_REG_A2] = offsetof(struct pt_regs, a2),
> [RV_REG_A3] = offsetof(struct pt_regs, a3),
> [RV_REG_A4] = offsetof(struct pt_regs, a4),
> - [RV_REG_A5] = offsetof(struct pt_regs, a5),
> [RV_REG_S1] = offsetof(struct pt_regs, s1),
> [RV_REG_S2] = offsetof(struct pt_regs, s2),
> [RV_REG_S3] = offsetof(struct pt_regs, s3),
> [RV_REG_S4] = offsetof(struct pt_regs, s4),
> [RV_REG_S5] = offsetof(struct pt_regs, s5),
> [RV_REG_T0] = offsetof(struct pt_regs, t0),
> + [RV_REG_T6] = offsetof(struct pt_regs, t6),
> };
[ ... ]
---
AI reviewed your patch. Please fix the bug or email reply why it's not a bug.
See: https://github.com/kernel-patches/vmtest/blob/master/ci/claude/README.md
CI run summary: https://github.com/kernel-patches/bpf/actions/runs/33956847598
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH bpf-next v5 1/3] riscv, bpf: Remap BPF_REG_0 and RV_REG_TCC
2026-09-05 9:42 ` bot+bpf-ci
@ 2026-09-05 9:56 ` Pu Lehui
0 siblings, 0 replies; 8+ messages in thread
From: Pu Lehui @ 2026-09-05 9:56 UTC (permalink / raw)
To: bot+bpf-ci, bpf, linux-riscv, linux-kernel, jiangfeng
Cc: bjorn, ast, daniel, andrii, eddyz87, memxor, martin.lau, song,
yonghong.song, jolsa, emil, ihor.solodrai, puranjay, pjw, palmer,
alex, pulehui, martin.lau, mason
On 2026/9/5 17:42, bot+bpf-ci@kernel.org wrote:
>> diff --git a/arch/riscv/net/bpf_jit_comp64.c b/arch/riscv/net/bpf_jit_comp64.c
>> index e7378be171a9..fc1c8c5480b6 100644
>> --- a/arch/riscv/net/bpf_jit_comp64.c
>> +++ b/arch/riscv/net/bpf_jit_comp64.c
>> @@ -23,11 +23,11 @@
>> /* fentry and TCC init insns will be skipped on tailcall */
>> #define RV_TAILCALL_OFFSET ((RV_FENTRY_NINSNS + 1) * 4)
>>
>> -#define RV_REG_TCC RV_REG_A6
>> +#define RV_REG_TCC RV_REG_T5
>> #define RV_REG_ARENA RV_REG_S7 /* For storing arena_vm_start */
>>
>> static const int regmap[] = {
>> - [BPF_REG_0] = RV_REG_A5,
>> + [BPF_REG_0] = RV_REG_T6,
>> [BPF_REG_1] = RV_REG_A0,
>> [BPF_REG_2] = RV_REG_A1,
>> [BPF_REG_3] = RV_REG_A2,
>
> This isn't a bug, but does moving BPF_REG_0 to t6 affect code density?
> arch/riscv/net/bpf_jit.h:is_creg() only accepts fp, s1, and a0-a5 for
> RVC-compressible forms. With CONFIG_RISCV_ISA_C, every emitter that gates
> on is_creg() now falls back to 4-byte instructions whenever BPF R0 is the
> destination or base register. Since R0 holds return values and helper
> results, could this measurably grow JIT image size for R0-heavy code?
This is expected. The bpf prog image size growth is expected to be
negligible, and it is a necessary trade-off to free up registers for the
calling convention.
>
> The changelog explains why a5 and a6 needed to be freed, but it doesn't
> mention why t6 and t5 were chosen. Could a sentence be added about the
> register selection rationale, particularly since t4 appears unused by
> the JIT?
It's fine, let's mention here. We prefer caller-saved registers that are
unused both now and going forward.
>
>> @@ -47,13 +47,13 @@ static const int pt_regmap[] = {
>> [RV_REG_A2] = offsetof(struct pt_regs, a2),
>> [RV_REG_A3] = offsetof(struct pt_regs, a3),
>> [RV_REG_A4] = offsetof(struct pt_regs, a4),
>> - [RV_REG_A5] = offsetof(struct pt_regs, a5),
>> [RV_REG_S1] = offsetof(struct pt_regs, s1),
>> [RV_REG_S2] = offsetof(struct pt_regs, s2),
>> [RV_REG_S3] = offsetof(struct pt_regs, s3),
>> [RV_REG_S4] = offsetof(struct pt_regs, s4),
>> [RV_REG_S5] = offsetof(struct pt_regs, s5),
>> [RV_REG_T0] = offsetof(struct pt_regs, t0),
>> + [RV_REG_T6] = offsetof(struct pt_regs, t6),
>> };
>
> [ ... ]
>
>
> ---
> AI reviewed your patch. Please fix the bug or email reply why it's not a bug.
> See: https://github.com/kernel-patches/vmtest/blob/master/ci/claude/README.md
>
> CI run summary: https://github.com/kernel-patches/bpf/actions/runs/33956847598
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH bpf-next v5 0/3] Add bpf stack arguments support for RV64
2026-09-05 8:58 [PATCH bpf-next v5 0/3] Add bpf stack arguments support for RV64 Pu Lehui
` (2 preceding siblings ...)
2026-09-05 8:58 ` [PATCH bpf-next v5 3/3] selftests/bpf: Enable stack argument tests for RV64 Pu Lehui
@ 2026-09-06 14:22 ` Björn Töpel
2026-09-06 14:30 ` patchwork-bot+netdevbpf
4 siblings, 0 replies; 8+ messages in thread
From: Björn Töpel @ 2026-09-06 14:22 UTC (permalink / raw)
To: Pu Lehui, bpf, linux-riscv, linux-kernel, Feng Jiang
Cc: Alexei Starovoitov, Daniel Borkmann, Andrii Nakryiko,
Eduard Zingerman, Kumar Kartikeya Dwivedi, Martin KaFai Lau,
Song Liu, Yonghong Song, Jiri Olsa, Emil Tsalapatis,
Ihor Solodrai, Puranjay Mohan, Paul Walmsley, Palmer Dabbelt,
Alexandre Ghiti, Pu Lehui
Pu Lehui <pulehui@huaweicloud.com> writes:
> Implement bpf_jit_supports_stack_args() on RV64 JIT to allow bpf
> subprogs and kfuncs to pass and receive more than 5 arguments.
>
> Tested on riscv64 QEMU with LLVM main [1]; BPF-to-BPF and kfunc
> selftests pass.
>
> [1] https://github.com/llvm/llvm-project/pull/189060
>
> ---
> Changes in v5:
> - Add RV_EXTRA_STK_ARGS macro to represent the exceeding stack args
> passed in riscv arg regs. (BPF CI)
> - Optimize emit_stack_arg_st() by materializing immediates directly
> into destination registers. (BPF CI)
> - Update stale comments. (BPF CI and sashiko)
>
> Changes in v4:
> - Remap BPF_REG_0 and RV_REG_TCC to align the calling convention of
> bpf2bpf and kfunc calls with the riscv abi.
> - Adapt the bpf stack arguments implementation based on change 1.
>
> Changes in v3:
> - Drop the exceptions.c guard change: the guarded programs use
> bpf_throw(), unsupported by the RV64 JIT, so the test is denylisted
> on riscv64 and the guard has no effect. (BPF CI)
> - Link to v2: https://lore.kernel.org/r/20260813-bpf-riscv-stack-args-v2-0-efea8f9b3fe1@kylinos.cn
>
> Changes in v2:
> - Sign-extend 32-bit kfunc arguments passed on the stack (args 9+),
> matching the register path and the RISC-V psABI. (Sashiko)
> - Restrict the riscv selftest guard to __riscv_xlen == 64 so the
> tests are not enabled on RV32. (Sashiko)
> - Link to v1: https://lore.kernel.org/r/20260812-bpf-riscv-stack-args-v1-0-67b246806e59@kylinos.cn
>
> Feng Jiang (2):
> riscv, bpf: Add BPF stack arguments support for RV64 JIT
> selftests/bpf: Enable stack argument tests for RV64
>
> Pu Lehui (1):
> riscv, bpf: Remap BPF_REG_0 and RV_REG_TCC
Thanks!
For the series:
Acked-by: Björn Töpel <bjorn@kernel.org>
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH bpf-next v5 0/3] Add bpf stack arguments support for RV64
2026-09-05 8:58 [PATCH bpf-next v5 0/3] Add bpf stack arguments support for RV64 Pu Lehui
` (3 preceding siblings ...)
2026-09-06 14:22 ` [PATCH bpf-next v5 0/3] Add bpf stack arguments support " Björn Töpel
@ 2026-09-06 14:30 ` patchwork-bot+netdevbpf
4 siblings, 0 replies; 8+ messages in thread
From: patchwork-bot+netdevbpf @ 2026-09-06 14:30 UTC (permalink / raw)
To: Pu Lehui
Cc: bpf, linux-riscv, linux-kernel, jiangfeng, bjorn, ast, daniel,
andrii, eddyz87, memxor, martin.lau, song, yonghong.song, jolsa,
emil, ihor.solodrai, puranjay, pjw, palmer, alex, pulehui
Hello:
This series was applied to bpf/bpf-next.git (master)
by Kumar Kartikeya Dwivedi <memxor@gmail.com>:
On Sat, 5 Sep 2026 08:58:54 +0000 you wrote:
> Implement bpf_jit_supports_stack_args() on RV64 JIT to allow bpf
> subprogs and kfuncs to pass and receive more than 5 arguments.
>
> Tested on riscv64 QEMU with LLVM main [1]; BPF-to-BPF and kfunc
> selftests pass.
>
> [1] https://github.com/llvm/llvm-project/pull/189060
>
> [...]
Here is the summary with links:
- [bpf-next,v5,1/3] riscv, bpf: Remap BPF_REG_0 and RV_REG_TCC
https://git.kernel.org/bpf/bpf-next/c/f80a09c486e7
- [bpf-next,v5,2/3] riscv, bpf: Add BPF stack arguments support for RV64 JIT
https://git.kernel.org/bpf/bpf-next/c/ba754185f902
- [bpf-next,v5,3/3] selftests/bpf: Enable stack argument tests for RV64
https://git.kernel.org/bpf/bpf-next/c/7687f1cbbaf8
You are awesome, thank you!
--
Deet-doot-dot, I am a bot.
https://korg.docs.kernel.org/patchwork/pwbot.html
^ permalink raw reply [flat|nested] 8+ messages in thread
end of thread, other threads:[~2026-09-06 14:31 UTC | newest]
Thread overview: 8+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-09-05 8:58 [PATCH bpf-next v5 0/3] Add bpf stack arguments support for RV64 Pu Lehui
2026-09-05 8:58 ` [PATCH bpf-next v5 1/3] riscv, bpf: Remap BPF_REG_0 and RV_REG_TCC Pu Lehui
2026-09-05 9:42 ` bot+bpf-ci
2026-09-05 9:56 ` Pu Lehui
2026-09-05 8:58 ` [PATCH bpf-next v5 2/3] riscv, bpf: Add BPF stack arguments support for RV64 JIT Pu Lehui
2026-09-05 8:58 ` [PATCH bpf-next v5 3/3] selftests/bpf: Enable stack argument tests for RV64 Pu Lehui
2026-09-06 14:22 ` [PATCH bpf-next v5 0/3] Add bpf stack arguments support " Björn Töpel
2026-09-06 14:30 ` patchwork-bot+netdevbpf
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®