2012-06-20 22:48:06

by John Stultz

[permalink] [raw]
Subject: [PATCH 00/15] Android ETM driver changes

Since I didn't hear any objections to the earlier RFC release
last week, I wanted to send this on for inclusion.

The Android kernel tree has a number of changes to the ETM driver.
Arve sent the first 9 of these to the list over a year ago and
got very little response.

I didn't want these to get lost, so I pinged Alexander about
these privately and he stated that he wasn't actively
maintaining the driver, but after skimming the entire set he
acked the series and suggested I send it on to Russel for
review and inclusion.

thanks
-john


CC: Russell King <[email protected]>
CC: Paul Gortmaker <[email protected]>
CC: Alexander Shishkin <[email protected]>
CC: Arve Hjønnevåg <[email protected]>

Arve Hjønnevåg (15):
ARM: etm: Don't require clock control
ARM: etm: Don't limit tracing to only non-secure code.
ARM: etm: Don't try to clear the buffer full status after reading the
buffer
ARM: etm: Allow range selection
ARM: etm: Configure data tracing
ARM: etm: Add some missing locks and error checks
ARM: etm: Return the entire trace buffer if it is empty after reset
ARM: etm: Support multiple ETMs/PTMs.
ARM: etm: Power down etm(s) when tracing is not enabled
ARM: etm: Wait for etm/ptm(s) to stop before requesting PowerDown
ARM: etm: Check arch version and disable data tracing for ptm
ARM: etm: Add sysfs entry to enable timestamps if supported
ARM: etm: Add sysfs entry to set context-id-size
ARM: etm: Add sysfs entry to disable branch_output flag
ARM: etm: Add sysfs entry to enable return stack if supported

arch/arm/include/asm/hardware/coresight.h | 50 ++-
arch/arm/kernel/etm.c | 680 +++++++++++++++++++++++------
2 files changed, 587 insertions(+), 143 deletions(-)

--
1.7.9.5


2012-06-20 22:48:24

by John Stultz

[permalink] [raw]
Subject: [PATCH 14/15] ARM: etm: Add sysfs entry to disable branch_output flag

From: Arve Hjønnevåg <[email protected]>

Add sysfs entry to disable branch_output flag

CC: Russell King <[email protected]>
CC: Paul Gortmaker <[email protected]>
CC: Alexander Shishkin <[email protected]>
Acked-by: Alexander Shishkin <[email protected]>
Signed-off-by: Arve Hjønnevåg <[email protected]>
Signed-off-by: John Stultz <[email protected]>
---
arch/arm/include/asm/hardware/coresight.h | 5 ++--
arch/arm/kernel/etm.c | 41 ++++++++++++++++++++++++++++-
2 files changed, 43 insertions(+), 3 deletions(-)

diff --git a/arch/arm/include/asm/hardware/coresight.h b/arch/arm/include/asm/hardware/coresight.h
index 47b7696..727ba0f 100644
--- a/arch/arm/include/asm/hardware/coresight.h
+++ b/arch/arm/include/asm/hardware/coresight.h
@@ -19,11 +19,13 @@
#define TRACER_CYCLE_ACC_BIT 2
#define TRACER_TRACE_DATA_BIT 3
#define TRACER_TIMESTAMP_BIT 4
+#define TRACER_BRANCHOUTPUT_BIT 5
#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_TIMESTAMP BIT(TRACER_TIMESTAMP_BIT)
+#define TRACER_BRANCHOUTPUT BIT(TRACER_BRANCHOUTPUT_BIT)

#define TRACER_TIMEOUT 10000

@@ -126,8 +128,7 @@
#define ETMR_VIEWDATACTRL3 0x3c
#define ETMVDC3_EXCLONLY BIT(16)

-#define ETMCTRL_OPTS (ETMCTRL_DO_CPRT | \
- ETMCTRL_BRANCH_OUTPUT)
+#define ETMCTRL_OPTS (ETMCTRL_DO_CPRT)

#define ETMR_ID 0x1e4
#define ETMIDR_VERSION(x) (((x) >> 4) & 0xff)
diff --git a/arch/arm/kernel/etm.c b/arch/arm/kernel/etm.c
index f00a3f39..8e84d5c 100644
--- a/arch/arm/kernel/etm.c
+++ b/arch/arm/kernel/etm.c
@@ -115,6 +115,9 @@ static int trace_start_etm(struct tracectx *t, int id)
if (t->flags & TRACER_CYCLE_ACC)
v |= ETMCTRL_CYCLEACCURATE;

+ if (t->flags & TRACER_BRANCHOUTPUT)
+ v |= ETMCTRL_BRANCH_OUTPUT;
+
if (t->flags & TRACER_TRACE_DATA)
v |= ETMCTRL_DATA_DO_ADDR;

@@ -683,6 +686,36 @@ static struct kobj_attribute trace_contextid_size_attr =
__ATTR(trace_contextid_size, 0644,
trace_contextid_size_show, trace_contextid_size_store);

