diff mbox series

[v4,4/6] coresight: Use PMU driver configuration for sink selection

Message ID 1543442478-31465-5-git-send-email-mathieu.poirier@linaro.org (mailing list archive)
State New, archived
Headers show
Series perf: Add ioctl for PMU driver configuration | expand

Commit Message

Mathieu Poirier Nov. 28, 2018, 10:01 p.m. UTC
This patch uses the PMU driver configuration held in event::hw::drv_config
to select a sink for each event that is created (the old sysFS way of
working is kept around for backward compatibility).

By proceeding in this way a sink can be used by multiple sessions
without having to play games with entries in sysFS.

Signed-off-by: Mathieu Poirier <mathieu.poirier@linaro.org>
---
 drivers/hwtracing/coresight/coresight-etm-perf.c | 58 +++++++++++++++++++-----
 1 file changed, 46 insertions(+), 12 deletions(-)

Comments

Greg KH Nov. 29, 2018, 7:49 a.m. UTC | #1
On Wed, Nov 28, 2018 at 03:01:16PM -0700, Mathieu Poirier wrote:
> This patch uses the PMU driver configuration held in event::hw::drv_config
> to select a sink for each event that is created (the old sysFS way of
> working is kept around for backward compatibility).

It is "sysfs", no InterCaps please, I've never called it that in the
past.

And just use sysfs, if that does not work properly, then fix that, don't
create yet-another-way-to-configure-this-thing to just confuse people.

thanks,

greg k-h
Mathieu Poirier Nov. 29, 2018, 11:09 p.m. UTC | #2
Hi Greg,

On Thu, Nov 29, 2018 at 08:49:36AM +0100, Greg KH wrote:
> On Wed, Nov 28, 2018 at 03:01:16PM -0700, Mathieu Poirier wrote:
> > This patch uses the PMU driver configuration held in event::hw::drv_config
> > to select a sink for each event that is created (the old sysFS way of
> > working is kept around for backward compatibility).
> 
> It is "sysfs", no InterCaps please, I've never called it that in the
> past.
> 
> And just use sysfs, if that does not work properly, then fix that, don't
> create yet-another-way-to-configure-this-thing to just confuse people.

Thanks for the review, you've provided usefull comments.

Regarding the "char *" argument for the ioctl, I followed an example that
currently exist but I can proceed differently.  

My goal with this patchset was specifically to fix what is wrong with sysfs and
completely take it out of the equation.  The only reason to keep the kernel 
interface alive was to prevent braking older user space perf tools currently
using it.  

I chose to use an ioctl() because it is flexible and well suited for the dynamic
nature of perf events.  It is also currently used to set various event specific 
configuration so doing the same adds to the established pattern and avoids
creating a new way of doing things, something the perf crew would have been
quick to point out.

Was my approach wrong?

Regards,
Mathieu

> 
> thanks,
> 
> greg k-h
Greg KH Nov. 30, 2018, 7:42 a.m. UTC | #3
On Thu, Nov 29, 2018 at 04:09:15PM -0700, Mathieu Poirier wrote:
> Hi Greg,
> 
> On Thu, Nov 29, 2018 at 08:49:36AM +0100, Greg KH wrote:
> > On Wed, Nov 28, 2018 at 03:01:16PM -0700, Mathieu Poirier wrote:
> > > This patch uses the PMU driver configuration held in event::hw::drv_config
> > > to select a sink for each event that is created (the old sysFS way of
> > > working is kept around for backward compatibility).
> > 
> > It is "sysfs", no InterCaps please, I've never called it that in the
> > past.
> > 
> > And just use sysfs, if that does not work properly, then fix that, don't
> > create yet-another-way-to-configure-this-thing to just confuse people.
> 
> Thanks for the review, you've provided usefull comments.
> 
> Regarding the "char *" argument for the ioctl, I followed an example that
> currently exist but I can proceed differently.  

What driver currently uses a char * on an ioctl to parse arbritrary
userspace information to set its configuration?  That should be fixed...

