Skip to content

Commit fc83265

Browse files
puranjaymohanAlexei Starovoitov
authored and
Alexei Starovoitov
committed
arm32, bpf: add support for sign-extension mov instruction
The cpuv4 added a new BPF_MOVSX instruction that sign extends the src before moving it to the destination. BPF_ALU | BPF_MOVSX sign extends 8-bit and 16-bit operands into 32-bit operands, and zeroes the remaining upper 32 bits. BPF_ALU64 | BPF_MOVSX sign extends 8-bit, 16-bit, and 32-bit operands into 64-bit operands. The offset field of the instruction is used to tell the number of bit to use for sign-extension. BPF_MOV and BPF_MOVSX have the same code but the former sets offset to 0 and the later one sets the offset to 8, 16 or 32 The behaviour of this instruction is dst = (s8,s16,s32)src On ARM32 the implementation uses LSH and ARSH to extend the 8/16 bits to a 32-bit register and then it is sign extended to the upper 32-bit register using ARSH. For 32-bit we just move it to the destination register and use ARSH to extend it to the upper 32-bit register. Signed-off-by: Puranjay Mohan <puranjay12@gmail.com> Reviewed-by: Russell King (Oracle) <rmk+kernel@armlinux.org.uk> Link: https://lore.kernel.org/r/20230907230550.1417590-4-puranjay12@gmail.com Signed-off-by: Alexei Starovoitov <ast@kernel.org>
1 parent f9e6981 commit fc83265

File tree

1 file changed

+30
-5
lines changed

1 file changed

+30
-5
lines changed

arch/arm/net/bpf_jit_32.c

+30-5
Original file line numberDiff line numberDiff line change
@@ -747,12 +747,16 @@ static inline void emit_a32_alu_r64(const bool is64, const s8 dst[],
747747
}
748748

749749
/* dst = src (4 bytes)*/
750-
static inline void emit_a32_mov_r(const s8 dst, const s8 src,
750+
static inline void emit_a32_mov_r(const s8 dst, const s8 src, const u8 off,
751751
struct jit_ctx *ctx) {
752752
const s8 *tmp = bpf2a32[TMP_REG_1];
753753
s8 rt;
754754

755755
rt = arm_bpf_get_reg32(src, tmp[0], ctx);
756+
if (off && off != 32) {
757+
emit(ARM_LSL_I(rt, rt, 32 - off), ctx);
758+
emit(ARM_ASR_I(rt, rt, 32 - off), ctx);
759+
}
756760
arm_bpf_put_reg32(dst, rt, ctx);
757761
}
758762

@@ -761,15 +765,15 @@ static inline void emit_a32_mov_r64(const bool is64, const s8 dst[],
761765
const s8 src[],
762766
struct jit_ctx *ctx) {
763767
if (!is64) {
764-
emit_a32_mov_r(dst_lo, src_lo, ctx);
768+
emit_a32_mov_r(dst_lo, src_lo, 0, ctx);
765769
if (!ctx->prog->aux->verifier_zext)
766770
/* Zero out high 4 bytes */
767771
emit_a32_mov_i(dst_hi, 0, ctx);
768772
} else if (__LINUX_ARM_ARCH__ < 6 &&
769773
ctx->cpu_architecture < CPU_ARCH_ARMv5TE) {
770774
/* complete 8 byte move */
771-
emit_a32_mov_r(dst_lo, src_lo, ctx);
772-
emit_a32_mov_r(dst_hi, src_hi, ctx);
775+
emit_a32_mov_r(dst_lo, src_lo, 0, ctx);
776+
emit_a32_mov_r(dst_hi, src_hi, 0, ctx);
773777
} else if (is_stacked(src_lo) && is_stacked(dst_lo)) {
774778
const u8 *tmp = bpf2a32[TMP_REG_1];
775779

@@ -785,6 +789,24 @@ static inline void emit_a32_mov_r64(const bool is64, const s8 dst[],
785789
}
786790
}
787791

792+
/* dst = (signed)src */
793+
static inline void emit_a32_movsx_r64(const bool is64, const u8 off, const s8 dst[], const s8 src[],
794+
struct jit_ctx *ctx) {
795+
const s8 *tmp = bpf2a32[TMP_REG_1];
796+
const s8 *rt;
797+
798+
rt = arm_bpf_get_reg64(dst, tmp, ctx);
799+
800+
emit_a32_mov_r(dst_lo, src_lo, off, ctx);
801+
if (!is64) {
802+
if (!ctx->prog->aux->verifier_zext)
803+
/* Zero out high 4 bytes */
804+
emit_a32_mov_i(dst_hi, 0, ctx);
805+
} else {
806+
emit(ARM_ASR_I(rt[0], rt[1], 31), ctx);
807+
}
808+
}
809+
788810
/* Shift operations */
789811
static inline void emit_a32_alu_i(const s8 dst, const u32 val,
790812
struct jit_ctx *ctx, const u8 op) {
@@ -1450,7 +1472,10 @@ static int build_insn(const struct bpf_insn *insn, struct jit_ctx *ctx)
14501472
emit_a32_mov_i(dst_hi, 0, ctx);
14511473
break;
14521474
}
1453-
emit_a32_mov_r64(is64, dst, src, ctx);
1475+
if (insn->off)
1476+
emit_a32_movsx_r64(is64, insn->off, dst, src, ctx);
1477+
else
1478+
emit_a32_mov_r64(is64, dst, src, ctx);
14541479
break;
14551480
case BPF_K:
14561481
/* Sign-extend immediate value to destination reg */

0 commit comments

Comments
 (0)