diff options
author | Wolfram Sang <wsa@the-dreams.de> | 2018-12-11 20:58:20 +0100 |
---|---|---|
committer | Wolfram Sang <wsa@the-dreams.de> | 2018-12-11 20:58:20 +0100 |
commit | 66693960f574aa830986e1603657af36423b24eb (patch) | |
tree | 035aae54d64d79e514f95e18cc3dcf411a98c55e /kernel/bpf/core.c | |
parent | 3ca3f86f7f4856222a8b697d60d32717160a1a1b (diff) | |
parent | 40e020c129cfc991e8ab4736d2665351ffd1468d (diff) |
Merge tag 'v4.20-rc6' into i2c/for-5.0
Linux 4.20-rc6
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) bpf_prog_unlock_free(fp); } +int bpf_jit_get_func_addr(const struct bpf_prog *prog, + const struct bpf_insn *insn, bool extra_pass, + u64 *func_addr, bool *func_addr_fixed) +{ + s16 off = insn->off; + s32 imm = insn->imm; + u8 *addr; + + *func_addr_fixed = insn->src_reg != BPF_PSEUDO_CALL; + if (!*func_addr_fixed) { + /* Place-holder address till the last pass has collected + * all addresses for JITed subprograms in which case we + * can pick them up from prog->aux. + */ + if (!extra_pass) + addr = NULL; + else if (prog->aux->func && + off >= 0 && off < prog->aux->func_cnt) + addr = (u8 *)prog->aux->func[off]->bpf_func; + else + return -EINVAL; + } else { + /* Address of a BPF helper call. Since part of the core + * kernel, it's always at a fixed location. __bpf_call_base + * and the helper with imm relative to it are both in core + * kernel. + */ + addr = (u8 *)__bpf_call_base + imm; + } + + *func_addr = (unsigned long)addr; + return 0; +} + static int bpf_jit_blind_insn(const struct bpf_insn *from, const struct bpf_insn *aux, struct bpf_insn *to_buff) |