> My goal with this patchset was specifically to fix what is wrong with sysfs and
> completely take it out of the equation.  The only reason to keep the kernel 
> interface alive was to prevent braking older user space perf tools currently
> using it.  

That's fine, just don't create a new syscall that takes arbritrary data
and parses it in the kernel, that's not ok.

> I chose to use an ioctl() because it is flexible and well suited for the dynamic
> nature of perf events.  It is also currently used to set various event specific 
> configuration so doing the same adds to the established pattern and avoids
> creating a new way of doing things, something the perf crew would have been
> quick to point out.
> 
> Was my approach wrong?

I don't know how the perf interface works, so perhaps work with those
developers to sync up and match what they use today?

But step back, what exactly are you trying to do here?  You have an
implementation of a solution but I don't see the problem stated anywhere
here.

thanks,

greg k-h
Mathieu Poirier Nov. 30, 2018, 6:05 p.m. UTC | #4
On Fri, 30 Nov 2018 at 00:42, Greg KH <gregkh@linuxfoundation.org> wrote:
>
> On Thu, Nov 29, 2018 at 04:09:15PM -0700, Mathieu Poirier wrote:
> > Hi Greg,
> >
> > On Thu, Nov 29, 2018 at 08:49:36AM +0100, Greg KH wrote:
> > > On Wed, Nov 28, 2018 at 03:01:16PM -0700, Mathieu Poirier wrote:
> > > > This patch uses the PMU driver configuration held in event::hw::drv_config
> > > > to select a sink for each event that is created (the old sysFS way of
> > > > working is kept around for backward compatibility).
> > >
> > > It is "sysfs", no InterCaps please, I've never called it that in the
> > > past.
> > >
> > > And just use sysfs, if that does not work properly, then fix that, don't
> > > create yet-another-way-to-configure-this-thing to just confuse people.
> >
> > Thanks for the review, you've provided usefull comments.
> >
> > Regarding the "char *" argument for the ioctl, I followed an example that
> > currently exist but I can proceed differently.
>
> What driver currently uses a char * on an ioctl to parse arbritrary
> userspace information to set its configuration?  That should be fixed...
>

Perf filters [1] are communicated to the kernel as a char *.  Given
the dynamic nature of event creation I really don't know how else it
could have been done.

[1]. https://elixir.bootlin.com/linux/latest/source/include/uapi/linux/perf_event.h#L459

> > My goal with this patchset was specifically to fix what is wrong with sysfs and
> > completely take it out of the equation.  The only reason to keep the kernel
> > interface alive was to prevent braking older user space perf tools currently
> > using it.
>
> That's fine, just don't create a new syscall that takes arbritrary data
> and parses it in the kernel, that's not ok.

You got it.

>
> > I chose to use an ioctl() because it is flexible and well suited for the dynamic
> > nature of perf events.  It is also currently used to set various event specific
> > configuration so doing the same adds to the established pattern and avoids
> > creating a new way of doing things, something the perf crew would have been
> > quick to point out.
> >
> > Was my approach wrong?
>
> I don't know how the perf interface works, so perhaps work with those
> developers to sync up and match what they use today?

I have already done a fair amount of work with them.

>
> But step back, what exactly are you trying to do here?  You have an
> implementation of a solution but I don't see the problem stated anywhere
> here.

In the coresight world there can be more than one sink to aggregate
trace data generated by CPUs, hence the need for users to select which
one to use from the perf command line.

Up until now sysfs was used to communicate sink information to the
kernel but that was never the right way to proceed because it breaks
when more than one perf session are created at the same time.  The
situation was manageable when working with per-thread scenarios where
a single HW trace event is created but in CPU-wide mode a HW trace
event is created for each CPU that is specified on the perf command
line, taking us back to the concurrency problem we have when dealing
with multiple per-thread session.

Since my goal is to add coresight support for CPU-wide trace
scenarios, the issue with sysfs concurrency needs to be addressed
first, which this set is aiming at.  Sysfs is a problem so I'm
removing it in favour of an ioctl() where a specific sink can be
assigned to each event.

The above should probably go in the cover letter.  Let me know if you
want more information.

