* [RFC bpf-next 0/2] bpf, mips: Add BPF_MEMSX support to the JITs
@ 2026-08-21 2:46 Nicholas Dudar
2026-08-21 2:46 ` [RFC bpf-next 1/2] bpf, mips: Factor narrow loads out of emit_ldx() Nicholas Dudar
2026-08-21 2:46 ` [RFC bpf-next 2/2] bpf, mips: Add BPF_MEMSX support to the JITs Nicholas Dudar
0 siblings, 2 replies; 3+ messages in thread
From: Nicholas Dudar @ 2026-08-21 2:46 UTC (permalink / raw)
To: ast, daniel, andrii, eddyz87, memxor, johan.almbladh, paulburton,
tsbogend
Cc: martin.lau, song, yonghong.song, jolsa, emil, ihor.solodrai, bpf,
linux-mips, linux-kernel
bpf-next is closed for the merge window, so I am sending this for
review. I plan to post this series after it reopens.
The MIPS32 and MIPS64 JITs reject BPF_MEMSX byte, half-word, and word
instructions, so a program containing one cannot run when JIT execution
is required.
First factor ordinary narrow-load selection into backend-local helpers.
Then extend those helpers to select signed native loads for BPF_MEMSX.
MIPS32 observes the load-delay rule and propagates the low-word sign into
the high half; MIPS64 obtains the full result from the native load.
Ordinary loads remain unsigned, and BPF_MEMSX with BPF_DW remains
unsupported.
This series must be applied after the in-review MIPS MOVSX and SDIV/SMOD
series:
MOVSX: https://lore.kernel.org/bpf/20260819010523.1057789-1-main.kalliope@gmail.com/
SDIV/SMOD: https://lore.kernel.org/bpf/20260810194215.3754591-1-main.kalliope@gmail.com/
Applying MEMSX removes a whole-program JIT fallback that otherwise keeps
mixed programs containing unsupported MOVSX or signed DIV/MOD out of the
JIT.
The ordering discussion is here:
https://lore.kernel.org/bpf/CAJZwKkis=3NGw9At0WfiZaRYEoMPbQfqJKN0e+vtRDvp4VY5Ng@mail.gmail.com/
On four little-endian profiles, patch 1 leaves the complete test_bpf
results with 1031 passed/31 failed on MIPS32 and 1030/31 on MIPS64.
Patch 2 changes the three MEMSX cases, yielding 1034/28 and 1033/28,
respectively. Ordinary unsigned-load controls passed at each boundary.
Selector-focused QEMU testing covered MIPS32 base, R2, and R6 plus
pre-R6 MIPS64, each in big- and little-endian configurations. The focused
mixed-operation matrix reproduced the unsafe MEMSX-first ordering and the
correct fully composed result on MIPS32 and MIPS64, both big- and
little-endian. No physical MIPS hardware was tested.
Nicholas Dudar (2):
bpf, mips: Factor narrow loads out of emit_ldx()
bpf, mips: Add BPF_MEMSX support to the JITs
arch/mips/net/bpf_jit_comp32.c | 51 ++++++++++++++++++++++++++++------
arch/mips/net/bpf_jit_comp64.c | 47 +++++++++++++++++++++++++++----
2 files changed, 85 insertions(+), 13 deletions(-)
base-commit: 91ec2035134982b98fab0609a9fd8480e8217dc1
prerequisite-patch-id: aa8ca3f50fc4b0160c5fdba43a92e4b7ec3f2e07
prerequisite-patch-id: bda4c3f3d59b48d784ed98bd8558d9591399bc86
prerequisite-patch-id: 35236f563c0536859077709d52b345b696e5c26e
prerequisite-patch-id: c0f282b0e57ecd60e9582fb1e89e4b3112ae7893
prerequisite-patch-id: 4e93eed38f6585e21fc13931c314907b4e437ef5
^ permalink raw reply [flat|nested] 3+ messages in thread
* [RFC bpf-next 1/2] bpf, mips: Factor narrow loads out of emit_ldx()
2026-08-21 2:46 [RFC bpf-next 0/2] bpf, mips: Add BPF_MEMSX support to the JITs Nicholas Dudar
@ 2026-08-21 2:46 ` Nicholas Dudar
2026-08-21 2:46 ` [RFC bpf-next 2/2] bpf, mips: Add BPF_MEMSX support to the JITs Nicholas Dudar
1 sibling, 0 replies; 3+ messages in thread
From: Nicholas Dudar @ 2026-08-21 2:46 UTC (permalink / raw)
To: ast, daniel, andrii, eddyz87, memxor, johan.almbladh, paulburton,
tsbogend
Cc: martin.lau, song, yonghong.song, jolsa, emil, ihor.solodrai, bpf,
linux-mips, linux-kernel
Factor the byte, half-word, and word load selection out of emit_ldx()
in both MIPS JIT backends. The existing unsigned LDX paths remain the
only callers and retain the same native instructions, upper-half
handling, and clobber accounting. The double-word paths remain
unchanged.
This gives narrow loads one width dispatcher that can be extended
without duplicating the BPF size switch. No functional change
intended.
Assisted-by: Codex:gpt-5.6-sol
Signed-off-by: Nicholas Dudar <main.kalliope@gmail.com>
---
arch/mips/net/bpf_jit_comp32.c | 28 ++++++++++++++++++++--------
arch/mips/net/bpf_jit_comp64.c | 18 ++++++++++++++++--
2 files changed, 36 insertions(+), 10 deletions(-)
diff --git a/arch/mips/net/bpf_jit_comp32.c b/arch/mips/net/bpf_jit_comp32.c
index b3f6b92ac34ed..48a3c834453f2 100644
--- a/arch/mips/net/bpf_jit_comp32.c
+++ b/arch/mips/net/bpf_jit_comp32.c
@@ -707,24 +707,36 @@ static void emit_trunc_r64(struct jit_context *ctx, const u8 dst[], u32 width)
}
}
-/* Load operation: dst = *(size*)(src + off) */
-static void emit_ldx(struct jit_context *ctx,
- const u8 dst[], u8 src, s16 off, u8 size)
+/* Narrow load operation: dst = *(size *)(src + off) */
+static void emit_ldx_narrow(struct jit_context *ctx,
+ u8 dst, u8 src, s16 off, u8 size)
{
switch (size) {
/* Load a byte */
case BPF_B:
- emit(ctx, lbu, lo(dst), off, src);
- emit(ctx, move, hi(dst), MIPS_R_ZERO);
+ emit(ctx, lbu, dst, off, src);
break;
/* Load a half word */
case BPF_H:
- emit(ctx, lhu, lo(dst), off, src);
- emit(ctx, move, hi(dst), MIPS_R_ZERO);
+ emit(ctx, lhu, dst, off, src);
break;
/* Load a word */
case BPF_W:
- emit(ctx, lw, lo(dst), off, src);
+ emit(ctx, lw, dst, off, src);
+ break;
+ }
+}
+
+/* Load operation: dst = *(size *)(src + off) */
+static void emit_ldx(struct jit_context *ctx,
+ const u8 dst[], u8 src, s16 off, u8 size)
+{
+ switch (size) {
+ /* Load a byte, half word or word */
+ case BPF_B:
+ case BPF_H:
+ case BPF_W:
+ emit_ldx_narrow(ctx, lo(dst), src, off, size);
emit(ctx, move, hi(dst), MIPS_R_ZERO);
break;
/* Load a double word */
diff --git a/arch/mips/net/bpf_jit_comp64.c b/arch/mips/net/bpf_jit_comp64.c
index ee99f46828c86..22fb58f970223 100644
--- a/arch/mips/net/bpf_jit_comp64.c
+++ b/arch/mips/net/bpf_jit_comp64.c
@@ -398,8 +398,9 @@ static void emit_trunc_r64(struct jit_context *ctx, u8 dst, u32 width)
clobber_reg(ctx, dst);
}
-/* Load operation: dst = *(size*)(src + off) */
-static void emit_ldx(struct jit_context *ctx, u8 dst, u8 src, s16 off, u8 size)
+/* Narrow load operation: dst = *(size *)(src + off) */
+static void emit_ldx_narrow(struct jit_context *ctx,
+ u8 dst, u8 src, s16 off, u8 size)
{
switch (size) {
/* Load a byte */
@@ -414,6 +415,19 @@ static void emit_ldx(struct jit_context *ctx, u8 dst, u8 src, s16 off, u8 size)
case BPF_W:
emit(ctx, lwu, dst, off, src);
break;
+ }
+}
+
+/* Load operation: dst = *(size *)(src + off) */
+static void emit_ldx(struct jit_context *ctx, u8 dst, u8 src, s16 off, u8 size)
+{
+ switch (size) {
+ /* Load a byte, half word or word */
+ case BPF_B:
+ case BPF_H:
+ case BPF_W:
+ emit_ldx_narrow(ctx, dst, src, off, size);
+ break;
/* Load a double word */
case BPF_DW:
emit(ctx, ld, dst, off, src);
^ permalink raw reply related [flat|nested] 3+ messages in thread
* [RFC bpf-next 2/2] bpf, mips: Add BPF_MEMSX support to the JITs
2026-08-21 2:46 [RFC bpf-next 0/2] bpf, mips: Add BPF_MEMSX support to the JITs Nicholas Dudar
2026-08-21 2:46 ` [RFC bpf-next 1/2] bpf, mips: Factor narrow loads out of emit_ldx() Nicholas Dudar
@ 2026-08-21 2:46 ` Nicholas Dudar
1 sibling, 0 replies; 3+ messages in thread
From: Nicholas Dudar @ 2026-08-21 2:46 UTC (permalink / raw)
To: ast, daniel, andrii, eddyz87, memxor, johan.almbladh, paulburton,
tsbogend
Cc: martin.lau, song, yonghong.song, jolsa, emil, ihor.solodrai, bpf,
linux-mips, linux-kernel
BPF_LDX with BPF_MEMSX loads a signed byte, half-word, or word and
sign-extends it through the full 64-bit destination. Both MIPS JITs
predate this mode and reject all three verifier-valid encodings when
JIT execution is required.
Teach the narrow-load helpers to select signed native loads. MIPS64
gets the full result from lb, lh, or lw. MIPS32 loads the low half,
observes the MIPS I load-delay rule, and propagates bit 31 into the
high half. Keep BPF_MEMSX with BPF_DW unsupported, and leave ordinary
loads on their existing unsigned helper path.
The existing BPF_LDX_MEMSX byte, half-word, and word test_bpf cases
cover the verifier-valid widths.
Assisted-by: Codex:gpt-5.6-sol
Signed-off-by: Nicholas Dudar <main.kalliope@gmail.com>
---
arch/mips/net/bpf_jit_comp32.c | 31 +++++++++++++++++++++++++++----
arch/mips/net/bpf_jit_comp64.c | 33 ++++++++++++++++++++++++++++-----
2 files changed, 55 insertions(+), 9 deletions(-)
diff --git a/arch/mips/net/bpf_jit_comp32.c b/arch/mips/net/bpf_jit_comp32.c
index 48a3c834453f2..3de7aac72fb83 100644
--- a/arch/mips/net/bpf_jit_comp32.c
+++ b/arch/mips/net/bpf_jit_comp32.c
@@ -709,16 +709,23 @@ static void emit_trunc_r64(struct jit_context *ctx, const u8 dst[], u32 width)
/* Narrow load operation: dst = *(size *)(src + off) */
static void emit_ldx_narrow(struct jit_context *ctx,
- u8 dst, u8 src, s16 off, u8 size)
+ u8 dst, u8 src, s16 off, u8 size,
+ bool sign_extend)
{
switch (size) {
/* Load a byte */
case BPF_B:
- emit(ctx, lbu, dst, off, src);
+ if (sign_extend)
+ emit(ctx, lb, dst, off, src);
+ else
+ emit(ctx, lbu, dst, off, src);
break;
/* Load a half word */
case BPF_H:
- emit(ctx, lhu, dst, off, src);
+ if (sign_extend)
+ emit(ctx, lh, dst, off, src);
+ else
+ emit(ctx, lhu, dst, off, src);
break;
/* Load a word */
case BPF_W:
@@ -736,7 +743,7 @@ static void emit_ldx(struct jit_context *ctx,
case BPF_B:
case BPF_H:
case BPF_W:
- emit_ldx_narrow(ctx, lo(dst), src, off, size);
+ emit_ldx_narrow(ctx, lo(dst), src, off, size, false);
emit(ctx, move, hi(dst), MIPS_R_ZERO);
break;
/* Load a double word */
@@ -754,6 +761,16 @@ 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)
+{
+ emit_ldx_narrow(ctx, lo(dst), src, off, size, true);
+ 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)
@@ -1725,6 +1742,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 22fb58f970223..14ef3f475c1c1 100644
--- a/arch/mips/net/bpf_jit_comp64.c
+++ b/arch/mips/net/bpf_jit_comp64.c
@@ -400,20 +400,30 @@ static void emit_trunc_r64(struct jit_context *ctx, u8 dst, u32 width)
/* Narrow load operation: dst = *(size *)(src + off) */
static void emit_ldx_narrow(struct jit_context *ctx,
- u8 dst, u8 src, s16 off, u8 size)
+ u8 dst, u8 src, s16 off, u8 size,
+ bool sign_extend)
{
switch (size) {
/* Load a byte */
case BPF_B:
- emit(ctx, lbu, dst, off, src);
+ if (sign_extend)
+ emit(ctx, lb, dst, off, src);
+ else
+ emit(ctx, lbu, dst, off, src);
break;
/* Load a half word */
case BPF_H:
- emit(ctx, lhu, dst, off, src);
+ if (sign_extend)
+ emit(ctx, lh, dst, off, src);
+ else
+ emit(ctx, lhu, dst, off, src);
break;
/* Load a word */
case BPF_W:
- emit(ctx, lwu, dst, off, src);
+ if (sign_extend)
+ emit(ctx, lw, dst, off, src);
+ else
+ emit(ctx, lwu, dst, off, src);
break;
}
}
@@ -426,7 +436,7 @@ static void emit_ldx(struct jit_context *ctx, u8 dst, u8 src, s16 off, u8 size)
case BPF_B:
case BPF_H:
case BPF_W:
- emit_ldx_narrow(ctx, dst, src, off, size);
+ emit_ldx_narrow(ctx, dst, src, off, size, false);
break;
/* Load a double word */
case BPF_DW:
@@ -436,6 +446,13 @@ 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)
+{
+ emit_ldx_narrow(ctx, dst, src, off, size, true);
+ 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)
{
@@ -908,6 +925,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:
^ permalink raw reply related [flat|nested] 3+ messages in thread
end of thread, other threads:[~2026-08-21 2:50 UTC | newest]
Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-08-21 2:46 [RFC bpf-next 0/2] bpf, mips: Add BPF_MEMSX support to the JITs Nicholas Dudar
2026-08-21 2:46 ` [RFC bpf-next 1/2] bpf, mips: Factor narrow loads out of emit_ldx() Nicholas Dudar
2026-08-21 2:46 ` [RFC bpf-next 2/2] bpf, mips: Add BPF_MEMSX support to the JITs Nicholas Dudar
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.