Re: [PATCH RFC 2/2] LoongArch: BPF: Eliminate zero/sign extensions for 32-bit operations
Hengqi Chen <[email protected]> Sun, 26 Jul 2026 17:23:42 +0800
| Newsgroups | dev.linux.lists.loongarch,org.kernel.vger.bpf,org.kernel.vger.linux-kernel |
|---|---|
| Message-ID | <CAEyhmHRahSQeasoz2J1QTFcaNCtGPHdH7OT7VC3uKvTy61byfA@mail.gmail.com> |
On Sat, Jul 11, 2026 at 6:17=E2=80=AFPM Tiezhu Yang <[email protected]= > wrote: > > Eliminate frequent and redundant zero-extensions and sign-extensions > for 32-bit operations. This prevents potential functional bugs caused > by incorrect extension selections and reduces runtime overhead. > > For explicit 32-bit zero-extensions (imm =3D=3D 1), generate a `lu32id` > instruction to guarantee the zero-extended form when they cannot be > bypassed by the look-ahead logic. > > For other 32-bit arithmetic, emit LoongArch native 32-bit instructions > which inherently perform hardware-level sign-extension. > > For bitwise logical instructions, append `addiw dst, dst, 0` to enforce > the standard sign-extended form of the result. > > For 32-bit signed conditional jumps, remove redundant register copies > and pre-jump `emit_sext_32` helpers to leverage native branching, as > operands are now natively sign-extended. > > For 32-bit unsigned conditional jumps, use `bstrpickd` to clear the > upper 32 bits of the operands. > > For JSET bit-testing, maintain `addiw t1, t1, 0` in the jmp32 path to > ensure correctness. > > With this patch, deliver an optimal native execution stream and reduce > the overall JIT image size. > > Signed-off-by: Tiezhu Yang <[email protected]> > --- > arch/loongarch/net/bpf_jit.c | 357 +++++++++++++++++++---------------- > arch/loongarch/net/bpf_jit.h | 25 +-- > 2 files changed, 198 insertions(+), 184 deletions(-) > > diff --git a/arch/loongarch/net/bpf_jit.c b/arch/loongarch/net/bpf_jit.c > index b8cef3ea5c6d..08a5903dd5a3 100644 > --- a/arch/loongarch/net/bpf_jit.c > +++ b/arch/loongarch/net/bpf_jit.c > @@ -209,7 +209,7 @@ static void build_prologue(struct jit_ctx *ctx) > ctx->stack_size =3D stack_adjust; > > if (ctx->arena_vm_start) > - move_imm(ctx, REG_ARENA, ctx->arena_vm_start, false); > + move_imm(ctx, REG_ARENA, ctx->arena_vm_start); > } > > static void __build_epilogue(struct jit_ctx *ctx, bool is_tail_call) > @@ -311,7 +311,6 @@ static int emit_bpf_tail_call(struct jit_ctx *ctx, in= t insn) > * goto out; > */ > tc_ninsn =3D insn ? ctx->offset[insn+1] - ctx->offset[insn] : ctx= ->offset[0]; > - emit_zext_32(ctx, a2, true); > > off =3D offsetof(struct bpf_array, map.max_entries); > emit_insn(ctx, ldwu, t1, a1, off); > @@ -361,7 +360,7 @@ static int emit_bpf_tail_call(struct jit_ctx *ctx, in= t insn) > > static void emit_store_stack_imm64(struct jit_ctx *ctx, int reg, int sta= ck_off, u64 imm64) > { > - move_imm(ctx, reg, imm64, false); > + move_imm(ctx, reg, imm64); > emit_insn(ctx, std, reg, LOONGARCH_GPR_FP, stack_off); > } > > @@ -377,7 +376,7 @@ static int emit_atomic_rmw(const struct bpf_insn *ins= n, struct jit_ctx *ctx) > const s32 imm =3D insn->imm; > const bool isdw =3D BPF_SIZE(insn->code) =3D=3D BPF_DW; > > - move_imm(ctx, t1, off, false); > + move_imm(ctx, t1, off); > emit_insn(ctx, addd, t1, dst, t1); > move_reg(ctx, t3, src); > > @@ -434,7 +433,6 @@ static int emit_atomic_rmw(const struct bpf_insn *ins= n, struct jit_ctx *ctx) > return -EINVAL; > } > emit_insn(ctx, amaddb, src, t1, t3); > - emit_zext_32(ctx, src, true); > break; > case BPF_H: > if (!cpu_has_lam_bh) { > @@ -442,11 +440,9 @@ static int emit_atomic_rmw(const struct bpf_insn *in= sn, struct jit_ctx *ctx) > return -EINVAL; > } > emit_insn(ctx, amaddh, src, t1, t3); > - emit_zext_32(ctx, src, true); > break; > case BPF_W: > emit_insn(ctx, amaddw, src, t1, t3); > - emit_zext_32(ctx, src, true); > break; > case BPF_DW: > emit_insn(ctx, amaddd, src, t1, t3); > @@ -454,28 +450,22 @@ static int emit_atomic_rmw(const struct bpf_insn *i= nsn, struct jit_ctx *ctx) > } > break; > case BPF_AND | BPF_FETCH: > - if (isdw) { > + if (isdw) > emit_insn(ctx, amandd, src, t1, t3); > - } else { > + else > emit_insn(ctx, amandw, src, t1, t3); > - emit_zext_32(ctx, src, true); > - } > break; > case BPF_OR | BPF_FETCH: > - if (isdw) { > + if (isdw) > emit_insn(ctx, amord, src, t1, t3); > - } else { > + else > emit_insn(ctx, amorw, src, t1, t3); > - emit_zext_32(ctx, src, true); > - } > break; > case BPF_XOR | BPF_FETCH: > - if (isdw) { > + if (isdw) > emit_insn(ctx, amxord, src, t1, t3); > - } else { > + else > emit_insn(ctx, amxorw, src, t1, t3); > - emit_zext_32(ctx, src, true); > - } > break; > /* src =3D atomic_xchg(dst + off, src); */ > case BPF_XCHG: > @@ -486,7 +476,6 @@ static int emit_atomic_rmw(const struct bpf_insn *ins= n, struct jit_ctx *ctx) > return -EINVAL; > } > emit_insn(ctx, amswapb, src, t1, t3); > - emit_zext_32(ctx, src, true); > break; > case BPF_H: > if (!cpu_has_lam_bh) { > @@ -494,11 +483,9 @@ static int emit_atomic_rmw(const struct bpf_insn *in= sn, struct jit_ctx *ctx) > return -EINVAL; > } > emit_insn(ctx, amswaph, src, t1, t3); > - emit_zext_32(ctx, src, true); > break; > case BPF_W: > emit_insn(ctx, amswapw, src, t1, t3); > - emit_zext_32(ctx, src, true); > break; > case BPF_DW: > emit_insn(ctx, amswapd, src, t1, t3); > @@ -516,13 +503,10 @@ static int emit_atomic_rmw(const struct bpf_insn *i= nsn, struct jit_ctx *ctx) > emit_insn(ctx, beq, t3, LOONGARCH_GPR_ZERO, -4); > } else { > emit_insn(ctx, llw, r0, t1, 0); > - emit_zext_32(ctx, t2, true); > - emit_zext_32(ctx, r0, true); > emit_insn(ctx, bne, t2, r0, 4); > move_reg(ctx, t3, src); > emit_insn(ctx, scw, t3, t1, 0); > emit_insn(ctx, beq, t3, LOONGARCH_GPR_ZERO, -6); > - emit_zext_32(ctx, r0, true); > } > break; > default: > @@ -549,7 +533,7 @@ static int emit_atomic_ld_st(const struct bpf_insn *i= nsn, struct jit_ctx *ctx) > if (is_signed_imm12(off)) { > emit_insn(ctx, ldbu, dst, src, off); > } else { > - move_imm(ctx, t1, off, false); > + move_imm(ctx, t1, off); > emit_insn(ctx, ldxbu, dst, src, t1); > } > break; > @@ -557,7 +541,7 @@ static int emit_atomic_ld_st(const struct bpf_insn *i= nsn, struct jit_ctx *ctx) > if (is_signed_imm12(off)) { > emit_insn(ctx, ldhu, dst, src, off); > } else { > - move_imm(ctx, t1, off, false); > + move_imm(ctx, t1, off); > emit_insn(ctx, ldxhu, dst, src, t1); > } > break; > @@ -565,7 +549,7 @@ static int emit_atomic_ld_st(const struct bpf_insn *i= nsn, struct jit_ctx *ctx) > if (is_signed_imm12(off)) { > emit_insn(ctx, ldwu, dst, src, off); > } else { > - move_imm(ctx, t1, off, false); > + move_imm(ctx, t1, off); > emit_insn(ctx, ldxwu, dst, src, t1); > } > break; > @@ -573,7 +557,7 @@ static int emit_atomic_ld_st(const struct bpf_insn *i= nsn, struct jit_ctx *ctx) > if (is_signed_imm12(off)) { > emit_insn(ctx, ldd, dst, src, off); > } else { > - move_imm(ctx, t1, off, false); > + move_imm(ctx, t1, off); > emit_insn(ctx, ldxd, dst, src, t1); > } > break; > @@ -596,7 +580,7 @@ static int emit_atomic_ld_st(const struct bpf_insn *i= nsn, struct jit_ctx *ctx) > if (is_signed_imm12(off)) { > emit_insn(ctx, stb, src, dst, off); > } else { > - move_imm(ctx, t1, off, false); > + move_imm(ctx, t1, off); > emit_insn(ctx, stxb, src, dst, t1); > } > break; > @@ -604,7 +588,7 @@ static int emit_atomic_ld_st(const struct bpf_insn *i= nsn, struct jit_ctx *ctx) > if (is_signed_imm12(off)) { > emit_insn(ctx, sth, src, dst, off); > } else { > - move_imm(ctx, t1, off, false); > + move_imm(ctx, t1, off); > emit_insn(ctx, stxh, src, dst, t1); > } > break; > @@ -612,7 +596,7 @@ static int emit_atomic_ld_st(const struct bpf_insn *i= nsn, struct jit_ctx *ctx) > if (is_signed_imm12(off)) { > emit_insn(ctx, stw, src, dst, off); > } else { > - move_imm(ctx, t1, off, false); > + move_imm(ctx, t1, off); > emit_insn(ctx, stxw, src, dst, t1); > } > break; > @@ -620,7 +604,7 @@ static int emit_atomic_ld_st(const struct bpf_insn *i= nsn, struct jit_ctx *ctx) > if (is_signed_imm12(off)) { > emit_insn(ctx, std, src, dst, off); > } else { > - move_imm(ctx, t1, off, false); > + move_imm(ctx, t1, off); > emit_insn(ctx, stxd, src, dst, t1); > } > break; > @@ -741,28 +725,32 @@ static int build_insn(const struct bpf_insn *insn, = struct jit_ctx *ctx, bool ext > switch (code) { > /* dst =3D src */ > case BPF_ALU | BPF_MOV | BPF_X: > + if (imm =3D=3D 1) { > + emit_insn(ctx, lu32id, reg, 0); reg ? > + break; > + } > + > + emit_insn(ctx, addw, dst, src, LOONGARCH_GPR_ZERO); > + break; > case BPF_ALU64 | BPF_MOV | BPF_X: > if (insn_is_cast_user(insn)) { > move_reg(ctx, t1, src); > - emit_zext_32(ctx, t1, true); > - move_imm(ctx, dst, (ctx->user_vm_start >> 32) << = 32, false); > + move_imm(ctx, dst, (ctx->user_vm_start >> 32) << = 32); > emit_insn(ctx, beq, t1, LOONGARCH_GPR_ZERO, 1); > emit_insn(ctx, or, t1, dst, t1); > move_reg(ctx, dst, t1); > break; > } > + > switch (off) { > case 0: > move_reg(ctx, dst, src); > - emit_zext_32(ctx, dst, is32); > break; > case 8: > emit_insn(ctx, extwb, dst, src); > - emit_zext_32(ctx, dst, is32); > break; > case 16: > emit_insn(ctx, extwh, dst, src); > - emit_zext_32(ctx, dst, is32); > break; > case 32: > emit_insn(ctx, addw, dst, src, LOONGARCH_GPR_ZERO= ); > @@ -773,202 +761,234 @@ static int build_insn(const struct bpf_insn *insn= , struct jit_ctx *ctx, bool ext > /* dst =3D imm */ > case BPF_ALU | BPF_MOV | BPF_K: > case BPF_ALU64 | BPF_MOV | BPF_K: > - move_imm(ctx, dst, imm, is32); > + move_imm(ctx, dst, imm); > break; > > /* dst =3D dst + src */ > case BPF_ALU | BPF_ADD | BPF_X: > + emit_insn(ctx, addw, dst, dst, src); > + break; > case BPF_ALU64 | BPF_ADD | BPF_X: > emit_insn(ctx, addd, dst, dst, src); > - emit_zext_32(ctx, dst, is32); > break; > > /* dst =3D dst + imm */ > case BPF_ALU | BPF_ADD | BPF_K: > + if (is_signed_imm12(imm)) { > + emit_insn(ctx, addiw, dst, dst, imm); > + } else { > + move_imm(ctx, t1, imm); > + emit_insn(ctx, addw, dst, dst, t1); > + } > + break; > case BPF_ALU64 | BPF_ADD | BPF_K: > if (is_signed_imm12(imm)) { > emit_insn(ctx, addid, dst, dst, imm); > } else { > - move_imm(ctx, t1, imm, is32); > + move_imm(ctx, t1, imm); > emit_insn(ctx, addd, dst, dst, t1); > } > - emit_zext_32(ctx, dst, is32); > break; > > /* dst =3D dst - src */ > case BPF_ALU | BPF_SUB | BPF_X: > + emit_insn(ctx, subw, dst, dst, src); > + break; > case BPF_ALU64 | BPF_SUB | BPF_X: > emit_insn(ctx, subd, dst, dst, src); > - emit_zext_32(ctx, dst, is32); > break; > > /* dst =3D dst - imm */ > case BPF_ALU | BPF_SUB | BPF_K: > + if (is_signed_imm12(-imm)) { > + emit_insn(ctx, addiw, dst, dst, -imm); > + } else { > + move_imm(ctx, t1, imm); > + emit_insn(ctx, subw, dst, dst, t1); > + } > + break; > case BPF_ALU64 | BPF_SUB | BPF_K: > if (is_signed_imm12(-imm)) { > emit_insn(ctx, addid, dst, dst, -imm); > } else { > - move_imm(ctx, t1, imm, is32); > + move_imm(ctx, t1, imm); > emit_insn(ctx, subd, dst, dst, t1); > } > - emit_zext_32(ctx, dst, is32); > break; > > /* dst =3D dst * src */ > case BPF_ALU | BPF_MUL | BPF_X: > + emit_insn(ctx, mulw, dst, dst, src); > + break; > case BPF_ALU64 | BPF_MUL | BPF_X: > emit_insn(ctx, muld, dst, dst, src); > - emit_zext_32(ctx, dst, is32); > break; > > /* dst =3D dst * imm */ > case BPF_ALU | BPF_MUL | BPF_K: > + move_imm(ctx, t1, imm); > + emit_insn(ctx, mulw, dst, dst, t1); > + break; > case BPF_ALU64 | BPF_MUL | BPF_K: > - move_imm(ctx, t1, imm, is32); > + move_imm(ctx, t1, imm); > emit_insn(ctx, muld, dst, dst, t1); > - emit_zext_32(ctx, dst, is32); > break; > > /* dst =3D dst / src */ > case BPF_ALU | BPF_DIV | BPF_X: > + if (!off) > + emit_insn(ctx, divwu, dst, dst, src); > + else > + emit_insn(ctx, divw, dst, dst, src); > + break; > case BPF_ALU64 | BPF_DIV | BPF_X: > - if (!off) { > - emit_zext_32(ctx, dst, is32); > - move_reg(ctx, t1, src); > - emit_zext_32(ctx, t1, is32); > - emit_insn(ctx, divdu, dst, dst, t1); > - emit_zext_32(ctx, dst, is32); > - } else { > - emit_sext_32(ctx, dst, is32); > - move_reg(ctx, t1, src); > - emit_sext_32(ctx, t1, is32); > - emit_insn(ctx, divd, dst, dst, t1); > - emit_sext_32(ctx, dst, is32); > - } > + if (!off) > + emit_insn(ctx, divdu, dst, dst, src); > + else > + emit_insn(ctx, divd, dst, dst, src); > break; > > /* dst =3D dst / imm */ > case BPF_ALU | BPF_DIV | BPF_K: > + move_imm(ctx, t1, imm); > + if (!off) > + emit_insn(ctx, divwu, dst, dst, t1); > + else > + emit_insn(ctx, divw, dst, dst, t1); > + break; > case BPF_ALU64 | BPF_DIV | BPF_K: > - if (!off) { > - move_imm(ctx, t1, imm, is32); > - emit_zext_32(ctx, dst, is32); > + move_imm(ctx, t1, imm); > + if (!off) > emit_insn(ctx, divdu, dst, dst, t1); > - emit_zext_32(ctx, dst, is32); > - } else { > - move_imm(ctx, t1, imm, false); > - emit_sext_32(ctx, t1, is32); > - emit_sext_32(ctx, dst, is32); > + else > emit_insn(ctx, divd, dst, dst, t1); > - emit_sext_32(ctx, dst, is32); > - } > break; > > /* dst =3D dst % src */ > case BPF_ALU | BPF_MOD | BPF_X: > + if (!off) > + emit_insn(ctx, modwu, dst, dst, src); > + else > + emit_insn(ctx, modw, dst, dst, src); > + break; > case BPF_ALU64 | BPF_MOD | BPF_X: > - if (!off) { > - emit_zext_32(ctx, dst, is32); > - move_reg(ctx, t1, src); > - emit_zext_32(ctx, t1, is32); > - emit_insn(ctx, moddu, dst, dst, t1); > - emit_zext_32(ctx, dst, is32); > - } else { > - emit_sext_32(ctx, dst, is32); > - move_reg(ctx, t1, src); > - emit_sext_32(ctx, t1, is32); > - emit_insn(ctx, modd, dst, dst, t1); > - emit_sext_32(ctx, dst, is32); > - } > + if (!off) > + emit_insn(ctx, moddu, dst, dst, src); > + else > + emit_insn(ctx, modd, dst, dst, src); > break; > > /* dst =3D dst % imm */ > case BPF_ALU | BPF_MOD | BPF_K: > + move_imm(ctx, t1, imm); > + if (!off) > + emit_insn(ctx, modwu, dst, dst, t1); > + else > + emit_insn(ctx, modw, dst, dst, t1); > + break; > case BPF_ALU64 | BPF_MOD | BPF_K: > - if (!off) { > - move_imm(ctx, t1, imm, is32); > - emit_zext_32(ctx, dst, is32); > + move_imm(ctx, t1, imm); > + if (!off) > emit_insn(ctx, moddu, dst, dst, t1); > - emit_zext_32(ctx, dst, is32); > - } else { > - move_imm(ctx, t1, imm, false); > - emit_sext_32(ctx, t1, is32); > - emit_sext_32(ctx, dst, is32); > + else > emit_insn(ctx, modd, dst, dst, t1); > - emit_sext_32(ctx, dst, is32); > - } > break; > > /* dst =3D -dst */ > case BPF_ALU | BPF_NEG: > + emit_insn(ctx, subw, dst, LOONGARCH_GPR_ZERO, dst); > + break; > case BPF_ALU64 | BPF_NEG: > emit_insn(ctx, subd, dst, LOONGARCH_GPR_ZERO, dst); > - emit_zext_32(ctx, dst, is32); > break; > > /* dst =3D dst & src */ > case BPF_ALU | BPF_AND | BPF_X: > + emit_insn(ctx, and, dst, dst, src); > + emit_insn(ctx, addiw, dst, dst, 0); > + break; > case BPF_ALU64 | BPF_AND | BPF_X: > emit_insn(ctx, and, dst, dst, src); > - emit_zext_32(ctx, dst, is32); > break; > > /* dst =3D dst & imm */ > case BPF_ALU | BPF_AND | BPF_K: > + if (is_unsigned_imm12(imm)) { > + emit_insn(ctx, andi, dst, dst, imm); > + } else { > + move_imm(ctx, t1, imm); > + emit_insn(ctx, and, dst, dst, t1); > + } > + emit_insn(ctx, addiw, dst, dst, 0); break; ? > case BPF_ALU64 | BPF_AND | BPF_K: > if (is_unsigned_imm12(imm)) { > emit_insn(ctx, andi, dst, dst, imm); > } else { > - move_imm(ctx, t1, imm, is32); > + move_imm(ctx, t1, imm); > emit_insn(ctx, and, dst, dst, t1); > } > - emit_zext_32(ctx, dst, is32); > break; > > /* dst =3D dst | src */ > case BPF_ALU | BPF_OR | BPF_X: > + emit_insn(ctx, or, dst, dst, src); > + emit_insn(ctx, addiw, dst, dst, 0); > + break; > case BPF_ALU64 | BPF_OR | BPF_X: > emit_insn(ctx, or, dst, dst, src); > - emit_zext_32(ctx, dst, is32); > break; > > /* dst =3D dst | imm */ > case BPF_ALU | BPF_OR | BPF_K: > + if (is_unsigned_imm12(imm)) { > + emit_insn(ctx, ori, dst, dst, imm); > + } else { > + move_imm(ctx, t1, imm); > + emit_insn(ctx, or, dst, dst, t1); > + } > + emit_insn(ctx, addiw, dst, dst, 0); > + break; > case BPF_ALU64 | BPF_OR | BPF_K: > if (is_unsigned_imm12(imm)) { > emit_insn(ctx, ori, dst, dst, imm); > } else { > - move_imm(ctx, t1, imm, is32); > + move_imm(ctx, t1, imm); > emit_insn(ctx, or, dst, dst, t1); > } > - emit_zext_32(ctx, dst, is32); > break; > > /* dst =3D dst ^ src */ > case BPF_ALU | BPF_XOR | BPF_X: > + emit_insn(ctx, xor, dst, dst, src); > + emit_insn(ctx, addiw, dst, dst, 0); > + break; > case BPF_ALU64 | BPF_XOR | BPF_X: > emit_insn(ctx, xor, dst, dst, src); > - emit_zext_32(ctx, dst, is32); > break; > > /* dst =3D dst ^ imm */ > case BPF_ALU | BPF_XOR | BPF_K: > + if (is_unsigned_imm12(imm)) { > + emit_insn(ctx, xori, dst, dst, imm); > + } else { > + move_imm(ctx, t1, imm); > + emit_insn(ctx, xor, dst, dst, t1); > + } > + emit_insn(ctx, addiw, dst, dst, 0); > + break; > case BPF_ALU64 | BPF_XOR | BPF_K: > if (is_unsigned_imm12(imm)) { > emit_insn(ctx, xori, dst, dst, imm); > } else { > - move_imm(ctx, t1, imm, is32); > + move_imm(ctx, t1, imm); > emit_insn(ctx, xor, dst, dst, t1); > } > - emit_zext_32(ctx, dst, is32); > break; > > /* dst =3D dst << src (logical) */ > case BPF_ALU | BPF_LSH | BPF_X: > emit_insn(ctx, sllw, dst, dst, src); > - emit_zext_32(ctx, dst, is32); > break; > - > case BPF_ALU64 | BPF_LSH | BPF_X: > emit_insn(ctx, slld, dst, dst, src); > break; > @@ -976,9 +996,7 @@ static int build_insn(const struct bpf_insn *insn, st= ruct jit_ctx *ctx, bool ext > /* dst =3D dst << imm (logical) */ > case BPF_ALU | BPF_LSH | BPF_K: > emit_insn(ctx, slliw, dst, dst, imm); > - emit_zext_32(ctx, dst, is32); > break; > - > case BPF_ALU64 | BPF_LSH | BPF_K: > emit_insn(ctx, sllid, dst, dst, imm); > break; > @@ -986,9 +1004,7 @@ static int build_insn(const struct bpf_insn *insn, s= truct jit_ctx *ctx, bool ext > /* dst =3D dst >> src (logical) */ > case BPF_ALU | BPF_RSH | BPF_X: > emit_insn(ctx, srlw, dst, dst, src); > - emit_zext_32(ctx, dst, is32); > break; > - > case BPF_ALU64 | BPF_RSH | BPF_X: > emit_insn(ctx, srld, dst, dst, src); > break; > @@ -996,9 +1012,7 @@ static int build_insn(const struct bpf_insn *insn, s= truct jit_ctx *ctx, bool ext > /* dst =3D dst >> imm (logical) */ > case BPF_ALU | BPF_RSH | BPF_K: > emit_insn(ctx, srliw, dst, dst, imm); > - emit_zext_32(ctx, dst, is32); > break; > - > case BPF_ALU64 | BPF_RSH | BPF_K: > emit_insn(ctx, srlid, dst, dst, imm); > break; > @@ -1006,9 +1020,7 @@ static int build_insn(const struct bpf_insn *insn, = struct jit_ctx *ctx, bool ext > /* dst =3D dst >> src (arithmetic) */ > case BPF_ALU | BPF_ARSH | BPF_X: > emit_insn(ctx, sraw, dst, dst, src); > - emit_zext_32(ctx, dst, is32); > break; > - > case BPF_ALU64 | BPF_ARSH | BPF_X: > emit_insn(ctx, srad, dst, dst, src); > break; > @@ -1016,9 +1028,7 @@ static int build_insn(const struct bpf_insn *insn, = struct jit_ctx *ctx, bool ext > /* dst =3D dst >> imm (arithmetic) */ > case BPF_ALU | BPF_ARSH | BPF_K: > emit_insn(ctx, sraiw, dst, dst, imm); > - emit_zext_32(ctx, dst, is32); > break; > - > case BPF_ALU64 | BPF_ARSH | BPF_K: > emit_insn(ctx, sraid, dst, dst, imm); > break; > @@ -1031,8 +1041,7 @@ static int build_insn(const struct bpf_insn *insn, = struct jit_ctx *ctx, bool ext > emit_insn(ctx, bstrpickd, dst, dst, 15, 0); > break; > case 32: > - /* zero-extend 32 bits into 64 bits */ > - emit_zext_32(ctx, dst, is32); > + emit_insn(ctx, addiw, dst, dst, 0); > break; > case 64: > /* do nothing */ > @@ -1050,8 +1059,6 @@ static int build_insn(const struct bpf_insn *insn, = struct jit_ctx *ctx, bool ext > break; > case 32: > emit_insn(ctx, revb2w, dst, dst); > - /* clear the upper 32 bits */ > - emit_zext_32(ctx, dst, true); > break; > case 64: > emit_insn(ctx, revbd, dst, dst); > @@ -1070,6 +1077,11 @@ static int build_insn(const struct bpf_insn *insn,= struct jit_ctx *ctx, bool ext > case BPF_JMP | BPF_JSGE | BPF_X: > case BPF_JMP | BPF_JSLT | BPF_X: > case BPF_JMP | BPF_JSLE | BPF_X: > + jmp_offset =3D bpf2la_offset(i, off, ctx); > + if (emit_cond_jmp(ctx, cond, dst, src, jmp_offset) < 0) > + goto toofar; > + break; > + > case BPF_JMP32 | BPF_JEQ | BPF_X: > case BPF_JMP32 | BPF_JNE | BPF_X: > case BPF_JMP32 | BPF_JGT | BPF_X: > @@ -1081,17 +1093,15 @@ static int build_insn(const struct bpf_insn *insn= , struct jit_ctx *ctx, bool ext > case BPF_JMP32 | BPF_JSLT | BPF_X: > case BPF_JMP32 | BPF_JSLE | BPF_X: > jmp_offset =3D bpf2la_offset(i, off, ctx); > - move_reg(ctx, t1, dst); > - move_reg(ctx, t2, src); > if (is_signed_bpf_cond(BPF_OP(code))) { > - emit_sext_32(ctx, t1, is32); > - emit_sext_32(ctx, t2, is32); > + if (emit_cond_jmp(ctx, cond, dst, src, jmp_offset= ) < 0) > + goto toofar; > } else { > - emit_zext_32(ctx, t1, is32); > - emit_zext_32(ctx, t2, is32); > + emit_insn(ctx, bstrpickd, t1, dst, 31, 0); > + emit_insn(ctx, bstrpickd, t2, src, 31, 0); > + if (emit_cond_jmp(ctx, cond, t1, t2, jmp_offset) = < 0) > + goto toofar; > } > - if (emit_cond_jmp(ctx, cond, t1, t2, jmp_offset) < 0) > - goto toofar; > break; > > /* PC +=3D off if dst cond imm */ > @@ -1105,6 +1115,17 @@ static int build_insn(const struct bpf_insn *insn,= struct jit_ctx *ctx, bool ext > case BPF_JMP | BPF_JSGE | BPF_K: > case BPF_JMP | BPF_JSLT | BPF_K: > case BPF_JMP | BPF_JSLE | BPF_K: > + jmp_offset =3D bpf2la_offset(i, off, ctx); > + if (imm) { > + move_imm(ctx, t1, imm); > + tm =3D t1; > + } else { > + tm =3D LOONGARCH_GPR_ZERO; > + } > + > + if (emit_cond_jmp(ctx, cond, dst, tm, jmp_offset) < 0) > + goto toofar; > + break; > case BPF_JMP32 | BPF_JEQ | BPF_K: > case BPF_JMP32 | BPF_JNE | BPF_K: > case BPF_JMP32 | BPF_JGT | BPF_K: > @@ -1117,41 +1138,55 @@ static int build_insn(const struct bpf_insn *insn= , struct jit_ctx *ctx, bool ext > case BPF_JMP32 | BPF_JSLE | BPF_K: > jmp_offset =3D bpf2la_offset(i, off, ctx); > if (imm) { > - move_imm(ctx, t1, imm, false); > + move_imm(ctx, t1, imm); > tm =3D t1; > } else { > - /* If imm is 0, simply use zero register. */ > tm =3D LOONGARCH_GPR_ZERO; > } > - move_reg(ctx, t2, dst); > + > if (is_signed_bpf_cond(BPF_OP(code))) { > - emit_sext_32(ctx, tm, is32); > - emit_sext_32(ctx, t2, is32); > + if (emit_cond_jmp(ctx, cond, dst, tm, jmp_offset)= < 0) > + goto toofar; > } else { > - emit_zext_32(ctx, tm, is32); > - emit_zext_32(ctx, t2, is32); > + emit_insn(ctx, bstrpickd, t2, dst, 31, 0); > + if (imm) > + emit_insn(ctx, bstrpickd, t1, tm, 31, 0); > + else > + t1 =3D LOONGARCH_GPR_ZERO; > + > + if (emit_cond_jmp(ctx, cond, t2, t1, jmp_offset) = < 0) > + goto toofar; > } > - if (emit_cond_jmp(ctx, cond, t2, tm, jmp_offset) < 0) > - goto toofar; > break; > > /* PC +=3D off if dst & src */ > case BPF_JMP | BPF_JSET | BPF_X: > + jmp_offset =3D bpf2la_offset(i, off, ctx); > + emit_insn(ctx, and, t1, dst, src); > + if (emit_cond_jmp(ctx, cond, t1, LOONGARCH_GPR_ZERO, jmp_= offset) < 0) > + goto toofar; > + break; > case BPF_JMP32 | BPF_JSET | BPF_X: > jmp_offset =3D bpf2la_offset(i, off, ctx); > emit_insn(ctx, and, t1, dst, src); > - emit_zext_32(ctx, t1, is32); > + emit_insn(ctx, addiw, t1, t1, 0); > if (emit_cond_jmp(ctx, cond, t1, LOONGARCH_GPR_ZERO, jmp_= offset) < 0) > goto toofar; > break; > > /* PC +=3D off if dst & imm */ > case BPF_JMP | BPF_JSET | BPF_K: > + jmp_offset =3D bpf2la_offset(i, off, ctx); > + move_imm(ctx, t1, imm); > + emit_insn(ctx, and, t1, dst, t1); > + if (emit_cond_jmp(ctx, cond, t1, LOONGARCH_GPR_ZERO, jmp_= offset) < 0) > + goto toofar; > + break; > case BPF_JMP32 | BPF_JSET | BPF_K: > jmp_offset =3D bpf2la_offset(i, off, ctx); > - move_imm(ctx, t1, imm, is32); > + move_imm(ctx, t1, imm); > emit_insn(ctx, and, t1, dst, t1); > - emit_zext_32(ctx, t1, is32); > + emit_insn(ctx, addiw, t1, t1, 0); > if (emit_cond_jmp(ctx, cond, t1, LOONGARCH_GPR_ZERO, jmp_= offset) < 0) > goto toofar; > break; > @@ -1241,7 +1276,7 @@ static int build_insn(const struct bpf_insn *insn, = struct jit_ctx *ctx, bool ext > if (bpf_pseudo_func(insn)) > move_addr(ctx, dst, imm64); > else > - move_imm(ctx, dst, imm64, is32); > + move_imm(ctx, dst, imm64); > return 1; > } > > @@ -1282,7 +1317,7 @@ static int build_insn(const struct bpf_insn *insn, = struct jit_ctx *ctx, bool ext > else > emit_insn(ctx, ldbu, dst, src, of= f); > } else { > - move_imm(ctx, t1, off, is32); > + move_imm(ctx, t1, off); > if (sign_extend) > emit_insn(ctx, ldxb, dst, src, t1= ); > else > @@ -1296,7 +1331,7 @@ static int build_insn(const struct bpf_insn *insn, = struct jit_ctx *ctx, bool ext > else > emit_insn(ctx, ldhu, dst, src, of= f); > } else { > - move_imm(ctx, t1, off, is32); > + move_imm(ctx, t1, off); > if (sign_extend) > emit_insn(ctx, ldxh, dst, src, t1= ); > else > @@ -1310,7 +1345,7 @@ static int build_insn(const struct bpf_insn *insn, = struct jit_ctx *ctx, bool ext > else > emit_insn(ctx, ldwu, dst, src, of= f); > } else { > - move_imm(ctx, t1, off, is32); > + move_imm(ctx, t1, off); > if (sign_extend) > emit_insn(ctx, ldxw, dst, src, t1= ); > else > @@ -1318,7 +1353,7 @@ static int build_insn(const struct bpf_insn *insn, = struct jit_ctx *ctx, bool ext > } > break; > case BPF_DW: > - move_imm(ctx, t1, off, is32); > + move_imm(ctx, t1, off); > emit_insn(ctx, ldxd, dst, src, t1); > break; > } > @@ -1353,42 +1388,42 @@ static int build_insn(const struct bpf_insn *insn= , struct jit_ctx *ctx, bool ext > > switch (BPF_SIZE(code)) { > case BPF_B: > - move_imm(ctx, t1, imm, is32); > + move_imm(ctx, t1, imm); > if (is_signed_imm12(off)) { > emit_insn(ctx, stb, t1, dst, off); > } else { > - move_imm(ctx, t2, off, is32); > + move_imm(ctx, t2, off); > emit_insn(ctx, stxb, t1, dst, t2); > } > break; > case BPF_H: > - move_imm(ctx, t1, imm, is32); > + move_imm(ctx, t1, imm); > if (is_signed_imm12(off)) { > emit_insn(ctx, sth, t1, dst, off); > } else { > - move_imm(ctx, t2, off, is32); > + move_imm(ctx, t2, off); > emit_insn(ctx, stxh, t1, dst, t2); > } > break; > case BPF_W: > - move_imm(ctx, t1, imm, is32); > + move_imm(ctx, t1, imm); > if (is_signed_imm12(off)) { > emit_insn(ctx, stw, t1, dst, off); > } else if (is_signed_imm14(off)) { > emit_insn(ctx, stptrw, t1, dst, off); > } else { > - move_imm(ctx, t2, off, is32); > + move_imm(ctx, t2, off); > emit_insn(ctx, stxw, t1, dst, t2); > } > break; > case BPF_DW: > - move_imm(ctx, t1, imm, is32); > + move_imm(ctx, t1, imm); > if (is_signed_imm12(off)) { > emit_insn(ctx, std, t1, dst, off); > } else if (is_signed_imm14(off)) { > emit_insn(ctx, stptrd, t1, dst, off); > } else { > - move_imm(ctx, t2, off, is32); > + move_imm(ctx, t2, off); > emit_insn(ctx, stxd, t1, dst, t2); > } > break; > @@ -1419,7 +1454,7 @@ static int build_insn(const struct bpf_insn *insn, = struct jit_ctx *ctx, bool ext > if (is_signed_imm12(off)) { > emit_insn(ctx, stb, src, dst, off); > } else { > - move_imm(ctx, t1, off, is32); > + move_imm(ctx, t1, off); > emit_insn(ctx, stxb, src, dst, t1); > } > break; > @@ -1427,7 +1462,7 @@ static int build_insn(const struct bpf_insn *insn, = struct jit_ctx *ctx, bool ext > if (is_signed_imm12(off)) { > emit_insn(ctx, sth, src, dst, off); > } else { > - move_imm(ctx, t1, off, is32); > + move_imm(ctx, t1, off); > emit_insn(ctx, stxh, src, dst, t1); > } > break; > @@ -1437,7 +1472,7 @@ static int build_insn(const struct bpf_insn *insn, = struct jit_ctx *ctx, bool ext > } else if (is_signed_imm14(off)) { > emit_insn(ctx, stptrw, src, dst, off); > } else { > - move_imm(ctx, t1, off, is32); > + move_imm(ctx, t1, off); > emit_insn(ctx, stxw, src, dst, t1); > } > break; > @@ -1447,7 +1482,7 @@ static int build_insn(const struct bpf_insn *insn, = struct jit_ctx *ctx, bool ext > } else if (is_signed_imm14(off)) { > emit_insn(ctx, stptrd, src, dst, off); > } else { > - move_imm(ctx, t1, off, is32); > + move_imm(ctx, t1, off); > emit_insn(ctx, stxd, src, dst, t1); > } > break; > @@ -1559,7 +1594,7 @@ static int emit_jump_and_link(struct jit_ctx *ctx, = u8 rd, u64 target) > return -EFAULT; > } > > - move_imm(ctx, LOONGARCH_GPR_T1, target, false); > + move_imm(ctx, LOONGARCH_GPR_T1, target); > emit_insn(ctx, jirl, rd, LOONGARCH_GPR_T1, 0); > > return 0; > @@ -1733,7 +1768,7 @@ static int invoke_bpf_prog(struct jit_ctx *ctx, str= uct bpf_tramp_node *n, > emit_insn(ctx, std, LOONGARCH_GPR_ZERO, LOONGARCH_GPR_FP,= -run_ctx_off + cookie_off); > > /* arg1: prog */ > - move_imm(ctx, LOONGARCH_GPR_A0, (const s64)p, false); > + move_imm(ctx, LOONGARCH_GPR_A0, (const s64)p); > /* arg2: &run_ctx */ > emit_insn(ctx, addid, LOONGARCH_GPR_A1, LOONGARCH_GPR_FP, -run_ct= x_off); > ret =3D emit_call(ctx, (const u64)bpf_trampoline_enter(p)); > @@ -1754,7 +1789,7 @@ static int invoke_bpf_prog(struct jit_ctx *ctx, str= uct bpf_tramp_node *n, > /* arg1: &args_off */ > emit_insn(ctx, addid, LOONGARCH_GPR_A0, LOONGARCH_GPR_FP, -args_o= ff); > if (!p->jited) > - move_imm(ctx, LOONGARCH_GPR_A1, (const s64)p->insnsi, fal= se); > + move_imm(ctx, LOONGARCH_GPR_A1, (const s64)p->insnsi); > ret =3D emit_call(ctx, (const u64)p->bpf_func); > if (ret) > return ret; > @@ -1771,7 +1806,7 @@ static int invoke_bpf_prog(struct jit_ctx *ctx, str= uct bpf_tramp_node *n, > } > > /* arg1: prog */ > - move_imm(ctx, LOONGARCH_GPR_A0, (const s64)p, false); > + move_imm(ctx, LOONGARCH_GPR_A0, (const s64)p); > /* arg2: prog start time */ > move_reg(ctx, LOONGARCH_GPR_A1, LOONGARCH_GPR_S1); > /* arg3: &run_ctx */ > diff --git a/arch/loongarch/net/bpf_jit.h b/arch/loongarch/net/bpf_jit.h > index bb58c42c2f2a..2bd0dc5b911c 100644 > --- a/arch/loongarch/net/bpf_jit.h > +++ b/arch/loongarch/net/bpf_jit.h > @@ -72,24 +72,6 @@ static inline int epilogue_offset(const struct jit_ctx= *ctx) > return (to - from); > } > > -/* Zero-extend 32 bits into 64 bits */ > -static inline void emit_zext_32(struct jit_ctx *ctx, enum loongarch_gpr = reg, bool is32) > -{ > - if (!is32) > - return; > - > - emit_insn(ctx, lu32id, reg, 0); > -} > - > -/* Signed-extend 32 bits into 64 bits */ > -static inline void emit_sext_32(struct jit_ctx *ctx, enum loongarch_gpr = reg, bool is32) > -{ > - if (!is32) > - return; > - > - emit_insn(ctx, addiw, reg, reg, 0); > -} > - > /* Emit proper extension according to ABI requirements. > * Note that it requires a value of size `size` already resides in regis= ter `reg`. > */ > @@ -137,7 +119,7 @@ static inline void move_addr(struct jit_ctx *ctx, enu= m loongarch_gpr rd, u64 add > emit_insn(ctx, lu52id, rd, rd, imm_63_52); > } > > -static inline void move_imm(struct jit_ctx *ctx, enum loongarch_gpr rd, = long imm, bool is32) > +static inline void move_imm(struct jit_ctx *ctx, enum loongarch_gpr rd, = long imm) > { > long imm_11_0, imm_31_12, imm_51_32, imm_63_52, imm_51_0, imm_51_= 31; > > @@ -150,7 +132,7 @@ static inline void move_imm(struct jit_ctx *ctx, enum= loongarch_gpr rd, long imm > /* addiw rd, $zero, imm_11_0 */ > if (is_signed_imm12(imm)) { > emit_insn(ctx, addiw, rd, LOONGARCH_GPR_ZERO, imm); > - goto zext; > + return; > } > > /* ori rd, $zero, imm_11_0 */ > @@ -195,9 +177,6 @@ static inline void move_imm(struct jit_ctx *ctx, enum= loongarch_gpr rd, long imm > if (!is_signed_imm52(imm)) > emit_insn(ctx, lu52id, rd, rd, imm_63_52); > } > - > -zext: > - emit_zext_32(ctx, rd, is32); > } > > static inline void move_reg(struct jit_ctx *ctx, enum loongarch_gpr rd, > -- > 2.42.0 > >