Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 078295fb authored by David S. Miller's avatar David S. Miller
Browse files

Merge branch 'bpf-new-branches'



Daniel Borkmann says:

====================
bpf: Add BPF_J{LT,LE,SLT,SLE} instructions

This set adds BPF_J{LT,LE,SLT,SLE} instructions to the BPF
insn set, interpreter, JIT hardening code and all JITs are
also updated to support the new instructions. Basic idea is
to reduce register pressure by avoiding BPF_J{GT,GE,SGT,SGE}
rewrites. Removing the workaround for the rewrites in LLVM,
this can result in shorter BPF programs, less stack usage
and less verification complexity. First patch provides some
more details on rationale and integration.

Thanks a lot!

v1 -> v2:
  - Reworded commit msg in patch 1
====================

Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 0bdf7101 31e482bf
Loading
Loading
Loading
Loading
+4 −0
Original line number Original line Diff line number Diff line
@@ -906,6 +906,10 @@ If BPF_CLASS(code) == BPF_JMP, BPF_OP(code) is one of:
  BPF_JSGE  0x70  /* eBPF only: signed '>=' */
  BPF_JSGE  0x70  /* eBPF only: signed '>=' */
  BPF_CALL  0x80  /* eBPF only: function call */
  BPF_CALL  0x80  /* eBPF only: function call */
  BPF_EXIT  0x90  /* eBPF only: function return */
  BPF_EXIT  0x90  /* eBPF only: function return */
  BPF_JLT   0xa0  /* eBPF only: unsigned '<' */
  BPF_JLE   0xb0  /* eBPF only: unsigned '<=' */
  BPF_JSLT  0xc0  /* eBPF only: signed '<' */
  BPF_JSLE  0xd0  /* eBPF only: signed '<=' */


So BPF_ADD | BPF_X | BPF_ALU means 32-bit addition in both classic BPF
So BPF_ADD | BPF_X | BPF_ALU means 32-bit addition in both classic BPF
and eBPF. There are only two registers in classic BPF, so it means A += X.
and eBPF. There are only two registers in classic BPF, so it means A += X.
+4 −0
Original line number Original line Diff line number Diff line
@@ -44,8 +44,12 @@
#define A64_COND_NE	AARCH64_INSN_COND_NE /* != */
#define A64_COND_NE	AARCH64_INSN_COND_NE /* != */
#define A64_COND_CS	AARCH64_INSN_COND_CS /* unsigned >= */
#define A64_COND_CS	AARCH64_INSN_COND_CS /* unsigned >= */
#define A64_COND_HI	AARCH64_INSN_COND_HI /* unsigned > */
#define A64_COND_HI	AARCH64_INSN_COND_HI /* unsigned > */
#define A64_COND_LS	AARCH64_INSN_COND_LS /* unsigned <= */
#define A64_COND_CC	AARCH64_INSN_COND_CC /* unsigned < */
#define A64_COND_GE	AARCH64_INSN_COND_GE /* signed >= */
#define A64_COND_GE	AARCH64_INSN_COND_GE /* signed >= */
#define A64_COND_GT	AARCH64_INSN_COND_GT /* signed > */
#define A64_COND_GT	AARCH64_INSN_COND_GT /* signed > */
#define A64_COND_LE	AARCH64_INSN_COND_LE /* signed <= */
#define A64_COND_LT	AARCH64_INSN_COND_LT /* signed < */
#define A64_B_(cond, imm19) A64_COND_BRANCH(cond, (imm19) << 2)
#define A64_B_(cond, imm19) A64_COND_BRANCH(cond, (imm19) << 2)


/* Unconditional branch (immediate) */
/* Unconditional branch (immediate) */
+20 −0
Original line number Original line Diff line number Diff line
@@ -527,10 +527,14 @@ static int build_insn(const struct bpf_insn *insn, struct jit_ctx *ctx)
	/* IF (dst COND src) JUMP off */
	/* IF (dst COND src) JUMP off */
	case BPF_JMP | BPF_JEQ | BPF_X:
	case BPF_JMP | BPF_JEQ | BPF_X:
	case BPF_JMP | BPF_JGT | BPF_X:
	case BPF_JMP | BPF_JGT | BPF_X:
	case BPF_JMP | BPF_JLT | BPF_X:
	case BPF_JMP | BPF_JGE | BPF_X:
	case BPF_JMP | BPF_JGE | BPF_X:
	case BPF_JMP | BPF_JLE | BPF_X:
	case BPF_JMP | BPF_JNE | BPF_X:
	case BPF_JMP | BPF_JNE | BPF_X:
	case BPF_JMP | BPF_JSGT | BPF_X:
	case BPF_JMP | BPF_JSGT | BPF_X:
	case BPF_JMP | BPF_JSLT | BPF_X:
	case BPF_JMP | BPF_JSGE | BPF_X:
	case BPF_JMP | BPF_JSGE | BPF_X:
	case BPF_JMP | BPF_JSLE | BPF_X:
		emit(A64_CMP(1, dst, src), ctx);
		emit(A64_CMP(1, dst, src), ctx);