Thanks,
Mathieu
diff mbox series

Patch

diff --git a/drivers/hwtracing/coresight/coresight-etm-perf.c b/drivers/hwtracing/coresight/coresight-etm-perf.c
index f21eb28b6782..0fbff912d515 100644
--- a/drivers/hwtracing/coresight/coresight-etm-perf.c
+++ b/drivers/hwtracing/coresight/coresight-etm-perf.c
@@ -14,6 +14,7 @@ 
 #include <linux/perf_event.h>
 #include <linux/percpu-defs.h>
 #include <linux/slab.h>
+#include <linux/string.h>
 #include <linux/types.h>
 #include <linux/workqueue.h>
 
@@ -177,6 +178,26 @@  static void etm_free_aux(void *data)
 	schedule_work(&event_data->work);
 }
 
+static struct coresight_device *etm_drv_config_sync(struct perf_event *event)
+{
+	struct coresight_device *sink = NULL;
+	struct pmu_drv_config *drv_config = perf_event_get_drv_config(event);
+
+	/*
+	 * Make sure we don't race with perf_drv_config_replace() in
+	 * kernel/events/core.c.
+	 */
+	raw_spin_lock(&drv_config->lock);
+
+	/* Copy what we got from user space if applicable. */
+	if (drv_config->config)
+		sink = drv_config->config;
+
+	raw_spin_unlock(&drv_config->lock);
+
+	return sink;
+}
+
 static void *etm_setup_aux(struct perf_event *event, void **pages,
 			   int nr_pages, bool overwrite)
 {
@@ -190,18 +211,11 @@  static void *etm_setup_aux(struct perf_event *event, void **pages,
 		return NULL;
 	INIT_WORK(&event_data->work, free_event_data);
 
-	/*
-	 * In theory nothing prevent tracers in a trace session from being
-	 * associated with different sinks, nor having a sink per tracer.  But
-	 * until we have HW with this kind of topology we need to assume tracers
-	 * in a trace session are using the same sink.  Therefore go through
-	 * the coresight bus and pick the first enabled sink.
-	 *
-	 * When operated from sysFS users are responsible to enable the sink
-	 * while from perf, the perf tools will do it based on the choice made
-	 * on the cmd line.  As such the "enable_sink" flag in sysFS is reset.
-	 */
-	sink = coresight_get_enabled_sink(true);
+	/* First get the sink config from user space. */
+	sink = etm_drv_config_sync(event);
+	if (!sink)
+		sink = coresight_get_enabled_sink(true);
+
 	if (!sink || !sink_ops(sink)->alloc_buffer)
 		goto err;
 
@@ -454,6 +468,25 @@  static void etm_addr_filters_sync(struct perf_event *event)
 	filters->nr_filters = i;
 }
 
+static void *etm_drv_config_validate(struct perf_event *event, char *cstr)
+{
+	char drv_config[NAME_MAX];
+	struct device *dev;
+	struct coresight_device *sink;
+
+	strncpy(drv_config, cstr, NAME_MAX);
+
+	/* Look for the device with that name on the CS bus. */
+	dev = bus_find_device_by_name(&coresight_bustype, NULL, drv_config);
+	if (!dev)
+		return ERR_PTR(-EINVAL);
+
+	sink = to_coresight_device(dev);
+	put_device(dev);
+
+	return sink;
+}
+
 int etm_perf_symlink(struct coresight_device *csdev, bool link)
 {
 	char entry[sizeof("cpu9999999")];
@@ -498,6 +531,7 @@  static int __init etm_perf_init(void)
 	etm_pmu.addr_filters_sync	= etm_addr_filters_sync;
 	etm_pmu.addr_filters_validate	= etm_addr_filters_validate;
 	etm_pmu.nr_addr_filters		= ETM_ADDR_CMP_MAX;
+	etm_pmu.drv_config_validate	= etm_drv_config_validate;
 
 	ret = perf_pmu_register(&etm_pmu, CORESIGHT_ETM_PMU_NAME, -1);
 	if (ret == 0)