Blame view
kernel/trace/trace_mmiotrace.c
8.63 KB
b24413180 License cleanup: ... |
1 |
// SPDX-License-Identifier: GPL-2.0 |
f984b51e0 ftrace: add mmiot... |
2 3 4 5 6 7 8 9 10 11 |
/* * Memory mapped I/O tracing * * Copyright (C) 2008 Pekka Paalanen <pq@iki.fi> */ #define DEBUG 1 #include <linux/kernel.h> #include <linux/mmiotrace.h> |
138295373 ftrace: mmiotrace... |
12 |
#include <linux/pci.h> |
5a0e3ad6a include cleanup: ... |
13 |
#include <linux/slab.h> |
a5dec5573 tracing: use macr... |
14 |
#include <linux/time.h> |
60063497a atomic: use <linu... |
15 |
#include <linux/atomic.h> |
f984b51e0 ftrace: add mmiot... |
16 17 |
#include "trace.h" |
f0868d1e2 ftrace: set up tr... |
18 |
#include "trace_output.h" |
f984b51e0 ftrace: add mmiot... |
19 |
|
d0a7e8ca5 mmiotrace: print ... |
20 21 22 |
struct header_iter { struct pci_dev *dev; }; |
f984b51e0 ftrace: add mmiot... |
23 |
static struct trace_array *mmio_trace_array; |
2039238b7 mmiotrace: print ... |
24 |
static bool overrun_detected; |
7ee1768dd x86, mmiotrace: f... |
25 |
static unsigned long prev_overruns; |
173ed24ee mmiotrace: count ... |
26 |
static atomic_t dropped_count; |
f984b51e0 ftrace: add mmiot... |
27 |
|
bd8ac686c ftrace: mmiotrace... |
28 29 |
static void mmio_reset_data(struct trace_array *tr) { |
2039238b7 mmiotrace: print ... |
30 |
overrun_detected = false; |
7ee1768dd x86, mmiotrace: f... |
31 |
prev_overruns = 0; |
bd8ac686c ftrace: mmiotrace... |
32 |
|
12883efb6 tracing: Consolid... |
33 |
tracing_reset_online_cpus(&tr->trace_buffer); |
bd8ac686c ftrace: mmiotrace... |
34 |
} |
f984b51e0 ftrace: add mmiot... |
35 |
|
1c80025a4 tracing/ftrace: c... |
36 |
static int mmio_trace_init(struct trace_array *tr) |
f984b51e0 ftrace: add mmiot... |
37 38 39 40 |
{ pr_debug("in %s ", __func__); mmio_trace_array = tr; |
c76f06945 ftrace: remove tr... |
41 42 43 |
mmio_reset_data(tr); enable_mmiotrace(); |
1c80025a4 tracing/ftrace: c... |
44 |
return 0; |
f984b51e0 ftrace: add mmiot... |
45 46 47 48 49 50 |
} static void mmio_trace_reset(struct trace_array *tr) { pr_debug("in %s ", __func__); |
c76f06945 ftrace: remove tr... |
51 52 |
disable_mmiotrace(); |
bd8ac686c ftrace: mmiotrace... |
53 54 |
mmio_reset_data(tr); mmio_trace_array = NULL; |
f984b51e0 ftrace: add mmiot... |
55 |
} |
bbf5b1a0c ftrace: remove ct... |
56 |
static void mmio_trace_start(struct trace_array *tr) |
f984b51e0 ftrace: add mmiot... |
57 58 59 |
{ pr_debug("in %s ", __func__); |
bbf5b1a0c ftrace: remove ct... |
60 |
mmio_reset_data(tr); |
bd8ac686c ftrace: mmiotrace... |
61 |
} |
a72e10afa tracing: Do not c... |
62 |
static void mmio_print_pcidev(struct trace_seq *s, const struct pci_dev *dev) |
138295373 ftrace: mmiotrace... |
63 |
{ |
138295373 ftrace: mmiotrace... |
64 65 66 |
int i; resource_size_t start, end; const struct pci_driver *drv = pci_dev_driver(dev); |
a72e10afa tracing: Do not c... |
67 68 69 |
trace_seq_printf(s, "PCIDEV %02x%02x %04x%04x %x", dev->bus->number, dev->devfn, dev->vendor, dev->device, dev->irq); |
138295373 ftrace: mmiotrace... |
70 |
for (i = 0; i < 7; i++) { |
9a51933e3 tracing: Expose C... |
71 |
start = dev->resource[i].start; |
a72e10afa tracing: Do not c... |
72 |
trace_seq_printf(s, " %llx", |
138295373 ftrace: mmiotrace... |
73 74 75 76 |
(unsigned long long)(start | (dev->resource[i].flags & PCI_REGION_FLAG_MASK))); } for (i = 0; i < 7; i++) { |
9a51933e3 tracing: Expose C... |
77 78 |
start = dev->resource[i].start; end = dev->resource[i].end; |
a72e10afa tracing: Do not c... |
79 |
trace_seq_printf(s, " %llx", |
138295373 ftrace: mmiotrace... |
80 81 82 83 |
dev->resource[i].start < dev->resource[i].end ? (unsigned long long)(end - start) + 1 : 0); } if (drv) |
a72e10afa tracing: Do not c... |
84 85 |
trace_seq_printf(s, " %s ", drv->name); |
138295373 ftrace: mmiotrace... |
86 |
else |
a72e10afa tracing: Do not c... |
87 88 |
trace_seq_puts(s, " "); |
138295373 ftrace: mmiotrace... |
89 |
} |
d0a7e8ca5 mmiotrace: print ... |
90 91 92 93 94 95 96 97 98 |
static void destroy_header_iter(struct header_iter *hiter) { if (!hiter) return; pci_dev_put(hiter->dev); kfree(hiter); } static void mmio_pipe_open(struct trace_iterator *iter) |
bd8ac686c ftrace: mmiotrace... |
99 |
{ |
d0a7e8ca5 mmiotrace: print ... |
100 |
struct header_iter *hiter; |
bd8ac686c ftrace: mmiotrace... |
101 |
struct trace_seq *s = &iter->seq; |
138295373 ftrace: mmiotrace... |
102 |
|
146c3442f tracing: Use trac... |
103 104 |
trace_seq_puts(s, "VERSION 20070824 "); |
138295373 ftrace: mmiotrace... |
105 |
|
d0a7e8ca5 mmiotrace: print ... |
106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 |
hiter = kzalloc(sizeof(*hiter), GFP_KERNEL); if (!hiter) return; hiter->dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, NULL); iter->private = hiter; } /* XXX: This is not called when the pipe is closed! */ static void mmio_close(struct trace_iterator *iter) { struct header_iter *hiter = iter->private; destroy_header_iter(hiter); iter->private = NULL; } |
2039238b7 mmiotrace: print ... |
121 122 |
static unsigned long count_overruns(struct trace_iterator *iter) { |
173ed24ee mmiotrace: count ... |
123 |
unsigned long cnt = atomic_xchg(&dropped_count, 0); |
12883efb6 tracing: Consolid... |
124 |
unsigned long over = ring_buffer_overruns(iter->trace_buffer->buffer); |
7ee1768dd x86, mmiotrace: f... |
125 126 |
if (over > prev_overruns) |
173ed24ee mmiotrace: count ... |
127 |
cnt += over - prev_overruns; |
7ee1768dd x86, mmiotrace: f... |
128 |
prev_overruns = over; |
2039238b7 mmiotrace: print ... |
129 130 |
return cnt; } |
d0a7e8ca5 mmiotrace: print ... |
131 132 133 134 135 136 |
static ssize_t mmio_read(struct trace_iterator *iter, struct file *filp, char __user *ubuf, size_t cnt, loff_t *ppos) { ssize_t ret; struct header_iter *hiter = iter->private; struct trace_seq *s = &iter->seq; |
2039238b7 mmiotrace: print ... |
137 138 139 140 141 142 143 144 |
unsigned long n; n = count_overruns(iter); if (n) { /* XXX: This is later than where events were lost. */ trace_seq_printf(s, "MARK 0.000000 Lost %lu events. ", n); if (!overrun_detected) |
a395d6a7e kernel/...: conve... |
145 146 |
pr_warn("mmiotrace has lost events "); |
2039238b7 mmiotrace: print ... |
147 148 149 |
overrun_detected = true; goto print_out; } |
d0a7e8ca5 mmiotrace: print ... |
150 151 152 153 154 155 156 157 158 159 160 |
if (!hiter) return 0; mmio_print_pcidev(s, hiter->dev); hiter->dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, hiter->dev); if (!hiter->dev) { destroy_header_iter(hiter); iter->private = NULL; } |
2039238b7 mmiotrace: print ... |
161 |
print_out: |
d0a7e8ca5 mmiotrace: print ... |
162 163 |
ret = trace_seq_to_user(s, ubuf, cnt); return (ret == -EBUSY) ? 0 : ret; |
bd8ac686c ftrace: mmiotrace... |
164 |
} |
07f4e4f79 tracing/ftrace: a... |
165 |
static enum print_line_t mmio_print_rw(struct trace_iterator *iter) |
bd8ac686c ftrace: mmiotrace... |
166 167 |
{ struct trace_entry *entry = iter->ent; |
7104f300c ftrace: type cast... |
168 169 |
struct trace_mmiotrace_rw *field; struct mmiotrace_rw *rw; |
bd8ac686c ftrace: mmiotrace... |
170 |
struct trace_seq *s = &iter->seq; |
3928a8a2d ftrace: make work... |
171 |
unsigned long long t = ns2usecs(iter->ts); |
a5dec5573 tracing: use macr... |
172 |
unsigned long usec_rem = do_div(t, USEC_PER_SEC); |
bd8ac686c ftrace: mmiotrace... |
173 |
unsigned secs = (unsigned long)t; |
bd8ac686c ftrace: mmiotrace... |
174 |
|
7104f300c ftrace: type cast... |
175 176 |
trace_assign_type(field, entry); rw = &field->rw; |
777e208d4 ftrace: take adva... |
177 |
switch (rw->opcode) { |
bd8ac686c ftrace: mmiotrace... |
178 |
case MMIO_READ: |
a72e10afa tracing: Do not c... |
179 |
trace_seq_printf(s, |
5e4abc983 trace: clean up f... |
180 181 |
"R %d %u.%06lu %d 0x%llx 0x%lx 0x%lx %d ", |
dee310d0a x86 mmiotrace: us... |
182 183 |
rw->width, secs, usec_rem, rw->map_id, (unsigned long long)rw->phys, |
736ca61fa x86 mmiotrace: Do... |
184 |
rw->value, rw->pc, 0); |
bd8ac686c ftrace: mmiotrace... |
185 186 |
break; case MMIO_WRITE: |
a72e10afa tracing: Do not c... |
187 |
trace_seq_printf(s, |
5e4abc983 trace: clean up f... |
188 189 |
"W %d %u.%06lu %d 0x%llx 0x%lx 0x%lx %d ", |
dee310d0a x86 mmiotrace: us... |
190 191 |
rw->width, secs, usec_rem, rw->map_id, (unsigned long long)rw->phys, |
736ca61fa x86 mmiotrace: Do... |
192 |
rw->value, rw->pc, 0); |
bd8ac686c ftrace: mmiotrace... |
193 194 |
break; case MMIO_UNKNOWN_OP: |
a72e10afa tracing: Do not c... |
195 |
trace_seq_printf(s, |
5e4abc983 trace: clean up f... |
196 197 198 |
"UNKNOWN %u.%06lu %d 0x%llx %02lx,%02lx," "%02lx 0x%lx %d ", |
dee310d0a x86 mmiotrace: us... |
199 200 |
secs, usec_rem, rw->map_id, (unsigned long long)rw->phys, |
bd8ac686c ftrace: mmiotrace... |
201 |
(rw->value >> 16) & 0xff, (rw->value >> 8) & 0xff, |
736ca61fa x86 mmiotrace: Do... |
202 |
(rw->value >> 0) & 0xff, rw->pc, 0); |
bd8ac686c ftrace: mmiotrace... |
203 204 |
break; default: |
a72e10afa tracing: Do not c... |
205 206 |
trace_seq_puts(s, "rw what? "); |
bd8ac686c ftrace: mmiotrace... |
207 208 |
break; } |
a72e10afa tracing: Do not c... |
209 210 |
return trace_handle_return(s); |
bd8ac686c ftrace: mmiotrace... |
211 |
} |
07f4e4f79 tracing/ftrace: a... |
212 |
static enum print_line_t mmio_print_map(struct trace_iterator *iter) |
bd8ac686c ftrace: mmiotrace... |
213 214 |
{ struct trace_entry *entry = iter->ent; |
7104f300c ftrace: type cast... |
215 216 |
struct trace_mmiotrace_map *field; struct mmiotrace_map *m; |
bd8ac686c ftrace: mmiotrace... |
217 |
struct trace_seq *s = &iter->seq; |
3928a8a2d ftrace: make work... |
218 |
unsigned long long t = ns2usecs(iter->ts); |
a5dec5573 tracing: use macr... |
219 |
unsigned long usec_rem = do_div(t, USEC_PER_SEC); |
bd8ac686c ftrace: mmiotrace... |
220 |
unsigned secs = (unsigned long)t; |
bd8ac686c ftrace: mmiotrace... |
221 |
|
7104f300c ftrace: type cast... |
222 223 |
trace_assign_type(field, entry); m = &field->map; |
777e208d4 ftrace: take adva... |
224 |
switch (m->opcode) { |
bd8ac686c ftrace: mmiotrace... |
225 |
case MMIO_PROBE: |
a72e10afa tracing: Do not c... |
226 |
trace_seq_printf(s, |
5e4abc983 trace: clean up f... |
227 228 |
"MAP %u.%06lu %d 0x%llx 0x%lx 0x%lx 0x%lx %d ", |
dee310d0a x86 mmiotrace: us... |
229 230 |
secs, usec_rem, m->map_id, (unsigned long long)m->phys, m->virt, m->len, |
e0fd5c2fa mmiotrace: do not... |
231 |
0UL, 0); |
bd8ac686c ftrace: mmiotrace... |
232 233 |
break; case MMIO_UNPROBE: |
a72e10afa tracing: Do not c... |
234 |
trace_seq_printf(s, |
5e4abc983 trace: clean up f... |
235 236 |
"UNMAP %u.%06lu %d 0x%lx %d ", |
e0fd5c2fa mmiotrace: do not... |
237 |
secs, usec_rem, m->map_id, 0UL, 0); |
bd8ac686c ftrace: mmiotrace... |
238 239 |
break; default: |
a72e10afa tracing: Do not c... |
240 241 |
trace_seq_puts(s, "map what? "); |
bd8ac686c ftrace: mmiotrace... |
242 243 |
break; } |
a72e10afa tracing: Do not c... |
244 245 |
return trace_handle_return(s); |
bd8ac686c ftrace: mmiotrace... |
246 |
} |
07f4e4f79 tracing/ftrace: a... |
247 |
static enum print_line_t mmio_print_mark(struct trace_iterator *iter) |
fc5e27ae4 mmiotrace: handle... |
248 249 |
{ struct trace_entry *entry = iter->ent; |
777e208d4 ftrace: take adva... |
250 |
struct print_entry *print = (struct print_entry *)entry; |
48ead0203 tracing/core: bri... |
251 |
const char *msg = print->buf; |
fc5e27ae4 mmiotrace: handle... |
252 |
struct trace_seq *s = &iter->seq; |
3928a8a2d ftrace: make work... |
253 |
unsigned long long t = ns2usecs(iter->ts); |
769b0441f tracing/core: dro... |
254 |
unsigned long usec_rem = do_div(t, USEC_PER_SEC); |
fc5e27ae4 mmiotrace: handle... |
255 |
unsigned secs = (unsigned long)t; |
fc5e27ae4 mmiotrace: handle... |
256 257 |
/* The trailing newline must be in the message. */ |
a72e10afa tracing: Do not c... |
258 |
trace_seq_printf(s, "MARK %u.%06lu %s", secs, usec_rem, msg); |
fc5e27ae4 mmiotrace: handle... |
259 |
|
a72e10afa tracing: Do not c... |
260 |
return trace_handle_return(s); |
fc5e27ae4 mmiotrace: handle... |
261 |
} |
07f4e4f79 tracing/ftrace: a... |
262 |
static enum print_line_t mmio_print_line(struct trace_iterator *iter) |
bd8ac686c ftrace: mmiotrace... |
263 264 265 266 267 268 |
{ switch (iter->ent->type) { case TRACE_MMIO_RW: return mmio_print_rw(iter); case TRACE_MMIO_MAP: return mmio_print_map(iter); |
fc5e27ae4 mmiotrace: handle... |
269 270 |
case TRACE_PRINT: return mmio_print_mark(iter); |
bd8ac686c ftrace: mmiotrace... |
271 |
default: |
07f4e4f79 tracing/ftrace: a... |
272 |
return TRACE_TYPE_HANDLED; /* ignore unknown entries */ |
bd8ac686c ftrace: mmiotrace... |
273 |
} |
f984b51e0 ftrace: add mmiot... |
274 275 276 277 278 279 280 |
} static struct tracer mmio_tracer __read_mostly = { .name = "mmiotrace", .init = mmio_trace_init, .reset = mmio_trace_reset, |
bbf5b1a0c ftrace: remove ct... |
281 |
.start = mmio_trace_start, |
d0a7e8ca5 mmiotrace: print ... |
282 283 284 |
.pipe_open = mmio_pipe_open, .close = mmio_close, .read = mmio_read, |
bd8ac686c ftrace: mmiotrace... |
285 |
.print_line = mmio_print_line, |
c7b3ae0bd tracing: Ignore m... |
286 |
.noboot = true, |
f984b51e0 ftrace: add mmiot... |
287 288 289 290 |
}; __init static int init_mmio_trace(void) { |
f984b51e0 ftrace: add mmiot... |
291 292 293 |
return register_tracer(&mmio_tracer); } device_initcall(init_mmio_trace); |
45dcd8b8a ftrace: move mmio... |
294 295 296 297 |
static void __trace_mmiotrace_rw(struct trace_array *tr, struct trace_array_cpu *data, struct mmiotrace_rw *rw) { |
2425bcb92 tracing: Rename f... |
298 |
struct trace_event_call *call = &event_mmiotrace_rw; |
12883efb6 tracing: Consolid... |
299 |
struct ring_buffer *buffer = tr->trace_buffer.buffer; |
3928a8a2d ftrace: make work... |
300 |
struct ring_buffer_event *event; |
777e208d4 ftrace: take adva... |
301 |
struct trace_mmiotrace_rw *entry; |
51a763dd8 tracing: Introduc... |
302 |
int pc = preempt_count(); |
45dcd8b8a ftrace: move mmio... |
303 |
|
e77405ad8 tracing: pass aro... |
304 |
event = trace_buffer_lock_reserve(buffer, TRACE_MMIO_RW, |
51a763dd8 tracing: Introduc... |
305 |
sizeof(*entry), 0, pc); |
173ed24ee mmiotrace: count ... |
306 307 |
if (!event) { atomic_inc(&dropped_count); |
3928a8a2d ftrace: make work... |
308 |
return; |
173ed24ee mmiotrace: count ... |
309 |
} |
3928a8a2d ftrace: make work... |
310 |
entry = ring_buffer_event_data(event); |
777e208d4 ftrace: take adva... |
311 |
entry->rw = *rw; |
60ba77022 tracing: add filt... |
312 |
|
f306cc82a tracing: Update e... |
313 |
if (!call_filter_check_discard(call, entry, buffer, event)) |
b7f0c959e tracing: Pass tra... |
314 |
trace_buffer_unlock_commit(tr, buffer, event, 0, pc); |
45dcd8b8a ftrace: move mmio... |
315 |
} |
bd8ac686c ftrace: mmiotrace... |
316 |
void mmio_trace_rw(struct mmiotrace_rw *rw) |
f984b51e0 ftrace: add mmiot... |
317 318 |
{ struct trace_array *tr = mmio_trace_array; |
12883efb6 tracing: Consolid... |
319 |
struct trace_array_cpu *data = per_cpu_ptr(tr->trace_buffer.data, smp_processor_id()); |
bd8ac686c ftrace: mmiotrace... |
320 321 |
__trace_mmiotrace_rw(tr, data, rw); } |
f984b51e0 ftrace: add mmiot... |
322 |
|
45dcd8b8a ftrace: move mmio... |
323 324 325 326 |
static void __trace_mmiotrace_map(struct trace_array *tr, struct trace_array_cpu *data, struct mmiotrace_map *map) { |
2425bcb92 tracing: Rename f... |
327 |
struct trace_event_call *call = &event_mmiotrace_map; |
12883efb6 tracing: Consolid... |
328 |
struct ring_buffer *buffer = tr->trace_buffer.buffer; |
3928a8a2d ftrace: make work... |
329 |
struct ring_buffer_event *event; |
777e208d4 ftrace: take adva... |
330 |
struct trace_mmiotrace_map *entry; |
51a763dd8 tracing: Introduc... |
331 |
int pc = preempt_count(); |
45dcd8b8a ftrace: move mmio... |
332 |
|
e77405ad8 tracing: pass aro... |
333 |
event = trace_buffer_lock_reserve(buffer, TRACE_MMIO_MAP, |
51a763dd8 tracing: Introduc... |
334 |
sizeof(*entry), 0, pc); |
173ed24ee mmiotrace: count ... |
335 336 |
if (!event) { atomic_inc(&dropped_count); |
3928a8a2d ftrace: make work... |
337 |
return; |
173ed24ee mmiotrace: count ... |
338 |
} |
3928a8a2d ftrace: make work... |
339 |
entry = ring_buffer_event_data(event); |
777e208d4 ftrace: take adva... |
340 |
entry->map = *map; |
60ba77022 tracing: add filt... |
341 |
|
f306cc82a tracing: Update e... |
342 |
if (!call_filter_check_discard(call, entry, buffer, event)) |
b7f0c959e tracing: Pass tra... |
343 |
trace_buffer_unlock_commit(tr, buffer, event, 0, pc); |
45dcd8b8a ftrace: move mmio... |
344 |
} |
bd8ac686c ftrace: mmiotrace... |
345 346 347 348 349 350 |
void mmio_trace_mapping(struct mmiotrace_map *map) { struct trace_array *tr = mmio_trace_array; struct trace_array_cpu *data; preempt_disable(); |
12883efb6 tracing: Consolid... |
351 |
data = per_cpu_ptr(tr->trace_buffer.data, smp_processor_id()); |
bd8ac686c ftrace: mmiotrace... |
352 353 |
__trace_mmiotrace_map(tr, data, map); preempt_enable(); |
f984b51e0 ftrace: add mmiot... |
354 |
} |
9e57fb35d x86 mmiotrace: im... |
355 356 357 |
int mmio_trace_printk(const char *fmt, va_list args) { |
40ce74f19 tracing: remove r... |
358 |
return trace_vprintk(0, fmt, args); |
9e57fb35d x86 mmiotrace: im... |
359 |
} |