diff options
Diffstat (limited to 'kernel/trace')
-rw-r--r-- | kernel/trace/trace.h | 17 | ||||
-rw-r--r-- | kernel/trace/trace_boot.c | 123 |
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 | ||
126 | struct trace_boot { | 127 | struct 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 | |||
132 | struct 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 | ||
61 | static enum print_line_t initcall_print_line(struct trace_iterator *iter) | 61 | static enum print_line_t |
62 | initcall_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 | |||
86 | static enum print_line_t | ||
87 | initcall_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 | |||
114 | static 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 | ||
92 | struct tracer boot_tracer __read_mostly = | 128 | struct 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 | ||
100 | void trace_boot(struct boot_trace *it, initcall_t fn) | 136 | void 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 | |||
168 | void 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(); |