* [GIT PULL 0/6] perf/ebpf basic integration
@ 2015-10-29 11:16 Arnaldo Carvalho de Melo
2015-10-29 11:16 ` [PATCH 1/6] perf tools: Make perf depend on libbpf Arnaldo Carvalho de Melo
` (6 more replies)
0 siblings, 7 replies; 9+ messages in thread
From: Arnaldo Carvalho de Melo @ 2015-10-29 11:16 UTC (permalink / raw)
To: Ingo Molnar
Cc: linux-kernel, Arnaldo Carvalho de Melo, Alexei Starovoitov,
Brendan Gregg, Daniel Borkmann, David Ahern, He Kuang, Jiri Olsa,
Kaixu Xia, Masami Hiramatsu, Namhyung Kim, Paul Mackerras,
Peter Zijlstra, pi3orama, Wang Nan, Zefan Li,
Arnaldo Carvalho de Melo
Hi Ingo,
Please take a look at the changeset comments, I made notes in most of
them, this seems like a nice cutoff point to allow basic testing, by
developers, for the very basic integration of perf and ebpf, i.e. we can,
having a ready built object file, built with clang, be able to use it as a perf
event, passing it via -e/--event, etc.
Wang has lots more in the queue and I intend to work on them till I get
all reviewed/tested/merged, i.e. in the immediate future.
What do you think? Fair to get his smaller gulp now? Or do you want to
get it all the way with the code to get a .c file, build it, etc, that is
ready, but I haven't reviewed/tested yet?
Ah, this is on top of what I sent to you via perf/core yesterday.
Thanks,
- Arnaldo
The following changes since commit 443f8c75e8d58d394b0e65b47e02e5cd8ed32b41:
perf symbols: Fix endless loop in dso__split_kallsyms_for_kcore (2015-10-28 11:19:30 -0300)
are available in the git repository at:
git://git.kernel.org/pub/scm/linux/kernel/git/acme/linux.git tags/perf-ebpf-for-mingo
for you to fetch changes up to 4edf30e39e6cff32390eaff6a1508969b3cd967b:
perf bpf: Collect perf_evsel in BPF object files (2015-10-28 13:11:59 -0300)
----------------------------------------------------------------
perf/ebpf basic 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>
----------------------------------------------------------------
Wang Nan (6):
perf tools: Make perf depend on libbpf
perf ebpf: Add the libbpf glue
perf tools: Enable passing bpf object file to --event
perf tools: Create probe points for BPF programs
perf tools: Load eBPF object into kernel
perf bpf: Collect perf_evsel in BPF object files
tools/build/Makefile.feature | 6 +-
tools/perf/MANIFEST | 3 +
tools/perf/Makefile.perf | 21 ++-
tools/perf/config/Makefile | 19 ++-
tools/perf/perf.c | 2 +
tools/perf/tests/make | 4 +-
tools/perf/util/Build | 1 +
tools/perf/util/bpf-loader.c | 339 +++++++++++++++++++++++++++++++++++++++++
tools/perf/util/bpf-loader.h | 84 ++++++++++
tools/perf/util/parse-events.c | 118 ++++++++++++++
tools/perf/util/parse-events.h | 8 +
tools/perf/util/parse-events.l | 3 +
tools/perf/util/parse-events.y | 18 ++-
13 files changed, 619 insertions(+), 7 deletions(-)
create mode 100644 tools/perf/util/bpf-loader.c
create mode 100644 tools/perf/util/bpf-loader.h
^ permalink raw reply [flat|nested] 9+ messages in thread
* [PATCH 1/6] perf tools: Make perf depend on libbpf
2015-10-29 11:16 [GIT PULL 0/6] perf/ebpf basic integration Arnaldo Carvalho de Melo
@ 2015-10-29 11:16 ` Arnaldo Carvalho de Melo
2015-10-29 11:16 ` [PATCH 2/6] perf ebpf: Add the libbpf glue Arnaldo Carvalho de Melo
` (5 subsequent siblings)
6 siblings, 0 replies; 9+ messages in thread
From: Arnaldo Carvalho de Melo @ 2015-10-29 11:16 UTC (permalink / raw)
To: Ingo Molnar
Cc: linux-kernel, Wang Nan, Brendan Gregg, Daniel Borkmann,
David Ahern, He Kuang, Jiri Olsa, Kaixu Xia, Masami Hiramatsu,
Namhyung Kim, Peter Zijlstra, Zefan Li, pi3orama,
Arnaldo Carvalho de Melo
From: Wang Nan <wangnan0@huawei.com>
By adding libbpf into perf's Makefile, this patch enables perf to build
libbpf if libelf is found and neither NO_LIBELF nor NO_LIBBPF is set.
The newly introduced code is similar to how libapi and libtraceevent
are wired into Makefile.perf.
MANIFEST is also updated for 'make perf-*-src-pkg'.
Append make_no_libbpf to tools/perf/tests/make.
The 'bpf' feature check is appended into default FEATURE_TESTS and
FEATURE_DISPLAY, so perf will check the API version of bpf in
/path/to/kernel/include/uapi/linux/bpf.h. Which should not fail except
when we are trying to port this code to an old kernel.
Error messages are also updated to notify users about the lack of BPF
support in 'perf record' if libelf is missing or the BPF API check
failed.
tools/lib/bpf is added to TAG_FOLDERS to allow us to navigate libbpf
files when working on perf using tools/perf/tags.
Signed-off-by: Wang Nan <wangnan0@huawei.com>
Acked-by: Alexei Starovoitov <ast@plumgrid.com>
Cc: Brendan Gregg <brendan.d.gregg@gmail.com>
Cc: Daniel Borkmann <daniel@iogearbox.net>
Cc: David Ahern <dsahern@gmail.com>
Cc: He Kuang <hekuang@huawei.com>
Cc: Jiri Olsa <jolsa@kernel.org>
Cc: Kaixu Xia <xiakaixu@huawei.com>
Cc: Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Zefan Li <lizefan@huawei.com>
Cc: pi3orama@163.com
Link: http://lkml.kernel.org/r/1444826502-49291-2-git-send-email-wangnan0@huawei.com
[ Document NO_LIBBPF in Makefile.perf, noted by Jiri Olsa ]
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
tools/build/Makefile.feature | 6 ++++--
tools/perf/MANIFEST | 3 +++
tools/perf/Makefile.perf | 21 +++++++++++++++++++--
tools/perf/config/Makefile | 19 ++++++++++++++++++-
tools/perf/tests/make | 4 +++-
5 files changed, 47 insertions(+), 6 deletions(-)
diff --git a/tools/build/Makefile.feature b/tools/build/Makefile.feature
index 72817e4d5e70..37ff4c9f92f1 100644
--- a/tools/build/Makefile.feature
+++ b/tools/build/Makefile.feature
@@ -53,7 +53,8 @@ FEATURE_TESTS ?= \
libdw-dwarf-unwind \
zlib \
lzma \
- get_cpuid
+ get_cpuid \
+ bpf
FEATURE_DISPLAY ?= \
dwarf \
@@ -71,7 +72,8 @@ FEATURE_DISPLAY ?= \
libdw-dwarf-unwind \
zlib \
lzma \
- get_cpuid
+ get_cpuid \
+ bpf
# Set FEATURE_CHECK_(C|LD)FLAGS-all for all FEATURE_TESTS features.
# If in the future we need per-feature checks/flags for features not
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
tools/arch/x86/include/asm/atomic.h
tools/arch/x86/include/asm/rmwcc.h
tools/lib/traceevent
+tools/lib/bpf
tools/lib/api
tools/lib/bpf
tools/lib/hweight.c
@@ -69,6 +70,8 @@ arch/*/lib/memset*.S
include/linux/poison.h
include/linux/hw_breakpoint.h
include/uapi/linux/perf_event.h
+include/uapi/linux/bpf.h
+include/uapi/linux/bpf_common.h
include/uapi/linux/const.h
include/uapi/linux/swab.h
include/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
# Define NO_LZMA if you do not want to support compressed (xz) kernel modules
#
# Define NO_AUXTRACE if you do not want AUX area tracing support
+#
+# Define NO_LIBBPF if you do not want BPF support
# As per kernel Makefile, avoid funny character set dependencies
unexport LC_ALL
@@ -145,6 +147,7 @@ AWK = awk
LIB_DIR = $(srctree)/tools/lib/api/
TRACE_EVENT_DIR = $(srctree)/tools/lib/traceevent/
+BPF_DIR = $(srctree)/tools/lib/bpf/
# include config/Makefile by default and rule out
# non-config cases
@@ -180,6 +183,7 @@ strip-libs = $(filter-out -l%,$(1))
ifneq ($(OUTPUT),)
TE_PATH=$(OUTPUT)
+ BPF_PATH=$(OUTPUT)
ifneq ($(subdir),)
LIB_PATH=$(OUTPUT)/../lib/api/
else
@@ -188,6 +192,7 @@ endif
else
TE_PATH=$(TRACE_EVENT_DIR)
LIB_PATH=$(LIB_DIR)
+ BPF_PATH=$(BPF_DIR)
endif
LIBTRACEEVENT = $(TE_PATH)libtraceevent.a
@@ -199,6 +204,8 @@ LIBTRACEEVENT_DYNAMIC_LIST_LDFLAGS = -Xlinker --dynamic-list=$(LIBTRACEEVENT_DYN
LIBAPI = $(LIB_PATH)libapi.a
export LIBAPI
+LIBBPF = $(BPF_PATH)libbpf.a
+
# python extension build directories
PYTHON_EXTBUILD := $(OUTPUT)python_ext_build/
PYTHON_EXTBUILD_LIB := $(PYTHON_EXTBUILD)lib/
@@ -251,6 +258,9 @@ export PERL_PATH
LIB_FILE=$(OUTPUT)libperf.a
PERFLIBS = $(LIB_FILE) $(LIBAPI) $(LIBTRACEEVENT)
+ifndef NO_LIBBPF
+ PERFLIBS += $(LIBBPF)
+endif
# We choose to avoid "if .. else if .. else .. endif endif"
# because maintaining the nesting to match is a pain. If
@@ -420,6 +430,13 @@ $(LIBAPI)-clean:
$(call QUIET_CLEAN, libapi)
$(Q)$(MAKE) -C $(LIB_DIR) O=$(OUTPUT) clean >/dev/null
+$(LIBBPF): FORCE
+ $(Q)$(MAKE) -C $(BPF_DIR) O=$(OUTPUT) $(OUTPUT)libbpf.a
+
+$(LIBBPF)-clean:
+ $(call QUIET_CLEAN, libbpf)
+ $(Q)$(MAKE) -C $(BPF_DIR) O=$(OUTPUT) clean >/dev/null
+
help:
@echo 'Perf make targets:'
@echo ' doc - make *all* documentation (see below)'
@@ -459,7 +476,7 @@ INSTALL_DOC_TARGETS += quick-install-doc quick-install-man quick-install-html
$(DOC_TARGETS):
$(QUIET_SUBDIR0)Documentation $(QUIET_SUBDIR1) $(@:doc=all)
-TAG_FOLDERS= . ../lib/traceevent ../lib/api ../lib/symbol ../include
+TAG_FOLDERS= . ../lib/traceevent ../lib/api ../lib/symbol ../include ../lib/bpf
TAG_FILES= ../../include/uapi/linux/perf_event.h
TAGS:
@@ -567,7 +584,7 @@ config-clean:
$(call QUIET_CLEAN, config)
$(Q)$(MAKE) -C $(srctree)/tools/build/feature/ clean >/dev/null
-clean: $(LIBTRACEEVENT)-clean $(LIBAPI)-clean config-clean
+clean: $(LIBTRACEEVENT)-clean $(LIBAPI)-clean $(LIBBPF)-clean config-clean
$(call QUIET_CLEAN, core-objs) $(RM) $(LIB_FILE) $(OUTPUT)perf-archive $(OUTPUT)perf-with-kcore $(LANG_BINDINGS)
$(Q)find . -name '*.o' -delete -o -name '\.*.cmd' -delete -o -name '\.*.d' -delete
$(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
FEATURE_CHECK_LDFLAGS-libbabeltrace := $(LIBBABELTRACE_LDFLAGS) -lbabeltrace-ctf
endif
+FEATURE_CHECK_CFLAGS-bpf = -I. -I$(srctree)/tools/include -I$(srctree)/arch/$(ARCH)/include/uapi -I$(srctree)/include/uapi
# include ARCH specific config
-include $(src-perf)/arch/$(ARCH)/Makefile
@@ -237,6 +238,7 @@ ifdef NO_LIBELF
NO_DEMANGLE := 1
NO_LIBUNWIND := 1
NO_LIBDW_DWARF_UNWIND := 1
+ NO_LIBBPF := 1
else
ifeq ($(feature-libelf), 0)
ifeq ($(feature-glibc), 1)
@@ -246,13 +248,14 @@ else
LIBC_SUPPORT := 1
endif
ifeq ($(LIBC_SUPPORT),1)
- msg := $(warning No libelf found, disables 'probe' tool, please install elfutils-libelf-devel/libelf-dev);
+ msg := $(warning No libelf found, disables 'probe' tool and BPF support in 'perf record', please install elfutils-libelf-devel/libelf-dev);
NO_LIBELF := 1
NO_DWARF := 1
NO_DEMANGLE := 1
NO_LIBUNWIND := 1
NO_LIBDW_DWARF_UNWIND := 1
+ NO_LIBBPF := 1
else
ifneq ($(filter s% -static%,$(LDFLAGS),),)
msg := $(error No static glibc found, please install glibc-static);
@@ -309,6 +312,13 @@ ifndef NO_LIBELF
$(call detected,CONFIG_DWARF)
endif # PERF_HAVE_DWARF_REGS
endif # NO_DWARF
+
+ ifndef NO_LIBBPF
+ ifeq ($(feature-bpf), 1)
+ CFLAGS += -DHAVE_LIBBPF_SUPPORT
+ $(call detected,CONFIG_LIBBPF)
+ endif
+ endif # NO_LIBBPF
endif # NO_LIBELF
ifeq ($(ARCH),powerpc)
@@ -324,6 +334,13 @@ ifndef NO_LIBUNWIND
endif
endif
+ifndef NO_LIBBPF
+ ifneq ($(feature-bpf), 1)
+ msg := $(warning BPF API too old. Please install recent kernel headers. BPF support in 'perf record' is disabled.)
+ NO_LIBBPF := 1
+ endif
+endif
+
dwarf-post-unwind := 1
dwarf-post-unwind-text := BUG
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
make_no_libaudit := NO_LIBAUDIT=1
make_no_libbionic := NO_LIBBIONIC=1
make_no_auxtrace := NO_AUXTRACE=1
+make_no_libbpf := NO_LIBBPF=1
make_tags := tags
make_cscope := cscope
make_help := help
@@ -66,7 +67,7 @@ make_static := LDFLAGS=-static
make_minimal := NO_LIBPERL=1 NO_LIBPYTHON=1 NO_NEWT=1 NO_GTK2=1
make_minimal += NO_DEMANGLE=1 NO_LIBELF=1 NO_LIBUNWIND=1 NO_BACKTRACE=1
make_minimal += NO_LIBNUMA=1 NO_LIBAUDIT=1 NO_LIBBIONIC=1
-make_minimal += NO_LIBDW_DWARF_UNWIND=1 NO_AUXTRACE=1
+make_minimal += NO_LIBDW_DWARF_UNWIND=1 NO_AUXTRACE=1 NO_LIBBPF=1
# $(run) contains all available tests
run := make_pure
@@ -94,6 +95,7 @@ run += make_no_libnuma
run += make_no_libaudit
run += make_no_libbionic
run += make_no_auxtrace
+run += make_no_libbpf
run += make_help
run += make_doc
run += make_perf_o
--
2.1.0
^ permalink raw reply related [flat|nested] 9+ messages in thread
* [PATCH 2/6] perf ebpf: Add the libbpf glue
2015-10-29 11:16 [GIT PULL 0/6] perf/ebpf basic integration Arnaldo Carvalho de Melo
2015-10-29 11:16 ` [PATCH 1/6] perf tools: Make perf depend on libbpf Arnaldo Carvalho de Melo
@ 2015-10-29 11:16 ` Arnaldo Carvalho de Melo
2015-10-29 11:16 ` [PATCH 3/6] perf tools: Enable passing bpf object file to --event Arnaldo Carvalho de Melo
` (4 subsequent siblings)
6 siblings, 0 replies; 9+ messages in thread
From: Arnaldo Carvalho de Melo @ 2015-10-29 11:16 UTC (permalink / raw)
To: Ingo Molnar
Cc: linux-kernel, Wang Nan, Brendan Gregg, Daniel Borkmann,
David Ahern, He Kuang, Jiri Olsa, Kaixu Xia, Masami Hiramatsu,
Namhyung Kim, Peter Zijlstra, Zefan Li, pi3orama,
Arnaldo Carvalho de Melo
From: Wang Nan <wangnan0@huawei.com>
The 'bpf-loader.[ch]' files are introduced in this patch. Which will be
the interface between perf and libbpf. bpf__prepare_load() resides in
bpf-loader.c. Following patches will enrich these two files.
Signed-off-by: Wang Nan <wangnan0@huawei.com>
Acked-by: Alexei Starovoitov <ast@plumgrid.com>
Cc: Brendan Gregg <brendan.d.gregg@gmail.com>
Cc: Daniel Borkmann <daniel@iogearbox.net>
Cc: David Ahern <dsahern@gmail.com>
Cc: He Kuang <hekuang@huawei.com>
Cc: Jiri Olsa <jolsa@kernel.org>
Cc: Kaixu Xia <xiakaixu@huawei.com>
Cc: Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Zefan Li <lizefan@huawei.com>
Cc: pi3orama@163.com
Link: http://lkml.kernel.org/r/1444826502-49291-3-git-send-email-wangnan0@huawei.com
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
tools/perf/util/bpf-loader.c | 57 ++++++++++++++++++++++++++++++++++++++++++++
tools/perf/util/bpf-loader.h | 29 ++++++++++++++++++++++
2 files changed, 86 insertions(+)
create mode 100644 tools/perf/util/bpf-loader.c
create mode 100644 tools/perf/util/bpf-loader.h
diff --git a/tools/perf/util/bpf-loader.c b/tools/perf/util/bpf-loader.c
new file mode 100644
index 000000000000..ab56073c5d6e
--- /dev/null
+++ b/tools/perf/util/bpf-loader.c
@@ -0,0 +1,57 @@
+/*
+ * bpf-loader.c
+ *
+ * Copyright (C) 2015 Wang Nan <wangnan0@huawei.com>
+ * Copyright (C) 2015 Huawei Inc.
+ */
+
+#include <bpf/libbpf.h>
+#include <linux/err.h>
+#include "perf.h"
+#include "debug.h"
+#include "bpf-loader.h"
+
+#define DEFINE_PRINT_FN(name, level) \
+static int libbpf_##name(const char *fmt, ...) \
+{ \
+ va_list args; \
+ int ret; \
+ \
+ va_start(args, fmt); \
+ ret = veprintf(level, verbose, pr_fmt(fmt), args);\
+ va_end(args); \
+ return ret; \
+}
+
+DEFINE_PRINT_FN(warning, 0)
+DEFINE_PRINT_FN(info, 0)
+DEFINE_PRINT_FN(debug, 1)
+
+struct bpf_object *bpf__prepare_load(const char *filename)
+{
+ struct bpf_object *obj;
+ static bool libbpf_initialized;
+
+ if (!libbpf_initialized) {
+ libbpf_set_print(libbpf_warning,
+ libbpf_info,
+ libbpf_debug);
+ libbpf_initialized = true;
+ }
+
+ obj = bpf_object__open(filename);
+ if (!obj) {
+ pr_debug("bpf: failed to load %s\n", filename);
+ return ERR_PTR(-EINVAL);
+ }
+
+ return obj;
+}
+
+void bpf__clear(void)
+{
+ struct bpf_object *obj, *tmp;
+
+ bpf_object__for_each_safe(obj, tmp)
+ bpf_object__close(obj);
+}
diff --git a/tools/perf/util/bpf-loader.h b/tools/perf/util/bpf-loader.h
new file mode 100644
index 000000000000..f402d7c8c288
--- /dev/null
+++ b/tools/perf/util/bpf-loader.h
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2015, Wang Nan <wangnan0@huawei.com>
+ * Copyright (C) 2015, Huawei Inc.
+ */
+#ifndef __BPF_LOADER_H
+#define __BPF_LOADER_H
+
+#include <linux/compiler.h>
+#include <linux/err.h>
+#include <string.h>
+#include "debug.h"
+
+struct bpf_object;
+
+#ifdef HAVE_LIBBPF_SUPPORT
+struct bpf_object *bpf__prepare_load(const char *filename);
+
+void bpf__clear(void);
+#else
+static inline struct bpf_object *
+bpf__prepare_load(const char *filename __maybe_unused)
+{
+ pr_debug("ERROR: eBPF object loading is disabled during compiling.\n");
+ return ERR_PTR(-ENOTSUP);
+}
+
+static inline void bpf__clear(void) { }
+#endif
+#endif
--
2.1.0
^ permalink raw reply related [flat|nested] 9+ messages in thread
* [PATCH 3/6] perf tools: Enable passing bpf object file to --event
2015-10-29 11:16 [GIT PULL 0/6] perf/ebpf basic integration Arnaldo Carvalho de Melo
2015-10-29 11:16 ` [PATCH 1/6] perf tools: Make perf depend on libbpf Arnaldo Carvalho de Melo
2015-10-29 11:16 ` [PATCH 2/6] perf ebpf: Add the libbpf glue Arnaldo Carvalho de Melo
@ 2015-10-29 11:16 ` Arnaldo Carvalho de Melo
2015-10-29 11:17 ` [PATCH 4/6] perf tools: Create probe points for BPF programs Arnaldo Carvalho de Melo
` (3 subsequent siblings)
6 siblings, 0 replies; 9+ messages in thread
From: Arnaldo Carvalho de Melo @ 2015-10-29 11:16 UTC (permalink / raw)
To: Ingo Molnar
Cc: linux-kernel, Wang Nan, Alexei Starovoitov, Brendan Gregg,
Daniel Borkmann, David Ahern, He Kuang, Jiri Olsa, Kaixu Xia,
Masami Hiramatsu, Namhyung Kim, Peter Zijlstra, Zefan Li,
pi3orama, Arnaldo Carvalho de Melo
From: Wang Nan <wangnan0@huawei.com>
By introducing new rules in tools/perf/util/parse-events.[ly], this
patch enables 'perf record --event bpf_file.o' to select events by an
eBPF object file. It calls parse_events_load_bpf() to load that file,
which uses bpf__prepare_load() and finally calls bpf_object__open() for
the object files.
After applying this patch, commands like:
# perf record --event foo.o sleep
become possible.
However, at this point it is unable to link any useful things onto the
evsel list because the creating of probe points and BPF program
attaching have not been implemented. Before real events are possible to
be extracted, to avoid perf report error because of empty evsel list,
this patch link a dummy evsel. The dummy event related code will be
removed when probing and extracting code is ready.
Commiter notes:
Using it:
$ ls -la foo.o
ls: cannot access foo.o: No such file or directory
$ perf record --event foo.o sleep
libbpf: failed to open foo.o: No such file or directory
event syntax error: 'foo.o'
\___ BPF object file 'foo.o' is invalid
(add -v to see detail)
Run 'perf list' for a list of valid events
Usage: perf record [<options>] [<command>]
or: perf record [<options>] -- <command> [<options>]
-e, --event <event> event selector. use 'perf list' to list available events
$
$ file /tmp/build/perf/perf.o
/tmp/build/perf/perf.o: ELF 64-bit LSB relocatable, x86-64, version 1 (SYSV), not stripped
$ perf record --event /tmp/build/perf/perf.o sleep
libbpf: /tmp/build/perf/perf.o is not an eBPF object file
event syntax error: '/tmp/build/perf/perf.o'
\___ BPF object file '/tmp/build/perf/perf.o' is invalid
(add -v to see detail)
Run 'perf list' for a list of valid events
Usage: perf record [<options>] [<command>]
or: perf record [<options>] -- <command> [<options>]
-e, --event <event> event selector. use 'perf list' to list available events
$
$ file /tmp/foo.o
/tmp/foo.o: ELF 64-bit LSB relocatable, no machine, version 1 (SYSV), not stripped
$ perf record --event /tmp/foo.o sleep 1
[ perf record: Woken up 1 times to write data ]
[ perf record: Captured and wrote 0.013 MB perf.data ]
$ perf evlist
/tmp/foo.o
$ perf evlist -v
/tmp/foo.o: type: 1, size: 112, config: 0x9, { sample_period, sample_freq }: 4000, sample_type: IP|TID|TIME|PERIOD, disabled: 1, inherit: 1, mmap: 1, comm: 1, freq: 1, enable_on_exec: 1, task: 1, sample_id_all: 1, exclude_guest: 1, mmap2: 1, comm_exec: 1
$
So, type 1 is PERF_TYPE_SOFTWARE, config 0x9 is PERF_COUNT_SW_DUMMY, ok.
$ perf report --stdio
Error:
The perf.data file has no samples!
# To display the perf.data header info, please use --header/--header-only options.
#
$
Signed-off-by: Wang Nan <wangnan0@huawei.com>
Tested-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: Alexei Starovoitov <ast@plumgrid.com>
Cc: Brendan Gregg <brendan.d.gregg@gmail.com>
Cc: Daniel Borkmann <daniel@iogearbox.net>
Cc: David Ahern <dsahern@gmail.com>
Cc: He Kuang <hekuang@huawei.com>
Cc: Jiri Olsa <jolsa@kernel.org>
Cc: Kaixu Xia <xiakaixu@huawei.com>
Cc: Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Zefan Li <lizefan@huawei.com>
Cc: pi3orama@163.com
Link: http://lkml.kernel.org/r/1444826502-49291-4-git-send-email-wangnan0@huawei.com
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
tools/perf/perf.c | 2 ++
tools/perf/util/Build | 1 +
tools/perf/util/parse-events.c | 57 ++++++++++++++++++++++++++++++++++++++++++
tools/perf/util/parse-events.h | 8 ++++++
tools/perf/util/parse-events.l | 3 +++
tools/perf/util/parse-events.y | 18 ++++++++++++-
6 files changed, 88 insertions(+), 1 deletion(-)
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 @@
#include "util/run-command.h"
#include "util/parse-events.h"
#include "util/parse-options.h"
+#include "util/bpf-loader.h"
#include "util/debug.h"
#include <api/fs/tracing_path.h>
#include <pthread.h>
@@ -385,6 +386,7 @@ static int run_builtin(struct cmd_struct *p, int argc, const char **argv)
status = p->fn(argc, argv, prefix);
exit_browser(status);
perf_env__exit(&perf_env);
+ bpf__clear();
if (status)
return status & 0xff;
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
libperf-y += parse-branch-options.o
libperf-y += parse-regs-options.o
+libperf-$(CONFIG_LIBBPF) += bpf-loader.o
libperf-$(CONFIG_LIBELF) += symbol-elf.o
libperf-$(CONFIG_LIBELF) += probe-file.o
libperf-$(CONFIG_LIBELF) += probe-event.o
diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c
index 72abcf254ccb..a9e1d79d17d7 100644
--- a/tools/perf/util/parse-events.c
+++ b/tools/perf/util/parse-events.c
@@ -11,6 +11,7 @@
#include "symbol.h"
#include "cache.h"
#include "header.h"
+#include "bpf-loader.h"
#include "debug.h"
#include <api/fs/tracing_path.h>
#include "parse-events-bison.h"
@@ -529,6 +530,62 @@ static int add_tracepoint_multi_sys(struct list_head *list, int *idx,
return ret;
}
+int parse_events_load_bpf_obj(struct parse_events_evlist *data,
+ struct list_head *list,
+ struct bpf_object *obj)
+{
+ int err;
+ char errbuf[BUFSIZ];
+
+ if (IS_ERR(obj) || !obj) {
+ snprintf(errbuf, sizeof(errbuf),
+ "Internal error: load bpf obj with NULL");
+ err = -EINVAL;
+ goto errout;
+ }
+
+ /*
+ * Temporary add a dummy event here so we can check whether
+ * basic bpf loader works. Following patches will replace
+ * dummy event by useful evsels.
+ */
+ return parse_events_add_numeric(data, list, PERF_TYPE_SOFTWARE,
+ PERF_COUNT_SW_DUMMY, NULL);
+errout:
+ data->error->help = strdup("(add -v to see detail)");
+ data->error->str = strdup(errbuf);
+ return err;
+}
+
+int parse_events_load_bpf(struct parse_events_evlist *data,
+ struct list_head *list,
+ char *bpf_file_name)
+{
+ struct bpf_object *obj;
+
+ obj = bpf__prepare_load(bpf_file_name);
+ if (IS_ERR(obj) || !obj) {
+ char errbuf[BUFSIZ];
+ int err;
+
+ err = obj ? PTR_ERR(obj) : -EINVAL;
+
+ if (err == -ENOTSUP)
+ snprintf(errbuf, sizeof(errbuf),
+ "BPF support is not compiled");
+ else
+ snprintf(errbuf, sizeof(errbuf),
+ "BPF object file '%s' is invalid",
+ bpf_file_name);
+
+ data->error->help = strdup("(add -v to see detail)");
+ data->error->str = strdup(errbuf);
+ return err;
+ }
+
+ return parse_events_load_bpf_obj(data, list, obj);
+}
+
static int
parse_breakpoint_type(const char *type, struct perf_event_attr *attr)
{
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,
char *sys, char *event,
struct parse_events_error *error,
struct list_head *head_config);
+int parse_events_load_bpf(struct parse_events_evlist *data,
+ struct list_head *list,
+ char *bpf_file_name);
+/* Provide this function for perf test */
+struct bpf_object;
+int parse_events_load_bpf_obj(struct parse_events_evlist *data,
+ struct list_head *list,
+ struct bpf_object *obj);
int parse_events_add_numeric(struct parse_events_evlist *data,
struct list_head *list,
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 { \
group [^,{}/]*[{][^}]*[}][^,{}/]*
event_pmu [^,{}/]+[/][^/]*[/][^,{}/]*
event [^,{}/]+
+bpf_object .*\.(o|bpf)
num_dec [0-9]+
num_hex 0x[a-fA-F0-9]+
@@ -159,6 +160,7 @@ modifier_bp [rwx]{1,3}
}
{event_pmu} |
+{bpf_object} |
{event} {
BEGIN(INITIAL);
REWIND(1);
@@ -266,6 +268,7 @@ r{num_raw_hex} { return raw(yyscanner); }
{num_hex} { return value(yyscanner, 16); }
{modifier_event} { return str(yyscanner, PE_MODIFIER_EVENT); }
+{bpf_object} { return str(yyscanner, PE_BPF_OBJECT); }
{name} { return pmu_str_check(yyscanner); }
"/" { BEGIN(config); return '/'; }
- { 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,
%token PE_VALUE PE_VALUE_SYM_HW PE_VALUE_SYM_SW PE_RAW PE_TERM
%token PE_EVENT_NAME
%token PE_NAME
+%token PE_BPF_OBJECT
%token PE_MODIFIER_EVENT PE_MODIFIER_BP
%token PE_NAME_CACHE_TYPE PE_NAME_CACHE_OP_RESULT
%token PE_PREFIX_MEM PE_PREFIX_RAW PE_PREFIX_GROUP
@@ -53,6 +54,7 @@ static inc_group_count(struct list_head *list,
%type <num> PE_RAW
%type <num> PE_TERM
%type <str> PE_NAME
+%type <str> PE_BPF_OBJECT
%type <str> PE_NAME_CACHE_TYPE
%type <str> PE_NAME_CACHE_OP_RESULT
%type <str> PE_MODIFIER_EVENT
@@ -70,6 +72,7 @@ static inc_group_count(struct list_head *list,
%type <tracepoint_name> tracepoint_name
%type <head> event_legacy_numeric
%type <head> event_legacy_raw
+%type <head> event_bpf_file
%type <head> event_def
%type <head> event_mod
%type <head> event_name
@@ -203,7 +206,8 @@ event_def: event_pmu |
event_legacy_mem |
event_legacy_tracepoint sep_dc |
event_legacy_numeric sep_dc |
- event_legacy_raw sep_dc
+ event_legacy_raw sep_dc |
+ event_bpf_file
event_pmu:
PE_NAME '/' event_config '/'
@@ -449,6 +453,18 @@ PE_RAW
$$ = list;
}
+event_bpf_file:
+PE_BPF_OBJECT
+{
+ struct parse_events_evlist *data = _data;
+ struct parse_events_error *error = data->error;
+ struct list_head *list;
+
+ ALLOC_LIST(list);
+ ABORT_ON(parse_events_load_bpf(data, list, $1));
+ $$ = list;
+}
+
start_terms: event_config
{
struct parse_events_terms *data = _data;
--
2.1.0
^ permalink raw reply related [flat|nested] 9+ messages in thread
* [PATCH 4/6] perf tools: Create probe points for BPF programs
2015-10-29 11:16 [GIT PULL 0/6] perf/ebpf basic integration Arnaldo Carvalho de Melo
` (2 preceding siblings ...)
2015-10-29 11:16 ` [PATCH 3/6] perf tools: Enable passing bpf object file to --event Arnaldo Carvalho de Melo
@ 2015-10-29 11:17 ` Arnaldo Carvalho de Melo
2015-10-29 11:17 ` [PATCH 5/6] perf tools: Load eBPF object into kernel Arnaldo Carvalho de Melo
` (2 subsequent siblings)
6 siblings, 0 replies; 9+ messages in thread
From: Arnaldo Carvalho de Melo @ 2015-10-29 11:17 UTC (permalink / raw)
To: Ingo Molnar
Cc: linux-kernel, Wang Nan, Alexei Starovoitov, Brendan Gregg,
Daniel Borkmann, David Ahern, He Kuang, Jiri Olsa, Kaixu Xia,
Masami Hiramatsu, Namhyung Kim, Peter Zijlstra, Zefan Li,
pi3orama, Arnaldo Carvalho de Melo
From: Wang Nan <wangnan0@huawei.com>
This patch introduces bpf__{un,}probe() functions to enable callers to
create kprobe points based on section names a BPF program. It parses the
section names in the program and creates corresponding 'struct
perf_probe_event' structures. The parse_perf_probe_command() function is
used to do the main parsing work. The resuling 'struct perf_probe_event'
is stored into program private data for further using.
By utilizing the new probing API, this patch creates probe points during
event parsing.
To ensure probe points be removed correctly, register an atexit hook so
even perf quit through exit() bpf__clear() is still called, so probing
points are cleared. Note that bpf_clear() should be registered before
bpf__probe() is called, so failure of bpf__probe() can still trigger
bpf__clear() to remove probe points which are already probed.
strerror style error reporting scaffold is created by this patch.
bpf__strerror_probe() is the first error reporting function in
bpf-loader.c.
Committer note:
Trying it:
To build a test eBPF object file:
I am testing using a script I built from the 'perf test -v LLVM' output:
$ cat ~/bin/hello-ebpf
export KERNEL_INC_OPTIONS="-nostdinc -isystem /usr/lib/gcc/x86_64-redhat-linux/4.8.3/include -I/home/acme/git/linux/arch/x86/include -Iarch/x86/include/generated/uapi -Iarch/x86/include/generated -I/home/acme/git/linux/include -Iinclude -I/home/acme/git/linux/arch/x86/include/uapi -Iarch/x86/include/generated/uapi -I/home/acme/git/linux/include/uapi -Iinclude/generated/uapi -include /home/acme/git/linux/include/linux/kconfig.h"
export WORKING_DIR=/lib/modules/4.2.0/build
export CLANG_SOURCE=-
export CLANG_OPTIONS=-xc
OBJ=/tmp/foo.o
rm -f $OBJ
echo '__attribute__((section("fork=do_fork"), used)) int fork(void *ctx) {return 0;} char _license[] __attribute__((section("license"), used)) = "GPL";int _version __attribute__((section("version"), used)) = 0x40100;' | \
clang -D__KERNEL__ $CLANG_OPTIONS $KERNEL_INC_OPTIONS -Wno-unused-value -Wno-pointer-sign -working-directory $WORKING_DIR -c "$CLANG_SOURCE" -target bpf -O2 -o /tmp/foo.o && file $OBJ
---
First asking to put a probe in a function not present in the kernel
(misses the initial _):
$ perf record --event /tmp/foo.o sleep 1
Probe point 'do_fork' not found.
event syntax error: '/tmp/foo.o'
\___ You need to check probing points in BPF file
(add -v to see detail)
Run 'perf list' for a list of valid events
Usage: perf record [<options>] [<command>]
or: perf record [<options>] -- <command> [<options>]
-e, --event <event> event selector. use 'perf list' to list available events
$
---
Now, with "__attribute__((section("fork=_do_fork"), used)):
$ grep _do_fork /proc/kallsyms
ffffffff81099ab0 T _do_fork
$ perf record --event /tmp/foo.o sleep 1
Failed to open kprobe_events: Permission denied
event syntax error: '/tmp/foo.o'
\___ Permission denied
---
Cool, we need to provide some better hints, "kprobe_events" is too low
level, one doesn't strictly need to know the precise details of how
these things are put in place, so something that shows the command
needed to fix the permissions would be more helpful.
Lets try as root instead:
# perf record --event /tmp/foo.o sleep 1
Lowering default frequency rate to 1000.
Please consider tweaking /proc/sys/kernel/perf_event_max_sample_rate.
[ perf record: Woken up 1 times to write data ]
[ perf record: Captured and wrote 0.013 MB perf.data ]
# perf evlist
/tmp/foo.o
[root@felicio ~]# perf evlist -v
/tmp/foo.o: type: 1, size: 112, config: 0x9, { sample_period,
sample_freq }: 1000, sample_type: IP|TID|TIME|PERIOD, disabled: 1,
inherit: 1, mmap: 1, comm: 1, freq: 1, enable_on_exec: 1, task: 1,
sample_id_all: 1, exclude_guest: 1, mmap2: 1, comm_exec: 1
---
Signed-off-by: Wang Nan <wangnan0@huawei.com>
Tested-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: Alexei Starovoitov <ast@plumgrid.com>
Cc: Brendan Gregg <brendan.d.gregg@gmail.com>
Cc: Daniel Borkmann <daniel@iogearbox.net>
Cc: David Ahern <dsahern@gmail.com>
Cc: He Kuang <hekuang@huawei.com>
Cc: Jiri Olsa <jolsa@kernel.org>
Cc: Kaixu Xia <xiakaixu@huawei.com>
Cc: Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Zefan Li <lizefan@huawei.com>
Cc: pi3orama@163.com
Link: http://lkml.kernel.org/r/1444826502-49291-5-git-send-email-wangnan0@huawei.com
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
tools/perf/util/bpf-loader.c | 222 ++++++++++++++++++++++++++++++++++++++++-
tools/perf/util/bpf-loader.h | 30 ++++++
tools/perf/util/parse-events.c | 17 ++++
3 files changed, 268 insertions(+), 1 deletion(-)
diff --git a/tools/perf/util/bpf-loader.c b/tools/perf/util/bpf-loader.c
index ab56073c5d6e..56f6fe8cf318 100644
--- a/tools/perf/util/bpf-loader.c
+++ b/tools/perf/util/bpf-loader.c
@@ -10,6 +10,8 @@
#include "perf.h"
#include "debug.h"
#include "bpf-loader.h"
+#include "probe-event.h"
+#include "probe-finder.h" // for MAX_PROBES
#define DEFINE_PRINT_FN(name, level) \
static int libbpf_##name(const char *fmt, ...) \
@@ -27,6 +29,10 @@ DEFINE_PRINT_FN(warning, 0)
DEFINE_PRINT_FN(info, 0)
DEFINE_PRINT_FN(debug, 1)
+struct bpf_prog_priv {
+ struct perf_probe_event pev;
+};
+
struct bpf_object *bpf__prepare_load(const char *filename)
{
struct bpf_object *obj;
@@ -52,6 +58,220 @@ void bpf__clear(void)
{
struct bpf_object *obj, *tmp;
- bpf_object__for_each_safe(obj, tmp)
+ bpf_object__for_each_safe(obj, tmp) {
+ bpf__unprobe(obj);
bpf_object__close(obj);
+ }
+}
+
+static void
+bpf_prog_priv__clear(struct bpf_program *prog __maybe_unused,
+ void *_priv)
+{
+ struct bpf_prog_priv *priv = _priv;
+
+ cleanup_perf_probe_events(&priv->pev, 1);
+ free(priv);
+}
+
+static int
+config_bpf_program(struct bpf_program *prog)
+{
+ struct perf_probe_event *pev = NULL;
+ struct bpf_prog_priv *priv = NULL;
+ const char *config_str;
+ int err;
+
+ config_str = bpf_program__title(prog, false);
+ if (!config_str) {
+ pr_debug("bpf: unable to get title for program\n");
+ return -EINVAL;
+ }
+
+ priv = calloc(sizeof(*priv), 1);
+ if (!priv) {
+ pr_debug("bpf: failed to alloc priv\n");
+ return -ENOMEM;
+ }
+ pev = &priv->pev;
+
+ pr_debug("bpf: config program '%s'\n", config_str);
+ err = parse_perf_probe_command(config_str, pev);
+ if (err < 0) {
+ pr_debug("bpf: '%s' is not a valid config string\n",
+ config_str);
+ err = -EINVAL;
+ goto errout;
+ }
+
+ if (pev->group && strcmp(pev->group, PERF_BPF_PROBE_GROUP)) {
+ pr_debug("bpf: '%s': group for event is set and not '%s'.\n",
+ config_str, PERF_BPF_PROBE_GROUP);
+ err = -EINVAL;
+ goto errout;
+ } else if (!pev->group)
+ pev->group = strdup(PERF_BPF_PROBE_GROUP);
+
+ if (!pev->group) {
+ pr_debug("bpf: strdup failed\n");
+ err = -ENOMEM;
+ goto errout;
+ }
+
+ if (!pev->event) {
+ pr_debug("bpf: '%s': event name is missing\n",
+ config_str);
+ err = -EINVAL;
+ goto errout;
+ }
+ pr_debug("bpf: config '%s' is ok\n", config_str);
+
+ err = bpf_program__set_private(prog, priv, bpf_prog_priv__clear);
+ if (err) {
+ pr_debug("Failed to set priv for program '%s'\n", config_str);
+ goto errout;
+ }
+
+ return 0;
+
+errout:
+ if (pev)
+ clear_perf_probe_event(pev);
+ free(priv);
+ return err;
+}
+
+static int bpf__prepare_probe(void)
+{
+ static int err = 0;
+ static bool initialized = false;
+
+ /*
+ * Make err static, so if init failed the first, bpf__prepare_probe()
+ * fails each time without calling init_probe_symbol_maps multiple
+ * times.
+ */
+ if (initialized)
+ return err;
+
+ initialized = true;
+ err = init_probe_symbol_maps(false);
+ if (err < 0)
+ pr_debug("Failed to init_probe_symbol_maps\n");
+ probe_conf.max_probes = MAX_PROBES;
+ return err;
+}
+
+int bpf__probe(struct bpf_object *obj)
+{
+ int err = 0;
+ struct bpf_program *prog;
+ struct bpf_prog_priv *priv;
+ struct perf_probe_event *pev;
+
+ err = bpf__prepare_probe();
+ if (err) {
+ pr_debug("bpf__prepare_probe failed\n");
+ return err;
+ }
+
+ bpf_object__for_each_program(prog, obj) {
+ err = config_bpf_program(prog);
+ if (err)
+ goto out;
+
+ err = bpf_program__get_private(prog, (void **)&priv);
+ if (err || !priv)
+ goto out;
+ pev = &priv->pev;
+
+ err = convert_perf_probe_events(pev, 1);
+ if (err < 0) {
+ pr_debug("bpf_probe: failed to convert perf probe events");
+ goto out;
+ }
+
+ err = apply_perf_probe_events(pev, 1);
+ if (err < 0) {
+ pr_debug("bpf_probe: failed to apply perf probe events");
+ goto out;
+ }
+ }
+out:
+ return err < 0 ? err : 0;
+}
+
+#define EVENTS_WRITE_BUFSIZE 4096
+int bpf__unprobe(struct bpf_object *obj)
+{
+ int err, ret = 0;
+ struct bpf_program *prog;
+ struct bpf_prog_priv *priv;
+
+ bpf_object__for_each_program(prog, obj) {
+ int i;
+
+ err = bpf_program__get_private(prog, (void **)&priv);
+ if (err || !priv)
+ continue;
+
+ for (i = 0; i < priv->pev.ntevs; i++) {
+ struct probe_trace_event *tev = &priv->pev.tevs[i];
+ char name_buf[EVENTS_WRITE_BUFSIZE];
+ struct strfilter *delfilter;
+
+ snprintf(name_buf, EVENTS_WRITE_BUFSIZE,
+ "%s:%s", tev->group, tev->event);
+ name_buf[EVENTS_WRITE_BUFSIZE - 1] = '\0';
+
+ delfilter = strfilter__new(name_buf, NULL);
+ if (!delfilter) {
+ pr_debug("Failed to create filter for unprobing\n");
+ ret = -ENOMEM;
+ continue;
+ }
+
+ err = del_perf_probe_events(delfilter);
+ strfilter__delete(delfilter);
+ if (err) {
+ pr_debug("Failed to delete %s\n", name_buf);
+ ret = err;
+ continue;
+ }
+ }
+ }
+ return ret;
+}
+
+#define bpf__strerror_head(err, buf, size) \
+ char sbuf[STRERR_BUFSIZE], *emsg;\
+ if (!size)\
+ return 0;\
+ if (err < 0)\
+ err = -err;\
+ emsg = strerror_r(err, sbuf, sizeof(sbuf));\
+ switch (err) {\
+ default:\
+ scnprintf(buf, size, "%s", emsg);\
+ break;
+
+#define bpf__strerror_entry(val, fmt...)\
+ case val: {\
+ scnprintf(buf, size, fmt);\
+ break;\
+ }
+
+#define bpf__strerror_end(buf, size)\
+ }\
+ buf[size - 1] = '\0';
+
+int bpf__strerror_probe(struct bpf_object *obj __maybe_unused,
+ int err, char *buf, size_t size)
+{
+ bpf__strerror_head(err, buf, size);
+ bpf__strerror_entry(EEXIST, "Probe point exist. Try use 'perf probe -d \"*\"'");
+ bpf__strerror_entry(EPERM, "You need to be root, and /proc/sys/kernel/kptr_restrict should be 0\n");
+ bpf__strerror_entry(ENOENT, "You need to check probing points in BPF file\n");
+ bpf__strerror_end(buf, size);
+ return 0;
}
diff --git a/tools/perf/util/bpf-loader.h b/tools/perf/util/bpf-loader.h
index f402d7c8c288..b819622dc7ce 100644
--- a/tools/perf/util/bpf-loader.h
+++ b/tools/perf/util/bpf-loader.h
@@ -11,11 +11,18 @@
#include "debug.h"
struct bpf_object;
+#define PERF_BPF_PROBE_GROUP "perf_bpf_probe"
#ifdef HAVE_LIBBPF_SUPPORT
struct bpf_object *bpf__prepare_load(const char *filename);
void bpf__clear(void);
+
+int bpf__probe(struct bpf_object *obj);
+int bpf__unprobe(struct bpf_object *obj);
+int bpf__strerror_probe(struct bpf_object *obj, int err,
+ char *buf, size_t size);
+
#else
static inline struct bpf_object *
bpf__prepare_load(const char *filename __maybe_unused)
@@ -25,5 +32,28 @@ bpf__prepare_load(const char *filename __maybe_unused)
}
static inline void bpf__clear(void) { }
+
+static inline int bpf__probe(struct bpf_object *obj __maybe_unused) { return 0;}
+static inline int bpf__unprobe(struct bpf_object *obj __maybe_unused) { return 0;}
+
+static inline int
+__bpf_strerror(char *buf, size_t size)
+{
+ if (!size)
+ return 0;
+ strncpy(buf,
+ "ERROR: eBPF object loading is disabled during compiling.\n",
+ size);
+ buf[size - 1] = '\0';
+ return 0;
+}
+
+static inline int
+bpf__strerror_probe(struct bpf_object *obj __maybe_unused,
+ int err __maybe_unused,
+ char *buf, size_t size)
+{
+ return __bpf_strerror(buf, size);
+}
#endif
#endif
diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c
index a9e1d79d17d7..10a946779f46 100644
--- a/tools/perf/util/parse-events.c
+++ b/tools/perf/util/parse-events.c
@@ -536,6 +536,7 @@ int parse_events_load_bpf_obj(struct parse_events_evlist *data,
{
int err;
char errbuf[BUFSIZ];
+ static bool registered_unprobe_atexit = false;
if (IS_ERR(obj) || !obj) {
snprintf(errbuf, sizeof(errbuf),
@@ -545,6 +546,22 @@ int parse_events_load_bpf_obj(struct parse_events_evlist *data,
}
/*
+ * Register atexit handler before calling bpf__probe() so
+ * bpf__probe() don't need to unprobe probe points its already
+ * created when failure.
+ */
+ if (!registered_unprobe_atexit) {
+ atexit(bpf__clear);
+ registered_unprobe_atexit = true;
+ }
+
+ err = bpf__probe(obj);
+ if (err) {
+ bpf__strerror_probe(obj, err, errbuf, sizeof(errbuf));
+ goto errout;
+ }
+
+ /*
* Temporary add a dummy event here so we can check whether
* basic bpf loader works. Following patches will replace
* dummy event by useful evsels.
--
2.1.0
^ permalink raw reply related [flat|nested] 9+ messages in thread
* [PATCH 5/6] perf tools: Load eBPF object into kernel
2015-10-29 11:16 [GIT PULL 0/6] perf/ebpf basic integration Arnaldo Carvalho de Melo
` (3 preceding siblings ...)
2015-10-29 11:17 ` [PATCH 4/6] perf tools: Create probe points for BPF programs Arnaldo Carvalho de Melo
@ 2015-10-29 11:17 ` Arnaldo Carvalho de Melo
2015-10-29 11:17 ` [PATCH 6/6] perf bpf: Collect perf_evsel in BPF object files Arnaldo Carvalho de Melo
2015-10-29 12:17 ` [GIT PULL 0/6] perf/ebpf basic integration Ingo Molnar
6 siblings, 0 replies; 9+ messages in thread
From: Arnaldo Carvalho de Melo @ 2015-10-29 11:17 UTC (permalink / raw)
To: Ingo Molnar
Cc: linux-kernel, Wang Nan, Alexei Starovoitov, Brendan Gregg,
Daniel Borkmann, David Ahern, He Kuang, Jiri Olsa, Kaixu Xia,
Masami Hiramatsu, Namhyung Kim, Paul Mackerras, Peter Zijlstra,
Zefan Li, pi3orama, Arnaldo Carvalho de Melo
From: Wang Nan <wangnan0@huawei.com>
This patch utilizes bpf_object__load() provided by libbpf to load all
objects into kernel.
Committer notes:
Testing it:
When using an incorrect kernel version number, i.e., having this in your
eBPF proggie:
int _version __attribute__((section("version"), used)) = 0x40100;
For a 4.3.0-rc6+ kernel, say, this happens and needs checking at event
parsing time, to provide a better error report to the user:
# perf record --event /tmp/foo.o sleep 1
libbpf: load bpf program failed: Invalid argument
libbpf: -- BEGIN DUMP LOG ---
libbpf:
libbpf: -- END LOG --
libbpf: failed to load program 'fork=_do_fork'
libbpf: failed to load object '/tmp/foo.o'
event syntax error: '/tmp/foo.o'
\___ Invalid argument: Are you root and runing a CONFIG_BPF_SYSCALL kernel?
(add -v to see detail)
Run 'perf list' for a list of valid events
Usage: perf record [<options>] [<command>]
or: perf record [<options>] -- <command> [<options>]
-e, --event <event> event selector. use 'perf list' to list available events
If we instead make it match, i.e. use 0x40300 on this v4.3.0-rc6+
kernel, the whole process goes thru:
# perf record --event /tmp/foo.o -a usleep 1
[ perf record: Woken up 1 times to write data ]
[ perf record: Captured and wrote 0.202 MB perf.data ]
# perf evlist -v
/tmp/foo.o: type: 1, size: 112, config: 0x9, { sample_period,
sample_freq }: 4000, sample_type: IP|TID|TIME|CPU|PERIOD, disabled: 1,
inherit: 1, mmap: 1, comm: 1, freq: 1, task: 1, sample_id_all: 1,
exclude_guest: 1, mmap2: 1, comm_exec: 1
#
Signed-off-by: Wang Nan <wangnan0@huawei.com>
Tested-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: Alexei Starovoitov <ast@plumgrid.com>
Cc: Brendan Gregg <brendan.d.gregg@gmail.com>
Cc: Daniel Borkmann <daniel@iogearbox.net>
Cc: David Ahern <dsahern@gmail.com>
Cc: He Kuang <hekuang@huawei.com>
Cc: Jiri Olsa <jolsa@kernel.org>
Cc: Kaixu Xia <xiakaixu@huawei.com>
Cc: Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Zefan Li <lizefan@huawei.com>
Cc: pi3orama@163.com
Link: http://lkml.kernel.org/r/1444826502-49291-6-git-send-email-wangnan0@huawei.com
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
tools/perf/util/bpf-loader.c | 22 ++++++++++++++++++++++
tools/perf/util/bpf-loader.h | 11 +++++++++++
tools/perf/util/parse-events.c | 6 ++++++
3 files changed, 39 insertions(+)
diff --git a/tools/perf/util/bpf-loader.c b/tools/perf/util/bpf-loader.c
index 56f6fe8cf318..727955858d00 100644
--- a/tools/perf/util/bpf-loader.c
+++ b/tools/perf/util/bpf-loader.c
@@ -243,6 +243,18 @@ int bpf__unprobe(struct bpf_object *obj)
return ret;
}
+int bpf__load(struct bpf_object *obj)
+{
+ int err;
+
+ err = bpf_object__load(obj);
+ if (err) {
+ pr_debug("bpf: load objects failed\n");
+ return err;
+ }
+ return 0;
+}
+
#define bpf__strerror_head(err, buf, size) \
char sbuf[STRERR_BUFSIZE], *emsg;\
if (!size)\
@@ -275,3 +287,13 @@ int bpf__strerror_probe(struct bpf_object *obj __maybe_unused,
bpf__strerror_end(buf, size);
return 0;
}
+
+int bpf__strerror_load(struct bpf_object *obj __maybe_unused,
+ int err, char *buf, size_t size)
+{
+ bpf__strerror_head(err, buf, size);
+ bpf__strerror_entry(EINVAL, "%s: Are you root and runing a CONFIG_BPF_SYSCALL kernel?",
+ emsg)
+ bpf__strerror_end(buf, size);
+ return 0;
+}
diff --git a/tools/perf/util/bpf-loader.h b/tools/perf/util/bpf-loader.h
index b819622dc7ce..b091ceb19c48 100644
--- a/tools/perf/util/bpf-loader.h
+++ b/tools/perf/util/bpf-loader.h
@@ -23,6 +23,9 @@ int bpf__unprobe(struct bpf_object *obj);
int bpf__strerror_probe(struct bpf_object *obj, int err,
char *buf, size_t size);
+int bpf__load(struct bpf_object *obj);
+int bpf__strerror_load(struct bpf_object *obj, int err,
+ char *buf, size_t size);
#else
static inline struct bpf_object *
bpf__prepare_load(const char *filename __maybe_unused)
@@ -35,6 +38,7 @@ static inline void bpf__clear(void) { }
static inline int bpf__probe(struct bpf_object *obj __maybe_unused) { return 0;}
static inline int bpf__unprobe(struct bpf_object *obj __maybe_unused) { return 0;}
+static inline int bpf__load(struct bpf_object *obj __maybe_unused) { return 0; }
static inline int
__bpf_strerror(char *buf, size_t size)
@@ -55,5 +59,12 @@ bpf__strerror_probe(struct bpf_object *obj __maybe_unused,
{
return __bpf_strerror(buf, size);
}
+
+static inline int bpf__strerror_load(struct bpf_object *obj __maybe_unused,
+ int err __maybe_unused,
+ char *buf, size_t size)
+{
+ return __bpf_strerror(buf, size);
+}
#endif
#endif
diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c
index 10a946779f46..c3aabeb63e88 100644
--- a/tools/perf/util/parse-events.c
+++ b/tools/perf/util/parse-events.c
@@ -561,6 +561,12 @@ int parse_events_load_bpf_obj(struct parse_events_evlist *data,
goto errout;
}
+ err = bpf__load(obj);
+ if (err) {
+ bpf__strerror_load(obj, err, errbuf, sizeof(errbuf));
+ goto errout;
+ }
+
/*
* Temporary add a dummy event here so we can check whether
* basic bpf loader works. Following patches will replace
--
2.1.0
^ permalink raw reply related [flat|nested] 9+ messages in thread
* [PATCH 6/6] perf bpf: Collect perf_evsel in BPF object files
2015-10-29 11:16 [GIT PULL 0/6] perf/ebpf basic integration Arnaldo Carvalho de Melo
` (4 preceding siblings ...)
2015-10-29 11:17 ` [PATCH 5/6] perf tools: Load eBPF object into kernel Arnaldo Carvalho de Melo
@ 2015-10-29 11:17 ` Arnaldo Carvalho de Melo
2015-10-29 12:17 ` [GIT PULL 0/6] perf/ebpf basic integration Ingo Molnar
6 siblings, 0 replies; 9+ messages in thread
From: Arnaldo Carvalho de Melo @ 2015-10-29 11:17 UTC (permalink / raw)
To: Ingo Molnar
Cc: linux-kernel, Wang Nan, Alexei Starovoitov, Brendan Gregg,
Daniel Borkmann, David Ahern, He Kuang, Jiri Olsa, Kaixu Xia,
Masami Hiramatsu, Namhyung Kim, Peter Zijlstra, Zefan Li,
pi3orama, Arnaldo Carvalho de Melo
From: Wang Nan <wangnan0@huawei.com>
This patch creates a 'struct perf_evsel' for every probe in a BPF object
file(s) and fills 'struct evlist' with them. The previously introduced
dummy event is now removed. After this patch, the following command:
# perf record --event filter.o ls
Can trace on each of the probes defined in filter.o.
The core of this patch is bpf__foreach_tev(), which calls a callback
function for each 'struct probe_trace_event' event for a bpf program
with each associated file descriptors. The add_bpf_event() callback
creates evsels by calling parse_events_add_tracepoint().
Since bpf-loader.c will not be built if libbpf is turned off, an empty
bpf__foreach_tev() is defined in bpf-loader.h to avoid build errors.
Committer notes:
Before:
# /tmp/oldperf record --event /tmp/foo.o -a usleep 1
[ perf record: Woken up 1 times to write data ]
[ perf record: Captured and wrote 0.198 MB perf.data ]
# perf evlist
/tmp/foo.o
# perf evlist -v
/tmp/foo.o: type: 1, size: 112, config: 0x9, { sample_period,
sample_freq }: 4000, sample_type: IP|TID|TIME|CPU|PERIOD, disabled: 1,
inherit: 1, mmap: 1, comm: 1, freq: 1, task: 1, sample_id_all: 1,
exclude_guest: 1, mmap2: 1, comm_exec: 1
I.e. we create just the PERF_TYPE_SOFTWARE (type: 1),
PERF_COUNT_SW_DUMMY(config 0x9) event, now, with this patch:
# perf record --event /tmp/foo.o -a usleep 1
[ perf record: Woken up 1 times to write data ]
[ perf record: Captured and wrote 0.210 MB perf.data ]
# perf evlist -v
perf_bpf_probe:fork: type: 2, size: 112, config: 0x6bd, { sample_period,
sample_freq }: 1, sample_type: IP|TID|TIME|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
#
We now have a PERF_TYPE_SOFTWARE (type: 1), but the config states 0x6bd,
which is how, after setting up the event via the kprobes interface, the
'perf_bpf_probe:fork' event is accessible via the perf_event_open
syscall. This is all transient, as soon as the 'perf record' session
ends, these probes will go away.
To see how it looks like, lets try doing a neverending session, one that
expects a control+C to end:
# perf record --event /tmp/foo.o -a
So, with that in place, we can use 'perf probe' to see what is in place:
# perf probe -l
perf_bpf_probe:fork (on _do_fork@acme/git/linux/kernel/fork.c)
We also can use debugfs:
[root@felicio ~]# cat /sys/kernel/debug/tracing/kprobe_events
p:perf_bpf_probe/fork _text+638512
Ok, now lets stop and see if we got some forks:
[root@felicio linux]# perf record --event /tmp/foo.o -a
^C[ perf record: Woken up 1 times to write data ]
[ perf record: Captured and wrote 0.325 MB perf.data (111 samples) ]
[root@felicio linux]# perf script
sshd 1271 [003] 81797.507678: perf_bpf_probe:fork: (ffffffff8109be30)
sshd 18309 [000] 81797.524917: perf_bpf_probe:fork: (ffffffff8109be30)
sshd 18309 [001] 81799.381603: perf_bpf_probe:fork: (ffffffff8109be30)
sshd 18309 [001] 81799.408635: perf_bpf_probe:fork: (ffffffff8109be30)
<SNIP>
Sure enough, we have 111 forks :-)
Callchains seems to work as well:
# perf report --stdio --no-child
# To display the perf.data header info, please use --header/--header-only options.
#
# Total Lost Samples: 0
#
# Samples: 562 of event 'perf_bpf_probe:fork'
# Event count (approx.): 562
#
# Overhead Command Shared Object Symbol
# ........ ........ ................ ............
#
44.66% sh [kernel.vmlinux] [k] _do_fork
|
---_do_fork
entry_SYSCALL_64_fastpath
__libc_fork
make_child
26.16% make [kernel.vmlinux] [k] _do_fork
<SNIP>
#
Signed-off-by: Wang Nan <wangnan0@huawei.com>
Tested-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: Alexei Starovoitov <ast@plumgrid.com>
Cc: Brendan Gregg <brendan.d.gregg@gmail.com>
Cc: Daniel Borkmann <daniel@iogearbox.net>
Cc: David Ahern <dsahern@gmail.com>
Cc: He Kuang <hekuang@huawei.com>
Cc: Jiri Olsa <jolsa@kernel.org>
Cc: Kaixu Xia <xiakaixu@huawei.com>
Cc: Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Zefan Li <lizefan@huawei.com>
Cc: pi3orama@163.com
Link: http://lkml.kernel.org/r/1444826502-49291-7-git-send-email-wangnan0@huawei.com
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
tools/perf/util/bpf-loader.c | 40 ++++++++++++++++++++++++++++++++
tools/perf/util/bpf-loader.h | 14 ++++++++++++
tools/perf/util/parse-events.c | 52 ++++++++++++++++++++++++++++++++++++------
3 files changed, 99 insertions(+), 7 deletions(-)
diff --git a/tools/perf/util/bpf-loader.c b/tools/perf/util/bpf-loader.c
index 727955858d00..aa784a498c48 100644
--- a/tools/perf/util/bpf-loader.c
+++ b/tools/perf/util/bpf-loader.c
@@ -255,6 +255,46 @@ int bpf__load(struct bpf_object *obj)
return 0;
}
+int bpf__foreach_tev(struct bpf_object *obj,
+ bpf_prog_iter_callback_t func,
+ void *arg)
+{
+ struct bpf_program *prog;
+ int err;
+
+ bpf_object__for_each_program(prog, obj) {
+ struct probe_trace_event *tev;
+ struct perf_probe_event *pev;
+ struct bpf_prog_priv *priv;
+ int i, fd;
+
+ err = bpf_program__get_private(prog,
+ (void **)&priv);
+ if (err || !priv) {
+ pr_debug("bpf: failed to get private field\n");
+ return -EINVAL;
+ }
+
+ pev = &priv->pev;
+ for (i = 0; i < pev->ntevs; i++) {
+ tev = &pev->tevs[i];
+
+ fd = bpf_program__fd(prog);
+ if (fd < 0) {
+ pr_debug("bpf: failed to get file descriptor\n");
+ return fd;
+ }
+
+ err = (*func)(tev, fd, arg);
+ if (err) {
+ pr_debug("bpf: call back failed, stop iterate\n");
+ return err;
+ }
+ }
+ }
+ return 0;
+}
+
#define bpf__strerror_head(err, buf, size) \
char sbuf[STRERR_BUFSIZE], *emsg;\
if (!size)\
diff --git a/tools/perf/util/bpf-loader.h b/tools/perf/util/bpf-loader.h
index b091ceb19c48..a8f25ee06fc5 100644
--- a/tools/perf/util/bpf-loader.h
+++ b/tools/perf/util/bpf-loader.h
@@ -8,11 +8,15 @@
#include <linux/compiler.h>
#include <linux/err.h>
#include <string.h>
+#include "probe-event.h"
#include "debug.h"
struct bpf_object;
#define PERF_BPF_PROBE_GROUP "perf_bpf_probe"
+typedef int (*bpf_prog_iter_callback_t)(struct probe_trace_event *tev,
+ int fd, void *arg);
+
#ifdef HAVE_LIBBPF_SUPPORT
struct bpf_object *bpf__prepare_load(const char *filename);
@@ -26,6 +30,8 @@ int bpf__strerror_probe(struct bpf_object *obj, int err,
int bpf__load(struct bpf_object *obj);
int bpf__strerror_load(struct bpf_object *obj, int err,
char *buf, size_t size);
+int bpf__foreach_tev(struct bpf_object *obj,
+ bpf_prog_iter_callback_t func, void *arg);
#else
static inline struct bpf_object *
bpf__prepare_load(const char *filename __maybe_unused)
@@ -41,6 +47,14 @@ static inline int bpf__unprobe(struct bpf_object *obj __maybe_unused) { return 0
static inline int bpf__load(struct bpf_object *obj __maybe_unused) { return 0; }
static inline int
+bpf__foreach_tev(struct bpf_object *obj __maybe_unused,
+ bpf_prog_iter_callback_t func __maybe_unused,
+ void *arg __maybe_unused)
+{
+ return 0;
+}
+
+static inline int
__bpf_strerror(char *buf, size_t size)
{
if (!size)
diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c
index c3aabeb63e88..d97b03710331 100644
--- a/tools/perf/util/parse-events.c
+++ b/tools/perf/util/parse-events.c
@@ -530,12 +530,49 @@ static int add_tracepoint_multi_sys(struct list_head *list, int *idx,
return ret;
}
+struct __add_bpf_event_param {
+ struct parse_events_evlist *data;
+ struct list_head *list;
+};
+
+static int add_bpf_event(struct probe_trace_event *tev, int fd,
+ void *_param)
+{
+ LIST_HEAD(new_evsels);
+ struct __add_bpf_event_param *param = _param;
+ struct parse_events_evlist *evlist = param->data;
+ struct list_head *list = param->list;
+ int err;
+
+ pr_debug("add bpf event %s:%s and attach bpf program %d\n",
+ tev->group, tev->event, fd);
+
+ err = parse_events_add_tracepoint(&new_evsels, &evlist->idx, tev->group,
+ tev->event, evlist->error, NULL);
+ if (err) {
+ struct perf_evsel *evsel, *tmp;
+
+ pr_debug("Failed to add BPF event %s:%s\n",
+ tev->group, tev->event);
+ list_for_each_entry_safe(evsel, tmp, &new_evsels, node) {
+ list_del(&evsel->node);
+ perf_evsel__delete(evsel);
+ }
+ return err;
+ }
+ pr_debug("adding %s:%s\n", tev->group, tev->event);
+
+ list_splice(&new_evsels, list);
+ return 0;
+}
+
int parse_events_load_bpf_obj(struct parse_events_evlist *data,
struct list_head *list,
struct bpf_object *obj)
{
int err;
char errbuf[BUFSIZ];
+ struct __add_bpf_event_param param = {data, list};
static bool registered_unprobe_atexit = false;
if (IS_ERR(obj) || !obj) {
@@ -567,13 +604,14 @@ int parse_events_load_bpf_obj(struct parse_events_evlist *data,
goto errout;
}
- /*
- * Temporary add a dummy event here so we can check whether
- * basic bpf loader works. Following patches will replace
- * dummy event by useful evsels.
- */
- return parse_events_add_numeric(data, list, PERF_TYPE_SOFTWARE,
- PERF_COUNT_SW_DUMMY, NULL);
+ err = bpf__foreach_tev(obj, add_bpf_event, ¶m);
+ if (err) {
+ snprintf(errbuf, sizeof(errbuf),
+ "Attach events in BPF object failed");
+ goto errout;
+ }
+
+ return 0;
errout:
data->error->help = strdup("(add -v to see detail)");
data->error->str = strdup(errbuf);
--
2.1.0
^ permalink raw reply related [flat|nested] 9+ messages in thread
* Re: [GIT PULL 0/6] perf/ebpf basic integration
2015-10-29 11:16 [GIT PULL 0/6] perf/ebpf basic integration Arnaldo Carvalho de Melo
` (5 preceding siblings ...)
2015-10-29 11:17 ` [PATCH 6/6] perf bpf: Collect perf_evsel in BPF object files Arnaldo Carvalho de Melo
@ 2015-10-29 12:17 ` Ingo Molnar
2015-10-29 13:10 ` Arnaldo Carvalho de Melo
6 siblings, 1 reply; 9+ messages in thread
From: Ingo Molnar @ 2015-10-29 12:17 UTC (permalink / raw)
To: Arnaldo Carvalho de Melo
Cc: linux-kernel, Alexei Starovoitov, Brendan Gregg, Daniel Borkmann,
David Ahern, He Kuang, Jiri Olsa, Kaixu Xia, Masami Hiramatsu,
Namhyung Kim, Paul Mackerras, Peter Zijlstra, pi3orama, Wang Nan,
Zefan Li, Arnaldo Carvalho de Melo
* Arnaldo Carvalho de Melo <acme@kernel.org> wrote:
> Hi Ingo,
>
> Please take a look at the changeset comments, I made notes in most of
> them, this seems like a nice cutoff point to allow basic testing, by
> developers, for the very basic integration of perf and ebpf, i.e. we can,
> having a ready built object file, built with clang, be able to use it as a perf
> event, passing it via -e/--event, etc.
>
> Wang has lots more in the queue and I intend to work on them till I get
> all reviewed/tested/merged, i.e. in the immediate future.
>
> What do you think? Fair to get his smaller gulp now? Or do you want to
> get it all the way with the code to get a .c file, build it, etc, that is
> ready, but I haven't reviewed/tested yet?
>
> Ah, this is on top of what I sent to you via perf/core yesterday.
I'm fine with this, as long as this bit:
> 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)
... is treated as the primary interface. Very few people will use object files, so
we need to integrate the whole life-time workflow, from instrumentation source
code to perf output.
Thanks,
Ingo
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [GIT PULL 0/6] perf/ebpf basic integration
2015-10-29 12:17 ` [GIT PULL 0/6] perf/ebpf basic integration Ingo Molnar
@ 2015-10-29 13:10 ` Arnaldo Carvalho de Melo
0 siblings, 0 replies; 9+ messages in thread
From: Arnaldo Carvalho de Melo @ 2015-10-29 13:10 UTC (permalink / raw)
To: Ingo Molnar
Cc: linux-kernel, Alexei Starovoitov, Brendan Gregg, Daniel Borkmann,
David Ahern, He Kuang, Jiri Olsa, Kaixu Xia, Masami Hiramatsu,
Namhyung Kim, Paul Mackerras, Peter Zijlstra, pi3orama, Wang Nan,
Zefan Li
Em Thu, Oct 29, 2015 at 01:17:32PM +0100, Ingo Molnar escreveu:
> * Arnaldo Carvalho de Melo <acme@kernel.org> wrote:
> > Please take a look at the changeset comments, I made notes in most of
> > them, this seems like a nice cutoff point to allow basic testing, by
> > developers, for the very basic integration of perf and ebpf, i.e. we can,
> > having a ready built object file, built with clang, be able to use it as a perf
> > event, passing it via -e/--event, etc.
> > Wang has lots more in the queue and I intend to work on them till I get
> > all reviewed/tested/merged, i.e. in the immediate future.
> > What do you think? Fair to get his smaller gulp now? Or do you want to
> > get it all the way with the code to get a .c file, build it, etc, that is
> > ready, but I haven't reviewed/tested yet?
> > Ah, this is on top of what I sent to you via perf/core yesterday.
> I'm fine with this, as long as this bit:
> > 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)
> ... is treated as the primary interface. Very few people will use object files, so
> we need to integrate the whole life-time workflow, from instrumentation source
> code to perf output.
Sure, I'm doing the review/test now, but at the same time, stressing
that you _can_ shortcut all that and, having a suitable .o file, use all
the other perf features with it is also cool and something worth
pointing out.
To _have to_ produce a .o to use this is, of course, bad and shortly
will be done completely automatically in as a streamlined way as we can
conceive.
- Arnaldo
^ permalink raw reply [flat|nested] 9+ messages in thread
end of thread, other threads:[~2015-10-29 13:10 UTC | newest]
Thread overview: 9+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2015-10-29 11:16 [GIT PULL 0/6] perf/ebpf basic integration Arnaldo Carvalho de Melo
2015-10-29 11:16 ` [PATCH 1/6] perf tools: Make perf depend on libbpf Arnaldo Carvalho de Melo
2015-10-29 11:16 ` [PATCH 2/6] perf ebpf: Add the libbpf glue Arnaldo Carvalho de Melo
2015-10-29 11:16 ` [PATCH 3/6] perf tools: Enable passing bpf object file to --event Arnaldo Carvalho de Melo
2015-10-29 11:17 ` [PATCH 4/6] perf tools: Create probe points for BPF programs Arnaldo Carvalho de Melo
2015-10-29 11:17 ` [PATCH 5/6] perf tools: Load eBPF object into kernel Arnaldo Carvalho de Melo
2015-10-29 11:17 ` [PATCH 6/6] perf bpf: Collect perf_evsel in BPF object files Arnaldo Carvalho de Melo
2015-10-29 12:17 ` [GIT PULL 0/6] perf/ebpf basic integration Ingo Molnar
2015-10-29 13:10 ` Arnaldo Carvalho de Melo
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox