2 * ring buffer based initcalls tracer
4 * Copyright (C) 2008 Frederic Weisbecker <fweisbec@gmail.com>
8 #include <linux/init.h>
9 #include <linux/debugfs.h>
10 #include <linux/ftrace.h>
11 #include <linux/kallsyms.h>
15 static struct trace_array
*boot_trace
;
16 static bool pre_initcalls_finished
;
18 /* Tells the boot tracer that the pre_smp_initcalls are finished.
20 * It doesn't enable sched events tracing however.
21 * You have to call enable_boot_trace to do so.
23 void start_boot_trace(void)
25 pre_initcalls_finished
= true;
28 void enable_boot_trace(void)
30 if (pre_initcalls_finished
)
31 tracing_start_cmdline_record();
34 void disable_boot_trace(void)
36 if (pre_initcalls_finished
)
37 tracing_stop_cmdline_record();
40 static void reset_boot_trace(struct trace_array
*tr
)
44 tr
->time_start
= ftrace_now(tr
->cpu
);
46 for_each_online_cpu(cpu
)
47 tracing_reset(tr
, cpu
);
50 static void boot_trace_init(struct trace_array
*tr
)
55 for_each_cpu_mask(cpu
, cpu_possible_map
)
56 tracing_reset(tr
, cpu
);
58 tracing_cmdline_assign_trace(tr
);
61 static void boot_trace_ctrl_update(struct trace_array
*tr
)
69 static enum print_line_t
initcall_print_line(struct trace_iterator
*iter
)
72 struct trace_entry
*entry
= iter
->ent
;
73 struct trace_boot
*field
= (struct trace_boot
*)entry
;
74 struct boot_trace
*it
= &field
->initcall
;
75 struct trace_seq
*s
= &iter
->seq
;
76 struct timespec calltime
= ktime_to_timespec(it
->calltime
);
77 struct timespec rettime
= ktime_to_timespec(it
->rettime
);
79 if (entry
->type
== TRACE_BOOT
) {
80 ret
= trace_seq_printf(s
, "[%5ld.%09ld] calling %s @ %i\n",
83 it
->func
, it
->caller
);
85 return TRACE_TYPE_PARTIAL_LINE
;
87 ret
= trace_seq_printf(s
, "[%5ld.%09ld] initcall %s "
88 "returned %d after %lld msecs\n",
91 it
->func
, it
->result
, it
->duration
);
94 return TRACE_TYPE_PARTIAL_LINE
;
95 return TRACE_TYPE_HANDLED
;
97 return TRACE_TYPE_UNHANDLED
;
100 struct tracer boot_tracer __read_mostly
=
103 .init
= boot_trace_init
,
104 .reset
= reset_boot_trace
,
105 .ctrl_update
= boot_trace_ctrl_update
,
106 .print_line
= initcall_print_line
,
109 void trace_boot(struct boot_trace
*it
, initcall_t fn
)
111 struct ring_buffer_event
*event
;
112 struct trace_boot
*entry
;
113 struct trace_array_cpu
*data
;
114 unsigned long irq_flags
;
115 struct trace_array
*tr
= boot_trace
;
117 if (!pre_initcalls_finished
)
120 /* Get its name now since this function could
121 * disappear because it is in the .init section.
123 sprint_symbol(it
->func
, (unsigned long)fn
);
125 data
= tr
->data
[smp_processor_id()];
127 event
= ring_buffer_lock_reserve(tr
->buffer
, sizeof(*entry
),
131 entry
= ring_buffer_event_data(event
);
132 tracing_generic_entry_update(&entry
->ent
, 0, 0);
133 entry
->ent
.type
= TRACE_BOOT
;
134 entry
->initcall
= *it
;
135 ring_buffer_unlock_commit(tr
->buffer
, event
, irq_flags
);