Message ID | 1543442478-31465-5-git-send-email-mathieu.poirier@linaro.org |
---|---|
State | New |
Headers | show |
Series | perf: Add ioctl for PMU driver configuration | expand |
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
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
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
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 --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)
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(-) -- 2.7.4