perf bpf: Add prologue for BPF programs for fetching arguments
authorHe Kuang <hekuang@huawei.com>
Mon, 16 Nov 2015 12:10:12 +0000 (12:10 +0000)
committerArnaldo Carvalho de Melo <acme@redhat.com>
Wed, 18 Nov 2015 20:51:04 +0000 (17:51 -0300)
commitbfc077b4cf106793b30bf942e426ee99f1f4ac44
treed4407dbe9c60203cc92642d1514bfd3986f4eb8b
parent03e01f568759ddbfdaff892e299758e7771a3478
perf bpf: Add prologue for BPF programs for fetching arguments

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>
tools/perf/util/Build
tools/perf/util/bpf-loader.c
tools/perf/util/bpf-loader.h
tools/perf/util/bpf-prologue.c [new file with mode: 0644]
tools/perf/util/bpf-prologue.h [new file with mode: 0644]