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

Commit 9c662cad authored by Philippe Bergheaud's avatar Philippe Bergheaud Committed by Benjamin Herrenschmidt
Browse files

powerpc/bpf: BPF JIT compiler for 64-bit Little Endian



This enables the Berkeley Packet Filter JIT compiler
for the PowerPC running in 64bit Little Endian.

Signed-off-by: default avatarPhilippe Bergheaud <felix@linux.vnet.ibm.com>
Signed-off-by: default avatarBenjamin Herrenschmidt <benh@kernel.crashing.org>
parent 711b5138
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -203,6 +203,7 @@
/* Misc instructions for BPF compiler */
#define PPC_INST_LD			0xe8000000
#define PPC_INST_LHZ			0xa0000000
#define PPC_INST_LHBRX			0x7c00062c
#define PPC_INST_LWZ			0x80000000
#define PPC_INST_STD			0xf8000000
#define PPC_INST_STDU			0xf8000001
+10 −0
Original line number Diff line number Diff line
@@ -92,6 +92,8 @@ DECLARE_LOAD_FUNC(sk_load_byte_msh);
				     ___PPC_RA(base) | IMM_L(i))
#define PPC_LHZ(r, base, i)	EMIT(PPC_INST_LHZ | ___PPC_RT(r) |	      \
				     ___PPC_RA(base) | IMM_L(i))
#define PPC_LHBRX(r, base, b)	EMIT(PPC_INST_LHBRX | ___PPC_RT(r) |	      \
				     ___PPC_RA(base) | ___PPC_RB(b))
/* Convenience helpers for the above with 'far' offsets: */
#define PPC_LD_OFFS(r, base, i) do { if ((i) < 32768) PPC_LD(r, base, i);     \
		else {	PPC_ADDIS(r, base, IMM_HA(i));			      \
@@ -186,6 +188,14 @@ DECLARE_LOAD_FUNC(sk_load_byte_msh);
				PPC_ORI(d, d, (uintptr_t)(i) & 0xffff);	      \
		} } while (0);

#define PPC_LHBRX_OFFS(r, base, i) \
		do { PPC_LI32(r, i); PPC_LHBRX(r, r, base); } while(0)
#ifdef __LITTLE_ENDIAN__
#define PPC_NTOHS_OFFS(r, base, i)	PPC_LHBRX_OFFS(r, base, i)
#else
#define PPC_NTOHS_OFFS(r, base, i)	PPC_LHZ_OFFS(r, base, i)
#endif

static inline bool is_nearbranch(int offset)
{
	return (offset < 32768) && (offset >= -32768);
+8 −1
Original line number Diff line number Diff line
@@ -43,8 +43,11 @@ sk_load_word_positive_offset:
	cmpd	r_scratch1, r_addr
	blt	bpf_slow_path_word
	/* Nope, just hitting the header.  cr0 here is eq or gt! */
#ifdef __LITTLE_ENDIAN__
	lwbrx	r_A, r_D, r_addr
#else
	lwzx	r_A, r_D, r_addr
	/* When big endian we don't need to byteswap. */
#endif
	blr	/* Return success, cr0 != LT */

	.globl	sk_load_half
@@ -56,7 +59,11 @@ sk_load_half_positive_offset:
	subi	r_scratch1, r_HL, 2
	cmpd	r_scratch1, r_addr
	blt	bpf_slow_path_half
#ifdef __LITTLE_ENDIAN__
	lhbrx	r_A, r_D, r_addr
#else
	lhzx	r_A, r_D, r_addr
#endif
	blr

	.globl	sk_load_byte
+2 −15
Original line number Diff line number Diff line
@@ -17,14 +17,8 @@

#include "bpf_jit.h"

#ifndef __BIG_ENDIAN
/* There are endianness assumptions herein. */
#error "Little-endian PPC not supported in BPF compiler"
#endif

int bpf_jit_enable __read_mostly;


static inline void bpf_flush_icache(void *start, void *end)
{
	smp_wmb();
@@ -346,18 +340,11 @@ static int bpf_jit_build_body(struct sk_filter *fp, u32 *image,
			break;

			/*** Ancillary info loads ***/

			/* None of the BPF_S_ANC* codes appear to be passed by
			 * sk_chk_filter().  The interpreter and the x86 BPF
			 * compiler implement them so we do too -- they may be
			 * planted in future.
			 */
		case BPF_S_ANC_PROTOCOL: /* A = ntohs(skb->protocol); */
			BUILD_BUG_ON(FIELD_SIZEOF(struct sk_buff,
						  protocol) != 2);
			PPC_LHZ_OFFS(r_A, r_skb, offsetof(struct sk_buff,
			PPC_NTOHS_OFFS(r_A, r_skb, offsetof(struct sk_buff,
							    protocol));
			/* ntohs is a NOP with BE loads. */
			break;
		case BPF_S_ANC_IFINDEX:
			PPC_LD_OFFS(r_scratch1, r_skb, offsetof(struct sk_buff,