| From db7bee653859ef7179be933e7d1384644f795f26 Mon Sep 17 00:00:00 2001 |
| From: Ilya Leoshkevich <iii@linux.ibm.com> |
| Date: Mon, 6 Sep 2021 15:04:14 +0200 |
| Subject: s390/bpf: Fix optimizing out zero-extensions |
| |
| From: Ilya Leoshkevich <iii@linux.ibm.com> |
| |
| commit db7bee653859ef7179be933e7d1384644f795f26 upstream. |
| |
| Currently the JIT completely removes things like `reg32 += 0`, |
| however, the BPF_ALU semantics requires the target register to be |
| zero-extended in such cases. |
| |
| Fix by optimizing out only the arithmetic operation, but not the |
| subsequent zero-extension. |
| |
| Reported-by: Johan Almbladh <johan.almbladh@anyfinetworks.com> |
| Fixes: 054623105728 ("s390/bpf: Add s390x eBPF JIT compiler backend") |
| Reviewed-by: Heiko Carstens <hca@linux.ibm.com> |
| Signed-off-by: Ilya Leoshkevich <iii@linux.ibm.com> |
| Signed-off-by: Vasily Gorbik <gor@linux.ibm.com> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| |
| --- |
| arch/s390/net/bpf_jit_comp.c | 50 ++++++++++++++++++++++--------------------- |
| 1 file changed, 26 insertions(+), 24 deletions(-) |
| |
| --- a/arch/s390/net/bpf_jit_comp.c |
| +++ b/arch/s390/net/bpf_jit_comp.c |
| @@ -561,10 +561,10 @@ static noinline int bpf_jit_insn(struct |
| EMIT4(0xb9080000, dst_reg, src_reg); |
| break; |
| case BPF_ALU | BPF_ADD | BPF_K: /* dst = (u32) dst + (u32) imm */ |
| - if (!imm) |
| - break; |
| - /* alfi %dst,imm */ |
| - EMIT6_IMM(0xc20b0000, dst_reg, imm); |
| + if (imm != 0) { |
| + /* alfi %dst,imm */ |
| + EMIT6_IMM(0xc20b0000, dst_reg, imm); |
| + } |
| EMIT_ZERO(dst_reg); |
| break; |
| case BPF_ALU64 | BPF_ADD | BPF_K: /* dst = dst + imm */ |
| @@ -586,10 +586,10 @@ static noinline int bpf_jit_insn(struct |
| EMIT4(0xb9090000, dst_reg, src_reg); |
| break; |
| case BPF_ALU | BPF_SUB | BPF_K: /* dst = (u32) dst - (u32) imm */ |
| - if (!imm) |
| - break; |
| - /* alfi %dst,-imm */ |
| - EMIT6_IMM(0xc20b0000, dst_reg, -imm); |
| + if (imm != 0) { |
| + /* alfi %dst,-imm */ |
| + EMIT6_IMM(0xc20b0000, dst_reg, -imm); |
| + } |
| EMIT_ZERO(dst_reg); |
| break; |
| case BPF_ALU64 | BPF_SUB | BPF_K: /* dst = dst - imm */ |
| @@ -616,10 +616,10 @@ static noinline int bpf_jit_insn(struct |
| EMIT4(0xb90c0000, dst_reg, src_reg); |
| break; |
| case BPF_ALU | BPF_MUL | BPF_K: /* dst = (u32) dst * (u32) imm */ |
| - if (imm == 1) |
| - break; |
| - /* msfi %r5,imm */ |
| - EMIT6_IMM(0xc2010000, dst_reg, imm); |
| + if (imm != 1) { |
| + /* msfi %r5,imm */ |
| + EMIT6_IMM(0xc2010000, dst_reg, imm); |
| + } |
| EMIT_ZERO(dst_reg); |
| break; |
| case BPF_ALU64 | BPF_MUL | BPF_K: /* dst = dst * imm */ |
| @@ -670,6 +670,8 @@ static noinline int bpf_jit_insn(struct |
| if (BPF_OP(insn->code) == BPF_MOD) |
| /* lhgi %dst,0 */ |
| EMIT4_IMM(0xa7090000, dst_reg, 0); |
| + else |
| + EMIT_ZERO(dst_reg); |
| break; |
| } |
| /* lhi %w0,0 */ |
| @@ -762,10 +764,10 @@ static noinline int bpf_jit_insn(struct |
| EMIT4(0xb9820000, dst_reg, src_reg); |
| break; |
| case BPF_ALU | BPF_XOR | BPF_K: /* dst = (u32) dst ^ (u32) imm */ |
| - if (!imm) |
| - break; |
| - /* xilf %dst,imm */ |
| - EMIT6_IMM(0xc0070000, dst_reg, imm); |
| + if (imm != 0) { |
| + /* xilf %dst,imm */ |
| + EMIT6_IMM(0xc0070000, dst_reg, imm); |
| + } |
| EMIT_ZERO(dst_reg); |
| break; |
| case BPF_ALU64 | BPF_XOR | BPF_K: /* dst = dst ^ imm */ |
| @@ -786,10 +788,10 @@ static noinline int bpf_jit_insn(struct |
| EMIT6_DISP_LH(0xeb000000, 0x000d, dst_reg, dst_reg, src_reg, 0); |
| break; |
| case BPF_ALU | BPF_LSH | BPF_K: /* dst = (u32) dst << (u32) imm */ |
| - if (imm == 0) |
| - break; |
| - /* sll %dst,imm(%r0) */ |
| - EMIT4_DISP(0x89000000, dst_reg, REG_0, imm); |
| + if (imm != 0) { |
| + /* sll %dst,imm(%r0) */ |
| + EMIT4_DISP(0x89000000, dst_reg, REG_0, imm); |
| + } |
| EMIT_ZERO(dst_reg); |
| break; |
| case BPF_ALU64 | BPF_LSH | BPF_K: /* dst = dst << imm */ |
| @@ -811,10 +813,10 @@ static noinline int bpf_jit_insn(struct |
| EMIT6_DISP_LH(0xeb000000, 0x000c, dst_reg, dst_reg, src_reg, 0); |
| break; |
| case BPF_ALU | BPF_RSH | BPF_K: /* dst = (u32) dst >> (u32) imm */ |
| - if (imm == 0) |
| - break; |
| - /* srl %dst,imm(%r0) */ |
| - EMIT4_DISP(0x88000000, dst_reg, REG_0, imm); |
| + if (imm != 0) { |
| + /* srl %dst,imm(%r0) */ |
| + EMIT4_DISP(0x88000000, dst_reg, REG_0, imm); |
| + } |
| EMIT_ZERO(dst_reg); |
| break; |
| case BPF_ALU64 | BPF_RSH | BPF_K: /* dst = dst >> imm */ |