+static ssize_t trace_branch_output_show(struct kobject *kobj,
+ struct kobj_attribute *attr,
+ char *buf)
+{
+ return sprintf(buf, "%d\n", !!(tracer.flags & TRACER_BRANCHOUTPUT));
+}
+
+static ssize_t trace_branch_output_store(struct kobject *kobj,
+ struct kobj_attribute *attr,
+ const char *buf, size_t n)
+{
+ unsigned int branch_output;
+
+ if (sscanf(buf, "%u", &branch_output) != 1)
+ return -EINVAL;
+
+ mutex_lock(&tracer.mutex);
+ if (branch_output)
+ tracer.flags |= TRACER_BRANCHOUTPUT;
+ else
+ tracer.flags &= ~TRACER_BRANCHOUTPUT;
+ mutex_unlock(&tracer.mutex);
+
+ return n;
+}
+
+static struct kobj_attribute trace_branch_output_attr =
+ __ATTR(trace_branch_output, 0644,
+ trace_branch_output_show, trace_branch_output_store);
+
static ssize_t trace_timestamp_show(struct kobject *kobj,
struct kobj_attribute *attr,
char *buf)
@@ -820,7 +853,7 @@ static int __devinit etm_probe(struct amba_device *dev, const struct amba_id *id

amba_set_drvdata(dev, t->etm_regs[t->etm_regs_count]);

- t->flags = TRACER_CYCLE_ACC | TRACER_TRACE_DATA;
+ t->flags = TRACER_CYCLE_ACC | TRACER_TRACE_DATA | TRACER_BRANCHOUTPUT;
t->etm_portsz = 1;
t->etm_contextid_size = 3;

@@ -861,6 +894,12 @@ static int __devinit etm_probe(struct amba_device *dev, const struct amba_id *id
dev_dbg(&dev->dev,
"Failed to create trace_contextid_size in sysfs\n");

+ ret = sysfs_create_file(&dev->dev.kobj,
+ &trace_branch_output_attr.attr);
+ if (ret)
+ dev_dbg(&dev->dev,
+ "Failed to create trace_branch_output in sysfs\n");
+
if (etmccer & ETMCCER_TIMESTAMPING_IMPLEMENTED) {
ret = sysfs_create_file(&dev->dev.kobj,
&trace_timestamp_attr.attr);
--
1.7.9.5

2012-06-20 22:48:40

by John Stultz

[permalink] [raw]
Subject: [PATCH 07/15] ARM: etm: Return the entire trace buffer if it is empty after reset

From: Arve Hjønnevåg <[email protected]>

On some SOCs the read and write pointer are reset when the chip
resets, but the trace buffer content is preserved. If the status
bits indicates that the buffer is empty and we have never started
tracing, assume the buffer is full instead. This can be useful
if the system rebooted from a watchdog reset.

CC: Russell King <[email protected]>
CC: Paul Gortmaker <[email protected]>
CC: Alexander Shishkin <[email protected]>
Acked-by: Alexander Shishkin <[email protected]>
Signed-off-by: Arve Hjønnevåg <[email protected]>
Signed-off-by: John Stultz <[email protected]>
---
arch/arm/kernel/etm.c | 5 +++++
1 file changed, 5 insertions(+)

diff --git a/arch/arm/kernel/etm.c b/arch/arm/kernel/etm.c
index 3d21cf6..74444e5 100644
--- a/arch/arm/kernel/etm.c
+++ b/arch/arm/kernel/etm.c
@@ -45,6 +45,7 @@ struct tracectx {
unsigned long range_end;
unsigned long data_range_start;
unsigned long data_range_end;
+ bool dump_initial_etb;
struct device *dev;
struct clk *emu_clk;
struct mutex mutex;
@@ -106,6 +107,7 @@ static int trace_start(struct tracectx *t)

etb_unlock(t);

+ t->dump_initial_etb = false;
etb_writel(t, 0, ETBR_WRITEADDR);
etb_writel(t, 0, ETBR_FORMATTERCTRL);
etb_writel(t, 1, ETBR_CTRL);
@@ -312,6 +314,8 @@ static ssize_t etb_read(struct file *file, char __user *data,
etb_unlock(t);

total = etb_getdatalen(t);
+ if (total == 0 && t->dump_initial_etb)
+ total = t->etb_bufsz;
if (total == t->etb_bufsz)
first = etb_readl(t, ETBR_WRITEADDR);

@@ -386,6 +390,7 @@ static int __devinit etb_probe(struct amba_device *dev, const struct amba_id *id
goto out_release;
}

+ t->dump_initial_etb = true;
amba_set_drvdata(dev, t);

etb_unlock(t);
--
1.7.9.5

2012-06-20 22:48:45

by John Stultz

[permalink] [raw]
Subject: [PATCH 15/15] ARM: etm: Add sysfs entry to enable return stack if supported

From: Arve Hjønnevåg <[email protected]>

Add sysfs entry to enable return stack if supported

CC: Russell King <[email protected]>
CC: Paul Gortmaker <[email protected]>
CC: Alexander Shishkin <[email protected]>
Acked-by: Alexander Shishkin <[email protected]>
Signed-off-by: Arve Hjønnevåg <[email protected]>
Signed-off-by: John Stultz <[email protected]>
---
arch/arm/include/asm/hardware/coresight.h | 4 +++
arch/arm/kernel/etm.c | 51 +++++++++++++++++++++++++++--
2 files changed, 53 insertions(+), 2 deletions(-)

diff --git a/arch/arm/include/asm/hardware/coresight.h b/arch/arm/include/asm/hardware/coresight.h
index 727ba0f..dcf74d7 100644
--- a/arch/arm/include/asm/hardware/coresight.h
+++ b/arch/arm/include/asm/hardware/coresight.h
@@ -20,12 +20,14 @@
#define TRACER_TRACE_DATA_BIT 3
#define TRACER_TIMESTAMP_BIT 4
#define TRACER_BRANCHOUTPUT_BIT 5
+#define TRACER_RETURN_STACK_BIT 6
#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_TIMESTAMP BIT(TRACER_TIMESTAMP_BIT)
#define TRACER_BRANCHOUTPUT BIT(TRACER_BRANCHOUTPUT_BIT)
+#define TRACER_RETURN_STACK BIT(TRACER_RETURN_STACK_BIT)

#define TRACER_TIMEOUT 10000

@@ -62,6 +64,7 @@
#define ETMCTRL_BRANCH_OUTPUT (1 << 8)
#define ETMCTRL_CYCLEACCURATE (1 << 12)
#define ETMCTRL_TIMESTAMP_EN (1 << 28)
+#define ETMCTRL_RETURN_STACK_EN (1 << 29)

/* ETM configuration code register */
#define ETMR_CONFCODE (0x04)
@@ -136,6 +139,7 @@
#define ETMIDR_VERSION_PFT_1_0 0x30

#define ETMR_CCE 0x1e8
+#define ETMCCER_RETURN_STACK_IMPLEMENTED BIT(23)
#define ETMCCER_TIMESTAMPING_IMPLEMENTED BIT(22)

#define ETMR_TRACEIDR 0x200
diff --git a/arch/arm/kernel/etm.c b/arch/arm/kernel/etm.c
index 8e84d5c..c5fb6c9 100644
--- a/arch/arm/kernel/etm.c
+++ b/arch/arm/kernel/etm.c
@@ -124,6 +124,9 @@ static int trace_start_etm(struct tracectx *t, int id)
if (t->flags & TRACER_TIMESTAMP)
v |= ETMCTRL_TIMESTAMP_EN;

+ if (t->flags & TRACER_RETURN_STACK)
+ v |= ETMCTRL_RETURN_STACK_EN;
+
etm_unlock(t, id);

etm_writel(t, id, v, ETMR_CTRL);
@@ -703,10 +706,13 @@ static ssize_t trace_branch_output_store(struct kobject *kobj,
return -EINVAL;

mutex_lock(&tracer.mutex);
- if (branch_output)
+ if (branch_output) {
tracer.flags |= TRACER_BRANCHOUTPUT;
- else
+ /* Branch broadcasting is incompatible with the return stack */
+ tracer.flags &= ~TRACER_RETURN_STACK;
+ } else {
tracer.flags &= ~TRACER_BRANCHOUTPUT;
+ }
mutex_unlock(&tracer.mutex);

return n;
@@ -716,6 +722,39 @@ static struct kobj_attribute trace_branch_output_attr =
__ATTR(trace_branch_output, 0644,
trace_branch_output_show, trace_branch_output_store);

+static ssize_t trace_return_stack_show(struct kobject *kobj,
+ struct kobj_attribute *attr,
+ char *buf)
+{
+ return sprintf(buf, "%d\n", !!(tracer.flags & TRACER_RETURN_STACK));
+}
+
+static ssize_t trace_return_stack_store(struct kobject *kobj,
+ struct kobj_attribute *attr,
+ const char *buf, size_t n)
+{
+ unsigned int return_stack;
+
+ if (sscanf(buf, "%u", &return_stack) != 1)
+ return -EINVAL;
+
+ mutex_lock(&tracer.mutex);
+ if (return_stack) {
+ tracer.flags |= TRACER_RETURN_STACK;
+ /* Return stack is incompatible with branch broadcasting */
+ tracer.flags &= ~TRACER_BRANCHOUTPUT;
+ } else {
+ tracer.flags &= ~TRACER_RETURN_STACK;
+ }
+ mutex_unlock(&tracer.mutex);
+
+ return n;
+}
+
+static struct kobj_attribute trace_return_stack_attr =
+ __ATTR(trace_return_stack, 0644,
+ trace_return_stack_show, trace_return_stack_store);
+
static ssize_t trace_timestamp_show(struct kobject *kobj,
struct kobj_attribute *attr,
char *buf)
@@ -900,6 +939,14 @@ static int __devinit etm_probe(struct amba_device *dev, const struct amba_id *id
dev_dbg(&dev->dev,
"Failed to create trace_branch_output in sysfs\n");

+ if (etmccer & ETMCCER_RETURN_STACK_IMPLEMENTED) {
+ ret = sysfs_create_file(&dev->dev.kobj,
+ &trace_return_stack_attr.attr);
+ if (ret)
+ dev_dbg(&dev->dev,
+ "Failed to create trace_return_stack in sysfs\n");
+ }
+
if (etmccer & ETMCCER_TIMESTAMPING_IMPLEMENTED) {
ret = sysfs_create_file(&dev->dev.kobj,
&trace_timestamp_attr.attr);
--
1.7.9.5

2012-06-20 22:49:21

by John Stultz

[permalink] [raw]
Subject: [PATCH 06/15] ARM: etm: Add some missing locks and error checks

From: Arve Hjønnevåg <[email protected]>

It is not safe to call etm_lock or etb_lock without holding the
mutex since another thread may also have unlocked the registers.

Also add some missing checks for valid etb_regs in the etm sysfs
entries.

CC: Russell King <[email protected]>
CC: Paul Gortmaker <[email protected]>
CC: Alexander Shishkin <[email protected]>
Acked-by: Alexander Shishkin <[email protected]>
Signed-off-by: Arve Hjønnevåg <[email protected]>
Signed-off-by: John Stultz <[email protected]>
---
arch/arm/kernel/etm.c | 57 +++++++++++++++++++++++++++++++++----------------
1 file changed, 39 insertions(+), 18 deletions(-)

diff --git a/arch/arm/kernel/etm.c b/arch/arm/kernel/etm.c
index c651cf9..3d21cf6 100644
--- a/arch/arm/kernel/etm.c
+++ b/arch/arm/kernel/etm.c
@@ -264,8 +264,13 @@ static void etm_dump(void)

static void sysrq_etm_dump(int key)
{
+ if (!mutex_trylock(&tracer.mutex)) {
+ printk(KERN_INFO "Tracing hardware busy\n");
+ return;
+ }
dev_dbg(tracer.dev, "Dumping ETB buffer\n");
etm_dump();
+ mutex_unlock(&tracer.mutex);
}

static struct sysrq_key_op sysrq_etm_op = {
@@ -374,6 +379,7 @@ static int __devinit etb_probe(struct amba_device *dev, const struct amba_id *id
if (ret)
goto out;

+ mutex_lock(&t->mutex);
t->etb_regs = ioremap_nocache(dev->res.start, resource_size(&dev->res));
if (!t->etb_regs) {
ret = -ENOMEM;
@@ -382,6 +388,16 @@ static int __devinit etb_probe(struct amba_device *dev, const struct amba_id *id

amba_set_drvdata(dev, t);

+ etb_unlock(t);
+ t->etb_bufsz = etb_readl(t, ETBR_DEPTH);
+ dev_dbg(&dev->dev, "Size: %x\n", t->etb_bufsz);
+
+ /* make sure trace capture is disabled */
+ etb_writel(t, 0, ETBR_CTRL);
+ etb_writel(t, 0x1000, ETBR_FORMATTERCTRL);
+ etb_lock(t);
+ mutex_unlock(&t->mutex);
+
etb_miscdev.parent = &dev->dev;

ret = misc_register(&etb_miscdev);
@@ -395,25 +411,19 @@ static int __devinit etb_probe(struct amba_device *dev, const struct amba_id *id
else
clk_enable(t->emu_clk);

- etb_unlock(t);
- t->etb_bufsz = etb_readl(t, ETBR_DEPTH);
- dev_dbg(&dev->dev, "Size: %x\n", t->etb_bufsz);
-
- /* make sure trace capture is disabled */
- etb_writel(t, 0, ETBR_CTRL);
- etb_writel(t, 0x1000, ETBR_FORMATTERCTRL);
- etb_lock(t);
-
dev_dbg(&dev->dev, "ETB AMBA driver initialized.\n");

out:
return ret;

out_unmap:
+ mutex_lock(&t->mutex);
amba_set_drvdata(dev, NULL);
iounmap(t->etb_regs);
+ t->etb_regs = NULL;

out_release:
+ mutex_unlock(&t->mutex);
amba_release_regions(dev);

return ret;
@@ -475,7 +485,10 @@ static ssize_t trace_running_store(struct kobject *kobj,
return -EINVAL;

mutex_lock(&tracer.mutex);
- ret = value ? trace_start(&tracer) : trace_stop(&tracer);
+ if (!tracer.etb_regs)
+ ret = -ENODEV;
+ else
+ ret = value ? trace_start(&tracer) : trace_stop(&tracer);
mutex_unlock(&tracer.mutex);

return ret ? : n;
@@ -491,18 +504,25 @@ static ssize_t trace_info_show(struct kobject *kobj,
u32 etb_wa, etb_ra, etb_st, etb_fc, etm_ctrl, etm_st;
int datalen;

- etb_unlock(&tracer);
- datalen = etb_getdatalen(&tracer);
- etb_wa = etb_readl(&tracer, ETBR_WRITEADDR);
- etb_ra = etb_readl(&tracer, ETBR_READADDR);
- etb_st = etb_readl(&tracer, ETBR_STATUS);
- etb_fc = etb_readl(&tracer, ETBR_FORMATTERCTRL);
- etb_lock(&tracer);
+ mutex_lock(&tracer.mutex);
+ if (tracer.etb_regs) {
+ etb_unlock(&tracer);
+ datalen = etb_getdatalen(&tracer);
+ etb_wa = etb_readl(&tracer, ETBR_WRITEADDR);
+ etb_ra = etb_readl(&tracer, ETBR_READADDR);
+ etb_st = etb_readl(&tracer, ETBR_STATUS);
+ etb_fc = etb_readl(&tracer, ETBR_FORMATTERCTRL);
+ etb_lock(&tracer);
+ } else {
+ etb_wa = etb_ra = etb_st = etb_fc = ~0;
+ datalen = -1;
+ }

etm_unlock(&tracer);
etm_ctrl = etm_readl(&tracer, ETMR_CTRL);
etm_st = etm_readl(&tracer, ETMR_STATUS);
etm_lock(&tracer);
+ mutex_unlock(&tracer.mutex);

return sprintf(buf, "Trace buffer len: %d\nComparator pairs: %d\n"
"ETBR_WRITEADDR:\t%08x\n"
@@ -652,7 +672,6 @@ static int __devinit etm_probe(struct amba_device *dev, const struct amba_id *id

amba_set_drvdata(dev, t);

- mutex_init(&t->mutex);
t->dev = &dev->dev;
t->flags = TRACER_CYCLE_ACC | TRACER_TRACE_DATA;
t->etm_portsz = 1;
@@ -746,6 +765,8 @@ static int __init etm_init(void)
{
int retval;

+ mutex_init(&tracer.mutex);
+
retval = amba_driver_register(&etb_driver);
if (retval) {
printk(KERN_ERR "Failed to register etb\n");
--
1.7.9.5

2012-06-20 22:49:27

by John Stultz

[permalink] [raw]
Subject: [PATCH 03/15] ARM: etm: Don't try to clear the buffer full status after reading the buffer

From: Arve Hjønnevåg <[email protected]>

If the write address was at the end of the buffer, toggling the trace
capture bit would set the RAM-full status instead of clearing it, and
if any of the stop bits in the formatter is set toggling the trace
capture bit may not do anything.

Instead use the read position to find out if the data has already
been returned.

This also fixes the read function so it works when the trace buffer is
larger than the buffer passed in from user space. The old version
would reset the trace buffer pointers after every read, so the second
call to read would always return 0.

CC: Russell King <[email protected]>
CC: Paul Gortmaker <[email protected]>
CC: Alexander Shishkin <[email protected]>
Acked-by: Alexander Shishkin <[email protected]>
Signed-off-by: Arve Hjønnevåg <[email protected]>
Signed-off-by: John Stultz <[email protected]>
---
arch/arm/kernel/etm.c | 58 ++++++++++++++++++++++---------------------------
1 file changed, 26 insertions(+), 32 deletions(-)

diff --git a/arch/arm/kernel/etm.c b/arch/arm/kernel/etm.c
index d7622f9..a51bccc 100644
--- a/arch/arm/kernel/etm.c
+++ b/arch/arm/kernel/etm.c
@@ -92,6 +92,7 @@ static int trace_start(struct tracectx *t)

etb_unlock(t);

+ etb_writel(t, 0, ETBR_WRITEADDR);
etb_writel(t, 0, ETBR_FORMATTERCTRL);
etb_writel(t, 1, ETBR_CTRL);

@@ -185,24 +186,15 @@ static int trace_stop(struct tracectx *t)
static int etb_getdatalen(struct tracectx *t)
{
u32 v;
- int rp, wp;
+ int wp;

v = etb_readl(t, ETBR_STATUS);

if (v & 1)
return t->etb_bufsz;

- rp = etb_readl(t, ETBR_READADDR);
wp = etb_readl(t, ETBR_WRITEADDR);
-
- if (rp > wp) {
- etb_writel(t, 0, ETBR_READADDR);
- etb_writel(t, 0, ETBR_WRITEADDR);
-
- return 0;
- }
-
- return wp - rp;
+ return wp;
}

/* sysrq+v will always stop the running trace and leave it at that */
@@ -235,14 +227,6 @@ static void etm_dump(void)
printk("%08x", cpu_to_be32(etb_readl(t, ETBR_READMEM)));
printk(KERN_INFO "\n--- ETB buffer end ---\n");

- /* deassert the overflow bit */
- etb_writel(t, 1, ETBR_CTRL);
- etb_writel(t, 0, ETBR_CTRL);
-
- etb_writel(t, 0, ETBR_TRIGGERCOUNT);
- etb_writel(t, 0, ETBR_READADDR);
- etb_writel(t, 0, ETBR_WRITEADDR);
-
etb_lock(t);
}

@@ -276,6 +260,10 @@ static ssize_t etb_read(struct file *file, char __user *data,
struct tracectx *t = file->private_data;
u32 first = 0;
u32 *buf;
+ int wpos;
+ int skip;
+ long wlength;
+ loff_t pos = *ppos;

mutex_lock(&t->mutex);

@@ -290,28 +278,34 @@ static ssize_t etb_read(struct file *file, char __user *data,
if (total == t->etb_bufsz)
first = etb_readl(t, ETBR_WRITEADDR);

+ if (pos > total * 4) {
+ skip = 0;
+ wpos = total;
+ } else {
+ skip = (int)pos % 4;
+ wpos = (int)pos / 4;
+ }
+ total -= wpos;
+ first = (first + wpos) % t->etb_bufsz;
+
etb_writel(t, first, ETBR_READADDR);

- length = min(total * 4, (int)len);
- buf = vmalloc(length);
+ wlength = min(total, DIV_ROUND_UP(skip + (int)len, 4));
+ length = min(total * 4 - skip, (int)len);
+ buf = vmalloc(wlength * 4);

- dev_dbg(t->dev, "ETB buffer length: %d\n", total);
+ dev_dbg(t->dev, "ETB read %ld bytes to %lld from %ld words at %d\n",
+ length, pos, wlength, first);
+ dev_dbg(t->dev, "ETB buffer length: %d\n", total + wpos);
dev_dbg(t->dev, "ETB status reg: %x\n", etb_readl(t, ETBR_STATUS));
- for (i = 0; i < length / 4; i++)
+ for (i = 0; i < wlength; i++)
buf[i] = etb_readl(t, ETBR_READMEM);

- /* the only way to deassert overflow bit in ETB status is this */
- etb_writel(t, 1, ETBR_CTRL);
- etb_writel(t, 0, ETBR_CTRL);
-
- etb_writel(t, 0, ETBR_WRITEADDR);
- etb_writel(t, 0, ETBR_READADDR);
- etb_writel(t, 0, ETBR_TRIGGERCOUNT);
-
etb_lock(t);

- length -= copy_to_user(data, buf, length);
+ length -= copy_to_user(data, (u8 *)buf + skip, length);
vfree(buf);
+ *ppos = pos + length;

out:
mutex_unlock(&t->mutex);
--
1.7.9.5

2012-06-20 22:49:51

by John Stultz

[permalink] [raw]
Subject: [PATCH 01/15] ARM: etm: Don't require clock control

From: Arve Hjønnevåg <[email protected]>

If clk_get fail, assume the etb does not need a separate clock.

CC: Russell King <[email protected]>
CC: Paul Gortmaker <[email protected]>
CC: Alexander Shishkin <[email protected]>
Acked-by: Alexander Shishkin <[email protected]>
Signed-off-by: Arve Hjønnevåg <[email protected]>
Signed-off-by: John Stultz <[email protected]>
---
arch/arm/kernel/etm.c | 15 ++++++++-------
1 file changed, 8 insertions(+), 7 deletions(-)

diff --git a/arch/arm/kernel/etm.c b/arch/arm/kernel/etm.c
index 36d20bd..bd295e8 100644
--- a/arch/arm/kernel/etm.c
+++ b/arch/arm/kernel/etm.c
@@ -362,13 +362,12 @@ static int __devinit etb_probe(struct amba_device *dev, const struct amba_id *id
if (ret)
goto out_unmap;

+ /* Get optional clock. Currently used to select clock source on omap3 */
t->emu_clk = clk_get(&dev->dev, "emu_src_ck");
- if (IS_ERR(t->emu_clk)) {
+ if (IS_ERR(t->emu_clk))
dev_dbg(&dev->dev, "Failed to obtain emu_src_ck.\n");
- return -EFAULT;
- }
-
- clk_enable(t->emu_clk);
+ else
+ clk_enable(t->emu_clk);

etb_unlock(t);
t->etb_bufsz = etb_readl(t, ETBR_DEPTH);
@@ -403,8 +402,10 @@ static int etb_remove(struct amba_device *dev)
iounmap(t->etb_regs);
t->etb_regs = NULL;

- clk_disable(t->emu_clk);
- clk_put(t->emu_clk);
+ if (!IS_ERR(t->emu_clk)) {
+ clk_disable(t->emu_clk);
+ clk_put(t->emu_clk);
+ }

amba_release_regions(dev);

--
1.7.9.5

2012-06-20 22:49:58

by John Stultz

[permalink] [raw]
Subject: [PATCH 13/15] ARM: etm: Add sysfs entry to set context-id-size

From: Arve Hjønnevåg <[email protected]>

Add sysfs entry to set context-id-size

CC: Russell King <[email protected]>
CC: Paul Gortmaker <[email protected]>
CC: Alexander Shishkin <[email protected]>
Acked-by: Alexander Shishkin <[email protected]>
Signed-off-by: Arve Hjønnevåg <[email protected]>
Signed-off-by: John Stultz <[email protected]>
---
arch/arm/include/asm/hardware/coresight.h | 5 ++--
arch/arm/kernel/etm.c | 40 +++++++++++++++++++++++++++++
2 files changed, 42 insertions(+), 3 deletions(-)

diff --git a/arch/arm/include/asm/hardware/coresight.h b/arch/arm/include/asm/hardware/coresight.h
index 42059d3..47b7696 100644
--- a/arch/arm/include/asm/hardware/coresight.h
+++ b/arch/arm/include/asm/hardware/coresight.h
@@ -47,7 +47,7 @@
#define ETMCTRL_POWERDOWN 1
#define ETMCTRL_PROGRAM (1 << 10)
#define ETMCTRL_PORTSEL (1 << 11)
-#define ETMCTRL_DO_CONTEXTID (3 << 14)
+#define ETMCTRL_CONTEXTIDSIZE(x) (((x) & 3) << 14)
#define ETMCTRL_PORTMASK1 (7 << 4)
#define ETMCTRL_PORTMASK2 (1 << 21)
#define ETMCTRL_PORTMASK (ETMCTRL_PORTMASK1 | ETMCTRL_PORTMASK2)
@@ -127,8 +127,7 @@
#define ETMVDC3_EXCLONLY BIT(16)

#define ETMCTRL_OPTS (ETMCTRL_DO_CPRT | \
- ETMCTRL_BRANCH_OUTPUT | \
- ETMCTRL_DO_CONTEXTID)
+ ETMCTRL_BRANCH_OUTPUT)

#define ETMR_ID 0x1e4
#define ETMIDR_VERSION(x) (((x) >> 4) & 0xff)
diff --git a/arch/arm/kernel/etm.c b/arch/arm/kernel/etm.c
index 460a7d8..f00a3f39 100644
--- a/arch/arm/kernel/etm.c
+++ b/arch/arm/kernel/etm.c
@@ -43,6 +43,7 @@ struct tracectx {
unsigned long flags;
int ncmppairs;
int etm_portsz;
+ int etm_contextid_size;
u32 etb_fc;
unsigned long range_start;
unsigned long range_end;
@@ -109,6 +110,7 @@ static int trace_start_etm(struct tracectx *t, int id)
unsigned long timeout = TRACER_TIMEOUT;

v = ETMCTRL_OPTS | ETMCTRL_PROGRAM | ETMCTRL_PORTSIZE(t->etm_portsz);
+ v |= ETMCTRL_CONTEXTIDSIZE(t->etm_contextid_size);

if (t->flags & TRACER_CYCLE_ACC)
v |= ETMCTRL_CYCLEACCURATE;
@@ -650,6 +652,37 @@ static ssize_t trace_mode_store(struct kobject *kobj,
static struct kobj_attribute trace_mode_attr =
__ATTR(trace_mode, 0644, trace_mode_show, trace_mode_store);

+static ssize_t trace_contextid_size_show(struct kobject *kobj,
+ struct kobj_attribute *attr,
+ char *buf)
+{
+ /* 0: No context id tracing, 1: One byte, 2: Two bytes, 3: Four bytes */
+ return sprintf(buf, "%d\n", (1 << tracer.etm_contextid_size) >> 1);
+}
+
+static ssize_t trace_contextid_size_store(struct kobject *kobj,
+ struct kobj_attribute *attr,
+ const char *buf, size_t n)
+{
+ unsigned int contextid_size;
+
+ if (sscanf(buf, "%u", &contextid_size) != 1)
+ return -EINVAL;
+
+ if (contextid_size == 3 || contextid_size > 4)
+ return -EINVAL;
+
+ mutex_lock(&tracer.mutex);
+ tracer.etm_contextid_size = fls(contextid_size);
+ mutex_unlock(&tracer.mutex);
+
+ return n;
+}
+
+static struct kobj_attribute trace_contextid_size_attr =
+ __ATTR(trace_contextid_size, 0644,
+ trace_contextid_size_show, trace_contextid_size_store);
+
static ssize_t trace_timestamp_show(struct kobject *kobj,
struct kobj_attribute *attr,
char *buf)
@@ -789,6 +822,7 @@ static int __devinit etm_probe(struct amba_device *dev, const struct amba_id *id

t->flags = TRACER_CYCLE_ACC | TRACER_TRACE_DATA;
t->etm_portsz = 1;
+ t->etm_contextid_size = 3;

etm_unlock(t, t->etm_regs_count);
(void)etm_readl(t, t->etm_regs_count, ETMMR_PDSR);
@@ -821,6 +855,12 @@ static int __devinit etm_probe(struct amba_device *dev, const struct amba_id *id
if (ret)
dev_dbg(&dev->dev, "Failed to create trace_mode in sysfs\n");

+ ret = sysfs_create_file(&dev->dev.kobj,
+ &trace_contextid_size_attr.attr);
+ if (ret)
+ dev_dbg(&dev->dev,
+ "Failed to create trace_contextid_size in sysfs\n");
+
if (etmccer & ETMCCER_TIMESTAMPING_IMPLEMENTED) {
ret = sysfs_create_file(&dev->dev.kobj,
&trace_timestamp_attr.attr);
--
1.7.9.5

2012-06-20 22:50:07

by John Stultz

[permalink] [raw]
Subject: [PATCH 10/15] ARM: etm: Wait for etm/ptm(s) to stop before requesting PowerDown

From: Arve Hjønnevåg <[email protected]>

When PowerDown was requested at the same time as ProgBit, the
formatter flush command that follows could get stuck.

CC: Russell King <[email protected]>
CC: Paul Gortmaker <[email protected]>
CC: Alexander Shishkin <[email protected]>
Acked-by: Alexander Shishkin <[email protected]>
Signed-off-by: Arve Hjønnevåg <[email protected]>
Signed-off-by: John Stultz <[email protected]>
---
arch/arm/kernel/etm.c | 36 ++++++++++++++++++++++++++++--------
1 file changed, 28 insertions(+), 8 deletions(-)

diff --git a/arch/arm/kernel/etm.c b/arch/arm/kernel/etm.c
index 66bf592..bad28de 100644
--- a/arch/arm/kernel/etm.c
+++ b/arch/arm/kernel/etm.c
@@ -200,11 +200,13 @@ static int trace_stop_etm(struct tracectx *t, int id)

etm_unlock(t, id);

- etm_writel(t, id, 0x441, ETMR_CTRL);
+ etm_writel(t, id, 0x440, ETMR_CTRL);
while (!(etm_readl(t, id, ETMR_CTRL) & ETMCTRL_PROGRAM) && --timeout)
;
if (!timeout) {
- dev_dbg(t->dev, "Waiting for progbit to assert timed out\n");
+ dev_err(t->dev,
+ "etm%d: Waiting for progbit to assert timed out\n",
+ id);
etm_lock(t, id);
return -EFAULT;
}
@@ -213,18 +215,36 @@ static int trace_stop_etm(struct tracectx *t, int id)
return 0;
}

+static int trace_power_down_etm(struct tracectx *t, int id)
+{
+ unsigned long timeout = TRACER_TIMEOUT;
+ etm_unlock(t, id);
+ while (!(etm_readl(t, id, ETMR_STATUS) & ETMST_PROGBIT) && --timeout)
+ ;
+ if (!timeout) {
+ dev_err(t->dev, "etm%d: Waiting for status progbit to assert timed out\n",
+ id);
+ etm_lock(t, id);
+ return -EFAULT;
+ }
+
+ etm_writel(t, id, 0x441, ETMR_CTRL);
+
+ etm_lock(t, id);
+ return 0;
+}
+
static int trace_stop(struct tracectx *t)
{
int id;
- int ret;
unsigned long timeout = TRACER_TIMEOUT;
u32 etb_fc = t->etb_fc;

- for (id = 0; id < t->etm_regs_count; id++) {
- ret = trace_stop_etm(t, id);
- if (ret)
- return ret;
- }
+ for (id = 0; id < t->etm_regs_count; id++)
+ trace_stop_etm(t, id);
+
+ for (id = 0; id < t->etm_regs_count; id++)
+ trace_power_down_etm(t, id);

etb_unlock(t);
if (etb_fc) {
--
1.7.9.5

2012-06-20 22:48:38

by John Stultz

[permalink] [raw]
Subject: [PATCH 12/15] ARM: etm: Add sysfs entry to enable timestamps if supported

From: Arve Hjønnevåg <[email protected]>

Add sysfs entry to enable timestamps if supported

CC: Russell King <[email protected]>
CC: Paul Gortmaker <[email protected]>
CC: Alexander Shishkin <[email protected]>
Acked-by: Alexander Shishkin <[email protected]>
Signed-off-by: Arve Hjønnevåg <[email protected]>
Signed-off-by: John Stultz <[email protected]>
---
arch/arm/include/asm/hardware/coresight.h | 7 +++++
arch/arm/kernel/etm.c | 44 +++++++++++++++++++++++++++++
2 files changed, 51 insertions(+)

diff --git a/arch/arm/include/asm/hardware/coresight.h b/arch/arm/include/asm/hardware/coresight.h
index 0fad8f8..42059d3 100644
--- a/arch/arm/include/asm/hardware/coresight.h
+++ b/arch/arm/include/asm/hardware/coresight.h
@@ -18,10 +18,12 @@
#define TRACER_RUNNING_BIT 1
#define TRACER_CYCLE_ACC_BIT 2
#define TRACER_TRACE_DATA_BIT 3
+#define TRACER_TIMESTAMP_BIT 4
#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_TIMESTAMP BIT(TRACER_TIMESTAMP_BIT)

#define TRACER_TIMEOUT 10000

@@ -57,6 +59,7 @@
#define ETMCTRL_DATA_DO_BOTH (ETMCTRL_DATA_DO_DATA | ETMCTRL_DATA_DO_ADDR)
#define ETMCTRL_BRANCH_OUTPUT (1 << 8)
#define ETMCTRL_CYCLEACCURATE (1 << 12)
+#define ETMCTRL_TIMESTAMP_EN (1 << 28)

/* ETM configuration code register */
#define ETMR_CONFCODE (0x04)
@@ -129,8 +132,12 @@

#define ETMR_ID 0x1e4
#define ETMIDR_VERSION(x) (((x) >> 4) & 0xff)
+#define ETMIDR_VERSION_3_1 0x21
#define ETMIDR_VERSION_PFT_1_0 0x30

+#define ETMR_CCE 0x1e8
+#define ETMCCER_TIMESTAMPING_IMPLEMENTED BIT(22)
+
#define ETMR_TRACEIDR 0x200

/* ETM management registers, "ETM Architecture", 3.5.24 */
diff --git a/arch/arm/kernel/etm.c b/arch/arm/kernel/etm.c
index e42b706..460a7d8 100644
--- a/arch/arm/kernel/etm.c
+++ b/arch/arm/kernel/etm.c
@@ -116,6 +116,9 @@ static int trace_start_etm(struct tracectx *t, int id)
if (t->flags & TRACER_TRACE_DATA)
v |= ETMCTRL_DATA_DO_ADDR;

+ if (t->flags & TRACER_TIMESTAMP)
+ v |= ETMCTRL_TIMESTAMP_EN;
+
etm_unlock(t, id);

etm_writel(t, id, v, ETMR_CTRL);
@@ -647,6 +650,36 @@ static ssize_t trace_mode_store(struct kobject *kobj,
static struct kobj_attribute trace_mode_attr =
__ATTR(trace_mode, 0644, trace_mode_show, trace_mode_store);

+static ssize_t trace_timestamp_show(struct kobject *kobj,
+ struct kobj_attribute *attr,
+ char *buf)
+{
+ return sprintf(buf, "%d\n", !!(tracer.flags & TRACER_TIMESTAMP));
+}
+
+static ssize_t trace_timestamp_store(struct kobject *kobj,
+ struct kobj_attribute *attr,
+ const char *buf, size_t n)
+{
+ unsigned int timestamp;
+
+ if (sscanf(buf, "%u", &timestamp) != 1)
+ return -EINVAL;
+
+ mutex_lock(&tracer.mutex);
+ if (timestamp)
+ tracer.flags |= TRACER_TIMESTAMP;
+ else
+ tracer.flags &= ~TRACER_TIMESTAMP;
+ mutex_unlock(&tracer.mutex);
+
+ return n;
+}
+
+static struct kobj_attribute trace_timestamp_attr =
+ __ATTR(trace_timestamp, 0644,
+ trace_timestamp_show, trace_timestamp_store);
+
static ssize_t trace_range_show(struct kobject *kobj,
struct kobj_attribute *attr,
char *buf)
@@ -726,6 +759,7 @@ static int __devinit etm_probe(struct amba_device *dev, const struct amba_id *id
int new_count;
u32 etmccr;
u32 etmidr;
+ u32 etmccer = 0;
u8 etm_version = 0;

mutex_lock(&t->mutex);
@@ -766,6 +800,8 @@ static int __devinit etm_probe(struct amba_device *dev, const struct amba_id *id
if (etmccr & ETMCCR_ETMIDR_PRESENT) {
etmidr = etm_readl(t, t->etm_regs_count, ETMR_ID);
etm_version = ETMIDR_VERSION(etmidr);
+ if (etm_version >= ETMIDR_VERSION_3_1)
+ etmccer = etm_readl(t, t->etm_regs_count, ETMR_CCE);
}
etm_writel(t, t->etm_regs_count, 0x441, ETMR_CTRL);
etm_writel(t, t->etm_regs_count, new_count, ETMR_TRACEIDR);
@@ -785,6 +821,14 @@ static int __devinit etm_probe(struct amba_device *dev, const struct amba_id *id
if (ret)
dev_dbg(&dev->dev, "Failed to create trace_mode in sysfs\n");

+ if (etmccer & ETMCCER_TIMESTAMPING_IMPLEMENTED) {
+ ret = sysfs_create_file(&dev->dev.kobj,
+ &trace_timestamp_attr.attr);
+ if (ret)
+ dev_dbg(&dev->dev,
+ "Failed to create trace_timestamp in sysfs\n");
+ }
+
ret = sysfs_create_file(&dev->dev.kobj, &trace_range_attr.attr);
if (ret)
dev_dbg(&dev->dev, "Failed to create trace_range in sysfs\n");
--
1.7.9.5

2012-06-20 22:51:07

by John Stultz

[permalink] [raw]
Subject: [PATCH 04/15] ARM: etm: Allow range selection

From: Arve Hjønnevåg <[email protected]>

Trace kernel text segment by default as before, allow tracing of other
ranges by writing a range to /sys/devices/etm/trace_range, or to trace
everything by writing 0 0.

CC: Russell King <[email protected]>
CC: Paul Gortmaker <[email protected]>
CC: Alexander Shishkin <[email protected]>
Acked-by: Alexander Shishkin <[email protected]>
Signed-off-by: Arve Hjønnevåg <[email protected]>
Signed-off-by: John Stultz <[email protected]>
---
arch/arm/kernel/etm.c | 49 ++++++++++++++++++++++++++++++++++++++++++++++---
1 file changed, 46 insertions(+), 3 deletions(-)

diff --git a/arch/arm/kernel/etm.c b/arch/arm/kernel/etm.c
index a51bccc..bf34d34 100644
--- a/arch/arm/kernel/etm.c
+++ b/arch/arm/kernel/etm.c
@@ -41,12 +41,17 @@ struct tracectx {
unsigned long flags;
int ncmppairs;
int etm_portsz;
+ unsigned long range_start;
+ unsigned long range_end;
struct device *dev;
struct clk *emu_clk;
struct mutex mutex;
};

-static struct tracectx tracer;
+static struct tracectx tracer = {
+ .range_start = (unsigned long)_stext,
+ .range_end = (unsigned long)_etext,
+};

static inline bool trace_isrunning(struct tracectx *t)
{
@@ -116,8 +121,12 @@ static int trace_start(struct tracectx *t)
return -EFAULT;
}

- etm_setup_address_range(t, 1, (unsigned long)_stext,
- (unsigned long)_etext, 0, 0);
+ if (t->range_start || t->range_end)
+ etm_setup_address_range(t, 1,
+ t->range_start, t->range_end, 0, 0);
+ else
+ etm_writel(t, ETMTE_INCLEXCL, ETMR_TRACEENCTRL);
+
etm_writel(t, 0, ETMR_TRACEENCTRL2);
etm_writel(t, 0, ETMR_TRACESSCTRL);
etm_writel(t, 0x6f, ETMR_TRACEENEVT);
@@ -526,6 +535,35 @@ static ssize_t trace_mode_store(struct kobject *kobj,
static struct kobj_attribute trace_mode_attr =
__ATTR(trace_mode, 0644, trace_mode_show, trace_mode_store);

+static ssize_t trace_range_show(struct kobject *kobj,
+ struct kobj_attribute *attr,
+ char *buf)
+{
+ return sprintf(buf, "%08lx %08lx\n",
+ tracer.range_start, tracer.range_end);
+}
+
+static ssize_t trace_range_store(struct kobject *kobj,
+ struct kobj_attribute *attr,
+ const char *buf, size_t n)
+{
+ unsigned long range_start, range_end;
+
+ if (sscanf(buf, "%lx %lx", &range_start, &range_end) != 2)
+ return -EINVAL;
+
+ mutex_lock(&tracer.mutex);
+ tracer.range_start = range_start;
+ tracer.range_end = range_end;
+ mutex_unlock(&tracer.mutex);
+
+ return n;
+}
+
+
+static struct kobj_attribute trace_range_attr =
+ __ATTR(trace_range, 0644, trace_range_show, trace_range_store);
+
static int __devinit etm_probe(struct amba_device *dev, const struct amba_id *id)
{
struct tracectx *t = &tracer;
@@ -577,6 +615,10 @@ static int __devinit etm_probe(struct amba_device *dev, const struct amba_id *id
if (ret)
dev_dbg(&dev->dev, "Failed to create trace_mode in sysfs\n");

+ ret = sysfs_create_file(&dev->dev.kobj, &trace_range_attr.attr);
+ if (ret)
+ dev_dbg(&dev->dev, "Failed to create trace_range in sysfs\n");
+
dev_dbg(t->dev, "ETM AMBA driver initialized.\n");

out:
@@ -606,6 +648,7 @@ static int etm_remove(struct amba_device *dev)
sysfs_remove_file(&dev->dev.kobj, &trace_running_attr.attr);
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);

return 0;
}
--
1.7.9.5

2012-06-20 22:48:21

by John Stultz

[permalink] [raw]
Subject: [PATCH 11/15] ARM: etm: Check arch version and disable data tracing for ptm

From: Arve Hjønnevåg <[email protected]>

Check arch version and disable data tracing for ptm

CC: Russell King <[email protected]>
CC: Paul Gortmaker <[email protected]>
CC: Alexander Shishkin <[email protected]>
Acked-by: Alexander Shishkin <[email protected]>
Signed-off-by: Arve Hjønnevåg <[email protected]>
Signed-off-by: John Stultz <[email protected]>
---
arch/arm/include/asm/hardware/coresight.h | 5 +++++
arch/arm/kernel/etm.c | 23 ++++++++++++++++++-----
2 files changed, 23 insertions(+), 5 deletions(-)

diff --git a/arch/arm/include/asm/hardware/coresight.h b/arch/arm/include/asm/hardware/coresight.h
index 6643d6c..0fad8f8 100644
--- a/arch/arm/include/asm/hardware/coresight.h
+++ b/arch/arm/include/asm/hardware/coresight.h
@@ -60,6 +60,7 @@

/* ETM configuration code register */
#define ETMR_CONFCODE (0x04)
+#define ETMCCR_ETMIDR_PRESENT BIT(31)

/* ETM trace start/stop resource control register */
#define ETMR_TRACESSCTRL (0x18)
@@ -126,6 +127,10 @@
ETMCTRL_BRANCH_OUTPUT | \
ETMCTRL_DO_CONTEXTID)

+#define ETMR_ID 0x1e4
+#define ETMIDR_VERSION(x) (((x) >> 4) & 0xff)
+#define ETMIDR_VERSION_PFT_1_0 0x30
+
#define ETMR_TRACEIDR 0x200

/* ETM management registers, "ETM Architecture", 3.5.24 */
diff --git a/arch/arm/kernel/etm.c b/arch/arm/kernel/etm.c
index bad28de..e42b706 100644
--- a/arch/arm/kernel/etm.c
+++ b/arch/arm/kernel/etm.c
@@ -724,6 +724,9 @@ static int __devinit etm_probe(struct amba_device *dev, const struct amba_id *id
int ret = 0;
void __iomem **new_regs;
int new_count;
+ u32 etmccr;
+ u32 etmidr;
+ u8 etm_version = 0;

mutex_lock(&t->mutex);
new_count = t->etm_regs_count + 1;
@@ -758,7 +761,12 @@ static int __devinit etm_probe(struct amba_device *dev, const struct amba_id *id
/* dummy first read */
(void)etm_readl(&tracer, t->etm_regs_count, ETMMR_OSSRR);

- t->ncmppairs = etm_readl(t, t->etm_regs_count, ETMR_CONFCODE) & 0xf;
+ etmccr = etm_readl(t, t->etm_regs_count, ETMR_CONFCODE);
+ t->ncmppairs = etmccr & 0xf;
+ if (etmccr & ETMCCR_ETMIDR_PRESENT) {
+ etmidr = etm_readl(t, t->etm_regs_count, ETMR_ID);
+ etm_version = ETMIDR_VERSION(etmidr);
+ }
etm_writel(t, t->etm_regs_count, 0x441, ETMR_CTRL);
etm_writel(t, t->etm_regs_count, new_count, ETMR_TRACEIDR);
etm_lock(t, t->etm_regs_count);
@@ -781,10 +789,15 @@ 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");
+ if (etm_version < ETMIDR_VERSION_PFT_1_0) {
+ 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");
+ } else {
+ tracer.flags &= ~TRACER_TRACE_DATA;
+ }

dev_dbg(&dev->dev, "ETM AMBA driver initialized.\n");

--
1.7.9.5

2012-06-20 22:51:32

by John Stultz

[permalink] [raw]
Subject: [PATCH 08/15] ARM: etm: Support multiple ETMs/PTMs.

From: Arve Hjønnevåg <[email protected]>

If more than one ETM or PTM are present, configure all of them
and enable the formatter in the ETB. This allows tracing on dual
core systems (e.g. omap4).

CC: Russell King <[email protected]>
CC: Paul Gortmaker <[email protected]>
CC: Alexander Shishkin <[email protected]>
Acked-by: Alexander Shishkin <[email protected]>
Signed-off-by: Arve Hjønnevåg <[email protected]>
Signed-off-by: John Stultz <[email protected]>
---
arch/arm/include/asm/hardware/coresight.h | 16 +-
arch/arm/kernel/etm.c | 234 +++++++++++++++++++----------
2 files changed, 166 insertions(+), 84 deletions(-)

diff --git a/arch/arm/include/asm/hardware/coresight.h b/arch/arm/include/asm/hardware/coresight.h
index 6ea507f..6643d6c 100644
--- a/arch/arm/include/asm/hardware/coresight.h
+++ b/arch/arm/include/asm/hardware/coresight.h
@@ -25,9 +25,9 @@

#define TRACER_TIMEOUT 10000

-#define etm_writel(t, v, x) \
- (__raw_writel((v), (t)->etm_regs + (x)))
-#define etm_readl(t, x) (__raw_readl((t)->etm_regs + (x)))
+#define etm_writel(t, id, v, x) \
+ (__raw_writel((v), (t)->etm_regs[(id)] + (x)))
+#define etm_readl(t, id, x) (__raw_readl((t)->etm_regs[(id)] + (x)))

/* CoreSight Management Registers */
#define CSMR_LOCKACCESS 0xfb0
@@ -126,6 +126,8 @@
ETMCTRL_BRANCH_OUTPUT | \
ETMCTRL_DO_CONTEXTID)

+#define ETMR_TRACEIDR 0x200
+
/* ETM management registers, "ETM Architecture", 3.5.24 */
#define ETMMR_OSLAR 0x300
#define ETMMR_OSLSR 0x304
@@ -148,14 +150,16 @@
#define ETBFF_TRIGIN BIT(8)
#define ETBFF_TRIGEVT BIT(9)
#define ETBFF_TRIGFL BIT(10)
+#define ETBFF_STOPFL BIT(12)

#define etb_writel(t, v, x) \
(__raw_writel((v), (t)->etb_regs + (x)))
#define etb_readl(t, x) (__raw_readl((t)->etb_regs + (x)))

-#define etm_lock(t) do { etm_writel((t), 0, CSMR_LOCKACCESS); } while (0)
-#define etm_unlock(t) \
- do { etm_writel((t), UNLOCK_MAGIC, CSMR_LOCKACCESS); } while (0)
+#define etm_lock(t, id) \
+ do { etm_writel((t), (id), 0, CSMR_LOCKACCESS); } while (0)
+#define etm_unlock(t, id) \
+ do { etm_writel((t), (id), UNLOCK_MAGIC, CSMR_LOCKACCESS); } while (0)

#define etb_lock(t) do { etb_writel((t), 0, CSMR_LOCKACCESS); } while (0)
#define etb_unlock(t) \
diff --git a/arch/arm/kernel/etm.c b/arch/arm/kernel/etm.c
index 74444e5..e3309ea 100644
--- a/arch/arm/kernel/etm.c
+++ b/arch/arm/kernel/etm.c
@@ -15,6 +15,7 @@
#include <linux/init.h>
#include <linux/types.h>
#include <linux/io.h>
+#include <linux/slab.h>
#include <linux/sysrq.h>
#include <linux/device.h>
#include <linux/clk.h>
@@ -37,10 +38,12 @@ MODULE_AUTHOR("Alexander Shishkin");
struct tracectx {
unsigned int etb_bufsz;
void __iomem *etb_regs;
- void __iomem *etm_regs;
+ void __iomem **etm_regs;
+ int etm_regs_count;
unsigned long flags;
int ncmppairs;
int etm_portsz;
+ u32 etb_fc;
unsigned long range_start;
unsigned long range_end;
unsigned long data_range_start;
@@ -61,7 +64,7 @@ static inline bool trace_isrunning(struct tracectx *t)
return !!(t->flags & TRACER_RUNNING);
}

-static int etm_setup_address_range(struct tracectx *t, int n,
+static int etm_setup_address_range(struct tracectx *t, int id, int n,
unsigned long start, unsigned long end, int exclude, int data)
{
u32 flags = ETMAAT_ARM | ETMAAT_IGNCONTEXTID | ETMAAT_IGNSECURITY |
@@ -80,41 +83,31 @@ static int etm_setup_address_range(struct tracectx *t, int n,
flags |= ETMAAT_IEXEC;

/* first comparator for the range */
- etm_writel(t, flags, ETMR_COMP_ACC_TYPE(n * 2));
- etm_writel(t, start, ETMR_COMP_VAL(n * 2));
+ etm_writel(t, id, flags, ETMR_COMP_ACC_TYPE(n * 2));
+ etm_writel(t, id, start, ETMR_COMP_VAL(n * 2));

/* second comparator is right next to it */
- etm_writel(t, flags, ETMR_COMP_ACC_TYPE(n * 2 + 1));
- etm_writel(t, end, ETMR_COMP_VAL(n * 2 + 1));
+ etm_writel(t, id, flags, ETMR_COMP_ACC_TYPE(n * 2 + 1));
+ etm_writel(t, id, end, ETMR_COMP_VAL(n * 2 + 1));

if (data) {
flags = exclude ? ETMVDC3_EXCLONLY : 0;
if (exclude)
n += 8;
- etm_writel(t, flags | BIT(n), ETMR_VIEWDATACTRL3);
+ etm_writel(t, id, flags | BIT(n), ETMR_VIEWDATACTRL3);
} else {
flags = exclude ? ETMTE_INCLEXCL : 0;
- etm_writel(t, flags | (1 << n), ETMR_TRACEENCTRL);
+ etm_writel(t, id, flags | (1 << n), ETMR_TRACEENCTRL);
}

return 0;
}

-static int trace_start(struct tracectx *t)
+static int trace_start_etm(struct tracectx *t, int id)
{
u32 v;
unsigned long timeout = TRACER_TIMEOUT;

- etb_unlock(t);
-
- t->dump_initial_etb = false;
- etb_writel(t, 0, ETBR_WRITEADDR);
- etb_writel(t, 0, ETBR_FORMATTERCTRL);
- etb_writel(t, 1, ETBR_CTRL);
-
- etb_lock(t);
-
- /* configure etm */
v = ETMCTRL_OPTS | ETMCTRL_PROGRAM | ETMCTRL_PORTSIZE(t->etm_portsz);

if (t->flags & TRACER_CYCLE_ACC)
@@ -123,79 +116,122 @@ static int trace_start(struct tracectx *t)
if (t->flags & TRACER_TRACE_DATA)
v |= ETMCTRL_DATA_DO_ADDR;

- etm_unlock(t);
+ etm_unlock(t, id);

- etm_writel(t, v, ETMR_CTRL);
+ etm_writel(t, id, v, ETMR_CTRL);

- while (!(etm_readl(t, ETMR_CTRL) & ETMCTRL_PROGRAM) && --timeout)
+ while (!(etm_readl(t, id, ETMR_CTRL) & ETMCTRL_PROGRAM) && --timeout)
;
if (!timeout) {
dev_dbg(t->dev, "Waiting for progbit to assert timed out\n");
- etm_lock(t);
+ etm_lock(t, id);
return -EFAULT;
}

if (t->range_start || t->range_end)
- etm_setup_address_range(t, 1,
+ etm_setup_address_range(t, id, 1,
t->range_start, t->range_end, 0, 0);
else
- etm_writel(t, ETMTE_INCLEXCL, ETMR_TRACEENCTRL);
+ etm_writel(t, id, ETMTE_INCLEXCL, ETMR_TRACEENCTRL);

- etm_writel(t, 0, ETMR_TRACEENCTRL2);
- etm_writel(t, 0, ETMR_TRACESSCTRL);
- etm_writel(t, 0x6f, ETMR_TRACEENEVT);
+ etm_writel(t, id, 0, ETMR_TRACEENCTRL2);
+ etm_writel(t, id, 0, ETMR_TRACESSCTRL);
+ etm_writel(t, id, 0x6f, ETMR_TRACEENEVT);

- etm_writel(t, 0, ETMR_VIEWDATACTRL1);
- etm_writel(t, 0, ETMR_VIEWDATACTRL2);
+ etm_writel(t, id, 0, ETMR_VIEWDATACTRL1);
+ etm_writel(t, id, 0, ETMR_VIEWDATACTRL2);

if (t->data_range_start || t->data_range_end)
- etm_setup_address_range(t, 2, t->data_range_start,
+ etm_setup_address_range(t, id, 2, t->data_range_start,
t->data_range_end, 0, 1);
else
- etm_writel(t, ETMVDC3_EXCLONLY, ETMR_VIEWDATACTRL3);
+ etm_writel(t, id, ETMVDC3_EXCLONLY, ETMR_VIEWDATACTRL3);

- etm_writel(t, 0x6f, ETMR_VIEWDATAEVT);
+ etm_writel(t, id, 0x6f, ETMR_VIEWDATAEVT);

v &= ~ETMCTRL_PROGRAM;
v |= ETMCTRL_PORTSEL;

- etm_writel(t, v, ETMR_CTRL);
+ etm_writel(t, id, v, ETMR_CTRL);

timeout = TRACER_TIMEOUT;
- while (etm_readl(t, ETMR_CTRL) & ETMCTRL_PROGRAM && --timeout)
+ while (etm_readl(t, id, ETMR_CTRL) & ETMCTRL_PROGRAM && --timeout)
;
if (!timeout) {
dev_dbg(t->dev, "Waiting for progbit to deassert timed out\n");
- etm_lock(t);
+ etm_lock(t, id);
return -EFAULT;
}

- etm_lock(t);
+ etm_lock(t, id);
+ return 0;
+}
+
+static int trace_start(struct tracectx *t)
+{
+ int ret;
+ int id;
+ u32 etb_fc = t->etb_fc;
+
+ etb_unlock(t);
+
+ t->dump_initial_etb = false;
+ etb_writel(t, 0, ETBR_WRITEADDR);
+ etb_writel(t, etb_fc, ETBR_FORMATTERCTRL);
+ etb_writel(t, 1, ETBR_CTRL);
+
+ etb_lock(t);
+
+ /* configure etm(s) */
+ for (id = 0; id < t->etm_regs_count; id++) {
+ ret = trace_start_etm(t, id);
+ if (ret)
+ return ret;
+ }

t->flags |= TRACER_RUNNING;

return 0;
}

-static int trace_stop(struct tracectx *t)
+static int trace_stop_etm(struct tracectx *t, int id)
{
unsigned long timeout = TRACER_TIMEOUT;

- etm_unlock(t);
+ etm_unlock(t, id);

- etm_writel(t, 0x440, ETMR_CTRL);
- while (!(etm_readl(t, ETMR_CTRL) & ETMCTRL_PROGRAM) && --timeout)
+ etm_writel(t, id, 0x440, ETMR_CTRL);
+ while (!(etm_readl(t, id, ETMR_CTRL) & ETMCTRL_PROGRAM) && --timeout)
;
if (!timeout) {
dev_dbg(t->dev, "Waiting for progbit to assert timed out\n");
- etm_lock(t);
+ etm_lock(t, id);
return -EFAULT;
}

- etm_lock(t);
+ etm_lock(t, id);
+ return 0;
+}
+
+static int trace_stop(struct tracectx *t)
+{
+ int id;
+ int ret;
+ unsigned long timeout = TRACER_TIMEOUT;
+ u32 etb_fc = t->etb_fc;
+
+ for (id = 0; id < t->etm_regs_count; id++) {
+ ret = trace_stop_etm(t, id);
+ if (ret)
+ return ret;
+ }

etb_unlock(t);
- etb_writel(t, ETBFF_MANUAL_FLUSH, ETBR_FORMATTERCTRL);
+ if (etb_fc) {
+ etb_fc |= ETBFF_STOPFL;
+ etb_writel(t, t->etb_fc, ETBR_FORMATTERCTRL);
+ }
+ etb_writel(t, etb_fc | ETBFF_MANUAL_FLUSH, ETBR_FORMATTERCTRL);

timeout = TRACER_TIMEOUT;
while (etb_readl(t, ETBR_FORMATTERCTRL) &
@@ -390,6 +426,7 @@ static int __devinit etb_probe(struct amba_device *dev, const struct amba_id *id
goto out_release;
}

+ t->dev = &dev->dev;
t->dump_initial_etb = true;
amba_set_drvdata(dev, t);

@@ -508,6 +545,8 @@ static ssize_t trace_info_show(struct kobject *kobj,
{
u32 etb_wa, etb_ra, etb_st, etb_fc, etm_ctrl, etm_st;
int datalen;
+ int id;
+ int ret;

mutex_lock(&tracer.mutex);
if (tracer.etb_regs) {
@@ -523,28 +562,33 @@ static ssize_t trace_info_show(struct kobject *kobj,
datalen = -1;
}

- etm_unlock(&tracer);
- etm_ctrl = etm_readl(&tracer, ETMR_CTRL);
- etm_st = etm_readl(&tracer, ETMR_STATUS);
- etm_lock(&tracer);
- mutex_unlock(&tracer.mutex);
-
- return sprintf(buf, "Trace buffer len: %d\nComparator pairs: %d\n"
+ ret = sprintf(buf, "Trace buffer len: %d\nComparator pairs: %d\n"
"ETBR_WRITEADDR:\t%08x\n"
"ETBR_READADDR:\t%08x\n"
"ETBR_STATUS:\t%08x\n"
- "ETBR_FORMATTERCTRL:\t%08x\n"
- "ETMR_CTRL:\t%08x\n"
- "ETMR_STATUS:\t%08x\n",
+ "ETBR_FORMATTERCTRL:\t%08x\n",
datalen,
tracer.ncmppairs,
etb_wa,
etb_ra,
etb_st,
- etb_fc,
+ etb_fc
+ );
+
+ for (id = 0; id < tracer.etm_regs_count; id++) {
+ etm_unlock(&tracer, id);
+ etm_ctrl = etm_readl(&tracer, id, ETMR_CTRL);
+ etm_st = etm_readl(&tracer, id, ETMR_STATUS);
+ etm_lock(&tracer, id);
+ ret += sprintf(buf + ret, "ETMR_CTRL:\t%08x\n"
+ "ETMR_STATUS:\t%08x\n",
etm_ctrl,
etm_st
);
+ }
+ mutex_unlock(&tracer.mutex);
+
+ return ret;
}

static struct kobj_attribute trace_info_attr =
@@ -658,37 +702,46 @@ static int __devinit etm_probe(struct amba_device *dev, const struct amba_id *id
{
struct tracectx *t = &tracer;
int ret = 0;
+ void __iomem **new_regs;
+ int new_count;

- if (t->etm_regs) {
- dev_dbg(&dev->dev, "ETM already initialized\n");
- ret = -EBUSY;
+ mutex_lock(&t->mutex);
+ new_count = t->etm_regs_count + 1;
+ new_regs = krealloc(t->etm_regs,
+ sizeof(t->etm_regs[0]) * new_count, GFP_KERNEL);
+
+ if (!new_regs) {
+ dev_dbg(&dev->dev, "Failed to allocate ETM register array\n");
+ ret = -ENOMEM;
goto out;
}
+ t->etm_regs = new_regs;

ret = amba_request_regions(dev, NULL);
if (ret)
goto out;

- t->etm_regs = ioremap_nocache(dev->res.start, resource_size(&dev->res));
- if (!t->etm_regs) {
+ t->etm_regs[t->etm_regs_count] =
+ ioremap_nocache(dev->res.start, resource_size(&dev->res));
+ if (!t->etm_regs[t->etm_regs_count]) {
ret = -ENOMEM;
goto out_release;
}

- amba_set_drvdata(dev, t);
+ amba_set_drvdata(dev, t->etm_regs[t->etm_regs_count]);

- t->dev = &dev->dev;
t->flags = TRACER_CYCLE_ACC | TRACER_TRACE_DATA;
t->etm_portsz = 1;

- etm_unlock(t);
- (void)etm_readl(t, ETMMR_PDSR);
+ etm_unlock(t, t->etm_regs_count);
+ (void)etm_readl(t, t->etm_regs_count, ETMMR_PDSR);
/* dummy first read */
- (void)etm_readl(&tracer, ETMMR_OSSRR);
+ (void)etm_readl(&tracer, t->etm_regs_count, ETMMR_OSSRR);

- t->ncmppairs = etm_readl(t, ETMR_CONFCODE) & 0xf;
- etm_writel(t, 0x440, ETMR_CTRL);
- etm_lock(t);
+ t->ncmppairs = etm_readl(t, t->etm_regs_count, ETMR_CONFCODE) & 0xf;
+ etm_writel(t, t->etm_regs_count, 0x440, ETMR_CTRL);
+ etm_writel(t, t->etm_regs_count, new_count, ETMR_TRACEIDR);
+ etm_lock(t, t->etm_regs_count);

ret = sysfs_create_file(&dev->dev.kobj,
&trace_running_attr.attr);
@@ -713,31 +766,34 @@ static int __devinit etm_probe(struct amba_device *dev, const struct amba_id *id
dev_dbg(&dev->dev,
"Failed to create trace_data_range in sysfs\n");

- dev_dbg(t->dev, "ETM AMBA driver initialized.\n");
+ dev_dbg(&dev->dev, "ETM AMBA driver initialized.\n");
+
+ /* Enable formatter if there are multiple trace sources */
+ if (new_count > 1)
+ t->etb_fc = ETBFF_ENFCONT | ETBFF_ENFTC;
+
+ t->etm_regs_count = new_count;

out:
+ mutex_unlock(&t->mutex);
return ret;

out_unmap:
amba_set_drvdata(dev, NULL);
- iounmap(t->etm_regs);
+ iounmap(t->etm_regs[t->etm_regs_count]);

out_release:
amba_release_regions(dev);

+ mutex_unlock(&t->mutex);
return ret;
}

static int etm_remove(struct amba_device *dev)
{
- struct tracectx *t = amba_get_drvdata(dev);
-
- amba_set_drvdata(dev, NULL);
-
- iounmap(t->etm_regs);
- t->etm_regs = NULL;
-
- amba_release_regions(dev);
+ int i;
+ struct tracectx *t = &tracer;
+ void __iomem *etm_regs = amba_get_drvdata(dev);

sysfs_remove_file(&dev->dev.kobj, &trace_running_attr.attr);
sysfs_remove_file(&dev->dev.kobj, &trace_info_attr.attr);
@@ -745,6 +801,24 @@ static int etm_remove(struct amba_device *dev)
sysfs_remove_file(&dev->dev.kobj, &trace_range_attr.attr);
sysfs_remove_file(&dev->dev.kobj, &trace_data_range_attr.attr);

+ amba_set_drvdata(dev, NULL);
+
+ mutex_lock(&t->mutex);
+ for (i = 0; i < t->etm_regs_count; i++)
+ if (t->etm_regs[i] == etm_regs)
+ break;
+ for (; i < t->etm_regs_count - 1; i++)
+ t->etm_regs[i] = t->etm_regs[i + 1];
+ t->etm_regs_count--;
+ if (!t->etm_regs_count) {
+ kfree(t->etm_regs);
+ t->etm_regs = NULL;
+ }
+ mutex_unlock(&t->mutex);
+
+ iounmap(etm_regs);
+ amba_release_regions(dev);
+
return 0;
}

@@ -753,6 +827,10 @@ static struct amba_id etm_ids[] = {
.id = 0x0003b921,
.mask = 0x0007ffff,
},
+ {
+ .id = 0x0003b950,
+ .mask = 0x0007ffff,
+ },
{ 0, 0 },
};

--
1.7.9.5

2012-06-20 22:48:19

by John Stultz

[permalink] [raw]
Subject: [PATCH 09/15] ARM: etm: Power down etm(s) when tracing is not enabled

From: Arve Hjønnevåg <[email protected]>

Without this change a saw an 18% increase in idle power consumption
on one deivce when trace support is compiled into the kernel. Now
I see the same increase only when tracing.

CC: Russell King <[email protected]>
CC: Paul Gortmaker <[email protected]>
CC: Alexander Shishkin <[email protected]>
Acked-by: Alexander Shishkin <[email protected]>
Signed-off-by: Arve Hjønnevåg <[email protected]>
Signed-off-by: John Stultz <[email protected]>
---
arch/arm/kernel/etm.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/arch/arm/kernel/etm.c b/arch/arm/kernel/etm.c
index e3309ea..66bf592 100644
--- a/arch/arm/kernel/etm.c
+++ b/arch/arm/kernel/etm.c
@@ -200,7 +200,7 @@ static int trace_stop_etm(struct tracectx *t, int id)

etm_unlock(t, id);

- etm_writel(t, id, 0x440, ETMR_CTRL);
+ etm_writel(t, id, 0x441, ETMR_CTRL);
while (!(etm_readl(t, id, ETMR_CTRL) & ETMCTRL_PROGRAM) && --timeout)
;
if (!timeout) {
@@ -739,7 +739,7 @@ static int __devinit etm_probe(struct amba_device *dev, const struct amba_id *id
(void)etm_readl(&tracer, t->etm_regs_count, ETMMR_OSSRR);

t->ncmppairs = etm_readl(t, t->etm_regs_count, ETMR_CONFCODE) & 0xf;
- etm_writel(t, t->etm_regs_count, 0x440, ETMR_CTRL);
+ etm_writel(t, t->etm_regs_count, 0x441, ETMR_CTRL);
etm_writel(t, t->etm_regs_count, new_count, ETMR_TRACEIDR);
etm_lock(t, t->etm_regs_count);

--
1.7.9.5

2012-06-20 22:48:17

by John Stultz

[permalink] [raw]
Subject: [PATCH 02/15] ARM: etm: Don't limit tracing to only non-secure code.

From: Arve Hjønnevåg <[email protected]>

On some systems kernel code is considered secure, and this code
already limits tracing to the kernel text segment which results
in no trace data.

CC: Russell King <[email protected]>
CC: Paul Gortmaker <[email protected]>
CC: Alexander Shishkin <[email protected]>
Acked-by: Alexander Shishkin <[email protected]>
Signed-off-by: Arve Hjønnevåg <[email protected]>
Signed-off-by: John Stultz <[email protected]>
---
arch/arm/kernel/etm.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/arm/kernel/etm.c b/arch/arm/kernel/etm.c
index bd295e8..d7622f9 100644
--- a/arch/arm/kernel/etm.c
+++ b/arch/arm/kernel/etm.c
@@ -56,7 +56,7 @@ static inline bool trace_isrunning(struct tracectx *t)
static int etm_setup_address_range(struct tracectx *t, int n,
unsigned long start, unsigned long end, int exclude, int data)
{
- u32 flags = ETMAAT_ARM | ETMAAT_IGNCONTEXTID | ETMAAT_NSONLY | \
+ u32 flags = ETMAAT_ARM | ETMAAT_IGNCONTEXTID | ETMAAT_IGNSECURITY |
ETMAAT_NOVALCMP;

if (n < 1 || n > t->ncmppairs)
--
1.7.9.5

2012-06-20 22:52:29

by John Stultz

[permalink] [raw]
Subject: [PATCH 05/15] ARM: etm: Configure data tracing

From: Arve Hjønnevåg <[email protected]>

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.

CC: Russell King <[email protected]>
CC: Paul Gortmaker <[email protected]>
CC: Alexander Shishkin <[email protected]>
Acked-by: Alexander Shishkin <[email protected]>
Signed-off-by: Arve Hjønnevåg <[email protected]>
Signed-off-by: John Stultz <[email protected]>
---
arch/arm/include/asm/hardware/coresight.h | 10 +++-
arch/arm/kernel/etm.c | 77 +++++++++++++++++++++++++++--
2 files changed, 83 insertions(+), 4 deletions(-)

diff --git a/arch/arm/include/asm/hardware/coresight.h b/arch/arm/include/asm/hardware/coresight.h
index 7ecd793..6ea507f 100644
--- a/arch/arm/include/asm/hardware/coresight.h
+++ b/arch/arm/include/asm/hardware/coresight.h
@@ -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)

diff --git a/arch/arm/kernel/etm.c b/arch/arm/kernel/etm.c
index bf34d34..c651cf9 100644
--- a/arch/arm/kernel/etm.c
+++ b/arch/arm/kernel/etm.c
@@ -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;

@@ -564,6 +587,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;
@@ -589,7 +654,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);
@@ -619,6 +684,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:
@@ -649,6 +719,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;
}
--
1.7.9.5

2012-06-28 15:47:59

by Linus Walleij

[permalink] [raw]
Subject: Re: [PATCH 01/15] ARM: etm: Don't require clock control

On Thu, Jun 21, 2012 at 12:47 AM, John Stultz <[email protected]> wrote:

> - ? ? ? clk_enable(t->emu_clk);
> + ? ? ? else
> + ? ? ? ? ? ? ? clk_enable(t->emu_clk);

Take this opportunity to use clk_prepare_enable();

> ? ? ? ?etb_unlock(t);
> ? ? ? ?t->etb_bufsz = etb_readl(t, ETBR_DEPTH);
> @@ -403,8 +402,10 @@ static int etb_remove(struct amba_device *dev)
> ? ? ? ?iounmap(t->etb_regs);
> ? ? ? ?t->etb_regs = NULL;
>
> - ? ? ? clk_disable(t->emu_clk);
> - ? ? ? clk_put(t->emu_clk);
> + ? ? ? if (!IS_ERR(t->emu_clk)) {
> + ? ? ? ? ? ? ? clk_disable(t->emu_clk);

And clk_disable_uprepare() here.

> + ? ? ? ? ? ? ? clk_put(t->emu_clk);
> + ? ? ? }

After that it's
Acked-by: Linus Walleij <[email protected]>

Yours,
Linus Walleij

2012-06-28 15:49:31

by Linus Walleij

[permalink] [raw]
Subject: Re: [PATCH 02/15] ARM: etm: Don't limit tracing to only non-secure code.

On Thu, Jun 21, 2012 at 12:47 AM, John Stultz <[email protected]> wrote:

> From: Arve Hj?nnev?g <[email protected]>
>
> On some systems kernel code is considered secure, and this code
> already limits tracing to the kernel text segment which results
> in no trace data.

Acked-by: Linus Walleij <[email protected]>

Yours,
Linus Walleij

2012-06-28 15:54:27

by Linus Walleij

[permalink] [raw]
Subject: Re: [PATCH 04/15] ARM: etm: Allow range selection

On Thu, Jun 21, 2012 at 12:47 AM, John Stultz <[email protected]> wrote:

> From: Arve Hj?nnev?g <[email protected]>
>
> Trace kernel text segment by default as before, allow tracing of other
> ranges by writing a range to /sys/devices/etm/trace_range, or to trace
> everything by writing 0 0.
>
> CC: Russell King <[email protected]>
> CC: Paul Gortmaker <[email protected]>
> CC: Alexander Shishkin <[email protected]>
> Acked-by: Alexander Shishkin <[email protected]>
> Signed-off-by: Arve Hj?nnev?g <[email protected]>
> Signed-off-by: John Stultz <[email protected]>

It hurts my feelings that this ETM stuff isn't documented in Documentation/ABI/*
but it hardly makes things worse, so Acked-by: Linus Walleij
<[email protected]>

Yours,
Linus Walleij

2012-06-28 15:55:32

by Linus Walleij

[permalink] [raw]
Subject: Re: [PATCH 05/15] ARM: etm: Configure data tracing

On Thu, Jun 21, 2012 at 12:47 AM, John Stultz <[email protected]> wrote:

> From: Arve Hj?nnev?g <[email protected]>
>
> 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.
>
> CC: Russell King <[email protected]>
> CC: Paul Gortmaker <[email protected]>
> CC: Alexander Shishkin <[email protected]>
> Acked-by: Alexander Shishkin <[email protected]>
> Signed-off-by: Arve Hj?nnev?g <[email protected]>
> Signed-off-by: John Stultz <[email protected]>

As per same ABI reasoning:
Acked-by: Linus Walleij <[email protected]>

Yours,
Linus Walleij

2012-06-28 15:56:57

by Linus Walleij

[permalink] [raw]
Subject: Re: [PATCH 06/15] ARM: etm: Add some missing locks and error checks

On Thu, Jun 21, 2012 at 12:47 AM, John Stultz <[email protected]> wrote:

> From: Arve Hj?nnev?g <[email protected]>
>
> It is not safe to call etm_lock or etb_lock without holding the
> mutex since another thread may also have unlocked the registers.
>
> Also add some missing checks for valid etb_regs in the etm sysfs
> entries.
>
> CC: Russell King <[email protected]>
> CC: Paul Gortmaker <[email protected]>
> CC: Alexander Shishkin <[email protected]>
> Acked-by: Alexander Shishkin <[email protected]>
> Signed-off-by: Arve Hj?nnev?g <[email protected]>
> Signed-off-by: John Stultz <[email protected]>

Acked-by: Linus Walleij <[email protected]>

Yours,
Linus Walleij

2012-06-28 15:57:52

by Linus Walleij

[permalink] [raw]
Subject: Re: [PATCH 07/15] ARM: etm: Return the entire trace buffer if it is empty after reset

On Thu, Jun 21, 2012 at 12:47 AM, John Stultz <[email protected]> wrote:

> From: Arve Hj?nnev?g <[email protected]>
>
> On some SOCs the read and write pointer are reset when the chip
> resets, but the trace buffer content is preserved. If the status
> bits indicates that the buffer is empty and we have never started
> tracing, assume the buffer is full instead. This can be useful
> if the system rebooted from a watchdog reset.
>
> CC: Russell King <[email protected]>
> CC: Paul Gortmaker <[email protected]>
> CC: Alexander Shishkin <[email protected]>
> Acked-by: Alexander Shishkin <[email protected]>
> Signed-off-by: Arve Hj?nnev?g <[email protected]>
> Signed-off-by: John Stultz <[email protected]>

This looks *very* useful.
Acked-by: Linus Walleij <[email protected]>

Yours,
Linus Walleij

2012-06-28 16:00:28

by Linus Walleij

[permalink] [raw]
Subject: Re: [PATCH 08/15] ARM: etm: Support multiple ETMs/PTMs.

On Thu, Jun 21, 2012 at 12:47 AM, John Stultz <[email protected]> wrote:

> From: Arve Hj?nnev?g <[email protected]>
>
> If more than one ETM or PTM are present, configure all of them
> and enable the formatter in the ETB. This allows tracing on dual
> core systems (e.g. omap4).
>
> CC: Russell King <[email protected]>
> CC: Paul Gortmaker <[email protected]>
> CC: Alexander Shishkin <[email protected]>
> Acked-by: Alexander Shishkin <[email protected]>
> Signed-off-by: Arve Hj?nnev?g <[email protected]>
> Signed-off-by: John Stultz <[email protected]>

Acked-by: Linus Walleij <[email protected]>

> @@ -753,6 +827,10 @@ static struct amba_id etm_ids[] = {
> ? ? ? ? ? ? ? ?.id ? ? = 0x0003b921,
> ? ? ? ? ? ? ? ?.mask ? = 0x0007ffff,
> ? ? ? ?},
> + ? ? ? {
> + ? ? ? ? ? ? ? .id ? ? = 0x0003b950,
> + ? ? ? ? ? ? ? .mask ? = 0x0007ffff,
> + ? ? ? },

Add some blurb to the commit that there is a newer version of the
ETM called PTM that has this ID (or whatever that thing is, I suspect
that's the ID of a PTM?)

Yours,
Linus Walleij

2012-06-28 16:01:16

by Linus Walleij

[permalink] [raw]
Subject: Re: [PATCH 09/15] ARM: etm: Power down etm(s) when tracing is not enabled

On Thu, Jun 21, 2012 at 12:47 AM, John Stultz <[email protected]> wrote:

> From: Arve Hj?nnev?g <[email protected]>
>
> Without this change a saw an 18% increase in idle power consumption
> on one deivce when trace support is compiled into the kernel. Now
> I see the same increase only when tracing.
>
> CC: Russell King <[email protected]>
> CC: Paul Gortmaker <[email protected]>
> CC: Alexander Shishkin <[email protected]>
> Acked-by: Alexander Shishkin <[email protected]>
> Signed-off-by: Arve Hj?nnev?g <[email protected]>
> Signed-off-by: John Stultz <[email protected]>

We can't have this no.
Acked-by: Linus Walleij <[email protected]>

Yours,
Linus Walleij

2012-06-28 16:02:10

by Linus Walleij

[permalink] [raw]
Subject: Re: [PATCH 10/15] ARM: etm: Wait for etm/ptm(s) to stop before requesting PowerDown

On Thu, Jun 21, 2012 at 12:47 AM, John Stultz <[email protected]> wrote:

> From: Arve Hj?nnev?g <[email protected]>
>
> When PowerDown was requested at the same time as ProgBit, the
> formatter flush command that follows could get stuck.
>
> CC: Russell King <[email protected]>
> CC: Paul Gortmaker <[email protected]>
> CC: Alexander Shishkin <[email protected]>
> Acked-by: Alexander Shishkin <[email protected]>
> Signed-off-by: Arve Hj?nnev?g <[email protected]>
> Signed-off-by: John Stultz <[email protected]>

Acked-by: Linus Walleij <[email protected]>

Yours,
Linus Walleij

2012-06-28 16:07:51

by Linus Walleij

[permalink] [raw]
Subject: Re: [PATCH 11/15] ARM: etm: Check arch version and disable data tracing for ptm

On Thu, Jun 21, 2012 at 12:47 AM, John Stultz <[email protected]> wrote:

> +#define ETMR_ID ? ? ? ? ? ? ? ? ? ? ? ?0x1e4
> +#define ETMIDR_VERSION(x) ? ? ?(((x) >> 4) & 0xff)
> +#define ETMIDR_VERSION_PFT_1_0 0x30

NAK don't reinvent this stuff.

>From <linux/amba/bus.h>

Use these macros on the periphid:
#define amba_config(d) AMBA_CONFIG_BITS((d)->periphid)
#define amba_rev(d) AMBA_REV_BITS((d)->periphid)
#define amba_manf(d) AMBA_MANF_BITS((d)->periphid)
#define amba_part(d) AMBA_PART_BITS((d)->periphid)

I thin amba_rev() is the one you're looking for (not sure).

So here:

> @@ -724,6 +724,9 @@ static int __devinit etm_probe(struct amba_device *dev, const struct amba_id *id

> + ? ? ? if (etmccr & ETMCCR_ETMIDR_PRESENT) {
> + ? ? ? ? ? ? ? etmidr = etm_readl(t, t->etm_regs_count, ETMR_ID);
> + ? ? ? ? ? ? ? etm_version = ETMIDR_VERSION(etmidr);

etm_version = amba_rev(dev);

etc.

Yours,
Linus Walleij

2012-06-28 16:08:53

by Linus Walleij

[permalink] [raw]
Subject: Re: [PATCH 12/15] ARM: etm: Add sysfs entry to enable timestamps if supported

On Thu, Jun 21, 2012 at 12:47 AM, John Stultz <[email protected]> wrote:

> From: Arve Hj?nnev?g <[email protected]>
>
> Add sysfs entry to enable timestamps if supported
>
> CC: Russell King <[email protected]>
> CC: Paul Gortmaker <[email protected]>
> CC: Alexander Shishkin <[email protected]>
> Acked-by: Alexander Shishkin <[email protected]>
> Signed-off-by: Arve Hj?nnev?g <[email protected]>
> Signed-off-by: John Stultz <[email protected]>

After proper changes to previous patch:
Acked-by: Linus Walleij <[email protected]>

Yours,
Linus Walleij

2012-06-28 16:10:03

by Linus Walleij

[permalink] [raw]
Subject: Re: [PATCH 13/15] ARM: etm: Add sysfs entry to set context-id-size

On Thu, Jun 21, 2012 at 12:47 AM, John Stultz <[email protected]> wrote:

> From: Arve Hj?nnev?g <[email protected]>
>
> Add sysfs entry to set context-id-size
>
> CC: Russell King <[email protected]>
> CC: Paul Gortmaker <[email protected]>
> CC: Alexander Shishkin <[email protected]>
> Acked-by: Alexander Shishkin <[email protected]>
> Signed-off-by: Arve Hj?nnev?g <[email protected]>
> Signed-off-by: John Stultz <[email protected]>

ABI docs...

Ohwell.
Acked-by: Linus Walleij <[email protected]>

The wild idea strikes me that maybe all of these files would be better
off in debugfs???

Yours,
Linus Walleij

2012-06-28 16:10:46

by Linus Walleij

[permalink] [raw]
Subject: Re: [PATCH 14/15] ARM: etm: Add sysfs entry to disable branch_output flag

On Thu, Jun 21, 2012 at 12:47 AM, John Stultz <[email protected]> wrote:

> From: Arve Hj?nnev?g <[email protected]>
>
> Add sysfs entry to disable branch_output flag
>
> CC: Russell King <[email protected]>
> CC: Paul Gortmaker <[email protected]>
> CC: Alexander Shishkin <[email protected]>
> Acked-by: Alexander Shishkin <[email protected]>
> Signed-off-by: Arve Hj?nnev?g <[email protected]>
> Signed-off-by: John Stultz <[email protected]>

Suggest move to debugfs.
Acked-by: Linus Walleij <[email protected]>

Yours,
Linus Walleij

2012-06-28 16:11:19

by Linus Walleij

[permalink] [raw]
Subject: Re: [PATCH 15/15] ARM: etm: Add sysfs entry to enable return stack if supported

On Thu, Jun 21, 2012 at 12:47 AM, John Stultz <[email protected]> wrote:

> From: Arve Hj?nnev?g <[email protected]>
>
> Add sysfs entry to enable return stack if supported
>
> CC: Russell King <[email protected]>
> CC: Paul Gortmaker <[email protected]>
> CC: Alexander Shishkin <[email protected]>
> Acked-by: Alexander Shishkin <[email protected]>
> Signed-off-by: Arve Hj?nnev?g <[email protected]>
> Signed-off-by: John Stultz <[email protected]>

Suggest moveall to debugfs.
Acked-by: Linus Walleij <[email protected]>

Yours,
Linus Walleij

2012-06-28 21:31:50

by Arve Hjønnevåg

[permalink] [raw]
Subject: Re: [PATCH 11/15] ARM: etm: Check arch version and disable data tracing for ptm

On Thu, Jun 28, 2012 at 9:07 AM, Linus Walleij <[email protected]> wrote:
> On Thu, Jun 21, 2012 at 12:47 AM, John Stultz <[email protected]> wrote:
>
>> +#define ETMR_ID ? ? ? ? ? ? ? ? ? ? ? ?0x1e4
>> +#define ETMIDR_VERSION(x) ? ? ?(((x) >> 4) & 0xff)
>> +#define ETMIDR_VERSION_PFT_1_0 0x30
>
> NAK don't reinvent this stuff.
>
> From <linux/amba/bus.h>
>
> Use these macros on the periphid:
> #define amba_config(d) ?AMBA_CONFIG_BITS((d)->periphid)
> #define amba_rev(d) ? ? AMBA_REV_BITS((d)->periphid)
> #define amba_manf(d) ? ?AMBA_MANF_BITS((d)->periphid)
> #define amba_part(d) ? ?AMBA_PART_BITS((d)->periphid)
>

Those values do not come from the same register. The revision is
duplicated there, but I did not find the major and minor etm version
which is what I'm looking at. Also, if these values are set in the
amba_device before calling amba_device_register the hardware registers
are not read at all and the information could be from an older
hardware rev than what you are currently running on.

> I thin amba_rev() is the one you're looking for (not sure).
>
> So here:
>
>> @@ -724,6 +724,9 @@ static int __devinit etm_probe(struct amba_device *dev, const struct amba_id *id
>
>> + ? ? ? if (etmccr & ETMCCR_ETMIDR_PRESENT) {
>> + ? ? ? ? ? ? ? etmidr = etm_readl(t, t->etm_regs_count, ETMR_ID);
>> + ? ? ? ? ? ? ? etm_version = ETMIDR_VERSION(etmidr);
>
> etm_version = amba_rev(dev);
>
> etc.
>
> Yours,
> Linus Walleij



--
Arve Hj?nnev?g

2012-06-30 19:34:19

by Linus Walleij

[permalink] [raw]
Subject: Re: [PATCH 11/15] ARM: etm: Check arch version and disable data tracing for ptm

On Thu, Jun 28, 2012 at 11:31 PM, Arve Hj?nnev?g <[email protected]> wrote:
> On Thu, Jun 28, 2012 at 9:07 AM, Linus Walleij <[email protected]> wrote:
>> On Thu, Jun 21, 2012 at 12:47 AM, John Stultz <[email protected]> wrote:
>>
>>> +#define ETMR_ID 0x1e4
>>> +#define ETMIDR_VERSION(x) (((x) >> 4) & 0xff)

Damned I was reading 0x0fe4 ...

> Those values do not come from the same register. The revision is
> duplicated there, but I did not find the major and minor etm version
> which is what I'm looking at.

OK sorry for getting this backwards.

Acked-by: Linus Walleij <[email protected]>

Yours,
Linus Walleij