tracing/ftrace: fix the check on nopped sites
[linux-2.6-block.git] / kernel / trace / trace_output.c
CommitLineData
f0868d1e
SR
1/*
2 * trace_output.c
3 *
4 * Copyright (C) 2008 Red Hat Inc, Steven Rostedt <srostedt@redhat.com>
5 *
6 */
7
8#include <linux/module.h>
9#include <linux/mutex.h>
10#include <linux/ftrace.h>
11
12#include "trace_output.h"
13
14/* must be a power of 2 */
15#define EVENT_HASHSIZE 128
16
17static DEFINE_MUTEX(trace_event_mutex);
18static struct hlist_head event_hash[EVENT_HASHSIZE] __read_mostly;
19
20static int next_event_type = __TRACE_LAST_TYPE + 1;
21
22/**
23 * trace_seq_printf - sequence printing of trace information
24 * @s: trace sequence descriptor
25 * @fmt: printf format string
26 *
27 * The tracer may use either sequence operations or its own
28 * copy to user routines. To simplify formating of a trace
29 * trace_seq_printf is used to store strings into a special
30 * buffer (@s). Then the output may be either used by
31 * the sequencer or pulled into another buffer.
32 */
33int
34trace_seq_printf(struct trace_seq *s, const char *fmt, ...)
35{
36 int len = (PAGE_SIZE - 1) - s->len;
37 va_list ap;
38 int ret;
39
40 if (!len)
41 return 0;
42
43 va_start(ap, fmt);
44 ret = vsnprintf(s->buffer + s->len, len, fmt, ap);
45 va_end(ap);
46
47 /* If we can't write it all, don't bother writing anything */
48 if (ret >= len)
49 return 0;
50
51 s->len += ret;
52
53 return len;
54}
55
769b0441 56int trace_seq_bprintf(struct trace_seq *s, const char *fmt, const u32 *binary)
1427cdf0
LJ
57{
58 int len = (PAGE_SIZE - 1) - s->len;
59 int ret;
60
61 if (!len)
62 return 0;
63
64 ret = bstr_printf(s->buffer + s->len, len, fmt, binary);
65
66 /* If we can't write it all, don't bother writing anything */
67 if (ret >= len)
68 return 0;
69
70 s->len += ret;
71
72 return len;
73}
74
f0868d1e
SR
75/**
76 * trace_seq_puts - trace sequence printing of simple string
77 * @s: trace sequence descriptor
78 * @str: simple string to record
79 *
80 * The tracer may use either the sequence operations or its own
81 * copy to user routines. This function records a simple string
82 * into a special buffer (@s) for later retrieval by a sequencer
83 * or other mechanism.
84 */
85int trace_seq_puts(struct trace_seq *s, const char *str)
86{
87 int len = strlen(str);
88
89 if (len > ((PAGE_SIZE - 1) - s->len))
90 return 0;
91
92 memcpy(s->buffer + s->len, str, len);
93 s->len += len;
94
95 return len;
96}
97
98int trace_seq_putc(struct trace_seq *s, unsigned char c)
99{
100 if (s->len >= (PAGE_SIZE - 1))
101 return 0;
102
103 s->buffer[s->len++] = c;
104
105 return 1;
106}
107
108int trace_seq_putmem(struct trace_seq *s, void *mem, size_t len)
109{
110 if (len > ((PAGE_SIZE - 1) - s->len))
111 return 0;
112
113 memcpy(s->buffer + s->len, mem, len);
114 s->len += len;
115
116 return len;
117}
118
119int trace_seq_putmem_hex(struct trace_seq *s, void *mem, size_t len)
120{
121 unsigned char hex[HEX_CHARS];
122 unsigned char *data = mem;
123 int i, j;
124
125#ifdef __BIG_ENDIAN
126 for (i = 0, j = 0; i < len; i++) {
127#else
128 for (i = len-1, j = 0; i >= 0; i--) {
129#endif
130 hex[j++] = hex_asc_hi(data[i]);
131 hex[j++] = hex_asc_lo(data[i]);
132 }
133 hex[j++] = ' ';
134
135 return trace_seq_putmem(s, hex, j);
136}
137
138int trace_seq_path(struct trace_seq *s, struct path *path)
139{
140 unsigned char *p;
141
142 if (s->len >= (PAGE_SIZE - 1))
143 return 0;
144 p = d_path(path, s->buffer + s->len, PAGE_SIZE - s->len);
145 if (!IS_ERR(p)) {
146 p = mangle_path(s->buffer + s->len, p, "\n");
147 if (p) {
148 s->len = p - s->buffer;
149 return 1;
150 }
151 } else {
152 s->buffer[s->len++] = '?';
153 return 1;
154 }
155
156 return 0;
157}
158
159#ifdef CONFIG_KRETPROBES
160static inline const char *kretprobed(const char *name)
161{
162 static const char tramp_name[] = "kretprobe_trampoline";
163 int size = sizeof(tramp_name);
164
165 if (strncmp(tramp_name, name, size) == 0)
166 return "[unknown/kretprobe'd]";
167 return name;
168}
169#else
170static inline const char *kretprobed(const char *name)
171{
172 return name;
173}
174#endif /* CONFIG_KRETPROBES */
175
176static int
177seq_print_sym_short(struct trace_seq *s, const char *fmt, unsigned long address)
178{
179#ifdef CONFIG_KALLSYMS
180 char str[KSYM_SYMBOL_LEN];
181 const char *name;
182
183 kallsyms_lookup(address, NULL, NULL, NULL, str);
184
185 name = kretprobed(str);
186
187 return trace_seq_printf(s, fmt, name);
188#endif
189 return 1;
190}
191
192static int
193seq_print_sym_offset(struct trace_seq *s, const char *fmt,
194 unsigned long address)
195{
196#ifdef CONFIG_KALLSYMS
197 char str[KSYM_SYMBOL_LEN];
198 const char *name;
199
200 sprint_symbol(str, address);
201 name = kretprobed(str);
202
203 return trace_seq_printf(s, fmt, name);
204#endif
205 return 1;
206}
207
208#ifndef CONFIG_64BIT
209# define IP_FMT "%08lx"
210#else
211# define IP_FMT "%016lx"
212#endif
213
214int seq_print_user_ip(struct trace_seq *s, struct mm_struct *mm,
215 unsigned long ip, unsigned long sym_flags)
216{
217 struct file *file = NULL;
218 unsigned long vmstart = 0;
219 int ret = 1;
220
221 if (mm) {
222 const struct vm_area_struct *vma;
223
224 down_read(&mm->mmap_sem);
225 vma = find_vma(mm, ip);
226 if (vma) {
227 file = vma->vm_file;
228 vmstart = vma->vm_start;
229 }
230 if (file) {
231 ret = trace_seq_path(s, &file->f_path);
232 if (ret)
233 ret = trace_seq_printf(s, "[+0x%lx]",
234 ip - vmstart);
235 }
236 up_read(&mm->mmap_sem);
237 }
238 if (ret && ((sym_flags & TRACE_ITER_SYM_ADDR) || !file))
239 ret = trace_seq_printf(s, " <" IP_FMT ">", ip);
240 return ret;
241}
242
243int
244seq_print_userip_objs(const struct userstack_entry *entry, struct trace_seq *s,
245 unsigned long sym_flags)
246{
247 struct mm_struct *mm = NULL;
248 int ret = 1;
249 unsigned int i;
250
251 if (trace_flags & TRACE_ITER_SYM_USEROBJ) {
252 struct task_struct *task;
253 /*
254 * we do the lookup on the thread group leader,
255 * since individual threads might have already quit!
256 */
257 rcu_read_lock();
258 task = find_task_by_vpid(entry->ent.tgid);
259 if (task)
260 mm = get_task_mm(task);
261 rcu_read_unlock();
262 }
263
264 for (i = 0; i < FTRACE_STACK_ENTRIES; i++) {
265 unsigned long ip = entry->caller[i];
266
267 if (ip == ULONG_MAX || !ret)
268 break;
269 if (i && ret)
270 ret = trace_seq_puts(s, " <- ");
271 if (!ip) {
272 if (ret)
273 ret = trace_seq_puts(s, "??");
274 continue;
275 }
276 if (!ret)
277 break;
278 if (ret)
279 ret = seq_print_user_ip(s, mm, ip, sym_flags);
280 }
281
282 if (mm)
283 mmput(mm);
284 return ret;
285}
286
287int
288seq_print_ip_sym(struct trace_seq *s, unsigned long ip, unsigned long sym_flags)
289{
290 int ret;
291
292 if (!ip)
293 return trace_seq_printf(s, "0");
294
295 if (sym_flags & TRACE_ITER_SYM_OFFSET)
296 ret = seq_print_sym_offset(s, "%s", ip);
297 else
298 ret = seq_print_sym_short(s, "%s", ip);
299
300 if (!ret)
301 return 0;
302
303 if (sym_flags & TRACE_ITER_SYM_ADDR)
304 ret = trace_seq_printf(s, " <" IP_FMT ">", ip);
305 return ret;
306}
307
d9793bd8 308static int
c4a8e8be
FW
309lat_print_generic(struct trace_seq *s, struct trace_entry *entry, int cpu)
310{
311 int hardirq, softirq;
312 char *comm;
313
314 comm = trace_find_cmdline(entry->pid);
c4a8e8be
FW
315 hardirq = entry->flags & TRACE_FLAG_HARDIRQ;
316 softirq = entry->flags & TRACE_FLAG_SOFTIRQ;
d9793bd8
ACM
317
318 if (!trace_seq_printf(s, "%8.8s-%-5d %3d%c%c%c",
319 comm, entry->pid, cpu,
320 (entry->flags & TRACE_FLAG_IRQS_OFF) ? 'd' :
321 (entry->flags & TRACE_FLAG_IRQS_NOSUPPORT) ?
322 'X' : '.',
323 (entry->flags & TRACE_FLAG_NEED_RESCHED) ?
324 'N' : '.',
325 (hardirq && softirq) ? 'H' :
326 hardirq ? 'h' : softirq ? 's' : '.'))
327 return 0;
c4a8e8be
FW
328
329 if (entry->preempt_count)
d9793bd8
ACM
330 return trace_seq_printf(s, "%x", entry->preempt_count);
331 return trace_seq_puts(s, ".");
c4a8e8be
FW
332}
333
334static unsigned long preempt_mark_thresh = 100;
335
d9793bd8 336static int
c4a8e8be
FW
337lat_print_timestamp(struct trace_seq *s, u64 abs_usecs,
338 unsigned long rel_usecs)
339{
d9793bd8
ACM
340 return trace_seq_printf(s, " %4lldus%c: ", abs_usecs,
341 rel_usecs > preempt_mark_thresh ? '!' :
342 rel_usecs > 1 ? '+' : ' ');
c4a8e8be
FW
343}
344
345int trace_print_context(struct trace_iterator *iter)
346{
347 struct trace_seq *s = &iter->seq;
348 struct trace_entry *entry = iter->ent;
349 char *comm = trace_find_cmdline(entry->pid);
350 unsigned long long t = ns2usecs(iter->ts);
351 unsigned long usec_rem = do_div(t, USEC_PER_SEC);
352 unsigned long secs = (unsigned long)t;
353
d9793bd8 354 return trace_seq_printf(s, "%16s-%-5d [%03d] %5lu.%06lu: ",
1830b52d 355 comm, entry->pid, iter->cpu, secs, usec_rem);
c4a8e8be
FW
356}
357
358int trace_print_lat_context(struct trace_iterator *iter)
359{
360 u64 next_ts;
d9793bd8 361 int ret;
c4a8e8be
FW
362 struct trace_seq *s = &iter->seq;
363 struct trace_entry *entry = iter->ent,
364 *next_entry = trace_find_next_entry(iter, NULL,
365 &next_ts);
366 unsigned long verbose = (trace_flags & TRACE_ITER_VERBOSE);
367 unsigned long abs_usecs = ns2usecs(iter->ts - iter->tr->time_start);
368 unsigned long rel_usecs;
369
370 if (!next_entry)
371 next_ts = iter->ts;
372 rel_usecs = ns2usecs(next_ts - iter->ts);
373
374 if (verbose) {
375 char *comm = trace_find_cmdline(entry->pid);
d9793bd8
ACM
376 ret = trace_seq_printf(s, "%16s %5d %3d %d %08x %08lx [%08lx]"
377 " %ld.%03ldms (+%ld.%03ldms): ", comm,
1830b52d 378 entry->pid, iter->cpu, entry->flags,
d9793bd8
ACM
379 entry->preempt_count, iter->idx,
380 ns2usecs(iter->ts),
381 abs_usecs / USEC_PER_MSEC,
382 abs_usecs % USEC_PER_MSEC,
383 rel_usecs / USEC_PER_MSEC,
384 rel_usecs % USEC_PER_MSEC);
c4a8e8be 385 } else {
1830b52d 386 ret = lat_print_generic(s, entry, iter->cpu);
d9793bd8
ACM
387 if (ret)
388 ret = lat_print_timestamp(s, abs_usecs, rel_usecs);
c4a8e8be
FW
389 }
390
d9793bd8 391 return ret;
c4a8e8be
FW
392}
393
f633cef0
SR
394static const char state_to_char[] = TASK_STATE_TO_CHAR_STR;
395
396static int task_state_char(unsigned long state)
397{
398 int bit = state ? __ffs(state) + 1 : 0;
399
400 return bit < sizeof(state_to_char) - 1 ? state_to_char[bit] : '?';
401}
402
f0868d1e
SR
403/**
404 * ftrace_find_event - find a registered event
405 * @type: the type of event to look for
406 *
407 * Returns an event of type @type otherwise NULL
408 */
409struct trace_event *ftrace_find_event(int type)
410{
411 struct trace_event *event;
412 struct hlist_node *n;
413 unsigned key;
414
415 key = type & (EVENT_HASHSIZE - 1);
416
417 hlist_for_each_entry_rcu(event, n, &event_hash[key], node) {
418 if (event->type == type)
419 return event;
420 }
421
422 return NULL;
423}
424
425/**
426 * register_ftrace_event - register output for an event type
427 * @event: the event type to register
428 *
429 * Event types are stored in a hash and this hash is used to
430 * find a way to print an event. If the @event->type is set
431 * then it will use that type, otherwise it will assign a
432 * type to use.
433 *
434 * If you assign your own type, please make sure it is added
435 * to the trace_type enum in trace.h, to avoid collisions
436 * with the dynamic types.
437 *
438 * Returns the event type number or zero on error.
439 */
440int register_ftrace_event(struct trace_event *event)
441{
442 unsigned key;
443 int ret = 0;
444
445 mutex_lock(&trace_event_mutex);
446
447 if (!event->type)
448 event->type = next_event_type++;
449 else if (event->type > __TRACE_LAST_TYPE) {
450 printk(KERN_WARNING "Need to add type to trace.h\n");
451 WARN_ON(1);
452 }
453
454 if (ftrace_find_event(event->type))
455 goto out;
456
268ccda0
ACM
457 if (event->trace == NULL)
458 event->trace = trace_nop_print;
268ccda0
ACM
459 if (event->raw == NULL)
460 event->raw = trace_nop_print;
461 if (event->hex == NULL)
462 event->hex = trace_nop_print;
463 if (event->binary == NULL)
464 event->binary = trace_nop_print;
465
f0868d1e
SR
466 key = event->type & (EVENT_HASHSIZE - 1);
467
468 hlist_add_head_rcu(&event->node, &event_hash[key]);
469
470 ret = event->type;
471 out:
472 mutex_unlock(&trace_event_mutex);
473
474 return ret;
475}
476
477/**
478 * unregister_ftrace_event - remove a no longer used event
479 * @event: the event to remove
480 */
481int unregister_ftrace_event(struct trace_event *event)
482{
483 mutex_lock(&trace_event_mutex);
484 hlist_del(&event->node);
485 mutex_unlock(&trace_event_mutex);
486
487 return 0;
488}
f633cef0
SR
489
490/*
491 * Standard events
492 */
493
ae7462b4 494enum print_line_t trace_nop_print(struct trace_iterator *iter, int flags)
f633cef0 495{
d9793bd8 496 return TRACE_TYPE_HANDLED;
f633cef0
SR
497}
498
499/* TRACE_FN */
ae7462b4 500static enum print_line_t trace_fn_trace(struct trace_iterator *iter, int flags)
f633cef0
SR
501{
502 struct ftrace_entry *field;
2c9b238e 503 struct trace_seq *s = &iter->seq;
f633cef0 504
2c9b238e 505 trace_assign_type(field, iter->ent);
f633cef0
SR
506
507 if (!seq_print_ip_sym(s, field->ip, flags))
508 goto partial;
509
510 if ((flags & TRACE_ITER_PRINT_PARENT) && field->parent_ip) {
511 if (!trace_seq_printf(s, " <-"))
512 goto partial;
513 if (!seq_print_ip_sym(s,
514 field->parent_ip,
515 flags))
516 goto partial;
517 }
518 if (!trace_seq_printf(s, "\n"))
519 goto partial;
520
d9793bd8 521 return TRACE_TYPE_HANDLED;
f633cef0
SR
522
523 partial:
524 return TRACE_TYPE_PARTIAL_LINE;
525}
526
ae7462b4 527static enum print_line_t trace_fn_raw(struct trace_iterator *iter, int flags)
f633cef0
SR
528{
529 struct ftrace_entry *field;
530
2c9b238e 531 trace_assign_type(field, iter->ent);
f633cef0 532
2c9b238e 533 if (!trace_seq_printf(&iter->seq, "%lx %lx\n",
6c1a99af
LJ
534 field->ip,
535 field->parent_ip))
f633cef0
SR
536 return TRACE_TYPE_PARTIAL_LINE;
537
d9793bd8 538 return TRACE_TYPE_HANDLED;
f633cef0
SR
539}
540
ae7462b4 541static enum print_line_t trace_fn_hex(struct trace_iterator *iter, int flags)
f633cef0
SR
542{
543 struct ftrace_entry *field;
2c9b238e 544 struct trace_seq *s = &iter->seq;
f633cef0 545
2c9b238e 546 trace_assign_type(field, iter->ent);
f633cef0
SR
547
548 SEQ_PUT_HEX_FIELD_RET(s, field->ip);
549 SEQ_PUT_HEX_FIELD_RET(s, field->parent_ip);
550
d9793bd8 551 return TRACE_TYPE_HANDLED;
f633cef0
SR
552}
553
ae7462b4 554static enum print_line_t trace_fn_bin(struct trace_iterator *iter, int flags)
f633cef0
SR
555{
556 struct ftrace_entry *field;
2c9b238e 557 struct trace_seq *s = &iter->seq;
f633cef0 558
2c9b238e 559 trace_assign_type(field, iter->ent);
f633cef0
SR
560
561 SEQ_PUT_FIELD_RET(s, field->ip);
562 SEQ_PUT_FIELD_RET(s, field->parent_ip);
563
d9793bd8 564 return TRACE_TYPE_HANDLED;
f633cef0
SR
565}
566
567static struct trace_event trace_fn_event = {
ef18012b 568 .type = TRACE_FN,
f633cef0 569 .trace = trace_fn_trace,
f633cef0
SR
570 .raw = trace_fn_raw,
571 .hex = trace_fn_hex,
572 .binary = trace_fn_bin,
573};
574
575/* TRACE_CTX an TRACE_WAKE */
ae7462b4
ACM
576static enum print_line_t trace_ctxwake_print(struct trace_iterator *iter,
577 char *delim)
f633cef0
SR
578{
579 struct ctx_switch_entry *field;
580 char *comm;
581 int S, T;
582
2c9b238e 583 trace_assign_type(field, iter->ent);
f633cef0
SR
584
585 T = task_state_char(field->next_state);
586 S = task_state_char(field->prev_state);
587 comm = trace_find_cmdline(field->next_pid);
2c9b238e
ACM
588 if (!trace_seq_printf(&iter->seq,
589 " %5d:%3d:%c %s [%03d] %5d:%3d:%c %s\n",
6c1a99af
LJ
590 field->prev_pid,
591 field->prev_prio,
592 S, delim,
593 field->next_cpu,
594 field->next_pid,
595 field->next_prio,
596 T, comm))
f633cef0
SR
597 return TRACE_TYPE_PARTIAL_LINE;
598
d9793bd8 599 return TRACE_TYPE_HANDLED;
f633cef0
SR
600}
601
ae7462b4 602static enum print_line_t trace_ctx_print(struct trace_iterator *iter, int flags)
f633cef0 603{
2c9b238e 604 return trace_ctxwake_print(iter, "==>");
f633cef0
SR
605}
606
ae7462b4
ACM
607static enum print_line_t trace_wake_print(struct trace_iterator *iter,
608 int flags)
f633cef0 609{
2c9b238e 610 return trace_ctxwake_print(iter, " +");
f633cef0
SR
611}
612
2c9b238e 613static int trace_ctxwake_raw(struct trace_iterator *iter, char S)
f633cef0
SR
614{
615 struct ctx_switch_entry *field;
616 int T;
617
2c9b238e 618 trace_assign_type(field, iter->ent);
f633cef0
SR
619
620 if (!S)
621 task_state_char(field->prev_state);
622 T = task_state_char(field->next_state);
2c9b238e 623 if (!trace_seq_printf(&iter->seq, "%d %d %c %d %d %d %c\n",
6c1a99af
LJ
624 field->prev_pid,
625 field->prev_prio,
626 S,
627 field->next_cpu,
628 field->next_pid,
629 field->next_prio,
630 T))
f633cef0
SR
631 return TRACE_TYPE_PARTIAL_LINE;
632
d9793bd8 633 return TRACE_TYPE_HANDLED;
f633cef0
SR
634}
635
ae7462b4 636static enum print_line_t trace_ctx_raw(struct trace_iterator *iter, int flags)
f633cef0 637{
2c9b238e 638 return trace_ctxwake_raw(iter, 0);
f633cef0
SR
639}
640
ae7462b4 641static enum print_line_t trace_wake_raw(struct trace_iterator *iter, int flags)
f633cef0 642{
2c9b238e 643 return trace_ctxwake_raw(iter, '+');
f633cef0
SR
644}
645
646
2c9b238e 647static int trace_ctxwake_hex(struct trace_iterator *iter, char S)
f633cef0
SR
648{
649 struct ctx_switch_entry *field;
2c9b238e 650 struct trace_seq *s = &iter->seq;
f633cef0
SR
651 int T;
652
2c9b238e 653 trace_assign_type(field, iter->ent);
f633cef0
SR
654
655 if (!S)
656 task_state_char(field->prev_state);
657 T = task_state_char(field->next_state);
658
659 SEQ_PUT_HEX_FIELD_RET(s, field->prev_pid);
660 SEQ_PUT_HEX_FIELD_RET(s, field->prev_prio);
661 SEQ_PUT_HEX_FIELD_RET(s, S);
662 SEQ_PUT_HEX_FIELD_RET(s, field->next_cpu);
663 SEQ_PUT_HEX_FIELD_RET(s, field->next_pid);
664 SEQ_PUT_HEX_FIELD_RET(s, field->next_prio);
665 SEQ_PUT_HEX_FIELD_RET(s, T);
666
d9793bd8 667 return TRACE_TYPE_HANDLED;
f633cef0
SR
668}
669
ae7462b4 670static enum print_line_t trace_ctx_hex(struct trace_iterator *iter, int flags)
f633cef0 671{
2c9b238e 672 return trace_ctxwake_hex(iter, 0);
f633cef0
SR
673}
674
ae7462b4 675static enum print_line_t trace_wake_hex(struct trace_iterator *iter, int flags)
f633cef0 676{
2c9b238e 677 return trace_ctxwake_hex(iter, '+');
f633cef0
SR
678}
679
ae7462b4
ACM
680static enum print_line_t trace_ctxwake_bin(struct trace_iterator *iter,
681 int flags)
f633cef0
SR
682{
683 struct ctx_switch_entry *field;
2c9b238e 684 struct trace_seq *s = &iter->seq;
f633cef0 685
2c9b238e 686 trace_assign_type(field, iter->ent);
f633cef0
SR
687
688 SEQ_PUT_FIELD_RET(s, field->prev_pid);
689 SEQ_PUT_FIELD_RET(s, field->prev_prio);
690 SEQ_PUT_FIELD_RET(s, field->prev_state);
691 SEQ_PUT_FIELD_RET(s, field->next_pid);
692 SEQ_PUT_FIELD_RET(s, field->next_prio);
693 SEQ_PUT_FIELD_RET(s, field->next_state);
694
d9793bd8 695 return TRACE_TYPE_HANDLED;
f633cef0
SR
696}
697
698static struct trace_event trace_ctx_event = {
ef18012b 699 .type = TRACE_CTX,
f633cef0 700 .trace = trace_ctx_print,
f633cef0
SR
701 .raw = trace_ctx_raw,
702 .hex = trace_ctx_hex,
703 .binary = trace_ctxwake_bin,
704};
705
706static struct trace_event trace_wake_event = {
ef18012b 707 .type = TRACE_WAKE,
f633cef0 708 .trace = trace_wake_print,
f633cef0
SR
709 .raw = trace_wake_raw,
710 .hex = trace_wake_hex,
711 .binary = trace_ctxwake_bin,
712};
713
714/* TRACE_SPECIAL */
ae7462b4
ACM
715static enum print_line_t trace_special_print(struct trace_iterator *iter,
716 int flags)
f633cef0
SR
717{
718 struct special_entry *field;
719
2c9b238e 720 trace_assign_type(field, iter->ent);
f633cef0 721
2c9b238e 722 if (!trace_seq_printf(&iter->seq, "# %ld %ld %ld\n",
6c1a99af
LJ
723 field->arg1,
724 field->arg2,
725 field->arg3))
f633cef0
SR
726 return TRACE_TYPE_PARTIAL_LINE;
727
d9793bd8 728 return TRACE_TYPE_HANDLED;
f633cef0
SR
729}
730
ae7462b4
ACM
731static enum print_line_t trace_special_hex(struct trace_iterator *iter,
732 int flags)
f633cef0
SR
733{
734 struct special_entry *field;
2c9b238e 735 struct trace_seq *s = &iter->seq;
f633cef0 736
2c9b238e 737 trace_assign_type(field, iter->ent);
f633cef0
SR
738
739 SEQ_PUT_HEX_FIELD_RET(s, field->arg1);
740 SEQ_PUT_HEX_FIELD_RET(s, field->arg2);
741 SEQ_PUT_HEX_FIELD_RET(s, field->arg3);
742
d9793bd8 743 return TRACE_TYPE_HANDLED;
f633cef0
SR
744}
745
ae7462b4
ACM
746static enum print_line_t trace_special_bin(struct trace_iterator *iter,
747 int flags)
f633cef0
SR
748{
749 struct special_entry *field;
2c9b238e 750 struct trace_seq *s = &iter->seq;
f633cef0 751
2c9b238e 752 trace_assign_type(field, iter->ent);
f633cef0
SR
753
754 SEQ_PUT_FIELD_RET(s, field->arg1);
755 SEQ_PUT_FIELD_RET(s, field->arg2);
756 SEQ_PUT_FIELD_RET(s, field->arg3);
757
d9793bd8 758 return TRACE_TYPE_HANDLED;
f633cef0
SR
759}
760
761static struct trace_event trace_special_event = {
ef18012b 762 .type = TRACE_SPECIAL,
f633cef0 763 .trace = trace_special_print,
f633cef0
SR
764 .raw = trace_special_print,
765 .hex = trace_special_hex,
766 .binary = trace_special_bin,
767};
768
769/* TRACE_STACK */
770
ae7462b4
ACM
771static enum print_line_t trace_stack_print(struct trace_iterator *iter,
772 int flags)
f633cef0
SR
773{
774 struct stack_entry *field;
2c9b238e 775 struct trace_seq *s = &iter->seq;
f633cef0
SR
776 int i;
777
2c9b238e 778 trace_assign_type(field, iter->ent);
f633cef0
SR
779
780 for (i = 0; i < FTRACE_STACK_ENTRIES; i++) {
781 if (i) {
6c1a99af 782 if (!trace_seq_puts(s, " <= "))
f633cef0
SR
783 goto partial;
784
6c1a99af 785 if (!seq_print_ip_sym(s, field->caller[i], flags))
f633cef0
SR
786 goto partial;
787 }
6c1a99af 788 if (!trace_seq_puts(s, "\n"))
f633cef0
SR
789 goto partial;
790 }
791
d9793bd8 792 return TRACE_TYPE_HANDLED;
f633cef0
SR
793
794 partial:
795 return TRACE_TYPE_PARTIAL_LINE;
796}
797
798static struct trace_event trace_stack_event = {
ef18012b 799 .type = TRACE_STACK,
f633cef0 800 .trace = trace_stack_print,
f633cef0
SR
801 .raw = trace_special_print,
802 .hex = trace_special_hex,
803 .binary = trace_special_bin,
804};
805
806/* TRACE_USER_STACK */
ae7462b4
ACM
807static enum print_line_t trace_user_stack_print(struct trace_iterator *iter,
808 int flags)
f633cef0
SR
809{
810 struct userstack_entry *field;
2c9b238e 811 struct trace_seq *s = &iter->seq;
f633cef0 812
2c9b238e 813 trace_assign_type(field, iter->ent);
f633cef0 814
6c1a99af 815 if (!seq_print_userip_objs(field, s, flags))
f633cef0
SR
816 goto partial;
817
6c1a99af 818 if (!trace_seq_putc(s, '\n'))
f633cef0
SR
819 goto partial;
820
d9793bd8 821 return TRACE_TYPE_HANDLED;
f633cef0
SR
822
823 partial:
824 return TRACE_TYPE_PARTIAL_LINE;
825}
826
827static struct trace_event trace_user_stack_event = {
ef18012b 828 .type = TRACE_USER_STACK,
f633cef0 829 .trace = trace_user_stack_print,
f633cef0
SR
830 .raw = trace_special_print,
831 .hex = trace_special_hex,
832 .binary = trace_special_bin,
833};
834
48ead020 835/* TRACE_BPRINT */
1427cdf0 836static enum print_line_t
48ead020 837trace_bprint_print(struct trace_iterator *iter, int flags)
1427cdf0
LJ
838{
839 struct trace_entry *entry = iter->ent;
840 struct trace_seq *s = &iter->seq;
48ead020 841 struct bprint_entry *field;
1427cdf0
LJ
842
843 trace_assign_type(field, entry);
844
845 if (!seq_print_ip_sym(s, field->ip, flags))
846 goto partial;
847
848 if (!trace_seq_puts(s, ": "))
849 goto partial;
850
851 if (!trace_seq_bprintf(s, field->fmt, field->buf))
852 goto partial;
853
854 return TRACE_TYPE_HANDLED;
855
856 partial:
857 return TRACE_TYPE_PARTIAL_LINE;
858}
859
769b0441 860
48ead020
FW
861static enum print_line_t
862trace_bprint_raw(struct trace_iterator *iter, int flags)
1427cdf0 863{
48ead020 864 struct bprint_entry *field;
1427cdf0 865 struct trace_seq *s = &iter->seq;
1427cdf0 866
769b0441 867 trace_assign_type(field, iter->ent);
1427cdf0
LJ
868
869 if (!trace_seq_printf(s, ": %lx : ", field->ip))
870 goto partial;
871
872 if (!trace_seq_bprintf(s, field->fmt, field->buf))
873 goto partial;
874
875 return TRACE_TYPE_HANDLED;
876
877 partial:
878 return TRACE_TYPE_PARTIAL_LINE;
879}
880
769b0441 881
48ead020
FW
882static struct trace_event trace_bprint_event = {
883 .type = TRACE_BPRINT,
884 .trace = trace_bprint_print,
885 .raw = trace_bprint_raw,
886};
887
888/* TRACE_PRINT */
889static enum print_line_t trace_print_print(struct trace_iterator *iter,
890 int flags)
891{
892 struct print_entry *field;
893 struct trace_seq *s = &iter->seq;
894
895 trace_assign_type(field, iter->ent);
896
897 if (!seq_print_ip_sym(s, field->ip, flags))
898 goto partial;
899
900 if (!trace_seq_printf(s, ": %s", field->buf))
901 goto partial;
902
903 return TRACE_TYPE_HANDLED;
904
905 partial:
906 return TRACE_TYPE_PARTIAL_LINE;
907}
908
909static enum print_line_t trace_print_raw(struct trace_iterator *iter, int flags)
910{
911 struct print_entry *field;
912
913 trace_assign_type(field, iter->ent);
914
915 if (!trace_seq_printf(&iter->seq, "# %lx %s", field->ip, field->buf))
916 goto partial;
917
918 return TRACE_TYPE_HANDLED;
919
920 partial:
921 return TRACE_TYPE_PARTIAL_LINE;
922}
923
769b0441 924static struct trace_event trace_print_event = {
48ead020 925 .type = TRACE_PRINT,
769b0441
FW
926 .trace = trace_print_print,
927 .raw = trace_print_raw,
1427cdf0
LJ
928};
929
48ead020 930
f633cef0
SR
931static struct trace_event *events[] __initdata = {
932 &trace_fn_event,
933 &trace_ctx_event,
934 &trace_wake_event,
935 &trace_special_event,
936 &trace_stack_event,
937 &trace_user_stack_event,
48ead020 938 &trace_bprint_event,
f633cef0
SR
939 &trace_print_event,
940 NULL
941};
942
943__init static int init_events(void)
944{
945 struct trace_event *event;
946 int i, ret;
947
948 for (i = 0; events[i]; i++) {
949 event = events[i];
950
951 ret = register_ftrace_event(event);
952 if (!ret) {
953 printk(KERN_WARNING "event %d failed to register\n",
954 event->type);
955 WARN_ON_ONCE(1);
956 }
957 }
958
959 return 0;
960}
961device_initcall(init_events);