mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-08 20:07:46 +09:00
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>
This commit is contained in:
committed by
Colin Cross
parent
9d87d4816d
commit
4edf87412c
@@ -17,9 +17,11 @@
|
||||
#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
|
||||
|
||||
@@ -113,8 +115,14 @@
|
||||
#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)
|
||||
|
||||
|
||||
@@ -43,6 +43,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;
|
||||
@@ -84,8 +86,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;
|
||||
}
|
||||
@@ -109,6 +118,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);
|
||||
@@ -131,6 +143,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;
|
||||
|
||||
@@ -561,6 +584,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 etm_probe(struct amba_device *dev, const struct amba_id *id)
|
||||
{
|
||||
struct tracectx *t = &tracer;
|
||||
@@ -586,7 +651,7 @@ static int 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);
|
||||
@@ -616,6 +681,11 @@ static int 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:
|
||||
@@ -643,6 +713,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;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user