lkml.org 
[lkml]   [2017]   [Jan]   [27]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 02/10] perf, tools: Add support for parsing uncore json files
    Date
    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" 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
    Acked-by: Jiri Olsa <jolsa@kernel.org>
    Signed-off-by: Andi Kleen <ak@linux.intel.com>
    ---
    tools/perf/pmu-events/jevents.c | 74 +++++++++++++++++++++++++++++++++++---
    tools/perf/pmu-events/jevents.h | 4 ++-
    tools/perf/pmu-events/pmu-events.h | 3 ++
    tools/perf/util/pmu.c | 30 +++++++++++-----
    4 files changed, 98 insertions(+), 13 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;
    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 78b16100567d..6dc3cc050105 100644
    --- a/tools/perf/util/pmu.c
    +++ b/tools/perf/util/pmu.c
    @@ -229,11 +229,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, 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)
    @@ -267,7 +269,12 @@ 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) {
    + if (convert_scale(unit, &unit, &alias->scale) < 0)
    + return -1;
    + 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;
    @@ -284,7 +291,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)
    @@ -504,7 +512,7 @@ char * __weak get_cpuid_str(void)
    * to the current running CPU. Then, add all PMU events from that table
    * as aliases.
    */
    -static void pmu_add_cpu_aliases(struct list_head *head)
    +static void pmu_add_cpu_aliases(struct list_head *head, const char *name)
    {
    int i;
    struct pmu_events_map *map;
    @@ -540,14 +548,21 @@ static void pmu_add_cpu_aliases(struct list_head *head)
    */
    i = 0;
    while (1) {
    + const char *pname;
    +
    pe = &map->table[i++];
    if (!pe->name)
    break;

    + pname = pe->pmu ? pe->pmu : "cpu";
    + if (strncmp(pname, name, strlen(pname)))
    + 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:
    @@ -578,8 +593,7 @@ static struct perf_pmu *pmu_lookup(const char *name)
    if (pmu_aliases(name, &aliases))
    return NULL;

    - if (!strcmp(name, "cpu"))
    - pmu_add_cpu_aliases(&aliases);
    + pmu_add_cpu_aliases(&aliases, name);

    if (pmu_type(name, &type))
    return NULL;
    --
    2.9.3
    \
     
     \ /
      Last update: 2017-01-28 03:05    [W:20.206 / U:0.008 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site