summaryrefslogtreecommitdiffstats
path: root/arch/powerpc/net
diff options
context:
space:
mode:
authorVladimir Murzin <murzin.v@gmail.com>2013-09-28 10:22:01 +0200
committerBenjamin Herrenschmidt <benh@kernel.crashing.org>2013-10-31 16:19:21 +1100
commitb0c06d333505c5503d0de5dee1ddf8478dcf5251 (patch)
tree1259372fc700cfc93e5b8353f802ee2b303cc389 /arch/powerpc/net
parenta40a2b670706494610d794927b9aebe77e18af8d (diff)
powerpc/bpf: Support MOD operation
commit b6069a9570 (filter: add MOD operation) added generic support for modulus operation in BPF. This patch brings JIT support for PPC64 Signed-off-by: Vladimir Murzin <murzin.v@gmail.com> Acked-by: Matt Evans <matt@ozlabs.org> Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Diffstat (limited to 'arch/powerpc/net')
-rw-r--r--arch/powerpc/net/bpf_jit.h1
-rw-r--r--arch/powerpc/net/bpf_jit_comp.c20
2 files changed, 21 insertions, 0 deletions
diff --git a/arch/powerpc/net/bpf_jit.h b/arch/powerpc/net/bpf_jit.h
index 0baf2b826e2..9aee27c582d 100644
--- a/arch/powerpc/net/bpf_jit.h
+++ b/arch/powerpc/net/bpf_jit.h
@@ -39,6 +39,7 @@
#define r_X 5
#define r_addr 6
#define r_scratch1 7
+#define r_scratch2 8
#define r_D 14
#define r_HL 15
#define r_M 16
diff --git a/arch/powerpc/net/bpf_jit_comp.c b/arch/powerpc/net/bpf_jit_comp.c
index 81cd6c79bab..475d4f26fc6 100644
--- a/arch/powerpc/net/bpf_jit_comp.c
+++ b/arch/powerpc/net/bpf_jit_comp.c
@@ -187,6 +187,26 @@ static int bpf_jit_build_body(struct sk_filter *fp, u32 *image,
PPC_MUL(r_A, r_A, r_scratch1);
}
break;
+ case BPF_S_ALU_MOD_X: /* A %= X; */
+ ctx->seen |= SEEN_XREG;
+ PPC_CMPWI(r_X, 0);
+ if (ctx->pc_ret0 != -1) {
+ PPC_BCC(COND_EQ, addrs[ctx->pc_ret0]);
+ } else {
+ PPC_BCC_SHORT(COND_NE, (ctx->idx*4)+12);
+ PPC_LI(r_ret, 0);
+ PPC_JMP(exit_addr);
+ }
+ PPC_DIVWU(r_scratch1, r_A, r_X);
+ PPC_MUL(r_scratch1, r_X, r_scratch1);
+ PPC_SUB(r_A, r_A, r_scratch1);
+ break;
+ case BPF_S_ALU_MOD_K: /* A %= K; */
+ PPC_LI32(r_scratch2, K);
+ PPC_DIVWU(r_scratch1, r_A, r_scratch2);
+ PPC_MUL(r_scratch1, r_scratch2, r_scratch1);
+ PPC_SUB(r_A, r_A, r_scratch1);
+ break;
case BPF_S_ALU_DIV_X: /* A /= X; */
ctx->seen |= SEEN_XREG;
PPC_CMPWI(r_X, 0);