[PATCH bpf-next v1 03/14] bpf, riscv: JIT arena kfunc argument rebasing

Kumar Kartikeya Dwivedi <[email protected]>
Newsgroups org.kernel.vger.bpf
Message-ID <[email protected]>
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;
 			}
+
+			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;
-- 
2.53.0
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.