aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorWang Nan <wangnan0@huawei.com>2015-06-30 22:13:50 -0400
committerArnaldo Carvalho de Melo <acme@redhat.com>2015-08-06 14:29:14 -0400
commit04a22fae4cbc1f7d3f7471e9b36359f98bd3f043 (patch)
tree56aaf8966290b8718c6792ec0df9095221fd8d8a
parent098d2164e3441c252eaa28906d45e16b7bf1bd2b (diff)
tracing, perf: Implement BPF programs attached to uprobes
By copying BPF related operation to uprobe processing path, this patch allow users attach BPF programs to uprobes like what they are already doing on kprobes. After this patch, users are allowed to use PERF_EVENT_IOC_SET_BPF on a uprobe perf event. Which make it possible to profile user space programs and kernel events together using BPF. Because of this patch, CONFIG_BPF_EVENTS should be selected by CONFIG_UPROBE_EVENT to ensure trace_call_bpf() is compiled even if KPROBE_EVENT is not set. 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/1435716878-189507-3-git-send-email-wangnan0@huawei.com Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
-rw-r--r--include/linux/trace_events.h5
-rw-r--r--kernel/events/core.c4
-rw-r--r--kernel/trace/Kconfig2
-rw-r--r--kernel/trace/trace_uprobe.c5
4 files changed, 13 insertions, 3 deletions
diff --git a/include/linux/trace_events.h b/include/linux/trace_events.h
index 180dbf8720f9..ed27917cabc9 100644
--- a/include/linux/trace_events.h
+++ b/include/linux/trace_events.h
@@ -243,6 +243,7 @@ enum {
243 TRACE_EVENT_FL_USE_CALL_FILTER_BIT, 243 TRACE_EVENT_FL_USE_CALL_FILTER_BIT,
244 TRACE_EVENT_FL_TRACEPOINT_BIT, 244 TRACE_EVENT_FL_TRACEPOINT_BIT,
245 TRACE_EVENT_FL_KPROBE_BIT, 245 TRACE_EVENT_FL_KPROBE_BIT,
246 TRACE_EVENT_FL_UPROBE_BIT,
246}; 247};
247 248
248/* 249/*
@@ -257,6 +258,7 @@ enum {
257 * USE_CALL_FILTER - For trace internal events, don't use file filter 258 * USE_CALL_FILTER - For trace internal events, don't use file filter
258 * TRACEPOINT - Event is a tracepoint 259 * TRACEPOINT - Event is a tracepoint
259 * KPROBE - Event is a kprobe 260 * KPROBE - Event is a kprobe
261 * UPROBE - Event is a uprobe
260 */ 262 */
261enum { 263enum {
262 TRACE_EVENT_FL_FILTERED = (1 << TRACE_EVENT_FL_FILTERED_BIT), 264 TRACE_EVENT_FL_FILTERED = (1 << TRACE_EVENT_FL_FILTERED_BIT),
@@ -267,8 +269,11 @@ enum {
267 TRACE_EVENT_FL_USE_CALL_FILTER = (1 << TRACE_EVENT_FL_USE_CALL_FILTER_BIT), 269 TRACE_EVENT_FL_USE_CALL_FILTER = (1 << TRACE_EVENT_FL_USE_CALL_FILTER_BIT),
268 TRACE_EVENT_FL_TRACEPOINT = (1 << TRACE_EVENT_FL_TRACEPOINT_BIT), 270 TRACE_EVENT_FL_TRACEPOINT = (1 << TRACE_EVENT_FL_TRACEPOINT_BIT),
269 TRACE_EVENT_FL_KPROBE = (1 << TRACE_EVENT_FL_KPROBE_BIT), 271 TRACE_EVENT_FL_KPROBE = (1 << TRACE_EVENT_FL_KPROBE_BIT),
272 TRACE_EVENT_FL_UPROBE = (1 << TRACE_EVENT_FL_UPROBE_BIT),
270}; 273};
271 274
275#define TRACE_EVENT_FL_UKPROBE (TRACE_EVENT_FL_KPROBE | TRACE_EVENT_FL_UPROBE)
276
272struct trace_event_call { 277struct trace_event_call {
273 struct list_head list; 278 struct list_head list;
274 struct trace_event_class *class; 279 struct trace_event_class *class;
diff --git a/kernel/events/core.c b/kernel/events/core.c
index bdea12924b11..77f9e5d0e2d1 100644
--- a/kernel/events/core.c
+++ b/kernel/events/core.c
@@ -6846,8 +6846,8 @@ static int perf_event_set_bpf_prog(struct perf_event *event, u32 prog_fd)
6846 if (event->tp_event->prog) 6846 if (event->tp_event->prog)
6847 return -EEXIST; 6847 return -EEXIST;
6848 6848
6849 if (!(event->tp_event->flags & TRACE_EVENT_FL_KPROBE)) 6849 if (!(event->tp_event->flags & TRACE_EVENT_FL_UKPROBE))
6850 /* bpf programs can only be attached to kprobes */ 6850 /* bpf programs can only be attached to u/kprobes */
6851 return -EINVAL; 6851 return -EINVAL;
6852 6852
6853 prog = bpf_prog_get(prog_fd); 6853 prog = bpf_prog_get(prog_fd);
diff --git a/kernel/trace/Kconfig b/kernel/trace/Kconfig
index 3b9a48ae153a..1153c43428f3 100644
--- a/kernel/trace/Kconfig
+++ b/kernel/trace/Kconfig
@@ -434,7 +434,7 @@ config UPROBE_EVENT
434 434
435config BPF_EVENTS 435config BPF_EVENTS
436 depends on BPF_SYSCALL 436 depends on BPF_SYSCALL
437 depends on KPROBE_EVENT 437 depends on KPROBE_EVENT || UPROBE_EVENT
438 bool 438 bool
439 default y 439 default y
440 help 440 help
diff --git a/kernel/trace/trace_uprobe.c b/kernel/trace/trace_uprobe.c
index aa1ea7b36fa8..f97479f1ce35 100644
--- a/kernel/trace/trace_uprobe.c
+++ b/kernel/trace/trace_uprobe.c
@@ -1095,11 +1095,15 @@ static void __uprobe_perf_func(struct trace_uprobe *tu,
1095{ 1095{
1096 struct trace_event_call *call = &tu->tp.call; 1096 struct trace_event_call *call = &tu->tp.call;
1097 struct uprobe_trace_entry_head *entry; 1097 struct uprobe_trace_entry_head *entry;
1098 struct bpf_prog *prog = call->prog;
1098 struct hlist_head *head; 1099 struct hlist_head *head;
1099 void *data; 1100 void *data;
1100 int size, esize; 1101 int size, esize;
1101 int rctx; 1102 int rctx;
1102 1103
1104 if (prog && !trace_call_bpf(prog, regs))
1105 return;
1106
1103 esize = SIZEOF_TRACE_ENTRY(is_ret_probe(tu)); 1107 esize = SIZEOF_TRACE_ENTRY(is_ret_probe(tu));
1104 1108
1105 size = esize + tu->tp.size + dsize; 1109 size = esize + tu->tp.size + dsize;
@@ -1289,6 +1293,7 @@ static int register_uprobe_event(struct trace_uprobe *tu)
1289 return -ENODEV; 1293 return -ENODEV;
1290 } 1294 }
1291 1295
1296 call->flags = TRACE_EVENT_FL_UPROBE;
1292 call->class->reg = trace_uprobe_register; 1297 call->class->reg = trace_uprobe_register;
1293 call->data = tu; 1298 call->data = tu;
1294 ret = trace_add_event_call(call); 1299 ret = trace_add_event_call(call);