diff options
Diffstat (limited to 'kernel/trace/trace_boot.c')
| -rw-r--r-- | kernel/trace/trace_boot.c | 123 |
1 files changed, 93 insertions, 30 deletions
diff --git a/kernel/trace/trace_boot.c b/kernel/trace/trace_boot.c index 8f71915e8bb..cb333b7fd11 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(); |
