Skip to content

bpf, riscv: Add BPF stack arguments support for RV64 JIT - #13292

Open
kernel-patches-daemon-bpf[bot] wants to merge 3 commits into
bpf-next_basefrom
series/1145772=>bpf-next
Open

bpf, riscv: Add BPF stack arguments support for RV64 JIT#13292
kernel-patches-daemon-bpf[bot] wants to merge 3 commits into
bpf-next_basefrom
series/1145772=>bpf-next

Conversation

@kernel-patches-daemon-bpf

Copy link
Copy Markdown

Pull request for series with
subject: bpf, riscv: Add BPF stack arguments support for RV64 JIT
version: 3
url: https://patchwork.kernel.org/project/netdevbpf/list/?series=1145772

@kernel-patches-daemon-bpf

Copy link
Copy Markdown
Author

Upstream branch: 4d9551b
series: https://patchwork.kernel.org/project/netdevbpf/list/?series=1145772
version: 3

@kernel-patches-review-bot

Copy link
Copy Markdown
commit 8f86ad1c97a0ca38d816acf9b543e814ad4efb18
Author: Feng Jiang <jiangfeng@kylinos.cn>

bpf, riscv: Add BPF stack arguments support for RV64 JIT

This patch enables BPF stack arguments for the RV64 JIT, allowing
subprograms and kfuncs to receive more than 5 arguments. For BPF-to-BPF
calls, arguments are passed via memory (caller stores at SP, callee reads
at FP). For kfunc calls, arguments 6-8 are loaded into A5-A7 and
remaining arguments are copied down to match the RISC-V ABI.

> diff --git a/arch/riscv/net/bpf_jit_comp64.c b/arch/riscv/net/bpf_jit_comp64.c
> index 2504df1fa1118..62c84de22163f 100644
> --- a/arch/riscv/net/bpf_jit_comp64.c
> +++ b/arch/riscv/net/bpf_jit_comp64.c

[ ... ]

> @@ -1891,6 +1916,21 @@ int bpf_jit_emit_insn
>  	case BPF_LDX | BPF_MEM | BPF_H:
>  	case BPF_LDX | BPF_MEM | BPF_W:
>  	case BPF_LDX | BPF_MEM | BPF_DW:
> +		if (insn->src_reg == BPF_REG_PARAMS) {
> +			int idx = off / 8 - 1;
> +
> +			if (is_12b_int(idx * 8)) {
> +				emit_ldx_insn(rd, idx * 8, RV_REG_FP, BPF_SIZE(code), false, ctx);
> +			} else {
> +				emit_imm(RV_REG_T1, idx * 8, ctx);
> +				emit_add(RV_REG_T1, RV_REG_T1, RV_REG_FP, ctx);
> +				emit_ldx_insn(rd, 0, RV_REG_T1, BPF_SIZE(code), false, ctx);
> +			}
> +			if (BPF_SIZE(code) != BPF_DW && insn_is_zext(&insn[1]))
> +				return 1;
> +			break;
> +		}
> +		fallthrough;

Does this new BPF-to-BPF stack argument convention work correctly with
the existing RV64 trampoline code?

The convention here reads incoming stack arguments from FP+0, FP+8, etc
(callee FP == caller SP). But looking at store_args() in this same file,
the trampoline appears to use the native RISC-V ABI instead:

arch/riscv/net/bpf_jit_comp64.c:store_args() {
    for (i = 0; i < nr_arg_slots; i++) {
        if (i < RV_MAX_REG_ARGS)
            emit_sd(RV_REG_FP, -args_off, RV_REG_A0 + i, ctx);
        else
            emit_ld(RV_REG_T1, 16 + (i - RV_MAX_REG_ARGS) * 8, RV_REG_FP, ctx);

where RV_MAX_REG_ARGS is 8, so it expects arguments 6, 7, 8 in a5, a6, a7
and arguments 9+ at FP+16.

For a BPF subprogram using this new convention, arguments 6+ arrive in
memory, not in a5-a7. When an fentry or fexit program attaches to such a
subprogram, wouldn't it read unrelated register values instead of the real
arguments?

Both arm64 and x86-64 appear to avoid this by keeping their BPF stack
argument convention identical to their native ABIs. arm64 uses
`stack_arg_reg[] = { A64_R(5), A64_R(6), A64_R(7) }` and x86-64 keeps arg6
in r9, so their trampolines work without changes.

Can fentry/fexit attach to static BPF subprograms with more than 5
arguments, or is there a verifier check that prevents this?

[ ... ]



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

In-Reply-To-Subject: bpf, riscv: Add BPF stack arguments support for RV64 JIT
CI run summary: https://github.com/kernel-patches/bpf/actions/runs/31761418445

@kernel-patches-daemon-bpf

Copy link
Copy Markdown
Author

@kernel-patches-daemon-bpf

Copy link
Copy Markdown
Author

Upstream branch: 409a9bd
series: https://patchwork.kernel.org/project/netdevbpf/list/?series=1145772
version: 3

@kernel-patches-daemon-bpf

Copy link
Copy Markdown
Author

Upstream branch: c7e6175
series: https://patchwork.kernel.org/project/netdevbpf/list/?series=1145772
version: 3

@kernel-patches-daemon-bpf

Copy link
Copy Markdown
Author

Upstream branch: f2aaa62
series: https://patchwork.kernel.org/project/netdevbpf/list/?series=1145772
version: 3

@kernel-patches-daemon-bpf

Copy link
Copy Markdown
Author

Upstream branch: f2aaa62
series: https://patchwork.kernel.org/project/netdevbpf/list/?series=1145772
version: 3

@kernel-patches-daemon-bpf

Copy link
Copy Markdown
Author

Upstream branch: 90bd032
series: https://patchwork.kernel.org/project/netdevbpf/list/?series=1145772
version: 3

@kernel-patches-daemon-bpf

Copy link
Copy Markdown
Author

Upstream branch: a2b83a8
series: https://patchwork.kernel.org/project/netdevbpf/list/?series=1145772
version: 3

@kernel-patches-daemon-bpf

Copy link
Copy Markdown
Author

Upstream branch: fdd4fad
series: https://patchwork.kernel.org/project/netdevbpf/list/?series=1145772
version: 3

@kernel-patches-daemon-bpf

Copy link
Copy Markdown
Author

Upstream branch: 8eb1892
series: https://patchwork.kernel.org/project/netdevbpf/list/?series=1145772
version: 3

@kernel-patches-daemon-bpf

Copy link
Copy Markdown
Author

Upstream branch: d99bda7
series: https://patchwork.kernel.org/project/netdevbpf/list/?series=1145772
version: 3

@kernel-patches-daemon-bpf

Copy link
Copy Markdown
Author

Upstream branch: 34e0eb7
series: https://patchwork.kernel.org/project/netdevbpf/list/?series=1145772
version: 3

@kernel-patches-daemon-bpf

Copy link
Copy Markdown
Author

Upstream branch: 5fe7007
series: https://patchwork.kernel.org/project/netdevbpf/list/?series=1145772
version: 3

@kernel-patches-daemon-bpf

Copy link
Copy Markdown
Author

Upstream branch: 77877bf
series: https://patchwork.kernel.org/project/netdevbpf/list/?series=1145772
version: 3

@kernel-patches-daemon-bpf

Copy link
Copy Markdown
Author

Upstream branch: adb7719
series: https://patchwork.kernel.org/project/netdevbpf/list/?series=1145772
version: 3

@kernel-patches-daemon-bpf

Copy link
Copy Markdown
Author

Upstream branch: 6b0835a
series: https://patchwork.kernel.org/project/netdevbpf/list/?series=1145772
version: 3

@kernel-patches-daemon-bpf

Copy link
Copy Markdown
Author

Upstream branch: 6ab6a94
series: https://patchwork.kernel.org/project/netdevbpf/list/?series=1145772
version: 3

Add bpf_jit_supports_stack_args() for the RV64 JIT so BPF subprograms
and kfuncs can receive more than 5 arguments via the stack
(BPF_REG_PARAMS / r11).

For BPF-to-BPF calls the caller writes outgoing arguments at the
bottom of its frame (SP-relative). The callee reads them with
FP-relative loads. Its FP is set to the caller SP in the prologue,
so the offsets match.

The RISC-V ABI puts arguments 6-8 in A5-A7 and arguments 9+ at
SP+0. Before each kfunc call, load arguments 6-8 from the outgoing
area into A5-A7 and copy any remaining arguments down so argument 9
lands at SP+0.

A5 (BPF_REG_0), A6 (TCC) and A7 are safe to clobber here: R0 is not
live before a call, TCC is backed up on the stack, and A7 is unused
by the JIT.

Limit the existing kfunc sign-extension loop to MAX_BPF_FUNC_REG_ARGS
iterations; otherwise idx >= 5 resolves to S1-S5 (BPF_R6-FP) and
corrupts callee-saved registers.

Signed-off-by: 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] llvm/llvm-project#189060

Signed-off-by: Feng Jiang <jiangfeng@kylinos.cn>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant