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: Philippe Bergheaud <felix@linux.vnet.ibm.com> Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
This commit is contained in:
parent
711b5138d5
commit
9c662cad2f
4 changed files with 21 additions and 16 deletions
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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,
|
||||
protocol));
|
||||
/* ntohs is a NOP with BE loads. */
|
||||
PPC_NTOHS_OFFS(r_A, r_skb, offsetof(struct sk_buff,
|
||||
protocol));
|
||||
break;
|
||||
case BPF_S_ANC_IFINDEX:
|
||||
PPC_LD_OFFS(r_scratch1, r_skb, offsetof(struct sk_buff,
|
||||
|
|
Loading…
Reference in a new issue