diff options
Diffstat (limited to 'arch/powerpc/net/bpf_jit_comp.c')
-rw-r--r-- | arch/powerpc/net/bpf_jit_comp.c | 26 |
1 files changed, 9 insertions, 17 deletions
diff --git a/arch/powerpc/net/bpf_jit_comp.c b/arch/powerpc/net/bpf_jit_comp.c index 73619d3aeb6c..2dc8b1484845 100644 --- a/arch/powerpc/net/bpf_jit_comp.c +++ b/arch/powerpc/net/bpf_jit_comp.c | |||
@@ -127,6 +127,9 @@ static void bpf_jit_build_epilogue(u32 *image, struct codegen_context *ctx) | |||
127 | PPC_BLR(); | 127 | PPC_BLR(); |
128 | } | 128 | } |
129 | 129 | ||
130 | #define CHOOSE_LOAD_FUNC(K, func) \ | ||
131 | ((int)K < 0 ? ((int)K >= SKF_LL_OFF ? func##_negative_offset : func) : func##_positive_offset) | ||
132 | |||
130 | /* Assemble the body code between the prologue & epilogue. */ | 133 | /* Assemble the body code between the prologue & epilogue. */ |
131 | static int bpf_jit_build_body(struct sk_filter *fp, u32 *image, | 134 | static int bpf_jit_build_body(struct sk_filter *fp, u32 *image, |
132 | struct codegen_context *ctx, | 135 | struct codegen_context *ctx, |
@@ -391,21 +394,16 @@ static int bpf_jit_build_body(struct sk_filter *fp, u32 *image, | |||
391 | 394 | ||
392 | /*** Absolute loads from packet header/data ***/ | 395 | /*** Absolute loads from packet header/data ***/ |
393 | case BPF_S_LD_W_ABS: | 396 | case BPF_S_LD_W_ABS: |
394 | func = sk_load_word; | 397 | func = CHOOSE_LOAD_FUNC(K, sk_load_word); |
395 | goto common_load; | 398 | goto common_load; |
396 | case BPF_S_LD_H_ABS: | 399 | case BPF_S_LD_H_ABS: |
397 | func = sk_load_half; | 400 | func = CHOOSE_LOAD_FUNC(K, sk_load_half); |
398 | goto common_load; | 401 | goto common_load; |
399 | case BPF_S_LD_B_ABS: | 402 | case BPF_S_LD_B_ABS: |
400 | func = sk_load_byte; | 403 | func = CHOOSE_LOAD_FUNC(K, sk_load_byte); |
401 | common_load: | 404 | common_load: |
402 | /* | 405 | /* Load from [K]. */ |
403 | * Load from [K]. Reference with the (negative) | ||
404 | * SKF_NET_OFF/SKF_LL_OFF offsets is unsupported. | ||
405 | */ | ||
406 | ctx->seen |= SEEN_DATAREF; | 406 | ctx->seen |= SEEN_DATAREF; |
407 | if ((int)K < 0) | ||
408 | return -ENOTSUPP; | ||
409 | PPC_LI64(r_scratch1, func); | 407 | PPC_LI64(r_scratch1, func); |
410 | PPC_MTLR(r_scratch1); | 408 | PPC_MTLR(r_scratch1); |
411 | PPC_LI32(r_addr, K); | 409 | PPC_LI32(r_addr, K); |
@@ -429,7 +427,7 @@ static int bpf_jit_build_body(struct sk_filter *fp, u32 *image, | |||
429 | common_load_ind: | 427 | common_load_ind: |
430 | /* | 428 | /* |
431 | * Load from [X + K]. Negative offsets are tested for | 429 | * Load from [X + K]. Negative offsets are tested for |
432 | * in the helper functions, and result in a 'ret 0'. | 430 | * in the helper functions. |
433 | */ | 431 | */ |
434 | ctx->seen |= SEEN_DATAREF | SEEN_XREG; | 432 | ctx->seen |= SEEN_DATAREF | SEEN_XREG; |
435 | PPC_LI64(r_scratch1, func); | 433 | PPC_LI64(r_scratch1, func); |
@@ -443,13 +441,7 @@ static int bpf_jit_build_body(struct sk_filter *fp, u32 *image, | |||
443 | break; | 441 | break; |
444 | 442 | ||
445 | case BPF_S_LDX_B_MSH: | 443 | case BPF_S_LDX_B_MSH: |
446 | /* | 444 | func = CHOOSE_LOAD_FUNC(K, sk_load_byte_msh); |
447 | * x86 version drops packet (RET 0) when K<0, whereas | ||
448 | * interpreter does allow K<0 (__load_pointer, special | ||
449 | * ancillary data). common_load returns ENOTSUPP if K<0, | ||
450 | * so we fall back to interpreter & filter works. | ||
451 | */ | ||
452 | func = sk_load_byte_msh; | ||
453 | goto common_load; | 445 | goto common_load; |
454 | break; | 446 | break; |
455 | 447 | ||