aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/linux/tracepoint.h3
-rw-r--r--include/trace/irq_event_types.h24
-rw-r--r--include/trace/sched_event_types.h124
-rw-r--r--include/trace/trace_event_types.h4
-rw-r--r--include/trace/trace_events.h4
-rw-r--r--kernel/trace/events.c20
-rw-r--r--kernel/trace/trace.c14
-rw-r--r--kernel/trace/trace.h32
-rw-r--r--kernel/trace/trace_events.c294
-rw-r--r--kernel/trace/trace_events.h55
-rw-r--r--kernel/trace/trace_events_stage_1.h34
-rw-r--r--kernel/trace/trace_events_stage_2.h72
-rw-r--r--kernel/trace/trace_events_stage_3.h219
13 files changed, 776 insertions, 123 deletions
diff --git a/include/linux/tracepoint.h b/include/linux/tracepoint.h
index 62d13391a240..152b2f03fb86 100644
--- a/include/linux/tracepoint.h
+++ b/include/linux/tracepoint.h
@@ -157,4 +157,7 @@ static inline void tracepoint_synchronize_unregister(void)
157#define TRACE_FORMAT(name, proto, args, fmt) \ 157#define TRACE_FORMAT(name, proto, args, fmt) \
158 DECLARE_TRACE(name, PARAMS(proto), PARAMS(args)) 158 DECLARE_TRACE(name, PARAMS(proto), PARAMS(args))
159 159
160#define TRACE_EVENT_FORMAT(name, proto, args, fmt, struct, tpfmt) \
161 TRACE_FORMAT(name, PARAMS(proto), PARAMS(args), PARAMS(fmt))
162
160#endif 163#endif
diff --git a/include/trace/irq_event_types.h b/include/trace/irq_event_types.h
index 5d0919fdd2d4..65850bc5ea06 100644
--- a/include/trace/irq_event_types.h
+++ b/include/trace/irq_event_types.h
@@ -5,13 +5,29 @@
5# error Unless you know what you are doing. 5# error Unless you know what you are doing.
6#endif 6#endif
7 7
8TRACE_FORMAT(irq_handler_entry, 8#undef TRACE_SYSTEM
9#define TRACE_SYSTEM irq
10
11TRACE_EVENT_FORMAT(irq_handler_entry,
9 TPPROTO(int irq, struct irqaction *action), 12 TPPROTO(int irq, struct irqaction *action),
10 TPARGS(irq, action), 13 TPARGS(irq, action),
11 TPFMT("irq=%d handler=%s", irq, action->name)); 14 TPFMT("irq=%d handler=%s", irq, action->name),
15 TRACE_STRUCT(
16 TRACE_FIELD(int, irq, irq)
17 ),
18 TPRAWFMT("irq %d")
19 );
12 20
13TRACE_FORMAT(irq_handler_exit, 21TRACE_EVENT_FORMAT(irq_handler_exit,
14 TPPROTO(int irq, struct irqaction *action, int ret), 22 TPPROTO(int irq, struct irqaction *action, int ret),
15 TPARGS(irq, action, ret), 23 TPARGS(irq, action, ret),
16 TPFMT("irq=%d handler=%s return=%s", 24 TPFMT("irq=%d handler=%s return=%s",
17 irq, action->name, ret ? "handled" : "unhandled")); 25 irq, action->name, ret ? "handled" : "unhandled"),
26 TRACE_STRUCT(
27 TRACE_FIELD(int, irq, irq)
28 TRACE_FIELD(int, ret, ret)
29 ),
30 TPRAWFMT("irq %d ret %d")
31 );
32
33#undef TRACE_SYSTEM
diff --git a/include/trace/sched_event_types.h b/include/trace/sched_event_types.h
index a3d3d66a51c8..ba059c10b58a 100644
--- a/include/trace/sched_event_types.h
+++ b/include/trace/sched_event_types.h
@@ -1,72 +1,146 @@
1 1
2/* use <trace/sched.h> instead */ 2/* use <trace/sched.h> instead */
3#ifndef TRACE_FORMAT 3#ifndef TRACE_EVENT_FORMAT
4# error Do not include this file directly. 4# error Do not include this file directly.
5# error Unless you know what you are doing. 5# error Unless you know what you are doing.
6#endif 6#endif
7 7
8TRACE_FORMAT(sched_kthread_stop, 8#undef TRACE_SYSTEM
9#define TRACE_SYSTEM sched
10
11TRACE_EVENT_FORMAT(sched_kthread_stop,
9 TPPROTO(struct task_struct *t), 12 TPPROTO(struct task_struct *t),
10 TPARGS(t), 13 TPARGS(t),
11 TPFMT("task %s:%d", t->comm, t->pid)); 14 TPFMT("task %s:%d", t->comm, t->pid),
15 TRACE_STRUCT(
16 TRACE_FIELD(pid_t, pid, t->pid)
17 ),
18 TPRAWFMT("task %d")
19 );
12 20
13TRACE_FORMAT(sched_kthread_stop_ret, 21TRACE_EVENT_FORMAT(sched_kthread_stop_ret,
14 TPPROTO(int ret), 22 TPPROTO(int ret),
15 TPARGS(ret), 23 TPARGS(ret),
16 TPFMT("ret=%d", ret)); 24 TPFMT("ret=%d", ret),
25 TRACE_STRUCT(
26 TRACE_FIELD(int, ret, ret)
27 ),
28 TPRAWFMT("ret=%d")
29 );
17 30
18TRACE_FORMAT(sched_wait_task, 31TRACE_EVENT_FORMAT(sched_wait_task,
19 TPPROTO(struct rq *rq, struct task_struct *p), 32 TPPROTO(struct rq *rq, struct task_struct *p),
20 TPARGS(rq, p), 33 TPARGS(rq, p),
21 TPFMT("task %s:%d", p->comm, p->pid)); 34 TPFMT("task %s:%d", p->comm, p->pid),
35 TRACE_STRUCT(
36 TRACE_FIELD(pid_t, pid, p->pid)
37 ),
38 TPRAWFMT("task %d")
39 );
22 40
23TRACE_FORMAT(sched_wakeup, 41TRACE_EVENT_FORMAT(sched_wakeup,
24 TPPROTO(struct rq *rq, struct task_struct *p, int success), 42 TPPROTO(struct rq *rq, struct task_struct *p, int success),
25 TPARGS(rq, p, success), 43 TPARGS(rq, p, success),
26 TPFMT("task %s:%d %s", 44 TPFMT("task %s:%d %s",
27 p->comm, p->pid, success?"succeeded":"failed")); 45 p->comm, p->pid, success ? "succeeded" : "failed"),
46 TRACE_STRUCT(
47 TRACE_FIELD(pid_t, pid, p->pid)
48 TRACE_FIELD(int, success, success)
49 ),
50 TPRAWFMT("task %d success=%d")
51 );
28 52
29TRACE_FORMAT(sched_wakeup_new, 53TRACE_EVENT_FORMAT(sched_wakeup_new,
30 TPPROTO(struct rq *rq, struct task_struct *p, int success), 54 TPPROTO(struct rq *rq, struct task_struct *p, int success),
31 TPARGS(rq, p, success), 55 TPARGS(rq, p, success),
32 TPFMT("task %s:%d", 56 TPFMT("task %s:%d",
33 p->comm, p->pid, success?"succeeded":"failed")); 57 p->comm, p->pid, success ? "succeeded" : "failed"),
58 TRACE_STRUCT(
59 TRACE_FIELD(pid_t, pid, p->pid)
60 TRACE_FIELD(int, success, success)
61 ),
62 TPRAWFMT("task %d success=%d")
63 );
34 64
35TRACE_FORMAT(sched_switch, 65TRACE_EVENT_FORMAT(sched_switch,
36 TPPROTO(struct rq *rq, struct task_struct *prev, 66 TPPROTO(struct rq *rq, struct task_struct *prev,
37 struct task_struct *next), 67 struct task_struct *next),
38 TPARGS(rq, prev, next), 68 TPARGS(rq, prev, next),
39 TPFMT("task %s:%d ==> %s:%d", 69 TPFMT("task %s:%d ==> %s:%d",
40 prev->comm, prev->pid, next->comm, next->pid)); 70 prev->comm, prev->pid, next->comm, next->pid),
71 TRACE_STRUCT(
72 TRACE_FIELD(pid_t, prev_pid, prev->pid)
73 TRACE_FIELD(int, prev_prio, prev->prio)
74 TRACE_FIELD(pid_t, next_pid, next->pid)
75 TRACE_FIELD(int, next_prio, next->prio)
76 ),
77 TPRAWFMT("prev %d:%d ==> next %d:%d")
78 );
41 79
42TRACE_FORMAT(sched_migrate_task, 80TRACE_EVENT_FORMAT(sched_migrate_task,
43 TPPROTO(struct task_struct *p, int orig_cpu, int dest_cpu), 81 TPPROTO(struct task_struct *p, int orig_cpu, int dest_cpu),
44 TPARGS(p, orig_cpu, dest_cpu), 82 TPARGS(p, orig_cpu, dest_cpu),
45 TPFMT("task %s:%d from: %d to: %d", 83 TPFMT("task %s:%d from: %d to: %d",
46 p->comm, p->pid, orig_cpu, dest_cpu)); 84 p->comm, p->pid, orig_cpu, dest_cpu),
85 TRACE_STRUCT(
86 TRACE_FIELD(pid_t, pid, p->pid)
87 TRACE_FIELD(int, orig_cpu, orig_cpu)
88 TRACE_FIELD(int, dest_cpu, dest_cpu)
89 ),
90 TPRAWFMT("task %d from: %d to: %d")
91 );
47 92
48TRACE_FORMAT(sched_process_free, 93TRACE_EVENT_FORMAT(sched_process_free,
49 TPPROTO(struct task_struct *p), 94 TPPROTO(struct task_struct *p),
50 TPARGS(p), 95 TPARGS(p),
51 TPFMT("task %s:%d", p->comm, p->pid)); 96 TPFMT("task %s:%d", p->comm, p->pid),
97 TRACE_STRUCT(
98 TRACE_FIELD(pid_t, pid, p->pid)
99 ),
100 TPRAWFMT("task %d")
101 );
52 102
53TRACE_FORMAT(sched_process_exit, 103TRACE_EVENT_FORMAT(sched_process_exit,
54 TPPROTO(struct task_struct *p), 104 TPPROTO(struct task_struct *p),
55 TPARGS(p), 105 TPARGS(p),
56 TPFMT("task %s:%d", p->comm, p->pid)); 106 TPFMT("task %s:%d", p->comm, p->pid),
107 TRACE_STRUCT(
108 TRACE_FIELD(pid_t, pid, p->pid)
109 ),
110 TPRAWFMT("task %d")
111 );
57 112
58TRACE_FORMAT(sched_process_wait, 113TRACE_EVENT_FORMAT(sched_process_wait,
59 TPPROTO(struct pid *pid), 114 TPPROTO(struct pid *pid),
60 TPARGS(pid), 115 TPARGS(pid),
61 TPFMT("pid %d", pid)); 116 TPFMT("pid %d", pid_nr(pid)),
117 TRACE_STRUCT(
118 TRACE_FIELD(pid_t, pid, pid_nr(pid))
119 ),
120 TPRAWFMT("task %d")
121 );
62 122
63TRACE_FORMAT(sched_process_fork, 123TRACE_EVENT_FORMAT(sched_process_fork,
64 TPPROTO(struct task_struct *parent, struct task_struct *child), 124 TPPROTO(struct task_struct *parent, struct task_struct *child),
65 TPARGS(parent, child), 125 TPARGS(parent, child),
66 TPFMT("parent %s:%d child %s:%d", 126 TPFMT("parent %s:%d child %s:%d",
67 parent->comm, parent->pid, child->comm, child->pid)); 127 parent->comm, parent->pid, child->comm, child->pid),
128 TRACE_STRUCT(
129 TRACE_FIELD(pid_t, parent, parent->pid)
130 TRACE_FIELD(pid_t, child, child->pid)
131 ),
132 TPRAWFMT("parent %d child %d")
133 );
68 134
69TRACE_FORMAT(sched_signal_send, 135TRACE_EVENT_FORMAT(sched_signal_send,
70 TPPROTO(int sig, struct task_struct *p), 136 TPPROTO(int sig, struct task_struct *p),
71 TPARGS(sig, p), 137 TPARGS(sig, p),
72 TPFMT("sig: %d task %s:%d", sig, p->comm, p->pid)); 138 TPFMT("sig: %d task %s:%d", sig, p->comm, p->pid),
139 TRACE_STRUCT(
140 TRACE_FIELD(int, sig, sig)
141 TRACE_FIELD(pid_t, pid, p->pid)
142 ),
143 TPRAWFMT("sig: %d task %d")
144 );
145
146#undef TRACE_SYSTEM
diff --git a/include/trace/trace_event_types.h b/include/trace/trace_event_types.h
new file mode 100644
index 000000000000..33c8ed5ccb6c
--- /dev/null
+++ b/include/trace/trace_event_types.h
@@ -0,0 +1,4 @@
1/* trace/<type>_event_types.h here */
2
3#include <trace/sched_event_types.h>
4#include <trace/irq_event_types.h>
diff --git a/include/trace/trace_events.h b/include/trace/trace_events.h
new file mode 100644
index 000000000000..ea2ef2051762
--- /dev/null
+++ b/include/trace/trace_events.h
@@ -0,0 +1,4 @@
1/* trace/<type>.h here */
2
3#include <trace/sched.h>
4#include <trace/irq.h>
diff --git a/kernel/trace/events.c b/kernel/trace/events.c
index 3c75623893cc..f2509cbaacea 100644
--- a/kernel/trace/events.c
+++ b/kernel/trace/events.c
@@ -1,15 +1,17 @@
1/* 1/*
2 * This is the place to register all trace points as events. 2 * This is the place to register all trace points as events.
3 * Include the trace/<type>.h at the top.
4 * Include the trace/<type>_event_types.h at the bottom.
5 */ 3 */
6 4
7/* trace/<type>.h here */ 5/* someday this needs to go in a generic header */
8#include <trace/sched.h> 6#define __STR(x) #x
9#include <trace/irq.h> 7#define STR(x) __STR(x)
10 8
11#include "trace_events.h" 9#include <trace/trace_events.h>
12 10
13/* trace/<type>_event_types.h here */ 11#include "trace_output.h"
14#include <trace/sched_event_types.h> 12
15#include <trace/irq_event_types.h> 13#include "trace_events_stage_1.h"
14#include "trace_events_stage_2.h"
15#include "trace_events_stage_3.h"
16
17#include <trace/trace_event_types.h>
diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c
index 9c5987aca74b..c5e39cd7310d 100644
--- a/kernel/trace/trace.c
+++ b/kernel/trace/trace.c
@@ -846,6 +846,20 @@ void trace_buffer_unlock_commit(struct trace_array *tr,
846 trace_wake_up(); 846 trace_wake_up();
847} 847}
848 848
849struct ring_buffer_event *
850trace_current_buffer_lock_reserve(unsigned char type, unsigned long len,
851 unsigned long flags, int pc)
852{
853 return trace_buffer_lock_reserve(&global_trace,
854 type, len, flags, pc);
855}
856
857void trace_current_buffer_unlock_commit(struct ring_buffer_event *event,
858 unsigned long flags, int pc)
859{
860 return trace_buffer_unlock_commit(&global_trace, event, flags, pc);
861}
862
849void 863void
850trace_function(struct trace_array *tr, 864trace_function(struct trace_array *tr,
851 unsigned long ip, unsigned long parent_ip, unsigned long flags, 865 unsigned long ip, unsigned long parent_ip, unsigned long flags,
diff --git a/kernel/trace/trace.h b/kernel/trace/trace.h
index 632191770aac..f6fa0b9f83a8 100644
--- a/kernel/trace/trace.h
+++ b/kernel/trace/trace.h
@@ -442,6 +442,12 @@ void trace_buffer_unlock_commit(struct trace_array *tr,
442 struct ring_buffer_event *event, 442 struct ring_buffer_event *event,
443 unsigned long flags, int pc); 443 unsigned long flags, int pc);
444 444
445struct ring_buffer_event *
446trace_current_buffer_lock_reserve(unsigned char type, unsigned long len,
447 unsigned long flags, int pc);
448void trace_current_buffer_unlock_commit(struct ring_buffer_event *event,
449 unsigned long flags, int pc);
450
445struct trace_entry *tracing_get_trace_entry(struct trace_array *tr, 451struct trace_entry *tracing_get_trace_entry(struct trace_array *tr,
446 struct trace_array_cpu *data); 452 struct trace_array_cpu *data);
447 453
@@ -720,4 +726,30 @@ static inline void trace_branch_disable(void)
720} 726}
721#endif /* CONFIG_BRANCH_TRACER */ 727#endif /* CONFIG_BRANCH_TRACER */
722 728
729/* trace event type bit fields, not numeric */
730enum {
731 TRACE_EVENT_TYPE_PRINTF = 1,
732 TRACE_EVENT_TYPE_RAW = 2,
733};
734
735struct ftrace_event_call {
736 char *name;
737 char *system;
738 struct dentry *dir;
739 int enabled;
740 int (*regfunc)(void);
741 void (*unregfunc)(void);
742 int id;
743 struct dentry *raw_dir;
744 int raw_enabled;
745 int type;
746 int (*raw_init)(void);
747 int (*raw_reg)(void);
748 void (*raw_unreg)(void);
749};
750
751void event_trace_printk(unsigned long ip, const char *fmt, ...);
752extern struct ftrace_event_call __start_ftrace_events[];
753extern struct ftrace_event_call __stop_ftrace_events[];
754
723#endif /* _LINUX_KERNEL_TRACE_H */ 755#endif /* _LINUX_KERNEL_TRACE_H */
diff --git a/kernel/trace/trace_events.c b/kernel/trace/trace_events.c
index 3bcb9df93342..1d07f800a9ce 100644
--- a/kernel/trace/trace_events.c
+++ b/kernel/trace/trace_events.c
@@ -10,7 +10,9 @@
10#include <linux/module.h> 10#include <linux/module.h>
11#include <linux/ctype.h> 11#include <linux/ctype.h>
12 12
13#include "trace_events.h" 13#include "trace.h"
14
15#define TRACE_SYSTEM "TRACE_SYSTEM"
14 16
15#define events_for_each(event) \ 17#define events_for_each(event) \
16 for (event = __start_ftrace_events; \ 18 for (event = __start_ftrace_events; \
@@ -42,35 +44,87 @@ static void ftrace_clear_events(void)
42 } 44 }
43} 45}
44 46
47static void ftrace_event_enable_disable(struct ftrace_event_call *call,
48 int enable)
49{
50
51 switch (enable) {
52 case 0:
53 if (call->enabled) {
54 call->enabled = 0;
55 call->unregfunc();
56 }
57 if (call->raw_enabled) {
58 call->raw_enabled = 0;
59 call->raw_unreg();
60 }
61 break;
62 case 1:
63 if (!call->enabled &&
64 (call->type & TRACE_EVENT_TYPE_PRINTF)) {
65 call->enabled = 1;
66 call->regfunc();
67 }
68 if (!call->raw_enabled &&
69 (call->type & TRACE_EVENT_TYPE_RAW)) {
70 call->raw_enabled = 1;
71 call->raw_reg();
72 }
73 break;
74 }
75}
76
45static int ftrace_set_clr_event(char *buf, int set) 77static int ftrace_set_clr_event(char *buf, int set)
46{ 78{
47 struct ftrace_event_call *call = __start_ftrace_events; 79 struct ftrace_event_call *call = __start_ftrace_events;
48 80 char *event = NULL, *sub = NULL, *match;
81 int ret = -EINVAL;
82
83 /*
84 * The buf format can be <subsystem>:<event-name>
85 * *:<event-name> means any event by that name.
86 * :<event-name> is the same.
87 *
88 * <subsystem>:* means all events in that subsystem
89 * <subsystem>: means the same.
90 *
91 * <name> (no ':') means all events in a subsystem with
92 * the name <name> or any event that matches <name>
93 */
94
95 match = strsep(&buf, ":");
96 if (buf) {
97 sub = match;
98 event = buf;
99 match = NULL;
100
101 if (!strlen(sub) || strcmp(sub, "*") == 0)
102 sub = NULL;
103 if (!strlen(event) || strcmp(event, "*") == 0)
104 event = NULL;
105 }
49 106
50 events_for_each(call) { 107 events_for_each(call) {
51 108
52 if (!call->name) 109 if (!call->name)
53 continue; 110 continue;
54 111
55 if (strcmp(buf, call->name) != 0) 112 if (match &&
113 strcmp(match, call->name) != 0 &&
114 strcmp(match, call->system) != 0)
56 continue; 115 continue;
57 116
58 if (set) { 117 if (sub && strcmp(sub, call->system) != 0)
59 /* Already set? */ 118 continue;
60 if (call->enabled) 119
61 return 0; 120 if (event && strcmp(event, call->name) != 0)
62 call->enabled = 1; 121 continue;
63 call->regfunc(); 122
64 } else { 123 ftrace_event_enable_disable(call, set);
65 /* Already cleared? */ 124
66 if (!call->enabled) 125 ret = 0;
67 return 0;
68 call->enabled = 0;
69 call->unregfunc();
70 }
71 return 0;
72 } 126 }
73 return -EINVAL; 127 return ret;
74} 128}
75 129
76/* 128 should be much more than enough */ 130/* 128 should be much more than enough */
@@ -200,6 +254,8 @@ static int t_show(struct seq_file *m, void *v)
200{ 254{
201 struct ftrace_event_call *call = v; 255 struct ftrace_event_call *call = v;
202 256
257 if (strcmp(call->system, TRACE_SYSTEM) != 0)
258 seq_printf(m, "%s:", call->system);
203 seq_printf(m, "%s\n", call->name); 259 seq_printf(m, "%s\n", call->name);
204 260
205 return 0; 261 return 0;
@@ -236,7 +292,7 @@ event_enable_read(struct file *filp, char __user *ubuf, size_t cnt,
236 struct ftrace_event_call *call = filp->private_data; 292 struct ftrace_event_call *call = filp->private_data;
237 char *buf; 293 char *buf;
238 294
239 if (call->enabled) 295 if (call->enabled || call->raw_enabled)
240 buf = "1\n"; 296 buf = "1\n";
241 else 297 else
242 buf = "0\n"; 298 buf = "0\n";
@@ -267,18 +323,8 @@ event_enable_write(struct file *filp, const char __user *ubuf, size_t cnt,
267 323
268 switch (val) { 324 switch (val) {
269 case 0: 325 case 0:
270 if (!call->enabled)
271 break;
272
273 call->enabled = 0;
274 call->unregfunc();
275 break;
276 case 1: 326 case 1:
277 if (call->enabled) 327 ftrace_event_enable_disable(call, val);
278 break;
279
280 call->enabled = 1;
281 call->regfunc();
282 break; 328 break;
283 329
284 default: 330 default:
@@ -290,6 +336,107 @@ event_enable_write(struct file *filp, const char __user *ubuf, size_t cnt,
290 return cnt; 336 return cnt;
291} 337}
292 338
339static ssize_t
340event_type_read(struct file *filp, char __user *ubuf, size_t cnt,
341 loff_t *ppos)
342{
343 struct ftrace_event_call *call = filp->private_data;
344 char buf[16];
345 int r = 0;
346
347 if (call->type & TRACE_EVENT_TYPE_PRINTF)
348 r += sprintf(buf, "printf\n");
349
350 if (call->type & TRACE_EVENT_TYPE_RAW)
351 r += sprintf(buf+r, "raw\n");
352
353 return simple_read_from_buffer(ubuf, cnt, ppos, buf, r);
354}
355
356static ssize_t
357event_type_write(struct file *filp, const char __user *ubuf, size_t cnt,
358 loff_t *ppos)
359{
360 struct ftrace_event_call *call = filp->private_data;
361 char buf[64];
362
363 /*
364 * If there's only one type, we can't change it.
365 * And currently we always have printf type, and we
366 * may or may not have raw type.
367 *
368 * This is a redundant check, the file should be read
369 * only if this is the case anyway.
370 */
371
372 if (!call->raw_init)
373 return -EPERM;
374
375 if (cnt >= sizeof(buf))
376 return -EINVAL;
377
378 if (copy_from_user(&buf, ubuf, cnt))
379 return -EFAULT;
380
381 buf[cnt] = 0;
382
383 if (!strncmp(buf, "printf", 6) &&
384 (!buf[6] || isspace(buf[6]))) {
385
386 call->type = TRACE_EVENT_TYPE_PRINTF;
387
388 /*
389 * If raw enabled, the disable it and enable
390 * printf type.
391 */
392 if (call->raw_enabled) {
393 call->raw_enabled = 0;
394 call->raw_unreg();
395
396 call->enabled = 1;
397 call->regfunc();
398 }
399
400 } else if (!strncmp(buf, "raw", 3) &&
401 (!buf[3] || isspace(buf[3]))) {
402
403 call->type = TRACE_EVENT_TYPE_RAW;
404
405 /*
406 * If printf enabled, the disable it and enable
407 * raw type.
408 */
409 if (call->enabled) {
410 call->enabled = 0;
411 call->unregfunc();
412
413 call->raw_enabled = 1;
414 call->raw_reg();
415 }
416 } else
417 return -EINVAL;
418
419 *ppos += cnt;
420
421 return cnt;
422}
423
424static ssize_t
425event_available_types_read(struct file *filp, char __user *ubuf, size_t cnt,
426 loff_t *ppos)
427{
428 struct ftrace_event_call *call = filp->private_data;
429 char buf[16];
430 int r = 0;
431
432 r += sprintf(buf, "printf\n");
433
434 if (call->raw_init)
435 r += sprintf(buf+r, "raw\n");
436
437 return simple_read_from_buffer(ubuf, cnt, ppos, buf, r);
438}
439
293static const struct seq_operations show_event_seq_ops = { 440static const struct seq_operations show_event_seq_ops = {
294 .start = t_start, 441 .start = t_start,
295 .next = t_next, 442 .next = t_next,
@@ -325,6 +472,17 @@ static const struct file_operations ftrace_enable_fops = {
325 .write = event_enable_write, 472 .write = event_enable_write,
326}; 473};
327 474
475static const struct file_operations ftrace_type_fops = {
476 .open = tracing_open_generic,
477 .read = event_type_read,
478 .write = event_type_write,
479};
480
481static const struct file_operations ftrace_available_types_fops = {
482 .open = tracing_open_generic,
483 .read = event_available_types_read,
484};
485
328static struct dentry *event_trace_events_dir(void) 486static struct dentry *event_trace_events_dir(void)
329{ 487{
330 static struct dentry *d_tracer; 488 static struct dentry *d_tracer;
@@ -345,10 +503,71 @@ static struct dentry *event_trace_events_dir(void)
345 return d_events; 503 return d_events;
346} 504}
347 505
506struct event_subsystem {
507 struct list_head list;
508 const char *name;
509 struct dentry *entry;
510};
511
512static LIST_HEAD(event_subsystems);
513
514static struct dentry *
515event_subsystem_dir(const char *name, struct dentry *d_events)
516{
517 struct event_subsystem *system;
518
519 /* First see if we did not already create this dir */
520 list_for_each_entry(system, &event_subsystems, list) {
521 if (strcmp(system->name, name) == 0)
522 return system->entry;
523 }
524
525 /* need to create new entry */
526 system = kmalloc(sizeof(*system), GFP_KERNEL);
527 if (!system) {
528 pr_warning("No memory to create event subsystem %s\n",
529 name);
530 return d_events;
531 }
532
533 system->entry = debugfs_create_dir(name, d_events);
534 if (!system->entry) {
535 pr_warning("Could not create event subsystem %s\n",
536 name);
537 kfree(system);
538 return d_events;
539 }
540
541 system->name = name;
542 list_add(&system->list, &event_subsystems);
543
544 return system->entry;
545}
546
348static int 547static int
349event_create_dir(struct ftrace_event_call *call, struct dentry *d_events) 548event_create_dir(struct ftrace_event_call *call, struct dentry *d_events)
350{ 549{
351 struct dentry *entry; 550 struct dentry *entry;
551 int ret;
552
553 /*
554 * If the trace point header did not define TRACE_SYSTEM
555 * then the system would be called "TRACE_SYSTEM".
556 */
557 if (strcmp(call->system, "TRACE_SYSTEM") != 0)
558 d_events = event_subsystem_dir(call->system, d_events);
559
560 if (call->raw_init) {
561 ret = call->raw_init();
562 if (ret < 0) {
563 pr_warning("Could not initialize trace point"
564 " events/%s\n", call->name);
565 return ret;
566 }
567 }
568
569 /* default the output to printf */
570 call->type = TRACE_EVENT_TYPE_PRINTF;
352 571
353 call->dir = debugfs_create_dir(call->name, d_events); 572 call->dir = debugfs_create_dir(call->name, d_events);
354 if (!call->dir) { 573 if (!call->dir) {
@@ -363,6 +582,21 @@ event_create_dir(struct ftrace_event_call *call, struct dentry *d_events)
363 pr_warning("Could not create debugfs " 582 pr_warning("Could not create debugfs "
364 "'%s/enable' entry\n", call->name); 583 "'%s/enable' entry\n", call->name);
365 584
585 /* Only let type be writable, if we can change it */
586 entry = debugfs_create_file("type",
587 call->raw_init ? 0644 : 0444,
588 call->dir, call,
589 &ftrace_type_fops);
590 if (!entry)
591 pr_warning("Could not create debugfs "
592 "'%s/type' entry\n", call->name);
593
594 entry = debugfs_create_file("available_types", 0444, call->dir, call,
595 &ftrace_available_types_fops);
596 if (!entry)
597 pr_warning("Could not create debugfs "
598 "'%s/type' available_types\n", call->name);
599
366 return 0; 600 return 0;
367} 601}
368 602
diff --git a/kernel/trace/trace_events.h b/kernel/trace/trace_events.h
deleted file mode 100644
index deb95e5006c8..000000000000
--- a/kernel/trace/trace_events.h
+++ /dev/null
@@ -1,55 +0,0 @@
1#ifndef _LINUX_KERNEL_TRACE_EVENTS_H
2#define _LINUX_KERNEL_TRACE_EVENTS_H
3
4#include <linux/debugfs.h>
5#include <linux/ftrace.h>
6#include "trace.h"
7
8struct ftrace_event_call {
9 char *name;
10 struct dentry *dir;
11 int enabled;
12 int (*regfunc)(void);
13 void (*unregfunc)(void);
14};
15
16
17#undef TPFMT
18#define TPFMT(fmt, args...) fmt "\n", ##args
19
20#undef TRACE_FORMAT
21#define TRACE_FORMAT(call, proto, args, fmt) \
22static void ftrace_event_##call(proto) \
23{ \
24 event_trace_printk(_RET_IP_, "(" #call ") " fmt); \
25} \
26 \
27static int ftrace_reg_event_##call(void) \
28{ \
29 int ret; \
30 \
31 ret = register_trace_##call(ftrace_event_##call); \
32 if (!ret) \
33 pr_info("event trace: Could not activate trace point " \
34 "probe to " #call); \
35 return ret; \
36} \
37 \
38static void ftrace_unreg_event_##call(void) \
39{ \
40 unregister_trace_##call(ftrace_event_##call); \
41} \
42 \
43static struct ftrace_event_call __used \
44__attribute__((__aligned__(4))) \
45__attribute__((section("_ftrace_events"))) event_##call = { \
46 .name = #call, \
47 .regfunc = ftrace_reg_event_##call, \
48 .unregfunc = ftrace_unreg_event_##call, \
49}
50
51void event_trace_printk(unsigned long ip, const char *fmt, ...);
52extern struct ftrace_event_call __start_ftrace_events[];
53extern struct ftrace_event_call __stop_ftrace_events[];
54
55#endif /* _LINUX_KERNEL_TRACE_EVENTS_H */
diff --git a/kernel/trace/trace_events_stage_1.h b/kernel/trace/trace_events_stage_1.h
new file mode 100644
index 000000000000..fd3bf9382d37
--- /dev/null
+++ b/kernel/trace/trace_events_stage_1.h
@@ -0,0 +1,34 @@
1/*
2 * Stage 1 of the trace events.
3 *
4 * Override the macros in <trace/trace_event_types.h> to include the following:
5 *
6 * struct ftrace_raw_<call> {
7 * struct trace_entry ent;
8 * <type> <item>;
9 * [...]
10 * };
11 *
12 * The <type> <item> is created by the TRACE_FIELD(type, item, assign)
13 * macro. We simply do "type item;", and that will create the fields
14 * in the structure.
15 */
16
17#undef TRACE_FORMAT
18#define TRACE_FORMAT(call, proto, args, fmt)
19
20#undef TRACE_EVENT_FORMAT
21#define TRACE_EVENT_FORMAT(name, proto, args, fmt, tstruct, tpfmt) \
22 struct ftrace_raw_##name { \
23 struct trace_entry ent; \
24 tstruct \
25 }; \
26 static struct ftrace_event_call event_##name
27
28#undef TRACE_STRUCT
29#define TRACE_STRUCT(args...) args
30
31#define TRACE_FIELD(type, item, assign) \
32 type item;
33
34#include <trace/trace_event_types.h>
diff --git a/kernel/trace/trace_events_stage_2.h b/kernel/trace/trace_events_stage_2.h
new file mode 100644
index 000000000000..3eaaef5f19e1
--- /dev/null
+++ b/kernel/trace/trace_events_stage_2.h
@@ -0,0 +1,72 @@
1/*
2 * Stage 2 of the trace events.
3 *
4 * Override the macros in <trace/trace_event_types.h> to include the following:
5 *
6 * enum print_line_t
7 * ftrace_raw_output_<call>(struct trace_iterator *iter, int flags)
8 * {
9 * struct trace_seq *s = &iter->seq;
10 * struct ftrace_raw_<call> *field; <-- defined in stage 1
11 * struct trace_entry *entry;
12 * int ret;
13 *
14 * entry = iter->ent;
15 *
16 * if (entry->type != event_<call>.id) {
17 * WARN_ON_ONCE(1);
18 * return TRACE_TYPE_UNHANDLED;
19 * }
20 *
21 * field = (typeof(field))entry;
22 *
23 * ret = trace_seq_printf(s, <TPRAWFMT> "%s", <ARGS> "\n");
24 * if (!ret)
25 * return TRACE_TYPE_PARTIAL_LINE;
26 *
27 * return TRACE_TYPE_HANDLED;
28 * }
29 *
30 * This is the method used to print the raw event to the trace
31 * output format. Note, this is not needed if the data is read
32 * in binary.
33 */
34
35#undef TRACE_STRUCT
36#define TRACE_STRUCT(args...) args
37
38#undef TRACE_FIELD
39#define TRACE_FIELD(type, item, assign) \
40 field->item,
41
42
43#undef TPRAWFMT
44#define TPRAWFMT(args...) args
45
46#undef TRACE_EVENT_FORMAT
47#define TRACE_EVENT_FORMAT(call, proto, args, fmt, tstruct, tpfmt) \
48enum print_line_t \
49ftrace_raw_output_##call(struct trace_iterator *iter, int flags) \
50{ \
51 struct trace_seq *s = &iter->seq; \
52 struct ftrace_raw_##call *field; \
53 struct trace_entry *entry; \
54 int ret; \
55 \
56 entry = iter->ent; \
57 \
58 if (entry->type != event_##call.id) { \
59 WARN_ON_ONCE(1); \
60 return TRACE_TYPE_UNHANDLED; \
61 } \
62 \
63 field = (typeof(field))entry; \
64 \
65 ret = trace_seq_printf(s, tpfmt "%s", tstruct "\n"); \
66 if (!ret) \
67 return TRACE_TYPE_PARTIAL_LINE; \
68 \
69 return TRACE_TYPE_HANDLED; \
70}
71
72#include <trace/trace_event_types.h>
diff --git a/kernel/trace/trace_events_stage_3.h b/kernel/trace/trace_events_stage_3.h
new file mode 100644
index 000000000000..7a161c49deb4
--- /dev/null
+++ b/kernel/trace/trace_events_stage_3.h
@@ -0,0 +1,219 @@
1/*
2 * Stage 3 of the trace events.
3 *
4 * Override the macros in <trace/trace_event_types.h> to include the following:
5 *
6 * static void ftrace_event_<call>(proto)
7 * {
8 * event_trace_printk(_RET_IP_, "(<call>) " <fmt>);
9 * }
10 *
11 * static int ftrace_reg_event_<call>(void)
12 * {
13 * int ret;
14 *
15 * ret = register_trace_<call>(ftrace_event_<call>);
16 * if (!ret)
17 * pr_info("event trace: Could not activate trace point "
18 * "probe to <call>");
19 * return ret;
20 * }
21 *
22 * static void ftrace_unreg_event_<call>(void)
23 * {
24 * unregister_trace_<call>(ftrace_event_<call>);
25 * }
26 *
27 * For those macros defined with TRACE_FORMAT:
28 *
29 * static struct ftrace_event_call __used
30 * __attribute__((__aligned__(4)))
31 * __attribute__((section("_ftrace_events"))) event_<call> = {
32 * .name = "<call>",
33 * .regfunc = ftrace_reg_event_<call>,
34 * .unregfunc = ftrace_unreg_event_<call>,
35 * }
36 *
37 *
38 * For those macros defined with TRACE_EVENT_FORMAT:
39 *
40 * static struct ftrace_event_call event_<call>;
41 *
42 * static void ftrace_raw_event_<call>(proto)
43 * {
44 * struct ring_buffer_event *event;
45 * struct ftrace_raw_<call> *entry; <-- defined in stage 1
46 * unsigned long irq_flags;
47 * int pc;
48 *
49 * local_save_flags(irq_flags);
50 * pc = preempt_count();
51 *
52 * event = trace_current_buffer_lock_reserve(event_<call>.id,
53 * sizeof(struct ftrace_raw_<call>),
54 * irq_flags, pc);
55 * if (!event)
56 * return;
57 * entry = ring_buffer_event_data(event);
58 *
59 * <tstruct>; <-- Here we assign the entries by the TRACE_FIELD.
60 *
61 * trace_current_buffer_unlock_commit(event, irq_flags, pc);
62 * }
63 *
64 * static int ftrace_raw_reg_event_<call>(void)
65 * {
66 * int ret;
67 *
68 * ret = register_trace_<call>(ftrace_raw_event_<call>);
69 * if (!ret)
70 * pr_info("event trace: Could not activate trace point "
71 * "probe to <call>");
72 * return ret;
73 * }
74 *
75 * static void ftrace_unreg_event_<call>(void)
76 * {
77 * unregister_trace_<call>(ftrace_raw_event_<call>);
78 * }
79 *
80 * static struct trace_event ftrace_event_type_<call> = {
81 * .trace = ftrace_raw_output_<call>, <-- stage 2
82 * };
83 *
84 * static int ftrace_raw_init_event_<call>(void)
85 * {
86 * int id;
87 *
88 * id = register_ftrace_event(&ftrace_event_type_<call>);
89 * if (!id)
90 * return -ENODEV;
91 * event_<call>.id = id;
92 * return 0;
93 * }
94 *
95 * static struct ftrace_event_call __used
96 * __attribute__((__aligned__(4)))
97 * __attribute__((section("_ftrace_events"))) event_<call> = {
98 * .name = "<call>",
99 * .regfunc = ftrace_reg_event_<call>,
100 * .unregfunc = ftrace_unreg_event_<call>,
101 * .raw_init = ftrace_raw_init_event_<call>,
102 * .raw_reg = ftrace_raw_reg_event_<call>,
103 * .raw_unreg = ftrace_raw_unreg_event_<call>,
104 * }
105 *
106 */
107
108#undef TPFMT
109#define TPFMT(fmt, args...) fmt "\n", ##args
110
111#define _TRACE_FORMAT(call, proto, args, fmt) \
112static void ftrace_event_##call(proto) \
113{ \
114 event_trace_printk(_RET_IP_, "(" #call ") " fmt); \
115} \
116 \
117static int ftrace_reg_event_##call(void) \
118{ \
119 int ret; \
120 \
121 ret = register_trace_##call(ftrace_event_##call); \
122 if (!ret) \
123 pr_info("event trace: Could not activate trace point " \
124 "probe to " #call); \
125 return ret; \
126} \
127 \
128static void ftrace_unreg_event_##call(void) \
129{ \
130 unregister_trace_##call(ftrace_event_##call); \
131} \
132
133
134#undef TRACE_FORMAT
135#define TRACE_FORMAT(call, proto, args, fmt) \
136_TRACE_FORMAT(call, PARAMS(proto), PARAMS(args), PARAMS(fmt)) \
137static struct ftrace_event_call __used \
138__attribute__((__aligned__(4))) \
139__attribute__((section("_ftrace_events"))) event_##call = { \
140 .name = #call, \
141 .system = STR(TRACE_SYSTEM), \
142 .regfunc = ftrace_reg_event_##call, \
143 .unregfunc = ftrace_unreg_event_##call, \
144}
145
146#undef TRACE_FIELD
147#define TRACE_FIELD(type, item, assign)\
148 entry->item = assign;
149
150#undef TRACE_EVENT_FORMAT
151#define TRACE_EVENT_FORMAT(call, proto, args, fmt, tstruct, tpfmt) \
152_TRACE_FORMAT(call, PARAMS(proto), PARAMS(args), PARAMS(fmt)) \
153 \
154static struct ftrace_event_call event_##call; \
155 \
156static void ftrace_raw_event_##call(proto) \
157{ \
158 struct ring_buffer_event *event; \
159 struct ftrace_raw_##call *entry; \
160 unsigned long irq_flags; \
161 int pc; \
162 \
163 local_save_flags(irq_flags); \
164 pc = preempt_count(); \
165 \
166 event = trace_current_buffer_lock_reserve(event_##call.id, \
167 sizeof(struct ftrace_raw_##call), \
168 irq_flags, pc); \
169 if (!event) \
170 return; \
171 entry = ring_buffer_event_data(event); \
172 \
173 tstruct; \
174 \
175 trace_current_buffer_unlock_commit(event, irq_flags, pc); \
176} \
177 \
178static int ftrace_raw_reg_event_##call(void) \
179{ \
180 int ret; \
181 \
182 ret = register_trace_##call(ftrace_raw_event_##call); \
183 if (!ret) \
184 pr_info("event trace: Could not activate trace point " \
185 "probe to " #call); \
186 return ret; \
187} \
188 \
189static void ftrace_raw_unreg_event_##call(void) \
190{ \
191 unregister_trace_##call(ftrace_raw_event_##call); \
192} \
193 \
194static struct trace_event ftrace_event_type_##call = { \
195 .trace = ftrace_raw_output_##call, \
196}; \
197 \
198static int ftrace_raw_init_event_##call(void) \
199{ \
200 int id; \
201 \
202 id = register_ftrace_event(&ftrace_event_type_##call); \
203 if (!id) \
204 return -ENODEV; \
205 event_##call.id = id; \
206 return 0; \
207} \
208 \
209static struct ftrace_event_call __used \
210__attribute__((__aligned__(4))) \
211__attribute__((section("_ftrace_events"))) event_##call = { \
212 .name = #call, \
213 .system = STR(TRACE_SYSTEM), \
214 .regfunc = ftrace_reg_event_##call, \
215 .unregfunc = ftrace_unreg_event_##call, \
216 .raw_init = ftrace_raw_init_event_##call, \
217 .raw_reg = ftrace_raw_reg_event_##call, \
218 .raw_unreg = ftrace_raw_unreg_event_##call, \
219}