diff --git a/tools/perf/util/s390-sample-raw.c b/tools/perf/util/s390-sample-raw.c index 1c5a4d63bc9d..6650f599ed9c 100644 --- a/tools/perf/util/s390-sample-raw.c +++ b/tools/perf/util/s390-sample-raw.c @@ -30,6 +30,7 @@ #include "color.h" #include "sample-raw.h" #include "s390-cpumcf-kernel.h" +#include "pmu-events/pmu-events.h" static size_t ctrset_size(struct cf_ctrset_entry *set) { @@ -112,14 +113,61 @@ static void s390_cpumcfdg_dumptrail(const char *color, size_t offset, te.tod_base, te.mach_type); } +/* Return starting number of a counter set */ +static int get_counterset_start(int setnr) +{ + switch (setnr) { + case CPUMF_CTR_SET_BASIC: /* Basic counter set */ + return 0; + case CPUMF_CTR_SET_USER: /* Problem state counter set */ + return 32; + case CPUMF_CTR_SET_CRYPTO: /* Crypto counter set */ + return 64; + case CPUMF_CTR_SET_EXT: /* Extended counter set */ + return 128; + case CPUMF_CTR_SET_MT_DIAG: /* Diagnostic counter set */ + return 448; + default: + return -1; + } +} + +/* Scan the PMU table and extract the logical name of a counter from the + * PMU events table. Input is the counter set and counter number with in the + * set. Construct the event number and use this as key. If they match return + * the name of this counter. + * If no match is found a NULL pointer is returned. + */ +static const char *get_counter_name(int set, int nr, struct pmu_events_map *map) +{ + int rc, event_nr, wanted = get_counterset_start(set) + nr; + + if (map) { + struct pmu_event *evp = map->table; + + for (; evp->name || evp->event || evp->desc; ++evp) { + if (evp->name == NULL || evp->event == NULL) + continue; + rc = sscanf(evp->event, "event=%x", &event_nr); + if (rc == 1 && event_nr == wanted) + return evp->name; + } + } + return NULL; +} + static void s390_cpumcfdg_dump(struct perf_sample *sample) { size_t i, len = sample->raw_size, offset = 0; unsigned char *buf = sample->raw_data; const char *color = PERF_COLOR_BLUE; struct cf_ctrset_entry *cep, ce; + struct pmu_events_map *map; + struct perf_pmu pmu; u64 *p; + memset(&pmu, 0, sizeof(pmu)); + map = perf_pmu__find_map(&pmu); while (offset < len) { cep = (struct cf_ctrset_entry *)(buf + offset); @@ -136,12 +184,13 @@ static void s390_cpumcfdg_dump(struct perf_sample *sample) color_fprintf(stdout, color, " [%#08zx] Counterset:%d" " Counters:%d\n", offset, ce.set, ce.ctr); - for (i = 0, p = (u64 *)(cep + 1); i < ce.ctr; i += 2, p += 2) + for (i = 0, p = (u64 *)(cep + 1); i < ce.ctr; ++i, ++p) { + const char *ev_name = get_counter_name(ce.set, i, map); + color_fprintf(stdout, color, - "\tCounter:%03d Value:%#018lx" - " Counter:%03d Value:%#018lx\n", - i, be64_to_cpu(*p), - i + 1, be64_to_cpu(*(p + 1))); + "\tCounter:%03d %s Value:%#018lx\n", i, + ev_name ?: "", be64_to_cpu(*p)); + } offset += ctrset_size(&ce); } }