[PATCH bpf-next v2] bpf, mips: Add BPF_MEMSX support to the JITs
From: Nicholas Dudar <hidden>
Date: 2026-09-12 18:06:48
Also in:
bpf, lkml
Subsystem:
bpf jit for mips (32-bit and 64-bit), bpf [general] (safe dynamic programs and tools), mips, the rest · Maintainers:
Johan Almbladh, Paul Burton, Alexei Starovoitov, Daniel Borkmann, Andrii Nakryiko, Eduard Zingerman, Kumar Kartikeya Dwivedi, Thomas Bogendoerfer, Linus Torvalds
The MIPS JITs reject BPF_MEMSX loads, preventing programs that use them from running where JIT compilation is required. Codex-assisted analysis of public test output identified the missing MEMSX support. Add signed byte, half-word and word loads using lb, lh and lw. On MIPS64 these produce the full result. On MIPS32, propagate the loaded word's sign into the high word after the required load delay. Keep signed loads separate from ordinary loads, which can clear the high word in the load-delay slot. Suggested-by: Johan Almbladh <johan.almbladh@anyfinetworks.com> Assisted-by: Codex:gpt-6 Signed-off-by: Nicholas Dudar <redacted> --- Changes in v2: - Keep unsigned LDX and signed LDSX as separate complete emitters. - Drop the helper-only preparatory patch from v1. This patch depends on SDIV/SMOD v4 and MOVSX v3, in that order. Enabling MEMSX lets mixed programs reach JIT execution, so their signed arithmetic and register moves must also be implemented. https://lore.kernel.org/bpf/20260911213340.3767930-1-main.kalliope@gmail.com/ (local) https://lore.kernel.org/bpf/20260912041220.444715-1-main.kalliope@gmail.com/ (local) I ran the full test_bpf suite on both the prerequisite stack and this patch under QEMU Malta, using little-endian MIPS32 R2 and MIPS64 R2. An out-of-tree fixture strengthens the signed/unsigned load comparisons and adds negative and sign-clear loads with dst == src. All five MEMSX tests move from JIT rejection to passing: MIPS32 goes from 1050/14 to 1055/9 pass/fail, and MIPS64 from 1049/14 to 1054/9. The remaining failures are 8 BSWAP and 1 JMP32_JA cases. No other test verdict changes. Additional test_bpf fixtures passed on MIPS32 R2 big-endian and MIPS64 R2 little-endian, covering signed boundaries, aliasing, R6-R9 preservation across a helper call, and large signed offsets. JIT disassembly confirmed the load and register-save sequences. These tests exercise the JIT directly, bypassing the verifier. Earlier comparisons covered MIPS32 R1/R2/R6 and MIPS64 R2 in both byte orders, plus MIPS64 R6 little-endian. Those results predate this rebase; the signed-load emitters and their delay/clobber helpers are identical. No physical hardware or MIPS I CPU was tested. Link to v1: https://lore.kernel.org/bpf/20260821024640.1601299-1-main.kalliope@gmail.com/ (local) arch/mips/net/bpf_jit_comp32.c | 29 +++++++++++++++++++++++++++++ arch/mips/net/bpf_jit_comp64.c | 26 ++++++++++++++++++++++++++ 2 files changed, 55 insertions(+)
diff --git a/arch/mips/net/bpf_jit_comp32.c b/arch/mips/net/bpf_jit_comp32.c
index 8f1ab851863fc9aaa4a107dcd3633c5f51f219ea..f72cd21eb5ccbb6eaba15439958c12eb072b3900 100644
--- a/arch/mips/net/bpf_jit_comp32.c
+++ b/arch/mips/net/bpf_jit_comp32.c@@ -757,6 +757,29 @@ static void emit_ldx(struct jit_context *ctx, clobber_reg64(ctx, dst); } +/* Load operation with sign extension: dst = *(signed size *)(src + off) */ +static void emit_ldsx(struct jit_context *ctx, + const u8 dst[], u8 src, s16 off, u8 size) +{ + switch (size) { + /* Load a byte */ + case BPF_B: + emit(ctx, lb, lo(dst), off, src); + break; + /* Load a half word */ + case BPF_H: + emit(ctx, lh, lo(dst), off, src); + break; + /* Load a word */ + case BPF_W: + emit(ctx, lw, lo(dst), off, src); + break; + } + emit_load_delay(ctx); + emit(ctx, sra, hi(dst), lo(dst), 31); + clobber_reg64(ctx, dst); +} + /* Store operation: *(size *)(dst + off) = src */ static void emit_stx(struct jit_context *ctx, const u8 dst, const u8 src[], s16 off, u8 size)
@@ -1728,6 +1751,12 @@ int build_insn(const struct bpf_insn *insn, struct jit_context *ctx) case BPF_LDX | BPF_MEM | BPF_DW: emit_ldx(ctx, dst, lo(src), off, BPF_SIZE(code)); break; + /* LDSX: dst = *(signed size *)(src + off) */ + case BPF_LDX | BPF_MEMSX | BPF_W: + case BPF_LDX | BPF_MEMSX | BPF_H: + case BPF_LDX | BPF_MEMSX | BPF_B: + emit_ldsx(ctx, dst, lo(src), off, BPF_SIZE(code)); + break; /* ST: *(size *)(dst + off) = imm */ case BPF_ST | BPF_MEM | BPF_W: case BPF_ST | BPF_MEM | BPF_H:
diff --git a/arch/mips/net/bpf_jit_comp64.c b/arch/mips/net/bpf_jit_comp64.c
index 4507841a922484cda126e57d52d6a2924ef33a72..7bba0d4b0b2c04a742dec6234e4c6e610532e132 100644
--- a/arch/mips/net/bpf_jit_comp64.c
+++ b/arch/mips/net/bpf_jit_comp64.c@@ -431,6 +431,26 @@ static void emit_ldx(struct jit_context *ctx, u8 dst, u8 src, s16 off, u8 size) clobber_reg(ctx, dst); } +/* Load operation with sign extension: dst = *(signed size *)(src + off) */ +static void emit_ldsx(struct jit_context *ctx, u8 dst, u8 src, s16 off, u8 size) +{ + switch (size) { + /* Load a byte */ + case BPF_B: + emit(ctx, lb, dst, off, src); + break; + /* Load a half word */ + case BPF_H: + emit(ctx, lh, dst, off, src); + break; + /* Load a word */ + case BPF_W: + emit(ctx, lw, dst, off, src); + break; + } + clobber_reg(ctx, dst); +} + /* Store operation: *(size *)(dst + off) = src */ static void emit_stx(struct jit_context *ctx, u8 dst, u8 src, s16 off, u8 size) {
@@ -903,6 +923,12 @@ int build_insn(const struct bpf_insn *insn, struct jit_context *ctx) case BPF_LDX | BPF_MEM | BPF_DW: emit_ldx(ctx, dst, src, off, BPF_SIZE(code)); break; + /* LDSX: dst = *(signed size *)(src + off) */ + case BPF_LDX | BPF_MEMSX | BPF_W: + case BPF_LDX | BPF_MEMSX | BPF_H: + case BPF_LDX | BPF_MEMSX | BPF_B: + emit_ldsx(ctx, dst, src, off, BPF_SIZE(code)); + break; /* ST: *(size *)(dst + off) = imm */ case BPF_ST | BPF_MEM | BPF_W: case BPF_ST | BPF_MEM | BPF_H:
base-commit: c1ff425d625eb2a4d2967e9889b85f202f24eb5d prerequisite-patch-id: aa8ca3f50fc4b0160c5fdba43a92e4b7ec3f2e07 prerequisite-patch-id: 9f324d79755bae54c56ce6c90769acc8595c9ad6 prerequisite-patch-id: 35236f563c0536859077709d52b345b696e5c26e prerequisite-patch-id: c0f282b0e57ecd60e9582fb1e89e4b3112ae7893 prerequisite-patch-id: 528eee53fa86686e7e69fa8a12c605b386381a33