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

This Linux kernel change "s390: 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:24 2019 +0100. The commit for this change in Linux stable tree is 591006b (patch).

s390: bpf: eliminate zero extension code-gen

Cc: Martin Schwidefsky <schwidefsky@de.ibm.com>
Cc: Heiko Carstens <heiko.carstens@de.ibm.com>
Signed-off-by: Jiong Wang <jiong.wang@netronome.com>
Signed-off-by: Alexei Starovoitov <ast@kernel.org>

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

 arch/s390/net/bpf_jit_comp.c | 41 ++++++++++++++++++++++++++++++++++-------
 1 file changed, 34 insertions(+), 7 deletions(-)

diff --git a/arch/s390/net/bpf_jit_comp.c b/arch/s390/net/bpf_jit_comp.c
index 5e7c630..e636728 100644
--- a/arch/s390/net/bpf_jit_comp.c
+++ b/arch/s390/net/bpf_jit_comp.c
@@ -299,9 +299,11 @@ static inline void reg_set_seen(struct bpf_jit *jit, u32 b1)

 #define EMIT_ZERO(b1)                      \
 ({                             \
-   /* llgfr %dst,%dst (zero extend to 64 bit) */       \
-   EMIT4(0xb9160000, b1, b1);              \
-   REG_SET_SEEN(b1);                   \
+   if (!fp->aux->verifier_zext) {              \
+       /* llgfr %dst,%dst (zero extend to 64 bit) */   \
+       EMIT4(0xb9160000, b1, b1);          \
+       REG_SET_SEEN(b1);               \
+   }                           \
 })

 /*
@@ -520,6 +522,8 @@ static noinline int bpf_jit_insn(struct bpf_jit *jit, struct bpf_prog *fp, int i
    case BPF_ALU | BPF_MOV | BPF_X: /* dst = (u32) src */
        /* llgfr %dst,%src */
        EMIT4(0xb9160000, dst_reg, src_reg);
+       if (insn_is_zext(&insn[1]))
+           insn_count = 2;
        break;
    case BPF_ALU64 | BPF_MOV | BPF_X: /* dst = src */
        /* lgr %dst,%src */
@@ -528,6 +532,8 @@ static noinline int bpf_jit_insn(struct bpf_jit *jit, struct bpf_prog *fp, int i
    case BPF_ALU | BPF_MOV | BPF_K: /* dst = (u32) imm */
        /* llilf %dst,imm */
        EMIT6_IMM(0xc00f0000, dst_reg, imm);
+       if (insn_is_zext(&insn[1]))
+           insn_count = 2;
        break;
    case BPF_ALU64 | BPF_MOV | BPF_K: /* dst = imm */
        /* lgfi %dst,imm */
@@ -639,6 +645,8 @@ static noinline int bpf_jit_insn(struct bpf_jit *jit, struct bpf_prog *fp, int i
        EMIT4(0xb9970000, REG_W0, src_reg);
        /* llgfr %dst,%rc */
        EMIT4(0xb9160000, dst_reg, rc_reg);
+       if (insn_is_zext(&insn[1]))
+           insn_count = 2;
        break;
    }
    case BPF_ALU64 | BPF_DIV | BPF_X: /* dst = dst / src */
@@ -676,6 +684,8 @@ static noinline int bpf_jit_insn(struct bpf_jit *jit, struct bpf_prog *fp, int i
                  EMIT_CONST_U32(imm));
        /* llgfr %dst,%rc */
        EMIT4(0xb9160000, dst_reg, rc_reg);
+       if (insn_is_zext(&insn[1]))
+           insn_count = 2;
        break;
    }
    case BPF_ALU64 | BPF_DIV | BPF_K: /* dst = dst / imm */
@@ -864,10 +874,13 @@ static noinline int bpf_jit_insn(struct bpf_jit *jit, struct bpf_prog *fp, int i
        case 16: /* dst = (u16) cpu_to_be16(dst) */
            /* llghr %dst,%dst */
            EMIT4(0xb9850000, dst_reg, dst_reg);
+           if (insn_is_zext(&insn[1]))
+               insn_count = 2;
            break;
        case 32: /* dst = (u32) cpu_to_be32(dst) */
-           /* llgfr %dst,%dst */
-           EMIT4(0xb9160000, dst_reg, dst_reg);
+           if (!fp->aux->verifier_zext)
+               /* llgfr %dst,%dst */
+               EMIT4(0xb9160000, dst_reg, dst_reg);
            break;
        case 64: /* dst = (u64) cpu_to_be64(dst) */
            break;
@@ -882,12 +895,15 @@ static noinline int bpf_jit_insn(struct bpf_jit *jit, struct bpf_prog *fp, int i
            EMIT4_DISP(0x88000000, dst_reg, REG_0, 16);
            /* llghr %dst,%dst */
            EMIT4(0xb9850000, dst_reg, dst_reg);
+           if (insn_is_zext(&insn[1]))
+               insn_count = 2;
            break;
        case 32: /* dst = (u32) cpu_to_le32(dst) */
            /* lrvr %dst,%dst */
            EMIT4(0xb91f0000, dst_reg, dst_reg);
-           /* llgfr %dst,%dst */
-           EMIT4(0xb9160000, dst_reg, dst_reg);
+           if (!fp->aux->verifier_zext)
+               /* llgfr %dst,%dst */
+               EMIT4(0xb9160000, dst_reg, dst_reg);
            break;
        case 64: /* dst = (u64) cpu_to_le64(dst) */
            /* lrvgr %dst,%dst */
@@ -968,16 +984,22 @@ static noinline int bpf_jit_insn(struct bpf_jit *jit, struct bpf_prog *fp, int i
        /* llgc %dst,0(off,%src) */
        EMIT6_DISP_LH(0xe3000000, 0x0090, dst_reg, src_reg, REG_0, off);
        jit->seen |= SEEN_MEM;
+       if (insn_is_zext(&insn[1]))
+           insn_count = 2;
        break;
    case BPF_LDX | BPF_MEM | BPF_H: /* dst = *(u16 *)(ul) (src + off) */
        /* llgh %dst,0(off,%src) */
        EMIT6_DISP_LH(0xe3000000, 0x0091, dst_reg, src_reg, REG_0, off);
        jit->seen |= SEEN_MEM;
+       if (insn_is_zext(&insn[1]))
+           insn_count = 2;
        break;
    case BPF_LDX | BPF_MEM | BPF_W: /* dst = *(u32 *)(ul) (src + off) */
        /* llgf %dst,off(%src) */
        jit->seen |= SEEN_MEM;
        EMIT6_DISP_LH(0xe3000000, 0x0016, dst_reg, src_reg, REG_0, off);
+       if (insn_is_zext(&insn[1]))
+           insn_count = 2;
        break;
    case BPF_LDX | BPF_MEM | BPF_DW: /* dst = *(u64 *)(ul) (src + off) */
        /* lg %dst,0(off,%src) */
@@ -1282,6 +1304,11 @@ static int bpf_jit_prog(struct bpf_jit *jit, struct bpf_prog *fp)
    return 0;
 }

+bool bpf_jit_needs_zext(void)
+{
+   return true;
+}
+
 /*
  * Compile eBPF program "fp"
  */

Leave a Reply

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