All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH] perf tools: unbreak perf record for arm/arm64
@ 2017-10-06 18:38 Mark Rutland
  2017-10-09  9:38 ` Jiri Olsa
                   ` (2 more replies)
  0 siblings, 3 replies; 7+ messages in thread
From: Mark Rutland @ 2017-10-06 18:38 UTC (permalink / raw)
  To: linux-kernel, jolsa, acme
  Cc: Mark Rutland, stable, Adrian Hunter, Borislav Petkov,
	David Ahern, Namhyung Kim, Peter Zijlstra, Will Deacon

Currently, perf record is broken on arm/arm64 systems when the PMU is
specified explicitly as part of the event, e.g.

$ ./perf record -e armv8_cortex_a53/cpu_cycles/u true

In such cases, perf record fails to open events unless
perf_event_paranoid is set to -1, even if the PMU in question supports
mode exclusion. Further, even when perf_event_paranoid is toggled, no
samples are recorded.

This is an unintended side effect of commit:

  e3ba76deef23064f ("perf tools: Force uncore events to system wide monitoring)

... which assumes that if a PMU has an associated cpu_map, it is an
uncore PMU, and forces events for such PMUs to be system-wide.

This is not true for arm/arm64 systems, which can have heterogeneous
CPUs. To account for this, multiple CPU PMUs are exposed, each with a
"cpus" field under sysfs, which the perf tool parses into a cpu_map. ARM
PMUs do not have a "cpumask" file, and only have a "cpus" file. For the
gory details as to why, see commit:

 7e3fcffe95544010 ("perf pmu: Support alternative sysfs cpumask")

Given all of this, we can instead identify uncore PMUs by explicitly
checking for a "cpumask" file, and restore arm/arm64 PMU support back to
a working state. This patch does so, adding a new perf_pmu::is_uncore
field, and splitting the existing cpumask parsing so that it can be
reused.

Signed-off-by: Mark Rutland <mark.rutland@arm.com>
Fixes: e3ba76deef23064f ("perf tools: Force uncore events to system wide monitoring)
Cc: stable@vger.kernel.org
Cc: Adrian Hunter <adrian.hunter@intel.com>
Cc: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: Borislav Petkov <bp@alien8.de>
Cc: David Ahern <dsahern@gmail.com>
Cc: Jiri Olsa <jolsa@kernel.org>
Cc: Jiri Olsa <jolsa@kernel.org>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Will Deacon <will.deacon@arm.com>
---
 tools/perf/util/parse-events.c |  9 ++++---
 tools/perf/util/pmu.c          | 56 +++++++++++++++++++++++++++++++-----------
 tools/perf/util/pmu.h          |  1 +
 3 files changed, 47 insertions(+), 19 deletions(-)

diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c
index f6257fb..39b1596 100644
--- a/tools/perf/util/parse-events.c
+++ b/tools/perf/util/parse-events.c
@@ -309,10 +309,11 @@ static char *get_config_name(struct list_head *head_terms)
 static struct perf_evsel *
 __add_event(struct list_head *list, int *idx,
 	    struct perf_event_attr *attr,
-	    char *name, struct cpu_map *cpus,
+	    char *name, struct perf_pmu *pmu,
 	    struct list_head *config_terms, bool auto_merge_stats)
 {
 	struct perf_evsel *evsel;
+	struct cpu_map *cpus = pmu ? pmu->cpus : NULL;
 
 	event_attr_init(attr);
 
@@ -323,7 +324,7 @@ static char *get_config_name(struct list_head *head_terms)
 	(*idx)++;
 	evsel->cpus        = cpu_map__get(cpus);
 	evsel->own_cpus    = cpu_map__get(cpus);
-	evsel->system_wide = !!cpus;
+	evsel->system_wide = pmu ? pmu->is_uncore : false;
 	evsel->auto_merge_stats = auto_merge_stats;
 
 	if (name)
@@ -1233,7 +1234,7 @@ static int __parse_events_add_pmu(struct parse_events_state *parse_state,
 
 	if (!head_config) {
 		attr.type = pmu->type;
-		evsel = __add_event(list, &parse_state->idx, &attr, NULL, pmu->cpus, NULL, auto_merge_stats);
+		evsel = __add_event(list, &parse_state->idx, &attr, NULL, pmu, NULL, auto_merge_stats);
 		return evsel ? 0 : -ENOMEM;
 	}
 
@@ -1254,7 +1255,7 @@ static int __parse_events_add_pmu(struct parse_events_state *parse_state,
 		return -EINVAL;
 
 	evsel = __add_event(list, &parse_state->idx, &attr,
-			    get_config_name(head_config), pmu->cpus,
+			    get_config_name(head_config), pmu,
 			    &config_terms, auto_merge_stats);
 	if (evsel) {
 		evsel->unit = info.unit;
diff --git a/tools/perf/util/pmu.c b/tools/perf/util/pmu.c
index ac16a9d..1c4d7b4 100644
--- a/tools/perf/util/pmu.c
+++ b/tools/perf/util/pmu.c
@@ -470,17 +470,36 @@ static void pmu_read_sysfs(void)
 	closedir(dir);
 }
 
+static struct cpu_map *__pmu_cpumask(const char *path)
+{
+	FILE *file;
+	struct cpu_map *cpus;
+
+	file = fopen(path, "r");
+	if (!file)
+		return NULL;
+
+	cpus = cpu_map__read(file);
+	fclose(file);
+	return cpus;
+}
+
+/*
+ * Uncore PMUs have a "cpumask" file under sysfs. CPU PMUs (e.g. on arm/arm64)
+ * may have a "cpus" file.
+ */
+#define CPUS_TEMPLATE_UNCORE	"%s/bus/event_source/devices/%s/cpumask"
+#define CPUS_TEMPLATE_CPU	"%s/bus/event_source/devices/%s/cpus"
+
 static struct cpu_map *pmu_cpumask(const char *name)
 {
-	struct stat st;
 	char path[PATH_MAX];
-	FILE *file;
 	struct cpu_map *cpus;
 	const char *sysfs = sysfs__mountpoint();
 	const char *templates[] = {
-		 "%s/bus/event_source/devices/%s/cpumask",
-		 "%s/bus/event_source/devices/%s/cpus",
-		 NULL
+		CPUS_TEMPLATE_UNCORE,
+		CPUS_TEMPLATE_CPU,
+		NULL
 	};
 	const char **template;
 
@@ -489,20 +508,25 @@ static struct cpu_map *pmu_cpumask(const char *name)
 
 	for (template = templates; *template; template++) {
 		snprintf(path, PATH_MAX, *template, sysfs, name);
-		if (stat(path, &st) == 0)
-			break;
+		cpus = __pmu_cpumask(path);
+		if (cpus)
+			return cpus;
 	}
 
-	if (!*template)
-		return NULL;
+	return NULL;
+}
 
-	file = fopen(path, "r");
-	if (!file)
-		return NULL;
+static bool pmu_is_uncore(const char *name)
+{
+	char path[PATH_MAX];
+	struct cpu_map *cpus;
+	const char *sysfs = sysfs__mountpoint();
 
-	cpus = cpu_map__read(file);
-	fclose(file);
-	return cpus;
+	snprintf(path, PATH_MAX, CPUS_TEMPLATE_UNCORE, sysfs, name);
+	cpus = __pmu_cpumask(path);
+	cpu_map__put(cpus);
+
+	return !!cpus;
 }
 
 /*
@@ -617,6 +641,8 @@ static struct perf_pmu *pmu_lookup(const char *name)
 
 	pmu->cpus = pmu_cpumask(name);
 
+	pmu->is_uncore = pmu_is_uncore(name);
+
 	INIT_LIST_HEAD(&pmu->format);
 	INIT_LIST_HEAD(&pmu->aliases);
 	list_splice(&format, &pmu->format);
diff --git a/tools/perf/util/pmu.h b/tools/perf/util/pmu.h
index 389e972..fe0de05 100644
--- a/tools/perf/util/pmu.h
+++ b/tools/perf/util/pmu.h
@@ -22,6 +22,7 @@ struct perf_pmu {
 	char *name;
 	__u32 type;
 	bool selectable;
+	bool is_uncore;
 	struct perf_event_attr *default_config;
 	struct cpu_map *cpus;
 	struct list_head format;  /* HEAD struct perf_pmu_format -> list */
-- 
1.9.1

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

* Re: [PATCH] perf tools: unbreak perf record for arm/arm64
  2017-10-06 18:38 [PATCH] perf tools: unbreak perf record for arm/arm64 Mark Rutland
@ 2017-10-09  9:38 ` Jiri Olsa
  2017-10-09 10:22 ` Will Deacon
  2017-10-10 17:28 ` [tip:perf/urgent] perf pmu: Unbreak perf record for arm/arm64 with events with explicit PMU tip-bot for Mark Rutland
  2 siblings, 0 replies; 7+ messages in thread
From: Jiri Olsa @ 2017-10-09  9:38 UTC (permalink / raw)
  To: Mark Rutland
  Cc: linux-kernel, jolsa, acme, stable, Adrian Hunter,
	Borislav Petkov, David Ahern, Namhyung Kim, Peter Zijlstra,
	Will Deacon

On Fri, Oct 06, 2017 at 07:38:22PM +0100, Mark Rutland wrote:
> Currently, perf record is broken on arm/arm64 systems when the PMU is
> specified explicitly as part of the event, e.g.
> 
> $ ./perf record -e armv8_cortex_a53/cpu_cycles/u true
> 
> In such cases, perf record fails to open events unless
> perf_event_paranoid is set to -1, even if the PMU in question supports
> mode exclusion. Further, even when perf_event_paranoid is toggled, no
> samples are recorded.
> 
> This is an unintended side effect of commit:
> 
>   e3ba76deef23064f ("perf tools: Force uncore events to system wide monitoring)
> 
> ... which assumes that if a PMU has an associated cpu_map, it is an
> uncore PMU, and forces events for such PMUs to be system-wide.
> 
> This is not true for arm/arm64 systems, which can have heterogeneous
> CPUs. To account for this, multiple CPU PMUs are exposed, each with a
> "cpus" field under sysfs, which the perf tool parses into a cpu_map. ARM
> PMUs do not have a "cpumask" file, and only have a "cpus" file. For the
> gory details as to why, see commit:
> 
>  7e3fcffe95544010 ("perf pmu: Support alternative sysfs cpumask")
> 
> Given all of this, we can instead identify uncore PMUs by explicitly
> checking for a "cpumask" file, and restore arm/arm64 PMU support back to
> a working state. This patch does so, adding a new perf_pmu::is_uncore
> field, and splitting the existing cpumask parsing so that it can be
> reused.
> 
> Signed-off-by: Mark Rutland <mark.rutland@arm.com>
> Fixes: e3ba76deef23064f ("perf tools: Force uncore events to system wide monitoring)

Acked-by: Jiri Olsa <jolsa@kernel.org>

thanks,
jirka

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

* Re: [PATCH] perf tools: unbreak perf record for arm/arm64
  2017-10-06 18:38 [PATCH] perf tools: unbreak perf record for arm/arm64 Mark Rutland
  2017-10-09  9:38 ` Jiri Olsa
@ 2017-10-09 10:22 ` Will Deacon
  2017-10-09 10:51   ` Mark Rutland
  2017-10-09 19:00   ` Arnaldo Carvalho de Melo
  2017-10-10 17:28 ` [tip:perf/urgent] perf pmu: Unbreak perf record for arm/arm64 with events with explicit PMU tip-bot for Mark Rutland
  2 siblings, 2 replies; 7+ messages in thread
From: Will Deacon @ 2017-10-09 10:22 UTC (permalink / raw)
  To: Mark Rutland
  Cc: linux-kernel, jolsa, acme, stable, Adrian Hunter,
	Borislav Petkov, David Ahern, Namhyung Kim, Peter Zijlstra

On Fri, Oct 06, 2017 at 07:38:22PM +0100, Mark Rutland wrote:
> Currently, perf record is broken on arm/arm64 systems when the PMU is
> specified explicitly as part of the event, e.g.
> 
> $ ./perf record -e armv8_cortex_a53/cpu_cycles/u true
> 
> In such cases, perf record fails to open events unless
> perf_event_paranoid is set to -1, even if the PMU in question supports
> mode exclusion. Further, even when perf_event_paranoid is toggled, no
> samples are recorded.
> 
> This is an unintended side effect of commit:
> 
>   e3ba76deef23064f ("perf tools: Force uncore events to system wide monitoring)
> 
> ... which assumes that if a PMU has an associated cpu_map, it is an
> uncore PMU, and forces events for such PMUs to be system-wide.
> 
> This is not true for arm/arm64 systems, which can have heterogeneous
> CPUs. To account for this, multiple CPU PMUs are exposed, each with a
> "cpus" field under sysfs, which the perf tool parses into a cpu_map. ARM
> PMUs do not have a "cpumask" file, and only have a "cpus" file. For the
> gory details as to why, see commit:
> 
>  7e3fcffe95544010 ("perf pmu: Support alternative sysfs cpumask")
> 
> Given all of this, we can instead identify uncore PMUs by explicitly
> checking for a "cpumask" file, and restore arm/arm64 PMU support back to
> a working state. This patch does so, adding a new perf_pmu::is_uncore
> field, and splitting the existing cpumask parsing so that it can be
> reused.
> 
> Signed-off-by: Mark Rutland <mark.rutland@arm.com>
> Fixes: e3ba76deef23064f ("perf tools: Force uncore events to system wide monitoring)

It sucks that we haven't noticed this being broken for so long, but I can
confirm that this fixes the issue:

Acked-by: Will Deacon <will.deacon@arm.com>
Tested-by Will Deacon <will.deacon@arm.com>

Any chance we can get this into 4.14? You'll probably need to do some stable
backports too, since this is a bit spread out.

Will

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

* Re: [PATCH] perf tools: unbreak perf record for arm/arm64
  2017-10-09 10:22 ` Will Deacon
@ 2017-10-09 10:51   ` Mark Rutland
  2017-10-09 19:00   ` Arnaldo Carvalho de Melo
  1 sibling, 0 replies; 7+ messages in thread
From: Mark Rutland @ 2017-10-09 10:51 UTC (permalink / raw)
  To: Will Deacon
  Cc: linux-kernel, jolsa, acme, stable, Adrian Hunter,
	Borislav Petkov, David Ahern, Namhyung Kim, Peter Zijlstra

On Mon, Oct 09, 2017 at 11:22:00AM +0100, Will Deacon wrote:
> It sucks that we haven't noticed this being broken for so long, but I can
> confirm that this fixes the issue:
> 
> Acked-by: Will Deacon <will.deacon@arm.com>
> Tested-by Will Deacon <will.deacon@arm.com>

Cheers.

> Any chance we can get this into 4.14? You'll probably need to do some
> stable backports too, since this is a bit spread out.

FWIW, I'm happy to do the backport(s) to stable.

As long as the Fixes tag and stable Cc are kept, I should get pinged by
the stable maintainers if/when the patch fails to apply.

Thanks,
Mark.

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

* Re: [PATCH] perf tools: unbreak perf record for arm/arm64
  2017-10-09 10:22 ` Will Deacon
  2017-10-09 10:51   ` Mark Rutland
@ 2017-10-09 19:00   ` Arnaldo Carvalho de Melo
  2017-10-09 19:02     ` Will Deacon
  1 sibling, 1 reply; 7+ messages in thread
From: Arnaldo Carvalho de Melo @ 2017-10-09 19:00 UTC (permalink / raw)
  To: Will Deacon
  Cc: Mark Rutland, linux-kernel, jolsa, stable, Adrian Hunter,
	Borislav Petkov, David Ahern, Namhyung Kim, Peter Zijlstra

Em Mon, Oct 09, 2017 at 11:22:00AM +0100, Will Deacon escreveu:
> On Fri, Oct 06, 2017 at 07:38:22PM +0100, Mark Rutland wrote:
> > Currently, perf record is broken on arm/arm64 systems when the PMU is
> > specified explicitly as part of the event, e.g.
> > 
> > $ ./perf record -e armv8_cortex_a53/cpu_cycles/u true
> > 
> > In such cases, perf record fails to open events unless
> > perf_event_paranoid is set to -1, even if the PMU in question supports
> > mode exclusion. Further, even when perf_event_paranoid is toggled, no
> > samples are recorded.
> > 
> > This is an unintended side effect of commit:
> > 
> >   e3ba76deef23064f ("perf tools: Force uncore events to system wide monitoring)
> > 
> > ... which assumes that if a PMU has an associated cpu_map, it is an
> > uncore PMU, and forces events for such PMUs to be system-wide.
> > 
> > This is not true for arm/arm64 systems, which can have heterogeneous
> > CPUs. To account for this, multiple CPU PMUs are exposed, each with a
> > "cpus" field under sysfs, which the perf tool parses into a cpu_map. ARM
> > PMUs do not have a "cpumask" file, and only have a "cpus" file. For the
> > gory details as to why, see commit:
> > 
> >  7e3fcffe95544010 ("perf pmu: Support alternative sysfs cpumask")
> > 
> > Given all of this, we can instead identify uncore PMUs by explicitly
> > checking for a "cpumask" file, and restore arm/arm64 PMU support back to
> > a working state. This patch does so, adding a new perf_pmu::is_uncore
> > field, and splitting the existing cpumask parsing so that it can be
> > reused.
> > 
> > Signed-off-by: Mark Rutland <mark.rutland@arm.com>
> > Fixes: e3ba76deef23064f ("perf tools: Force uncore events to system wide monitoring)
> 
> It sucks that we haven't noticed this being broken for so long, but I can
> confirm that this fixes the issue:
> 
> Acked-by: Will Deacon <will.deacon@arm.com>
> Tested-by Will Deacon <will.deacon@arm.com>
> 
> Any chance we can get this into 4.14? You'll probably need to do some stable
> backports too, since this is a bit spread out.

Sure, I've added this to my perf/urgent branch, that, together with a
few other fixes is undergoing testing now.

- Arnaldo

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

* Re: [PATCH] perf tools: unbreak perf record for arm/arm64
  2017-10-09 19:00   ` Arnaldo Carvalho de Melo
@ 2017-10-09 19:02     ` Will Deacon
  0 siblings, 0 replies; 7+ messages in thread
From: Will Deacon @ 2017-10-09 19:02 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: Mark Rutland, linux-kernel, jolsa, stable, Adrian Hunter,
	Borislav Petkov, David Ahern, Namhyung Kim, Peter Zijlstra

On Mon, Oct 09, 2017 at 04:00:00PM -0300, Arnaldo Carvalho de Melo wrote:
> Em Mon, Oct 09, 2017 at 11:22:00AM +0100, Will Deacon escreveu:
> > On Fri, Oct 06, 2017 at 07:38:22PM +0100, Mark Rutland wrote:
> > > Currently, perf record is broken on arm/arm64 systems when the PMU is
> > > specified explicitly as part of the event, e.g.
> > > 
> > > $ ./perf record -e armv8_cortex_a53/cpu_cycles/u true
> > > 
> > > In such cases, perf record fails to open events unless
> > > perf_event_paranoid is set to -1, even if the PMU in question supports
> > > mode exclusion. Further, even when perf_event_paranoid is toggled, no
> > > samples are recorded.
> > > 
> > > This is an unintended side effect of commit:
> > > 
> > >   e3ba76deef23064f ("perf tools: Force uncore events to system wide monitoring)
> > > 
> > > ... which assumes that if a PMU has an associated cpu_map, it is an
> > > uncore PMU, and forces events for such PMUs to be system-wide.
> > > 
> > > This is not true for arm/arm64 systems, which can have heterogeneous
> > > CPUs. To account for this, multiple CPU PMUs are exposed, each with a
> > > "cpus" field under sysfs, which the perf tool parses into a cpu_map. ARM
> > > PMUs do not have a "cpumask" file, and only have a "cpus" file. For the
> > > gory details as to why, see commit:
> > > 
> > >  7e3fcffe95544010 ("perf pmu: Support alternative sysfs cpumask")
> > > 
> > > Given all of this, we can instead identify uncore PMUs by explicitly
> > > checking for a "cpumask" file, and restore arm/arm64 PMU support back to
> > > a working state. This patch does so, adding a new perf_pmu::is_uncore
> > > field, and splitting the existing cpumask parsing so that it can be
> > > reused.
> > > 
> > > Signed-off-by: Mark Rutland <mark.rutland@arm.com>
> > > Fixes: e3ba76deef23064f ("perf tools: Force uncore events to system wide monitoring)
> > 
> > It sucks that we haven't noticed this being broken for so long, but I can
> > confirm that this fixes the issue:
> > 
> > Acked-by: Will Deacon <will.deacon@arm.com>
> > Tested-by Will Deacon <will.deacon@arm.com>
> > 
> > Any chance we can get this into 4.14? You'll probably need to do some stable
> > backports too, since this is a bit spread out.
> 
> Sure, I've added this to my perf/urgent branch, that, together with a
> few other fixes is undergoing testing now.

Thanks, Arnaldo.

Will

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

* [tip:perf/urgent] perf pmu: Unbreak perf record for arm/arm64 with events with explicit PMU
  2017-10-06 18:38 [PATCH] perf tools: unbreak perf record for arm/arm64 Mark Rutland
  2017-10-09  9:38 ` Jiri Olsa
  2017-10-09 10:22 ` Will Deacon
@ 2017-10-10 17:28 ` tip-bot for Mark Rutland
  2 siblings, 0 replies; 7+ messages in thread
From: tip-bot for Mark Rutland @ 2017-10-10 17:28 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: jolsa, adrian.hunter, stable, mingo, hpa, acme, tglx, bp,
	dsahern, mark.rutland, namhyung, linux-kernel, peterz

Commit-ID:  66ec11919a0f96e936bb731fdbc2851316077d26
Gitweb:     https://git.kernel.org/tip/66ec11919a0f96e936bb731fdbc2851316077d26
Author:     Mark Rutland <mark.rutland@arm.com>
AuthorDate: Fri, 6 Oct 2017 19:38:22 +0100
Committer:  Arnaldo Carvalho de Melo <acme@redhat.com>
CommitDate: Mon, 9 Oct 2017 15:48:46 -0300

perf pmu: Unbreak perf record for arm/arm64 with events with explicit PMU

Currently, perf record is broken on arm/arm64 systems when the PMU is
specified explicitly as part of the event, e.g.

$ ./perf record -e armv8_cortex_a53/cpu_cycles/u true

In such cases, perf record fails to open events unless
perf_event_paranoid is set to -1, even if the PMU in question supports
mode exclusion. Further, even when perf_event_paranoid is toggled, no
samples are recorded.

This is an unintended side effect of commit:

  e3ba76deef23064f ("perf tools: Force uncore events to system wide monitoring)

... which assumes that if a PMU has an associated cpu_map, it is an
uncore PMU, and forces events for such PMUs to be system-wide.

This is not true for arm/arm64 systems, which can have heterogeneous
CPUs. To account for this, multiple CPU PMUs are exposed, each with a
"cpus" field under sysfs, which the perf tool parses into a cpu_map. ARM
PMUs do not have a "cpumask" file, and only have a "cpus" file. For the
gory details as to why, see commit:

 7e3fcffe95544010 ("perf pmu: Support alternative sysfs cpumask")

Given all of this, we can instead identify uncore PMUs by explicitly
checking for a "cpumask" file, and restore arm/arm64 PMU support back to
a working state. This patch does so, adding a new perf_pmu::is_uncore
field, and splitting the existing cpumask parsing so that it can be
reused.

Signed-off-by: Mark Rutland <mark.rutland@arm.com>
Tested-by Will Deacon <will.deacon@arm.com>
Acked-by: Jiri Olsa <jolsa@kernel.org>
Cc: Adrian Hunter <adrian.hunter@intel.com>
Cc: Borislav Petkov <bp@alien8.de>
Cc: David Ahern <dsahern@gmail.com>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: 4.12+ <stable@vger.kernel.org>
Fixes: e3ba76deef23064f ("perf tools: Force uncore events to system wide monitoring)
Link: http://lkml.kernel.org/r/1507315102-5942-1-git-send-email-mark.rutland@arm.com
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
 tools/perf/util/parse-events.c |  9 ++++---
 tools/perf/util/pmu.c          | 56 +++++++++++++++++++++++++++++++-----------
 tools/perf/util/pmu.h          |  1 +
 3 files changed, 47 insertions(+), 19 deletions(-)

diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c
index f6257fb..39b1596 100644
--- a/tools/perf/util/parse-events.c
+++ b/tools/perf/util/parse-events.c
@@ -309,10 +309,11 @@ static char *get_config_name(struct list_head *head_terms)
 static struct perf_evsel *
 __add_event(struct list_head *list, int *idx,
 	    struct perf_event_attr *attr,
-	    char *name, struct cpu_map *cpus,
+	    char *name, struct perf_pmu *pmu,
 	    struct list_head *config_terms, bool auto_merge_stats)
 {
 	struct perf_evsel *evsel;
+	struct cpu_map *cpus = pmu ? pmu->cpus : NULL;
 
 	event_attr_init(attr);
 
@@ -323,7 +324,7 @@ __add_event(struct list_head *list, int *idx,
 	(*idx)++;
 	evsel->cpus        = cpu_map__get(cpus);
 	evsel->own_cpus    = cpu_map__get(cpus);
-	evsel->system_wide = !!cpus;
+	evsel->system_wide = pmu ? pmu->is_uncore : false;
 	evsel->auto_merge_stats = auto_merge_stats;
 
 	if (name)
@@ -1233,7 +1234,7 @@ static int __parse_events_add_pmu(struct parse_events_state *parse_state,
 
 	if (!head_config) {
 		attr.type = pmu->type;
-		evsel = __add_event(list, &parse_state->idx, &attr, NULL, pmu->cpus, NULL, auto_merge_stats);
+		evsel = __add_event(list, &parse_state->idx, &attr, NULL, pmu, NULL, auto_merge_stats);
 		return evsel ? 0 : -ENOMEM;
 	}
 
@@ -1254,7 +1255,7 @@ static int __parse_events_add_pmu(struct parse_events_state *parse_state,
 		return -EINVAL;
 
 	evsel = __add_event(list, &parse_state->idx, &attr,
-			    get_config_name(head_config), pmu->cpus,
+			    get_config_name(head_config), pmu,
 			    &config_terms, auto_merge_stats);
 	if (evsel) {
 		evsel->unit = info.unit;
diff --git a/tools/perf/util/pmu.c b/tools/perf/util/pmu.c
index ac16a9d..1c4d7b4 100644
--- a/tools/perf/util/pmu.c
+++ b/tools/perf/util/pmu.c
@@ -470,17 +470,36 @@ static void pmu_read_sysfs(void)
 	closedir(dir);
 }
 
+static struct cpu_map *__pmu_cpumask(const char *path)
+{
+	FILE *file;
+	struct cpu_map *cpus;
+
+	file = fopen(path, "r");
+	if (!file)
+		return NULL;
+
+	cpus = cpu_map__read(file);
+	fclose(file);
+	return cpus;
+}
+
+/*
+ * Uncore PMUs have a "cpumask" file under sysfs. CPU PMUs (e.g. on arm/arm64)
+ * may have a "cpus" file.
+ */
+#define CPUS_TEMPLATE_UNCORE	"%s/bus/event_source/devices/%s/cpumask"
+#define CPUS_TEMPLATE_CPU	"%s/bus/event_source/devices/%s/cpus"
+
 static struct cpu_map *pmu_cpumask(const char *name)
 {
-	struct stat st;
 	char path[PATH_MAX];
-	FILE *file;
 	struct cpu_map *cpus;
 	const char *sysfs = sysfs__mountpoint();
 	const char *templates[] = {
-		 "%s/bus/event_source/devices/%s/cpumask",
-		 "%s/bus/event_source/devices/%s/cpus",
-		 NULL
+		CPUS_TEMPLATE_UNCORE,
+		CPUS_TEMPLATE_CPU,
+		NULL
 	};
 	const char **template;
 
@@ -489,20 +508,25 @@ static struct cpu_map *pmu_cpumask(const char *name)
 
 	for (template = templates; *template; template++) {
 		snprintf(path, PATH_MAX, *template, sysfs, name);
-		if (stat(path, &st) == 0)
-			break;
+		cpus = __pmu_cpumask(path);
+		if (cpus)
+			return cpus;
 	}
 
-	if (!*template)
-		return NULL;
+	return NULL;
+}
 
-	file = fopen(path, "r");
-	if (!file)
-		return NULL;
+static bool pmu_is_uncore(const char *name)
+{
+	char path[PATH_MAX];
+	struct cpu_map *cpus;
+	const char *sysfs = sysfs__mountpoint();
 
-	cpus = cpu_map__read(file);
-	fclose(file);
-	return cpus;
+	snprintf(path, PATH_MAX, CPUS_TEMPLATE_UNCORE, sysfs, name);
+	cpus = __pmu_cpumask(path);
+	cpu_map__put(cpus);
+
+	return !!cpus;
 }
 
 /*
@@ -617,6 +641,8 @@ static struct perf_pmu *pmu_lookup(const char *name)
 
 	pmu->cpus = pmu_cpumask(name);
 
+	pmu->is_uncore = pmu_is_uncore(name);
+
 	INIT_LIST_HEAD(&pmu->format);
 	INIT_LIST_HEAD(&pmu->aliases);
 	list_splice(&format, &pmu->format);
diff --git a/tools/perf/util/pmu.h b/tools/perf/util/pmu.h
index 389e972..fe0de05 100644
--- a/tools/perf/util/pmu.h
+++ b/tools/perf/util/pmu.h
@@ -22,6 +22,7 @@ struct perf_pmu {
 	char *name;
 	__u32 type;
 	bool selectable;
+	bool is_uncore;
 	struct perf_event_attr *default_config;
 	struct cpu_map *cpus;
 	struct list_head format;  /* HEAD struct perf_pmu_format -> list */

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

end of thread, other threads:[~2017-10-10 17:33 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-10-06 18:38 [PATCH] perf tools: unbreak perf record for arm/arm64 Mark Rutland
2017-10-09  9:38 ` Jiri Olsa
2017-10-09 10:22 ` Will Deacon
2017-10-09 10:51   ` Mark Rutland
2017-10-09 19:00   ` Arnaldo Carvalho de Melo
2017-10-09 19:02     ` Will Deacon
2017-10-10 17:28 ` [tip:perf/urgent] perf pmu: Unbreak perf record for arm/arm64 with events with explicit PMU tip-bot for Mark Rutland

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.