diff options
Diffstat (limited to 'arch/s390/net/bpf_jit_comp.c')
| -rw-r--r-- | arch/s390/net/bpf_jit_comp.c | 72 | 
1 files changed, 39 insertions, 33 deletions
| diff --git a/arch/s390/net/bpf_jit_comp.c b/arch/s390/net/bpf_jit_comp.c index 88419263a89a..1a374d021e25 100644 --- a/arch/s390/net/bpf_jit_comp.c +++ b/arch/s390/net/bpf_jit_comp.c @@ -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)		\  ({								\ -	/* Branch instruction needs 6 bytes */			\ -	int rel = (addrs[(i) + (off) + 1] - (addrs[(i) + 1] - 6)) / 2;\ +	int rel = (addrs[(i) + (off) + 1] - jit->prg) / 2;	\  	_EMIT6((op1) | reg(b1, b2) << 16 | (rel & 0xffff), (op2) | (mask));\  	REG_SET_SEEN(b1);					\  	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);  		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 */ @@ -786,17 +785,22 @@ static noinline int bpf_jit_insn(struct bpf_jit *jit, struct bpf_prog *fp,  		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 */  		if (!imm)  			break; -		/* agfi %dst,-imm */ -		EMIT6_IMM(0xc2080000, dst_reg, -imm); +		if (imm == -0x80000000) { +			/* algfi %dst,0x80000000 */ +			EMIT6_IMM(0xc20a0000, dst_reg, 0x80000000); +		} else { +			/* agfi %dst,-imm */ +			EMIT6_IMM(0xc2080000, dst_reg, -imm); +		}  		break;  	/*  	 * 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);  		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 */ @@ -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)  				/* lhgi %dst,0 */  				EMIT4_IMM(0xa7090000, dst_reg, 0); +			else +				EMIT_ZERO(dst_reg);  			break;  		}  		/* 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);  		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 */ @@ -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);  		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 */ @@ -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);  		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 */ @@ -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);  		break;  	case BPF_ALU | BPF_ARSH | BPF_K: /* ((s32) dst >> imm */ -		if (imm == 0) -			break; -		/* sra %dst,imm(%r0) */ -		EMIT4_DISP(0x8a000000, dst_reg, REG_0, imm); +		if (imm != 0) { +			/* sra %dst,imm(%r0) */ +			EMIT4_DISP(0x8a000000, dst_reg, REG_0, imm); +		}  		EMIT_ZERO(dst_reg);  		break;  	case BPF_ALU64 | BPF_ARSH | BPF_K: /* ((s64) dst) >>= imm */ @@ -1820,7 +1826,7 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *fp)  	jit.addrs = kvcalloc(fp->len + 1, sizeof(*jit.addrs), GFP_KERNEL);  	if (jit.addrs == NULL) {  		fp = orig_fp; -		goto out; +		goto free_addrs;  	}  	/*  	 * Three initial passes: |