Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > linux.kernel > #1500565 > unrolled thread

[PATCH 03/10] perf, tools: Add support for parsing uncore json files

Started byAndi Kleen <andi@firstfloor.org>
First post2016-10-13 23:20 +0200
Last post2016-10-14 17:40 +0200
Articles 6 — 2 participants

Back to article view | Back to linux.kernel

This discussion starts older than the indexed window; earlier articles aren't shown. The article labeled Started by below is the oldest one visible, not the original post.


Contents

  [PATCH 03/10] perf, tools: Add support for parsing uncore json files Andi Kleen <andi@firstfloor.org> - 2016-10-13 23:20 +0200
    Re: [PATCH 03/10] perf, tools: Add support for parsing uncore json  files Jiri Olsa <jolsa@redhat.com> - 2016-10-14 11:10 +0200
    Re: [PATCH 03/10] perf, tools: Add support for parsing uncore json  files Jiri Olsa <jolsa@redhat.com> - 2016-10-14 14:20 +0200
    Re: [PATCH 03/10] perf, tools: Add support for parsing uncore json  files Jiri Olsa <jolsa@redhat.com> - 2016-10-14 14:30 +0200
    Re: [PATCH 03/10] perf, tools: Add support for parsing uncore json  files Jiri Olsa <jolsa@redhat.com> - 2016-10-14 14:30 +0200
      Re: [PATCH 03/10] perf, tools: Add support for parsing uncore json  files Andi Kleen <andi@firstfloor.org> - 2016-10-14 17:40 +0200

#1500565 — [PATCH 03/10] perf, tools: Add support for parsing uncore json files

FromAndi Kleen <andi@firstfloor.org>
Date2016-10-13 23:20 +0200
Subject[PATCH 03/10] perf, tools: Add support for parsing uncore json files
Message-ID<srVzX-qJ-1@gated-at.bofh.it>
From: Andi Kleen <ak@linux.intel.com>

Handle the Unit field, which is needed to find the right PMU for
an event. We call it "pmu".  Handle the ExtSel field.
Handle the Filter field. Then output the fields into the pmu-events
data structures which are compiled into perf.

Filter out zero fields, except for the event itself.

Signed-off-by: Andi Kleen <ak@linux.intel.com>
---
 tools/perf/pmu-events/jevents.c    | 85 +++++++++++++++++++++++++++++++++++---
 tools/perf/pmu-events/jevents.h    |  4 +-
 tools/perf/pmu-events/pmu-events.h |  3 ++
 tools/perf/util/pmu.c              | 21 +++++++---
 4 files changed, 102 insertions(+), 11 deletions(-)

diff --git a/tools/perf/pmu-events/jevents.c b/tools/perf/pmu-events/jevents.c
index 41611d7f9873..23517db584e6 100644
--- a/tools/perf/pmu-events/jevents.c
+++ b/tools/perf/pmu-events/jevents.c
@@ -135,7 +135,6 @@ static struct field {
 	const char *field;
 	const char *kernel;
 } fields[] = {
-	{ "EventCode",	"event=" },
 	{ "UMask",	"umask=" },
 	{ "CounterMask", "cmask=" },
 	{ "Invert",	"inv=" },
@@ -164,6 +163,9 @@ static int match_field(char *map, jsmntok_t *field, int nz,
 
 	for (f = fields; f->field; f++)
 		if (json_streq(map, field, f->field) && nz) {
+			if (json_streq(map, val, "0x00") ||
+			     json_streq(map, val, "0x0"))
+				return 1;
 			cut_comma(map, &newval);
 			addfield(map, event, ",", f->kernel, &newval);
 			return 1;
@@ -189,6 +191,27 @@ static struct msrmap *lookup_msr(char *map, jsmntok_t *val)
 	return NULL;
 }
 
+static struct map {
+	const char *json;
+	const char *perf;
+} unit_to_pmu[] = {
+	{ "CBO", "cbox" },
+	{ "QPI LL", "qpi" },
+	{ "SBO", "sbox" },
+	{}
+};
+
+static const char *field_to_perf(struct map *table, char *map, jsmntok_t *val)
+{
+	int i;
+
+	for (i = 0; table[i].json; i++) {
+		if (json_streq(map, val, table[i].json))
+			return table[i].perf;
+	}
+	return NULL;
+}
+
 #define EXPECT(e, t, m) do { if (!(e)) {			\
 	jsmntok_t *loc = (t);					\
 	if (!(t)->start && (t) > tokens)			\
@@ -270,7 +293,8 @@ static void print_events_table_prefix(FILE *fp, const char *tblname)
 }
 
 static int print_events_table_entry(void *data, char *name, char *event,
-				    char *desc, char *long_desc)
+				    char *desc, char *long_desc,
+				    char *pmu, char *unit, char *perpkg)
 {
 	struct perf_entry_data *pd = data;
 	FILE *outfp = pd->outfp;
@@ -288,7 +312,12 @@ static int print_events_table_entry(void *data, char *name, char *event,
 	fprintf(outfp, "\t.topic = \"%s\",\n", topic);
 	if (long_desc && long_desc[0])
 		fprintf(outfp, "\t.long_desc = \"%s\",\n", long_desc);
-
+	if (pmu)
+		fprintf(outfp, "\t.pmu = \"%s\",\n", pmu);
+	if (unit)
+		fprintf(outfp, "\t.unit = \"%s\",\n", unit);
+	if (perpkg)
+		fprintf(outfp, "\t.perpkg = \"%s\",\n", perpkg);
 	fprintf(outfp, "},\n");
 
 	return 0;
@@ -335,7 +364,8 @@ static char *real_event(const char *name, char *event)
 /* Call func with each event in the json file */
 int json_events(const char *fn,
 	  int (*func)(void *data, char *name, char *event, char *desc,
-		      char *long_desc),
+		      char *long_desc,
+		      char *pmu, char *unit, char *perpkg),
 	  void *data)
 {
 	int err = -EIO;
@@ -343,6 +373,7 @@ int json_events(const char *fn,
 	jsmntok_t *tokens, *tok;
 	int i, j, len;
 	char *map;
+	char buf[128];
 
 	if (!fn)
 		return -ENOENT;
@@ -356,6 +387,11 @@ int json_events(const char *fn,
 		char *event = NULL, *desc = NULL, *name = NULL;
 		char *long_desc = NULL;
 		char *extra_desc = NULL;
+		char *pmu = NULL;
+		char *filter = NULL;
+		char *perpkg = NULL;
+		char *unit = NULL;
+		unsigned long long eventcode = 0;
 		struct msrmap *msr = NULL;
 		jsmntok_t *msrval = NULL;
 		jsmntok_t *precise = NULL;
@@ -376,6 +412,16 @@ int json_events(const char *fn,
 			nz = !json_streq(map, val, "0");
 			if (match_field(map, field, nz, &event, val)) {
 				/* ok */
+			} else if (json_streq(map, field, "EventCode")) {
+				char *code = NULL;
+				addfield(map, &code, "", "", val);
+				eventcode |= strtoul(code, NULL, 0);
+				free(code);
+			} else if (json_streq(map, field, "ExtSel")) {
+				char *code = NULL;
+				addfield(map, &code, "", "", val);
+				eventcode |= strtoul(code, NULL, 0) << 21;
+				free(code);
 			} else if (json_streq(map, field, "EventName")) {
 				addfield(map, &name, "", "", val);
 			} else if (json_streq(map, field, "BriefDescription")) {
@@ -399,6 +445,26 @@ int json_events(const char *fn,
 				addfield(map, &extra_desc, ". ",
 					" Supports address when precise",
 					NULL);
+			} else if (json_streq(map, field, "Unit")) {
+				const char *ppmu;
+				char *s;
+
+				ppmu = field_to_perf(unit_to_pmu, map, val);
+				if (ppmu) {
+					pmu = strdup(ppmu);
+				} else {
+					addfield(map, &pmu, "", "", val);
+					for (s = pmu; *s; s++)
+						*s = tolower(*s);
+				}
+				addfield(map, &desc, ". ", "Unit: ", NULL);
+				addfield(map, &desc, "", pmu, NULL);
+			} else if (json_streq(map, field, "Filter")) {
+				addfield(map, &filter, "", "", val);
+			} else if (json_streq(map, field, "ScaleUnit")) {
+				addfield(map, &unit, "", "", val);
+			} else if (json_streq(map, field, "PerPkg")) {
+				addfield(map, &perpkg, "", "", val);
 			}
 			/* ignore unknown fields */
 		}
@@ -410,20 +476,29 @@ int json_events(const char *fn,
 				addfield(map, &extra_desc, " ",
 						"(Precise event)", NULL);
 		}
+		snprintf(buf, sizeof buf, "event=%#llx", eventcode);
+		addfield(map, &event, ",", buf, NULL);
 		if (desc && extra_desc)
 			addfield(map, &desc, " ", extra_desc, NULL);
 		if (long_desc && extra_desc)
 			addfield(map, &long_desc, " ", extra_desc, NULL);
+		if (filter)
+			addfield(map, &event, ",", filter, NULL);
 		if (msr != NULL)
 			addfield(map, &event, ",", msr->pname, msrval);
 		fixname(name);
 
-		err = func(data, name, real_event(name, event), desc, long_desc);
+		err = func(data, name, real_event(name, event), desc, long_desc,
+				pmu, unit, perpkg);
 		free(event);
 		free(desc);
 		free(name);
 		free(long_desc);
 		free(extra_desc);
+		free(pmu);
+		free(filter);
+		free(perpkg);
+		free(unit);
 		if (err)
 			break;
 		tok += j;
diff --git a/tools/perf/pmu-events/jevents.h b/tools/perf/pmu-events/jevents.h
index b0eb2744b498..71e13de31092 100644
--- a/tools/perf/pmu-events/jevents.h
+++ b/tools/perf/pmu-events/jevents.h
@@ -3,7 +3,9 @@
 
 int json_events(const char *fn,
 		int (*func)(void *data, char *name, char *event, char *desc,
-				char *long_desc),
+				char *long_desc,
+				char *pmu,
+				char *unit, char *perpkg),
 		void *data);
 char *get_cpu_str(void);
 
diff --git a/tools/perf/pmu-events/pmu-events.h b/tools/perf/pmu-events/pmu-events.h
index 2eaef595d8a0..c669a3cdb9f0 100644
--- a/tools/perf/pmu-events/pmu-events.h
+++ b/tools/perf/pmu-events/pmu-events.h
@@ -10,6 +10,9 @@ struct pmu_event {
 	const char *desc;
 	const char *topic;
 	const char *long_desc;
+	const char *pmu;
+	const char *unit;
+	const char *perpkg;
 };
 
 /*
diff --git a/tools/perf/util/pmu.c b/tools/perf/util/pmu.c
index b36bf9e77799..363cb7b0ccc7 100644
--- a/tools/perf/util/pmu.c
+++ b/tools/perf/util/pmu.c
@@ -227,11 +227,13 @@ static int perf_pmu__parse_snapshot(struct perf_pmu_alias *alias,
 }
 
 static int __perf_pmu__new_alias(struct list_head *list, char *dir, char *name,
-				 char *desc, char *val, char *long_desc,
-				 char *topic)
+				 char *desc __maybe_unused, char *val,
+				 char *long_desc, char *topic,
+				 char *unit, char *perpkg)
 {
 	struct perf_pmu_alias *alias;
 	int ret;
+	int num;
 
 	alias = malloc(sizeof(*alias));
 	if (!alias)
@@ -265,7 +267,11 @@ static int __perf_pmu__new_alias(struct list_head *list, char *dir, char *name,
 	alias->long_desc = long_desc ? strdup(long_desc) :
 				desc ? strdup(desc) : NULL;
 	alias->topic = topic ? strdup(topic) : NULL;
-
+	if (unit) {
+		alias->scale = convert_scale(unit, &unit);
+		snprintf(alias->unit, sizeof(alias->unit), "%s", unit);
+	}
+	alias->per_pkg = perpkg && sscanf(perpkg, "%d", &num) == 1 && num == 1;
 	list_add_tail(&alias->list, list);
 
 	return 0;
@@ -282,7 +288,8 @@ static int perf_pmu__new_alias(struct list_head *list, char *dir, char *name, FI
 
 	buf[ret] = 0;
 
-	return __perf_pmu__new_alias(list, dir, name, NULL, buf, NULL, NULL);
+	return __perf_pmu__new_alias(list, dir, name, NULL, buf, NULL, NULL, NULL,
+				     NULL);
 }
 
 static inline bool pmu_alias_info_file(char *name)
@@ -542,10 +549,14 @@ static void pmu_add_cpu_aliases(struct list_head *head)
 		if (!pe->name)
 			break;
 
+		if (pe->pmu && strncmp(pe->pmu, name, strlen(pe->pmu)))
+			continue;
+
 		/* need type casts to override 'const' */
 		__perf_pmu__new_alias(head, NULL, (char *)pe->name,
 				(char *)pe->desc, (char *)pe->event,
-				(char *)pe->long_desc, (char *)pe->topic);
+				(char *)pe->long_desc, (char *)pe->topic,
+				(char *)pe->unit, (char *)pe->perpkg);
 	}
 
 out:
-- 
2.5.5

[toc] | [next] | [standalone]


#1500775 — Re: [PATCH 03/10] perf, tools: Add support for parsing uncore json files

FromJiri Olsa <jolsa@redhat.com>
Date2016-10-14 11:10 +0200
SubjectRe: [PATCH 03/10] perf, tools: Add support for parsing uncore json files
Message-ID<ss6F3-7JP-1@gated-at.bofh.it>
In reply to#1500565
On Thu, Oct 13, 2016 at 02:15:25PM -0700, Andi Kleen wrote:
> From: Andi Kleen <ak@linux.intel.com>
> 
> Handle the Unit field, which is needed to find the right PMU for
> an event. We call it "pmu".  Handle the ExtSel field.
> Handle the Filter field. Then output the fields into the pmu-events
> data structures which are compiled into perf.
> 
> Filter out zero fields, except for the event itself.

got compile error with this patch:

  CC       util/pmu.o
In file included from /usr/include/string.h:630:0,
                 from util/util.h:55,
                 from util/pmu.c:11:
util/pmu.c: In function ‘pmu_add_cpu_aliases’:
util/pmu.c:552:35: error: ‘name’ undeclared (first use in this function)
   if (pe->pmu && strncmp(pe->pmu, name, strlen(pe->pmu)))
                                   ^
util/pmu.c:552:35: note: each undeclared identifier is reported only once for each function it appears in
mv: cannot stat 'util/.pmu.o.tmp': No such file or directory
/home/jolsa/kernel/linux-perf/tools/build/Makefile.build:91: recipe for target 'util/pmu.o' failed


jirka

[toc] | [prev] | [next] | [standalone]


#1500880 — Re: [PATCH 03/10] perf, tools: Add support for parsing uncore json files

FromJiri Olsa <jolsa@redhat.com>
Date2016-10-14 14:20 +0200
SubjectRe: [PATCH 03/10] perf, tools: Add support for parsing uncore json files
Message-ID<ss9CW-197-9@gated-at.bofh.it>
In reply to#1500565
On Thu, Oct 13, 2016 at 02:15:25PM -0700, Andi Kleen wrote:

SNIP

> @@ -376,6 +412,16 @@ int json_events(const char *fn,
>  			nz = !json_streq(map, val, "0");
>  			if (match_field(map, field, nz, &event, val)) {
>  				/* ok */
> +			} else if (json_streq(map, field, "EventCode")) {
> +				char *code = NULL;
> +				addfield(map, &code, "", "", val);
> +				eventcode |= strtoul(code, NULL, 0);
> +				free(code);
> +			} else if (json_streq(map, field, "ExtSel")) {
> +				char *code = NULL;
> +				addfield(map, &code, "", "", val);
> +				eventcode |= strtoul(code, NULL, 0) << 21;
> +				free(code);

could you please separate this (EventCode/ExtSel) change from the rest?


thanks,
jirka

[toc] | [prev] | [next] | [standalone]


#1500896 — Re: [PATCH 03/10] perf, tools: Add support for parsing uncore json files

FromJiri Olsa <jolsa@redhat.com>
Date2016-10-14 14:30 +0200
SubjectRe: [PATCH 03/10] perf, tools: Add support for parsing uncore json files
Message-ID<ss9MB-1cq-19@gated-at.bofh.it>
In reply to#1500565
On Thu, Oct 13, 2016 at 02:15:25PM -0700, Andi Kleen wrote:
> From: Andi Kleen <ak@linux.intel.com>
> 
> Handle the Unit field, which is needed to find the right PMU for
> an event. We call it "pmu".  Handle the ExtSel field.
> Handle the Filter field. Then output the fields into the pmu-events
> data structures which are compiled into perf.

Could you be more specific and put more description for new fields?

Some of them are obvous, but some not.. what's the 'filter' expected value?

thanks,
jirka

[toc] | [prev] | [next] | [standalone]


#1500905 — Re: [PATCH 03/10] perf, tools: Add support for parsing uncore json files

FromJiri Olsa <jolsa@redhat.com>
Date2016-10-14 14:30 +0200
SubjectRe: [PATCH 03/10] perf, tools: Add support for parsing uncore json files
Message-ID<ss9MC-1cq-37@gated-at.bofh.it>
In reply to#1500565
On Thu, Oct 13, 2016 at 02:15:25PM -0700, Andi Kleen wrote:

SNIP

> @@ -376,6 +412,16 @@ int json_events(const char *fn,
>  			nz = !json_streq(map, val, "0");
>  			if (match_field(map, field, nz, &event, val)) {
>  				/* ok */
> +			} else if (json_streq(map, field, "EventCode")) {
> +				char *code = NULL;
> +				addfield(map, &code, "", "", val);
> +				eventcode |= strtoul(code, NULL, 0);
> +				free(code);
> +			} else if (json_streq(map, field, "ExtSel")) {
> +				char *code = NULL;
> +				addfield(map, &code, "", "", val);
> +				eventcode |= strtoul(code, NULL, 0) << 21;
> +				free(code);
>  			} else if (json_streq(map, field, "EventName")) {
>  				addfield(map, &name, "", "", val);
>  			} else if (json_streq(map, field, "BriefDescription")) {
> @@ -399,6 +445,26 @@ int json_events(const char *fn,
>  				addfield(map, &extra_desc, ". ",
>  					" Supports address when precise",
>  					NULL);
> +			} else if (json_streq(map, field, "Unit")) {

so I remember you said you're preparing JSON events files for perf,
so why not call this field "Pmu" directly? Would be less confusing
wrt the ScaleUnit field

thanks,
jirka

[toc] | [prev] | [next] | [standalone]


#1501061 — Re: [PATCH 03/10] perf, tools: Add support for parsing uncore json files

FromAndi Kleen <andi@firstfloor.org>
Date2016-10-14 17:40 +0200
SubjectRe: [PATCH 03/10] perf, tools: Add support for parsing uncore json files
Message-ID<sscKu-36Y-11@gated-at.bofh.it>
In reply to#1500905
> >  				addfield(map, &extra_desc, ". ",
> >  					" Supports address when precise",
> >  					NULL);
> > +			} else if (json_streq(map, field, "Unit")) {
> 
> so I remember you said you're preparing JSON events files for perf,
> so why not call this field "Pmu" directly? Would be less confusing
> wrt the ScaleUnit field

While I'm cleaning up the files somewhat, I'm still trying to be
compatible with the original format, so that it's also possible
to drop in unchanged files. Also it's better if there is only
one kind of JSON event format, not multiple subtle incompatible
versions.

-Andi

[toc] | [prev] | [standalone]


Back to top | Article view | linux.kernel


csiph-web