summaryrefslogtreecommitdiff
path: root/arch/arm/kernel
diff options
context:
space:
mode:
authorArve Hjønnevåg <arve@android.com>2011-01-31 18:33:55 -0800
committerFrank Li <Frank.Li@freescale.com>2012-09-26 13:23:15 +0800
commit3e235453f19fbc4825d280a82ee21823dc8558be (patch)
treec7e01680e0f91cfbb925dc1d90cd407da2dc57f0 /arch/arm/kernel
parent6076866b604c73943dab3b84a129878bb1d7a4eb (diff)
ARM: etm: Configure data tracing
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>
Diffstat (limited to 'arch/arm/kernel')
-rw-r--r--arch/arm/kernel/etm.c77
1 files changed, 74 insertions, 3 deletions
diff --git a/arch/arm/kernel/etm.c b/arch/arm/kernel/etm.c
index 2e7bff8fb44a..b5f5aadf6f0a 100644
--- a/arch/arm/kernel/etm.c
+++ b/arch/arm/kernel/etm.c
@@ -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;
}