diff options
Diffstat (limited to 'kernel/trace/trace.h')
-rw-r--r-- | kernel/trace/trace.h | 211 |
1 files changed, 146 insertions, 65 deletions
diff --git a/kernel/trace/trace.h b/kernel/trace/trace.h index f69f86788c2b..f1f99572cde7 100644 --- a/kernel/trace/trace.h +++ b/kernel/trace/trace.h | |||
@@ -5,7 +5,9 @@ | |||
5 | #include <asm/atomic.h> | 5 | #include <asm/atomic.h> |
6 | #include <linux/sched.h> | 6 | #include <linux/sched.h> |
7 | #include <linux/clocksource.h> | 7 | #include <linux/clocksource.h> |
8 | #include <linux/ring_buffer.h> | ||
8 | #include <linux/mmiotrace.h> | 9 | #include <linux/mmiotrace.h> |
10 | #include <linux/ftrace.h> | ||
9 | 11 | ||
10 | enum trace_type { | 12 | enum trace_type { |
11 | __TRACE_FIRST_TYPE = 0, | 13 | __TRACE_FIRST_TYPE = 0, |
@@ -13,38 +15,60 @@ enum trace_type { | |||
13 | TRACE_FN, | 15 | TRACE_FN, |
14 | TRACE_CTX, | 16 | TRACE_CTX, |
15 | TRACE_WAKE, | 17 | TRACE_WAKE, |
18 | TRACE_CONT, | ||
16 | TRACE_STACK, | 19 | TRACE_STACK, |
20 | TRACE_PRINT, | ||
17 | TRACE_SPECIAL, | 21 | TRACE_SPECIAL, |
18 | TRACE_MMIO_RW, | 22 | TRACE_MMIO_RW, |
19 | TRACE_MMIO_MAP, | 23 | TRACE_MMIO_MAP, |
24 | TRACE_BOOT, | ||
20 | 25 | ||
21 | __TRACE_LAST_TYPE | 26 | __TRACE_LAST_TYPE |
22 | }; | 27 | }; |
23 | 28 | ||
24 | /* | 29 | /* |
30 | * The trace entry - the most basic unit of tracing. This is what | ||
31 | * is printed in the end as a single line in the trace output, such as: | ||
32 | * | ||
33 | * bash-15816 [01] 235.197585: idle_cpu <- irq_enter | ||
34 | */ | ||
35 | struct trace_entry { | ||
36 | unsigned char type; | ||
37 | unsigned char cpu; | ||
38 | unsigned char flags; | ||
39 | unsigned char preempt_count; | ||
40 | int pid; | ||
41 | }; | ||
42 | |||
43 | /* | ||
25 | * Function trace entry - function address and parent function addres: | 44 | * Function trace entry - function address and parent function addres: |
26 | */ | 45 | */ |
27 | struct ftrace_entry { | 46 | struct ftrace_entry { |
47 | struct trace_entry ent; | ||
28 | unsigned long ip; | 48 | unsigned long ip; |
29 | unsigned long parent_ip; | 49 | unsigned long parent_ip; |
30 | }; | 50 | }; |
51 | extern struct tracer boot_tracer; | ||
31 | 52 | ||
32 | /* | 53 | /* |
33 | * Context switch trace entry - which task (and prio) we switched from/to: | 54 | * Context switch trace entry - which task (and prio) we switched from/to: |
34 | */ | 55 | */ |
35 | struct ctx_switch_entry { | 56 | struct ctx_switch_entry { |
57 | struct trace_entry ent; | ||
36 | unsigned int prev_pid; | 58 | unsigned int prev_pid; |
37 | unsigned char prev_prio; | 59 | unsigned char prev_prio; |
38 | unsigned char prev_state; | 60 | unsigned char prev_state; |
39 | unsigned int next_pid; | 61 | unsigned int next_pid; |
40 | unsigned char next_prio; | 62 | unsigned char next_prio; |
41 | unsigned char next_state; | 63 | unsigned char next_state; |
64 | unsigned int next_cpu; | ||
42 | }; | 65 | }; |
43 | 66 | ||
44 | /* | 67 | /* |
45 | * Special (free-form) trace entry: | 68 | * Special (free-form) trace entry: |
46 | */ | 69 | */ |
47 | struct special_entry { | 70 | struct special_entry { |
71 | struct trace_entry ent; | ||
48 | unsigned long arg1; | 72 | unsigned long arg1; |
49 | unsigned long arg2; | 73 | unsigned long arg2; |
50 | unsigned long arg3; | 74 | unsigned long arg3; |
@@ -57,33 +81,60 @@ struct special_entry { | |||
57 | #define FTRACE_STACK_ENTRIES 8 | 81 | #define FTRACE_STACK_ENTRIES 8 |
58 | 82 | ||
59 | struct stack_entry { | 83 | struct stack_entry { |
84 | struct trace_entry ent; | ||
60 | unsigned long caller[FTRACE_STACK_ENTRIES]; | 85 | unsigned long caller[FTRACE_STACK_ENTRIES]; |
61 | }; | 86 | }; |
62 | 87 | ||
63 | /* | 88 | /* |
64 | * The trace entry - the most basic unit of tracing. This is what | 89 | * ftrace_printk entry: |
65 | * is printed in the end as a single line in the trace output, such as: | ||
66 | * | ||
67 | * bash-15816 [01] 235.197585: idle_cpu <- irq_enter | ||
68 | */ | 90 | */ |
69 | struct trace_entry { | 91 | struct print_entry { |
70 | char type; | 92 | struct trace_entry ent; |
71 | char cpu; | 93 | unsigned long ip; |
72 | char flags; | 94 | char buf[]; |
73 | char preempt_count; | 95 | }; |
74 | int pid; | 96 | |
75 | cycle_t t; | 97 | #define TRACE_OLD_SIZE 88 |
76 | union { | 98 | |
77 | struct ftrace_entry fn; | 99 | struct trace_field_cont { |
78 | struct ctx_switch_entry ctx; | 100 | unsigned char type; |
79 | struct special_entry special; | 101 | /* Temporary till we get rid of this completely */ |
80 | struct stack_entry stack; | 102 | char buf[TRACE_OLD_SIZE - 1]; |
81 | struct mmiotrace_rw mmiorw; | 103 | }; |
82 | struct mmiotrace_map mmiomap; | 104 | |
83 | }; | 105 | struct trace_mmiotrace_rw { |
106 | struct trace_entry ent; | ||
107 | struct mmiotrace_rw rw; | ||
84 | }; | 108 | }; |
85 | 109 | ||
86 | #define TRACE_ENTRY_SIZE sizeof(struct trace_entry) | 110 | struct trace_mmiotrace_map { |
111 | struct trace_entry ent; | ||
112 | struct mmiotrace_map map; | ||
113 | }; | ||
114 | |||
115 | struct trace_boot { | ||
116 | struct trace_entry ent; | ||
117 | struct boot_trace initcall; | ||
118 | }; | ||
119 | |||
120 | /* | ||
121 | * trace_flag_type is an enumeration that holds different | ||
122 | * states when a trace occurs. These are: | ||
123 | * IRQS_OFF - interrupts were disabled | ||
124 | * NEED_RESCED - reschedule is requested | ||
125 | * HARDIRQ - inside an interrupt handler | ||
126 | * SOFTIRQ - inside a softirq handler | ||
127 | * CONT - multiple entries hold the trace item | ||
128 | */ | ||
129 | enum trace_flag_type { | ||
130 | TRACE_FLAG_IRQS_OFF = 0x01, | ||
131 | TRACE_FLAG_NEED_RESCHED = 0x02, | ||
132 | TRACE_FLAG_HARDIRQ = 0x04, | ||
133 | TRACE_FLAG_SOFTIRQ = 0x08, | ||
134 | TRACE_FLAG_CONT = 0x10, | ||
135 | }; | ||
136 | |||
137 | #define TRACE_BUF_SIZE 1024 | ||
87 | 138 | ||
88 | /* | 139 | /* |
89 | * The CPU trace array - it consists of thousands of trace entries | 140 | * The CPU trace array - it consists of thousands of trace entries |
@@ -91,16 +142,9 @@ struct trace_entry { | |||
91 | * the trace, etc.) | 142 | * the trace, etc.) |
92 | */ | 143 | */ |
93 | struct trace_array_cpu { | 144 | struct trace_array_cpu { |
94 | struct list_head trace_pages; | ||
95 | atomic_t disabled; | 145 | atomic_t disabled; |
96 | raw_spinlock_t lock; | ||
97 | struct lock_class_key lock_key; | ||
98 | 146 | ||
99 | /* these fields get copied into max-trace: */ | 147 | /* these fields get copied into max-trace: */ |
100 | unsigned trace_head_idx; | ||
101 | unsigned trace_tail_idx; | ||
102 | void *trace_head; /* producer */ | ||
103 | void *trace_tail; /* consumer */ | ||
104 | unsigned long trace_idx; | 148 | unsigned long trace_idx; |
105 | unsigned long overrun; | 149 | unsigned long overrun; |
106 | unsigned long saved_latency; | 150 | unsigned long saved_latency; |
@@ -124,6 +168,7 @@ struct trace_iterator; | |||
124 | * They have on/off state as well: | 168 | * They have on/off state as well: |
125 | */ | 169 | */ |
126 | struct trace_array { | 170 | struct trace_array { |
171 | struct ring_buffer *buffer; | ||
127 | unsigned long entries; | 172 | unsigned long entries; |
128 | long ctrl; | 173 | long ctrl; |
129 | int cpu; | 174 | int cpu; |
@@ -132,6 +177,56 @@ struct trace_array { | |||
132 | struct trace_array_cpu *data[NR_CPUS]; | 177 | struct trace_array_cpu *data[NR_CPUS]; |
133 | }; | 178 | }; |
134 | 179 | ||
180 | #define FTRACE_CMP_TYPE(var, type) \ | ||
181 | __builtin_types_compatible_p(typeof(var), type *) | ||
182 | |||
183 | #undef IF_ASSIGN | ||
184 | #define IF_ASSIGN(var, entry, etype, id) \ | ||
185 | if (FTRACE_CMP_TYPE(var, etype)) { \ | ||
186 | var = (typeof(var))(entry); \ | ||
187 | WARN_ON(id && (entry)->type != id); \ | ||
188 | break; \ | ||
189 | } | ||
190 | |||
191 | /* Will cause compile errors if type is not found. */ | ||
192 | extern void __ftrace_bad_type(void); | ||
193 | |||
194 | /* | ||
195 | * The trace_assign_type is a verifier that the entry type is | ||
196 | * the same as the type being assigned. To add new types simply | ||
197 | * add a line with the following format: | ||
198 | * | ||
199 | * IF_ASSIGN(var, ent, type, id); | ||
200 | * | ||
201 | * Where "type" is the trace type that includes the trace_entry | ||
202 | * as the "ent" item. And "id" is the trace identifier that is | ||
203 | * used in the trace_type enum. | ||
204 | * | ||
205 | * If the type can have more than one id, then use zero. | ||
206 | */ | ||
207 | #define trace_assign_type(var, ent) \ | ||
208 | do { \ | ||
209 | IF_ASSIGN(var, ent, struct ftrace_entry, TRACE_FN); \ | ||
210 | IF_ASSIGN(var, ent, struct ctx_switch_entry, 0); \ | ||
211 | IF_ASSIGN(var, ent, struct trace_field_cont, TRACE_CONT); \ | ||
212 | IF_ASSIGN(var, ent, struct stack_entry, TRACE_STACK); \ | ||
213 | IF_ASSIGN(var, ent, struct print_entry, TRACE_PRINT); \ | ||
214 | IF_ASSIGN(var, ent, struct special_entry, 0); \ | ||
215 | IF_ASSIGN(var, ent, struct trace_mmiotrace_rw, \ | ||
216 | TRACE_MMIO_RW); \ | ||
217 | IF_ASSIGN(var, ent, struct trace_mmiotrace_map, \ | ||
218 | TRACE_MMIO_MAP); \ | ||
219 | IF_ASSIGN(var, ent, struct trace_boot, TRACE_BOOT); \ | ||
220 | __ftrace_bad_type(); \ | ||
221 | } while (0) | ||
222 | |||
223 | /* Return values for print_line callback */ | ||
224 | enum print_line_t { | ||
225 | TRACE_TYPE_PARTIAL_LINE = 0, /* Retry after flushing the seq */ | ||
226 | TRACE_TYPE_HANDLED = 1, | ||
227 | TRACE_TYPE_UNHANDLED = 2 /* Relay to other output functions */ | ||
228 | }; | ||
229 | |||
135 | /* | 230 | /* |
136 | * A specific tracer, represented by methods that operate on a trace array: | 231 | * A specific tracer, represented by methods that operate on a trace array: |
137 | */ | 232 | */ |
@@ -152,7 +247,7 @@ struct tracer { | |||
152 | int (*selftest)(struct tracer *trace, | 247 | int (*selftest)(struct tracer *trace, |
153 | struct trace_array *tr); | 248 | struct trace_array *tr); |
154 | #endif | 249 | #endif |
155 | int (*print_line)(struct trace_iterator *iter); | 250 | enum print_line_t (*print_line)(struct trace_iterator *iter); |
156 | struct tracer *next; | 251 | struct tracer *next; |
157 | int print_max; | 252 | int print_max; |
158 | }; | 253 | }; |
@@ -171,57 +266,58 @@ struct trace_iterator { | |||
171 | struct trace_array *tr; | 266 | struct trace_array *tr; |
172 | struct tracer *trace; | 267 | struct tracer *trace; |
173 | void *private; | 268 | void *private; |
174 | long last_overrun[NR_CPUS]; | 269 | struct ring_buffer_iter *buffer_iter[NR_CPUS]; |
175 | long overrun[NR_CPUS]; | ||
176 | 270 | ||
177 | /* The below is zeroed out in pipe_read */ | 271 | /* The below is zeroed out in pipe_read */ |
178 | struct trace_seq seq; | 272 | struct trace_seq seq; |
179 | struct trace_entry *ent; | 273 | struct trace_entry *ent; |
180 | int cpu; | 274 | int cpu; |
181 | 275 | u64 ts; | |
182 | struct trace_entry *prev_ent; | ||
183 | int prev_cpu; | ||
184 | 276 | ||
185 | unsigned long iter_flags; | 277 | unsigned long iter_flags; |
186 | loff_t pos; | 278 | loff_t pos; |
187 | unsigned long next_idx[NR_CPUS]; | ||
188 | struct list_head *next_page[NR_CPUS]; | ||
189 | unsigned next_page_idx[NR_CPUS]; | ||
190 | long idx; | 279 | long idx; |
191 | }; | 280 | }; |
192 | 281 | ||
193 | void tracing_reset(struct trace_array_cpu *data); | 282 | void trace_wake_up(void); |
283 | void tracing_reset(struct trace_array *tr, int cpu); | ||
194 | int tracing_open_generic(struct inode *inode, struct file *filp); | 284 | int tracing_open_generic(struct inode *inode, struct file *filp); |
195 | struct dentry *tracing_init_dentry(void); | 285 | struct dentry *tracing_init_dentry(void); |
196 | void init_tracer_sysprof_debugfs(struct dentry *d_tracer); | 286 | void init_tracer_sysprof_debugfs(struct dentry *d_tracer); |
197 | 287 | ||
288 | struct trace_entry *tracing_get_trace_entry(struct trace_array *tr, | ||
289 | struct trace_array_cpu *data); | ||
290 | void tracing_generic_entry_update(struct trace_entry *entry, | ||
291 | unsigned long flags, | ||
292 | int pc); | ||
293 | |||
198 | void ftrace(struct trace_array *tr, | 294 | void ftrace(struct trace_array *tr, |
199 | struct trace_array_cpu *data, | 295 | struct trace_array_cpu *data, |
200 | unsigned long ip, | 296 | unsigned long ip, |
201 | unsigned long parent_ip, | 297 | unsigned long parent_ip, |
202 | unsigned long flags); | 298 | unsigned long flags, int pc); |
203 | void tracing_sched_switch_trace(struct trace_array *tr, | 299 | void tracing_sched_switch_trace(struct trace_array *tr, |
204 | struct trace_array_cpu *data, | 300 | struct trace_array_cpu *data, |
205 | struct task_struct *prev, | 301 | struct task_struct *prev, |
206 | struct task_struct *next, | 302 | struct task_struct *next, |
207 | unsigned long flags); | 303 | unsigned long flags, int pc); |
208 | void tracing_record_cmdline(struct task_struct *tsk); | 304 | void tracing_record_cmdline(struct task_struct *tsk); |
209 | 305 | ||
210 | void tracing_sched_wakeup_trace(struct trace_array *tr, | 306 | void tracing_sched_wakeup_trace(struct trace_array *tr, |
211 | struct trace_array_cpu *data, | 307 | struct trace_array_cpu *data, |
212 | struct task_struct *wakee, | 308 | struct task_struct *wakee, |
213 | struct task_struct *cur, | 309 | struct task_struct *cur, |
214 | unsigned long flags); | 310 | unsigned long flags, int pc); |
215 | void trace_special(struct trace_array *tr, | 311 | void trace_special(struct trace_array *tr, |
216 | struct trace_array_cpu *data, | 312 | struct trace_array_cpu *data, |
217 | unsigned long arg1, | 313 | unsigned long arg1, |
218 | unsigned long arg2, | 314 | unsigned long arg2, |
219 | unsigned long arg3); | 315 | unsigned long arg3, int pc); |
220 | void trace_function(struct trace_array *tr, | 316 | void trace_function(struct trace_array *tr, |
221 | struct trace_array_cpu *data, | 317 | struct trace_array_cpu *data, |
222 | unsigned long ip, | 318 | unsigned long ip, |
223 | unsigned long parent_ip, | 319 | unsigned long parent_ip, |
224 | unsigned long flags); | 320 | unsigned long flags, int pc); |
225 | 321 | ||
226 | void tracing_start_cmdline_record(void); | 322 | void tracing_start_cmdline_record(void); |
227 | void tracing_stop_cmdline_record(void); | 323 | void tracing_stop_cmdline_record(void); |
@@ -268,51 +364,33 @@ extern unsigned long ftrace_update_tot_cnt; | |||
268 | extern int DYN_FTRACE_TEST_NAME(void); | 364 | extern int DYN_FTRACE_TEST_NAME(void); |
269 | #endif | 365 | #endif |
270 | 366 | ||
271 | #ifdef CONFIG_MMIOTRACE | ||
272 | extern void __trace_mmiotrace_rw(struct trace_array *tr, | ||
273 | struct trace_array_cpu *data, | ||
274 | struct mmiotrace_rw *rw); | ||
275 | extern void __trace_mmiotrace_map(struct trace_array *tr, | ||
276 | struct trace_array_cpu *data, | ||
277 | struct mmiotrace_map *map); | ||
278 | #endif | ||
279 | |||
280 | #ifdef CONFIG_FTRACE_STARTUP_TEST | 367 | #ifdef CONFIG_FTRACE_STARTUP_TEST |
281 | #ifdef CONFIG_FTRACE | ||
282 | extern int trace_selftest_startup_function(struct tracer *trace, | 368 | extern int trace_selftest_startup_function(struct tracer *trace, |
283 | struct trace_array *tr); | 369 | struct trace_array *tr); |
284 | #endif | ||
285 | #ifdef CONFIG_IRQSOFF_TRACER | ||
286 | extern int trace_selftest_startup_irqsoff(struct tracer *trace, | 370 | extern int trace_selftest_startup_irqsoff(struct tracer *trace, |
287 | struct trace_array *tr); | 371 | struct trace_array *tr); |
288 | #endif | ||
289 | #ifdef CONFIG_PREEMPT_TRACER | ||
290 | extern int trace_selftest_startup_preemptoff(struct tracer *trace, | 372 | extern int trace_selftest_startup_preemptoff(struct tracer *trace, |
291 | struct trace_array *tr); | 373 | struct trace_array *tr); |
292 | #endif | ||
293 | #if defined(CONFIG_IRQSOFF_TRACER) && defined(CONFIG_PREEMPT_TRACER) | ||
294 | extern int trace_selftest_startup_preemptirqsoff(struct tracer *trace, | 374 | extern int trace_selftest_startup_preemptirqsoff(struct tracer *trace, |
295 | struct trace_array *tr); | 375 | struct trace_array *tr); |
296 | #endif | ||
297 | #ifdef CONFIG_SCHED_TRACER | ||
298 | extern int trace_selftest_startup_wakeup(struct tracer *trace, | 376 | extern int trace_selftest_startup_wakeup(struct tracer *trace, |
299 | struct trace_array *tr); | 377 | struct trace_array *tr); |
300 | #endif | 378 | extern int trace_selftest_startup_nop(struct tracer *trace, |
301 | #ifdef CONFIG_CONTEXT_SWITCH_TRACER | 379 | struct trace_array *tr); |
302 | extern int trace_selftest_startup_sched_switch(struct tracer *trace, | 380 | extern int trace_selftest_startup_sched_switch(struct tracer *trace, |
303 | struct trace_array *tr); | 381 | struct trace_array *tr); |
304 | #endif | ||
305 | #ifdef CONFIG_SYSPROF_TRACER | ||
306 | extern int trace_selftest_startup_sysprof(struct tracer *trace, | 382 | extern int trace_selftest_startup_sysprof(struct tracer *trace, |
307 | struct trace_array *tr); | 383 | struct trace_array *tr); |
308 | #endif | ||
309 | #endif /* CONFIG_FTRACE_STARTUP_TEST */ | 384 | #endif /* CONFIG_FTRACE_STARTUP_TEST */ |
310 | 385 | ||
311 | extern void *head_page(struct trace_array_cpu *data); | 386 | extern void *head_page(struct trace_array_cpu *data); |
312 | extern int trace_seq_printf(struct trace_seq *s, const char *fmt, ...); | 387 | extern int trace_seq_printf(struct trace_seq *s, const char *fmt, ...); |
388 | extern void trace_seq_print_cont(struct trace_seq *s, | ||
389 | struct trace_iterator *iter); | ||
313 | extern ssize_t trace_seq_to_user(struct trace_seq *s, char __user *ubuf, | 390 | extern ssize_t trace_seq_to_user(struct trace_seq *s, char __user *ubuf, |
314 | size_t cnt); | 391 | size_t cnt); |
315 | extern long ns2usecs(cycle_t nsec); | 392 | extern long ns2usecs(cycle_t nsec); |
393 | extern int trace_vprintk(unsigned long ip, const char *fmt, va_list args); | ||
316 | 394 | ||
317 | extern unsigned long trace_flags; | 395 | extern unsigned long trace_flags; |
318 | 396 | ||
@@ -334,6 +412,9 @@ enum trace_iterator_flags { | |||
334 | TRACE_ITER_BLOCK = 0x80, | 412 | TRACE_ITER_BLOCK = 0x80, |
335 | TRACE_ITER_STACKTRACE = 0x100, | 413 | TRACE_ITER_STACKTRACE = 0x100, |
336 | TRACE_ITER_SCHED_TREE = 0x200, | 414 | TRACE_ITER_SCHED_TREE = 0x200, |
415 | TRACE_ITER_PRINTK = 0x400, | ||
337 | }; | 416 | }; |
338 | 417 | ||
418 | extern struct tracer nop_trace; | ||
419 | |||
339 | #endif /* _LINUX_KERNEL_TRACE_H */ | 420 | #endif /* _LINUX_KERNEL_TRACE_H */ |