diff options
Diffstat (limited to 'arch/powerpc/net/bpf_jit_comp.c')
| -rw-r--r-- | arch/powerpc/net/bpf_jit_comp.c | 49 | 
1 files changed, 26 insertions, 23 deletions
diff --git a/arch/powerpc/net/bpf_jit_comp.c b/arch/powerpc/net/bpf_jit_comp.c index cbae2dfd053c..1ca125b9c226 100644 --- a/arch/powerpc/net/bpf_jit_comp.c +++ b/arch/powerpc/net/bpf_jit_comp.c @@ -181,6 +181,7 @@ static int bpf_jit_build_body(struct bpf_prog *fp, u32 *image,  			}  			break;  		case BPF_ALU | BPF_MOD | BPF_X: /* A %= X; */ +		case BPF_ALU | BPF_DIV | BPF_X: /* A /= X; */  			ctx->seen |= SEEN_XREG;  			PPC_CMPWI(r_X, 0);  			if (ctx->pc_ret0 != -1) { @@ -190,9 +191,13 @@ static int bpf_jit_build_body(struct bpf_prog *fp, u32 *image,  				PPC_LI(r_ret, 0);  				PPC_JMP(exit_addr);  			} -			PPC_DIVWU(r_scratch1, r_A, r_X); -			PPC_MUL(r_scratch1, r_X, r_scratch1); -			PPC_SUB(r_A, r_A, r_scratch1); +			if (code == (BPF_ALU | BPF_MOD | BPF_X)) { +				PPC_DIVWU(r_scratch1, r_A, r_X); +				PPC_MUL(r_scratch1, r_X, r_scratch1); +				PPC_SUB(r_A, r_A, r_scratch1); +			} else { +				PPC_DIVWU(r_A, r_A, r_X); +			}  			break;  		case BPF_ALU | BPF_MOD | BPF_K: /* A %= K; */  			PPC_LI32(r_scratch2, K); @@ -200,22 +205,6 @@ static int bpf_jit_build_body(struct bpf_prog *fp, u32 *image,  			PPC_MUL(r_scratch1, r_scratch2, r_scratch1);  			PPC_SUB(r_A, r_A, r_scratch1);  			break; -		case BPF_ALU | BPF_DIV | BPF_X: /* A /= X; */ -			ctx->seen |= SEEN_XREG; -			PPC_CMPWI(r_X, 0); -			if (ctx->pc_ret0 != -1) { -				PPC_BCC(COND_EQ, addrs[ctx->pc_ret0]); -			} else { -				/* -				 * Exit, returning 0; first pass hits here -				 * (longer worst-case code size). -				 */ -				PPC_BCC_SHORT(COND_NE, (ctx->idx*4)+12); -				PPC_LI(r_ret, 0); -				PPC_JMP(exit_addr); -			} -			PPC_DIVWU(r_A, r_A, r_X); -			break;  		case BPF_ALU | BPF_DIV | BPF_K: /* A /= K */  			if (K == 1)  				break; @@ -361,6 +350,11 @@ static int bpf_jit_build_body(struct bpf_prog *fp, u32 *image,  							    protocol));  			break;  		case BPF_ANC | SKF_AD_IFINDEX: +		case BPF_ANC | SKF_AD_HATYPE: +			BUILD_BUG_ON(FIELD_SIZEOF(struct net_device, +						ifindex) != 4); +			BUILD_BUG_ON(FIELD_SIZEOF(struct net_device, +						type) != 2);  			PPC_LD_OFFS(r_scratch1, r_skb, offsetof(struct sk_buff,  								dev));  			PPC_CMPDI(r_scratch1, 0); @@ -368,14 +362,18 @@ static int bpf_jit_build_body(struct bpf_prog *fp, u32 *image,  				PPC_BCC(COND_EQ, addrs[ctx->pc_ret0]);  			} else {  				/* Exit, returning 0; first pass hits here. */ -				PPC_BCC_SHORT(COND_NE, (ctx->idx*4)+12); +				PPC_BCC_SHORT(COND_NE, ctx->idx * 4 + 12);  				PPC_LI(r_ret, 0);  				PPC_JMP(exit_addr);  			} -			BUILD_BUG_ON(FIELD_SIZEOF(struct net_device, -						  ifindex) != 4); -			PPC_LWZ_OFFS(r_A, r_scratch1, +			if (code == (BPF_ANC | SKF_AD_IFINDEX)) { +				PPC_LWZ_OFFS(r_A, r_scratch1,  				     offsetof(struct net_device, ifindex)); +			} else { +				PPC_LHZ_OFFS(r_A, r_scratch1, +				     offsetof(struct net_device, type)); +			} +  			break;  		case BPF_ANC | SKF_AD_MARK:  			BUILD_BUG_ON(FIELD_SIZEOF(struct sk_buff, mark) != 4); @@ -407,6 +405,11 @@ static int bpf_jit_build_body(struct bpf_prog *fp, u32 *image,  			PPC_LHZ_OFFS(r_A, r_skb, offsetof(struct sk_buff,  							  queue_mapping));  			break; +		case BPF_ANC | SKF_AD_PKTTYPE: +			PPC_LBZ_OFFS(r_A, r_skb, PKT_TYPE_OFFSET()); +			PPC_ANDI(r_A, r_A, PKT_TYPE_MAX); +			PPC_SRWI(r_A, r_A, 5); +			break;  		case BPF_ANC | SKF_AD_CPU:  #ifdef CONFIG_SMP  			/*  |