Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

perf list: Display hybrid PMU events with cpu type

Add a new option '--cputype' to 'perf list' to display core-only PMU
events or atom-only PMU events.

Each hybrid PMU event has been assigned with a PMU name, this patch
compares the PMU name before listing the result.

For example:

perf list --cputype atom
...
cache:
core_reject_l2q.any
[Counts the number of request that were not accepted into the L2Q because the L2Q is FULL. Unit: cpu_atom]
...

The "Unit: cpu_atom" is displayed in the brief description section
to indicate this is an atom event.

Signed-off-by: Jin Yao <yao.jin@linux.intel.com>
Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com>
Cc: Andi Kleen <ak@linux.intel.com>
Cc: Jin Yao <yao.jin@intel.com>
Cc: Jiri Olsa <jolsa@kernel.org>
Cc: Kan Liang <kan.liang@linux.intel.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Link: http://lore.kernel.org/lkml/20210903025239.22754-1-yao.jin@linux.intel.com
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>

authored by

Jin Yao and committed by
Arnaldo Carvalho de Melo
0e0ae874 83e1ada6

+73 -24
+4
tools/perf/Documentation/perf-list.txt
··· 39 39 --deprecated:: 40 40 Print deprecated events. By default the deprecated events are hidden. 41 41 42 + --cputype:: 43 + Print events applying cpu with this type for hybrid platform 44 + (e.g. --cputype core or --cputype atom) 45 + 42 46 [[EVENT_MODIFIERS]] 43 47 EVENT MODIFIERS 44 48 ---------------
+30 -12
tools/perf/builtin-list.c
··· 12 12 13 13 #include "util/parse-events.h" 14 14 #include "util/pmu.h" 15 + #include "util/pmu-hybrid.h" 15 16 #include "util/debug.h" 16 17 #include "util/metricgroup.h" 17 18 #include <subcmd/pager.h> ··· 21 20 22 21 static bool desc_flag = true; 23 22 static bool details_flag; 23 + static const char *hybrid_type; 24 24 25 25 int cmd_list(int argc, const char **argv) 26 26 { 27 - int i; 27 + int i, ret = 0; 28 28 bool raw_dump = false; 29 29 bool long_desc_flag = false; 30 30 bool deprecated = false; 31 + char *pmu_name = NULL; 31 32 struct option list_options[] = { 32 33 OPT_BOOLEAN(0, "raw-dump", &raw_dump, "Dump raw events"), 33 34 OPT_BOOLEAN('d', "desc", &desc_flag, ··· 40 37 "Print information on the perf event names and expressions used internally by events."), 41 38 OPT_BOOLEAN(0, "deprecated", &deprecated, 42 39 "Print deprecated events."), 40 + OPT_STRING(0, "cputype", &hybrid_type, "hybrid cpu type", 41 + "Print events applying cpu with this type for hybrid platform " 42 + "(e.g. core or atom)"), 43 43 OPT_INCR(0, "debug", &verbose, 44 44 "Enable debugging output"), 45 45 OPT_END() ··· 62 56 if (!raw_dump && pager_in_use()) 63 57 printf("\nList of pre-defined events (to be used in -e):\n\n"); 64 58 59 + if (hybrid_type) { 60 + pmu_name = perf_pmu__hybrid_type_to_pmu(hybrid_type); 61 + if (!pmu_name) 62 + pr_warning("WARNING: hybrid cputype is not supported!\n"); 63 + } 64 + 65 65 if (argc == 0) { 66 66 print_events(NULL, raw_dump, !desc_flag, long_desc_flag, 67 - details_flag, deprecated); 68 - return 0; 67 + details_flag, deprecated, pmu_name); 68 + goto out; 69 69 } 70 70 71 71 for (i = 0; i < argc; ++i) { ··· 94 82 else if (strcmp(argv[i], "pmu") == 0) 95 83 print_pmu_events(NULL, raw_dump, !desc_flag, 96 84 long_desc_flag, details_flag, 97 - deprecated); 85 + deprecated, pmu_name); 98 86 else if (strcmp(argv[i], "sdt") == 0) 99 87 print_sdt_events(NULL, NULL, raw_dump); 100 88 else if (strcmp(argv[i], "metric") == 0 || strcmp(argv[i], "metrics") == 0) 101 - metricgroup__print(true, false, NULL, raw_dump, details_flag); 89 + metricgroup__print(true, false, NULL, raw_dump, details_flag, pmu_name); 102 90 else if (strcmp(argv[i], "metricgroup") == 0 || strcmp(argv[i], "metricgroups") == 0) 103 - metricgroup__print(false, true, NULL, raw_dump, details_flag); 91 + metricgroup__print(false, true, NULL, raw_dump, details_flag, pmu_name); 104 92 else if ((sep = strchr(argv[i], ':')) != NULL) { 105 93 int sep_idx; 106 94 107 95 sep_idx = sep - argv[i]; 108 96 s = strdup(argv[i]); 109 - if (s == NULL) 110 - return -1; 97 + if (s == NULL) { 98 + ret = -1; 99 + goto out; 100 + } 111 101 112 102 s[sep_idx] = '\0'; 113 103 print_tracepoint_events(s, s + sep_idx + 1, raw_dump); 114 104 print_sdt_events(s, s + sep_idx + 1, raw_dump); 115 - metricgroup__print(true, true, s, raw_dump, details_flag); 105 + metricgroup__print(true, true, s, raw_dump, details_flag, pmu_name); 116 106 free(s); 117 107 } else { 118 108 if (asprintf(&s, "*%s*", argv[i]) < 0) { ··· 130 116 print_pmu_events(s, raw_dump, !desc_flag, 131 117 long_desc_flag, 132 118 details_flag, 133 - deprecated); 119 + deprecated, 120 + pmu_name); 134 121 print_tracepoint_events(NULL, s, raw_dump); 135 122 print_sdt_events(NULL, s, raw_dump); 136 - metricgroup__print(true, true, s, raw_dump, details_flag); 123 + metricgroup__print(true, true, s, raw_dump, details_flag, pmu_name); 137 124 free(s); 138 125 } 139 126 } 140 - return 0; 127 + 128 + out: 129 + free(pmu_name); 130 + return ret; 141 131 }
+6 -1
tools/perf/util/metricgroup.c
··· 11 11 #include "evsel.h" 12 12 #include "strbuf.h" 13 13 #include "pmu.h" 14 + #include "pmu-hybrid.h" 14 15 #include "expr.h" 15 16 #include "rblist.h" 16 17 #include <string.h> ··· 536 535 } 537 536 538 537 void metricgroup__print(bool metrics, bool metricgroups, char *filter, 539 - bool raw, bool details) 538 + bool raw, bool details, const char *pmu_name) 540 539 { 541 540 const struct pmu_events_map *map = pmu_events_map__find(); 542 541 const struct pmu_event *pe; ··· 562 561 break; 563 562 if (!pe->metric_expr) 564 563 continue; 564 + if (pmu_name && perf_pmu__is_hybrid(pe->pmu) && 565 + strcmp(pmu_name, pe->pmu)) { 566 + continue; 567 + } 565 568 if (metricgroup__print_pmu_event(pe, metricgroups, filter, 566 569 raw, details, &groups, 567 570 metriclist) < 0)
+1 -1
tools/perf/util/metricgroup.h
··· 80 80 struct rblist *metric_events); 81 81 82 82 void metricgroup__print(bool metrics, bool groups, char *filter, 83 - bool raw, bool details); 83 + bool raw, bool details, const char *pmu_name); 84 84 bool metricgroup__has_metric(const char *metric); 85 85 int arch_get_runtimeparam(const struct pmu_event *pe __maybe_unused); 86 86 void metricgroup__rblist_exit(struct rblist *metric_events);
+5 -3
tools/perf/util/parse-events.c
··· 3089 3089 * Print the help text for the event symbols: 3090 3090 */ 3091 3091 void print_events(const char *event_glob, bool name_only, bool quiet_flag, 3092 - bool long_desc, bool details_flag, bool deprecated) 3092 + bool long_desc, bool details_flag, bool deprecated, 3093 + const char *pmu_name) 3093 3094 { 3094 3095 print_symbol_events(event_glob, PERF_TYPE_HARDWARE, 3095 3096 event_symbols_hw, PERF_COUNT_HW_MAX, name_only); ··· 3102 3101 print_hwcache_events(event_glob, name_only); 3103 3102 3104 3103 print_pmu_events(event_glob, name_only, quiet_flag, long_desc, 3105 - details_flag, deprecated); 3104 + details_flag, deprecated, pmu_name); 3106 3105 3107 3106 if (event_glob != NULL) 3108 3107 return; ··· 3128 3127 3129 3128 print_sdt_events(NULL, NULL, name_only); 3130 3129 3131 - metricgroup__print(true, true, NULL, name_only, details_flag); 3130 + metricgroup__print(true, true, NULL, name_only, details_flag, 3131 + pmu_name); 3132 3132 3133 3133 print_libpfm_events(name_only, long_desc); 3134 3134 }
+2 -1
tools/perf/util/parse-events.h
··· 221 221 int idx, const char *str); 222 222 223 223 void print_events(const char *event_glob, bool name_only, bool quiet, 224 - bool long_desc, bool details_flag, bool deprecated); 224 + bool long_desc, bool details_flag, bool deprecated, 225 + const char *pmu_name); 225 226 226 227 struct event_symbol { 227 228 const char *symbol;
+24 -5
tools/perf/util/pmu.c
··· 1608 1608 { 1609 1609 const struct sevent *as = a; 1610 1610 const struct sevent *bs = b; 1611 + int ret; 1611 1612 1612 1613 /* Put extra events last */ 1613 1614 if (!!as->desc != !!bs->desc) ··· 1624 1623 if (as->is_cpu != bs->is_cpu) 1625 1624 return bs->is_cpu - as->is_cpu; 1626 1625 1627 - return strcmp(as->name, bs->name); 1626 + ret = strcmp(as->name, bs->name); 1627 + if (!ret) { 1628 + if (as->pmu && bs->pmu) 1629 + return strcmp(as->pmu, bs->pmu); 1630 + } 1631 + 1632 + return ret; 1628 1633 } 1629 1634 1630 1635 static void wordwrap(char *s, int start, int max, int corr) ··· 1660 1653 } 1661 1654 1662 1655 void print_pmu_events(const char *event_glob, bool name_only, bool quiet_flag, 1663 - bool long_desc, bool details_flag, bool deprecated) 1656 + bool long_desc, bool details_flag, bool deprecated, 1657 + const char *pmu_name) 1664 1658 { 1665 1659 struct perf_pmu *pmu; 1666 1660 struct perf_pmu_alias *alias; ··· 1687 1679 pmu = NULL; 1688 1680 j = 0; 1689 1681 while ((pmu = perf_pmu__scan(pmu)) != NULL) { 1682 + if (pmu_name && perf_pmu__is_hybrid(pmu->name) && 1683 + strcmp(pmu_name, pmu->name)) { 1684 + continue; 1685 + } 1686 + 1690 1687 list_for_each_entry(alias, &pmu->aliases, list) { 1691 1688 char *name = alias->desc ? alias->name : 1692 1689 format_alias(buf, sizeof(buf), pmu, alias); 1693 - bool is_cpu = is_pmu_core(pmu->name); 1690 + bool is_cpu = is_pmu_core(pmu->name) || 1691 + perf_pmu__is_hybrid(pmu->name); 1694 1692 1695 1693 if (alias->deprecated && !deprecated) 1696 1694 continue; ··· 1744 1730 qsort(aliases, len, sizeof(struct sevent), cmp_sevent); 1745 1731 for (j = 0; j < len; j++) { 1746 1732 /* Skip duplicates */ 1747 - if (j > 0 && !strcmp(aliases[j].name, aliases[j - 1].name)) 1748 - continue; 1733 + if (j > 0 && !strcmp(aliases[j].name, aliases[j - 1].name)) { 1734 + if (!aliases[j].pmu || !aliases[j - 1].pmu || 1735 + !strcmp(aliases[j].pmu, aliases[j - 1].pmu)) { 1736 + continue; 1737 + } 1738 + } 1739 + 1749 1740 if (name_only) { 1750 1741 printf("%s ", aliases[j].name); 1751 1742 continue;
+1 -1
tools/perf/util/pmu.h
··· 111 111 bool is_pmu_core(const char *name); 112 112 void print_pmu_events(const char *event_glob, bool name_only, bool quiet, 113 113 bool long_desc, bool details_flag, 114 - bool deprecated); 114 + bool deprecated, const char *pmu_name); 115 115 bool pmu_have_event(const char *pname, const char *name); 116 116 117 117 int perf_pmu__scan_file(struct perf_pmu *pmu, const char *name, const char *fmt, ...) __scanf(3, 4);