s390/bpf: Implement BPF_MOV | BPF_X with sign-extension
authorIlya Leoshkevich <iii@linux.ibm.com>
Tue, 19 Sep 2023 10:09:06 +0000 (12:09 +0200)
committerAlexei Starovoitov <ast@kernel.org>
Thu, 21 Sep 2023 21:21:59 +0000 (14:21 -0700)
Implement the cpuv4 register-to-register move with sign extension. It
is distinguished from the normal moves by non-zero values in
insn->off, which determine the source size. s390x has instructions to
deal with all of them: lbr, lhr, lgbr, lghr and lgfr.

Signed-off-by: Ilya Leoshkevich <iii@linux.ibm.com>
Link: https://lore.kernel.org/r/20230919101336.2223655-5-iii@linux.ibm.com
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
arch/s390/net/bpf_jit_comp.c

index eeb42e5cd7d6d0ee0f71c480a0db600251518d13..6fb24ebb36187ee63cd421ffaba71aca8304d357 100644 (file)
@@ -795,15 +795,47 @@ static noinline int bpf_jit_insn(struct bpf_jit *jit, struct bpf_prog *fp,
        /*
         * BPF_MOV
         */
-       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;
+       case BPF_ALU | BPF_MOV | BPF_X:
+               switch (insn->off) {
+               case 0: /* DST = (u32) SRC */
+                       /* llgfr %dst,%src */
+                       EMIT4(0xb9160000, dst_reg, src_reg);
+                       if (insn_is_zext(&insn[1]))
+                               insn_count = 2;
+                       break;
+               case 8: /* DST = (u32)(s8) SRC */
+                       /* lbr %dst,%src */
+                       EMIT4(0xb9260000, dst_reg, src_reg);
+                       /* llgfr %dst,%dst */
+                       EMIT4(0xb9160000, dst_reg, dst_reg);
+                       break;
+               case 16: /* DST = (u32)(s16) SRC */
+                       /* lhr %dst,%src */
+                       EMIT4(0xb9270000, dst_reg, src_reg);
+                       /* llgfr %dst,%dst */
+                       EMIT4(0xb9160000, dst_reg, dst_reg);
+                       break;
+               }
                break;
-       case BPF_ALU64 | BPF_MOV | BPF_X: /* dst = src */
-               /* lgr %dst,%src */
-               EMIT4(0xb9040000, dst_reg, src_reg);
+       case BPF_ALU64 | BPF_MOV | BPF_X:
+               switch (insn->off) {
+               case 0: /* DST = SRC */
+                       /* lgr %dst,%src */
+                       EMIT4(0xb9040000, dst_reg, src_reg);
+                       break;
+               case 8: /* DST = (s8) SRC */
+                       /* lgbr %dst,%src */
+                       EMIT4(0xb9060000, dst_reg, src_reg);
+                       break;
+               case 16: /* DST = (s16) SRC */
+                       /* lghr %dst,%src */
+                       EMIT4(0xb9070000, dst_reg, src_reg);
+                       break;
+               case 32: /* DST = (s32) SRC */
+                       /* lgfr %dst,%src */
+                       EMIT4(0xb9140000, dst_reg, src_reg);
+                       break;
+               }
                break;
        case BPF_ALU | BPF_MOV | BPF_K: /* dst = (u32) imm */
                /* llilf %dst,imm */