public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
* [RFC PATCH 0/4] perf tools: Use the new ability of eBPF programs to access hardware PMU counter
@ 2015-08-27 10:42 Kaixu Xia
  2015-08-27 10:42 ` [RFC PATCH 1/4] bpf tools: Add bpf_update_elem() and perf_event_open() for common bpf operations Kaixu Xia
                   ` (4 more replies)
  0 siblings, 5 replies; 8+ messages in thread
From: Kaixu Xia @ 2015-08-27 10:42 UTC (permalink / raw)
  To: ast, davem, daniel, acme, mingo, a.p.zijlstra,
	masami.hiramatsu.pt, jolsa
  Cc: linux-kernel, wangnan0, pi3orama, xiakaixu

According to the discussions on this subject https://lkml.org/lkml/2015/5/27/1027,
we want to give eBPF programs the ability to access hardware PMU counter
and use this ability with perf.

Now the kernel side patch set 'bpf: Introduce the new ability of eBPF
programs to access hardware PMU counter' has been applied and can be
found in the net-next tree.

  ffe8690c85b8 ("perf: add the necessary core perf APIs when accessing events counters in eBPF programs")
  2a36f0b92eb6 ("bpf: Make the bpf_prog_array_map more generic")
  ea317b267e9d ("bpf: Add new bpf map type to store the pointer to struct perf_event")
  35578d798400 ("bpf: Implement function bpf_perf_event_read() that get the selected hardware PMU conuter")
  47efb30274cb ("samples/bpf: example of get selected PMU counter value")

