diff options
author | Andi Kleen <ak@linux.intel.com> | 2017-01-28 05:03:37 +0300 |
---|---|---|
committer | Arnaldo Carvalho de Melo <acme@redhat.com> | 2017-02-08 14:55:03 +0300 |
commit | fedb2b518239cbc00abcf0d200e0be8436251c11 (patch) | |
tree | 8ab7fa4997f4b77d10f80bef73cdbdb550330998 /tools/perf/pmu-events/jevents.c | |
parent | d581141970ef3965c1624960fa928d765afd8a3e (diff) | |
download | linux-fedb2b518239cbc00abcf0d200e0be8436251c11.tar.xz |
perf jevents: Add support for parsing uncore json files
Handle the "Unit" field, which is needed to find the right PMU for an
event. We call it "pmu" and convert it to the perf pmu name with an
uncore prefix.
Handle the "ExtSel" field, which just extends the event mask with an
additional bit.
Handle the "Filter" field which adds parameters to the main event
to configure filtering.
Handle the "Unit" field which declares the unit the values should be
scaled too (similar to what the kernel exports)
Set up the "perpkg" field for uncore events so that perf knows they are
per package (similar to what the kernel exports)
Then output the fields into the pmu-events data structures which are
compiled into perf.
Filter out zero fields, except for the event itself.
v2: Fix compilation. Add uncore_ prefix at pre-processing time.
Move eventcode change to separate patch.
v3: Remove extra __maybe_unused
v4: dont duplicate aliases for cpu pmu events
Signed-off-by: Andi Kleen <ak@linux.intel.com>
Acked-by: Jiri Olsa <jolsa@kernel.org>
Link: http://lkml.kernel.org/r/20170128020345.19007-3-andi@firstfloor.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Diffstat (limited to 'tools/perf/pmu-events/jevents.c')
-rw-r--r-- | tools/perf/pmu-events/jevents.c | 74 |
1 files changed, 70 insertions, 4 deletions
diff --git a/tools/perf/pmu-events/jevents.c b/tools/perf/pmu-events/jevents.c index 551377bf8428..eed09346a72a 100644 --- a/tools/perf/pmu-events/jevents.c +++ b/tools/perf/pmu-events/jevents.c @@ -188,6 +188,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", "uncore_cbox" }, + { "QPI LL", "uncore_qpi" }, + { "SBO", "uncore_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) \ @@ -269,7 +290,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; @@ -287,7 +309,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; @@ -334,7 +361,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; @@ -356,6 +384,10 @@ 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; @@ -382,6 +414,11 @@ int json_events(const char *fn, 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")) { @@ -405,6 +442,28 @@ 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 { + if (!pmu) + pmu = strdup("uncore_"); + 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 */ } @@ -422,16 +481,23 @@ int json_events(const char *fn, 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; |