lkml.org 
[lkml]   [2015]   [Jul]   [17]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[RFC PATCH 6/6] samples/bpf: example of get selected PMU counter value
    Date
    This is a simple example and shows how to use the new ability
    to get the selected PMU counter value.

    The trace output:
    $ ./bpf_pmu_test
    $ cat /sys/kernel/debug/tracing/trace
    ...
    syslog-ng-555 [001] dn.1 10189.004626: : bpf count: CPU-0 9935764297
    syslog-ng-555 [001] d..1 10189.053776: : bpf count: CPU-0 10000706398
    syslog-ng-555 [001] dn.1 10189.102972: : bpf count: CPU-0 10067117321
    syslog-ng-555 [001] d..1 10189.152925: : bpf count: CPU-0 10134551505
    syslog-ng-555 [001] dn.1 10189.202043: : bpf count: CPU-0 10200869299
    syslog-ng-555 [001] d..1 10189.251167: : bpf count: CPU-0 10267179481
    syslog-ng-555 [001] dn.1 10189.300285: : bpf count: CPU-0 10333493522
    syslog-ng-555 [001] d..1 10189.349410: : bpf count: CPU-0 10399808073
    syslog-ng-555 [001] dn.1 10189.398528: : bpf count: CPU-0 10466121583
    syslog-ng-555 [001] d..1 10189.447645: : bpf count: CPU-0 10532433368
    syslog-ng-555 [001] d..1 10189.496841: : bpf count: CPU-0 10598841104
    syslog-ng-555 [001] d..1 10189.546891: : bpf count: CPU-0 10666410564
    syslog-ng-555 [001] dn.1 10189.596016: : bpf count: CPU-0 10732729739
    syslog-ng-555 [001] d..1 10189.645146: : bpf count: CPU-0 12884941186
    syslog-ng-555 [001] d..1 10189.694263: : bpf count: CPU-0 12951249903
    syslog-ng-555 [001] dn.1 10189.743382: : bpf count: CPU-0 13017561470
    syslog-ng-555 [001] d..1 10189.792506: : bpf count: CPU-0 13083873521
    syslog-ng-555 [001] d..1 10189.841631: : bpf count: CPU-0 13150190416
    syslog-ng-555 [001] d..1 10189.890749: : bpf count: CPU-0 13216505962
    syslog-ng-555 [001] d..1 10189.939945: : bpf count: CPU-0 13282913062
    ...

    Signed-off-by: kaixu xia <xiakaixu@huawei.com>
    ---
    samples/bpf/bpf_helpers.h | 2 +
    samples/bpf/bpf_pmu_test.c | 143 ++++++++++++++++++++++++++++++++++++++++++++
    2 files changed, 145 insertions(+)
    create mode 100644 samples/bpf/bpf_pmu_test.c

    diff --git a/samples/bpf/bpf_helpers.h b/samples/bpf/bpf_helpers.h
    index bdf1c16..a421be1 100644
    --- a/samples/bpf/bpf_helpers.h
    +++ b/samples/bpf/bpf_helpers.h
    @@ -31,6 +31,8 @@ static unsigned long long (*bpf_get_current_uid_gid)(void) =
    (void *) BPF_FUNC_get_current_uid_gid;
    static int (*bpf_get_current_comm)(void *buf, int buf_size) =
    (void *) BPF_FUNC_get_current_comm;
    +static int (*bpf_read_pmu)(void *pmu) =
    + (void *) BPF_FUNC_read_pmu;

    /* llvm builtin functions that eBPF C program may use to
    * emit BPF_LD_ABS and BPF_LD_IND instructions
    diff --git a/samples/bpf/bpf_pmu_test.c b/samples/bpf/bpf_pmu_test.c
    new file mode 100644
    index 0000000..aced233
    --- /dev/null
    +++ b/samples/bpf/bpf_pmu_test.c
    @@ -0,0 +1,143 @@
    +/* eBPF example program shows how to get hardware PMU counter
    + * - creates hashmap in kernel
    + *
    + * - save the pointer to struct perf_event to map
    + *
    + * - loads eBPF program:
    + * r0 = 0 (the chosen key: CPU-0)
    + * *(u32 *)(fp - 4) = r0
    + * value = bpf_map_lookup_elem(map_fd, fp - 4);
    + * count = bpf_read_pmu(value);
    + * bpf_trace_printk(fmt, fmt_size, key, count);
    + *
    + * - attaches this program to kprobes/sys_write
    + */
    +
    +#include <stdio.h>
    +#include <unistd.h>
    +#include <assert.h>
    +#include <linux/bpf.h>
    +#include <string.h>
    +#include <stdlib.h>
    +#include <errno.h>
    +#include <stddef.h>
    +#include <fcntl.h>
    +#include <poll.h>
    +#include <sys/ioctl.h>
    +#include <linux/perf_event.h>
    +#include "libbpf.h"
    +
    +static int test_pmu(void)
    +{
    + int kprobe_fd, prog_fd, i;
    + int nr_cpus = sysconf(_SC_NPROCESSORS_CONF);
    + int *pmu_fd = malloc(nr_cpus * sizeof(int));
    + int key, map_fd;
    + unsigned long value;
    +
    + char fmt[] = "bpf count: CPU-%d %lld\n";
    + int fmt_size = sizeof(fmt);
    +
    + int type = BPF_MAP_TYPE_HASH | BPF_MAP_FLAG_PERF_EVENT;
    +
    + map_fd = bpf_create_map(type, sizeof(key), sizeof(value),
    + nr_cpus);
    + if(map_fd < 0) {
    + printf("failed to create map '%s'\n", strerror(errno));
    + return -1;
    + }
    +
    + struct perf_event_attr attr_insn_kprobe = {
    + .sample_period = 1,
    + .type = PERF_TYPE_TRACEPOINT,
    + .sample_type = PERF_SAMPLE_RAW,
    + .wakeup_events = 1,
    + .config = 0x46B, /* sys_write (this ID maybe change) */
    + };
    +
    + struct perf_event_attr attr_insn_pmu = {
    + .freq = 0,
    + .sample_period = 0x7fffffffffffffffULL,
    + .inherit = 0,
    + .type = PERF_TYPE_RAW,
    + .read_format = 0,
    + .sample_type = 0,
    + .config = 0x11,/* PMU: cycles (ARM) */
    +
    + };
    +
    + for(i = 0; i < nr_cpus; i++) {
    + pmu_fd[i] = perf_event_open(&attr_insn_pmu, -1/*pid*/, i/*cpu*/, -1/*group_fd*/, 0);
    + if (pmu_fd[i] < 0) {
    + printf("event syscall failed ****\n");
    + return -1;
    + }
    +
    + ioctl(pmu_fd[i], PERF_EVENT_IOC_ENABLE, 0);
    +
    + bpf_update_elem(map_fd, &i, (pmu_fd + i), BPF_ANY);
    + }
    +
    + kprobe_fd = perf_event_open(&attr_insn_kprobe, -1/*pid*/, 0/*cpu*/, -1/*group_fd*/, 0);
    + if (kprobe_fd < 0) {
    + printf("kprobe event syscall failed ****\n");
    + return -1;
    + }
    + ioctl(kprobe_fd, PERF_EVENT_IOC_ENABLE, 0);
    +
    + struct bpf_insn prog[] = {
    + BPF_MOV64_IMM(BPF_REG_0, 0), /* r0 = 0 */
    + BPF_STX_MEM(BPF_W, BPF_REG_10, BPF_REG_0, -4), /* *(u32 *)(fp - 4) = r0 */
    + BPF_MOV64_REG(BPF_REG_2, BPF_REG_10), /* r2 = fp */
    + BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -4), /* r2 = fp - 4 */
    + BPF_LD_MAP_FD(BPF_REG_1, map_fd),
    + BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem),
    + BPF_MOV64_REG(BPF_REG_1, BPF_REG_0),
    + BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_read_pmu),
    + BPF_MOV64_REG(BPF_REG_6, BPF_REG_0),
    + BPF_MOV64_IMM(BPF_REG_1, 0),
    + BPF_STX_MEM(BPF_W, BPF_REG_10, BPF_REG_1, -8),
    + BPF_LD_IMM64(BPF_REG_1, 748842649785475172),
    + BPF_STX_MEM(BPF_DW, BPF_REG_10, BPF_REG_1, -16),
    + BPF_LD_IMM64(BPF_REG_1, 2678891156567243380),
    + BPF_STX_MEM(BPF_DW, BPF_REG_10, BPF_REG_1, -24),
    + BPF_LD_IMM64(BPF_REG_1, 7959390387983249506),
    + BPF_STX_MEM(BPF_DW, BPF_REG_10, BPF_REG_1, -32),
    + BPF_MOV64_REG(BPF_REG_1, BPF_REG_10),
    + BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, -32),
    + BPF_MOV64_IMM(BPF_REG_2, 25),
    + BPF_MOV64_IMM(BPF_REG_3, 0),
    + BPF_MOV64_REG(BPF_REG_4, BPF_REG_6),
    + BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_trace_printk),
    + BPF_EXIT_INSN(),
    + };
    +
    + prog_fd = bpf_prog_load(BPF_PROG_TYPE_KPROBE, prog, sizeof(prog),
    + "GPL", 0);
    + if (prog_fd < 0) {
    + printf("failed to load prog '%s'\n", strerror(errno));
    + return -1;
    + }
    +
    + ioctl(kprobe_fd, PERF_EVENT_IOC_SET_BPF, prog_fd);
    +
    + system("ls");
    + system("pwd");
    + system("sleep 4");
    +
    + for(i = 0; i < nr_cpus; i++) {
    + close(pmu_fd[i]);
    + }
    +
    + close(map_fd);
    +
    + free(pmu_fd);
    + return 0;
    +}
    +
    +int main(int argc, char **argv)
    +{
    + test_pmu();
    +
    + return 0;
    +}
    --
    1.7.10.4


    \
     
     \ /
      Last update: 2015-07-17 13:01    [W:3.925 / U:0.292 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site