linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH V3 0/5] ARM CoreSight: ETM: Fix a vmalloc/vfree failure and enhance tracing control
@ 2014-01-30 16:11 Adrien Vergé
  2014-01-30 16:11 ` [PATCH V3 1/5] ARM CoreSight: ETM: Fix a memory allocation failure Adrien Vergé
                   ` (4 more replies)
  0 siblings, 5 replies; 7+ messages in thread
From: Adrien Vergé @ 2014-01-30 16:11 UTC (permalink / raw)
  To: Russell King
  Cc: Adrien Vergé,
	Catalin Marinas, Will Deacon, Ben Dooks, zhangwei(Jovi),
	Andrew Morton, Randy Dunlap, Mathieu Poirier,
	Christopher Covington, Dirk Behme, Michel Dagenais,
	linux-arm-kernel, linux-kernel

Hi Russell,

Different ARM users have shown their interest in this patch, so I made
a third version that is compatible with PID namespaces.

Mainly:
- It fixes a "vmalloc: allocation failure: 0 bytes" when reading an
  ETB buffer that is empty.
- It extends current support of CoreSight ETM, that is currently
  very limited.

ETM is a dedicated hardware that provides program tracing, a
cycle-precise and low-overhead solution that software tools such as
'perf record' cannot provide.

Usage of ETM tracing facility is presently limited to start and stop
tracing.  This set of patches enables management of address combinations
and PIDs that trigger tracing, thus allowing to trace specific
functions and processes.  ETM management was done via sysfs entries
(trace_info, trace_running...), this code adds trace_addrrange and
trace_pid to let the user read/write custom values.

Changes in V2:
- Fix a vmalloc/vfree failure when ETB is empty
- Use device attributes rather than raw kobjects
- Make PID_IN_CONTEXTIDR incompatible with PID_NS in Kconfig
- Use pid_t instead of long

Changes in V3:
- Support tracing processes by their PID in PID namespaces
- Reset PID_IN_CONTEXTIDR and PID_NS independent

This series of patches applies to v3.13.

Adrien Vergé (5):
  ARM CoreSight: ETM: Fix a memory allocation failure
  ARM CoreSight: ETM: Use device attributes
  ARM CoreSight: ETM: Rename 'comparator' to 'address comparator'
  ARM CoreSight: ETM: Add address control support
  ARM CoreSight: ETM: Add PID control support

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

-- 
1.8.5.3


^ permalink raw reply	[flat|nested] 7+ messages in thread

* [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: Russell King
  Cc: Adrien Vergé,
	Catalin Marinas, Will Deacon, Ben Dooks, zhangwei(Jovi),
	Andrew Morton, Randy Dunlap, Mathieu Poirier,
	Christopher Covington, Dirk Behme, Michel Dagenais,
	linux-arm-kernel, linux-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: Russell King
  Cc: Adrien Vergé,
	Catalin Marinas, Will Deacon, Ben Dooks, zhangwei(Jovi),
	Andrew Morton, Randy Dunlap, Mathieu Poirier,
	Christopher Covington, Dirk Behme, Michel Dagenais,
	linux-arm-kernel, linux-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: Russell King
  Cc: Adrien Vergé,
	Catalin Marinas, Will Deacon, Ben Dooks, zhangwei(Jovi),
	Andrew Morton, Randy Dunlap, Mathieu Poirier,
	Christopher Covington, Dirk Behme, Michel Dagenais,
	linux-arm-kernel, linux-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: Russell King
  Cc: Adrien Vergé,
	Catalin Marinas, Will Deacon, Ben Dooks, zhangwei(Jovi),
	Andrew Morton, Randy Dunlap, Mathieu Poirier,
	Christopher Covington, Dirk Behme, Michel Dagenais,
	linux-arm-kernel, linux-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: Russell King
  Cc: Adrien Vergé,
	Catalin Marinas, Will Deacon, Ben Dooks, zhangwei(Jovi),
	Andrew Morton, Randy Dunlap, Mathieu Poirier,
	Christopher Covington, Dirk Behme, Michel Dagenais,
	linux-arm-kernel, linux-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

* Re: [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: Adrien Vergé
  Cc: Russell King, Catalin Marinas, Ben Dooks, zhangwei(Jovi),
	Andrew Morton, Randy Dunlap, Mathieu Poirier,
	Christopher Covington, Dirk Behme, Michel Dagenais,
	linux-arm-kernel, linux-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

end of thread, other threads:[~2014-02-03 10:48 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
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 ` [PATCH V3 3/5] ARM CoreSight: ETM: Rename 'comparator' to 'address comparator' 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é
2014-02-03 10:46   ` Will Deacon

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).