mirror of
https://github.com/Fishwaldo/Star64_linux.git
synced 2025-07-04 21:31:51 +00:00
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 */
|
/* Misc instructions for BPF compiler */
|
||||||
#define PPC_INST_LD 0xe8000000
|
#define PPC_INST_LD 0xe8000000
|
||||||
#define PPC_INST_LHZ 0xa0000000
|
#define PPC_INST_LHZ 0xa0000000
|
||||||
|
#define PPC_INST_LHBRX 0x7c00062c
|
||||||
#define PPC_INST_LWZ 0x80000000
|
#define PPC_INST_LWZ 0x80000000
|
||||||
#define PPC_INST_STD 0xf8000000
|
#define PPC_INST_STD 0xf8000000
|
||||||
#define PPC_INST_STDU 0xf8000001
|
#define PPC_INST_STDU 0xf8000001
|
||||||
|
|
|
@ -92,6 +92,8 @@ DECLARE_LOAD_FUNC(sk_load_byte_msh);
|
||||||
___PPC_RA(base) | IMM_L(i))
|
___PPC_RA(base) | IMM_L(i))
|
||||||
#define PPC_LHZ(r, base, i) EMIT(PPC_INST_LHZ | ___PPC_RT(r) | \
|
#define PPC_LHZ(r, base, i) EMIT(PPC_INST_LHZ | ___PPC_RT(r) | \
|
||||||
___PPC_RA(base) | IMM_L(i))
|
___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: */
|
/* Convenience helpers for the above with 'far' offsets: */
|
||||||
#define PPC_LD_OFFS(r, base, i) do { if ((i) < 32768) PPC_LD(r, base, i); \
|
#define PPC_LD_OFFS(r, base, i) do { if ((i) < 32768) PPC_LD(r, base, i); \
|
||||||
else { PPC_ADDIS(r, base, IMM_HA(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); \
|
PPC_ORI(d, d, (uintptr_t)(i) & 0xffff); \
|
||||||
} } while (0);
|
} } 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)
|
static inline bool is_nearbranch(int offset)
|
||||||
{
|
{
|
||||||
return (offset < 32768) && (offset >= -32768);
|
return (offset < 32768) && (offset >= -32768);
|
||||||
|
|
|
@ -43,8 +43,11 @@ sk_load_word_positive_offset:
|
||||||
cmpd r_scratch1, r_addr
|
cmpd r_scratch1, r_addr
|
||||||
blt bpf_slow_path_word
|
blt bpf_slow_path_word
|
||||||
/* Nope, just hitting the header. cr0 here is eq or gt! */
|
/* 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
|
lwzx r_A, r_D, r_addr
|
||||||
/* When big endian we don't need to byteswap. */
|
#endif
|
||||||
blr /* Return success, cr0 != LT */
|
blr /* Return success, cr0 != LT */
|
||||||
|
|
||||||
.globl sk_load_half
|
.globl sk_load_half
|
||||||
|
@ -56,7 +59,11 @@ sk_load_half_positive_offset:
|
||||||
subi r_scratch1, r_HL, 2
|
subi r_scratch1, r_HL, 2
|
||||||
cmpd r_scratch1, r_addr
|
cmpd r_scratch1, r_addr
|
||||||
blt bpf_slow_path_half
|
blt bpf_slow_path_half
|
||||||
|
#ifdef __LITTLE_ENDIAN__
|
||||||
|
lhbrx r_A, r_D, r_addr
|
||||||
|
#else
|
||||||
lhzx r_A, r_D, r_addr
|
lhzx r_A, r_D, r_addr
|
||||||
|
#endif
|
||||||
blr
|
blr
|
||||||
|
|
||||||
.globl sk_load_byte
|
.globl sk_load_byte
|
||||||
|
|
|
@ -17,14 +17,8 @@
|
||||||
|
|
||||||
#include "bpf_jit.h"
|
#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;
|
int bpf_jit_enable __read_mostly;
|
||||||
|
|
||||||
|
|
||||||
static inline void bpf_flush_icache(void *start, void *end)
|
static inline void bpf_flush_icache(void *start, void *end)
|
||||||
{
|
{
|
||||||
smp_wmb();
|
smp_wmb();
|
||||||
|
@ -346,18 +340,11 @@ static int bpf_jit_build_body(struct sk_filter *fp, u32 *image,
|
||||||
break;
|
break;
|
||||||
|
|
||||||
/*** Ancillary info loads ***/
|
/*** 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); */
|
case BPF_S_ANC_PROTOCOL: /* A = ntohs(skb->protocol); */
|
||||||
BUILD_BUG_ON(FIELD_SIZEOF(struct sk_buff,
|
BUILD_BUG_ON(FIELD_SIZEOF(struct sk_buff,
|
||||||
protocol) != 2);
|
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));
|
protocol));
|
||||||
/* ntohs is a NOP with BE loads. */
|
|
||||||
break;
|
break;
|
||||||
case BPF_S_ANC_IFINDEX:
|
case BPF_S_ANC_IFINDEX:
|
||||||
PPC_LD_OFFS(r_scratch1, r_skb, offsetof(struct sk_buff,
|
PPC_LD_OFFS(r_scratch1, r_skb, offsetof(struct sk_buff,
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue