Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
awilliam
GitHub Repository: awilliam/linux-vfio
Path: blob/master/arch/arm/kernel/etm.c
10817 views
1
/*
2
* linux/arch/arm/kernel/etm.c
3
*
4
* Driver for ARM's Embedded Trace Macrocell and Embedded Trace Buffer.
5
*
6
* Copyright (C) 2009 Nokia Corporation.
7
* Alexander Shishkin
8
*
9
* This program is free software; you can redistribute it and/or modify
10
* it under the terms of the GNU General Public License version 2 as
11
* published by the Free Software Foundation.
12
*/
13
14
#include <linux/kernel.h>
15
#include <linux/init.h>
16
#include <linux/types.h>
17
#include <linux/io.h>
18
#include <linux/sysrq.h>
19
#include <linux/device.h>
20
#include <linux/clk.h>
21
#include <linux/amba/bus.h>
22
#include <linux/fs.h>
23
#include <linux/uaccess.h>
24
#include <linux/miscdevice.h>
25
#include <linux/vmalloc.h>
26
#include <linux/mutex.h>
27
#include <asm/hardware/coresight.h>
28
#include <asm/sections.h>
29
30
MODULE_LICENSE("GPL");
31
MODULE_AUTHOR("Alexander Shishkin");
32
33
/*
34
* ETM tracer state
35
*/
36
struct tracectx {
37
unsigned int etb_bufsz;
38
void __iomem *etb_regs;
39
void __iomem *etm_regs;
40
unsigned long flags;
41
int ncmppairs;
42
int etm_portsz;
43
struct device *dev;
44
struct clk *emu_clk;
45
struct mutex mutex;
46
};
47
48
static struct tracectx tracer;
49
50
static inline bool trace_isrunning(struct tracectx *t)
51
{
52
return !!(t->flags & TRACER_RUNNING);
53
}
54
55
static int etm_setup_address_range(struct tracectx *t, int n,
56
unsigned long start, unsigned long end, int exclude, int data)
57
{
58
u32 flags = ETMAAT_ARM | ETMAAT_IGNCONTEXTID | ETMAAT_NSONLY | \
59
ETMAAT_NOVALCMP;
60
61
if (n < 1 || n > t->ncmppairs)
62
return -EINVAL;
63
64
/* comparators and ranges are numbered starting with 1 as opposed
65
* to bits in a word */
66
n--;
67
68
if (data)
69
flags |= ETMAAT_DLOADSTORE;
70
else
71
flags |= ETMAAT_IEXEC;
72
73
/* first comparator for the range */
74
etm_writel(t, flags, ETMR_COMP_ACC_TYPE(n * 2));
75
etm_writel(t, start, ETMR_COMP_VAL(n * 2));
76
77
/* second comparator is right next to it */
78
etm_writel(t, flags, ETMR_COMP_ACC_TYPE(n * 2 + 1));
79
etm_writel(t, end, ETMR_COMP_VAL(n * 2 + 1));
80
81
flags = exclude ? ETMTE_INCLEXCL : 0;
82
etm_writel(t, flags | (1 << n), ETMR_TRACEENCTRL);
83
84
return 0;
85
}
86
87
static int trace_start(struct tracectx *t)
88
{
89
u32 v;
90
unsigned long timeout = TRACER_TIMEOUT;
91
92
etb_unlock(t);
93
94
etb_writel(t, 0, ETBR_FORMATTERCTRL);
95
etb_writel(t, 1, ETBR_CTRL);
96
97
etb_lock(t);
98
99
/* configure etm */
100
v = ETMCTRL_OPTS | ETMCTRL_PROGRAM | ETMCTRL_PORTSIZE(t->etm_portsz);
101
102
if (t->flags & TRACER_CYCLE_ACC)
103
v |= ETMCTRL_CYCLEACCURATE;
104
105
etm_unlock(t);
106
107
etm_writel(t, v, ETMR_CTRL);
108
109
while (!(etm_readl(t, ETMR_CTRL) & ETMCTRL_PROGRAM) && --timeout)
110
;
111
if (!timeout) {
112
dev_dbg(t->dev, "Waiting for progbit to assert timed out\n");
113
etm_lock(t);
114
return -EFAULT;
115
}
116
117
etm_setup_address_range(t, 1, (unsigned long)_stext,
118
(unsigned long)_etext, 0, 0);
119
etm_writel(t, 0, ETMR_TRACEENCTRL2);
120
etm_writel(t, 0, ETMR_TRACESSCTRL);
121
etm_writel(t, 0x6f, ETMR_TRACEENEVT);
122
123
v &= ~ETMCTRL_PROGRAM;
124
v |= ETMCTRL_PORTSEL;
125
126
etm_writel(t, v, ETMR_CTRL);
127
128
timeout = TRACER_TIMEOUT;
129
while (etm_readl(t, ETMR_CTRL) & ETMCTRL_PROGRAM && --timeout)
130
;
131
if (!timeout) {
132
dev_dbg(t->dev, "Waiting for progbit to deassert timed out\n");
133
etm_lock(t);
134
return -EFAULT;
135
}
136
137
etm_lock(t);
138
139
t->flags |= TRACER_RUNNING;
140
141
return 0;
142
}
143
144
static int trace_stop(struct tracectx *t)
145
{
146
unsigned long timeout = TRACER_TIMEOUT;
147
148
etm_unlock(t);
149
150
etm_writel(t, 0x440, ETMR_CTRL);
151
while (!(etm_readl(t, ETMR_CTRL) & ETMCTRL_PROGRAM) && --timeout)
152
;
153
if (!timeout) {
154
dev_dbg(t->dev, "Waiting for progbit to assert timed out\n");
155
etm_lock(t);
156
return -EFAULT;
157
}
158
159
etm_lock(t);
160
161
etb_unlock(t);
162
etb_writel(t, ETBFF_MANUAL_FLUSH, ETBR_FORMATTERCTRL);
163
164
timeout = TRACER_TIMEOUT;
165
while (etb_readl(t, ETBR_FORMATTERCTRL) &
166
ETBFF_MANUAL_FLUSH && --timeout)
167
;
168
if (!timeout) {
169
dev_dbg(t->dev, "Waiting for formatter flush to commence "
170
"timed out\n");
171
etb_lock(t);
172
return -EFAULT;
173
}
174
175
etb_writel(t, 0, ETBR_CTRL);
176
177
etb_lock(t);
178
179
t->flags &= ~TRACER_RUNNING;
180
181
return 0;
182
}
183
184
static int etb_getdatalen(struct tracectx *t)
185
{
186
u32 v;
187
int rp, wp;
188
189
v = etb_readl(t, ETBR_STATUS);
190
191
if (v & 1)
192
return t->etb_bufsz;
193
194
rp = etb_readl(t, ETBR_READADDR);
195
wp = etb_readl(t, ETBR_WRITEADDR);
196
197
if (rp > wp) {
198
etb_writel(t, 0, ETBR_READADDR);
199
etb_writel(t, 0, ETBR_WRITEADDR);
200
201
return 0;
202
}
203
204
return wp - rp;
205
}
206
207
/* sysrq+v will always stop the running trace and leave it at that */
208
static void etm_dump(void)
209
{
210
struct tracectx *t = &tracer;
211
u32 first = 0;
212
int length;
213
214
if (!t->etb_regs) {
215
printk(KERN_INFO "No tracing hardware found\n");
216
return;
217
}
218
219
if (trace_isrunning(t))
220
trace_stop(t);
221
222
etb_unlock(t);
223
224
length = etb_getdatalen(t);
225
226
if (length == t->etb_bufsz)
227
first = etb_readl(t, ETBR_WRITEADDR);
228
229
etb_writel(t, first, ETBR_READADDR);
230
231
printk(KERN_INFO "Trace buffer contents length: %d\n", length);
232
printk(KERN_INFO "--- ETB buffer begin ---\n");
233
for (; length; length--)
234
printk("%08x", cpu_to_be32(etb_readl(t, ETBR_READMEM)));
235
printk(KERN_INFO "\n--- ETB buffer end ---\n");
236
237
/* deassert the overflow bit */
238
etb_writel(t, 1, ETBR_CTRL);
239
etb_writel(t, 0, ETBR_CTRL);
240
241
etb_writel(t, 0, ETBR_TRIGGERCOUNT);
242
etb_writel(t, 0, ETBR_READADDR);
243
etb_writel(t, 0, ETBR_WRITEADDR);
244
245
etb_lock(t);
246
}
247
248
static void sysrq_etm_dump(int key)
249
{
250
dev_dbg(tracer.dev, "Dumping ETB buffer\n");
251
etm_dump();
252
}
253
254
static struct sysrq_key_op sysrq_etm_op = {
255
.handler = sysrq_etm_dump,
256
.help_msg = "ETM buffer dump",
257
.action_msg = "etm",
258
};
259
260
static int etb_open(struct inode *inode, struct file *file)
261
{
262
if (!tracer.etb_regs)
263
return -ENODEV;
264
265
file->private_data = &tracer;
266
267
return nonseekable_open(inode, file);
268
}
269
270
static ssize_t etb_read(struct file *file, char __user *data,
271
size_t len, loff_t *ppos)
272
{
273
int total, i;
274
long length;
275
struct tracectx *t = file->private_data;
276
u32 first = 0;
277
u32 *buf;
278
279
mutex_lock(&t->mutex);
280
281
if (trace_isrunning(t)) {
282
length = 0;
283
goto out;
284
}
285
286
etb_unlock(t);
287
288
total = etb_getdatalen(t);
289
if (total == t->etb_bufsz)
290
first = etb_readl(t, ETBR_WRITEADDR);
291
292
etb_writel(t, first, ETBR_READADDR);
293
294
length = min(total * 4, (int)len);
295
buf = vmalloc(length);
296
297
dev_dbg(t->dev, "ETB buffer length: %d\n", total);
298
dev_dbg(t->dev, "ETB status reg: %x\n", etb_readl(t, ETBR_STATUS));
299
for (i = 0; i < length / 4; i++)
300
buf[i] = etb_readl(t, ETBR_READMEM);
301
302
/* the only way to deassert overflow bit in ETB status is this */
303
etb_writel(t, 1, ETBR_CTRL);
304
etb_writel(t, 0, ETBR_CTRL);
305
306
etb_writel(t, 0, ETBR_WRITEADDR);
307
etb_writel(t, 0, ETBR_READADDR);
308
etb_writel(t, 0, ETBR_TRIGGERCOUNT);
309
310
etb_lock(t);
311
312
length -= copy_to_user(data, buf, length);
313
vfree(buf);
314
315
out:
316
mutex_unlock(&t->mutex);
317
318
return length;
319
}
320
321
static int etb_release(struct inode *inode, struct file *file)
322
{
323
/* there's nothing to do here, actually */
324
return 0;
325
}
326
327
static const struct file_operations etb_fops = {
328
.owner = THIS_MODULE,
329
.read = etb_read,
330
.open = etb_open,
331
.release = etb_release,
332
.llseek = no_llseek,
333
};
334
335
static struct miscdevice etb_miscdev = {
336
.name = "tracebuf",
337
.minor = 0,
338
.fops = &etb_fops,
339
};
340
341
static int __devinit etb_probe(struct amba_device *dev, const struct amba_id *id)
342
{
343
struct tracectx *t = &tracer;
344
int ret = 0;
345
346
ret = amba_request_regions(dev, NULL);
347
if (ret)
348
goto out;
349
350
t->etb_regs = ioremap_nocache(dev->res.start, resource_size(&dev->res));
351
if (!t->etb_regs) {
352
ret = -ENOMEM;
353
goto out_release;
354
}
355
356
amba_set_drvdata(dev, t);
357
358
etb_miscdev.parent = &dev->dev;
359
360
ret = misc_register(&etb_miscdev);
361
if (ret)
362
goto out_unmap;
363
364
t->emu_clk = clk_get(&dev->dev, "emu_src_ck");
365
if (IS_ERR(t->emu_clk)) {
366
dev_dbg(&dev->dev, "Failed to obtain emu_src_ck.\n");
367
return -EFAULT;
368
}
369
370
clk_enable(t->emu_clk);
371
372
etb_unlock(t);
373
t->etb_bufsz = etb_readl(t, ETBR_DEPTH);
374
dev_dbg(&dev->dev, "Size: %x\n", t->etb_bufsz);
375
376
/* make sure trace capture is disabled */
377
etb_writel(t, 0, ETBR_CTRL);
378
etb_writel(t, 0x1000, ETBR_FORMATTERCTRL);
379
etb_lock(t);
380
381
dev_dbg(&dev->dev, "ETB AMBA driver initialized.\n");
382
383
out:
384
return ret;
385
386
out_unmap:
387
amba_set_drvdata(dev, NULL);
388
iounmap(t->etb_regs);
389
390
out_release:
391
amba_release_regions(dev);
392
393
return ret;
394
}
395
396
static int etb_remove(struct amba_device *dev)
397
{
398
struct tracectx *t = amba_get_drvdata(dev);
399
400
amba_set_drvdata(dev, NULL);
401
402
iounmap(t->etb_regs);
403
t->etb_regs = NULL;
404
405
clk_disable(t->emu_clk);
406
clk_put(t->emu_clk);
407
408
amba_release_regions(dev);
409
410
return 0;
411
}
412
413
static struct amba_id etb_ids[] = {
414
{
415
.id = 0x0003b907,
416
.mask = 0x0007ffff,
417
},
418
{ 0, 0 },
419
};
420
421
static struct amba_driver etb_driver = {
422
.drv = {
423
.name = "etb",
424
.owner = THIS_MODULE,
425
},
426
.probe = etb_probe,
427
.remove = etb_remove,
428
.id_table = etb_ids,
429
};
430
431
/* use a sysfs file "trace_running" to start/stop tracing */
432
static ssize_t trace_running_show(struct kobject *kobj,
433
struct kobj_attribute *attr,
434
char *buf)
435
{
436
return sprintf(buf, "%x\n", trace_isrunning(&tracer));
437
}
438
439
static ssize_t trace_running_store(struct kobject *kobj,
440
struct kobj_attribute *attr,
441
const char *buf, size_t n)
442
{
443
unsigned int value;
444
int ret;
445
446
if (sscanf(buf, "%u", &value) != 1)
447
return -EINVAL;
448
449
mutex_lock(&tracer.mutex);
450
ret = value ? trace_start(&tracer) : trace_stop(&tracer);
451
mutex_unlock(&tracer.mutex);
452
453
return ret ? : n;
454
}
455
456
static struct kobj_attribute trace_running_attr =
457
__ATTR(trace_running, 0644, trace_running_show, trace_running_store);
458
459
static ssize_t trace_info_show(struct kobject *kobj,
460
struct kobj_attribute *attr,
461
char *buf)
462
{
463
u32 etb_wa, etb_ra, etb_st, etb_fc, etm_ctrl, etm_st;
464
int datalen;
465
466
etb_unlock(&tracer);
467
datalen = etb_getdatalen(&tracer);
468
etb_wa = etb_readl(&tracer, ETBR_WRITEADDR);
469
etb_ra = etb_readl(&tracer, ETBR_READADDR);
470
etb_st = etb_readl(&tracer, ETBR_STATUS);
471
etb_fc = etb_readl(&tracer, ETBR_FORMATTERCTRL);
472
etb_lock(&tracer);
473
474
etm_unlock(&tracer);
475
etm_ctrl = etm_readl(&tracer, ETMR_CTRL);
476
etm_st = etm_readl(&tracer, ETMR_STATUS);
477
etm_lock(&tracer);
478
479
return sprintf(buf, "Trace buffer len: %d\nComparator pairs: %d\n"
480
"ETBR_WRITEADDR:\t%08x\n"
481
"ETBR_READADDR:\t%08x\n"
482
"ETBR_STATUS:\t%08x\n"
483
"ETBR_FORMATTERCTRL:\t%08x\n"
484
"ETMR_CTRL:\t%08x\n"
485
"ETMR_STATUS:\t%08x\n",
486
datalen,
487
tracer.ncmppairs,
488
etb_wa,
489
etb_ra,
490
etb_st,
491
etb_fc,
492
etm_ctrl,
493
etm_st
494
);
495
}
496
497
static struct kobj_attribute trace_info_attr =
498
__ATTR(trace_info, 0444, trace_info_show, NULL);
499
500
static ssize_t trace_mode_show(struct kobject *kobj,
501
struct kobj_attribute *attr,
502
char *buf)
503
{
504
return sprintf(buf, "%d %d\n",
505
!!(tracer.flags & TRACER_CYCLE_ACC),
506
tracer.etm_portsz);
507
}
508
509
static ssize_t trace_mode_store(struct kobject *kobj,
510
struct kobj_attribute *attr,
511
const char *buf, size_t n)
512
{
513
unsigned int cycacc, portsz;
514
515
if (sscanf(buf, "%u %u", &cycacc, &portsz) != 2)
516
return -EINVAL;
517
518
mutex_lock(&tracer.mutex);
519
if (cycacc)
520
tracer.flags |= TRACER_CYCLE_ACC;
521
else
522
tracer.flags &= ~TRACER_CYCLE_ACC;
523
524
tracer.etm_portsz = portsz & 0x0f;
525
mutex_unlock(&tracer.mutex);
526
527
return n;
528
}
529
530
static struct kobj_attribute trace_mode_attr =
531
__ATTR(trace_mode, 0644, trace_mode_show, trace_mode_store);
532
533
static int __devinit etm_probe(struct amba_device *dev, const struct amba_id *id)
534
{
535
struct tracectx *t = &tracer;
536
int ret = 0;
537
538
if (t->etm_regs) {
539
dev_dbg(&dev->dev, "ETM already initialized\n");
540
ret = -EBUSY;
541
goto out;
542
}
543
544
ret = amba_request_regions(dev, NULL);
545
if (ret)
546
goto out;
547
548
t->etm_regs = ioremap_nocache(dev->res.start, resource_size(&dev->res));
549
if (!t->etm_regs) {
550
ret = -ENOMEM;
551
goto out_release;
552
}
553
554
amba_set_drvdata(dev, t);
555
556
mutex_init(&t->mutex);
557
t->dev = &dev->dev;
558
t->flags = TRACER_CYCLE_ACC;
559
t->etm_portsz = 1;
560
561
etm_unlock(t);
562
(void)etm_readl(t, ETMMR_PDSR);
563
/* dummy first read */
564
(void)etm_readl(&tracer, ETMMR_OSSRR);
565
566
t->ncmppairs = etm_readl(t, ETMR_CONFCODE) & 0xf;
567
etm_writel(t, 0x440, ETMR_CTRL);
568
etm_lock(t);
569
570
ret = sysfs_create_file(&dev->dev.kobj,
571
&trace_running_attr.attr);
572
if (ret)
573
goto out_unmap;
574
575
/* failing to create any of these two is not fatal */
576
ret = sysfs_create_file(&dev->dev.kobj, &trace_info_attr.attr);
577
if (ret)
578
dev_dbg(&dev->dev, "Failed to create trace_info in sysfs\n");
579
580
ret = sysfs_create_file(&dev->dev.kobj, &trace_mode_attr.attr);
581
if (ret)
582
dev_dbg(&dev->dev, "Failed to create trace_mode in sysfs\n");
583
584
dev_dbg(t->dev, "ETM AMBA driver initialized.\n");
585
586
out:
587
return ret;
588
589
out_unmap:
590
amba_set_drvdata(dev, NULL);
591
iounmap(t->etm_regs);
592
593
out_release:
594
amba_release_regions(dev);
595
596
return ret;
597
}
598
599
static int etm_remove(struct amba_device *dev)
600
{
601
struct tracectx *t = amba_get_drvdata(dev);
602
603
amba_set_drvdata(dev, NULL);
604
605
iounmap(t->etm_regs);
606
t->etm_regs = NULL;
607
608
amba_release_regions(dev);
609
610
sysfs_remove_file(&dev->dev.kobj, &trace_running_attr.attr);
611
sysfs_remove_file(&dev->dev.kobj, &trace_info_attr.attr);
612
sysfs_remove_file(&dev->dev.kobj, &trace_mode_attr.attr);
613
614
return 0;
615
}
616
617
static struct amba_id etm_ids[] = {
618
{
619
.id = 0x0003b921,
620
.mask = 0x0007ffff,
621
},
622
{ 0, 0 },
623
};
624
625
static struct amba_driver etm_driver = {
626
.drv = {
627
.name = "etm",
628
.owner = THIS_MODULE,
629
},
630
.probe = etm_probe,
631
.remove = etm_remove,
632
.id_table = etm_ids,
633
};
634
635
static int __init etm_init(void)
636
{
637
int retval;
638
639
retval = amba_driver_register(&etb_driver);
640
if (retval) {
641
printk(KERN_ERR "Failed to register etb\n");
642
return retval;
643
}
644
645
retval = amba_driver_register(&etm_driver);
646
if (retval) {
647
amba_driver_unregister(&etb_driver);
648
printk(KERN_ERR "Failed to probe etm\n");
649
return retval;
650
}
651
652
/* not being able to install this handler is not fatal */
653
(void)register_sysrq_key('v', &sysrq_etm_op);
654
655
return 0;
656
}
657
658
device_initcall(etm_init);
659
660
661