Skip to content
  • He Kuang's avatar
    perf bpf: Add prologue for BPF programs for fetching arguments · bfc077b4
    He Kuang authored
    
    
    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: default avatarHe Kuang <hekuang@huawei.com>
    Tested-by: default avatarArnaldo 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: default avatarWang Nan <wangnan0@huawei.com>
    Signed-off-by: default avatarArnaldo Carvalho de Melo <acme@redhat.com>
    bfc077b4