aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/trace/boot.h60
-rw-r--r--init/main.c27
-rw-r--r--kernel/trace/Kconfig17
-rw-r--r--kernel/trace/Makefile1
-rw-r--r--kernel/trace/trace.c3
-rw-r--r--kernel/trace/trace.h8
-rw-r--r--kernel/trace/trace_boot.c185
-rw-r--r--kernel/trace/trace_entries.h27
8 files changed, 10 insertions, 318 deletions
diff --git a/include/trace/boot.h b/include/trace/boot.h
deleted file mode 100644
index 088ea089e31d..000000000000
--- a/include/trace/boot.h
+++ /dev/null
@@ -1,60 +0,0 @@
1#ifndef _LINUX_TRACE_BOOT_H
2#define _LINUX_TRACE_BOOT_H
3
4#include <linux/module.h>
5#include <linux/kallsyms.h>
6#include <linux/init.h>
7
8/*
9 * Structure which defines the trace of an initcall
10 * while it is called.
11 * You don't have to fill the func field since it is
12 * only used internally by the tracer.
13 */
14struct boot_trace_call {
15 pid_t caller;
16 char func[KSYM_SYMBOL_LEN];
17};
18
19/*
20 * Structure which defines the trace of an initcall
21 * while it returns.
22 */
23struct boot_trace_ret {
24 char func[KSYM_SYMBOL_LEN];
25 int result;
26 unsigned long long duration; /* nsecs */
27};
28
29#ifdef CONFIG_BOOT_TRACER
30/* Append the traces on the ring-buffer */
31extern void trace_boot_call(struct boot_trace_call *bt, initcall_t fn);
32extern void trace_boot_ret(struct boot_trace_ret *bt, initcall_t fn);
33
34/* Tells the tracer that smp_pre_initcall is finished.
35 * So we can start the tracing
36 */
37extern void start_boot_trace(void);
38
39/* Resume the tracing of other necessary events
40 * such as sched switches
41 */
42extern void enable_boot_trace(void);
43
44/* Suspend this tracing. Actually, only sched_switches tracing have
45 * to be suspended. Initcalls doesn't need it.)
46 */
47extern void disable_boot_trace(void);
48#else
49static inline
50void trace_boot_call(struct boot_trace_call *bt, initcall_t fn) { }
51
52static inline
53void trace_boot_ret(struct boot_trace_ret *bt, initcall_t fn) { }
54
55static inline void start_boot_trace(void) { }
56static inline void enable_boot_trace(void) { }
57static inline void disable_boot_trace(void) { }
58#endif /* CONFIG_BOOT_TRACER */
59
60#endif /* __LINUX_TRACE_BOOT_H */
diff --git a/init/main.c b/init/main.c
index 3bdb152f412f..94f65efdc65a 100644
--- a/init/main.c
+++ b/init/main.c
@@ -70,7 +70,6 @@
70#include <linux/sfi.h> 70#include <linux/sfi.h>
71#include <linux/shmem_fs.h> 71#include <linux/shmem_fs.h>
72#include <linux/slab.h> 72#include <linux/slab.h>
73#include <trace/boot.h>
74 73
75#include <asm/io.h> 74#include <asm/io.h>
76#include <asm/bugs.h> 75#include <asm/bugs.h>
@@ -715,38 +714,33 @@ int initcall_debug;
715core_param(initcall_debug, initcall_debug, bool, 0644); 714core_param(initcall_debug, initcall_debug, bool, 0644);
716 715
717static char msgbuf[64]; 716static char msgbuf[64];
718static struct boot_trace_call call;
719static struct boot_trace_ret ret;
720 717
721int do_one_initcall(initcall_t fn) 718int do_one_initcall(initcall_t fn)
722{ 719{
723 int count = preempt_count(); 720 int count = preempt_count();
724 ktime_t calltime, delta, rettime; 721 ktime_t calltime, delta, rettime;
722 unsigned long long duration;
723 int ret;
725 724
726 if (initcall_debug) { 725 if (initcall_debug) {
727 call.caller = task_pid_nr(current); 726 printk("calling %pF @ %i\n", fn, task_pid_nr(current));
728 printk("calling %pF @ %i\n", fn, call.caller);
729 calltime = ktime_get(); 727 calltime = ktime_get();
730 trace_boot_call(&call, fn);
731 enable_boot_trace();
732 } 728 }
733 729
734 ret.result = fn(); 730 ret = fn();
735 731
736 if (initcall_debug) { 732 if (initcall_debug) {
737 disable_boot_trace();
738 rettime = ktime_get(); 733 rettime = ktime_get();
739 delta = ktime_sub(rettime, calltime); 734 delta = ktime_sub(rettime, calltime);
740 ret.duration = (unsigned long long) ktime_to_ns(delta) >> 10; 735 duration = (unsigned long long) ktime_to_ns(delta) >> 10;
741 trace_boot_ret(&ret, fn); 736 printk("initcall %pF returned %d after %lld usecs\n", fn,
742 printk("initcall %pF returned %d after %Ld usecs\n", fn, 737 ret, duration);
743 ret.result, ret.duration);
744 } 738 }
745 739
746 msgbuf[0] = 0; 740 msgbuf[0] = 0;
747 741
748 if (ret.result && ret.result != -ENODEV && initcall_debug) 742 if (ret && ret != -ENODEV && initcall_debug)
749 sprintf(msgbuf, "error code %d ", ret.result); 743 sprintf(msgbuf, "error code %d ", ret);
750 744
751 if (preempt_count() != count) { 745 if (preempt_count() != count) {
752 strlcat(msgbuf, "preemption imbalance ", sizeof(msgbuf)); 746 strlcat(msgbuf, "preemption imbalance ", sizeof(msgbuf));
@@ -760,7 +754,7 @@ int do_one_initcall(initcall_t fn)
760 printk("initcall %pF returned with %s\n", fn, msgbuf); 754 printk("initcall %pF returned with %s\n", fn, msgbuf);
761 } 755 }
762 756
763 return ret.result; 757 return ret;
764} 758}
765 759
766 760
@@ -880,7 +874,6 @@ static int __init kernel_init(void * unused)
880 smp_prepare_cpus(setup_max_cpus); 874 smp_prepare_cpus(setup_max_cpus);
881 875
882 do_pre_smp_initcalls(); 876 do_pre_smp_initcalls();
883 start_boot_trace();
884 877
885 smp_init(); 878 smp_init();
886 sched_init_smp(); 879 sched_init_smp();
diff --git a/kernel/trace/Kconfig b/kernel/trace/Kconfig
index 8b1797c4545b..572992abc71c 100644
--- a/kernel/trace/Kconfig
+++ b/kernel/trace/Kconfig
@@ -229,23 +229,6 @@ config FTRACE_SYSCALLS
229 help 229 help
230 Basic tracer to catch the syscall entry and exit events. 230 Basic tracer to catch the syscall entry and exit events.
231 231
232config BOOT_TRACER
233 bool "Trace boot initcalls"
234 select GENERIC_TRACER
235 select CONTEXT_SWITCH_TRACER
236 help
237 This tracer helps developers to optimize boot times: it records
238 the timings of the initcalls and traces key events and the identity
239 of tasks that can cause boot delays, such as context-switches.
240
241 Its aim is to be parsed by the scripts/bootgraph.pl tool to
242 produce pretty graphics about boot inefficiencies, giving a visual
243 representation of the delays during initcalls - but the raw
244 /debug/tracing/trace text output is readable too.
245
246 You must pass in initcall_debug and ftrace=initcall to the kernel
247 command line to enable this on bootup.
248
249config TRACE_BRANCH_PROFILING 232config TRACE_BRANCH_PROFILING
250 bool 233 bool
251 select GENERIC_TRACER 234 select GENERIC_TRACER
diff --git a/kernel/trace/Makefile b/kernel/trace/Makefile
index ffb1a5b0550e..c3aaeba82372 100644
--- a/kernel/trace/Makefile
+++ b/kernel/trace/Makefile
@@ -38,7 +38,6 @@ obj-$(CONFIG_SCHED_TRACER) += trace_sched_wakeup.o
38obj-$(CONFIG_NOP_TRACER) += trace_nop.o 38obj-$(CONFIG_NOP_TRACER) += trace_nop.o
39obj-$(CONFIG_STACK_TRACER) += trace_stack.o 39obj-$(CONFIG_STACK_TRACER) += trace_stack.o
40obj-$(CONFIG_MMIOTRACE) += trace_mmiotrace.o 40obj-$(CONFIG_MMIOTRACE) += trace_mmiotrace.o
41obj-$(CONFIG_BOOT_TRACER) += trace_boot.o
42obj-$(CONFIG_FUNCTION_GRAPH_TRACER) += trace_functions_graph.o 41obj-$(CONFIG_FUNCTION_GRAPH_TRACER) += trace_functions_graph.o
43obj-$(CONFIG_TRACE_BRANCH_PROFILING) += trace_branch.o 42obj-$(CONFIG_TRACE_BRANCH_PROFILING) += trace_branch.o
44obj-$(CONFIG_KMEMTRACE) += kmemtrace.o 43obj-$(CONFIG_KMEMTRACE) += kmemtrace.o
diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c
index 55e48511d7c8..036fbc22858b 100644
--- a/kernel/trace/trace.c
+++ b/kernel/trace/trace.c
@@ -4603,9 +4603,6 @@ __init static int tracer_alloc_buffers(void)
4603 4603
4604 register_tracer(&nop_trace); 4604 register_tracer(&nop_trace);
4605 current_trace = &nop_trace; 4605 current_trace = &nop_trace;
4606#ifdef CONFIG_BOOT_TRACER
4607 register_tracer(&boot_tracer);
4608#endif
4609 /* All seems OK, enable tracing */ 4606 /* All seems OK, enable tracing */
4610 tracing_disabled = 0; 4607 tracing_disabled = 0;
4611 4608
diff --git a/kernel/trace/trace.h b/kernel/trace/trace.h
index 2cd96399463f..75a5e800a737 100644
--- a/kernel/trace/trace.h
+++ b/kernel/trace/trace.h
@@ -9,10 +9,8 @@
9#include <linux/mmiotrace.h> 9#include <linux/mmiotrace.h>
10#include <linux/tracepoint.h> 10#include <linux/tracepoint.h>
11#include <linux/ftrace.h> 11#include <linux/ftrace.h>
12#include <trace/boot.h>
13#include <linux/kmemtrace.h> 12#include <linux/kmemtrace.h>
14#include <linux/hw_breakpoint.h> 13#include <linux/hw_breakpoint.h>
15
16#include <linux/trace_seq.h> 14#include <linux/trace_seq.h>
17#include <linux/ftrace_event.h> 15#include <linux/ftrace_event.h>
18 16
@@ -29,8 +27,6 @@ enum trace_type {
29 TRACE_MMIO_RW, 27 TRACE_MMIO_RW,
30 TRACE_MMIO_MAP, 28 TRACE_MMIO_MAP,
31 TRACE_BRANCH, 29 TRACE_BRANCH,
32 TRACE_BOOT_CALL,
33 TRACE_BOOT_RET,
34 TRACE_GRAPH_RET, 30 TRACE_GRAPH_RET,
35 TRACE_GRAPH_ENT, 31 TRACE_GRAPH_ENT,
36 TRACE_USER_STACK, 32 TRACE_USER_STACK,
@@ -48,8 +44,6 @@ enum kmemtrace_type_id {
48 KMEMTRACE_TYPE_PAGES, /* __get_free_pages() and friends. */ 44 KMEMTRACE_TYPE_PAGES, /* __get_free_pages() and friends. */
49}; 45};
50 46
51extern struct tracer boot_tracer;
52
53#undef __field 47#undef __field
54#define __field(type, item) type item; 48#define __field(type, item) type item;
55 49
@@ -209,8 +203,6 @@ extern void __ftrace_bad_type(void);
209 TRACE_MMIO_RW); \ 203 TRACE_MMIO_RW); \
210 IF_ASSIGN(var, ent, struct trace_mmiotrace_map, \ 204 IF_ASSIGN(var, ent, struct trace_mmiotrace_map, \
211 TRACE_MMIO_MAP); \ 205 TRACE_MMIO_MAP); \
212 IF_ASSIGN(var, ent, struct trace_boot_call, TRACE_BOOT_CALL);\
213 IF_ASSIGN(var, ent, struct trace_boot_ret, TRACE_BOOT_RET);\
214 IF_ASSIGN(var, ent, struct trace_branch, TRACE_BRANCH); \ 206 IF_ASSIGN(var, ent, struct trace_branch, TRACE_BRANCH); \
215 IF_ASSIGN(var, ent, struct ftrace_graph_ent_entry, \ 207 IF_ASSIGN(var, ent, struct ftrace_graph_ent_entry, \
216 TRACE_GRAPH_ENT); \ 208 TRACE_GRAPH_ENT); \
diff --git a/kernel/trace/trace_boot.c b/kernel/trace/trace_boot.c
deleted file mode 100644
index c21d5f3956ad..000000000000
--- a/kernel/trace/trace_boot.c
+++ /dev/null
@@ -1,185 +0,0 @@
1/*
2 * ring buffer based initcalls tracer
3 *
4 * Copyright (C) 2008 Frederic Weisbecker <fweisbec@gmail.com>
5 *
6 */
7
8#include <linux/init.h>
9#include <linux/debugfs.h>
10#include <linux/ftrace.h>
11#include <linux/kallsyms.h>
12#include <linux/time.h>
13
14#include "trace.h"
15#include "trace_output.h"
16
17static struct trace_array *boot_trace;
18static bool pre_initcalls_finished;
19
20/* Tells the boot tracer that the pre_smp_initcalls are finished.
21 * So we are ready .
22 * It doesn't enable sched events tracing however.
23 * You have to call enable_boot_trace to do so.
24 */
25void start_boot_trace(void)
26{
27 pre_initcalls_finished = true;
28}
29
30void enable_boot_trace(void)
31{
32 if (boot_trace && pre_initcalls_finished)
33 tracing_start_sched_switch_record();
34}
35
36void disable_boot_trace(void)
37{
38 if (boot_trace && pre_initcalls_finished)
39 tracing_stop_sched_switch_record();
40}
41
42static int boot_trace_init(struct trace_array *tr)
43{
44 boot_trace = tr;
45
46 if (!tr)
47 return 0;
48
49 tracing_reset_online_cpus(tr);
50
51 tracing_sched_switch_assign_trace(tr);
52 return 0;
53}
54
55static enum print_line_t
56initcall_call_print_line(struct trace_iterator *iter)
57{
58 struct trace_entry *entry = iter->ent;
59 struct trace_seq *s = &iter->seq;
60 struct trace_boot_call *field;
61 struct boot_trace_call *call;
62 u64 ts;
63 unsigned long nsec_rem;
64 int ret;
65
66 trace_assign_type(field, entry);
67 call = &field->boot_call;
68 ts = iter->ts;
69 nsec_rem = do_div(ts, NSEC_PER_SEC);
70
71 ret = trace_seq_printf(s, "[%5ld.%09ld] calling %s @ %i\n",
72 (unsigned long)ts, nsec_rem, call->func, call->caller);
73
74 if (!ret)
75 return TRACE_TYPE_PARTIAL_LINE;
76 else
77 return TRACE_TYPE_HANDLED;
78}
79
80static enum print_line_t
81initcall_ret_print_line(struct trace_iterator *iter)
82{
83 struct trace_entry *entry = iter->ent;
84 struct trace_seq *s = &iter->seq;
85 struct trace_boot_ret *field;
86 struct boot_trace_ret *init_ret;
87 u64 ts;
88 unsigned long nsec_rem;
89 int ret;
90
91 trace_assign_type(field, entry);
92 init_ret = &field->boot_ret;
93 ts = iter->ts;
94 nsec_rem = do_div(ts, NSEC_PER_SEC);
95
96 ret = trace_seq_printf(s, "[%5ld.%09ld] initcall %s "
97 "returned %d after %llu msecs\n",
98 (unsigned long) ts,
99 nsec_rem,
100 init_ret->func, init_ret->result, init_ret->duration);
101
102 if (!ret)
103 return TRACE_TYPE_PARTIAL_LINE;
104 else
105 return TRACE_TYPE_HANDLED;
106}
107
108static enum print_line_t initcall_print_line(struct trace_iterator *iter)
109{
110 struct trace_entry *entry = iter->ent;
111
112 switch (entry->type) {
113 case TRACE_BOOT_CALL:
114 return initcall_call_print_line(iter);
115 case TRACE_BOOT_RET:
116 return initcall_ret_print_line(iter);
117 default:
118 return TRACE_TYPE_UNHANDLED;
119 }
120}
121
122struct tracer boot_tracer __read_mostly =
123{
124 .name = "initcall",
125 .init = boot_trace_init,
126 .reset = tracing_reset_online_cpus,
127 .print_line = initcall_print_line,
128};
129
130void trace_boot_call(struct boot_trace_call *bt, initcall_t fn)
131{
132 struct ftrace_event_call *call = &event_boot_call;
133 struct ring_buffer_event *event;
134 struct ring_buffer *buffer;
135 struct trace_boot_call *entry;
136 struct trace_array *tr = boot_trace;
137
138 if (!tr || !pre_initcalls_finished)
139 return;
140
141 /* Get its name now since this function could
142 * disappear because it is in the .init section.
143 */
144 sprint_symbol(bt->func, (unsigned long)fn);
145 preempt_disable();
146
147 buffer = tr->buffer;
148 event = trace_buffer_lock_reserve(buffer, TRACE_BOOT_CALL,
149 sizeof(*entry), 0, 0);
150 if (!event)
151 goto out;
152 entry = ring_buffer_event_data(event);
153 entry->boot_call = *bt;
154 if (!filter_check_discard(call, entry, buffer, event))
155 trace_buffer_unlock_commit(buffer, event, 0, 0);
156 out:
157 preempt_enable();
158}
159
160void trace_boot_ret(struct boot_trace_ret *bt, initcall_t fn)
161{
162 struct ftrace_event_call *call = &event_boot_ret;
163 struct ring_buffer_event *event;
164 struct ring_buffer *buffer;
165 struct trace_boot_ret *entry;
166 struct trace_array *tr = boot_trace;
167
168 if (!tr || !pre_initcalls_finished)
169 return;
170
171 sprint_symbol(bt->func, (unsigned long)fn);
172 preempt_disable();
173
174 buffer = tr->buffer;
175 event = trace_buffer_lock_reserve(buffer, TRACE_BOOT_RET,
176 sizeof(*entry), 0, 0);
177 if (!event)
178 goto out;
179 entry = ring_buffer_event_data(event);
180 entry->boot_ret = *bt;
181 if (!filter_check_discard(call, entry, buffer, event))
182 trace_buffer_unlock_commit(buffer, event, 0, 0);
183 out:
184 preempt_enable();
185}
diff --git a/kernel/trace/trace_entries.h b/kernel/trace/trace_entries.h
index dc008c1240da..c293364c984f 100644
--- a/kernel/trace/trace_entries.h
+++ b/kernel/trace/trace_entries.h
@@ -271,33 +271,6 @@ FTRACE_ENTRY(mmiotrace_map, trace_mmiotrace_map,
271 __entry->map_id, __entry->opcode) 271 __entry->map_id, __entry->opcode)
272); 272);
273 273
274FTRACE_ENTRY(boot_call, trace_boot_call,
275
276 TRACE_BOOT_CALL,
277
278 F_STRUCT(
279 __field_struct( struct boot_trace_call, boot_call )
280 __field_desc( pid_t, boot_call, caller )
281 __array_desc( char, boot_call, func, KSYM_SYMBOL_LEN)
282 ),
283
284 F_printk("%d %s", __entry->caller, __entry->func)
285);
286
287FTRACE_ENTRY(boot_ret, trace_boot_ret,
288
289 TRACE_BOOT_RET,
290
291 F_STRUCT(
292 __field_struct( struct boot_trace_ret, boot_ret )
293 __array_desc( char, boot_ret, func, KSYM_SYMBOL_LEN)
294 __field_desc( int, boot_ret, result )
295 __field_desc( unsigned long, boot_ret, duration )
296 ),
297
298 F_printk("%s %d %lx",
299 __entry->func, __entry->result, __entry->duration)
300);
301 274
302#define TRACE_FUNC_SIZE 30 275#define TRACE_FUNC_SIZE 30
303#define TRACE_FILE_SIZE 20 276#define TRACE_FILE_SIZE 20