According to the design plan, we still need the perf side code.
This patch set based on Wang Nan's patches (perf tools: filtering events
using eBPF programs).
(git://git.kernel.org/pub/scm/linux/kernel/git/pi3orama/linux tags/perf-ebpf-for-acme-20150821)
The kernel side patch set above also need to be mergerd if you want to
test this patch set.

An example is pasted at the bottom of this cover letter. In that example,
we can get the cpu_cycles and exception taken in sys_write.

 $ cat /sys/kernel/debug/tracing/trace_pipe
 $ ./perf record --event perf-bpf.o ls
	...
             cat-1653  [003] d..1 88174.613854: : ente:  CPU-3	cyc:48746333	exc:84
             cat-1653  [003] d..2 88174.613861: : exit:  CPU-3	cyc:48756041	exc:84
             cat-1653  [003] d..1 88174.613872: : ente:  CPU-3	cyc:48771199	exc:86
             cat-1653  [003] d..2 88174.613879: : exit:  CPU-3	cyc:48780448	exc:86
             cat-1678  [003] d..1 88174.615001: : ente:  CPU-3	cyc:50293479	exc:93
            sshd-1669  [000] d..1 88174.615199: : ente:  CPU-0	cyc:44402694	exc:51
            sshd-1669  [000] d..2 88174.615283: : exit:  CPU-0	cyc:44517335	exc:51
              ls-1680  [003] d..1 88174.620260: : ente:  CPU-3	cyc:57281750	exc:241
            sshd-1669  [000] d..1 88174.620474: : ente:  CPU-0	cyc:44998837	exc:69
            sshd-1669  [000] d..2 88174.620549: : exit:  CPU-0	cyc:45101855	exc:69
            sshd-1669  [000] d..1 88174.620608: : ente:  CPU-0	cyc:45181848	exc:77
            sshd-1669  [000] d..2 88174.620709: : exit:  CPU-0	cyc:45317439	exc:78
            sshd-1669  [000] d..1 88174.620801: : ente:  CPU-0	cyc:45441321	exc:87
            sshd-1669  [000] d..2 88174.620856: : exit:  CPU-0	cyc:45515882	exc:87
	...

Limitation of this patch set: The eBPF programs can only create and access
the perf events depend on CPUs and can not do that depend on PID.

The detail of patches is as follow:

Patch 1/4 introduces bpf_update_elem() and perf_event_open() in
introduces bpf_update_elem() and perf_event_open(). We can store
the pointers to struct perf_event to maps;

Patch 2/4 collects BPF_MAP_TYPE_PERF_EVENT_ARRAY map definitions
from 'maps' section and get the event & map match;

Patch 3/4 saves the perf event fds from "maps" sections to
'struct bpf_object'. So we can enable/disable these perf events
at the appropriate time;

Patch 4/4 enable/disable the perf events stored in 'struct bpf_object';

  -------- EXAMPL --------
  ----- perf-bpf.c -----
 
 struct perf_event_map_def SEC("maps") my_cycles_map = {
 	.map_def = {
                .type = BPF_MAP_TYPE_PERF_EVENT_ARRAY,
                .key_size = sizeof(int),
                .value_size = sizeof(u32),
                .max_entries = 32,
        },
        .attr = {
                .freq = 0,
                .inherit = 0,
                .sample_period = 0x7fffffffffffffffULL,
                .type = PERF_TYPE_HARDWARE,
                .read_format = 0,
                .sample_type = 0,
                .config = 0,/* PMU: cycles */
        },
 };

 struct perf_event_map_def SEC("maps") my_exception_map = {
        .map_def = {
                .type = BPF_MAP_TYPE_PERF_EVENT_ARRAY,
                .key_size = sizeof(int),
                .value_size = sizeof(u32),
                .max_entries = 32,
        },
        .attr = {
                .freq = 0,
                .inherit = 0,
                .sample_period = 0x7fffffffffffffffULL,
                .type = PERF_TYPE_RAW,
                .read_format = 0,
                .sample_type = 0,
                .config = 0x09,/* PMU: exception */
        },
 };

 SEC("ente=sys_write")
 int bpf_prog_1(struct pt_regs *ctx)
 {
        u64 count_cycles, count_exception;
        u32 key = bpf_get_smp_processor_id();
        char fmt[] = "ente:  CPU-%d     cyc:%llu        exc:%llu\n";

        count_cycles = bpf_perf_event_read(&my_cycles_map, key);
        count_exception = bpf_perf_event_read(&my_exception_map, key);
        bpf_trace_printk(fmt, sizeof(fmt), key, count_cycles, count_exception);

        return 0;
 }

 SEC("exit=sys_write%return")
 int bpf_prog_2(struct pt_regs *ctx)
 {
        u64 count_cycles, count_exception;
        u32 key = bpf_get_smp_processor_id();
        char fmt[] = "exit:  CPU-%d     cyc:%llu        exc:%llu\n";

        count_cycles = bpf_perf_event_read(&my_cycles_map, key);
        count_exception = bpf_perf_event_read(&my_exception_map, key);
        bpf_trace_printk(fmt, sizeof(fmt), key, count_cycles, count_exception);

        return 0;
 }

Kaixu Xia (4):
  bpf tools: Add bpf_update_elem() and perf_event_open() for common bpf
    operations
  bpf tools: Collect BPF_MAP_TYPE_PERF_EVENT_ARRAY map definitions from
    'maps' section
  bpf tools: Save the perf event fds from "maps" sections to 'struct
    bpf_object'
  bpf tools: Enable/disable the perf events stored in 'struct
    bpf_object'

 tools/lib/bpf/bpf.c    |  34 +++++++++++++
 tools/lib/bpf/bpf.h    |   4 ++
 tools/lib/bpf/libbpf.c | 130 +++++++++++++++++++++++++++++++++++++++++++------
 tools/lib/bpf/libbpf.h |  13 +++++
 4 files changed, 166 insertions(+), 15 deletions(-)

-- 
1.8.3.4


^ permalink raw reply	[flat|nested] 8+ messages in thread

end of thread, other threads:[~2015-08-29  2:42 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2015-08-27 10:42 [RFC PATCH 0/4] perf tools: Use the new ability of eBPF programs to access hardware PMU counter Kaixu Xia
2015-08-27 10:42 ` [RFC PATCH 1/4] bpf tools: Add bpf_update_elem() and perf_event_open() for common bpf operations Kaixu Xia
2015-08-27 10:42 ` [RFC PATCH 2/4] bpf tools: Collect BPF_MAP_TYPE_PERF_EVENT_ARRAY map definitions from 'maps' section Kaixu Xia
2015-08-27 10:42 ` [RFC PATCH 3/4] bpf tools: Save the perf event fds from "maps" sections to 'struct bpf_object' Kaixu Xia
2015-08-27 10:42 ` [RFC PATCH 4/4] bpf tools: Enable/disable the perf events stored in " Kaixu Xia
2015-08-29  1:28 ` [RFC PATCH 0/4] perf tools: Use the new ability of eBPF programs to access hardware PMU counter Alexei Starovoitov
2015-08-29  2:14   ` xiakaixu
2015-08-29  2:42     ` Alexei Starovoitov

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox