diff options
Diffstat (limited to 'kernel/bpf/core.c')
-rw-r--r-- | kernel/bpf/core.c | 34 |
1 files changed, 34 insertions, 0 deletions
diff --git a/kernel/bpf/core.c b/kernel/bpf/core.c index 1a796e0799ec..b1a3545d0ec8 100644 --- a/kernel/bpf/core.c +++ b/kernel/bpf/core.c | |||
@@ -672,6 +672,40 @@ void __weak bpf_jit_free(struct bpf_prog *fp) | |||
672 | bpf_prog_unlock_free(fp); | 672 | bpf_prog_unlock_free(fp); |
673 | } | 673 | } |
674 | 674 | ||
675 | int bpf_jit_get_func_addr(const struct bpf_prog *prog, | ||
676 | const struct bpf_insn *insn, bool extra_pass, | ||
677 | u64 *func_addr, bool *func_addr_fixed) | ||
678 | { | ||
679 | s16 off = insn->off; | ||
680 | s32 imm = insn->imm; | ||
681 | u8 *addr; | ||
682 | |||
683 | *func_addr_fixed = insn->src_reg != BPF_PSEUDO_CALL; | ||
684 | if (!*func_addr_fixed) { | ||
685 | /* Place-holder address till the last pass has collected | ||
686 | * all addresses for JITed subprograms in which case we | ||
687 | * can pick them up from prog->aux. | ||
688 | */ | ||
689 | if (!extra_pass) | ||
690 | addr = NULL; | ||
691 | else if (prog->aux->func && | ||
692 | off >= 0 && off < prog->aux->func_cnt) | ||
693 | addr = (u8 *)prog->aux->func[off]->bpf_func; | ||
694 | else | ||
695 | return -EINVAL; | ||
696 | } else { | ||
697 | /* Address of a BPF helper call. Since part of the core | ||
698 | * kernel, it's always at a fixed location. __bpf_call_base | ||
699 | * and the helper with imm relative to it are both in core | ||
700 | * kernel. | ||
701 | */ | ||
702 | addr = (u8 *)__bpf_call_base + imm; | ||
703 | } | ||
704 | |||
705 | *func_addr = (unsigned long)addr; | ||
706 | return 0; | ||
707 | } | ||
708 | |||
675 | static int bpf_jit_blind_insn(const struct bpf_insn *from, | 709 | static int bpf_jit_blind_insn(const struct bpf_insn *from, |
676 | const struct bpf_insn *aux, | 710 | const struct bpf_insn *aux, |
677 | struct bpf_insn *to_buff) | 711 | struct bpf_insn *to_buff) |