emit_cond_jmp:
emit_cond_jmp:
		jmp_offset = bpf2a64_offset(i + off, i, ctx);
		jmp_offset = bpf2a64_offset(i + off, i, ctx);
@@ -542,9 +546,15 @@ static int build_insn(const struct bpf_insn *insn, struct jit_ctx *ctx)
		case BPF_JGT:
		case BPF_JGT:
			jmp_cond = A64_COND_HI;
			jmp_cond = A64_COND_HI;
			break;
			break;
		case BPF_JLT:
			jmp_cond = A64_COND_CC;
			break;
		case BPF_JGE:
		case BPF_JGE:
			jmp_cond = A64_COND_CS;
			jmp_cond = A64_COND_CS;
			break;
			break;
		case BPF_JLE:
			jmp_cond = A64_COND_LS;
			break;
		case BPF_JSET:
		case BPF_JSET:
		case BPF_JNE:
		case BPF_JNE:
			jmp_cond = A64_COND_NE;
			jmp_cond = A64_COND_NE;
@@ -552,9 +562,15 @@ static int build_insn(const struct bpf_insn *insn, struct jit_ctx *ctx)
		case BPF_JSGT:
		case BPF_JSGT:
			jmp_cond = A64_COND_GT;
			jmp_cond = A64_COND_GT;
			break;
			break;
		case BPF_JSLT:
			jmp_cond = A64_COND_LT;
			break;
		case BPF_JSGE:
		case BPF_JSGE:
			jmp_cond = A64_COND_GE;
			jmp_cond = A64_COND_GE;
			break;
			break;
		case BPF_JSLE:
			jmp_cond = A64_COND_LE;
			break;
		default:
		default:
			return -EFAULT;
			return -EFAULT;
		}
		}
@@ -566,10 +582,14 @@ static int build_insn(const struct bpf_insn *insn, struct jit_ctx *ctx)
	/* IF (dst COND imm) JUMP off */
	/* IF (dst COND imm) JUMP off */
	case BPF_JMP | BPF_JEQ | BPF_K:
	case BPF_JMP | BPF_JEQ | BPF_K:
	case BPF_JMP | BPF_JGT | BPF_K:
	case BPF_JMP | BPF_JGT | BPF_K:
	case BPF_JMP | BPF_JLT | BPF_K:
	case BPF_JMP | BPF_JGE | BPF_K:
	case BPF_JMP | BPF_JGE | BPF_K:
	case BPF_JMP | BPF_JLE | BPF_K:
	case BPF_JMP | BPF_JNE | BPF_K:
	case BPF_JMP | BPF_JNE | BPF_K:
	case BPF_JMP | BPF_JSGT | BPF_K:
	case BPF_JMP | BPF_JSGT | BPF_K:
	case BPF_JMP | BPF_JSLT | BPF_K:
	case BPF_JMP | BPF_JSGE | BPF_K:
	case BPF_JMP | BPF_JSGE | BPF_K:
	case BPF_JMP | BPF_JSLE | BPF_K:
		emit_a64_mov_i(1, tmp, imm, ctx);
		emit_a64_mov_i(1, tmp, imm, ctx);
		emit(A64_CMP(1, dst, tmp), ctx);
		emit(A64_CMP(1, dst, tmp), ctx);
		goto emit_cond_jmp;
		goto emit_cond_jmp;
+1 −0
Original line number Original line Diff line number Diff line
@@ -263,6 +263,7 @@ static inline bool is_nearbranch(int offset)
#define COND_EQ		(CR0_EQ | COND_CMP_TRUE)
#define COND_EQ		(CR0_EQ | COND_CMP_TRUE)
#define COND_NE		(CR0_EQ | COND_CMP_FALSE)
#define COND_NE		(CR0_EQ | COND_CMP_FALSE)
#define COND_LT		(CR0_LT | COND_CMP_TRUE)
#define COND_LT		(CR0_LT | COND_CMP_TRUE)
#define COND_LE		(CR0_GT | COND_CMP_FALSE)


#endif
#endif


