@@ -111,6 +111,11 @@ static u32 jit_udiv(u32 dividend, u32 divisor)
return dividend / divisor;
}
+static u32 jit_udiv_mod(u32 dividend, u32 divisor)
+{
+ return dividend % divisor;
+}
+
static inline void _emit(int cond, u32 inst, struct jit_ctx *ctx)
{
if (ctx->target != NULL)
@@ -458,6 +463,29 @@ static inline void emit_udiv(u8 rd, u8 rm, u8 rn, struct jit_ctx *ctx)
emit(ARM_MOV_R(rd, ARM_R0), ctx);
}
+static inline void emit_udiv_mod(u8 rd, u8 rm, u8 rn, struct jit_ctx *ctx)
+{
+#if __LINUX_ARM_ARCH__ == 7
+ if (elf_hwcap & HWCAP_IDIVA) {
+ emit(ARM_UDIV(ARM_R3, rm, rn), ctx);
+ emit(ARM_MLS(rd, ARM_R3, rn, rm), ctx);
+ return;
+ }
+#endif
+ if (rm != ARM_R0)
+ emit(ARM_MOV_R(ARM_R0, rm), ctx);
+ if (rn != ARM_R1)
+ emit(ARM_MOV_R(ARM_R1, rn), ctx);
+
+ ctx->seen |= SEEN_CALL;
+ emit_mov_i(ARM_R3, (u32)jit_udiv_mod, ctx);
+ emit_blx_r(ARM_R3, ctx);
+
+ if (rd != ARM_R0)
+ emit(ARM_MOV_R(rd, ARM_R0), ctx);
+}
+
+
static inline void update_on_xread(struct jit_ctx *ctx)
{
if (!(ctx->seen & SEEN_X))
@@ -636,6 +664,16 @@ load_ind:
update_on_xread(ctx);
emit(ARM_MUL(r_A, r_A, r_X), ctx);
break;
+ case BPF_S_ALU_MOD_X: /* A %= X; */
+ update_on_xread(ctx);
+ emit(ARM_CMP_I(r_X, 0), ctx);
+ emit_err_ret(ARM_COND_EQ, ctx);
+ emit_udiv_mod(r_A, r_A, r_X, ctx);
+ break;
+ case BPF_S_ALU_MOD_K: /* A %= K; */
+ emit_mov_i(r_scratch, k, ctx);
+ emit_udiv_mod(r_A, r_A, r_scratch, ctx);
+ break;
case BPF_S_ALU_DIV_K:
/* current k == reciprocal_value(userspace k) */
emit_mov_i(r_scratch, k, ctx);
@@ -90,6 +90,7 @@
#define ARM_INST_MOVT 0x03400000
#define ARM_INST_MUL 0x00000090
+#define ARM_INST_MLS 0x00600090
#define ARM_INST_POP 0x08bd0000
#define ARM_INST_PUSH 0x092d0000
@@ -192,5 +193,7 @@
#define ARM_UMULL(rd_lo, rd_hi, rn, rm) (ARM_INST_UMULL | (rd_hi) << 16 \
| (rd_lo) << 12 | (rm) << 8 | rn)
+#define ARM_MLS(rd, rn, rm, ra) (ARM_INST_MLS | (rd) << 16 \
+ | (ra) << 12 | (rm) << 8 | rn)
#endif /* PFILTER_OPCODES_ARM_H */
commit b6069a9570 (filter: add MOD operation) added generic support for modulus operation in BPF. This patch brings JIT support for ARM. Signed-off-by: Vladimir Murzin <murzin.v@gmail.com> --- v1->v2 - wrapper for udiv_mod is added - MUL and SUB are squashed into MLS instruction For BPF program (000) ldh [12] (001) jeq #0x800 jt 2 jf 10 (002) ldh [16] (003) sub #20 (004) mod #5 (005) jeq #0x0 jt 10 jf 6 (006) ldb [20] (007) and #0x20 (008) jeq #0x20 jt 9 jf 10 (009) ret #65535 (010) ret #0 Following code is generated 256 bytes emitted from JIT compiler (pass:2, flen:11) bf008000 + <x>: 0: push {r4, r6, r7, r8, lr} 4: mov r6, r0 8: ldr r7, [r6, #168] ; 0xa8 c: ldr r8, [r6, #80] ; 0x50 10: ldr r0, [r6, #84] ; 0x54 14: sub r8, r8, r0 18: mov r1, #12 1c: sub r0, r8, #2 20: cmp r0, r1 24: addcs r0, r1, r7 28: ldrhcs r4, [r0] 2c: rev16cs r4, r4 30: bcs 0x00000054 34: movw r3, #7012 ; 0x1b64 38: movt r3, #49154 ; 0xc002 3c: mov r0, r6 40: blx r3 44: cmp r1, #0 48: bne 0x000000f8 4c: nop ; (mov r0, r0) 50: mov r4, r0 54: cmp r4, #2048 ; 0x800 58: bne 0x000000f8 5c: mov r1, #16 60: sub r0, r8, #2 64: cmp r0, r1 68: addcs r0, r1, r7 6c: ldrhcs r4, [r0] 70: rev16cs r4, r4 74: bcs 0x00000098 78: movw r3, #7012 ; 0x1b64 7c: movt r3, #49154 ; 0xc002 80: mov r0, r6 84: blx r3 88: cmp r1, #0 8c: bne 0x000000f8 90: nop ; (mov r0, r0) 94: mov r4, r0 98: sub r4, r4, #20 9c: mov r0, #5 a0: udiv r3, r4, r0 a4: mls r4, r3, r0, r4 a8: cmp r4, #0 ac: beq 0x000000f8 b0: mov r1, #20 b4: cmp r8, r1 b8: addhi r0, r1, r7 bc: ldrbhi r4, [r0] c0: bhi 0x000000e4 c4: movw r3, #7068 ; 0x1b9c c8: movt r3, #49154 ; 0xc002 cc: mov r0, r6 d0: blx r3 d4: cmp r1, #0 d8: bne 0x000000f8 dc: nop ; (mov r0, r0) e0: mov r4, r0 e4: and r4, r4, #32 e8: cmp r4, #32 ec: bne 0x000000f8 f0: movw r0, #65535 ; 0xffff f4: b 0x000000fc f8: mov r0, #0 fc: pop {r4, r6, r7, r8, pc} Raw opcodes are flen=11 proglen=256 pass=2 image=bf008000 JIT code: 00000000: d0 41 2d e9 00 60 a0 e1 a8 70 96 e5 50 80 96 e5 JIT code: 00000010: 54 00 96 e5 00 80 48 e0 0c 10 a0 e3 02 00 48 e2 JIT code: 00000020: 01 00 50 e1 07 00 81 20 b0 40 d0 21 b4 4f bf 26 JIT code: 00000030: 07 00 00 2a 64 3b 01 e3 02 30 4c e3 06 00 a0 e1 JIT code: 00000040: 33 ff 2f e1 00 00 51 e3 2a 00 00 1a 00 00 a0 e1 JIT code: 00000050: 00 40 a0 e1 02 0b 54 e3 26 00 00 1a 10 10 a0 e3 JIT code: 00000060: 02 00 48 e2 01 00 50 e1 07 00 81 20 b0 40 d0 21 JIT code: 00000070: b4 4f bf 26 07 00 00 2a 64 3b 01 e3 02 30 4c e3 JIT code: 00000080: 06 00 a0 e1 33 ff 2f e1 00 00 51 e3 19 00 00 1a JIT code: 00000090: 00 00 a0 e1 00 40 a0 e1 14 40 44 e2 05 00 a0 e3 JIT code: 000000a0: 14 f0 33 e7 93 40 64 e0 00 00 54 e3 11 00 00 0a JIT code: 000000b0: 14 10 a0 e3 01 00 58 e1 07 00 81 80 00 40 d0 85 JIT code: 000000c0: 07 00 00 8a 9c 3b 01 e3 02 30 4c e3 06 00 a0 e1 JIT code: 000000d0: 33 ff 2f e1 00 00 51 e3 06 00 00 1a 00 00 a0 e1 JIT code: 000000e0: 00 40 a0 e1 20 40 04 e2 20 00 54 e3 01 00 00 1a JIT code: 000000f0: ff 0f 0f e3 00 00 00 ea 00 00 a0 e3 d0 81 bd e8 arch/arm/net/bpf_jit_32.c | 38 ++++++++++++++++++++++++++++++++++++++ arch/arm/net/bpf_jit_32.h | 3 +++ 2 files changed, 41 insertions(+)