[PATCH 03/13] perf tools: Add bpf command
Adding perf bpf command to allow to provide some fucs over ebpf objects, like compile, disassembly and loading, which is comming in following patches. Link: http://lkml.kernel.org/n/tip-51vi69jgn3nfa00azjlik...@git.kernel.org Signed-off-by: Jiri Olsa--- tools/perf/Build| 1 + tools/perf/builtin-bpf.c| 199 tools/perf/builtin.h| 1 + tools/perf/command-list.txt | 1 + tools/perf/perf.c | 1 + 5 files changed, 203 insertions(+) create mode 100644 tools/perf/builtin-bpf.c diff --git a/tools/perf/Build b/tools/perf/Build index e5232d567611..7f521ac16466 100644 --- a/tools/perf/Build +++ b/tools/perf/Build @@ -24,6 +24,7 @@ perf-y += builtin-mem.o perf-y += builtin-data.o perf-y += builtin-version.o perf-y += builtin-c2c.o +perf-y += builtin-bpf.o perf-$(CONFIG_TRACE) += builtin-trace.o perf-$(CONFIG_LIBELF) += builtin-probe.o diff --git a/tools/perf/builtin-bpf.c b/tools/perf/builtin-bpf.c new file mode 100644 index ..6f02352caf79 --- /dev/null +++ b/tools/perf/builtin-bpf.c @@ -0,0 +1,199 @@ +#include +#include +#include +#include +#include +#include +#include "builtin.h" +#include "perf.h" +#include "target.h" +#include "debug.h" +#include "parse-events.h" +#include "evlist.h" +#include "evsel.h" +#include "bpf-loader.h" + +struct perf_bpf { + struct targettarget; + struct perf_evlist *evlist; +}; + +struct perf_bpf bpf = { + .target = { .uid = UINT_MAX, }, +}; + +static volatile int done; +static volatile int workload_exec_errno; + +static void sig_handler(int sig __maybe_unused) +{ + done = 1; +} + +/* + * perf_evlist__prepare_workload will send a SIGUSR1 + * if the fork fails, since we asked by setting its + * want_signal to true. + */ +static void workload_exec_failed_signal(int signo __maybe_unused, siginfo_t *info, + void *ucontext __maybe_unused) +{ + workload_exec_errno = info->si_value.sival_int; +} + +static int create_perf_bpf_counter(struct perf_evsel *evsel) +{ + if (target__has_cpu() && !target__has_per_thread()) + return perf_evsel__open_per_cpu(evsel, perf_evsel__cpus(evsel)); + + return perf_evsel__open_per_thread(evsel, bpf.evlist->threads); +} + +static int __cmd_bpf(int argc , const char **argv) +{ + struct perf_evsel *evsel; + bool forks = argc > 0; + int err, status; + int child_pid = -1; + char msg[BUFSIZ]; + struct timespec ts = { .tv_sec = 0, .tv_nsec = 500 }; + + if (forks) { + err = perf_evlist__prepare_workload(bpf.evlist, , + argv, true, + workload_exec_failed_signal); + if (err < 0) { + pr_err("Couldn't run the workload!\n"); + status = err; + goto out; + } + + child_pid = bpf.evlist->workload.pid; + } + +evlist__for_each_entry(bpf.evlist, evsel) { +err =create_perf_bpf_counter(evsel); + if (err < 0) { +perf_evsel__open_strerror(evsel, , + errno, msg, sizeof(msg)); +pr_err("%s\n", msg); + goto out_child; +} + } + + err = bpf__apply_obj_config(); + if (err) { + char errbuf[BUFSIZ]; + + bpf__strerror_apply_obj_config(err, errbuf, sizeof(errbuf)); + pr_err("ERROR: Apply config to BPF failed: %s\n", + errbuf); + goto out_child; + } + + if (forks) { + perf_evlist__start_workload(bpf.evlist); + + if (!target__none()) + perf_evlist__enable(bpf.evlist); + +waitpid(child_pid, , 0); +} else { + if (!target__none()) + perf_evlist__enable(bpf.evlist); + +while (!done) { +nanosleep(, NULL); +} +} + + if (!target__none()) + perf_evlist__disable(bpf.evlist); + + child_pid = -1; + +out_child: + if (forks) { +if (workload_exec_errno) { +const char *emsg = str_error_r(workload_exec_errno, msg, sizeof(msg)); +pr_err("Workload failed: %s\n", emsg); +return -1; +} + + if (child_pid != -1) { + kill(child_pid, SIGTERM); + waitpid(child_pid, , 0); + } + +if (WIFSIGNALED(status)) +psignal(WTERMSIG(status), argv[0]); + } + +out: +
[PATCH 03/13] perf tools: Add bpf command
Adding perf bpf command to allow to provide some fucs over ebpf objects, like compile, disassembly and loading, which is comming in following patches. Link: http://lkml.kernel.org/n/tip-51vi69jgn3nfa00azjlik...@git.kernel.org Signed-off-by: Jiri Olsa --- tools/perf/Build| 1 + tools/perf/builtin-bpf.c| 199 tools/perf/builtin.h| 1 + tools/perf/command-list.txt | 1 + tools/perf/perf.c | 1 + 5 files changed, 203 insertions(+) create mode 100644 tools/perf/builtin-bpf.c diff --git a/tools/perf/Build b/tools/perf/Build index e5232d567611..7f521ac16466 100644 --- a/tools/perf/Build +++ b/tools/perf/Build @@ -24,6 +24,7 @@ perf-y += builtin-mem.o perf-y += builtin-data.o perf-y += builtin-version.o perf-y += builtin-c2c.o +perf-y += builtin-bpf.o perf-$(CONFIG_TRACE) += builtin-trace.o perf-$(CONFIG_LIBELF) += builtin-probe.o diff --git a/tools/perf/builtin-bpf.c b/tools/perf/builtin-bpf.c new file mode 100644 index ..6f02352caf79 --- /dev/null +++ b/tools/perf/builtin-bpf.c @@ -0,0 +1,199 @@ +#include +#include +#include +#include +#include +#include +#include "builtin.h" +#include "perf.h" +#include "target.h" +#include "debug.h" +#include "parse-events.h" +#include "evlist.h" +#include "evsel.h" +#include "bpf-loader.h" + +struct perf_bpf { + struct targettarget; + struct perf_evlist *evlist; +}; + +struct perf_bpf bpf = { + .target = { .uid = UINT_MAX, }, +}; + +static volatile int done; +static volatile int workload_exec_errno; + +static void sig_handler(int sig __maybe_unused) +{ + done = 1; +} + +/* + * perf_evlist__prepare_workload will send a SIGUSR1 + * if the fork fails, since we asked by setting its + * want_signal to true. + */ +static void workload_exec_failed_signal(int signo __maybe_unused, siginfo_t *info, + void *ucontext __maybe_unused) +{ + workload_exec_errno = info->si_value.sival_int; +} + +static int create_perf_bpf_counter(struct perf_evsel *evsel) +{ + if (target__has_cpu() && !target__has_per_thread()) + return perf_evsel__open_per_cpu(evsel, perf_evsel__cpus(evsel)); + + return perf_evsel__open_per_thread(evsel, bpf.evlist->threads); +} + +static int __cmd_bpf(int argc , const char **argv) +{ + struct perf_evsel *evsel; + bool forks = argc > 0; + int err, status; + int child_pid = -1; + char msg[BUFSIZ]; + struct timespec ts = { .tv_sec = 0, .tv_nsec = 500 }; + + if (forks) { + err = perf_evlist__prepare_workload(bpf.evlist, , + argv, true, + workload_exec_failed_signal); + if (err < 0) { + pr_err("Couldn't run the workload!\n"); + status = err; + goto out; + } + + child_pid = bpf.evlist->workload.pid; + } + +evlist__for_each_entry(bpf.evlist, evsel) { +err =create_perf_bpf_counter(evsel); + if (err < 0) { +perf_evsel__open_strerror(evsel, , + errno, msg, sizeof(msg)); +pr_err("%s\n", msg); + goto out_child; +} + } + + err = bpf__apply_obj_config(); + if (err) { + char errbuf[BUFSIZ]; + + bpf__strerror_apply_obj_config(err, errbuf, sizeof(errbuf)); + pr_err("ERROR: Apply config to BPF failed: %s\n", + errbuf); + goto out_child; + } + + if (forks) { + perf_evlist__start_workload(bpf.evlist); + + if (!target__none()) + perf_evlist__enable(bpf.evlist); + +waitpid(child_pid, , 0); +} else { + if (!target__none()) + perf_evlist__enable(bpf.evlist); + +while (!done) { +nanosleep(, NULL); +} +} + + if (!target__none()) + perf_evlist__disable(bpf.evlist); + + child_pid = -1; + +out_child: + if (forks) { +if (workload_exec_errno) { +const char *emsg = str_error_r(workload_exec_errno, msg, sizeof(msg)); +pr_err("Workload failed: %s\n", emsg); +return -1; +} + + if (child_pid != -1) { + kill(child_pid, SIGTERM); + waitpid(child_pid, , 0); + } + +if (WIFSIGNALED(status)) +psignal(WTERMSIG(status), argv[0]); + } + +out: +