Like tracepoint in kernel code, uBPF hooks can be added in perf code and
trigger uBPF programs passed by BPF scripts. The first two uBPF hooks
added are record start/end. uBPF scripts can initial BPF maps in
record start, and report result when record finished.

Signed-off-by: He Kuang <heku...@huawei.com>
Signed-off-by: Wang Nan <wangn...@huawei.com>
---
 tools/perf/builtin-record.c       |  4 +++
 tools/perf/util/Build             |  2 +-
 tools/perf/util/ubpf-hooks-list.h | 34 ++++++++++++++++++++
 tools/perf/util/ubpf-hooks.c      | 68 +++++++++++++++++++++++++++++++++++++++
 tools/perf/util/ubpf-hooks.h      | 41 +++++++++++++++++++++++
 5 files changed, 148 insertions(+), 1 deletion(-)
 create mode 100644 tools/perf/util/ubpf-hooks-list.h
 create mode 100644 tools/perf/util/ubpf-hooks.c
 create mode 100644 tools/perf/util/ubpf-hooks.h

diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c
index 81411b1..c956d57 100644
--- a/tools/perf/builtin-record.c
+++ b/tools/perf/builtin-record.c
@@ -36,6 +36,7 @@
 #include "util/llvm-utils.h"
 #include "util/bpf-loader.h"
 #include "util/trigger.h"
+#include "util/ubpf-hooks.h"
 #include "asm/bug.h"
 
 #include <unistd.h>
@@ -893,6 +894,7 @@ static int __cmd_record(struct record *rec, int argc, const 
char **argv)
 
        trigger_ready(&auxtrace_snapshot_trigger);
        trigger_ready(&switch_output_trigger);
+       ubpf_hook_perf_record_start(0);
        for (;;) {
                unsigned long long hits = rec->samples;
 
@@ -957,6 +959,8 @@ static int __cmd_record(struct record *rec, int argc, const 
char **argv)
                        disabled = true;
                }
        }
+       ubpf_hook_perf_record_end(rec->samples, 0);
+
        trigger_off(&auxtrace_snapshot_trigger);
        trigger_off(&switch_output_trigger);
 
diff --git a/tools/perf/util/Build b/tools/perf/util/Build
index d12ef7d..80f3c20 100644
--- a/tools/perf/util/Build
+++ b/tools/perf/util/Build
@@ -87,7 +87,7 @@ libperf-y += mem-events.o
 
 libperf-$(CONFIG_LIBBPF) += bpf-loader.o
 libperf-$(CONFIG_BPF_PROLOGUE) += bpf-prologue.o
