]> git.karo-electronics.de Git - karo-tx-linux.git/commitdiff
ARM: etm: Configure data tracing
authorArve Hjønnevåg <arve@android.com>
Tue, 1 Feb 2011 02:33:55 +0000 (18:33 -0800)
committerLothar Waßmann <LW@KARO-electronics.de>
Fri, 24 May 2013 06:35:27 +0000 (08:35 +0200)
The old code enabled data tracing, but did not configure the
range. We now configure it to trace all data addresses by default,
and add a trace_data_range attribute to change the range or disable
data tracing.

Change-Id: I9d04e3e1ea0d0b4d4d5bcb93b1b042938ad738b2
Signed-off-by: Arve Hjønnevåg <arve@android.com>
arch/arm/include/asm/hardware/coresight.h
arch/arm/kernel/etm.c

index 7ecd793b8f5a94ebdbba19ee26ac9a75eaaa33d6..6ea507fe5400ade846dfb4be2008944dc1cb1246 100644 (file)
 #define TRACER_ACCESSED_BIT    0
 #define TRACER_RUNNING_BIT     1
 #define TRACER_CYCLE_ACC_BIT   2
+#define TRACER_TRACE_DATA_BIT  3
 #define TRACER_ACCESSED                BIT(TRACER_ACCESSED_BIT)
 #define TRACER_RUNNING         BIT(TRACER_RUNNING_BIT)
 #define TRACER_CYCLE_ACC       BIT(TRACER_CYCLE_ACC_BIT)
+#define TRACER_TRACE_DATA      BIT(TRACER_TRACE_DATA_BIT)
 
 #define TRACER_TIMEOUT 10000
 
 #define ETMR_TRACEENCTRL       0x24
 #define ETMTE_INCLEXCL         BIT(24)
 #define ETMR_TRACEENEVT                0x20
+
+#define ETMR_VIEWDATAEVT       0x30
+#define ETMR_VIEWDATACTRL1     0x34
+#define ETMR_VIEWDATACTRL2     0x38
+#define ETMR_VIEWDATACTRL3     0x3c
+#define ETMVDC3_EXCLONLY       BIT(16)
+
 #define ETMCTRL_OPTS           (ETMCTRL_DO_CPRT | \
-                               ETMCTRL_DATA_DO_ADDR | \
                                ETMCTRL_BRANCH_OUTPUT | \
                                ETMCTRL_DO_CONTEXTID)
 
