summaryrefslogtreecommitdiffstats
path: root/arch/arm/net
diff options
context:
space:
mode:
Diffstat (limited to 'arch/arm/net')
-rw-r--r--arch/arm/net/bpf_jit_32.c29
-rw-r--r--arch/arm/net/bpf_jit_32.h2
2 files changed, 26 insertions, 5 deletions
diff --git a/arch/arm/net/bpf_jit_32.c b/arch/arm/net/bpf_jit_32.c
index b6f305e3b908..a34f1e214116 100644
--- a/arch/arm/net/bpf_jit_32.c
+++ b/arch/arm/net/bpf_jit_32.c
@@ -16,6 +16,7 @@
#include <linux/netdevice.h>
#include <linux/string.h>
#include <linux/slab.h>
+#include <linux/if_vlan.h>
#include <asm/cacheflush.h>
#include <asm/hwcap.h>
@@ -168,6 +169,8 @@ static inline bool is_load_to_a(u16 inst)
case BPF_S_ANC_MARK:
case BPF_S_ANC_PROTOCOL:
case BPF_S_ANC_RXHASH:
+ case BPF_S_ANC_VLAN_TAG:
+ case BPF_S_ANC_VLAN_TAG_PRESENT:
case BPF_S_ANC_QUEUE:
return true;
default:
@@ -646,6 +649,16 @@ load_ind:
update_on_xread(ctx);
emit(ARM_ORR_R(r_A, r_A, r_X), ctx);
break;
+ case BPF_S_ALU_XOR_K:
+ /* A ^= K; */
+ OP_IMM3(ARM_EOR, r_A, r_A, k, ctx);
+ break;
+ case BPF_S_ANC_ALU_XOR_X:
+ case BPF_S_ALU_XOR_X:
+ /* A ^= X */
+ update_on_xread(ctx);
+ emit(ARM_EOR_R(r_A, r_A, r_X), ctx);
+ break;
case BPF_S_ALU_AND_K:
/* A &= K */
OP_IMM3(ARM_AND, r_A, r_A, k, ctx);
@@ -762,11 +775,6 @@ b_epilogue:
update_on_xread(ctx);
emit(ARM_MOV_R(r_A, r_X), ctx);
break;
- case BPF_S_ANC_ALU_XOR_X:
- /* A ^= X */
- update_on_xread(ctx);
- emit(ARM_EOR_R(r_A, r_A, r_X), ctx);
- break;
case BPF_S_ANC_PROTOCOL:
/* A = ntohs(skb->protocol) */
ctx->seen |= SEEN_SKB;
@@ -810,6 +818,17 @@ b_epilogue:
off = offsetof(struct sk_buff, rxhash);
emit(ARM_LDR_I(r_A, r_skb, off), ctx);
break;
+ case BPF_S_ANC_VLAN_TAG:
+ case BPF_S_ANC_VLAN_TAG_PRESENT:
+ ctx->seen |= SEEN_SKB;
+ BUILD_BUG_ON(FIELD_SIZEOF(struct sk_buff, vlan_tci) != 2);
+ off = offsetof(struct sk_buff, vlan_tci);
+ emit(ARM_LDRH_I(r_A, r_skb, off), ctx);
+ if (inst->code == BPF_S_ANC_VLAN_TAG)
+ OP_IMM3(ARM_AND, r_A, r_A, VLAN_VID_MASK, ctx);
+ else
+ OP_IMM3(ARM_AND, r_A, r_A, VLAN_TAG_PRESENT, ctx);
+ break;
case BPF_S_ANC_QUEUE:
ctx->seen |= SEEN_SKB;
BUILD_BUG_ON(FIELD_SIZEOF(struct sk_buff,
diff --git a/arch/arm/net/bpf_jit_32.h b/arch/arm/net/bpf_jit_32.h
index 7fa2f7d3cb90..afb84621ff6f 100644
--- a/arch/arm/net/bpf_jit_32.h
+++ b/arch/arm/net/bpf_jit_32.h
@@ -69,6 +69,7 @@
#define ARM_INST_CMP_I 0x03500000
#define ARM_INST_EOR_R 0x00200000
+#define ARM_INST_EOR_I 0x02200000
#define ARM_INST_LDRB_I 0x05d00000
#define ARM_INST_LDRB_R 0x07d00000
@@ -135,6 +136,7 @@
#define ARM_CMP_I(rn, imm) _AL3_I(ARM_INST_CMP, 0, rn, imm)
#define ARM_EOR_R(rd, rn, rm) _AL3_R(ARM_INST_EOR, rd, rn, rm)
+#define ARM_EOR_I(rd, rn, imm) _AL3_I(ARM_INST_EOR, rd, rn, imm)
#define ARM_LDR_I(rt, rn, off) (ARM_INST_LDR_I | (rt) << 12 | (rn) << 16 \
| (off))