Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > linux.kernel > #1447450 > unrolled thread
| Started by | Mathieu Poirier <mathieu.poirier@linaro.org> |
|---|---|
| First post | 2016-07-20 22:40 +0200 |
| Last post | 2016-07-22 22:00 +0200 |
| Articles | 10 — 3 participants |
Back to article view | Back to linux.kernel
[PATCH V2 0/6] perf: Driver specific configuration for PMU Mathieu Poirier <mathieu.poirier@linaro.org> - 2016-07-20 22:40 +0200
[PATCH V2 1/6] perf/core: Adding PMU driver specific configuration Mathieu Poirier <mathieu.poirier@linaro.org> - 2016-07-20 22:40 +0200
[PATCH V2 6/6] coresight: etm-perf: incorporating sink definition from cmd line Mathieu Poirier <mathieu.poirier@linaro.org> - 2016-07-20 22:40 +0200
[PATCH V2 5/6] coresight: adding sink parameter to function coresight_build_path() Mathieu Poirier <mathieu.poirier@linaro.org> - 2016-07-20 22:40 +0200
Re: [PATCH V2 5/6] coresight: adding sink parameter to function coresight_build_path() Suzuki K Poulose <Suzuki.Poulose@arm.com> - 2016-07-21 12:50 +0200
Re: [PATCH V2 5/6] coresight: adding sink parameter to function coresight_build_path() Mathieu Poirier <mathieu.poirier@linaro.org> - 2016-07-21 17:10 +0200
[PATCH V2 2/6] perf: Passing struct perf_event to function setup_aux() Mathieu Poirier <mathieu.poirier@linaro.org> - 2016-07-20 22:40 +0200
[PATCH V2 4/6] perf tools: pushing driver configuration down to the kernel Mathieu Poirier <mathieu.poirier@linaro.org> - 2016-07-20 22:40 +0200
Re: [PATCH V2 4/6] perf tools: pushing driver configuration down to the kernel Jiri Olsa <jolsa@redhat.com> - 2016-07-21 09:50 +0200
Re: [PATCH V2 4/6] perf tools: pushing driver configuration down to the kernel Mathieu Poirier <mathieu.poirier@linaro.org> - 2016-07-22 22:00 +0200
| From | Mathieu Poirier <mathieu.poirier@linaro.org> |
|---|---|
| Date | 2016-07-20 22:40 +0200 |
| Subject | [PATCH V2 0/6] perf: Driver specific configuration for PMU |
| Message-ID | <rX6rD-6b4-5@gated-at.bofh.it> |
This patchset adds the possiblity of specifying PMU driver configuration directly from the perf command line. Anything that falls within the event specifiers '/.../' and that is preceeded by the '@' symbol is treated as a configurable. Two formats are supported, @cfg and @cfg=config. For example: perf record -e some_event/@cfg1/ ... or perf record -e some_event/@cfg2=config/ ... or perf record -e some_event/@cfg1,@cfg2=config/ ... The above are all valid configuration and will see the strings 'cfg1' and 'cfg2=config' sent to the PMU driver for parsing and interpretation using the existing ioctl() mechanism. The primary customers for this feature are the CoreSight drivers where the selection of a sink (where trace data is accumulated) needs to be done in a previous, and separated step, from the launching of the perf command. As such something that used to be a two-step process: # echo 1 > /sys/bus/coresight/devices/20070000.etr/enable_sink # perf record -e cs_etm//u --per-thread uname is integrated in a single command: # perf record -e cs_etm/@sink=20070000.etr/u --per-thread uname The patches include both the kernel and user space part so that the solution is complete and found in a single place. It is based on [1] and assumes this set [2] has been applied. Thanks, Mathieu Changes for V2: - Rebased to [1] as per Jiri's request. [1]. git://git.kernel.org/pub/scm/linux/kernel/git/acme/linux.git perf/core [2]. https://lkml.org/lkml/2016/7/20/519 Mathieu Poirier (6): perf/core: Adding PMU driver specific configuration perf: Passing struct perf_event to function setup_aux() perf tools: add infrastructure for PMU specific configuration perf tools: pushing driver configuration down to the kernel coresight: adding sink parameter to function coresight_build_path() coresight: etm-perf: incorporating sink definition from cmd line arch/x86/events/intel/bts.c | 4 +- arch/x86/events/intel/pt.c | 5 +- drivers/hwtracing/coresight/coresight-etm-perf.c | 105 ++++++++++++++++++++++- drivers/hwtracing/coresight/coresight-priv.h | 3 +- drivers/hwtracing/coresight/coresight.c | 40 ++++++--- include/linux/perf_event.h | 11 ++- include/uapi/linux/perf_event.h | 1 + kernel/events/core.c | 16 ++++ kernel/events/ring_buffer.c | 2 +- tools/include/uapi/linux/perf_event.h | 1 + tools/perf/builtin-record.c | 9 ++ tools/perf/util/evlist.c | 24 ++++++ tools/perf/util/evlist.h | 3 + tools/perf/util/evsel.c | 33 +++++++ tools/perf/util/evsel.h | 7 ++ tools/perf/util/parse-events.c | 76 +++++++++++----- tools/perf/util/parse-events.h | 1 + tools/perf/util/parse-events.l | 12 +++ tools/perf/util/parse-events.y | 11 +++ 19 files changed, 321 insertions(+), 43 deletions(-) -- 2.7.4
[toc] | [next] | [standalone]
| From | Mathieu Poirier <mathieu.poirier@linaro.org> |
|---|---|
| Date | 2016-07-20 22:40 +0200 |
| Subject | [PATCH V2 1/6] perf/core: Adding PMU driver specific configuration |
| Message-ID | <rX6rD-6b4-13@gated-at.bofh.it> |
| In reply to | #1447450 |
This patch somewhat mimics the work done on address filters to
add the infrastructure needed to pass PMU specific HW
configuration to the driver before a session starts.
Signed-off-by: Mathieu Poirier <mathieu.poirier@linaro.org>
---
include/linux/perf_event.h | 9 +++++++++
include/uapi/linux/perf_event.h | 1 +
kernel/events/core.c | 16 ++++++++++++++++
tools/include/uapi/linux/perf_event.h | 1 +
4 files changed, 27 insertions(+)
diff --git a/include/linux/perf_event.h b/include/linux/perf_event.h
index 7921f4f20a58..59d61a12cf9d 100644
--- a/include/linux/perf_event.h
+++ b/include/linux/perf_event.h
@@ -168,6 +168,9 @@ struct hw_perf_event {
/* Last sync'ed generation of filters */
unsigned long addr_filters_gen;
+ /* HW specific configuration */
+ void *drv_configs;
+
/*
* hw_perf_event::state flags; used to track the PERF_EF_* state.
*/
@@ -442,6 +445,12 @@ struct pmu {
* Filter events for PMU-specific reasons.
*/
int (*filter_match) (struct perf_event *event); /* optional */
+
+ /*
+ * PMU driver specific configuration.
+ */
+ int (*set_drv_configs) (struct perf_event *event,
+ void __user *arg); /* optional */
};
/**
diff --git a/include/uapi/linux/perf_event.h b/include/uapi/linux/perf_event.h
index c66a485a24ac..90fbc5fd3925 100644
--- a/include/uapi/linux/perf_event.h
+++ b/include/uapi/linux/perf_event.h
@@ -407,6 +407,7 @@ struct perf_event_attr {
#define PERF_EVENT_IOC_ID _IOR('$', 7, __u64 *)
#define PERF_EVENT_IOC_SET_BPF _IOW('$', 8, __u32)
#define PERF_EVENT_IOC_PAUSE_OUTPUT _IOW('$', 9, __u32)
+#define PERF_EVENT_IOC_SET_DRV_CONFIGS _IOW('$', 10, char *)
enum perf_event_ioc_flags {
PERF_IOC_FLAG_GROUP = 1U << 0,
diff --git a/kernel/events/core.c b/kernel/events/core.c
index 79dae188a987..9208e6ec036f 100644
--- a/kernel/events/core.c
+++ b/kernel/events/core.c
@@ -4457,6 +4457,8 @@ static int perf_event_set_output(struct perf_event *event,
struct perf_event *output_event);
static int perf_event_set_filter(struct perf_event *event, void __user *arg);
static int perf_event_set_bpf_prog(struct perf_event *event, u32 prog_fd);
+static int perf_event_set_drv_configs(struct perf_event *event,
+ void __user *arg);
static long _perf_ioctl(struct perf_event *event, unsigned int cmd, unsigned long arg)
{
@@ -4526,6 +4528,10 @@ static long _perf_ioctl(struct perf_event *event, unsigned int cmd, unsigned lon
rcu_read_unlock();
return 0;
}
+
+ case PERF_EVENT_IOC_SET_DRV_CONFIGS:
+ return perf_event_set_drv_configs(event, (void __user *)arg);
+
default:
return -ENOTTY;
}
@@ -4558,6 +4564,7 @@ static long perf_compat_ioctl(struct file *file, unsigned int cmd,
switch (_IOC_NR(cmd)) {
case _IOC_NR(PERF_EVENT_IOC_SET_FILTER):
case _IOC_NR(PERF_EVENT_IOC_ID):
+ case _IOC_NR(PERF_EVENT_IOC_SET_DRV_CONFIGS):
/* Fix up pointer size (usually 4 -> 8 in 32-on-64-bit case */
if (_IOC_SIZE(cmd) == sizeof(compat_uptr_t)) {
cmd &= ~IOCSIZE_MASK;
@@ -7633,6 +7640,15 @@ void perf_bp_event(struct perf_event *bp, void *data)
}
#endif
+static int perf_event_set_drv_configs(struct perf_event *event,
+ void __user *arg)
+{
+ if (!event->pmu->set_drv_configs)
+ return -EINVAL;
+
+ return event->pmu->set_drv_configs(event, arg);
+}
+
/*
* Allocate a new address filter
*/
diff --git a/tools/include/uapi/linux/perf_event.h b/tools/include/uapi/linux/perf_event.h
index c66a485a24ac..90fbc5fd3925 100644
--- a/tools/include/uapi/linux/perf_event.h
+++ b/tools/include/uapi/linux/perf_event.h
@@ -407,6 +407,7 @@ struct perf_event_attr {
#define PERF_EVENT_IOC_ID _IOR('$', 7, __u64 *)
#define PERF_EVENT_IOC_SET_BPF _IOW('$', 8, __u32)
#define PERF_EVENT_IOC_PAUSE_OUTPUT _IOW('$', 9, __u32)
+#define PERF_EVENT_IOC_SET_DRV_CONFIGS _IOW('$', 10, char *)
enum perf_event_ioc_flags {
PERF_IOC_FLAG_GROUP = 1U << 0,
--
2.7.4
[toc] | [prev] | [next] | [standalone]
| From | Mathieu Poirier <mathieu.poirier@linaro.org> |
|---|---|
| Date | 2016-07-20 22:40 +0200 |
| Subject | [PATCH V2 6/6] coresight: etm-perf: incorporating sink definition from cmd line |
| Message-ID | <rX6rD-6b4-3@gated-at.bofh.it> |
| In reply to | #1447450 |
Now that PMU specific configuration is available as part of the event,
lookup the sink identified by users from the perf command line and build
a path from source to sink.
With this functionality it is no longer required to select a sink in a
separate step (from sysFS) before a perf trace session can be started.
Signed-off-by: Mathieu Poirier <mathieu.poirier@linaro.org>
---
drivers/hwtracing/coresight/coresight-etm-perf.c | 101 ++++++++++++++++++++++-
1 file changed, 100 insertions(+), 1 deletion(-)
diff --git a/drivers/hwtracing/coresight/coresight-etm-perf.c b/drivers/hwtracing/coresight/coresight-etm-perf.c
index f8c7a8733b23..5658a7411a66 100644
--- a/drivers/hwtracing/coresight/coresight-etm-perf.c
+++ b/drivers/hwtracing/coresight/coresight-etm-perf.c
@@ -22,6 +22,7 @@
#include <linux/list.h>
#include <linux/mm.h>
#include <linux/init.h>
+#include <linux/parser.h>
#include <linux/perf_event.h>
#include <linux/slab.h>
#include <linux/types.h>
@@ -71,11 +72,20 @@ static const struct attribute_group *etm_pmu_attr_groups[] = {
static void etm_event_read(struct perf_event *event) {}
+static void etm_event_destroy(struct perf_event *event)
+{
+ kfree(event->hw.drv_configs);
+ event->hw.drv_configs = NULL;
+}
+
static int etm_event_init(struct perf_event *event)
{
if (event->attr.type != etm_pmu.type)
return -ENOENT;
+ event->destroy = etm_event_destroy;
+ event->hw.drv_configs = NULL;
+
return 0;
}
@@ -159,6 +169,7 @@ static void *etm_setup_aux(struct perf_event *event, void **pages,
int nr_pages, bool overwrite)
{
int cpu;
+ char *cmdl_sink;
cpumask_t *mask;
struct coresight_device *sink;
struct etm_event_data *event_data = NULL;
@@ -171,6 +182,12 @@ static void *etm_setup_aux(struct perf_event *event, void **pages,
mask = &event_data->mask;
+ /*
+ * If a sink was specified from the perf cmdline it will be part of
+ * the event's drv_configs.
+ */
+ cmdl_sink = (char *)event->hw.drv_configs;
+
/* Setup the path for each CPU in a trace session */
for_each_cpu(cpu, mask) {
struct coresight_device *csdev;
@@ -184,7 +201,7 @@ static void *etm_setup_aux(struct perf_event *event, void **pages,
* list of devices from source to sink that can be
* referenced later when the path is actually needed.
*/
- event_data->path[cpu] = coresight_build_path(csdev, NULL);
+ event_data->path[cpu] = coresight_build_path(csdev, cmdl_sink);
if (!event_data->path[cpu])
goto err;
}
@@ -342,6 +359,87 @@ static void etm_event_del(struct perf_event *event, int mode)
etm_event_stop(event, PERF_EF_UPDATE);
}
+enum {
+ ETM_TOKEN_SINK_CPU,
+ ETM_TOKEN_SINK,
+ ETM_TOKEN_ERR,
+};
+
+static const match_table_t drv_cfg_tokens = {
+ {ETM_TOKEN_SINK_CPU, "sink=cpu%d:%s"},
+ {ETM_TOKEN_SINK, "sink=%s"},
+ {ETM_TOKEN_ERR, NULL},
+};
+
+static int etm_set_drv_configs(struct perf_event *event, void __user *arg)
+{
+ char *config, *sink = NULL;
+ int cpu = -1, token, ret = 0;
+ substring_t args[MAX_OPT_ARGS];
+
+ /* Only one sink per event */
+ if (event->hw.drv_configs != NULL) {
+ ret = -EINVAL;
+ goto err;
+ }
+
+ /* Make user supplied input usable */
+ config = strndup_user(arg, PAGE_SIZE);
+ if (IS_ERR(config)) {
+ ret = PTR_ERR(config);
+ goto err;
+ }
+
+ /* See above declared @drv_cfg_tokens for the usable formats */
+ token = match_token(config, drv_cfg_tokens, args);
+ switch (token) {
+ case ETM_TOKEN_SINK:
+ /* Just a sink has been specified */
+ sink = match_strdup(&args[0]);
+ if (IS_ERR(sink)) {
+ ret = PTR_ERR(sink);
+ goto err;
+ }
+ break;
+ case ETM_TOKEN_SINK_CPU:
+ /* We have a sink and a CPU */
+
+ /* First get the cpu */
+ if (match_int(&args[0], &cpu)) {
+ ret = -EINVAL;
+ goto err;
+ }
+
+ /* Then the sink */
+ sink = match_strdup(&args[1]);
+ if (IS_ERR(sink)) {
+ ret = PTR_ERR(sink);
+ goto err;
+ }
+ break;
+ default:
+ ret = -EINVAL;
+ goto err;
+ }
+
+ /*
+ * If the CPUs don't match the sink is destined to another path. This
+ * isn't as an error hence not setting @ret.
+ */
+ if (event->cpu != cpu)
+ goto err;
+
+ /* We have a valid configuration */
+ event->hw.drv_configs = sink;
+
+out:
+ return ret;
+
+err:
+ kfree(sink);
+ goto out;
+}
+
int etm_perf_symlink(struct coresight_device *csdev, bool link)
{
char entry[sizeof("cpu9999999")];
@@ -383,6 +481,7 @@ static int __init etm_perf_init(void)
etm_pmu.stop = etm_event_stop;
etm_pmu.add = etm_event_add;
etm_pmu.del = etm_event_del;
+ etm_pmu.set_drv_configs = etm_set_drv_configs;
ret = perf_pmu_register(&etm_pmu, CORESIGHT_ETM_PMU_NAME, -1);
if (ret == 0)
--
2.7.4
[toc] | [prev] | [next] | [standalone]
| From | Mathieu Poirier <mathieu.poirier@linaro.org> |
|---|---|
| Date | 2016-07-20 22:40 +0200 |
| Subject | [PATCH V2 5/6] coresight: adding sink parameter to function coresight_build_path() |
| Message-ID | <rX6rD-6b4-21@gated-at.bofh.it> |
| In reply to | #1447450 |
Up to now function coresight_build_path() was counting on a sink to
have been selected (from sysFS) prior to being called. This patch
adds a string argument so that a sink matching the argument can be
selected.
Signed-off-by: Mathieu Poirier <mathieu.poirier@linaro.org>
---
drivers/hwtracing/coresight/coresight-etm-perf.c | 2 +-
drivers/hwtracing/coresight/coresight-priv.h | 3 +-
drivers/hwtracing/coresight/coresight.c | 40 +++++++++++++++---------
3 files changed, 29 insertions(+), 16 deletions(-)
diff --git a/drivers/hwtracing/coresight/coresight-etm-perf.c b/drivers/hwtracing/coresight/coresight-etm-perf.c
index f4174f36c5a0..f8c7a8733b23 100644
--- a/drivers/hwtracing/coresight/coresight-etm-perf.c
+++ b/drivers/hwtracing/coresight/coresight-etm-perf.c
@@ -184,7 +184,7 @@ static void *etm_setup_aux(struct perf_event *event, void **pages,
* list of devices from source to sink that can be
* referenced later when the path is actually needed.
*/
- event_data->path[cpu] = coresight_build_path(csdev);
+ event_data->path[cpu] = coresight_build_path(csdev, NULL);
if (!event_data->path[cpu])
goto err;
}
diff --git a/drivers/hwtracing/coresight/coresight-priv.h b/drivers/hwtracing/coresight/coresight-priv.h
index ad975c58080d..3cb574b3cdd9 100644
--- a/drivers/hwtracing/coresight/coresight-priv.h
+++ b/drivers/hwtracing/coresight/coresight-priv.h
@@ -94,7 +94,8 @@ static inline void CS_UNLOCK(void __iomem *addr)
void coresight_disable_path(struct list_head *path);
int coresight_enable_path(struct list_head *path, u32 mode);
struct coresight_device *coresight_get_sink(struct list_head *path);
-struct list_head *coresight_build_path(struct coresight_device *csdev);
+struct list_head *coresight_build_path(struct coresight_device *csdev,
+ const char *sink);
void coresight_release_path(struct list_head *path);
#ifdef CONFIG_CORESIGHT_SOURCE_ETM3X
diff --git a/drivers/hwtracing/coresight/coresight.c b/drivers/hwtracing/coresight/coresight.c
index d08d1ab9bba5..cbbb51a16dff 100644
--- a/drivers/hwtracing/coresight/coresight.c
+++ b/drivers/hwtracing/coresight/coresight.c
@@ -372,30 +372,41 @@ struct coresight_device *coresight_get_sink(struct list_head *path)
* _coresight_build_path - recursively build a path from a @csdev to a sink.
* @csdev: The device to start from.
* @path: The list to add devices to.
+ * @sink: The name of the sink this path should connect with.
*
- * The tree of Coresight device is traversed until an activated sink is
- * found. From there the sink is added to the list along with all the
- * devices that led to that point - the end result is a list from source
- * to sink. In that list the source is the first device and the sink the
- * last one.
+ * The tree of Coresight device is traversed until an activated sink or
+ * the one specified by @sink is found.
+ * From there the sink is added to the list along with all the devices that
+ * led to that point - the end result is a list from source to sink. In that
+ * list the source is the first device and the sink the last one.
*/
static int _coresight_build_path(struct coresight_device *csdev,
- struct list_head *path)
+ struct list_head *path, const char *sink)
{
int i;
bool found = false;
struct coresight_node *node;
- /* An activated sink has been found. Enqueue the element */
- if ((csdev->type == CORESIGHT_DEV_TYPE_SINK ||
- csdev->type == CORESIGHT_DEV_TYPE_LINKSINK) && csdev->activated)
- goto out;
+ /*
+ * First see if we are dealing with a sink. If we have one check if
+ * it was selected via sysFS or the perf cmd line.
+ */
+ if (csdev->type == CORESIGHT_DEV_TYPE_SINK ||
+ csdev->type == CORESIGHT_DEV_TYPE_LINKSINK) {
+ /* Activated via perf cmd line */
+ if (sink && !strcmp(dev_name(&csdev->dev), sink))
+ goto out;
+ /* Activated via sysFS */
+ if (csdev->activated)
+ goto out;
+ }
/* Not a sink - recursively explore each port found on this element */
for (i = 0; i < csdev->nr_outport; i++) {
struct coresight_device *child_dev = csdev->conns[i].child_dev;
- if (child_dev && _coresight_build_path(child_dev, path) == 0) {
+ if (child_dev &&
+ _coresight_build_path(child_dev, path, sink) == 0) {
found = true;
break;
}
@@ -422,7 +433,8 @@ out:
return 0;
}
-struct list_head *coresight_build_path(struct coresight_device *csdev)
+struct list_head *coresight_build_path(struct coresight_device *csdev,
+ const char *sink)
{
struct list_head *path;
int rc;
@@ -433,7 +445,7 @@ struct list_head *coresight_build_path(struct coresight_device *csdev)
INIT_LIST_HEAD(path);
- rc = _coresight_build_path(csdev, path);
+ rc = _coresight_build_path(csdev, path, sink);
if (rc) {
kfree(path);
return ERR_PTR(rc);
@@ -508,7 +520,7 @@ int coresight_enable(struct coresight_device *csdev)
if (csdev->enable)
goto out;
- path = coresight_build_path(csdev);
+ path = coresight_build_path(csdev, NULL);
if (IS_ERR(path)) {
pr_err("building path(s) failed\n");
ret = PTR_ERR(path);
--
2.7.4
[toc] | [prev] | [next] | [standalone]
| From | Suzuki K Poulose <Suzuki.Poulose@arm.com> |
|---|---|
| Date | 2016-07-21 12:50 +0200 |
| Subject | Re: [PATCH V2 5/6] coresight: adding sink parameter to function coresight_build_path() |
| Message-ID | <rXjIg-6iZ-75@gated-at.bofh.it> |
| In reply to | #1447455 |
On 20/07/16 21:38, Mathieu Poirier wrote:
> Up to now function coresight_build_path() was counting on a sink to
> have been selected (from sysFS) prior to being called. This patch
> adds a string argument so that a sink matching the argument can be
> selected.
>
> static int _coresight_build_path(struct coresight_device *csdev,
> - struct list_head *path)
> + struct list_head *path, const char *sink)
> {
> int i;
> bool found = false;
> struct coresight_node *node;
>
> - /* An activated sink has been found. Enqueue the element */
> - if ((csdev->type == CORESIGHT_DEV_TYPE_SINK ||
> - csdev->type == CORESIGHT_DEV_TYPE_LINKSINK) && csdev->activated)
> - goto out;
> + /*
> + * First see if we are dealing with a sink. If we have one check if
> + * it was selected via sysFS or the perf cmd line.
> + */
> + if (csdev->type == CORESIGHT_DEV_TYPE_SINK ||
> + csdev->type == CORESIGHT_DEV_TYPE_LINKSINK) {
> + /* Activated via perf cmd line */
> + if (sink && !strcmp(dev_name(&csdev->dev), sink))
> + goto out;
> + /* Activated via sysFS */
> + if (csdev->activated)
When a sink is specified, should we skip an activated sink and continue to
find the specified one ? or at least fail with an error as we may not be using
the sink specified by the user ?
i.e may be :
if (!sink && csdev->activated)
goto out;
Suzuki
[toc] | [prev] | [next] | [standalone]
| From | Mathieu Poirier <mathieu.poirier@linaro.org> |
|---|---|
| Date | 2016-07-21 17:10 +0200 |
| Subject | Re: [PATCH V2 5/6] coresight: adding sink parameter to function coresight_build_path() |
| Message-ID | <rXnLP-DS-5@gated-at.bofh.it> |
| In reply to | #1447790 |
On 21 July 2016 at 04:49, Suzuki K Poulose <Suzuki.Poulose@arm.com> wrote:
> On 20/07/16 21:38, Mathieu Poirier wrote:
>>
>> Up to now function coresight_build_path() was counting on a sink to
>> have been selected (from sysFS) prior to being called. This patch
>> adds a string argument so that a sink matching the argument can be
>> selected.
>>
>
>> static int _coresight_build_path(struct coresight_device *csdev,
>> - struct list_head *path)
>> + struct list_head *path, const char *sink)
>> {
>> int i;
>> bool found = false;
>> struct coresight_node *node;
>>
>> - /* An activated sink has been found. Enqueue the element */
>> - if ((csdev->type == CORESIGHT_DEV_TYPE_SINK ||
>> - csdev->type == CORESIGHT_DEV_TYPE_LINKSINK) &&
>> csdev->activated)
>> - goto out;
>> + /*
>> + * First see if we are dealing with a sink. If we have one check
>> if
>> + * it was selected via sysFS or the perf cmd line.
>> + */
>> + if (csdev->type == CORESIGHT_DEV_TYPE_SINK ||
>> + csdev->type == CORESIGHT_DEV_TYPE_LINKSINK) {
>> + /* Activated via perf cmd line */
>> + if (sink && !strcmp(dev_name(&csdev->dev), sink))
>> + goto out;
>> + /* Activated via sysFS */
>> + if (csdev->activated)
>
>
> When a sink is specified, should we skip an activated sink and continue to
> find the specified one ? or at least fail with an error as we may not be
> using
> the sink specified by the user ?
> i.e may be :
> if (!sink && csdev->activated)
> goto out;
I understand your point. My goal though is to discourage people from
meddling in sysFS when using CS from the perf interface. As such if
any code is to be added here, it would be to report an error when both
a sink has been specified from perf and activated from sysFS.
>
> Suzuki
[toc] | [prev] | [next] | [standalone]
| From | Mathieu Poirier <mathieu.poirier@linaro.org> |
|---|---|
| Date | 2016-07-20 22:40 +0200 |
| Subject | [PATCH V2 2/6] perf: Passing struct perf_event to function setup_aux() |
| Message-ID | <rX6rE-6b4-25@gated-at.bofh.it> |
| In reply to | #1447450 |
Some information, like driver specific configuration, is found
in the hw_perf_event structure. As such pass a 'struct perf_event'
to function setup_aux() rather than just the CPU number so that
individual drivers can make the right configuration when setting
up a session.
Signed-off-by: Mathieu Poirier <mathieu.poirier@linaro.org>
Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com>
---
arch/x86/events/intel/bts.c | 4 +++-
arch/x86/events/intel/pt.c | 5 +++--
drivers/hwtracing/coresight/coresight-etm-perf.c | 4 ++--
include/linux/perf_event.h | 2 +-
kernel/events/ring_buffer.c | 2 +-
5 files changed, 10 insertions(+), 7 deletions(-)
diff --git a/arch/x86/events/intel/bts.c b/arch/x86/events/intel/bts.c
index 0a6e393a2e62..98155c2dfcce 100644
--- a/arch/x86/events/intel/bts.c
+++ b/arch/x86/events/intel/bts.c
@@ -68,8 +68,10 @@ static size_t buf_size(struct page *page)
}
static void *
-bts_buffer_setup_aux(int cpu, void **pages, int nr_pages, bool overwrite)
+bts_buffer_setup_aux(struct perf_event *event, void **pages,
+ int nr_pages, bool overwrite)
{
+ int cpu = event->cpu;
struct bts_buffer *buf;
struct page *page;
int node = (cpu == -1) ? cpu : cpu_to_node(cpu);
diff --git a/arch/x86/events/intel/pt.c b/arch/x86/events/intel/pt.c
index 04bb5fb5a8d7..5178c5de0b19 100644
--- a/arch/x86/events/intel/pt.c
+++ b/arch/x86/events/intel/pt.c
@@ -1003,10 +1003,11 @@ static int pt_buffer_init_topa(struct pt_buffer *buf, unsigned long nr_pages,
* Return: Our private PT buffer structure.
*/
static void *
-pt_buffer_setup_aux(int cpu, void **pages, int nr_pages, bool snapshot)
+pt_buffer_setup_aux(struct perf_event *event, void **pages,
+ int nr_pages, bool snapshot)
{
struct pt_buffer *buf;
- int node, ret;
+ int node, ret, cpu = event->cpu;
if (!nr_pages)
return NULL;
diff --git a/drivers/hwtracing/coresight/coresight-etm-perf.c b/drivers/hwtracing/coresight/coresight-etm-perf.c
index 755125f7917f..f4174f36c5a0 100644
--- a/drivers/hwtracing/coresight/coresight-etm-perf.c
+++ b/drivers/hwtracing/coresight/coresight-etm-perf.c
@@ -155,7 +155,7 @@ static void etm_free_aux(void *data)
schedule_work(&event_data->work);
}
-static void *etm_setup_aux(int event_cpu, void **pages,
+static void *etm_setup_aux(struct perf_event *event, void **pages,
int nr_pages, bool overwrite)
{
int cpu;
@@ -163,7 +163,7 @@ static void *etm_setup_aux(int event_cpu, void **pages,
struct coresight_device *sink;
struct etm_event_data *event_data = NULL;
- event_data = alloc_event_data(event_cpu);
+ event_data = alloc_event_data(event->cpu);
if (!event_data)
return NULL;
diff --git a/include/linux/perf_event.h b/include/linux/perf_event.h
index 59d61a12cf9d..5275b6594989 100644
--- a/include/linux/perf_event.h
+++ b/include/linux/perf_event.h
@@ -407,7 +407,7 @@ struct pmu {
/*
* Set up pmu-private data structures for an AUX area
*/
- void *(*setup_aux) (int cpu, void **pages,
+ void *(*setup_aux) (struct perf_event *event, void **pages,
int nr_pages, bool overwrite);
/* optional */
diff --git a/kernel/events/ring_buffer.c b/kernel/events/ring_buffer.c
index ae9b90dc9a5a..56aba90af437 100644
--- a/kernel/events/ring_buffer.c
+++ b/kernel/events/ring_buffer.c
@@ -616,7 +616,7 @@ int rb_alloc_aux(struct ring_buffer *rb, struct perf_event *event,
goto out;
}
- rb->aux_priv = event->pmu->setup_aux(event->cpu, rb->aux_pages, nr_pages,
+ rb->aux_priv = event->pmu->setup_aux(event, rb->aux_pages, nr_pages,
overwrite);
if (!rb->aux_priv)
goto out;
--
2.7.4
[toc] | [prev] | [next] | [standalone]
| From | Mathieu Poirier <mathieu.poirier@linaro.org> |
|---|---|
| Date | 2016-07-20 22:40 +0200 |
| Subject | [PATCH V2 4/6] perf tools: pushing driver configuration down to the kernel |
| Message-ID | <rX6rE-6b4-29@gated-at.bofh.it> |
| In reply to | #1447450 |
Now that PMU specific driver configuration are queued in
evsel::drv_config_terms, all we need to do is re-use the current
ioctl() mechanism to push down the information to the kernel
driver.
Signed-off-by: Mathieu Poirier <mathieu.poirier@linaro.org>
---
tools/perf/builtin-record.c | 9 +++++++++
tools/perf/util/evlist.c | 24 ++++++++++++++++++++++++
tools/perf/util/evlist.h | 3 +++
tools/perf/util/evsel.c | 32 ++++++++++++++++++++++++++++++++
tools/perf/util/evsel.h | 3 +++
5 files changed, 71 insertions(+)
diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c
index 8f2c16d9275f..dffea1033b8e 100644
--- a/tools/perf/builtin-record.c
+++ b/tools/perf/builtin-record.c
@@ -383,6 +383,7 @@ static int record__open(struct record *rec)
struct perf_evlist *evlist = rec->evlist;
struct perf_session *session = rec->session;
struct record_opts *opts = &rec->opts;
+ struct perf_evsel_config_term *err_term;
int rc = 0;
perf_evlist__config(evlist, opts, &callchain_param);
@@ -412,6 +413,14 @@ try_again:
goto out;
}
+ if (perf_evlist__apply_drv_configs(evlist, &pos, &err_term)) {
+ error("failed to set config \"%s\" on event %s with %d (%s)\n",
+ err_term->val.drv_cfg, perf_evsel__name(pos), errno,
+ strerror_r(errno, msg, sizeof(msg)));
+ rc = -1;
+ goto out;
+ }
+
rc = record__mmap(rec);
if (rc)
goto out;
diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c
index 2a40b8e1def7..0f485cebae18 100644
--- a/tools/perf/util/evlist.c
+++ b/tools/perf/util/evlist.c
@@ -1433,6 +1433,30 @@ int perf_evlist__apply_filters(struct perf_evlist *evlist, struct perf_evsel **e
return err;
}
+int perf_evlist__apply_drv_configs(struct perf_evlist *evlist,
+ struct perf_evsel **err_evsel,
+ struct perf_evsel_config_term **err_term)
+{
+ struct perf_evsel *evsel;
+ int err = 0;
+ const int ncpus = cpu_map__nr(evlist->cpus),
+ nthreads = thread_map__nr(evlist->threads);
+
+ evlist__for_each_entry(evlist, evsel) {
+ if (list_empty(&evsel->drv_config_terms))
+ continue;
+
+ err = perf_evsel__apply_drv_configs(evsel, ncpus,
+ nthreads, err_term);
+ if (err) {
+ *err_evsel = evsel;
+ break;
+ }
+ }
+
+ return err;
+}
+
int perf_evlist__set_filter(struct perf_evlist *evlist, const char *filter)
{
struct perf_evsel *evsel;
diff --git a/tools/perf/util/evlist.h b/tools/perf/util/evlist.h
index 4fd034f22d2f..bf7ed0be3f33 100644
--- a/tools/perf/util/evlist.h
+++ b/tools/perf/util/evlist.h
@@ -232,6 +232,9 @@ void perf_evlist__set_maps(struct perf_evlist *evlist, struct cpu_map *cpus,
struct thread_map *threads);
int perf_evlist__create_maps(struct perf_evlist *evlist, struct target *target);
int perf_evlist__apply_filters(struct perf_evlist *evlist, struct perf_evsel **err_evsel);
+int perf_evlist__apply_drv_configs(struct perf_evlist *evlist,
+ struct perf_evsel **err_evsel,
+ struct perf_evsel_config_term **term);
void __perf_evlist__set_leader(struct list_head *list);
void perf_evlist__set_leader(struct perf_evlist *evlist);
diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c
index b16f1621ce3e..e5b30d02a5dd 100644
--- a/tools/perf/util/evsel.c
+++ b/tools/perf/util/evsel.c
@@ -1035,6 +1035,27 @@ int perf_evsel__append_filter(struct perf_evsel *evsel,
return -1;
}
+int perf_evsel__apply_drv_configs(struct perf_evsel *evsel,
+ int ncpus, int nthreads,
+ struct perf_evsel_config_term **err_term)
+{
+ int err = 0;
+ struct perf_evsel_config_term *term;
+
+ list_for_each_entry(term, &evsel->drv_config_terms, list) {
+ err = perf_evsel__run_ioctl(evsel, ncpus, nthreads,
+ PERF_EVENT_IOC_SET_DRV_CONFIGS,
+ (void *)term->val.drv_cfg);
+
+ if (err) {
+ *err_term = term;
+ break;
+ }
+ }
+
+ return err;
+}
+
int perf_evsel__enable(struct perf_evsel *evsel)
{
int nthreads = thread_map__nr(evsel->threads);
@@ -1100,6 +1121,16 @@ static void perf_evsel__free_config_terms(struct perf_evsel *evsel)
}
}
+static void perf_evsel__free_drv_config_terms(struct perf_evsel *evsel)
+{
+ struct perf_evsel_config_term *term, *h;
+
+ list_for_each_entry_safe(term, h, &evsel->drv_config_terms, list) {
+ list_del(&term->list);
+ free(term);
+ }
+}
+
void perf_evsel__close_fd(struct perf_evsel *evsel, int ncpus, int nthreads)
{
int cpu, thread;
@@ -1121,6 +1152,7 @@ void perf_evsel__exit(struct perf_evsel *evsel)
perf_evsel__free_fd(evsel);
perf_evsel__free_id(evsel);
perf_evsel__free_config_terms(evsel);
+ perf_evsel__free_drv_config_terms(evsel);
close_cgroup(evsel->cgrp);
cpu_map__put(evsel->cpus);
cpu_map__put(evsel->own_cpus);
diff --git a/tools/perf/util/evsel.h b/tools/perf/util/evsel.h
index e25fd5e4c740..305b2e11992a 100644
--- a/tools/perf/util/evsel.h
+++ b/tools/perf/util/evsel.h
@@ -239,6 +239,9 @@ int perf_evsel__append_filter(struct perf_evsel *evsel,
const char *op, const char *filter);
int perf_evsel__apply_filter(struct perf_evsel *evsel, int ncpus, int nthreads,
const char *filter);
+int perf_evsel__apply_drv_configs(struct perf_evsel *evsel,
+ int ncpus, int nthreads,
+ struct perf_evsel_config_term **err_term);
int perf_evsel__enable(struct perf_evsel *evsel);
int perf_evsel__disable(struct perf_evsel *evsel);
--
2.7.4
[toc] | [prev] | [next] | [standalone]
| From | Jiri Olsa <jolsa@redhat.com> |
|---|---|
| Date | 2016-07-21 09:50 +0200 |
| Subject | Re: [PATCH V2 4/6] perf tools: pushing driver configuration down to the kernel |
| Message-ID | <rXgU1-4ur-1@gated-at.bofh.it> |
| In reply to | #1447459 |
On Wed, Jul 20, 2016 at 02:38:18PM -0600, Mathieu Poirier wrote:
> Now that PMU specific driver configuration are queued in
> evsel::drv_config_terms, all we need to do is re-use the current
> ioctl() mechanism to push down the information to the kernel
> driver.
>
> Signed-off-by: Mathieu Poirier <mathieu.poirier@linaro.org>
> ---
> tools/perf/builtin-record.c | 9 +++++++++
> tools/perf/util/evlist.c | 24 ++++++++++++++++++++++++
> tools/perf/util/evlist.h | 3 +++
> tools/perf/util/evsel.c | 32 ++++++++++++++++++++++++++++++++
> tools/perf/util/evsel.h | 3 +++
> 5 files changed, 71 insertions(+)
>
> diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c
> index 8f2c16d9275f..dffea1033b8e 100644
> --- a/tools/perf/builtin-record.c
> +++ b/tools/perf/builtin-record.c
> @@ -383,6 +383,7 @@ static int record__open(struct record *rec)
> struct perf_evlist *evlist = rec->evlist;
> struct perf_session *session = rec->session;
> struct record_opts *opts = &rec->opts;
> + struct perf_evsel_config_term *err_term;
> int rc = 0;
>
> perf_evlist__config(evlist, opts, &callchain_param);
> @@ -412,6 +413,14 @@ try_again:
> goto out;
> }
>
> + if (perf_evlist__apply_drv_configs(evlist, &pos, &err_term)) {
> + error("failed to set config \"%s\" on event %s with %d (%s)\n",
> + err_term->val.drv_cfg, perf_evsel__name(pos), errno,
> + strerror_r(errno, msg, sizeof(msg)));
> + rc = -1;
> + goto out;
> + }
> +
how about 'perf top' and 'perf stat', should they support this too?
thanks,
jirka
[toc] | [prev] | [next] | [standalone]
| From | Mathieu Poirier <mathieu.poirier@linaro.org> |
|---|---|
| Date | 2016-07-22 22:00 +0200 |
| Subject | Re: [PATCH V2 4/6] perf tools: pushing driver configuration down to the kernel |
| Message-ID | <rXOM2-1Io-15@gated-at.bofh.it> |
| In reply to | #1447676 |
On 21 July 2016 at 01:47, Jiri Olsa <jolsa@redhat.com> wrote:
> On Wed, Jul 20, 2016 at 02:38:18PM -0600, Mathieu Poirier wrote:
>> Now that PMU specific driver configuration are queued in
>> evsel::drv_config_terms, all we need to do is re-use the current
>> ioctl() mechanism to push down the information to the kernel
>> driver.
>>
>> Signed-off-by: Mathieu Poirier <mathieu.poirier@linaro.org>
>> ---
>> tools/perf/builtin-record.c | 9 +++++++++
>> tools/perf/util/evlist.c | 24 ++++++++++++++++++++++++
>> tools/perf/util/evlist.h | 3 +++
>> tools/perf/util/evsel.c | 32 ++++++++++++++++++++++++++++++++
>> tools/perf/util/evsel.h | 3 +++
>> 5 files changed, 71 insertions(+)
>>
>> diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c
>> index 8f2c16d9275f..dffea1033b8e 100644
>> --- a/tools/perf/builtin-record.c
>> +++ b/tools/perf/builtin-record.c
>> @@ -383,6 +383,7 @@ static int record__open(struct record *rec)
>> struct perf_evlist *evlist = rec->evlist;
>> struct perf_session *session = rec->session;
>> struct record_opts *opts = &rec->opts;
>> + struct perf_evsel_config_term *err_term;
>> int rc = 0;
>>
>> perf_evlist__config(evlist, opts, &callchain_param);
>> @@ -412,6 +413,14 @@ try_again:
>> goto out;
>> }
>>
>> + if (perf_evlist__apply_drv_configs(evlist, &pos, &err_term)) {
>> + error("failed to set config \"%s\" on event %s with %d (%s)\n",
>> + err_term->val.drv_cfg, perf_evsel__name(pos), errno,
>> + strerror_r(errno, msg, sizeof(msg)));
>> + rc = -1;
>> + goto out;
>> + }
>> +
>
> how about 'perf top' and 'perf stat', should they support this too?
After looking into this (hence the delayed reply) I'm not completely sure.
'perf stat' calls perf_evlist__apply_filters() and therefore the
semantic is likely to be close enough for PMU driver specific
configuration to make sense, should a particular use case lends itself
to it. But that is certainly not the case for CoreSight PMUs. Since
there is no current client for it, do you wish to see 'perf stat'
support this feature?
From a quick glance at the code, filters in the context of 'perf top'
seem to be related to symbols rather than the tuning of events. As
such I just can't see how driver specific configuration would fit in
that scheme.
Regards,
Mathieu
>
> thanks,
> jirka
[toc] | [prev] | [standalone]
Back to top | Article view | linux.kernel
csiph-web