Merge tag 'msm-fixes-2018-12-04' of https://gitlab.freedesktop.org/seanpaul/dpu-stagi...
[sfrench/cifs-2.6.git] / arch / sparc / net / bpf_jit_comp_64.c
index 222785af550b46736676808b6e00d8d8cef9a286..5fda4f7bf15d176fbb913435ea0a25c510c8df5a 100644 (file)
@@ -791,7 +791,7 @@ static int emit_compare_and_branch(const u8 code, const u8 dst, u8 src,
 }
 
 /* Just skip the save instruction and the ctx register move.  */
-#define BPF_TAILCALL_PROLOGUE_SKIP     16
+#define BPF_TAILCALL_PROLOGUE_SKIP     32
 #define BPF_TAILCALL_CNT_SP_OFF                (STACK_BIAS + 128)
 
 static void build_prologue(struct jit_ctx *ctx)
@@ -824,9 +824,15 @@ static void build_prologue(struct jit_ctx *ctx)
                const u8 vfp = bpf2sparc[BPF_REG_FP];
 
                emit(ADD | IMMED | RS1(FP) | S13(STACK_BIAS) | RD(vfp), ctx);
+       } else {
+               emit_nop(ctx);
        }
 
        emit_reg_move(I0, O0, ctx);
+       emit_reg_move(I1, O1, ctx);
+       emit_reg_move(I2, O2, ctx);
+       emit_reg_move(I3, O3, ctx);
+       emit_reg_move(I4, O4, ctx);
        /* If you add anything here, adjust BPF_TAILCALL_PROLOGUE_SKIP above. */
 }
 
@@ -1270,6 +1276,9 @@ static int build_insn(const struct bpf_insn *insn, struct jit_ctx *ctx)
                const u8 tmp2 = bpf2sparc[TMP_REG_2];
                u32 opcode = 0, rs2;
 
+               if (insn->dst_reg == BPF_REG_FP)
+                       ctx->saw_frame_pointer = true;
+
                ctx->tmp_2_used = true;
                emit_loadimm(imm, tmp2, ctx);
 
@@ -1308,6 +1317,9 @@ static int build_insn(const struct bpf_insn *insn, struct jit_ctx *ctx)
                const u8 tmp = bpf2sparc[TMP_REG_1];
                u32 opcode = 0, rs2;
 
+               if (insn->dst_reg == BPF_REG_FP)
+                       ctx->saw_frame_pointer = true;
+
                switch (BPF_SIZE(code)) {
                case BPF_W:
                        opcode = ST32;
@@ -1340,6 +1352,9 @@ static int build_insn(const struct bpf_insn *insn, struct jit_ctx *ctx)
                const u8 tmp2 = bpf2sparc[TMP_REG_2];
                const u8 tmp3 = bpf2sparc[TMP_REG_3];
 
+               if (insn->dst_reg == BPF_REG_FP)
+                       ctx->saw_frame_pointer = true;
+
                ctx->tmp_1_used = true;
                ctx->tmp_2_used = true;
                ctx->tmp_3_used = true;
@@ -1360,6 +1375,9 @@ static int build_insn(const struct bpf_insn *insn, struct jit_ctx *ctx)
                const u8 tmp2 = bpf2sparc[TMP_REG_2];
                const u8 tmp3 = bpf2sparc[TMP_REG_3];
 
+               if (insn->dst_reg == BPF_REG_FP)
+                       ctx->saw_frame_pointer = true;
+
                ctx->tmp_1_used = true;
                ctx->tmp_2_used = true;
                ctx->tmp_3_used = true;
@@ -1425,12 +1443,12 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *prog)
        struct bpf_prog *tmp, *orig_prog = prog;
        struct sparc64_jit_data *jit_data;
        struct bpf_binary_header *header;
+       u32 prev_image_size, image_size;
        bool tmp_blinded = false;
        bool extra_pass = false;
        struct jit_ctx ctx;
-       u32 image_size;
        u8 *image_ptr;
