aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc/net/bpf_jit_comp.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/powerpc/net/bpf_jit_comp.c')
-rw-r--r--arch/powerpc/net/bpf_jit_comp.c38
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
25int bpf_jit_enable __read_mostly; 20int bpf_jit_enable __read_mostly;
26 21
27
28static inline void bpf_flush_icache(void *start, void *end) 22static 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}