aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/bpf/core.c
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/bpf/core.c')
-rw-r--r--kernel/bpf/core.c34
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
675int 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
675static int bpf_jit_blind_insn(const struct bpf_insn *from, 709static 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)