--- v13
+++ v17
@@ -1,129 +1,192 @@
+From: Andi Kleen <ak@linux.intel.com>
+
+Add support to group the output of perf list by the Topic field
+in the JSON file.
+
+Example output:
+
+% perf list
+...
+Cache:
+ l1d.replacement
+ [L1D data line replacements]
+ l1d_pend_miss.pending
+ [L1D miss oustandings duration in cycles]
+ l1d_pend_miss.pending_cycles
+ [Cycles with L1D load Misses outstanding]
+ l2_l1d_wb_rqsts.all
+ [Not rejected writebacks from L1D to L2 cache lines in any state]
+ l2_l1d_wb_rqsts.hit_e
+ [Not rejected writebacks from L1D to L2 cache lines in E state]
+ l2_l1d_wb_rqsts.hit_m
+ [Not rejected writebacks from L1D to L2 cache lines in M state]
+
+...
+Pipeline:
+ arith.fpu_div
+ [Divide operations executed]
+ arith.fpu_div_active
+ [Cycles when divider is busy executing divide operations]
+ baclears.any
+ [Counts the total number when the front end is resteered, mainly
+ when the BPU cannot provide a correct prediction and this is
+ corrected by other branch handling mechanisms at the front end]
+ br_inst_exec.all_branches
+ [Speculative and retired branches]
+ br_inst_exec.all_conditional
+ [Speculative and retired macro-conditional branches]
+ br_inst_exec.all_direct_jmp
+ [Speculative and retired macro-unconditional branches excluding
+ calls and indirects]
+ br_inst_exec.all_direct_near_call
+ [Speculative and retired direct near calls]
+ br_inst_exec.all_indirect_jump_non_call_ret
+
+Signed-off-by: Andi Kleen <ak@linux.intel.com>
Signed-off-by: Sukadev Bhattiprolu <sukadev@linux.vnet.ibm.com>
+Acked-by: Jiri Olsa <jolsa@redhat.com>
---
- tools/perf/pmu-events/README | 115 ++++++++++++++++++++++++++++++++++++++++++
- 1 file changed, 115 insertions(+)
- create mode 100644 tools/perf/pmu-events/README
-diff --git a/tools/perf/pmu-events/README b/tools/perf/pmu-events/README
-new file mode 100644
-index 0000000..00fd2e1
---- /dev/null
-+++ b/tools/perf/pmu-events/README
-@@ -0,0 +1,115 @@
-+The contents of this directory allows users to specify PMU events in
-+their CPUs by their symbolic names rather than raw event codes (see
-+example below).
+Changelog[v14]
+ - [Jiri Olsa] Move jevents support for Topic to a separate patch.
+---
+ tools/perf/util/pmu.c | 37 +++++++++++++++++++++++++++----------
+ tools/perf/util/pmu.h | 1 +
+ 2 files changed, 28 insertions(+), 10 deletions(-)
+
+diff --git a/tools/perf/util/pmu.c b/tools/perf/util/pmu.c
+index e608ccc..75a53d3 100644
+--- a/tools/perf/util/pmu.c
++++ b/tools/perf/util/pmu.c
+@@ -210,7 +210,8 @@ 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 *desc, char *val, char *long_desc,
++ char *topic)
+ {
+ struct perf_pmu_alias *alias;
+ int ret;
+@@ -245,6 +246,7 @@ static int __perf_pmu__new_alias(struct list_head *list, char *dir, char *name,
+ alias->desc = desc ? strdup(desc) : NULL;
+ alias->long_desc = long_desc ? strdup(long_desc) :
+ desc ? strdup(desc) : NULL;
++ alias->topic = topic ? strdup(topic) : NULL;
+
+ list_add_tail(&alias->list, list);
+
+@@ -262,7 +264,7 @@ 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);
++ return __perf_pmu__new_alias(list, dir, name, NULL, buf, NULL, NULL);
+ }
+
+ static inline bool pmu_alias_info_file(char *name)
+@@ -511,7 +513,7 @@ static int pmu_add_cpu_aliases(struct list_head *head)
+ /* 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->long_desc, (char *)pe->topic);
+ }
+
+ out:
+@@ -1042,19 +1044,26 @@ static char *format_alias_or(char *buf, int len, struct perf_pmu *pmu,
+ return buf;
+ }
+
+-struct pair {
++struct sevent {
+ char *name;
+ char *desc;
++ char *topic;
+ };
+
+-static int cmp_pair(const void *a, const void *b)
++static int cmp_sevent(const void *a, const void *b)
+ {
+- const struct pair *as = a;
+- const struct pair *bs = b;
++ const struct sevent *as = a;
++ const struct sevent *bs = b;
+
+ /* Put extra events last */
+ if (!!as->desc != !!bs->desc)
+ return !!as->desc - !!bs->desc;
++ if (as->topic && bs->topic) {
++ int n = strcmp(as->topic, bs->topic);
+
-+The main program in this directory, is the 'jevents', which is built and
-+executed _before_ the perf binary itself is built.
-+
-+The 'jevents' program tries to locate and process JSON files in the directory
-+tree tools/perf/pmu-events/arch/xxx.
-+
-+ - Regular files with '.json' extension in the name are assumed to be
-+ JSON files.
-+
-+ - Regular files with base name starting with 'mapfile.csv' are assumed
-+ to be a CSV file that - maps a specific CPU to its set of PMU events.
-+
-+Directories are traversed, but all other files are ignored.
-+
-+Using the JSON files and the mapfile, 'jevents' generates a C source file,
-+'pmu-events.c', which encodes the two sets of tables:
-+
-+ - Set of 'PMU events tables' for all known CPUs in the architecture,
-+ (one table like the following, per JSON file; table name 'pme_power8'
-+ is derived from JSON file name, 'power8.json').
-+
-+ struct pmu_event pme_power8[] = {
-+
-+ ...
-+
-+ {
-+ .name = "pm_1plus_ppc_cmpl",
-+ .event = "event=0x100f2",
-+ .desc = "1 or more ppc insts finished,",
-+ },
-+
-+ ...
-+ }
-+
-+ - A 'mapping table' that maps each CPU of the architecture, to its
-+ 'PMU events table'
-+
-+ struct pmu_events_map pmu_events_map[] = {
-+ {
-+ .cpuid = "004b0000",
-+ .version = "1",
-+ .type = "core",
-+ .table = pme_power8
-+ },
-+ {
-+ ...
-+ },
-+
-+ };
-+
-+After the 'pmu-events.c' is generated, it is compiled and the resulting
-+'pmu-events.o' is added to 'libperf.a' which is then used to build perf.
-+
-+NOTES:
-+ 1. Several CPUs can support same set of events and hence use a common
-+ JSON file. Hence several entries in the pmu_events_map[] could map
-+ to a single 'PMU events table'.
-+
-+ 2. The 'pmu-events.h' has an extern declaration for the mapping table
-+ and the generated 'pmu-events.c' defines this table.
-+
-+ 3. _All_ known CPU tables for architecture are included in the perf
-+ binary.
-+
-+At run time, perf determines the actual CPU it is running on, finds the
-+matching events table and builds aliases for those events. This allows
-+users to specify events by their name:
-+
-+ $ perf stat -e pm_1plus_ppc_cmpl sleep 1
-+
-+where 'pm_1plus_ppc_cmpl' is a Power8 PMU event.
-+
-+In case of errors when processing files in the tools/perf/pmu-events/arch
-+directory, 'jevents' tries to create an empty mapping file to allow perf
-+build to succeed even if the PMU event aliases cannot be used.
-+
-+However some errors in processing may cause the perf build to fail.
-+
-+The mapfile format is expected to be:
-+
-+ Header line
-+ CPUID,Version,JSON/file/path/name,Type
-+
-+where:
-+
-+ Lines in which the first character is either '\n' or '#' are ignored.
-+
-+ Header line
-+ is the first line in the file and is ignored. Even if
-+ first line is empty or is a comment, subsequent non-comment/
-+ blank lines are expected to adhere to the format of the second
-+ line above.
-+
-+ Comma:
-+ is the required field delimiter (i.e other fields cannot
-+ have commas within them)
-+
-+ CPUID:
-+ represents is an arch-specific CPUID for the set of CPUs
-+ that use the PMU events specified in JSON/file/path/name.
-+ (Multiple CPU ids can point to the same JSON/file/path/name)
-+
-+ Version:
-+ is the Version of the mapfile.
-+
-+ JSON/file/path/name:
-+ is the pathname for the JSON file, relative to the directory
-+ containing the mapfile.csv
-+
-+ Type:
-+ indicates whether the events or "core" or "uncore" events.
++ if (n)
++ return n;
++ }
+ return strcmp(as->name, bs->name);
+ }
+
+@@ -1088,9 +1097,10 @@ void print_pmu_events(const char *event_glob, bool name_only, bool quiet_flag,
+ char buf[1024];
+ int printed = 0;
+ int len, j;
+- struct pair *aliases;
++ struct sevent *aliases;
+ int numdesc = 0;
+ int columns = pager_get_columns();
++ char *topic = NULL;
+
+ pmu = NULL;
+ len = 0;
+@@ -1100,7 +1110,7 @@ void print_pmu_events(const char *event_glob, bool name_only, bool quiet_flag,
+ if (pmu->selectable)
+ len++;
+ }
+- aliases = zalloc(sizeof(struct pair) * len);
++ aliases = zalloc(sizeof(struct sevent) * len);
+ if (!aliases)
+ goto out_enomem;
+ pmu = NULL;
+@@ -1130,6 +1140,7 @@ void print_pmu_events(const char *event_glob, bool name_only, bool quiet_flag,
+
+ aliases[j].desc = long_desc ? alias->long_desc :
+ alias->desc;
++ aliases[j].topic = alias->topic;
+ j++;
+ }
+ if (pmu->selectable) {
+@@ -1141,7 +1152,7 @@ void print_pmu_events(const char *event_glob, bool name_only, bool quiet_flag,
+ }
+ }
+ len = j;
+- qsort(aliases, len, sizeof(struct pair), cmp_pair);
++ qsort(aliases, len, sizeof(struct sevent), cmp_sevent);
+ for (j = 0; j < len; j++) {
+ if (name_only) {
+ printf("%s ", aliases[j].name);
+@@ -1150,6 +1161,12 @@ void print_pmu_events(const char *event_glob, bool name_only, bool quiet_flag,
+ if (aliases[j].desc && !quiet_flag) {
+ if (numdesc++ == 0)
+ printf("\n");
++ if (aliases[j].topic && (!topic ||
++ strcmp(topic, aliases[j].topic))) {
++ printf("%s%s:\n", topic ? "\n" : "",
++ aliases[j].topic);
++ topic = aliases[j].topic;
++ }
+ printf(" %-50s\n", aliases[j].name);
+ printf("%*s", 8, "[");
+ wordwrap(aliases[j].desc, 8, columns, 0);
+diff --git a/tools/perf/util/pmu.h b/tools/perf/util/pmu.h
+index 1aa614e..de26919 100644
+--- a/tools/perf/util/pmu.h
++++ b/tools/perf/util/pmu.h
+@@ -40,6 +40,7 @@ struct perf_pmu_alias {
+ char *name;
+ char *desc;
+ char *long_desc;
++ char *topic;
+ struct list_head terms; /* HEAD struct parse_events_term -> list */
+ struct list_head list; /* ELEM */
+ char unit[UNIT_MAX_LEN+1];
--
-1.7.9.5
+2.5.3