aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm64/net/bpf_jit_comp.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/arm64/net/bpf_jit_comp.c')
-rw-r--r--arch/arm64/net/bpf_jit_comp.c84
1 files changed, 74 insertions, 10 deletions
diff --git a/arch/arm64/net/bpf_jit_comp.c b/arch/arm64/net/bpf_jit_comp.c
index 7ae33545535b..41f1e3e2ea24 100644
--- a/arch/arm64/net/bpf_jit_comp.c
+++ b/arch/arm64/net/bpf_jit_comp.c
@@ -19,12 +19,13 @@
19#define pr_fmt(fmt) "bpf_jit: " fmt 19#define pr_fmt(fmt) "bpf_jit: " fmt
20 20
21#include <linux/filter.h> 21#include <linux/filter.h>
22#include <linux/moduleloader.h>
23#include <linux/printk.h> 22#include <linux/printk.h>
24#include <linux/skbuff.h> 23#include <linux/skbuff.h>
25#include <linux/slab.h> 24#include <linux/slab.h>
25
26#include <asm/byteorder.h> 26#include <asm/byteorder.h>
27#include <asm/cacheflush.h> 27#include <asm/cacheflush.h>
28#include <asm/debug-monitors.h>
28 29
29#include "bpf_jit.h" 30#include "bpf_jit.h"
30 31
@@ -119,6 +120,14 @@ static inline int bpf2a64_offset(int bpf_to, int bpf_from,
119 return to - from; 120 return to - from;
120} 121}
121 122
123static void jit_fill_hole(void *area, unsigned int size)
124{
125 u32 *ptr;
126 /* We are guaranteed to have aligned memory. */
127 for (ptr = area; size >= sizeof(u32); size -= sizeof(u32))
128 *ptr++ = cpu_to_le32(AARCH64_BREAK_FAULT);
129}
130
122static inline int epilogue_offset(const struct jit_ctx *ctx) 131static inline int epilogue_offset(const struct jit_ctx *ctx)
123{ 132{
124 int to = ctx->offset[ctx->prog->len - 1]; 133 int to = ctx->offset[ctx->prog->len - 1];
@@ -196,6 +205,12 @@ static void build_epilogue(struct jit_ctx *ctx)
196 emit(A64_RET(A64_LR), ctx); 205 emit(A64_RET(A64_LR), ctx);
197} 206}
198 207
208/* JITs an eBPF instruction.
209 * Returns:
210 * 0 - successfully JITed an 8-byte eBPF instruction.
211 * >0 - successfully JITed a 16-byte eBPF instruction.
212 * <0 - failed to JIT.
213 */
199static int build_insn(const struct bpf_insn *insn, struct jit_ctx *ctx) 214static int build_insn(const struct bpf_insn *insn, struct jit_ctx *ctx)
200{ 215{
201 const u8 code = insn->code; 216 const u8 code = insn->code;
@@ -252,6 +267,18 @@ static int build_insn(const struct bpf_insn *insn, struct jit_ctx *ctx)
252 emit(A64_MUL(is64, tmp, tmp, src), ctx); 267 emit(A64_MUL(is64, tmp, tmp, src), ctx);
253 emit(A64_SUB(is64, dst, dst, tmp), ctx); 268 emit(A64_SUB(is64, dst, dst, tmp), ctx);
254 break; 269 break;
270 case BPF_ALU | BPF_LSH | BPF_X:
271 case BPF_ALU64 | BPF_LSH | BPF_X:
272 emit(A64_LSLV(is64, dst, dst, src), ctx);
273 break;
274 case BPF_ALU | BPF_RSH | BPF_X:
275 case BPF_ALU64 | BPF_RSH | BPF_X:
276 emit(A64_LSRV(is64, dst, dst, src), ctx);
277 break;
278 case BPF_ALU | BPF_ARSH | BPF_X:
279 case BPF_ALU64 | BPF_ARSH | BPF_X:
280 emit(A64_ASRV(is64, dst, dst, src), ctx);
281 break;
255 /* dst = -dst */ 282 /* dst = -dst */
256 case BPF_ALU | BPF_NEG: 283 case BPF_ALU | BPF_NEG:
257 case BPF_ALU64 | BPF_NEG: 284 case BPF_ALU64 | BPF_NEG:
@@ -443,6 +470,27 @@ emit_cond_jmp:
443 emit(A64_B(jmp_offset), ctx); 470 emit(A64_B(jmp_offset), ctx);
444 break; 471 break;
445 472
473 /* dst = imm64 */
474 case BPF_LD | BPF_IMM | BPF_DW:
475 {
476 const struct bpf_insn insn1 = insn[1];
477 u64 imm64;
478
479 if (insn1.code != 0 || insn1.src_reg != 0 ||
480 insn1.dst_reg != 0 || insn1.off != 0) {
481 /* Note: verifier in BPF core must catch invalid
482 * instructions.
483 */
484 pr_err_once("Invalid BPF_LD_IMM64 instruction\n");
485 return -EINVAL;
486 }
487
488 imm64 = (u64)insn1.imm << 32 | imm;
489 emit_a64_mov_i64(dst, imm64, ctx);
490
491 return 1;
492 }
493
446 /* LDX: dst = *(size *)(src + off) */ 494 /* LDX: dst = *(size *)(src + off) */
447 case BPF_LDX | BPF_MEM | BPF_W: 495 case BPF_LDX | BPF_MEM | BPF_W:
448 case BPF_LDX | BPF_MEM | BPF_H: 496 case BPF_LDX | BPF_MEM | BPF_H:
@@ -594,6 +642,10 @@ static int build_body(struct jit_ctx *ctx)
594 ctx->offset[i] = ctx->idx; 642 ctx->offset[i] = ctx->idx;
595 643
596 ret = build_insn(insn, ctx); 644 ret = build_insn(insn, ctx);
645 if (ret > 0) {
646 i++;
647 continue;
648 }
597 if (ret) 649 if (ret)
598 return ret; 650 return ret;
599 } 651 }
@@ -613,8 +665,10 @@ void bpf_jit_compile(struct bpf_prog *prog)
613 665
614void bpf_int_jit_compile(struct bpf_prog *prog) 666void bpf_int_jit_compile(struct bpf_prog *prog)
615{ 667{
668 struct bpf_binary_header *header;
616 struct jit_ctx ctx; 669 struct jit_ctx ctx;
617 int image_size; 670 int image_size;
671 u8 *image_ptr;
618 672
619 if (!bpf_jit_enable) 673 if (!bpf_jit_enable)
620 return; 674 return;
@@ -636,23 +690,25 @@ void bpf_int_jit_compile(struct bpf_prog *prog)
636 goto out; 690 goto out;
637 691
638 build_prologue(&ctx); 692 build_prologue(&ctx);
639
640 build_epilogue(&ctx); 693 build_epilogue(&ctx);
641 694
642 /* Now we know the actual image size. */ 695 /* Now we know the actual image size. */
643 image_size = sizeof(u32) * ctx.idx; 696 image_size = sizeof(u32) * ctx.idx;
644 ctx.image = module_alloc(image_size); 697 header = bpf_jit_binary_alloc(image_size, &image_ptr,
645 if (unlikely(ctx.image == NULL)) 698 sizeof(u32), jit_fill_hole);
699 if (header == NULL)
646 goto out; 700 goto out;
647 701
648 /* 2. Now, the actual pass. */ 702 /* 2. Now, the actual pass. */
649 703
704 ctx.image = (u32 *)image_ptr;
650 ctx.idx = 0; 705 ctx.idx = 0;
706
651 build_prologue(&ctx); 707 build_prologue(&ctx);
652 708
653 ctx.body_offset = ctx.idx; 709 ctx.body_offset = ctx.idx;
654 if (build_body(&ctx)) { 710 if (build_body(&ctx)) {
655 module_free(NULL, ctx.image); 711 bpf_jit_binary_free(header);
656 goto out; 712 goto out;
657 } 713 }
658 714
@@ -663,17 +719,25 @@ void bpf_int_jit_compile(struct bpf_prog *prog)
663 bpf_jit_dump(prog->len, image_size, 2, ctx.image); 719 bpf_jit_dump(prog->len, image_size, 2, ctx.image);
664 720
665 bpf_flush_icache(ctx.image, ctx.image + ctx.idx); 721 bpf_flush_icache(ctx.image, ctx.image + ctx.idx);
666 prog->bpf_func = (void *)ctx.image;
667 prog->jited = 1;
668 722
723 set_memory_ro((unsigned long)header, header->pages);
724 prog->bpf_func = (void *)ctx.image;
725 prog->jited = true;
669out: 726out:
670 kfree(ctx.offset); 727 kfree(ctx.offset);
671} 728}
672 729
673void bpf_jit_free(struct bpf_prog *prog) 730void bpf_jit_free(struct bpf_prog *prog)
674{ 731{
675 if (prog->jited) 732 unsigned long addr = (unsigned long)prog->bpf_func & PAGE_MASK;
676 module_free(NULL, prog->bpf_func); 733 struct bpf_binary_header *header = (void *)addr;
734
735 if (!prog->jited)
736 goto free_filter;
737
738 set_memory_rw(addr, header->pages);
739 bpf_jit_binary_free(header);
677 740
678 kfree(prog); 741free_filter:
742 bpf_prog_unlock_free(prog);
679} 743}