-       int pass;
+       int pass, i;
 
        if (!prog->jit_requested)
                return orig_prog;
@@ -1461,61 +1479,82 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *prog)
                header = jit_data->header;
                extra_pass = true;
                image_size = sizeof(u32) * ctx.idx;
+               prev_image_size = image_size;
+               pass = 1;
                goto skip_init_ctx;
        }
 
        memset(&ctx, 0, sizeof(ctx));
        ctx.prog = prog;
 
-       ctx.offset = kcalloc(prog->len, sizeof(unsigned int), GFP_KERNEL);
+       ctx.offset = kmalloc_array(prog->len, sizeof(unsigned int), GFP_KERNEL);
        if (ctx.offset == NULL) {
                prog = orig_prog;
                goto out_off;
        }
 
-       /* Fake pass to detect features used, and get an accurate assessment
-        * of what the final image size will be.
+       /* Longest sequence emitted is for bswap32, 12 instructions.  Pre-cook
+        * the offset array so that we converge faster.
         */
-       if (build_body(&ctx)) {
-               prog = orig_prog;
-               goto out_off;
-       }
-       build_prologue(&ctx);
-       build_epilogue(&ctx);
-
-       /* Now we know the actual image size. */
-       image_size = sizeof(u32) * ctx.idx;
-       header = bpf_jit_binary_alloc(image_size, &image_ptr,
-                                     sizeof(u32), jit_fill_hole);
-       if (header == NULL) {
-               prog = orig_prog;
-               goto out_off;
-       }
+       for (i = 0; i < prog->len; i++)
+               ctx.offset[i] = i * (12 * 4);
 
-       ctx.image = (u32 *)image_ptr;
-skip_init_ctx:
-       for (pass = 1; pass < 3; pass++) {
+       prev_image_size = ~0U;
+       for (pass = 1; pass < 40; pass++) {
                ctx.idx = 0;
 
                build_prologue(&ctx);
-
                if (build_body(&ctx)) {
-                       bpf_jit_binary_free(header);
                        prog = orig_prog;
                        goto out_off;
                }
-
                build_epilogue(&ctx);
 
                if (bpf_jit_enable > 1)
-                       pr_info("Pass %d: shrink = %d, seen = [%c%c%c%c%c%c]\n", pass,
-                               image_size - (ctx.idx * 4),
+                       pr_info("Pass %d: size = %u, seen = [%c%c%c%c%c%c]\n", pass,
+                               ctx.idx * 4,
                                ctx.tmp_1_used ? '1' : ' ',
                                ctx.tmp_2_used ? '2' : ' ',
                                ctx.tmp_3_used ? '3' : ' ',
                                ctx.saw_frame_pointer ? 'F' : ' ',
                                ctx.saw_call ? 'C' : ' ',
                                ctx.saw_tail_call ? 'T' : ' ');
+
+               if (ctx.idx * 4 == prev_image_size)
+                       break;
+               prev_image_size = ctx.idx * 4;
+               cond_resched();
+       }
+
+       /* Now we know the actual image size. */
+       image_size = sizeof(u32) * ctx.idx;
+       header = bpf_jit_binary_alloc(image_size, &image_ptr,
+                                     sizeof(u32), jit_fill_hole);
+       if (header == NULL) {
+               prog = orig_prog;
+               goto out_off;
+       }
+
+       ctx.image = (u32 *)image_ptr;
+skip_init_ctx:
+       ctx.idx = 0;
+
+       build_prologue(&ctx);
+
+       if (build_body(&ctx)) {
+               bpf_jit_binary_free(header);
+               prog = orig_prog;
+               goto out_off;
+       }
+
+       build_epilogue(&ctx);
+
+       if (ctx.idx * 4 != prev_image_size) {
+               pr_err("bpf_jit: Failed to converge, prev_size=%u size=%d\n",
+                      prev_image_size, ctx.idx * 4);
+               bpf_jit_binary_free(header);
+               prog = orig_prog;
+               goto out_off;
        }
 
        if (bpf_jit_enable > 1)