linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Sukadev Bhattiprolu <sukadev@linux.vnet.ibm.com>
To: mingo@redhat.com, ak@linux.intel.com,
	Michael Ellerman <mpe@ellerman.id.au>,
	Jiri Olsa <jolsa@redhat.com>,
	Arnaldo Carvalho de Melo <acme@kernel.org>,
	Paul Mackerras <paulus@samba.org>
Cc: linuxppc-dev@lists.ozlabs.org, <linux-kernel@vger.kernel.org>
Subject: [RFC][PATCH 4/4] perf: Create aliases for PMU events
Date: Fri,  1 May 2015 00:05:41 -0700	[thread overview]
Message-ID: <1430463941-26109-5-git-send-email-sukadev@linux.vnet.ibm.com> (raw)
In-Reply-To: <1430463941-26109-1-git-send-email-sukadev@linux.vnet.ibm.com>

Using the tables of Power7 and Power8 events, create aliases for the
Power PMU events. This would allow us to specify all Power events by
name rather than by raw code:

	$ /tmp/perf stat -e PM_1PLUS_PPC_CMPL sleep 1

	 Performance counter stats for 'sleep 1':

		   757,661      PM_1PLUS_PPC_CMPL

	       1.001620145 seconds time elapsed

The perf binary built on Power8 can be copied to Power7 and it will use
the Power7 events (if arch/powerpc/util/pmu-events.h knows the CPU string).

Hopefully other architecutres can also implement arch_get_events_table()
and take advantage of this.

Signed-off-by: Sukadev Bhattiprolu <sukadev@linux.vnet.ibm.com>
---
 tools/perf/arch/powerpc/util/Build        |    2 +-
 tools/perf/arch/powerpc/util/pmu-events.c |   52 +++++++++++++++++++
 tools/perf/arch/powerpc/util/pmu-events.h |   17 +++++++
 tools/perf/util/pmu.c                     |   77 +++++++++++++++++++++++++++++
 tools/perf/util/pmu.h                     |   10 ++++
 5 files changed, 157 insertions(+), 1 deletion(-)
 create mode 100644 tools/perf/arch/powerpc/util/pmu-events.c
 create mode 100644 tools/perf/arch/powerpc/util/pmu-events.h

diff --git a/tools/perf/arch/powerpc/util/Build b/tools/perf/arch/powerpc/util/Build
index 0af6e9b..52fbc7f 100644
--- a/tools/perf/arch/powerpc/util/Build
+++ b/tools/perf/arch/powerpc/util/Build
@@ -1,4 +1,4 @@
-libperf-y += header.o
+libperf-y += header.o pmu-events.o
 
 libperf-$(CONFIG_DWARF) += dwarf-regs.o
 libperf-$(CONFIG_DWARF) += skip-callchain-idx.o
diff --git a/tools/perf/arch/powerpc/util/pmu-events.c b/tools/perf/arch/powerpc/util/pmu-events.c
new file mode 100644
index 0000000..7036f6d
--- /dev/null
+++ b/tools/perf/arch/powerpc/util/pmu-events.c
@@ -0,0 +1,52 @@
+#include <stdio.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include "pmu.h"
+#include "pmu-events.h"
+#include "../../util/debug.h"			/* verbose */
+#include "header.h"				/* mfspr */
+
+static char *get_cpu_str(void)
+{
+	char *bufp;
+
+	if (asprintf(&bufp, "%.8lx-core", mfspr(SPRN_PVR)) < 0)
+		bufp = NULL;
+
+	return bufp;
+}
+
+struct perf_pmu_event *arch_get_events_table(char *cpustr)
+{
+	int i, nmaps, must_free;
+	struct  perf_pmu_event *table;
+
+	must_free = 0;
+	if (!cpustr) {
+		cpustr = get_cpu_str();
+		if (!cpustr)
+			return NULL;
+		must_free = 1;
+	}
+
+	nmaps = sizeof(pvr_events_map) / sizeof(struct pvr_events_map_entry);
+
+	for (i = 0; i < nmaps; i++) {
+		if (!strcmp(pvr_events_map[i].pvr, cpustr))
+			break;
+	}
+
+	table = NULL;
+	if (i < nmaps) {
+		/* pvr_events_map is a const; cast to override */
+		table = (struct perf_pmu_event *)pvr_events_map[i].pmu_events;
+	} else if (verbose) {
+		printf("Unknown CPU %s, ignoring aliases\n", cpustr);
+	}
+
+	if (must_free)
+		free(cpustr);
+
+	return table;
+}
+
diff --git a/tools/perf/arch/powerpc/util/pmu-events.h b/tools/perf/arch/powerpc/util/pmu-events.h
new file mode 100644
index 0000000..1daf8e5
--- /dev/null
+++ b/tools/perf/arch/powerpc/util/pmu-events.h
@@ -0,0 +1,17 @@
+/*
+ * Include all Power processor tables that we care about.
+ */
+#include "power7-events.h"
+#include "power8-events.h"
+
+/*
+ * Map a processor version (PVR) to its table of events.
+ */
+struct pvr_events_map_entry {
+	const char *pvr;
+	const struct perf_pmu_event *pmu_events;
+} pvr_events_map[] = {
+	{ .pvr = "004d0100-core",	.pmu_events = power8_pmu_events },
+	{ .pvr = "003f0201-core",	.pmu_events = power7_pmu_events }
+};
+
diff --git a/tools/perf/util/pmu.c b/tools/perf/util/pmu.c
index 4841167..f998d91 100644
--- a/tools/perf/util/pmu.c
+++ b/tools/perf/util/pmu.c
@@ -435,6 +435,80 @@ perf_pmu__get_default_config(struct perf_pmu *pmu __maybe_unused)
 	return NULL;
 }
 
