linux/arch/arm/kernel/etm.c
<<
>>
Prefs
   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
  30MODULE_LICENSE("GPL");
  31MODULE_AUTHOR("Alexander Shishkin");
  32
  33/*
  34 * ETM tracer state
  35 */
  36struct 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
  48static struct tracectx tracer;
  49
  50static inline bool trace_isrunning(struct tracectx *t)
  51{
  52        return !!(t->flags & TRACER_RUNNING);
  53}
  54
  55static 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
  87static 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
 144static 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
 184static 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 */
 208static 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
 248static void sysrq_etm_dump(int key)
 249{
 250        dev_dbg(tracer.dev, "Dumping ETB buffer\n");
 251        etm_dump();
 252}
 253
 254static struct sysrq_key_op sysrq_etm_op = {
 255        .handler = sysrq_etm_dump,
 256        .help_msg = "ETM buffer dump",
 257        .action_msg = "etm",
 258};
 259
 260static 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
 270static 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
 315out:
 316        mutex_unlock(&t->mutex);
 317
 318        return length;
 319}
 320
 321static int etb_release(struct inode *inode, struct file *file)
 322{
 323        /* there's nothing to do here, actually */
 324        return 0;
 325}
 326
 327static 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
 335static struct miscdevice etb_miscdev = {
 336        .name = "tracebuf",
 337        .minor = 0,
 338        .fops = &etb_fops,
 339};
 340
 341static 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
 383out:
 384        return ret;
 385
 386out_unmap:
 387        amba_set_drvdata(dev, NULL);
 388        iounmap(t->etb_regs);
 389
 390out_release:
 391        amba_release_regions(dev);
 392
 393        return ret;
 394}
 395
 396static 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
 413static struct amba_id etb_ids[] = {
 414        {
 415                .id     = 0x0003b907,
 416                .mask   = 0x0007ffff,
 417        },
 418        { 0, 0 },
 419};
 420
 421static 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 */
 432static 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
 439static 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
 456static struct kobj_attribute trace_running_attr =
 457        __ATTR(trace_running, 0644, trace_running_show, trace_running_store);
 458
 459static 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
 497static struct kobj_attribute trace_info_attr =
 498        __ATTR(trace_info, 0444, trace_info_show, NULL);
 499
 500static 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
 509static 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
 530static struct kobj_attribute trace_mode_attr =
 531        __ATTR(trace_mode, 0644, trace_mode_show, trace_mode_store);
 532
 533static 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
 586out:
 587        return ret;
 588
 589out_unmap:
 590        amba_set_drvdata(dev, NULL);
 591        iounmap(t->etm_regs);
 592
 593out_release:
 594        amba_release_regions(dev);
 595
 596        return ret;
 597}
 598
 599static 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
 617static struct amba_id etm_ids[] = {
 618        {
 619                .id     = 0x0003b921,
 620                .mask   = 0x0007ffff,
 621        },
 622        { 0, 0 },
 623};
 624
 625static 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
 635static 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
 658device_initcall(etm_init);
 659
 660