aboutsummaryrefslogtreecommitdiffstats
path: root/tools/perf
diff options
context:
space:
mode:
authorIngo Molnar <mingo@kernel.org>2015-10-29 08:17:56 -0400
committerIngo Molnar <mingo@kernel.org>2015-10-29 08:17:56 -0400
commit66a565c203bc31b76969711fbd92da11bee2f129 (patch)
tree1d5a60b14b9f808b3c0cece5761002ad32f0e274 /tools/perf
parent6fc774ef4ceca99c35dd3fb230dab618f78c8d6f (diff)
parent4edf30e39e6cff32390eaff6a1508969b3cd967b (diff)
Merge tag 'perf-ebpf-for-mingo' of git://git.kernel.org/pub/scm/linux/kernel/git/acme/linux into perf/core
Pull basic perf/ebpf integration: "Please see the changeset comments, but this is the very basic integration of perf with libbpf that, given a .o file built for the 'bpf' target with clang, will get it validated and loaded into the kernel via the sys_bpf syscall, which can be seen using 'perf trace' to trace the whole thing looking just for the bpf and perf_event_open syscalls: # perf trace -e bpf,perf_event_open perf record -g --event /tmp/foo.o -a 362.779 ( 0.129 ms): perf/22408 bpf(cmd: 5, uattr: 0x7ffd4edb6db0, size: 48 ) = 3 384.192 ( 0.016 ms): perf/22408 perf_event_open(attr_uptr: 0x7ffd4edbace0, pid: -1, cpu: 3, group_fd: -1, flags: FD_CLOEXEC) = 5 384.247 ( 0.038 ms): perf/22408 perf_event_open(attr_uptr: 0x37aedd8, pid: -1, group_fd: -1, flags: FD_CLOEXEC) = 5 384.261 ( 0.007 ms): perf/22408 perf_event_open(attr_uptr: 0x37aedd8, pid: -1, group_fd: -1, flags: FD_CLOEXEC) = 5 387.680 ( 3.413 ms): perf/22408 perf_event_open(attr_uptr: 0x3222f08, pid: -1, group_fd: -1, flags: FD_CLOEXEC) = 5 387.688 ( 0.005 ms): perf/22408 perf_event_open(attr_uptr: 0x3222f08, pid: -1, cpu: 1, group_fd: -1, flags: FD_CLOEXEC) = 6 387.693 ( 0.004 ms): perf/22408 perf_event_open(attr_uptr: 0x3222f08, pid: -1, cpu: 2, group_fd: -1, flags: FD_CLOEXEC) = 7 387.698 ( 0.003 ms): perf/22408 perf_event_open(attr_uptr: 0x3222f08, pid: -1, cpu: 3, group_fd: -1, flags: FD_CLOEXEC) = 8 ^C[ perf record: Woken up 1 times to write data ] [ perf record: Captured and wrote 0.221 MB perf.data (2 samples) ] # perf script bash 18389 [002] 83446.412607: perf_bpf_probe:fork: (ffffffff8109be30) 29be31 _do_fork (/lib/modules/4.3.0-rc6+/build/vmlinux) 96d662 tracesys_phase2 (/lib/modules/4.3.0-rc6+/build/vmlinux) bd56c __libc_fork (/usr/lib64/libc-2.17.so) 413b2 make_child (/usr/bin/bash) bash 18389 [002] 83447.227255: perf_bpf_probe:fork: (ffffffff8109be30) 29be31 _do_fork (/lib/modules/4.3.0-rc6+/build/vmlinux) 96d662 tracesys_phase2 (/lib/modules/4.3.0-rc6+/build/vmlinux) bd56c __libc_fork (/usr/lib64/libc-2.17.so) 413b2 make_child (/usr/bin/bash) # perf evlist -v perf_bpf_probe:fork: type: 2, size: 112, config: 0x6cf, { sample_period, sample_freq }: 1, sample_type: IP|TID|TIME|CALLCHAIN|CPU|PERIOD|RAW, disabled: 1, inherit: 1, mmap: 1, comm: 1, task: 1, sample_id_all: 1, exclude_guest: 1, mmap2: 1, comm_exec: 1 # More work is about to be reviewed, tested and merged that will allow the whole process of going from a .c file to an .o file via clang, etc to be done automagically. (Wang Nan)" Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com> Signed-off-by: Ingo Molnar <mingo@kernel.org>
Diffstat (limited to 'tools/perf')
-rw-r--r--tools/perf/MANIFEST3
-rw-r--r--tools/perf/Makefile.perf21
-rw-r--r--tools/perf/config/Makefile19
-rw-r--r--tools/perf/perf.c2
-rw-r--r--tools/perf/tests/make4
-rw-r--r--tools/perf/util/Build1
-rw-r--r--tools/perf/util/bpf-loader.c339
-rw-r--r--tools/perf/util/bpf-loader.h84
-rw-r--r--tools/perf/util/parse-events.c118
-rw-r--r--tools/perf/util/parse-events.h8
-rw-r--r--tools/perf/util/parse-events.l3
-rw-r--r--tools/perf/util/parse-events.y18
12 files changed, 615 insertions, 5 deletions
diff --git a/tools/perf/MANIFEST b/tools/perf/MANIFEST
index 9e6bdf5b2df6..39c38cb45b00 100644
--- a/tools/perf/MANIFEST
+++ b/tools/perf/MANIFEST
@@ -17,6 +17,7 @@ tools/build
17tools/arch/x86/include/asm/atomic.h 17tools/arch/x86/include/asm/atomic.h
18tools/arch/x86/include/asm/rmwcc.h 18tools/arch/x86/include/asm/rmwcc.h
19tools/lib/traceevent 19tools/lib/traceevent
20tools/lib/bpf
20tools/lib/api 21tools/lib/api
21tools/lib/bpf 22tools/lib/bpf
22tools/lib/hweight.c 23tools/lib/hweight.c
@@ -69,6 +70,8 @@ arch/*/lib/memset*.S
69include/linux/poison.h 70include/linux/poison.h
70include/linux/hw_breakpoint.h 71include/linux/hw_breakpoint.h
71include/uapi/linux/perf_event.h 72include/uapi/linux/perf_event.h
73include/uapi/linux/bpf.h
74include/uapi/linux/bpf_common.h
72include/uapi/linux/const.h 75include/uapi/linux/const.h
73include/uapi/linux/swab.h 76include/uapi/linux/swab.h
74include/uapi/linux/hw_breakpoint.h 77include/uapi/linux/hw_breakpoint.h
diff --git a/tools/perf/Makefile.perf b/tools/perf/Makefile.perf
index 56517d304772..1e2e2d1d26b7 100644
--- a/tools/perf/Makefile.perf
+++ b/tools/perf/Makefile.perf
@@ -75,6 +75,8 @@ include config/utilities.mak
75# Define NO_LZMA if you do not want to support compressed (xz) kernel modules 75# Define NO_LZMA if you do not want to support compressed (xz) kernel modules
76# 76#
77# Define NO_AUXTRACE if you do not want AUX area tracing support 77# Define NO_AUXTRACE if you do not want AUX area tracing support
78#
79# Define NO_LIBBPF if you do not want BPF support
78 80
79# As per kernel Makefile, avoid funny character set dependencies 81# As per kernel Makefile, avoid funny character set dependencies
80unexport LC_ALL 82unexport LC_ALL
@@ -145,6 +147,7 @@ AWK = awk
145 147
146LIB_DIR = $(srctree)/tools/lib/api/ 148LIB_DIR = $(srctree)/tools/lib/api/
147TRACE_EVENT_DIR = $(srctree)/tools/lib/traceevent/ 149TRACE_EVENT_DIR = $(srctree)/tools/lib/traceevent/
150BPF_DIR = $(srctree)/tools/lib/bpf/
148 151
149# include config/Makefile by default and rule out 152# include config/Makefile by default and rule out
150# non-config cases 153# non-config cases
@@ -180,6 +183,7 @@ strip-libs = $(filter-out -l%,$(1))
180 183
181ifneq ($(OUTPUT),) 184ifneq ($(OUTPUT),)
182 TE_PATH=$(OUTPUT) 185 TE_PATH=$(OUTPUT)
186 BPF_PATH=$(OUTPUT)
183ifneq ($(subdir),) 187ifneq ($(subdir),)
184 LIB_PATH=$(OUTPUT)/../lib/api/ 188 LIB_PATH=$(OUTPUT)/../lib/api/
185else 189else
@@ -188,6 +192,7 @@ endif
188else 192else
189 TE_PATH=$(TRACE_EVENT_DIR) 193 TE_PATH=$(TRACE_EVENT_DIR)
190 LIB_PATH=$(LIB_DIR) 194 LIB_PATH=$(LIB_DIR)
195 BPF_PATH=$(BPF_DIR)
191endif 196endif
192 197
193LIBTRACEEVENT = $(TE_PATH)libtraceevent.a 198LIBTRACEEVENT = $(TE_PATH)libtraceevent.a
@@ -199,6 +204,8 @@ LIBTRACEEVENT_DYNAMIC_LIST_LDFLAGS = -Xlinker --dynamic-list=$(LIBTRACEEVENT_DYN
199LIBAPI = $(LIB_PATH)libapi.a 204LIBAPI = $(LIB_PATH)libapi.a
200export LIBAPI 205export LIBAPI
201 206
207LIBBPF = $(BPF_PATH)libbpf.a
208
202# python extension build directories 209# python extension build directories
203PYTHON_EXTBUILD := $(OUTPUT)python_ext_build/ 210PYTHON_EXTBUILD := $(OUTPUT)python_ext_build/
204PYTHON_EXTBUILD_LIB := $(PYTHON_EXTBUILD)lib/ 211PYTHON_EXTBUILD_LIB := $(PYTHON_EXTBUILD)lib/
@@ -251,6 +258,9 @@ export PERL_PATH
251LIB_FILE=$(OUTPUT)libperf.a 258LIB_FILE=$(OUTPUT)libperf.a
252 259
253PERFLIBS = $(LIB_FILE) $(LIBAPI) $(LIBTRACEEVENT) 260PERFLIBS = $(LIB_FILE) $(LIBAPI) $(LIBTRACEEVENT)
261ifndef NO_LIBBPF
262 PERFLIBS += $(LIBBPF)
263endif
254 264
255# We choose to avoid "if .. else if .. else .. endif endif" 265# We choose to avoid "if .. else if .. else .. endif endif"
256# because maintaining the nesting to match is a pain. If 266# because maintaining the nesting to match is a pain. If
@@ -420,6 +430,13 @@ $(LIBAPI)-clean:
420 $(call QUIET_CLEAN, libapi) 430 $(call QUIET_CLEAN, libapi)
421 $(Q)$(MAKE) -C $(LIB_DIR) O=$(OUTPUT) clean >/dev/null 431 $(Q)$(MAKE) -C $(LIB_DIR) O=$(OUTPUT) clean >/dev/null
422 432
433$(LIBBPF): FORCE
434 $(Q)$(MAKE) -C $(BPF_DIR) O=$(OUTPUT) $(OUTPUT)libbpf.a
435
436$(LIBBPF)-clean:
437 $(call QUIET_CLEAN, libbpf)
438 $(Q)$(MAKE) -C $(BPF_DIR) O=$(OUTPUT) clean >/dev/null
439
423help: 440help:
424 @echo 'Perf make targets:' 441 @echo 'Perf make targets:'
425 @echo ' doc - make *all* documentation (see below)' 442 @echo ' doc - make *all* documentation (see below)'
@@ -459,7 +476,7 @@ INSTALL_DOC_TARGETS += quick-install-doc quick-install-man quick-install-html
459$(DOC_TARGETS): 476$(DOC_TARGETS):
460 $(QUIET_SUBDIR0)Documentation $(QUIET_SUBDIR1) $(@:doc=all) 477 $(QUIET_SUBDIR0)Documentation $(QUIET_SUBDIR1) $(@:doc=all)
461 478
462TAG_FOLDERS= . ../lib/traceevent ../lib/api ../lib/symbol ../include 479TAG_FOLDERS= . ../lib/traceevent ../lib/api ../lib/symbol ../include ../lib/bpf
463TAG_FILES= ../../include/uapi/linux/perf_event.h 480TAG_FILES= ../../include/uapi/linux/perf_event.h
464 481
465TAGS: 482TAGS:
@@ -567,7 +584,7 @@ config-clean:
567 $(call QUIET_CLEAN, config) 584 $(call QUIET_CLEAN, config)
568 $(Q)$(MAKE) -C $(srctree)/tools/build/feature/ clean >/dev/null 585 $(Q)$(MAKE) -C $(srctree)/tools/build/feature/ clean >/dev/null
569 586
570clean: $(LIBTRACEEVENT)-clean $(LIBAPI)-clean config-clean 587clean: $(LIBTRACEEVENT)-clean $(LIBAPI)-clean $(LIBBPF)-clean config-clean
571 $(call QUIET_CLEAN, core-objs) $(RM) $(LIB_FILE) $(OUTPUT)perf-archive $(OUTPUT)perf-with-kcore $(LANG_BINDINGS) 588 $(call QUIET_CLEAN, core-objs) $(RM) $(LIB_FILE) $(OUTPUT)perf-archive $(OUTPUT)perf-with-kcore $(LANG_BINDINGS)
572 $(Q)find . -name '*.o' -delete -o -name '\.*.cmd' -delete -o -name '\.*.d' -delete 589 $(Q)find . -name '*.o' -delete -o -name '\.*.cmd' -delete -o -name '\.*.d' -delete
573 $(Q)$(RM) $(OUTPUT).config-detected 590 $(Q)$(RM) $(OUTPUT).config-detected
diff --git a/tools/perf/config/Makefile b/tools/perf/config/Makefile
index ab09adaabc9c..de89ec574361 100644
--- a/tools/perf/config/Makefile
+++ b/tools/perf/config/Makefile
@@ -106,6 +106,7 @@ ifdef LIBBABELTRACE
106 FEATURE_CHECK_LDFLAGS-libbabeltrace := $(LIBBABELTRACE_LDFLAGS) -lbabeltrace-ctf 106 FEATURE_CHECK_LDFLAGS-libbabeltrace := $(LIBBABELTRACE_LDFLAGS) -lbabeltrace-ctf
107endif 107endif
108 108
109FEATURE_CHECK_CFLAGS-bpf = -I. -I$(srctree)/tools/include -I$(srctree)/arch/$(ARCH)/include/uapi -I$(srctree)/include/uapi
109# include ARCH specific config 110# include ARCH specific config
110-include $(src-perf)/arch/$(ARCH)/Makefile 111-include $(src-perf)/arch/$(ARCH)/Makefile
111 112
@@ -237,6 +238,7 @@ ifdef NO_LIBELF
237 NO_DEMANGLE := 1 238 NO_DEMANGLE := 1
238 NO_LIBUNWIND := 1 239 NO_LIBUNWIND := 1
239 NO_LIBDW_DWARF_UNWIND := 1 240 NO_LIBDW_DWARF_UNWIND := 1
241 NO_LIBBPF := 1
240else 242else
241 ifeq ($(feature-libelf), 0) 243 ifeq ($(feature-libelf), 0)
242 ifeq ($(feature-glibc), 1) 244 ifeq ($(feature-glibc), 1)
@@ -246,13 +248,14 @@ else
246 LIBC_SUPPORT := 1 248 LIBC_SUPPORT := 1
247 endif 249 endif
248 ifeq ($(LIBC_SUPPORT),1) 250 ifeq ($(LIBC_SUPPORT),1)
249 msg := $(warning No libelf found, disables 'probe' tool, please install elfutils-libelf-devel/libelf-dev); 251 msg := $(warning No libelf found, disables 'probe' tool and BPF support in 'perf record', please install elfutils-libelf-devel/libelf-dev);
250 252
251 NO_LIBELF := 1 253 NO_LIBELF := 1
252 NO_DWARF := 1 254 NO_DWARF := 1
253 NO_DEMANGLE := 1 255 NO_DEMANGLE := 1
254 NO_LIBUNWIND := 1 256 NO_LIBUNWIND := 1
255 NO_LIBDW_DWARF_UNWIND := 1 257 NO_LIBDW_DWARF_UNWIND := 1
258 NO_LIBBPF := 1
256 else 259 else
257 ifneq ($(filter s% -static%,$(LDFLAGS),),) 260 ifneq ($(filter s% -static%,$(LDFLAGS),),)
258 msg := $(error No static glibc found, please install glibc-static); 261 msg := $(error No static glibc found, please install glibc-static);
@@ -309,6 +312,13 @@ ifndef NO_LIBELF
309 $(call detected,CONFIG_DWARF) 312 $(call detected,CONFIG_DWARF)
310 endif # PERF_HAVE_DWARF_REGS 313 endif # PERF_HAVE_DWARF_REGS
311 endif # NO_DWARF 314 endif # NO_DWARF
315
316 ifndef NO_LIBBPF
317 ifeq ($(feature-bpf), 1)
318 CFLAGS += -DHAVE_LIBBPF_SUPPORT
319 $(call detected,CONFIG_LIBBPF)
320 endif
321 endif # NO_LIBBPF
312endif # NO_LIBELF 322endif # NO_LIBELF
313 323
314ifeq ($(ARCH),powerpc) 324ifeq ($(ARCH),powerpc)
@@ -324,6 +334,13 @@ ifndef NO_LIBUNWIND
324 endif 334 endif
325endif 335endif
326 336
337ifndef NO_LIBBPF
338 ifneq ($(feature-bpf), 1)
339 msg := $(warning BPF API too old. Please install recent kernel headers. BPF support in 'perf record' is disabled.)
340 NO_LIBBPF := 1
341 endif
342endif
343
327dwarf-post-unwind := 1 344dwarf-post-unwind := 1
328dwarf-post-unwind-text := BUG 345dwarf-post-unwind-text := BUG
329 346
diff --git a/tools/perf/perf.c b/tools/perf/perf.c
index 543713422d14..3d4c7c09adea 100644
--- a/tools/perf/perf.c
+++ b/tools/perf/perf.c
@@ -15,6 +15,7 @@
15#include "util/run-command.h" 15#include "util/run-command.h"
16#include "util/parse-events.h" 16#include "util/parse-events.h"
17#include "util/parse-options.h" 17#include "util/parse-options.h"
18#include "util/bpf-loader.h"
18#include "util/debug.h" 19#include "util/debug.h"
19#include <api/fs/tracing_path.h> 20#include <api/fs/tracing_path.h>
20#include <pthread.h> 21#include <pthread.h>
@@ -385,6 +386,7 @@ static int run_builtin(struct cmd_struct *p, int argc, const char **argv)
385 status = p->fn(argc, argv, prefix); 386 status = p->fn(argc, argv, prefix);
386 exit_browser(status); 387 exit_browser(status);
387 perf_env__exit(&perf_env); 388 perf_env__exit(&perf_env);
389 bpf__clear();
388 390
389 if (status) 391 if (status)
390 return status & 0xff; 392 return status & 0xff;
diff --git a/tools/perf/tests/make b/tools/perf/tests/make
index ba31c4bd441d..2cbd0c6901e3 100644
--- a/tools/perf/tests/make
+++ b/tools/perf/tests/make
@@ -44,6 +44,7 @@ make_no_libnuma := NO_LIBNUMA=1
44make_no_libaudit := NO_LIBAUDIT=1 44make_no_libaudit := NO_LIBAUDIT=1
45make_no_libbionic := NO_LIBBIONIC=1 45make_no_libbionic := NO_LIBBIONIC=1
46make_no_auxtrace := NO_AUXTRACE=1 46make_no_auxtrace := NO_AUXTRACE=1
47make_no_libbpf := NO_LIBBPF=1
47make_tags := tags 48make_tags := tags
48make_cscope := cscope 49make_cscope := cscope
49make_help := help 50make_help := help
@@ -66,7 +67,7 @@ make_static := LDFLAGS=-static
66make_minimal := NO_LIBPERL=1 NO_LIBPYTHON=1 NO_NEWT=1 NO_GTK2=1 67make_minimal := NO_LIBPERL=1 NO_LIBPYTHON=1 NO_NEWT=1 NO_GTK2=1
67make_minimal += NO_DEMANGLE=1 NO_LIBELF=1 NO_LIBUNWIND=1 NO_BACKTRACE=1 68make_minimal += NO_DEMANGLE=1 NO_LIBELF=1 NO_LIBUNWIND=1 NO_BACKTRACE=1
68make_minimal += NO_LIBNUMA=1 NO_LIBAUDIT=1 NO_LIBBIONIC=1 69make_minimal += NO_LIBNUMA=1 NO_LIBAUDIT=1 NO_LIBBIONIC=1
69make_minimal += NO_LIBDW_DWARF_UNWIND=1 NO_AUXTRACE=1 70make_minimal += NO_LIBDW_DWARF_UNWIND=1 NO_AUXTRACE=1 NO_LIBBPF=1
70 71
71# $(run) contains all available tests 72# $(run) contains all available tests
72run := make_pure 73run := make_pure
@@ -94,6 +95,7 @@ run += make_no_libnuma
94run += make_no_libaudit 95run += make_no_libaudit
95run += make_no_libbionic 96run += make_no_libbionic
96run += make_no_auxtrace 97run += make_no_auxtrace
98run += make_no_libbpf
97run += make_help 99run += make_help
98run += make_doc 100run += make_doc
99run += make_perf_o 101run += make_perf_o
diff --git a/tools/perf/util/Build b/tools/perf/util/Build
index 9217119c4108..591b3fe3ed49 100644
--- a/tools/perf/util/Build
+++ b/tools/perf/util/Build
@@ -87,6 +87,7 @@ libperf-$(CONFIG_AUXTRACE) += intel-bts.o
87libperf-y += parse-branch-options.o 87libperf-y += parse-branch-options.o
88libperf-y += parse-regs-options.o 88libperf-y += parse-regs-options.o
89 89
90libperf-$(CONFIG_LIBBPF) += bpf-loader.o
90libperf-$(CONFIG_LIBELF) += symbol-elf.o 91libperf-$(CONFIG_LIBELF) += symbol-elf.o
91libperf-$(CONFIG_LIBELF) += probe-file.o 92libperf-$(CONFIG_LIBELF) += probe-file.o
92libperf-$(CONFIG_LIBELF) += probe-event.o 93libperf-$(CONFIG_LIBELF) += probe-event.o
diff --git a/tools/perf/util/bpf-loader.c b/tools/perf/util/bpf-loader.c
new file mode 100644
index 000000000000..aa784a498c48
--- /dev/null
+++ b/tools/perf/util/bpf-loader.c
@@ -0,0 +1,339 @@
1/*
2 * bpf-loader.c
3 *
4 * Copyright (C) 2015 Wang Nan <wangnan0@huawei.com>
5 * Copyright (C) 2015 Huawei Inc.
6 */
7
8#include <bpf/libbpf.h>
9#include <linux/err.h>
10#include "perf.h"
11#include "debug.h"
12#include "bpf-loader.h"
13#include "probe-event.h"
14#include "probe-finder.h" // for MAX_PROBES
15
16#define DEFINE_PRINT_FN(name, level) \
17static int libbpf_##name(const char *fmt, ...) \
18{ \
19 va_list args; \
20 int ret; \
21 \
22 va_start(args, fmt); \
23 ret = veprintf(level, verbose, pr_fmt(fmt), args);\
24 va_end(args); \
25 return ret; \
26}
27
28DEFINE_PRINT_FN(warning, 0)
29DEFINE_PRINT_FN(info, 0)
30DEFINE_PRINT_FN(debug, 1)
31
32struct bpf_prog_priv {
33 struct perf_probe_event pev;
34};
35
36struct bpf_object *bpf__prepare_load(const char *filename)
37{
38 struct bpf_object *obj;
39 static bool libbpf_initialized;
40
41 if (!libbpf_initialized) {
42 libbpf_set_print(libbpf_warning,
43 libbpf_info,
44 libbpf_debug);
45 libbpf_initialized = true;
46 }
47
48 obj = bpf_object__open(filename);
49 if (!obj) {
50 pr_debug("bpf: failed to load %s\n", filename);
51 return ERR_PTR(-EINVAL);
52 }
53
54 return obj;
55}
56
57void bpf__clear(void)
58{
59 struct bpf_object *obj, *tmp;
60
61 bpf_object__for_each_safe(obj, tmp) {
62 bpf__unprobe(obj);
63 bpf_object__close(obj);
64 }
65}
66
67static void
68bpf_prog_priv__clear(struct bpf_program *prog __maybe_unused,
69 void *_priv)
70{
71 struct bpf_prog_priv *priv = _priv;
72
73 cleanup_perf_probe_events(&priv->pev, 1);
74 free(priv);
75}
76
77static int
78config_bpf_program(struct bpf_program *prog)
79{
80 struct perf_probe_event *pev = NULL;
81 struct bpf_prog_priv *priv = NULL;
82 const char *config_str;
83 int err;
84
85 config_str = bpf_program__title(prog, false);
86 if (!config_str) {
87 pr_debug("bpf: unable to get title for program\n");
88 return -EINVAL;
89 }
90
91 priv = calloc(sizeof(*priv), 1);
92 if (!priv) {
93 pr_debug("bpf: failed to alloc priv\n");
94 return -ENOMEM;
95 }
96 pev = &priv->pev;
97
98 pr_debug("bpf: config program '%s'\n", config_str);
99 err = parse_perf_probe_command(config_str, pev);
100 if (err < 0) {
101 pr_debug("bpf: '%s' is not a valid config string\n",
102 config_str);
103 err = -EINVAL;
104 goto errout;
105 }
106
107 if (pev->group && strcmp(pev->group, PERF_BPF_PROBE_GROUP)) {
108 pr_debug("bpf: '%s': group for event is set and not '%s'.\n",
109 config_str, PERF_BPF_PROBE_GROUP);
110 err = -EINVAL;
111 goto errout;
112 } else if (!pev->group)
113 pev->group = strdup(PERF_BPF_PROBE_GROUP);
114
115 if (!pev->group) {
116 pr_debug("bpf: strdup failed\n");
117 err = -ENOMEM;
118 goto errout;
119 }
120
121 if (!pev->event) {
122 pr_debug("bpf: '%s': event name is missing\n",
123 config_str);
124 err = -EINVAL;
125 goto errout;
126 }
127 pr_debug("bpf: config '%s' is ok\n", config_str);
128
129 err = bpf_program__set_private(prog, priv, bpf_prog_priv__clear);
130 if (err) {
131 pr_debug("Failed to set priv for program '%s'\n", config_str);
132 goto errout;
133 }
134
135 return 0;
136
137errout:
138 if (pev)
139 clear_perf_probe_event(pev);
140 free(priv);
141 return err;
142}
143
144static int bpf__prepare_probe(void)
145{
146 static int err = 0;
147 static bool initialized = false;
148
149 /*
150 * Make err static, so if init failed the first, bpf__prepare_probe()
151 * fails each time without calling init_probe_symbol_maps multiple
152 * times.
153 */
154 if (initialized)
155 return err;
156
157 initialized = true;
158 err = init_probe_symbol_maps(false);
159 if (err < 0)
160 pr_debug("Failed to init_probe_symbol_maps\n");
161 probe_conf.max_probes = MAX_PROBES;
162 return err;
163}
164
165int bpf__probe(struct bpf_object *obj)
166{
167 int err = 0;
168 struct bpf_program *prog;
169 struct bpf_prog_priv *priv;
170 struct perf_probe_event *pev;
171
172 err = bpf__prepare_probe();
173 if (err) {
174 pr_debug("bpf__prepare_probe failed\n");
175 return err;
176 }
177
178 bpf_object__for_each_program(prog, obj) {
179 err = config_bpf_program(prog);
180 if (err)
181 goto out;
182
183 err = bpf_program__get_private(prog, (void **)&priv);
184 if (err || !priv)
185 goto out;
186 pev = &priv->pev;
187
188 err = convert_perf_probe_events(pev, 1);
189 if (err < 0) {
190 pr_debug("bpf_probe: failed to convert perf probe events");
191 goto out;
192 }
193
194 err = apply_perf_probe_events(pev, 1);
195 if (err < 0) {
196 pr_debug("bpf_probe: failed to apply perf probe events");
197 goto out;
198 }
199 }
200out:
201 return err < 0 ? err : 0;
202}
203
204#define EVENTS_WRITE_BUFSIZE 4096
205int bpf__unprobe(struct bpf_object *obj)
206{
207 int err, ret = 0;
208 struct bpf_program *prog;
209 struct bpf_prog_priv *priv;
210
211 bpf_object__for_each_program(prog, obj) {
212 int i;
213
214 err = bpf_program__get_private(prog, (void **)&priv);
215 if (err || !priv)
216 continue;
217
218 for (i = 0; i < priv->pev.ntevs; i++) {
219 struct probe_trace_event *tev = &priv->pev.tevs[i];
220 char name_buf[EVENTS_WRITE_BUFSIZE];
221 struct strfilter *delfilter;
222
223 snprintf(name_buf, EVENTS_WRITE_BUFSIZE,
224 "%s:%s", tev->group, tev->event);
225 name_buf[EVENTS_WRITE_BUFSIZE - 1] = '\0';
226
227 delfilter = strfilter__new(name_buf, NULL);
228 if (!delfilter) {
229 pr_debug("Failed to create filter for unprobing\n");
230 ret = -ENOMEM;
231 continue;
232 }
233
234 err = del_perf_probe_events(delfilter);
235 strfilter__delete(delfilter);
236 if (err) {
237 pr_debug("Failed to delete %s\n", name_buf);
238 ret = err;
239 continue;
240 }
241 }
242 }
243 return ret;
244}
245
246int bpf__load(struct bpf_object *obj)
247{
248 int err;
249
250 err = bpf_object__load(obj);
251 if (err) {
252 pr_debug("bpf: load objects failed\n");
253 return err;
254 }
255 return 0;
256}
257
258int bpf__foreach_tev(struct bpf_object *obj,
259 bpf_prog_iter_callback_t func,
260 void *arg)
261{
262 struct bpf_program *prog;
263 int err;
264
265 bpf_object__for_each_program(prog, obj) {
266 struct probe_trace_event *tev;
267 struct perf_probe_event *pev;
268 struct bpf_prog_priv *priv;
269 int i, fd;
270
271 err = bpf_program__get_private(prog,
272 (void **)&priv);
273 if (err || !priv) {
274 pr_debug("bpf: failed to get private field\n");
275 return -EINVAL;
276 }
277
278 pev = &priv->pev;
279 for (i = 0; i < pev->ntevs; i++) {
280 tev = &pev->tevs[i];
281
282 fd = bpf_program__fd(prog);
283 if (fd < 0) {
284 pr_debug("bpf: failed to get file descriptor\n");
285 return fd;
286 }
287
288 err = (*func)(tev, fd, arg);
289 if (err) {
290 pr_debug("bpf: call back failed, stop iterate\n");
291 return err;
292 }
293 }
294 }
295 return 0;
296}
297
298#define bpf__strerror_head(err, buf, size) \
299 char sbuf[STRERR_BUFSIZE], *emsg;\
300 if (!size)\
301 return 0;\
302 if (err < 0)\
303 err = -err;\
304 emsg = strerror_r(err, sbuf, sizeof(sbuf));\
305 switch (err) {\
306 default:\
307 scnprintf(buf, size, "%s", emsg);\
308 break;
309
310#define bpf__strerror_entry(val, fmt...)\
311 case val: {\
312 scnprintf(buf, size, fmt);\
313 break;\
314 }
315
316#define bpf__strerror_end(buf, size)\
317 }\
318 buf[size - 1] = '\0';
319
320int bpf__strerror_probe(struct bpf_object *obj __maybe_unused,
321 int err, char *buf, size_t size)
322{
323 bpf__strerror_head(err, buf, size);
324 bpf__strerror_entry(EEXIST, "Probe point exist. Try use 'perf probe -d \"*\"'");
325 bpf__strerror_entry(EPERM, "You need to be root, and /proc/sys/kernel/kptr_restrict should be 0\n");
326 bpf__strerror_entry(ENOENT, "You need to check probing points in BPF file\n");
327 bpf__strerror_end(buf, size);
328 return 0;
329}
330
331int bpf__strerror_load(struct bpf_object *obj __maybe_unused,
332 int err, char *buf, size_t size)
333{
334 bpf__strerror_head(err, buf, size);
335 bpf__strerror_entry(EINVAL, "%s: Are you root and runing a CONFIG_BPF_SYSCALL kernel?",
336 emsg)
337 bpf__strerror_end(buf, size);
338 return 0;
339}
diff --git a/tools/perf/util/bpf-loader.h b/tools/perf/util/bpf-loader.h
new file mode 100644
index 000000000000..a8f25ee06fc5
--- /dev/null
+++ b/tools/perf/util/bpf-loader.h
@@ -0,0 +1,84 @@
1/*
2 * Copyright (C) 2015, Wang Nan <wangnan0@huawei.com>
3 * Copyright (C) 2015, Huawei Inc.
4 */
5#ifndef __BPF_LOADER_H
6#define __BPF_LOADER_H
7
8#include <linux/compiler.h>
9#include <linux/err.h>
10#include <string.h>
11#include "probe-event.h"
12#include "debug.h"
13
14struct bpf_object;
15#define PERF_BPF_PROBE_GROUP "perf_bpf_probe"
16
17typedef int (*bpf_prog_iter_callback_t)(struct probe_trace_event *tev,
18 int fd, void *arg);
19
20#ifdef HAVE_LIBBPF_SUPPORT
21struct bpf_object *bpf__prepare_load(const char *filename);
22
23void bpf__clear(void);
24
25int bpf__probe(struct bpf_object *obj);
26int bpf__unprobe(struct bpf_object *obj);
27int bpf__strerror_probe(struct bpf_object *obj, int err,
28 char *buf, size_t size);
29
30int bpf__load(struct bpf_object *obj);
31int bpf__strerror_load(struct bpf_object *obj, int err,
32 char *buf, size_t size);
33int bpf__foreach_tev(struct bpf_object *obj,
34 bpf_prog_iter_callback_t func, void *arg);
35#else
36static inline struct bpf_object *
37bpf__prepare_load(const char *filename __maybe_unused)
38{
39 pr_debug("ERROR: eBPF object loading is disabled during compiling.\n");
40 return ERR_PTR(-ENOTSUP);
41}
42
43static inline void bpf__clear(void) { }
44
45static inline int bpf__probe(struct bpf_object *obj __maybe_unused) { return 0;}
46static inline int bpf__unprobe(struct bpf_object *obj __maybe_unused) { return 0;}
47static inline int bpf__load(struct bpf_object *obj __maybe_unused) { return 0; }
48
49static inline int
50bpf__foreach_tev(struct bpf_object *obj __maybe_unused,
51 bpf_prog_iter_callback_t func __maybe_unused,
52 void *arg __maybe_unused)
53{
54 return 0;
55}
56
57static inline int
58__bpf_strerror(char *buf, size_t size)
59{
60 if (!size)
61 return 0;
62 strncpy(buf,
63 "ERROR: eBPF object loading is disabled during compiling.\n",
64 size);
65 buf[size - 1] = '\0';
66 return 0;
67}
68
69static inline int
70bpf__strerror_probe(struct bpf_object *obj __maybe_unused,
71 int err __maybe_unused,
72 char *buf, size_t size)
73{
74 return __bpf_strerror(buf, size);
75}
76
77static inline int bpf__strerror_load(struct bpf_object *obj __maybe_unused,
78 int err __maybe_unused,
79 char *buf, size_t size)
80{
81 return __bpf_strerror(buf, size);
82}
83#endif
84#endif
diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c
index 72abcf254ccb..d97b03710331 100644
--- a/tools/perf/util/parse-events.c
+++ b/tools/perf/util/parse-events.c
@@ -11,6 +11,7 @@
11#include "symbol.h" 11#include "symbol.h"
12#include "cache.h" 12#include "cache.h"
13#include "header.h" 13#include "header.h"
14#include "bpf-loader.h"
14#include "debug.h" 15#include "debug.h"
15#include <api/fs/tracing_path.h> 16#include <api/fs/tracing_path.h>
16#include "parse-events-bison.h" 17#include "parse-events-bison.h"
@@ -529,6 +530,123 @@ static int add_tracepoint_multi_sys(struct list_head *list, int *idx,
529 return ret; 530 return ret;
530} 531}
531 532
533struct __add_bpf_event_param {
534 struct parse_events_evlist *data;
535 struct list_head *list;
536};
537
538static int add_bpf_event(struct probe_trace_event *tev, int fd,
539 void *_param)
540{
541 LIST_HEAD(new_evsels);
542 struct __add_bpf_event_param *param = _param;
543 struct parse_events_evlist *evlist = param->data;
544 struct list_head *list = param->list;
545 int err;
546
547 pr_debug("add bpf event %s:%s and attach bpf program %d\n",
548 tev->group, tev->event, fd);
549
550 err = parse_events_add_tracepoint(&new_evsels, &evlist->idx, tev->group,
551 tev->event, evlist->error, NULL);
552 if (err) {
553 struct perf_evsel *evsel, *tmp;
554
555 pr_debug("Failed to add BPF event %s:%s\n",
556 tev->group, tev->event);
557 list_for_each_entry_safe(evsel, tmp, &new_evsels, node) {
558 list_del(&evsel->node);
559 perf_evsel__delete(evsel);
560 }
561 return err;
562 }
563 pr_debug("adding %s:%s\n", tev->group, tev->event);
564
565 list_splice(&new_evsels, list);
566 return 0;
567}
568
569int parse_events_load_bpf_obj(struct parse_events_evlist *data,
570 struct list_head *list,
571 struct bpf_object *obj)
572{
573 int err;
574 char errbuf[BUFSIZ];
575 struct __add_bpf_event_param param = {data, list};
576 static bool registered_unprobe_atexit = false;
577
578 if (IS_ERR(obj) || !obj) {
579 snprintf(errbuf, sizeof(errbuf),
580 "Internal error: load bpf obj with NULL");
581 err = -EINVAL;
582 goto errout;
583 }
584
585 /*
586 * Register atexit handler before calling bpf__probe() so
587 * bpf__probe() don't need to unprobe probe points its already
588 * created when failure.
589 */
590 if (!registered_unprobe_atexit) {
591 atexit(bpf__clear);
592 registered_unprobe_atexit = true;
593 }
594
595 err = bpf__probe(obj);
596 if (err) {
597 bpf__strerror_probe(obj, err, errbuf, sizeof(errbuf));
598 goto errout;
599 }
600
601 err = bpf__load(obj);
602 if (err) {
603 bpf__strerror_load(obj, err, errbuf, sizeof(errbuf));
604 goto errout;
605 }
606
607 err = bpf__foreach_tev(obj, add_bpf_event, &param);
608 if (err) {
609 snprintf(errbuf, sizeof(errbuf),
610 "Attach events in BPF object failed");
611 goto errout;
612 }
613
614 return 0;
615errout:
616 data->error->help = strdup("(add -v to see detail)");
617 data->error->str = strdup(errbuf);
618 return err;
619}
620
621int parse_events_load_bpf(struct parse_events_evlist *data,
622 struct list_head *list,
623 char *bpf_file_name)
624{
625 struct bpf_object *obj;
626
627 obj = bpf__prepare_load(bpf_file_name);
628 if (IS_ERR(obj) || !obj) {
629 char errbuf[BUFSIZ];
630 int err;
631
632 err = obj ? PTR_ERR(obj) : -EINVAL;
633
634 if (err == -ENOTSUP)
635 snprintf(errbuf, sizeof(errbuf),
636 "BPF support is not compiled");
637 else
638 snprintf(errbuf, sizeof(errbuf),
639 "BPF object file '%s' is invalid",
640 bpf_file_name);
641
642 data->error->help = strdup("(add -v to see detail)");
643 data->error->str = strdup(errbuf);
644 return err;
645 }
646
647 return parse_events_load_bpf_obj(data, list, obj);
648}
649
532static int 650static int
533parse_breakpoint_type(const char *type, struct perf_event_attr *attr) 651parse_breakpoint_type(const char *type, struct perf_event_attr *attr)
534{ 652{
diff --git a/tools/perf/util/parse-events.h b/tools/perf/util/parse-events.h
index 13c9063513eb..765018a17448 100644
--- a/tools/perf/util/parse-events.h
+++ b/tools/perf/util/parse-events.h
@@ -123,6 +123,14 @@ int parse_events_add_tracepoint(struct list_head *list, int *idx,
123 char *sys, char *event, 123 char *sys, char *event,
124 struct parse_events_error *error, 124 struct parse_events_error *error,
125 struct list_head *head_config); 125 struct list_head *head_config);
126int parse_events_load_bpf(struct parse_events_evlist *data,
127 struct list_head *list,
128 char *bpf_file_name);
129/* Provide this function for perf test */
130struct bpf_object;
131int parse_events_load_bpf_obj(struct parse_events_evlist *data,
132 struct list_head *list,
133 struct bpf_object *obj);
126int parse_events_add_numeric(struct parse_events_evlist *data, 134int parse_events_add_numeric(struct parse_events_evlist *data,
127 struct list_head *list, 135 struct list_head *list,
128 u32 type, u64 config, 136 u32 type, u64 config,
diff --git a/tools/perf/util/parse-events.l b/tools/perf/util/parse-events.l
index 8d0de5b2991d..cf330ebf812c 100644
--- a/tools/perf/util/parse-events.l
+++ b/tools/perf/util/parse-events.l
@@ -115,6 +115,7 @@ do { \
115group [^,{}/]*[{][^}]*[}][^,{}/]* 115group [^,{}/]*[{][^}]*[}][^,{}/]*
116event_pmu [^,{}/]+[/][^/]*[/][^,{}/]* 116event_pmu [^,{}/]+[/][^/]*[/][^,{}/]*
117event [^,{}/]+ 117event [^,{}/]+
118bpf_object .*\.(o|bpf)
118 119
119num_dec [0-9]+ 120num_dec [0-9]+
120num_hex 0x[a-fA-F0-9]+ 121num_hex 0x[a-fA-F0-9]+
@@ -159,6 +160,7 @@ modifier_bp [rwx]{1,3}
159 } 160 }
160 161
161{event_pmu} | 162{event_pmu} |
163{bpf_object} |
162{event} { 164{event} {
163 BEGIN(INITIAL); 165 BEGIN(INITIAL);
164 REWIND(1); 166 REWIND(1);
@@ -266,6 +268,7 @@ r{num_raw_hex} { return raw(yyscanner); }
266{num_hex} { return value(yyscanner, 16); } 268{num_hex} { return value(yyscanner, 16); }
267 269
268{modifier_event} { return str(yyscanner, PE_MODIFIER_EVENT); } 270{modifier_event} { return str(yyscanner, PE_MODIFIER_EVENT); }
271{bpf_object} { return str(yyscanner, PE_BPF_OBJECT); }
269{name} { return pmu_str_check(yyscanner); } 272{name} { return pmu_str_check(yyscanner); }
270"/" { BEGIN(config); return '/'; } 273"/" { BEGIN(config); return '/'; }
271- { return '-'; } 274- { return '-'; }
diff --git a/tools/perf/util/parse-events.y b/tools/perf/util/parse-events.y
index ae6af269f9c9..497f19b20f0b 100644
--- a/tools/perf/util/parse-events.y
+++ b/tools/perf/util/parse-events.y
@@ -42,6 +42,7 @@ static inc_group_count(struct list_head *list,
42%token PE_VALUE PE_VALUE_SYM_HW PE_VALUE_SYM_SW PE_RAW PE_TERM 42%token PE_VALUE PE_VALUE_SYM_HW PE_VALUE_SYM_SW PE_RAW PE_TERM
43%token PE_EVENT_NAME 43%token PE_EVENT_NAME
44%token PE_NAME 44%token PE_NAME
45%token PE_BPF_OBJECT
45%token PE_MODIFIER_EVENT PE_MODIFIER_BP 46%token PE_MODIFIER_EVENT PE_MODIFIER_BP
46%token PE_NAME_CACHE_TYPE PE_NAME_CACHE_OP_RESULT 47%token PE_NAME_CACHE_TYPE PE_NAME_CACHE_OP_RESULT
47%token PE_PREFIX_MEM PE_PREFIX_RAW PE_PREFIX_GROUP 48%token PE_PREFIX_MEM PE_PREFIX_RAW PE_PREFIX_GROUP
@@ -53,6 +54,7 @@ static inc_group_count(struct list_head *list,
53%type <num> PE_RAW 54%type <num> PE_RAW
54%type <num> PE_TERM 55%type <num> PE_TERM
55%type <str> PE_NAME 56%type <str> PE_NAME
57%type <str> PE_BPF_OBJECT
56%type <str> PE_NAME_CACHE_TYPE 58%type <str> PE_NAME_CACHE_TYPE
57%type <str> PE_NAME_CACHE_OP_RESULT 59%type <str> PE_NAME_CACHE_OP_RESULT
58%type <str> PE_MODIFIER_EVENT 60%type <str> PE_MODIFIER_EVENT
@@ -70,6 +72,7 @@ static inc_group_count(struct list_head *list,
70%type <tracepoint_name> tracepoint_name 72%type <tracepoint_name> tracepoint_name
71%type <head> event_legacy_numeric 73%type <head> event_legacy_numeric
72%type <head> event_legacy_raw 74%type <head> event_legacy_raw
75%type <head> event_bpf_file
73%type <head> event_def 76%type <head> event_def
74%type <head> event_mod 77%type <head> event_mod
75%type <head> event_name 78%type <head> event_name
@@ -203,7 +206,8 @@ event_def: event_pmu |
203 event_legacy_mem | 206 event_legacy_mem |
204 event_legacy_tracepoint sep_dc | 207 event_legacy_tracepoint sep_dc |
205 event_legacy_numeric sep_dc | 208 event_legacy_numeric sep_dc |
206 event_legacy_raw sep_dc 209 event_legacy_raw sep_dc |
210 event_bpf_file
207 211
208event_pmu: 212event_pmu:
209PE_NAME '/' event_config '/' 213PE_NAME '/' event_config '/'
@@ -449,6 +453,18 @@ PE_RAW
449 $$ = list; 453 $$ = list;
450} 454}
451 455
456event_bpf_file:
457PE_BPF_OBJECT
458{
459 struct parse_events_evlist *data = _data;
460 struct parse_events_error *error = data->error;
461 struct list_head *list;
462
463 ALLOC_LIST(list);
464 ABORT_ON(parse_events_load_bpf(data, list, $1));
465 $$ = list;
466}
467
452start_terms: event_config 468start_terms: event_config
453{ 469{
454 struct parse_events_terms *data = _data; 470 struct parse_events_terms *data = _data;