[PATCH 03/13] perf tools: Add bpf command

2018-03-12 Thread Jiri Olsa
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

2018-03-12 Thread Jiri Olsa
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:
+