diff options
Diffstat (limited to 'arch/powerpc/net/bpf_jit_comp.c')
-rw-r--r-- | arch/powerpc/net/bpf_jit_comp.c | 38 |
1 files changed, 23 insertions, 15 deletions
diff --git a/arch/powerpc/net/bpf_jit_comp.c b/arch/powerpc/net/bpf_jit_comp.c index bf56e33f8257..ac3c2a10dafd 100644 --- a/arch/powerpc/net/bpf_jit_comp.c +++ b/arch/powerpc/net/bpf_jit_comp.c | |||
@@ -17,14 +17,8 @@ | |||
17 | 17 | ||
18 | #include "bpf_jit.h" | 18 | #include "bpf_jit.h" |
19 | 19 | ||
20 | #ifndef __BIG_ENDIAN | ||
21 | /* There are endianness assumptions herein. */ | ||
22 | #error "Little-endian PPC not supported in BPF compiler" | ||
23 | #endif | ||
24 | |||
25 | int bpf_jit_enable __read_mostly; | 20 | int bpf_jit_enable __read_mostly; |
26 | 21 | ||
27 | |||
28 | static inline void bpf_flush_icache(void *start, void *end) | 22 | static inline void bpf_flush_icache(void *start, void *end) |
29 | { | 23 | { |
30 | smp_wmb(); | 24 | smp_wmb(); |
@@ -193,6 +187,26 @@ static int bpf_jit_build_body(struct sk_filter *fp, u32 *image, | |||
193 | PPC_MUL(r_A, r_A, r_scratch1); | 187 | PPC_MUL(r_A, r_A, r_scratch1); |
194 | } | 188 | } |
195 | break; | 189 | break; |
190 | case BPF_S_ALU_MOD_X: /* A %= X; */ | ||
191 | ctx->seen |= SEEN_XREG; | ||
192 | PPC_CMPWI(r_X, 0); | ||
193 | if (ctx->pc_ret0 != -1) { | ||
194 | PPC_BCC(COND_EQ, addrs[ctx->pc_ret0]); | ||
195 | } else { | ||
196 | PPC_BCC_SHORT(COND_NE, (ctx->idx*4)+12); | ||
197 | PPC_LI(r_ret, 0); | ||
198 | PPC_JMP(exit_addr); | ||
199 | } | ||
200 | PPC_DIVWU(r_scratch1, r_A, r_X); | ||
201 | PPC_MUL(r_scratch1, r_X, r_scratch1); | ||
202 | PPC_SUB(r_A, r_A, r_scratch1); | ||
203 | break; | ||
204 | case BPF_S_ALU_MOD_K: /* A %= K; */ | ||
205 | PPC_LI32(r_scratch2, K); | ||
206 | PPC_DIVWU(r_scratch1, r_A, r_scratch2); | ||
207 | PPC_MUL(r_scratch1, r_scratch2, r_scratch1); | ||
208 | PPC_SUB(r_A, r_A, r_scratch1); | ||
209 | break; | ||
196 | case BPF_S_ALU_DIV_X: /* A /= X; */ | 210 | case BPF_S_ALU_DIV_X: /* A /= X; */ |
197 | ctx->seen |= SEEN_XREG; | 211 | ctx->seen |= SEEN_XREG; |
198 | PPC_CMPWI(r_X, 0); | 212 | PPC_CMPWI(r_X, 0); |
@@ -346,18 +360,11 @@ static int bpf_jit_build_body(struct sk_filter *fp, u32 *image, | |||
346 | break; | 360 | break; |
347 | 361 | ||
348 | /*** Ancillary info loads ***/ | 362 | /*** Ancillary info loads ***/ |
349 | |||
350 | /* None of the BPF_S_ANC* codes appear to be passed by | ||
351 | * sk_chk_filter(). The interpreter and the x86 BPF | ||
352 | * compiler implement them so we do too -- they may be | ||
353 | * planted in future. | ||
354 | */ | ||
355 | case BPF_S_ANC_PROTOCOL: /* A = ntohs(skb->protocol); */ | 363 | case BPF_S_ANC_PROTOCOL: /* A = ntohs(skb->protocol); */ |
356 | BUILD_BUG_ON(FIELD_SIZEOF(struct sk_buff, | 364 | BUILD_BUG_ON(FIELD_SIZEOF(struct sk_buff, |
357 | protocol) != 2); | 365 | protocol) != 2); |
358 | PPC_LHZ_OFFS(r_A, r_skb, offsetof(struct sk_buff, | 366 | PPC_NTOHS_OFFS(r_A, r_skb, offsetof(struct sk_buff, |
359 | protocol)); | 367 | protocol)); |
360 | /* ntohs is a NOP with BE loads. */ | ||
361 | break; | 368 | break; |
362 | case BPF_S_ANC_IFINDEX: | 369 | case BPF_S_ANC_IFINDEX: |
363 | PPC_LD_OFFS(r_scratch1, r_skb, offsetof(struct sk_buff, | 370 | PPC_LD_OFFS(r_scratch1, r_skb, offsetof(struct sk_buff, |
@@ -691,4 +698,5 @@ void bpf_jit_free(struct sk_filter *fp) | |||
691 | { | 698 | { |
692 | if (fp->bpf_func != sk_run_filter) | 699 | if (fp->bpf_func != sk_run_filter) |
693 | module_free(NULL, fp->bpf_func); | 700 | module_free(NULL, fp->bpf_func); |
701 | kfree(fp); | ||
694 | } | 702 | } |