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

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

Merge branch 's390-bpf-push-pop'



Michael Holzheu says:

====================
s390/bpf: recache skb->data/hlen for skb_vlan_push/pop

Here the s390 backend for Alexei's patch 4e10df9a ("bpf: introduce
bpf_skb_vlan_push/pop() helpers") plus two bugfixes and two minor
improvements.

The first patch "s390/bpf: clear correct BPF accumulator register" will
also go upstream via Martin's "fixes" branch.

* v2: Integrated suggestions from Joe Perches
====================

Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 35e455f4 9db7f2b8
Loading
Loading
Loading
Loading
+4 −1
Original line number Diff line number Diff line
@@ -36,6 +36,8 @@ extern u8 sk_load_word[], sk_load_half[], sk_load_byte[];
 *	      |   BPF stack   |     |
 *	      |		      |     |
 *	      +---------------+     |
 *	      | 8 byte skbp   |     |
 * R15+170 -> +---------------+     |
 *	      | 8 byte hlen   |     |
 * R15+168 -> +---------------+     |
 *	      | 4 byte align  |     |
@@ -51,11 +53,12 @@ extern u8 sk_load_word[], sk_load_half[], sk_load_byte[];
 * We get 160 bytes stack space from calling function, but only use
 * 12 * 8 byte for old backchain, r15..r6, and tail_call_cnt.
 */
#define STK_SPACE	(MAX_BPF_STACK + 8 + 4 + 4 + 160)
#define STK_SPACE	(MAX_BPF_STACK + 8 + 8 + 4 + 4 + 160)
#define STK_160_UNUSED	(160 - 12 * 8)
#define STK_OFF		(STK_SPACE - STK_160_UNUSED)
#define STK_OFF_TMP	160	/* Offset of tmp buffer on stack */
#define STK_OFF_HLEN	168	/* Offset of SKB header length on stack */
#define STK_OFF_SKBP	170	/* Offset of SKB pointer on stack */

#define STK_OFF_R6	(160 - 11 * 8)	/* Offset of r6 on stack */
#define STK_OFF_TCCNT	(160 - 12 * 8)	/* Offset of tail_call_cnt on stack */
+49 −44
Original line number Diff line number Diff line
@@ -45,7 +45,7 @@ struct bpf_jit {
	int labels[1];		/* Labels for local jumps */
};

#define BPF_SIZE_MAX	4096	/* Max size for program */
#define BPF_SIZE_MAX	0x7ffff	/* Max size for program (20 bit signed displ) */

