summaryrefslogtreecommitdiff
path: root/arch/powerpc/net
diff options
context:
space:
mode:
Diffstat (limited to 'arch/powerpc/net')
-rw-r--r--arch/powerpc/net/bpf_jit.h6
-rw-r--r--arch/powerpc/net/bpf_jit_comp.c25
2 files changed, 31 insertions, 0 deletions
diff --git a/arch/powerpc/net/bpf_jit.h b/arch/powerpc/net/bpf_jit.h
index 1fc8109..8a5dfaf 100644
--- a/arch/powerpc/net/bpf_jit.h
+++ b/arch/powerpc/net/bpf_jit.h
@@ -134,6 +134,12 @@ DECLARE_LOAD_FUNC(sk_load_byte_msh);
___PPC_RS(a) | IMM_L(i))
#define PPC_ORIS(d, a, i) EMIT(PPC_INST_ORIS | ___PPC_RA(d) | \
___PPC_RS(a) | IMM_L(i))
+#define PPC_XOR(d, a, b) EMIT(PPC_INST_XOR | ___PPC_RA(d) | \
+ ___PPC_RS(a) | ___PPC_RB(b))
+#define PPC_XORI(d, a, i) EMIT(PPC_INST_XORI | ___PPC_RA(d) | \
+ ___PPC_RS(a) | IMM_L(i))
+#define PPC_XORIS(d, a, i) EMIT(PPC_INST_XORIS | ___PPC_RA(d) | \
+ ___PPC_RS(a) | IMM_L(i))
#define PPC_SLW(d, a, s) EMIT(PPC_INST_SLW | ___PPC_RA(d) | \
___PPC_RS(a) | ___PPC_RB(s))
#define PPC_SRW(d, a, s) EMIT(PPC_INST_SRW | ___PPC_RA(d) | \
diff --git a/arch/powerpc/net/bpf_jit_comp.c b/arch/powerpc/net/bpf_jit_comp.c
index dd11306..e834f1e 100644
--- a/arch/powerpc/net/bpf_jit_comp.c
+++ b/arch/powerpc/net/bpf_jit_comp.c
@@ -13,6 +13,8 @@
#include <asm/cacheflush.h>
#include <linux/netdevice.h>
#include <linux/filter.h>
+#include <linux/if_vlan.h>
+
#include "bpf_jit.h"
#ifndef __BIG_ENDIAN
@@ -89,6 +91,8 @@ static void bpf_jit_build_prologue(struct sk_filter *fp, u32 *image,
case BPF_S_ANC_IFINDEX:
case BPF_S_ANC_MARK:
case BPF_S_ANC_RXHASH:
+ case BPF_S_ANC_VLAN_TAG:
+ case BPF_S_ANC_VLAN_TAG_PRESENT:
case BPF_S_ANC_CPU:
case BPF_S_ANC_QUEUE:
case BPF_S_LD_W_ABS:
@@ -232,6 +236,17 @@ static int bpf_jit_build_body(struct sk_filter *fp, u32 *image,
if (K >= 65536)
PPC_ORIS(r_A, r_A, IMM_H(K));
break;
+ case BPF_S_ANC_ALU_XOR_X:
+ case BPF_S_ALU_XOR_X: /* A ^= X */
+ ctx->seen |= SEEN_XREG;
+ PPC_XOR(r_A, r_A, r_X);
+ break;
+ case BPF_S_ALU_XOR_K: /* A ^= K */
+ if (IMM_L(K))
+ PPC_XORI(r_A, r_A, IMM_L(K));
+ if (K >= 65536)
+ PPC_XORIS(r_A, r_A, IMM_H(K));
+ break;
case BPF_S_ALU_LSH_X: /* A <<= X; */
ctx->seen |= SEEN_XREG;
PPC_SLW(r_A, r_A, r_X);
@@ -371,6 +386,16 @@ static int bpf_jit_build_body(struct sk_filter *fp, u32 *image,
PPC_LWZ_OFFS(r_A, r_skb, offsetof(struct sk_buff,
rxhash));
break;
+ case BPF_S_ANC_VLAN_TAG:
+ case BPF_S_ANC_VLAN_TAG_PRESENT:
+ BUILD_BUG_ON(FIELD_SIZEOF(struct sk_buff, vlan_tci) != 2);
+ PPC_LHZ_OFFS(r_A, r_skb, offsetof(struct sk_buff,
+ vlan_tci));
+ if (filter[i].code == BPF_S_ANC_VLAN_TAG)
+ PPC_ANDI(r_A, r_A, VLAN_VID_MASK);
+ else
+ PPC_ANDI(r_A, r_A, VLAN_TAG_PRESENT);
+ break;
case BPF_S_ANC_QUEUE:
BUILD_BUG_ON(FIELD_SIZEOF(struct sk_buff,
queue_mapping) != 2);