* [PATCH V3 1/5] ARM CoreSight: ETM: Fix a memory allocation failure
2014-01-30 16:11 [PATCH V3 0/5] ARM CoreSight: ETM: Fix a vmalloc/vfree failure and enhance tracing control Adrien Vergé
@ 2014-01-30 16:11 ` Adrien Vergé
2014-01-30 16:11 ` [PATCH V3 2/5] ARM CoreSight: ETM: Use device attributes Adrien Vergé
` (3 subsequent siblings)
4 siblings, 0 replies; 7+ messages in thread
From: Adrien Vergé @ 2014-01-30 16:11 UTC (permalink / raw)
To: linux-arm-kernel
When an application reads the ETB buffer too often, it can be empty.
In this case, it results in a "vmalloc: allocation failure: 0 bytes",
a backtrace in dmesg and a vfree on an incorrect address.
This patch allocates and frees the trace buffer only when necessary.
Signed-off-by: Adrien Verg? <adrienverge@gmail.com>
---
arch/arm/kernel/etm.c | 13 ++++++++-----
1 file changed, 8 insertions(+), 5 deletions(-)
diff --git a/arch/arm/kernel/etm.c b/arch/arm/kernel/etm.c
index 8ff0ecd..5192693 100644
--- a/arch/arm/kernel/etm.c
+++ b/arch/arm/kernel/etm.c
@@ -275,7 +275,7 @@ static ssize_t etb_read(struct file *file, char __user *data,
long length;
struct tracectx *t = file->private_data;
u32 first = 0;
- u32 *buf;
+ u32 *buf = NULL;
mutex_lock(&t->mutex);
@@ -293,12 +293,14 @@ static ssize_t etb_read(struct file *file, char __user *data,
etb_writel(t, first, ETBR_READADDR);
length = min(total * 4, (int)len);
- buf = vmalloc(length);
+ if (length != 0)
+ buf = vmalloc(length);
dev_dbg(t->dev, "ETB buffer length: %d\n", total);
dev_dbg(t->dev, "ETB status reg: %x\n", etb_readl(t, ETBR_STATUS));
- for (i = 0; i < length / 4; i++)
- buf[i] = etb_readl(t, ETBR_READMEM);
+ if (buf)
+ for (i = 0; i < length / 4; 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);
@@ -311,7 +313,8 @@ static ssize_t etb_read(struct file *file, char __user *data,
etb_lock(t);
length -= copy_to_user(data, buf, length);
- vfree(buf);
+ if (buf)
+ vfree(buf);
out:
mutex_unlock(&t->mutex);
--
1.8.5.3
^ permalink raw reply related [flat|nested] 7+ messages in thread* [PATCH V3 2/5] ARM CoreSight: ETM: Use device attributes
2014-01-30 16:11 [PATCH V3 0/5] ARM CoreSight: ETM: Fix a vmalloc/vfree failure and enhance tracing control Adrien Vergé
2014-01-30 16:11 ` [PATCH V3 1/5] ARM CoreSight: ETM: Fix a memory allocation failure Adrien Vergé
@ 2014-01-30 16:11 ` Adrien Vergé
2014-01-30 16:11 ` [PATCH V3 3/5] ARM CoreSight: ETM: Rename 'comparator' to 'address comparator' Adrien Vergé
` (2 subsequent siblings)
4 siblings, 0 replies; 7+ messages in thread
From: Adrien Vergé @ 2014-01-30 16:11 UTC (permalink / raw)
To: linux-arm-kernel
Replace all kobjects attributes with device attributes.
User experience isn't changed since the same files are created in sysfs.
Signed-off-by: Adrien Verg? <adrienverge@gmail.com>
---
arch/arm/kernel/etm.c | 48 +++++++++++++++++++++---------------------------
1 file changed, 21 insertions(+), 27 deletions(-)
diff --git a/arch/arm/kernel/etm.c b/arch/arm/kernel/etm.c
index 5192693..7a3ee66 100644
--- a/arch/arm/kernel/etm.c
+++ b/arch/arm/kernel/etm.c
@@ -433,15 +433,14 @@ static struct amba_driver etb_driver = {
};
/* use a sysfs file "trace_running" to start/stop tracing */
-static ssize_t trace_running_show(struct kobject *kobj,
- struct kobj_attribute *attr,
- char *buf)
+static ssize_t trace_running_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
{
return sprintf(buf, "%x\n", trace_isrunning(&tracer));
}
-static ssize_t trace_running_store(struct kobject *kobj,
- struct kobj_attribute *attr,
+static ssize_t trace_running_store(struct device *dev,
+ struct device_attribute *attr,
const char *buf, size_t n)
{
unsigned int value;
@@ -457,12 +456,11 @@ static ssize_t trace_running_store(struct kobject *kobj,
return ret ? : n;
}
-static struct kobj_attribute trace_running_attr =
- __ATTR(trace_running, 0644, trace_running_show, trace_running_store);
+DEVICE_ATTR(trace_running, S_IRUGO|S_IWUSR,
+ trace_running_show, trace_running_store);
-static ssize_t trace_info_show(struct kobject *kobj,
- struct kobj_attribute *attr,
- char *buf)
+static ssize_t trace_info_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
{
u32 etb_wa, etb_ra, etb_st, etb_fc, etm_ctrl, etm_st;
int datalen;
@@ -498,21 +496,19 @@ static ssize_t trace_info_show(struct kobject *kobj,
);
}
-static struct kobj_attribute trace_info_attr =
- __ATTR(trace_info, 0444, trace_info_show, NULL);
+DEVICE_ATTR(trace_info, S_IRUGO, trace_info_show, NULL);
-static ssize_t trace_mode_show(struct kobject *kobj,
- struct kobj_attribute *attr,
- char *buf)
+static ssize_t trace_mode_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
{
return sprintf(buf, "%d %d\n",
!!(tracer.flags & TRACER_CYCLE_ACC),
tracer.etm_portsz);
}
-static ssize_t trace_mode_store(struct kobject *kobj,
- struct kobj_attribute *attr,
- const char *buf, size_t n)
+static ssize_t trace_mode_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t n)
{
unsigned int cycacc, portsz;
@@ -531,8 +527,7 @@ static ssize_t trace_mode_store(struct kobject *kobj,
return n;
}
-static struct kobj_attribute trace_mode_attr =
- __ATTR(trace_mode, 0644, trace_mode_show, trace_mode_store);
+DEVICE_ATTR(trace_mode, S_IRUGO|S_IWUSR, trace_mode_show, trace_mode_store);
static int etm_probe(struct amba_device *dev, const struct amba_id *id)
{
@@ -571,17 +566,16 @@ static int etm_probe(struct amba_device *dev, const struct amba_id *id)
etm_writel(t, 0x440, ETMR_CTRL);
etm_lock(t);
- ret = sysfs_create_file(&dev->dev.kobj,
- &trace_running_attr.attr);
+ ret = device_create_file(&dev->dev, &dev_attr_trace_running);
if (ret)
goto out_unmap;
/* failing to create any of these two is not fatal */
- ret = sysfs_create_file(&dev->dev.kobj, &trace_info_attr.attr);
+ ret = device_create_file(&dev->dev, &dev_attr_trace_info);
if (ret)
dev_dbg(&dev->dev, "Failed to create trace_info in sysfs\n");
- ret = sysfs_create_file(&dev->dev.kobj, &trace_mode_attr.attr);
+ ret = device_create_file(&dev->dev, &dev_attr_trace_mode);
if (ret)
dev_dbg(&dev->dev, "Failed to create trace_mode in sysfs\n");
@@ -611,9 +605,9 @@ static int etm_remove(struct amba_device *dev)
amba_release_regions(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);
+ device_remove_file(&dev->dev, &dev_attr_trace_running);
+ device_remove_file(&dev->dev, &dev_attr_trace_info);
+ device_remove_file(&dev->dev, &dev_attr_trace_mode);
return 0;
}
--
1.8.5.3
^ permalink raw reply related [flat|nested] 7+ messages in thread* [PATCH V3 3/5] ARM CoreSight: ETM: Rename 'comparator' to 'address comparator'
2014-01-30 16:11 [PATCH V3 0/5] ARM CoreSight: ETM: Fix a vmalloc/vfree failure and enhance tracing control Adrien Vergé
2014-01-30 16:11 ` [PATCH V3 1/5] ARM CoreSight: ETM: Fix a memory allocation failure Adrien Vergé
2014-01-30 16:11 ` [PATCH V3 2/5] ARM CoreSight: ETM: Use device attributes Adrien Vergé
@ 2014-01-30 16:11 ` Adrien Vergé
2014-01-30 16:11 ` [PATCH V3 4/5] ARM CoreSight: ETM: Add address control support Adrien Vergé
2014-01-30 16:11 ` [PATCH V3 5/5] ARM CoreSight: ETM: Add PID " Adrien Vergé
4 siblings, 0 replies; 7+ messages in thread
From: Adrien Vergé @ 2014-01-30 16:11 UTC (permalink / raw)
To: linux-arm-kernel
Since there are different types of comparators, and other kinds will
be used (such as Context ID comparators), rename them properly.
Signed-off-by: Adrien Verg? <adrienverge@gmail.com>
---
arch/arm/include/asm/hardware/coresight.h | 4 ++--
arch/arm/kernel/etm.c | 19 ++++++++++---------
2 files changed, 12 insertions(+), 11 deletions(-)
diff --git a/arch/arm/include/asm/hardware/coresight.h b/arch/arm/include/asm/hardware/coresight.h
index ad774f3..8c50cf6 100644
--- a/arch/arm/include/asm/hardware/coresight.h
+++ b/arch/arm/include/asm/hardware/coresight.h
@@ -95,8 +95,8 @@
#define ETMAAT_NSONLY (1 << 10)
#define ETMAAT_SONLY (2 << 10)
-#define ETMR_COMP_VAL(x) (0x40 + (x) * 4)
-#define ETMR_COMP_ACC_TYPE(x) (0x80 + (x) * 4)
+#define ETMR_ADDRCOMP_VAL(x) (0x40 + (x) * 4)
+#define ETMR_ADDRCOMP_ACC_TYPE(x) (0x80 + (x) * 4)
/* ETM status register, "ETM Architecture", 3.3.2 */
#define ETMR_STATUS (0x10)
diff --git a/arch/arm/kernel/etm.c b/arch/arm/kernel/etm.c
index 7a3ee66..b3e6713 100644
--- a/arch/arm/kernel/etm.c
+++ b/arch/arm/kernel/etm.c
@@ -39,7 +39,7 @@ struct tracectx {
void __iomem *etb_regs;
void __iomem *etm_regs;
unsigned long flags;
- int ncmppairs;
+ int naddrcmppairs;
int etm_portsz;
struct device *dev;
struct clk *emu_clk;
@@ -59,7 +59,7 @@ static int etm_setup_address_range(struct tracectx *t, int n,
u32 flags = ETMAAT_ARM | ETMAAT_IGNCONTEXTID | ETMAAT_NSONLY | \
ETMAAT_NOVALCMP;
- if (n < 1 || n > t->ncmppairs)
+ if (n < 1 || n > t->naddrcmppairs)
return -EINVAL;
/* comparators and ranges are numbered starting with 1 as opposed
@@ -72,12 +72,12 @@ 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, flags, ETMR_ADDRCOMP_ACC_TYPE(n * 2));
+ etm_writel(t, start, ETMR_ADDRCOMP_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, flags, ETMR_ADDRCOMP_ACC_TYPE(n * 2 + 1));
+ etm_writel(t, end, ETMR_ADDRCOMP_VAL(n * 2 + 1));
flags = exclude ? ETMTE_INCLEXCL : 0;
etm_writel(t, flags | (1 << n), ETMR_TRACEENCTRL);
@@ -478,7 +478,8 @@ static ssize_t trace_info_show(struct device *dev,
etm_st = etm_readl(&tracer, ETMR_STATUS);
etm_lock(&tracer);
- return sprintf(buf, "Trace buffer len: %d\nComparator pairs: %d\n"
+ return sprintf(buf, "Trace buffer len: %d\n"
+ "Addr comparator pairs: %d\n"
"ETBR_WRITEADDR:\t%08x\n"
"ETBR_READADDR:\t%08x\n"
"ETBR_STATUS:\t%08x\n"
@@ -486,7 +487,7 @@ static ssize_t trace_info_show(struct device *dev,
"ETMR_CTRL:\t%08x\n"
"ETMR_STATUS:\t%08x\n",
datalen,
- tracer.ncmppairs,
+ tracer.naddrcmppairs,
etb_wa,
etb_ra,
etb_st,
@@ -562,7 +563,7 @@ static int etm_probe(struct amba_device *dev, const struct amba_id *id)
/* dummy first read */
(void)etm_readl(&tracer, ETMMR_OSSRR);
- t->ncmppairs = etm_readl(t, ETMR_CONFCODE) & 0xf;
+ t->naddrcmppairs = etm_readl(t, ETMR_CONFCODE) & 0xf;
etm_writel(t, 0x440, ETMR_CTRL);
etm_lock(t);
--
1.8.5.3
^ permalink raw reply related [flat|nested] 7+ messages in thread* [PATCH V3 4/5] ARM CoreSight: ETM: Add address control support
2014-01-30 16:11 [PATCH V3 0/5] ARM CoreSight: ETM: Fix a vmalloc/vfree failure and enhance tracing control Adrien Vergé
` (2 preceding siblings ...)
2014-01-30 16:11 ` [PATCH V3 3/5] ARM CoreSight: ETM: Rename 'comparator' to 'address comparator' Adrien Vergé
@ 2014-01-30 16:11 ` Adrien Vergé
2014-01-30 16:11 ` [PATCH V3 5/5] ARM CoreSight: ETM: Add PID " Adrien Vergé
4 siblings, 0 replies; 7+ messages in thread
From: Adrien Vergé @ 2014-01-30 16:11 UTC (permalink / raw)
To: linux-arm-kernel
In the same manner as for enabling tracing, an entry is created
in sysfs to set the address range that triggers tracing.
Signed-off-by: Adrien Verg? <adrienverge@gmail.com>
---
arch/arm/kernel/etm.c | 52 ++++++++++++++++++++++++++++++++++++++++++++++++---
1 file changed, 49 insertions(+), 3 deletions(-)
diff --git a/arch/arm/kernel/etm.c b/arch/arm/kernel/etm.c
index b3e6713..fa42e32 100644
--- a/arch/arm/kernel/etm.c
+++ b/arch/arm/kernel/etm.c
@@ -44,6 +44,8 @@ struct tracectx {
struct device *dev;
struct clk *emu_clk;
struct mutex mutex;
+ unsigned long addrrange_start;
+ unsigned long addrrange_end;
};
static struct tracectx tracer;
@@ -53,6 +55,13 @@ static inline bool trace_isrunning(struct tracectx *t)
return !!(t->flags & TRACER_RUNNING);
}
+/*
+ * Setups ETM to trace only when:
+ * - address between start and end
+ * or address not between start and end (if exclude)
+ * - trace executed instructions
+ * or trace loads and stores (if data)
+ */
static int etm_setup_address_range(struct tracectx *t, int n,
unsigned long start, unsigned long end, int exclude, int data)
{
@@ -115,8 +124,8 @@ static int trace_start(struct tracectx *t)
return -EFAULT;
}
- etm_setup_address_range(t, 1, (unsigned long)_stext,
- (unsigned long)_etext, 0, 0);
+ etm_setup_address_range(t, 1, t->addrrange_start, t->addrrange_end,
+ 0, 0);
etm_writel(t, 0, ETMR_TRACEENCTRL2);
etm_writel(t, 0, ETMR_TRACESSCTRL);
etm_writel(t, 0x6f, ETMR_TRACEENEVT);
@@ -530,6 +539,36 @@ static ssize_t trace_mode_store(struct device *dev,
DEVICE_ATTR(trace_mode, S_IRUGO|S_IWUSR, trace_mode_show, trace_mode_store);
+static ssize_t trace_addrrange_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ return sprintf(buf, "%08lx - %08lx\n", tracer.addrrange_start,
+ tracer.addrrange_end);
+}
+
+static ssize_t trace_addrrange_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t n)
+{
+ unsigned long start, end;
+
+ if (tracer.flags & TRACER_RUNNING)
+ return -EBUSY;
+
+ if (sscanf(buf, "%08lx - %08lx", &start, &end) != 2)
+ return -EINVAL;
+
+ mutex_lock(&tracer.mutex);
+ tracer.addrrange_start = start;
+ tracer.addrrange_end = end;
+ mutex_unlock(&tracer.mutex);
+
+ return n;
+}
+
+DEVICE_ATTR(trace_addrrange, S_IRUGO|S_IWUSR,
+ trace_addrrange_show, trace_addrrange_store);
+
static int etm_probe(struct amba_device *dev, const struct amba_id *id)
{
struct tracectx *t = &tracer;
@@ -557,6 +596,8 @@ static int etm_probe(struct amba_device *dev, const struct amba_id *id)
t->dev = &dev->dev;
t->flags = TRACER_CYCLE_ACC;
t->etm_portsz = 1;
+ t->addrrange_start = (unsigned long) _stext;
+ t->addrrange_end = (unsigned long) _etext;
etm_unlock(t);
(void)etm_readl(t, ETMMR_PDSR);
@@ -571,7 +612,7 @@ static int etm_probe(struct amba_device *dev, const struct amba_id *id)
if (ret)
goto out_unmap;
- /* failing to create any of these two is not fatal */
+ /* failing to create any of these three is not fatal */
ret = device_create_file(&dev->dev, &dev_attr_trace_info);
if (ret)
dev_dbg(&dev->dev, "Failed to create trace_info in sysfs\n");
@@ -580,6 +621,10 @@ static int 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 = device_create_file(&dev->dev, &dev_attr_trace_addrrange);
+ if (ret)
+ dev_dbg(&dev->dev, "Failed to create trace_addrrange in sysfs\n");
+
dev_dbg(t->dev, "ETM AMBA driver initialized.\n");
out:
@@ -609,6 +654,7 @@ static int etm_remove(struct amba_device *dev)
device_remove_file(&dev->dev, &dev_attr_trace_running);
device_remove_file(&dev->dev, &dev_attr_trace_info);
device_remove_file(&dev->dev, &dev_attr_trace_mode);
+ device_remove_file(&dev->dev, &dev_attr_trace_addrrange);
return 0;
}
--
1.8.5.3
^ permalink raw reply related [flat|nested] 7+ messages in thread* [PATCH V3 5/5] ARM CoreSight: ETM: Add PID control support
2014-01-30 16:11 [PATCH V3 0/5] ARM CoreSight: ETM: Fix a vmalloc/vfree failure and enhance tracing control Adrien Vergé
` (3 preceding siblings ...)
2014-01-30 16:11 ` [PATCH V3 4/5] ARM CoreSight: ETM: Add address control support Adrien Vergé
@ 2014-01-30 16:11 ` Adrien Vergé
2014-02-03 10:46 ` Will Deacon
4 siblings, 1 reply; 7+ messages in thread
From: Adrien Vergé @ 2014-01-30 16:11 UTC (permalink / raw)
To: linux-arm-kernel
In the same manner as for enabling tracing, an entry is created in
sysfs to set the PID that triggers tracing. This change is effective
only if CONFIG_PID_IN_CONTEXTIDR is set.
When using PID namespaces, the virtual PID given by the user is
converted to the globally unique ID (task_pid_nr) that is present
in the Context ID register.
Signed-off-by: Adrien Verg? <adrienverge@gmail.com>
---
arch/arm/include/asm/hardware/coresight.h | 5 ++
arch/arm/kernel/etm.c | 131 ++++++++++++++++++++++++++++--
2 files changed, 129 insertions(+), 7 deletions(-)
diff --git a/arch/arm/include/asm/hardware/coresight.h b/arch/arm/include/asm/hardware/coresight.h
index 8c50cf6..2051af0 100644
--- a/arch/arm/include/asm/hardware/coresight.h
+++ b/arch/arm/include/asm/hardware/coresight.h
@@ -98,6 +98,11 @@
#define ETMR_ADDRCOMP_VAL(x) (0x40 + (x) * 4)
#define ETMR_ADDRCOMP_ACC_TYPE(x) (0x80 + (x) * 4)
+#ifdef CONFIG_PID_IN_CONTEXTIDR
+#define ETMR_CTXIDCOMP_VAL(x) (0x1b0 + (x) * 4)
+#define ETMR_CTXIDCOMP_MASK (0x1bc)
+#endif
+
/* ETM status register, "ETM Architecture", 3.3.2 */
#define ETMR_STATUS (0x10)
#define ETMST_OVERFLOW BIT(0)
diff --git a/arch/arm/kernel/etm.c b/arch/arm/kernel/etm.c
index fa42e32..e8db9e2 100644
--- a/arch/arm/kernel/etm.c
+++ b/arch/arm/kernel/etm.c
@@ -25,6 +25,7 @@
#include <linux/vmalloc.h>
#include <linux/mutex.h>
#include <linux/module.h>
+#include <linux/sched.h>
#include <asm/hardware/coresight.h>
#include <asm/sections.h>
@@ -40,12 +41,17 @@ struct tracectx {
void __iomem *etm_regs;
unsigned long flags;
int naddrcmppairs;
+ int nctxidcmp;
int etm_portsz;
struct device *dev;
struct clk *emu_clk;
struct mutex mutex;
unsigned long addrrange_start;
unsigned long addrrange_end;
+ pid_t pid; /* globally unique PID */
+#ifdef CONFIG_PID_NS
+ pid_t vpid; /* virtual PID as seen in namespace */
+#endif
};
static struct tracectx tracer;
@@ -55,18 +61,42 @@ static inline bool trace_isrunning(struct tracectx *t)
return !!(t->flags & TRACER_RUNNING);
}
+#if defined(CONFIG_PID_IN_CONTEXTIDR) && defined(CONFIG_PID_NS)
+/*
+ * Returns the globally unique ID of a task referenced
+ * with its virtual namespace PID
+ */
+static inline pid_t pid_vnr_to_pid_nr(pid_t vpid)
+{
+ struct task_struct *task = find_task_by_vpid(vpid);
+
+ if (!task) {
+ printk(KERN_WARNING "CoreSight ETM: cannot track PID %d: "
+ "no such PID in current namespace\n",
+ vpid);
+ return -EINVAL;
+ }
+
+ return task_pid_nr(task);
+}
+#endif
+
/*
* Setups ETM to trace only when:
* - address between start and end
* or address not between start and end (if exclude)
+ * - in user-space when process id equals pid,
+ * in kernel-space (if pid == 0),
+ * always (if pid == -1)
* - trace executed instructions
* or trace loads and stores (if data)
*/
-static int etm_setup_address_range(struct tracectx *t, int n,
- unsigned long start, unsigned long end, int exclude, int data)
+static int etm_setup(struct tracectx *t, int n,
+ unsigned long start, unsigned long end, int exclude,
+ pid_t pid,
+ int data)
{
- u32 flags = ETMAAT_ARM | ETMAAT_IGNCONTEXTID | ETMAAT_NSONLY | \
- ETMAAT_NOVALCMP;
+ u32 flags = ETMAAT_ARM | ETMAAT_NSONLY | ETMAAT_NOVALCMP;
if (n < 1 || n > t->naddrcmppairs)
return -EINVAL;
@@ -75,6 +105,23 @@ static int etm_setup_address_range(struct tracectx *t, int n,
* to bits in a word */
n--;
+#ifdef CONFIG_PID_IN_CONTEXTIDR
+ if (pid < 0) {
+ /* ignore Context ID */
+ flags |= ETMAAT_IGNCONTEXTID;
+ } else {
+ flags |= ETMAAT_VALUE1;
+
+ /* Set up the first Context ID comparator.
+ Process ID is found in the 24 first bits of Context ID
+ (provided by CONFIG_PID_IN_CONTEXTIDR) */
+ etm_writel(t, pid << 8, ETMR_CTXIDCOMP_VAL(0));
+ etm_writel(t, 0xff, ETMR_CTXIDCOMP_MASK);
+ }
+#else
+ flags |= ETMAAT_IGNCONTEXTID;
+#endif
+
if (data)
flags |= ETMAAT_DLOADSTORE;
else
@@ -124,8 +171,10 @@ static int trace_start(struct tracectx *t)
return -EFAULT;
}
- etm_setup_address_range(t, 1, t->addrrange_start, t->addrrange_end,
- 0, 0);
+ etm_setup(t, 1,
+ t->addrrange_start, t->addrrange_end, 0,
+ t->pid,
+ 0);
etm_writel(t, 0, ETMR_TRACEENCTRL2);
etm_writel(t, 0, ETMR_TRACESSCTRL);
etm_writel(t, 0x6f, ETMR_TRACEENEVT);
@@ -489,6 +538,7 @@ static ssize_t trace_info_show(struct device *dev,
return sprintf(buf, "Trace buffer len: %d\n"
"Addr comparator pairs: %d\n"
+ "Ctx ID comparators: %d\n"
"ETBR_WRITEADDR:\t%08x\n"
"ETBR_READADDR:\t%08x\n"
"ETBR_STATUS:\t%08x\n"
@@ -497,6 +547,7 @@ static ssize_t trace_info_show(struct device *dev,
"ETMR_STATUS:\t%08x\n",
datalen,
tracer.naddrcmppairs,
+ tracer.nctxidcmp,
etb_wa,
etb_ra,
etb_st,
@@ -569,6 +620,61 @@ static ssize_t trace_addrrange_store(struct device *dev,
DEVICE_ATTR(trace_addrrange, S_IRUGO|S_IWUSR,
trace_addrrange_show, trace_addrrange_store);
+#ifdef CONFIG_PID_IN_CONTEXTIDR
+static ssize_t trace_pid_show(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+#ifdef CONFIG_PID_NS
+ return sprintf(buf, "%d\n", tracer.vpid);
+#else
+ return sprintf(buf, "%d\n", tracer.pid);
+#endif
+}
+
+static ssize_t trace_pid_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t n)
+{
+ pid_t pid;
+#ifdef CONFIG_PID_NS
+ pid_t vpid;
+#endif
+
+ if (tracer.flags & TRACER_RUNNING)
+ return -EBUSY;
+
+ if (sscanf(buf, "%i", &pid) != 1)
+ return -EINVAL;
+
+#ifdef CONFIG_PID_NS
+ /* the value written to the Context ID register is the global PID */
+ vpid = pid;
+
+ /* -1 means trace everything,
+ 0 means kernel tracing,
+ > 0 process tracing */
+ if (pid > 0) {
+ pid = pid_vnr_to_pid_nr(vpid);
+
+ if (pid < 0)
+ return pid;
+ }
+#endif
+
+ mutex_lock(&tracer.mutex);
+ tracer.pid = pid;
+#ifdef CONFIG_PID_NS
+ tracer.vpid = vpid;
+#endif
+ mutex_unlock(&tracer.mutex);
+
+ return n;
+}
+
+DEVICE_ATTR(trace_pid, S_IRUGO|S_IWUSR, trace_pid_show, trace_pid_store);
+#endif
+
static int etm_probe(struct amba_device *dev, const struct amba_id *id)
{
struct tracectx *t = &tracer;
@@ -598,6 +704,7 @@ static int etm_probe(struct amba_device *dev, const struct amba_id *id)
t->etm_portsz = 1;
t->addrrange_start = (unsigned long) _stext;
t->addrrange_end = (unsigned long) _etext;
+ t->pid = -1; /* trace everything */
etm_unlock(t);
(void)etm_readl(t, ETMMR_PDSR);
@@ -605,6 +712,7 @@ static int etm_probe(struct amba_device *dev, const struct amba_id *id)
(void)etm_readl(&tracer, ETMMR_OSSRR);
t->naddrcmppairs = etm_readl(t, ETMR_CONFCODE) & 0xf;
+ t->nctxidcmp = (etm_readl(t, ETMR_CONFCODE) >> 24) & 0x3;
etm_writel(t, 0x440, ETMR_CTRL);
etm_lock(t);
@@ -612,7 +720,7 @@ static int etm_probe(struct amba_device *dev, const struct amba_id *id)
if (ret)
goto out_unmap;
- /* failing to create any of these three is not fatal */
+ /* failing to create any of these four is not fatal */
ret = device_create_file(&dev->dev, &dev_attr_trace_info);
if (ret)
dev_dbg(&dev->dev, "Failed to create trace_info in sysfs\n");
@@ -625,6 +733,12 @@ static int etm_probe(struct amba_device *dev, const struct amba_id *id)
if (ret)
dev_dbg(&dev->dev, "Failed to create trace_addrrange in sysfs\n");
+#ifdef CONFIG_PID_IN_CONTEXTIDR
+ ret = device_create_file(&dev->dev, &dev_attr_trace_pid);
+ if (ret)
+ dev_dbg(&dev->dev, "Failed to create trace_pid in sysfs\n");
+#endif
+
dev_dbg(t->dev, "ETM AMBA driver initialized.\n");
out:
@@ -655,6 +769,9 @@ static int etm_remove(struct amba_device *dev)
device_remove_file(&dev->dev, &dev_attr_trace_info);
device_remove_file(&dev->dev, &dev_attr_trace_mode);
device_remove_file(&dev->dev, &dev_attr_trace_addrrange);
+#ifdef CONFIG_PID_IN_CONTEXTIDR
+ device_remove_file(&dev->dev, &dev_attr_trace_pid);
+#endif
return 0;
}
--
1.8.5.3
^ permalink raw reply related [flat|nested] 7+ messages in thread* [PATCH V3 5/5] ARM CoreSight: ETM: Add PID control support
2014-01-30 16:11 ` [PATCH V3 5/5] ARM CoreSight: ETM: Add PID " Adrien Vergé
@ 2014-02-03 10:46 ` Will Deacon
0 siblings, 0 replies; 7+ messages in thread
From: Will Deacon @ 2014-02-03 10:46 UTC (permalink / raw)
To: linux-arm-kernel
On Thu, Jan 30, 2014 at 04:11:10PM +0000, Adrien Verg? wrote:
> In the same manner as for enabling tracing, an entry is created in
> sysfs to set the PID that triggers tracing. This change is effective
> only if CONFIG_PID_IN_CONTEXTIDR is set.
>
> When using PID namespaces, the virtual PID given by the user is
> converted to the globally unique ID (task_pid_nr) that is present
> in the Context ID register.
Hmm, I wonder whether debugfs would be more suitable for this?
Will
^ permalink raw reply [flat|nested] 7+ messages in thread