ARM: etm: Don't require clock control
PATCH 1/5 ARM: etm: Don't require clock control
If clk_get fail, assume the etb does not need a separate clock.
--- arch/arm/kernel/etm.c | 14 +++++++------- 1 files changed, 7 insertions(+), 7 deletions(-)
arch/arm/kernel/etm.c +7 -7
@@ -362,12 +362,10 @@ static int __init etb_probe(struct amba_device *dev, struct amba_id *id) goto out_unmap; 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 );
@@ -402,8 +400,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);
Signature · 1 line
1.7.3.1
PATCH 2/5 ARM: etm: Don't limit tracing to only non-secure code.
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.
--- arch/arm/kernel/etm.c | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-)
arch/arm/kernel/etm.c +1 -1
@@ -55,7 +55,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)
Signature · 1 line
1.7.3.1
PATCH 3/5 ARM: etm: Don't trigger another overflow when trying to clear the RAM-full status
In reply to Arve HjønnevågIf 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.
--- arch/arm/kernel/etm.c | 2 ++ 1 files changed, 2 insertions(+), 0 deletions(-)
arch/arm/kernel/etm.c +2 -0
@@ -235,6 +235,7 @@ static void etm_dump(void)printk (KERN_INFO "\n--- ETB buffer end ---\n" );/* deassert the overflow bit */ +etb_writel (t,0 ,ETBR_WRITEADDR );etb_writel (t,1 ,ETBR_CTRL );etb_writel (t,0 ,ETBR_CTRL );
@@ -300,6 +301,7 @@ static ssize_t etb_read(struct file *file, char __user *data, buf[i] =etb_readl (t,ETBR_READMEM );/* the only way to deassert overflow bit in ETB status is this */ +etb_writel (t,0 ,ETBR_WRITEADDR );etb_writel (t,1 ,ETBR_CTRL );etb_writel (t,0 ,ETBR_CTRL );
Signature · 1 line
1.7.3.1
PATCH 4/5 ARM: etm: Allow range selection
In reply to Arve HjønnevågTrace 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.
--- arch/arm/kernel/etm.c | 48 +++++++++++++++++++++++++++++++++++++++++++++--- 1 files changed, 45 insertions(+), 3 deletions(-)
arch/arm/kernel/etm.c +45 -3
@@ -40,12 +40,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) {
@@ -114,8 +119,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 );
@@ -532,6 +541,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 __init etm_probe (struct amba_device *dev,struct amba_id *id) {struct tracectx *t = &tracer;
@@ -583,6 +621,10 @@ static int __init etm_probe(struct amba_device *dev, 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:
Signature · 1 line
1.7.3.1
PATCH 5/5 ARM: etm: Configure data tracing
In reply to Arve HjønnevågThe 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.
--- arch/arm/include/asm/hardware/coresight.h | 10 +++- arch/arm/kernel/etm.c | 76 +++++++++++++++++++++++++++- 2 files changed, 82 insertions(+), 4 deletions(-)
arch/arm/include/asm/hardware/coresight.h +9 -1
@@ -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 (1 << 16) +#define ETMCTRL_OPTS (ETMCTRL_DO_CPRT | \ - ETMCTRL_DATA_DO_ADDR | \ ETMCTRL_BRANCH_OUTPUT | \ ETMCTRL_DO_CONTEXTID)
arch/arm/kernel/etm.c +73 -3
118 lines not on this page · raw message
Signature · 1 line
1.7.3.1
Quoted 3 lines · Arve Hj??nnev??g
If
clk_getfail, assume the etb does not need a separate clock.Signed-off-by Arve Hj??nnev??g <[email protected]>
Would it not be cleaner for the affected platforms to ensure that clk_get() does the right thing here, for example by returning a dummy clock? Otherwise we'll just silently carry on if we can't get a clock we were supposed to which doesn't seem ideal.
Quoted 10 lines · Mark Brown
Quoted 3 lines · Arve Hj??nnev??g
If
clk_getfail, assume the etb does not need a separate clock.Signed-off-by Arve Hj??nnev??g <[email protected]>Would it not be cleaner for the affected platforms to ensure that
clk_get()does the right thing here, for example by returning a dummy clock? ?Otherwise we'll just silently carry on if we can't get a clock we were supposed to which doesn't seem ideal.
This clock seem to be an omap specific virtual clock that switches the clock source of the etb. It is not used to enable the clock when the etb is in use, and it does not seem to have a failure case other than not existing. So, I don't know that requiring this clock would cause fewer problems than making it optional.
--
Arve Hj?nnev?g
Quoted 7 lines · Arve Hjønnevåg
On Thu, Feb 3, 2011 at 4:45 AM, Mark Brown
Quoted 4 lines
Would it not be cleaner for the affected platforms to ensure that
clk_get()does the right thing here, for example by returning a dummy clock? Otherwise we'll just silently carry on if we can't get a clock we were supposed to which doesn't seem ideal.
Quoted 5 lines
This clock seem to be an omap specific virtual clock that switches the clock source of the etb. It is not used to enable the clock when the etb is in use, and it does not seem to have a failure case other than not existing. So, I don't know that requiring this clock would cause fewer problems than making it optional.
That doesn't seem unreasonable, but in that case it'd be good to explain why things are this way in the code (and the changelog) so someone doesn't change the code back.
PATCH 1/8 ARM: etm: Don't require clock control
In reply to Arve HjønnevågIf clk_get fail, assume the etb does not need a separate clock.
--- arch/arm/kernel/etm.c | 15 ++++++++------- 1 files changed, 8 insertions(+), 7 deletions(-)
arch/arm/kernel/etm.c +8 -7
@@ -361,13 +361,12 @@ static int __init etb_probe(struct amba_device *dev, 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 );
@@ -402,8 +401,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);
Signature · 1 line
1.7.3.1
PATCH 2/8 ARM: etm: Don't limit tracing to only non-secure code.
In reply to Arve HjønnevågOn some systems kernel code is considered secure, and this code already limits tracing to the kernel text segment which results in no trace data.
--- arch/arm/kernel/etm.c | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-)
arch/arm/kernel/etm.c +1 -1
@@ -55,7 +55,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)
Signature · 1 line
1.7.3.1
PATCH 3/8 ARM: etm: Don't try to clear the buffer full status after reading the buffer
In reply to Arve HjønnevågIf 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.
--- arch/arm/kernel/etm.c | 58 ++++++++++++++++++++++--------------------------- 1 files changed, 26 insertions(+), 32 deletions(-)
arch/arm/kernel/etm.c +26 -32
@@ -91,6 +91,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 );
@@ -184,24 +185,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 */
@@ -234,14 +226,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); }
@@ -275,6 +259,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);
@@ -289,28 +277,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);
Signature · 1 line
1.7.3.1
PATCH 4/8 ARM: etm: Allow range selection
In reply to Arve HjønnevågTrace 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.
--- arch/arm/kernel/etm.c | 49 ++++++++++++++++++++++++++++++++++++++++++++++--- 1 files changed, 46 insertions(+), 3 deletions(-)
arch/arm/kernel/etm.c +46 -3
@@ -40,12 +40,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) {
@@ -115,8 +120,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 );
@@ -525,6 +534,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 __init etm_probe (struct amba_device *dev,struct amba_id *id) {struct tracectx *t = &tracer;
@@ -576,6 +614,10 @@ static int __init etm_probe(struct amba_device *dev, 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:
@@ -605,6 +647,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 ; }
Signature · 1 line
1.7.3.1
Re: [PATCH 4/8] ARM: etm: Allow range selection
Quoted 3 lines · Arve Hj?nnev?g
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.
Since you're adding this, I think it might make sense to add a 3rd optional ctx id field, so that userspace tracing is also possible, especially when on-chip ETB sizes increase to something more sensible than what they are these days.
Thanks!
Quoted 102 lines
Signed-off-by Arve Hj?nnev?g <[email protected]>--- arch/arm/kernel/etm.c | 49 ++++++++++++++++++++++++++++++++++++++++++++++--- 1 files changed, 46 insertions(+), 3 deletions(-)arch/arm/kernel/etm.c +46
-3@@ -40,12 +40,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) {@@ -115,8 +120,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 );@@ -525,6 +534,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 __init etm_probe (struct amba_device *dev,struct amba_id *id) {struct tracectx *t = &tracer;@@ -576,6 +614,10 @@ static int __init etm_probe(struct amba_device *dev, 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:@@ -605,6 +647,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 ; }Signature · 1 line
1.7.3.1
Re: [PATCH 4/8] ARM: etm: Allow range selection
Quoted 10 lines · Alexander Shishkin
Quoted 3 lines · Arve Hj?nnev?g
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.Since you're adding this, I think it might make sense to add a 3rd optional ctx id field, so that userspace tracing is also possible, especially when on-chip ETB sizes increase to something more sensible than what they are these days.
That might be useful, but I think it can be added later. My main motivation for adding this is so we can turn off the filtering. We want to use tracing in combination with a hardware watchdog to debug hard lockups and we don't want any filtering in this case.
Signature · 1 line
Arve Hj?nnev?g
PATCH 5/8 ARM: etm: Configure data tracing
In reply to Arve HjønnevågThe 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.
--- arch/arm/include/asm/hardware/coresight.h | 10 +++- arch/arm/kernel/etm.c | 77 +++++++++++++++++++++++++++- 2 files changed, 83 insertions(+), 4 deletions(-)
arch/arm/include/asm/hardware/coresight.h +9 -1
@@ -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)
arch/arm/kernel/etm.c +74 -3
125 lines not on this page · raw message
Signature · 1 line
1.7.3.1
PATCH 6/8 ARM: etm: Add some missing locks and error checks
In reply to Arve HjønnevågIt 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.
--- arch/arm/kernel/etm.c | 57 +++++++++++++++++++++++++++++++++--------------- 1 files changed, 39 insertions(+), 18 deletions(-)
arch/arm/kernel/etm.c +39 -18
@@ -263,8 +263,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 = {
@@ -373,6 +378,7 @@ static int __init etb_probe(struct amba_device *dev, 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 ;
@@ -381,6 +387,16 @@ static int __init etb_probe(struct amba_device *dev, 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);
@@ -394,25 +410,19 @@ static int __init etb_probe(struct amba_device *dev, 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;
@@ -474,7 +484,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;
@@ -490,18 +503,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"
@@ -651,7 +671,6 @@ static int __init etm_probe(struct amba_device *dev, 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 ;
@@ -745,6 +764,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" );
Signature · 1 line
1.7.3.1
PATCH 7/8 ARM: etm: Return the entire trace buffer if it is empty after reset
In reply to Arve HjønnevågOn 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.
--- arch/arm/kernel/etm.c | 5 +++++ 1 files changed, 5 insertions(+), 0 deletions(-)
arch/arm/kernel/etm.c +5 -0
@@ -44,6 +44,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;
@@ -105,6 +106,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 );
@@ -311,6 +313,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 );
@@ -385,6 +389,7 @@ static int __init etb_probe(struct amba_device *dev, struct amba_id *id) goto out_release; } + t->dump_initial_etb = true;amba_set_drvdata (dev, t);etb_unlock (t);
Signature · 1 line
1.7.3.1
PATCH 8/8 ARM: etm: Support multiple ETMs/PTMs.
In reply to Arve HjønnevågIf 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).
--- arch/arm/include/asm/hardware/coresight.h | 16 ++- arch/arm/kernel/etm.c | 234 +++++++++++++++++++---------- 2 files changed, 166 insertions(+), 84 deletions(-)
arch/arm/include/asm/hardware/coresight.h +10 -6
@@ -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) \
arch/arm/kernel/etm.c +156 -78
419 lines not on this page · raw message
Signature · 1 line
1.7.3.1
PATCH 9/9 ARM: etm: Power down etm(s) when tracing is not enabled
In reply to Arve HjønnevågWithout 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.
--- arch/arm/kernel/etm.c | 4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-)
arch/arm/kernel/etm.c +2 -2
@@ -199,7 +199,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) {
@@ -738,7 +738,7 @@ static int __init etm_probe(struct amba_device *dev, 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);
Signature · 1 line
1.7.3.1