aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/linux/ftrace_event.h8
-rw-r--r--include/linux/perf_event.h2
-rw-r--r--include/trace/ftrace.h3
-rw-r--r--kernel/perf_event.c15
-rw-r--r--kernel/trace/trace_event_perf.c11
-rw-r--r--kernel/trace/trace_kprobe.c4
-rw-r--r--kernel/trace/trace_syscalls.c6
7 files changed, 31 insertions, 18 deletions
diff --git a/include/linux/ftrace_event.h b/include/linux/ftrace_event.h
index c0f4b364c711..c8091001b943 100644
--- a/include/linux/ftrace_event.h
+++ b/include/linux/ftrace_event.h
@@ -132,6 +132,7 @@ struct ftrace_event_call {
132 void *data; 132 void *data;
133 133
134 int perf_refcount; 134 int perf_refcount;
135 void *perf_data;
135 int (*perf_event_enable)(struct ftrace_event_call *); 136 int (*perf_event_enable)(struct ftrace_event_call *);
136 void (*perf_event_disable)(struct ftrace_event_call *); 137 void (*perf_event_disable)(struct ftrace_event_call *);
137}; 138};
@@ -190,7 +191,7 @@ struct perf_event;
190 191
191DECLARE_PER_CPU(struct pt_regs, perf_trace_regs); 192DECLARE_PER_CPU(struct pt_regs, perf_trace_regs);
192 193
193extern int perf_trace_enable(int event_id); 194extern int perf_trace_enable(int event_id, void *data);
194extern void perf_trace_disable(int event_id); 195extern void perf_trace_disable(int event_id);
195extern int ftrace_profile_set_filter(struct perf_event *event, int event_id, 196extern int ftrace_profile_set_filter(struct perf_event *event, int event_id,
196 char *filter_str); 197 char *filter_str);
@@ -201,11 +202,12 @@ perf_trace_buf_prepare(int size, unsigned short type, int *rctxp,
201 202
202static inline void 203static inline void
203perf_trace_buf_submit(void *raw_data, int size, int rctx, u64 addr, 204perf_trace_buf_submit(void *raw_data, int size, int rctx, u64 addr,
204 u64 count, unsigned long irq_flags, struct pt_regs *regs) 205 u64 count, unsigned long irq_flags, struct pt_regs *regs,
206 void *event)
205{ 207{
206 struct trace_entry *entry = raw_data; 208 struct trace_entry *entry = raw_data;
207 209
208 perf_tp_event(entry->type, addr, count, raw_data, size, regs); 210 perf_tp_event(entry->type, addr, count, raw_data, size, regs, event);
209 perf_swevent_put_recursion_context(rctx); 211 perf_swevent_put_recursion_context(rctx);
210 local_irq_restore(irq_flags); 212 local_irq_restore(irq_flags);
211} 213}
diff --git a/include/linux/perf_event.h b/include/linux/perf_event.h
index 3fd5c82e0e18..0b521fc8f5b0 100644
--- a/include/linux/perf_event.h
+++ b/include/linux/perf_event.h
@@ -994,7 +994,7 @@ static inline bool perf_paranoid_kernel(void)
994 994
995extern void perf_event_init(void); 995extern void perf_event_init(void);
996extern void perf_tp_event(int event_id, u64 addr, u64 count, void *record, 996extern void perf_tp_event(int event_id, u64 addr, u64 count, void *record,
997 int entry_size, struct pt_regs *regs); 997 int entry_size, struct pt_regs *regs, void *event);
998extern void perf_bp_event(struct perf_event *event, void *data); 998extern void perf_bp_event(struct perf_event *event, void *data);
999 999
1000#ifndef perf_misc_flags 1000#ifndef perf_misc_flags
diff --git a/include/trace/ftrace.h b/include/trace/ftrace.h
index 882c64832ffe..0a29df092922 100644
--- a/include/trace/ftrace.h
+++ b/include/trace/ftrace.h
@@ -785,7 +785,8 @@ perf_trace_templ_##call(struct ftrace_event_call *event_call, \
785 { assign; } \ 785 { assign; } \
786 \ 786 \
787 perf_trace_buf_submit(entry, __entry_size, rctx, __addr, \ 787 perf_trace_buf_submit(entry, __entry_size, rctx, __addr, \
788 __count, irq_flags, __regs); \ 788 __count, irq_flags, __regs, \
789 event_call->perf_data); \
789} 790}
790 791
791#undef DEFINE_EVENT 792#undef DEFINE_EVENT
diff --git a/kernel/perf_event.c b/kernel/perf_event.c
index a4fa381db3c2..17ac47f4bce6 100644
--- a/kernel/perf_event.c
+++ b/kernel/perf_event.c
@@ -4468,8 +4468,9 @@ static int swevent_hlist_get(struct perf_event *event)
4468#ifdef CONFIG_EVENT_TRACING 4468#ifdef CONFIG_EVENT_TRACING
4469 4469
4470void perf_tp_event(int event_id, u64 addr, u64 count, void *record, 4470void perf_tp_event(int event_id, u64 addr, u64 count, void *record,
4471 int entry_size, struct pt_regs *regs) 4471 int entry_size, struct pt_regs *regs, void *event)
4472{ 4472{
4473 const int type = PERF_TYPE_TRACEPOINT;
4473 struct perf_sample_data data; 4474 struct perf_sample_data data;
4474 struct perf_raw_record raw = { 4475 struct perf_raw_record raw = {
4475 .size = entry_size, 4476 .size = entry_size,
@@ -4479,9 +4480,13 @@ void perf_tp_event(int event_id, u64 addr, u64 count, void *record,
4479 perf_sample_data_init(&data, addr); 4480 perf_sample_data_init(&data, addr);
4480 data.raw = &raw; 4481 data.raw = &raw;
4481 4482
4482 /* Trace events already protected against recursion */ 4483 if (!event) {
4483 do_perf_sw_event(PERF_TYPE_TRACEPOINT, event_id, count, 1, 4484 do_perf_sw_event(type, event_id, count, 1, &data, regs);
4484 &data, regs); 4485 return;
4486 }
4487
4488 if (perf_swevent_match(event, type, event_id, &data, regs))
4489 perf_swevent_add(event, count, 1, &data, regs);
4485} 4490}
4486EXPORT_SYMBOL_GPL(perf_tp_event); 4491EXPORT_SYMBOL_GPL(perf_tp_event);
4487 4492
@@ -4514,7 +4519,7 @@ static const struct pmu *tp_perf_event_init(struct perf_event *event)
4514 !capable(CAP_SYS_ADMIN)) 4519 !capable(CAP_SYS_ADMIN))
4515 return ERR_PTR(-EPERM); 4520 return ERR_PTR(-EPERM);
4516 4521
4517 if (perf_trace_enable(event->attr.config)) 4522 if (perf_trace_enable(event->attr.config, event))
4518 return NULL; 4523 return NULL;
4519 4524
4520 event->destroy = tp_perf_event_destroy; 4525 event->destroy = tp_perf_event_destroy;
diff --git a/kernel/trace/trace_event_perf.c b/kernel/trace/trace_event_perf.c
index 0565bb42566f..89b780a7c522 100644
--- a/kernel/trace/trace_event_perf.c
+++ b/kernel/trace/trace_event_perf.c
@@ -27,13 +27,15 @@ typedef typeof(unsigned long [PERF_MAX_TRACE_SIZE / sizeof(unsigned long)])
27/* Count the events in use (per event id, not per instance) */ 27/* Count the events in use (per event id, not per instance) */
28static int total_ref_count; 28static int total_ref_count;
29 29
30static int perf_trace_event_enable(struct ftrace_event_call *event) 30static int perf_trace_event_enable(struct ftrace_event_call *event, void *data)
31{ 31{
32 char *buf; 32 char *buf;
33 int ret = -ENOMEM; 33 int ret = -ENOMEM;
34 34
35 if (event->perf_refcount++ > 0) 35 if (event->perf_refcount++ > 0) {
36 event->perf_data = NULL;
36 return 0; 37 return 0;
38 }
37 39
38 if (!total_ref_count) { 40 if (!total_ref_count) {
39 buf = (char *)alloc_percpu(perf_trace_t); 41 buf = (char *)alloc_percpu(perf_trace_t);
@@ -51,6 +53,7 @@ static int perf_trace_event_enable(struct ftrace_event_call *event)
51 53
52 ret = event->perf_event_enable(event); 54 ret = event->perf_event_enable(event);
53 if (!ret) { 55 if (!ret) {
56 event->perf_data = data;
54 total_ref_count++; 57 total_ref_count++;
55 return 0; 58 return 0;
56 } 59 }
@@ -68,7 +71,7 @@ fail_buf:
68 return ret; 71 return ret;
69} 72}
70 73
71int perf_trace_enable(int event_id) 74int perf_trace_enable(int event_id, void *data)
72{ 75{
73 struct ftrace_event_call *event; 76 struct ftrace_event_call *event;
74 int ret = -EINVAL; 77 int ret = -EINVAL;
@@ -77,7 +80,7 @@ int perf_trace_enable(int event_id)
77 list_for_each_entry(event, &ftrace_events, list) { 80 list_for_each_entry(event, &ftrace_events, list) {
78 if (event->id == event_id && event->perf_event_enable && 81 if (event->id == event_id && event->perf_event_enable &&
79 try_module_get(event->mod)) { 82 try_module_get(event->mod)) {
80 ret = perf_trace_event_enable(event); 83 ret = perf_trace_event_enable(event, data);
81 break; 84 break;
82 } 85 }
83 } 86 }
diff --git a/kernel/trace/trace_kprobe.c b/kernel/trace/trace_kprobe.c
index a7514326052b..2d7bf4146be8 100644
--- a/kernel/trace/trace_kprobe.c
+++ b/kernel/trace/trace_kprobe.c
@@ -1362,7 +1362,7 @@ static __kprobes void kprobe_perf_func(struct kprobe *kp,
1362 for (i = 0; i < tp->nr_args; i++) 1362 for (i = 0; i < tp->nr_args; i++)
1363 call_fetch(&tp->args[i].fetch, regs, data + tp->args[i].offset); 1363 call_fetch(&tp->args[i].fetch, regs, data + tp->args[i].offset);
1364 1364
1365 perf_trace_buf_submit(entry, size, rctx, entry->ip, 1, irq_flags, regs); 1365 perf_trace_buf_submit(entry, size, rctx, entry->ip, 1, irq_flags, regs, call->perf_data);
1366} 1366}
1367 1367
1368/* Kretprobe profile handler */ 1368/* Kretprobe profile handler */
@@ -1395,7 +1395,7 @@ static __kprobes void kretprobe_perf_func(struct kretprobe_instance *ri,
1395 call_fetch(&tp->args[i].fetch, regs, data + tp->args[i].offset); 1395 call_fetch(&tp->args[i].fetch, regs, data + tp->args[i].offset);
1396 1396
1397 perf_trace_buf_submit(entry, size, rctx, entry->ret_ip, 1, 1397 perf_trace_buf_submit(entry, size, rctx, entry->ret_ip, 1,
1398 irq_flags, regs); 1398 irq_flags, regs, call->perf_data);
1399} 1399}
1400 1400
1401static int probe_perf_enable(struct ftrace_event_call *call) 1401static int probe_perf_enable(struct ftrace_event_call *call)
diff --git a/kernel/trace/trace_syscalls.c b/kernel/trace/trace_syscalls.c
index 4d6d711717f2..9eff1a4b49b9 100644
--- a/kernel/trace/trace_syscalls.c
+++ b/kernel/trace/trace_syscalls.c
@@ -468,7 +468,8 @@ static void perf_syscall_enter(struct pt_regs *regs, long id)
468 rec->nr = syscall_nr; 468 rec->nr = syscall_nr;
469 syscall_get_arguments(current, regs, 0, sys_data->nb_args, 469 syscall_get_arguments(current, regs, 0, sys_data->nb_args,
470 (unsigned long *)&rec->args); 470 (unsigned long *)&rec->args);
471 perf_trace_buf_submit(rec, size, rctx, 0, 1, flags, regs); 471 perf_trace_buf_submit(rec, size, rctx, 0, 1, flags, regs,
472 sys_data->enter_event->perf_data);
472} 473}
473 474
474int perf_sysenter_enable(struct ftrace_event_call *call) 475int perf_sysenter_enable(struct ftrace_event_call *call)
@@ -543,7 +544,8 @@ static void perf_syscall_exit(struct pt_regs *regs, long ret)
543 rec->nr = syscall_nr; 544 rec->nr = syscall_nr;
544 rec->ret = syscall_get_return_value(current, regs); 545 rec->ret = syscall_get_return_value(current, regs);
545 546
546 perf_trace_buf_submit(rec, size, rctx, 0, 1, flags, regs); 547 perf_trace_buf_submit(rec, size, rctx, 0, 1, flags, regs,
548 sys_data->exit_event->perf_data);
547} 549}
548 550
549int perf_sysexit_enable(struct ftrace_event_call *call) 551int perf_sysexit_enable(struct ftrace_event_call *call)