Commit db7bee65 authored by Ilya Leoshkevich's avatar Ilya Leoshkevich Committed by Vasily Gorbik

s390/bpf: Fix optimizing out zero-extensions

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: default avatarJohan Almbladh <johan.almbladh@anyfinetworks.com>
Fixes: 05462310 ("s390/bpf: Add s390x eBPF JIT compiler backend")
Reviewed-by: default avatarHeiko Carstens <hca@linux.ibm.com>
Signed-off-by: default avatarIlya Leoshkevich <iii@linux.ibm.com>
Signed-off-by: default avatarVasily Gorbik <gor@linux.ibm.com>
parent 6e61dc9d
...@@ -760,10 +760,10 @@ static noinline int bpf_jit_insn(struct bpf_jit *jit, struct bpf_prog *fp, ...@@ -760,10 +760,10 @@ static noinline int bpf_jit_insn(struct bpf_jit *jit, struct bpf_prog *fp,
EMIT4(0xb9080000, dst_reg, src_reg); EMIT4(0xb9080000, dst_reg, src_reg);
break; break;
case BPF_ALU | BPF_ADD | BPF_K: /* dst = (u32) dst + (u32) imm */ case BPF_ALU | BPF_ADD | BPF_K: /* dst = (u32) dst + (u32) imm */
if (!imm) if (imm != 0) {
break; /* alfi %dst,imm */
/* alfi %dst,imm */ EMIT6_IMM(0xc20b0000, dst_reg, imm);
EMIT6_IMM(0xc20b0000, dst_reg, imm); }
EMIT_ZERO(dst_reg); EMIT_ZERO(dst_reg);
break; break;
case BPF_ALU64 | BPF_ADD | BPF_K: /* dst = dst + imm */ case BPF_ALU64 | BPF_ADD | BPF_K: /* dst = dst + imm */
...@@ -785,10 +785,10 @@ static noinline int bpf_jit_insn(struct bpf_jit *jit, struct bpf_prog *fp, ...@@ -785,10 +785,10 @@ static noinline int bpf_jit_insn(struct bpf_jit *jit, struct bpf_prog *fp,
EMIT4(0xb9090000, dst_reg, src_reg); EMIT4(0xb9090000, dst_reg, src_reg);
break; break;
case BPF_ALU | BPF_SUB | BPF_K: /* dst = (u32) dst - (u32) imm */ case BPF_ALU | BPF_SUB | BPF_K: /* dst = (u32) dst - (u32) imm */
if (!imm) if (imm != 0) {
break; /* alfi %dst,-imm */
/* alfi %dst,-imm */ EMIT6_IMM(0xc20b0000, dst_reg, -imm);
EMIT6_IMM(0xc20b0000, dst_reg, -imm); }
EMIT_ZERO(dst_reg); EMIT_ZERO(dst_reg);
break; break;
case BPF_ALU64 | BPF_SUB | BPF_K: /* dst = dst - imm */ case BPF_ALU64 | BPF_SUB | BPF_K: /* dst = dst - imm */
...@@ -815,10 +815,10 @@ static noinline int bpf_jit_insn(struct bpf_jit *jit, struct bpf_prog *fp, ...@@ -815,10 +815,10 @@ static noinline int bpf_jit_insn(struct bpf_jit *jit, struct bpf_prog *fp,
EMIT4(0xb90c0000, dst_reg, src_reg); EMIT4(0xb90c0000, dst_reg, src_reg);
break; break;
case BPF_ALU | BPF_MUL | BPF_K: /* dst = (u32) dst * (u32) imm */ case BPF_ALU | BPF_MUL | BPF_K: /* dst = (u32) dst * (u32) imm */
if (imm == 1) if (imm != 1) {
break; /* msfi %r5,imm */
/* msfi %r5,imm */ EMIT6_IMM(0xc2010000, dst_reg, imm);
EMIT6_IMM(0xc2010000, dst_reg, imm); }
EMIT_ZERO(dst_reg); EMIT_ZERO(dst_reg);
break; break;
case BPF_ALU64 | BPF_MUL | BPF_K: /* dst = dst * imm */ case BPF_ALU64 | BPF_MUL | BPF_K: /* dst = dst * imm */
...@@ -871,6 +871,8 @@ static noinline int bpf_jit_insn(struct bpf_jit *jit, struct bpf_prog *fp, ...@@ -871,6 +871,8 @@ static noinline int bpf_jit_insn(struct bpf_jit *jit, struct bpf_prog *fp,
if (BPF_OP(insn->code) == BPF_MOD) if (BPF_OP(insn->code) == BPF_MOD)
/* lhgi %dst,0 */ /* lhgi %dst,0 */
EMIT4_IMM(0xa7090000, dst_reg, 0); EMIT4_IMM(0xa7090000, dst_reg, 0);
else
EMIT_ZERO(dst_reg);
break; break;
} }
/* lhi %w0,0 */ /* lhi %w0,0 */
...@@ -1003,10 +1005,10 @@ static noinline int bpf_jit_insn(struct bpf_jit *jit, struct bpf_prog *fp, ...@@ -1003,10 +1005,10 @@ static noinline int bpf_jit_insn(struct bpf_jit *jit, struct bpf_prog *fp,
EMIT4(0xb9820000, dst_reg, src_reg); EMIT4(0xb9820000, dst_reg, src_reg);
break; break;
case BPF_ALU | BPF_XOR | BPF_K: /* dst = (u32) dst ^ (u32) imm */ case BPF_ALU | BPF_XOR | BPF_K: /* dst = (u32) dst ^ (u32) imm */
if (!imm) if (imm != 0) {
break; /* xilf %dst,imm */
/* xilf %dst,imm */ EMIT6_IMM(0xc0070000, dst_reg, imm);
EMIT6_IMM(0xc0070000, dst_reg, imm); }
EMIT_ZERO(dst_reg); EMIT_ZERO(dst_reg);
break; break;
case BPF_ALU64 | BPF_XOR | BPF_K: /* dst = dst ^ imm */ case BPF_ALU64 | BPF_XOR | BPF_K: /* dst = dst ^ imm */
...@@ -1037,10 +1039,10 @@ static noinline int bpf_jit_insn(struct bpf_jit *jit, struct bpf_prog *fp, ...@@ -1037,10 +1039,10 @@ static noinline int bpf_jit_insn(struct bpf_jit *jit, struct bpf_prog *fp,
EMIT6_DISP_LH(0xeb000000, 0x000d, dst_reg, dst_reg, src_reg, 0); EMIT6_DISP_LH(0xeb000000, 0x000d, dst_reg, dst_reg, src_reg, 0);
break; break;
case BPF_ALU | BPF_LSH | BPF_K: /* dst = (u32) dst << (u32) imm */ case BPF_ALU | BPF_LSH | BPF_K: /* dst = (u32) dst << (u32) imm */
if (imm == 0) if (imm != 0) {
break; /* sll %dst,imm(%r0) */
/* sll %dst,imm(%r0) */ EMIT4_DISP(0x89000000, dst_reg, REG_0, imm);
EMIT4_DISP(0x89000000, dst_reg, REG_0, imm); }
EMIT_ZERO(dst_reg); EMIT_ZERO(dst_reg);
break; break;
case BPF_ALU64 | BPF_LSH | BPF_K: /* dst = dst << imm */ case BPF_ALU64 | BPF_LSH | BPF_K: /* dst = dst << imm */
...@@ -1062,10 +1064,10 @@ static noinline int bpf_jit_insn(struct bpf_jit *jit, struct bpf_prog *fp, ...@@ -1062,10 +1064,10 @@ static noinline int bpf_jit_insn(struct bpf_jit *jit, struct bpf_prog *fp,
EMIT6_DISP_LH(0xeb000000, 0x000c, dst_reg, dst_reg, src_reg, 0); EMIT6_DISP_LH(0xeb000000, 0x000c, dst_reg, dst_reg, src_reg, 0);
break; break;
case BPF_ALU | BPF_RSH | BPF_K: /* dst = (u32) dst >> (u32) imm */ case BPF_ALU | BPF_RSH | BPF_K: /* dst = (u32) dst >> (u32) imm */
if (imm == 0) if (imm != 0) {
break; /* srl %dst,imm(%r0) */
/* srl %dst,imm(%r0) */ EMIT4_DISP(0x88000000, dst_reg, REG_0, imm);
EMIT4_DISP(0x88000000, dst_reg, REG_0, imm); }
EMIT_ZERO(dst_reg); EMIT_ZERO(dst_reg);
break; break;
case BPF_ALU64 | BPF_RSH | BPF_K: /* dst = dst >> imm */ case BPF_ALU64 | BPF_RSH | BPF_K: /* dst = dst >> imm */
...@@ -1087,10 +1089,10 @@ static noinline int bpf_jit_insn(struct bpf_jit *jit, struct bpf_prog *fp, ...@@ -1087,10 +1089,10 @@ static noinline int bpf_jit_insn(struct bpf_jit *jit, struct bpf_prog *fp,
EMIT6_DISP_LH(0xeb000000, 0x000a, dst_reg, dst_reg, src_reg, 0); EMIT6_DISP_LH(0xeb000000, 0x000a, dst_reg, dst_reg, src_reg, 0);
break; break;
case BPF_ALU | BPF_ARSH | BPF_K: /* ((s32) dst >> imm */ case BPF_ALU | BPF_ARSH | BPF_K: /* ((s32) dst >> imm */
if (imm == 0) if (imm != 0) {
break; /* sra %dst,imm(%r0) */
/* sra %dst,imm(%r0) */ EMIT4_DISP(0x8a000000, dst_reg, REG_0, imm);
EMIT4_DISP(0x8a000000, dst_reg, REG_0, imm); }
EMIT_ZERO(dst_reg); EMIT_ZERO(dst_reg);
break; break;
case BPF_ALU64 | BPF_ARSH | BPF_K: /* ((s64) dst) >>= imm */ case BPF_ALU64 | BPF_ARSH | BPF_K: /* ((s64) dst) >>= imm */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment