blob: 2ca9d66aa74ef7b352b9706a6e36c94e4122c7fb [file] [log] [blame]
Steven Rostedtbc0c38d2008-05-12 21:20:42 +02001/*
2 * ring buffer based function tracer
3 *
4 * Copyright (C) 2007-2008 Steven Rostedt <srostedt@redhat.com>
5 * Copyright (C) 2008 Ingo Molnar <mingo@redhat.com>
6 *
7 * Originally taken from the RT patch by:
8 * Arnaldo Carvalho de Melo <acme@redhat.com>
9 *
10 * Based on code from the latency_tracer, that is:
11 * Copyright (C) 2004-2006 Ingo Molnar
12 * Copyright (C) 2004 William Lee Irwin III
13 */
14#include <linux/utsrelease.h>
15#include <linux/kallsyms.h>
16#include <linux/seq_file.h>
17#include <linux/debugfs.h>
Steven Rostedt4c11d7a2008-05-12 21:20:43 +020018#include <linux/pagemap.h>
Steven Rostedtbc0c38d2008-05-12 21:20:42 +020019#include <linux/hardirq.h>
20#include <linux/linkage.h>
21#include <linux/uaccess.h>
22#include <linux/ftrace.h>
23#include <linux/module.h>
24#include <linux/percpu.h>
25#include <linux/ctype.h>
26#include <linux/init.h>
Soeren Sandmann Pedersen2a2cc8f2008-05-12 21:20:49 +020027#include <linux/poll.h>
Steven Rostedtbc0c38d2008-05-12 21:20:42 +020028#include <linux/gfp.h>
29#include <linux/fs.h>
30
Ingo Molnar86387f72008-05-12 21:20:51 +020031#include <linux/stacktrace.h>
32
Steven Rostedtbc0c38d2008-05-12 21:20:42 +020033#include "trace.h"
34
35unsigned long __read_mostly tracing_max_latency = (cycle_t)ULONG_MAX;
36unsigned long __read_mostly tracing_thresh;
37
Steven Rostedt60a11772008-05-12 21:20:44 +020038static int tracing_disabled = 1;
39
Ingo Molnare309b412008-05-12 21:20:51 +020040static long
Steven Rostedtbc0c38d2008-05-12 21:20:42 +020041ns2usecs(cycle_t nsec)
42{
43 nsec += 500;
44 do_div(nsec, 1000);
45 return nsec;
46}
47
Ingo Molnare309b412008-05-12 21:20:51 +020048cycle_t ftrace_now(int cpu)
Ingo Molnar750ed1a2008-05-12 21:20:46 +020049{
Ingo Molnar0fd9e0d2008-05-12 21:20:48 +020050 return cpu_clock(cpu);
Ingo Molnar750ed1a2008-05-12 21:20:46 +020051}
52
Steven Rostedtbc0c38d2008-05-12 21:20:42 +020053static struct trace_array global_trace;
54
55static DEFINE_PER_CPU(struct trace_array_cpu, global_trace_cpu);
56
57static struct trace_array max_tr;
58
59static DEFINE_PER_CPU(struct trace_array_cpu, max_data);
60
Steven Rostedt26994ea2008-05-12 21:20:48 +020061static int tracer_enabled = 1;
Ingo Molnar57422792008-05-12 21:20:51 +020062static unsigned long trace_nr_entries = 65536UL;
Steven Rostedtbc0c38d2008-05-12 21:20:42 +020063
64static struct tracer *trace_types __read_mostly;
65static struct tracer *current_trace __read_mostly;
66static int max_tracer_type_len;
67
68static DEFINE_MUTEX(trace_types_lock);
Ingo Molnar4e655512008-05-12 21:20:52 +020069static DECLARE_WAIT_QUEUE_HEAD(trace_wait);
70
71unsigned long trace_flags = TRACE_ITER_PRINT_PARENT;
72
Ingo Molnar4e655512008-05-12 21:20:52 +020073void trace_wake_up(void)
74{
Ingo Molnar017730c2008-05-12 21:20:52 +020075 /*
76 * The runqueue_is_locked() can fail, but this is the best we
77 * have for now:
78 */
79 if (!(trace_flags & TRACE_ITER_BLOCK) && !runqueue_is_locked())
Ingo Molnar4e655512008-05-12 21:20:52 +020080 wake_up(&trace_wait);
81}
Steven Rostedtbc0c38d2008-05-12 21:20:42 +020082
Steven Rostedt4c11d7a2008-05-12 21:20:43 +020083#define ENTRIES_PER_PAGE (PAGE_SIZE / sizeof(struct trace_entry))
84
Steven Rostedtbc0c38d2008-05-12 21:20:42 +020085static int __init set_nr_entries(char *str)
86{
87 if (!str)
88 return 0;
89 trace_nr_entries = simple_strtoul(str, &str, 0);
90 return 1;
91}
92__setup("trace_entries=", set_nr_entries);
93
Steven Rostedt57f50be2008-05-12 21:20:44 +020094unsigned long nsecs_to_usecs(unsigned long nsecs)
95{
96 return nsecs / 1000;
97}
98
Steven Rostedtbc0c38d2008-05-12 21:20:42 +020099enum trace_type {
100 __TRACE_FIRST_TYPE = 0,
101
102 TRACE_FN,
103 TRACE_CTX,
Ingo Molnar57422792008-05-12 21:20:51 +0200104 TRACE_WAKE,
Ingo Molnar86387f72008-05-12 21:20:51 +0200105 TRACE_STACK,
Ingo Molnarf0a920d2008-05-12 21:20:47 +0200106 TRACE_SPECIAL,
Steven Rostedtbc0c38d2008-05-12 21:20:42 +0200107
108 __TRACE_LAST_TYPE
109};
110
111enum trace_flag_type {
112 TRACE_FLAG_IRQS_OFF = 0x01,
113 TRACE_FLAG_NEED_RESCHED = 0x02,
114 TRACE_FLAG_HARDIRQ = 0x04,
115 TRACE_FLAG_SOFTIRQ = 0x08,
116};
117
Steven Rostedtbc0c38d2008-05-12 21:20:42 +0200118#define TRACE_ITER_SYM_MASK \
119 (TRACE_ITER_PRINT_PARENT|TRACE_ITER_SYM_OFFSET|TRACE_ITER_SYM_ADDR)
120
121/* These must match the bit postions above */
122static const char *trace_options[] = {
123 "print-parent",
124 "sym-offset",
125 "sym-addr",
126 "verbose",
Ingo Molnarf9896bf2008-05-12 21:20:47 +0200127 "raw",
Ingo Molnar5e3ca0e2008-05-12 21:20:49 +0200128 "hex",
Ingo Molnarcb0f12a2008-05-12 21:20:47 +0200129 "bin",
Soeren Sandmann Pedersen2a2cc8f2008-05-12 21:20:49 +0200130 "block",
Ingo Molnar86387f72008-05-12 21:20:51 +0200131 "stacktrace",
Steven Rostedtbc0c38d2008-05-12 21:20:42 +0200132 NULL
133};
134
Steven Rostedt4c11d7a2008-05-12 21:20:43 +0200135static DEFINE_SPINLOCK(ftrace_max_lock);
Steven Rostedtbc0c38d2008-05-12 21:20:42 +0200136
137/*
138 * Copy the new maximum trace into the separate maximum-trace
139 * structure. (this way the maximum trace is permanently saved,
140 * for later retrieval via /debugfs/tracing/latency_trace)
141 */
Ingo Molnare309b412008-05-12 21:20:51 +0200142static void
Steven Rostedtbc0c38d2008-05-12 21:20:42 +0200143__update_max_tr(struct trace_array *tr, struct task_struct *tsk, int cpu)
144{
145 struct trace_array_cpu *data = tr->data[cpu];
146
147 max_tr.cpu = cpu;
148 max_tr.time_start = data->preempt_timestamp;
149
150 data = max_tr.data[cpu];
151 data->saved_latency = tracing_max_latency;
152
153 memcpy(data->comm, tsk->comm, TASK_COMM_LEN);
154 data->pid = tsk->pid;
155 data->uid = tsk->uid;
156 data->nice = tsk->static_prio - 20 - MAX_RT_PRIO;
157 data->policy = tsk->policy;
158 data->rt_priority = tsk->rt_priority;
159
160 /* record this tasks comm */
161 tracing_record_cmdline(current);
162}
163
Ingo Molnarc7aafc52008-05-12 21:20:45 +0200164void check_pages(struct trace_array_cpu *data)
165{
166 struct page *page, *tmp;
167
168 BUG_ON(data->trace_pages.next->prev != &data->trace_pages);
169 BUG_ON(data->trace_pages.prev->next != &data->trace_pages);
170
171 list_for_each_entry_safe(page, tmp, &data->trace_pages, lru) {
172 BUG_ON(page->lru.next->prev != &page->lru);
173 BUG_ON(page->lru.prev->next != &page->lru);
174 }
175}
176
177void *head_page(struct trace_array_cpu *data)
178{
179 struct page *page;
180
181 check_pages(data);
182 if (list_empty(&data->trace_pages))
183 return NULL;
184
185 page = list_entry(data->trace_pages.next, struct page, lru);
186 BUG_ON(&page->lru == &data->trace_pages);
187
188 return page_address(page);
189}
190
Ingo Molnare309b412008-05-12 21:20:51 +0200191static int
Steven Rostedt214023c2008-05-12 21:20:46 +0200192trace_seq_printf(struct trace_seq *s, const char *fmt, ...)
193{
194 int len = (PAGE_SIZE - 1) - s->len;
195 va_list ap;
Steven Rostedtb3806b42008-05-12 21:20:46 +0200196 int ret;
Steven Rostedt214023c2008-05-12 21:20:46 +0200197
198 if (!len)
199 return 0;
200
201 va_start(ap, fmt);
Steven Rostedtb3806b42008-05-12 21:20:46 +0200202 ret = vsnprintf(s->buffer + s->len, len, fmt, ap);
Steven Rostedt214023c2008-05-12 21:20:46 +0200203 va_end(ap);
204
Steven Rostedtb3806b42008-05-12 21:20:46 +0200205 /* If we can't write it all, don't bother writing anything */
206 if (ret > len)
207 return 0;
208
209 s->len += ret;
Steven Rostedt214023c2008-05-12 21:20:46 +0200210
211 return len;
212}
213
Ingo Molnare309b412008-05-12 21:20:51 +0200214static int
Steven Rostedt214023c2008-05-12 21:20:46 +0200215trace_seq_puts(struct trace_seq *s, const char *str)
216{
217 int len = strlen(str);
218
219 if (len > ((PAGE_SIZE - 1) - s->len))
Steven Rostedtb3806b42008-05-12 21:20:46 +0200220 return 0;
Steven Rostedt214023c2008-05-12 21:20:46 +0200221
222 memcpy(s->buffer + s->len, str, len);
223 s->len += len;
224
225 return len;
226}
227
Ingo Molnare309b412008-05-12 21:20:51 +0200228static int
Steven Rostedt214023c2008-05-12 21:20:46 +0200229trace_seq_putc(struct trace_seq *s, unsigned char c)
230{
231 if (s->len >= (PAGE_SIZE - 1))
232 return 0;
233
234 s->buffer[s->len++] = c;
235
236 return 1;
237}
238
Ingo Molnare309b412008-05-12 21:20:51 +0200239static int
Ingo Molnarcb0f12a2008-05-12 21:20:47 +0200240trace_seq_putmem(struct trace_seq *s, void *mem, size_t len)
241{
242 if (len > ((PAGE_SIZE - 1) - s->len))
243 return 0;
244
245 memcpy(s->buffer + s->len, mem, len);
246 s->len += len;
247
248 return len;
249}
250
Ingo Molnar5e3ca0e2008-05-12 21:20:49 +0200251#define HEX_CHARS 17
252
Ingo Molnare309b412008-05-12 21:20:51 +0200253static int
Ingo Molnar5e3ca0e2008-05-12 21:20:49 +0200254trace_seq_putmem_hex(struct trace_seq *s, void *mem, size_t len)
255{
256 unsigned char hex[HEX_CHARS];
257 unsigned char *data;
258 unsigned char byte;
259 int i, j;
260
261 BUG_ON(len >= HEX_CHARS);
262
263 data = mem;
264
265#ifdef __BIG_ENDIAN
266 for (i = 0, j = 0; i < len; i++) {
267#else
268 for (i = len-1, j = 0; i >= 0; i--) {
269#endif
270 byte = data[i];
271
272 hex[j] = byte & 0x0f;
273 if (hex[j] >= 10)
274 hex[j] += 'a' - 10;
275 else
276 hex[j] += '0';
277 j++;
278
279 hex[j] = byte >> 4;
280 if (hex[j] >= 10)
281 hex[j] += 'a' - 10;
282 else
283 hex[j] += '0';
284 j++;
285 }
286 hex[j] = ' ';
287 j++;
288
289 return trace_seq_putmem(s, hex, j);
290}
291
Ingo Molnare309b412008-05-12 21:20:51 +0200292static void
Steven Rostedt214023c2008-05-12 21:20:46 +0200293trace_seq_reset(struct trace_seq *s)
294{
295 s->len = 0;
296}
297
Ingo Molnare309b412008-05-12 21:20:51 +0200298static void
Steven Rostedt214023c2008-05-12 21:20:46 +0200299trace_print_seq(struct seq_file *m, struct trace_seq *s)
300{
301 int len = s->len >= PAGE_SIZE ? PAGE_SIZE - 1 : s->len;
302
303 s->buffer[len] = 0;
304 seq_puts(m, s->buffer);
305
306 trace_seq_reset(s);
307}
308
Ingo Molnare309b412008-05-12 21:20:51 +0200309static void
Ingo Molnarc7aafc52008-05-12 21:20:45 +0200310flip_trace(struct trace_array_cpu *tr1, struct trace_array_cpu *tr2)
311{
312 struct list_head flip_pages;
313
314 INIT_LIST_HEAD(&flip_pages);
315
Steven Rostedt93a588f2008-05-12 21:20:45 +0200316 memcpy(&tr1->trace_head_idx, &tr2->trace_head_idx,
Ingo Molnarc7aafc52008-05-12 21:20:45 +0200317 sizeof(struct trace_array_cpu) -
Steven Rostedt93a588f2008-05-12 21:20:45 +0200318 offsetof(struct trace_array_cpu, trace_head_idx));
Ingo Molnarc7aafc52008-05-12 21:20:45 +0200319
320 check_pages(tr1);
321 check_pages(tr2);
322 list_splice_init(&tr1->trace_pages, &flip_pages);
323 list_splice_init(&tr2->trace_pages, &tr1->trace_pages);
324 list_splice_init(&flip_pages, &tr2->trace_pages);
325 BUG_ON(!list_empty(&flip_pages));
326 check_pages(tr1);
327 check_pages(tr2);
328}
329
Ingo Molnare309b412008-05-12 21:20:51 +0200330void
Steven Rostedtbc0c38d2008-05-12 21:20:42 +0200331update_max_tr(struct trace_array *tr, struct task_struct *tsk, int cpu)
332{
333 struct trace_array_cpu *data;
Steven Rostedtbc0c38d2008-05-12 21:20:42 +0200334 int i;
335
Steven Rostedt4c11d7a2008-05-12 21:20:43 +0200336 WARN_ON_ONCE(!irqs_disabled());
337 spin_lock(&ftrace_max_lock);
Steven Rostedtbc0c38d2008-05-12 21:20:42 +0200338 /* clear out all the previous traces */
339 for_each_possible_cpu(i) {
340 data = tr->data[i];
Ingo Molnarc7aafc52008-05-12 21:20:45 +0200341 flip_trace(max_tr.data[i], data);
Steven Rostedt89b2f972008-05-12 21:20:44 +0200342 tracing_reset(data);
Steven Rostedtbc0c38d2008-05-12 21:20:42 +0200343 }
344
345 __update_max_tr(tr, tsk, cpu);
Steven Rostedt4c11d7a2008-05-12 21:20:43 +0200346 spin_unlock(&ftrace_max_lock);
Steven Rostedtbc0c38d2008-05-12 21:20:42 +0200347}
348
349/**
350 * update_max_tr_single - only copy one trace over, and reset the rest
351 * @tr - tracer
352 * @tsk - task with the latency
353 * @cpu - the cpu of the buffer to copy.
354 */
Ingo Molnare309b412008-05-12 21:20:51 +0200355void
Steven Rostedtbc0c38d2008-05-12 21:20:42 +0200356update_max_tr_single(struct trace_array *tr, struct task_struct *tsk, int cpu)
357{
358 struct trace_array_cpu *data = tr->data[cpu];
Steven Rostedtbc0c38d2008-05-12 21:20:42 +0200359 int i;
360
Steven Rostedt4c11d7a2008-05-12 21:20:43 +0200361 WARN_ON_ONCE(!irqs_disabled());
362 spin_lock(&ftrace_max_lock);
Steven Rostedtbc0c38d2008-05-12 21:20:42 +0200363 for_each_possible_cpu(i)
364 tracing_reset(max_tr.data[i]);
365
Ingo Molnarc7aafc52008-05-12 21:20:45 +0200366 flip_trace(max_tr.data[cpu], data);
Steven Rostedt89b2f972008-05-12 21:20:44 +0200367 tracing_reset(data);
Steven Rostedtbc0c38d2008-05-12 21:20:42 +0200368
369 __update_max_tr(tr, tsk, cpu);
Steven Rostedt4c11d7a2008-05-12 21:20:43 +0200370 spin_unlock(&ftrace_max_lock);
Steven Rostedtbc0c38d2008-05-12 21:20:42 +0200371}
372
373int register_tracer(struct tracer *type)
374{
375 struct tracer *t;
376 int len;
377 int ret = 0;
378
379 if (!type->name) {
380 pr_info("Tracer must have a name\n");
381 return -1;
382 }
383
384 mutex_lock(&trace_types_lock);
385 for (t = trace_types; t; t = t->next) {
386 if (strcmp(type->name, t->name) == 0) {
387 /* already found */
388 pr_info("Trace %s already registered\n",
389 type->name);
390 ret = -1;
391 goto out;
392 }
393 }
394
Steven Rostedt60a11772008-05-12 21:20:44 +0200395#ifdef CONFIG_FTRACE_STARTUP_TEST
396 if (type->selftest) {
397 struct tracer *saved_tracer = current_trace;
398 struct trace_array_cpu *data;
399 struct trace_array *tr = &global_trace;
400 int saved_ctrl = tr->ctrl;
401 int i;
402 /*
403 * Run a selftest on this tracer.
404 * Here we reset the trace buffer, and set the current
405 * tracer to be this tracer. The tracer can then run some
406 * internal tracing to verify that everything is in order.
407 * If we fail, we do not register this tracer.
408 */
409 for_each_possible_cpu(i) {
Steven Rostedt60a11772008-05-12 21:20:44 +0200410 data = tr->data[i];
Ingo Molnarc7aafc52008-05-12 21:20:45 +0200411 if (!head_page(data))
412 continue;
Steven Rostedt60a11772008-05-12 21:20:44 +0200413 tracing_reset(data);
414 }
415 current_trace = type;
416 tr->ctrl = 0;
417 /* the test is responsible for initializing and enabling */
418 pr_info("Testing tracer %s: ", type->name);
419 ret = type->selftest(type, tr);
420 /* the test is responsible for resetting too */
421 current_trace = saved_tracer;
422 tr->ctrl = saved_ctrl;
423 if (ret) {
424 printk(KERN_CONT "FAILED!\n");
425 goto out;
426 }
Steven Rostedt1d4db002008-05-12 21:20:45 +0200427 /* Only reset on passing, to avoid touching corrupted buffers */
428 for_each_possible_cpu(i) {
429 data = tr->data[i];
430 if (!head_page(data))
431 continue;
432 tracing_reset(data);
433 }
Steven Rostedt60a11772008-05-12 21:20:44 +0200434 printk(KERN_CONT "PASSED\n");
435 }
436#endif
437
Steven Rostedtbc0c38d2008-05-12 21:20:42 +0200438 type->next = trace_types;
439 trace_types = type;
440 len = strlen(type->name);
441 if (len > max_tracer_type_len)
442 max_tracer_type_len = len;
Steven Rostedt60a11772008-05-12 21:20:44 +0200443
Steven Rostedtbc0c38d2008-05-12 21:20:42 +0200444 out:
445 mutex_unlock(&trace_types_lock);
446
447 return ret;
448}
449
450void unregister_tracer(struct tracer *type)
451{
452 struct tracer **t;
453 int len;
454
455 mutex_lock(&trace_types_lock);
456 for (t = &trace_types; *t; t = &(*t)->next) {
457 if (*t == type)
458 goto found;
459 }
460 pr_info("Trace %s not registered\n", type->name);
461 goto out;
462
463 found:
464 *t = (*t)->next;
465 if (strlen(type->name) != max_tracer_type_len)
466 goto out;
467
468 max_tracer_type_len = 0;
469 for (t = &trace_types; *t; t = &(*t)->next) {
470 len = strlen((*t)->name);
471 if (len > max_tracer_type_len)
472 max_tracer_type_len = len;
473 }
474 out:
475 mutex_unlock(&trace_types_lock);
476}
477
Ingo Molnare309b412008-05-12 21:20:51 +0200478void tracing_reset(struct trace_array_cpu *data)
Steven Rostedtbc0c38d2008-05-12 21:20:42 +0200479{
480 data->trace_idx = 0;
Steven Rostedt93a588f2008-05-12 21:20:45 +0200481 data->trace_head = data->trace_tail = head_page(data);
482 data->trace_head_idx = 0;
483 data->trace_tail_idx = 0;
Steven Rostedtbc0c38d2008-05-12 21:20:42 +0200484}
485
Steven Rostedtbc0c38d2008-05-12 21:20:42 +0200486#define SAVED_CMDLINES 128
487static unsigned map_pid_to_cmdline[PID_MAX_DEFAULT+1];
488static unsigned map_cmdline_to_pid[SAVED_CMDLINES];
489static char saved_cmdlines[SAVED_CMDLINES][TASK_COMM_LEN];
490static int cmdline_idx;
491static DEFINE_SPINLOCK(trace_cmdline_lock);
492atomic_t trace_record_cmdline_disabled;
493
494static void trace_init_cmdlines(void)
495{
496 memset(&map_pid_to_cmdline, -1, sizeof(map_pid_to_cmdline));
497 memset(&map_cmdline_to_pid, -1, sizeof(map_cmdline_to_pid));
498 cmdline_idx = 0;
499}
500
Ingo Molnare309b412008-05-12 21:20:51 +0200501void trace_stop_cmdline_recording(void);
Steven Rostedtbc0c38d2008-05-12 21:20:42 +0200502
Ingo Molnare309b412008-05-12 21:20:51 +0200503static void trace_save_cmdline(struct task_struct *tsk)
Steven Rostedtbc0c38d2008-05-12 21:20:42 +0200504{
505 unsigned map;
506 unsigned idx;
507
508 if (!tsk->pid || unlikely(tsk->pid > PID_MAX_DEFAULT))
509 return;
510
511 /*
512 * It's not the end of the world if we don't get
513 * the lock, but we also don't want to spin
514 * nor do we want to disable interrupts,
515 * so if we miss here, then better luck next time.
516 */
517 if (!spin_trylock(&trace_cmdline_lock))
518 return;
519
520 idx = map_pid_to_cmdline[tsk->pid];
521 if (idx >= SAVED_CMDLINES) {
522 idx = (cmdline_idx + 1) % SAVED_CMDLINES;
523
524 map = map_cmdline_to_pid[idx];
525 if (map <= PID_MAX_DEFAULT)
526 map_pid_to_cmdline[map] = (unsigned)-1;
527
528 map_pid_to_cmdline[tsk->pid] = idx;
529
530 cmdline_idx = idx;
531 }
532
533 memcpy(&saved_cmdlines[idx], tsk->comm, TASK_COMM_LEN);
534
535 spin_unlock(&trace_cmdline_lock);
536}
537
Ingo Molnare309b412008-05-12 21:20:51 +0200538static char *trace_find_cmdline(int pid)
Steven Rostedtbc0c38d2008-05-12 21:20:42 +0200539{
540 char *cmdline = "<...>";
541 unsigned map;
542
543 if (!pid)
544 return "<idle>";
545
546 if (pid > PID_MAX_DEFAULT)
547 goto out;
548
549 map = map_pid_to_cmdline[pid];
550 if (map >= SAVED_CMDLINES)
551 goto out;
552
553 cmdline = saved_cmdlines[map];
554
555 out:
556 return cmdline;
557}
558
Ingo Molnare309b412008-05-12 21:20:51 +0200559void tracing_record_cmdline(struct task_struct *tsk)
Steven Rostedtbc0c38d2008-05-12 21:20:42 +0200560{
561 if (atomic_read(&trace_record_cmdline_disabled))
562 return;
563
564 trace_save_cmdline(tsk);
565}
566
Ingo Molnare309b412008-05-12 21:20:51 +0200567static inline struct list_head *
Steven Rostedt93a588f2008-05-12 21:20:45 +0200568trace_next_list(struct trace_array_cpu *data, struct list_head *next)
569{
570 /*
571 * Roundrobin - but skip the head (which is not a real page):
572 */
573 next = next->next;
574 if (unlikely(next == &data->trace_pages))
575 next = next->next;
576 BUG_ON(next == &data->trace_pages);
577
578 return next;
579}
580
Ingo Molnare309b412008-05-12 21:20:51 +0200581static inline void *
Steven Rostedt93a588f2008-05-12 21:20:45 +0200582trace_next_page(struct trace_array_cpu *data, void *addr)
583{
584 struct list_head *next;
585 struct page *page;
586
587 page = virt_to_page(addr);
588
589 next = trace_next_list(data, &page->lru);
590 page = list_entry(next, struct page, lru);
591
592 return page_address(page);
593}
594
Ingo Molnare309b412008-05-12 21:20:51 +0200595static inline struct trace_entry *
Ingo Molnarc7aafc52008-05-12 21:20:45 +0200596tracing_get_trace_entry(struct trace_array *tr, struct trace_array_cpu *data)
Steven Rostedtbc0c38d2008-05-12 21:20:42 +0200597{
598 unsigned long idx, idx_next;
599 struct trace_entry *entry;
600
Steven Rostedt4c11d7a2008-05-12 21:20:43 +0200601 data->trace_idx++;
Steven Rostedt93a588f2008-05-12 21:20:45 +0200602 idx = data->trace_head_idx;
Steven Rostedtbc0c38d2008-05-12 21:20:42 +0200603 idx_next = idx + 1;
604
Ingo Molnarc7aafc52008-05-12 21:20:45 +0200605 BUG_ON(idx * TRACE_ENTRY_SIZE >= PAGE_SIZE);
606
Steven Rostedt93a588f2008-05-12 21:20:45 +0200607 entry = data->trace_head + idx * TRACE_ENTRY_SIZE;
Steven Rostedt4c11d7a2008-05-12 21:20:43 +0200608
609 if (unlikely(idx_next >= ENTRIES_PER_PAGE)) {
Steven Rostedt93a588f2008-05-12 21:20:45 +0200610 data->trace_head = trace_next_page(data, data->trace_head);
Steven Rostedtbc0c38d2008-05-12 21:20:42 +0200611 idx_next = 0;
612 }
613
Steven Rostedt93a588f2008-05-12 21:20:45 +0200614 if (data->trace_head == data->trace_tail &&
615 idx_next == data->trace_tail_idx) {
616 /* overrun */
617 data->trace_tail_idx++;
618 if (data->trace_tail_idx >= ENTRIES_PER_PAGE) {
619 data->trace_tail =
620 trace_next_page(data, data->trace_tail);
621 data->trace_tail_idx = 0;
622 }
623 }
624
625 data->trace_head_idx = idx_next;
Steven Rostedtbc0c38d2008-05-12 21:20:42 +0200626
627 return entry;
628}
629
Ingo Molnare309b412008-05-12 21:20:51 +0200630static inline void
Ingo Molnarc7aafc52008-05-12 21:20:45 +0200631tracing_generic_entry_update(struct trace_entry *entry, unsigned long flags)
Steven Rostedtbc0c38d2008-05-12 21:20:42 +0200632{
633 struct task_struct *tsk = current;
634 unsigned long pc;
635
636 pc = preempt_count();
637
Ingo Molnarc7aafc52008-05-12 21:20:45 +0200638 entry->preempt_count = pc & 0xff;
639 entry->pid = tsk->pid;
Ingo Molnar750ed1a2008-05-12 21:20:46 +0200640 entry->t = ftrace_now(raw_smp_processor_id());
Steven Rostedtbc0c38d2008-05-12 21:20:42 +0200641 entry->flags = (irqs_disabled_flags(flags) ? TRACE_FLAG_IRQS_OFF : 0) |
642 ((pc & HARDIRQ_MASK) ? TRACE_FLAG_HARDIRQ : 0) |
643 ((pc & SOFTIRQ_MASK) ? TRACE_FLAG_SOFTIRQ : 0) |
644 (need_resched() ? TRACE_FLAG_NEED_RESCHED : 0);
645}
646
Ingo Molnare309b412008-05-12 21:20:51 +0200647void
Steven Rostedt6fb44b72008-05-12 21:20:49 +0200648trace_function(struct trace_array *tr, struct trace_array_cpu *data,
649 unsigned long ip, unsigned long parent_ip, unsigned long flags)
Steven Rostedtbc0c38d2008-05-12 21:20:42 +0200650{
651 struct trace_entry *entry;
Ingo Molnardcb63082008-05-12 21:20:48 +0200652 unsigned long irq_flags;
Steven Rostedtbc0c38d2008-05-12 21:20:42 +0200653
Ingo Molnardcb63082008-05-12 21:20:48 +0200654 spin_lock_irqsave(&data->lock, irq_flags);
Ingo Molnarc7aafc52008-05-12 21:20:45 +0200655 entry = tracing_get_trace_entry(tr, data);
Steven Rostedtbc0c38d2008-05-12 21:20:42 +0200656 tracing_generic_entry_update(entry, flags);
Ingo Molnarc7aafc52008-05-12 21:20:45 +0200657 entry->type = TRACE_FN;
658 entry->fn.ip = ip;
659 entry->fn.parent_ip = parent_ip;
Ingo Molnardcb63082008-05-12 21:20:48 +0200660 spin_unlock_irqrestore(&data->lock, irq_flags);
Ingo Molnar017730c2008-05-12 21:20:52 +0200661
662 trace_wake_up();
Steven Rostedtbc0c38d2008-05-12 21:20:42 +0200663}
664
Ingo Molnare309b412008-05-12 21:20:51 +0200665void
Ingo Molnar2e0f5762008-05-12 21:20:49 +0200666ftrace(struct trace_array *tr, struct trace_array_cpu *data,
667 unsigned long ip, unsigned long parent_ip, unsigned long flags)
668{
669 if (likely(!atomic_read(&data->disabled)))
Steven Rostedt6fb44b72008-05-12 21:20:49 +0200670 trace_function(tr, data, ip, parent_ip, flags);
Ingo Molnar2e0f5762008-05-12 21:20:49 +0200671}
672
Ingo Molnar4e655512008-05-12 21:20:52 +0200673#ifdef CONFIG_CONTEXT_SWITCH_TRACER
674
Ingo Molnare309b412008-05-12 21:20:51 +0200675void
Ingo Molnar4e655512008-05-12 21:20:52 +0200676__trace_special(void *__tr, void *__data,
677 unsigned long arg1, unsigned long arg2, unsigned long arg3)
Ingo Molnarf0a920d2008-05-12 21:20:47 +0200678{
Ingo Molnar4e655512008-05-12 21:20:52 +0200679 struct trace_array_cpu *data = __data;
680 struct trace_array *tr = __tr;
Ingo Molnarf0a920d2008-05-12 21:20:47 +0200681 struct trace_entry *entry;
Ingo Molnardcb63082008-05-12 21:20:48 +0200682 unsigned long irq_flags;
Ingo Molnarf0a920d2008-05-12 21:20:47 +0200683
Ingo Molnardcb63082008-05-12 21:20:48 +0200684 spin_lock_irqsave(&data->lock, irq_flags);
Ingo Molnarf0a920d2008-05-12 21:20:47 +0200685 entry = tracing_get_trace_entry(tr, data);
686 tracing_generic_entry_update(entry, 0);
687 entry->type = TRACE_SPECIAL;
688 entry->special.arg1 = arg1;
689 entry->special.arg2 = arg2;
690 entry->special.arg3 = arg3;
Ingo Molnardcb63082008-05-12 21:20:48 +0200691 spin_unlock_irqrestore(&data->lock, irq_flags);
Ingo Molnar017730c2008-05-12 21:20:52 +0200692
693 trace_wake_up();
Ingo Molnar86387f72008-05-12 21:20:51 +0200694}
695
Ingo Molnar4e655512008-05-12 21:20:52 +0200696#endif
697
Ingo Molnar86387f72008-05-12 21:20:51 +0200698void __trace_stack(struct trace_array *tr,
699 struct trace_array_cpu *data,
700 unsigned long flags,
701 int skip)
702{
703 struct trace_entry *entry;
704 struct stack_trace trace;
705
706 if (!(trace_flags & TRACE_ITER_STACKTRACE))
707 return;
708
709 entry = tracing_get_trace_entry(tr, data);
710 tracing_generic_entry_update(entry, flags);
711 entry->type = TRACE_STACK;
712
713 memset(&entry->stack, 0, sizeof(entry->stack));
714
715 trace.nr_entries = 0;
716 trace.max_entries = FTRACE_STACK_ENTRIES;
717 trace.skip = skip;
718 trace.entries = entry->stack.caller;
719
720 save_stack_trace(&trace);
Ingo Molnarf0a920d2008-05-12 21:20:47 +0200721}
722
Ingo Molnare309b412008-05-12 21:20:51 +0200723void
Steven Rostedtbc0c38d2008-05-12 21:20:42 +0200724tracing_sched_switch_trace(struct trace_array *tr,
725 struct trace_array_cpu *data,
Ingo Molnar86387f72008-05-12 21:20:51 +0200726 struct task_struct *prev,
727 struct task_struct *next,
Steven Rostedtbc0c38d2008-05-12 21:20:42 +0200728 unsigned long flags)
729{
730 struct trace_entry *entry;
Ingo Molnardcb63082008-05-12 21:20:48 +0200731 unsigned long irq_flags;
Steven Rostedtbc0c38d2008-05-12 21:20:42 +0200732
Ingo Molnardcb63082008-05-12 21:20:48 +0200733 spin_lock_irqsave(&data->lock, irq_flags);
Ingo Molnarc7aafc52008-05-12 21:20:45 +0200734 entry = tracing_get_trace_entry(tr, data);
Steven Rostedtbc0c38d2008-05-12 21:20:42 +0200735 tracing_generic_entry_update(entry, flags);
736 entry->type = TRACE_CTX;
737 entry->ctx.prev_pid = prev->pid;
738 entry->ctx.prev_prio = prev->prio;
739 entry->ctx.prev_state = prev->state;
740 entry->ctx.next_pid = next->pid;
741 entry->ctx.next_prio = next->prio;
Ingo Molnar86387f72008-05-12 21:20:51 +0200742 __trace_stack(tr, data, flags, 4);
Ingo Molnardcb63082008-05-12 21:20:48 +0200743 spin_unlock_irqrestore(&data->lock, irq_flags);
Steven Rostedtbc0c38d2008-05-12 21:20:42 +0200744}
745
Ingo Molnar57422792008-05-12 21:20:51 +0200746void
747tracing_sched_wakeup_trace(struct trace_array *tr,
748 struct trace_array_cpu *data,
Ingo Molnar86387f72008-05-12 21:20:51 +0200749 struct task_struct *wakee,
750 struct task_struct *curr,
Ingo Molnar57422792008-05-12 21:20:51 +0200751 unsigned long flags)
752{
753 struct trace_entry *entry;
754 unsigned long irq_flags;
755
756 spin_lock_irqsave(&data->lock, irq_flags);
757 entry = tracing_get_trace_entry(tr, data);
758 tracing_generic_entry_update(entry, flags);
759 entry->type = TRACE_WAKE;
760 entry->ctx.prev_pid = curr->pid;
761 entry->ctx.prev_prio = curr->prio;
762 entry->ctx.prev_state = curr->state;
763 entry->ctx.next_pid = wakee->pid;
764 entry->ctx.next_prio = wakee->prio;
Ingo Molnar86387f72008-05-12 21:20:51 +0200765 __trace_stack(tr, data, flags, 5);
Ingo Molnar57422792008-05-12 21:20:51 +0200766 spin_unlock_irqrestore(&data->lock, irq_flags);
Ingo Molnar017730c2008-05-12 21:20:52 +0200767
768 trace_wake_up();
Ingo Molnar57422792008-05-12 21:20:51 +0200769}
770
Ingo Molnar2e0f5762008-05-12 21:20:49 +0200771#ifdef CONFIG_FTRACE
Ingo Molnare309b412008-05-12 21:20:51 +0200772static void
Ingo Molnar2e0f5762008-05-12 21:20:49 +0200773function_trace_call(unsigned long ip, unsigned long parent_ip)
774{
775 struct trace_array *tr = &global_trace;
776 struct trace_array_cpu *data;
777 unsigned long flags;
778 long disabled;
779 int cpu;
780
781 if (unlikely(!tracer_enabled))
782 return;
783
784 local_irq_save(flags);
785 cpu = raw_smp_processor_id();
786 data = tr->data[cpu];
787 disabled = atomic_inc_return(&data->disabled);
788
789 if (likely(disabled == 1))
Steven Rostedt6fb44b72008-05-12 21:20:49 +0200790 trace_function(tr, data, ip, parent_ip, flags);
Ingo Molnar2e0f5762008-05-12 21:20:49 +0200791
792 atomic_dec(&data->disabled);
793 local_irq_restore(flags);
794}
795
796static struct ftrace_ops trace_ops __read_mostly =
797{
798 .func = function_trace_call,
799};
800
Ingo Molnare309b412008-05-12 21:20:51 +0200801void tracing_start_function_trace(void)
Ingo Molnar2e0f5762008-05-12 21:20:49 +0200802{
803 register_ftrace_function(&trace_ops);
804}
805
Ingo Molnare309b412008-05-12 21:20:51 +0200806void tracing_stop_function_trace(void)
Ingo Molnar2e0f5762008-05-12 21:20:49 +0200807{
808 unregister_ftrace_function(&trace_ops);
809}
810#endif
811
Steven Rostedtbc0c38d2008-05-12 21:20:42 +0200812enum trace_file_type {
813 TRACE_FILE_LAT_FMT = 1,
814};
815
816static struct trace_entry *
Steven Rostedt4c11d7a2008-05-12 21:20:43 +0200817trace_entry_idx(struct trace_array *tr, struct trace_array_cpu *data,
818 struct trace_iterator *iter, int cpu)
Steven Rostedtbc0c38d2008-05-12 21:20:42 +0200819{
Steven Rostedt4c11d7a2008-05-12 21:20:43 +0200820 struct page *page;
821 struct trace_entry *array;
Steven Rostedtbc0c38d2008-05-12 21:20:42 +0200822
Steven Rostedt4c11d7a2008-05-12 21:20:43 +0200823 if (iter->next_idx[cpu] >= tr->entries ||
Steven Rostedtb3806b42008-05-12 21:20:46 +0200824 iter->next_idx[cpu] >= data->trace_idx ||
825 (data->trace_head == data->trace_tail &&
826 data->trace_head_idx == data->trace_tail_idx))
Steven Rostedtbc0c38d2008-05-12 21:20:42 +0200827 return NULL;
828
Steven Rostedt4c11d7a2008-05-12 21:20:43 +0200829 if (!iter->next_page[cpu]) {
Steven Rostedt93a588f2008-05-12 21:20:45 +0200830 /* Initialize the iterator for this cpu trace buffer */
831 WARN_ON(!data->trace_tail);
832 page = virt_to_page(data->trace_tail);
833 iter->next_page[cpu] = &page->lru;
834 iter->next_page_idx[cpu] = data->trace_tail_idx;
Steven Rostedt4c11d7a2008-05-12 21:20:43 +0200835 }
Steven Rostedtbc0c38d2008-05-12 21:20:42 +0200836
Steven Rostedt4c11d7a2008-05-12 21:20:43 +0200837 page = list_entry(iter->next_page[cpu], struct page, lru);
Ingo Molnarc7aafc52008-05-12 21:20:45 +0200838 BUG_ON(&data->trace_pages == &page->lru);
839
Steven Rostedt4c11d7a2008-05-12 21:20:43 +0200840 array = page_address(page);
841
Steven Rostedt93a588f2008-05-12 21:20:45 +0200842 WARN_ON(iter->next_page_idx[cpu] >= ENTRIES_PER_PAGE);
Steven Rostedt4c11d7a2008-05-12 21:20:43 +0200843 return &array[iter->next_page_idx[cpu]];
Steven Rostedtbc0c38d2008-05-12 21:20:42 +0200844}
845
Ingo Molnare309b412008-05-12 21:20:51 +0200846static struct trace_entry *
Steven Rostedtbc0c38d2008-05-12 21:20:42 +0200847find_next_entry(struct trace_iterator *iter, int *ent_cpu)
848{
849 struct trace_array *tr = iter->tr;
850 struct trace_entry *ent, *next = NULL;
851 int next_cpu = -1;
852 int cpu;
853
854 for_each_possible_cpu(cpu) {
Ingo Molnarc7aafc52008-05-12 21:20:45 +0200855 if (!head_page(tr->data[cpu]))
Steven Rostedtbc0c38d2008-05-12 21:20:42 +0200856 continue;
Steven Rostedt4c11d7a2008-05-12 21:20:43 +0200857 ent = trace_entry_idx(tr, tr->data[cpu], iter, cpu);
Ingo Molnarcdd31cd2008-05-12 21:20:46 +0200858 /*
859 * Pick the entry with the smallest timestamp:
860 */
861 if (ent && (!next || ent->t < next->t)) {
Steven Rostedtbc0c38d2008-05-12 21:20:42 +0200862 next = ent;
863 next_cpu = cpu;
864 }
865 }
866
867 if (ent_cpu)
868 *ent_cpu = next_cpu;
869
870 return next;
871}
872
Ingo Molnare309b412008-05-12 21:20:51 +0200873static void trace_iterator_increment(struct trace_iterator *iter)
Steven Rostedtb3806b42008-05-12 21:20:46 +0200874{
875 iter->idx++;
876 iter->next_idx[iter->cpu]++;
877 iter->next_page_idx[iter->cpu]++;
Ingo Molnar8c523a92008-05-12 21:20:46 +0200878
Steven Rostedtb3806b42008-05-12 21:20:46 +0200879 if (iter->next_page_idx[iter->cpu] >= ENTRIES_PER_PAGE) {
880 struct trace_array_cpu *data = iter->tr->data[iter->cpu];
881
882 iter->next_page_idx[iter->cpu] = 0;
883 iter->next_page[iter->cpu] =
884 trace_next_list(data, iter->next_page[iter->cpu]);
885 }
886}
887
Ingo Molnare309b412008-05-12 21:20:51 +0200888static void trace_consume(struct trace_iterator *iter)
Steven Rostedtb3806b42008-05-12 21:20:46 +0200889{
890 struct trace_array_cpu *data = iter->tr->data[iter->cpu];
891
892 data->trace_tail_idx++;
893 if (data->trace_tail_idx >= ENTRIES_PER_PAGE) {
894 data->trace_tail = trace_next_page(data, data->trace_tail);
895 data->trace_tail_idx = 0;
896 }
897
898 /* Check if we empty it, then reset the index */
899 if (data->trace_head == data->trace_tail &&
900 data->trace_head_idx == data->trace_tail_idx)
901 data->trace_idx = 0;
Steven Rostedtb3806b42008-05-12 21:20:46 +0200902}
903
Ingo Molnare309b412008-05-12 21:20:51 +0200904static void *find_next_entry_inc(struct trace_iterator *iter)
Steven Rostedtbc0c38d2008-05-12 21:20:42 +0200905{
906 struct trace_entry *next;
907 int next_cpu = -1;
908
909 next = find_next_entry(iter, &next_cpu);
910
Ingo Molnar4e3c3332008-05-12 21:20:45 +0200911 iter->prev_ent = iter->ent;
912 iter->prev_cpu = iter->cpu;
913
Steven Rostedtbc0c38d2008-05-12 21:20:42 +0200914 iter->ent = next;
915 iter->cpu = next_cpu;
916
Steven Rostedtb3806b42008-05-12 21:20:46 +0200917 if (next)
918 trace_iterator_increment(iter);
919
Steven Rostedtbc0c38d2008-05-12 21:20:42 +0200920 return next ? iter : NULL;
921}
922
Ingo Molnare309b412008-05-12 21:20:51 +0200923static void *s_next(struct seq_file *m, void *v, loff_t *pos)
Steven Rostedtbc0c38d2008-05-12 21:20:42 +0200924{
925 struct trace_iterator *iter = m->private;
Steven Rostedtbc0c38d2008-05-12 21:20:42 +0200926 void *last_ent = iter->ent;
927 int i = (int)*pos;
Ingo Molnar4e3c3332008-05-12 21:20:45 +0200928 void *ent;
Steven Rostedtbc0c38d2008-05-12 21:20:42 +0200929
930 (*pos)++;
931
932 /* can't go backwards */
933 if (iter->idx > i)
934 return NULL;
935
936 if (iter->idx < 0)
937 ent = find_next_entry_inc(iter);
938 else
939 ent = iter;
940
941 while (ent && iter->idx < i)
942 ent = find_next_entry_inc(iter);
943
944 iter->pos = *pos;
945
946 if (last_ent && !ent)
947 seq_puts(m, "\n\nvim:ft=help\n");
948
949 return ent;
950}
951
952static void *s_start(struct seq_file *m, loff_t *pos)
953{
954 struct trace_iterator *iter = m->private;
955 void *p = NULL;
956 loff_t l = 0;
957 int i;
958
959 mutex_lock(&trace_types_lock);
960
961 if (!current_trace || current_trace != iter->trace)
962 return NULL;
963
964 atomic_inc(&trace_record_cmdline_disabled);
965
966 /* let the tracer grab locks here if needed */
967 if (current_trace->start)
968 current_trace->start(iter);
969
970 if (*pos != iter->pos) {
971 iter->ent = NULL;
972 iter->cpu = 0;
973 iter->idx = -1;
Ingo Molnar4e3c3332008-05-12 21:20:45 +0200974 iter->prev_ent = NULL;
975 iter->prev_cpu = -1;
Steven Rostedtbc0c38d2008-05-12 21:20:42 +0200976
Steven Rostedt4c11d7a2008-05-12 21:20:43 +0200977 for_each_possible_cpu(i) {
Steven Rostedtbc0c38d2008-05-12 21:20:42 +0200978 iter->next_idx[i] = 0;
Steven Rostedt4c11d7a2008-05-12 21:20:43 +0200979 iter->next_page[i] = NULL;
980 }
Steven Rostedtbc0c38d2008-05-12 21:20:42 +0200981
982 for (p = iter; p && l < *pos; p = s_next(m, p, &l))
983 ;
984
985 } else {
Steven Rostedt4c11d7a2008-05-12 21:20:43 +0200986 l = *pos - 1;
Steven Rostedtbc0c38d2008-05-12 21:20:42 +0200987 p = s_next(m, p, &l);
988 }
989
990 return p;
991}
992
993static void s_stop(struct seq_file *m, void *p)
994{
995 struct trace_iterator *iter = m->private;
996
997 atomic_dec(&trace_record_cmdline_disabled);
998
999 /* let the tracer release locks here if needed */
1000 if (current_trace && current_trace == iter->trace && iter->trace->stop)
1001 iter->trace->stop(iter);
1002
1003 mutex_unlock(&trace_types_lock);
1004}
1005
Steven Rostedtb3806b42008-05-12 21:20:46 +02001006static int
Steven Rostedt214023c2008-05-12 21:20:46 +02001007seq_print_sym_short(struct trace_seq *s, const char *fmt, unsigned long address)
Steven Rostedtbc0c38d2008-05-12 21:20:42 +02001008{
1009#ifdef CONFIG_KALLSYMS
1010 char str[KSYM_SYMBOL_LEN];
1011
1012 kallsyms_lookup(address, NULL, NULL, NULL, str);
1013
Steven Rostedtb3806b42008-05-12 21:20:46 +02001014 return trace_seq_printf(s, fmt, str);
Steven Rostedtbc0c38d2008-05-12 21:20:42 +02001015#endif
Steven Rostedtb3806b42008-05-12 21:20:46 +02001016 return 1;
Steven Rostedtbc0c38d2008-05-12 21:20:42 +02001017}
1018
Steven Rostedtb3806b42008-05-12 21:20:46 +02001019static int
Steven Rostedt214023c2008-05-12 21:20:46 +02001020seq_print_sym_offset(struct trace_seq *s, const char *fmt,
1021 unsigned long address)
Steven Rostedtbc0c38d2008-05-12 21:20:42 +02001022{
1023#ifdef CONFIG_KALLSYMS
1024 char str[KSYM_SYMBOL_LEN];
1025
1026 sprint_symbol(str, address);
Steven Rostedtb3806b42008-05-12 21:20:46 +02001027 return trace_seq_printf(s, fmt, str);
Steven Rostedtbc0c38d2008-05-12 21:20:42 +02001028#endif
Steven Rostedtb3806b42008-05-12 21:20:46 +02001029 return 1;
Steven Rostedtbc0c38d2008-05-12 21:20:42 +02001030}
1031
1032#ifndef CONFIG_64BIT
1033# define IP_FMT "%08lx"
1034#else
1035# define IP_FMT "%016lx"
1036#endif
1037
Ingo Molnare309b412008-05-12 21:20:51 +02001038static int
Steven Rostedt214023c2008-05-12 21:20:46 +02001039seq_print_ip_sym(struct trace_seq *s, unsigned long ip, unsigned long sym_flags)
Steven Rostedtbc0c38d2008-05-12 21:20:42 +02001040{
Steven Rostedtb3806b42008-05-12 21:20:46 +02001041 int ret;
1042
1043 if (!ip)
1044 return trace_seq_printf(s, "0");
Steven Rostedtbc0c38d2008-05-12 21:20:42 +02001045
1046 if (sym_flags & TRACE_ITER_SYM_OFFSET)
Steven Rostedtb3806b42008-05-12 21:20:46 +02001047 ret = seq_print_sym_offset(s, "%s", ip);
Steven Rostedtbc0c38d2008-05-12 21:20:42 +02001048 else
Steven Rostedtb3806b42008-05-12 21:20:46 +02001049 ret = seq_print_sym_short(s, "%s", ip);
1050
1051 if (!ret)
1052 return 0;
Steven Rostedtbc0c38d2008-05-12 21:20:42 +02001053
1054 if (sym_flags & TRACE_ITER_SYM_ADDR)
Steven Rostedtb3806b42008-05-12 21:20:46 +02001055 ret = trace_seq_printf(s, " <" IP_FMT ">", ip);
1056 return ret;
Steven Rostedtbc0c38d2008-05-12 21:20:42 +02001057}
1058
Ingo Molnare309b412008-05-12 21:20:51 +02001059static void print_lat_help_header(struct seq_file *m)
Steven Rostedtbc0c38d2008-05-12 21:20:42 +02001060{
1061 seq_puts(m, "# _------=> CPU# \n");
1062 seq_puts(m, "# / _-----=> irqs-off \n");
1063 seq_puts(m, "# | / _----=> need-resched \n");
1064 seq_puts(m, "# || / _---=> hardirq/softirq \n");
1065 seq_puts(m, "# ||| / _--=> preempt-depth \n");
1066 seq_puts(m, "# |||| / \n");
1067 seq_puts(m, "# ||||| delay \n");
1068 seq_puts(m, "# cmd pid ||||| time | caller \n");
1069 seq_puts(m, "# \\ / ||||| \\ | / \n");
1070}
1071
Ingo Molnare309b412008-05-12 21:20:51 +02001072static void print_func_help_header(struct seq_file *m)
Steven Rostedtbc0c38d2008-05-12 21:20:42 +02001073{
1074 seq_puts(m, "# TASK-PID CPU# TIMESTAMP FUNCTION\n");
1075 seq_puts(m, "# | | | | |\n");
1076}
1077
1078
Ingo Molnare309b412008-05-12 21:20:51 +02001079static void
Steven Rostedtbc0c38d2008-05-12 21:20:42 +02001080print_trace_header(struct seq_file *m, struct trace_iterator *iter)
1081{
1082 unsigned long sym_flags = (trace_flags & TRACE_ITER_SYM_MASK);
1083 struct trace_array *tr = iter->tr;
1084 struct trace_array_cpu *data = tr->data[tr->cpu];
1085 struct tracer *type = current_trace;
Steven Rostedt4c11d7a2008-05-12 21:20:43 +02001086 unsigned long total = 0;
1087 unsigned long entries = 0;
Steven Rostedtbc0c38d2008-05-12 21:20:42 +02001088 int cpu;
1089 const char *name = "preemption";
1090
1091 if (type)
1092 name = type->name;
1093
1094 for_each_possible_cpu(cpu) {
Ingo Molnarc7aafc52008-05-12 21:20:45 +02001095 if (head_page(tr->data[cpu])) {
Steven Rostedt4c11d7a2008-05-12 21:20:43 +02001096 total += tr->data[cpu]->trace_idx;
1097 if (tr->data[cpu]->trace_idx > tr->entries)
Steven Rostedtbc0c38d2008-05-12 21:20:42 +02001098 entries += tr->entries;
Steven Rostedt4c11d7a2008-05-12 21:20:43 +02001099 else
Steven Rostedtbc0c38d2008-05-12 21:20:42 +02001100 entries += tr->data[cpu]->trace_idx;
1101 }
1102 }
1103
1104 seq_printf(m, "%s latency trace v1.1.5 on %s\n",
1105 name, UTS_RELEASE);
1106 seq_puts(m, "-----------------------------------"
1107 "---------------------------------\n");
1108 seq_printf(m, " latency: %lu us, #%lu/%lu, CPU#%d |"
1109 " (M:%s VP:%d, KP:%d, SP:%d HP:%d",
Steven Rostedt57f50be2008-05-12 21:20:44 +02001110 nsecs_to_usecs(data->saved_latency),
Steven Rostedtbc0c38d2008-05-12 21:20:42 +02001111 entries,
Steven Rostedt4c11d7a2008-05-12 21:20:43 +02001112 total,
Steven Rostedtbc0c38d2008-05-12 21:20:42 +02001113 tr->cpu,
1114#if defined(CONFIG_PREEMPT_NONE)
1115 "server",
1116#elif defined(CONFIG_PREEMPT_VOLUNTARY)
1117 "desktop",
1118#elif defined(CONFIG_PREEMPT_DESKTOP)
1119 "preempt",
1120#else
1121 "unknown",
1122#endif
1123 /* These are reserved for later use */
1124 0, 0, 0, 0);
1125#ifdef CONFIG_SMP
1126 seq_printf(m, " #P:%d)\n", num_online_cpus());
1127#else
1128 seq_puts(m, ")\n");
1129#endif
1130 seq_puts(m, " -----------------\n");
1131 seq_printf(m, " | task: %.16s-%d "
1132 "(uid:%d nice:%ld policy:%ld rt_prio:%ld)\n",
1133 data->comm, data->pid, data->uid, data->nice,
1134 data->policy, data->rt_priority);
1135 seq_puts(m, " -----------------\n");
1136
1137 if (data->critical_start) {
1138 seq_puts(m, " => started at: ");
Steven Rostedt214023c2008-05-12 21:20:46 +02001139 seq_print_ip_sym(&iter->seq, data->critical_start, sym_flags);
1140 trace_print_seq(m, &iter->seq);
Steven Rostedtbc0c38d2008-05-12 21:20:42 +02001141 seq_puts(m, "\n => ended at: ");
Steven Rostedt214023c2008-05-12 21:20:46 +02001142 seq_print_ip_sym(&iter->seq, data->critical_end, sym_flags);
1143 trace_print_seq(m, &iter->seq);
Steven Rostedtbc0c38d2008-05-12 21:20:42 +02001144 seq_puts(m, "\n");
1145 }
1146
1147 seq_puts(m, "\n");
1148}
1149
Ingo Molnare309b412008-05-12 21:20:51 +02001150static void
Steven Rostedt214023c2008-05-12 21:20:46 +02001151lat_print_generic(struct trace_seq *s, struct trace_entry *entry, int cpu)
Steven Rostedtbc0c38d2008-05-12 21:20:42 +02001152{
1153 int hardirq, softirq;
1154 char *comm;
1155
1156 comm = trace_find_cmdline(entry->pid);
1157
Steven Rostedt214023c2008-05-12 21:20:46 +02001158 trace_seq_printf(s, "%8.8s-%-5d ", comm, entry->pid);
1159 trace_seq_printf(s, "%d", cpu);
1160 trace_seq_printf(s, "%c%c",
1161 (entry->flags & TRACE_FLAG_IRQS_OFF) ? 'd' : '.',
1162 ((entry->flags & TRACE_FLAG_NEED_RESCHED) ? 'N' : '.'));
Steven Rostedtbc0c38d2008-05-12 21:20:42 +02001163
1164 hardirq = entry->flags & TRACE_FLAG_HARDIRQ;
1165 softirq = entry->flags & TRACE_FLAG_SOFTIRQ;
1166 if (hardirq && softirq)
Steven Rostedt214023c2008-05-12 21:20:46 +02001167 trace_seq_putc(s, 'H');
Steven Rostedtbc0c38d2008-05-12 21:20:42 +02001168 else {
1169 if (hardirq)
Steven Rostedt214023c2008-05-12 21:20:46 +02001170 trace_seq_putc(s, 'h');
Steven Rostedtbc0c38d2008-05-12 21:20:42 +02001171 else {
1172 if (softirq)
Steven Rostedt214023c2008-05-12 21:20:46 +02001173 trace_seq_putc(s, 's');
Steven Rostedtbc0c38d2008-05-12 21:20:42 +02001174 else
Steven Rostedt214023c2008-05-12 21:20:46 +02001175 trace_seq_putc(s, '.');
Steven Rostedtbc0c38d2008-05-12 21:20:42 +02001176 }
1177 }
1178
1179 if (entry->preempt_count)
Steven Rostedt214023c2008-05-12 21:20:46 +02001180 trace_seq_printf(s, "%x", entry->preempt_count);
Steven Rostedtbc0c38d2008-05-12 21:20:42 +02001181 else
Steven Rostedt214023c2008-05-12 21:20:46 +02001182 trace_seq_puts(s, ".");
Steven Rostedtbc0c38d2008-05-12 21:20:42 +02001183}
1184
1185unsigned long preempt_mark_thresh = 100;
1186
Ingo Molnare309b412008-05-12 21:20:51 +02001187static void
Steven Rostedt214023c2008-05-12 21:20:46 +02001188lat_print_timestamp(struct trace_seq *s, unsigned long long abs_usecs,
Steven Rostedtbc0c38d2008-05-12 21:20:42 +02001189 unsigned long rel_usecs)
1190{
Steven Rostedt214023c2008-05-12 21:20:46 +02001191 trace_seq_printf(s, " %4lldus", abs_usecs);
Steven Rostedtbc0c38d2008-05-12 21:20:42 +02001192 if (rel_usecs > preempt_mark_thresh)
Steven Rostedt214023c2008-05-12 21:20:46 +02001193 trace_seq_puts(s, "!: ");
Steven Rostedtbc0c38d2008-05-12 21:20:42 +02001194 else if (rel_usecs > 1)
Steven Rostedt214023c2008-05-12 21:20:46 +02001195 trace_seq_puts(s, "+: ");
Steven Rostedtbc0c38d2008-05-12 21:20:42 +02001196 else
Steven Rostedt214023c2008-05-12 21:20:46 +02001197 trace_seq_puts(s, " : ");
Steven Rostedtbc0c38d2008-05-12 21:20:42 +02001198}
1199
1200static const char state_to_char[] = TASK_STATE_TO_CHAR_STR;
1201
Ingo Molnare309b412008-05-12 21:20:51 +02001202static int
Steven Rostedt214023c2008-05-12 21:20:46 +02001203print_lat_fmt(struct trace_iterator *iter, unsigned int trace_idx, int cpu)
Steven Rostedtbc0c38d2008-05-12 21:20:42 +02001204{
Steven Rostedt214023c2008-05-12 21:20:46 +02001205 struct trace_seq *s = &iter->seq;
Steven Rostedtbc0c38d2008-05-12 21:20:42 +02001206 unsigned long sym_flags = (trace_flags & TRACE_ITER_SYM_MASK);
1207 struct trace_entry *next_entry = find_next_entry(iter, NULL);
1208 unsigned long verbose = (trace_flags & TRACE_ITER_VERBOSE);
1209 struct trace_entry *entry = iter->ent;
1210 unsigned long abs_usecs;
1211 unsigned long rel_usecs;
1212 char *comm;
1213 int S;
Ingo Molnar86387f72008-05-12 21:20:51 +02001214 int i;
Steven Rostedtbc0c38d2008-05-12 21:20:42 +02001215
1216 if (!next_entry)
1217 next_entry = entry;
1218 rel_usecs = ns2usecs(next_entry->t - entry->t);
1219 abs_usecs = ns2usecs(entry->t - iter->tr->time_start);
1220
1221 if (verbose) {
1222 comm = trace_find_cmdline(entry->pid);
Steven Rostedt214023c2008-05-12 21:20:46 +02001223 trace_seq_printf(s, "%16s %5d %d %d %08x %08x [%08lx]"
1224 " %ld.%03ldms (+%ld.%03ldms): ",
1225 comm,
1226 entry->pid, cpu, entry->flags,
1227 entry->preempt_count, trace_idx,
1228 ns2usecs(entry->t),
1229 abs_usecs/1000,
1230 abs_usecs % 1000, rel_usecs/1000,
1231 rel_usecs % 1000);
Steven Rostedtbc0c38d2008-05-12 21:20:42 +02001232 } else {
Ingo Molnar86387f72008-05-12 21:20:51 +02001233 if (entry->type != TRACE_STACK) {
1234 lat_print_generic(s, entry, cpu);
1235 lat_print_timestamp(s, abs_usecs, rel_usecs);
1236 }
Steven Rostedtbc0c38d2008-05-12 21:20:42 +02001237 }
1238 switch (entry->type) {
1239 case TRACE_FN:
Steven Rostedt214023c2008-05-12 21:20:46 +02001240 seq_print_ip_sym(s, entry->fn.ip, sym_flags);
1241 trace_seq_puts(s, " (");
1242 seq_print_ip_sym(s, entry->fn.parent_ip, sym_flags);
1243 trace_seq_puts(s, ")\n");
Steven Rostedtbc0c38d2008-05-12 21:20:42 +02001244 break;
1245 case TRACE_CTX:
Ingo Molnar57422792008-05-12 21:20:51 +02001246 case TRACE_WAKE:
Steven Rostedtbc0c38d2008-05-12 21:20:42 +02001247 S = entry->ctx.prev_state < sizeof(state_to_char) ?
1248 state_to_char[entry->ctx.prev_state] : 'X';
1249 comm = trace_find_cmdline(entry->ctx.next_pid);
Ingo Molnar57422792008-05-12 21:20:51 +02001250 trace_seq_printf(s, " %5d:%3d:%c %s %5d:%3d %s\n",
Steven Rostedt214023c2008-05-12 21:20:46 +02001251 entry->ctx.prev_pid,
1252 entry->ctx.prev_prio,
Ingo Molnar57422792008-05-12 21:20:51 +02001253 S, entry->type == TRACE_CTX ? "==>" : " +",
Steven Rostedt214023c2008-05-12 21:20:46 +02001254 entry->ctx.next_pid,
1255 entry->ctx.next_prio,
1256 comm);
Steven Rostedtbc0c38d2008-05-12 21:20:42 +02001257 break;
Ingo Molnarf0a920d2008-05-12 21:20:47 +02001258 case TRACE_SPECIAL:
Ingo Molnar4e655512008-05-12 21:20:52 +02001259 trace_seq_printf(s, " %ld %ld %ld\n",
Ingo Molnarf0a920d2008-05-12 21:20:47 +02001260 entry->special.arg1,
1261 entry->special.arg2,
1262 entry->special.arg3);
1263 break;
Ingo Molnar86387f72008-05-12 21:20:51 +02001264 case TRACE_STACK:
1265 for (i = 0; i < FTRACE_STACK_ENTRIES; i++) {
1266 if (i)
1267 trace_seq_puts(s, " <= ");
1268 seq_print_ip_sym(s, entry->stack.caller[i], sym_flags);
1269 }
1270 trace_seq_puts(s, "\n");
1271 break;
Steven Rostedt89b2f972008-05-12 21:20:44 +02001272 default:
Steven Rostedt214023c2008-05-12 21:20:46 +02001273 trace_seq_printf(s, "Unknown type %d\n", entry->type);
Steven Rostedtbc0c38d2008-05-12 21:20:42 +02001274 }
Ingo Molnarf9896bf2008-05-12 21:20:47 +02001275 return 1;
Steven Rostedtbc0c38d2008-05-12 21:20:42 +02001276}
1277
Ingo Molnare309b412008-05-12 21:20:51 +02001278static int print_trace_fmt(struct trace_iterator *iter)
Steven Rostedtbc0c38d2008-05-12 21:20:42 +02001279{
Steven Rostedt214023c2008-05-12 21:20:46 +02001280 struct trace_seq *s = &iter->seq;
Steven Rostedtbc0c38d2008-05-12 21:20:42 +02001281 unsigned long sym_flags = (trace_flags & TRACE_ITER_SYM_MASK);
Ingo Molnar4e3c3332008-05-12 21:20:45 +02001282 struct trace_entry *entry;
Steven Rostedtbc0c38d2008-05-12 21:20:42 +02001283 unsigned long usec_rem;
1284 unsigned long long t;
1285 unsigned long secs;
1286 char *comm;
Steven Rostedtb3806b42008-05-12 21:20:46 +02001287 int ret;
Ingo Molnar86387f72008-05-12 21:20:51 +02001288 int S;
1289 int i;
Steven Rostedtbc0c38d2008-05-12 21:20:42 +02001290
Ingo Molnar4e3c3332008-05-12 21:20:45 +02001291 entry = iter->ent;
1292
Steven Rostedtbc0c38d2008-05-12 21:20:42 +02001293 comm = trace_find_cmdline(iter->ent->pid);
1294
Ingo Molnarcdd31cd2008-05-12 21:20:46 +02001295 t = ns2usecs(entry->t);
Steven Rostedtbc0c38d2008-05-12 21:20:42 +02001296 usec_rem = do_div(t, 1000000ULL);
1297 secs = (unsigned long)t;
1298
Ingo Molnar86387f72008-05-12 21:20:51 +02001299 if (entry->type != TRACE_STACK) {
1300 ret = trace_seq_printf(s, "%16s-%-5d ", comm, entry->pid);
1301 if (!ret)
1302 return 0;
1303 ret = trace_seq_printf(s, "[%02d] ", iter->cpu);
1304 if (!ret)
1305 return 0;
1306 ret = trace_seq_printf(s, "%5lu.%06lu: ", secs, usec_rem);
1307 if (!ret)
1308 return 0;
1309 }
Steven Rostedtbc0c38d2008-05-12 21:20:42 +02001310
1311 switch (entry->type) {
1312 case TRACE_FN:
Steven Rostedtb3806b42008-05-12 21:20:46 +02001313 ret = seq_print_ip_sym(s, entry->fn.ip, sym_flags);
1314 if (!ret)
1315 return 0;
Steven Rostedtbc0c38d2008-05-12 21:20:42 +02001316 if ((sym_flags & TRACE_ITER_PRINT_PARENT) &&
1317 entry->fn.parent_ip) {
Steven Rostedtb3806b42008-05-12 21:20:46 +02001318 ret = trace_seq_printf(s, " <-");
1319 if (!ret)
1320 return 0;
1321 ret = seq_print_ip_sym(s, entry->fn.parent_ip,
1322 sym_flags);
1323 if (!ret)
1324 return 0;
Steven Rostedtbc0c38d2008-05-12 21:20:42 +02001325 }
Steven Rostedtb3806b42008-05-12 21:20:46 +02001326 ret = trace_seq_printf(s, "\n");
1327 if (!ret)
1328 return 0;
Steven Rostedtbc0c38d2008-05-12 21:20:42 +02001329 break;
1330 case TRACE_CTX:
Ingo Molnar57422792008-05-12 21:20:51 +02001331 case TRACE_WAKE:
Steven Rostedtbc0c38d2008-05-12 21:20:42 +02001332 S = entry->ctx.prev_state < sizeof(state_to_char) ?
1333 state_to_char[entry->ctx.prev_state] : 'X';
Ingo Molnar57422792008-05-12 21:20:51 +02001334 ret = trace_seq_printf(s, " %5d:%3d:%c %s %5d:%3d\n",
Steven Rostedtb3806b42008-05-12 21:20:46 +02001335 entry->ctx.prev_pid,
1336 entry->ctx.prev_prio,
1337 S,
Ingo Molnar57422792008-05-12 21:20:51 +02001338 entry->type == TRACE_CTX ? "==>" : " +",
Steven Rostedtb3806b42008-05-12 21:20:46 +02001339 entry->ctx.next_pid,
1340 entry->ctx.next_prio);
1341 if (!ret)
1342 return 0;
Steven Rostedtbc0c38d2008-05-12 21:20:42 +02001343 break;
Ingo Molnarf0a920d2008-05-12 21:20:47 +02001344 case TRACE_SPECIAL:
Ingo Molnar4e655512008-05-12 21:20:52 +02001345 ret = trace_seq_printf(s, " %ld %ld %ld\n",
Ingo Molnarf0a920d2008-05-12 21:20:47 +02001346 entry->special.arg1,
1347 entry->special.arg2,
1348 entry->special.arg3);
1349 if (!ret)
1350 return 0;
1351 break;
Ingo Molnar86387f72008-05-12 21:20:51 +02001352 case TRACE_STACK:
1353 for (i = 0; i < FTRACE_STACK_ENTRIES; i++) {
1354 if (i) {
1355 ret = trace_seq_puts(s, " <= ");
1356 if (!ret)
1357 return 0;
1358 }
1359 ret = seq_print_ip_sym(s, entry->stack.caller[i],
1360 sym_flags);
1361 if (!ret)
1362 return 0;
1363 }
1364 ret = trace_seq_puts(s, "\n");
1365 if (!ret)
1366 return 0;
1367 break;
Steven Rostedtbc0c38d2008-05-12 21:20:42 +02001368 }
Steven Rostedtb3806b42008-05-12 21:20:46 +02001369 return 1;
Steven Rostedtbc0c38d2008-05-12 21:20:42 +02001370}
1371
Ingo Molnare309b412008-05-12 21:20:51 +02001372static int print_raw_fmt(struct trace_iterator *iter)
Ingo Molnarf9896bf2008-05-12 21:20:47 +02001373{
1374 struct trace_seq *s = &iter->seq;
1375 struct trace_entry *entry;
1376 int ret;
1377 int S;
1378
1379 entry = iter->ent;
1380
1381 ret = trace_seq_printf(s, "%d %d %llu ",
1382 entry->pid, iter->cpu, entry->t);
1383 if (!ret)
1384 return 0;
1385
1386 switch (entry->type) {
1387 case TRACE_FN:
1388 ret = trace_seq_printf(s, "%x %x\n",
1389 entry->fn.ip, entry->fn.parent_ip);
1390 if (!ret)
1391 return 0;
1392 break;
1393 case TRACE_CTX:
Ingo Molnar57422792008-05-12 21:20:51 +02001394 case TRACE_WAKE:
Ingo Molnarf9896bf2008-05-12 21:20:47 +02001395 S = entry->ctx.prev_state < sizeof(state_to_char) ?
1396 state_to_char[entry->ctx.prev_state] : 'X';
Ingo Molnar57422792008-05-12 21:20:51 +02001397 if (entry->type == TRACE_WAKE)
1398 S = '+';
Ingo Molnarf9896bf2008-05-12 21:20:47 +02001399 ret = trace_seq_printf(s, "%d %d %c %d %d\n",
1400 entry->ctx.prev_pid,
1401 entry->ctx.prev_prio,
1402 S,
1403 entry->ctx.next_pid,
1404 entry->ctx.next_prio);
1405 if (!ret)
1406 return 0;
1407 break;
Ingo Molnarf0a920d2008-05-12 21:20:47 +02001408 case TRACE_SPECIAL:
Ingo Molnar86387f72008-05-12 21:20:51 +02001409 case TRACE_STACK:
Ingo Molnar4e655512008-05-12 21:20:52 +02001410 ret = trace_seq_printf(s, " %ld %ld %ld\n",
Ingo Molnarf0a920d2008-05-12 21:20:47 +02001411 entry->special.arg1,
1412 entry->special.arg2,
1413 entry->special.arg3);
1414 if (!ret)
1415 return 0;
1416 break;
Ingo Molnarf9896bf2008-05-12 21:20:47 +02001417 }
1418 return 1;
1419}
1420
Ingo Molnarcb0f12a2008-05-12 21:20:47 +02001421#define SEQ_PUT_FIELD_RET(s, x) \
1422do { \
1423 if (!trace_seq_putmem(s, &(x), sizeof(x))) \
1424 return 0; \
1425} while (0)
1426
Ingo Molnar5e3ca0e2008-05-12 21:20:49 +02001427#define SEQ_PUT_HEX_FIELD_RET(s, x) \
1428do { \
1429 if (!trace_seq_putmem_hex(s, &(x), sizeof(x))) \
1430 return 0; \
1431} while (0)
1432
Ingo Molnare309b412008-05-12 21:20:51 +02001433static int print_hex_fmt(struct trace_iterator *iter)
Ingo Molnar5e3ca0e2008-05-12 21:20:49 +02001434{
1435 struct trace_seq *s = &iter->seq;
1436 unsigned char newline = '\n';
1437 struct trace_entry *entry;
1438 int S;
1439
1440 entry = iter->ent;
1441
1442 SEQ_PUT_HEX_FIELD_RET(s, entry->pid);
1443 SEQ_PUT_HEX_FIELD_RET(s, iter->cpu);
1444 SEQ_PUT_HEX_FIELD_RET(s, entry->t);
1445
1446 switch (entry->type) {
1447 case TRACE_FN:
1448 SEQ_PUT_HEX_FIELD_RET(s, entry->fn.ip);
1449 SEQ_PUT_HEX_FIELD_RET(s, entry->fn.parent_ip);
1450 break;
1451 case TRACE_CTX:
Ingo Molnar57422792008-05-12 21:20:51 +02001452 case TRACE_WAKE:
Ingo Molnar5e3ca0e2008-05-12 21:20:49 +02001453 S = entry->ctx.prev_state < sizeof(state_to_char) ?
1454 state_to_char[entry->ctx.prev_state] : 'X';
Ingo Molnar57422792008-05-12 21:20:51 +02001455 if (entry->type == TRACE_WAKE)
1456 S = '+';
Ingo Molnar5e3ca0e2008-05-12 21:20:49 +02001457 SEQ_PUT_HEX_FIELD_RET(s, entry->ctx.prev_pid);
1458 SEQ_PUT_HEX_FIELD_RET(s, entry->ctx.prev_prio);
1459 SEQ_PUT_HEX_FIELD_RET(s, S);
1460 SEQ_PUT_HEX_FIELD_RET(s, entry->ctx.next_pid);
1461 SEQ_PUT_HEX_FIELD_RET(s, entry->ctx.next_prio);
1462 SEQ_PUT_HEX_FIELD_RET(s, entry->fn.parent_ip);
1463 break;
1464 case TRACE_SPECIAL:
Ingo Molnar86387f72008-05-12 21:20:51 +02001465 case TRACE_STACK:
Ingo Molnar5e3ca0e2008-05-12 21:20:49 +02001466 SEQ_PUT_HEX_FIELD_RET(s, entry->special.arg1);
1467 SEQ_PUT_HEX_FIELD_RET(s, entry->special.arg2);
1468 SEQ_PUT_HEX_FIELD_RET(s, entry->special.arg3);
1469 break;
1470 }
1471 SEQ_PUT_FIELD_RET(s, newline);
1472
1473 return 1;
1474}
1475
Ingo Molnare309b412008-05-12 21:20:51 +02001476static int print_bin_fmt(struct trace_iterator *iter)
Ingo Molnarcb0f12a2008-05-12 21:20:47 +02001477{
1478 struct trace_seq *s = &iter->seq;
1479 struct trace_entry *entry;
1480
1481 entry = iter->ent;
1482
1483 SEQ_PUT_FIELD_RET(s, entry->pid);
1484 SEQ_PUT_FIELD_RET(s, entry->cpu);
1485 SEQ_PUT_FIELD_RET(s, entry->t);
1486
1487 switch (entry->type) {
1488 case TRACE_FN:
1489 SEQ_PUT_FIELD_RET(s, entry->fn.ip);
1490 SEQ_PUT_FIELD_RET(s, entry->fn.parent_ip);
1491 break;
1492 case TRACE_CTX:
1493 SEQ_PUT_FIELD_RET(s, entry->ctx.prev_pid);
1494 SEQ_PUT_FIELD_RET(s, entry->ctx.prev_prio);
1495 SEQ_PUT_FIELD_RET(s, entry->ctx.prev_state);
1496 SEQ_PUT_FIELD_RET(s, entry->ctx.next_pid);
1497 SEQ_PUT_FIELD_RET(s, entry->ctx.next_prio);
1498 break;
Ingo Molnarf0a920d2008-05-12 21:20:47 +02001499 case TRACE_SPECIAL:
Ingo Molnar86387f72008-05-12 21:20:51 +02001500 case TRACE_STACK:
Ingo Molnarf0a920d2008-05-12 21:20:47 +02001501 SEQ_PUT_FIELD_RET(s, entry->special.arg1);
1502 SEQ_PUT_FIELD_RET(s, entry->special.arg2);
1503 SEQ_PUT_FIELD_RET(s, entry->special.arg3);
1504 break;
Ingo Molnarcb0f12a2008-05-12 21:20:47 +02001505 }
1506 return 1;
1507}
1508
Steven Rostedtbc0c38d2008-05-12 21:20:42 +02001509static int trace_empty(struct trace_iterator *iter)
1510{
1511 struct trace_array_cpu *data;
1512 int cpu;
1513
1514 for_each_possible_cpu(cpu) {
1515 data = iter->tr->data[cpu];
1516
Steven Rostedtb3806b42008-05-12 21:20:46 +02001517 if (head_page(data) && data->trace_idx &&
1518 (data->trace_tail != data->trace_head ||
1519 data->trace_tail_idx != data->trace_head_idx))
Steven Rostedtbc0c38d2008-05-12 21:20:42 +02001520 return 0;
1521 }
1522 return 1;
1523}
1524
Ingo Molnarf9896bf2008-05-12 21:20:47 +02001525static int print_trace_line(struct trace_iterator *iter)
1526{
Ingo Molnarcb0f12a2008-05-12 21:20:47 +02001527 if (trace_flags & TRACE_ITER_BIN)
1528 return print_bin_fmt(iter);
1529
Ingo Molnar5e3ca0e2008-05-12 21:20:49 +02001530 if (trace_flags & TRACE_ITER_HEX)
1531 return print_hex_fmt(iter);
1532
Ingo Molnarf9896bf2008-05-12 21:20:47 +02001533 if (trace_flags & TRACE_ITER_RAW)
1534 return print_raw_fmt(iter);
1535
1536 if (iter->iter_flags & TRACE_FILE_LAT_FMT)
1537 return print_lat_fmt(iter, iter->idx, iter->cpu);
1538
1539 return print_trace_fmt(iter);
1540}
1541
Steven Rostedtbc0c38d2008-05-12 21:20:42 +02001542static int s_show(struct seq_file *m, void *v)
1543{
1544 struct trace_iterator *iter = v;
1545
1546 if (iter->ent == NULL) {
1547 if (iter->tr) {
1548 seq_printf(m, "# tracer: %s\n", iter->trace->name);
1549 seq_puts(m, "#\n");
1550 }
1551 if (iter->iter_flags & TRACE_FILE_LAT_FMT) {
1552 /* print nothing if the buffers are empty */
1553 if (trace_empty(iter))
1554 return 0;
1555 print_trace_header(m, iter);
1556 if (!(trace_flags & TRACE_ITER_VERBOSE))
1557 print_lat_help_header(m);
1558 } else {
1559 if (!(trace_flags & TRACE_ITER_VERBOSE))
1560 print_func_help_header(m);
1561 }
1562 } else {
Ingo Molnarf9896bf2008-05-12 21:20:47 +02001563 print_trace_line(iter);
Steven Rostedt214023c2008-05-12 21:20:46 +02001564 trace_print_seq(m, &iter->seq);
Steven Rostedtbc0c38d2008-05-12 21:20:42 +02001565 }
1566
1567 return 0;
1568}
1569
1570static struct seq_operations tracer_seq_ops = {
Ingo Molnar4bf39a92008-05-12 21:20:46 +02001571 .start = s_start,
1572 .next = s_next,
1573 .stop = s_stop,
1574 .show = s_show,
Steven Rostedtbc0c38d2008-05-12 21:20:42 +02001575};
1576
Ingo Molnare309b412008-05-12 21:20:51 +02001577static struct trace_iterator *
Steven Rostedtbc0c38d2008-05-12 21:20:42 +02001578__tracing_open(struct inode *inode, struct file *file, int *ret)
1579{
1580 struct trace_iterator *iter;
1581
Steven Rostedt60a11772008-05-12 21:20:44 +02001582 if (tracing_disabled) {
1583 *ret = -ENODEV;
1584 return NULL;
1585 }
1586
Steven Rostedtbc0c38d2008-05-12 21:20:42 +02001587 iter = kzalloc(sizeof(*iter), GFP_KERNEL);
1588 if (!iter) {
1589 *ret = -ENOMEM;
1590 goto out;
1591 }
1592
1593 mutex_lock(&trace_types_lock);
1594 if (current_trace && current_trace->print_max)
1595 iter->tr = &max_tr;
1596 else
1597 iter->tr = inode->i_private;
1598 iter->trace = current_trace;
1599 iter->pos = -1;
1600
1601 /* TODO stop tracer */
1602 *ret = seq_open(file, &tracer_seq_ops);
1603 if (!*ret) {
1604 struct seq_file *m = file->private_data;
1605 m->private = iter;
1606
1607 /* stop the trace while dumping */
1608 if (iter->tr->ctrl)
1609 tracer_enabled = 0;
1610
1611 if (iter->trace && iter->trace->open)
1612 iter->trace->open(iter);
1613 } else {
1614 kfree(iter);
1615 iter = NULL;
1616 }
1617 mutex_unlock(&trace_types_lock);
1618
1619 out:
1620 return iter;
1621}
1622
1623int tracing_open_generic(struct inode *inode, struct file *filp)
1624{
Steven Rostedt60a11772008-05-12 21:20:44 +02001625 if (tracing_disabled)
1626 return -ENODEV;
1627
Steven Rostedtbc0c38d2008-05-12 21:20:42 +02001628 filp->private_data = inode->i_private;
1629 return 0;
1630}
1631
1632int tracing_release(struct inode *inode, struct file *file)
1633{
1634 struct seq_file *m = (struct seq_file *)file->private_data;
1635 struct trace_iterator *iter = m->private;
1636
1637 mutex_lock(&trace_types_lock);
1638 if (iter->trace && iter->trace->close)
1639 iter->trace->close(iter);
1640
1641 /* reenable tracing if it was previously enabled */
1642 if (iter->tr->ctrl)
1643 tracer_enabled = 1;
1644 mutex_unlock(&trace_types_lock);
1645
1646 seq_release(inode, file);
1647 kfree(iter);
1648 return 0;
1649}
1650
1651static int tracing_open(struct inode *inode, struct file *file)
1652{
1653 int ret;
1654
1655 __tracing_open(inode, file, &ret);
1656
1657 return ret;
1658}
1659
1660static int tracing_lt_open(struct inode *inode, struct file *file)
1661{
1662 struct trace_iterator *iter;
1663 int ret;
1664
1665 iter = __tracing_open(inode, file, &ret);
1666
1667 if (!ret)
1668 iter->iter_flags |= TRACE_FILE_LAT_FMT;
1669
1670 return ret;
1671}
1672
1673
Ingo Molnare309b412008-05-12 21:20:51 +02001674static void *
Steven Rostedtbc0c38d2008-05-12 21:20:42 +02001675t_next(struct seq_file *m, void *v, loff_t *pos)
1676{
1677 struct tracer *t = m->private;
1678
1679 (*pos)++;
1680
1681 if (t)
1682 t = t->next;
1683
1684 m->private = t;
1685
1686 return t;
1687}
1688
1689static void *t_start(struct seq_file *m, loff_t *pos)
1690{
1691 struct tracer *t = m->private;
1692 loff_t l = 0;
1693
1694 mutex_lock(&trace_types_lock);
1695 for (; t && l < *pos; t = t_next(m, t, &l))
1696 ;
1697
1698 return t;
1699}
1700
1701static void t_stop(struct seq_file *m, void *p)
1702{
1703 mutex_unlock(&trace_types_lock);
1704}
1705
1706static int t_show(struct seq_file *m, void *v)
1707{
1708 struct tracer *t = v;
1709
1710 if (!t)
1711 return 0;
1712
1713 seq_printf(m, "%s", t->name);
1714 if (t->next)
1715 seq_putc(m, ' ');
1716 else
1717 seq_putc(m, '\n');
1718
1719 return 0;
1720}
1721
1722static struct seq_operations show_traces_seq_ops = {
Ingo Molnar4bf39a92008-05-12 21:20:46 +02001723 .start = t_start,
1724 .next = t_next,
1725 .stop = t_stop,
1726 .show = t_show,
Steven Rostedtbc0c38d2008-05-12 21:20:42 +02001727};
1728
1729static int show_traces_open(struct inode *inode, struct file *file)
1730{
1731 int ret;
1732
Steven Rostedt60a11772008-05-12 21:20:44 +02001733 if (tracing_disabled)
1734 return -ENODEV;
1735
Steven Rostedtbc0c38d2008-05-12 21:20:42 +02001736 ret = seq_open(file, &show_traces_seq_ops);
1737 if (!ret) {
1738 struct seq_file *m = file->private_data;
1739 m->private = trace_types;
1740 }
1741
1742 return ret;
1743}
1744
1745static struct file_operations tracing_fops = {
Ingo Molnar4bf39a92008-05-12 21:20:46 +02001746 .open = tracing_open,
1747 .read = seq_read,
1748 .llseek = seq_lseek,
1749 .release = tracing_release,
Steven Rostedtbc0c38d2008-05-12 21:20:42 +02001750};
1751
1752static struct file_operations tracing_lt_fops = {
Ingo Molnar4bf39a92008-05-12 21:20:46 +02001753 .open = tracing_lt_open,
1754 .read = seq_read,
1755 .llseek = seq_lseek,
1756 .release = tracing_release,
Steven Rostedtbc0c38d2008-05-12 21:20:42 +02001757};
1758
1759static struct file_operations show_traces_fops = {
1760 .open = show_traces_open,
1761 .read = seq_read,
1762 .release = seq_release,
1763};
1764
1765static ssize_t
1766tracing_iter_ctrl_read(struct file *filp, char __user *ubuf,
1767 size_t cnt, loff_t *ppos)
1768{
1769 char *buf;
1770 int r = 0;
1771 int len = 0;
1772 int i;
1773
1774 /* calulate max size */
1775 for (i = 0; trace_options[i]; i++) {
1776 len += strlen(trace_options[i]);
1777 len += 3; /* "no" and space */
1778 }
1779
1780 /* +2 for \n and \0 */
1781 buf = kmalloc(len + 2, GFP_KERNEL);
1782 if (!buf)
1783 return -ENOMEM;
1784
1785 for (i = 0; trace_options[i]; i++) {
1786 if (trace_flags & (1 << i))
1787 r += sprintf(buf + r, "%s ", trace_options[i]);
1788 else
1789 r += sprintf(buf + r, "no%s ", trace_options[i]);
1790 }
1791
1792 r += sprintf(buf + r, "\n");
1793 WARN_ON(r >= len + 2);
1794
1795 r = simple_read_from_buffer(ubuf, cnt, ppos,
1796 buf, r);
1797
1798 kfree(buf);
1799
1800 return r;
1801}
1802
1803static ssize_t
1804tracing_iter_ctrl_write(struct file *filp, const char __user *ubuf,
1805 size_t cnt, loff_t *ppos)
1806{
1807 char buf[64];
1808 char *cmp = buf;
1809 int neg = 0;
1810 int i;
1811
1812 if (cnt > 63)
1813 cnt = 63;
1814
1815 if (copy_from_user(&buf, ubuf, cnt))
1816 return -EFAULT;
1817
1818 buf[cnt] = 0;
1819
1820 if (strncmp(buf, "no", 2) == 0) {
1821 neg = 1;
1822 cmp += 2;
1823 }
1824
1825 for (i = 0; trace_options[i]; i++) {
1826 int len = strlen(trace_options[i]);
1827
1828 if (strncmp(cmp, trace_options[i], len) == 0) {
1829 if (neg)
1830 trace_flags &= ~(1 << i);
1831 else
1832 trace_flags |= (1 << i);
1833 break;
1834 }
1835 }
1836
1837 filp->f_pos += cnt;
1838
1839 return cnt;
1840}
1841
1842static struct file_operations tracing_iter_fops = {
1843 .open = tracing_open_generic,
1844 .read = tracing_iter_ctrl_read,
1845 .write = tracing_iter_ctrl_write,
1846};
1847
Ingo Molnar7bd2f242008-05-12 21:20:45 +02001848static const char readme_msg[] =
1849 "tracing mini-HOWTO:\n\n"
1850 "# mkdir /debug\n"
1851 "# mount -t debugfs nodev /debug\n\n"
1852 "# cat /debug/tracing/available_tracers\n"
1853 "wakeup preemptirqsoff preemptoff irqsoff ftrace sched_switch none\n\n"
1854 "# cat /debug/tracing/current_tracer\n"
1855 "none\n"
1856 "# echo sched_switch > /debug/tracing/current_tracer\n"
1857 "# cat /debug/tracing/current_tracer\n"
1858 "sched_switch\n"
1859 "# cat /debug/tracing/iter_ctrl\n"
1860 "noprint-parent nosym-offset nosym-addr noverbose\n"
1861 "# echo print-parent > /debug/tracing/iter_ctrl\n"
1862 "# echo 1 > /debug/tracing/tracing_enabled\n"
1863 "# cat /debug/tracing/trace > /tmp/trace.txt\n"
1864 "echo 0 > /debug/tracing/tracing_enabled\n"
1865;
1866
1867static ssize_t
1868tracing_readme_read(struct file *filp, char __user *ubuf,
1869 size_t cnt, loff_t *ppos)
1870{
1871 return simple_read_from_buffer(ubuf, cnt, ppos,
1872 readme_msg, strlen(readme_msg));
1873}
1874
1875static struct file_operations tracing_readme_fops = {
1876 .open = tracing_open_generic,
1877 .read = tracing_readme_read,
1878};
1879
Steven Rostedtbc0c38d2008-05-12 21:20:42 +02001880static ssize_t
1881tracing_ctrl_read(struct file *filp, char __user *ubuf,
1882 size_t cnt, loff_t *ppos)
1883{
1884 struct trace_array *tr = filp->private_data;
1885 char buf[64];
1886 int r;
1887
1888 r = sprintf(buf, "%ld\n", tr->ctrl);
Ingo Molnar4e3c3332008-05-12 21:20:45 +02001889 return simple_read_from_buffer(ubuf, cnt, ppos, buf, r);
Steven Rostedtbc0c38d2008-05-12 21:20:42 +02001890}
1891
1892static ssize_t
1893tracing_ctrl_write(struct file *filp, const char __user *ubuf,
1894 size_t cnt, loff_t *ppos)
1895{
1896 struct trace_array *tr = filp->private_data;
1897 long val;
1898 char buf[64];
1899
1900 if (cnt > 63)
1901 cnt = 63;
1902
1903 if (copy_from_user(&buf, ubuf, cnt))
1904 return -EFAULT;
1905
1906 buf[cnt] = 0;
1907
1908 val = simple_strtoul(buf, NULL, 10);
1909
1910 val = !!val;
1911
1912 mutex_lock(&trace_types_lock);
1913 if (tr->ctrl ^ val) {
1914 if (val)
1915 tracer_enabled = 1;
1916 else
1917 tracer_enabled = 0;
1918
1919 tr->ctrl = val;
1920
1921 if (current_trace && current_trace->ctrl_update)
1922 current_trace->ctrl_update(tr);
1923 }
1924 mutex_unlock(&trace_types_lock);
1925
1926 filp->f_pos += cnt;
1927
1928 return cnt;
1929}
1930
1931static ssize_t
1932tracing_set_trace_read(struct file *filp, char __user *ubuf,
1933 size_t cnt, loff_t *ppos)
1934{
1935 char buf[max_tracer_type_len+2];
1936 int r;
1937
1938 mutex_lock(&trace_types_lock);
1939 if (current_trace)
1940 r = sprintf(buf, "%s\n", current_trace->name);
1941 else
1942 r = sprintf(buf, "\n");
1943 mutex_unlock(&trace_types_lock);
1944
Ingo Molnar4bf39a92008-05-12 21:20:46 +02001945 return simple_read_from_buffer(ubuf, cnt, ppos, buf, r);
Steven Rostedtbc0c38d2008-05-12 21:20:42 +02001946}
1947
1948static ssize_t
1949tracing_set_trace_write(struct file *filp, const char __user *ubuf,
1950 size_t cnt, loff_t *ppos)
1951{
1952 struct trace_array *tr = &global_trace;
1953 struct tracer *t;
1954 char buf[max_tracer_type_len+1];
1955 int i;
1956
1957 if (cnt > max_tracer_type_len)
1958 cnt = max_tracer_type_len;
1959
1960 if (copy_from_user(&buf, ubuf, cnt))
1961 return -EFAULT;
1962
1963 buf[cnt] = 0;
1964
1965 /* strip ending whitespace. */
1966 for (i = cnt - 1; i > 0 && isspace(buf[i]); i--)
1967 buf[i] = 0;
1968
1969 mutex_lock(&trace_types_lock);
1970 for (t = trace_types; t; t = t->next) {
1971 if (strcmp(t->name, buf) == 0)
1972 break;
1973 }
1974 if (!t || t == current_trace)
1975 goto out;
1976
1977 if (current_trace && current_trace->reset)
1978 current_trace->reset(tr);
1979
1980 current_trace = t;
1981 if (t->init)
1982 t->init(tr);
1983
1984 out:
1985 mutex_unlock(&trace_types_lock);
1986
1987 filp->f_pos += cnt;
1988
1989 return cnt;
1990}
1991
1992static ssize_t
1993tracing_max_lat_read(struct file *filp, char __user *ubuf,
1994 size_t cnt, loff_t *ppos)
1995{
1996 unsigned long *ptr = filp->private_data;
1997 char buf[64];
1998 int r;
1999
2000 r = snprintf(buf, 64, "%ld\n",
2001 *ptr == (unsigned long)-1 ? -1 : nsecs_to_usecs(*ptr));
2002 if (r > 64)
2003 r = 64;
Ingo Molnar4bf39a92008-05-12 21:20:46 +02002004 return simple_read_from_buffer(ubuf, cnt, ppos, buf, r);
Steven Rostedtbc0c38d2008-05-12 21:20:42 +02002005}
2006
2007static ssize_t
2008tracing_max_lat_write(struct file *filp, const char __user *ubuf,
2009 size_t cnt, loff_t *ppos)
2010{
2011 long *ptr = filp->private_data;
2012 long val;
2013 char buf[64];
2014
2015 if (cnt > 63)
2016 cnt = 63;
2017
2018 if (copy_from_user(&buf, ubuf, cnt))
2019 return -EFAULT;
2020
2021 buf[cnt] = 0;
2022
2023 val = simple_strtoul(buf, NULL, 10);
2024
2025 *ptr = val * 1000;
2026
2027 return cnt;
2028}
2029
Steven Rostedtb3806b42008-05-12 21:20:46 +02002030static atomic_t tracing_reader;
2031
2032static int tracing_open_pipe(struct inode *inode, struct file *filp)
2033{
2034 struct trace_iterator *iter;
2035
2036 if (tracing_disabled)
2037 return -ENODEV;
2038
2039 /* We only allow for reader of the pipe */
2040 if (atomic_inc_return(&tracing_reader) != 1) {
2041 atomic_dec(&tracing_reader);
2042 return -EBUSY;
2043 }
2044
2045 /* create a buffer to store the information to pass to userspace */
2046 iter = kzalloc(sizeof(*iter), GFP_KERNEL);
2047 if (!iter)
2048 return -ENOMEM;
2049
2050 iter->tr = &global_trace;
2051
2052 filp->private_data = iter;
2053
2054 return 0;
2055}
2056
2057static int tracing_release_pipe(struct inode *inode, struct file *file)
2058{
2059 struct trace_iterator *iter = file->private_data;
2060
2061 kfree(iter);
2062 atomic_dec(&tracing_reader);
2063
2064 return 0;
2065}
2066
Soeren Sandmann Pedersen2a2cc8f2008-05-12 21:20:49 +02002067static unsigned int
2068tracing_poll_pipe(struct file *filp, poll_table *poll_table)
2069{
2070 struct trace_iterator *iter = filp->private_data;
2071
2072 if (trace_flags & TRACE_ITER_BLOCK) {
2073 /*
2074 * Always select as readable when in blocking mode
2075 */
2076 return POLLIN | POLLRDNORM;
2077 }
2078 else {
2079 if (!trace_empty(iter))
2080 return POLLIN | POLLRDNORM;
2081 poll_wait(filp, &trace_wait, poll_table);
2082 if (!trace_empty(iter))
2083 return POLLIN | POLLRDNORM;
2084
2085 return 0;
2086 }
2087}
2088
Steven Rostedtb3806b42008-05-12 21:20:46 +02002089/*
2090 * Consumer reader.
2091 */
2092static ssize_t
2093tracing_read_pipe(struct file *filp, char __user *ubuf,
2094 size_t cnt, loff_t *ppos)
2095{
2096 struct trace_iterator *iter = filp->private_data;
2097 struct trace_array_cpu *data;
2098 static cpumask_t mask;
Steven Rostedtb3806b42008-05-12 21:20:46 +02002099 static int start;
2100 unsigned long flags;
Ingo Molnar25770462008-05-12 21:20:49 +02002101#ifdef CONFIG_FTRACE
Ingo Molnar2e0f5762008-05-12 21:20:49 +02002102 int ftrace_save;
Ingo Molnar25770462008-05-12 21:20:49 +02002103#endif
Steven Rostedtb3806b42008-05-12 21:20:46 +02002104 int read = 0;
2105 int cpu;
2106 int len;
2107 int ret;
2108
2109 /* return any leftover data */
2110 if (iter->seq.len > start) {
2111 len = iter->seq.len - start;
2112 if (cnt > len)
2113 cnt = len;
2114 ret = copy_to_user(ubuf, iter->seq.buffer + start, cnt);
2115 if (ret)
2116 cnt = -EFAULT;
2117
2118 start += len;
2119
2120 return cnt;
2121 }
2122
2123 trace_seq_reset(&iter->seq);
2124 start = 0;
2125
2126 while (trace_empty(iter)) {
Soeren Sandmann Pedersen2a2cc8f2008-05-12 21:20:49 +02002127 if (!(trace_flags & TRACE_ITER_BLOCK))
2128 return -EWOULDBLOCK;
Steven Rostedtb3806b42008-05-12 21:20:46 +02002129 /*
2130 * This is a make-shift waitqueue. The reason we don't use
2131 * an actual wait queue is because:
2132 * 1) we only ever have one waiter
2133 * 2) the tracing, traces all functions, we don't want
2134 * the overhead of calling wake_up and friends
2135 * (and tracing them too)
2136 * Anyway, this is really very primitive wakeup.
2137 */
2138 set_current_state(TASK_INTERRUPTIBLE);
2139 iter->tr->waiter = current;
2140
2141 /* sleep for one second, and try again. */
2142 schedule_timeout(HZ);
2143
2144 iter->tr->waiter = NULL;
2145
2146 if (signal_pending(current))
2147 return -EINTR;
2148
2149 /*
2150 * We block until we read something and tracing is disabled.
2151 * We still block if tracing is disabled, but we have never
2152 * read anything. This allows a user to cat this file, and
2153 * then enable tracing. But after we have read something,
2154 * we give an EOF when tracing is again disabled.
2155 *
2156 * iter->pos will be 0 if we haven't read anything.
2157 */
2158 if (!tracer_enabled && iter->pos)
2159 break;
2160
2161 continue;
2162 }
2163
2164 /* stop when tracing is finished */
2165 if (trace_empty(iter))
2166 return 0;
2167
2168 if (cnt >= PAGE_SIZE)
2169 cnt = PAGE_SIZE - 1;
2170
2171 memset(iter, 0, sizeof(*iter));
2172 iter->tr = &global_trace;
2173 iter->pos = -1;
2174
2175 /*
2176 * We need to stop all tracing on all CPUS to read the
2177 * the next buffer. This is a bit expensive, but is
2178 * not done often. We fill all what we can read,
2179 * and then release the locks again.
2180 */
2181
2182 cpus_clear(mask);
2183 local_irq_save(flags);
Ingo Molnar25770462008-05-12 21:20:49 +02002184#ifdef CONFIG_FTRACE
Ingo Molnar2e0f5762008-05-12 21:20:49 +02002185 ftrace_save = ftrace_enabled;
2186 ftrace_enabled = 0;
Ingo Molnar25770462008-05-12 21:20:49 +02002187#endif
Ingo Molnar2e0f5762008-05-12 21:20:49 +02002188 smp_wmb();
Steven Rostedtb3806b42008-05-12 21:20:46 +02002189 for_each_possible_cpu(cpu) {
2190 data = iter->tr->data[cpu];
2191
2192 if (!head_page(data) || !data->trace_idx)
2193 continue;
2194
2195 atomic_inc(&data->disabled);
Steven Rostedtb3806b42008-05-12 21:20:46 +02002196 cpu_set(cpu, mask);
2197 }
2198
Ingo Molnar2e0f5762008-05-12 21:20:49 +02002199 for_each_cpu_mask(cpu, mask) {
2200 data = iter->tr->data[cpu];
2201 spin_lock(&data->lock);
2202 }
2203
Steven Rostedt088b1e422008-05-12 21:20:48 +02002204 while (find_next_entry_inc(iter) != NULL) {
2205 int len = iter->seq.len;
2206
Ingo Molnarf9896bf2008-05-12 21:20:47 +02002207 ret = print_trace_line(iter);
Steven Rostedt088b1e422008-05-12 21:20:48 +02002208 if (!ret) {
2209 /* don't print partial lines */
2210 iter->seq.len = len;
Steven Rostedtb3806b42008-05-12 21:20:46 +02002211 break;
Steven Rostedt088b1e422008-05-12 21:20:48 +02002212 }
Steven Rostedtb3806b42008-05-12 21:20:46 +02002213
2214 trace_consume(iter);
2215
2216 if (iter->seq.len >= cnt)
2217 break;
Steven Rostedtb3806b42008-05-12 21:20:46 +02002218 }
2219
Ingo Molnard4c5a2f2008-05-12 21:20:46 +02002220 for_each_cpu_mask(cpu, mask) {
Steven Rostedtb3806b42008-05-12 21:20:46 +02002221 data = iter->tr->data[cpu];
Steven Rostedtb3806b42008-05-12 21:20:46 +02002222 spin_unlock(&data->lock);
Ingo Molnar2e0f5762008-05-12 21:20:49 +02002223 }
2224
2225 for_each_cpu_mask(cpu, mask) {
2226 data = iter->tr->data[cpu];
Steven Rostedtb3806b42008-05-12 21:20:46 +02002227 atomic_dec(&data->disabled);
2228 }
Ingo Molnar25770462008-05-12 21:20:49 +02002229#ifdef CONFIG_FTRACE
Ingo Molnar2e0f5762008-05-12 21:20:49 +02002230 ftrace_enabled = ftrace_save;
Ingo Molnar25770462008-05-12 21:20:49 +02002231#endif
Steven Rostedtb3806b42008-05-12 21:20:46 +02002232 local_irq_restore(flags);
2233
2234 /* Now copy what we have to the user */
2235 read = iter->seq.len;
2236 if (read > cnt)
2237 read = cnt;
2238
2239 ret = copy_to_user(ubuf, iter->seq.buffer, read);
2240
2241 if (read < iter->seq.len)
2242 start = read;
2243 else
2244 trace_seq_reset(&iter->seq);
2245
2246 if (ret)
2247 read = -EFAULT;
2248
2249 return read;
2250}
2251
Steven Rostedtbc0c38d2008-05-12 21:20:42 +02002252static struct file_operations tracing_max_lat_fops = {
Ingo Molnar4bf39a92008-05-12 21:20:46 +02002253 .open = tracing_open_generic,
2254 .read = tracing_max_lat_read,
2255 .write = tracing_max_lat_write,
Steven Rostedtbc0c38d2008-05-12 21:20:42 +02002256};
2257
2258static struct file_operations tracing_ctrl_fops = {
Ingo Molnar4bf39a92008-05-12 21:20:46 +02002259 .open = tracing_open_generic,
2260 .read = tracing_ctrl_read,
2261 .write = tracing_ctrl_write,
Steven Rostedtbc0c38d2008-05-12 21:20:42 +02002262};
2263
2264static struct file_operations set_tracer_fops = {
Ingo Molnar4bf39a92008-05-12 21:20:46 +02002265 .open = tracing_open_generic,
2266 .read = tracing_set_trace_read,
2267 .write = tracing_set_trace_write,
Steven Rostedtbc0c38d2008-05-12 21:20:42 +02002268};
2269
Steven Rostedtb3806b42008-05-12 21:20:46 +02002270static struct file_operations tracing_pipe_fops = {
Ingo Molnar4bf39a92008-05-12 21:20:46 +02002271 .open = tracing_open_pipe,
Soeren Sandmann Pedersen2a2cc8f2008-05-12 21:20:49 +02002272 .poll = tracing_poll_pipe,
Ingo Molnar4bf39a92008-05-12 21:20:46 +02002273 .read = tracing_read_pipe,
2274 .release = tracing_release_pipe,
Steven Rostedtb3806b42008-05-12 21:20:46 +02002275};
2276
Steven Rostedtbc0c38d2008-05-12 21:20:42 +02002277#ifdef CONFIG_DYNAMIC_FTRACE
2278
2279static ssize_t
2280tracing_read_long(struct file *filp, char __user *ubuf,
2281 size_t cnt, loff_t *ppos)
2282{
2283 unsigned long *p = filp->private_data;
2284 char buf[64];
2285 int r;
2286
2287 r = sprintf(buf, "%ld\n", *p);
Ingo Molnar4bf39a92008-05-12 21:20:46 +02002288
2289 return simple_read_from_buffer(ubuf, cnt, ppos, buf, r);
Steven Rostedtbc0c38d2008-05-12 21:20:42 +02002290}
2291
2292static struct file_operations tracing_read_long_fops = {
Ingo Molnar4bf39a92008-05-12 21:20:46 +02002293 .open = tracing_open_generic,
2294 .read = tracing_read_long,
Steven Rostedtbc0c38d2008-05-12 21:20:42 +02002295};
2296#endif
2297
2298static struct dentry *d_tracer;
2299
2300struct dentry *tracing_init_dentry(void)
2301{
2302 static int once;
2303
2304 if (d_tracer)
2305 return d_tracer;
2306
2307 d_tracer = debugfs_create_dir("tracing", NULL);
2308
2309 if (!d_tracer && !once) {
2310 once = 1;
2311 pr_warning("Could not create debugfs directory 'tracing'\n");
2312 return NULL;
2313 }
2314
2315 return d_tracer;
2316}
2317
Steven Rostedt60a11772008-05-12 21:20:44 +02002318#ifdef CONFIG_FTRACE_SELFTEST
2319/* Let selftest have access to static functions in this file */
2320#include "trace_selftest.c"
2321#endif
2322
Steven Rostedtbc0c38d2008-05-12 21:20:42 +02002323static __init void tracer_init_debugfs(void)
2324{
2325 struct dentry *d_tracer;
2326 struct dentry *entry;
2327
2328 d_tracer = tracing_init_dentry();
2329
2330 entry = debugfs_create_file("tracing_enabled", 0644, d_tracer,
2331 &global_trace, &tracing_ctrl_fops);
2332 if (!entry)
2333 pr_warning("Could not create debugfs 'tracing_enabled' entry\n");
2334
2335 entry = debugfs_create_file("iter_ctrl", 0644, d_tracer,
2336 NULL, &tracing_iter_fops);
2337 if (!entry)
2338 pr_warning("Could not create debugfs 'iter_ctrl' entry\n");
2339
2340 entry = debugfs_create_file("latency_trace", 0444, d_tracer,
2341 &global_trace, &tracing_lt_fops);
2342 if (!entry)
2343 pr_warning("Could not create debugfs 'latency_trace' entry\n");
2344
2345 entry = debugfs_create_file("trace", 0444, d_tracer,
2346 &global_trace, &tracing_fops);
2347 if (!entry)
2348 pr_warning("Could not create debugfs 'trace' entry\n");
2349
2350 entry = debugfs_create_file("available_tracers", 0444, d_tracer,
2351 &global_trace, &show_traces_fops);
2352 if (!entry)
2353 pr_warning("Could not create debugfs 'trace' entry\n");
2354
2355 entry = debugfs_create_file("current_tracer", 0444, d_tracer,
2356 &global_trace, &set_tracer_fops);
2357 if (!entry)
2358 pr_warning("Could not create debugfs 'trace' entry\n");
2359
2360 entry = debugfs_create_file("tracing_max_latency", 0644, d_tracer,
2361 &tracing_max_latency,
2362 &tracing_max_lat_fops);
2363 if (!entry)
2364 pr_warning("Could not create debugfs "
2365 "'tracing_max_latency' entry\n");
2366
2367 entry = debugfs_create_file("tracing_thresh", 0644, d_tracer,
2368 &tracing_thresh, &tracing_max_lat_fops);
2369 if (!entry)
2370 pr_warning("Could not create debugfs "
2371 "'tracing_threash' entry\n");
Ingo Molnar7bd2f242008-05-12 21:20:45 +02002372 entry = debugfs_create_file("README", 0644, d_tracer,
2373 NULL, &tracing_readme_fops);
2374 if (!entry)
2375 pr_warning("Could not create debugfs 'README' entry\n");
2376
Steven Rostedtb3806b42008-05-12 21:20:46 +02002377 entry = debugfs_create_file("trace_pipe", 0644, d_tracer,
2378 NULL, &tracing_pipe_fops);
2379 if (!entry)
2380 pr_warning("Could not create debugfs "
2381 "'tracing_threash' entry\n");
Steven Rostedtbc0c38d2008-05-12 21:20:42 +02002382
2383#ifdef CONFIG_DYNAMIC_FTRACE
2384 entry = debugfs_create_file("dyn_ftrace_total_info", 0444, d_tracer,
2385 &ftrace_update_tot_cnt,
2386 &tracing_read_long_fops);
2387 if (!entry)
2388 pr_warning("Could not create debugfs "
2389 "'dyn_ftrace_total_info' entry\n");
2390#endif
2391}
2392
2393/* dummy trace to disable tracing */
2394static struct tracer no_tracer __read_mostly =
2395{
Ingo Molnar4bf39a92008-05-12 21:20:46 +02002396 .name = "none",
Steven Rostedtbc0c38d2008-05-12 21:20:42 +02002397};
2398
Steven Rostedt4c11d7a2008-05-12 21:20:43 +02002399static int trace_alloc_page(void)
Steven Rostedtbc0c38d2008-05-12 21:20:42 +02002400{
Steven Rostedt4c11d7a2008-05-12 21:20:43 +02002401 struct trace_array_cpu *data;
Steven Rostedt4c11d7a2008-05-12 21:20:43 +02002402 struct page *page, *tmp;
2403 LIST_HEAD(pages);
Ingo Molnarc7aafc52008-05-12 21:20:45 +02002404 void *array;
Steven Rostedt4c11d7a2008-05-12 21:20:43 +02002405 int i;
2406
2407 /* first allocate a page for each CPU */
2408 for_each_possible_cpu(i) {
2409 array = (void *)__get_free_page(GFP_KERNEL);
2410 if (array == NULL) {
2411 printk(KERN_ERR "tracer: failed to allocate page"
2412 "for trace buffer!\n");
2413 goto free_pages;
2414 }
2415
2416 page = virt_to_page(array);
2417 list_add(&page->lru, &pages);
2418
2419/* Only allocate if we are actually using the max trace */
2420#ifdef CONFIG_TRACER_MAX_TRACE
2421 array = (void *)__get_free_page(GFP_KERNEL);
2422 if (array == NULL) {
2423 printk(KERN_ERR "tracer: failed to allocate page"
2424 "for trace buffer!\n");
2425 goto free_pages;
2426 }
2427 page = virt_to_page(array);
2428 list_add(&page->lru, &pages);
2429#endif
2430 }
2431
2432 /* Now that we successfully allocate a page per CPU, add them */
2433 for_each_possible_cpu(i) {
2434 data = global_trace.data[i];
Steven Rostedtb3806b42008-05-12 21:20:46 +02002435 spin_lock_init(&data->lock);
Ingo Molnard4c5a2f2008-05-12 21:20:46 +02002436 lockdep_set_class(&data->lock, &data->lock_key);
Steven Rostedt4c11d7a2008-05-12 21:20:43 +02002437 page = list_entry(pages.next, struct page, lru);
Ingo Molnarc7aafc52008-05-12 21:20:45 +02002438 list_del_init(&page->lru);
Steven Rostedt4c11d7a2008-05-12 21:20:43 +02002439 list_add_tail(&page->lru, &data->trace_pages);
2440 ClearPageLRU(page);
2441
2442#ifdef CONFIG_TRACER_MAX_TRACE
2443 data = max_tr.data[i];
Steven Rostedtb3806b42008-05-12 21:20:46 +02002444 spin_lock_init(&data->lock);
Ingo Molnard4c5a2f2008-05-12 21:20:46 +02002445 lockdep_set_class(&data->lock, &data->lock_key);
Steven Rostedt4c11d7a2008-05-12 21:20:43 +02002446 page = list_entry(pages.next, struct page, lru);
Ingo Molnarc7aafc52008-05-12 21:20:45 +02002447 list_del_init(&page->lru);
Steven Rostedt4c11d7a2008-05-12 21:20:43 +02002448 list_add_tail(&page->lru, &data->trace_pages);
2449 SetPageLRU(page);
2450#endif
2451 }
2452 global_trace.entries += ENTRIES_PER_PAGE;
2453
2454 return 0;
2455
2456 free_pages:
2457 list_for_each_entry_safe(page, tmp, &pages, lru) {
Ingo Molnarc7aafc52008-05-12 21:20:45 +02002458 list_del_init(&page->lru);
Steven Rostedt4c11d7a2008-05-12 21:20:43 +02002459 __free_page(page);
2460 }
2461 return -ENOMEM;
Steven Rostedtbc0c38d2008-05-12 21:20:42 +02002462}
2463
2464__init static int tracer_alloc_buffers(void)
2465{
Steven Rostedt4c11d7a2008-05-12 21:20:43 +02002466 struct trace_array_cpu *data;
2467 void *array;
2468 struct page *page;
2469 int pages = 0;
Steven Rostedt60a11772008-05-12 21:20:44 +02002470 int ret = -ENOMEM;
Steven Rostedtbc0c38d2008-05-12 21:20:42 +02002471 int i;
2472
Steven Rostedt26994ea2008-05-12 21:20:48 +02002473 global_trace.ctrl = tracer_enabled;
2474
Steven Rostedt4c11d7a2008-05-12 21:20:43 +02002475 /* Allocate the first page for all buffers */
Steven Rostedtbc0c38d2008-05-12 21:20:42 +02002476 for_each_possible_cpu(i) {
Steven Rostedt4c11d7a2008-05-12 21:20:43 +02002477 data = global_trace.data[i] = &per_cpu(global_trace_cpu, i);
Steven Rostedtbc0c38d2008-05-12 21:20:42 +02002478 max_tr.data[i] = &per_cpu(max_data, i);
2479
Steven Rostedt4c11d7a2008-05-12 21:20:43 +02002480 array = (void *)__get_free_page(GFP_KERNEL);
Steven Rostedtbc0c38d2008-05-12 21:20:42 +02002481 if (array == NULL) {
Steven Rostedt4c11d7a2008-05-12 21:20:43 +02002482 printk(KERN_ERR "tracer: failed to allocate page"
2483 "for trace buffer!\n");
Steven Rostedtbc0c38d2008-05-12 21:20:42 +02002484 goto free_buffers;
2485 }
Steven Rostedt4c11d7a2008-05-12 21:20:43 +02002486
2487 /* set the array to the list */
2488 INIT_LIST_HEAD(&data->trace_pages);
2489 page = virt_to_page(array);
2490 list_add(&page->lru, &data->trace_pages);
2491 /* use the LRU flag to differentiate the two buffers */
2492 ClearPageLRU(page);
Steven Rostedtbc0c38d2008-05-12 21:20:42 +02002493
2494/* Only allocate if we are actually using the max trace */
2495#ifdef CONFIG_TRACER_MAX_TRACE
Steven Rostedt4c11d7a2008-05-12 21:20:43 +02002496 array = (void *)__get_free_page(GFP_KERNEL);
Steven Rostedtbc0c38d2008-05-12 21:20:42 +02002497 if (array == NULL) {
Steven Rostedt4c11d7a2008-05-12 21:20:43 +02002498 printk(KERN_ERR "tracer: failed to allocate page"
2499 "for trace buffer!\n");
Steven Rostedtbc0c38d2008-05-12 21:20:42 +02002500 goto free_buffers;
2501 }
Steven Rostedt4c11d7a2008-05-12 21:20:43 +02002502
2503 INIT_LIST_HEAD(&max_tr.data[i]->trace_pages);
2504 page = virt_to_page(array);
2505 list_add(&page->lru, &max_tr.data[i]->trace_pages);
2506 SetPageLRU(page);
Steven Rostedtbc0c38d2008-05-12 21:20:42 +02002507#endif
2508 }
2509
2510 /*
2511 * Since we allocate by orders of pages, we may be able to
2512 * round up a bit.
2513 */
Steven Rostedt4c11d7a2008-05-12 21:20:43 +02002514 global_trace.entries = ENTRIES_PER_PAGE;
Steven Rostedt4c11d7a2008-05-12 21:20:43 +02002515 pages++;
Steven Rostedtbc0c38d2008-05-12 21:20:42 +02002516
Steven Rostedt4c11d7a2008-05-12 21:20:43 +02002517 while (global_trace.entries < trace_nr_entries) {
2518 if (trace_alloc_page())
2519 break;
2520 pages++;
2521 }
Steven Rostedt89b2f972008-05-12 21:20:44 +02002522 max_tr.entries = global_trace.entries;
Steven Rostedt4c11d7a2008-05-12 21:20:43 +02002523
2524 pr_info("tracer: %d pages allocated for %ld",
2525 pages, trace_nr_entries);
Steven Rostedtbc0c38d2008-05-12 21:20:42 +02002526 pr_info(" entries of %ld bytes\n", (long)TRACE_ENTRY_SIZE);
2527 pr_info(" actual entries %ld\n", global_trace.entries);
2528
2529 tracer_init_debugfs();
2530
2531 trace_init_cmdlines();
2532
2533 register_tracer(&no_tracer);
2534 current_trace = &no_tracer;
2535
Steven Rostedt60a11772008-05-12 21:20:44 +02002536 /* All seems OK, enable tracing */
2537 tracing_disabled = 0;
2538
Steven Rostedtbc0c38d2008-05-12 21:20:42 +02002539 return 0;
2540
2541 free_buffers:
2542 for (i-- ; i >= 0; i--) {
Steven Rostedt4c11d7a2008-05-12 21:20:43 +02002543 struct page *page, *tmp;
Steven Rostedtbc0c38d2008-05-12 21:20:42 +02002544 struct trace_array_cpu *data = global_trace.data[i];
2545
Ingo Molnarc7aafc52008-05-12 21:20:45 +02002546 if (data) {
Steven Rostedt4c11d7a2008-05-12 21:20:43 +02002547 list_for_each_entry_safe(page, tmp,
2548 &data->trace_pages, lru) {
Ingo Molnarc7aafc52008-05-12 21:20:45 +02002549 list_del_init(&page->lru);
Steven Rostedt4c11d7a2008-05-12 21:20:43 +02002550 __free_page(page);
2551 }
Steven Rostedtbc0c38d2008-05-12 21:20:42 +02002552 }
2553
2554#ifdef CONFIG_TRACER_MAX_TRACE
2555 data = max_tr.data[i];
Ingo Molnarc7aafc52008-05-12 21:20:45 +02002556 if (data) {
Steven Rostedt4c11d7a2008-05-12 21:20:43 +02002557 list_for_each_entry_safe(page, tmp,
2558 &data->trace_pages, lru) {
Ingo Molnarc7aafc52008-05-12 21:20:45 +02002559 list_del_init(&page->lru);
Steven Rostedt4c11d7a2008-05-12 21:20:43 +02002560 __free_page(page);
2561 }
Steven Rostedtbc0c38d2008-05-12 21:20:42 +02002562 }
2563#endif
2564 }
Steven Rostedt60a11772008-05-12 21:20:44 +02002565 return ret;
Steven Rostedtbc0c38d2008-05-12 21:20:42 +02002566}
Steven Rostedt60a11772008-05-12 21:20:44 +02002567fs_initcall(tracer_alloc_buffers);