-libperf-$(CONFIG_UBPF) += ubpf-helpers.o
+libperf-$(CONFIG_UBPF) += ubpf-helpers.o ubpf-hooks.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/ubpf-hooks-list.h 
b/tools/perf/util/ubpf-hooks-list.h
new file mode 100644
index 0000000..b796334
--- /dev/null
+++ b/tools/perf/util/ubpf-hooks-list.h
@@ -0,0 +1,34 @@
+UBPF_HOOK(perf_record_start,
+         __UBPF_HOOK_PROTO(
+                 __proto(int dummy)
+                 ),
+
+         __UBPF_HOOK_ARGS(dummy),
+
+         __UBPF_HOOK_STRUCT__entry(
+                 __field(int,  dummy)
+                 ),
+
+         __UBPF_HOOK_ASSIGN(
+                 __entry.dummy = dummy;
+                 )
+       );
+
+UBPF_HOOK(perf_record_end,
+         __UBPF_HOOK_PROTO(
+                 __proto(int samples),
+                 __proto(int dummy)
+                 ),
+
+         __UBPF_HOOK_ARGS(samples, dummy),
+
+         __UBPF_HOOK_STRUCT__entry(
+                 __field(int,  samples)
+                 __field(int,  dummy)
+                 ),
+
+         __UBPF_HOOK_ASSIGN(
+                 __entry.samples = samples;
+                 __entry.dummy = dummy;
+                 )
+       );
diff --git a/tools/perf/util/ubpf-hooks.c b/tools/perf/util/ubpf-hooks.c
new file mode 100644
index 0000000..6ffe344
--- /dev/null
+++ b/tools/perf/util/ubpf-hooks.c
@@ -0,0 +1,68 @@
+/*
+ * Copyright (C) 2016, Wang Nan <wangn...@huawei.com>
+ * Copyright (C) 2016, He Kuang <heku...@huawei.com>
+ * Copyright (C) 2016, Huawei Inc.
+ */
+
+#include <bpf/libbpf.h>
+#include <asm/bug.h>
+#include <ubpf.h>
+#include "ubpf-hooks.h"
+#include "debug.h"
+
+static int run_ubpf_program(struct bpf_program *prog __maybe_unused,
+                           void *mem __maybe_unused, size_t len __maybe_unused)
+{
+       return 0;
+}
+
+static int
+run_ubpf_programs(const char *expect_title, void *mem, size_t len)
+{
+
+       struct bpf_object *obj, *tmp;
+       struct bpf_program *prog;
+       const char *title;
+       int err;
+
+       bpf_object__for_each_safe(obj, tmp) {
+               bpf_object__for_each_program(prog, obj) {
+                       if (bpf_program__is_ubpf(prog)) {
+                               title = bpf_program__title(prog, false);
+                               if (!title)
+                                       continue;
+                               if (strcmp(title, expect_title) != 0)
+                                       continue;
+                               err = run_ubpf_program(prog, mem, len);
+                               if (err)
+                                       return err;
+                       }
+               }
+       }
+
+       return 0;
+}
+
+#define __UBPF_HOOK_PROTO(args...) args
+#define __UBPF_HOOK_ARG(args...) args
+#define __UBPF_HOOK_STRUCT__entry(args...) args
+#define __proto(args) args
+#define __field(type, item)            type    item;
+
+#define UBPF_HOOK(name, proto, args, tstruct, assign)  \
+       struct ubpf_hook_##name##_proto {tstruct}
+#include "ubpf-hooks-list.h"
+#undef UBPF_HOOK
+
+#define __UBPF_HOOK_ASSIGN(code...) code
+
+#define UBPF_HOOK(name, proto, args, tstruct, assign)                  \
+       int ubpf_hook_##name(proto)                                     \
+       {                                                               \
+               struct ubpf_hook_##name##_proto __entry;                \
+               assign;                                                 \
+               return run_ubpf_programs("UBPF;"#name,                  \
+                                        &__entry, sizeof(__entry));    \
+       }
+#include "ubpf-hooks-list.h"
+#undef UBPF_HOOK
diff --git a/tools/perf/util/ubpf-hooks.h b/tools/perf/util/ubpf-hooks.h
new file mode 100644
index 0000000..4d2f23e
--- /dev/null
+++ b/tools/perf/util/ubpf-hooks.h
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2016, Wang Nan <wangn...@huawei.com>
+ * Copyright (C) 2016, He Kuang <heku...@huawei.com>
+ * Copyright (C) 2016, Huawei Inc.
+ */
+#ifndef __PERF_UBPF_HOOKS_H
+#define __PERF_UBPF_HOOKS_H
+
+#include <linux/compiler.h>
+
+#define UBPF_HOOK_BREAKABLE    1
+
+#define __UBPF_HOOK_PROTO(args...) args
+#define __UBPF_HOOK_ARG(args...) args
+#define __UBPF_HOOK_STRUCT__entry(args...) args
+#define __field(type, item)            type    item;
+
+#ifdef HAVE_UBPF_SUPPORT
+
+#define __proto(args) args
+#define UBPF_HOOK(name, proto, args, struct, assign) int 
ubpf_hook_##name(proto)
+
+#include "ubpf-hooks-list.h"
+
+#else
+
+#define __proto(args) args __maybe_unused
+#define UBPF_HOOK(name, proto, args, struct, assign)           \
+       static inline int ubpf_hook_##name(proto) {return 0; }  \
+
+#include "ubpf-hooks-list.h"
+#endif
+
+#undef UBPF_HOOK
+#undef __UBPF_HOOK_PROTO
+#undef __UBPF_HOOK_ARG
+#undef __UBPF_HOOK_STRUCT__entry
+#undef __field
+#undef __proto
+
+#endif /* __PERF_UBPF_HOOKS_H */
-- 
1.8.5.2

Reply via email to