+/*
+ * Default arch_get_events_table() is empty.
+ *
+ * Actual implementation is in arch/$(ARCH)/util/pmu-events.c. This
+ * allows architectures could choose what set(s) of events to a) include
+ * in perf binary b) consider for _this_ invocation of perf.
+ *
+ * Eg: For Power, we include both Power7 and Power8 event tables in the
+ * 	perf binary. But depending on the processor where perf is executed,
+ * 	either the Power7 or Power8 table is returned.
+ */
+struct perf_pmu_event * __attribute__ ((weak))
+arch_get_events_table(char *cpustr __maybe_unused)
+{
+	return NULL;
+}
+
+static int pmu_add_cpu_aliases(char *cpustr, void *data)
+{
+	struct list_head *head = (struct list_head *)data;
+	struct perf_pmu_alias *alias;
+	int i;
+	struct perf_pmu_event *events_table, *event;
+	struct parse_events_term *term;
+
+	events_table = arch_get_events_table(cpustr);
+	if (!events_table)
+		return 0;
+
+	for (i = 0; events_table[i].name != NULL; i++) {
+		event = &events_table[i];
+
+		alias = malloc(sizeof(*alias));
+		if (!alias)
+			return -ENOMEM;
+
+		term = malloc(sizeof(*term));
+		if (!term) {
+			/*
+			 * TODO: cleanup aliases allocated so far?
+			 */
+			free(alias);
+			return -ENOMEM;
+		}
+
+		/* ->config is not const; cast to override */
+		term->config = (char *)"event";
+		term->val.num = event->code;
+		term->type_val = PARSE_EVENTS__TERM_TYPE_NUM;
+		term->type_term = PARSE_EVENTS__TERM_TYPE_USER;
+		INIT_LIST_HEAD(&term->list);
+		term->used = 0;
+
+		INIT_LIST_HEAD(&alias->terms);
+		list_add_tail(&alias->terms, &term->list);
+
+		alias->scale = 1.0;
+		alias->unit[0] = '\0';
+		alias->per_pkg = false;
+
+		alias->name = strdup(event->name);
+#if 0
+		/*
+		 * TODO: Need Andi Kleen's patch for ->desc
+		 */
+		alias->desc = event->short_desc ?
+					strdup(event->short_desc) : NULL;
+#endif
+		list_add_tail(&alias->list, head);
+	}
+
+	return 0;
+}
+
 static struct perf_pmu *pmu_lookup(const char *name)
 {
 	struct perf_pmu *pmu;
@@ -453,6 +527,9 @@ static struct perf_pmu *pmu_lookup(const char *name)
 	if (pmu_aliases(name, &aliases))
 		return NULL;
 
+	if (!strcmp(name, "cpu"))
+		(void)pmu_add_cpu_aliases(NULL, &aliases);
+
 	if (pmu_type(name, &type))
 		return NULL;
 
diff --git a/tools/perf/util/pmu.h b/tools/perf/util/pmu.h
index 6b1249f..ca3e7a0 100644
--- a/tools/perf/util/pmu.h
+++ b/tools/perf/util/pmu.h
@@ -45,6 +45,14 @@ struct perf_pmu_alias {
 	bool snapshot;
 };
 
+struct perf_pmu_event {
+	const char *name;
+	const unsigned long code;
+	const char *short_desc;
+	const char *long_desc;
+	/* add unit, mask etc as needed here */
+};
+
 struct perf_pmu *perf_pmu__find(const char *name);
 int perf_pmu__config(struct perf_pmu *pmu, struct perf_event_attr *attr,
 		     struct list_head *head_terms);
@@ -76,4 +84,6 @@ int perf_pmu__test(void);
 
 struct perf_event_attr *perf_pmu__get_default_config(struct perf_pmu *pmu);
 
+struct perf_pmu_event *arch_get_events_table(char *cpustr);
+
 #endif /* __PMU_H */
-- 
1.7.9.5


  parent reply	other threads:[~2015-05-01  7:06 UTC|newest]

Thread overview: 9+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2015-05-01  7:05 [RFC][PATCH 0/4] perf: Enable symbolic event names Sukadev Bhattiprolu
2015-05-01  7:05 ` [RFC][PATCH 1/4] perf: Create a table of Power7 PMU events Sukadev Bhattiprolu
2015-05-01  7:05 ` [RFC][PATCH 2/4] perf: Create a table of Power8 " Sukadev Bhattiprolu
2015-05-01  7:05 ` [RFC][PATCH 3/4] perf/powerpc: Move mfspr and friends to header file Sukadev Bhattiprolu
2015-05-01  7:05 ` Sukadev Bhattiprolu [this message]
2015-05-02  7:04   ` [RFC][PATCH 4/4] perf: Create aliases for PMU events Vineet Gupta
2015-05-02 15:38   ` Jiri Olsa
2015-05-04 11:44     ` Andi Kleen
2015-05-02  7:02 ` [RFC][PATCH 0/4] perf: Enable symbolic event names Vineet Gupta

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1430463941-26109-5-git-send-email-sukadev@linux.vnet.ibm.com \
    --to=sukadev@linux.vnet.ibm.com \
    --cc=acme@kernel.org \
    --cc=ak@linux.intel.com \
    --cc=jolsa@redhat.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linuxppc-dev@lists.ozlabs.org \
    --cc=mingo@redhat.com \
    --cc=mpe@ellerman.id.au \
    --cc=paulus@samba.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
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).