forked from Minki/linux
bfc077b4cf
This patch generates a prologue for a BPF program which fetches arguments for it. With this patch, the program can have arguments as follow: SEC("lock_page=__lock_page page->flags") int lock_page(struct pt_regs *ctx, int err, unsigned long flags) { return 1; } This patch passes at most 3 arguments from r3, r4 and r5. r1 is still the ctx pointer. r2 is used to indicate if dereferencing was done successfully. This patch uses r6 to hold ctx (struct pt_regs) and r7 to hold stack pointer for result. Result of each arguments first store on stack: low address BPF_REG_FP - 24 ARG3 BPF_REG_FP - 16 ARG2 BPF_REG_FP - 8 ARG1 BPF_REG_FP high address Then loaded into r3, r4 and r5. The output prologue for offn(...off2(off1(reg)))) should be: r6 <- r1 // save ctx into a callee saved register r7 <- fp r7 <- r7 - stack_offset // pointer to result slot /* load r3 with the offset in pt_regs of 'reg' */ (r7) <- r3 // make slot valid r3 <- r3 + off1 // prepare to read unsafe pointer r2 <- 8 r1 <- r7 // result put onto stack call probe_read // read unsafe pointer jnei r0, 0, err // error checking r3 <- (r7) // read result r3 <- r3 + off2 // prepare to read unsafe pointer r2 <- 8 r1 <- r7 call probe_read jnei r0, 0, err ... /* load r2, r3, r4 from stack */ goto success err: r2 <- 1 /* load r3, r4, r5 with 0 */ goto usercode success: r2 <- 0 usercode: r1 <- r6 // restore ctx // original user code If all of arguments reside in register (dereferencing is not required), gen_prologue_fastpath() will be used to create fast prologue: r3 <- (r1 + offset of reg1) r4 <- (r1 + offset of reg2) r5 <- (r1 + offset of reg3) r2 <- 0 P.S. eBPF calling convention is defined as: * r0 - return value from in-kernel function, and exit value for eBPF program * r1 - r5 - arguments from eBPF program to in-kernel function * r6 - r9 - callee saved registers that in-kernel function will preserve * r10 - read-only frame pointer to access stack Committer note: At least testing if it builds and loads: # cat test_probe_arg.c struct pt_regs; __attribute__((section("lock_page=__lock_page page->flags"), used)) int func(struct pt_regs *ctx, int err, unsigned long flags) { return 1; } char _license[] __attribute__((section("license"), used)) = "GPL"; int _version __attribute__((section("version"), used)) = 0x40300; # perf record -e ./test_probe_arg.c usleep 1 [ perf record: Woken up 1 times to write data ] [ perf record: Captured and wrote 0.016 MB perf.data ] # perf evlist perf_bpf_probe:lock_page # Signed-off-by: He Kuang <hekuang@huawei.com> Tested-by: Arnaldo Carvalho de Melo <acme@redhat.com> Cc: Alexei Starovoitov <ast@kernel.org> Cc: Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com> Cc: Wang Nan <wangnan0@huawei.com> Cc: Zefan Li <lizefan@huawei.com> Cc: pi3orama@163.com Link: http://lkml.kernel.org/r/1447675815-166222-11-git-send-email-wangnan0@huawei.com Signed-off-by: Wang Nan <wangnan0@huawei.com> Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
35 lines
847 B
C
35 lines
847 B
C
/*
|
|
* Copyright (C) 2015, He Kuang <hekuang@huawei.com>
|
|
* Copyright (C) 2015, Huawei Inc.
|
|
*/
|
|
#ifndef __BPF_PROLOGUE_H
|
|
#define __BPF_PROLOGUE_H
|
|
|
|
#include <linux/compiler.h>
|
|
#include <linux/filter.h>
|
|
#include "probe-event.h"
|
|
|
|
#define BPF_PROLOGUE_MAX_ARGS 3
|
|
#define BPF_PROLOGUE_START_ARG_REG BPF_REG_3
|
|
#define BPF_PROLOGUE_FETCH_RESULT_REG BPF_REG_2
|
|
|
|
#ifdef HAVE_BPF_PROLOGUE
|
|
int bpf__gen_prologue(struct probe_trace_arg *args, int nargs,
|
|
struct bpf_insn *new_prog, size_t *new_cnt,
|
|
size_t cnt_space);
|
|
#else
|
|
static inline int
|
|
bpf__gen_prologue(struct probe_trace_arg *args __maybe_unused,
|
|
int nargs __maybe_unused,
|
|
struct bpf_insn *new_prog __maybe_unused,
|
|
size_t *new_cnt,
|
|
size_t cnt_space __maybe_unused)
|
|
{
|
|
if (!new_cnt)
|
|
return -EINVAL;
|
|
*new_cnt = 0;
|
|
return -ENOTSUP;
|
|
}
|
|
#endif
|
|
#endif /* __BPF_PROLOGUE_H */
|