From patchwork Sat Sep 21 07:32:37 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Vladimir Murzin X-Patchwork-Id: 2922021 Return-Path: X-Original-To: patchwork-linux-arm@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork1.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.19.201]) by patchwork1.web.kernel.org (Postfix) with ESMTP id 305D49F1E2 for ; Sat, 21 Sep 2013 07:34:26 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id DB20E20513 for ; Sat, 21 Sep 2013 07:34:24 +0000 (UTC) Received: from casper.infradead.org (casper.infradead.org [85.118.1.10]) (using TLSv1 with cipher DHE-RSA-AES256-SHA (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 5029B2050E for ; Sat, 21 Sep 2013 07:34:23 +0000 (UTC) Received: from merlin.infradead.org ([2001:4978:20e::2]) by casper.infradead.org with esmtps (Exim 4.80.1 #2 (Red Hat Linux)) id 1VNHha-0006AU-CG; Sat, 21 Sep 2013 07:34:02 +0000 Received: from localhost ([::1] helo=merlin.infradead.org) by merlin.infradead.org with esmtp (Exim 4.80.1 #2 (Red Hat Linux)) id 1VNHhX-0003gY-N4; Sat, 21 Sep 2013 07:33:59 +0000 Received: from mail-la0-x235.google.com ([2a00:1450:4010:c03::235]) by merlin.infradead.org with esmtps (Exim 4.80.1 #2 (Red Hat Linux)) id 1VNHhR-0003fj-DD for linux-arm-kernel@lists.infradead.org; Sat, 21 Sep 2013 07:33:54 +0000 Received: by mail-la0-f53.google.com with SMTP id el20so1033621lab.26 for ; Sat, 21 Sep 2013 00:33:30 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=from:to:cc:subject:date:message-id; bh=X2V/12QTvTHpxdzBEF11EgUEbWN4YdEvrrh2ZfF06kI=; b=cO3nXpQQtfxM5pTzyPutMGWPqu241xcd6LW14Q6hNIe34sn9mOp3y91vtzrw0+riCe IXihGLdwXaNqwgE0bow2RXDaXzmMsgNxsv5ZihoR/SCr4PnjmQmuHf7DBqhG069DWDJ7 qpEbLKqiGyiUgTxOE8ehgicUUaWzf3aScjRNSSOrPg/k1M+uscsN3nrD8PJWb/6V0v50 wfs5clLj3acw021bmYEjg7UOcWJTS2h1laBkDA2vHtPTkL9ZyRrjyYrU8upDEscMaigQ s5G2h0RvuoZrngoXGFtJ1/84wwczc46+Y4Z97PLP1SoLxF+pdiXgjziydOrULey0/qbi mtTg== X-Received: by 10.152.87.143 with SMTP id ay15mr9756870lab.2.1379748810287; Sat, 21 Sep 2013 00:33:30 -0700 (PDT) Received: from localhost ([83.220.237.243]) by mx.google.com with ESMTPSA id b1sm7539961lah.6.1969.12.31.16.00.00 (version=TLSv1.2 cipher=ECDHE-RSA-RC4-SHA bits=128/128); Sat, 21 Sep 2013 00:33:29 -0700 (PDT) From: Vladimir Murzin To: linux-arm-kernel@lists.infradead.org Subject: [PATCH v2] arm: bpf_jit: support MOD operation Date: Sat, 21 Sep 2013 09:32:37 +0200 Message-Id: <1379748757-3512-1-git-send-email-murzin.v@gmail.com> X-Mailer: git-send-email 1.8.1.5 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20130921_033353_762393_0CAA507D X-CRM114-Status: GOOD ( 14.13 ) X-Spam-Score: -2.0 (--) Cc: linux@arm.linux.org.uk, netdev@vger.kernel.org, Vladimir Murzin , edumazet@google.com, mgherzan@gmail.com, dborkman@redhat.com, will.daecon@arm.com, davem@davemloft.net X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@lists.infradead.org X-Spam-Status: No, score=-4.7 required=5.0 tests=BAYES_00, DKIM_ADSP_CUSTOM_MED, DKIM_SIGNED, FREEMAIL_FROM, RCVD_IN_DNSWL_MED, RP_MATCHES_RCVD, T_DKIM_INVALID, UNPARSEABLE_RELAY autolearn=unavailable version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP 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 --- 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 + : 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(+) diff --git a/arch/arm/net/bpf_jit_32.c b/arch/arm/net/bpf_jit_32.c index f50d223..faec4d3 100644 --- a/arch/arm/net/bpf_jit_32.c +++ b/arch/arm/net/bpf_jit_32.c @@ -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); diff --git a/arch/arm/net/bpf_jit_32.h b/arch/arm/net/bpf_jit_32.h index afb8462..640a8fd 100644 --- a/arch/arm/net/bpf_jit_32.h +++ b/arch/arm/net/bpf_jit_32.h @@ -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 */