[PATCH bpf-next v2 06/11] LoongArch: BPF: Support sign-extending loads from arena
From: George Guo
Date: Wed Jul 01 2026 - 22:25:30 EST
From: George Guo <guodongtai@xxxxxxxxxx>
A sign-extending load from an arena pointer is rewritten by the verifier
to BPF_PROBE_MEM32SX once the JIT advertises support for it through
bpf_jit_supports_insn(); the generic helper otherwise defaults to
rejecting arena instructions. Add the callback and implement the load:
route BPF_PROBE_MEM32SX through the existing BPF_PROBE_MEM32 path, which
adds the arena base held in REG_ARENA, while selecting the
sign-extending load variants (ld.b/ld.h/ld.w), and register an exception
table entry so a fault on the access is handled like the other arena
probes.
Signed-off-by: George Guo <guodongtai@xxxxxxxxxx>
---
arch/loongarch/net/bpf_jit.c | 28 +++++++++++++++++++++++++---
1 file changed, 25 insertions(+), 3 deletions(-)
diff --git a/arch/loongarch/net/bpf_jit.c b/arch/loongarch/net/bpf_jit.c
index f172ffc2c011..4a3b632c1fde 100644
--- a/arch/loongarch/net/bpf_jit.c
+++ b/arch/loongarch/net/bpf_jit.c
@@ -739,7 +739,8 @@ static int add_exception_handler(const struct bpf_insn *insn,
if (BPF_MODE(insn->code) != BPF_PROBE_MEM &&
BPF_MODE(insn->code) != BPF_PROBE_MEMSX &&
- BPF_MODE(insn->code) != BPF_PROBE_MEM32)
+ BPF_MODE(insn->code) != BPF_PROBE_MEM32 &&
+ BPF_MODE(insn->code) != BPF_PROBE_MEM32SX)
return 0;
if (WARN_ON_ONCE(ctx->num_exentries >= ctx->prog->aux->num_exentries))
@@ -1349,10 +1350,16 @@ static int build_insn(const struct bpf_insn *insn, struct jit_ctx *ctx, bool ext
case BPF_LDX | BPF_PROBE_MEM32 | BPF_H:
case BPF_LDX | BPF_PROBE_MEM32 | BPF_W:
case BPF_LDX | BPF_PROBE_MEM32 | BPF_DW:
+ /* LDX | PROBE_MEM32SX: dst = *(signed size *)(src + REG_ARENA + off) */
+ case BPF_LDX | BPF_PROBE_MEM32SX | BPF_B:
+ case BPF_LDX | BPF_PROBE_MEM32SX | BPF_H:
+ case BPF_LDX | BPF_PROBE_MEM32SX | BPF_W:
sign_extend = BPF_MODE(code) == BPF_MEMSX ||
- BPF_MODE(code) == BPF_PROBE_MEMSX;
+ BPF_MODE(code) == BPF_PROBE_MEMSX ||
+ BPF_MODE(code) == BPF_PROBE_MEM32SX;
- if (BPF_MODE(code) == BPF_PROBE_MEM32) {
+ if (BPF_MODE(code) == BPF_PROBE_MEM32 ||
+ BPF_MODE(code) == BPF_PROBE_MEM32SX) {
emit_insn(ctx, addd, t2, src, REG_ARENA);
src = t2;
}
@@ -2548,6 +2555,21 @@ bool bpf_jit_supports_arena(void)
return true;
}
+bool bpf_jit_supports_insn(struct bpf_insn *insn, bool in_arena)
+{
+ if (!in_arena)
+ return true;
+
+ switch (insn->code) {
+ case BPF_STX | BPF_ATOMIC | BPF_W:
+ case BPF_STX | BPF_ATOMIC | BPF_DW:
+ /* Atomics on arena pointers are not implemented yet. */
+ return false;
+ }
+
+ return true;
+}
+
bool bpf_jit_supports_fsession(void)
{
return true;
--
2.25.1