]> asedeno.scripts.mit.edu Git - linux.git/commitdiff
ppc: bpf: implement jitting of JMP32
authorJiong Wang <jiong.wang@netronome.com>
Sat, 26 Jan 2019 17:26:10 +0000 (12:26 -0500)
committerAlexei Starovoitov <ast@kernel.org>
Sat, 26 Jan 2019 21:33:02 +0000 (13:33 -0800)
This patch implements code-gen for new JMP32 instructions on ppc.

For JMP32 | JSET, instruction encoding for PPC_RLWINM_DOT is added to check
the result of ANDing low 32-bit of operands.

Cc: Naveen N. Rao <naveen.n.rao@linux.ibm.com>
Cc: Sandipan Das <sandipan@linux.ibm.com>
Signed-off-by: Jiong Wang <jiong.wang@netronome.com>
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
arch/powerpc/include/asm/ppc-opcode.h
arch/powerpc/net/bpf_jit.h
arch/powerpc/net/bpf_jit_comp64.c

index 19a8834e0398c0ccf2380f6ece6cdf974ffaf7de..f9513ad38fa64f62d0093b9fb9962418c4697e26 100644 (file)
 #define PPC_INST_DIVWU                 0x7c000396
 #define PPC_INST_DIVD                  0x7c0003d2
 #define PPC_INST_RLWINM                        0x54000000
+#define PPC_INST_RLWINM_DOT            0x54000001
 #define PPC_INST_RLWIMI                        0x50000000
 #define PPC_INST_RLDICL                        0x78000000
 #define PPC_INST_RLDICR                        0x78000004
index c2d5192ed64faddf86dfaeba187d6ab81f85edaa..549e9490ff2aabd79e7e8a7acc970d8a599cba79 100644 (file)
 #define PPC_RLWINM(d, a, i, mb, me)    EMIT(PPC_INST_RLWINM | ___PPC_RA(d) | \
                                        ___PPC_RS(a) | __PPC_SH(i) |          \
                                        __PPC_MB(mb) | __PPC_ME(me))
+#define PPC_RLWINM_DOT(d, a, i, mb, me)        EMIT(PPC_INST_RLWINM_DOT |            \
+                                       ___PPC_RA(d) | ___PPC_RS(a) |         \
+                                       __PPC_SH(i) | __PPC_MB(mb) |          \
+                                       __PPC_ME(me))
 #define PPC_RLWIMI(d, a, i, mb, me)    EMIT(PPC_INST_RLWIMI | ___PPC_RA(d) | \
                                        ___PPC_RS(a) | __PPC_SH(i) |          \
                                        __PPC_MB(mb) | __PPC_ME(me))
