1 /* 2 * Memory mapped I/O tracing 3 * 4 * Copyright (C) 2008 Pekka Paalanen <pq@iki.fi> 5 */ 6 7 #define DEBUG 1 8 9 #include <linux/kernel.h> 10 #include <linux/mmiotrace.h> 11 #include <linux/pci.h> 12 13 #include "trace.h" 14 15 struct header_iter { 16 struct pci_dev *dev; 17 }; 18 19 static struct trace_array *mmio_trace_array; 20 static bool overrun_detected; 21 static unsigned long prev_overruns; 22 23 static void mmio_reset_data(struct trace_array *tr) 24 { 25 overrun_detected = false; 26 prev_overruns = 0; 27 28 tracing_reset_online_cpus(tr); 29 } 30 31 static int mmio_trace_init(struct trace_array *tr) 32 { 33 pr_debug("in %s\n", __func__); 34 mmio_trace_array = tr; 35 36 mmio_reset_data(tr); 37 enable_mmiotrace(); 38 return 0; 39 } 40 41 static void mmio_trace_reset(struct trace_array *tr) 42 { 43 pr_debug("in %s\n", __func__); 44 45 disable_mmiotrace(); 46 mmio_reset_data(tr); 47 mmio_trace_array = NULL; 48 } 49 50 static void mmio_trace_start(struct trace_array *tr) 51 { 52 pr_debug("in %s\n", __func__); 53 mmio_reset_data(tr); 54 } 55 56 static int mmio_print_pcidev(struct trace_seq *s, const struct pci_dev *dev) 57 { 58 int ret = 0; 59 int i; 60 resource_size_t start, end; 61 const struct pci_driver *drv = pci_dev_driver(dev); 62 63 /* XXX: incomplete checks for trace_seq_printf() return value */ 64 ret += trace_seq_printf(s, "PCIDEV %02x%02x %04x%04x %x", 65 dev->bus->number, dev->devfn, 66 dev->vendor, dev->device, dev->irq); 67 /* 68 * XXX: is pci_resource_to_user() appropriate, since we are 69 * supposed to interpret the __ioremap() phys_addr argument based on 70 * these printed values? 71 */ 72 for (i = 0; i < 7; i++) { 73 pci_resource_to_user(dev, i, &dev->resource[i], &start, &end); 74 ret += trace_seq_printf(s, " %llx", 75 (unsigned long long)(start | 76 (dev->resource[i].flags & PCI_REGION_FLAG_MASK))); 77 } 78 for (i = 0; i < 7; i++) { 79 pci_resource_to_user(dev, i, &dev->resource[i], &start, &end); 80 ret += trace_seq_printf(s, " %llx", 81 dev->resource[i].start < dev->resource[i].end ? 82 (unsigned long long)(end - start) + 1 : 0); 83 } 84 if (drv) 85 ret += trace_seq_printf(s, " %s\n", drv->name); 86 else 87 ret += trace_seq_printf(s, " \n"); 88 return ret; 89 } 90 91 static void destroy_header_iter(struct header_iter *hiter) 92 { 93 if (!hiter) 94 return; 95 pci_dev_put(hiter->dev); 96 kfree(hiter); 97 } 98 99 static void mmio_pipe_open(struct trace_iterator *iter) 100 { 101 struct header_iter *hiter; 102 struct trace_seq *s = &iter->seq; 103 104 trace_seq_printf(s, "VERSION 20070824\n"); 105 106 hiter = kzalloc(sizeof(*hiter), GFP_KERNEL); 107 if (!hiter) 108 return; 109 110 hiter->dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, NULL); 111 iter->private = hiter; 112 } 113 114 /* XXX: This is not called when the pipe is closed! */ 115 static void mmio_close(struct trace_iterator *iter) 116 { 117 struct header_iter *hiter = iter->private; 118 destroy_header_iter(hiter); 119 iter->private = NULL; 120 } 121 122 static unsigned long count_overruns(struct trace_iterator *iter) 123 { 124 unsigned long cnt = 0; 125 unsigned long over = ring_buffer_overruns(iter->tr->buffer); 126 127 if (over > prev_overruns) 128 cnt = over - prev_overruns; 129 prev_overruns = over; 130 return cnt; 131 } 132 133 static ssize_t mmio_read(struct trace_iterator *iter, struct file *filp, 134 char __user *ubuf, size_t cnt, loff_t *ppos) 135 { 136 ssize_t ret; 137 struct header_iter *hiter = iter->private; 138 struct trace_seq *s = &iter->seq; 139 unsigned long n; 140 141 n = count_overruns(iter); 142 if (n) { 143 /* XXX: This is later than where events were lost. */ 144 trace_seq_printf(s, "MARK 0.000000 Lost %lu events.\n", n); 145 if (!overrun_detected) 146 pr_warning("mmiotrace has lost events.\n"); 147 overrun_detected = true; 148 goto print_out; 149 } 150 151 if (!hiter) 152 return 0; 153 154 mmio_print_pcidev(s, hiter->dev); 155 hiter->dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, hiter->dev); 156 157 if (!hiter->dev) { 158 destroy_header_iter(hiter); 159 iter->private = NULL; 160 } 161 162 print_out: 163 ret = trace_seq_to_user(s, ubuf, cnt); 164 return (ret == -EBUSY) ? 0 : ret; 165 } 166 167 static enum print_line_t mmio_print_rw(struct trace_iterator *iter) 168 { 169 struct trace_entry *entry = iter->ent; 170 struct trace_mmiotrace_rw *field; 171 struct mmiotrace_rw *rw; 172 struct trace_seq *s = &iter->seq; 173 unsigned long long t = ns2usecs(iter->ts); 174 unsigned long usec_rem = do_div(t, 1000000ULL); 175 unsigned secs = (unsigned long)t; 176 int ret = 1; 177 178 trace_assign_type(field, entry); 179 rw = &field->rw; 180 181 switch (rw->opcode) { 182 case MMIO_READ: 183 ret = trace_seq_printf(s, 184 "R %d %lu.%06lu %d 0x%llx 0x%lx 0x%lx %d\n", 185 rw->width, secs, usec_rem, rw->map_id, 186 (unsigned long long)rw->phys, 187 rw->value, rw->pc, 0); 188 break; 189 case MMIO_WRITE: 190 ret = trace_seq_printf(s, 191 "W %d %lu.%06lu %d 0x%llx 0x%lx 0x%lx %d\n", 192 rw->width, secs, usec_rem, rw->map_id, 193 (unsigned long long)rw->phys, 194 rw->value, rw->pc, 0); 195 break; 196 case MMIO_UNKNOWN_OP: 197 ret = trace_seq_printf(s, 198 "UNKNOWN %lu.%06lu %d 0x%llx %02x,%02x,%02x 0x%lx %d\n", 199 secs, usec_rem, rw->map_id, 200 (unsigned long long)rw->phys, 201 (rw->value >> 16) & 0xff, (rw->value >> 8) & 0xff, 202 (rw->value >> 0) & 0xff, rw->pc, 0); 203 break; 204 default: 205 ret = trace_seq_printf(s, "rw what?\n"); 206 break; 207 } 208 if (ret) 209 return TRACE_TYPE_HANDLED; 210 return TRACE_TYPE_PARTIAL_LINE; 211 } 212 213 static enum print_line_t mmio_print_map(struct trace_iterator *iter) 214 { 215 struct trace_entry *entry = iter->ent; 216 struct trace_mmiotrace_map *field; 217 struct mmiotrace_map *m; 218 struct trace_seq *s = &iter->seq; 219 unsigned long long t = ns2usecs(iter->ts); 220 unsigned long usec_rem = do_div(t, 1000000ULL); 221 unsigned secs = (unsigned long)t; 222 int ret; 223 224 trace_assign_type(field, entry); 225 m = &field->map; 226 227 switch (m->opcode) { 228 case MMIO_PROBE: 229 ret = trace_seq_printf(s, 230 "MAP %lu.%06lu %d 0x%llx 0x%lx 0x%lx 0x%lx %d\n", 231 secs, usec_rem, m->map_id, 232 (unsigned long long)m->phys, m->virt, m->len, 233 0UL, 0); 234 break; 235 case MMIO_UNPROBE: 236 ret = trace_seq_printf(s, 237 "UNMAP %lu.%06lu %d 0x%lx %d\n", 238 secs, usec_rem, m->map_id, 0UL, 0); 239 break; 240 default: 241 ret = trace_seq_printf(s, "map what?\n"); 242 break; 243 } 244 if (ret) 245 return TRACE_TYPE_HANDLED; 246 return TRACE_TYPE_PARTIAL_LINE; 247 } 248 249 static enum print_line_t mmio_print_mark(struct trace_iterator *iter) 250 { 251 struct trace_entry *entry = iter->ent; 252 struct print_entry *print = (struct print_entry *)entry; 253 const char *msg = print->buf; 254 struct trace_seq *s = &iter->seq; 255 unsigned long long t = ns2usecs(iter->ts); 256 unsigned long usec_rem = do_div(t, 1000000ULL); 257 unsigned secs = (unsigned long)t; 258 int ret; 259 260 /* The trailing newline must be in the message. */ 261 ret = trace_seq_printf(s, "MARK %lu.%06lu %s", secs, usec_rem, msg); 262 if (!ret) 263 return TRACE_TYPE_PARTIAL_LINE; 264 265 return TRACE_TYPE_HANDLED; 266 } 267 268 static enum print_line_t mmio_print_line(struct trace_iterator *iter) 269 { 270 switch (iter->ent->type) { 271 case TRACE_MMIO_RW: 272 return mmio_print_rw(iter); 273 case TRACE_MMIO_MAP: 274 return mmio_print_map(iter); 275 case TRACE_PRINT: 276 return mmio_print_mark(iter); 277 default: 278 return TRACE_TYPE_HANDLED; /* ignore unknown entries */ 279 } 280 } 281 282 static struct tracer mmio_tracer __read_mostly = 283 { 284 .name = "mmiotrace", 285 .init = mmio_trace_init, 286 .reset = mmio_trace_reset, 287 .start = mmio_trace_start, 288 .pipe_open = mmio_pipe_open, 289 .close = mmio_close, 290 .read = mmio_read, 291 .print_line = mmio_print_line, 292 }; 293 294 __init static int init_mmio_trace(void) 295 { 296 return register_tracer(&mmio_tracer); 297 } 298 device_initcall(init_mmio_trace); 299 300 static void __trace_mmiotrace_rw(struct trace_array *tr, 301 struct trace_array_cpu *data, 302 struct mmiotrace_rw *rw) 303 { 304 struct ring_buffer_event *event; 305 struct trace_mmiotrace_rw *entry; 306 unsigned long irq_flags; 307 308 event = ring_buffer_lock_reserve(tr->buffer, sizeof(*entry), 309 &irq_flags); 310 if (!event) 311 return; 312 entry = ring_buffer_event_data(event); 313 tracing_generic_entry_update(&entry->ent, 0, preempt_count()); 314 entry->ent.type = TRACE_MMIO_RW; 315 entry->rw = *rw; 316 ring_buffer_unlock_commit(tr->buffer, event, irq_flags); 317 318 trace_wake_up(); 319 } 320 321 void mmio_trace_rw(struct mmiotrace_rw *rw) 322 { 323 struct trace_array *tr = mmio_trace_array; 324 struct trace_array_cpu *data = tr->data[smp_processor_id()]; 325 __trace_mmiotrace_rw(tr, data, rw); 326 } 327 328 static void __trace_mmiotrace_map(struct trace_array *tr, 329 struct trace_array_cpu *data, 330 struct mmiotrace_map *map) 331 { 332 struct ring_buffer_event *event; 333 struct trace_mmiotrace_map *entry; 334 unsigned long irq_flags; 335 336 event = ring_buffer_lock_reserve(tr->buffer, sizeof(*entry), 337 &irq_flags); 338 if (!event) 339 return; 340 entry = ring_buffer_event_data(event); 341 tracing_generic_entry_update(&entry->ent, 0, preempt_count()); 342 entry->ent.type = TRACE_MMIO_MAP; 343 entry->map = *map; 344 ring_buffer_unlock_commit(tr->buffer, event, irq_flags); 345 346 trace_wake_up(); 347 } 348 349 void mmio_trace_mapping(struct mmiotrace_map *map) 350 { 351 struct trace_array *tr = mmio_trace_array; 352 struct trace_array_cpu *data; 353 354 preempt_disable(); 355 data = tr->data[smp_processor_id()]; 356 __trace_mmiotrace_map(tr, data, map); 357 preempt_enable(); 358 } 359 360 int mmio_trace_printk(const char *fmt, va_list args) 361 { 362 return trace_vprintk(0, -1, fmt, args); 363 } 364