#define SEEN_SKB	1	/* skb access */
#define SEEN_MEM	2	/* use mem[] for temporary storage */
@@ -53,6 +53,7 @@ struct bpf_jit {
#define SEEN_LITERAL	8	/* code uses literals */
#define SEEN_FUNC	16	/* calls C functions */
#define SEEN_TAIL_CALL	32	/* code uses tail calls */
#define SEEN_SKB_CHANGE	64	/* code changes skb data */
#define SEEN_STACK	(SEEN_FUNC | SEEN_MEM | SEEN_SKB)

/*
@@ -203,19 +204,11 @@ static inline void reg_set_seen(struct bpf_jit *jit, u32 b1)
	_EMIT6(op1 | __disp, op2);				\
})

#define EMIT6_DISP(op1, op2, b1, b2, b3, disp)			\
({								\
	_EMIT6_DISP(op1 | reg(b1, b2) << 16 |			\
		    reg_high(b3) << 8, op2, disp);		\
	REG_SET_SEEN(b1);					\
	REG_SET_SEEN(b2);					\
	REG_SET_SEEN(b3);					\
})

#define _EMIT6_DISP_LH(op1, op2, disp)				\
({								\
	unsigned int __disp_h = ((u32)disp) & 0xff000;		\
	unsigned int __disp_l = ((u32)disp) & 0x00fff;		\
	u32 _disp = (u32) disp;					\
	unsigned int __disp_h = _disp & 0xff000;		\
	unsigned int __disp_l = _disp & 0x00fff;		\
	_EMIT6(op1 | __disp_l, op2 | __disp_h >> 4);		\
})

@@ -389,13 +382,33 @@ static void save_restore_regs(struct bpf_jit *jit, int op)
	} while (re <= 15);
}

/*
 * For SKB access %b1 contains the SKB pointer. For "bpf_jit.S"
 * we store the SKB header length on the stack and the SKB data
 * pointer in REG_SKB_DATA.
 */
static void emit_load_skb_data_hlen(struct bpf_jit *jit)
{
	/* Header length: llgf %w1,<len>(%b1) */
	EMIT6_DISP_LH(0xe3000000, 0x0016, REG_W1, REG_0, BPF_REG_1,
		      offsetof(struct sk_buff, len));
	/* s %w1,<data_len>(%b1) */
	EMIT4_DISP(0x5b000000, REG_W1, BPF_REG_1,
		   offsetof(struct sk_buff, data_len));
	/* stg %w1,ST_OFF_HLEN(%r0,%r15) */
	EMIT6_DISP_LH(0xe3000000, 0x0024, REG_W1, REG_0, REG_15, STK_OFF_HLEN);
	/* lg %skb_data,data_off(%b1) */
	EMIT6_DISP_LH(0xe3000000, 0x0004, REG_SKB_DATA, REG_0,
		      BPF_REG_1, offsetof(struct sk_buff, data));
}

/*
 * Emit function prologue
 *
 * Save registers and create stack frame if necessary.
 * See stack frame layout desription in "bpf_jit.h"!
 */
static void bpf_jit_prologue(struct bpf_jit *jit)
static void bpf_jit_prologue(struct bpf_jit *jit, bool is_classic)
{
	if (jit->seen & SEEN_TAIL_CALL) {
		/* xc STK_OFF_TCCNT(4,%r15),STK_OFF_TCCNT(%r15) */
@@ -429,32 +442,21 @@ static void bpf_jit_prologue(struct bpf_jit *jit)
			EMIT6_DISP_LH(0xe3000000, 0x0024, REG_W1, REG_0,
				      REG_15, 152);
	}
	/*
	 * For SKB access %b1 contains the SKB pointer. For "bpf_jit.S"
	 * we store the SKB header length on the stack and the SKB data
	 * pointer in REG_SKB_DATA.
	 */
	if (jit->seen & SEEN_SKB) {
		/* Header length: llgf %w1,<len>(%b1) */
		EMIT6_DISP_LH(0xe3000000, 0x0016, REG_W1, REG_0, BPF_REG_1,
			      offsetof(struct sk_buff, len));
		/* s %w1,<data_len>(%b1) */
		EMIT4_DISP(0x5b000000, REG_W1, BPF_REG_1,
			   offsetof(struct sk_buff, data_len));
		/* stg %w1,ST_OFF_HLEN(%r0,%r15) */
	if (jit->seen & SEEN_SKB)
		emit_load_skb_data_hlen(jit);
	if (jit->seen & SEEN_SKB_CHANGE)
		/* stg %b1,ST_OFF_SKBP(%r0,%r15) */
		EMIT6_DISP_LH(0xe3000000, 0x0024, REG_W1, REG_0, REG_15,
			      STK_OFF_HLEN);
		/* lg %skb_data,data_off(%b1) */
		EMIT6_DISP_LH(0xe3000000, 0x0004, REG_SKB_DATA, REG_0,
			      BPF_REG_1, offsetof(struct sk_buff, data));
			      STK_OFF_SKBP);
	/* Clear A (%b0) and X (%b7) registers for converted BPF programs */
	if (is_classic) {
		if (REG_SEEN(BPF_REG_A))
			/* lghi %ba,0 */
			EMIT4_IMM(0xa7090000, BPF_REG_A, 0);
		if (REG_SEEN(BPF_REG_X))
			/* lghi %bx,0 */
			EMIT4_IMM(0xa7090000, BPF_REG_X, 0);
	}
	/* BPF compatibility: clear A (%b7) and X (%b8) registers */
	if (REG_SEEN(BPF_REG_7))
		/* lghi %b7,0 */
		EMIT4_IMM(0xa7090000, BPF_REG_7, 0);
	if (REG_SEEN(BPF_REG_8))
		/* lghi %b8,0 */
		EMIT4_IMM(0xa7090000, BPF_REG_8, 0);
}

/*
@@ -973,19 +975,22 @@ static noinline int bpf_jit_insn(struct bpf_jit *jit, struct bpf_prog *fp, int i
		 */
		const u64 func = (u64)__bpf_call_base + imm;

		if (bpf_helper_changes_skb_data((void *)func))
			/* TODO reload skb->data, hlen */
			return -1;

		REG_SET_SEEN(BPF_REG_5);
		jit->seen |= SEEN_FUNC;
		/* lg %w1,<d(imm)>(%l) */
		EMIT6_DISP(0xe3000000, 0x0004, REG_W1, REG_0, REG_L,
		EMIT6_DISP_LH(0xe3000000, 0x0004, REG_W1, REG_0, REG_L,
			      EMIT_CONST_U64(func));
		/* basr %r14,%w1 */
		EMIT2(0x0d00, REG_14, REG_W1);
		/* lgr %b0,%r2: load return value into %b0 */
		EMIT4(0xb9040000, BPF_REG_0, REG_2);
		if (bpf_helper_changes_skb_data((void *)func)) {
			jit->seen |= SEEN_SKB_CHANGE;
			/* lg %b1,ST_OFF_SKBP(%r15) */
			EMIT6_DISP_LH(0xe3000000, 0x0004, BPF_REG_1, REG_0,
				      REG_15, STK_OFF_SKBP);
			emit_load_skb_data_hlen(jit);
		}
		break;
	}
	case BPF_JMP | BPF_CALL | BPF_X:
@@ -1240,7 +1245,7 @@ static int bpf_jit_prog(struct bpf_jit *jit, struct bpf_prog *fp)
	jit->lit = jit->lit_start;
	jit->prg = 0;

	bpf_jit_prologue(jit);
	bpf_jit_prologue(jit, fp->type == BPF_PROG_TYPE_UNSPEC);
	for (i = 0; i < fp->len; i += insn_count) {
		insn_count = bpf_jit_insn(jit, fp, i);
		if (insn_count < 0)