diff options
| author | Dmitry Torokhov <dmitry.torokhov@gmail.com> | 2013-05-01 08:47:44 -0700 | 
|---|---|---|
| committer | Dmitry Torokhov <dmitry.torokhov@gmail.com> | 2013-05-01 08:47:44 -0700 | 
| commit | bf61c8840efe60fd8f91446860b63338fb424158 (patch) | |
| tree | 7a71832407a4f0d6346db773343f4c3ae2257b19 /arch/arm/net/bpf_jit_32.c | |
| parent | 5846115b30f3a881e542c8bfde59a699c1c13740 (diff) | |
| parent | 0c6a61657da78098472fd0eb71cc01f2387fa1bb (diff) | |
| download | olio-linux-3.10-bf61c8840efe60fd8f91446860b63338fb424158.tar.xz olio-linux-3.10-bf61c8840efe60fd8f91446860b63338fb424158.zip  | |
Merge branch 'next' into for-linus
Prepare first set of updates for 3.10 merge window.
Diffstat (limited to 'arch/arm/net/bpf_jit_32.c')
| -rw-r--r-- | arch/arm/net/bpf_jit_32.c | 50 | 
1 files changed, 38 insertions, 12 deletions
diff --git a/arch/arm/net/bpf_jit_32.c b/arch/arm/net/bpf_jit_32.c index c641fb68501..6828ef6ce80 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> @@ -42,7 +43,7 @@  #define r_skb_hl	ARM_R8  #define SCRATCH_SP_OFFSET	0 -#define SCRATCH_OFF(k)		(SCRATCH_SP_OFFSET + (k)) +#define SCRATCH_OFF(k)		(SCRATCH_SP_OFFSET + 4 * (k))  #define SEEN_MEM		((1 << BPF_MEMWORDS) - 1)  #define SEEN_MEM_WORD(k)	(1 << (k)) @@ -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: @@ -338,10 +341,17 @@ static void emit_load_be16(u8 cond, u8 r_res, u8 r_addr, struct jit_ctx *ctx)  static inline void emit_swap16(u8 r_dst, u8 r_src, struct jit_ctx *ctx)  { -	emit(ARM_LSL_R(ARM_R1, r_src, 8), ctx); -	emit(ARM_ORR_S(r_dst, ARM_R1, r_src, SRTYPE_LSL, 8), ctx); -	emit(ARM_LSL_I(r_dst, r_dst, 8), ctx); -	emit(ARM_LSL_R(r_dst, r_dst, 8), ctx); +	/* r_dst = (r_src << 8) | (r_src >> 8) */ +	emit(ARM_LSL_I(ARM_R1, r_src, 8), ctx); +	emit(ARM_ORR_S(r_dst, ARM_R1, r_src, SRTYPE_LSR, 8), ctx); + +	/* +	 * we need to mask out the bits set in r_dst[23:16] due to +	 * the first shift instruction. +	 * +	 * note that 0x8ff is the encoded immediate 0x00ff0000. +	 */ +	emit(ARM_BIC_I(r_dst, r_dst, 0x8ff), ctx);  }  #else  /* ARMv6+ */ @@ -646,6 +656,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 +782,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 +825,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, @@ -845,7 +871,7 @@ void bpf_jit_compile(struct sk_filter *fp)  	ctx.skf		= fp;  	ctx.ret0_fp_idx = -1; -	ctx.offsets = kzalloc(GFP_KERNEL, 4 * (ctx.skf->len + 1)); +	ctx.offsets = kzalloc(4 * (ctx.skf->len + 1), GFP_KERNEL);  	if (ctx.offsets == NULL)  		return; @@ -864,7 +890,7 @@ void bpf_jit_compile(struct sk_filter *fp)  	ctx.idx += ctx.imm_count;  	if (ctx.imm_count) { -		ctx.imms = kzalloc(GFP_KERNEL, 4 * ctx.imm_count); +		ctx.imms = kzalloc(4 * ctx.imm_count, GFP_KERNEL);  		if (ctx.imms == NULL)  			goto out;  	}  |