index 2e7bff8fb44abf11fd60ea53aac79b2ce1c4a608..b5f5aadf6f0ab61e4687ac2b42a92e8c6d51671e 100644 (file)
@@ -42,6 +42,8 @@ struct tracectx {
        int             etm_portsz;
        unsigned long   range_start;
        unsigned long   range_end;
+       unsigned long   data_range_start;
+       unsigned long   data_range_end;
        struct device   *dev;
        struct clk      *emu_clk;
        struct mutex    mutex;
@@ -83,8 +85,15 @@ static int etm_setup_address_range(struct tracectx *t, int n,
        etm_writel(t, flags, ETMR_COMP_ACC_TYPE(n * 2 + 1));
        etm_writel(t, end, ETMR_COMP_VAL(n * 2 + 1));
 
-       flags = exclude ? ETMTE_INCLEXCL : 0;
-       etm_writel(t, flags | (1 << n), ETMR_TRACEENCTRL);
+       if (data) {
+               flags = exclude ? ETMVDC3_EXCLONLY : 0;
+               if (exclude)
+                       n += 8;
+               etm_writel(t, flags | BIT(n), ETMR_VIEWDATACTRL3);
+       } else {
+               flags = exclude ? ETMTE_INCLEXCL : 0;
+               etm_writel(t, flags | (1 << n), ETMR_TRACEENCTRL);
+       }
 
        return 0;
 }
@@ -108,6 +117,9 @@ static int trace_start(struct tracectx *t)
        if (t->flags & TRACER_CYCLE_ACC)
                v |= ETMCTRL_CYCLEACCURATE;
 
+       if (t->flags & TRACER_TRACE_DATA)
+               v |= ETMCTRL_DATA_DO_ADDR;
+
        etm_unlock(t);
 
        etm_writel(t, v, ETMR_CTRL);
@@ -130,6 +142,17 @@ static int trace_start(struct tracectx *t)
        etm_writel(t, 0, ETMR_TRACESSCTRL);
        etm_writel(t, 0x6f, ETMR_TRACEENEVT);
 
+       etm_writel(t, 0, ETMR_VIEWDATACTRL1);
+       etm_writel(t, 0, ETMR_VIEWDATACTRL2);
+
+       if (t->data_range_start || t->data_range_end)
+               etm_setup_address_range(t, 2, t->data_range_start,
+                                       t->data_range_end, 0, 1);
+       else
+               etm_writel(t, ETMVDC3_EXCLONLY, ETMR_VIEWDATACTRL3);
+
+       etm_writel(t, 0x6f, ETMR_VIEWDATAEVT);
+
        v &= ~ETMCTRL_PROGRAM;
        v |= ETMCTRL_PORTSEL;
 
@@ -563,6 +586,48 @@ static ssize_t trace_range_store(struct kobject *kobj,
 static struct kobj_attribute trace_range_attr =
        __ATTR(trace_range, 0644, trace_range_show, trace_range_store);
 
+static ssize_t trace_data_range_show(struct kobject *kobj,
+                                 struct kobj_attribute *attr,
+                                 char *buf)
+{
+       unsigned long range_start;
+       u64 range_end;
+       mutex_lock(&tracer.mutex);
+       range_start = tracer.data_range_start;
+       range_end = tracer.data_range_end;
+       if (!range_end && (tracer.flags & TRACER_TRACE_DATA))
+               range_end = 0x100000000ULL;
+       mutex_unlock(&tracer.mutex);
+       return sprintf(buf, "%08lx %08llx\n", range_start, range_end);
+}
+
+static ssize_t trace_data_range_store(struct kobject *kobj,
+                                  struct kobj_attribute *attr,
+                                  const char *buf, size_t n)
+{
+       unsigned long range_start;
+       u64 range_end;
+
+       if (sscanf(buf, "%lx %llx", &range_start, &range_end) != 2)
+               return -EINVAL;
+
+       mutex_lock(&tracer.mutex);
+       tracer.data_range_start = range_start;
+       tracer.data_range_end = (unsigned long)range_end;
+       if (range_end)
+               tracer.flags |= TRACER_TRACE_DATA;
+       else
+               tracer.flags &= ~TRACER_TRACE_DATA;
+       mutex_unlock(&tracer.mutex);
+
+       return n;
+}
+
+
+static struct kobj_attribute trace_data_range_attr =
+       __ATTR(trace_data_range, 0644,
+               trace_data_range_show, trace_data_range_store);
+
 static int __devinit etm_probe(struct amba_device *dev, const struct amba_id *id)
 {
        struct tracectx *t = &tracer;
@@ -588,7 +653,7 @@ static int __devinit etm_probe(struct amba_device *dev, const struct amba_id *id
 
        mutex_init(&t->mutex);
        t->dev = &dev->dev;
-       t->flags = TRACER_CYCLE_ACC;
+       t->flags = TRACER_CYCLE_ACC | TRACER_TRACE_DATA;
        t->etm_portsz = 1;
 
        etm_unlock(t);
@@ -618,6 +683,11 @@ static int __devinit etm_probe(struct amba_device *dev, const struct amba_id *id
        if (ret)
                dev_dbg(&dev->dev, "Failed to create trace_range in sysfs\n");
 
+       ret = sysfs_create_file(&dev->dev.kobj, &trace_data_range_attr.attr);
+       if (ret)
+               dev_dbg(&dev->dev,
+                       "Failed to create trace_data_range in sysfs\n");
+
        dev_dbg(t->dev, "ETM AMBA driver initialized.\n");
 
 out:
@@ -648,6 +718,7 @@ static int etm_remove(struct amba_device *dev)
        sysfs_remove_file(&dev->dev.kobj, &trace_info_attr.attr);
        sysfs_remove_file(&dev->dev.kobj, &trace_mode_attr.attr);
        sysfs_remove_file(&dev->dev.kobj, &trace_range_attr.attr);
+       sysfs_remove_file(&dev->dev.kobj, &trace_data_range_attr.attr);
 
        return 0;
 }