aboutsummaryrefslogtreecommitdiffstats
path: root/kernel
diff options
context:
space:
mode:
Diffstat (limited to 'kernel')
-rw-r--r--kernel/trace/trace.h17
-rw-r--r--kernel/trace/trace_boot.c123
2 files changed, 105 insertions, 35 deletions
diff --git a/kernel/trace/trace.h b/kernel/trace/trace.h
index f69a5199596b..b5f91f198fd4 100644
--- a/kernel/trace/trace.h
+++ b/kernel/trace/trace.h
@@ -22,7 +22,8 @@ enum trace_type {
22 TRACE_SPECIAL, 22 TRACE_SPECIAL,
23 TRACE_MMIO_RW, 23 TRACE_MMIO_RW,
24 TRACE_MMIO_MAP, 24 TRACE_MMIO_MAP,
25 TRACE_BOOT, 25 TRACE_BOOT_CALL,
26 TRACE_BOOT_RET,
26 TRACE_FN_RET, 27 TRACE_FN_RET,
27 28
28 __TRACE_LAST_TYPE 29 __TRACE_LAST_TYPE
@@ -123,9 +124,14 @@ struct trace_mmiotrace_map {
123 struct mmiotrace_map map; 124 struct mmiotrace_map map;
124}; 125};
125 126
126struct trace_boot { 127struct trace_boot_call {
127 struct trace_entry ent; 128 struct trace_entry ent;
128 struct boot_trace initcall; 129 struct boot_trace_call boot_call;
130};
131
132struct trace_boot_ret {
133 struct trace_entry ent;
134 struct boot_trace_ret boot_ret;
129}; 135};
130 136
131/* 137/*
@@ -228,8 +234,9 @@ extern void __ftrace_bad_type(void);
228 TRACE_MMIO_RW); \ 234 TRACE_MMIO_RW); \
229 IF_ASSIGN(var, ent, struct trace_mmiotrace_map, \ 235 IF_ASSIGN(var, ent, struct trace_mmiotrace_map, \
230 TRACE_MMIO_MAP); \ 236 TRACE_MMIO_MAP); \
231 IF_ASSIGN(var, ent, struct trace_boot, TRACE_BOOT); \ 237 IF_ASSIGN(var, ent, struct trace_boot_call, TRACE_BOOT_CALL);\
232 IF_ASSIGN(var, ent, struct ftrace_ret_entry, TRACE_FN_RET); \ 238 IF_ASSIGN(var, ent, struct trace_boot_ret, TRACE_BOOT_RET);\
239 IF_ASSIGN(var, ent, struct ftrace_ret_entry, TRACE_FN_RET);\
233 __ftrace_bad_type(); \ 240 __ftrace_bad_type(); \
234 } while (0) 241 } while (0)
235 242
diff --git a/kernel/trace/trace_boot.c b/kernel/trace/trace_boot.c
index 8f71915e8bb4..cb333b7fd113 100644
--- a/kernel/trace/trace_boot.c
+++ b/kernel/trace/trace_boot.c
@@ -58,35 +58,71 @@ static void boot_trace_init(struct trace_array *tr)
58 tracing_sched_switch_assign_trace(tr); 58 tracing_sched_switch_assign_trace(tr);
59} 59}
60 60
61static enum print_line_t initcall_print_line(struct trace_iterator *iter) 61static enum print_line_t
62initcall_call_print_line(struct trace_iterator *iter)
62{ 63{
64 struct trace_entry *entry = iter->ent;
65 struct trace_seq *s = &iter->seq;
66 struct trace_boot_call *field;
67 struct boot_trace_call *call;
68 u64 ts;
69 unsigned long nsec_rem;
63 int ret; 70 int ret;
71
72 trace_assign_type(field, entry);
73 call = &field->boot_call;
74 ts = iter->ts;
75 nsec_rem = do_div(ts, 1000000000);
76
77 ret = trace_seq_printf(s, "[%5ld.%09ld] calling %s @ %i\n",
78 (unsigned long)ts, nsec_rem, call->func, call->caller);
79
80 if (!ret)
81 return TRACE_TYPE_PARTIAL_LINE;
82 else
83 return TRACE_TYPE_HANDLED;
84}
85
86static enum print_line_t
87initcall_ret_print_line(struct trace_iterator *iter)
88{
64 struct trace_entry *entry = iter->ent; 89 struct trace_entry *entry = iter->ent;
65 struct trace_boot *field = (struct trace_boot *)entry;
66 struct boot_trace *it = &field->initcall;
67 struct trace_seq *s = &iter->seq; 90 struct trace_seq *s = &iter->seq;
68 struct timespec calltime = ktime_to_timespec(it->calltime); 91 struct trace_boot_ret *field;
69 struct timespec rettime = ktime_to_timespec(it->rettime); 92 struct boot_trace_ret *init_ret;
70 93 u64 ts;
71 if (entry->type == TRACE_BOOT) { 94 unsigned long nsec_rem;
72 ret = trace_seq_printf(s, "[%5ld.%09ld] calling %s @ %i\n", 95 int ret;
73 calltime.tv_sec, 96
74 calltime.tv_nsec, 97 trace_assign_type(field, entry);
75 it->func, it->caller); 98 init_ret = &field->boot_ret;
76 if (!ret) 99 ts = iter->ts;
77 return TRACE_TYPE_PARTIAL_LINE; 100 nsec_rem = do_div(ts, 1000000000);
78 101
79 ret = trace_seq_printf(s, "[%5ld.%09ld] initcall %s " 102 ret = trace_seq_printf(s, "[%5ld.%09ld] initcall %s "
80 "returned %d after %lld msecs\n", 103 "returned %d after %llu msecs\n",
81 rettime.tv_sec, 104 (unsigned long) ts,
82 rettime.tv_nsec, 105 nsec_rem,
83 it->func, it->result, it->duration); 106 init_ret->func, init_ret->result, init_ret->duration);
84 107
85 if (!ret) 108 if (!ret)
86 return TRACE_TYPE_PARTIAL_LINE; 109 return TRACE_TYPE_PARTIAL_LINE;
110 else
87 return TRACE_TYPE_HANDLED; 111 return TRACE_TYPE_HANDLED;
112}
113
114static enum print_line_t initcall_print_line(struct trace_iterator *iter)
115{
116 struct trace_entry *entry = iter->ent;
117
118 switch (entry->type) {
119 case TRACE_BOOT_CALL:
120 return initcall_call_print_line(iter);
121 case TRACE_BOOT_RET:
122 return initcall_ret_print_line(iter);
123 default:
124 return TRACE_TYPE_UNHANDLED;
88 } 125 }
89 return TRACE_TYPE_UNHANDLED;
90} 126}
91 127
92struct tracer boot_tracer __read_mostly = 128struct tracer boot_tracer __read_mostly =
@@ -97,11 +133,10 @@ struct tracer boot_tracer __read_mostly =
97 .print_line = initcall_print_line, 133 .print_line = initcall_print_line,
98}; 134};
99 135
100void trace_boot(struct boot_trace *it, initcall_t fn) 136void trace_boot_call(struct boot_trace_call *bt, initcall_t fn)
101{ 137{
102 struct ring_buffer_event *event; 138 struct ring_buffer_event *event;
103 struct trace_boot *entry; 139 struct trace_boot_call *entry;
104 struct trace_array_cpu *data;
105 unsigned long irq_flags; 140 unsigned long irq_flags;
106 struct trace_array *tr = boot_trace; 141 struct trace_array *tr = boot_trace;
107 142
@@ -111,9 +146,37 @@ void trace_boot(struct boot_trace *it, initcall_t fn)
111 /* Get its name now since this function could 146 /* Get its name now since this function could
112 * disappear because it is in the .init section. 147 * disappear because it is in the .init section.
113 */ 148 */
114 sprint_symbol(it->func, (unsigned long)fn); 149 sprint_symbol(bt->func, (unsigned long)fn);
150 preempt_disable();
151
152 event = ring_buffer_lock_reserve(tr->buffer, sizeof(*entry),
153 &irq_flags);
154 if (!event)
155 goto out;
156 entry = ring_buffer_event_data(event);
157 tracing_generic_entry_update(&entry->ent, 0, 0);
158 entry->ent.type = TRACE_BOOT_CALL;
159 entry->boot_call = *bt;
160 ring_buffer_unlock_commit(tr->buffer, event, irq_flags);
161
162 trace_wake_up();
163
164 out:
165 preempt_enable();
166}
167
168void trace_boot_ret(struct boot_trace_ret *bt, initcall_t fn)
169{
170 struct ring_buffer_event *event;
171 struct trace_boot_ret *entry;
172 unsigned long irq_flags;
173 struct trace_array *tr = boot_trace;
174
175 if (!pre_initcalls_finished)
176 return;
177
178 sprint_symbol(bt->func, (unsigned long)fn);
115 preempt_disable(); 179 preempt_disable();
116 data = tr->data[smp_processor_id()];
117 180
118 event = ring_buffer_lock_reserve(tr->buffer, sizeof(*entry), 181 event = ring_buffer_lock_reserve(tr->buffer, sizeof(*entry),
119 &irq_flags); 182 &irq_flags);
@@ -121,8 +184,8 @@ void trace_boot(struct boot_trace *it, initcall_t fn)
121 goto out; 184 goto out;
122 entry = ring_buffer_event_data(event); 185 entry = ring_buffer_event_data(event);
123 tracing_generic_entry_update(&entry->ent, 0, 0); 186 tracing_generic_entry_update(&entry->ent, 0, 0);
124 entry->ent.type = TRACE_BOOT; 187 entry->ent.type = TRACE_BOOT_RET;
125 entry->initcall = *it; 188 entry->boot_ret = *bt;
126 ring_buffer_unlock_commit(tr->buffer, event, irq_flags); 189 ring_buffer_unlock_commit(tr->buffer, event, irq_flags);
127 190
128 trace_wake_up(); 191 trace_wake_up();