diff options
Diffstat (limited to 'kernel/trace')
-rw-r--r-- | kernel/trace/events.c | 6 | ||||
-rw-r--r-- | kernel/trace/trace.h | 19 | ||||
-rw-r--r-- | kernel/trace/trace_events.c | 2 | ||||
-rw-r--r-- | kernel/trace/trace_events.h | 57 | ||||
-rw-r--r-- | kernel/trace/trace_events_stage_1.h | 34 | ||||
-rw-r--r-- | kernel/trace/trace_events_stage_2.h | 72 | ||||
-rw-r--r-- | kernel/trace/trace_events_stage_3.h | 219 |
7 files changed, 350 insertions, 59 deletions
diff --git a/kernel/trace/events.c b/kernel/trace/events.c index 4e4e45860c58..f2509cbaacea 100644 --- a/kernel/trace/events.c +++ b/kernel/trace/events.c | |||
@@ -8,6 +8,10 @@ | |||
8 | 8 | ||
9 | #include <trace/trace_events.h> | 9 | #include <trace/trace_events.h> |
10 | 10 | ||
11 | #include "trace_events.h" | 11 | #include "trace_output.h" |
12 | |||
13 | #include "trace_events_stage_1.h" | ||
14 | #include "trace_events_stage_2.h" | ||
15 | #include "trace_events_stage_3.h" | ||
12 | 16 | ||
13 | #include <trace/trace_event_types.h> | 17 | #include <trace/trace_event_types.h> |
diff --git a/kernel/trace/trace.h b/kernel/trace/trace.h index adf161f6dd11..aa1ab0cb80ab 100644 --- a/kernel/trace/trace.h +++ b/kernel/trace/trace.h | |||
@@ -726,4 +726,23 @@ static inline void trace_branch_disable(void) | |||
726 | } | 726 | } |
727 | #endif /* CONFIG_BRANCH_TRACER */ | 727 | #endif /* CONFIG_BRANCH_TRACER */ |
728 | 728 | ||
729 | struct ftrace_event_call { | ||
730 | char *name; | ||
731 | char *system; | ||
732 | struct dentry *dir; | ||
733 | int enabled; | ||
734 | int (*regfunc)(void); | ||
735 | void (*unregfunc)(void); | ||
736 | int id; | ||
737 | struct dentry *raw_dir; | ||
738 | int raw_enabled; | ||
739 | int (*raw_init)(void); | ||
740 | int (*raw_reg)(void); | ||
741 | void (*raw_unreg)(void); | ||
742 | }; | ||
743 | |||
744 | void event_trace_printk(unsigned long ip, const char *fmt, ...); | ||
745 | extern struct ftrace_event_call __start_ftrace_events[]; | ||
746 | extern struct ftrace_event_call __stop_ftrace_events[]; | ||
747 | |||
729 | #endif /* _LINUX_KERNEL_TRACE_H */ | 748 | #endif /* _LINUX_KERNEL_TRACE_H */ |
diff --git a/kernel/trace/trace_events.c b/kernel/trace/trace_events.c index b811eb343522..77a5c02bd634 100644 --- a/kernel/trace/trace_events.c +++ b/kernel/trace/trace_events.c | |||
@@ -10,7 +10,7 @@ | |||
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 | 14 | ||
15 | #define TRACE_SYSTEM "TRACE_SYSTEM" | 15 | #define TRACE_SYSTEM "TRACE_SYSTEM" |
16 | 16 | ||
diff --git a/kernel/trace/trace_events.h b/kernel/trace/trace_events.h deleted file mode 100644 index b015d7b19878..000000000000 --- a/kernel/trace/trace_events.h +++ /dev/null | |||
@@ -1,57 +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 | |||
8 | struct ftrace_event_call { | ||
9 | char *name; | ||
10 | char *system; | ||
11 | struct dentry *dir; | ||
12 | int enabled; | ||
13 | int (*regfunc)(void); | ||
14 | void (*unregfunc)(void); | ||
15 | }; | ||
16 | |||
17 | |||
18 | #undef TPFMT | ||
19 | #define TPFMT(fmt, args...) fmt "\n", ##args | ||
20 | |||
21 | #undef TRACE_FORMAT | ||
22 | #define TRACE_FORMAT(call, proto, args, fmt) \ | ||
23 | static void ftrace_event_##call(proto) \ | ||
24 | { \ | ||
25 | event_trace_printk(_RET_IP_, "(" #call ") " fmt); \ | ||
26 | } \ | ||
27 | \ | ||
28 | static int ftrace_reg_event_##call(void) \ | ||
29 | { \ | ||
30 | int ret; \ | ||
31 | \ | ||
32 | ret = register_trace_##call(ftrace_event_##call); \ | ||
33 | if (!ret) \ | ||
34 | pr_info("event trace: Could not activate trace point " \ | ||
35 | "probe to " #call); \ | ||
36 | return ret; \ | ||
37 | } \ | ||
38 | \ | ||
39 | static void ftrace_unreg_event_##call(void) \ | ||
40 | { \ | ||
41 | unregister_trace_##call(ftrace_event_##call); \ | ||
42 | } \ | ||
43 | \ | ||
44 | static struct ftrace_event_call __used \ | ||
45 | __attribute__((__aligned__(4))) \ | ||
46 | __attribute__((section("_ftrace_events"))) event_##call = { \ | ||
47 | .name = #call, \ | ||
48 | .system = STR(TRACE_SYSTEM), \ | ||
49 | .regfunc = ftrace_reg_event_##call, \ | ||
50 | .unregfunc = ftrace_unreg_event_##call, \ | ||
51 | } | ||
52 | |||
53 | void event_trace_printk(unsigned long ip, const char *fmt, ...); | ||
54 | extern struct ftrace_event_call __start_ftrace_events[]; | ||
55 | extern struct ftrace_event_call __stop_ftrace_events[]; | ||
56 | |||
57 | #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) \ | ||
48 | enum print_line_t \ | ||
49 | ftrace_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) \ | ||
112 | static void ftrace_event_##call(proto) \ | ||
113 | { \ | ||
114 | event_trace_printk(_RET_IP_, "(" #call ") " fmt); \ | ||
115 | } \ | ||
116 | \ | ||
117 | static 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 | \ | ||
128 | static 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)) \ | ||
137 | static 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 | \ | ||
154 | static struct ftrace_event_call event_##call; \ | ||
155 | \ | ||
156 | static 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 | \ | ||
178 | static 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 | \ | ||
189 | static void ftrace_raw_unreg_event_##call(void) \ | ||
190 | { \ | ||
191 | unregister_trace_##call(ftrace_raw_event_##call); \ | ||
192 | } \ | ||
193 | \ | ||
194 | static struct trace_event ftrace_event_type_##call = { \ | ||
195 | .trace = ftrace_raw_output_##call, \ | ||
196 | }; \ | ||
197 | \ | ||
198 | static 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 | \ | ||
209 | static 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 | } | ||