From: Chen Pei <cp0613@linux.alibaba.com>
To: ast@kernel.org, daniel@iogearbox.net, andrii@kernel.org,
memxor@gmail.com, bjorn@kernel.org, puranjay@kernel.org
Cc: eddyz87@gmail.com, martin.lau@linux.dev, song@kernel.org,
yonghong.song@linux.dev, jolsa@kernel.org, emil@etsalapatis.com,
ihor.solodrai@linux.dev, pulehui@huawei.com, pjw@kernel.org,
palmer@dabbelt.com, aou@eecs.berkeley.edu, alex@ghiti.fr,
luke.r.nels@gmail.com, xi.wang@gmail.com, shuah@kernel.org,
rgbi3307@gmail.com, guoren@kernel.org, bpf@vger.kernel.org,
linux-riscv@lists.infradead.org, linux-kselftest@vger.kernel.org,
linux-kernel@vger.kernel.org
Subject: [PATCH bpf-next 0/3] riscv: bpf: Add BPF private stack support
Date: Thu, 15 Oct 2026 10:12:35 +0800 [thread overview]
Message-ID: <20261015021238.5657-1-cp0613@linux.alibaba.com> (raw)
This series adds private-stack support to the RV64 BPF JIT.
The verifier rejects a struct_ops program that requests a private stack
with -EACCES when the JIT does not report
bpf_jit_supports_private_stack(), and sched_ext requests one for its
dispatch callback, so no sched_ext scheduler can load on riscv64 today.
Allocation, the 16-byte guard regions at both ends, the guard value and
the lifetime handling follow arm64, x86-64 and powerpc64. What is
specific to riscv64 is where the pointers end up:
- Every BPF stack access goes through BPF_REG_FP (S5), so pointing S5
at the top of the per-CPU area and leaving SP on the kernel stack is
all the JIT has to do. S5 is callee-saved and each subprog derives
its own, so bpf2bpf calls need no extra save and restore.
- The outgoing stack-argument area stays in the kernel frame: callers
write it relative to SP while callees read it relative to RV_REG_FP.
Unlike x86-64, no register here is shared with the private-stack
frame pointer, so no verifier-side exclusion is needed and stack
arguments keep working together with a private stack. arm64 already
does the same, and patch 3 measures the three ranges at run time and
pins them in the disassembly.
- The per-CPU lookup is emitted after the tail-call entry point. A
program using a private stack can still be entered as a tail-call
target, at RV_TAILCALL_OFFSET, so it has to set up its own S5 there;
and since that offset is a constant added to the target's bpf_func,
everything in front of it must be the same size in every program.
The base address is materialized with absolute moves, as on arm64,
x86-64 and powerpc64. Those three reach the per-CPU offset through gs:,
TPIDR or r13 and only have to move the base into a register; riscv64 has
no such register, so the address of __per_cpu_offset is loaded here too.
A PC-relative pair is not an option for the base itself: the dynamic
per-CPU area is vmalloc'd, further from the JIT region than auipc
reaches, which is why the whole setup is ten instructions on the sv39
kernel tested here. __per_cpu_offset is a kernel-image symbol and could
use the emit_addr() form that insn_is_mov_percpu_addr() already uses, at
the same two instructions; unifying the two needs an extra_pass argument
and an error return in bpf_jit_build_prologue(), which also touches
bpf_jit_comp32.c, so it is left as is. Both constants are fixed before
the offset-convergence loop, so the prologue length is stable across
passes.
RV32 does not declare support and keeps the existing behaviour; the
prologue signature is unchanged, so bpf_jit_comp32.c needs no edit.
Testing
=======
QEMU virt rv64, an 8 vCPU SMP kernel and a 1 vCPU UP kernel, source tree
clean at the head of this series, selftests built from these patches, no
private-stack related failures. On UP, kfunc_call/subprog,
kfunc_call/subprog_lskel and scx_simple are not run: all three fail the
same way on the unpatched base.
- verifier_private_stack, struct_ops_private_stack,
private_stack_runtime
- tailcalls, stack_arg, subprogs, fentry_fexit, kfunc_call,
percpu_alloc, async_stack_depth, arena_atomics, arena_ldsx
- may_goto_priv_stack, may_goto_far, verifier_may_goto_1,
verifier_may_goto_2
- scx_simple on SMP
Chen Pei (3):
riscv: bpf: Add BPF private stack support
selftests/bpf: Enable private stack tests for riscv64
selftests/bpf: Add a runtime test for private stack and stack
arguments
arch/riscv/net/bpf_jit.h | 1 +
arch/riscv/net/bpf_jit_comp64.c | 42 +++++-
arch/riscv/net/bpf_jit_core.c | 84 +++++++++--
.../selftests/bpf/private_stack_runtime.h | 12 ++
.../bpf/prog_tests/private_stack_runtime.c | 83 +++++++++++
.../bpf/prog_tests/struct_ops_private_stack.c | 3 +-
.../bpf/progs/private_stack_runtime.c | 140 ++++++++++++++++++
.../bpf/progs/verifier_private_stack.c | 41 ++++-
8 files changed, 392 insertions(+), 14 deletions(-)
create mode 100644 tools/testing/selftests/bpf/private_stack_runtime.h
create mode 100644 tools/testing/selftests/bpf/prog_tests/private_stack_runtime.c
create mode 100644 tools/testing/selftests/bpf/progs/private_stack_runtime.c
--
2.50.1
WARNING: multiple messages have this Message-ID (diff)
From: Chen Pei <cp0613@linux.alibaba.com>
To: ast@kernel.org, daniel@iogearbox.net, andrii@kernel.org,
memxor@gmail.com, bjorn@kernel.org, puranjay@kernel.org
Cc: eddyz87@gmail.com, martin.lau@linux.dev, song@kernel.org,
yonghong.song@linux.dev, jolsa@kernel.org, emil@etsalapatis.com,
ihor.solodrai@linux.dev, pulehui@huawei.com, pjw@kernel.org,
palmer@dabbelt.com, aou@eecs.berkeley.edu, alex@ghiti.fr,
luke.r.nels@gmail.com, xi.wang@gmail.com, shuah@kernel.org,
rgbi3307@gmail.com, guoren@kernel.org, bpf@vger.kernel.org,
linux-riscv@lists.infradead.org, linux-kselftest@vger.kernel.org,
linux-kernel@vger.kernel.org
Subject: [PATCH bpf-next 0/3] riscv: bpf: Add BPF private stack support
Date: Thu, 15 Oct 2026 10:12:35 +0800 [thread overview]
Message-ID: <20261015021238.5657-1-cp0613@linux.alibaba.com> (raw)
This series adds private-stack support to the RV64 BPF JIT.
The verifier rejects a struct_ops program that requests a private stack
with -EACCES when the JIT does not report
bpf_jit_supports_private_stack(), and sched_ext requests one for its
dispatch callback, so no sched_ext scheduler can load on riscv64 today.
Allocation, the 16-byte guard regions at both ends, the guard value and
the lifetime handling follow arm64, x86-64 and powerpc64. What is
specific to riscv64 is where the pointers end up:
- Every BPF stack access goes through BPF_REG_FP (S5), so pointing S5
at the top of the per-CPU area and leaving SP on the kernel stack is
all the JIT has to do. S5 is callee-saved and each subprog derives
its own, so bpf2bpf calls need no extra save and restore.
- The outgoing stack-argument area stays in the kernel frame: callers
write it relative to SP while callees read it relative to RV_REG_FP.
Unlike x86-64, no register here is shared with the private-stack
frame pointer, so no verifier-side exclusion is needed and stack
arguments keep working together with a private stack. arm64 already
does the same, and patch 3 measures the three ranges at run time and
pins them in the disassembly.
- The per-CPU lookup is emitted after the tail-call entry point. A
program using a private stack can still be entered as a tail-call
target, at RV_TAILCALL_OFFSET, so it has to set up its own S5 there;
and since that offset is a constant added to the target's bpf_func,
everything in front of it must be the same size in every program.
The base address is materialized with absolute moves, as on arm64,
x86-64 and powerpc64. Those three reach the per-CPU offset through gs:,
TPIDR or r13 and only have to move the base into a register; riscv64 has
no such register, so the address of __per_cpu_offset is loaded here too.
A PC-relative pair is not an option for the base itself: the dynamic
per-CPU area is vmalloc'd, further from the JIT region than auipc
reaches, which is why the whole setup is ten instructions on the sv39
kernel tested here. __per_cpu_offset is a kernel-image symbol and could
use the emit_addr() form that insn_is_mov_percpu_addr() already uses, at
the same two instructions; unifying the two needs an extra_pass argument
and an error return in bpf_jit_build_prologue(), which also touches
bpf_jit_comp32.c, so it is left as is. Both constants are fixed before
the offset-convergence loop, so the prologue length is stable across
passes.
RV32 does not declare support and keeps the existing behaviour; the
prologue signature is unchanged, so bpf_jit_comp32.c needs no edit.
Testing
=======
QEMU virt rv64, an 8 vCPU SMP kernel and a 1 vCPU UP kernel, source tree
clean at the head of this series, selftests built from these patches, no
private-stack related failures. On UP, kfunc_call/subprog,
kfunc_call/subprog_lskel and scx_simple are not run: all three fail the
same way on the unpatched base.
- verifier_private_stack, struct_ops_private_stack,
private_stack_runtime
- tailcalls, stack_arg, subprogs, fentry_fexit, kfunc_call,
percpu_alloc, async_stack_depth, arena_atomics, arena_ldsx
- may_goto_priv_stack, may_goto_far, verifier_may_goto_1,
verifier_may_goto_2
- scx_simple on SMP
Chen Pei (3):
riscv: bpf: Add BPF private stack support
selftests/bpf: Enable private stack tests for riscv64
selftests/bpf: Add a runtime test for private stack and stack
arguments
arch/riscv/net/bpf_jit.h | 1 +
arch/riscv/net/bpf_jit_comp64.c | 42 +++++-
arch/riscv/net/bpf_jit_core.c | 84 +++++++++--
.../selftests/bpf/private_stack_runtime.h | 12 ++
.../bpf/prog_tests/private_stack_runtime.c | 83 +++++++++++
.../bpf/prog_tests/struct_ops_private_stack.c | 3 +-
.../bpf/progs/private_stack_runtime.c | 140 ++++++++++++++++++
.../bpf/progs/verifier_private_stack.c | 41 ++++-
8 files changed, 392 insertions(+), 14 deletions(-)
create mode 100644 tools/testing/selftests/bpf/private_stack_runtime.h
create mode 100644 tools/testing/selftests/bpf/prog_tests/private_stack_runtime.c
create mode 100644 tools/testing/selftests/bpf/progs/private_stack_runtime.c
--
2.50.1
_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv
next reply other threads:[~2026-10-15 2:13 UTC|newest]
Thread overview: 15+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-10-15 2:12 Chen Pei [this message]
2026-10-15 2:12 ` [PATCH bpf-next 0/3] riscv: bpf: Add BPF private stack support Chen Pei
2026-10-15 2:12 ` [PATCH bpf-next 1/3] " Chen Pei
2026-10-15 2:12 ` Chen Pei
2026-10-15 2:58 ` bot+bpf-ci
2026-10-15 2:58 ` bot+bpf-ci
2026-10-15 2:12 ` [PATCH bpf-next 2/3] selftests/bpf: Enable private stack tests for riscv64 Chen Pei
2026-10-15 2:12 ` Chen Pei
2026-10-15 2:22 ` sashiko-bot
2026-10-15 8:00 ` Chen Pei
2026-10-15 2:12 ` [PATCH bpf-next 3/3] selftests/bpf: Add a runtime test for private stack and stack arguments Chen Pei
2026-10-15 2:12 ` Chen Pei
2026-10-15 2:23 ` sashiko-bot
2026-10-15 2:59 ` bot+bpf-ci
2026-10-15 2:59 ` bot+bpf-ci
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20261015021238.5657-1-cp0613@linux.alibaba.com \
--to=cp0613@linux.alibaba.com \
--cc=alex@ghiti.fr \
--cc=andrii@kernel.org \
--cc=aou@eecs.berkeley.edu \
--cc=ast@kernel.org \
--cc=bjorn@kernel.org \
--cc=bpf@vger.kernel.org \
--cc=daniel@iogearbox.net \
--cc=eddyz87@gmail.com \
--cc=emil@etsalapatis.com \
--cc=guoren@kernel.org \
--cc=ihor.solodrai@linux.dev \
--cc=jolsa@kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-kselftest@vger.kernel.org \
--cc=linux-riscv@lists.infradead.org \
--cc=luke.r.nels@gmail.com \
--cc=martin.lau@linux.dev \
--cc=memxor@gmail.com \
--cc=palmer@dabbelt.com \
--cc=pjw@kernel.org \
--cc=pulehui@huawei.com \
--cc=puranjay@kernel.org \
--cc=rgbi3307@gmail.com \
--cc=shuah@kernel.org \
--cc=song@kernel.org \
--cc=xi.wang@gmail.com \
--cc=yonghong.song@linux.dev \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.