diff options
Diffstat (limited to 'kernel/trace/trace_branch.c')
| -rw-r--r-- | kernel/trace/trace_branch.c | 278 |
1 files changed, 158 insertions, 120 deletions
diff --git a/kernel/trace/trace_branch.c b/kernel/trace/trace_branch.c index 6c00feb3bac..ad8c22efff4 100644 --- a/kernel/trace/trace_branch.c +++ b/kernel/trace/trace_branch.c | |||
| @@ -14,12 +14,17 @@ | |||
| 14 | #include <linux/hash.h> | 14 | #include <linux/hash.h> |
| 15 | #include <linux/fs.h> | 15 | #include <linux/fs.h> |
| 16 | #include <asm/local.h> | 16 | #include <asm/local.h> |
| 17 | |||
| 17 | #include "trace.h" | 18 | #include "trace.h" |
| 19 | #include "trace_stat.h" | ||
| 20 | #include "trace_output.h" | ||
| 18 | 21 | ||
| 19 | #ifdef CONFIG_BRANCH_TRACER | 22 | #ifdef CONFIG_BRANCH_TRACER |
| 20 | 23 | ||
| 24 | static struct tracer branch_trace; | ||
| 21 | static int branch_tracing_enabled __read_mostly; | 25 | static int branch_tracing_enabled __read_mostly; |
| 22 | static DEFINE_MUTEX(branch_tracing_mutex); | 26 | static DEFINE_MUTEX(branch_tracing_mutex); |
| 27 | |||
| 23 | static struct trace_array *branch_tracer; | 28 | static struct trace_array *branch_tracer; |
| 24 | 29 | ||
| 25 | static void | 30 | static void |
| @@ -28,7 +33,7 @@ probe_likely_condition(struct ftrace_branch_data *f, int val, int expect) | |||
| 28 | struct trace_array *tr = branch_tracer; | 33 | struct trace_array *tr = branch_tracer; |
| 29 | struct ring_buffer_event *event; | 34 | struct ring_buffer_event *event; |
| 30 | struct trace_branch *entry; | 35 | struct trace_branch *entry; |
| 31 | unsigned long flags, irq_flags; | 36 | unsigned long flags; |
| 32 | int cpu, pc; | 37 | int cpu, pc; |
| 33 | const char *p; | 38 | const char *p; |
| 34 | 39 | ||
| @@ -47,15 +52,13 @@ probe_likely_condition(struct ftrace_branch_data *f, int val, int expect) | |||
| 47 | if (atomic_inc_return(&tr->data[cpu]->disabled) != 1) | 52 | if (atomic_inc_return(&tr->data[cpu]->disabled) != 1) |
| 48 | goto out; | 53 | goto out; |
| 49 | 54 | ||
| 50 | event = ring_buffer_lock_reserve(tr->buffer, sizeof(*entry), | 55 | pc = preempt_count(); |
| 51 | &irq_flags); | 56 | event = trace_buffer_lock_reserve(tr, TRACE_BRANCH, |
| 57 | sizeof(*entry), flags, pc); | ||
| 52 | if (!event) | 58 | if (!event) |
| 53 | goto out; | 59 | goto out; |
| 54 | 60 | ||
| 55 | pc = preempt_count(); | ||
| 56 | entry = ring_buffer_event_data(event); | 61 | entry = ring_buffer_event_data(event); |
| 57 | tracing_generic_entry_update(&entry->ent, flags, pc); | ||
| 58 | entry->ent.type = TRACE_BRANCH; | ||
| 59 | 62 | ||
| 60 | /* Strip off the path, only save the file */ | 63 | /* Strip off the path, only save the file */ |
| 61 | p = f->file + strlen(f->file); | 64 | p = f->file + strlen(f->file); |
| @@ -70,7 +73,7 @@ probe_likely_condition(struct ftrace_branch_data *f, int val, int expect) | |||
| 70 | entry->line = f->line; | 73 | entry->line = f->line; |
| 71 | entry->correct = val == expect; | 74 | entry->correct = val == expect; |
| 72 | 75 | ||
| 73 | ring_buffer_unlock_commit(tr->buffer, event, irq_flags); | 76 | ring_buffer_unlock_commit(tr->buffer, event); |
| 74 | 77 | ||
| 75 | out: | 78 | out: |
| 76 | atomic_dec(&tr->data[cpu]->disabled); | 79 | atomic_dec(&tr->data[cpu]->disabled); |
| @@ -88,8 +91,6 @@ void trace_likely_condition(struct ftrace_branch_data *f, int val, int expect) | |||
| 88 | 91 | ||
| 89 | int enable_branch_tracing(struct trace_array *tr) | 92 | int enable_branch_tracing(struct trace_array *tr) |
| 90 | { | 93 | { |
| 91 | int ret = 0; | ||
| 92 | |||
| 93 | mutex_lock(&branch_tracing_mutex); | 94 | mutex_lock(&branch_tracing_mutex); |
| 94 | branch_tracer = tr; | 95 | branch_tracer = tr; |
| 95 | /* | 96 | /* |
| @@ -100,7 +101,7 @@ int enable_branch_tracing(struct trace_array *tr) | |||
| 100 | branch_tracing_enabled++; | 101 | branch_tracing_enabled++; |
| 101 | mutex_unlock(&branch_tracing_mutex); | 102 | mutex_unlock(&branch_tracing_mutex); |
| 102 | 103 | ||
| 103 | return ret; | 104 | return 0; |
| 104 | } | 105 | } |
| 105 | 106 | ||
| 106 | void disable_branch_tracing(void) | 107 | void disable_branch_tracing(void) |
| @@ -128,11 +129,6 @@ static void stop_branch_trace(struct trace_array *tr) | |||
| 128 | 129 | ||
| 129 | static int branch_trace_init(struct trace_array *tr) | 130 | static int branch_trace_init(struct trace_array *tr) |
| 130 | { | 131 | { |
| 131 | int cpu; | ||
| 132 | |||
| 133 | for_each_online_cpu(cpu) | ||
| 134 | tracing_reset(tr, cpu); | ||
| 135 | |||
| 136 | start_branch_trace(tr); | 132 | start_branch_trace(tr); |
| 137 | return 0; | 133 | return 0; |
| 138 | } | 134 | } |
| @@ -142,22 +138,53 @@ static void branch_trace_reset(struct trace_array *tr) | |||
| 142 | stop_branch_trace(tr); | 138 | stop_branch_trace(tr); |
| 143 | } | 139 | } |
| 144 | 140 | ||
| 145 | struct tracer branch_trace __read_mostly = | 141 | static enum print_line_t trace_branch_print(struct trace_iterator *iter, |
| 142 | int flags) | ||
| 143 | { | ||
| 144 | struct trace_branch *field; | ||
| 145 | |||
| 146 | trace_assign_type(field, iter->ent); | ||
| 147 | |||
| 148 | if (trace_seq_printf(&iter->seq, "[%s] %s:%s:%d\n", | ||
| 149 | field->correct ? " ok " : " MISS ", | ||
| 150 | field->func, | ||
| 151 | field->file, | ||
| 152 | field->line)) | ||
| 153 | return TRACE_TYPE_PARTIAL_LINE; | ||
| 154 | |||
| 155 | return TRACE_TYPE_HANDLED; | ||
| 156 | } | ||
| 157 | |||
| 158 | |||
| 159 | static struct trace_event trace_branch_event = { | ||
| 160 | .type = TRACE_BRANCH, | ||
| 161 | .trace = trace_branch_print, | ||
| 162 | }; | ||
| 163 | |||
| 164 | static struct tracer branch_trace __read_mostly = | ||
| 146 | { | 165 | { |
| 147 | .name = "branch", | 166 | .name = "branch", |
| 148 | .init = branch_trace_init, | 167 | .init = branch_trace_init, |
| 149 | .reset = branch_trace_reset, | 168 | .reset = branch_trace_reset, |
| 150 | #ifdef CONFIG_FTRACE_SELFTEST | 169 | #ifdef CONFIG_FTRACE_SELFTEST |
| 151 | .selftest = trace_selftest_startup_branch, | 170 | .selftest = trace_selftest_startup_branch, |
| 152 | #endif | 171 | #endif /* CONFIG_FTRACE_SELFTEST */ |
| 153 | }; | 172 | }; |
| 154 | 173 | ||
| 155 | __init static int init_branch_trace(void) | 174 | __init static int init_branch_tracer(void) |
| 156 | { | 175 | { |
| 176 | int ret; | ||
| 177 | |||
| 178 | ret = register_ftrace_event(&trace_branch_event); | ||
| 179 | if (!ret) { | ||
| 180 | printk(KERN_WARNING "Warning: could not register " | ||
| 181 | "branch events\n"); | ||
| 182 | return 1; | ||
| 183 | } | ||
| 157 | return register_tracer(&branch_trace); | 184 | return register_tracer(&branch_trace); |
| 158 | } | 185 | } |
| 186 | device_initcall(init_branch_tracer); | ||
| 159 | 187 | ||
| 160 | device_initcall(init_branch_trace); | ||
| 161 | #else | 188 | #else |
| 162 | static inline | 189 | static inline |
| 163 | void trace_likely_condition(struct ftrace_branch_data *f, int val, int expect) | 190 | void trace_likely_condition(struct ftrace_branch_data *f, int val, int expect) |
| @@ -183,66 +210,39 @@ void ftrace_likely_update(struct ftrace_branch_data *f, int val, int expect) | |||
| 183 | } | 210 | } |
| 184 | EXPORT_SYMBOL(ftrace_likely_update); | 211 | EXPORT_SYMBOL(ftrace_likely_update); |
| 185 | 212 | ||
| 186 | struct ftrace_pointer { | 213 | extern unsigned long __start_annotated_branch_profile[]; |
| 187 | void *start; | 214 | extern unsigned long __stop_annotated_branch_profile[]; |
| 188 | void *stop; | ||
| 189 | int hit; | ||
| 190 | }; | ||
| 191 | 215 | ||
| 192 | static void * | 216 | static int annotated_branch_stat_headers(struct seq_file *m) |
| 193 | t_next(struct seq_file *m, void *v, loff_t *pos) | ||
| 194 | { | 217 | { |
| 195 | const struct ftrace_pointer *f = m->private; | 218 | seq_printf(m, " correct incorrect %% "); |
| 196 | struct ftrace_branch_data *p = v; | 219 | seq_printf(m, " Function " |
| 197 | 220 | " File Line\n" | |
| 198 | (*pos)++; | 221 | " ------- --------- - " |
| 199 | 222 | " -------- " | |
| 200 | if (v == (void *)1) | 223 | " ---- ----\n"); |
| 201 | return f->start; | 224 | return 0; |
| 202 | |||
| 203 | ++p; | ||
| 204 | |||
| 205 | if ((void *)p >= (void *)f->stop) | ||
| 206 | return NULL; | ||
| 207 | |||
| 208 | return p; | ||
| 209 | } | 225 | } |
| 210 | 226 | ||
| 211 | static void *t_start(struct seq_file | ||
