sparc: bpf: eliminate zero extension code-gen [Linux 5.3]

This Linux kernel change "sparc: bpf: eliminate zero extension code-gen" is included in the Linux 5.3 release. This change is authored by Jiong Wang <jiong.wang [at] netronome.com> on Fri May 24 23:25:25 2019 +0100. The commit for this change in Linux stable tree is 3e2a33c (patch).

sparc: bpf: eliminate zero extension code-gen

Cc: David S. Miller <davem@davemloft.net>
Signed-off-by: Jiong Wang <jiong.wang@netronome.com>
Signed-off-by: Alexei Starovoitov <ast@kernel.org>

There are 29 lines of Linux source code added/deleted in this change. Code changes to Linux kernel are as follows.

 arch/sparc/net/bpf_jit_comp_64.c | 29 +++++++++++++++++++++++++++--
 1 file changed, 27 insertions(+), 2 deletions(-)

diff --git a/arch/sparc/net/bpf_jit_comp_64.c b/arch/sparc/net/bpf_jit_comp_64.c
index 65428e7..3364e2a 100644
--- a/arch/sparc/net/bpf_jit_comp_64.c
+++ b/arch/sparc/net/bpf_jit_comp_64.c
@@ -908,6 +908,8 @@ static int build_insn(const struct bpf_insn *insn, struct jit_ctx *ctx)
    /* dst = src */
    case BPF_ALU | BPF_MOV | BPF_X:
        emit_alu3_K(SRL, src, 0, dst, ctx);
+       if (insn_is_zext(&insn[1]))
+           return 1;
        break;
    case BPF_ALU64 | BPF_MOV | BPF_X:
        emit_reg_move(src, dst, ctx);
@@ -942,6 +944,8 @@ static int build_insn(const struct bpf_insn *insn, struct jit_ctx *ctx)
    case BPF_ALU | BPF_DIV | BPF_X:
        emit_write_y(G0, ctx);
        emit_alu(DIV, src, dst, ctx);
+       if (insn_is_zext(&insn[1]))
+           return 1;
        break;
    case BPF_ALU64 | BPF_DIV | BPF_X:
        emit_alu(UDIVX, src, dst, ctx);
@@ -975,6 +979,8 @@ static int build_insn(const struct bpf_insn *insn, struct jit_ctx *ctx)
        break;
    case BPF_ALU | BPF_RSH | BPF_X:
        emit_alu(SRL, src, dst, ctx);
+       if (insn_is_zext(&insn[1]))
+           return 1;
        break;
    case BPF_ALU64 | BPF_RSH | BPF_X:
        emit_alu(SRLX, src, dst, ctx);
@@ -997,9 +1003,12 @@ static int build_insn(const struct bpf_insn *insn, struct jit_ctx *ctx)
        case 16:
            emit_alu_K(SLL, dst, 16, ctx);
            emit_alu_K(SRL, dst, 16, ctx);
+           if (insn_is_zext(&insn[1]))
+               return 1;
            break;
        case 32:
-           emit_alu_K(SRL, dst, 0, ctx);
+           if (!ctx->prog->aux->verifier_zext)
+               emit_alu_K(SRL, dst, 0, ctx);
            break;
        case 64:
            /* nop */
@@ -1021,6 +1030,8 @@ static int build_insn(const struct bpf_insn *insn, struct jit_ctx *ctx)
            emit_alu3_K(AND, dst, 0xff, dst, ctx);
            emit_alu3_K(SLL, tmp, 8, tmp, ctx);
            emit_alu(OR, tmp, dst, ctx);
+           if (insn_is_zext(&insn[1]))
+               return 1;
            break;

        case 32:
@@ -1037,6 +1048,8 @@ static int build_insn(const struct bpf_insn *insn, struct jit_ctx *ctx)
            emit_alu3_K(AND, dst, 0xff, dst, ctx);  /* dst  = dst & 0xff */
            emit_alu3_K(SLL, dst, 24, dst, ctx);    /* dst  = dst << 24 */
            emit_alu(OR, tmp, dst, ctx);        /* dst  = dst | tmp */
+           if (insn_is_zext(&insn[1]))
+               return 1;
            break;

        case 64:
@@ -1050,6 +1063,8 @@ static int build_insn(const struct bpf_insn *insn, struct jit_ctx *ctx)
    /* dst = imm */
    case BPF_ALU | BPF_MOV | BPF_K:
        emit_loadimm32(imm, dst, ctx);
+       if (insn_is_zext(&insn[1]))
+           return 1;
        break;
    case BPF_ALU64 | BPF_MOV | BPF_K:
        emit_loadimm_sext(imm, dst, ctx);
@@ -1132,6 +1147,8 @@ static int build_insn(const struct bpf_insn *insn, struct jit_ctx *ctx)
        break;
    case BPF_ALU | BPF_RSH | BPF_K:
        emit_alu_K(SRL, dst, imm, ctx);
+       if (insn_is_zext(&insn[1]))
+           return 1;
        break;
    case BPF_ALU64 | BPF_RSH | BPF_K:
        emit_alu_K(SRLX, dst, imm, ctx);
@@ -1144,7 +1161,8 @@ static int build_insn(const struct bpf_insn *insn, struct jit_ctx *ctx)
        break;

    do_alu32_trunc:
-       if (BPF_CLASS(code) == BPF_ALU)
+       if (BPF_CLASS(code) == BPF_ALU &&
+           !ctx->prog->aux->verifier_zext)
            emit_alu_K(SRL, dst, 0, ctx);
        break;

@@ -1265,6 +1283,8 @@ static int build_insn(const struct bpf_insn *insn, struct jit_ctx *ctx)
            rs2 = RS2(tmp);
        }
        emit(opcode | RS1(src) | rs2 | RD(dst), ctx);
+       if (opcode != LD64 && insn_is_zext(&insn[1]))
+           return 1;
        break;
    }
    /* ST: *(size *)(dst + off) = imm */
@@ -1432,6 +1452,11 @@ static void jit_fill_hole(void *area, unsigned int size)
        *ptr++ = 0x91d02005; /* ta 5 */
 }

+bool bpf_jit_needs_zext(void)
+{
+   return true;
+}
+
 struct sparc64_jit_data {
    struct bpf_binary_header *header;
    u8 *image;

Leave a Reply

Your email address will not be published. Required fields are marked *