+20 −0
Original line number Original line Diff line number Diff line
@@ -795,12 +795,24 @@ static int bpf_jit_build_body(struct bpf_prog *fp, u32 *image,
		case BPF_JMP | BPF_JSGT | BPF_X:
		case BPF_JMP | BPF_JSGT | BPF_X:
			true_cond = COND_GT;
			true_cond = COND_GT;
			goto cond_branch;
			goto cond_branch;
		case BPF_JMP | BPF_JLT | BPF_K:
		case BPF_JMP | BPF_JLT | BPF_X:
		case BPF_JMP | BPF_JSLT | BPF_K:
		case BPF_JMP | BPF_JSLT | BPF_X:
			true_cond = COND_LT;
			goto cond_branch;
		case BPF_JMP | BPF_JGE | BPF_K:
		case BPF_JMP | BPF_JGE | BPF_K:
		case BPF_JMP | BPF_JGE | BPF_X:
		case BPF_JMP | BPF_JGE | BPF_X:
		case BPF_JMP | BPF_JSGE | BPF_K:
		case BPF_JMP | BPF_JSGE | BPF_K:
		case BPF_JMP | BPF_JSGE | BPF_X:
		case BPF_JMP | BPF_JSGE | BPF_X:
			true_cond = COND_GE;
			true_cond = COND_GE;
			goto cond_branch;
			goto cond_branch;
		case BPF_JMP | BPF_JLE | BPF_K:
		case BPF_JMP | BPF_JLE | BPF_X:
		case BPF_JMP | BPF_JSLE | BPF_K:
		case BPF_JMP | BPF_JSLE | BPF_X:
			true_cond = COND_LE;
			goto cond_branch;
		case BPF_JMP | BPF_JEQ | BPF_K:
		case BPF_JMP | BPF_JEQ | BPF_K:
		case BPF_JMP | BPF_JEQ | BPF_X:
		case BPF_JMP | BPF_JEQ | BPF_X:
			true_cond = COND_EQ;
			true_cond = COND_EQ;
@@ -817,14 +829,18 @@ static int bpf_jit_build_body(struct bpf_prog *fp, u32 *image,
cond_branch:
cond_branch:
			switch (code) {
			switch (code) {
			case BPF_JMP | BPF_JGT | BPF_X:
			case BPF_JMP | BPF_JGT | BPF_X:
			case BPF_JMP | BPF_JLT | BPF_X:
			case BPF_JMP | BPF_JGE | BPF_X:
			case BPF_JMP | BPF_JGE | BPF_X:
			case BPF_JMP | BPF_JLE | BPF_X:
			case BPF_JMP | BPF_JEQ | BPF_X:
			case BPF_JMP | BPF_JEQ | BPF_X:
			case BPF_JMP | BPF_JNE | BPF_X:
			case BPF_JMP | BPF_JNE | BPF_X:
				/* unsigned comparison */
				/* unsigned comparison */
				PPC_CMPLD(dst_reg, src_reg);
				PPC_CMPLD(dst_reg, src_reg);
				break;
				break;
			case BPF_JMP | BPF_JSGT | BPF_X:
			case BPF_JMP | BPF_JSGT | BPF_X:
			case BPF_JMP | BPF_JSLT | BPF_X:
			case BPF_JMP | BPF_JSGE | BPF_X:
			case BPF_JMP | BPF_JSGE | BPF_X:
			case BPF_JMP | BPF_JSLE | BPF_X:
				/* signed comparison */
				/* signed comparison */
				PPC_CMPD(dst_reg, src_reg);
				PPC_CMPD(dst_reg, src_reg);
				break;
				break;
@@ -834,7 +850,9 @@ static int bpf_jit_build_body(struct bpf_prog *fp, u32 *image,
			case BPF_JMP | BPF_JNE | BPF_K:
			case BPF_JMP | BPF_JNE | BPF_K:
			case BPF_JMP | BPF_JEQ | BPF_K:
			case BPF_JMP | BPF_JEQ | BPF_K:
			case BPF_JMP | BPF_JGT | BPF_K:
			case BPF_JMP | BPF_JGT | BPF_K:
			case BPF_JMP | BPF_JLT | BPF_K:
			case BPF_JMP | BPF_JGE | BPF_K:
			case BPF_JMP | BPF_JGE | BPF_K:
			case BPF_JMP | BPF_JLE | BPF_K:
				/*
				/*
				 * Need sign-extended load, so only positive
				 * Need sign-extended load, so only positive
				 * values can be used as imm in cmpldi
				 * values can be used as imm in cmpldi
@@ -849,7 +867,9 @@ static int bpf_jit_build_body(struct bpf_prog *fp, u32 *image,
				}
				}
				break;
				break;
			case BPF_JMP | BPF_JSGT | BPF_K:
			case BPF_JMP | BPF_JSGT | BPF_K:
			case BPF_JMP | BPF_JSLT | BPF_K:
			case BPF_JMP | BPF_JSGE | BPF_K:
			case BPF_JMP | BPF_JSGE | BPF_K:
			case BPF_JMP | BPF_JSLE | BPF_K:
				/*
				/*
				 * signed comparison, so any 16-bit value
				 * signed comparison, so any 16-bit value
				 * can be used in cmpdi
				 * can be used in cmpdi
Loading