index 7ce57657d3b8f07696185120dc56516aacbbb625..15bba765fa792b4533e44c162071f3ad2b4304a2 100644 (file)
@@ -768,36 +768,58 @@ static int bpf_jit_build_body(struct bpf_prog *fp, u32 *image,
                case BPF_JMP | BPF_JGT | BPF_X:
                case BPF_JMP | BPF_JSGT | BPF_K:
                case BPF_JMP | BPF_JSGT | BPF_X:
+               case BPF_JMP32 | BPF_JGT | BPF_K:
+               case BPF_JMP32 | BPF_JGT | BPF_X:
+               case BPF_JMP32 | BPF_JSGT | BPF_K:
+               case BPF_JMP32 | BPF_JSGT | BPF_X:
                        true_cond = COND_GT;
                        goto cond_branch;
                case BPF_JMP | BPF_JLT | BPF_K:
                case BPF_JMP | BPF_JLT | BPF_X:
                case BPF_JMP | BPF_JSLT | BPF_K:
                case BPF_JMP | BPF_JSLT | BPF_X:
+               case BPF_JMP32 | BPF_JLT | BPF_K:
+               case BPF_JMP32 | BPF_JLT | BPF_X:
+               case BPF_JMP32 | BPF_JSLT | BPF_K:
+               case BPF_JMP32 | BPF_JSLT | BPF_X:
                        true_cond = COND_LT;
                        goto cond_branch;
                case BPF_JMP | BPF_JGE | BPF_K:
                case BPF_JMP | BPF_JGE | BPF_X:
                case BPF_JMP | BPF_JSGE | BPF_K:
                case BPF_JMP | BPF_JSGE | BPF_X:
+               case BPF_JMP32 | BPF_JGE | BPF_K:
+               case BPF_JMP32 | BPF_JGE | BPF_X:
+               case BPF_JMP32 | BPF_JSGE | BPF_K:
+               case BPF_JMP32 | BPF_JSGE | BPF_X:
                        true_cond = COND_GE;
                        goto cond_branch;
                case BPF_JMP | BPF_JLE | BPF_K:
                case BPF_JMP | BPF_JLE | BPF_X:
                case BPF_JMP | BPF_JSLE | BPF_K:
                case BPF_JMP | BPF_JSLE | BPF_X:
+               case BPF_JMP32 | BPF_JLE | BPF_K:
+               case BPF_JMP32 | BPF_JLE | BPF_X:
+               case BPF_JMP32 | BPF_JSLE | BPF_K:
+               case BPF_JMP32 | BPF_JSLE | BPF_X:
                        true_cond = COND_LE;
                        goto cond_branch;
                case BPF_JMP | BPF_JEQ | BPF_K:
                case BPF_JMP | BPF_JEQ | BPF_X:
+               case BPF_JMP32 | BPF_JEQ | BPF_K:
+               case BPF_JMP32 | BPF_JEQ | BPF_X:
                        true_cond = COND_EQ;
                        goto cond_branch;
                case BPF_JMP | BPF_JNE | BPF_K:
                case BPF_JMP | BPF_JNE | BPF_X:
+               case BPF_JMP32 | BPF_JNE | BPF_K:
+               case BPF_JMP32 | BPF_JNE | BPF_X:
                        true_cond = COND_NE;
                        goto cond_branch;
                case BPF_JMP | BPF_JSET | BPF_K:
                case BPF_JMP | BPF_JSET | BPF_X:
+               case BPF_JMP32 | BPF_JSET | BPF_K:
+               case BPF_JMP32 | BPF_JSET | BPF_X:
                        true_cond = COND_NE;
                        /* Fall through */
 
@@ -809,18 +831,44 @@ static int bpf_jit_build_body(struct bpf_prog *fp, u32 *image,
                        case BPF_JMP | BPF_JLE | BPF_X:
                        case BPF_JMP | BPF_JEQ | BPF_X:
                        case BPF_JMP | BPF_JNE | BPF_X:
+                       case BPF_JMP32 | BPF_JGT | BPF_X:
+                       case BPF_JMP32 | BPF_JLT | BPF_X:
+                       case BPF_JMP32 | BPF_JGE | BPF_X:
+                       case BPF_JMP32 | BPF_JLE | BPF_X:
+                       case BPF_JMP32 | BPF_JEQ | BPF_X:
+                       case BPF_JMP32 | BPF_JNE | BPF_X:
                                /* unsigned comparison */
-                               PPC_CMPLD(dst_reg, src_reg);
+                               if (BPF_CLASS(code) == BPF_JMP32)
+                                       PPC_CMPLW(dst_reg, src_reg);
+                               else
+                                       PPC_CMPLD(dst_reg, src_reg);
                                break;
                        case BPF_JMP | BPF_JSGT | BPF_X:
                        case BPF_JMP | BPF_JSLT | BPF_X:
                        case BPF_JMP | BPF_JSGE | BPF_X:
                        case BPF_JMP | BPF_JSLE | BPF_X:
+                       case BPF_JMP32 | BPF_JSGT | BPF_X:
+                       case BPF_JMP32 | BPF_JSLT | BPF_X:
+                       case BPF_JMP32 | BPF_JSGE | BPF_X:
+                       case BPF_JMP32 | BPF_JSLE | BPF_X:
                                /* signed comparison */
-                               PPC_CMPD(dst_reg, src_reg);
+                               if (BPF_CLASS(code) == BPF_JMP32)
+                                       PPC_CMPW(dst_reg, src_reg);
+                               else
+                                       PPC_CMPD(dst_reg, src_reg);
                                break;
                        case BPF_JMP | BPF_JSET | BPF_X:
-                               PPC_AND_DOT(b2p[TMP_REG_1], dst_reg, src_reg);
+                       case BPF_JMP32 | BPF_JSET | BPF_X:
+                               if (BPF_CLASS(code) == BPF_JMP) {
+                                       PPC_AND_DOT(b2p[TMP_REG_1], dst_reg,
+                                                   src_reg);
+                               } else {
+                                       int tmp_reg = b2p[TMP_REG_1];
+
+                                       PPC_AND(tmp_reg, dst_reg, src_reg);
+                                       PPC_RLWINM_DOT(tmp_reg, tmp_reg, 0, 0,
+                                                      31);
+                               }
                                break;
                        case BPF_JMP | BPF_JNE | BPF_K:
                        case BPF_JMP | BPF_JEQ | BPF_K:
@@ -828,43 +876,87 @@ static int bpf_jit_build_body(struct bpf_prog *fp, u32 *image,
                        case BPF_JMP | BPF_JLT | BPF_K:
                        case BPF_JMP | BPF_JGE | BPF_K:
                        case BPF_JMP | BPF_JLE | BPF_K:
+                       case BPF_JMP32 | BPF_JNE | BPF_K:
+                       case BPF_JMP32 | BPF_JEQ | BPF_K:
+                       case BPF_JMP32 | BPF_JGT | BPF_K:
+                       case BPF_JMP32 | BPF_JLT | BPF_K:
+                       case BPF_JMP32 | BPF_JGE | BPF_K:
+                       case BPF_JMP32 | BPF_JLE | BPF_K:
+                       {
+                               bool is_jmp32 = BPF_CLASS(code) == BPF_JMP32;
+
                                /*
                                 * Need sign-extended load, so only positive
                                 * values can be used as imm in cmpldi
                                 */
-                               if (imm >= 0 && imm < 32768)
-                                       PPC_CMPLDI(dst_reg, imm);
-                               else {
+                               if (imm >= 0 && imm < 32768) {
+                                       if (is_jmp32)
+                                               PPC_CMPLWI(dst_reg, imm);
+                                       else
+                                               PPC_CMPLDI(dst_reg, imm);
+                               } else {
                                        /* sign-extending load */
                                        PPC_LI32(b2p[TMP_REG_1], imm);
                                        /* ... but unsigned comparison */
-                                       PPC_CMPLD(dst_reg, b2p[TMP_REG_1]);
+                                       if (is_jmp32)
+                                               PPC_CMPLW(dst_reg,
+                                                         b2p[TMP_REG_1]);
+                                       else
+                                               PPC_CMPLD(dst_reg,
+                                                         b2p[TMP_REG_1]);
                                }
                                break;
+                       }
                        case BPF_JMP | BPF_JSGT | BPF_K:
                        case BPF_JMP | BPF_JSLT | BPF_K:
                        case BPF_JMP | BPF_JSGE | BPF_K:
                        case BPF_JMP | BPF_JSLE | BPF_K:
+                       case BPF_JMP32 | BPF_JSGT | BPF_K:
+                       case BPF_JMP32 | BPF_JSLT | BPF_K:
+                       case BPF_JMP32 | BPF_JSGE | BPF_K:
+                       case BPF_JMP32 | BPF_JSLE | BPF_K:
+                       {
+                               bool is_jmp32 = BPF_CLASS(code) == BPF_JMP32;
+
                                /*
                                 * signed comparison, so any 16-bit value
                                 * can be used in cmpdi
                                 */
-                               if (imm >= -32768 && imm < 32768)
-                                       PPC_CMPDI(dst_reg, imm);
-                               else {
+                               if (imm >= -32768 && imm < 32768) {
+                                       if (is_jmp32)
+                                               PPC_CMPWI(dst_reg, imm);
+                                       else
+                                               PPC_CMPDI(dst_reg, imm);
+                               } else {
                                        PPC_LI32(b2p[TMP_REG_1], imm);
-                                       PPC_CMPD(dst_reg, b2p[TMP_REG_1]);
+                                       if (is_jmp32)
+                                               PPC_CMPW(dst_reg,
+                                                        b2p[TMP_REG_1]);
+                                       else
+                                               PPC_CMPD(dst_reg,
+                                                        b2p[TMP_REG_1]);
                                }
                                break;
+                       }
                        case BPF_JMP | BPF_JSET | BPF_K:
+                       case BPF_JMP32 | BPF_JSET | BPF_K:
                                /* andi does not sign-extend the immediate */
                                if (imm >= 0 && imm < 32768)
                                        /* PPC_ANDI is _only/always_ dot-form */
                                        PPC_ANDI(b2p[TMP_REG_1], dst_reg, imm);
                                else {
-                                       PPC_LI32(b2p[TMP_REG_1], imm);
-                                       PPC_AND_DOT(b2p[TMP_REG_1], dst_reg,
-                                                   b2p[TMP_REG_1]);
+                                       int tmp_reg = b2p[TMP_REG_1];
+
+                                       PPC_LI32(tmp_reg, imm);
+                                       if (BPF_CLASS(code) == BPF_JMP) {
+                                               PPC_AND_DOT(tmp_reg, dst_reg,
+                                                           tmp_reg);
+                                       } else {
+                                               PPC_AND(tmp_reg, dst_reg,
+                                                       tmp_reg);
+                                               PPC_RLWINM_DOT(tmp_reg, tmp_reg,
+                                                              0, 0, 31);
+                                       }
                                }
                                break;
                        }