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