Commit 92477dd1 authored by Linus Torvalds's avatar Linus Torvalds
Browse files

Merge tag 's390-5.15-ebpf-jit-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/s390/linux

Pull s390 eBPF fixes from Vasily Gorbik:
 "Johan Almbladh has implemented a number of new testcases for eBPF [1],
  which uncovered three miscompilation issues in the s390 eBPF JIT"

Link: https://lore.kernel.org/bpf/20210902185229.1840281-1-johan.almbladh@anyfinetworks.com/ [1]

* tag 's390-5.15-ebpf-jit-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/s390/linux:
  s390/bpf: Fix optimizing out zero-extensions
  s390/bpf: Fix 64-bit subtraction of the -0x80000000 constant
  s390/bpf: Fix branch shortening during codegen pass
parents d5f65459 db7bee65
Loading
Loading
Loading
Loading
+38 −32
Original line number Original line Diff line number Diff line
@@ -248,8 +248,7 @@ static inline void reg_set_seen(struct bpf_jit *jit, u32 b1)


#define EMIT6_PCREL(op1, op2, b1, b2, i, off, mask)		\
#define EMIT6_PCREL(op1, op2, b1, b2, i, off, mask)		\
({								\
({								\
	/* Branch instruction needs 6 bytes */			\
	int rel = (addrs[(i) + (off) + 1] - jit->prg) / 2;	\
	int rel = (addrs[(i) + (off) + 1] - (addrs[(i) + 1] - 6)) / 2;\
	_EMIT6((op1) | reg(b1, b2) << 16 | (rel & 0xffff), (op2) | (mask));\
	_EMIT6((op1) | reg(b1, b2) << 16 | (rel & 0xffff), (op2) | (mask));\
	REG_SET_SEEN(b1);					\
	REG_SET_SEEN(b1);					\
	REG_SET_SEEN(b2);					\
	REG_SET_SEEN(b2);					\
@@ -761,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 */
@@ -786,17 +785,22 @@ 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 */
		if (!imm)
		if (!imm)
			break;
			break;
		if (imm == -0x80000000) {
			/* algfi %dst,0x80000000 */
			EMIT6_IMM(0xc20a0000, dst_reg, 0x80000000);
		} else {
			/* agfi %dst,-imm */
			/* agfi %dst,-imm */
			EMIT6_IMM(0xc2080000, dst_reg, -imm);
			EMIT6_IMM(0xc2080000, dst_reg, -imm);
		}
		break;
		break;
	/*
	/*
	 * BPF_MUL
	 * BPF_MUL
@@ -811,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 */
@@ -867,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 */
@@ -999,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 */
@@ -1033,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 */
@@ -1058,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 */
@@ -1083,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 */