Re: [PATCH bpf-next v1 03/14] bpf, riscv: JIT arena kfunc argument rebasing
Pu Lehui <[email protected]>
| Newsgroups | org.kernel.vger.bpf |
|---|---|
| Message-ID | <[email protected]> |
On 2026/8/22 7:34, Kumar Kartikeya Dwivedi wrote: > A BPF arena pointer is represented as a zero-extended 32-bit offset while > a kfunc receives a kernel address. Kfuncs whose BTF argument names carry > the __arena suffix therefore need the JIT to rebase those offsets > immediately before the native call. > > RV_REG_ARENA already holds kern_vm_start whenever the program uses an > arena. Zero-extend each tagged argument and add that base: > > zext.w aN, aN > add aN, s7, aN > > For an __arena__nullable argument, branch over the fixed-width add when > the truncated offset is zero so that NULL remains NULL. An unconditionally > tagged zero is intentionally converted to the arena base. > > The sequence is emitted as native code after the BPF instruction stream > has been blinded, and its size depends only on the function model and > enabled ISA extensions. Advertise the kfunc capability independently; > struct_ops argument conversion is not enabled by this change. > > Cc: Björn Töpel <[email protected]> > Cc: Pu Lehui <[email protected]> > Signed-off-by: Kumar Kartikeya Dwivedi <[email protected]> > --- > arch/riscv/net/bpf_jit_comp64.c | 40 +++++++++++++++++++++++++++++++++ > 1 file changed, 40 insertions(+) > > diff --git a/arch/riscv/net/bpf_jit_comp64.c b/arch/riscv/net/bpf_jit_comp64.c > index b1084f30f3ce..c97d13a3eae4 100644 > --- a/arch/riscv/net/bpf_jit_comp64.c > +++ b/arch/riscv/net/bpf_jit_comp64.c > @@ -714,6 +714,37 @@ static int sign_extend(u8 rd, u8 rs, u8 sz, bool sign, struct rv_jit_context *ct > return 0; > } > > +/* > + * Rebase the __arena args of a kfunc call to arena kernel addresses, > + * aN = kern_vm_start + (u32)aN, with RV_REG_ARENA holding kern_vm_start. > + * A nullable arg preserves NULL by skipping the add, tested on the > + * truncated value as arena NULL is offset 0. > + */ > +static int emit_kfunc_arena_args(struct rv_jit_context *ctx, > + const struct btf_func_model *fm) > +{ > + int i; > + > + for (i = 0; i < min_t(int, fm->nr_args, MAX_BPF_FUNC_REG_ARGS); i++) { > + u8 flags = fm->arg_flags[i]; > + u8 reg = bpf_to_rv_reg(BPF_REG_1 + i, ctx); > + > + if (!(flags & BTF_FMODEL_ARENA_ARG)) > + continue; > + if (WARN_ON_ONCE(!ctx->arena_vm_start)) > + return -EINVAL; > + > + emit_zextw(reg, reg, ctx); > + if (flags & BTF_FMODEL_NULLABLE_ARG) { > + /* Skip the fixed-width add so that NULL stays NULL. */ > + emit(rv_beq(reg, RV_REG_ZERO, 4), ctx); > + } > + emit(rv_add(reg, RV_REG_ARENA, reg), ctx); > + } > + > + return 0; > +} > + > #define BPF_FIXUP_OFFSET_MASK GENMASK(26, 0) > #define BPF_FIXUP_REG_MASK GENMASK(31, 27) > #define REG_DONT_CLEAR_MARKER 0 /* RV_REG_ZERO unused in pt_regmap */ > @@ -1834,6 +1865,10 @@ int bpf_jit_emit_insn(const struct bpf_insn *insn, struct rv_jit_context *ctx, > if (sign_extend(reg, reg, fm->arg_size[idx], sign, ctx)) > return -EINVAL; sign_extend will emit for both signed and unsigned 4-byte kfunc arguments. The current patch therefore generates a redundant sign-ext prior to zero-ext for arena pointers. It would be cleaner to merge the two passes into a single loop: for (idx = 0; idx < fm->nr_args; idx++) { u8 flags = fm->arg_flags[idx]; bool sign = flags & BTF_FMODEL_SIGNED_ARG; u8 reg = bpf_to_rv_reg(BPF_REG_1 + idx, ctx); if (flags & BTF_FMODEL_ARENA_ARG) { xxx continue; } if (sign_extend(reg, reg, fm->arg_size[idx], sign, ctx)) return -EINVAL; } > } > + > + ret = emit_kfunc_arena_args(ctx, fm); > + if (ret) > + return ret; > } > > /* restore TCC to RV_REG_TCC before bpf2bpf call */ > @@ -2132,6 +2167,11 @@ bool bpf_jit_supports_kfunc_ret_reg_pair(void) > return true; > } > > +bool bpf_jit_supports_arena_kfunc_args(void) > +{ > + return true; > +} > + > bool bpf_jit_supports_ptr_xchg(void) > { > return true;