diff options
Diffstat (limited to 'arch/arm/net/bpf_jit_32.c')
| -rw-r--r-- | arch/arm/net/bpf_jit_32.c | 35 |
1 files changed, 27 insertions, 8 deletions
diff --git a/arch/arm/net/bpf_jit_32.c b/arch/arm/net/bpf_jit_32.c index c641fb685017..a34f1e214116 100644 --- a/arch/arm/net/bpf_jit_32.c +++ b/arch/arm/net/bpf_jit_32.c | |||
| @@ -16,6 +16,7 @@ | |||
| 16 | #include <linux/netdevice.h> | 16 | #include <linux/netdevice.h> |
| 17 | #include <linux/string.h> | 17 | #include <linux/string.h> |
| 18 | #include <linux/slab.h> | 18 | #include <linux/slab.h> |
| 19 | #include <linux/if_vlan.h> | ||
| 19 | #include <asm/cacheflush.h> | 20 | #include <asm/cacheflush.h> |
| 20 | #include <asm/hwcap.h> | 21 | #include <asm/hwcap.h> |
| 21 | 22 | ||
| @@ -42,7 +43,7 @@ | |||
| 42 | #define r_skb_hl ARM_R8 | 43 | #define r_skb_hl ARM_R8 |
| 43 | 44 | ||
| 44 | #define SCRATCH_SP_OFFSET 0 | 45 | #define SCRATCH_SP_OFFSET 0 |
| 45 | #define SCRATCH_OFF(k) (SCRATCH_SP_OFFSET + (k)) | 46 | #define SCRATCH_OFF(k) (SCRATCH_SP_OFFSET + 4 * (k)) |
| 46 | 47 | ||
| 47 | #define SEEN_MEM ((1 << BPF_MEMWORDS) - 1) | 48 | #define SEEN_MEM ((1 << BPF_MEMWORDS) - 1) |
| 48 | #define SEEN_MEM_WORD(k) (1 << (k)) | 49 | #define SEEN_MEM_WORD(k) (1 << (k)) |
| @@ -168,6 +169,8 @@ static inline bool is_load_to_a(u16 inst) | |||
| 168 | case BPF_S_ANC_MARK: | 169 | case BPF_S_ANC_MARK: |
| 169 | case BPF_S_ANC_PROTOCOL: | 170 | case BPF_S_ANC_PROTOCOL: |
| 170 | case BPF_S_ANC_RXHASH: | 171 | case BPF_S_ANC_RXHASH: |
| 172 | case BPF_S_ANC_VLAN_TAG: | ||
| 173 | case BPF_S_ANC_VLAN_TAG_PRESENT: | ||
| 171 | case BPF_S_ANC_QUEUE: | 174 | case BPF_S_ANC_QUEUE: |
| 172 | return true; | 175 | return true; |
| 173 | default: | 176 | default: |
| @@ -646,6 +649,16 @@ load_ind: | |||
| 646 | update_on_xread(ctx); | 649 | update_on_xread(ctx); |
| 647 | emit(ARM_ORR_R(r_A, r_A, r_X), ctx); | 650 | emit(ARM_ORR_R(r_A, r_A, r_X), ctx); |
| 648 | break; | 651 | break; |
| 652 | case BPF_S_ALU_XOR_K: | ||
| 653 | /* A ^= K; */ | ||
| 654 | OP_IMM3(ARM_EOR, r_A, r_A, k, ctx); | ||
| 655 | break; | ||
| 656 | case BPF_S_ANC_ALU_XOR_X: | ||
| 657 | case BPF_S_ALU_XOR_X: | ||
| 658 | /* A ^= X */ | ||
| 659 | update_on_xread(ctx); | ||
| 660 | emit(ARM_EOR_R(r_A, r_A, r_X), ctx); | ||
| 661 | break; | ||
| 649 | case BPF_S_ALU_AND_K: | 662 | case BPF_S_ALU_AND_K: |
| 650 | /* A &= K */ | 663 | /* A &= K */ |
| 651 | OP_IMM3(ARM_AND, r_A, r_A, k, ctx); | 664 | OP_IMM3(ARM_AND, r_A, r_A, k, ctx); |
| @@ -762,11 +775,6 @@ b_epilogue: | |||
| 762 | update_on_xread(ctx); | 775 | update_on_xread(ctx); |
| 763 | emit(ARM_MOV_R(r_A, r_X), ctx); | 776 | emit(ARM_MOV_R(r_A, r_X), ctx); |
| 764 | break; | 777 | break; |
| 765 | case BPF_S_ANC_ALU_XOR_X: | ||
| 766 | /* A ^= X */ | ||
| 767 | update_on_xread(ctx); | ||
| 768 | emit(ARM_EOR_R(r_A, r_A, r_X), ctx); | ||
| 769 | break; | ||
| 770 | case BPF_S_ANC_PROTOCOL: | 778 | case BPF_S_ANC_PROTOCOL: |
| 771 | /* A = ntohs(skb->protocol) */ | 779 | /* A = ntohs(skb->protocol) */ |
| 772 | ctx->seen |= SEEN_SKB; | 780 | ctx->seen |= SEEN_SKB; |
| @@ -810,6 +818,17 @@ b_epilogue: | |||
| 810 | off = offsetof(struct sk_buff, rxhash); | 818 | off = offsetof(struct sk_buff, rxhash); |
| 811 | emit(ARM_LDR_I(r_A, r_skb, off), ctx); | 819 | emit(ARM_LDR_I(r_A, r_skb, off), ctx); |
| 812 | break; | 820 | break; |
| 821 | case BPF_S_ANC_VLAN_TAG: | ||
| 822 | case BPF_S_ANC_VLAN_TAG_PRESENT: | ||
| 823 | ctx->seen |= SEEN_SKB; | ||
| 824 | BUILD_BUG_ON(FIELD_SIZEOF(struct sk_buff, vlan_tci) != 2); | ||
| 825 | off = offsetof(struct sk_buff, vlan_tci); | ||
| 826 | emit(ARM_LDRH_I(r_A, r_skb, off), ctx); | ||
| 827 | if (inst->code == BPF_S_ANC_VLAN_TAG) | ||
| 828 | OP_IMM3(ARM_AND, r_A, r_A, VLAN_VID_MASK, ctx); | ||
| 829 | else | ||
| 830 | OP_IMM3(ARM_AND, r_A, r_A, VLAN_TAG_PRESENT, ctx); | ||
| 831 | break; | ||
| 813 | case BPF_S_ANC_QUEUE: | 832 | case BPF_S_ANC_QUEUE: |
| 814 | ctx->seen |= SEEN_SKB; | 833 | ctx->seen |= SEEN_SKB; |
| 815 | BUILD_BUG_ON(FIELD_SIZEOF(struct sk_buff, | 834 | BUILD_BUG_ON(FIELD_SIZEOF(struct sk_buff, |
| @@ -845,7 +864,7 @@ void bpf_jit_compile(struct sk_filter *fp) | |||
| 845 | ctx.skf = fp; | 864 | ctx.skf = fp; |
| 846 | ctx.ret0_fp_idx = -1; | 865 | ctx.ret0_fp_idx = -1; |
| 847 | 866 | ||
| 848 | ctx.offsets = kzalloc(GFP_KERNEL, 4 * (ctx.skf->len + 1)); | 867 | ctx.offsets = kzalloc(4 * (ctx.skf->len + 1), GFP_KERNEL); |
| 849 | if (ctx.offsets == NULL) | 868 | if (ctx.offsets == NULL) |
| 850 | return; | 869 | return; |
| 851 | 870 | ||
| @@ -864,7 +883,7 @@ void bpf_jit_compile(struct sk_filter *fp) | |||
| 864 | 883 | ||
| 865 | ctx.idx += ctx.imm_count; | 884 | ctx.idx += ctx.imm_count; |
| 866 | if (ctx.imm_count) { | 885 | if (ctx.imm_count) { |
| 867 | ctx.imms = kzalloc(GFP_KERNEL, 4 * ctx.imm_count); | 886 | ctx.imms = kzalloc(4 * ctx.imm_count, GFP_KERNEL); |
| 868 | if (ctx.imms == NULL) | 887 | if (ctx.imms == NULL) |
| 869 | goto out; | 888 | goto out; |
| 870 | } | 889 | } |
