linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v7 00/16] New perf ilist app
@ 2025-07-14 16:43 Ian Rogers
  2025-07-14 16:43 ` [PATCH v7 01/16] perf python: Add more exceptions on error paths Ian Rogers
                   ` (16 more replies)
  0 siblings, 17 replies; 41+ messages in thread
From: Ian Rogers @ 2025-07-14 16:43 UTC (permalink / raw)
  To: Peter Zijlstra, Ingo Molnar, Arnaldo Carvalho de Melo,
	Namhyung Kim, Mark Rutland, Alexander Shishkin, Jiri Olsa,
	Ian Rogers, Adrian Hunter, Kan Liang, James Clark, Xu Yang,
	Masami Hiramatsu (Google), Collin Funk, Howard Chu, Weilin Wang,
	Andi Kleen, Dr. David Alan Gilbert, Thomas Richter, Tiezhu Yang,
	Gautam Menghani, Thomas Falcon, Chun-Tse Shao, linux-kernel,
	linux-perf-users

This patch series builds up to the addition of a new ilist app written
in python using textual [1] for the UI. The app presents perf PMUs and
events, displays the event information as in `perf list` while at the
bottom of the console showing recent activity of the event in total
and across all CPUs. It also displays metrics, placed in a tree
through their metric group, again with counts being displayed in the
bottom panel.

The first ground work patches of fixes, cleanup and refactoring were
separated into their own series here:
https://lore.kernel.org/lkml/20250709214029.1769089-1-irogers@google.com/

The second part of the patches adds event json for the software PMU
and makes the tracepoint PMU support iteration of events and the
like. Without these improvements the tracepoint and software PMUs will
appear to have no events in the ilist app. As the software PMU moves
parsing to json, the legacy hard coded parsing is removed. This has
proven controversial for hardware events and so that cleanup isn't
done here.

The final patches expand the perf python APIs and add the ilist
command. To run it you need the updated perf.cpython.so in your
PYTHONPATH and then execute the script. Expanding PMUs and then
selecting events will cause event informatin to be displayed in the
top-right and the counters values to be displayed as sparklines and
counts in the bottom half of the screen.
 
[1] https://textual.textualize.io/

v7: Better handle errors in the python code and ignore errors when
    scanning PMU/events in ilist.py, improving the behavior when not
    root. Add a tp_pmu/python clean up. Minor kernel coding style
    clean up. Fix behavior of ilist if a search result isn't found but
    then next is chosen.

v6: For metrics on hybrid systems don't purely match by name, also
    match the CPU and thread so that if the same metric exists for
    different PMUs the appropriate one is selected and counters may be
    read. Likewise use evsel maps and not the evlists.

v5: Split the series in two. Add metric support. Various clean ups and
    tweaks to the app in particular around the handling of searches.

v4: No conflict rebase. Picks up perf-tools-next DRM PMU which
    displays as expected.

v3: Add a search dialog to the ilist app with 'n'ext and 'p'revious
    keys. No changes in the ground work first 14 patches.

v2: In the jevents event description duplication, some minor changes
    accidentally missed from v1 meaning that in v1 the descriptions
    were still duplicated. Expand the cover letter with some thoughts
    on the series.

Ian Rogers (16):
  perf python: Add more exceptions on error paths
  perf jevents: Add common software event json
  perf parse-events: Remove non-json software events
  perf tp_pmu: Factor existing tracepoint logic to new file
  perf tp_pmu: Add event APIs
  perf list: Remove tracepoint printing code
  perf list: Skip ABI PMUs when printing pmu values
  perf python: Improve the tracepoint function if no libtraceevent
  perf python: Add basic PMU abstraction and pmus sequence
  perf python: Add function returning dictionary of all events on a PMU
  perf ilist: Add new python ilist command
  perf python: Add parse_metrics function
  perf python: Add evlist metrics function
  perf python: Add evlist compute_metric
  perf python: Add metrics function
  perf ilist: Add support for metrics

 tools/perf/builtin-list.c                     |  65 ++-
 .../arch/common/common/software.json          |  92 ++++
 tools/perf/pmu-events/empty-pmu-events.c      | 266 +++++----
 tools/perf/pmu-events/jevents.py              |  15 +-
 tools/perf/python/ilist.py                    | 491 +++++++++++++++++
 tools/perf/util/Build                         |   1 +
 tools/perf/util/evsel.c                       |  21 +-
 tools/perf/util/parse-events.c                | 198 ++-----
 tools/perf/util/parse-events.h                |   1 -
 tools/perf/util/parse-events.l                |  38 +-
 tools/perf/util/parse-events.y                |  29 +-
 tools/perf/util/pfm.c                         |   2 +
 tools/perf/util/pmu.c                         |   7 +
 tools/perf/util/pmus.c                        |   2 +
 tools/perf/util/print-events.c                | 100 +---
 tools/perf/util/print-events.h                |   4 +-
 tools/perf/util/python.c                      | 519 +++++++++++++++++-
 tools/perf/util/tp_pmu.c                      | 209 +++++++
 tools/perf/util/tp_pmu.h                      |  19 +
 19 files changed, 1638 insertions(+), 441 deletions(-)
 create mode 100644 tools/perf/pmu-events/arch/common/common/software.json
 create mode 100755 tools/perf/python/ilist.py
 create mode 100644 tools/perf/util/tp_pmu.c
 create mode 100644 tools/perf/util/tp_pmu.h

-- 
2.50.0.727.gbf7dc18ff4-goog


^ permalink raw reply	[flat|nested] 41+ messages in thread

* [PATCH v7 01/16] perf python: Add more exceptions on error paths
  2025-07-14 16:43 [PATCH v7 00/16] New perf ilist app Ian Rogers
@ 2025-07-14 16:43 ` Ian Rogers
  2025-07-23 16:48   ` Arnaldo Carvalho de Melo
  2025-07-23 18:12   ` Namhyung Kim
  2025-07-14 16:43 ` [PATCH v7 02/16] perf jevents: Add common software event json Ian Rogers
                   ` (15 subsequent siblings)
  16 siblings, 2 replies; 41+ messages in thread
From: Ian Rogers @ 2025-07-14 16:43 UTC (permalink / raw)
  To: Peter Zijlstra, Ingo Molnar, Arnaldo Carvalho de Melo,
	Namhyung Kim, Mark Rutland, Alexander Shishkin, Jiri Olsa,
	Ian Rogers, Adrian Hunter, Kan Liang, James Clark, Xu Yang,
	Masami Hiramatsu (Google), Collin Funk, Howard Chu, Weilin Wang,
	Andi Kleen, Dr. David Alan Gilbert, Thomas Richter, Tiezhu Yang,
	Gautam Menghani, Thomas Falcon, Chun-Tse Shao, linux-kernel,
	linux-perf-users

Returning NULL will cause the python interpreter to fail but not
report an error. If none wants to be returned then Py_None needs
returning. Set the error for the cases returning NULL so that more
meaningful interpreter behavior is had.

Signed-off-by: Ian Rogers <irogers@google.com>
---
 tools/perf/util/python.c | 14 +++++++++++---
 1 file changed, 11 insertions(+), 3 deletions(-)

diff --git a/tools/perf/util/python.c b/tools/perf/util/python.c
index 2f28f71325a8..02544387f39d 100644
--- a/tools/perf/util/python.c
+++ b/tools/perf/util/python.c
@@ -475,13 +475,19 @@ static PyObject *pyrf_event__new(const union perf_event *event)
 	if ((event->header.type < PERF_RECORD_MMAP ||
 	     event->header.type > PERF_RECORD_SAMPLE) &&
 	    !(event->header.type == PERF_RECORD_SWITCH ||
-	      event->header.type == PERF_RECORD_SWITCH_CPU_WIDE))
+	      event->header.type == PERF_RECORD_SWITCH_CPU_WIDE)){
+		PyErr_Format(PyExc_TypeError, "Unexpected header type %u",
+			     event->header.type);
 		return NULL;
+	}
 
 	// FIXME this better be dynamic or we need to parse everything
 	// before calling perf_mmap__consume(), including tracepoint fields.
-	if (sizeof(pevent->event) < event->header.size)
+	if (sizeof(pevent->event) < event->header.size) {
+		PyErr_Format(PyExc_TypeError, "Unexpected event version: %zd < %u",
+			     sizeof(pevent->event), event->header.size);
 		return NULL;
+	}
 
 	ptype = pyrf_event__type[event->header.type];
 	pevent = PyObject_New(struct pyrf_event, ptype);
@@ -1199,8 +1205,10 @@ static PyObject *pyrf_evlist__read_on_cpu(struct pyrf_evlist *pevlist,
 		return NULL;
 
 	md = get_md(evlist, cpu);
-	if (!md)
+	if (!md) {
+		PyErr_Format(PyExc_TypeError, "Unknown CPU '%d'", cpu);
 		return NULL;
+	}
 
 	if (perf_mmap__read_init(&md->core) < 0)
 		goto end;
-- 
2.50.0.727.gbf7dc18ff4-goog


^ permalink raw reply related	[flat|nested] 41+ messages in thread

* [PATCH v7 02/16] perf jevents: Add common software event json
  2025-07-14 16:43 [PATCH v7 00/16] New perf ilist app Ian Rogers
  2025-07-14 16:43 ` [PATCH v7 01/16] perf python: Add more exceptions on error paths Ian Rogers
@ 2025-07-14 16:43 ` Ian Rogers
  2025-07-23 16:52   ` Arnaldo Carvalho de Melo
  2025-07-23 18:24   ` Namhyung Kim
  2025-07-14 16:43 ` [PATCH v7 03/16] perf parse-events: Remove non-json software events Ian Rogers
                   ` (14 subsequent siblings)
  16 siblings, 2 replies; 41+ messages in thread
From: Ian Rogers @ 2025-07-14 16:43 UTC (permalink / raw)
  To: Peter Zijlstra, Ingo Molnar, Arnaldo Carvalho de Melo,
	Namhyung Kim, Mark Rutland, Alexander Shishkin, Jiri Olsa,
	Ian Rogers, Adrian Hunter, Kan Liang, James Clark, Xu Yang,
	Masami Hiramatsu (Google), Collin Funk, Howard Chu, Weilin Wang,
	Andi Kleen, Dr. David Alan Gilbert, Thomas Richter, Tiezhu Yang,
	Gautam Menghani, Thomas Falcon, Chun-Tse Shao, linux-kernel,
	linux-perf-users

Add json for software events so that in perf list the events can have
a description.  Common json exists for the tool PMU but it has no
sysfs equivalent. Modify the map_for_pmu code to return the common map
(rather than an architecture specific one) when a PMU with a common
name is being looked for, this allows the events to be found.

Signed-off-by: Ian Rogers <irogers@google.com>
---
 .../arch/common/common/software.json          |  92 ++++++
 tools/perf/pmu-events/empty-pmu-events.c      | 266 +++++++++++-------
 tools/perf/pmu-events/jevents.py              |  15 +-
 3 files changed, 264 insertions(+), 109 deletions(-)
 create mode 100644 tools/perf/pmu-events/arch/common/common/software.json

diff --git a/tools/perf/pmu-events/arch/common/common/software.json b/tools/perf/pmu-events/arch/common/common/software.json
new file mode 100644
index 000000000000..3af2f565a601
--- /dev/null
+++ b/tools/perf/pmu-events/arch/common/common/software.json
@@ -0,0 +1,92 @@
+[
+  {
+    "Unit": "software",
+    "EventName": "cpu-clock",
+    "BriefDescription": "Per-CPU high-resolution timer based event",
+    "ConfigCode": "0"
+  },
+  {
+    "Unit": "software",
+    "EventName": "task-clock",
+    "BriefDescription": "Task based high-resolution timer based event",
+    "ConfigCode": "1"
+  },
+  {
+    "Unit": "software",
+    "EventName": "faults",
+    "BriefDescription": "Number of page faults [This event is an alias of page-faults]",
+    "ConfigCode": "2"
+  },
+  {
+    "Unit": "software",
+    "EventName": "page-faults",
+    "BriefDescription": "Number of page faults [This event is an alias of faults]",
+    "ConfigCode": "2"
+  },
+  {
+    "Unit": "software",
+    "EventName": "context-switches",
+    "BriefDescription": "Number of context switches [This event is an alias of cs]",
+    "ConfigCode": "3"
+  },
+  {
+    "Unit": "software",
+    "EventName": "cs",
+    "BriefDescription": "Number of context switches [This event is an alias of context-switches]",
+    "ConfigCode": "3"
+  },
+  {
+    "Unit": "software",
+    "EventName": "cpu-migrations",
+    "BriefDescription": "Number of times a process has migrated to a new CPU [This event is an alias of migrations]",
+    "ConfigCode": "4"
+  },
+  {
+    "Unit": "software",
+    "EventName": "migrations",
+    "BriefDescription": "Number of times a process has migrated to a new CPU [This event is an alias of cpu-migrations]",
+    "ConfigCode": "4"
+  },
+  {
+    "Unit": "software",
+    "EventName": "minor-faults",
+    "BriefDescription": "Number of minor page faults. Minor faults don't require I/O to handle",
+    "ConfigCode": "5"
+  },
+  {
+    "Unit": "software",
+    "EventName": "major-faults",
+    "BriefDescription": "Number of major page faults. Major faults require I/O to handle",
+    "ConfigCode": "6"
+  },
+  {
+    "Unit": "software",
+    "EventName": "alignment-faults",
+    "BriefDescription": "Number of kernel handled memory alignment faults",
+    "ConfigCode": "7"
+  },
+  {
+    "Unit": "software",
+    "EventName": "emulation-faults",
+    "BriefDescription": "Number of kernel handled unimplemented instruction faults handled through emulation",
+    "ConfigCode": "8"
+  },
+  {
+    "Unit": "software",
+    "EventName": "dummy",
+    "BriefDescription": "A placeholder event that doesn't count anything",
+    "ConfigCode": "9"
+  },
+  {
+    "Unit": "software",
+    "EventName": "bpf-output",
+    "BriefDescription": "An event used by BPF programs to write to the perf ring buffer",
+    "ConfigCode": "10"
+  },
+  {
+    "Unit": "software",
+    "EventName": "cgroup-switches",
+    "BriefDescription": "Number of context switches to a task in a different cgroup",
+    "ConfigCode": "11"
+  }
+]
diff --git a/tools/perf/pmu-events/empty-pmu-events.c b/tools/perf/pmu-events/empty-pmu-events.c
index a4569a74db07..7d179d703ab1 100644
--- a/tools/perf/pmu-events/empty-pmu-events.c
+++ b/tools/perf/pmu-events/empty-pmu-events.c
@@ -19,109 +19,147 @@ struct pmu_table_entry {
 };
 
 static const char *const big_c_string =
-/* offset=0 */ "tool\000"
-/* offset=5 */ "duration_time\000tool\000Wall clock interval time in nanoseconds\000config=1\000\00000\000\000\000\000\000"
-/* offset=81 */ "user_time\000tool\000User (non-kernel) time in nanoseconds\000config=2\000\00000\000\000\000\000\000"
-/* offset=151 */ "system_time\000tool\000System/kernel time in nanoseconds\000config=3\000\00000\000\000\000\000\000"
-/* offset=219 */ "has_pmem\000tool\0001 if persistent memory installed otherwise 0\000config=4\000\00000\000\000\000\000\000"
-/* offset=295 */ "num_cores\000tool\000Number of cores. A core consists of 1 or more thread, with each thread being associated with a logical Linux CPU\000config=5\000\00000\000\000\000\000\000"
-/* offset=440 */ "num_cpus\000tool\000Number of logical Linux CPUs. There may be multiple such CPUs on a core\000config=6\000\00000\000\000\000\000\000"
-/* offset=543 */ "num_cpus_online\000tool\000Number of online logical Linux CPUs. There may be multiple such CPUs on a core\000config=7\000\00000\000\000\000\000\000"
-/* offset=660 */ "num_dies\000tool\000Number of dies. Each die has 1 or more cores\000config=8\000\00000\000\000\000\000\000"
-/* offset=736 */ "num_packages\000tool\000Number of packages. Each package has 1 or more die\000config=9\000\00000\000\000\000\000\000"
-/* offset=822 */ "slots\000tool\000Number of functional units that in parallel can execute parts of an instruction\000config=0xa\000\00000\000\000\000\000\000"
-/* offset=932 */ "smt_on\000tool\0001 if simultaneous multithreading (aka hyperthreading) is enable otherwise 0\000config=0xb\000\00000\000\000\000\000\000"
-/* offset=1039 */ "system_tsc_freq\000tool\000The amount a Time Stamp Counter (TSC) increases per second\000config=0xc\000\00000\000\000\000\000\000"
-/* offset=1138 */ "default_core\000"
-/* offset=1151 */ "bp_l1_btb_correct\000branch\000L1 BTB Correction\000event=0x8a\000\00000\000\000\000\000\000"
-/* offset=1213 */ "bp_l2_btb_correct\000branch\000L2 BTB Correction\000event=0x8b\000\00000\000\000\000\000\000"
-/* offset=1275 */ "l3_cache_rd\000cache\000L3 cache access, read\000event=0x40\000\00000\000\000\000\000Attributable Level 3 cache access, read\000"
-/* offset=1373 */ "segment_reg_loads.any\000other\000Number of segment register loads\000event=6,period=200000,umask=0x80\000\00000\000\000\000\000\000"
-/* offset=1475 */ "dispatch_blocked.any\000other\000Memory cluster signals to block micro-op dispatch for any reason\000event=9,period=200000,umask=0x20\000\00000\000\000\000\000\000"
-/* offset=1608 */ "eist_trans\000other\000Number of Enhanced Intel SpeedStep(R) Technology (EIST) transitions\000event=0x3a,period=200000\000\00000\000\000\000\000\000"
-/* offset=1726 */ "hisi_sccl,ddrc\000"
-/* offset=1741 */ "uncore_hisi_ddrc.flux_wcmd\000uncore\000DDRC write commands\000event=2\000\00000\000\000\000\000\000"
-/* offset=1811 */ "uncore_cbox\000"
-/* offset=1823 */ "unc_cbo_xsnp_response.miss_eviction\000uncore\000A cross-core snoop resulted from L3 Eviction which misses in some processor core\000event=0x22,umask=0x81\000\00000\000\000\000\000\000"
-/* offset=1977 */ "event-hyphen\000uncore\000UNC_CBO_HYPHEN\000event=0xe0\000\00000\000\000\000\000\000"
-/* offset=2031 */ "event-two-hyph\000uncore\000UNC_CBO_TWO_HYPH\000event=0xc0\000\00000\000\000\000\000\000"
-/* offset=2089 */ "hisi_sccl,l3c\000"
-/* offset=2103 */ "uncore_hisi_l3c.rd_hit_cpipe\000uncore\000Total read hits\000event=7\000\00000\000\000\000\000\000"
-/* offset=2171 */ "uncore_imc_free_running\000"
-/* offset=2195 */ "uncore_imc_free_running.cache_miss\000uncore\000Total cache misses\000event=0x12\000\00000\000\000\000\000\000"
-/* offset=2275 */ "uncore_imc\000"
-/* offset=2286 */ "uncore_imc.cache_hits\000uncore\000Total cache hits\000event=0x34\000\00000\000\000\000\000\000"
-/* offset=2351 */ "uncore_sys_ddr_pmu\000"
-/* offset=2370 */ "sys_ddr_pmu.write_cycles\000uncore\000ddr write-cycles event\000event=0x2b\000v8\00000\000\000\000\000\000"
-/* offset=2446 */ "uncore_sys_ccn_pmu\000"
-/* offset=2465 */ "sys_ccn_pmu.read_cycles\000uncore\000ccn read-cycles event\000config=0x2c\0000x01\00000\000\000\000\000\000"
-/* offset=2542 */ "uncore_sys_cmn_pmu\000"
-/* offset=2561 */ "sys_cmn_pmu.hnf_cache_miss\000uncore\000Counts total cache misses in first lookup result (high priority)\000eventid=1,type=5\000(434|436|43c|43a).*\00000\000\000\000\000\000"
-/* offset=2704 */ "CPI\000\0001 / IPC\000\000\000\000\000\000\000\00000"
-/* offset=2726 */ "IPC\000group1\000inst_retired.any / cpu_clk_unhalted.thread\000\000\000\000\000\000\000\00000"
-/* offset=2789 */ "Frontend_Bound_SMT\000\000idq_uops_not_delivered.core / (4 * (cpu_clk_unhalted.thread / 2 * (1 + cpu_clk_unhalted.one_thread_active / cpu_clk_unhalted.ref_xclk)))\000\000\000\000\000\000\000\00000"
-/* offset=2955 */ "dcache_miss_cpi\000\000l1d\\-loads\\-misses / inst_retired.any\000\000\000\000\000\000\000\00000"
-/* offset=3019 */ "icache_miss_cycles\000\000l1i\\-loads\\-misses / inst_retired.any\000\000\000\000\000\000\000\00000"
-/* offset=3086 */ "cache_miss_cycles\000group1\000dcache_miss_cpi + icache_miss_cycles\000\000\000\000\000\000\000\00000"
-/* offset=3157 */ "DCache_L2_All_Hits\000\000l2_rqsts.demand_data_rd_hit + l2_rqsts.pf_hit + l2_rqsts.rfo_hit\000\000\000\000\000\000\000\00000"
-/* offset=3251 */ "DCache_L2_All_Miss\000\000max(l2_rqsts.all_demand_data_rd - l2_rqsts.demand_data_rd_hit, 0) + l2_rqsts.pf_miss + l2_rqsts.rfo_miss\000\000\000\000\000\000\000\00000"
-/* offset=3385 */ "DCache_L2_All\000\000DCache_L2_All_Hits + DCache_L2_All_Miss\000\000\000\000\000\000\000\00000"
-/* offset=3449 */ "DCache_L2_Hits\000\000d_ratio(DCache_L2_All_Hits, DCache_L2_All)\000\000\000\000\000\000\000\00000"
-/* offset=3517 */ "DCache_L2_Misses\000\000d_ratio(DCache_L2_All_Miss, DCache_L2_All)\000\000\000\000\000\000\000\00000"
-/* offset=3587 */ "M1\000\000ipc + M2\000\000\000\000\000\000\000\00000"
-/* offset=3609 */ "M2\000\000ipc + M1\000\000\000\000\000\000\000\00000"
-/* offset=3631 */ "M3\000\0001 / M3\000\000\000\000\000\000\000\00000"
-/* offset=3651 */ "L1D_Cache_Fill_BW\000\00064 * l1d.replacement / 1e9 / duration_time\000\000\000\000\000\000\000\00000"
+/* offset=0 */ "software\000"
+/* offset=9 */ "cpu-clock\000software\000Per-CPU high-resolution timer based event\000config=0\000\00000\000\000\000\000\000"
+/* offset=87 */ "task-clock\000software\000Task based high-resolution timer based event\000config=1\000\00000\000\000\000\000\000"
+/* offset=169 */ "faults\000software\000Number of page faults [This event is an alias of page-faults]\000config=2\000\00000\000\000\000\000\000"
+/* offset=264 */ "page-faults\000software\000Number of page faults [This event is an alias of faults]\000config=2\000\00000\000\000\000\000\000"
+/* offset=359 */ "context-switches\000software\000Number of context switches [This event is an alias of cs]\000config=3\000\00000\000\000\000\000\000"
+/* offset=460 */ "cs\000software\000Number of context switches [This event is an alias of context-switches]\000config=3\000\00000\000\000\000\000\000"
+/* offset=561 */ "cpu-migrations\000software\000Number of times a process has migrated to a new CPU [This event is an alias of migrations]\000config=4\000\00000\000\000\000\000\000"
+/* offset=693 */ "migrations\000software\000Number of times a process has migrated to a new CPU [This event is an alias of cpu-migrations]\000config=4\000\00000\000\000\000\000\000"
+/* offset=825 */ "minor-faults\000software\000Number of minor page faults. Minor faults don't require I/O to handle\000config=5\000\00000\000\000\000\000\000"
+/* offset=934 */ "major-faults\000software\000Number of major page faults. Major faults require I/O to handle\000config=6\000\00000\000\000\000\000\000"
+/* offset=1037 */ "alignment-faults\000software\000Number of kernel handled memory alignment faults\000config=7\000\00000\000\000\000\000\000"
+/* offset=1129 */ "emulation-faults\000software\000Number of kernel handled unimplemented instruction faults handled through emulation\000config=8\000\00000\000\000\000\000\000"
+/* offset=1256 */ "dummy\000software\000A placeholder event that doesn't count anything\000config=9\000\00000\000\000\000\000\000"
+/* offset=1336 */ "bpf-output\000software\000An event used by BPF programs to write to the perf ring buffer\000config=0xa\000\00000\000\000\000\000\000"
+/* offset=1438 */ "cgroup-switches\000software\000Number of context switches to a task in a different cgroup\000config=0xb\000\00000\000\000\000\000\000"
+/* offset=1541 */ "tool\000"
+/* offset=1546 */ "duration_time\000tool\000Wall clock interval time in nanoseconds\000config=1\000\00000\000\000\000\000\000"
+/* offset=1622 */ "user_time\000tool\000User (non-kernel) time in nanoseconds\000config=2\000\00000\000\000\000\000\000"
+/* offset=1692 */ "system_time\000tool\000System/kernel time in nanoseconds\000config=3\000\00000\000\000\000\000\000"
+/* offset=1760 */ "has_pmem\000tool\0001 if persistent memory installed otherwise 0\000config=4\000\00000\000\000\000\000\000"
+/* offset=1836 */ "num_cores\000tool\000Number of cores. A core consists of 1 or more thread, with each thread being associated with a logical Linux CPU\000config=5\000\00000\000\000\000\000\000"
+/* offset=1981 */ "num_cpus\000tool\000Number of logical Linux CPUs. There may be multiple such CPUs on a core\000config=6\000\00000\000\000\000\000\000"
+/* offset=2084 */ "num_cpus_online\000tool\000Number of online logical Linux CPUs. There may be multiple such CPUs on a core\000config=7\000\00000\000\000\000\000\000"
+/* offset=2201 */ "num_dies\000tool\000Number of dies. Each die has 1 or more cores\000config=8\000\00000\000\000\000\000\000"
+/* offset=2277 */ "num_packages\000tool\000Number of packages. Each package has 1 or more die\000config=9\000\00000\000\000\000\000\000"
+/* offset=2363 */ "slots\000tool\000Number of functional units that in parallel can execute parts of an instruction\000config=0xa\000\00000\000\000\000\000\000"
+/* offset=2473 */ "smt_on\000tool\0001 if simultaneous multithreading (aka hyperthreading) is enable otherwise 0\000config=0xb\000\00000\000\000\000\000\000"
+/* offset=2580 */ "system_tsc_freq\000tool\000The amount a Time Stamp Counter (TSC) increases per second\000config=0xc\000\00000\000\000\000\000\000"
+/* offset=2679 */ "default_core\000"
+/* offset=2692 */ "bp_l1_btb_correct\000branch\000L1 BTB Correction\000event=0x8a\000\00000\000\000\000\000\000"
+/* offset=2754 */ "bp_l2_btb_correct\000branch\000L2 BTB Correction\000event=0x8b\000\00000\000\000\000\000\000"
+/* offset=2816 */ "l3_cache_rd\000cache\000L3 cache access, read\000event=0x40\000\00000\000\000\000\000Attributable Level 3 cache access, read\000"
+/* offset=2914 */ "segment_reg_loads.any\000other\000Number of segment register loads\000event=6,period=200000,umask=0x80\000\00000\000\000\000\000\000"
+/* offset=3016 */ "dispatch_blocked.any\000other\000Memory cluster signals to block micro-op dispatch for any reason\000event=9,period=200000,umask=0x20\000\00000\000\000\000\000\000"
+/* offset=3149 */ "eist_trans\000other\000Number of Enhanced Intel SpeedStep(R) Technology (EIST) transitions\000event=0x3a,period=200000\000\00000\000\000\000\000\000"
+/* offset=3267 */ "hisi_sccl,ddrc\000"
+/* offset=3282 */ "uncore_hisi_ddrc.flux_wcmd\000uncore\000DDRC write commands\000event=2\000\00000\000\000\000\000\000"
+/* offset=3352 */ "uncore_cbox\000"
+/* offset=3364 */ "unc_cbo_xsnp_response.miss_eviction\000uncore\000A cross-core snoop resulted from L3 Eviction which misses in some processor core\000event=0x22,umask=0x81\000\00000\000\000\000\000\000"
+/* offset=3518 */ "event-hyphen\000uncore\000UNC_CBO_HYPHEN\000event=0xe0\000\00000\000\000\000\000\000"
+/* offset=3572 */ "event-two-hyph\000uncore\000UNC_CBO_TWO_HYPH\000event=0xc0\000\00000\000\000\000\000\000"
+/* offset=3630 */ "hisi_sccl,l3c\000"
+/* offset=3644 */ "uncore_hisi_l3c.rd_hit_cpipe\000uncore\000Total read hits\000event=7\000\00000\000\000\000\000\000"
+/* offset=3712 */ "uncore_imc_free_running\000"
+/* offset=3736 */ "uncore_imc_free_running.cache_miss\000uncore\000Total cache misses\000event=0x12\000\00000\000\000\000\000\000"
+/* offset=3816 */ "uncore_imc\000"
+/* offset=3827 */ "uncore_imc.cache_hits\000uncore\000Total cache hits\000event=0x34\000\00000\000\000\000\000\000"
+/* offset=3892 */ "uncore_sys_ddr_pmu\000"
+/* offset=3911 */ "sys_ddr_pmu.write_cycles\000uncore\000ddr write-cycles event\000event=0x2b\000v8\00000\000\000\000\000\000"
+/* offset=3987 */ "uncore_sys_ccn_pmu\000"
+/* offset=4006 */ "sys_ccn_pmu.read_cycles\000uncore\000ccn read-cycles event\000config=0x2c\0000x01\00000\000\000\000\000\000"
+/* offset=4083 */ "uncore_sys_cmn_pmu\000"
+/* offset=4102 */ "sys_cmn_pmu.hnf_cache_miss\000uncore\000Counts total cache misses in first lookup result (high priority)\000eventid=1,type=5\000(434|436|43c|43a).*\00000\000\000\000\000\000"
+/* offset=4245 */ "CPI\000\0001 / IPC\000\000\000\000\000\000\000\00000"
+/* offset=4267 */ "IPC\000group1\000inst_retired.any / cpu_clk_unhalted.thread\000\000\000\000\000\000\000\00000"
+/* offset=4330 */ "Frontend_Bound_SMT\000\000idq_uops_not_delivered.core / (4 * (cpu_clk_unhalted.thread / 2 * (1 + cpu_clk_unhalted.one_thread_active / cpu_clk_unhalted.ref_xclk)))\000\000\000\000\000\000\000\00000"
+/* offset=4496 */ "dcache_miss_cpi\000\000l1d\\-loads\\-misses / inst_retired.any\000\000\000\000\000\000\000\00000"
+/* offset=4560 */ "icache_miss_cycles\000\000l1i\\-loads\\-misses / inst_retired.any\000\000\000\000\000\000\000\00000"
+/* offset=4627 */ "cache_miss_cycles\000group1\000dcache_miss_cpi + icache_miss_cycles\000\000\000\000\000\000\000\00000"
+/* offset=4698 */ "DCache_L2_All_Hits\000\000l2_rqsts.demand_data_rd_hit + l2_rqsts.pf_hit + l2_rqsts.rfo_hit\000\000\000\000\000\000\000\00000"
+/* offset=4792 */ "DCache_L2_All_Miss\000\000max(l2_rqsts.all_demand_data_rd - l2_rqsts.demand_data_rd_hit, 0) + l2_rqsts.pf_miss + l2_rqsts.rfo_miss\000\000\000\000\000\000\000\00000"
+/* offset=4926 */ "DCache_L2_All\000\000DCache_L2_All_Hits + DCache_L2_All_Miss\000\000\000\000\000\000\000\00000"
+/* offset=4990 */ "DCache_L2_Hits\000\000d_ratio(DCache_L2_All_Hits, DCache_L2_All)\000\000\000\000\000\000\000\00000"
+/* offset=5058 */ "DCache_L2_Misses\000\000d_ratio(DCache_L2_All_Miss, DCache_L2_All)\000\000\000\000\000\000\000\00000"
+/* offset=5128 */ "M1\000\000ipc + M2\000\000\000\000\000\000\000\00000"
+/* offset=5150 */ "M2\000\000ipc + M1\000\000\000\000\000\000\000\00000"
+/* offset=5172 */ "M3\000\0001 / M3\000\000\000\000\000\000\000\00000"
+/* offset=5192 */ "L1D_Cache_Fill_BW\000\00064 * l1d.replacement / 1e9 / duration_time\000\000\000\000\000\000\000\00000"
 ;
 
+static const struct compact_pmu_event pmu_events__common_software[] = {
+{ 1037 }, /* alignment-faults\000software\000Number of kernel handled memory alignment faults\000config=7\000\00000\000\000\000\000\000 */
+{ 1336 }, /* bpf-output\000software\000An event used by BPF programs to write to the perf ring buffer\000config=0xa\000\00000\000\000\000\000\000 */
+{ 1438 }, /* cgroup-switches\000software\000Number of context switches to a task in a different cgroup\000config=0xb\000\00000\000\000\000\000\000 */
+{ 359 }, /* context-switches\000software\000Number of context switches [This event is an alias of cs]\000config=3\000\00000\000\000\000\000\000 */
+{ 9 }, /* cpu-clock\000software\000Per-CPU high-resolution timer based event\000config=0\000\00000\000\000\000\000\000 */
+{ 561 }, /* cpu-migrations\000software\000Number of times a process has migrated to a new CPU [This event is an alias of migrations]\000config=4\000\00000\000\000\000\000\000 */
+{ 460 }, /* cs\000software\000Number of context switches [This event is an alias of context-switches]\000config=3\000\00000\000\000\000\000\000 */
+{ 1256 }, /* dummy\000software\000A placeholder event that doesn't count anything\000config=9\000\00000\000\000\000\000\000 */
+{ 1129 }, /* emulation-faults\000software\000Number of kernel handled unimplemented instruction faults handled through emulation\000config=8\000\00000\000\000\000\000\000 */
+{ 169 }, /* faults\000software\000Number of page faults [This event is an alias of page-faults]\000config=2\000\00000\000\000\000\000\000 */
+{ 934 }, /* major-faults\000software\000Number of major page faults. Major faults require I/O to handle\000config=6\000\00000\000\000\000\000\000 */
+{ 693 }, /* migrations\000software\000Number of times a process has migrated to a new CPU [This event is an alias of cpu-migrations]\000config=4\000\00000\000\000\000\000\000 */
+{ 825 }, /* minor-faults\000software\000Number of minor page faults. Minor faults don't require I/O to handle\000config=5\000\00000\000\000\000\000\000 */
+{ 264 }, /* page-faults\000software\000Number of page faults [This event is an alias of faults]\000config=2\000\00000\000\000\000\000\000 */
+{ 87 }, /* task-clock\000software\000Task based high-resolution timer based event\000config=1\000\00000\000\000\000\000\000 */
+};
 static const struct compact_pmu_event pmu_events__common_tool[] = {
-{ 5 }, /* duration_time\000tool\000Wall clock interval time in nanoseconds\000config=1\000\00000\000\000\000\000\000 */
-{ 219 }, /* has_pmem\000tool\0001 if persistent memory installed otherwise 0\000config=4\000\00000\000\000\000\000\000 */
-{ 295 }, /* num_cores\000tool\000Number of cores. A core consists of 1 or more thread, with each thread being associated with a logical Linux CPU\000config=5\000\00000\000\000\000\000\000 */
-{ 440 }, /* num_cpus\000tool\000Number of logical Linux CPUs. There may be multiple such CPUs on a core\000config=6\000\00000\000\000\000\000\000 */
-{ 543 }, /* num_cpus_online\000tool\000Number of online logical Linux CPUs. There may be multiple such CPUs on a core\000config=7\000\00000\000\000\000\000\000 */
-{ 660 }, /* num_dies\000tool\000Number of dies. Each die has 1 or more cores\000config=8\000\00000\000\000\000\000\000 */
-{ 736 }, /* num_packages\000tool\000Number of packages. Each package has 1 or more die\000config=9\000\00000\000\000\000\000\000 */
-{ 822 }, /* slots\000tool\000Number of functional units that in parallel can execute parts of an instruction\000config=0xa\000\00000\000\000\000\000\000 */
-{ 932 }, /* smt_on\000tool\0001 if simultaneous multithreading (aka hyperthreading) is enable otherwise 0\000config=0xb\000\00000\000\000\000\000\000 */
-{ 151 }, /* system_time\000tool\000System/kernel time in nanoseconds\000config=3\000\00000\000\000\000\000\000 */
-{ 1039 }, /* system_tsc_freq\000tool\000The amount a Time Stamp Counter (TSC) increases per second\000config=0xc\000\00000\000\000\000\000\000 */
-{ 81 }, /* user_time\000tool\000User (non-kernel) time in nanoseconds\000config=2\000\00000\000\000\000\000\000 */
+{ 1546 }, /* duration_time\000tool\000Wall clock interval time in nanoseconds\000config=1\000\00000\000\000\000\000\000 */
+{ 1760 }, /* has_pmem\000tool\0001 if persistent memory installed otherwise 0\000config=4\000\00000\000\000\000\000\000 */
+{ 1836 }, /* num_cores\000tool\000Number of cores. A core consists of 1 or more thread, with each thread being associated with a logical Linux CPU\000config=5\000\00000\000\000\000\000\000 */
+{ 1981 }, /* num_cpus\000tool\000Number of logical Linux CPUs. There may be multiple such CPUs on a core\000config=6\000\00000\000\000\000\000\000 */
+{ 2084 }, /* num_cpus_online\000tool\000Number of online logical Linux CPUs. There may be multiple such CPUs on a core\000config=7\000\00000\000\000\000\000\000 */
+{ 2201 }, /* num_dies\000tool\000Number of dies. Each die has 1 or more cores\000config=8\000\00000\000\000\000\000\000 */
+{ 2277 }, /* num_packages\000tool\000Number of packages. Each package has 1 or more die\000config=9\000\00000\000\000\000\000\000 */
+{ 2363 }, /* slots\000tool\000Number of functional units that in parallel can execute parts of an instruction\000config=0xa\000\00000\000\000\000\000\000 */
+{ 2473 }, /* smt_on\000tool\0001 if simultaneous multithreading (aka hyperthreading) is enable otherwise 0\000config=0xb\000\00000\000\000\000\000\000 */
+{ 1692 }, /* system_time\000tool\000System/kernel time in nanoseconds\000config=3\000\00000\000\000\000\000\000 */
+{ 2580 }, /* system_tsc_freq\000tool\000The amount a Time Stamp Counter (TSC) increases per second\000config=0xc\000\00000\000\000\000\000\000 */
+{ 1622 }, /* user_time\000tool\000User (non-kernel) time in nanoseconds\000config=2\000\00000\000\000\000\000\000 */
 
 };
 
 const struct pmu_table_entry pmu_events__common[] = {
+{
+     .entries = pmu_events__common_software,
+     .num_entries = ARRAY_SIZE(pmu_events__common_software),
+     .pmu_name = { 0 /* software\000 */ },
+},
 {
      .entries = pmu_events__common_tool,
      .num_entries = ARRAY_SIZE(pmu_events__common_tool),
-     .pmu_name = { 0 /* tool\000 */ },
+     .pmu_name = { 1541 /* tool\000 */ },
 },
 };
 
 static const struct compact_pmu_event pmu_events__test_soc_cpu_default_core[] = {
-{ 1151 }, /* bp_l1_btb_correct\000branch\000L1 BTB Correction\000event=0x8a\000\00000\000\000\000\000\000 */
-{ 1213 }, /* bp_l2_btb_correct\000branch\000L2 BTB Correction\000event=0x8b\000\00000\000\000\000\000\000 */
-{ 1475 }, /* dispatch_blocked.any\000other\000Memory cluster signals to block micro-op dispatch for any reason\000event=9,period=200000,umask=0x20\000\00000\000\000\000\000\000 */
-{ 1608 }, /* eist_trans\000other\000Number of Enhanced Intel SpeedStep(R) Technology (EIST) transitions\000event=0x3a,period=200000\000\00000\000\000\000\000\000 */
-{ 1275 }, /* l3_cache_rd\000cache\000L3 cache access, read\000event=0x40\000\00000\000\000\000\000Attributable Level 3 cache access, read\000 */
-{ 1373 }, /* segment_reg_loads.any\000other\000Number of segment register loads\000event=6,period=200000,umask=0x80\000\00000\000\000\000\000\000 */
+{ 2692 }, /* bp_l1_btb_correct\000branch\000L1 BTB Correction\000event=0x8a\000\00000\000\000\000\000\000 */
+{ 2754 }, /* bp_l2_btb_correct\000branch\000L2 BTB Correction\000event=0x8b\000\00000\000\000\000\000\000 */
+{ 3016 }, /* dispatch_blocked.any\000other\000Memory cluster signals to block micro-op dispatch for any reason\000event=9,period=200000,umask=0x20\000\00000\000\000\000\000\000 */
+{ 3149 }, /* eist_trans\000other\000Number of Enhanced Intel SpeedStep(R) Technology (EIST) transitions\000event=0x3a,period=200000\000\00000\000\000\000\000\000 */
+{ 2816 }, /* l3_cache_rd\000cache\000L3 cache access, read\000event=0x40\000\00000\000\000\000\000Attributable Level 3 cache access, read\000 */
+{ 2914 }, /* segment_reg_loads.any\000other\000Number of segment register loads\000event=6,period=200000,umask=0x80\000\00000\000\000\000\000\000 */
 };
 static const struct compact_pmu_event pmu_events__test_soc_cpu_hisi_sccl_ddrc[] = {
-{ 1741 }, /* uncore_hisi_ddrc.flux_wcmd\000uncore\000DDRC write commands\000event=2\000\00000\000\000\000\000\000 */
+{ 3282 }, /* uncore_hisi_ddrc.flux_wcmd\000uncore\000DDRC write commands\000event=2\000\00000\000\000\000\000\000 */
 };
 static const struct compact_pmu_event pmu_events__test_soc_cpu_hisi_sccl_l3c[] = {
-{ 2103 }, /* uncore_hisi_l3c.rd_hit_cpipe\000uncore\000Total read hits\000event=7\000\00000\000\000\000\000\000 */
+{ 3644 }, /* uncore_hisi_l3c.rd_hit_cpipe\000uncore\000Total read hits\000event=7\000\00000\000\000\000\000\000 */
 };
 static const struct compact_pmu_event pmu_events__test_soc_cpu_uncore_cbox[] = {
-{ 1977 }, /* event-hyphen\000uncore\000UNC_CBO_HYPHEN\000event=0xe0\000\00000\000\000\000\000\000 */
-{ 2031 }, /* event-two-hyph\000uncore\000UNC_CBO_TWO_HYPH\000event=0xc0\000\00000\000\000\000\000\000 */
-{ 1823 }, /* unc_cbo_xsnp_response.miss_eviction\000uncore\000A cross-core snoop resulted from L3 Eviction which misses in some processor core\000event=0x22,umask=0x81\000\00000\000\000\000\000\000 */
+{ 3518 }, /* event-hyphen\000uncore\000UNC_CBO_HYPHEN\000event=0xe0\000\00000\000\000\000\000\000 */
+{ 3572 }, /* event-two-hyph\000uncore\000UNC_CBO_TWO_HYPH\000event=0xc0\000\00000\000\000\000\000\000 */
+{ 3364 }, /* unc_cbo_xsnp_response.miss_eviction\000uncore\000A cross-core snoop resulted from L3 Eviction which misses in some processor core\000event=0x22,umask=0x81\000\00000\000\000\000\000\000 */
 };
 static const struct compact_pmu_event pmu_events__test_soc_cpu_uncore_imc[] = {
-{ 2286 }, /* uncore_imc.cache_hits\000uncore\000Total cache hits\000event=0x34\000\00000\000\000\000\000\000 */
+{ 3827 }, /* uncore_imc.cache_hits\000uncore\000Total cache hits\000event=0x34\000\00000\000\000\000\000\000 */
 };
 static const struct compact_pmu_event pmu_events__test_soc_cpu_uncore_imc_free_running[] = {
-{ 2195 }, /* uncore_imc_free_running.cache_miss\000uncore\000Total cache misses\000event=0x12\000\00000\000\000\000\000\000 */
+{ 3736 }, /* uncore_imc_free_running.cache_miss\000uncore\000Total cache misses\000event=0x12\000\00000\000\000\000\000\000 */
 
 };
 
@@ -129,51 +167,51 @@ const struct pmu_table_entry pmu_events__test_soc_cpu[] = {
 {
      .entries = pmu_events__test_soc_cpu_default_core,
      .num_entries = ARRAY_SIZE(pmu_events__test_soc_cpu_default_core),
-     .pmu_name = { 1138 /* default_core\000 */ },
+     .pmu_name = { 2679 /* default_core\000 */ },
 },
 {
      .entries = pmu_events__test_soc_cpu_hisi_sccl_ddrc,
      .num_entries = ARRAY_SIZE(pmu_events__test_soc_cpu_hisi_sccl_ddrc),
-     .pmu_name = { 1726 /* hisi_sccl,ddrc\000 */ },
+     .pmu_name = { 3267 /* hisi_sccl,ddrc\000 */ },
 },
 {
      .entries = pmu_events__test_soc_cpu_hisi_sccl_l3c,
      .num_entries = ARRAY_SIZE(pmu_events__test_soc_cpu_hisi_sccl_l3c),
-     .pmu_name = { 2089 /* hisi_sccl,l3c\000 */ },
+     .pmu_name = { 3630 /* hisi_sccl,l3c\000 */ },
 },
 {
      .entries = pmu_events__test_soc_cpu_uncore_cbox,
      .num_entries = ARRAY_SIZE(pmu_events__test_soc_cpu_uncore_cbox),
-     .pmu_name = { 1811 /* uncore_cbox\000 */ },
+     .pmu_name = { 3352 /* uncore_cbox\000 */ },
 },
 {
      .entries = pmu_events__test_soc_cpu_uncore_imc,
      .num_entries = ARRAY_SIZE(pmu_events__test_soc_cpu_uncore_imc),
-     .pmu_name = { 2275 /* uncore_imc\000 */ },
+     .pmu_name = { 3816 /* uncore_imc\000 */ },
 },
 {
      .entries = pmu_events__test_soc_cpu_uncore_imc_free_running,
      .num_entries = ARRAY_SIZE(pmu_events__test_soc_cpu_uncore_imc_free_running),
-     .pmu_name = { 2171 /* uncore_imc_free_running\000 */ },
+     .pmu_name = { 3712 /* uncore_imc_free_running\000 */ },
 },
 };
 
 static const struct compact_pmu_event pmu_metrics__test_soc_cpu_default_core[] = {
-{ 2704 }, /* CPI\000\0001 / IPC\000\000\000\000\000\000\000\00000 */
-{ 3385 }, /* DCache_L2_All\000\000DCache_L2_All_Hits + DCache_L2_All_Miss\000\000\000\000\000\000\000\00000 */
-{ 3157 }, /* DCache_L2_All_Hits\000\000l2_rqsts.demand_data_rd_hit + l2_rqsts.pf_hit + l2_rqsts.rfo_hit\000\000\000\000\000\000\000\00000 */
-{ 3251 }, /* DCache_L2_All_Miss\000\000max(l2_rqsts.all_demand_data_rd - l2_rqsts.demand_data_rd_hit, 0) + l2_rqsts.pf_miss + l2_rqsts.rfo_miss\000\000\000\000\000\000\000\00000 */
-{ 3449 }, /* DCache_L2_Hits\000\000d_ratio(DCache_L2_All_Hits, DCache_L2_All)\000\000\000\000\000\000\000\00000 */
-{ 3517 }, /* DCache_L2_Misses\000\000d_ratio(DCache_L2_All_Miss, DCache_L2_All)\000\000\000\000\000\000\000\00000 */
-{ 2789 }, /* Frontend_Bound_SMT\000\000idq_uops_not_delivered.core / (4 * (cpu_clk_unhalted.thread / 2 * (1 + cpu_clk_unhalted.one_thread_active / cpu_clk_unhalted.ref_xclk)))\000\000\000\000\000\000\000\00000 */
-{ 2726 }, /* IPC\000group1\000inst_retired.any / cpu_clk_unhalted.thread\000\000\000\000\000\000\000\00000 */
-{ 3651 }, /* L1D_Cache_Fill_BW\000\00064 * l1d.replacement / 1e9 / duration_time\000\000\000\000\000\000\000\00000 */
-{ 3587 }, /* M1\000\000ipc + M2\000\000\000\000\000\000\000\00000 */
-{ 3609 }, /* M2\000\000ipc + M1\000\000\000\000\000\000\000\00000 */
-{ 3631 }, /* M3\000\0001 / M3\000\000\000\000\000\000\000\00000 */
-{ 3086 }, /* cache_miss_cycles\000group1\000dcache_miss_cpi + icache_miss_cycles\000\000\000\000\000\000\000\00000 */
-{ 2955 }, /* dcache_miss_cpi\000\000l1d\\-loads\\-misses / inst_retired.any\000\000\000\000\000\000\000\00000 */
-{ 3019 }, /* icache_miss_cycles\000\000l1i\\-loads\\-misses / inst_retired.any\000\000\000\000\000\000\000\00000 */
+{ 4245 }, /* CPI\000\0001 / IPC\000\000\000\000\000\000\000\00000 */
+{ 4926 }, /* DCache_L2_All\000\000DCache_L2_All_Hits + DCache_L2_All_Miss\000\000\000\000\000\000\000\00000 */
+{ 4698 }, /* DCache_L2_All_Hits\000\000l2_rqsts.demand_data_rd_hit + l2_rqsts.pf_hit + l2_rqsts.rfo_hit\000\000\000\000\000\000\000\00000 */
+{ 4792 }, /* DCache_L2_All_Miss\000\000max(l2_rqsts.all_demand_data_rd - l2_rqsts.demand_data_rd_hit, 0) + l2_rqsts.pf_miss + l2_rqsts.rfo_miss\000\000\000\000\000\000\000\00000 */
+{ 4990 }, /* DCache_L2_Hits\000\000d_ratio(DCache_L2_All_Hits, DCache_L2_All)\000\000\000\000\000\000\000\00000 */
+{ 5058 }, /* DCache_L2_Misses\000\000d_ratio(DCache_L2_All_Miss, DCache_L2_All)\000\000\000\000\000\000\000\00000 */
+{ 4330 }, /* Frontend_Bound_SMT\000\000idq_uops_not_delivered.core / (4 * (cpu_clk_unhalted.thread / 2 * (1 + cpu_clk_unhalted.one_thread_active / cpu_clk_unhalted.ref_xclk)))\000\000\000\000\000\000\000\00000 */
+{ 4267 }, /* IPC\000group1\000inst_retired.any / cpu_clk_unhalted.thread\000\000\000\000\000\000\000\00000 */
+{ 5192 }, /* L1D_Cache_Fill_BW\000\00064 * l1d.replacement / 1e9 / duration_time\000\000\000\000\000\000\000\00000 */
+{ 5128 }, /* M1\000\000ipc + M2\000\000\000\000\000\000\000\00000 */
+{ 5150 }, /* M2\000\000ipc + M1\000\000\000\000\000\000\000\00000 */
+{ 5172 }, /* M3\000\0001 / M3\000\000\000\000\000\000\000\00000 */
+{ 4627 }, /* cache_miss_cycles\000group1\000dcache_miss_cpi + icache_miss_cycles\000\000\000\000\000\000\000\00000 */
+{ 4496 }, /* dcache_miss_cpi\000\000l1d\\-loads\\-misses / inst_retired.any\000\000\000\000\000\000\000\00000 */
+{ 4560 }, /* icache_miss_cycles\000\000l1i\\-loads\\-misses / inst_retired.any\000\000\000\000\000\000\000\00000 */
 
 };
 
@@ -181,18 +219,18 @@ const struct pmu_table_entry pmu_metrics__test_soc_cpu[] = {
 {
      .entries = pmu_metrics__test_soc_cpu_default_core,
      .num_entries = ARRAY_SIZE(pmu_metrics__test_soc_cpu_default_core),
-     .pmu_name = { 1138 /* default_core\000 */ },
+     .pmu_name = { 2679 /* default_core\000 */ },
 },
 };
 
 static const struct compact_pmu_event pmu_events__test_soc_sys_uncore_sys_ccn_pmu[] = {
-{ 2465 }, /* sys_ccn_pmu.read_cycles\000uncore\000ccn read-cycles event\000config=0x2c\0000x01\00000\000\000\000\000\000 */
+{ 4006 }, /* sys_ccn_pmu.read_cycles\000uncore\000ccn read-cycles event\000config=0x2c\0000x01\00000\000\000\000\000\000 */
 };
 static const struct compact_pmu_event pmu_events__test_soc_sys_uncore_sys_cmn_pmu[] = {
-{ 2561 }, /* sys_cmn_pmu.hnf_cache_miss\000uncore\000Counts total cache misses in first lookup result (high priority)\000eventid=1,type=5\000(434|436|43c|43a).*\00000\000\000\000\000\000 */
+{ 4102 }, /* sys_cmn_pmu.hnf_cache_miss\000uncore\000Counts total cache misses in first lookup result (high priority)\000eventid=1,type=5\000(434|436|43c|43a).*\00000\000\000\000\000\000 */
 };
 static const struct compact_pmu_event pmu_events__test_soc_sys_uncore_sys_ddr_pmu[] = {
-{ 2370 }, /* sys_ddr_pmu.write_cycles\000uncore\000ddr write-cycles event\000event=0x2b\000v8\00000\000\000\000\000\000 */
+{ 3911 }, /* sys_ddr_pmu.write_cycles\000uncore\000ddr write-cycles event\000event=0x2b\000v8\00000\000\000\000\000\000 */
 
 };
 
@@ -200,17 +238,17 @@ const struct pmu_table_entry pmu_events__test_soc_sys[] = {
 {
      .entries = pmu_events__test_soc_sys_uncore_sys_ccn_pmu,
      .num_entries = ARRAY_SIZE(pmu_events__test_soc_sys_uncore_sys_ccn_pmu),
-     .pmu_name = { 2446 /* uncore_sys_ccn_pmu\000 */ },
+     .pmu_name = { 3987 /* uncore_sys_ccn_pmu\000 */ },
 },
 {
      .entries = pmu_events__test_soc_sys_uncore_sys_cmn_pmu,
      .num_entries = ARRAY_SIZE(pmu_events__test_soc_sys_uncore_sys_cmn_pmu),
-     .pmu_name = { 2542 /* uncore_sys_cmn_pmu\000 */ },
+     .pmu_name = { 4083 /* uncore_sys_cmn_pmu\000 */ },
 },
 {
      .entries = pmu_events__test_soc_sys_uncore_sys_ddr_pmu,
      .num_entries = ARRAY_SIZE(pmu_events__test_soc_sys_uncore_sys_ddr_pmu),
-     .pmu_name = { 2351 /* uncore_sys_ddr_pmu\000 */ },
+     .pmu_name = { 3892 /* uncore_sys_ddr_pmu\000 */ },
 },
 };
 
@@ -632,8 +670,20 @@ static const struct pmu_events_map *map_for_pmu(struct perf_pmu *pmu)
 {
         struct perf_cpu cpu = {-1};
 
-        if (pmu)
+        if (pmu) {
+                for (size_t i=0; i < ARRAY_SIZE(pmu_events__common); i++) {
+                        const char *pmu_name = &big_c_string[pmu_events__common[i].pmu_name.offset];
+
+                        if (!strcmp(pmu_name, pmu->name)) {
+                                const struct pmu_events_map *map = &pmu_events_map[0];
+
+                                while (strcmp("common", map->arch))
+                                        map++;
+                                return map;
+                        }
+                }
                 cpu = perf_cpu_map__min(pmu->cpus);
+        }
         return map_for_cpu(cpu);
 }
 
diff --git a/tools/perf/pmu-events/jevents.py b/tools/perf/pmu-events/jevents.py
index e821155151ec..76c1e7b0bc22 100755
--- a/tools/perf/pmu-events/jevents.py
+++ b/tools/perf/pmu-events/jevents.py
@@ -295,6 +295,7 @@ class JsonEvent:
           'cpu_atom': 'cpu_atom',
           'ali_drw': 'ali_drw',
           'arm_cmn': 'arm_cmn',
+          'software': 'software',
           'tool': 'tool',
       }
       return table[unit] if unit in table else f'uncore_{unit.lower()}'
@@ -1158,8 +1159,20 @@ static const struct pmu_events_map *map_for_pmu(struct perf_pmu *pmu)
 {
         struct perf_cpu cpu = {-1};
 
-        if (pmu)
+        if (pmu) {
+                for (size_t i=0; i < ARRAY_SIZE(pmu_events__common); i++) {
+                        const char *pmu_name = &big_c_string[pmu_events__common[i].pmu_name.offset];
+
+                        if (!strcmp(pmu_name, pmu->name)) {
+                                const struct pmu_events_map *map = &pmu_events_map[0];
+
+                                while (strcmp("common", map->arch))
+                                        map++;
+                                return map;
+                        }
+                }
                 cpu = perf_cpu_map__min(pmu->cpus);
+        }
         return map_for_cpu(cpu);
 }
 
-- 
2.50.0.727.gbf7dc18ff4-goog


^ permalink raw reply related	[flat|nested] 41+ messages in thread

* [PATCH v7 03/16] perf parse-events: Remove non-json software events
  2025-07-14 16:43 [PATCH v7 00/16] New perf ilist app Ian Rogers
  2025-07-14 16:43 ` [PATCH v7 01/16] perf python: Add more exceptions on error paths Ian Rogers
  2025-07-14 16:43 ` [PATCH v7 02/16] perf jevents: Add common software event json Ian Rogers
@ 2025-07-14 16:43 ` Ian Rogers
  2025-07-24  0:20   ` Namhyung Kim
  2025-07-14 16:43 ` [PATCH v7 04/16] perf tp_pmu: Factor existing tracepoint logic to new file Ian Rogers
                   ` (13 subsequent siblings)
  16 siblings, 1 reply; 41+ messages in thread
From: Ian Rogers @ 2025-07-14 16:43 UTC (permalink / raw)
  To: Peter Zijlstra, Ingo Molnar, Arnaldo Carvalho de Melo,
	Namhyung Kim, Mark Rutland, Alexander Shishkin, Jiri Olsa,
	Ian Rogers, Adrian Hunter, Kan Liang, James Clark, Xu Yang,
	Masami Hiramatsu (Google), Collin Funk, Howard Chu, Weilin Wang,
	Andi Kleen, Dr. David Alan Gilbert, Thomas Richter, Tiezhu Yang,
	Gautam Menghani, Thomas Falcon, Chun-Tse Shao, linux-kernel,
	linux-perf-users

Remove the hard coded encodings from parse-events. This has the
consequence that software events are matched using the sysfs/json
priority, will be case insensitive and will be wildcarded across PMUs.
As there were software and hardware types in the parsing code, the
removal means software vs hardware logic can be removed and hardware
assumed.

Now the perf json provides detailed descriptions of software events,
remove the previous listing support that didn't contain event
descriptions. When globbing is required for the "sw" option in perf
list, use string PMU globbing as was done previously for the tool PMU.

Signed-off-by: Ian Rogers <irogers@google.com>
---
 tools/perf/builtin-list.c      | 19 ++++++-------
 tools/perf/util/parse-events.c | 51 ----------------------------------
 tools/perf/util/parse-events.h |  1 -
 tools/perf/util/parse-events.l | 38 +++++++++----------------
 tools/perf/util/parse-events.y | 29 ++++++++-----------
 tools/perf/util/print-events.c |  2 --
 6 files changed, 33 insertions(+), 107 deletions(-)

diff --git a/tools/perf/builtin-list.c b/tools/perf/builtin-list.c
index e9b595d75df2..674bb0afbf93 100644
--- a/tools/perf/builtin-list.c
+++ b/tools/perf/builtin-list.c
@@ -623,16 +623,17 @@ int cmd_list(int argc, const char **argv)
 		else if (strcmp(argv[i], "sw") == 0 ||
 			 strcmp(argv[i], "software") == 0) {
 			char *old_pmu_glob = default_ps.pmu_glob;
+			static const char * const sw_globs[] = { "software", "tool" };
 
-			print_symbol_events(&print_cb, ps, PERF_TYPE_SOFTWARE,
-					event_symbols_sw, PERF_COUNT_SW_MAX);
-			default_ps.pmu_glob = strdup("tool");
-			if (!default_ps.pmu_glob) {
-				ret = -1;
-				goto out;
+			for (size_t j = 0; j < ARRAY_SIZE(sw_globs); j++) {
+				default_ps.pmu_glob = strdup(sw_globs[j]);
+				if (!default_ps.pmu_glob) {
+					ret = -1;
+					goto out;
+				}
+				perf_pmus__print_pmu_events(&print_cb, ps);
+				zfree(&default_ps.pmu_glob);
 			}
-			perf_pmus__print_pmu_events(&print_cb, ps);
-			zfree(&default_ps.pmu_glob);
 			default_ps.pmu_glob = old_pmu_glob;
 		} else if (strcmp(argv[i], "cache") == 0 ||
 			 strcmp(argv[i], "hwcache") == 0)
@@ -679,8 +680,6 @@ int cmd_list(int argc, const char **argv)
 			default_ps.event_glob = s;
 			print_symbol_events(&print_cb, ps, PERF_TYPE_HARDWARE,
 					event_symbols_hw, PERF_COUNT_HW_MAX);
-			print_symbol_events(&print_cb, ps, PERF_TYPE_SOFTWARE,
-					event_symbols_sw, PERF_COUNT_SW_MAX);
 			print_hwcache_events(&print_cb, ps);
 			perf_pmus__print_pmu_events(&print_cb, ps);
 			print_tracepoint_events(&print_cb, ps);
diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c
index a59ae5ca0f89..1ae481c9802b 100644
--- a/tools/perf/util/parse-events.c
+++ b/tools/perf/util/parse-events.c
@@ -84,57 +84,6 @@ const struct event_symbol event_symbols_hw[PERF_COUNT_HW_MAX] = {
 	},
 };
 
-const struct event_symbol event_symbols_sw[PERF_COUNT_SW_MAX] = {
-	[PERF_COUNT_SW_CPU_CLOCK] = {
-		.symbol = "cpu-clock",
-		.alias  = "",
-	},
-	[PERF_COUNT_SW_TASK_CLOCK] = {
-		.symbol = "task-clock",
-		.alias  = "",
-	},
-	[PERF_COUNT_SW_PAGE_FAULTS] = {
-		.symbol = "page-faults",
-		.alias  = "faults",
-	},
-	[PERF_COUNT_SW_CONTEXT_SWITCHES] = {
-		.symbol = "context-switches",
-		.alias  = "cs",
-	},
-	[PERF_COUNT_SW_CPU_MIGRATIONS] = {
-		.symbol = "cpu-migrations",
-		.alias  = "migrations",
-	},
-	[PERF_COUNT_SW_PAGE_FAULTS_MIN] = {
-		.symbol = "minor-faults",
-		.alias  = "",
-	},
-	[PERF_COUNT_SW_PAGE_FAULTS_MAJ] = {
-		.symbol = "major-faults",
-		.alias  = "",
-	},
-	[PERF_COUNT_SW_ALIGNMENT_FAULTS] = {
-		.symbol = "alignment-faults",
-		.alias  = "",
-	},
-	[PERF_COUNT_SW_EMULATION_FAULTS] = {
-		.symbol = "emulation-faults",
-		.alias  = "",
-	},
-	[PERF_COUNT_SW_DUMMY] = {
-		.symbol = "dummy",
-		.alias  = "",
-	},
-	[PERF_COUNT_SW_BPF_OUTPUT] = {
-		.symbol = "bpf-output",
-		.alias  = "",
-	},
-	[PERF_COUNT_SW_CGROUP_SWITCHES] = {
-		.symbol = "cgroup-switches",
-		.alias  = "",
-	},
-};
-
 static const char *const event_types[] = {
 	[PERF_TYPE_HARDWARE]	= "hardware",
 	[PERF_TYPE_SOFTWARE]	= "software",
diff --git a/tools/perf/util/parse-events.h b/tools/perf/util/parse-events.h
index b47bf2810112..62dc7202e3ba 100644
--- a/tools/perf/util/parse-events.h
+++ b/tools/perf/util/parse-events.h
@@ -264,7 +264,6 @@ struct event_symbol {
 	const char	*alias;
 };
 extern const struct event_symbol event_symbols_hw[];
-extern const struct event_symbol event_symbols_sw[];
 
 char *parse_events_formats_error_string(char *additional_terms);
 
diff --git a/tools/perf/util/parse-events.l b/tools/perf/util/parse-events.l
index 4af7b9c1f44d..2034590eb789 100644
--- a/tools/perf/util/parse-events.l
+++ b/tools/perf/util/parse-events.l
@@ -117,12 +117,12 @@ do {								\
 	yyless(0);						\
 } while (0)
 
-static int sym(yyscan_t scanner, int type, int config)
+static int sym(yyscan_t scanner, int config)
 {
 	YYSTYPE *yylval = parse_events_get_lval(scanner);
 
-	yylval->num = (type << 16) + config;
-	return type == PERF_TYPE_HARDWARE ? PE_VALUE_SYM_HW : PE_VALUE_SYM_SW;
+	yylval->num = config;
+	return PE_VALUE_SYM_HW;
 }
 
 static int term(yyscan_t scanner, enum parse_events__term_type type)
@@ -391,28 +391,16 @@ r0x{num_raw_hex}	{ return str(yyscanner, PE_RAW); }
 <<EOF>>			{ BEGIN(INITIAL); }
 }
 
-cpu-cycles|cycles				{ return sym(yyscanner, PERF_TYPE_HARDWARE, PERF_COUNT_HW_CPU_CYCLES); }
-stalled-cycles-frontend|idle-cycles-frontend	{ return sym(yyscanner, PERF_TYPE_HARDWARE, PERF_COUNT_HW_STALLED_CYCLES_FRONTEND); }
-stalled-cycles-backend|idle-cycles-backend	{ return sym(yyscanner, PERF_TYPE_HARDWARE, PERF_COUNT_HW_STALLED_CYCLES_BACKEND); }
-instructions					{ return sym(yyscanner, PERF_TYPE_HARDWARE, PERF_COUNT_HW_INSTRUCTIONS); }
-cache-references				{ return sym(yyscanner, PERF_TYPE_HARDWARE, PERF_COUNT_HW_CACHE_REFERENCES); }
-cache-misses					{ return sym(yyscanner, PERF_TYPE_HARDWARE, PERF_COUNT_HW_CACHE_MISSES); }
-branch-instructions|branches			{ return sym(yyscanner, PERF_TYPE_HARDWARE, PERF_COUNT_HW_BRANCH_INSTRUCTIONS); }
-branch-misses					{ return sym(yyscanner, PERF_TYPE_HARDWARE, PERF_COUNT_HW_BRANCH_MISSES); }
-bus-cycles					{ return sym(yyscanner, PERF_TYPE_HARDWARE, PERF_COUNT_HW_BUS_CYCLES); }
-ref-cycles					{ return sym(yyscanner, PERF_TYPE_HARDWARE, PERF_COUNT_HW_REF_CPU_CYCLES); }
-cpu-clock					{ return sym(yyscanner, PERF_TYPE_SOFTWARE, PERF_COUNT_SW_CPU_CLOCK); }
-task-clock					{ return sym(yyscanner, PERF_TYPE_SOFTWARE, PERF_COUNT_SW_TASK_CLOCK); }
-page-faults|faults				{ return sym(yyscanner, PERF_TYPE_SOFTWARE, PERF_COUNT_SW_PAGE_FAULTS); }
-minor-faults					{ return sym(yyscanner, PERF_TYPE_SOFTWARE, PERF_COUNT_SW_PAGE_FAULTS_MIN); }
-major-faults					{ return sym(yyscanner, PERF_TYPE_SOFTWARE, PERF_COUNT_SW_PAGE_FAULTS_MAJ); }
-context-switches|cs				{ return sym(yyscanner, PERF_TYPE_SOFTWARE, PERF_COUNT_SW_CONTEXT_SWITCHES); }
-cpu-migrations|migrations			{ return sym(yyscanner, PERF_TYPE_SOFTWARE, PERF_COUNT_SW_CPU_MIGRATIONS); }
-alignment-faults				{ return sym(yyscanner, PERF_TYPE_SOFTWARE, PERF_COUNT_SW_ALIGNMENT_FAULTS); }
-emulation-faults				{ return sym(yyscanner, PERF_TYPE_SOFTWARE, PERF_COUNT_SW_EMULATION_FAULTS); }
-dummy						{ return sym(yyscanner, PERF_TYPE_SOFTWARE, PERF_COUNT_SW_DUMMY); }
-bpf-output					{ return sym(yyscanner, PERF_TYPE_SOFTWARE, PERF_COUNT_SW_BPF_OUTPUT); }
-cgroup-switches					{ return sym(yyscanner, PERF_TYPE_SOFTWARE, PERF_COUNT_SW_CGROUP_SWITCHES); }
+cpu-cycles|cycles				{ return sym(yyscanner, PERF_COUNT_HW_CPU_CYCLES); }
+stalled-cycles-frontend|idle-cycles-frontend	{ return sym(yyscanner, PERF_COUNT_HW_STALLED_CYCLES_FRONTEND); }
+stalled-cycles-backend|idle-cycles-backend	{ return sym(yyscanner, PERF_COUNT_HW_STALLED_CYCLES_BACKEND); }
+instructions					{ return sym(yyscanner, PERF_COUNT_HW_INSTRUCTIONS); }
+cache-references				{ return sym(yyscanner, PERF_COUNT_HW_CACHE_REFERENCES); }
+cache-misses					{ return sym(yyscanner, PERF_COUNT_HW_CACHE_MISSES); }
+branch-instructions|branches			{ return sym(yyscanner, PERF_COUNT_HW_BRANCH_INSTRUCTIONS); }
+branch-misses					{ return sym(yyscanner, PERF_COUNT_HW_BRANCH_MISSES); }
+bus-cycles					{ return sym(yyscanner, PERF_COUNT_HW_BUS_CYCLES); }
+ref-cycles					{ return sym(yyscanner, PERF_COUNT_HW_REF_CPU_CYCLES); }
 
 {lc_type}			{ return str(yyscanner, PE_LEGACY_CACHE); }
 {lc_type}-{lc_op_result}	{ return str(yyscanner, PE_LEGACY_CACHE); }
diff --git a/tools/perf/util/parse-events.y b/tools/perf/util/parse-events.y
index f888cbb076d6..a2361c0040d7 100644
--- a/tools/perf/util/parse-events.y
+++ b/tools/perf/util/parse-events.y
@@ -55,7 +55,7 @@ static void free_list_evsel(struct list_head* list_evsel)
 %}
 
 %token PE_START_EVENTS PE_START_TERMS
-%token PE_VALUE PE_VALUE_SYM_HW PE_VALUE_SYM_SW PE_TERM
+%token PE_VALUE PE_VALUE_SYM_HW PE_TERM
 %token PE_EVENT_NAME
 %token PE_RAW PE_NAME
 %token PE_MODIFIER_EVENT PE_MODIFIER_BP PE_BP_COLON PE_BP_SLASH
@@ -66,10 +66,8 @@ static void free_list_evsel(struct list_head* list_evsel)
 %token PE_TERM_HW
 %type <num> PE_VALUE
 %type <num> PE_VALUE_SYM_HW
-%type <num> PE_VALUE_SYM_SW
 %type <mod> PE_MODIFIER_EVENT
 %type <term_type> PE_TERM
-%type <num> value_sym
 %type <str> PE_RAW
 %type <str> PE_NAME
 %type <str> PE_LEGACY_CACHE
@@ -306,24 +304,19 @@ PE_NAME sep_dc
 	$$ = list;
 }
 
-value_sym:
-PE_VALUE_SYM_HW
-|
-PE_VALUE_SYM_SW
-
 event_legacy_symbol:
-value_sym '/' event_config '/'
+PE_VALUE_SYM_HW '/' event_config '/'
 {
 	struct list_head *list;
-	int type = $1 >> 16;
-	int config = $1 & 255;
 	int err;
-	bool wildcard = (type == PERF_TYPE_HARDWARE || type == PERF_TYPE_HW_CACHE);
 
 	list = alloc_list();
 	if (!list)
 		YYNOMEM;
-	err = parse_events_add_numeric(_parse_state, list, type, config, $3, wildcard);
+	err = parse_events_add_numeric(_parse_state, list,
+				       PERF_TYPE_HARDWARE, $1,
+				       $3,
+				       /*wildcard=*/true);
 	parse_events_terms__delete($3);
 	if (err) {
 		free_list_evsel(list);
@@ -332,18 +325,18 @@ value_sym '/' event_config '/'
 	$$ = list;
 }
 |
-value_sym sep_slash_slash_dc
+PE_VALUE_SYM_HW sep_slash_slash_dc
 {
 	struct list_head *list;
-	int type = $1 >> 16;
-	int config = $1 & 255;
-	bool wildcard = (type == PERF_TYPE_HARDWARE || type == PERF_TYPE_HW_CACHE);
 	int err;
 
 	list = alloc_list();
 	if (!list)
 		YYNOMEM;
-	err = parse_events_add_numeric(_parse_state, list, type, config, /*head_config=*/NULL, wildcard);
+	err = parse_events_add_numeric(_parse_state, list,
+				       PERF_TYPE_HARDWARE, $1,
+				       /*head_config=*/NULL,
+				       /*wildcard=*/true);
 	if (err)
 		PE_ABORT(err);
 	$$ = list;
diff --git a/tools/perf/util/print-events.c b/tools/perf/util/print-events.c
index e233bacaa641..c1a8708b55ab 100644
--- a/tools/perf/util/print-events.c
+++ b/tools/perf/util/print-events.c
@@ -521,8 +521,6 @@ void print_events(const struct print_callbacks *print_cb, void *print_state)
 {
 	print_symbol_events(print_cb, print_state, PERF_TYPE_HARDWARE,
 			event_symbols_hw, PERF_COUNT_HW_MAX);
-	print_symbol_events(print_cb, print_state, PERF_TYPE_SOFTWARE,
-			event_symbols_sw, PERF_COUNT_SW_MAX);
 
 	print_hwcache_events(print_cb, print_state);
 
-- 
2.50.0.727.gbf7dc18ff4-goog


^ permalink raw reply related	[flat|nested] 41+ messages in thread

* [PATCH v7 04/16] perf tp_pmu: Factor existing tracepoint logic to new file
  2025-07-14 16:43 [PATCH v7 00/16] New perf ilist app Ian Rogers
                   ` (2 preceding siblings ...)
  2025-07-14 16:43 ` [PATCH v7 03/16] perf parse-events: Remove non-json software events Ian Rogers
@ 2025-07-14 16:43 ` Ian Rogers
  2025-07-23 16:57   ` Arnaldo Carvalho de Melo
  2025-07-14 16:43 ` [PATCH v7 05/16] perf tp_pmu: Add event APIs Ian Rogers
                   ` (12 subsequent siblings)
  16 siblings, 1 reply; 41+ messages in thread
From: Ian Rogers @ 2025-07-14 16:43 UTC (permalink / raw)
  To: Peter Zijlstra, Ingo Molnar, Arnaldo Carvalho de Melo,
	Namhyung Kim, Mark Rutland, Alexander Shishkin, Jiri Olsa,
	Ian Rogers, Adrian Hunter, Kan Liang, James Clark, Xu Yang,
	Masami Hiramatsu (Google), Collin Funk, Howard Chu, Weilin Wang,
	Andi Kleen, Dr. David Alan Gilbert, Thomas Richter, Tiezhu Yang,
	Gautam Menghani, Thomas Falcon, Chun-Tse Shao, linux-kernel,
	linux-perf-users

Start the creation of a tracepoint PMU abstraction. Tracepoint events
don't follow the regular sysfs perf conventions. Eventually the new
PMU abstraction will bridge the gap so tracepoint events look more
like regular perf ones.

Signed-off-by: Ian Rogers <irogers@google.com>
---
 tools/perf/util/Build          |   1 +
 tools/perf/util/evsel.c        |  21 +----
 tools/perf/util/parse-events.c | 147 ++++++++++++++-------------------
 tools/perf/util/tp_pmu.c       |  95 +++++++++++++++++++++
 tools/perf/util/tp_pmu.h       |  12 +++
 5 files changed, 170 insertions(+), 106 deletions(-)
 create mode 100644 tools/perf/util/tp_pmu.c
 create mode 100644 tools/perf/util/tp_pmu.h

diff --git a/tools/perf/util/Build b/tools/perf/util/Build
index 12bc01c843b2..4959e7a990e4 100644
--- a/tools/perf/util/Build
+++ b/tools/perf/util/Build
@@ -88,6 +88,7 @@ perf-util-y += pmu-bison.o
 perf-util-y += drm_pmu.o
 perf-util-y += hwmon_pmu.o
 perf-util-y += tool_pmu.o
+perf-util-y += tp_pmu.o
 perf-util-y += svghelper.o
 perf-util-y += trace-event-info.o
 perf-util-y += trace-event-scripting.o
diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c
index 3896a04d90af..5a1d19b4e5cd 100644
--- a/tools/perf/util/evsel.c
+++ b/tools/perf/util/evsel.c
@@ -59,6 +59,7 @@
 #include "drm_pmu.h"
 #include "hwmon_pmu.h"
 #include "tool_pmu.h"
+#include "tp_pmu.h"
 #include "rlimit.h"
 #include "../perf-sys.h"
 #include "util/parse-branch-options.h"
@@ -571,24 +572,6 @@ struct evsel *evsel__clone(struct evsel *dest, struct evsel *orig)
 	return NULL;
 }
 
-static int trace_event__id(const char *sys, const char *name)
-{
-	char *tp_dir = get_events_file(sys);
-	char path[PATH_MAX];
-	int id, err;
-
-	if (!tp_dir)
-		return -1;
-
-	scnprintf(path, PATH_MAX, "%s/%s/id", tp_dir, name);
-	put_events_file(tp_dir);
-	err = filename__read_int(path, &id);
-	if (err)
-		return err;
-
-	return id;
-}
-
 /*
  * Returns pointer with encoded error via <linux/err.h> interface.
  */
@@ -622,7 +605,7 @@ struct evsel *evsel__newtp_idx(const char *sys, const char *name, int idx, bool
 	event_attr_init(&attr);
 
 	if (format) {
-		id = trace_event__id(sys, name);
+		id = tp_pmu__id(sys, name);
 		if (id < 0) {
 			err = id;
 			goto out_free;
diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c
index 1ae481c9802b..f19541ca5268 100644
--- a/tools/perf/util/parse-events.c
+++ b/tools/perf/util/parse-events.c
@@ -17,13 +17,12 @@
 #include "string2.h"
 #include "strbuf.h"
 #include "debug.h"
-#include <api/fs/tracing_path.h>
-#include <api/io_dir.h>
 #include <perf/cpumap.h>
 #include <util/parse-events-bison.h>
 #include <util/parse-events-flex.h>
 #include "pmu.h"
 #include "pmus.h"
+#include "tp_pmu.h"
 #include "asm/bug.h"
 #include "ui/ui.h"
 #include "util/parse-branch-options.h"
@@ -33,6 +32,7 @@
 #include "util/stat.h"
 #include "util/util.h"
 #include "tracepoint.h"
+#include <api/fs/tracing_path.h>
 
 #define MAX_NAME_LEN 100
 
@@ -558,105 +558,82 @@ static int add_tracepoint(struct parse_events_state *parse_state,
 	return 0;
 }
 
-static int add_tracepoint_multi_event(struct parse_events_state *parse_state,
-				      struct list_head *list,
-				      const char *sys_name, const char *evt_name,
-				      struct parse_events_error *err,
-				      struct parse_events_terms *head_config, YYLTYPE *loc)
-{
-	char *evt_path;
-	struct io_dirent64 *evt_ent;
-	struct io_dir evt_dir;
-	int ret = 0, found = 0;
-
-	evt_path = get_events_file(sys_name);
-	if (!evt_path) {
-		tracepoint_error(err, errno, sys_name, evt_name, loc->first_column);
-		return -1;
-	}
-	io_dir__init(&evt_dir, open(evt_path, O_CLOEXEC | O_DIRECTORY | O_RDONLY));
-	if (evt_dir.dirfd < 0) {
-		put_events_file(evt_path);
-		tracepoint_error(err, errno, sys_name, evt_name, loc->first_column);
-		return -1;
-	}
+struct add_tracepoint_multi_args {
+	struct parse_events_state *parse_state;
+	struct list_head *list;
+	const char *sys_glob;
+	const char *evt_glob;
+	struct parse_events_error *err;
+	struct parse_events_terms *head_config;
+	YYLTYPE *loc;
+	int found;
+};
 
-	while (!ret && (evt_ent = io_dir__readdir(&evt_dir))) {
-		if (!strcmp(evt_ent->d_name, ".")
-		    || !strcmp(evt_ent->d_name, "..")
-		    || !strcmp(evt_ent->d_name, "enable")
-		    || !strcmp(evt_ent->d_name, "filter"))
-			continue;
+static int add_tracepoint_multi_event_cb(void *state, const char *sys_name, const char *evt_name)
+{
+	struct add_tracepoint_multi_args *args = state;
+	int ret;
 
-		if (!strglobmatch(evt_ent->d_name, evt_name))
-			continue;
+	if (!strglobmatch(evt_name, args->evt_glob))
+		return 0;
 
-		found++;
+	args->found++;
+	ret = add_tracepoint(args->parse_state, args->list, sys_name, evt_name,
+			     args->err, args->head_config, args->loc);
 
-		ret = add_tracepoint(parse_state, list, sys_name, evt_ent->d_name,
-				     err, head_config, loc);
-	}
+	return ret;
+}
 
-	if (!found) {
-		tracepoint_error(err, ENOENT, sys_name, evt_name, loc->first_column);
-		ret = -1;
+static int add_tracepoint_multi_event(struct add_tracepoint_multi_args *args, const char *sys_name)
+{
+	if (strpbrk(args->evt_glob, "*?") == NULL) {
+		/* Not a glob. */
+		args->found++;
+		return add_tracepoint(args->parse_state, args->list, sys_name, args->evt_glob,
+				      args->err, args->head_config, args->loc);
 	}
 
-	put_events_file(evt_path);
-	close(evt_dir.dirfd);
-	return ret;
+	return tp_pmu__for_each_tp_event(sys_name, args, add_tracepoint_multi_event_cb);
 }
 
-static int add_tracepoint_event(struct parse_events_state *parse_state,
-				struct list_head *list,
-				const char *sys_name, const char *evt_name,
-				struct parse_events_error *err,
-				struct parse_events_terms *head_config, YYLTYPE *loc)
+static int add_tracepoint_multi_sys_cb(void *state, const char *sys_name)
 {
-	return strpbrk(evt_name, "*?") ?
-		add_tracepoint_multi_event(parse_state, list, sys_name, evt_name,
-					   err, head_config, loc) :
-		add_tracepoint(parse_state, list, sys_name, evt_name,
-			       err, head_config, loc);
+	struct add_tracepoint_multi_args *args = state;
+
+	if (!strglobmatch(sys_name, args->sys_glob))
+		return 0;
+
+	return add_tracepoint_multi_event(args, sys_name);
 }
 
 static int add_tracepoint_multi_sys(struct parse_events_state *parse_state,
 				    struct list_head *list,
-				    const char *sys_name, const char *evt_name,
+				    const char *sys_glob, const char *evt_glob,
 				    struct parse_events_error *err,
 				    struct parse_events_terms *head_config, YYLTYPE *loc)
 {
-	struct io_dirent64 *events_ent;
-	struct io_dir events_dir;
-	int ret = 0;
-	char *events_dir_path = get_tracing_file("events");
+	struct add_tracepoint_multi_args args = {
+		.parse_state = parse_state,
+		.list = list,
+		.sys_glob = sys_glob,
+		.evt_glob = evt_glob,
+		.err = err,
+		.head_config = head_config,
+		.loc = loc,
+		.found = 0,
+	};
+	int ret;
 
-	if (!events_dir_path) {
-		tracepoint_error(err, errno, sys_name, evt_name, loc->first_column);
-		return -1;
+	if (strpbrk(sys_glob, "*?") == NULL) {
+		/* Not a glob. */
+		ret = add_tracepoint_multi_event(&args, sys_glob);
+	} else {
+		ret = tp_pmu__for_each_tp_sys(&args, add_tracepoint_multi_sys_cb);
 	}
-	io_dir__init(&events_dir, open(events_dir_path, O_CLOEXEC | O_DIRECTORY | O_RDONLY));
-	put_events_file(events_dir_path);
-	if (events_dir.dirfd < 0) {
-		tracepoint_error(err, errno, sys_name, evt_name, loc->first_column);
-		return -1;
+	if (args.found == 0) {
+		tracepoint_error(err, ENOENT, sys_glob, evt_glob, loc->first_column);
+		return -ENOENT;
 	}
-
-	while (!ret && (events_ent = io_dir__readdir(&events_dir))) {
-		if (!strcmp(events_ent->d_name, ".")
-		    || !strcmp(events_ent->d_name, "..")
-		    || !strcmp(events_ent->d_name, "enable")
-		    || !strcmp(events_ent->d_name, "header_event")
-		    || !strcmp(events_ent->d_name, "header_page"))
-			continue;
-
-		if (!strglobmatch(events_ent->d_name, sys_name))
-			continue;
-
-		ret = add_tracepoint_event(parse_state, list, events_ent->d_name,
-					   evt_name, err, head_config, loc);
-	}
-	close(events_dir.dirfd);
 	return ret;
 }
 
@@ -1348,12 +1325,8 @@ int parse_events_add_tracepoint(struct parse_events_state *parse_state,
 			return -EINVAL;
 	}
 
-	if (strpbrk(sys, "*?"))
-		return add_tracepoint_multi_sys(parse_state, list, sys, event,
-						err, head_config, loc);
-	else
-		return add_tracepoint_event(parse_state, list, sys, event,
-					    err, head_config, loc);
+	return add_tracepoint_multi_sys(parse_state, list, sys, event,
+					err, head_config, loc);
 }
 
 static int __parse_events_add_numeric(struct parse_events_state *parse_state,
diff --git a/tools/perf/util/tp_pmu.c b/tools/perf/util/tp_pmu.c
new file mode 100644
index 000000000000..fd83164f8763
--- /dev/null
+++ b/tools/perf/util/tp_pmu.c
@@ -0,0 +1,95 @@
+// SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause)
+#include "tp_pmu.h"
+#include <api/fs/fs.h>
+#include <api/fs/tracing_path.h>
+#include <api/io_dir.h>
+#include <linux/kernel.h>
+#include <errno.h>
+#include <string.h>
+
+int tp_pmu__id(const char *sys, const char *name)
+{
+	char *tp_dir = get_events_file(sys);
+	char path[PATH_MAX];
+	int id, err;
+
+	if (!tp_dir)
+		return -1;
+
+	scnprintf(path, PATH_MAX, "%s/%s/id", tp_dir, name);
+	put_events_file(tp_dir);
+	err = filename__read_int(path, &id);
+	if (err)
+		return err;
+
+	return id;
+}
+
+
+int tp_pmu__for_each_tp_event(const char *sys, void *state, tp_event_callback cb)
+{
+	char *evt_path;
+	struct io_dirent64 *evt_ent;
+	struct io_dir evt_dir;
+	int ret = 0;
+
+	evt_path = get_events_file(sys);
+	if (!evt_path)
+		return -errno;
+
+	io_dir__init(&evt_dir, open(evt_path, O_CLOEXEC | O_DIRECTORY | O_RDONLY));
+	if (evt_dir.dirfd < 0) {
+		ret = -errno;
+		put_events_file(evt_path);
+		return ret;
+	}
+	put_events_file(evt_path);
+
+	while (!ret && (evt_ent = io_dir__readdir(&evt_dir))) {
+		if (!strcmp(evt_ent->d_name, ".")
+		    || !strcmp(evt_ent->d_name, "..")
+		    || !strcmp(evt_ent->d_name, "enable")
+		    || !strcmp(evt_ent->d_name, "filter"))
+			continue;
+
+		ret = cb(state, sys, evt_ent->d_name);
+		if (ret)
+			break;
+	}
+	close(evt_dir.dirfd);
+	return ret;
+}
+
+int tp_pmu__for_each_tp_sys(void *state, tp_sys_callback cb)
+{
+	struct io_dirent64 *events_ent;
+	struct io_dir events_dir;
+	int ret = 0;
+	char *events_dir_path = get_tracing_file("events");
+
+	if (!events_dir_path)
+		return -errno;
+
+	io_dir__init(&events_dir, open(events_dir_path, O_CLOEXEC | O_DIRECTORY | O_RDONLY));
+	if (events_dir.dirfd < 0) {
+		ret = -errno;
+		put_events_file(events_dir_path);
+		return ret;
+	}
+	put_events_file(events_dir_path);
+
+	while (!ret && (events_ent = io_dir__readdir(&events_dir))) {
+		if (!strcmp(events_ent->d_name, ".")
+		    || !strcmp(events_ent->d_name, "..")
+		    || !strcmp(events_ent->d_name, "enable")
+		    || !strcmp(events_ent->d_name, "header_event")
+		    || !strcmp(events_ent->d_name, "header_page"))
+			continue;
+
+		ret = cb(state, events_ent->d_name);
+		if (ret)
+			break;
+	}
+	close(events_dir.dirfd);
+	return ret;
+}
diff --git a/tools/perf/util/tp_pmu.h b/tools/perf/util/tp_pmu.h
new file mode 100644
index 000000000000..49537303bd73
--- /dev/null
+++ b/tools/perf/util/tp_pmu.h
@@ -0,0 +1,12 @@
+/* SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause) */
+#ifndef __TP_PMU_H
+#define __TP_PMU_H
+
+typedef int (*tp_sys_callback)(void *state, const char *sys_name);
+typedef int (*tp_event_callback)(void *state, const char *sys_name, const char *evt_name);
+
+int tp_pmu__id(const char *sys, const char *name);
+int tp_pmu__for_each_tp_event(const char *sys, void *state, tp_event_callback cb);
+int tp_pmu__for_each_tp_sys(void *state, tp_sys_callback cb);
+
+#endif /* __TP_PMU_H */
-- 
2.50.0.727.gbf7dc18ff4-goog


^ permalink raw reply related	[flat|nested] 41+ messages in thread

* [PATCH v7 05/16] perf tp_pmu: Add event APIs
  2025-07-14 16:43 [PATCH v7 00/16] New perf ilist app Ian Rogers
                   ` (3 preceding siblings ...)
  2025-07-14 16:43 ` [PATCH v7 04/16] perf tp_pmu: Factor existing tracepoint logic to new file Ian Rogers
@ 2025-07-14 16:43 ` Ian Rogers
  2025-07-23 18:57   ` Arnaldo Carvalho de Melo
  2025-07-14 16:43 ` [PATCH v7 06/16] perf list: Remove tracepoint printing code Ian Rogers
                   ` (11 subsequent siblings)
  16 siblings, 1 reply; 41+ messages in thread
From: Ian Rogers @ 2025-07-14 16:43 UTC (permalink / raw)
  To: Peter Zijlstra, Ingo Molnar, Arnaldo Carvalho de Melo,
	Namhyung Kim, Mark Rutland, Alexander Shishkin, Jiri Olsa,
	Ian Rogers, Adrian Hunter, Kan Liang, James Clark, Xu Yang,
	Masami Hiramatsu (Google), Collin Funk, Howard Chu, Weilin Wang,
	Andi Kleen, Dr. David Alan Gilbert, Thomas Richter, Tiezhu Yang,
	Gautam Menghani, Thomas Falcon, Chun-Tse Shao, linux-kernel,
	linux-perf-users

Add event APIs for the tracepoint PMU allowing things like perf list
to function using it. For perf list add the tracepoint format in the
long description (shown with -v).

Signed-off-by: Ian Rogers <irogers@google.com>
---
 tools/perf/util/pmu.c    |   7 +++
 tools/perf/util/tp_pmu.c | 114 +++++++++++++++++++++++++++++++++++++++
 tools/perf/util/tp_pmu.h |   7 +++
 3 files changed, 128 insertions(+)

diff --git a/tools/perf/util/pmu.c b/tools/perf/util/pmu.c
index b09b2ea2407a..dc05233e8232 100644
--- a/tools/perf/util/pmu.c
+++ b/tools/perf/util/pmu.c
@@ -24,6 +24,7 @@
 #include "hwmon_pmu.h"
 #include "pmus.h"
 #include "tool_pmu.h"
+#include "tp_pmu.h"
 #include <util/pmu-bison.h>
 #include <util/pmu-flex.h>
 #include "parse-events.h"
@@ -1983,6 +1984,8 @@ bool perf_pmu__have_event(struct perf_pmu *pmu, const char *name)
 		return false;
 	if (perf_pmu__is_tool(pmu) && tool_pmu__skip_event(name))
 		return false;
+	if (perf_pmu__is_tracepoint(pmu))
+		return tp_pmu__have_event(pmu, name);
 	if (perf_pmu__is_hwmon(pmu))
 		return hwmon_pmu__have_event(pmu, name);
 	if (perf_pmu__is_drm(pmu))
@@ -1998,6 +2001,8 @@ size_t perf_pmu__num_events(struct perf_pmu *pmu)
 {
 	size_t nr;
 
+	if (perf_pmu__is_tracepoint(pmu))
+		return tp_pmu__num_events(pmu);
 	if (perf_pmu__is_hwmon(pmu))
 		return hwmon_pmu__num_events(pmu);
 	if (perf_pmu__is_drm(pmu))
@@ -2068,6 +2073,8 @@ int perf_pmu__for_each_event(struct perf_pmu *pmu, bool skip_duplicate_pmus,
 	struct hashmap_entry *entry;
 	size_t bkt;
 
+	if (perf_pmu__is_tracepoint(pmu))
+		return tp_pmu__for_each_event(pmu, state, cb);
 	if (perf_pmu__is_hwmon(pmu))
 		return hwmon_pmu__for_each_event(pmu, state, cb);
 	if (perf_pmu__is_drm(pmu))
diff --git a/tools/perf/util/tp_pmu.c b/tools/perf/util/tp_pmu.c
index fd83164f8763..9d68a1da17f6 100644
--- a/tools/perf/util/tp_pmu.c
+++ b/tools/perf/util/tp_pmu.c
@@ -1,5 +1,6 @@
 // SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause)
 #include "tp_pmu.h"
+#include "pmus.h"
 #include <api/fs/fs.h>
 #include <api/fs/tracing_path.h>
 #include <api/io_dir.h>
@@ -93,3 +94,116 @@ int tp_pmu__for_each_tp_sys(void *state, tp_sys_callback cb)
 	close(events_dir.dirfd);
 	return ret;
 }
+
+bool perf_pmu__is_tracepoint(const struct perf_pmu *pmu)
+{
+	return pmu->type == PERF_TYPE_TRACEPOINT;
+}
+
+struct for_each_event_args {
+	void *state;
+	pmu_event_callback cb;
+	const struct perf_pmu *pmu;
+};
+
+static int for_each_event_cb(void *state, const char *sys_name, const char *evt_name)
+{
+	struct for_each_event_args *args = state;
+	char name[2 * FILENAME_MAX + 2];
+	/* 16 possible hex digits and 22 other characters and \0. */
+	char encoding[16 + 22];
+	char *format = NULL;
+	size_t format_size;
+	struct pmu_event_info info = {
+		.pmu = args->pmu,
+		.pmu_name = args->pmu->name,
+		.event_type_desc = "Tracepoint event",
+	};
+	char *tp_dir = get_events_file(sys_name);
+	char path[PATH_MAX];
+	int id, err;
+
+	if (!tp_dir)
+		return -1;
+
+	scnprintf(path, sizeof(path), "%s/%s/id", tp_dir, evt_name);
+	err = filename__read_int(path, &id);
+	if (err == 0) {
+		snprintf(encoding, sizeof(encoding), "tracepoint/config=0x%x/", id);
+		info.encoding_desc = encoding;
+	}
+
+	scnprintf(path, sizeof(path), "%s/%s/format", tp_dir, evt_name);
+	put_events_file(tp_dir);
+	err = filename__read_str(path, &format, &format_size);
+	if (err == 0) {
+		info.long_desc = format;
+		for (size_t i = 0 ; i < format_size; i++) {
+			/* Swap tabs to spaces due to some rendering issues. */
+			if (format[i] == '\t')
+				format[i] = ' ';
+		}
+	}
+	snprintf(name, sizeof(name), "%s:%s", sys_name, evt_name);
+	info.name = name;
+	err = args->cb(args->state, &info);
+	free(format);
+	return err;
+}
+
+static int for_each_event_sys_cb(void *state, const char *sys_name)
+{
+	return tp_pmu__for_each_tp_event(sys_name, state, for_each_event_cb);
+}
+
+int tp_pmu__for_each_event(struct perf_pmu *pmu, void *state, pmu_event_callback cb)
+{
+	struct for_each_event_args args = {
+		.state = state,
+		.cb = cb,
+		.pmu = pmu,
+	};
+
+	return tp_pmu__for_each_tp_sys(&args, for_each_event_sys_cb);
+}
+
+static int num_events_cb(void *state, const char *sys_name __maybe_unused,
+			 const char *evt_name __maybe_unused)
+{
+	size_t *count = state;
+
+	(*count)++;
+	return 0;
+}
+
+static int num_events_sys_cb(void *state, const char *sys_name)
+{
+	return tp_pmu__for_each_tp_event(sys_name, state, num_events_cb);
+}
+
+size_t tp_pmu__num_events(struct perf_pmu *pmu __maybe_unused)
+{
+	size_t count = 0;
+
+	tp_pmu__for_each_tp_sys(&count, num_events_sys_cb);
+	return count;
+}
+
+bool tp_pmu__have_event(struct perf_pmu *pmu __maybe_unused, const char *name)
+{
+	char *dup_name, *colon;
+	int id;
+
+	if (strchr(name, ':') == NULL)
+		return false;
+
+	dup_name = strdup(name);
+	if (!dup_name)
+		return false;
+
+	colon = strchr(dup_name, ':');
+	*colon = '\0';
+	id = tp_pmu__id(dup_name, colon + 1);
+	free(dup_name);
+	return id >= 0;
+}
diff --git a/tools/perf/util/tp_pmu.h b/tools/perf/util/tp_pmu.h
index 49537303bd73..30456bd6943d 100644
--- a/tools/perf/util/tp_pmu.h
+++ b/tools/perf/util/tp_pmu.h
@@ -2,6 +2,8 @@
 #ifndef __TP_PMU_H
 #define __TP_PMU_H
 
+#include "pmu.h"
+
 typedef int (*tp_sys_callback)(void *state, const char *sys_name);
 typedef int (*tp_event_callback)(void *state, const char *sys_name, const char *evt_name);
 
@@ -9,4 +11,9 @@ int tp_pmu__id(const char *sys, const char *name);
 int tp_pmu__for_each_tp_event(const char *sys, void *state, tp_event_callback cb);
 int tp_pmu__for_each_tp_sys(void *state, tp_sys_callback cb);
 
+bool perf_pmu__is_tracepoint(const struct perf_pmu *pmu);
+int tp_pmu__for_each_event(struct perf_pmu *pmu, void *state, pmu_event_callback cb);
+size_t tp_pmu__num_events(struct perf_pmu *pmu);
+bool tp_pmu__have_event(struct perf_pmu *pmu, const char *name);
+
 #endif /* __TP_PMU_H */
-- 
2.50.0.727.gbf7dc18ff4-goog


^ permalink raw reply related	[flat|nested] 41+ messages in thread

* [PATCH v7 06/16] perf list: Remove tracepoint printing code
  2025-07-14 16:43 [PATCH v7 00/16] New perf ilist app Ian Rogers
                   ` (4 preceding siblings ...)
  2025-07-14 16:43 ` [PATCH v7 05/16] perf tp_pmu: Add event APIs Ian Rogers
@ 2025-07-14 16:43 ` Ian Rogers
  2025-07-14 16:43 ` [PATCH v7 07/16] perf list: Skip ABI PMUs when printing pmu values Ian Rogers
                   ` (10 subsequent siblings)
  16 siblings, 0 replies; 41+ messages in thread
From: Ian Rogers @ 2025-07-14 16:43 UTC (permalink / raw)
  To: Peter Zijlstra, Ingo Molnar, Arnaldo Carvalho de Melo,
	Namhyung Kim, Mark Rutland, Alexander Shishkin, Jiri Olsa,
	Ian Rogers, Adrian Hunter, Kan Liang, James Clark, Xu Yang,
	Masami Hiramatsu (Google), Collin Funk, Howard Chu, Weilin Wang,
	Andi Kleen, Dr. David Alan Gilbert, Thomas Richter, Tiezhu Yang,
	Gautam Menghani, Thomas Falcon, Chun-Tse Shao, linux-kernel,
	linux-perf-users

Now that the tp_pmu can iterate and describe events remove the custom
tracepoint printing logic, this avoids perf list showing the
tracepoint events twice.

Signed-off-by: Ian Rogers <irogers@google.com>
---
 tools/perf/builtin-list.c      | 29 ++++++++---
 tools/perf/util/print-events.c | 93 ----------------------------------
 tools/perf/util/print-events.h |  2 -
 3 files changed, 23 insertions(+), 101 deletions(-)

diff --git a/tools/perf/builtin-list.c b/tools/perf/builtin-list.c
index 674bb0afbf93..3a4061d02f6c 100644
--- a/tools/perf/builtin-list.c
+++ b/tools/perf/builtin-list.c
@@ -614,9 +614,18 @@ int cmd_list(int argc, const char **argv)
 	for (i = 0; i < argc; ++i) {
 		char *sep, *s;
 
-		if (strcmp(argv[i], "tracepoint") == 0)
-			print_tracepoint_events(&print_cb, ps);
-		else if (strcmp(argv[i], "hw") == 0 ||
+		if (strcmp(argv[i], "tracepoint") == 0) {
+			char *old_pmu_glob = default_ps.pmu_glob;
+
+			default_ps.pmu_glob = strdup("tracepoint");
+			if (!default_ps.pmu_glob) {
+				ret = -1;
+				goto out;
+			}
+			perf_pmus__print_pmu_events(&print_cb, ps);
+			zfree(&default_ps.pmu_glob);
+			default_ps.pmu_glob = old_pmu_glob;
+		} else if (strcmp(argv[i], "hw") == 0 ||
 			 strcmp(argv[i], "hardware") == 0)
 			print_symbol_events(&print_cb, ps, PERF_TYPE_HARDWARE,
 					event_symbols_hw, PERF_COUNT_HW_MAX);
@@ -658,6 +667,7 @@ int cmd_list(int argc, const char **argv)
 #endif
 		else if ((sep = strchr(argv[i], ':')) != NULL) {
 			char *old_pmu_glob = default_ps.pmu_glob;
+			char *old_event_glob = default_ps.event_glob;
 
 			default_ps.event_glob = strdup(argv[i]);
 			if (!default_ps.event_glob) {
@@ -665,13 +675,21 @@ int cmd_list(int argc, const char **argv)
 				goto out;
 			}
 
-			print_tracepoint_events(&print_cb, ps);
+			default_ps.pmu_glob = strdup("tracepoint");
+			if (!default_ps.pmu_glob) {
+				zfree(&default_ps.event_glob);
+				ret = -1;
+				goto out;
+			}
+			perf_pmus__print_pmu_events(&print_cb, ps);
+			zfree(&default_ps.pmu_glob);
+			default_ps.pmu_glob = old_pmu_glob;
 			print_sdt_events(&print_cb, ps);
 			default_ps.metrics = true;
 			default_ps.metricgroups = true;
 			metricgroup__print(&print_cb, ps);
 			zfree(&default_ps.event_glob);
-			default_ps.pmu_glob = old_pmu_glob;
+			default_ps.event_glob = old_event_glob;
 		} else {
 			if (asprintf(&s, "*%s*", argv[i]) < 0) {
 				printf("Critical: Not enough memory! Trying to continue...\n");
@@ -682,7 +700,6 @@ int cmd_list(int argc, const char **argv)
 					event_symbols_hw, PERF_COUNT_HW_MAX);
 			print_hwcache_events(&print_cb, ps);
 			perf_pmus__print_pmu_events(&print_cb, ps);
-			print_tracepoint_events(&print_cb, ps);
 			print_sdt_events(&print_cb, ps);
 			default_ps.metrics = true;
 			default_ps.metricgroups = true;
diff --git a/tools/perf/util/print-events.c b/tools/perf/util/print-events.c
index c1a8708b55ab..3a5e5e7bae13 100644
--- a/tools/perf/util/print-events.c
+++ b/tools/perf/util/print-events.c
@@ -44,97 +44,6 @@ static const char * const event_type_descriptors[] = {
 	"Hardware breakpoint",
 };
 
-/*
- * Print the events from <debugfs_mount_point>/tracing/events
- */
-void print_tracepoint_events(const struct print_callbacks *print_cb __maybe_unused, void *print_state __maybe_unused)
-{
-	char *events_path = get_tracing_file("events");
-	int events_fd = open(events_path, O_PATH);
-	struct dirent **sys_namelist = NULL;
-	int sys_items;
-
-	if (events_fd < 0) {
-		pr_err("Error: failed to open tracing events directory\n");
-		pr_err("%s: %s\n", events_path, strerror(errno));
-		return;
-	}
-	put_tracing_file(events_path);
-
-	sys_items = tracing_events__scandir_alphasort(&sys_namelist);
-
-	for (int i = 0; i < sys_items; i++) {
-		struct dirent *sys_dirent = sys_namelist[i];
-		struct dirent **evt_namelist = NULL;
-		int dir_fd;
-		int evt_items;
-
-		if (sys_dirent->d_type != DT_DIR ||
-		    !strcmp(sys_dirent->d_name, ".") ||
-		    !strcmp(sys_dirent->d_name, ".."))
-			goto next_sys;
-
-		dir_fd = openat(events_fd, sys_dirent->d_name, O_PATH);
-		if (dir_fd < 0)
-			goto next_sys;
-
-		evt_items = scandirat(events_fd, sys_dirent->d_name, &evt_namelist, NULL, alphasort);
-		for (int j = 0; j < evt_items; j++) {
-			/*
-			 * Buffer sized at twice the max filename length + 1
-			 * separator + 1 \0 terminator.
-			 */
-			char buf[NAME_MAX * 2 + 2];
-			/* 16 possible hex digits and 22 other characters and \0. */
-			char encoding[16 + 22];
-			struct dirent *evt_dirent = evt_namelist[j];
-			struct io id;
-			__u64 config;
-
-			if (evt_dirent->d_type != DT_DIR ||
-			    !strcmp(evt_dirent->d_name, ".") ||
-			    !strcmp(evt_dirent->d_name, ".."))
-				goto next_evt;
-
-			snprintf(buf, sizeof(buf), "%s/id", evt_dirent->d_name);
-			io__init(&id, openat(dir_fd, buf, O_RDONLY), buf, sizeof(buf));
-
-			if (id.fd < 0)
-				goto next_evt;
-
-			if (io__get_dec(&id, &config) < 0) {
-				close(id.fd);
-				goto next_evt;
-			}
-			close(id.fd);
-
-			snprintf(buf, sizeof(buf), "%s:%s",
-				 sys_dirent->d_name, evt_dirent->d_name);
-			snprintf(encoding, sizeof(encoding), "tracepoint/config=0x%llx/", config);
-			print_cb->print_event(print_state,
-					/*topic=*/NULL,
-					/*pmu_name=*/NULL, /* really "tracepoint" */
-					/*event_name=*/buf,
-					/*event_alias=*/NULL,
-					/*scale_unit=*/NULL,
-					/*deprecated=*/false,
-					"Tracepoint event",
-					/*desc=*/NULL,
-					/*long_desc=*/NULL,
-					encoding);
-next_evt:
-			free(evt_namelist[j]);
-		}
-		close(dir_fd);
-		free(evt_namelist);
-next_sys:
-		free(sys_namelist[i]);
-	}
-
-	free(sys_namelist);
-	close(events_fd);
-}
-
 void print_sdt_events(const struct print_callbacks *print_cb, void *print_state)
 {
 	struct strlist *bidlist, *sdtlist;
@@ -552,8 +461,6 @@ void print_events(const struct print_callbacks *print_cb, void *print_state)
 			/*long_desc=*/NULL,
 			/*encoding_desc=*/NULL);
 
-	print_tracepoint_events(print_cb, print_state);
-
 	print_sdt_events(print_cb, print_state);
 
 	metricgroup__print(print_cb, print_state);
diff --git a/tools/perf/util/print-events.h b/tools/perf/util/print-events.h
index 48682e2d166d..4d95b8257e23 100644
--- a/tools/perf/util/print-events.h
+++ b/tools/perf/util/print-events.h
@@ -37,8 +37,6 @@ void print_sdt_events(const struct print_callbacks *print_cb, void *print_state)
 void print_symbol_events(const struct print_callbacks *print_cb, void *print_state,
 			 unsigned int type, const struct event_symbol *syms,
 			 unsigned int max);
-
-void print_tracepoint_events(const struct print_callbacks *print_cb, void *print_state);
 void metricgroup__print(const struct print_callbacks *print_cb, void *print_state);
 bool is_event_supported(u8 type, u64 config);
 
-- 
2.50.0.727.gbf7dc18ff4-goog


^ permalink raw reply related	[flat|nested] 41+ messages in thread

* [PATCH v7 07/16] perf list: Skip ABI PMUs when printing pmu values
  2025-07-14 16:43 [PATCH v7 00/16] New perf ilist app Ian Rogers
                   ` (5 preceding siblings ...)
  2025-07-14 16:43 ` [PATCH v7 06/16] perf list: Remove tracepoint printing code Ian Rogers
@ 2025-07-14 16:43 ` Ian Rogers
  2025-07-14 16:43 ` [PATCH v7 08/16] perf python: Improve the tracepoint function if no libtraceevent Ian Rogers
                   ` (9 subsequent siblings)
  16 siblings, 0 replies; 41+ messages in thread
From: Ian Rogers @ 2025-07-14 16:43 UTC (permalink / raw)
  To: Peter Zijlstra, Ingo Molnar, Arnaldo Carvalho de Melo,
	Namhyung Kim, Mark Rutland, Alexander Shishkin, Jiri Olsa,
	Ian Rogers, Adrian Hunter, Kan Liang, James Clark, Xu Yang,
	Masami Hiramatsu (Google), Collin Funk, Howard Chu, Weilin Wang,
	Andi Kleen, Dr. David Alan Gilbert, Thomas Richter, Tiezhu Yang,
	Gautam Menghani, Thomas Falcon, Chun-Tse Shao, linux-kernel,
	linux-perf-users

Avoid printing tracepoint, legacy and software events when listing for
the pmu option. Add the PMU type to the print_event callbacks to ease
detection.

Signed-off-by: Ian Rogers <irogers@google.com>
---
 tools/perf/builtin-list.c      | 17 +++++++++++++----
 tools/perf/util/pfm.c          |  2 ++
 tools/perf/util/pmus.c         |  2 ++
 tools/perf/util/print-events.c |  5 +++++
 tools/perf/util/print-events.h |  2 +-
 5 files changed, 23 insertions(+), 5 deletions(-)

diff --git a/tools/perf/builtin-list.c b/tools/perf/builtin-list.c
index 3a4061d02f6c..caf42276bd0f 100644
--- a/tools/perf/builtin-list.c
+++ b/tools/perf/builtin-list.c
@@ -58,6 +58,8 @@ struct print_state {
 	bool metrics;
 	/** @metricgroups: Controls printing of metric and metric groups. */
 	bool metricgroups;
+	/** @exclude_abi: Exclude PMUs with types less than PERF_TYPE_MAX except PERF_TYPE_RAW. */
+	bool exclude_abi;
 	/** @last_topic: The last printed event topic. */
 	char *last_topic;
 	/** @last_metricgroups: The last printed metric group. */
@@ -113,7 +115,8 @@ static void wordwrap(FILE *fp, const char *s, int start, int max, int corr)
 	}
 }
 
-static void default_print_event(void *ps, const char *topic, const char *pmu_name,
+static void default_print_event(void *ps, const char *topic,
+				const char *pmu_name, u32 pmu_type,
 				const char *event_name, const char *event_alias,
 				const char *scale_unit __maybe_unused,
 				bool deprecated, const char *event_type_desc,
@@ -130,6 +133,9 @@ static void default_print_event(void *ps, const char *topic, const char *pmu_nam
 	if (print_state->pmu_glob && pmu_name && !strglobmatch(pmu_name, print_state->pmu_glob))
 		return;
 
+	if (print_state->exclude_abi && pmu_type < PERF_TYPE_MAX && pmu_type != PERF_TYPE_RAW)
+		return;
+
 	if (print_state->event_glob &&
 	    (!event_name || !strglobmatch(event_name, print_state->event_glob)) &&
 	    (!event_alias || !strglobmatch(event_alias, print_state->event_glob)) &&
@@ -354,7 +360,8 @@ static void fix_escape_fprintf(FILE *fp, struct strbuf *buf, const char *fmt, ..
 	fputs(buf->buf, fp);
 }
 
-static void json_print_event(void *ps, const char *topic, const char *pmu_name,
+static void json_print_event(void *ps, const char *topic,
+			     const char *pmu_name, u32 pmu_type __maybe_unused,
 			     const char *event_name, const char *event_alias,
 			     const char *scale_unit,
 			     bool deprecated, const char *event_type_desc,
@@ -647,9 +654,11 @@ int cmd_list(int argc, const char **argv)
 		} else if (strcmp(argv[i], "cache") == 0 ||
 			 strcmp(argv[i], "hwcache") == 0)
 			print_hwcache_events(&print_cb, ps);
-		else if (strcmp(argv[i], "pmu") == 0)
+		else if (strcmp(argv[i], "pmu") == 0) {
+			default_ps.exclude_abi = true;
 			perf_pmus__print_pmu_events(&print_cb, ps);
-		else if (strcmp(argv[i], "sdt") == 0)
+			default_ps.exclude_abi = false;
+		} else if (strcmp(argv[i], "sdt") == 0)
 			print_sdt_events(&print_cb, ps);
 		else if (strcmp(argv[i], "metric") == 0 || strcmp(argv[i], "metrics") == 0) {
 			default_ps.metricgroups = false;
diff --git a/tools/perf/util/pfm.c b/tools/perf/util/pfm.c
index 0dacc133ed39..15fc3898ec83 100644
--- a/tools/perf/util/pfm.c
+++ b/tools/perf/util/pfm.c
@@ -234,6 +234,7 @@ print_libpfm_event(const struct print_callbacks *print_cb, void *print_state,
 
 	if (is_libpfm_event_supported(name, cpus, threads)) {
 		print_cb->print_event(print_state, topic, pinfo->name,
+				      /*pmu_type=*/PERF_TYPE_RAW,
 				      name, info->equiv,
 				      /*scale_unit=*/NULL,
 				      /*deprecated=*/NULL, "PFM event",
@@ -269,6 +270,7 @@ print_libpfm_event(const struct print_callbacks *print_cb, void *print_state,
 			print_cb->print_event(print_state,
 					topic,
 					pinfo->name,
+					/*pmu_type=*/PERF_TYPE_RAW,
 					name, /*alias=*/NULL,
 					/*scale_unit=*/NULL,
 					/*deprecated=*/NULL, "PFM event",
diff --git a/tools/perf/util/pmus.c b/tools/perf/util/pmus.c
index 409b909cfa02..004f5f0c621f 100644
--- a/tools/perf/util/pmus.c
+++ b/tools/perf/util/pmus.c
@@ -645,6 +645,7 @@ void perf_pmus__print_pmu_events(const struct print_callbacks *print_cb, void *p
 		print_cb->print_event(print_state,
 				aliases[j].topic,
 				aliases[j].pmu_name,
+				aliases[j].pmu->type,
 				aliases[j].name,
 				aliases[j].alias,
 				aliases[j].scale_unit,
@@ -749,6 +750,7 @@ void perf_pmus__print_raw_pmu_events(const struct print_callbacks *print_cb, voi
 		print_cb->print_event(print_state,
 				/*topic=*/NULL,
 				/*pmu_name=*/NULL,
+				pmu->type,
 				format_args.short_string.buf,
 				/*event_alias=*/NULL,
 				/*scale_unit=*/NULL,
diff --git a/tools/perf/util/print-events.c b/tools/perf/util/print-events.c
index 3a5e5e7bae13..4153124a9948 100644
--- a/tools/perf/util/print-events.c
+++ b/tools/perf/util/print-events.c
@@ -121,6 +121,7 @@ void print_sdt_events(const struct print_callbacks *print_cb, void *print_state)
 		print_cb->print_event(print_state,
 				/*topic=*/NULL,
 				/*pmu_name=*/NULL,
+				PERF_TYPE_TRACEPOINT,
 				evt_name ?: sdt_name->s,
 				/*event_alias=*/NULL,
 				/*deprecated=*/false,
@@ -222,6 +223,7 @@ int print_hwcache_events(const struct print_callbacks *print_cb, void *print_sta
 					print_cb->print_event(print_state,
 							"cache",
 							pmu->name,
+							pmu->type,
 							name,
 							alias_name,
 							/*scale_unit=*/NULL,
@@ -278,6 +280,7 @@ void print_symbol_events(const struct print_callbacks *print_cb, void *print_sta
 		print_cb->print_event(print_state,
 				/*topic=*/NULL,
 				/*pmu_name=*/NULL,
+				type,
 				nd->s,
 				alias,
 				/*scale_unit=*/NULL,
@@ -438,6 +441,7 @@ void print_events(const struct print_callbacks *print_cb, void *print_state)
 	print_cb->print_event(print_state,
 			/*topic=*/NULL,
 			/*pmu_name=*/NULL,
+			PERF_TYPE_RAW,
 			"rNNN",
 			/*event_alias=*/NULL,
 			/*scale_unit=*/NULL,
@@ -452,6 +456,7 @@ void print_events(const struct print_callbacks *print_cb, void *print_state)
 	print_cb->print_event(print_state,
 			/*topic=*/NULL,
 			/*pmu_name=*/NULL,
+			PERF_TYPE_BREAKPOINT,
 			"mem:<addr>[/len][:access]",
 			/*scale_unit=*/NULL,
 			/*event_alias=*/NULL,
diff --git a/tools/perf/util/print-events.h b/tools/perf/util/print-events.h
index 4d95b8257e23..d6ba384f0c66 100644
--- a/tools/perf/util/print-events.h
+++ b/tools/perf/util/print-events.h
@@ -12,7 +12,7 @@ struct print_callbacks {
 	void (*print_start)(void *print_state);
 	void (*print_end)(void *print_state);
 	void (*print_event)(void *print_state, const char *topic,
-			const char *pmu_name,
+			const char *pmu_name, u32 pmu_type,
 			const char *event_name, const char *event_alias,
 			const char *scale_unit,
 			bool deprecated, const char *event_type_desc,
-- 
2.50.0.727.gbf7dc18ff4-goog


^ permalink raw reply related	[flat|nested] 41+ messages in thread

* [PATCH v7 08/16] perf python: Improve the tracepoint function if no libtraceevent
  2025-07-14 16:43 [PATCH v7 00/16] New perf ilist app Ian Rogers
                   ` (6 preceding siblings ...)
  2025-07-14 16:43 ` [PATCH v7 07/16] perf list: Skip ABI PMUs when printing pmu values Ian Rogers
@ 2025-07-14 16:43 ` Ian Rogers
  2025-07-14 16:43 ` [PATCH v7 09/16] perf python: Add basic PMU abstraction and pmus sequence Ian Rogers
                   ` (8 subsequent siblings)
  16 siblings, 0 replies; 41+ messages in thread
From: Ian Rogers @ 2025-07-14 16:43 UTC (permalink / raw)
  To: Peter Zijlstra, Ingo Molnar, Arnaldo Carvalho de Melo,
	Namhyung Kim, Mark Rutland, Alexander Shishkin, Jiri Olsa,
	Ian Rogers, Adrian Hunter, Kan Liang, James Clark, Xu Yang,
	Masami Hiramatsu (Google), Collin Funk, Howard Chu, Weilin Wang,
	Andi Kleen, Dr. David Alan Gilbert, Thomas Richter, Tiezhu Yang,
	Gautam Menghani, Thomas Falcon, Chun-Tse Shao, linux-kernel,
	linux-perf-users

The tracepoint function just returns the tracepoint id, this doesn't
require libtraceevent which is only used for parsing the event format
data. Implement the function using the id function in tp_pmu. No
current code in perf is using this, the previous code migrated to
perf.parse_events, but it feels good to have less ifdef
HAVE_LIBTRACEEVENT.

Signed-off-by: Ian Rogers <irogers@google.com>
---
 tools/perf/util/python.c | 12 ++----------
 1 file changed, 2 insertions(+), 10 deletions(-)

diff --git a/tools/perf/util/python.c b/tools/perf/util/python.c
index 02544387f39d..9d97affb79c1 100644
--- a/tools/perf/util/python.c
+++ b/tools/perf/util/python.c
@@ -18,6 +18,7 @@
 #include "record.h"
 #include "strbuf.h"
 #include "thread_map.h"
+#include "tp_pmu.h"
 #include "trace-event.h"
 #include "metricgroup.h"
 #include "mmap.h"
@@ -1544,10 +1545,6 @@ static const struct perf_constant perf__constants[] = {
 static PyObject *pyrf__tracepoint(struct pyrf_evsel *pevsel,
 				  PyObject *args, PyObject *kwargs)
 {
-#ifndef HAVE_LIBTRACEEVENT
-	return NULL;
-#else
-	struct tep_event *tp_format;
 	static char *kwlist[] = { "sys", "name", NULL };
 	char *sys  = NULL;
 	char *name = NULL;
@@ -1556,12 +1553,7 @@ static PyObject *pyrf__tracepoint(struct pyrf_evsel *pevsel,
 					 &sys, &name))
 		return NULL;
 
-	tp_format = trace_event__tp_format(sys, name);
-	if (IS_ERR(tp_format))
-		return PyLong_FromLong(-1);
-
-	return PyLong_FromLong(tp_format->id);
-#endif // HAVE_LIBTRACEEVENT
+	return PyLong_FromLong(tp_pmu__id(sys, name));
 }
 
 static PyObject *pyrf_evsel__from_evsel(struct evsel *evsel)
-- 
2.50.0.727.gbf7dc18ff4-goog


^ permalink raw reply related	[flat|nested] 41+ messages in thread

* [PATCH v7 09/16] perf python: Add basic PMU abstraction and pmus sequence
  2025-07-14 16:43 [PATCH v7 00/16] New perf ilist app Ian Rogers
                   ` (7 preceding siblings ...)
  2025-07-14 16:43 ` [PATCH v7 08/16] perf python: Improve the tracepoint function if no libtraceevent Ian Rogers
@ 2025-07-14 16:43 ` Ian Rogers
  2025-07-14 16:43 ` [PATCH v7 10/16] perf python: Add function returning dictionary of all events on a PMU Ian Rogers
                   ` (7 subsequent siblings)
  16 siblings, 0 replies; 41+ messages in thread
From: Ian Rogers @ 2025-07-14 16:43 UTC (permalink / raw)
  To: Peter Zijlstra, Ingo Molnar, Arnaldo Carvalho de Melo,
	Namhyung Kim, Mark Rutland, Alexander Shishkin, Jiri Olsa,
	Ian Rogers, Adrian Hunter, Kan Liang, James Clark, Xu Yang,
	Masami Hiramatsu (Google), Collin Funk, Howard Chu, Weilin Wang,
	Andi Kleen, Dr. David Alan Gilbert, Thomas Richter, Tiezhu Yang,
	Gautam Menghani, Thomas Falcon, Chun-Tse Shao, linux-kernel,
	linux-perf-users

Add an ability to iterate over PMUs and a basic PMU type then can just
show the PMU's name.

An example usage:
```
$ python
Python 3.12.9 (main, Feb  5 2025, 01:31:18) [GCC 14.2.0] on linux
>>> import perf
>>> list(perf.pmus())
[pmu(cpu), pmu(breakpoint), pmu(cstate_core), pmu(cstate_pkg),
pmu(hwmon_acpitz), pmu(hwmon_ac), pmu(hwmon_bat0),
pmu(hwmon_coretemp), pmu(hwmon_iwlwifi_1), pmu(hwmon_nvme),
pmu(hwmon_thinkpad), pmu(hwmon_ucsi_source_psy_usbc000_0),
pmu(hwmon_ucsi_source_psy_usbc000_0), pmu(i915), pmu(intel_bts),
pmu(intel_pt), pmu(kprobe), pmu(msr), pmu(power), pmu(software),
pmu(tool), pmu(tracepoint), pmu(uncore_arb), pmu(uncore_cbox_0),
pmu(uncore_cbox_1), pmu(uncore_cbox_2), pmu(uncore_cbox_3),
pmu(uncore_cbox_4), pmu(uncore_cbox_5), pmu(uncore_cbox_6),
pmu(uncore_cbox_7), pmu(uncore_clock), pmu(uncore_imc_free_running_0),
pmu(uncore_imc_free_running_1), pmu(uprobe)]
```

Signed-off-by: Ian Rogers <irogers@google.com>
---
 tools/perf/util/python.c | 140 +++++++++++++++++++++++++++++++++++++++
 1 file changed, 140 insertions(+)

diff --git a/tools/perf/util/python.c b/tools/perf/util/python.c
index 9d97affb79c1..860df6436f87 100644
--- a/tools/perf/util/python.c
+++ b/tools/perf/util/python.c
@@ -639,6 +639,138 @@ static int pyrf_thread_map__setup_types(void)
 	return PyType_Ready(&pyrf_thread_map__type);
 }
 
+/**
+ * A python wrapper for perf_pmus that are globally owned by the pmus.c code.
+ */
+struct pyrf_pmu {
+	PyObject_HEAD
+
+	struct perf_pmu *pmu;
+};
+
+static void pyrf_pmu__delete(struct pyrf_pmu *ppmu)
+{
+	Py_TYPE(ppmu)->tp_free((PyObject *)ppmu);
+}
+
+static PyObject *pyrf_pmu__name(PyObject *self)
+{
+	struct pyrf_pmu *ppmu = (void *)self;
+
+	return PyUnicode_FromString(ppmu->pmu->name);
+}
+
+static PyObject *pyrf_pmu__repr(PyObject *self)
+{
+	struct pyrf_pmu *ppmu = (void *)self;
+
+	return PyUnicode_FromFormat("pmu(%s)", ppmu->pmu->name);
+}
+
+static const char pyrf_pmu__doc[] = PyDoc_STR("perf Performance Monitoring Unit (PMU) object.");
+
+static PyMethodDef pyrf_pmu__methods[] = {
+	{
+		.ml_name  = "name",
+		.ml_meth  = (PyCFunction)pyrf_pmu__name,
+		.ml_flags = METH_NOARGS,
+		.ml_doc	  = PyDoc_STR("Name of the PMU including suffixes.")
+	},
+	{ .ml_name = NULL, }
+};
+
+/** The python type for a perf.pmu. */
+static PyTypeObject pyrf_pmu__type = {
+	PyVarObject_HEAD_INIT(NULL, 0)
+	.tp_name	= "perf.pmu",
+	.tp_basicsize	= sizeof(struct pyrf_pmu),
+	.tp_dealloc	= (destructor)pyrf_pmu__delete,
+	.tp_flags	= Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE,
+	.tp_doc		= pyrf_pmu__doc,
+	.tp_methods	= pyrf_pmu__methods,
+	.tp_str         = pyrf_pmu__name,
+	.tp_repr        = pyrf_pmu__repr,
+};
+
+static int pyrf_pmu__setup_types(void)
+{
+	pyrf_pmu__type.tp_new = PyType_GenericNew;
+	return PyType_Ready(&pyrf_pmu__type);
+}
+
+
+/** A python iterator for pmus that has no equivalent in the C code. */
+struct pyrf_pmu_iterator {
+	PyObject_HEAD
+	struct perf_pmu *pmu;
+};
+
+static void pyrf_pmu_iterator__dealloc(struct pyrf_pmu_iterator *self)
+{
+	Py_TYPE(self)->tp_free((PyObject *) self);
+}
+
+static PyObject *pyrf_pmu_iterator__new(PyTypeObject *type, PyObject *args __maybe_unused,
+					PyObject *kwds __maybe_unused)
+{
+	struct pyrf_pmu_iterator *itr = (void *)type->tp_alloc(type, 0);
+
+	if (itr != NULL)
+		itr->pmu = perf_pmus__scan(/*pmu=*/NULL);
+
+	return (PyObject *) itr;
+}
+
+static PyObject *pyrf_pmu_iterator__iter(PyObject *self)
+{
+	Py_INCREF(self);
+	return self;
+}
+
+static PyObject *pyrf_pmu_iterator__iternext(PyObject *self)
+{
+	struct pyrf_pmu_iterator *itr = (void *)self;
+	struct pyrf_pmu *ppmu;
+
+	if (itr->pmu == NULL) {
+		PyErr_SetNone(PyExc_StopIteration);
+		return NULL;
+	}
+	// Create object to return.
+	ppmu = PyObject_New(struct pyrf_pmu, &pyrf_pmu__type);
+	if (ppmu) {
+		ppmu->pmu = itr->pmu;
+		// Advance iterator.
+		itr->pmu = perf_pmus__scan(itr->pmu);
+	}
+	return (PyObject *)ppmu;
+}
+
+/** The python type for the PMU iterator. */
+static PyTypeObject pyrf_pmu_iterator__type = {
+	PyVarObject_HEAD_INIT(NULL, 0)
+	.tp_name = "pmus.iterator",
+	.tp_doc = "Iterator for the pmus string sequence.",
+	.tp_basicsize = sizeof(struct pyrf_pmu_iterator),
+	.tp_itemsize = 0,
+	.tp_flags = Py_TPFLAGS_DEFAULT,
+	.tp_new = pyrf_pmu_iterator__new,
+	.tp_dealloc = (destructor) pyrf_pmu_iterator__dealloc,
+	.tp_iter = pyrf_pmu_iterator__iter,
+	.tp_iternext = pyrf_pmu_iterator__iternext,
+};
+
+static int pyrf_pmu_iterator__setup_types(void)
+{
+	return PyType_Ready(&pyrf_pmu_iterator__type);
+}
+
+static PyObject *pyrf__pmus(PyObject *self, PyObject *args)
+{
+	// Calling the class creates an instance of the iterator.
+	return PyObject_CallObject((PyObject *) &pyrf_pmu_iterator__type, /*args=*/NULL);
+}
+
 struct pyrf_counts_values {
 	PyObject_HEAD
 
@@ -1691,6 +1823,12 @@ static PyMethodDef perf__methods[] = {
 		.ml_flags = METH_VARARGS,
 		.ml_doc	  = PyDoc_STR("Parse a string of events and return an evlist.")
 	},
+	{
+		.ml_name  = "pmus",
+		.ml_meth  = (PyCFunction) pyrf__pmus,
+		.ml_flags = METH_NOARGS,
+		.ml_doc	  = PyDoc_STR("Returns a sequence of pmus.")
+	},
 	{ .ml_name = NULL, }
 };
 
@@ -1718,6 +1856,8 @@ PyMODINIT_FUNC PyInit_perf(void)
 	    pyrf_evsel__setup_types() < 0 ||
 	    pyrf_thread_map__setup_types() < 0 ||
 	    pyrf_cpu_map__setup_types() < 0 ||
+	    pyrf_pmu_iterator__setup_types() < 0 ||
+	    pyrf_pmu__setup_types() < 0 ||
 	    pyrf_counts_values__setup_types() < 0)
 		return module;
 
-- 
2.50.0.727.gbf7dc18ff4-goog


^ permalink raw reply related	[flat|nested] 41+ messages in thread

* [PATCH v7 10/16] perf python: Add function returning dictionary of all events on a PMU
  2025-07-14 16:43 [PATCH v7 00/16] New perf ilist app Ian Rogers
                   ` (8 preceding siblings ...)
  2025-07-14 16:43 ` [PATCH v7 09/16] perf python: Add basic PMU abstraction and pmus sequence Ian Rogers
@ 2025-07-14 16:43 ` Ian Rogers
  2025-07-14 16:43 ` [PATCH v7 11/16] perf ilist: Add new python ilist command Ian Rogers
                   ` (6 subsequent siblings)
  16 siblings, 0 replies; 41+ messages in thread
From: Ian Rogers @ 2025-07-14 16:43 UTC (permalink / raw)
  To: Peter Zijlstra, Ingo Molnar, Arnaldo Carvalho de Melo,
	Namhyung Kim, Mark Rutland, Alexander Shishkin, Jiri Olsa,
	Ian Rogers, Adrian Hunter, Kan Liang, James Clark, Xu Yang,
	Masami Hiramatsu (Google), Collin Funk, Howard Chu, Weilin Wang,
	Andi Kleen, Dr. David Alan Gilbert, Thomas Richter, Tiezhu Yang,
	Gautam Menghani, Thomas Falcon, Chun-Tse Shao, linux-kernel,
	linux-perf-users

Allow all events on a PMU to be gathered, similar to how perf list
gathers event information.

An example usage:
```
$ python
Python 3.12.9 (main, Feb  5 2025, 01:31:18) [GCC 14.2.0] on linux
>>> import perf
>>> for pmu in perf.pmus():
...   print(pmu.events())
...
[{'name': 'mem_load_retired.l3_hit', 'desc': 'Retired load instructions...
```

Signed-off-by: Ian Rogers <irogers@google.com>
---
 tools/perf/util/python.c | 71 ++++++++++++++++++++++++++++++++++++++++
 1 file changed, 71 insertions(+)

diff --git a/tools/perf/util/python.c b/tools/perf/util/python.c
index 860df6436f87..845476411576 100644
--- a/tools/perf/util/python.c
+++ b/tools/perf/util/python.c
@@ -660,6 +660,71 @@ static PyObject *pyrf_pmu__name(PyObject *self)
 	return PyUnicode_FromString(ppmu->pmu->name);
 }
 
+static bool add_to_dict(PyObject *dict, const char *key, const char *value)
+{
+	PyObject *pkey, *pvalue;
+	bool ret;
+
+	if (value == NULL)
+		return true;
+
+	pkey = PyUnicode_FromString(key);
+	pvalue = PyUnicode_FromString(value);
+
+	ret = pkey && pvalue && PyDict_SetItem(dict, pkey, pvalue) == 0;
+	Py_XDECREF(pkey);
+	Py_XDECREF(pvalue);
+	return ret;
+}
+
+static int pyrf_pmu__events_cb(void *state, struct pmu_event_info *info)
+{
+	PyObject *py_list = state;
+	PyObject *dict = PyDict_New();
+
+	if (!dict)
+		return -ENOMEM;
+
+	if (!add_to_dict(dict, "name", info->name) ||
+	    !add_to_dict(dict, "alias", info->alias) ||
+	    !add_to_dict(dict, "scale_unit", info->scale_unit) ||
+	    !add_to_dict(dict, "desc", info->desc) ||
+	    !add_to_dict(dict, "long_desc", info->long_desc) ||
+	    !add_to_dict(dict, "encoding_desc", info->encoding_desc) ||
+	    !add_to_dict(dict, "topic", info->topic) ||
+	    !add_to_dict(dict, "event_type_desc", info->event_type_desc) ||
+	    !add_to_dict(dict, "str", info->str) ||
+	    !add_to_dict(dict, "deprecated", info->deprecated ? "deprecated" : NULL) ||
+	    PyList_Append(py_list, dict) != 0) {
+		Py_DECREF(dict);
+		return -ENOMEM;
+	}
+	Py_DECREF(dict);
+	return 0;
+}
+
+static PyObject *pyrf_pmu__events(PyObject *self)
+{
+	struct pyrf_pmu *ppmu = (void *)self;
+	PyObject *py_list = PyList_New(0);
+	int ret;
+
+	if (!py_list)
+		return NULL;
+
+	ret = perf_pmu__for_each_event(ppmu->pmu,
+				       /*skip_duplicate_pmus=*/false,
+				       py_list,
+				       pyrf_pmu__events_cb);
+	if (ret) {
+		Py_DECREF(py_list);
+		errno = -ret;
+		PyErr_SetFromErrno(PyExc_OSError);
+		return NULL;
+	}
+	return py_list;
+}
+
 static PyObject *pyrf_pmu__repr(PyObject *self)
 {
 	struct pyrf_pmu *ppmu = (void *)self;
@@ -670,6 +735,12 @@ static PyObject *pyrf_pmu__repr(PyObject *self)
 static const char pyrf_pmu__doc[] = PyDoc_STR("perf Performance Monitoring Unit (PMU) object.");
 
 static PyMethodDef pyrf_pmu__methods[] = {
+	{
+		.ml_name  = "events",
+		.ml_meth  = (PyCFunction)pyrf_pmu__events,
+		.ml_flags = METH_NOARGS,
+		.ml_doc	  = PyDoc_STR("Name of the PMU including suffixes.")
+	},
 	{
 		.ml_name  = "name",
 		.ml_meth  = (PyCFunction)pyrf_pmu__name,
-- 
2.50.0.727.gbf7dc18ff4-goog


^ permalink raw reply related	[flat|nested] 41+ messages in thread

* [PATCH v7 11/16] perf ilist: Add new python ilist command
  2025-07-14 16:43 [PATCH v7 00/16] New perf ilist app Ian Rogers
                   ` (9 preceding siblings ...)
  2025-07-14 16:43 ` [PATCH v7 10/16] perf python: Add function returning dictionary of all events on a PMU Ian Rogers
@ 2025-07-14 16:43 ` Ian Rogers
  2025-07-21  7:32   ` Gautam Menghani
  2025-07-23 18:33   ` Falcon, Thomas
  2025-07-14 16:44 ` [PATCH v7 12/16] perf python: Add parse_metrics function Ian Rogers
                   ` (5 subsequent siblings)
  16 siblings, 2 replies; 41+ messages in thread
From: Ian Rogers @ 2025-07-14 16:43 UTC (permalink / raw)
  To: Peter Zijlstra, Ingo Molnar, Arnaldo Carvalho de Melo,
	Namhyung Kim, Mark Rutland, Alexander Shishkin, Jiri Olsa,
	Ian Rogers, Adrian Hunter, Kan Liang, James Clark, Xu Yang,
	Masami Hiramatsu (Google), Collin Funk, Howard Chu, Weilin Wang,
	Andi Kleen, Dr. David Alan Gilbert, Thomas Richter, Tiezhu Yang,
	Gautam Menghani, Thomas Falcon, Chun-Tse Shao, linux-kernel,
	linux-perf-users

The perf ilist command is a textual app [1] similar to perf list. In
the top-left pane a tree of PMUs is displayed. Selecting a PMU expands
the events within it. Selecting an event displays the `perf list`
style event information in the top-right pane.

When an event is selected it is opened and the counters on each CPU
the event is for are periodically read. The bottom of the screen
contains a scrollable set of sparklines showing the events in total
and on each CPU. Scrolling below the sparklines shows the same data as
raw counts. The sparklines are small graphs where the height of the
bar is in relation to maximum of the other counts in the graph.

By default the counts are read with an interval of 0.1 seconds (10
times per second). A -I/--interval command line option allows the
interval to be changed. The oldest read counts are dropped when the
counts fill the line causing the sparkline to move from right to left.

A search box can be pulled up with the 's' key. 'n' and 'p' iterate
through the search results. As some PMUs have hundreds of events a 'c'
key will collapse the events in the current PMU to make navigating the
PMUs easier.

[1] https://textual.textualize.io/

Signed-off-by: Ian Rogers <irogers@google.com>
---
 tools/perf/python/ilist.py | 392 +++++++++++++++++++++++++++++++++++++
 1 file changed, 392 insertions(+)
 create mode 100755 tools/perf/python/ilist.py

diff --git a/tools/perf/python/ilist.py b/tools/perf/python/ilist.py
new file mode 100755
index 000000000000..b21f4c93247e
--- /dev/null
+++ b/tools/perf/python/ilist.py
@@ -0,0 +1,392 @@
+#!/usr/bin/env python3
+# SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause)
+"""Interactive perf list."""
+
+import argparse
+from typing import Any, Dict, Tuple
+import perf
+from textual import on
+from textual.app import App, ComposeResult
+from textual.binding import Binding
+from textual.containers import Horizontal, HorizontalGroup, Vertical, VerticalScroll
+from textual.command import SearchIcon
+from textual.screen import ModalScreen
+from textual.widgets import Button, Footer, Header, Input, Label, Sparkline, Static, Tree
+from textual.widgets.tree import TreeNode
+
+class ErrorScreen(ModalScreen[bool]):
+    """Pop up dialog for errors."""
+
+    CSS="""
+    ErrorScreen {
+        align: center middle;
+    }
+    """
+    def __init__(self, error: str):
+        self.error = error
+        super().__init__()
+
+    def compose(self) -> ComposeResult:
+        yield Button(f"Error: {self.error}", variant="primary", id="error")
+
+    def on_button_pressed(self, event: Button.Pressed) -> None:
+        self.dismiss(True)
+
+
+class SearchScreen(ModalScreen[str]):
+    """Pop up dialog for search."""
+
+    CSS="""
+    SearchScreen Horizontal {
+        align: center middle;
+        margin-top: 1;
+    }
+    SearchScreen Input {
+        width: 1fr;
+    }
+    """
+    def compose(self) -> ComposeResult:
+        yield Horizontal(SearchIcon(), Input(placeholder="Event name"))
+
+    def on_input_submitted(self, event: Input.Submitted) -> None:
+        """Handle the user pressing Enter in the input field."""
+        self.dismiss(event.value)
+
+
+class Counter(HorizontalGroup):
+    """Two labels for a CPU and its counter value."""
+
+    CSS="""
+    Label {
+        gutter: 1;
+    }
+    """
+
+    def __init__(self, cpu: int) -> None:
+        self.cpu = cpu
+        super().__init__()
+
+    def compose(self) -> ComposeResult:
+        label = f"cpu{self.cpu}" if self.cpu >= 0 else "total"
+        yield Label(label + " ")
+        yield Label("0", id=f"counter_{label}")
+
+
+class CounterSparkline(HorizontalGroup):
+    """A Sparkline for a performance counter."""
+
+    def __init__(self, cpu: int) -> None:
+        self.cpu = cpu
+        super().__init__()
+
+    def compose(self) -> ComposeResult:
+        label = f"cpu{self.cpu}" if self.cpu >= 0 else "total"
+        yield Label(label)
+        yield Sparkline([], summary_function=max, id=f"sparkline_{label}")
+
+
+class IListApp(App):
+    TITLE = "Interactive Perf List"
+
+    BINDINGS = [
+        Binding(key="s", action="search", description="Search",
+                tooltip="Search events and PMUs"),
+        Binding(key="n", action="next", description="Next",
+                tooltip="Next search result or item"),
+        Binding(key="p", action="prev", description="Previous",
+                tooltip="Previous search result or item"),
+        Binding(key="c", action="collapse", description="Collapse",
+                tooltip="Collapse the current PMU"),
+        Binding(key="^q", action="quit", description="Quit",
+                tooltip="Quit the app"),
+    ]
+
+    CSS = """
+        /* Make the 'total' sparkline a different color. */
+        #sparkline_total > .sparkline--min-color {
+            color: $accent;
+        }
+        #sparkline_total > .sparkline--max-color {
+            color: $accent 30%;
+        }
+        /*
+         * Make the active_search initially not displayed with the text in
+         * the middle of the line.
+         */
+        #active_search {
+            display: none;
+            width: 100%;
+            text-align: center;
+        }
+    """
+
+    def __init__(self, interval: float) -> None:
+        self.interval = interval
+        self.evlist = None
+        self.search_results: list[TreeNode[str]] = []
+        self.cur_search_result: TreeNode[str] | None = None
+        super().__init__()
+
+
+
+    def expand_and_select(self, node: TreeNode[Any]) -> None:
+        """Expand select a node in the tree."""
+        if node.parent:
+            node.parent.expand()
+            if node.parent.parent:
+                node.parent.parent.expand()
+        node.expand()
+        node.tree.select_node(node)
+        node.tree.scroll_to_node(node)
+
+
+    def set_searched_tree_node(self, previous: bool) -> None:
+        """Set the cur_search_result node to either the next or previous."""
+        l = len(self.search_results)
+
+        if l < 1:
+            tree: Tree[str] = self.query_one("#pmus", Tree)
+            if previous:
+                tree.action_cursor_up()
+            else:
+                tree.action_cursor_down()
+            return
+
+        if self.cur_search_result:
+            idx = self.search_results.index(self.cur_search_result)
+            if previous:
+                idx = idx - 1 if idx > 0 else l - 1
+            else:
+                idx = idx + 1 if idx < l - 1 else 0
+        else:
+            idx = l - 1 if previous else 0
+
+        node = self.search_results[idx]
+        if node == self.cur_search_result:
+            return
+
+        self.cur_search_result = node
+        self.expand_and_select(node)
+
+    def action_search(self) -> None:
+        """Search was chosen."""
+        def set_initial_focus(event: str | None) -> None:
+            """Sets the focus after the SearchScreen is dismissed."""
+
+            search_label = self.query_one("#active_search", Label)
+            search_label.display = True if event else False
+            if not event:
+                return
+            event = event.lower()
+            search_label.update(f'Searching for events matching "{event}"')
+
+            tree: Tree[str] = self.query_one("#pmus", Tree)
+            def find_search_results(event: str, node: TreeNode[str], \
+                                    cursor_seen: bool = False, \
+                                    match_after_cursor: TreeNode[str] | None = None) \
+                    -> Tuple[bool, TreeNode[str] | None]:
+                """Find nodes that match the search remembering the one after the cursor."""
+                if not cursor_seen and node == tree.cursor_node:
+                    cursor_seen = True
+                if node.data and event in node.data:
+                    if cursor_seen and not match_after_cursor:
+                        match_after_cursor = node
+                    self.search_results.append(node)
+
+                if node.children:
+                    for child in node.children:
+                        (cursor_seen, match_after_cursor) = \
+                            find_search_results(event, child, cursor_seen, match_after_cursor)
+                return (cursor_seen, match_after_cursor)
+
+            self.search_results.clear()
+            (_ , self.cur_search_result) = find_search_results(event, tree.root)
+            if len(self.search_results) < 1:
+                self.push_screen(ErrorScreen(f"Failed to find pmu/event {event}"))
+                search_label.display = False
+            elif self.cur_search_result:
+                self.expand_and_select(self.cur_search_result)
+            else:
+                self.set_searched_tree_node(previous=False)
+
+        self.push_screen(SearchScreen(), set_initial_focus)
+
+
+    def action_next(self) -> None:
+        """Next was chosen."""
+        self.set_searched_tree_node(previous=False)
+
+
+    def action_prev(self) -> None:
+        """Previous was chosen."""
+        self.set_searched_tree_node(previous=True)
+
+
+    def action_collapse(self) -> None:
+        """Collapse the potentially large number of events under a PMU."""
+        tree: Tree[str] = self.query_one("#pmus", Tree)
+        node = tree.cursor_node
+        if node and node.parent and node.parent.parent:
+            node.parent.collapse_all()
+            node.tree.scroll_to_node(node.parent)
+
+
+    def update_counts(self) -> None:
+        """Called every interval to update counts."""
+        if not self.evlist:
+            return
+
+        def update_count(cpu: int, count: int):
+            # Update the raw count display.
+            counter: Label = self.query(f"#counter_cpu{cpu}" if cpu >= 0 else "#counter_total")
+            if not counter:
+                return
+            counter = counter.first(Label)
+            counter.update(str(count))
+
+            # Update the sparkline.
+            line: Sparkline = self.query(f"#sparkline_cpu{cpu}" if cpu >= 0 else "#sparkline_total")
+            if not line:
+                return
+            line = line.first(Sparkline)
+            # If there are more events than the width, remove the front event.
+            if len(line.data) > line.size.width:
+                line.data.pop(0)
+            line.data.append(count)
+            line.mutate_reactive(Sparkline.data)
+
+        # Update the total and each CPU counts, assume there's just 1 evsel.
+        total = 0
+        self.evlist.disable()
+        for evsel in self.evlist:
+            for cpu in evsel.cpus():
+                aggr = 0
+                for thread in evsel.threads():
+                    counts = evsel.read(cpu, thread)
+                    aggr += counts.val
+                update_count(cpu, aggr)
+                total += aggr
+        update_count(-1, total)
+        self.evlist.enable()
+
+
+    def on_mount(self) -> None:
+        """When App starts set up periodic event updating."""
+        self.update_counts()
+        self.set_interval(self.interval, self.update_counts)
+
+
+    def set_pmu_and_event(self, pmu: str, event: str) -> None:
+        """Updates the event/description and starts the counters."""
+        # Remove previous event information.
+        if self.evlist:
+            self.evlist.disable()
+            self.evlist.close()
+            lines = self.query(CounterSparkline)
+            for line in lines:
+                line.remove()
+            lines = self.query(Counter)
+            for line in lines:
+                line.remove()
+
+        def pmu_event_description(pmu: str, event: str) -> str:
+            """Find and format event description for {pmu}/{event}/."""
+            def get_info(info: Dict[str, str], key: str):
+                return (info[key] + "\n") if key in info else ""
+
+            for p in perf.pmus():
+                if p.name() != pmu:
+                    continue
+                for info in p.events():
+                    if "name" not in info or info["name"] != event:
+                        continue
+
+                    desc = get_info(info, "topic")
+                    desc += get_info(info, "event_type_desc")
+                    desc += get_info(info, "desc")
+                    desc += get_info(info, "long_desc")
+                    desc += get_info(info, "encoding_desc")
+                    return desc
+            return "description"
+
+        # Parse event, update event text and description.
+        full_name = event if event.startswith(pmu) or ':' in event else f"{pmu}/{event}/"
+        self.query_one("#event_name", Label).update(full_name)
+        self.query_one("#event_description", Static).update(pmu_event_description(pmu, event))
+
+        # Open the event.
+        try:
+            self.evlist = perf.parse_events(full_name)
+            if self.evlist:
+                self.evlist.open()
+                self.evlist.enable()
+        except:
+            self.evlist = None
+
+        if not self.evlist:
+            self.push_screen(ErrorScreen(f"Failed to open {full_name}"))
+            return
+
+        # Add spark lines for all the CPUs. Note, must be done after
+        # open so that the evlist CPUs have been computed by propagate
+        # maps.
+        lines = self.query_one("#lines")
+        line = CounterSparkline(cpu=-1)
+        lines.mount(line)
+        for cpu in self.evlist.all_cpus():
+            line = CounterSparkline(cpu)
+            lines.mount(line)
+        line = Counter(cpu=-1)
+        lines.mount(line)
+        for cpu in self.evlist.all_cpus():
+            line = Counter(cpu)
+            lines.mount(line)
+
+
+    def compose(self) -> ComposeResult:
+        """Draws the app."""
+        def pmu_event_tree() -> Tree:
+            """Create tree of PMUs with events under."""
+            tree: Tree[str] = Tree("PMUs", id="pmus")
+            tree.root.expand()
+            for pmu in perf.pmus():
+                pmu_name = pmu.name().lower()
+                pmu_node = tree.root.add(pmu_name, data=pmu_name)
+                try:
+                    for event in sorted(pmu.events(), key=lambda x: x["name"]):
+                        if "name" in event:
+                            e = event["name"].lower()
+                            if "alias" in event:
+                                pmu_node.add_leaf(f'{e} ({event["alias"]})', data=e)
+                            else:
+                                pmu_node.add_leaf(e, data=e)
+                except:
+                    # Reading events may fail with EPERM, ignore.
+                    pass
+            return tree
+
+        yield Header(id="header")
+        yield Horizontal(Vertical(pmu_event_tree(), id="events"),
+                         Vertical(Label("event name", id="event_name"),
+                                  Static("description", markup=False, id="event_description"),
+                                  ))
+        yield Label(id="active_search")
+        yield VerticalScroll(id="lines")
+        yield Footer(id="footer")
+
+
+    @on(Tree.NodeSelected)
+    def on_tree_node_selected(self, event: Tree.NodeSelected[str]) -> None:
+        """Called when a tree node is selected, selecting the event."""
+        if event.node.parent and event.node.parent.parent:
+            assert event.node.parent.data is not None
+            assert event.node.data is not None
+            self.set_pmu_and_event(event.node.parent.data, event.node.data)
+
+
+if __name__ == "__main__":
+    ap = argparse.ArgumentParser()
+    ap.add_argument('-I', '--interval', help="Counter update interval in seconds", default=0.1)
+    args = ap.parse_args()
+    app = IListApp(float(args.interval))
+    app.run()
-- 
2.50.0.727.gbf7dc18ff4-goog


^ permalink raw reply related	[flat|nested] 41+ messages in thread

* [PATCH v7 12/16] perf python: Add parse_metrics function
  2025-07-14 16:43 [PATCH v7 00/16] New perf ilist app Ian Rogers
                   ` (10 preceding siblings ...)
  2025-07-14 16:43 ` [PATCH v7 11/16] perf ilist: Add new python ilist command Ian Rogers
@ 2025-07-14 16:44 ` Ian Rogers
  2025-07-14 16:44 ` [PATCH v7 13/16] perf python: Add evlist metrics function Ian Rogers
                   ` (4 subsequent siblings)
  16 siblings, 0 replies; 41+ messages in thread
From: Ian Rogers @ 2025-07-14 16:44 UTC (permalink / raw)
  To: Peter Zijlstra, Ingo Molnar, Arnaldo Carvalho de Melo,
	Namhyung Kim, Mark Rutland, Alexander Shishkin, Jiri Olsa,
	Ian Rogers, Adrian Hunter, Kan Liang, James Clark, Xu Yang,
	Masami Hiramatsu (Google), Collin Funk, Howard Chu, Weilin Wang,
	Andi Kleen, Dr. David Alan Gilbert, Thomas Richter, Tiezhu Yang,
	Gautam Menghani, Thomas Falcon, Chun-Tse Shao, linux-kernel,
	linux-perf-users

Add parse_metrics function that takes a string of metrics and/or
metric groups and returns the evlist containing the events and
metrics.

For example:
```
>>> import perf
>>> perf.parse_metrics("TopdownL1")
evlist([cpu/TOPDOWN.SLOTS/,cpu/topdown-retiring/,cpu/topdown-fe-bound/,
cpu/topdown-be-bound/,cpu/topdown-bad-spec/,cpu/INT_MISC.CLEARS_COUNT/,
cpu/INT_MISC.UOP_DROPPING/])
```

Signed-off-by: Ian Rogers <irogers@google.com>
---
 tools/perf/util/python.c | 41 ++++++++++++++++++++++++++++++++++++++++
 1 file changed, 41 insertions(+)

diff --git a/tools/perf/util/python.c b/tools/perf/util/python.c
index 845476411576..6454f24cd810 100644
--- a/tools/perf/util/python.c
+++ b/tools/perf/util/python.c
@@ -1881,6 +1881,40 @@ static PyObject *pyrf__parse_events(PyObject *self, PyObject *args)
 	return result;
 }
 
+static PyObject *pyrf__parse_metrics(PyObject *self, PyObject *args)
+{
+	const char *input;
+	struct evlist evlist = {};
+	PyObject *result;
+	PyObject *pcpus = NULL, *pthreads = NULL;
+	struct perf_cpu_map *cpus;
+	struct perf_thread_map *threads;
+	int ret;
+
+	if (!PyArg_ParseTuple(args, "s|OO", &input, &pcpus, &pthreads))
+		return NULL;
+
+	threads = pthreads ? ((struct pyrf_thread_map *)pthreads)->threads : NULL;
+	cpus = pcpus ? ((struct pyrf_cpu_map *)pcpus)->cpus : NULL;
+
+	evlist__init(&evlist, cpus, threads);
+	ret = metricgroup__parse_groups(&evlist, /*pmu=*/"all", input,
+					/*metric_no_group=*/ false,
+					/*metric_no_merge=*/ false,
+					/*metric_no_threshold=*/ true,
+					/*user_requested_cpu_list=*/ NULL,
+					/*system_wide=*/true,
+					/*hardware_aware_grouping=*/ false);
+	if (ret) {
+		errno = -ret;
+		PyErr_SetFromErrno(PyExc_OSError);
+		return NULL;
+	}
+	result = pyrf_evlist__from_evlist(&evlist);
+	evlist__exit(&evlist);
+	return result;
+}
+
 static PyMethodDef perf__methods[] = {
 	{
 		.ml_name  = "tracepoint",
@@ -1894,6 +1928,13 @@ static PyMethodDef perf__methods[] = {
 		.ml_flags = METH_VARARGS,
 		.ml_doc	  = PyDoc_STR("Parse a string of events and return an evlist.")
 	},
+	{
+		.ml_name  = "parse_metrics",
+		.ml_meth  = (PyCFunction) pyrf__parse_metrics,
+		.ml_flags = METH_VARARGS,
+		.ml_doc	  = PyDoc_STR(
+			"Parse a string of metics or metric groups and return an evlist.")
+	},
 	{
 		.ml_name  = "pmus",
 		.ml_meth  = (PyCFunction) pyrf__pmus,
-- 
2.50.0.727.gbf7dc18ff4-goog


^ permalink raw reply related	[flat|nested] 41+ messages in thread

* [PATCH v7 13/16] perf python: Add evlist metrics function
  2025-07-14 16:43 [PATCH v7 00/16] New perf ilist app Ian Rogers
                   ` (11 preceding siblings ...)
  2025-07-14 16:44 ` [PATCH v7 12/16] perf python: Add parse_metrics function Ian Rogers
@ 2025-07-14 16:44 ` Ian Rogers
  2025-07-14 16:44 ` [PATCH v7 14/16] perf python: Add evlist compute_metric Ian Rogers
                   ` (3 subsequent siblings)
  16 siblings, 0 replies; 41+ messages in thread
From: Ian Rogers @ 2025-07-14 16:44 UTC (permalink / raw)
  To: Peter Zijlstra, Ingo Molnar, Arnaldo Carvalho de Melo,
	Namhyung Kim, Mark Rutland, Alexander Shishkin, Jiri Olsa,
	Ian Rogers, Adrian Hunter, Kan Liang, James Clark, Xu Yang,
	Masami Hiramatsu (Google), Collin Funk, Howard Chu, Weilin Wang,
	Andi Kleen, Dr. David Alan Gilbert, Thomas Richter, Tiezhu Yang,
	Gautam Menghani, Thomas Falcon, Chun-Tse Shao, linux-kernel,
	linux-perf-users

The function returns a list of the names of metrics within the
evlist. For example:
```
>>> import perf
>>> perf.parse_metrics("TopdownL1").metrics()
['tma_bad_speculation', 'tma_frontend_bound', 'tma_backend_bound', 'tma_retiring']
```

Signed-off-by: Ian Rogers <irogers@google.com>
---
 tools/perf/util/python.c | 33 +++++++++++++++++++++++++++++++++
 1 file changed, 33 insertions(+)

diff --git a/tools/perf/util/python.c b/tools/perf/util/python.c
index 6454f24cd810..c1eab506f55b 100644
--- a/tools/perf/util/python.c
+++ b/tools/perf/util/python.c
@@ -1293,6 +1293,33 @@ static PyObject *pyrf_evlist__all_cpus(struct pyrf_evlist *pevlist)
 	return (PyObject *)pcpu_map;
 }
 
+static PyObject *pyrf_evlist__metrics(struct pyrf_evlist *pevlist)
+{
+	PyObject *list = PyList_New(/*len=*/0);
+	struct rb_node *node;
+
+	if (!list)
+		return NULL;
+
+	for (node = rb_first_cached(&pevlist->evlist.metric_events.entries); node;
+	     node = rb_next(node)) {
+		struct metric_event *me = container_of(node, struct metric_event, nd);
+		struct list_head *pos;
+
+		list_for_each(pos, &me->head) {
+			struct metric_expr *expr = container_of(pos, struct metric_expr, nd);
+			PyObject *str = PyUnicode_FromString(expr->metric_name);
+
+			if (!str || PyList_Append(list, str) != 0) {
+				Py_DECREF(list);
+				return NULL;
+			}
+			Py_DECREF(str);
+		}
+	}
+	return list;
+}
+
 static PyObject *pyrf_evlist__mmap(struct pyrf_evlist *pevlist,
 				   PyObject *args, PyObject *kwargs)
 {
@@ -1521,6 +1548,12 @@ static PyMethodDef pyrf_evlist__methods[] = {
 		.ml_flags = METH_NOARGS,
 		.ml_doc	  = PyDoc_STR("CPU map union of all evsel CPU maps.")
 	},
+	{
+		.ml_name  = "metrics",
+		.ml_meth  = (PyCFunction)pyrf_evlist__metrics,
+		.ml_flags = METH_NOARGS,
+		.ml_doc	  = PyDoc_STR("List of metric names within the evlist.")
+	},
 	{
 		.ml_name  = "mmap",
 		.ml_meth  = (PyCFunction)pyrf_evlist__mmap,
-- 
2.50.0.727.gbf7dc18ff4-goog


^ permalink raw reply related	[flat|nested] 41+ messages in thread

* [PATCH v7 14/16] perf python: Add evlist compute_metric
  2025-07-14 16:43 [PATCH v7 00/16] New perf ilist app Ian Rogers
                   ` (12 preceding siblings ...)
  2025-07-14 16:44 ` [PATCH v7 13/16] perf python: Add evlist metrics function Ian Rogers
@ 2025-07-14 16:44 ` Ian Rogers
  2025-07-14 16:44 ` [PATCH v7 15/16] perf python: Add metrics function Ian Rogers
                   ` (2 subsequent siblings)
  16 siblings, 0 replies; 41+ messages in thread
From: Ian Rogers @ 2025-07-14 16:44 UTC (permalink / raw)
  To: Peter Zijlstra, Ingo Molnar, Arnaldo Carvalho de Melo,
	Namhyung Kim, Mark Rutland, Alexander Shishkin, Jiri Olsa,
	Ian Rogers, Adrian Hunter, Kan Liang, James Clark, Xu Yang,
	Masami Hiramatsu (Google), Collin Funk, Howard Chu, Weilin Wang,
	Andi Kleen, Dr. David Alan Gilbert, Thomas Richter, Tiezhu Yang,
	Gautam Menghani, Thomas Falcon, Chun-Tse Shao, linux-kernel,
	linux-perf-users

Add a compute_metric function that computes a metric double value for a
given evlist, metric name, CPU and thread. For example:
```
>>> import perf
>>> x = perf.parse_metrics("TopdownL1")
>>> x.open()
>>> x.enable()
>>> x.disable()
>>> x.metrics()
['tma_bad_speculation', 'tma_frontend_bound', 'tma_backend_bound', 'tma_retiring']
>>> x.compute_metric('tma_bad_speculation', 0, -1)
0.08605342847131037
```

Signed-off-by: Ian Rogers <irogers@google.com>
---
 tools/perf/util/python.c | 125 +++++++++++++++++++++++++++++++++++++++
 1 file changed, 125 insertions(+)

diff --git a/tools/perf/util/python.c b/tools/perf/util/python.c
index c1eab506f55b..980490684ab9 100644
--- a/tools/perf/util/python.c
+++ b/tools/perf/util/python.c
@@ -14,6 +14,7 @@
 #include "evlist.h"
 #include "evsel.h"
 #include "event.h"
+#include "expr.h"
 #include "print_binary.h"
 #include "record.h"
 #include "strbuf.h"
@@ -1320,6 +1321,124 @@ static PyObject *pyrf_evlist__metrics(struct pyrf_evlist *pevlist)
 	return list;
 }
 
+static int prepare_metric(const struct metric_expr *mexp,
+			  const struct evsel *evsel,
+			  struct expr_parse_ctx *pctx,
+			  int cpu_idx, int thread_idx)
+{
+	struct evsel * const *metric_events = mexp->metric_events;
+	struct metric_ref *metric_refs = mexp->metric_refs;
+
+	for (int i = 0; metric_events[i]; i++) {
+		char *n = strdup(evsel__metric_id(metric_events[i]));
+		double val, ena, run;
+		int source_count = evsel__source_count(metric_events[i]);
+		int ret;
+		struct perf_counts_values *old_count, *new_count;
+
+		if (!n)
+			return -ENOMEM;
+
+		if (source_count == 0)
+			source_count = 1;
+
+		ret = evsel__ensure_counts(metric_events[i]);
+		if (ret)
+			return ret;
+
+		/* Set up pointers to the old and newly read counter values. */
+		old_count = perf_counts(metric_events[i]->prev_raw_counts, cpu_idx, thread_idx);
+		new_count = perf_counts(metric_events[i]->counts, cpu_idx, thread_idx);
+		/* Update the value in metric_events[i]->counts. */
+		evsel__read_counter(metric_events[i], cpu_idx, thread_idx);
+
+		val = new_count->val - old_count->val;
+		ena = new_count->ena - old_count->ena;
+		run = new_count->run - old_count->run;
+
+		if (ena != run && run != 0)
+			val = val * ena / run;
+		ret = expr__add_id_val_source_count(pctx, n, val, source_count);
+		if (ret)
+			return ret;
+	}
+
+	for (int i = 0; metric_refs && metric_refs[i].metric_name; i++) {
+		int ret = expr__add_ref(pctx, &metric_refs[i]);
+
+		if (ret)
+			return ret;
+	}
+
+	return 0;
+}
+
+static PyObject *pyrf_evlist__compute_metric(struct pyrf_evlist *pevlist,
+					     PyObject *args, PyObject *kwargs)
+{
+	int ret, cpu = 0, cpu_idx, thread = 0, thread_idx;
+	const char *metric;
+	struct rb_node *node;
+	struct metric_expr *mexp = NULL;
+	struct expr_parse_ctx *pctx;
+	double result = 0;
+
+	if (!PyArg_ParseTuple(args, "sii", &metric, &cpu, &thread))
+		return NULL;
+
+	for (node = rb_first_cached(&pevlist->evlist.metric_events.entries);
+	     mexp == NULL && node;
+	     node = rb_next(node)) {
+		struct metric_event *me = container_of(node, struct metric_event, nd);
+		struct list_head *pos;
+
+		list_for_each(pos, &me->head) {
+			struct metric_expr *e = container_of(pos, struct metric_expr, nd);
+
+			if (strcmp(e->metric_name, metric))
+				continue;
+
+			if (e->metric_events[0] == NULL)
+				continue;
+
+			cpu_idx = perf_cpu_map__idx(e->metric_events[0]->core.cpus,
+						    (struct perf_cpu){.cpu = cpu});
+			if (cpu_idx < 0)
+				continue;
+
+			thread_idx = perf_thread_map__idx(e->metric_events[0]->core.threads,
+							  thread);
+			if (thread_idx < 0)
+				continue;
+
+			mexp = e;
+			break;
+		}
+	}
+	if (!mexp) {
+		PyErr_Format(PyExc_TypeError, "Unknown metric '%s' for CPU '%d' and thread '%d'",
+			     metric, cpu, thread);
+		return NULL;
+	}
+
+	pctx = expr__ctx_new();
+	if (!pctx)
+		return PyErr_NoMemory();
+
+	ret = prepare_metric(mexp, mexp->metric_events[0], pctx, cpu_idx, thread_idx);
+	if (ret) {
+		expr__ctx_free(pctx);
+		errno = -ret;
+		PyErr_SetFromErrno(PyExc_OSError);
+		return NULL;
+	}
+	if (expr__parse(&result, pctx, mexp->metric_expr))
+		result = 0.0;
+
+	expr__ctx_free(pctx);
+	return PyFloat_FromDouble(result);
+}
+
 static PyObject *pyrf_evlist__mmap(struct pyrf_evlist *pevlist,
 				   PyObject *args, PyObject *kwargs)
 {
@@ -1554,6 +1673,12 @@ static PyMethodDef pyrf_evlist__methods[] = {
 		.ml_flags = METH_NOARGS,
 		.ml_doc	  = PyDoc_STR("List of metric names within the evlist.")
 	},
+	{
+		.ml_name  = "compute_metric",
+		.ml_meth  = (PyCFunction)pyrf_evlist__compute_metric,
+		.ml_flags = METH_VARARGS | METH_KEYWORDS,
+		.ml_doc	  = PyDoc_STR("compute metric for given name, cpu and thread")
+	},
 	{
 		.ml_name  = "mmap",
 		.ml_meth  = (PyCFunction)pyrf_evlist__mmap,
-- 
2.50.0.727.gbf7dc18ff4-goog


^ permalink raw reply related	[flat|nested] 41+ messages in thread

* [PATCH v7 15/16] perf python: Add metrics function
  2025-07-14 16:43 [PATCH v7 00/16] New perf ilist app Ian Rogers
                   ` (13 preceding siblings ...)
  2025-07-14 16:44 ` [PATCH v7 14/16] perf python: Add evlist compute_metric Ian Rogers
@ 2025-07-14 16:44 ` Ian Rogers
  2025-07-14 16:44 ` [PATCH v7 16/16] perf ilist: Add support for metrics Ian Rogers
  2025-07-23 15:32 ` [PATCH v7 00/16] New perf ilist app Ian Rogers
  16 siblings, 0 replies; 41+ messages in thread
From: Ian Rogers @ 2025-07-14 16:44 UTC (permalink / raw)
  To: Peter Zijlstra, Ingo Molnar, Arnaldo Carvalho de Melo,
	Namhyung Kim, Mark Rutland, Alexander Shishkin, Jiri Olsa,
	Ian Rogers, Adrian Hunter, Kan Liang, James Clark, Xu Yang,
	Masami Hiramatsu (Google), Collin Funk, Howard Chu, Weilin Wang,
	Andi Kleen, Dr. David Alan Gilbert, Thomas Richter, Tiezhu Yang,
	Gautam Menghani, Thomas Falcon, Chun-Tse Shao, linux-kernel,
	linux-perf-users

The metrics function returns a list dictionaries describing metrics as
strings mapping to strings, except for metric groups that are a string
mapping to a list of strings. For example:
```
>>> import perf
>>> perf.metrics()[0]
{'MetricGroup': ['Power'], 'MetricName': 'C10_Pkg_Residency',
 'PMU': 'default_core', 'MetricExpr': 'cstate_pkg@c10\\-residency@ / TSC',
 'ScaleUnit': '100%', 'BriefDescription': 'C10 residency percent per package'}
```

Signed-off-by: Ian Rogers <irogers@google.com>
---
 tools/perf/util/python.c | 83 ++++++++++++++++++++++++++++++++++++++++
 1 file changed, 83 insertions(+)

diff --git a/tools/perf/util/python.c b/tools/perf/util/python.c
index 980490684ab9..4ccf761335e9 100644
--- a/tools/perf/util/python.c
+++ b/tools/perf/util/python.c
@@ -2073,7 +2073,90 @@ static PyObject *pyrf__parse_metrics(PyObject *self, PyObject *args)
 	return result;
 }
 
+static PyObject *pyrf__metrics_groups(const struct pmu_metric *pm)
+{
+	PyObject *groups = PyList_New(/*len=*/0);
+	const char *mg = pm->metric_group;
+
+	if (!groups)
+		return NULL;
+
+	while (mg) {
+		PyObject *val = NULL;
+		const char *sep = strchr(mg, ';');
+		size_t len = sep ? (size_t)(sep - mg) : strlen(mg);
+
+		if (len > 0) {
+			val = PyUnicode_FromStringAndSize(mg, len);
+			if (val)
+				PyList_Append(groups, val);
+
+			Py_XDECREF(val);
+		}
+		mg = sep ? sep + 1 : NULL;
+	}
+	return groups;
+}
+
+static int pyrf__metrics_cb(const struct pmu_metric *pm,
+			    const struct pmu_metrics_table *table __maybe_unused,
+			    void *vdata)
+{
+	PyObject *py_list = vdata;
+	PyObject *dict = PyDict_New();
+	PyObject *key = dict ? PyUnicode_FromString("MetricGroup") : NULL;
+	PyObject *value = key ? pyrf__metrics_groups(pm) : NULL;
+
+	if (!value || PyDict_SetItem(dict, key, value) != 0) {
+		Py_XDECREF(key);
+		Py_XDECREF(value);
+		Py_XDECREF(dict);
+		return -ENOMEM;
+	}
+
+	if (!add_to_dict(dict, "MetricName", pm->metric_name) ||
+	    !add_to_dict(dict, "PMU", pm->pmu) ||
+	    !add_to_dict(dict, "MetricExpr", pm->metric_expr) ||
+	    !add_to_dict(dict, "MetricThreshold", pm->metric_threshold) ||
+	    !add_to_dict(dict, "ScaleUnit", pm->unit) ||
+	    !add_to_dict(dict, "Compat", pm->compat) ||
+	    !add_to_dict(dict, "BriefDescription", pm->desc) ||
+	    !add_to_dict(dict, "PublicDescription", pm->long_desc) ||
+	    PyList_Append(py_list, dict) != 0) {
+		Py_DECREF(dict);
+		return -ENOMEM;
+	}
+	Py_DECREF(dict);
+	return 0;
+}
+
+static PyObject *pyrf__metrics(PyObject *self, PyObject *args)
+{
+	const struct pmu_metrics_table *table = pmu_metrics_table__find();
+	PyObject *list = PyList_New(/*len=*/0);
+	int ret;
+
+	if (!list)
+		return NULL;
+
+	ret = pmu_metrics_table__for_each_metric(table, pyrf__metrics_cb, list);
+	if (ret) {
+		Py_DECREF(list);
+		errno = -ret;
+		PyErr_SetFromErrno(PyExc_OSError);
+		return NULL;
+	}
+	return list;
+}
+
 static PyMethodDef perf__methods[] = {
+	{
+		.ml_name  = "metrics",
+		.ml_meth  = (PyCFunction) pyrf__metrics,
+		.ml_flags = METH_NOARGS,
+		.ml_doc	  = PyDoc_STR(
+			"Returns a list of metrics represented as string values in dictionaries.")
+	},
 	{
 		.ml_name  = "tracepoint",
 		.ml_meth  = (PyCFunction) pyrf__tracepoint,
-- 
2.50.0.727.gbf7dc18ff4-goog


^ permalink raw reply related	[flat|nested] 41+ messages in thread

* [PATCH v7 16/16] perf ilist: Add support for metrics
  2025-07-14 16:43 [PATCH v7 00/16] New perf ilist app Ian Rogers
                   ` (14 preceding siblings ...)
  2025-07-14 16:44 ` [PATCH v7 15/16] perf python: Add metrics function Ian Rogers
@ 2025-07-14 16:44 ` Ian Rogers
  2025-07-23 15:32 ` [PATCH v7 00/16] New perf ilist app Ian Rogers
  16 siblings, 0 replies; 41+ messages in thread
From: Ian Rogers @ 2025-07-14 16:44 UTC (permalink / raw)
  To: Peter Zijlstra, Ingo Molnar, Arnaldo Carvalho de Melo,
	Namhyung Kim, Mark Rutland, Alexander Shishkin, Jiri Olsa,
	Ian Rogers, Adrian Hunter, Kan Liang, James Clark, Xu Yang,
	Masami Hiramatsu (Google), Collin Funk, Howard Chu, Weilin Wang,
	Andi Kleen, Dr. David Alan Gilbert, Thomas Richter, Tiezhu Yang,
	Gautam Menghani, Thomas Falcon, Chun-Tse Shao, linux-kernel,
	linux-perf-users

Change tree nodes to having a value of either Metric or PmuEvent,
these values have the ability to match searches, be parsed to create
evlists and to give a value per CPU and per thread to display.  Use
perf.metrics to generate a tree of metrics. Most metrics are placed
under their metric group, if the metric group name ends with '_group'
then the metric group is placed next to the associated metric.

Signed-off-by: Ian Rogers <irogers@google.com>
---
 tools/perf/python/ilist.py | 211 +++++++++++++++++++++++++++----------
 1 file changed, 155 insertions(+), 56 deletions(-)

diff --git a/tools/perf/python/ilist.py b/tools/perf/python/ilist.py
index b21f4c93247e..188c3706b4c7 100755
--- a/tools/perf/python/ilist.py
+++ b/tools/perf/python/ilist.py
@@ -2,8 +2,11 @@
 # SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause)
 """Interactive perf list."""
 
+from abc import ABC, abstractmethod
 import argparse
-from typing import Any, Dict, Tuple
+from dataclasses import dataclass
+from typing import Any, Dict, Optional, Tuple
+import math
 import perf
 from textual import on
 from textual.app import App, ComposeResult
@@ -14,6 +17,103 @@ from textual.screen import ModalScreen
 from textual.widgets import Button, Footer, Header, Input, Label, Sparkline, Static, Tree
 from textual.widgets.tree import TreeNode
 
+def get_info(info: Dict[str, str], key: str):
+    return (info[key] + "\n") if key in info else ""
+
+class TreeValue(ABC):
+    """Abstraction for the data of value in the tree."""
+
+    @abstractmethod
+    def name(self) -> str:
+        pass
+
+    @abstractmethod
+    def description(self) -> str:
+        pass
+
+    @abstractmethod
+    def matches(self, query: str) -> bool:
+        pass
+
+    @abstractmethod
+    def parse(self) -> perf.evlist:
+        pass
+
+    @abstractmethod
+    def value(self, evlist: perf.evlist, evsel: perf.evsel, cpu: int, thread: int) -> float:
+        pass
+
+
+@dataclass
+class Metric(TreeValue):
+    """A metric in the tree."""
+    metric_name: str
+
+    def name(self) -> str:
+        return self.metric_name
+
+    def description(self) -> str:
+        """Find and format metric description."""
+        for metric in perf.metrics():
+            if metric["MetricName"] != self.metric_name:
+                continue
+            desc = get_info(metric, "BriefDescription")
+            desc += get_info(metric, "PublicDescription")
+            desc += get_info(metric, "MetricExpr")
+            desc += get_info(metric, "MetricThreshold")
+            return desc
+        return "description"
+
+    def matches(self, query: str) -> bool:
+        return query in self.metric_name
+
+    def parse(self) -> perf.evlist:
+        return perf.parse_metrics(self.metric_name)
+
+    def value(self, evlist: perf.evlist, evsel: perf.evsel, cpu: int, thread: int) -> float:
+        val = evlist.compute_metric(self.metric_name, cpu, thread)
+        return 0 if math.isnan(val) else val
+
+
+@dataclass
+class PmuEvent(TreeValue):
+    """A PMU and event within the tree."""
+    pmu: str
+    event: str
+
+    def name(self) -> str:
+        if self.event.startswith(self.pmu) or ':' in self.event:
+            return self.event
+        else:
+            return f"{self.pmu}/{self.event}/"
+
+    def description(self) -> str:
+        """Find and format event description for {pmu}/{event}/."""
+        for p in perf.pmus():
+            if p.name() != self.pmu:
+                continue
+            for info in p.events():
+                if "name" not in info or info["name"] != self.event:
+                    continue
+
+                desc = get_info(info, "topic")
+                desc += get_info(info, "event_type_desc")
+                desc += get_info(info, "desc")
+                desc += get_info(info, "long_desc")
+                desc += get_info(info, "encoding_desc")
+                return desc
+        return "description"
+
+    def matches(self, query: str) -> bool:
+        return query in self.pmu or query in self.event
+
+    def parse(self) -> perf.evlist:
+        return perf.parse_events(self.name())
+
+    def value(self, evlist: perf.evlist, evsel: perf.evsel, cpu: int, thread: int) -> float:
+        return evsel.read(cpu, thread).val
+
+
 class ErrorScreen(ModalScreen[bool]):
     """Pop up dialog for errors."""
 
@@ -123,8 +223,9 @@ class IListApp(App):
     def __init__(self, interval: float) -> None:
         self.interval = interval
         self.evlist = None
-        self.search_results: list[TreeNode[str]] = []
-        self.cur_search_result: TreeNode[str] | None = None
+        self.selected: Optional[TreeValue] = None
+        self.search_results: list[TreeNode[TreeValue]] = []
+        self.cur_search_result: TreeNode[TreeValue] | None = None
         super().__init__()
 
 
@@ -145,7 +246,7 @@ class IListApp(App):
         l = len(self.search_results)
 
         if l < 1:
-            tree: Tree[str] = self.query_one("#pmus", Tree)
+            tree: Tree[TreeValue] = self.query_one("#root", Tree)
             if previous:
                 tree.action_cursor_up()
             else:
@@ -180,15 +281,15 @@ class IListApp(App):
             event = event.lower()
             search_label.update(f'Searching for events matching "{event}"')
 
-            tree: Tree[str] = self.query_one("#pmus", Tree)
-            def find_search_results(event: str, node: TreeNode[str], \
+            tree: Tree[TreeValue] = self.query_one("#root", Tree)
+            def find_search_results(event: str, node: TreeNode[TreeValue], \
                                     cursor_seen: bool = False, \
-                                    match_after_cursor: TreeNode[str] | None = None) \
-                    -> Tuple[bool, TreeNode[str] | None]:
+                                    match_after_cursor: TreeNode[TreeValue] | None = None) \
+                    -> Tuple[bool, TreeNode[TreeValue] | None]:
                 """Find nodes that match the search remembering the one after the cursor."""
                 if not cursor_seen and node == tree.cursor_node:
                     cursor_seen = True
-                if node.data and event in node.data:
+                if node.data and node.data.matches(event):
                     if cursor_seen and not match_after_cursor:
                         match_after_cursor = node
                     self.search_results.append(node)
@@ -202,7 +303,7 @@ class IListApp(App):
             self.search_results.clear()
             (_ , self.cur_search_result) = find_search_results(event, tree.root)
             if len(self.search_results) < 1:
-                self.push_screen(ErrorScreen(f"Failed to find pmu/event {event}"))
+                self.push_screen(ErrorScreen(f"Failed to find pmu/event or metric {event}"))
                 search_label.display = False
             elif self.cur_search_result:
                 self.expand_and_select(self.cur_search_result)
@@ -223,17 +324,17 @@ class IListApp(App):
 
 
     def action_collapse(self) -> None:
-        """Collapse the potentially large number of events under a PMU."""
-        tree: Tree[str] = self.query_one("#pmus", Tree)
+        """Collapse the part of the tree currently on."""
+        tree: Tree[str] = self.query_one("#root", Tree)
         node = tree.cursor_node
-        if node and node.parent and node.parent.parent:
+        if node and node.parent:
             node.parent.collapse_all()
             node.tree.scroll_to_node(node.parent)
 
 
     def update_counts(self) -> None:
         """Called every interval to update counts."""
-        if not self.evlist:
+        if not self.selected or not self.evlist:
             return
 
         def update_count(cpu: int, count: int):
@@ -262,8 +363,7 @@ class IListApp(App):
             for cpu in evsel.cpus():
                 aggr = 0
                 for thread in evsel.threads():
-                    counts = evsel.read(cpu, thread)
-                    aggr += counts.val
+                    aggr += self.selected.value(self.evlist, evsel, cpu, thread)
                 update_count(cpu, aggr)
                 total += aggr
         update_count(-1, total)
@@ -276,8 +376,10 @@ class IListApp(App):
         self.set_interval(self.interval, self.update_counts)
 
 
-    def set_pmu_and_event(self, pmu: str, event: str) -> None:
+    def set_selected(self, value: TreeValue) -> None:
         """Updates the event/description and starts the counters."""
+        self.selected = value
+
         # Remove previous event information.
         if self.evlist:
             self.evlist.disable()
@@ -289,34 +391,13 @@ class IListApp(App):
             for line in lines:
                 line.remove()
 
-        def pmu_event_description(pmu: str, event: str) -> str:
-            """Find and format event description for {pmu}/{event}/."""
-            def get_info(info: Dict[str, str], key: str):
-                return (info[key] + "\n") if key in info else ""
-
-            for p in perf.pmus():
-                if p.name() != pmu:
-                    continue
-                for info in p.events():
-                    if "name" not in info or info["name"] != event:
-                        continue
-
-                    desc = get_info(info, "topic")
-                    desc += get_info(info, "event_type_desc")
-                    desc += get_info(info, "desc")
-                    desc += get_info(info, "long_desc")
-                    desc += get_info(info, "encoding_desc")
-                    return desc
-            return "description"
-
-        # Parse event, update event text and description.
-        full_name = event if event.startswith(pmu) or ':' in event else f"{pmu}/{event}/"
-        self.query_one("#event_name", Label).update(full_name)
-        self.query_one("#event_description", Static).update(pmu_event_description(pmu, event))
+        # Update event/metric text and description.
+        self.query_one("#event_name", Label).update(value.name())
+        self.query_one("#event_description", Static).update(value.description())
 
         # Open the event.
         try:
-            self.evlist = perf.parse_events(full_name)
+            self.evlist = value.parse()
             if self.evlist:
                 self.evlist.open()
                 self.evlist.enable()
@@ -324,7 +405,7 @@ class IListApp(App):
             self.evlist = None
 
         if not self.evlist:
-            self.push_screen(ErrorScreen(f"Failed to open {full_name}"))
+            self.push_screen(ErrorScreen(f"Failed to open {value.name()}"))
             return
 
         # Add spark lines for all the CPUs. Note, must be done after
@@ -345,28 +426,48 @@ class IListApp(App):
 
     def compose(self) -> ComposeResult:
         """Draws the app."""
-        def pmu_event_tree() -> Tree:
-            """Create tree of PMUs with events under."""
-            tree: Tree[str] = Tree("PMUs", id="pmus")
-            tree.root.expand()
+        def metric_event_tree() -> Tree:
+            """Create tree of PMUs and metricgroups with events or metrics under."""
+            tree: Tree[TreeValue] = Tree("Root", id="root")
+            pmus = tree.root.add("PMUs")
             for pmu in perf.pmus():
                 pmu_name = pmu.name().lower()
-                pmu_node = tree.root.add(pmu_name, data=pmu_name)
+                pmu_node = pmus.add(pmu_name)
                 try:
                     for event in sorted(pmu.events(), key=lambda x: x["name"]):
                         if "name" in event:
                             e = event["name"].lower()
                             if "alias" in event:
-                                pmu_node.add_leaf(f'{e} ({event["alias"]})', data=e)
+                                pmu_node.add_leaf(f'{e} ({event["alias"]})', data=PmuEvent(pmu_name, e))
                             else:
-                                pmu_node.add_leaf(e, data=e)
+                                pmu_node.add_leaf(e, data=PmuEvent(pmu_name, e))
                 except:
                     # Reading events may fail with EPERM, ignore.
                     pass
+            metrics = tree.root.add("Metrics")
+            groups = set()
+            for metric in perf.metrics():
+                groups.update(metric["MetricGroup"])
+
+            def add_metrics_to_tree(node: TreeNode[TreeValue], parent: str):
+                for metric in sorted(perf.metrics(), key=lambda x: x["MetricName"]):
+                    if parent in metric["MetricGroup"]:
+                        name = metric["MetricName"]
+                        node.add_leaf(name, data=Metric(name))
+                        child_group_name = f'{name}_group'
+                        if child_group_name in groups:
+                            add_metrics_to_tree(node.add(child_group_name), child_group_name)
+
+            for group in sorted(groups):
+                if group.endswith('_group'):
+                    continue
+                add_metrics_to_tree(metrics.add(group), group)
+
+            tree.root.expand()
             return tree
 
         yield Header(id="header")
-        yield Horizontal(Vertical(pmu_event_tree(), id="events"),
+        yield Horizontal(Vertical(metric_event_tree(), id="events"),
                          Vertical(Label("event name", id="event_name"),
                                   Static("description", markup=False, id="event_description"),
                                   ))
@@ -376,12 +477,10 @@ class IListApp(App):
 
 
     @on(Tree.NodeSelected)
-    def on_tree_node_selected(self, event: Tree.NodeSelected[str]) -> None:
+    def on_tree_node_selected(self, event: Tree.NodeSelected[TreeValue]) -> None:
         """Called when a tree node is selected, selecting the event."""
-        if event.node.parent and event.node.parent.parent:
-            assert event.node.parent.data is not None
-            assert event.node.data is not None
-            self.set_pmu_and_event(event.node.parent.data, event.node.data)
+        if event.node.data:
+            self.set_selected(event.node.data)
 
 
 if __name__ == "__main__":
-- 
2.50.0.727.gbf7dc18ff4-goog


^ permalink raw reply related	[flat|nested] 41+ messages in thread

* Re: [PATCH v7 11/16] perf ilist: Add new python ilist command
  2025-07-14 16:43 ` [PATCH v7 11/16] perf ilist: Add new python ilist command Ian Rogers
@ 2025-07-21  7:32   ` Gautam Menghani
  2025-07-21 13:41     ` Ian Rogers
  2025-07-23 18:33   ` Falcon, Thomas
  1 sibling, 1 reply; 41+ messages in thread
From: Gautam Menghani @ 2025-07-21  7:32 UTC (permalink / raw)
  To: Ian Rogers
  Cc: Peter Zijlstra, Ingo Molnar, Arnaldo Carvalho de Melo,
	Namhyung Kim, Mark Rutland, Alexander Shishkin, Jiri Olsa,
	Adrian Hunter, Kan Liang, James Clark, Xu Yang,
	Masami Hiramatsu (Google), Collin Funk, Howard Chu, Weilin Wang,
	Andi Kleen, Dr. David Alan Gilbert, Thomas Richter, Tiezhu Yang,
	Thomas Falcon, Chun-Tse Shao, linux-kernel, linux-perf-users

Hi Ian,

Thanks for this. I tested this on both x86 and IBM pseries machine, the
entire series LGTM

Tested-by: Gautam Menghani <gautam@linux.ibm.com>

Thanks,
Gautam



^ permalink raw reply	[flat|nested] 41+ messages in thread

* Re: [PATCH v7 11/16] perf ilist: Add new python ilist command
  2025-07-21  7:32   ` Gautam Menghani
@ 2025-07-21 13:41     ` Ian Rogers
  0 siblings, 0 replies; 41+ messages in thread
From: Ian Rogers @ 2025-07-21 13:41 UTC (permalink / raw)
  To: Gautam Menghani
  Cc: Peter Zijlstra, Ingo Molnar, Arnaldo Carvalho de Melo,
	Namhyung Kim, Mark Rutland, Alexander Shishkin, Jiri Olsa,
	Adrian Hunter, Kan Liang, James Clark, Xu Yang,
	Masami Hiramatsu (Google), Collin Funk, Howard Chu, Weilin Wang,
	Andi Kleen, Dr. David Alan Gilbert, Thomas Richter, Tiezhu Yang,
	Thomas Falcon, Chun-Tse Shao, linux-kernel, linux-perf-users

On Mon, Jul 21, 2025 at 12:32 AM Gautam Menghani <gautam@linux.ibm.com> wrote:
>
> Hi Ian,
>
> Thanks for this. I tested this on both x86 and IBM pseries machine, the
> entire series LGTM
>
> Tested-by: Gautam Menghani <gautam@linux.ibm.com>

Many thanks,
Ian

^ permalink raw reply	[flat|nested] 41+ messages in thread

* Re: [PATCH v7 00/16] New perf ilist app
  2025-07-14 16:43 [PATCH v7 00/16] New perf ilist app Ian Rogers
                   ` (15 preceding siblings ...)
  2025-07-14 16:44 ` [PATCH v7 16/16] perf ilist: Add support for metrics Ian Rogers
@ 2025-07-23 15:32 ` Ian Rogers
  2025-07-23 18:00   ` Namhyung Kim
  16 siblings, 1 reply; 41+ messages in thread
From: Ian Rogers @ 2025-07-23 15:32 UTC (permalink / raw)
  To: Peter Zijlstra, Ingo Molnar, Arnaldo Carvalho de Melo,
	Namhyung Kim, Mark Rutland, Alexander Shishkin, Jiri Olsa,
	Ian Rogers, Adrian Hunter, Kan Liang, James Clark, Xu Yang,
	Masami Hiramatsu (Google), Collin Funk, Howard Chu, Weilin Wang,
	Andi Kleen, Dr. David Alan Gilbert, Thomas Richter, Tiezhu Yang,
	Gautam Menghani, Thomas Falcon, Chun-Tse Shao, linux-kernel,
	linux-perf-users

On Mon, Jul 14, 2025 at 9:44 AM Ian Rogers <irogers@google.com> wrote:
>
> This patch series builds up to the addition of a new ilist app written
> in python using textual [1] for the UI. The app presents perf PMUs and
> events, displays the event information as in `perf list` while at the
> bottom of the console showing recent activity of the event in total
> and across all CPUs. It also displays metrics, placed in a tree
> through their metric group, again with counts being displayed in the
> bottom panel.
>
> The first ground work patches of fixes, cleanup and refactoring were
> separated into their own series here:
> https://lore.kernel.org/lkml/20250709214029.1769089-1-irogers@google.com/
>
> The second part of the patches adds event json for the software PMU
> and makes the tracepoint PMU support iteration of events and the
> like. Without these improvements the tracepoint and software PMUs will
> appear to have no events in the ilist app. As the software PMU moves
> parsing to json, the legacy hard coded parsing is removed. This has
> proven controversial for hardware events and so that cleanup isn't
> done here.
>
> The final patches expand the perf python APIs and add the ilist
> command. To run it you need the updated perf.cpython.so in your
> PYTHONPATH and then execute the script. Expanding PMUs and then
> selecting events will cause event informatin to be displayed in the
> top-right and the counters values to be displayed as sparklines and
> counts in the bottom half of the screen.
>
> [1] https://textual.textualize.io/
>
> v7: Better handle errors in the python code and ignore errors when
>     scanning PMU/events in ilist.py, improving the behavior when not
>     root. Add a tp_pmu/python clean up. Minor kernel coding style
>     clean up. Fix behavior of ilist if a search result isn't found but
>     then next is chosen.
>
> v6: For metrics on hybrid systems don't purely match by name, also
>     match the CPU and thread so that if the same metric exists for
>     different PMUs the appropriate one is selected and counters may be
>     read. Likewise use evsel maps and not the evlists.
>
> v5: Split the series in two. Add metric support. Various clean ups and
>     tweaks to the app in particular around the handling of searches.
>
> v4: No conflict rebase. Picks up perf-tools-next DRM PMU which
>     displays as expected.
>
> v3: Add a search dialog to the ilist app with 'n'ext and 'p'revious
>     keys. No changes in the ground work first 14 patches.
>
> v2: In the jevents event description duplication, some minor changes
>     accidentally missed from v1 meaning that in v1 the descriptions
>     were still duplicated. Expand the cover letter with some thoughts
>     on the series.
>
> Ian Rogers (16):
>   perf python: Add more exceptions on error paths
>   perf jevents: Add common software event json
>   perf parse-events: Remove non-json software events
>   perf tp_pmu: Factor existing tracepoint logic to new file
>   perf tp_pmu: Add event APIs
>   perf list: Remove tracepoint printing code
>   perf list: Skip ABI PMUs when printing pmu values
>   perf python: Improve the tracepoint function if no libtraceevent
>   perf python: Add basic PMU abstraction and pmus sequence
>   perf python: Add function returning dictionary of all events on a PMU
>   perf ilist: Add new python ilist command
>   perf python: Add parse_metrics function
>   perf python: Add evlist metrics function
>   perf python: Add evlist compute_metric
>   perf python: Add metrics function
>   perf ilist: Add support for metrics

Hi,

Is there any more I can do to get this series landed? I appreciate having:

Tested-by: Gautam Menghani <gautam@linux.ibm.com>

I think there is some follow up for "make install" for scripts like
these, but I'm keen for the python API to move forward.

Thanks,
Ian

>
>  tools/perf/builtin-list.c                     |  65 ++-
>  .../arch/common/common/software.json          |  92 ++++
>  tools/perf/pmu-events/empty-pmu-events.c      | 266 +++++----
>  tools/perf/pmu-events/jevents.py              |  15 +-
>  tools/perf/python/ilist.py                    | 491 +++++++++++++++++
>  tools/perf/util/Build                         |   1 +
>  tools/perf/util/evsel.c                       |  21 +-
>  tools/perf/util/parse-events.c                | 198 ++-----
>  tools/perf/util/parse-events.h                |   1 -
>  tools/perf/util/parse-events.l                |  38 +-
>  tools/perf/util/parse-events.y                |  29 +-
>  tools/perf/util/pfm.c                         |   2 +
>  tools/perf/util/pmu.c                         |   7 +
>  tools/perf/util/pmus.c                        |   2 +
>  tools/perf/util/print-events.c                | 100 +---
>  tools/perf/util/print-events.h                |   4 +-
>  tools/perf/util/python.c                      | 519 +++++++++++++++++-
>  tools/perf/util/tp_pmu.c                      | 209 +++++++
>  tools/perf/util/tp_pmu.h                      |  19 +
>  19 files changed, 1638 insertions(+), 441 deletions(-)
>  create mode 100644 tools/perf/pmu-events/arch/common/common/software.json
>  create mode 100755 tools/perf/python/ilist.py
>  create mode 100644 tools/perf/util/tp_pmu.c
>  create mode 100644 tools/perf/util/tp_pmu.h
>
> --
> 2.50.0.727.gbf7dc18ff4-goog
>

^ permalink raw reply	[flat|nested] 41+ messages in thread

* Re: [PATCH v7 01/16] perf python: Add more exceptions on error paths
  2025-07-14 16:43 ` [PATCH v7 01/16] perf python: Add more exceptions on error paths Ian Rogers
@ 2025-07-23 16:48   ` Arnaldo Carvalho de Melo
  2025-07-23 18:12   ` Namhyung Kim
  1 sibling, 0 replies; 41+ messages in thread
From: Arnaldo Carvalho de Melo @ 2025-07-23 16:48 UTC (permalink / raw)
  To: Ian Rogers
  Cc: Peter Zijlstra, Ingo Molnar, Namhyung Kim, Mark Rutland,
	Alexander Shishkin, Jiri Olsa, Adrian Hunter, Kan Liang,
	James Clark, Xu Yang, Masami Hiramatsu (Google), Collin Funk,
	Howard Chu, Weilin Wang, Andi Kleen, Dr. David Alan Gilbert,
	Thomas Richter, Tiezhu Yang, Gautam Menghani, Thomas Falcon,
	Chun-Tse Shao, linux-kernel, linux-perf-users

On Mon, Jul 14, 2025 at 09:43:49AM -0700, Ian Rogers wrote:
> Returning NULL will cause the python interpreter to fail but not
> report an error. If none wants to be returned then Py_None needs
> returning. Set the error for the cases returning NULL so that more
> meaningful interpreter behavior is had.
> 
> Signed-off-by: Ian Rogers <irogers@google.com>
> ---
>  tools/perf/util/python.c | 14 +++++++++++---
>  1 file changed, 11 insertions(+), 3 deletions(-)
> 
> diff --git a/tools/perf/util/python.c b/tools/perf/util/python.c
> index 2f28f71325a8..02544387f39d 100644
> --- a/tools/perf/util/python.c
> +++ b/tools/perf/util/python.c
> @@ -475,13 +475,19 @@ static PyObject *pyrf_event__new(const union perf_event *event)
>  	if ((event->header.type < PERF_RECORD_MMAP ||
>  	     event->header.type > PERF_RECORD_SAMPLE) &&
>  	    !(event->header.type == PERF_RECORD_SWITCH ||
> -	      event->header.type == PERF_RECORD_SWITCH_CPU_WIDE))
> +	      event->header.type == PERF_RECORD_SWITCH_CPU_WIDE)){

Nit, missing space before {

> +		PyErr_Format(PyExc_TypeError, "Unexpected header type %u",
> +			     event->header.type);
>  		return NULL;
> +	}
>  
>  	// FIXME this better be dynamic or we need to parse everything
>  	// before calling perf_mmap__consume(), including tracepoint fields.
> -	if (sizeof(pevent->event) < event->header.size)
> +	if (sizeof(pevent->event) < event->header.size) {
> +		PyErr_Format(PyExc_TypeError, "Unexpected event version: %zd < %u",
> +			     sizeof(pevent->event), event->header.size);
>  		return NULL;
> +	}
>  
>  	ptype = pyrf_event__type[event->header.type];
>  	pevent = PyObject_New(struct pyrf_event, ptype);
> @@ -1199,8 +1205,10 @@ static PyObject *pyrf_evlist__read_on_cpu(struct pyrf_evlist *pevlist,
>  		return NULL;
>  
>  	md = get_md(evlist, cpu);
> -	if (!md)
> +	if (!md) {
> +		PyErr_Format(PyExc_TypeError, "Unknown CPU '%d'", cpu);
>  		return NULL;
> +	}
>  
>  	if (perf_mmap__read_init(&md->core) < 0)
>  		goto end;
> -- 
> 2.50.0.727.gbf7dc18ff4-goog

^ permalink raw reply	[flat|nested] 41+ messages in thread

* Re: [PATCH v7 02/16] perf jevents: Add common software event json
  2025-07-14 16:43 ` [PATCH v7 02/16] perf jevents: Add common software event json Ian Rogers
@ 2025-07-23 16:52   ` Arnaldo Carvalho de Melo
  2025-07-23 18:24   ` Namhyung Kim
  1 sibling, 0 replies; 41+ messages in thread
From: Arnaldo Carvalho de Melo @ 2025-07-23 16:52 UTC (permalink / raw)
  To: Ian Rogers
  Cc: Peter Zijlstra, Ingo Molnar, Namhyung Kim, Mark Rutland,
	Alexander Shishkin, Jiri Olsa, Adrian Hunter, Kan Liang,
	James Clark, Xu Yang, Masami Hiramatsu (Google), Collin Funk,
	Howard Chu, Weilin Wang, Andi Kleen, Dr. David Alan Gilbert,
	Thomas Richter, Tiezhu Yang, Gautam Menghani, Thomas Falcon,
	Chun-Tse Shao, linux-kernel, linux-perf-users

On Mon, Jul 14, 2025 at 09:43:50AM -0700, Ian Rogers wrote:
> Add json for software events so that in perf list the events can have
> a description.  Common json exists for the tool PMU but it has no
> sysfs equivalent. Modify the map_for_pmu code to return the common map
> (rather than an architecture specific one) when a PMU with a common
> name is being looked for, this allows the events to be found.
> 
> Signed-off-by: Ian Rogers <irogers@google.com>
> ---
>  .../arch/common/common/software.json          |  92 ++++++
>  tools/perf/pmu-events/empty-pmu-events.c      | 266 +++++++++++-------
>  tools/perf/pmu-events/jevents.py              |  15 +-
>  3 files changed, 264 insertions(+), 109 deletions(-)
>  create mode 100644 tools/perf/pmu-events/arch/common/common/software.json
> 
> diff --git a/tools/perf/pmu-events/arch/common/common/software.json b/tools/perf/pmu-events/arch/common/common/software.json
> new file mode 100644
> index 000000000000..3af2f565a601
> --- /dev/null
> +++ b/tools/perf/pmu-events/arch/common/common/software.json
> @@ -0,0 +1,92 @@
> +[
> +  {
> +    "Unit": "software",
> +    "EventName": "cpu-clock",
> +    "BriefDescription": "Per-CPU high-resolution timer based event",
> +    "ConfigCode": "0"
> +  },
> +  {
> +    "Unit": "software",
> +    "EventName": "task-clock",
> +    "BriefDescription": "Task based high-resolution timer based event",
> +    "ConfigCode": "1"
> +  },
> +  {
> +    "Unit": "software",
> +    "EventName": "faults",
> +    "BriefDescription": "Number of page faults [This event is an alias of page-faults]",
> +    "ConfigCode": "2"
> +  },
> +  {
> +    "Unit": "software",
> +    "EventName": "page-faults",
> +    "BriefDescription": "Number of page faults [This event is an alias of faults]",
> +    "ConfigCode": "2"
> +  },
> +  {
> +    "Unit": "software",
> +    "EventName": "context-switches",
> +    "BriefDescription": "Number of context switches [This event is an alias of cs]",
> +    "ConfigCode": "3"
> +  },
> +  {
> +    "Unit": "software",
> +    "EventName": "cs",
> +    "BriefDescription": "Number of context switches [This event is an alias of context-switches]",
> +    "ConfigCode": "3"
> +  },
> +  {
> +    "Unit": "software",
> +    "EventName": "cpu-migrations",
> +    "BriefDescription": "Number of times a process has migrated to a new CPU [This event is an alias of migrations]",
> +    "ConfigCode": "4"
> +  },
> +  {
> +    "Unit": "software",
> +    "EventName": "migrations",
> +    "BriefDescription": "Number of times a process has migrated to a new CPU [This event is an alias of cpu-migrations]",
> +    "ConfigCode": "4"
> +  },
> +  {
> +    "Unit": "software",
> +    "EventName": "minor-faults",
> +    "BriefDescription": "Number of minor page faults. Minor faults don't require I/O to handle",
> +    "ConfigCode": "5"
> +  },
> +  {
> +    "Unit": "software",
> +    "EventName": "major-faults",
> +    "BriefDescription": "Number of major page faults. Major faults require I/O to handle",
> +    "ConfigCode": "6"
> +  },
> +  {
> +    "Unit": "software",
> +    "EventName": "alignment-faults",
> +    "BriefDescription": "Number of kernel handled memory alignment faults",
> +    "ConfigCode": "7"
> +  },
> +  {
> +    "Unit": "software",
> +    "EventName": "emulation-faults",
> +    "BriefDescription": "Number of kernel handled unimplemented instruction faults handled through emulation",
> +    "ConfigCode": "8"
> +  },
> +  {
> +    "Unit": "software",
> +    "EventName": "dummy",
> +    "BriefDescription": "A placeholder event that doesn't count anything",
> +    "ConfigCode": "9"
> +  },
> +  {
> +    "Unit": "software",
> +    "EventName": "bpf-output",
> +    "BriefDescription": "An event used by BPF programs to write to the perf ring buffer",
> +    "ConfigCode": "10"
> +  },
> +  {
> +    "Unit": "software",
> +    "EventName": "cgroup-switches",
> +    "BriefDescription": "Number of context switches to a task in a different cgroup",
> +    "ConfigCode": "11"
> +  }
> +]
> diff --git a/tools/perf/pmu-events/empty-pmu-events.c b/tools/perf/pmu-events/empty-pmu-events.c
> index a4569a74db07..7d179d703ab1 100644
> --- a/tools/perf/pmu-events/empty-pmu-events.c
> +++ b/tools/perf/pmu-events/empty-pmu-events.c
> @@ -19,109 +19,147 @@ struct pmu_table_entry {
>  };
>  
>  static const char *const big_c_string =
> -/* offset=0 */ "tool\000"
> -/* offset=5 */ "duration_time\000tool\000Wall clock interval time in nanoseconds\000config=1\000\00000\000\000\000\000\000"
> -/* offset=81 */ "user_time\000tool\000User (non-kernel) time in nanoseconds\000config=2\000\00000\000\000\000\000\000"
> -/* offset=151 */ "system_time\000tool\000System/kernel time in nanoseconds\000config=3\000\00000\000\000\000\000\000"
> -/* offset=219 */ "has_pmem\000tool\0001 if persistent memory installed otherwise 0\000config=4\000\00000\000\000\000\000\000"
> -/* offset=295 */ "num_cores\000tool\000Number of cores. A core consists of 1 or more thread, with each thread being associated with a logical Linux CPU\000config=5\000\00000\000\000\000\000\000"
> -/* offset=440 */ "num_cpus\000tool\000Number of logical Linux CPUs. There may be multiple such CPUs on a core\000config=6\000\00000\000\000\000\000\000"
> -/* offset=543 */ "num_cpus_online\000tool\000Number of online logical Linux CPUs. There may be multiple such CPUs on a core\000config=7\000\00000\000\000\000\000\000"
> -/* offset=660 */ "num_dies\000tool\000Number of dies. Each die has 1 or more cores\000config=8\000\00000\000\000\000\000\000"
> -/* offset=736 */ "num_packages\000tool\000Number of packages. Each package has 1 or more die\000config=9\000\00000\000\000\000\000\000"
> -/* offset=822 */ "slots\000tool\000Number of functional units that in parallel can execute parts of an instruction\000config=0xa\000\00000\000\000\000\000\000"
> -/* offset=932 */ "smt_on\000tool\0001 if simultaneous multithreading (aka hyperthreading) is enable otherwise 0\000config=0xb\000\00000\000\000\000\000\000"
> -/* offset=1039 */ "system_tsc_freq\000tool\000The amount a Time Stamp Counter (TSC) increases per second\000config=0xc\000\00000\000\000\000\000\000"
> -/* offset=1138 */ "default_core\000"
> -/* offset=1151 */ "bp_l1_btb_correct\000branch\000L1 BTB Correction\000event=0x8a\000\00000\000\000\000\000\000"
> -/* offset=1213 */ "bp_l2_btb_correct\000branch\000L2 BTB Correction\000event=0x8b\000\00000\000\000\000\000\000"
> -/* offset=1275 */ "l3_cache_rd\000cache\000L3 cache access, read\000event=0x40\000\00000\000\000\000\000Attributable Level 3 cache access, read\000"
> -/* offset=1373 */ "segment_reg_loads.any\000other\000Number of segment register loads\000event=6,period=200000,umask=0x80\000\00000\000\000\000\000\000"
> -/* offset=1475 */ "dispatch_blocked.any\000other\000Memory cluster signals to block micro-op dispatch for any reason\000event=9,period=200000,umask=0x20\000\00000\000\000\000\000\000"
> -/* offset=1608 */ "eist_trans\000other\000Number of Enhanced Intel SpeedStep(R) Technology (EIST) transitions\000event=0x3a,period=200000\000\00000\000\000\000\000\000"
> -/* offset=1726 */ "hisi_sccl,ddrc\000"
> -/* offset=1741 */ "uncore_hisi_ddrc.flux_wcmd\000uncore\000DDRC write commands\000event=2\000\00000\000\000\000\000\000"
> -/* offset=1811 */ "uncore_cbox\000"
> -/* offset=1823 */ "unc_cbo_xsnp_response.miss_eviction\000uncore\000A cross-core snoop resulted from L3 Eviction which misses in some processor core\000event=0x22,umask=0x81\000\00000\000\000\000\000\000"
> -/* offset=1977 */ "event-hyphen\000uncore\000UNC_CBO_HYPHEN\000event=0xe0\000\00000\000\000\000\000\000"
> -/* offset=2031 */ "event-two-hyph\000uncore\000UNC_CBO_TWO_HYPH\000event=0xc0\000\00000\000\000\000\000\000"
> -/* offset=2089 */ "hisi_sccl,l3c\000"
> -/* offset=2103 */ "uncore_hisi_l3c.rd_hit_cpipe\000uncore\000Total read hits\000event=7\000\00000\000\000\000\000\000"
> -/* offset=2171 */ "uncore_imc_free_running\000"
> -/* offset=2195 */ "uncore_imc_free_running.cache_miss\000uncore\000Total cache misses\000event=0x12\000\00000\000\000\000\000\000"
> -/* offset=2275 */ "uncore_imc\000"
> -/* offset=2286 */ "uncore_imc.cache_hits\000uncore\000Total cache hits\000event=0x34\000\00000\000\000\000\000\000"
> -/* offset=2351 */ "uncore_sys_ddr_pmu\000"
> -/* offset=2370 */ "sys_ddr_pmu.write_cycles\000uncore\000ddr write-cycles event\000event=0x2b\000v8\00000\000\000\000\000\000"
> -/* offset=2446 */ "uncore_sys_ccn_pmu\000"
> -/* offset=2465 */ "sys_ccn_pmu.read_cycles\000uncore\000ccn read-cycles event\000config=0x2c\0000x01\00000\000\000\000\000\000"
> -/* offset=2542 */ "uncore_sys_cmn_pmu\000"
> -/* offset=2561 */ "sys_cmn_pmu.hnf_cache_miss\000uncore\000Counts total cache misses in first lookup result (high priority)\000eventid=1,type=5\000(434|436|43c|43a).*\00000\000\000\000\000\000"
> -/* offset=2704 */ "CPI\000\0001 / IPC\000\000\000\000\000\000\000\00000"
> -/* offset=2726 */ "IPC\000group1\000inst_retired.any / cpu_clk_unhalted.thread\000\000\000\000\000\000\000\00000"
> -/* offset=2789 */ "Frontend_Bound_SMT\000\000idq_uops_not_delivered.core / (4 * (cpu_clk_unhalted.thread / 2 * (1 + cpu_clk_unhalted.one_thread_active / cpu_clk_unhalted.ref_xclk)))\000\000\000\000\000\000\000\00000"
> -/* offset=2955 */ "dcache_miss_cpi\000\000l1d\\-loads\\-misses / inst_retired.any\000\000\000\000\000\000\000\00000"
> -/* offset=3019 */ "icache_miss_cycles\000\000l1i\\-loads\\-misses / inst_retired.any\000\000\000\000\000\000\000\00000"
> -/* offset=3086 */ "cache_miss_cycles\000group1\000dcache_miss_cpi + icache_miss_cycles\000\000\000\000\000\000\000\00000"
> -/* offset=3157 */ "DCache_L2_All_Hits\000\000l2_rqsts.demand_data_rd_hit + l2_rqsts.pf_hit + l2_rqsts.rfo_hit\000\000\000\000\000\000\000\00000"
> -/* offset=3251 */ "DCache_L2_All_Miss\000\000max(l2_rqsts.all_demand_data_rd - l2_rqsts.demand_data_rd_hit, 0) + l2_rqsts.pf_miss + l2_rqsts.rfo_miss\000\000\000\000\000\000\000\00000"
> -/* offset=3385 */ "DCache_L2_All\000\000DCache_L2_All_Hits + DCache_L2_All_Miss\000\000\000\000\000\000\000\00000"
> -/* offset=3449 */ "DCache_L2_Hits\000\000d_ratio(DCache_L2_All_Hits, DCache_L2_All)\000\000\000\000\000\000\000\00000"
> -/* offset=3517 */ "DCache_L2_Misses\000\000d_ratio(DCache_L2_All_Miss, DCache_L2_All)\000\000\000\000\000\000\000\00000"
> -/* offset=3587 */ "M1\000\000ipc + M2\000\000\000\000\000\000\000\00000"
> -/* offset=3609 */ "M2\000\000ipc + M1\000\000\000\000\000\000\000\00000"
> -/* offset=3631 */ "M3\000\0001 / M3\000\000\000\000\000\000\000\00000"
> -/* offset=3651 */ "L1D_Cache_Fill_BW\000\00064 * l1d.replacement / 1e9 / duration_time\000\000\000\000\000\000\000\00000"
> +/* offset=0 */ "software\000"
> +/* offset=9 */ "cpu-clock\000software\000Per-CPU high-resolution timer based event\000config=0\000\00000\000\000\000\000\000"
> +/* offset=87 */ "task-clock\000software\000Task based high-resolution timer based event\000config=1\000\00000\000\000\000\000\000"
> +/* offset=169 */ "faults\000software\000Number of page faults [This event is an alias of page-faults]\000config=2\000\00000\000\000\000\000\000"
> +/* offset=264 */ "page-faults\000software\000Number of page faults [This event is an alias of faults]\000config=2\000\00000\000\000\000\000\000"
> +/* offset=359 */ "context-switches\000software\000Number of context switches [This event is an alias of cs]\000config=3\000\00000\000\000\000\000\000"
> +/* offset=460 */ "cs\000software\000Number of context switches [This event is an alias of context-switches]\000config=3\000\00000\000\000\000\000\000"
> +/* offset=561 */ "cpu-migrations\000software\000Number of times a process has migrated to a new CPU [This event is an alias of migrations]\000config=4\000\00000\000\000\000\000\000"
> +/* offset=693 */ "migrations\000software\000Number of times a process has migrated to a new CPU [This event is an alias of cpu-migrations]\000config=4\000\00000\000\000\000\000\000"
> +/* offset=825 */ "minor-faults\000software\000Number of minor page faults. Minor faults don't require I/O to handle\000config=5\000\00000\000\000\000\000\000"
> +/* offset=934 */ "major-faults\000software\000Number of major page faults. Major faults require I/O to handle\000config=6\000\00000\000\000\000\000\000"
> +/* offset=1037 */ "alignment-faults\000software\000Number of kernel handled memory alignment faults\000config=7\000\00000\000\000\000\000\000"
> +/* offset=1129 */ "emulation-faults\000software\000Number of kernel handled unimplemented instruction faults handled through emulation\000config=8\000\00000\000\000\000\000\000"
> +/* offset=1256 */ "dummy\000software\000A placeholder event that doesn't count anything\000config=9\000\00000\000\000\000\000\000"
> +/* offset=1336 */ "bpf-output\000software\000An event used by BPF programs to write to the perf ring buffer\000config=0xa\000\00000\000\000\000\000\000"
> +/* offset=1438 */ "cgroup-switches\000software\000Number of context switches to a task in a different cgroup\000config=0xb\000\00000\000\000\000\000\000"
> +/* offset=1541 */ "tool\000"
> +/* offset=1546 */ "duration_time\000tool\000Wall clock interval time in nanoseconds\000config=1\000\00000\000\000\000\000\000"
> +/* offset=1622 */ "user_time\000tool\000User (non-kernel) time in nanoseconds\000config=2\000\00000\000\000\000\000\000"
> +/* offset=1692 */ "system_time\000tool\000System/kernel time in nanoseconds\000config=3\000\00000\000\000\000\000\000"
> +/* offset=1760 */ "has_pmem\000tool\0001 if persistent memory installed otherwise 0\000config=4\000\00000\000\000\000\000\000"
> +/* offset=1836 */ "num_cores\000tool\000Number of cores. A core consists of 1 or more thread, with each thread being associated with a logical Linux CPU\000config=5\000\00000\000\000\000\000\000"
> +/* offset=1981 */ "num_cpus\000tool\000Number of logical Linux CPUs. There may be multiple such CPUs on a core\000config=6\000\00000\000\000\000\000\000"
> +/* offset=2084 */ "num_cpus_online\000tool\000Number of online logical Linux CPUs. There may be multiple such CPUs on a core\000config=7\000\00000\000\000\000\000\000"
> +/* offset=2201 */ "num_dies\000tool\000Number of dies. Each die has 1 or more cores\000config=8\000\00000\000\000\000\000\000"
> +/* offset=2277 */ "num_packages\000tool\000Number of packages. Each package has 1 or more die\000config=9\000\00000\000\000\000\000\000"
> +/* offset=2363 */ "slots\000tool\000Number of functional units that in parallel can execute parts of an instruction\000config=0xa\000\00000\000\000\000\000\000"
> +/* offset=2473 */ "smt_on\000tool\0001 if simultaneous multithreading (aka hyperthreading) is enable otherwise 0\000config=0xb\000\00000\000\000\000\000\000"
> +/* offset=2580 */ "system_tsc_freq\000tool\000The amount a Time Stamp Counter (TSC) increases per second\000config=0xc\000\00000\000\000\000\000\000"
> +/* offset=2679 */ "default_core\000"
> +/* offset=2692 */ "bp_l1_btb_correct\000branch\000L1 BTB Correction\000event=0x8a\000\00000\000\000\000\000\000"
> +/* offset=2754 */ "bp_l2_btb_correct\000branch\000L2 BTB Correction\000event=0x8b\000\00000\000\000\000\000\000"
> +/* offset=2816 */ "l3_cache_rd\000cache\000L3 cache access, read\000event=0x40\000\00000\000\000\000\000Attributable Level 3 cache access, read\000"
> +/* offset=2914 */ "segment_reg_loads.any\000other\000Number of segment register loads\000event=6,period=200000,umask=0x80\000\00000\000\000\000\000\000"
> +/* offset=3016 */ "dispatch_blocked.any\000other\000Memory cluster signals to block micro-op dispatch for any reason\000event=9,period=200000,umask=0x20\000\00000\000\000\000\000\000"
> +/* offset=3149 */ "eist_trans\000other\000Number of Enhanced Intel SpeedStep(R) Technology (EIST) transitions\000event=0x3a,period=200000\000\00000\000\000\000\000\000"
> +/* offset=3267 */ "hisi_sccl,ddrc\000"
> +/* offset=3282 */ "uncore_hisi_ddrc.flux_wcmd\000uncore\000DDRC write commands\000event=2\000\00000\000\000\000\000\000"
> +/* offset=3352 */ "uncore_cbox\000"
> +/* offset=3364 */ "unc_cbo_xsnp_response.miss_eviction\000uncore\000A cross-core snoop resulted from L3 Eviction which misses in some processor core\000event=0x22,umask=0x81\000\00000\000\000\000\000\000"
> +/* offset=3518 */ "event-hyphen\000uncore\000UNC_CBO_HYPHEN\000event=0xe0\000\00000\000\000\000\000\000"
> +/* offset=3572 */ "event-two-hyph\000uncore\000UNC_CBO_TWO_HYPH\000event=0xc0\000\00000\000\000\000\000\000"
> +/* offset=3630 */ "hisi_sccl,l3c\000"
> +/* offset=3644 */ "uncore_hisi_l3c.rd_hit_cpipe\000uncore\000Total read hits\000event=7\000\00000\000\000\000\000\000"
> +/* offset=3712 */ "uncore_imc_free_running\000"
> +/* offset=3736 */ "uncore_imc_free_running.cache_miss\000uncore\000Total cache misses\000event=0x12\000\00000\000\000\000\000\000"
> +/* offset=3816 */ "uncore_imc\000"
> +/* offset=3827 */ "uncore_imc.cache_hits\000uncore\000Total cache hits\000event=0x34\000\00000\000\000\000\000\000"
> +/* offset=3892 */ "uncore_sys_ddr_pmu\000"
> +/* offset=3911 */ "sys_ddr_pmu.write_cycles\000uncore\000ddr write-cycles event\000event=0x2b\000v8\00000\000\000\000\000\000"
> +/* offset=3987 */ "uncore_sys_ccn_pmu\000"
> +/* offset=4006 */ "sys_ccn_pmu.read_cycles\000uncore\000ccn read-cycles event\000config=0x2c\0000x01\00000\000\000\000\000\000"
> +/* offset=4083 */ "uncore_sys_cmn_pmu\000"
> +/* offset=4102 */ "sys_cmn_pmu.hnf_cache_miss\000uncore\000Counts total cache misses in first lookup result (high priority)\000eventid=1,type=5\000(434|436|43c|43a).*\00000\000\000\000\000\000"
> +/* offset=4245 */ "CPI\000\0001 / IPC\000\000\000\000\000\000\000\00000"
> +/* offset=4267 */ "IPC\000group1\000inst_retired.any / cpu_clk_unhalted.thread\000\000\000\000\000\000\000\00000"
> +/* offset=4330 */ "Frontend_Bound_SMT\000\000idq_uops_not_delivered.core / (4 * (cpu_clk_unhalted.thread / 2 * (1 + cpu_clk_unhalted.one_thread_active / cpu_clk_unhalted.ref_xclk)))\000\000\000\000\000\000\000\00000"
> +/* offset=4496 */ "dcache_miss_cpi\000\000l1d\\-loads\\-misses / inst_retired.any\000\000\000\000\000\000\000\00000"
> +/* offset=4560 */ "icache_miss_cycles\000\000l1i\\-loads\\-misses / inst_retired.any\000\000\000\000\000\000\000\00000"
> +/* offset=4627 */ "cache_miss_cycles\000group1\000dcache_miss_cpi + icache_miss_cycles\000\000\000\000\000\000\000\00000"
> +/* offset=4698 */ "DCache_L2_All_Hits\000\000l2_rqsts.demand_data_rd_hit + l2_rqsts.pf_hit + l2_rqsts.rfo_hit\000\000\000\000\000\000\000\00000"
> +/* offset=4792 */ "DCache_L2_All_Miss\000\000max(l2_rqsts.all_demand_data_rd - l2_rqsts.demand_data_rd_hit, 0) + l2_rqsts.pf_miss + l2_rqsts.rfo_miss\000\000\000\000\000\000\000\00000"
> +/* offset=4926 */ "DCache_L2_All\000\000DCache_L2_All_Hits + DCache_L2_All_Miss\000\000\000\000\000\000\000\00000"
> +/* offset=4990 */ "DCache_L2_Hits\000\000d_ratio(DCache_L2_All_Hits, DCache_L2_All)\000\000\000\000\000\000\000\00000"
> +/* offset=5058 */ "DCache_L2_Misses\000\000d_ratio(DCache_L2_All_Miss, DCache_L2_All)\000\000\000\000\000\000\000\00000"
> +/* offset=5128 */ "M1\000\000ipc + M2\000\000\000\000\000\000\000\00000"
> +/* offset=5150 */ "M2\000\000ipc + M1\000\000\000\000\000\000\000\00000"
> +/* offset=5172 */ "M3\000\0001 / M3\000\000\000\000\000\000\000\00000"
> +/* offset=5192 */ "L1D_Cache_Fill_BW\000\00064 * l1d.replacement / 1e9 / duration_time\000\000\000\000\000\000\000\00000"
>  ;
>  
> +static const struct compact_pmu_event pmu_events__common_software[] = {
> +{ 1037 }, /* alignment-faults\000software\000Number of kernel handled memory alignment faults\000config=7\000\00000\000\000\000\000\000 */
> +{ 1336 }, /* bpf-output\000software\000An event used by BPF programs to write to the perf ring buffer\000config=0xa\000\00000\000\000\000\000\000 */
> +{ 1438 }, /* cgroup-switches\000software\000Number of context switches to a task in a different cgroup\000config=0xb\000\00000\000\000\000\000\000 */
> +{ 359 }, /* context-switches\000software\000Number of context switches [This event is an alias of cs]\000config=3\000\00000\000\000\000\000\000 */
> +{ 9 }, /* cpu-clock\000software\000Per-CPU high-resolution timer based event\000config=0\000\00000\000\000\000\000\000 */
> +{ 561 }, /* cpu-migrations\000software\000Number of times a process has migrated to a new CPU [This event is an alias of migrations]\000config=4\000\00000\000\000\000\000\000 */
> +{ 460 }, /* cs\000software\000Number of context switches [This event is an alias of context-switches]\000config=3\000\00000\000\000\000\000\000 */
> +{ 1256 }, /* dummy\000software\000A placeholder event that doesn't count anything\000config=9\000\00000\000\000\000\000\000 */
> +{ 1129 }, /* emulation-faults\000software\000Number of kernel handled unimplemented instruction faults handled through emulation\000config=8\000\00000\000\000\000\000\000 */
> +{ 169 }, /* faults\000software\000Number of page faults [This event is an alias of page-faults]\000config=2\000\00000\000\000\000\000\000 */
> +{ 934 }, /* major-faults\000software\000Number of major page faults. Major faults require I/O to handle\000config=6\000\00000\000\000\000\000\000 */
> +{ 693 }, /* migrations\000software\000Number of times a process has migrated to a new CPU [This event is an alias of cpu-migrations]\000config=4\000\00000\000\000\000\000\000 */
> +{ 825 }, /* minor-faults\000software\000Number of minor page faults. Minor faults don't require I/O to handle\000config=5\000\00000\000\000\000\000\000 */
> +{ 264 }, /* page-faults\000software\000Number of page faults [This event is an alias of faults]\000config=2\000\00000\000\000\000\000\000 */
> +{ 87 }, /* task-clock\000software\000Task based high-resolution timer based event\000config=1\000\00000\000\000\000\000\000 */
> +};
>  static const struct compact_pmu_event pmu_events__common_tool[] = {
> -{ 5 }, /* duration_time\000tool\000Wall clock interval time in nanoseconds\000config=1\000\00000\000\000\000\000\000 */
> -{ 219 }, /* has_pmem\000tool\0001 if persistent memory installed otherwise 0\000config=4\000\00000\000\000\000\000\000 */
> -{ 295 }, /* num_cores\000tool\000Number of cores. A core consists of 1 or more thread, with each thread being associated with a logical Linux CPU\000config=5\000\00000\000\000\000\000\000 */
> -{ 440 }, /* num_cpus\000tool\000Number of logical Linux CPUs. There may be multiple such CPUs on a core\000config=6\000\00000\000\000\000\000\000 */
> -{ 543 }, /* num_cpus_online\000tool\000Number of online logical Linux CPUs. There may be multiple such CPUs on a core\000config=7\000\00000\000\000\000\000\000 */
> -{ 660 }, /* num_dies\000tool\000Number of dies. Each die has 1 or more cores\000config=8\000\00000\000\000\000\000\000 */
> -{ 736 }, /* num_packages\000tool\000Number of packages. Each package has 1 or more die\000config=9\000\00000\000\000\000\000\000 */
> -{ 822 }, /* slots\000tool\000Number of functional units that in parallel can execute parts of an instruction\000config=0xa\000\00000\000\000\000\000\000 */
> -{ 932 }, /* smt_on\000tool\0001 if simultaneous multithreading (aka hyperthreading) is enable otherwise 0\000config=0xb\000\00000\000\000\000\000\000 */
> -{ 151 }, /* system_time\000tool\000System/kernel time in nanoseconds\000config=3\000\00000\000\000\000\000\000 */
> -{ 1039 }, /* system_tsc_freq\000tool\000The amount a Time Stamp Counter (TSC) increases per second\000config=0xc\000\00000\000\000\000\000\000 */
> -{ 81 }, /* user_time\000tool\000User (non-kernel) time in nanoseconds\000config=2\000\00000\000\000\000\000\000 */
> +{ 1546 }, /* duration_time\000tool\000Wall clock interval time in nanoseconds\000config=1\000\00000\000\000\000\000\000 */
> +{ 1760 }, /* has_pmem\000tool\0001 if persistent memory installed otherwise 0\000config=4\000\00000\000\000\000\000\000 */
> +{ 1836 }, /* num_cores\000tool\000Number of cores. A core consists of 1 or more thread, with each thread being associated with a logical Linux CPU\000config=5\000\00000\000\000\000\000\000 */
> +{ 1981 }, /* num_cpus\000tool\000Number of logical Linux CPUs. There may be multiple such CPUs on a core\000config=6\000\00000\000\000\000\000\000 */
> +{ 2084 }, /* num_cpus_online\000tool\000Number of online logical Linux CPUs. There may be multiple such CPUs on a core\000config=7\000\00000\000\000\000\000\000 */
> +{ 2201 }, /* num_dies\000tool\000Number of dies. Each die has 1 or more cores\000config=8\000\00000\000\000\000\000\000 */
> +{ 2277 }, /* num_packages\000tool\000Number of packages. Each package has 1 or more die\000config=9\000\00000\000\000\000\000\000 */
> +{ 2363 }, /* slots\000tool\000Number of functional units that in parallel can execute parts of an instruction\000config=0xa\000\00000\000\000\000\000\000 */
> +{ 2473 }, /* smt_on\000tool\0001 if simultaneous multithreading (aka hyperthreading) is enable otherwise 0\000config=0xb\000\00000\000\000\000\000\000 */
> +{ 1692 }, /* system_time\000tool\000System/kernel time in nanoseconds\000config=3\000\00000\000\000\000\000\000 */
> +{ 2580 }, /* system_tsc_freq\000tool\000The amount a Time Stamp Counter (TSC) increases per second\000config=0xc\000\00000\000\000\000\000\000 */
> +{ 1622 }, /* user_time\000tool\000User (non-kernel) time in nanoseconds\000config=2\000\00000\000\000\000\000\000 */
>  
>  };
>  
>  const struct pmu_table_entry pmu_events__common[] = {
> +{
> +     .entries = pmu_events__common_software,
> +     .num_entries = ARRAY_SIZE(pmu_events__common_software),
> +     .pmu_name = { 0 /* software\000 */ },
> +},
>  {
>       .entries = pmu_events__common_tool,
>       .num_entries = ARRAY_SIZE(pmu_events__common_tool),
> -     .pmu_name = { 0 /* tool\000 */ },
> +     .pmu_name = { 1541 /* tool\000 */ },
>  },
>  };
>  
>  static const struct compact_pmu_event pmu_events__test_soc_cpu_default_core[] = {
> -{ 1151 }, /* bp_l1_btb_correct\000branch\000L1 BTB Correction\000event=0x8a\000\00000\000\000\000\000\000 */
> -{ 1213 }, /* bp_l2_btb_correct\000branch\000L2 BTB Correction\000event=0x8b\000\00000\000\000\000\000\000 */
> -{ 1475 }, /* dispatch_blocked.any\000other\000Memory cluster signals to block micro-op dispatch for any reason\000event=9,period=200000,umask=0x20\000\00000\000\000\000\000\000 */
> -{ 1608 }, /* eist_trans\000other\000Number of Enhanced Intel SpeedStep(R) Technology (EIST) transitions\000event=0x3a,period=200000\000\00000\000\000\000\000\000 */
> -{ 1275 }, /* l3_cache_rd\000cache\000L3 cache access, read\000event=0x40\000\00000\000\000\000\000Attributable Level 3 cache access, read\000 */
> -{ 1373 }, /* segment_reg_loads.any\000other\000Number of segment register loads\000event=6,period=200000,umask=0x80\000\00000\000\000\000\000\000 */
> +{ 2692 }, /* bp_l1_btb_correct\000branch\000L1 BTB Correction\000event=0x8a\000\00000\000\000\000\000\000 */
> +{ 2754 }, /* bp_l2_btb_correct\000branch\000L2 BTB Correction\000event=0x8b\000\00000\000\000\000\000\000 */
> +{ 3016 }, /* dispatch_blocked.any\000other\000Memory cluster signals to block micro-op dispatch for any reason\000event=9,period=200000,umask=0x20\000\00000\000\000\000\000\000 */
> +{ 3149 }, /* eist_trans\000other\000Number of Enhanced Intel SpeedStep(R) Technology (EIST) transitions\000event=0x3a,period=200000\000\00000\000\000\000\000\000 */
> +{ 2816 }, /* l3_cache_rd\000cache\000L3 cache access, read\000event=0x40\000\00000\000\000\000\000Attributable Level 3 cache access, read\000 */
> +{ 2914 }, /* segment_reg_loads.any\000other\000Number of segment register loads\000event=6,period=200000,umask=0x80\000\00000\000\000\000\000\000 */
>  };
>  static const struct compact_pmu_event pmu_events__test_soc_cpu_hisi_sccl_ddrc[] = {
> -{ 1741 }, /* uncore_hisi_ddrc.flux_wcmd\000uncore\000DDRC write commands\000event=2\000\00000\000\000\000\000\000 */
> +{ 3282 }, /* uncore_hisi_ddrc.flux_wcmd\000uncore\000DDRC write commands\000event=2\000\00000\000\000\000\000\000 */
>  };
>  static const struct compact_pmu_event pmu_events__test_soc_cpu_hisi_sccl_l3c[] = {
> -{ 2103 }, /* uncore_hisi_l3c.rd_hit_cpipe\000uncore\000Total read hits\000event=7\000\00000\000\000\000\000\000 */
> +{ 3644 }, /* uncore_hisi_l3c.rd_hit_cpipe\000uncore\000Total read hits\000event=7\000\00000\000\000\000\000\000 */
>  };
>  static const struct compact_pmu_event pmu_events__test_soc_cpu_uncore_cbox[] = {
> -{ 1977 }, /* event-hyphen\000uncore\000UNC_CBO_HYPHEN\000event=0xe0\000\00000\000\000\000\000\000 */
> -{ 2031 }, /* event-two-hyph\000uncore\000UNC_CBO_TWO_HYPH\000event=0xc0\000\00000\000\000\000\000\000 */
> -{ 1823 }, /* unc_cbo_xsnp_response.miss_eviction\000uncore\000A cross-core snoop resulted from L3 Eviction which misses in some processor core\000event=0x22,umask=0x81\000\00000\000\000\000\000\000 */
> +{ 3518 }, /* event-hyphen\000uncore\000UNC_CBO_HYPHEN\000event=0xe0\000\00000\000\000\000\000\000 */
> +{ 3572 }, /* event-two-hyph\000uncore\000UNC_CBO_TWO_HYPH\000event=0xc0\000\00000\000\000\000\000\000 */
> +{ 3364 }, /* unc_cbo_xsnp_response.miss_eviction\000uncore\000A cross-core snoop resulted from L3 Eviction which misses in some processor core\000event=0x22,umask=0x81\000\00000\000\000\000\000\000 */
>  };
>  static const struct compact_pmu_event pmu_events__test_soc_cpu_uncore_imc[] = {
> -{ 2286 }, /* uncore_imc.cache_hits\000uncore\000Total cache hits\000event=0x34\000\00000\000\000\000\000\000 */
> +{ 3827 }, /* uncore_imc.cache_hits\000uncore\000Total cache hits\000event=0x34\000\00000\000\000\000\000\000 */
>  };
>  static const struct compact_pmu_event pmu_events__test_soc_cpu_uncore_imc_free_running[] = {
> -{ 2195 }, /* uncore_imc_free_running.cache_miss\000uncore\000Total cache misses\000event=0x12\000\00000\000\000\000\000\000 */
> +{ 3736 }, /* uncore_imc_free_running.cache_miss\000uncore\000Total cache misses\000event=0x12\000\00000\000\000\000\000\000 */
>  
>  };
>  
> @@ -129,51 +167,51 @@ const struct pmu_table_entry pmu_events__test_soc_cpu[] = {
>  {
>       .entries = pmu_events__test_soc_cpu_default_core,
>       .num_entries = ARRAY_SIZE(pmu_events__test_soc_cpu_default_core),
> -     .pmu_name = { 1138 /* default_core\000 */ },
> +     .pmu_name = { 2679 /* default_core\000 */ },
>  },
>  {
>       .entries = pmu_events__test_soc_cpu_hisi_sccl_ddrc,
>       .num_entries = ARRAY_SIZE(pmu_events__test_soc_cpu_hisi_sccl_ddrc),
> -     .pmu_name = { 1726 /* hisi_sccl,ddrc\000 */ },
> +     .pmu_name = { 3267 /* hisi_sccl,ddrc\000 */ },
>  },
>  {
>       .entries = pmu_events__test_soc_cpu_hisi_sccl_l3c,
>       .num_entries = ARRAY_SIZE(pmu_events__test_soc_cpu_hisi_sccl_l3c),
> -     .pmu_name = { 2089 /* hisi_sccl,l3c\000 */ },
> +     .pmu_name = { 3630 /* hisi_sccl,l3c\000 */ },
>  },
>  {
>       .entries = pmu_events__test_soc_cpu_uncore_cbox,
>       .num_entries = ARRAY_SIZE(pmu_events__test_soc_cpu_uncore_cbox),
> -     .pmu_name = { 1811 /* uncore_cbox\000 */ },
> +     .pmu_name = { 3352 /* uncore_cbox\000 */ },
>  },
>  {
>       .entries = pmu_events__test_soc_cpu_uncore_imc,
>       .num_entries = ARRAY_SIZE(pmu_events__test_soc_cpu_uncore_imc),
> -     .pmu_name = { 2275 /* uncore_imc\000 */ },
> +     .pmu_name = { 3816 /* uncore_imc\000 */ },
>  },
>  {
>       .entries = pmu_events__test_soc_cpu_uncore_imc_free_running,
>       .num_entries = ARRAY_SIZE(pmu_events__test_soc_cpu_uncore_imc_free_running),
> -     .pmu_name = { 2171 /* uncore_imc_free_running\000 */ },
> +     .pmu_name = { 3712 /* uncore_imc_free_running\000 */ },
>  },
>  };
>  
>  static const struct compact_pmu_event pmu_metrics__test_soc_cpu_default_core[] = {
> -{ 2704 }, /* CPI\000\0001 / IPC\000\000\000\000\000\000\000\00000 */
> -{ 3385 }, /* DCache_L2_All\000\000DCache_L2_All_Hits + DCache_L2_All_Miss\000\000\000\000\000\000\000\00000 */
> -{ 3157 }, /* DCache_L2_All_Hits\000\000l2_rqsts.demand_data_rd_hit + l2_rqsts.pf_hit + l2_rqsts.rfo_hit\000\000\000\000\000\000\000\00000 */
> -{ 3251 }, /* DCache_L2_All_Miss\000\000max(l2_rqsts.all_demand_data_rd - l2_rqsts.demand_data_rd_hit, 0) + l2_rqsts.pf_miss + l2_rqsts.rfo_miss\000\000\000\000\000\000\000\00000 */
> -{ 3449 }, /* DCache_L2_Hits\000\000d_ratio(DCache_L2_All_Hits, DCache_L2_All)\000\000\000\000\000\000\000\00000 */
> -{ 3517 }, /* DCache_L2_Misses\000\000d_ratio(DCache_L2_All_Miss, DCache_L2_All)\000\000\000\000\000\000\000\00000 */
> -{ 2789 }, /* Frontend_Bound_SMT\000\000idq_uops_not_delivered.core / (4 * (cpu_clk_unhalted.thread / 2 * (1 + cpu_clk_unhalted.one_thread_active / cpu_clk_unhalted.ref_xclk)))\000\000\000\000\000\000\000\00000 */
> -{ 2726 }, /* IPC\000group1\000inst_retired.any / cpu_clk_unhalted.thread\000\000\000\000\000\000\000\00000 */
> -{ 3651 }, /* L1D_Cache_Fill_BW\000\00064 * l1d.replacement / 1e9 / duration_time\000\000\000\000\000\000\000\00000 */
> -{ 3587 }, /* M1\000\000ipc + M2\000\000\000\000\000\000\000\00000 */
> -{ 3609 }, /* M2\000\000ipc + M1\000\000\000\000\000\000\000\00000 */
> -{ 3631 }, /* M3\000\0001 / M3\000\000\000\000\000\000\000\00000 */
> -{ 3086 }, /* cache_miss_cycles\000group1\000dcache_miss_cpi + icache_miss_cycles\000\000\000\000\000\000\000\00000 */
> -{ 2955 }, /* dcache_miss_cpi\000\000l1d\\-loads\\-misses / inst_retired.any\000\000\000\000\000\000\000\00000 */
> -{ 3019 }, /* icache_miss_cycles\000\000l1i\\-loads\\-misses / inst_retired.any\000\000\000\000\000\000\000\00000 */
> +{ 4245 }, /* CPI\000\0001 / IPC\000\000\000\000\000\000\000\00000 */
> +{ 4926 }, /* DCache_L2_All\000\000DCache_L2_All_Hits + DCache_L2_All_Miss\000\000\000\000\000\000\000\00000 */
> +{ 4698 }, /* DCache_L2_All_Hits\000\000l2_rqsts.demand_data_rd_hit + l2_rqsts.pf_hit + l2_rqsts.rfo_hit\000\000\000\000\000\000\000\00000 */
> +{ 4792 }, /* DCache_L2_All_Miss\000\000max(l2_rqsts.all_demand_data_rd - l2_rqsts.demand_data_rd_hit, 0) + l2_rqsts.pf_miss + l2_rqsts.rfo_miss\000\000\000\000\000\000\000\00000 */
> +{ 4990 }, /* DCache_L2_Hits\000\000d_ratio(DCache_L2_All_Hits, DCache_L2_All)\000\000\000\000\000\000\000\00000 */
> +{ 5058 }, /* DCache_L2_Misses\000\000d_ratio(DCache_L2_All_Miss, DCache_L2_All)\000\000\000\000\000\000\000\00000 */
> +{ 4330 }, /* Frontend_Bound_SMT\000\000idq_uops_not_delivered.core / (4 * (cpu_clk_unhalted.thread / 2 * (1 + cpu_clk_unhalted.one_thread_active / cpu_clk_unhalted.ref_xclk)))\000\000\000\000\000\000\000\00000 */
> +{ 4267 }, /* IPC\000group1\000inst_retired.any / cpu_clk_unhalted.thread\000\000\000\000\000\000\000\00000 */
> +{ 5192 }, /* L1D_Cache_Fill_BW\000\00064 * l1d.replacement / 1e9 / duration_time\000\000\000\000\000\000\000\00000 */
> +{ 5128 }, /* M1\000\000ipc + M2\000\000\000\000\000\000\000\00000 */
> +{ 5150 }, /* M2\000\000ipc + M1\000\000\000\000\000\000\000\00000 */
> +{ 5172 }, /* M3\000\0001 / M3\000\000\000\000\000\000\000\00000 */
> +{ 4627 }, /* cache_miss_cycles\000group1\000dcache_miss_cpi + icache_miss_cycles\000\000\000\000\000\000\000\00000 */
> +{ 4496 }, /* dcache_miss_cpi\000\000l1d\\-loads\\-misses / inst_retired.any\000\000\000\000\000\000\000\00000 */
> +{ 4560 }, /* icache_miss_cycles\000\000l1i\\-loads\\-misses / inst_retired.any\000\000\000\000\000\000\000\00000 */
>  
>  };
>  
> @@ -181,18 +219,18 @@ const struct pmu_table_entry pmu_metrics__test_soc_cpu[] = {
>  {
>       .entries = pmu_metrics__test_soc_cpu_default_core,
>       .num_entries = ARRAY_SIZE(pmu_metrics__test_soc_cpu_default_core),
> -     .pmu_name = { 1138 /* default_core\000 */ },
> +     .pmu_name = { 2679 /* default_core\000 */ },
>  },
>  };
>  
>  static const struct compact_pmu_event pmu_events__test_soc_sys_uncore_sys_ccn_pmu[] = {
> -{ 2465 }, /* sys_ccn_pmu.read_cycles\000uncore\000ccn read-cycles event\000config=0x2c\0000x01\00000\000\000\000\000\000 */
> +{ 4006 }, /* sys_ccn_pmu.read_cycles\000uncore\000ccn read-cycles event\000config=0x2c\0000x01\00000\000\000\000\000\000 */
>  };
>  static const struct compact_pmu_event pmu_events__test_soc_sys_uncore_sys_cmn_pmu[] = {
> -{ 2561 }, /* sys_cmn_pmu.hnf_cache_miss\000uncore\000Counts total cache misses in first lookup result (high priority)\000eventid=1,type=5\000(434|436|43c|43a).*\00000\000\000\000\000\000 */
> +{ 4102 }, /* sys_cmn_pmu.hnf_cache_miss\000uncore\000Counts total cache misses in first lookup result (high priority)\000eventid=1,type=5\000(434|436|43c|43a).*\00000\000\000\000\000\000 */
>  };
>  static const struct compact_pmu_event pmu_events__test_soc_sys_uncore_sys_ddr_pmu[] = {
> -{ 2370 }, /* sys_ddr_pmu.write_cycles\000uncore\000ddr write-cycles event\000event=0x2b\000v8\00000\000\000\000\000\000 */
> +{ 3911 }, /* sys_ddr_pmu.write_cycles\000uncore\000ddr write-cycles event\000event=0x2b\000v8\00000\000\000\000\000\000 */
>  
>  };
>  
> @@ -200,17 +238,17 @@ const struct pmu_table_entry pmu_events__test_soc_sys[] = {
>  {
>       .entries = pmu_events__test_soc_sys_uncore_sys_ccn_pmu,
>       .num_entries = ARRAY_SIZE(pmu_events__test_soc_sys_uncore_sys_ccn_pmu),
> -     .pmu_name = { 2446 /* uncore_sys_ccn_pmu\000 */ },
> +     .pmu_name = { 3987 /* uncore_sys_ccn_pmu\000 */ },
>  },
>  {
>       .entries = pmu_events__test_soc_sys_uncore_sys_cmn_pmu,
>       .num_entries = ARRAY_SIZE(pmu_events__test_soc_sys_uncore_sys_cmn_pmu),
> -     .pmu_name = { 2542 /* uncore_sys_cmn_pmu\000 */ },
> +     .pmu_name = { 4083 /* uncore_sys_cmn_pmu\000 */ },
>  },
>  {
>       .entries = pmu_events__test_soc_sys_uncore_sys_ddr_pmu,
>       .num_entries = ARRAY_SIZE(pmu_events__test_soc_sys_uncore_sys_ddr_pmu),
> -     .pmu_name = { 2351 /* uncore_sys_ddr_pmu\000 */ },
> +     .pmu_name = { 3892 /* uncore_sys_ddr_pmu\000 */ },
>  },
>  };
>  
> @@ -632,8 +670,20 @@ static const struct pmu_events_map *map_for_pmu(struct perf_pmu *pmu)
>  {
>          struct perf_cpu cpu = {-1};
>  
> -        if (pmu)
> +        if (pmu) {
> +                for (size_t i=0; i < ARRAY_SIZE(pmu_events__common); i++) {
> +                        const char *pmu_name = &big_c_string[pmu_events__common[i].pmu_name.offset];
> +
> +                        if (!strcmp(pmu_name, pmu->name)) {
> +                                const struct pmu_events_map *map = &pmu_events_map[0];
> +
> +                                while (strcmp("common", map->arch))
> +                                        map++;
> +                                return map;
> +                        }
> +                }
>                  cpu = perf_cpu_map__min(pmu->cpus);
> +        }
>          return map_for_cpu(cpu);
>  }
>  
> diff --git a/tools/perf/pmu-events/jevents.py b/tools/perf/pmu-events/jevents.py
> index e821155151ec..76c1e7b0bc22 100755
> --- a/tools/perf/pmu-events/jevents.py
> +++ b/tools/perf/pmu-events/jevents.py
> @@ -295,6 +295,7 @@ class JsonEvent:
>            'cpu_atom': 'cpu_atom',
>            'ali_drw': 'ali_drw',
>            'arm_cmn': 'arm_cmn',
> +          'software': 'software',
>            'tool': 'tool',
>        }
>        return table[unit] if unit in table else f'uncore_{unit.lower()}'
> @@ -1158,8 +1159,20 @@ static const struct pmu_events_map *map_for_pmu(struct perf_pmu *pmu)
>  {
>          struct perf_cpu cpu = {-1};
>  
> -        if (pmu)
> +        if (pmu) {
> +                for (size_t i=0; i < ARRAY_SIZE(pmu_events__common); i++) {

Nit, space around =

> +                        const char *pmu_name = &big_c_string[pmu_events__common[i].pmu_name.offset];
> +
> +                        if (!strcmp(pmu_name, pmu->name)) {
> +                                const struct pmu_events_map *map = &pmu_events_map[0];
> +
> +                                while (strcmp("common", map->arch))
> +                                        map++;
> +                                return map;
> +                        }
> +                }
>                  cpu = perf_cpu_map__min(pmu->cpus);
> +        }
>          return map_for_cpu(cpu);
>  }
>  
> -- 
> 2.50.0.727.gbf7dc18ff4-goog
> 

^ permalink raw reply	[flat|nested] 41+ messages in thread

* Re: [PATCH v7 04/16] perf tp_pmu: Factor existing tracepoint logic to new file
  2025-07-14 16:43 ` [PATCH v7 04/16] perf tp_pmu: Factor existing tracepoint logic to new file Ian Rogers
@ 2025-07-23 16:57   ` Arnaldo Carvalho de Melo
  0 siblings, 0 replies; 41+ messages in thread
From: Arnaldo Carvalho de Melo @ 2025-07-23 16:57 UTC (permalink / raw)
  To: Ian Rogers
  Cc: Peter Zijlstra, Ingo Molnar, Namhyung Kim, Mark Rutland,
	Alexander Shishkin, Jiri Olsa, Adrian Hunter, Kan Liang,
	James Clark, Xu Yang, Masami Hiramatsu (Google), Collin Funk,
	Howard Chu, Weilin Wang, Andi Kleen, Dr. David Alan Gilbert,
	Thomas Richter, Tiezhu Yang, Gautam Menghani, Thomas Falcon,
	Chun-Tse Shao, linux-kernel, linux-perf-users

On Mon, Jul 14, 2025 at 09:43:52AM -0700, Ian Rogers wrote:
> Start the creation of a tracepoint PMU abstraction. Tracepoint events
> don't follow the regular sysfs perf conventions. Eventually the new
> PMU abstraction will bridge the gap so tracepoint events look more
> like regular perf ones.
> 
> Signed-off-by: Ian Rogers <irogers@google.com>
> ---
>  tools/perf/util/Build          |   1 +
>  tools/perf/util/evsel.c        |  21 +----
>  tools/perf/util/parse-events.c | 147 ++++++++++++++-------------------
>  tools/perf/util/tp_pmu.c       |  95 +++++++++++++++++++++
>  tools/perf/util/tp_pmu.h       |  12 +++
>  5 files changed, 170 insertions(+), 106 deletions(-)
>  create mode 100644 tools/perf/util/tp_pmu.c
>  create mode 100644 tools/perf/util/tp_pmu.h
> 
> diff --git a/tools/perf/util/Build b/tools/perf/util/Build
> index 12bc01c843b2..4959e7a990e4 100644
> --- a/tools/perf/util/Build
> +++ b/tools/perf/util/Build
> @@ -88,6 +88,7 @@ perf-util-y += pmu-bison.o
>  perf-util-y += drm_pmu.o
>  perf-util-y += hwmon_pmu.o
>  perf-util-y += tool_pmu.o
> +perf-util-y += tp_pmu.o
>  perf-util-y += svghelper.o
>  perf-util-y += trace-event-info.o
>  perf-util-y += trace-event-scripting.o
> diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c
> index 3896a04d90af..5a1d19b4e5cd 100644
> --- a/tools/perf/util/evsel.c
> +++ b/tools/perf/util/evsel.c
> @@ -59,6 +59,7 @@
>  #include "drm_pmu.h"
>  #include "hwmon_pmu.h"
>  #include "tool_pmu.h"
> +#include "tp_pmu.h"
>  #include "rlimit.h"
>  #include "../perf-sys.h"
>  #include "util/parse-branch-options.h"
> @@ -571,24 +572,6 @@ struct evsel *evsel__clone(struct evsel *dest, struct evsel *orig)
>  	return NULL;
>  }
>  
> -static int trace_event__id(const char *sys, const char *name)
> -{
> -	char *tp_dir = get_events_file(sys);
> -	char path[PATH_MAX];
> -	int id, err;
> -
> -	if (!tp_dir)
> -		return -1;
> -
> -	scnprintf(path, PATH_MAX, "%s/%s/id", tp_dir, name);
> -	put_events_file(tp_dir);
> -	err = filename__read_int(path, &id);
> -	if (err)
> -		return err;
> -
> -	return id;
> -}
> -
>  /*
>   * Returns pointer with encoded error via <linux/err.h> interface.
>   */
> @@ -622,7 +605,7 @@ struct evsel *evsel__newtp_idx(const char *sys, const char *name, int idx, bool
>  	event_attr_init(&attr);
>  
>  	if (format) {
> -		id = trace_event__id(sys, name);
> +		id = tp_pmu__id(sys, name);
>  		if (id < 0) {
>  			err = id;
>  			goto out_free;
> diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c
> index 1ae481c9802b..f19541ca5268 100644
> --- a/tools/perf/util/parse-events.c
> +++ b/tools/perf/util/parse-events.c
> @@ -17,13 +17,12 @@
>  #include "string2.h"
>  #include "strbuf.h"
>  #include "debug.h"
> -#include <api/fs/tracing_path.h>
> -#include <api/io_dir.h>
>  #include <perf/cpumap.h>
>  #include <util/parse-events-bison.h>
>  #include <util/parse-events-flex.h>
>  #include "pmu.h"
>  #include "pmus.h"
> +#include "tp_pmu.h"
>  #include "asm/bug.h"
>  #include "ui/ui.h"
>  #include "util/parse-branch-options.h"
> @@ -33,6 +32,7 @@
>  #include "util/stat.h"
>  #include "util/util.h"
>  #include "tracepoint.h"
> +#include <api/fs/tracing_path.h>
>  
>  #define MAX_NAME_LEN 100
>  
> @@ -558,105 +558,82 @@ static int add_tracepoint(struct parse_events_state *parse_state,
>  	return 0;
>  }
>  
> -static int add_tracepoint_multi_event(struct parse_events_state *parse_state,
> -				      struct list_head *list,
> -				      const char *sys_name, const char *evt_name,
> -				      struct parse_events_error *err,
> -				      struct parse_events_terms *head_config, YYLTYPE *loc)
> -{
> -	char *evt_path;
> -	struct io_dirent64 *evt_ent;
> -	struct io_dir evt_dir;
> -	int ret = 0, found = 0;
> -
> -	evt_path = get_events_file(sys_name);
> -	if (!evt_path) {
> -		tracepoint_error(err, errno, sys_name, evt_name, loc->first_column);
> -		return -1;
> -	}
> -	io_dir__init(&evt_dir, open(evt_path, O_CLOEXEC | O_DIRECTORY | O_RDONLY));
> -	if (evt_dir.dirfd < 0) {
> -		put_events_file(evt_path);
> -		tracepoint_error(err, errno, sys_name, evt_name, loc->first_column);
> -		return -1;
> -	}
> +struct add_tracepoint_multi_args {
> +	struct parse_events_state *parse_state;
> +	struct list_head *list;
> +	const char *sys_glob;
> +	const char *evt_glob;
> +	struct parse_events_error *err;
> +	struct parse_events_terms *head_config;
> +	YYLTYPE *loc;
> +	int found;
> +};
>  
> -	while (!ret && (evt_ent = io_dir__readdir(&evt_dir))) {
> -		if (!strcmp(evt_ent->d_name, ".")
> -		    || !strcmp(evt_ent->d_name, "..")
> -		    || !strcmp(evt_ent->d_name, "enable")
> -		    || !strcmp(evt_ent->d_name, "filter"))
> -			continue;
> +static int add_tracepoint_multi_event_cb(void *state, const char *sys_name, const char *evt_name)
> +{
> +	struct add_tracepoint_multi_args *args = state;
> +	int ret;
>  
> -		if (!strglobmatch(evt_ent->d_name, evt_name))
> -			continue;
> +	if (!strglobmatch(evt_name, args->evt_glob))
> +		return 0;
>  
> -		found++;
> +	args->found++;
> +	ret = add_tracepoint(args->parse_state, args->list, sys_name, evt_name,
> +			     args->err, args->head_config, args->loc);
>  
> -		ret = add_tracepoint(parse_state, list, sys_name, evt_ent->d_name,
> -				     err, head_config, loc);
> -	}
> +	return ret;
> +}
>  
> -	if (!found) {
> -		tracepoint_error(err, ENOENT, sys_name, evt_name, loc->first_column);
> -		ret = -1;
> +static int add_tracepoint_multi_event(struct add_tracepoint_multi_args *args, const char *sys_name)
> +{
> +	if (strpbrk(args->evt_glob, "*?") == NULL) {
> +		/* Not a glob. */
> +		args->found++;
> +		return add_tracepoint(args->parse_state, args->list, sys_name, args->evt_glob,
> +				      args->err, args->head_config, args->loc);
>  	}
>  
> -	put_events_file(evt_path);
> -	close(evt_dir.dirfd);
> -	return ret;
> +	return tp_pmu__for_each_tp_event(sys_name, args, add_tracepoint_multi_event_cb);
>  }
>  
> -static int add_tracepoint_event(struct parse_events_state *parse_state,
> -				struct list_head *list,
> -				const char *sys_name, const char *evt_name,
> -				struct parse_events_error *err,
> -				struct parse_events_terms *head_config, YYLTYPE *loc)
> +static int add_tracepoint_multi_sys_cb(void *state, const char *sys_name)
>  {
> -	return strpbrk(evt_name, "*?") ?
> -		add_tracepoint_multi_event(parse_state, list, sys_name, evt_name,
> -					   err, head_config, loc) :
> -		add_tracepoint(parse_state, list, sys_name, evt_name,
> -			       err, head_config, loc);
> +	struct add_tracepoint_multi_args *args = state;
> +
> +	if (!strglobmatch(sys_name, args->sys_glob))
> +		return 0;
> +
> +	return add_tracepoint_multi_event(args, sys_name);
>  }
>  
>  static int add_tracepoint_multi_sys(struct parse_events_state *parse_state,
>  				    struct list_head *list,
> -				    const char *sys_name, const char *evt_name,
> +				    const char *sys_glob, const char *evt_glob,
>  				    struct parse_events_error *err,
>  				    struct parse_events_terms *head_config, YYLTYPE *loc)
>  {
> -	struct io_dirent64 *events_ent;
> -	struct io_dir events_dir;
> -	int ret = 0;
> -	char *events_dir_path = get_tracing_file("events");
> +	struct add_tracepoint_multi_args args = {
> +		.parse_state = parse_state,
> +		.list = list,
> +		.sys_glob = sys_glob,
> +		.evt_glob = evt_glob,
> +		.err = err,
> +		.head_config = head_config,
> +		.loc = loc,
> +		.found = 0,
> +	};
> +	int ret;
>  
> -	if (!events_dir_path) {
> -		tracepoint_error(err, errno, sys_name, evt_name, loc->first_column);
> -		return -1;
> +	if (strpbrk(sys_glob, "*?") == NULL) {
> +		/* Not a glob. */
> +		ret = add_tracepoint_multi_event(&args, sys_glob);
> +	} else {
> +		ret = tp_pmu__for_each_tp_sys(&args, add_tracepoint_multi_sys_cb);
>  	}
> -	io_dir__init(&events_dir, open(events_dir_path, O_CLOEXEC | O_DIRECTORY | O_RDONLY));
> -	put_events_file(events_dir_path);
> -	if (events_dir.dirfd < 0) {
> -		tracepoint_error(err, errno, sys_name, evt_name, loc->first_column);
> -		return -1;
> +	if (args.found == 0) {
> +		tracepoint_error(err, ENOENT, sys_glob, evt_glob, loc->first_column);
> +		return -ENOENT;
>  	}
> -
> -	while (!ret && (events_ent = io_dir__readdir(&events_dir))) {
> -		if (!strcmp(events_ent->d_name, ".")
> -		    || !strcmp(events_ent->d_name, "..")
> -		    || !strcmp(events_ent->d_name, "enable")
> -		    || !strcmp(events_ent->d_name, "header_event")
> -		    || !strcmp(events_ent->d_name, "header_page"))
> -			continue;
> -
> -		if (!strglobmatch(events_ent->d_name, sys_name))
> -			continue;
> -
> -		ret = add_tracepoint_event(parse_state, list, events_ent->d_name,
> -					   evt_name, err, head_config, loc);
> -	}
> -	close(events_dir.dirfd);
>  	return ret;
>  }
>  
> @@ -1348,12 +1325,8 @@ int parse_events_add_tracepoint(struct parse_events_state *parse_state,
>  			return -EINVAL;
>  	}
>  
> -	if (strpbrk(sys, "*?"))
> -		return add_tracepoint_multi_sys(parse_state, list, sys, event,
> -						err, head_config, loc);
> -	else
> -		return add_tracepoint_event(parse_state, list, sys, event,
> -					    err, head_config, loc);
> +	return add_tracepoint_multi_sys(parse_state, list, sys, event,
> +					err, head_config, loc);
>  }
>  
>  static int __parse_events_add_numeric(struct parse_events_state *parse_state,
> diff --git a/tools/perf/util/tp_pmu.c b/tools/perf/util/tp_pmu.c
> new file mode 100644
> index 000000000000..fd83164f8763
> --- /dev/null
> +++ b/tools/perf/util/tp_pmu.c
> @@ -0,0 +1,95 @@
> +// SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause)
> +#include "tp_pmu.h"
> +#include <api/fs/fs.h>
> +#include <api/fs/tracing_path.h>
> +#include <api/io_dir.h>
> +#include <linux/kernel.h>
> +#include <errno.h>
> +#include <string.h>
> +
> +int tp_pmu__id(const char *sys, const char *name)
> +{
> +	char *tp_dir = get_events_file(sys);
> +	char path[PATH_MAX];
> +	int id, err;
> +
> +	if (!tp_dir)
> +		return -1;
> +
> +	scnprintf(path, PATH_MAX, "%s/%s/id", tp_dir, name);
> +	put_events_file(tp_dir);
> +	err = filename__read_int(path, &id);
> +	if (err)
> +		return err;
> +
> +	return id;
> +}
> +
> +
> +int tp_pmu__for_each_tp_event(const char *sys, void *state, tp_event_callback cb)
> +{
> +	char *evt_path;
> +	struct io_dirent64 *evt_ent;
> +	struct io_dir evt_dir;
> +	int ret = 0;
> +
> +	evt_path = get_events_file(sys);
> +	if (!evt_path)
> +		return -errno;
> +
> +	io_dir__init(&evt_dir, open(evt_path, O_CLOEXEC | O_DIRECTORY | O_RDONLY));
> +	if (evt_dir.dirfd < 0) {
> +		ret = -errno;
> +		put_events_file(evt_path);
> +		return ret;
> +	}
> +	put_events_file(evt_path);
> +
> +	while (!ret && (evt_ent = io_dir__readdir(&evt_dir))) {
> +		if (!strcmp(evt_ent->d_name, ".")
> +		    || !strcmp(evt_ent->d_name, "..")
> +		    || !strcmp(evt_ent->d_name, "enable")
> +		    || !strcmp(evt_ent->d_name, "filter"))
> +			continue;

I see that the previous code had this style, but since we're moving it
to this separate file, can we have the || at the end of the lines
please?

> +
> +		ret = cb(state, sys, evt_ent->d_name);
> +		if (ret)
> +			break;
> +	}
> +	close(evt_dir.dirfd);
> +	return ret;
> +}
> +
> +int tp_pmu__for_each_tp_sys(void *state, tp_sys_callback cb)
> +{
> +	struct io_dirent64 *events_ent;
> +	struct io_dir events_dir;
> +	int ret = 0;
> +	char *events_dir_path = get_tracing_file("events");
> +
> +	if (!events_dir_path)
> +		return -errno;
> +
> +	io_dir__init(&events_dir, open(events_dir_path, O_CLOEXEC | O_DIRECTORY | O_RDONLY));
> +	if (events_dir.dirfd < 0) {
> +		ret = -errno;
> +		put_events_file(events_dir_path);
> +		return ret;
> +	}
> +	put_events_file(events_dir_path);
> +
> +	while (!ret && (events_ent = io_dir__readdir(&events_dir))) {
> +		if (!strcmp(events_ent->d_name, ".")
> +		    || !strcmp(events_ent->d_name, "..")
> +		    || !strcmp(events_ent->d_name, "enable")
> +		    || !strcmp(events_ent->d_name, "header_event")
> +		    || !strcmp(events_ent->d_name, "header_page"))
> +			continue;

Ditto

> +
> +		ret = cb(state, events_ent->d_name);
> +		if (ret)
> +			break;
> +	}
> +	close(events_dir.dirfd);
> +	return ret;
> +}
> diff --git a/tools/perf/util/tp_pmu.h b/tools/perf/util/tp_pmu.h
> new file mode 100644
> index 000000000000..49537303bd73
> --- /dev/null
> +++ b/tools/perf/util/tp_pmu.h
> @@ -0,0 +1,12 @@
> +/* SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause) */
> +#ifndef __TP_PMU_H
> +#define __TP_PMU_H
> +
> +typedef int (*tp_sys_callback)(void *state, const char *sys_name);
> +typedef int (*tp_event_callback)(void *state, const char *sys_name, const char *evt_name);
> +
> +int tp_pmu__id(const char *sys, const char *name);
> +int tp_pmu__for_each_tp_event(const char *sys, void *state, tp_event_callback cb);
> +int tp_pmu__for_each_tp_sys(void *state, tp_sys_callback cb);
> +
> +#endif /* __TP_PMU_H */
> -- 
> 2.50.0.727.gbf7dc18ff4-goog
> 

^ permalink raw reply	[flat|nested] 41+ messages in thread

* Re: [PATCH v7 00/16] New perf ilist app
  2025-07-23 15:32 ` [PATCH v7 00/16] New perf ilist app Ian Rogers
@ 2025-07-23 18:00   ` Namhyung Kim
  2025-07-23 18:15     ` Ian Rogers
  2025-07-23 19:08     ` Arnaldo Carvalho de Melo
  0 siblings, 2 replies; 41+ messages in thread
From: Namhyung Kim @ 2025-07-23 18:00 UTC (permalink / raw)
  To: Ian Rogers
  Cc: Peter Zijlstra, Ingo Molnar, Arnaldo Carvalho de Melo,
	Mark Rutland, Alexander Shishkin, Jiri Olsa, Adrian Hunter,
	Kan Liang, James Clark, Xu Yang, Masami Hiramatsu (Google),
	Collin Funk, Howard Chu, Weilin Wang, Andi Kleen,
	Dr. David Alan Gilbert, Thomas Richter, Tiezhu Yang,
	Gautam Menghani, Thomas Falcon, Chun-Tse Shao, linux-kernel,
	linux-perf-users

Hi Ian,

On Wed, Jul 23, 2025 at 08:32:33AM -0700, Ian Rogers wrote:
> On Mon, Jul 14, 2025 at 9:44 AM Ian Rogers <irogers@google.com> wrote:
> >
> > This patch series builds up to the addition of a new ilist app written
> > in python using textual [1] for the UI. The app presents perf PMUs and
> > events, displays the event information as in `perf list` while at the
> > bottom of the console showing recent activity of the event in total
> > and across all CPUs. It also displays metrics, placed in a tree
> > through their metric group, again with counts being displayed in the
> > bottom panel.
> >
> > The first ground work patches of fixes, cleanup and refactoring were
> > separated into their own series here:
> > https://lore.kernel.org/lkml/20250709214029.1769089-1-irogers@google.com/
> >
> > The second part of the patches adds event json for the software PMU
> > and makes the tracepoint PMU support iteration of events and the
> > like. Without these improvements the tracepoint and software PMUs will
> > appear to have no events in the ilist app. As the software PMU moves
> > parsing to json, the legacy hard coded parsing is removed. This has
> > proven controversial for hardware events and so that cleanup isn't
> > done here.
> >
> > The final patches expand the perf python APIs and add the ilist
> > command. To run it you need the updated perf.cpython.so in your
> > PYTHONPATH and then execute the script. Expanding PMUs and then
> > selecting events will cause event informatin to be displayed in the
> > top-right and the counters values to be displayed as sparklines and
> > counts in the bottom half of the screen.
> >
> > [1] https://textual.textualize.io/
> >
> > v7: Better handle errors in the python code and ignore errors when
> >     scanning PMU/events in ilist.py, improving the behavior when not
> >     root. Add a tp_pmu/python clean up. Minor kernel coding style
> >     clean up. Fix behavior of ilist if a search result isn't found but
> >     then next is chosen.
> >
> > v6: For metrics on hybrid systems don't purely match by name, also
> >     match the CPU and thread so that if the same metric exists for
> >     different PMUs the appropriate one is selected and counters may be
> >     read. Likewise use evsel maps and not the evlists.
> >
> > v5: Split the series in two. Add metric support. Various clean ups and
> >     tweaks to the app in particular around the handling of searches.
> >
> > v4: No conflict rebase. Picks up perf-tools-next DRM PMU which
> >     displays as expected.
> >
> > v3: Add a search dialog to the ilist app with 'n'ext and 'p'revious
> >     keys. No changes in the ground work first 14 patches.
> >
> > v2: In the jevents event description duplication, some minor changes
> >     accidentally missed from v1 meaning that in v1 the descriptions
> >     were still duplicated. Expand the cover letter with some thoughts
> >     on the series.
> >
> > Ian Rogers (16):
> >   perf python: Add more exceptions on error paths
> >   perf jevents: Add common software event json
> >   perf parse-events: Remove non-json software events
> >   perf tp_pmu: Factor existing tracepoint logic to new file
> >   perf tp_pmu: Add event APIs
> >   perf list: Remove tracepoint printing code
> >   perf list: Skip ABI PMUs when printing pmu values
> >   perf python: Improve the tracepoint function if no libtraceevent
> >   perf python: Add basic PMU abstraction and pmus sequence
> >   perf python: Add function returning dictionary of all events on a PMU
> >   perf ilist: Add new python ilist command
> >   perf python: Add parse_metrics function
> >   perf python: Add evlist metrics function
> >   perf python: Add evlist compute_metric
> >   perf python: Add metrics function
> >   perf ilist: Add support for metrics
> 
> Hi,
> 
> Is there any more I can do to get this series landed? I appreciate having:
> 
> Tested-by: Gautam Menghani <gautam@linux.ibm.com>
> 
> I think there is some follow up for "make install" for scripts like
> these, but I'm keen for the python API to move forward.
 
I'll review the series today so that we can get some part of it, at
least.  Basically I think we need a wrapper script like perf-ilist to
run this easily (maybe with documentation).

Thanks,
Namhyung

> >
> >  tools/perf/builtin-list.c                     |  65 ++-
> >  .../arch/common/common/software.json          |  92 ++++
> >  tools/perf/pmu-events/empty-pmu-events.c      | 266 +++++----
> >  tools/perf/pmu-events/jevents.py              |  15 +-
> >  tools/perf/python/ilist.py                    | 491 +++++++++++++++++
> >  tools/perf/util/Build                         |   1 +
> >  tools/perf/util/evsel.c                       |  21 +-
> >  tools/perf/util/parse-events.c                | 198 ++-----
> >  tools/perf/util/parse-events.h                |   1 -
> >  tools/perf/util/parse-events.l                |  38 +-
> >  tools/perf/util/parse-events.y                |  29 +-
> >  tools/perf/util/pfm.c                         |   2 +
> >  tools/perf/util/pmu.c                         |   7 +
> >  tools/perf/util/pmus.c                        |   2 +
> >  tools/perf/util/print-events.c                | 100 +---
> >  tools/perf/util/print-events.h                |   4 +-
> >  tools/perf/util/python.c                      | 519 +++++++++++++++++-
> >  tools/perf/util/tp_pmu.c                      | 209 +++++++
> >  tools/perf/util/tp_pmu.h                      |  19 +
> >  19 files changed, 1638 insertions(+), 441 deletions(-)
> >  create mode 100644 tools/perf/pmu-events/arch/common/common/software.json
> >  create mode 100755 tools/perf/python/ilist.py
> >  create mode 100644 tools/perf/util/tp_pmu.c
> >  create mode 100644 tools/perf/util/tp_pmu.h
> >
> > --
> > 2.50.0.727.gbf7dc18ff4-goog
> >

^ permalink raw reply	[flat|nested] 41+ messages in thread

* Re: [PATCH v7 01/16] perf python: Add more exceptions on error paths
  2025-07-14 16:43 ` [PATCH v7 01/16] perf python: Add more exceptions on error paths Ian Rogers
  2025-07-23 16:48   ` Arnaldo Carvalho de Melo
@ 2025-07-23 18:12   ` Namhyung Kim
  2025-07-23 18:21     ` Ian Rogers
  1 sibling, 1 reply; 41+ messages in thread
From: Namhyung Kim @ 2025-07-23 18:12 UTC (permalink / raw)
  To: Ian Rogers
  Cc: Peter Zijlstra, Ingo Molnar, Arnaldo Carvalho de Melo,
	Mark Rutland, Alexander Shishkin, Jiri Olsa, Adrian Hunter,
	Kan Liang, James Clark, Xu Yang, Masami Hiramatsu (Google),
	Collin Funk, Howard Chu, Weilin Wang, Andi Kleen,
	Dr. David Alan Gilbert, Thomas Richter, Tiezhu Yang,
	Gautam Menghani, Thomas Falcon, Chun-Tse Shao, linux-kernel,
	linux-perf-users

On Mon, Jul 14, 2025 at 09:43:49AM -0700, Ian Rogers wrote:
> Returning NULL will cause the python interpreter to fail but not
> report an error. If none wants to be returned then Py_None needs
> returning. Set the error for the cases returning NULL so that more
> meaningful interpreter behavior is had.

It looks like you are adding error messages for the failure cases, not
adding new exceptions, right?  IIUC returning NULL in pyrf_event__new()
ends up having PyErr_NoMemory().  Then now it has different messages?

> 
> Signed-off-by: Ian Rogers <irogers@google.com>
> ---
>  tools/perf/util/python.c | 14 +++++++++++---
>  1 file changed, 11 insertions(+), 3 deletions(-)
> 
> diff --git a/tools/perf/util/python.c b/tools/perf/util/python.c
> index 2f28f71325a8..02544387f39d 100644
> --- a/tools/perf/util/python.c
> +++ b/tools/perf/util/python.c
> @@ -475,13 +475,19 @@ static PyObject *pyrf_event__new(const union perf_event *event)
>  	if ((event->header.type < PERF_RECORD_MMAP ||
>  	     event->header.type > PERF_RECORD_SAMPLE) &&
>  	    !(event->header.type == PERF_RECORD_SWITCH ||
> -	      event->header.type == PERF_RECORD_SWITCH_CPU_WIDE))
> +	      event->header.type == PERF_RECORD_SWITCH_CPU_WIDE)){
> +		PyErr_Format(PyExc_TypeError, "Unexpected header type %u",
> +			     event->header.type);
>  		return NULL;
> +	}
>  
>  	// FIXME this better be dynamic or we need to parse everything
>  	// before calling perf_mmap__consume(), including tracepoint fields.
> -	if (sizeof(pevent->event) < event->header.size)
> +	if (sizeof(pevent->event) < event->header.size) {
> +		PyErr_Format(PyExc_TypeError, "Unexpected event version: %zd < %u",

Maybe "Unexpected event size" instead?

Thanks,
Namhyung


> +			     sizeof(pevent->event), event->header.size);
>  		return NULL;
> +	}
>  
>  	ptype = pyrf_event__type[event->header.type];
>  	pevent = PyObject_New(struct pyrf_event, ptype);
> @@ -1199,8 +1205,10 @@ static PyObject *pyrf_evlist__read_on_cpu(struct pyrf_evlist *pevlist,
>  		return NULL;
>  
>  	md = get_md(evlist, cpu);
> -	if (!md)
> +	if (!md) {
> +		PyErr_Format(PyExc_TypeError, "Unknown CPU '%d'", cpu);
>  		return NULL;
> +	}
>  
>  	if (perf_mmap__read_init(&md->core) < 0)
>  		goto end;
> -- 
> 2.50.0.727.gbf7dc18ff4-goog
> 

^ permalink raw reply	[flat|nested] 41+ messages in thread

* Re: [PATCH v7 00/16] New perf ilist app
  2025-07-23 18:00   ` Namhyung Kim
@ 2025-07-23 18:15     ` Ian Rogers
  2025-07-23 19:08     ` Arnaldo Carvalho de Melo
  1 sibling, 0 replies; 41+ messages in thread
From: Ian Rogers @ 2025-07-23 18:15 UTC (permalink / raw)
  To: Namhyung Kim
  Cc: Peter Zijlstra, Ingo Molnar, Arnaldo Carvalho de Melo,
	Mark Rutland, Alexander Shishkin, Jiri Olsa, Adrian Hunter,
	Kan Liang, James Clark, Xu Yang, Masami Hiramatsu (Google),
	Collin Funk, Howard Chu, Weilin Wang, Andi Kleen,
	Dr. David Alan Gilbert, Thomas Richter, Tiezhu Yang,
	Gautam Menghani, Thomas Falcon, Chun-Tse Shao, linux-kernel,
	linux-perf-users

On Wed, Jul 23, 2025 at 11:00 AM Namhyung Kim <namhyung@kernel.org> wrote:
>
> Hi Ian,
>
> On Wed, Jul 23, 2025 at 08:32:33AM -0700, Ian Rogers wrote:
> > On Mon, Jul 14, 2025 at 9:44 AM Ian Rogers <irogers@google.com> wrote:
> > >
> > > This patch series builds up to the addition of a new ilist app written
> > > in python using textual [1] for the UI. The app presents perf PMUs and
> > > events, displays the event information as in `perf list` while at the
> > > bottom of the console showing recent activity of the event in total
> > > and across all CPUs. It also displays metrics, placed in a tree
> > > through their metric group, again with counts being displayed in the
> > > bottom panel.
> > >
> > > The first ground work patches of fixes, cleanup and refactoring were
> > > separated into their own series here:
> > > https://lore.kernel.org/lkml/20250709214029.1769089-1-irogers@google.com/
> > >
> > > The second part of the patches adds event json for the software PMU
> > > and makes the tracepoint PMU support iteration of events and the
> > > like. Without these improvements the tracepoint and software PMUs will
> > > appear to have no events in the ilist app. As the software PMU moves
> > > parsing to json, the legacy hard coded parsing is removed. This has
> > > proven controversial for hardware events and so that cleanup isn't
> > > done here.
> > >
> > > The final patches expand the perf python APIs and add the ilist
> > > command. To run it you need the updated perf.cpython.so in your
> > > PYTHONPATH and then execute the script. Expanding PMUs and then
> > > selecting events will cause event informatin to be displayed in the
> > > top-right and the counters values to be displayed as sparklines and
> > > counts in the bottom half of the screen.
> > >
> > > [1] https://textual.textualize.io/
> > >
> > > v7: Better handle errors in the python code and ignore errors when
> > >     scanning PMU/events in ilist.py, improving the behavior when not
> > >     root. Add a tp_pmu/python clean up. Minor kernel coding style
> > >     clean up. Fix behavior of ilist if a search result isn't found but
> > >     then next is chosen.
> > >
> > > v6: For metrics on hybrid systems don't purely match by name, also
> > >     match the CPU and thread so that if the same metric exists for
> > >     different PMUs the appropriate one is selected and counters may be
> > >     read. Likewise use evsel maps and not the evlists.
> > >
> > > v5: Split the series in two. Add metric support. Various clean ups and
> > >     tweaks to the app in particular around the handling of searches.
> > >
> > > v4: No conflict rebase. Picks up perf-tools-next DRM PMU which
> > >     displays as expected.
> > >
> > > v3: Add a search dialog to the ilist app with 'n'ext and 'p'revious
> > >     keys. No changes in the ground work first 14 patches.
> > >
> > > v2: In the jevents event description duplication, some minor changes
> > >     accidentally missed from v1 meaning that in v1 the descriptions
> > >     were still duplicated. Expand the cover letter with some thoughts
> > >     on the series.
> > >
> > > Ian Rogers (16):
> > >   perf python: Add more exceptions on error paths
> > >   perf jevents: Add common software event json
> > >   perf parse-events: Remove non-json software events
> > >   perf tp_pmu: Factor existing tracepoint logic to new file
> > >   perf tp_pmu: Add event APIs
> > >   perf list: Remove tracepoint printing code
> > >   perf list: Skip ABI PMUs when printing pmu values
> > >   perf python: Improve the tracepoint function if no libtraceevent
> > >   perf python: Add basic PMU abstraction and pmus sequence
> > >   perf python: Add function returning dictionary of all events on a PMU
> > >   perf ilist: Add new python ilist command
> > >   perf python: Add parse_metrics function
> > >   perf python: Add evlist metrics function
> > >   perf python: Add evlist compute_metric
> > >   perf python: Add metrics function
> > >   perf ilist: Add support for metrics
> >
> > Hi,
> >
> > Is there any more I can do to get this series landed? I appreciate having:
> >
> > Tested-by: Gautam Menghani <gautam@linux.ibm.com>
> >
> > I think there is some follow up for "make install" for scripts like
> > these, but I'm keen for the python API to move forward.
>
> I'll review the series today so that we can get some part of it, at
> least.  Basically I think we need a wrapper script like perf-ilist to
> run this easily (maybe with documentation).

Sgtm, I'll hold off on a new version, Arnaldo has caught some useful
nits to clean up in it.

Something related are the scripting engine scripts like gecko and
flamegraph. Something I've discovered is that those scripts work less
well than standalone apps like the ilist.py here. One issue there is
that the scripting engine tends to throw lots of data into a
dictionary in case it is useful, which means there is a higher
overhead than in the standalone app. Another issue is that the
scripting engine wants perf to drive python to drive the script. This
conflicts with python wanting to own the main thread, things like
asyncio, etc. For textual it isn't possible for the app to run on
anything other than the main thread, but it'd be useful to
incrementally load data while displaying it. With the scripting engine
it is only possible to run a textual app at trace_end (i.e. not
incrementally). Something we found in the gecko work was that it was
hard to handle command line arguments in a scripting engine style
script, what options are for record, report and live mode.

What does this mean? I think we want to move the scripting engine into
the python.c and perf python .so and expose it with something like the
session/tool API. I think we should migrate the existing scripts to
use this and then I think we can deprecate the python interpreter
script engine integration. Perhaps we can deprecate perl scripting
engine support at the same time. Then things like ilist.py can be run
with "perf script ilist", similar to how the scripting engine scripts
run today. Your proposal would avoid the need for the script keyword,
but perhaps that'd make it clear why the UI changes. I don't mind
having or not having "script" in the command line :-)

Thanks,
Ian

> Thanks,
> Namhyung
>
> > >
> > >  tools/perf/builtin-list.c                     |  65 ++-
> > >  .../arch/common/common/software.json          |  92 ++++
> > >  tools/perf/pmu-events/empty-pmu-events.c      | 266 +++++----
> > >  tools/perf/pmu-events/jevents.py              |  15 +-
> > >  tools/perf/python/ilist.py                    | 491 +++++++++++++++++
> > >  tools/perf/util/Build                         |   1 +
> > >  tools/perf/util/evsel.c                       |  21 +-
> > >  tools/perf/util/parse-events.c                | 198 ++-----
> > >  tools/perf/util/parse-events.h                |   1 -
> > >  tools/perf/util/parse-events.l                |  38 +-
> > >  tools/perf/util/parse-events.y                |  29 +-
> > >  tools/perf/util/pfm.c                         |   2 +
> > >  tools/perf/util/pmu.c                         |   7 +
> > >  tools/perf/util/pmus.c                        |   2 +
> > >  tools/perf/util/print-events.c                | 100 +---
> > >  tools/perf/util/print-events.h                |   4 +-
> > >  tools/perf/util/python.c                      | 519 +++++++++++++++++-
> > >  tools/perf/util/tp_pmu.c                      | 209 +++++++
> > >  tools/perf/util/tp_pmu.h                      |  19 +
> > >  19 files changed, 1638 insertions(+), 441 deletions(-)
> > >  create mode 100644 tools/perf/pmu-events/arch/common/common/software.json
> > >  create mode 100755 tools/perf/python/ilist.py
> > >  create mode 100644 tools/perf/util/tp_pmu.c
> > >  create mode 100644 tools/perf/util/tp_pmu.h
> > >
> > > --
> > > 2.50.0.727.gbf7dc18ff4-goog
> > >

^ permalink raw reply	[flat|nested] 41+ messages in thread

* Re: [PATCH v7 01/16] perf python: Add more exceptions on error paths
  2025-07-23 18:12   ` Namhyung Kim
@ 2025-07-23 18:21     ` Ian Rogers
  2025-07-23 22:24       ` Ian Rogers
  0 siblings, 1 reply; 41+ messages in thread
From: Ian Rogers @ 2025-07-23 18:21 UTC (permalink / raw)
  To: Namhyung Kim
  Cc: Peter Zijlstra, Ingo Molnar, Arnaldo Carvalho de Melo,
	Mark Rutland, Alexander Shishkin, Jiri Olsa, Adrian Hunter,
	Kan Liang, James Clark, Xu Yang, Masami Hiramatsu (Google),
	Collin Funk, Howard Chu, Weilin Wang, Andi Kleen,
	Dr. David Alan Gilbert, Thomas Richter, Tiezhu Yang,
	Gautam Menghani, Thomas Falcon, Chun-Tse Shao, linux-kernel,
	linux-perf-users

On Wed, Jul 23, 2025 at 11:13 AM Namhyung Kim <namhyung@kernel.org> wrote:
>
> On Mon, Jul 14, 2025 at 09:43:49AM -0700, Ian Rogers wrote:
> > Returning NULL will cause the python interpreter to fail but not
> > report an error. If none wants to be returned then Py_None needs
> > returning. Set the error for the cases returning NULL so that more
> > meaningful interpreter behavior is had.
>
> It looks like you are adding error messages for the failure cases, not
> adding new exceptions, right?  IIUC returning NULL in pyrf_event__new()
> ends up having PyErr_NoMemory().  Then now it has different messages?

This change doesn't alter the exception if there already is one. There
are lots of cases where NULL is being returned for an error but that
causes the python interpreter to fail/crash. This patch is just adding
the exceptions and still returning NULL, previously set exceptions are
left alone. With the exceptions returned the python interpreter does
something more useful than fail/crash :-)

> >
> > Signed-off-by: Ian Rogers <irogers@google.com>
> > ---
> >  tools/perf/util/python.c | 14 +++++++++++---
> >  1 file changed, 11 insertions(+), 3 deletions(-)
> >
> > diff --git a/tools/perf/util/python.c b/tools/perf/util/python.c
> > index 2f28f71325a8..02544387f39d 100644
> > --- a/tools/perf/util/python.c
> > +++ b/tools/perf/util/python.c
> > @@ -475,13 +475,19 @@ static PyObject *pyrf_event__new(const union perf_event *event)
> >       if ((event->header.type < PERF_RECORD_MMAP ||
> >            event->header.type > PERF_RECORD_SAMPLE) &&
> >           !(event->header.type == PERF_RECORD_SWITCH ||
> > -           event->header.type == PERF_RECORD_SWITCH_CPU_WIDE))
> > +           event->header.type == PERF_RECORD_SWITCH_CPU_WIDE)){
> > +             PyErr_Format(PyExc_TypeError, "Unexpected header type %u",
> > +                          event->header.type);
> >               return NULL;
> > +     }
> >
> >       // FIXME this better be dynamic or we need to parse everything
> >       // before calling perf_mmap__consume(), including tracepoint fields.
> > -     if (sizeof(pevent->event) < event->header.size)
> > +     if (sizeof(pevent->event) < event->header.size) {
> > +             PyErr_Format(PyExc_TypeError, "Unexpected event version: %zd < %u",
>
> Maybe "Unexpected event size" instead?

I think size is more accurate to the code, version is more useful to
the user. I believe there is existing use of the event size being used
as a quasi version number, so I think this description is consistent.
If you feel strongly I can change it.

Thanks,
Ian

> Thanks,
> Namhyung
>
>
> > +                          sizeof(pevent->event), event->header.size);
> >               return NULL;
> > +     }
> >
> >       ptype = pyrf_event__type[event->header.type];
> >       pevent = PyObject_New(struct pyrf_event, ptype);
> > @@ -1199,8 +1205,10 @@ static PyObject *pyrf_evlist__read_on_cpu(struct pyrf_evlist *pevlist,
> >               return NULL;
> >
> >       md = get_md(evlist, cpu);
> > -     if (!md)
> > +     if (!md) {
> > +             PyErr_Format(PyExc_TypeError, "Unknown CPU '%d'", cpu);
> >               return NULL;
> > +     }
> >
> >       if (perf_mmap__read_init(&md->core) < 0)
> >               goto end;
> > --
> > 2.50.0.727.gbf7dc18ff4-goog
> >

^ permalink raw reply	[flat|nested] 41+ messages in thread

* Re: [PATCH v7 02/16] perf jevents: Add common software event json
  2025-07-14 16:43 ` [PATCH v7 02/16] perf jevents: Add common software event json Ian Rogers
  2025-07-23 16:52   ` Arnaldo Carvalho de Melo
@ 2025-07-23 18:24   ` Namhyung Kim
  2025-07-23 22:34     ` Ian Rogers
  1 sibling, 1 reply; 41+ messages in thread
From: Namhyung Kim @ 2025-07-23 18:24 UTC (permalink / raw)
  To: Ian Rogers
  Cc: Peter Zijlstra, Ingo Molnar, Arnaldo Carvalho de Melo,
	Mark Rutland, Alexander Shishkin, Jiri Olsa, Adrian Hunter,
	Kan Liang, James Clark, Xu Yang, Masami Hiramatsu (Google),
	Collin Funk, Howard Chu, Weilin Wang, Andi Kleen,
	Dr. David Alan Gilbert, Thomas Richter, Tiezhu Yang,
	Gautam Menghani, Thomas Falcon, Chun-Tse Shao, linux-kernel,
	linux-perf-users

On Mon, Jul 14, 2025 at 09:43:50AM -0700, Ian Rogers wrote:
> Add json for software events so that in perf list the events can have
> a description.  Common json exists for the tool PMU but it has no
> sysfs equivalent. Modify the map_for_pmu code to return the common map
> (rather than an architecture specific one) when a PMU with a common
> name is being looked for, this allows the events to be found.

Can you please share new output of `perf list sw`?  I'm glad we have
description for software events.  But I'm also curious what's the side
effect of having them in JSON - maybe case insensitivity?

> 
> Signed-off-by: Ian Rogers <irogers@google.com>
> ---
>  .../arch/common/common/software.json          |  92 ++++++
>  tools/perf/pmu-events/empty-pmu-events.c      | 266 +++++++++++-------
>  tools/perf/pmu-events/jevents.py              |  15 +-
>  3 files changed, 264 insertions(+), 109 deletions(-)
>  create mode 100644 tools/perf/pmu-events/arch/common/common/software.json
> 
> diff --git a/tools/perf/pmu-events/arch/common/common/software.json b/tools/perf/pmu-events/arch/common/common/software.json
> new file mode 100644
> index 000000000000..3af2f565a601
> --- /dev/null
> +++ b/tools/perf/pmu-events/arch/common/common/software.json
> @@ -0,0 +1,92 @@
> +[
> +  {
> +    "Unit": "software",
> +    "EventName": "cpu-clock",
> +    "BriefDescription": "Per-CPU high-resolution timer based event",
> +    "ConfigCode": "0"
> +  },
> +  {
> +    "Unit": "software",
> +    "EventName": "task-clock",
> +    "BriefDescription": "Task based high-resolution timer based event",

s/Task based/Per-task/ ?


> +    "ConfigCode": "1"
> +  },
> +  {
> +    "Unit": "software",
> +    "EventName": "faults",
> +    "BriefDescription": "Number of page faults [This event is an alias of page-faults]",
> +    "ConfigCode": "2"

It'd be nice if it can handle aliases without adding a new entry.  But I
guess it requires non-trivial changes.

Thanks,
Namhyung

> +  },
> +  {
> +    "Unit": "software",
> +    "EventName": "page-faults",
> +    "BriefDescription": "Number of page faults [This event is an alias of faults]",
> +    "ConfigCode": "2"
> +  },
> +  {
> +    "Unit": "software",
> +    "EventName": "context-switches",
> +    "BriefDescription": "Number of context switches [This event is an alias of cs]",
> +    "ConfigCode": "3"
> +  },
> +  {
> +    "Unit": "software",
> +    "EventName": "cs",
> +    "BriefDescription": "Number of context switches [This event is an alias of context-switches]",
> +    "ConfigCode": "3"
> +  },
> +  {
> +    "Unit": "software",
> +    "EventName": "cpu-migrations",
> +    "BriefDescription": "Number of times a process has migrated to a new CPU [This event is an alias of migrations]",
> +    "ConfigCode": "4"
> +  },
> +  {
> +    "Unit": "software",
> +    "EventName": "migrations",
> +    "BriefDescription": "Number of times a process has migrated to a new CPU [This event is an alias of cpu-migrations]",
> +    "ConfigCode": "4"
> +  },
> +  {
> +    "Unit": "software",
> +    "EventName": "minor-faults",
> +    "BriefDescription": "Number of minor page faults. Minor faults don't require I/O to handle",
> +    "ConfigCode": "5"
> +  },
> +  {
> +    "Unit": "software",
> +    "EventName": "major-faults",
> +    "BriefDescription": "Number of major page faults. Major faults require I/O to handle",
> +    "ConfigCode": "6"
> +  },
> +  {
> +    "Unit": "software",
> +    "EventName": "alignment-faults",
> +    "BriefDescription": "Number of kernel handled memory alignment faults",
> +    "ConfigCode": "7"
> +  },
> +  {
> +    "Unit": "software",
> +    "EventName": "emulation-faults",
> +    "BriefDescription": "Number of kernel handled unimplemented instruction faults handled through emulation",
> +    "ConfigCode": "8"
> +  },
> +  {
> +    "Unit": "software",
> +    "EventName": "dummy",
> +    "BriefDescription": "A placeholder event that doesn't count anything",
> +    "ConfigCode": "9"
> +  },
> +  {
> +    "Unit": "software",
> +    "EventName": "bpf-output",
> +    "BriefDescription": "An event used by BPF programs to write to the perf ring buffer",
> +    "ConfigCode": "10"
> +  },
> +  {
> +    "Unit": "software",
> +    "EventName": "cgroup-switches",
> +    "BriefDescription": "Number of context switches to a task in a different cgroup",
> +    "ConfigCode": "11"
> +  }
> +]
> diff --git a/tools/perf/pmu-events/empty-pmu-events.c b/tools/perf/pmu-events/empty-pmu-events.c
> index a4569a74db07..7d179d703ab1 100644
> --- a/tools/perf/pmu-events/empty-pmu-events.c
> +++ b/tools/perf/pmu-events/empty-pmu-events.c
> @@ -19,109 +19,147 @@ struct pmu_table_entry {
>  };
>  
>  static const char *const big_c_string =
> -/* offset=0 */ "tool\000"
> -/* offset=5 */ "duration_time\000tool\000Wall clock interval time in nanoseconds\000config=1\000\00000\000\000\000\000\000"
> -/* offset=81 */ "user_time\000tool\000User (non-kernel) time in nanoseconds\000config=2\000\00000\000\000\000\000\000"
> -/* offset=151 */ "system_time\000tool\000System/kernel time in nanoseconds\000config=3\000\00000\000\000\000\000\000"
> -/* offset=219 */ "has_pmem\000tool\0001 if persistent memory installed otherwise 0\000config=4\000\00000\000\000\000\000\000"
> -/* offset=295 */ "num_cores\000tool\000Number of cores. A core consists of 1 or more thread, with each thread being associated with a logical Linux CPU\000config=5\000\00000\000\000\000\000\000"
> -/* offset=440 */ "num_cpus\000tool\000Number of logical Linux CPUs. There may be multiple such CPUs on a core\000config=6\000\00000\000\000\000\000\000"
> -/* offset=543 */ "num_cpus_online\000tool\000Number of online logical Linux CPUs. There may be multiple such CPUs on a core\000config=7\000\00000\000\000\000\000\000"
> -/* offset=660 */ "num_dies\000tool\000Number of dies. Each die has 1 or more cores\000config=8\000\00000\000\000\000\000\000"
> -/* offset=736 */ "num_packages\000tool\000Number of packages. Each package has 1 or more die\000config=9\000\00000\000\000\000\000\000"
> -/* offset=822 */ "slots\000tool\000Number of functional units that in parallel can execute parts of an instruction\000config=0xa\000\00000\000\000\000\000\000"
> -/* offset=932 */ "smt_on\000tool\0001 if simultaneous multithreading (aka hyperthreading) is enable otherwise 0\000config=0xb\000\00000\000\000\000\000\000"
> -/* offset=1039 */ "system_tsc_freq\000tool\000The amount a Time Stamp Counter (TSC) increases per second\000config=0xc\000\00000\000\000\000\000\000"
> -/* offset=1138 */ "default_core\000"
> -/* offset=1151 */ "bp_l1_btb_correct\000branch\000L1 BTB Correction\000event=0x8a\000\00000\000\000\000\000\000"
> -/* offset=1213 */ "bp_l2_btb_correct\000branch\000L2 BTB Correction\000event=0x8b\000\00000\000\000\000\000\000"
> -/* offset=1275 */ "l3_cache_rd\000cache\000L3 cache access, read\000event=0x40\000\00000\000\000\000\000Attributable Level 3 cache access, read\000"
> -/* offset=1373 */ "segment_reg_loads.any\000other\000Number of segment register loads\000event=6,period=200000,umask=0x80\000\00000\000\000\000\000\000"
> -/* offset=1475 */ "dispatch_blocked.any\000other\000Memory cluster signals to block micro-op dispatch for any reason\000event=9,period=200000,umask=0x20\000\00000\000\000\000\000\000"
> -/* offset=1608 */ "eist_trans\000other\000Number of Enhanced Intel SpeedStep(R) Technology (EIST) transitions\000event=0x3a,period=200000\000\00000\000\000\000\000\000"
> -/* offset=1726 */ "hisi_sccl,ddrc\000"
> -/* offset=1741 */ "uncore_hisi_ddrc.flux_wcmd\000uncore\000DDRC write commands\000event=2\000\00000\000\000\000\000\000"
> -/* offset=1811 */ "uncore_cbox\000"
> -/* offset=1823 */ "unc_cbo_xsnp_response.miss_eviction\000uncore\000A cross-core snoop resulted from L3 Eviction which misses in some processor core\000event=0x22,umask=0x81\000\00000\000\000\000\000\000"
> -/* offset=1977 */ "event-hyphen\000uncore\000UNC_CBO_HYPHEN\000event=0xe0\000\00000\000\000\000\000\000"
> -/* offset=2031 */ "event-two-hyph\000uncore\000UNC_CBO_TWO_HYPH\000event=0xc0\000\00000\000\000\000\000\000"
> -/* offset=2089 */ "hisi_sccl,l3c\000"
> -/* offset=2103 */ "uncore_hisi_l3c.rd_hit_cpipe\000uncore\000Total read hits\000event=7\000\00000\000\000\000\000\000"
> -/* offset=2171 */ "uncore_imc_free_running\000"
> -/* offset=2195 */ "uncore_imc_free_running.cache_miss\000uncore\000Total cache misses\000event=0x12\000\00000\000\000\000\000\000"
> -/* offset=2275 */ "uncore_imc\000"
> -/* offset=2286 */ "uncore_imc.cache_hits\000uncore\000Total cache hits\000event=0x34\000\00000\000\000\000\000\000"
> -/* offset=2351 */ "uncore_sys_ddr_pmu\000"
> -/* offset=2370 */ "sys_ddr_pmu.write_cycles\000uncore\000ddr write-cycles event\000event=0x2b\000v8\00000\000\000\000\000\000"
> -/* offset=2446 */ "uncore_sys_ccn_pmu\000"
> -/* offset=2465 */ "sys_ccn_pmu.read_cycles\000uncore\000ccn read-cycles event\000config=0x2c\0000x01\00000\000\000\000\000\000"
> -/* offset=2542 */ "uncore_sys_cmn_pmu\000"
> -/* offset=2561 */ "sys_cmn_pmu.hnf_cache_miss\000uncore\000Counts total cache misses in first lookup result (high priority)\000eventid=1,type=5\000(434|436|43c|43a).*\00000\000\000\000\000\000"
> -/* offset=2704 */ "CPI\000\0001 / IPC\000\000\000\000\000\000\000\00000"
> -/* offset=2726 */ "IPC\000group1\000inst_retired.any / cpu_clk_unhalted.thread\000\000\000\000\000\000\000\00000"
> -/* offset=2789 */ "Frontend_Bound_SMT\000\000idq_uops_not_delivered.core / (4 * (cpu_clk_unhalted.thread / 2 * (1 + cpu_clk_unhalted.one_thread_active / cpu_clk_unhalted.ref_xclk)))\000\000\000\000\000\000\000\00000"
> -/* offset=2955 */ "dcache_miss_cpi\000\000l1d\\-loads\\-misses / inst_retired.any\000\000\000\000\000\000\000\00000"
> -/* offset=3019 */ "icache_miss_cycles\000\000l1i\\-loads\\-misses / inst_retired.any\000\000\000\000\000\000\000\00000"
> -/* offset=3086 */ "cache_miss_cycles\000group1\000dcache_miss_cpi + icache_miss_cycles\000\000\000\000\000\000\000\00000"
> -/* offset=3157 */ "DCache_L2_All_Hits\000\000l2_rqsts.demand_data_rd_hit + l2_rqsts.pf_hit + l2_rqsts.rfo_hit\000\000\000\000\000\000\000\00000"
> -/* offset=3251 */ "DCache_L2_All_Miss\000\000max(l2_rqsts.all_demand_data_rd - l2_rqsts.demand_data_rd_hit, 0) + l2_rqsts.pf_miss + l2_rqsts.rfo_miss\000\000\000\000\000\000\000\00000"
> -/* offset=3385 */ "DCache_L2_All\000\000DCache_L2_All_Hits + DCache_L2_All_Miss\000\000\000\000\000\000\000\00000"
> -/* offset=3449 */ "DCache_L2_Hits\000\000d_ratio(DCache_L2_All_Hits, DCache_L2_All)\000\000\000\000\000\000\000\00000"
> -/* offset=3517 */ "DCache_L2_Misses\000\000d_ratio(DCache_L2_All_Miss, DCache_L2_All)\000\000\000\000\000\000\000\00000"
> -/* offset=3587 */ "M1\000\000ipc + M2\000\000\000\000\000\000\000\00000"
> -/* offset=3609 */ "M2\000\000ipc + M1\000\000\000\000\000\000\000\00000"
> -/* offset=3631 */ "M3\000\0001 / M3\000\000\000\000\000\000\000\00000"
> -/* offset=3651 */ "L1D_Cache_Fill_BW\000\00064 * l1d.replacement / 1e9 / duration_time\000\000\000\000\000\000\000\00000"
> +/* offset=0 */ "software\000"
> +/* offset=9 */ "cpu-clock\000software\000Per-CPU high-resolution timer based event\000config=0\000\00000\000\000\000\000\000"
> +/* offset=87 */ "task-clock\000software\000Task based high-resolution timer based event\000config=1\000\00000\000\000\000\000\000"
> +/* offset=169 */ "faults\000software\000Number of page faults [This event is an alias of page-faults]\000config=2\000\00000\000\000\000\000\000"
> +/* offset=264 */ "page-faults\000software\000Number of page faults [This event is an alias of faults]\000config=2\000\00000\000\000\000\000\000"
> +/* offset=359 */ "context-switches\000software\000Number of context switches [This event is an alias of cs]\000config=3\000\00000\000\000\000\000\000"
> +/* offset=460 */ "cs\000software\000Number of context switches [This event is an alias of context-switches]\000config=3\000\00000\000\000\000\000\000"
> +/* offset=561 */ "cpu-migrations\000software\000Number of times a process has migrated to a new CPU [This event is an alias of migrations]\000config=4\000\00000\000\000\000\000\000"
> +/* offset=693 */ "migrations\000software\000Number of times a process has migrated to a new CPU [This event is an alias of cpu-migrations]\000config=4\000\00000\000\000\000\000\000"
> +/* offset=825 */ "minor-faults\000software\000Number of minor page faults. Minor faults don't require I/O to handle\000config=5\000\00000\000\000\000\000\000"
> +/* offset=934 */ "major-faults\000software\000Number of major page faults. Major faults require I/O to handle\000config=6\000\00000\000\000\000\000\000"
> +/* offset=1037 */ "alignment-faults\000software\000Number of kernel handled memory alignment faults\000config=7\000\00000\000\000\000\000\000"
> +/* offset=1129 */ "emulation-faults\000software\000Number of kernel handled unimplemented instruction faults handled through emulation\000config=8\000\00000\000\000\000\000\000"
> +/* offset=1256 */ "dummy\000software\000A placeholder event that doesn't count anything\000config=9\000\00000\000\000\000\000\000"
> +/* offset=1336 */ "bpf-output\000software\000An event used by BPF programs to write to the perf ring buffer\000config=0xa\000\00000\000\000\000\000\000"
> +/* offset=1438 */ "cgroup-switches\000software\000Number of context switches to a task in a different cgroup\000config=0xb\000\00000\000\000\000\000\000"
> +/* offset=1541 */ "tool\000"
> +/* offset=1546 */ "duration_time\000tool\000Wall clock interval time in nanoseconds\000config=1\000\00000\000\000\000\000\000"
> +/* offset=1622 */ "user_time\000tool\000User (non-kernel) time in nanoseconds\000config=2\000\00000\000\000\000\000\000"
> +/* offset=1692 */ "system_time\000tool\000System/kernel time in nanoseconds\000config=3\000\00000\000\000\000\000\000"
> +/* offset=1760 */ "has_pmem\000tool\0001 if persistent memory installed otherwise 0\000config=4\000\00000\000\000\000\000\000"
> +/* offset=1836 */ "num_cores\000tool\000Number of cores. A core consists of 1 or more thread, with each thread being associated with a logical Linux CPU\000config=5\000\00000\000\000\000\000\000"
> +/* offset=1981 */ "num_cpus\000tool\000Number of logical Linux CPUs. There may be multiple such CPUs on a core\000config=6\000\00000\000\000\000\000\000"
> +/* offset=2084 */ "num_cpus_online\000tool\000Number of online logical Linux CPUs. There may be multiple such CPUs on a core\000config=7\000\00000\000\000\000\000\000"
> +/* offset=2201 */ "num_dies\000tool\000Number of dies. Each die has 1 or more cores\000config=8\000\00000\000\000\000\000\000"
> +/* offset=2277 */ "num_packages\000tool\000Number of packages. Each package has 1 or more die\000config=9\000\00000\000\000\000\000\000"
> +/* offset=2363 */ "slots\000tool\000Number of functional units that in parallel can execute parts of an instruction\000config=0xa\000\00000\000\000\000\000\000"
> +/* offset=2473 */ "smt_on\000tool\0001 if simultaneous multithreading (aka hyperthreading) is enable otherwise 0\000config=0xb\000\00000\000\000\000\000\000"
> +/* offset=2580 */ "system_tsc_freq\000tool\000The amount a Time Stamp Counter (TSC) increases per second\000config=0xc\000\00000\000\000\000\000\000"
> +/* offset=2679 */ "default_core\000"
> +/* offset=2692 */ "bp_l1_btb_correct\000branch\000L1 BTB Correction\000event=0x8a\000\00000\000\000\000\000\000"
> +/* offset=2754 */ "bp_l2_btb_correct\000branch\000L2 BTB Correction\000event=0x8b\000\00000\000\000\000\000\000"
> +/* offset=2816 */ "l3_cache_rd\000cache\000L3 cache access, read\000event=0x40\000\00000\000\000\000\000Attributable Level 3 cache access, read\000"
> +/* offset=2914 */ "segment_reg_loads.any\000other\000Number of segment register loads\000event=6,period=200000,umask=0x80\000\00000\000\000\000\000\000"
> +/* offset=3016 */ "dispatch_blocked.any\000other\000Memory cluster signals to block micro-op dispatch for any reason\000event=9,period=200000,umask=0x20\000\00000\000\000\000\000\000"
> +/* offset=3149 */ "eist_trans\000other\000Number of Enhanced Intel SpeedStep(R) Technology (EIST) transitions\000event=0x3a,period=200000\000\00000\000\000\000\000\000"
> +/* offset=3267 */ "hisi_sccl,ddrc\000"
> +/* offset=3282 */ "uncore_hisi_ddrc.flux_wcmd\000uncore\000DDRC write commands\000event=2\000\00000\000\000\000\000\000"
> +/* offset=3352 */ "uncore_cbox\000"
> +/* offset=3364 */ "unc_cbo_xsnp_response.miss_eviction\000uncore\000A cross-core snoop resulted from L3 Eviction which misses in some processor core\000event=0x22,umask=0x81\000\00000\000\000\000\000\000"
> +/* offset=3518 */ "event-hyphen\000uncore\000UNC_CBO_HYPHEN\000event=0xe0\000\00000\000\000\000\000\000"
> +/* offset=3572 */ "event-two-hyph\000uncore\000UNC_CBO_TWO_HYPH\000event=0xc0\000\00000\000\000\000\000\000"
> +/* offset=3630 */ "hisi_sccl,l3c\000"
> +/* offset=3644 */ "uncore_hisi_l3c.rd_hit_cpipe\000uncore\000Total read hits\000event=7\000\00000\000\000\000\000\000"
> +/* offset=3712 */ "uncore_imc_free_running\000"
> +/* offset=3736 */ "uncore_imc_free_running.cache_miss\000uncore\000Total cache misses\000event=0x12\000\00000\000\000\000\000\000"
> +/* offset=3816 */ "uncore_imc\000"
> +/* offset=3827 */ "uncore_imc.cache_hits\000uncore\000Total cache hits\000event=0x34\000\00000\000\000\000\000\000"
> +/* offset=3892 */ "uncore_sys_ddr_pmu\000"
> +/* offset=3911 */ "sys_ddr_pmu.write_cycles\000uncore\000ddr write-cycles event\000event=0x2b\000v8\00000\000\000\000\000\000"
> +/* offset=3987 */ "uncore_sys_ccn_pmu\000"
> +/* offset=4006 */ "sys_ccn_pmu.read_cycles\000uncore\000ccn read-cycles event\000config=0x2c\0000x01\00000\000\000\000\000\000"
> +/* offset=4083 */ "uncore_sys_cmn_pmu\000"
> +/* offset=4102 */ "sys_cmn_pmu.hnf_cache_miss\000uncore\000Counts total cache misses in first lookup result (high priority)\000eventid=1,type=5\000(434|436|43c|43a).*\00000\000\000\000\000\000"
> +/* offset=4245 */ "CPI\000\0001 / IPC\000\000\000\000\000\000\000\00000"
> +/* offset=4267 */ "IPC\000group1\000inst_retired.any / cpu_clk_unhalted.thread\000\000\000\000\000\000\000\00000"
> +/* offset=4330 */ "Frontend_Bound_SMT\000\000idq_uops_not_delivered.core / (4 * (cpu_clk_unhalted.thread / 2 * (1 + cpu_clk_unhalted.one_thread_active / cpu_clk_unhalted.ref_xclk)))\000\000\000\000\000\000\000\00000"
> +/* offset=4496 */ "dcache_miss_cpi\000\000l1d\\-loads\\-misses / inst_retired.any\000\000\000\000\000\000\000\00000"
> +/* offset=4560 */ "icache_miss_cycles\000\000l1i\\-loads\\-misses / inst_retired.any\000\000\000\000\000\000\000\00000"
> +/* offset=4627 */ "cache_miss_cycles\000group1\000dcache_miss_cpi + icache_miss_cycles\000\000\000\000\000\000\000\00000"
> +/* offset=4698 */ "DCache_L2_All_Hits\000\000l2_rqsts.demand_data_rd_hit + l2_rqsts.pf_hit + l2_rqsts.rfo_hit\000\000\000\000\000\000\000\00000"
> +/* offset=4792 */ "DCache_L2_All_Miss\000\000max(l2_rqsts.all_demand_data_rd - l2_rqsts.demand_data_rd_hit, 0) + l2_rqsts.pf_miss + l2_rqsts.rfo_miss\000\000\000\000\000\000\000\00000"
> +/* offset=4926 */ "DCache_L2_All\000\000DCache_L2_All_Hits + DCache_L2_All_Miss\000\000\000\000\000\000\000\00000"
> +/* offset=4990 */ "DCache_L2_Hits\000\000d_ratio(DCache_L2_All_Hits, DCache_L2_All)\000\000\000\000\000\000\000\00000"
> +/* offset=5058 */ "DCache_L2_Misses\000\000d_ratio(DCache_L2_All_Miss, DCache_L2_All)\000\000\000\000\000\000\000\00000"
> +/* offset=5128 */ "M1\000\000ipc + M2\000\000\000\000\000\000\000\00000"
> +/* offset=5150 */ "M2\000\000ipc + M1\000\000\000\000\000\000\000\00000"
> +/* offset=5172 */ "M3\000\0001 / M3\000\000\000\000\000\000\000\00000"
> +/* offset=5192 */ "L1D_Cache_Fill_BW\000\00064 * l1d.replacement / 1e9 / duration_time\000\000\000\000\000\000\000\00000"
>  ;
>  
> +static const struct compact_pmu_event pmu_events__common_software[] = {
> +{ 1037 }, /* alignment-faults\000software\000Number of kernel handled memory alignment faults\000config=7\000\00000\000\000\000\000\000 */
> +{ 1336 }, /* bpf-output\000software\000An event used by BPF programs to write to the perf ring buffer\000config=0xa\000\00000\000\000\000\000\000 */
> +{ 1438 }, /* cgroup-switches\000software\000Number of context switches to a task in a different cgroup\000config=0xb\000\00000\000\000\000\000\000 */
> +{ 359 }, /* context-switches\000software\000Number of context switches [This event is an alias of cs]\000config=3\000\00000\000\000\000\000\000 */
> +{ 9 }, /* cpu-clock\000software\000Per-CPU high-resolution timer based event\000config=0\000\00000\000\000\000\000\000 */
> +{ 561 }, /* cpu-migrations\000software\000Number of times a process has migrated to a new CPU [This event is an alias of migrations]\000config=4\000\00000\000\000\000\000\000 */
> +{ 460 }, /* cs\000software\000Number of context switches [This event is an alias of context-switches]\000config=3\000\00000\000\000\000\000\000 */
> +{ 1256 }, /* dummy\000software\000A placeholder event that doesn't count anything\000config=9\000\00000\000\000\000\000\000 */
> +{ 1129 }, /* emulation-faults\000software\000Number of kernel handled unimplemented instruction faults handled through emulation\000config=8\000\00000\000\000\000\000\000 */
> +{ 169 }, /* faults\000software\000Number of page faults [This event is an alias of page-faults]\000config=2\000\00000\000\000\000\000\000 */
> +{ 934 }, /* major-faults\000software\000Number of major page faults. Major faults require I/O to handle\000config=6\000\00000\000\000\000\000\000 */
> +{ 693 }, /* migrations\000software\000Number of times a process has migrated to a new CPU [This event is an alias of cpu-migrations]\000config=4\000\00000\000\000\000\000\000 */
> +{ 825 }, /* minor-faults\000software\000Number of minor page faults. Minor faults don't require I/O to handle\000config=5\000\00000\000\000\000\000\000 */
> +{ 264 }, /* page-faults\000software\000Number of page faults [This event is an alias of faults]\000config=2\000\00000\000\000\000\000\000 */
> +{ 87 }, /* task-clock\000software\000Task based high-resolution timer based event\000config=1\000\00000\000\000\000\000\000 */
> +};
>  static const struct compact_pmu_event pmu_events__common_tool[] = {
> -{ 5 }, /* duration_time\000tool\000Wall clock interval time in nanoseconds\000config=1\000\00000\000\000\000\000\000 */
> -{ 219 }, /* has_pmem\000tool\0001 if persistent memory installed otherwise 0\000config=4\000\00000\000\000\000\000\000 */
> -{ 295 }, /* num_cores\000tool\000Number of cores. A core consists of 1 or more thread, with each thread being associated with a logical Linux CPU\000config=5\000\00000\000\000\000\000\000 */
> -{ 440 }, /* num_cpus\000tool\000Number of logical Linux CPUs. There may be multiple such CPUs on a core\000config=6\000\00000\000\000\000\000\000 */
> -{ 543 }, /* num_cpus_online\000tool\000Number of online logical Linux CPUs. There may be multiple such CPUs on a core\000config=7\000\00000\000\000\000\000\000 */
> -{ 660 }, /* num_dies\000tool\000Number of dies. Each die has 1 or more cores\000config=8\000\00000\000\000\000\000\000 */
> -{ 736 }, /* num_packages\000tool\000Number of packages. Each package has 1 or more die\000config=9\000\00000\000\000\000\000\000 */
> -{ 822 }, /* slots\000tool\000Number of functional units that in parallel can execute parts of an instruction\000config=0xa\000\00000\000\000\000\000\000 */
> -{ 932 }, /* smt_on\000tool\0001 if simultaneous multithreading (aka hyperthreading) is enable otherwise 0\000config=0xb\000\00000\000\000\000\000\000 */
> -{ 151 }, /* system_time\000tool\000System/kernel time in nanoseconds\000config=3\000\00000\000\000\000\000\000 */
> -{ 1039 }, /* system_tsc_freq\000tool\000The amount a Time Stamp Counter (TSC) increases per second\000config=0xc\000\00000\000\000\000\000\000 */
> -{ 81 }, /* user_time\000tool\000User (non-kernel) time in nanoseconds\000config=2\000\00000\000\000\000\000\000 */
> +{ 1546 }, /* duration_time\000tool\000Wall clock interval time in nanoseconds\000config=1\000\00000\000\000\000\000\000 */
> +{ 1760 }, /* has_pmem\000tool\0001 if persistent memory installed otherwise 0\000config=4\000\00000\000\000\000\000\000 */
> +{ 1836 }, /* num_cores\000tool\000Number of cores. A core consists of 1 or more thread, with each thread being associated with a logical Linux CPU\000config=5\000\00000\000\000\000\000\000 */
> +{ 1981 }, /* num_cpus\000tool\000Number of logical Linux CPUs. There may be multiple such CPUs on a core\000config=6\000\00000\000\000\000\000\000 */
> +{ 2084 }, /* num_cpus_online\000tool\000Number of online logical Linux CPUs. There may be multiple such CPUs on a core\000config=7\000\00000\000\000\000\000\000 */
> +{ 2201 }, /* num_dies\000tool\000Number of dies. Each die has 1 or more cores\000config=8\000\00000\000\000\000\000\000 */
> +{ 2277 }, /* num_packages\000tool\000Number of packages. Each package has 1 or more die\000config=9\000\00000\000\000\000\000\000 */
> +{ 2363 }, /* slots\000tool\000Number of functional units that in parallel can execute parts of an instruction\000config=0xa\000\00000\000\000\000\000\000 */
> +{ 2473 }, /* smt_on\000tool\0001 if simultaneous multithreading (aka hyperthreading) is enable otherwise 0\000config=0xb\000\00000\000\000\000\000\000 */
> +{ 1692 }, /* system_time\000tool\000System/kernel time in nanoseconds\000config=3\000\00000\000\000\000\000\000 */
> +{ 2580 }, /* system_tsc_freq\000tool\000The amount a Time Stamp Counter (TSC) increases per second\000config=0xc\000\00000\000\000\000\000\000 */
> +{ 1622 }, /* user_time\000tool\000User (non-kernel) time in nanoseconds\000config=2\000\00000\000\000\000\000\000 */
>  
>  };
>  
>  const struct pmu_table_entry pmu_events__common[] = {
> +{
> +     .entries = pmu_events__common_software,
> +     .num_entries = ARRAY_SIZE(pmu_events__common_software),
> +     .pmu_name = { 0 /* software\000 */ },
> +},
>  {
>       .entries = pmu_events__common_tool,
>       .num_entries = ARRAY_SIZE(pmu_events__common_tool),
> -     .pmu_name = { 0 /* tool\000 */ },
> +     .pmu_name = { 1541 /* tool\000 */ },
>  },
>  };
>  
>  static const struct compact_pmu_event pmu_events__test_soc_cpu_default_core[] = {
> -{ 1151 }, /* bp_l1_btb_correct\000branch\000L1 BTB Correction\000event=0x8a\000\00000\000\000\000\000\000 */
> -{ 1213 }, /* bp_l2_btb_correct\000branch\000L2 BTB Correction\000event=0x8b\000\00000\000\000\000\000\000 */
> -{ 1475 }, /* dispatch_blocked.any\000other\000Memory cluster signals to block micro-op dispatch for any reason\000event=9,period=200000,umask=0x20\000\00000\000\000\000\000\000 */
> -{ 1608 }, /* eist_trans\000other\000Number of Enhanced Intel SpeedStep(R) Technology (EIST) transitions\000event=0x3a,period=200000\000\00000\000\000\000\000\000 */
> -{ 1275 }, /* l3_cache_rd\000cache\000L3 cache access, read\000event=0x40\000\00000\000\000\000\000Attributable Level 3 cache access, read\000 */
> -{ 1373 }, /* segment_reg_loads.any\000other\000Number of segment register loads\000event=6,period=200000,umask=0x80\000\00000\000\000\000\000\000 */
> +{ 2692 }, /* bp_l1_btb_correct\000branch\000L1 BTB Correction\000event=0x8a\000\00000\000\000\000\000\000 */
> +{ 2754 }, /* bp_l2_btb_correct\000branch\000L2 BTB Correction\000event=0x8b\000\00000\000\000\000\000\000 */
> +{ 3016 }, /* dispatch_blocked.any\000other\000Memory cluster signals to block micro-op dispatch for any reason\000event=9,period=200000,umask=0x20\000\00000\000\000\000\000\000 */
> +{ 3149 }, /* eist_trans\000other\000Number of Enhanced Intel SpeedStep(R) Technology (EIST) transitions\000event=0x3a,period=200000\000\00000\000\000\000\000\000 */
> +{ 2816 }, /* l3_cache_rd\000cache\000L3 cache access, read\000event=0x40\000\00000\000\000\000\000Attributable Level 3 cache access, read\000 */
> +{ 2914 }, /* segment_reg_loads.any\000other\000Number of segment register loads\000event=6,period=200000,umask=0x80\000\00000\000\000\000\000\000 */
>  };
>  static const struct compact_pmu_event pmu_events__test_soc_cpu_hisi_sccl_ddrc[] = {
> -{ 1741 }, /* uncore_hisi_ddrc.flux_wcmd\000uncore\000DDRC write commands\000event=2\000\00000\000\000\000\000\000 */
> +{ 3282 }, /* uncore_hisi_ddrc.flux_wcmd\000uncore\000DDRC write commands\000event=2\000\00000\000\000\000\000\000 */
>  };
>  static const struct compact_pmu_event pmu_events__test_soc_cpu_hisi_sccl_l3c[] = {
> -{ 2103 }, /* uncore_hisi_l3c.rd_hit_cpipe\000uncore\000Total read hits\000event=7\000\00000\000\000\000\000\000 */
> +{ 3644 }, /* uncore_hisi_l3c.rd_hit_cpipe\000uncore\000Total read hits\000event=7\000\00000\000\000\000\000\000 */
>  };
>  static const struct compact_pmu_event pmu_events__test_soc_cpu_uncore_cbox[] = {
> -{ 1977 }, /* event-hyphen\000uncore\000UNC_CBO_HYPHEN\000event=0xe0\000\00000\000\000\000\000\000 */
> -{ 2031 }, /* event-two-hyph\000uncore\000UNC_CBO_TWO_HYPH\000event=0xc0\000\00000\000\000\000\000\000 */
> -{ 1823 }, /* unc_cbo_xsnp_response.miss_eviction\000uncore\000A cross-core snoop resulted from L3 Eviction which misses in some processor core\000event=0x22,umask=0x81\000\00000\000\000\000\000\000 */
> +{ 3518 }, /* event-hyphen\000uncore\000UNC_CBO_HYPHEN\000event=0xe0\000\00000\000\000\000\000\000 */
> +{ 3572 }, /* event-two-hyph\000uncore\000UNC_CBO_TWO_HYPH\000event=0xc0\000\00000\000\000\000\000\000 */
> +{ 3364 }, /* unc_cbo_xsnp_response.miss_eviction\000uncore\000A cross-core snoop resulted from L3 Eviction which misses in some processor core\000event=0x22,umask=0x81\000\00000\000\000\000\000\000 */
>  };
>  static const struct compact_pmu_event pmu_events__test_soc_cpu_uncore_imc[] = {
> -{ 2286 }, /* uncore_imc.cache_hits\000uncore\000Total cache hits\000event=0x34\000\00000\000\000\000\000\000 */
> +{ 3827 }, /* uncore_imc.cache_hits\000uncore\000Total cache hits\000event=0x34\000\00000\000\000\000\000\000 */
>  };
>  static const struct compact_pmu_event pmu_events__test_soc_cpu_uncore_imc_free_running[] = {
> -{ 2195 }, /* uncore_imc_free_running.cache_miss\000uncore\000Total cache misses\000event=0x12\000\00000\000\000\000\000\000 */
> +{ 3736 }, /* uncore_imc_free_running.cache_miss\000uncore\000Total cache misses\000event=0x12\000\00000\000\000\000\000\000 */
>  
>  };
>  
> @@ -129,51 +167,51 @@ const struct pmu_table_entry pmu_events__test_soc_cpu[] = {
>  {
>       .entries = pmu_events__test_soc_cpu_default_core,
>       .num_entries = ARRAY_SIZE(pmu_events__test_soc_cpu_default_core),
> -     .pmu_name = { 1138 /* default_core\000 */ },
> +     .pmu_name = { 2679 /* default_core\000 */ },
>  },
>  {
>       .entries = pmu_events__test_soc_cpu_hisi_sccl_ddrc,
>       .num_entries = ARRAY_SIZE(pmu_events__test_soc_cpu_hisi_sccl_ddrc),
> -     .pmu_name = { 1726 /* hisi_sccl,ddrc\000 */ },
> +     .pmu_name = { 3267 /* hisi_sccl,ddrc\000 */ },
>  },
>  {
>       .entries = pmu_events__test_soc_cpu_hisi_sccl_l3c,
>       .num_entries = ARRAY_SIZE(pmu_events__test_soc_cpu_hisi_sccl_l3c),
> -     .pmu_name = { 2089 /* hisi_sccl,l3c\000 */ },
> +     .pmu_name = { 3630 /* hisi_sccl,l3c\000 */ },
>  },
>  {
>       .entries = pmu_events__test_soc_cpu_uncore_cbox,
>       .num_entries = ARRAY_SIZE(pmu_events__test_soc_cpu_uncore_cbox),
> -     .pmu_name = { 1811 /* uncore_cbox\000 */ },
> +     .pmu_name = { 3352 /* uncore_cbox\000 */ },
>  },
>  {
>       .entries = pmu_events__test_soc_cpu_uncore_imc,
>       .num_entries = ARRAY_SIZE(pmu_events__test_soc_cpu_uncore_imc),
> -     .pmu_name = { 2275 /* uncore_imc\000 */ },
> +     .pmu_name = { 3816 /* uncore_imc\000 */ },
>  },
>  {
>       .entries = pmu_events__test_soc_cpu_uncore_imc_free_running,
>       .num_entries = ARRAY_SIZE(pmu_events__test_soc_cpu_uncore_imc_free_running),
> -     .pmu_name = { 2171 /* uncore_imc_free_running\000 */ },
> +     .pmu_name = { 3712 /* uncore_imc_free_running\000 */ },
>  },
>  };
>  
>  static const struct compact_pmu_event pmu_metrics__test_soc_cpu_default_core[] = {
> -{ 2704 }, /* CPI\000\0001 / IPC\000\000\000\000\000\000\000\00000 */
> -{ 3385 }, /* DCache_L2_All\000\000DCache_L2_All_Hits + DCache_L2_All_Miss\000\000\000\000\000\000\000\00000 */
> -{ 3157 }, /* DCache_L2_All_Hits\000\000l2_rqsts.demand_data_rd_hit + l2_rqsts.pf_hit + l2_rqsts.rfo_hit\000\000\000\000\000\000\000\00000 */
> -{ 3251 }, /* DCache_L2_All_Miss\000\000max(l2_rqsts.all_demand_data_rd - l2_rqsts.demand_data_rd_hit, 0) + l2_rqsts.pf_miss + l2_rqsts.rfo_miss\000\000\000\000\000\000\000\00000 */
> -{ 3449 }, /* DCache_L2_Hits\000\000d_ratio(DCache_L2_All_Hits, DCache_L2_All)\000\000\000\000\000\000\000\00000 */
> -{ 3517 }, /* DCache_L2_Misses\000\000d_ratio(DCache_L2_All_Miss, DCache_L2_All)\000\000\000\000\000\000\000\00000 */
> -{ 2789 }, /* Frontend_Bound_SMT\000\000idq_uops_not_delivered.core / (4 * (cpu_clk_unhalted.thread / 2 * (1 + cpu_clk_unhalted.one_thread_active / cpu_clk_unhalted.ref_xclk)))\000\000\000\000\000\000\000\00000 */
> -{ 2726 }, /* IPC\000group1\000inst_retired.any / cpu_clk_unhalted.thread\000\000\000\000\000\000\000\00000 */
> -{ 3651 }, /* L1D_Cache_Fill_BW\000\00064 * l1d.replacement / 1e9 / duration_time\000\000\000\000\000\000\000\00000 */
> -{ 3587 }, /* M1\000\000ipc + M2\000\000\000\000\000\000\000\00000 */
> -{ 3609 }, /* M2\000\000ipc + M1\000\000\000\000\000\000\000\00000 */
> -{ 3631 }, /* M3\000\0001 / M3\000\000\000\000\000\000\000\00000 */
> -{ 3086 }, /* cache_miss_cycles\000group1\000dcache_miss_cpi + icache_miss_cycles\000\000\000\000\000\000\000\00000 */
> -{ 2955 }, /* dcache_miss_cpi\000\000l1d\\-loads\\-misses / inst_retired.any\000\000\000\000\000\000\000\00000 */
> -{ 3019 }, /* icache_miss_cycles\000\000l1i\\-loads\\-misses / inst_retired.any\000\000\000\000\000\000\000\00000 */
> +{ 4245 }, /* CPI\000\0001 / IPC\000\000\000\000\000\000\000\00000 */
> +{ 4926 }, /* DCache_L2_All\000\000DCache_L2_All_Hits + DCache_L2_All_Miss\000\000\000\000\000\000\000\00000 */
> +{ 4698 }, /* DCache_L2_All_Hits\000\000l2_rqsts.demand_data_rd_hit + l2_rqsts.pf_hit + l2_rqsts.rfo_hit\000\000\000\000\000\000\000\00000 */
> +{ 4792 }, /* DCache_L2_All_Miss\000\000max(l2_rqsts.all_demand_data_rd - l2_rqsts.demand_data_rd_hit, 0) + l2_rqsts.pf_miss + l2_rqsts.rfo_miss\000\000\000\000\000\000\000\00000 */
> +{ 4990 }, /* DCache_L2_Hits\000\000d_ratio(DCache_L2_All_Hits, DCache_L2_All)\000\000\000\000\000\000\000\00000 */
> +{ 5058 }, /* DCache_L2_Misses\000\000d_ratio(DCache_L2_All_Miss, DCache_L2_All)\000\000\000\000\000\000\000\00000 */
> +{ 4330 }, /* Frontend_Bound_SMT\000\000idq_uops_not_delivered.core / (4 * (cpu_clk_unhalted.thread / 2 * (1 + cpu_clk_unhalted.one_thread_active / cpu_clk_unhalted.ref_xclk)))\000\000\000\000\000\000\000\00000 */
> +{ 4267 }, /* IPC\000group1\000inst_retired.any / cpu_clk_unhalted.thread\000\000\000\000\000\000\000\00000 */
> +{ 5192 }, /* L1D_Cache_Fill_BW\000\00064 * l1d.replacement / 1e9 / duration_time\000\000\000\000\000\000\000\00000 */
> +{ 5128 }, /* M1\000\000ipc + M2\000\000\000\000\000\000\000\00000 */
> +{ 5150 }, /* M2\000\000ipc + M1\000\000\000\000\000\000\000\00000 */
> +{ 5172 }, /* M3\000\0001 / M3\000\000\000\000\000\000\000\00000 */
> +{ 4627 }, /* cache_miss_cycles\000group1\000dcache_miss_cpi + icache_miss_cycles\000\000\000\000\000\000\000\00000 */
> +{ 4496 }, /* dcache_miss_cpi\000\000l1d\\-loads\\-misses / inst_retired.any\000\000\000\000\000\000\000\00000 */
> +{ 4560 }, /* icache_miss_cycles\000\000l1i\\-loads\\-misses / inst_retired.any\000\000\000\000\000\000\000\00000 */
>  
>  };
>  
> @@ -181,18 +219,18 @@ const struct pmu_table_entry pmu_metrics__test_soc_cpu[] = {
>  {
>       .entries = pmu_metrics__test_soc_cpu_default_core,
>       .num_entries = ARRAY_SIZE(pmu_metrics__test_soc_cpu_default_core),
> -     .pmu_name = { 1138 /* default_core\000 */ },
> +     .pmu_name = { 2679 /* default_core\000 */ },
>  },
>  };
>  
>  static const struct compact_pmu_event pmu_events__test_soc_sys_uncore_sys_ccn_pmu[] = {
> -{ 2465 }, /* sys_ccn_pmu.read_cycles\000uncore\000ccn read-cycles event\000config=0x2c\0000x01\00000\000\000\000\000\000 */
> +{ 4006 }, /* sys_ccn_pmu.read_cycles\000uncore\000ccn read-cycles event\000config=0x2c\0000x01\00000\000\000\000\000\000 */
>  };
>  static const struct compact_pmu_event pmu_events__test_soc_sys_uncore_sys_cmn_pmu[] = {
> -{ 2561 }, /* sys_cmn_pmu.hnf_cache_miss\000uncore\000Counts total cache misses in first lookup result (high priority)\000eventid=1,type=5\000(434|436|43c|43a).*\00000\000\000\000\000\000 */
> +{ 4102 }, /* sys_cmn_pmu.hnf_cache_miss\000uncore\000Counts total cache misses in first lookup result (high priority)\000eventid=1,type=5\000(434|436|43c|43a).*\00000\000\000\000\000\000 */
>  };
>  static const struct compact_pmu_event pmu_events__test_soc_sys_uncore_sys_ddr_pmu[] = {
> -{ 2370 }, /* sys_ddr_pmu.write_cycles\000uncore\000ddr write-cycles event\000event=0x2b\000v8\00000\000\000\000\000\000 */
> +{ 3911 }, /* sys_ddr_pmu.write_cycles\000uncore\000ddr write-cycles event\000event=0x2b\000v8\00000\000\000\000\000\000 */
>  
>  };
>  
> @@ -200,17 +238,17 @@ const struct pmu_table_entry pmu_events__test_soc_sys[] = {
>  {
>       .entries = pmu_events__test_soc_sys_uncore_sys_ccn_pmu,
>       .num_entries = ARRAY_SIZE(pmu_events__test_soc_sys_uncore_sys_ccn_pmu),
> -     .pmu_name = { 2446 /* uncore_sys_ccn_pmu\000 */ },
> +     .pmu_name = { 3987 /* uncore_sys_ccn_pmu\000 */ },
>  },
>  {
>       .entries = pmu_events__test_soc_sys_uncore_sys_cmn_pmu,
>       .num_entries = ARRAY_SIZE(pmu_events__test_soc_sys_uncore_sys_cmn_pmu),
> -     .pmu_name = { 2542 /* uncore_sys_cmn_pmu\000 */ },
> +     .pmu_name = { 4083 /* uncore_sys_cmn_pmu\000 */ },
>  },
>  {
>       .entries = pmu_events__test_soc_sys_uncore_sys_ddr_pmu,
>       .num_entries = ARRAY_SIZE(pmu_events__test_soc_sys_uncore_sys_ddr_pmu),
> -     .pmu_name = { 2351 /* uncore_sys_ddr_pmu\000 */ },
> +     .pmu_name = { 3892 /* uncore_sys_ddr_pmu\000 */ },
>  },
>  };
>  
> @@ -632,8 +670,20 @@ static const struct pmu_events_map *map_for_pmu(struct perf_pmu *pmu)
>  {
>          struct perf_cpu cpu = {-1};
>  
> -        if (pmu)
> +        if (pmu) {
> +                for (size_t i=0; i < ARRAY_SIZE(pmu_events__common); i++) {
> +                        const char *pmu_name = &big_c_string[pmu_events__common[i].pmu_name.offset];
> +
> +                        if (!strcmp(pmu_name, pmu->name)) {
> +                                const struct pmu_events_map *map = &pmu_events_map[0];
> +
> +                                while (strcmp("common", map->arch))
> +                                        map++;
> +                                return map;
> +                        }
> +                }
>                  cpu = perf_cpu_map__min(pmu->cpus);
> +        }
>          return map_for_cpu(cpu);
>  }
>  
> diff --git a/tools/perf/pmu-events/jevents.py b/tools/perf/pmu-events/jevents.py
> index e821155151ec..76c1e7b0bc22 100755
> --- a/tools/perf/pmu-events/jevents.py
> +++ b/tools/perf/pmu-events/jevents.py
> @@ -295,6 +295,7 @@ class JsonEvent:
>            'cpu_atom': 'cpu_atom',
>            'ali_drw': 'ali_drw',
>            'arm_cmn': 'arm_cmn',
> +          'software': 'software',
>            'tool': 'tool',
>        }
>        return table[unit] if unit in table else f'uncore_{unit.lower()}'
> @@ -1158,8 +1159,20 @@ static const struct pmu_events_map *map_for_pmu(struct perf_pmu *pmu)
>  {
>          struct perf_cpu cpu = {-1};
>  
> -        if (pmu)
> +        if (pmu) {
> +                for (size_t i=0; i < ARRAY_SIZE(pmu_events__common); i++) {
> +                        const char *pmu_name = &big_c_string[pmu_events__common[i].pmu_name.offset];
> +
> +                        if (!strcmp(pmu_name, pmu->name)) {
> +                                const struct pmu_events_map *map = &pmu_events_map[0];
> +
> +                                while (strcmp("common", map->arch))
> +                                        map++;
> +                                return map;
> +                        }
> +                }
>                  cpu = perf_cpu_map__min(pmu->cpus);
> +        }
>          return map_for_cpu(cpu);
>  }
>  
> -- 
> 2.50.0.727.gbf7dc18ff4-goog
> 

^ permalink raw reply	[flat|nested] 41+ messages in thread

* Re: [PATCH v7 11/16] perf ilist: Add new python ilist command
  2025-07-14 16:43 ` [PATCH v7 11/16] perf ilist: Add new python ilist command Ian Rogers
  2025-07-21  7:32   ` Gautam Menghani
@ 2025-07-23 18:33   ` Falcon, Thomas
  2025-07-23 21:33     ` Ian Rogers
  1 sibling, 1 reply; 41+ messages in thread
From: Falcon, Thomas @ 2025-07-23 18:33 UTC (permalink / raw)
  To: alexander.shishkin@linux.intel.com, mhiramat@kernel.org,
	tmricht@linux.ibm.com, xu.yang_2@nxp.com, howardchu95@gmail.com,
	Hunter, Adrian, ak@linux.intel.com, mingo@redhat.com,
	irogers@google.com, gautam@linux.ibm.com, ctshao@google.com,
	linux-kernel@vger.kernel.org, james.clark@linaro.org,
	collin.funk1@gmail.com, mark.rutland@arm.com,
	peterz@infradead.org, linux@treblig.org, Wang, Weilin,
	yangtiezhu@loongson.cn, acme@kernel.org,
	linux-perf-users@vger.kernel.org, kan.liang@linux.intel.com,
	jolsa@kernel.org, namhyung@kernel.org

On Mon, 2025-07-14 at 09:43 -0700, Ian Rogers wrote:
> The perf ilist command is a textual app [1] similar to perf list. In
> the top-left pane a tree of PMUs is displayed. Selecting a PMU expands
> the events within it. Selecting an event displays the `perf list`
> style event information in the top-right pane.
> 
> When an event is selected it is opened and the counters on each CPU
> the event is for are periodically read. The bottom of the screen
> contains a scrollable set of sparklines showing the events in total
> and on each CPU. Scrolling below the sparklines shows the same data as
> raw counts. The sparklines are small graphs where the height of the
> bar is in relation to maximum of the other counts in the graph.
> 
> By default the counts are read with an interval of 0.1 seconds (10
> times per second). A -I/--interval command line option allows the
> interval to be changed. The oldest read counts are dropped when the
> counts fill the line causing the sparkline to move from right to left.
> 
> A search box can be pulled up with the 's' key. 'n' and 'p' iterate
> through the search results. As some PMUs have hundreds of events a 'c'
> key will collapse the events in the current PMU to make navigating the
> PMUs easier.
> 
> [1] https://textual.textualize.io/
> 
> Signed-off-by: Ian Rogers <irogers@google.com>

Hi Ian, I hit a segfault playing around with the ilist search feature. I can recreate it pretty
reliably by searching for something then holding down 'n' to quickly cycle through the results.
After a few seconds, the program crashes.

I've attached a backtrace from gdb below.

Thanks,
Tom

#0  __memset_avx2_unaligned_erms () at ../sysdeps/x86_64/multiarch/memset-vec-unaligned-erms.S:210
#1  0x00007fffe88121a7 in perf_evsel__read (evsel=0x555557b16390, cpu_map_idx=8, thread=0,
count=0x0) at evsel.c:403
#2  0x00007fffe88cbf97 in evsel__read_one (evsel=0x555557b16390, cpu_map_idx=8, thread=0) at
util/evsel.c:1719
#3  0x00007fffe88cc794 in evsel__read_counter (evsel=0x555557b16390, cpu_map_idx=8, thread=0) at
util/evsel.c:1896
#4  0x00007fffe880c0a8 in prepare_metric (mexp=0x555555d25660, evsel=<optimized out>,
pctx=0x5555579b5d00, cpu_idx=8, thread_idx=0)
    at /home/tfalcon/perf-tools-next/tools/perf/util/python.c:1353
#5  pyrf_evlist__compute_metric (pevlist=<optimized out>, args=<optimized out>, kwargs=<optimized
out>) at /home/tfalcon/perf-tools-next/tools/perf/util/python.c:1428
#6  0x00007ffff7978655 in method_vectorcall_VARARGS_KEYWORDS (func=<optimized out>,
args=0x7ffff7fb1680, nargsf=<optimized out>, kwnames=<optimized out>)
    at /usr/src/debug/python3.13-3.13.5-1.fc41.x86_64/Objects/descrobject.c:358
#7  0x00007ffff793f337 in _PyObject_VectorcallTstate (tstate=0x7ffff7d599d0 <_PyRuntime+283024>,
callable=0x7fffe94f3dd0, args=<optimized out>, nargsf=<optimized out>, 
    kwnames=<optimized out>) at /usr/src/debug/python3.13-3.13.5-
1.fc41.x86_64/Include/internal/pycore_call.h:168
#8  PyObject_Vectorcall (callable=0x7fffe94f3dd0, args=<optimized out>, nargsf=<optimized out>,
kwnames=<optimized out>)
    at /usr/src/debug/python3.13-3.13.5-1.fc41.x86_64/Objects/call.c:327
#9  0x00007ffff794f1c1 in _PyEval_EvalFrameDefault (tstate=<optimized out>, frame=<optimized out>,
throwflag=<optimized out>)
    at /usr/src/debug/python3.13-3.13.5-1.fc41.x86_64/Python/generated_cases.c.h:1843
#10 0x00007ffff79ab59f in _PyEval_EvalFrame (tstate=0x7ffff7d599d0 <_PyRuntime+283024>,
frame=<optimized out>, throwflag=0)
    at /usr/src/debug/python3.13-3.13.5-1.fc41.x86_64/Include/internal/pycore_ceval.h:119
#11 _PyEval_Vector (tstate=0x7ffff7d599d0 <_PyRuntime+283024>, func=0x7fffdde34400, locals=0x0,
args=0x7fffffffc9a8, argcount=1, kwnames=0x0)
    at /usr/src/debug/python3.13-3.13.5-1.fc41.x86_64/Python/ceval.c:1816
#12 _PyFunction_Vectorcall (func=0x7fffdde34400, stack=0x7fffffffc9a8, nargsf=1, kwnames=0x0) at
/usr/src/debug/python3.13-3.13.5-1.fc41.x86_64/Objects/call.c:413
#13 _PyObject_VectorcallTstate (tstate=0x7ffff7d599d0 <_PyRuntime+283024>, callable=0x7fffdde34400,
args=0x7fffffffc9a8, nargsf=1, kwnames=0x0)
    at /usr/src/debug/python3.13-3.13.5-1.fc41.x86_64/Include/internal/pycore_call.h:168
#14 method_vectorcall (method=<optimized out>, args=0x7ffff7d2a140 <_PyRuntime+88320>,
nargsf=<optimized out>, kwnames=<optimized out>)
    at /usr/src/debug/python3.13-3.13.5-1.fc41.x86_64/Objects/classobject.c:70
#15 0x00007ffff795369d in PyObject_Call (callable=0x7fffcfc978c0, args=0x7ffff7d2a128
<_PyRuntime+88296>, kwargs=0x0)
    at /usr/src/debug/python3.13-3.13.5-1.fc41.x86_64/Objects/call.c:373
#16 PyCFunction_Call (callable=0x7fffcfc978c0, args=0x7ffff7d2a128 <_PyRuntime+88296>, kwargs=0x0)
at /usr/src/debug/python3.13-3.13.5-1.fc41.x86_64/Objects/call.c:381
#17 _PyEval_EvalFrameDefault (tstate=<optimized out>, frame=<optimized out>, throwflag=<optimized
out>)
    at /usr/src/debug/python3.13-3.13.5-1.fc41.x86_64/Python/generated_cases.c.h:1355
#18 0x00007ffff7a3a861 in _PyEval_EvalFrame (tstate=0x7ffff7d599d0 <_PyRuntime+283024>,
frame=<optimized out>, throwflag=0)
    at /usr/src/debug/python3.13-3.13.5-1.fc41.x86_64/Include/internal/pycore_ceval.h:119
#19 gen_send_ex2 (gen=0x7fffdccfcba0, arg=0x7ffff7d0bd30 <_Py_NoneStruct>, presult=0x7fffffffcc68,
exc=0, closing=<optimized out>)
    at /usr/src/debug/python3.13-3.13.5-1.fc41.x86_64/Objects/genobject.c:229
#20 0x00007fffde564149 in task_step_impl (state=state@entry=0x7fffde89dfd0,
task=task@entry=0x7fffdcd443c0, exc=exc@entry=0x0)
    at /usr/src/debug/python3.13-3.13.5-1.fc41.x86_64/Modules/_asynciomodule.c:2782
#21 0x00007fffde5657a5 in task_step (state=0x7fffde89dfd0, task=0x7fffdcd443c0, exc=0x0) at
/usr/src/debug/python3.13-3.13.5-1.fc41.x86_64/Modules/_asynciomodule.c:3101
#22 0x00007ffff79700a7 in cfunction_vectorcall_O (func=0x7fffcc0b1ad0, args=0x7fffcc37e860,
nargsf=<optimized out>, kwnames=<optimized out>)
    at /usr/src/debug/python3.13-3.13.5-1.fc41.x86_64/Include/cpython/methodobject.h:50
#23 0x00007ffff7ad6a3f in _PyObject_VectorcallTstate (tstate=0x7ffff7d599d0 <_PyRuntime+283024>,
callable=0x7fffcc0b1ad0, args=<optimized out>, nargsf=<optimized out>, 
    kwnames=<optimized out>) at /usr/src/debug/python3.13-3.13.5-
1.fc41.x86_64/Include/internal/pycore_call.h:168
#24 0x00007ffff78ef15b in context_run (self=0x7fffddf2a440, args=0x7fffcc37e858, nargs=2,
kwnames=0x0)
    at /usr/src/debug/python3.13-3.13.5-1.fc41.x86_64/Python/context.c:664
#25 0x00007ffff7969b4b in cfunction_vectorcall_FASTCALL_KEYWORDS (func=<optimized out>,
args=0x7fffcc37e858, nargsf=<optimized out>, kwnames=<optimized out>)
    at /usr/src/debug/python3.13-3.13.5-1.fc41.x86_64/Objects/methodobject.c:441
#26 0x00007ffff795369d in PyObject_Call (callable=0x7fffcdff8950, args=0x7fffcc37e840, kwargs=0x0)
at /usr/src/debug/python3.13-3.13.5-1.fc41.x86_64/Objects/call.c:373
#27 PyCFunction_Call (callable=0x7fffcdff8950, args=0x7fffcc37e840, kwargs=0x0) at
/usr/src/debug/python3.13-3.13.5-1.fc41.x86_64/Objects/call.c:381
#28 _PyEval_EvalFrameDefault (tstate=<optimized out>, frame=<optimized out>, throwflag=<optimized
out>)
    at /usr/src/debug/python3.13-3.13.5-1.fc41.x86_64/Python/generated_cases.c.h:1355
#29 0x00007ffff7a25fcb in PyEval_EvalCode (co=0x5555555d9a90, globals=<optimized out>,
locals=0x7fffe9634c80)
    at /usr/src/debug/python3.13-3.13.5-1.fc41.x86_64/Python/ceval.c:604
#30 0x00007ffff7a640c3 in run_eval_code_obj (tstate=tstate@entry=0x7ffff7d599d0 <_PyRuntime+283024>,
co=co@entry=0x5555555d9a90, globals=globals@entry=0x7fffe9634c80, 
    locals=locals@entry=0x7fffe9634c80) at /usr/src/debug/python3.13-3.13.5-
1.fc41.x86_64/Python/pythonrun.c:1381
#31 0x00007ffff7a615f3 in run_mod (mod=mod@entry=0x555555710ec8,
filename=filename@entry=0x7fffe96568e0, globals=globals@entry=0x7fffe9634c80, 
    locals=locals@entry=0x7fffe9634c80, flags=flags@entry=0x7fffffffd298,
arena=arena@entry=0x7fffe971bdb0, interactive_src=0x0, generate_new_source=0)
    at /usr/src/debug/python3.13-3.13.5-1.fc41.x86_64/Python/pythonrun.c:1466
#32 0x00007ffff7a5dfd6 in pyrun_file (fp=fp@entry=0x5555555703a0,
filename=filename@entry=0x7fffe96568e0, start=start@entry=257, globals=globals@entry=0x7fffe9634c80,
    locals=locals@entry=0x7fffe9634c80, closeit=closeit@entry=1, flags=0x7fffffffd298) at
/usr/src/debug/python3.13-3.13.5-1.fc41.x86_64/Python/pythonrun.c:1295
#33 0x00007ffff7a5dc4f in _PyRun_SimpleFileObject (fp=fp@entry=0x5555555703a0,
filename=filename@entry=0x7fffe96568e0, closeit=closeit@entry=1, 
    flags=flags@entry=0x7fffffffd298) at /usr/src/debug/python3.13-3.13.5-
1.fc41.x86_64/Python/pythonrun.c:517
#34 0x00007ffff7a5d881 in _PyRun_AnyFileObject (fp=fp@entry=0x5555555703a0,
filename=filename@entry=0x7fffe96568e0, closeit=closeit@entry=1, 
    flags=flags@entry=0x7fffffffd298) at /usr/src/debug/python3.13-3.13.5-
1.fc41.x86_64/Python/pythonrun.c:77
#35 0x00007ffff7a5beda in pymain_run_file_obj (program_name=0x7fffe9634db0, filename=0x7fffe96568e0,
skip_source_first_line=0)
    at /usr/src/debug/python3.13-3.13.5-1.fc41.x86_64/Modules/main.c:410
#36 pymain_run_file (config=0x7ffff7d2c0c8 <_PyRuntime+96392>) at /usr/src/debug/python3.13-3.13.5-
1.fc41.x86_64/Modules/main.c:429
#37 pymain_run_python (exitcode=0x7fffffffd28c) at /usr/src/debug/python3.13-3.13.5-
1.fc41.x86_64/Modules/main.c:696
#38 Py_RunMain () at /usr/src/debug/python3.13-3.13.5-1.fc41.x86_64/Modules/main.c:775
#39 0x00007ffff7a1396c in Py_BytesMain (argc=<optimized out>, argv=<optimized out>) at
/usr/src/debug/python3.13-3.13.5-1.fc41.x86_64/Modules/main.c:829
#40 0x00007ffff760f488 in __libc_start_call_main (main=main@entry=0x555555555160 <main>,
argc=argc@entry=2, argv=argv@entry=0x7fffffffd4f8)
    at ../sysdeps/nptl/libc_start_call_main.h:58
#41 0x00007ffff760f54b in __libc_start_main_impl (main=0x555555555160 <main>, argc=2,
argv=0x7fffffffd4f8, init=<optimized out>, fini=<optimized out>, 
    rtld_fini=<optimized out>, stack_end=0x7fffffffd4e8) at ../csu/libc-start.c:360
#42 0x0000555555555095 in _start ()


> ---
>  tools/perf/python/ilist.py | 392 +++++++++++++++++++++++++++++++++++++
>  1 file changed, 392 insertions(+)
>  create mode 100755 tools/perf/python/ilist.py
> 
> diff --git a/tools/perf/python/ilist.py b/tools/perf/python/ilist.py
> new file mode 100755
> index 000000000000..b21f4c93247e
> --- /dev/null
> +++ b/tools/perf/python/ilist.py
> @@ -0,0 +1,392 @@
> +#!/usr/bin/env python3
> +# SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause)
> +"""Interactive perf list."""
> +
> +import argparse
> +from typing import Any, Dict, Tuple
> +import perf
> +from textual import on
> +from textual.app import App, ComposeResult
> +from textual.binding import Binding
> +from textual.containers import Horizontal, HorizontalGroup, Vertical, VerticalScroll
> +from textual.command import SearchIcon
> +from textual.screen import ModalScreen
> +from textual.widgets import Button, Footer, Header, Input, Label, Sparkline, Static, Tree
> +from textual.widgets.tree import TreeNode
> +
> +class ErrorScreen(ModalScreen[bool]):
> +    """Pop up dialog for errors."""
> +
> +    CSS="""
> +    ErrorScreen {
> +        align: center middle;
> +    }
> +    """
> +    def __init__(self, error: str):
> +        self.error = error
> +        super().__init__()
> +
> +    def compose(self) -> ComposeResult:
> +        yield Button(f"Error: {self.error}", variant="primary", id="error")
> +
> +    def on_button_pressed(self, event: Button.Pressed) -> None:
> +        self.dismiss(True)
> +
> +
> +class SearchScreen(ModalScreen[str]):
> +    """Pop up dialog for search."""
> +
> +    CSS="""
> +    SearchScreen Horizontal {
> +        align: center middle;
> +        margin-top: 1;
> +    }
> +    SearchScreen Input {
> +        width: 1fr;
> +    }
> +    """
> +    def compose(self) -> ComposeResult:
> +        yield Horizontal(SearchIcon(), Input(placeholder="Event name"))
> +
> +    def on_input_submitted(self, event: Input.Submitted) -> None:
> +        """Handle the user pressing Enter in the input field."""
> +        self.dismiss(event.value)
> +
> +
> +class Counter(HorizontalGroup):
> +    """Two labels for a CPU and its counter value."""
> +
> +    CSS="""
> +    Label {
> +        gutter: 1;
> +    }
> +    """
> +
> +    def __init__(self, cpu: int) -> None:
> +        self.cpu = cpu
> +        super().__init__()
> +
> +    def compose(self) -> ComposeResult:
> +        label = f"cpu{self.cpu}" if self.cpu >= 0 else "total"
> +        yield Label(label + " ")
> +        yield Label("0", id=f"counter_{label}")
> +
> +
> +class CounterSparkline(HorizontalGroup):
> +    """A Sparkline for a performance counter."""
> +
> +    def __init__(self, cpu: int) -> None:
> +        self.cpu = cpu
> +        super().__init__()
> +
> +    def compose(self) -> ComposeResult:
> +        label = f"cpu{self.cpu}" if self.cpu >= 0 else "total"
> +        yield Label(label)
> +        yield Sparkline([], summary_function=max, id=f"sparkline_{label}")
> +
> +
> +class IListApp(App):
> +    TITLE = "Interactive Perf List"
> +
> +    BINDINGS = [
> +        Binding(key="s", action="search", description="Search",
> +                tooltip="Search events and PMUs"),
> +        Binding(key="n", action="next", description="Next",
> +                tooltip="Next search result or item"),
> +        Binding(key="p", action="prev", description="Previous",
> +                tooltip="Previous search result or item"),
> +        Binding(key="c", action="collapse", description="Collapse",
> +                tooltip="Collapse the current PMU"),
> +        Binding(key="^q", action="quit", description="Quit",
> +                tooltip="Quit the app"),
> +    ]
> +
> +    CSS = """
> +        /* Make the 'total' sparkline a different color. */
> +        #sparkline_total > .sparkline--min-color {
> +            color: $accent;
> +        }
> +        #sparkline_total > .sparkline--max-color {
> +            color: $accent 30%;
> +        }
> +        /*
> +         * Make the active_search initially not displayed with the text in
> +         * the middle of the line.
> +         */
> +        #active_search {
> +            display: none;
> +            width: 100%;
> +            text-align: center;
> +        }
> +    """
> +
> +    def __init__(self, interval: float) -> None:
> +        self.interval = interval
> +        self.evlist = None
> +        self.search_results: list[TreeNode[str]] = []
> +        self.cur_search_result: TreeNode[str] | None = None
> +        super().__init__()
> +
> +
> +
> +    def expand_and_select(self, node: TreeNode[Any]) -> None:
> +        """Expand select a node in the tree."""
> +        if node.parent:
> +            node.parent.expand()
> +            if node.parent.parent:
> +                node.parent.parent.expand()
> +        node.expand()
> +        node.tree.select_node(node)
> +        node.tree.scroll_to_node(node)
> +
> +
> +    def set_searched_tree_node(self, previous: bool) -> None:
> +        """Set the cur_search_result node to either the next or previous."""
> +        l = len(self.search_results)
> +
> +        if l < 1:
> +            tree: Tree[str] = self.query_one("#pmus", Tree)
> +            if previous:
> +                tree.action_cursor_up()
> +            else:
> +                tree.action_cursor_down()
> +            return
> +
> +        if self.cur_search_result:
> +            idx = self.search_results.index(self.cur_search_result)
> +            if previous:
> +                idx = idx - 1 if idx > 0 else l - 1
> +            else:
> +                idx = idx + 1 if idx < l - 1 else 0
> +        else:
> +            idx = l - 1 if previous else 0
> +
> +        node = self.search_results[idx]
> +        if node == self.cur_search_result:
> +            return
> +
> +        self.cur_search_result = node
> +        self.expand_and_select(node)
> +
> +    def action_search(self) -> None:
> +        """Search was chosen."""
> +        def set_initial_focus(event: str | None) -> None:
> +            """Sets the focus after the SearchScreen is dismissed."""
> +
> +            search_label = self.query_one("#active_search", Label)
> +            search_label.display = True if event else False
> +            if not event:
> +                return
> +            event = event.lower()
> +            search_label.update(f'Searching for events matching "{event}"')
> +
> +            tree: Tree[str] = self.query_one("#pmus", Tree)
> +            def find_search_results(event: str, node: TreeNode[str], \
> +                                    cursor_seen: bool = False, \
> +                                    match_after_cursor: TreeNode[str] | None = None) \
> +                    -> Tuple[bool, TreeNode[str] | None]:
> +                """Find nodes that match the search remembering the one after the cursor."""
> +                if not cursor_seen and node == tree.cursor_node:
> +                    cursor_seen = True
> +                if node.data and event in node.data:
> +                    if cursor_seen and not match_after_cursor:
> +                        match_after_cursor = node
> +                    self.search_results.append(node)
> +
> +                if node.children:
> +                    for child in node.children:
> +                        (cursor_seen, match_after_cursor) = \
> +                            find_search_results(event, child, cursor_seen, match_after_cursor)
> +                return (cursor_seen, match_after_cursor)
> +
> +            self.search_results.clear()
> +            (_ , self.cur_search_result) = find_search_results(event, tree.root)
> +            if len(self.search_results) < 1:
> +                self.push_screen(ErrorScreen(f"Failed to find pmu/event {event}"))
> +                search_label.display = False
> +            elif self.cur_search_result:
> +                self.expand_and_select(self.cur_search_result)
> +            else:
> +                self.set_searched_tree_node(previous=False)
> +
> +        self.push_screen(SearchScreen(), set_initial_focus)
> +
> +
> +    def action_next(self) -> None:
> +        """Next was chosen."""
> +        self.set_searched_tree_node(previous=False)
> +
> +
> +    def action_prev(self) -> None:
> +        """Previous was chosen."""
> +        self.set_searched_tree_node(previous=True)
> +
> +
> +    def action_collapse(self) -> None:
> +        """Collapse the potentially large number of events under a PMU."""
> +        tree: Tree[str] = self.query_one("#pmus", Tree)
> +        node = tree.cursor_node
> +        if node and node.parent and node.parent.parent:
> +            node.parent.collapse_all()
> +            node.tree.scroll_to_node(node.parent)
> +
> +
> +    def update_counts(self) -> None:
> +        """Called every interval to update counts."""
> +        if not self.evlist:
> +            return
> +
> +        def update_count(cpu: int, count: int):
> +            # Update the raw count display.
> +            counter: Label = self.query(f"#counter_cpu{cpu}" if cpu >= 0 else "#counter_total")
> +            if not counter:
> +                return
> +            counter = counter.first(Label)
> +            counter.update(str(count))
> +
> +            # Update the sparkline.
> +            line: Sparkline = self.query(f"#sparkline_cpu{cpu}" if cpu >= 0 else "#sparkline_total")
> +            if not line:
> +                return
> +            line = line.first(Sparkline)
> +            # If there are more events than the width, remove the front event.
> +            if len(line.data) > line.size.width:
> +                line.data.pop(0)
> +            line.data.append(count)
> +            line.mutate_reactive(Sparkline.data)
> +
> +        # Update the total and each CPU counts, assume there's just 1 evsel.
> +        total = 0
> +        self.evlist.disable()
> +        for evsel in self.evlist:
> +            for cpu in evsel.cpus():
> +                aggr = 0
> +                for thread in evsel.threads():
> +                    counts = evsel.read(cpu, thread)
> +                    aggr += counts.val
> +                update_count(cpu, aggr)
> +                total += aggr
> +        update_count(-1, total)
> +        self.evlist.enable()
> +
> +
> +    def on_mount(self) -> None:
> +        """When App starts set up periodic event updating."""
> +        self.update_counts()
> +        self.set_interval(self.interval, self.update_counts)
> +
> +
> +    def set_pmu_and_event(self, pmu: str, event: str) -> None:
> +        """Updates the event/description and starts the counters."""
> +        # Remove previous event information.
> +        if self.evlist:
> +            self.evlist.disable()
> +            self.evlist.close()
> +            lines = self.query(CounterSparkline)
> +            for line in lines:
> +                line.remove()
> +            lines = self.query(Counter)
> +            for line in lines:
> +                line.remove()
> +
> +        def pmu_event_description(pmu: str, event: str) -> str:
> +            """Find and format event description for {pmu}/{event}/."""
> +            def get_info(info: Dict[str, str], key: str):
> +                return (info[key] + "\n") if key in info else ""
> +
> +            for p in perf.pmus():
> +                if p.name() != pmu:
> +                    continue
> +                for info in p.events():
> +                    if "name" not in info or info["name"] != event:
> +                        continue
> +
> +                    desc = get_info(info, "topic")
> +                    desc += get_info(info, "event_type_desc")
> +                    desc += get_info(info, "desc")
> +                    desc += get_info(info, "long_desc")
> +                    desc += get_info(info, "encoding_desc")
> +                    return desc
> +            return "description"
> +
> +        # Parse event, update event text and description.
> +        full_name = event if event.startswith(pmu) or ':' in event else f"{pmu}/{event}/"
> +        self.query_one("#event_name", Label).update(full_name)
> +        self.query_one("#event_description", Static).update(pmu_event_description(pmu, event))
> +
> +        # Open the event.
> +        try:
> +            self.evlist = perf.parse_events(full_name)
> +            if self.evlist:
> +                self.evlist.open()
> +                self.evlist.enable()
> +        except:
> +            self.evlist = None
> +
> +        if not self.evlist:
> +            self.push_screen(ErrorScreen(f"Failed to open {full_name}"))
> +            return
> +
> +        # Add spark lines for all the CPUs. Note, must be done after
> +        # open so that the evlist CPUs have been computed by propagate
> +        # maps.
> +        lines = self.query_one("#lines")
> +        line = CounterSparkline(cpu=-1)
> +        lines.mount(line)
> +        for cpu in self.evlist.all_cpus():
> +            line = CounterSparkline(cpu)
> +            lines.mount(line)
> +        line = Counter(cpu=-1)
> +        lines.mount(line)
> +        for cpu in self.evlist.all_cpus():
> +            line = Counter(cpu)
> +            lines.mount(line)
> +
> +
> +    def compose(self) -> ComposeResult:
> +        """Draws the app."""
> +        def pmu_event_tree() -> Tree:
> +            """Create tree of PMUs with events under."""
> +            tree: Tree[str] = Tree("PMUs", id="pmus")
> +            tree.root.expand()
> +            for pmu in perf.pmus():
> +                pmu_name = pmu.name().lower()
> +                pmu_node = tree.root.add(pmu_name, data=pmu_name)
> +                try:
> +                    for event in sorted(pmu.events(), key=lambda x: x["name"]):
> +                        if "name" in event:
> +                            e = event["name"].lower()
> +                            if "alias" in event:
> +                                pmu_node.add_leaf(f'{e} ({event["alias"]})', data=e)
> +                            else:
> +                                pmu_node.add_leaf(e, data=e)
> +                except:
> +                    # Reading events may fail with EPERM, ignore.
> +                    pass
> +            return tree
> +
> +        yield Header(id="header")
> +        yield Horizontal(Vertical(pmu_event_tree(), id="events"),
> +                         Vertical(Label("event name", id="event_name"),
> +                                  Static("description", markup=False, id="event_description"),
> +                                  ))
> +        yield Label(id="active_search")
> +        yield VerticalScroll(id="lines")
> +        yield Footer(id="footer")
> +
> +
> +    @on(Tree.NodeSelected)
> +    def on_tree_node_selected(self, event: Tree.NodeSelected[str]) -> None:
> +        """Called when a tree node is selected, selecting the event."""
> +        if event.node.parent and event.node.parent.parent:
> +            assert event.node.parent.data is not None
> +            assert event.node.data is not None
> +            self.set_pmu_and_event(event.node.parent.data, event.node.data)
> +
> +
> +if __name__ == "__main__":
> +    ap = argparse.ArgumentParser()
> +    ap.add_argument('-I', '--interval', help="Counter update interval in seconds", default=0.1)
> +    args = ap.parse_args()
> +    app = IListApp(float(args.interval))
> +    app.run()


^ permalink raw reply	[flat|nested] 41+ messages in thread

* Re: [PATCH v7 05/16] perf tp_pmu: Add event APIs
  2025-07-14 16:43 ` [PATCH v7 05/16] perf tp_pmu: Add event APIs Ian Rogers
@ 2025-07-23 18:57   ` Arnaldo Carvalho de Melo
  0 siblings, 0 replies; 41+ messages in thread
From: Arnaldo Carvalho de Melo @ 2025-07-23 18:57 UTC (permalink / raw)
  To: Ian Rogers
  Cc: Peter Zijlstra, Ingo Molnar, Namhyung Kim, Mark Rutland,
	Alexander Shishkin, Jiri Olsa, Adrian Hunter, Kan Liang,
	James Clark, Xu Yang, Masami Hiramatsu (Google), Collin Funk,
	Howard Chu, Weilin Wang, Andi Kleen, Dr. David Alan Gilbert,
	Thomas Richter, Tiezhu Yang, Gautam Menghani, Thomas Falcon,
	Chun-Tse Shao, linux-kernel, linux-perf-users

On Mon, Jul 14, 2025 at 09:43:53AM -0700, Ian Rogers wrote:
> Add event APIs for the tracepoint PMU allowing things like perf list
> to function using it. For perf list add the tracepoint format in the
> long description (shown with -v).
> 
> Signed-off-by: Ian Rogers <irogers@google.com>
> ---
>  tools/perf/util/pmu.c    |   7 +++
>  tools/perf/util/tp_pmu.c | 114 +++++++++++++++++++++++++++++++++++++++
>  tools/perf/util/tp_pmu.h |   7 +++
>  3 files changed, 128 insertions(+)
> 
> diff --git a/tools/perf/util/pmu.c b/tools/perf/util/pmu.c
> index b09b2ea2407a..dc05233e8232 100644
> --- a/tools/perf/util/pmu.c
> +++ b/tools/perf/util/pmu.c
> @@ -24,6 +24,7 @@
>  #include "hwmon_pmu.h"
>  #include "pmus.h"
>  #include "tool_pmu.h"
> +#include "tp_pmu.h"
>  #include <util/pmu-bison.h>
>  #include <util/pmu-flex.h>
>  #include "parse-events.h"
> @@ -1983,6 +1984,8 @@ bool perf_pmu__have_event(struct perf_pmu *pmu, const char *name)
>  		return false;
>  	if (perf_pmu__is_tool(pmu) && tool_pmu__skip_event(name))
>  		return false;
> +	if (perf_pmu__is_tracepoint(pmu))
> +		return tp_pmu__have_event(pmu, name);
>  	if (perf_pmu__is_hwmon(pmu))
>  		return hwmon_pmu__have_event(pmu, name);
>  	if (perf_pmu__is_drm(pmu))
> @@ -1998,6 +2001,8 @@ size_t perf_pmu__num_events(struct perf_pmu *pmu)
>  {
>  	size_t nr;
>  
> +	if (perf_pmu__is_tracepoint(pmu))
> +		return tp_pmu__num_events(pmu);
>  	if (perf_pmu__is_hwmon(pmu))
>  		return hwmon_pmu__num_events(pmu);
>  	if (perf_pmu__is_drm(pmu))
> @@ -2068,6 +2073,8 @@ int perf_pmu__for_each_event(struct perf_pmu *pmu, bool skip_duplicate_pmus,
>  	struct hashmap_entry *entry;
>  	size_t bkt;
>  
> +	if (perf_pmu__is_tracepoint(pmu))
> +		return tp_pmu__for_each_event(pmu, state, cb);
>  	if (perf_pmu__is_hwmon(pmu))
>  		return hwmon_pmu__for_each_event(pmu, state, cb);
>  	if (perf_pmu__is_drm(pmu))
> diff --git a/tools/perf/util/tp_pmu.c b/tools/perf/util/tp_pmu.c
> index fd83164f8763..9d68a1da17f6 100644
> --- a/tools/perf/util/tp_pmu.c
> +++ b/tools/perf/util/tp_pmu.c
> @@ -1,5 +1,6 @@
>  // SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause)
>  #include "tp_pmu.h"
> +#include "pmus.h"
>  #include <api/fs/fs.h>
>  #include <api/fs/tracing_path.h>
>  #include <api/io_dir.h>
> @@ -93,3 +94,116 @@ int tp_pmu__for_each_tp_sys(void *state, tp_sys_callback cb)
>  	close(events_dir.dirfd);
>  	return ret;
>  }
> +
> +bool perf_pmu__is_tracepoint(const struct perf_pmu *pmu)
> +{
> +	return pmu->type == PERF_TYPE_TRACEPOINT;
> +}
> +
> +struct for_each_event_args {
> +	void *state;
> +	pmu_event_callback cb;
> +	const struct perf_pmu *pmu;
> +};
> +
> +static int for_each_event_cb(void *state, const char *sys_name, const char *evt_name)
> +{
> +	struct for_each_event_args *args = state;
> +	char name[2 * FILENAME_MAX + 2];
> +	/* 16 possible hex digits and 22 other characters and \0. */
> +	char encoding[16 + 22];
> +	char *format = NULL;
> +	size_t format_size;
> +	struct pmu_event_info info = {
> +		.pmu = args->pmu,
> +		.pmu_name = args->pmu->name,
> +		.event_type_desc = "Tracepoint event",
> +	};
> +	char *tp_dir = get_events_file(sys_name);
> +	char path[PATH_MAX];
> +	int id, err;
> +
> +	if (!tp_dir)
> +		return -1;
> +
> +	scnprintf(path, sizeof(path), "%s/%s/id", tp_dir, evt_name);
> +	err = filename__read_int(path, &id);
> +	if (err == 0) {
> +		snprintf(encoding, sizeof(encoding), "tracepoint/config=0x%x/", id);
> +		info.encoding_desc = encoding;
> +	}
> +
> +	scnprintf(path, sizeof(path), "%s/%s/format", tp_dir, evt_name);
> +	put_events_file(tp_dir);
> +	err = filename__read_str(path, &format, &format_size);
> +	if (err == 0) {
> +		info.long_desc = format;
> +		for (size_t i = 0 ; i < format_size; i++) {
> +			/* Swap tabs to spaces due to some rendering issues. */
> +			if (format[i] == '\t')
> +				format[i] = ' ';
> +		}
> +	}
> +	snprintf(name, sizeof(name), "%s:%s", sys_name, evt_name);
> +	info.name = name;
> +	err = args->cb(args->state, &info);
> +	free(format);
> +	return err;
> +}
> +
> +static int for_each_event_sys_cb(void *state, const char *sys_name)
> +{
> +	return tp_pmu__for_each_tp_event(sys_name, state, for_each_event_cb);
> +}
> +
> +int tp_pmu__for_each_event(struct perf_pmu *pmu, void *state, pmu_event_callback cb)
> +{
> +	struct for_each_event_args args = {
> +		.state = state,
> +		.cb = cb,
> +		.pmu = pmu,
> +	};
> +
> +	return tp_pmu__for_each_tp_sys(&args, for_each_event_sys_cb);
> +}
> +
> +static int num_events_cb(void *state, const char *sys_name __maybe_unused,
> +			 const char *evt_name __maybe_unused)
> +{
> +	size_t *count = state;
> +
> +	(*count)++;
> +	return 0;
> +}
> +
> +static int num_events_sys_cb(void *state, const char *sys_name)
> +{
> +	return tp_pmu__for_each_tp_event(sys_name, state, num_events_cb);
> +}
> +
> +size_t tp_pmu__num_events(struct perf_pmu *pmu __maybe_unused)
> +{
> +	size_t count = 0;
> +
> +	tp_pmu__for_each_tp_sys(&count, num_events_sys_cb);
> +	return count;
> +}
> +
> +bool tp_pmu__have_event(struct perf_pmu *pmu __maybe_unused, const char *name)
> +{
> +	char *dup_name, *colon;
> +	int id;
> +
> +	if (strchr(name, ':') == NULL)
> +		return false;

Nit:

	colon = strchr(name, ':');
	if (colon == NULL)
		return false;

> +
> +	dup_name = strdup(name);
> +	if (!dup_name)
> +		return false;
> +
> +	colon = strchr(dup_name, ':');

	colon = dup_name + (colon - name);

> +	*colon = '\0';
> +	id = tp_pmu__id(dup_name, colon + 1);
> +	free(dup_name);
> +	return id >= 0;
> +}
> diff --git a/tools/perf/util/tp_pmu.h b/tools/perf/util/tp_pmu.h
> index 49537303bd73..30456bd6943d 100644
> --- a/tools/perf/util/tp_pmu.h
> +++ b/tools/perf/util/tp_pmu.h
> @@ -2,6 +2,8 @@
>  #ifndef __TP_PMU_H
>  #define __TP_PMU_H
>  
> +#include "pmu.h"
> +
>  typedef int (*tp_sys_callback)(void *state, const char *sys_name);
>  typedef int (*tp_event_callback)(void *state, const char *sys_name, const char *evt_name);
>  
> @@ -9,4 +11,9 @@ int tp_pmu__id(const char *sys, const char *name);
>  int tp_pmu__for_each_tp_event(const char *sys, void *state, tp_event_callback cb);
>  int tp_pmu__for_each_tp_sys(void *state, tp_sys_callback cb);
>  
> +bool perf_pmu__is_tracepoint(const struct perf_pmu *pmu);
> +int tp_pmu__for_each_event(struct perf_pmu *pmu, void *state, pmu_event_callback cb);
> +size_t tp_pmu__num_events(struct perf_pmu *pmu);
> +bool tp_pmu__have_event(struct perf_pmu *pmu, const char *name);
> +
>  #endif /* __TP_PMU_H */
> -- 
> 2.50.0.727.gbf7dc18ff4-goog
> 

^ permalink raw reply	[flat|nested] 41+ messages in thread

* Re: [PATCH v7 00/16] New perf ilist app
  2025-07-23 18:00   ` Namhyung Kim
  2025-07-23 18:15     ` Ian Rogers
@ 2025-07-23 19:08     ` Arnaldo Carvalho de Melo
  2025-07-23 19:11       ` Arnaldo Carvalho de Melo
  1 sibling, 1 reply; 41+ messages in thread
From: Arnaldo Carvalho de Melo @ 2025-07-23 19:08 UTC (permalink / raw)
  To: Namhyung Kim
  Cc: Ian Rogers, Peter Zijlstra, Ingo Molnar, Mark Rutland,
	Alexander Shishkin, Jiri Olsa, Adrian Hunter, Kan Liang,
	James Clark, Xu Yang, Masami Hiramatsu (Google), Collin Funk,
	Howard Chu, Weilin Wang, Andi Kleen, Dr. David Alan Gilbert,
	Thomas Richter, Tiezhu Yang, Gautam Menghani, Thomas Falcon,
	Chun-Tse Shao, linux-kernel, linux-perf-users

On Wed, Jul 23, 2025 at 11:00:18AM -0700, Namhyung Kim wrote:
> Hi Ian,
> 
> On Wed, Jul 23, 2025 at 08:32:33AM -0700, Ian Rogers wrote:
> > On Mon, Jul 14, 2025 at 9:44 AM Ian Rogers <irogers@google.com> wrote:
> > >
> > > This patch series builds up to the addition of a new ilist app written
> > > in python using textual [1] for the UI. The app presents perf PMUs and
> > > events, displays the event information as in `perf list` while at the
> > > bottom of the console showing recent activity of the event in total
> > > and across all CPUs. It also displays metrics, placed in a tree
> > > through their metric group, again with counts being displayed in the
> > > bottom panel.
> > >
> > > The first ground work patches of fixes, cleanup and refactoring were
> > > separated into their own series here:
> > > https://lore.kernel.org/lkml/20250709214029.1769089-1-irogers@google.com/
> > >
> > > The second part of the patches adds event json for the software PMU
> > > and makes the tracepoint PMU support iteration of events and the
> > > like. Without these improvements the tracepoint and software PMUs will
> > > appear to have no events in the ilist app. As the software PMU moves
> > > parsing to json, the legacy hard coded parsing is removed. This has
> > > proven controversial for hardware events and so that cleanup isn't
> > > done here.
> > >
> > > The final patches expand the perf python APIs and add the ilist
> > > command. To run it you need the updated perf.cpython.so in your
> > > PYTHONPATH and then execute the script. Expanding PMUs and then
> > > selecting events will cause event informatin to be displayed in the
> > > top-right and the counters values to be displayed as sparklines and
> > > counts in the bottom half of the screen.
> > >
> > > [1] https://textual.textualize.io/
> > >
> > > v7: Better handle errors in the python code and ignore errors when
> > >     scanning PMU/events in ilist.py, improving the behavior when not
> > >     root. Add a tp_pmu/python clean up. Minor kernel coding style
> > >     clean up. Fix behavior of ilist if a search result isn't found but
> > >     then next is chosen.
> > >
> > > v6: For metrics on hybrid systems don't purely match by name, also
> > >     match the CPU and thread so that if the same metric exists for
> > >     different PMUs the appropriate one is selected and counters may be
> > >     read. Likewise use evsel maps and not the evlists.
> > >
> > > v5: Split the series in two. Add metric support. Various clean ups and
> > >     tweaks to the app in particular around the handling of searches.
> > >
> > > v4: No conflict rebase. Picks up perf-tools-next DRM PMU which
> > >     displays as expected.
> > >
> > > v3: Add a search dialog to the ilist app with 'n'ext and 'p'revious
> > >     keys. No changes in the ground work first 14 patches.
> > >
> > > v2: In the jevents event description duplication, some minor changes
> > >     accidentally missed from v1 meaning that in v1 the descriptions
> > >     were still duplicated. Expand the cover letter with some thoughts
> > >     on the series.
> > >
> > > Ian Rogers (16):
> > >   perf python: Add more exceptions on error paths
> > >   perf jevents: Add common software event json
> > >   perf parse-events: Remove non-json software events
> > >   perf tp_pmu: Factor existing tracepoint logic to new file
> > >   perf tp_pmu: Add event APIs
> > >   perf list: Remove tracepoint printing code
> > >   perf list: Skip ABI PMUs when printing pmu values
> > >   perf python: Improve the tracepoint function if no libtraceevent
> > >   perf python: Add basic PMU abstraction and pmus sequence
> > >   perf python: Add function returning dictionary of all events on a PMU
> > >   perf ilist: Add new python ilist command
> > >   perf python: Add parse_metrics function
> > >   perf python: Add evlist metrics function
> > >   perf python: Add evlist compute_metric
> > >   perf python: Add metrics function
> > >   perf ilist: Add support for metrics
> > 
> > Hi,
> > 
> > Is there any more I can do to get this series landed? I appreciate having:
> > 
> > Tested-by: Gautam Menghani <gautam@linux.ibm.com>
> > 
> > I think there is some follow up for "make install" for scripts like
> > these, but I'm keen for the python API to move forward.
>  
> I'll review the series today so that we can get some part of it, at
> least.  Basically I think we need a wrapper script like perf-ilist to
> run this easily (maybe with documentation).

I just tried, with the series applied:

root@number:~# perf ilist
perf: 'ilist' is not a perf-command. See 'perf --help'.

Did you mean this?
	list
root@number:~#

Now trying to figure out why it is not running.

- Arnaldo

^ permalink raw reply	[flat|nested] 41+ messages in thread

* Re: [PATCH v7 00/16] New perf ilist app
  2025-07-23 19:08     ` Arnaldo Carvalho de Melo
@ 2025-07-23 19:11       ` Arnaldo Carvalho de Melo
  2025-07-23 19:24         ` Arnaldo Carvalho de Melo
  0 siblings, 1 reply; 41+ messages in thread
From: Arnaldo Carvalho de Melo @ 2025-07-23 19:11 UTC (permalink / raw)
  To: Namhyung Kim
  Cc: Ian Rogers, Peter Zijlstra, Ingo Molnar, Mark Rutland,
	Alexander Shishkin, Jiri Olsa, Adrian Hunter, Kan Liang,
	James Clark, Xu Yang, Masami Hiramatsu (Google), Collin Funk,
	Howard Chu, Weilin Wang, Andi Kleen, Dr. David Alan Gilbert,
	Thomas Richter, Tiezhu Yang, Gautam Menghani, Thomas Falcon,
	Chun-Tse Shao, linux-kernel, linux-perf-users

On Wed, Jul 23, 2025 at 04:08:55PM -0300, Arnaldo Carvalho de Melo wrote:
> On Wed, Jul 23, 2025 at 11:00:18AM -0700, Namhyung Kim wrote:
> > > I think there is some follow up for "make install" for scripts like
> > > these, but I'm keen for the python API to move forward.
> >  
> > I'll review the series today so that we can get some part of it, at
> > least.  Basically I think we need a wrapper script like perf-ilist to
> > run this easily (maybe with documentation).
> 
> I just tried, with the series applied:
> 
> root@number:~# perf ilist
> perf: 'ilist' is not a perf-command. See 'perf --help'.
> 
> Did you mean this?
> 	list
> root@number:~#
> 
> Now trying to figure out why it is not running.

So it is not wired up like 'perf archive', trying it directly:

root@number:~# ~acme/git/perf-tools-next/tools/perf/python/ilist.py 
Traceback (most recent call last):
  File "/home/acme/git/perf-tools-next/tools/perf/python/ilist.py", line 11, in <module>
    from textual import on
ModuleNotFoundError: No module named 'textual'
root@number:~#

I thought there was some discussion about catching this exception and
providing guidance, lemme try...

- Arnaldo

^ permalink raw reply	[flat|nested] 41+ messages in thread

* Re: [PATCH v7 00/16] New perf ilist app
  2025-07-23 19:11       ` Arnaldo Carvalho de Melo
@ 2025-07-23 19:24         ` Arnaldo Carvalho de Melo
  2025-07-23 21:30           ` Ian Rogers
  0 siblings, 1 reply; 41+ messages in thread
From: Arnaldo Carvalho de Melo @ 2025-07-23 19:24 UTC (permalink / raw)
  To: Ian Rogers
  Cc: Namhyung Kim, Peter Zijlstra, Ingo Molnar, Mark Rutland,
	Alexander Shishkin, Jiri Olsa, Adrian Hunter, Kan Liang,
	James Clark, Xu Yang, Masami Hiramatsu (Google), Collin Funk,
	Howard Chu, Weilin Wang, Andi Kleen, Dr. David Alan Gilbert,
	Thomas Richter, Tiezhu Yang, Gautam Menghani, Thomas Falcon,
	Chun-Tse Shao, linux-kernel, linux-perf-users

On Wed, Jul 23, 2025 at 04:11:13PM -0300, Arnaldo Carvalho de Melo wrote:
> On Wed, Jul 23, 2025 at 04:08:55PM -0300, Arnaldo Carvalho de Melo wrote:
> > On Wed, Jul 23, 2025 at 11:00:18AM -0700, Namhyung Kim wrote:
> > > > I think there is some follow up for "make install" for scripts like
> > > > these, but I'm keen for the python API to move forward.
  
> > > I'll review the series today so that we can get some part of it, at
> > > least.  Basically I think we need a wrapper script like perf-ilist to
> > > run this easily (maybe with documentation).
 
> > I just tried, with the series applied:
 
> > root@number:~# perf ilist
> > perf: 'ilist' is not a perf-command. See 'perf --help'.
 
> > Did you mean this?
> > 	list
> > root@number:~#
 
> > Now trying to figure out why it is not running.
 
> So it is not wired up like 'perf archive', trying it directly:
 
> root@number:~# ~acme/git/perf-tools-next/tools/perf/python/ilist.py 
> Traceback (most recent call last):
>   File "/home/acme/git/perf-tools-next/tools/perf/python/ilist.py", line 11, in <module>
>     from textual import on
> ModuleNotFoundError: No module named 'textual'
> root@number:~#
 
> I thought there was some discussion about catching this exception and
> providing guidance, lemme try...

root@number:~# sudo dnf install python-textual
Updating and loading repositories:
 google-chrome                                        100% |   6.1 KiB/s |   1.3 KiB |  00m00s
 Copr repo for PyCharm owned by phracek               100% |   2.0 KiB/s |   2.1 KiB |  00m01s
 RPM Fusion for Fedora 42 - Nonfree - NVIDIA Driver   100% |   2.6 KiB/s |   2.5 KiB |  00m01s
 RPM Fusion for Fedora 42 - Nonfree - Steam           100% |   5.8 KiB/s |   2.4 KiB |  00m00s
 google-chrome                                        100% |   7.2 KiB/s |   3.2 KiB |  00m00s
 Copr repo for PyCharm owned by phracek               100% |  15.7 KiB/s |   4.8 KiB |  00m00s
Repositories loaded.
Package                           Arch    Version         Repository     Size
Installing:
 python3-textual                  noarch  1.0.0-1.fc42    fedora      6.6 MiB
Installing dependencies:
 python3-linkify-it-py            noarch  2.0.3-4.fc42    fedora    110.4 KiB
 python3-markdown-it-py           noarch  3.0.0-8.fc42    fedora    496.3 KiB
 python3-markdown-it-py+linkify   noarch  3.0.0-8.fc42    fedora      9.0 KiB
 python3-markdown-it-py+plugins   noarch  3.0.0-8.fc42    fedora      9.0 KiB
 python3-mdit-py-plugins          noarch  0.4.2-2.fc42    fedora    289.4 KiB
 python3-mdurl                    noarch  0.1.2-9.fc42    fedora     41.4 KiB
 python3-platformdirs             noarch  4.2.2-4.fc42    fedora    162.0 KiB
 python3-pygments                 noarch  2.18.0-4.fc42   fedora     10.6 MiB
 python3-rich                     noarch  13.9.4-2.fc42   fedora      2.5 MiB
 python3-uc-micro-py              noarch  1.0.3-4.fc42    fedora     13.1 KiB

Transaction Summary:
 Installing:        11 packages

Total size of inbound packages is 5 MiB. Need to download 5 MiB.
After this operation, 21 MiB extra will be used (install 21 MiB, remove 0 B).
Is this ok [y/N]: y
<SNIP>
[13/13] Installing python3-textual-0:1.0.0-1.fc42.noarch                                                                         100% |  10.1 MiB/s |   6.8 MiB |  00m01s
Complete!
root@number:~# ~acme/git/perf-tools-next/tools/perf/python/ilist.py 
╭────────────────────────────────────────────────────────────────── Traceback (most recent call last) ──────────────────────────────────────────────────────────────────╮
│ /home/acme/git/perf-tools-next/tools/perf/python/ilist.py:470 in compose                                                                                              │
│                                                                                                                                                                       │
│   467 │   │   │   return tree                                                                                                                                         │
│   468 │   │                                                                                                                                                           │
│   469 │   │   yield Header(id="header")                                                                                                                               │
│ ❱ 470 │   │   yield Horizontal(Vertical(metric_event_tree(), id="events"),                                                                                            │
│   471 │   │   │   │   │   │    Vertical(Label("event name", id="event_name"),                                                                                         │
│   472 │   │   │   │   │   │   │   │     Static("description", markup=False, id="event_descript                                                                        │
│   473 │   │   │   │   │   │   │   │     ))                                                                                                                            │
│                                                                                                                                                                       │
│ ╭───────────────────────────────────────────────── locals ─────────────────────────────────────────────────╮                                                          │
│ │ self = IListApp(title='Interactive Perf List', classes={'-dark-mode'}, pseudo_classes={'dark', 'focus'}) │                                                          │
│ ╰──────────────────────────────────────────────────────────────────────────────────────────────────────────╯                                                          │
│                                                                                                                                                                       │
│ /home/acme/git/perf-tools-next/tools/perf/python/ilist.py:433 in metric_event_tree                                                                                    │
│                                                                                                                                                                       │
│   430 │   │   │   """Create tree of PMUs and metricgroups with events or metrics under."""     ╭─────────── locals ────────────╮                                      │
│   431 │   │   │   tree: Tree[TreeValue] = Tree("Root", id="root")                              │ pmus = TreeNode('PMUs', None) │                                      │
│   432 │   │   │   pmus = tree.root.add("PMUs")                                                 │ tree = Tree(id='root')        │                                      │
│ ❱ 433 │   │   │   for pmu in perf.pmus():                                                      ╰───────────────────────────────╯                                      │
│   434 │   │   │   │   pmu_name = pmu.name().lower()                                                                                                                   │
│   435 │   │   │   │   pmu_node = pmus.add(pmu_name)                                                                                                                   │
│   436 │   │   │   │   try:                                                                                                                                            │
╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯
AttributeError: module 'perf' has no attribute 'pmus'
root@number:~# 

Ok, that was with the 'python-perf3' rpm package on fedora 42, trying
with the new one...

root@number:~# export PYTHONPATH=/tmp/build/perf-tools-next/python
root@number:~# ~acme/git/perf-tools-next/tools/perf/python/ilist.py 

Cool stuff!

Lots of flashing lights! :-)

Interesting to quickly browse all those events, I like it.

I searched for "wakeup" and stumbled on ftrace:wakeup failures, but that
should be just a minor adjustment, some exception list:

root@number:~# ls -la /sys/kernel/tracing/events/ftrace/wakeup/
total 0
drwxr-xr-x. 1 root root 0 Jul 23 16:04 .
drwxr-xr-x. 1 root root 0 Jul 23 16:04 ..
-r--r-----. 1 root root 0 Jul 23 16:04 format
-r--r-----. 1 root root 0 Jul 23 16:19 hist
root@number:~# 
root@number:~# ls -la /sys/kernel/tracing/events/sched/sched_wakeup/
total 0
drwxr-xr-x. 1 root root 0 Jul 23 16:04 .
drwxr-xr-x. 1 root root 0 Jul 23 16:04 ..
-rw-r-----. 1 root root 0 Jul 23 16:19 enable
-rw-r-----. 1 root root 0 Jul 23 16:19 filter
-r--r-----. 1 root root 0 Jul 23 16:04 format
-r--r-----. 1 root root 0 Jul 23 16:19 hist
-r--r-----. 1 root root 0 Jul 23 16:04 id
-rw-r-----. 1 root root 0 Jul 23 16:19 trigger
root@number:~#

Do you know how to take text screen shots in textual?

Apart from the super minor nits, thanks for working on this:

Tested-by: Arnaldo Carvalho de Melo <acme@redhat.com>

- Arnaldo

^ permalink raw reply	[flat|nested] 41+ messages in thread

* Re: [PATCH v7 00/16] New perf ilist app
  2025-07-23 19:24         ` Arnaldo Carvalho de Melo
@ 2025-07-23 21:30           ` Ian Rogers
  0 siblings, 0 replies; 41+ messages in thread
From: Ian Rogers @ 2025-07-23 21:30 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: Namhyung Kim, Peter Zijlstra, Ingo Molnar, Mark Rutland,
	Alexander Shishkin, Jiri Olsa, Adrian Hunter, Kan Liang,
	James Clark, Xu Yang, Masami Hiramatsu (Google), Collin Funk,
	Howard Chu, Weilin Wang, Andi Kleen, Dr. David Alan Gilbert,
	Thomas Richter, Tiezhu Yang, Gautam Menghani, Thomas Falcon,
	Chun-Tse Shao, linux-kernel, linux-perf-users

On Wed, Jul 23, 2025 at 12:24 PM Arnaldo Carvalho de Melo
<acme@kernel.org> wrote:
>
> On Wed, Jul 23, 2025 at 04:11:13PM -0300, Arnaldo Carvalho de Melo wrote:
> > On Wed, Jul 23, 2025 at 04:08:55PM -0300, Arnaldo Carvalho de Melo wrote:
> > > On Wed, Jul 23, 2025 at 11:00:18AM -0700, Namhyung Kim wrote:
> > > > > I think there is some follow up for "make install" for scripts like
> > > > > these, but I'm keen for the python API to move forward.
>
> > > > I'll review the series today so that we can get some part of it, at
> > > > least.  Basically I think we need a wrapper script like perf-ilist to
> > > > run this easily (maybe with documentation).
>
> > > I just tried, with the series applied:
>
> > > root@number:~# perf ilist
> > > perf: 'ilist' is not a perf-command. See 'perf --help'.
>
> > > Did you mean this?
> > >     list
> > > root@number:~#
>
> > > Now trying to figure out why it is not running.
>
> > So it is not wired up like 'perf archive', trying it directly:
>
> > root@number:~# ~acme/git/perf-tools-next/tools/perf/python/ilist.py
> > Traceback (most recent call last):
> >   File "/home/acme/git/perf-tools-next/tools/perf/python/ilist.py", line 11, in <module>
> >     from textual import on
> > ModuleNotFoundError: No module named 'textual'
> > root@number:~#
>
> > I thought there was some discussion about catching this exception and
> > providing guidance, lemme try...
>
> root@number:~# sudo dnf install python-textual
> Updating and loading repositories:
>  google-chrome                                        100% |   6.1 KiB/s |   1.3 KiB |  00m00s
>  Copr repo for PyCharm owned by phracek               100% |   2.0 KiB/s |   2.1 KiB |  00m01s
>  RPM Fusion for Fedora 42 - Nonfree - NVIDIA Driver   100% |   2.6 KiB/s |   2.5 KiB |  00m01s
>  RPM Fusion for Fedora 42 - Nonfree - Steam           100% |   5.8 KiB/s |   2.4 KiB |  00m00s
>  google-chrome                                        100% |   7.2 KiB/s |   3.2 KiB |  00m00s
>  Copr repo for PyCharm owned by phracek               100% |  15.7 KiB/s |   4.8 KiB |  00m00s
> Repositories loaded.
> Package                           Arch    Version         Repository     Size
> Installing:
>  python3-textual                  noarch  1.0.0-1.fc42    fedora      6.6 MiB
> Installing dependencies:
>  python3-linkify-it-py            noarch  2.0.3-4.fc42    fedora    110.4 KiB
>  python3-markdown-it-py           noarch  3.0.0-8.fc42    fedora    496.3 KiB
>  python3-markdown-it-py+linkify   noarch  3.0.0-8.fc42    fedora      9.0 KiB
>  python3-markdown-it-py+plugins   noarch  3.0.0-8.fc42    fedora      9.0 KiB
>  python3-mdit-py-plugins          noarch  0.4.2-2.fc42    fedora    289.4 KiB
>  python3-mdurl                    noarch  0.1.2-9.fc42    fedora     41.4 KiB
>  python3-platformdirs             noarch  4.2.2-4.fc42    fedora    162.0 KiB
>  python3-pygments                 noarch  2.18.0-4.fc42   fedora     10.6 MiB
>  python3-rich                     noarch  13.9.4-2.fc42   fedora      2.5 MiB
>  python3-uc-micro-py              noarch  1.0.3-4.fc42    fedora     13.1 KiB
>
> Transaction Summary:
>  Installing:        11 packages
>
> Total size of inbound packages is 5 MiB. Need to download 5 MiB.
> After this operation, 21 MiB extra will be used (install 21 MiB, remove 0 B).
> Is this ok [y/N]: y
> <SNIP>
> [13/13] Installing python3-textual-0:1.0.0-1.fc42.noarch                                                                         100% |  10.1 MiB/s |   6.8 MiB |  00m01s
> Complete!
> root@number:~# ~acme/git/perf-tools-next/tools/perf/python/ilist.py
> ╭────────────────────────────────────────────────────────────────── Traceback (most recent call last) ──────────────────────────────────────────────────────────────────╮
> │ /home/acme/git/perf-tools-next/tools/perf/python/ilist.py:470 in compose                                                                                              │
> │                                                                                                                                                                       │
> │   467 │   │   │   return tree                                                                                                                                         │
> │   468 │   │                                                                                                                                                           │
> │   469 │   │   yield Header(id="header")                                                                                                                               │
> │ ❱ 470 │   │   yield Horizontal(Vertical(metric_event_tree(), id="events"),                                                                                            │
> │   471 │   │   │   │   │   │    Vertical(Label("event name", id="event_name"),                                                                                         │
> │   472 │   │   │   │   │   │   │   │     Static("description", markup=False, id="event_descript                                                                        │
> │   473 │   │   │   │   │   │   │   │     ))                                                                                                                            │
> │                                                                                                                                                                       │
> │ ╭───────────────────────────────────────────────── locals ─────────────────────────────────────────────────╮                                                          │
> │ │ self = IListApp(title='Interactive Perf List', classes={'-dark-mode'}, pseudo_classes={'dark', 'focus'}) │                                                          │
> │ ╰──────────────────────────────────────────────────────────────────────────────────────────────────────────╯                                                          │
> │                                                                                                                                                                       │
> │ /home/acme/git/perf-tools-next/tools/perf/python/ilist.py:433 in metric_event_tree                                                                                    │
> │                                                                                                                                                                       │
> │   430 │   │   │   """Create tree of PMUs and metricgroups with events or metrics under."""     ╭─────────── locals ────────────╮                                      │
> │   431 │   │   │   tree: Tree[TreeValue] = Tree("Root", id="root")                              │ pmus = TreeNode('PMUs', None) │                                      │
> │   432 │   │   │   pmus = tree.root.add("PMUs")                                                 │ tree = Tree(id='root')        │                                      │
> │ ❱ 433 │   │   │   for pmu in perf.pmus():                                                      ╰───────────────────────────────╯                                      │
> │   434 │   │   │   │   pmu_name = pmu.name().lower()                                                                                                                   │
> │   435 │   │   │   │   pmu_node = pmus.add(pmu_name)                                                                                                                   │
> │   436 │   │   │   │   try:                                                                                                                                            │
> ╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯
> AttributeError: module 'perf' has no attribute 'pmus'
> root@number:~#
>
> Ok, that was with the 'python-perf3' rpm package on fedora 42, trying
> with the new one...
>
> root@number:~# export PYTHONPATH=/tmp/build/perf-tools-next/python
> root@number:~# ~acme/git/perf-tools-next/tools/perf/python/ilist.py
>
> Cool stuff!
>
> Lots of flashing lights! :-)
>
> Interesting to quickly browse all those events, I like it.
>
> I searched for "wakeup" and stumbled on ftrace:wakeup failures, but that
> should be just a minor adjustment, some exception list:
>
> root@number:~# ls -la /sys/kernel/tracing/events/ftrace/wakeup/
> total 0
> drwxr-xr-x. 1 root root 0 Jul 23 16:04 .
> drwxr-xr-x. 1 root root 0 Jul 23 16:04 ..
> -r--r-----. 1 root root 0 Jul 23 16:04 format
> -r--r-----. 1 root root 0 Jul 23 16:19 hist
> root@number:~#
> root@number:~# ls -la /sys/kernel/tracing/events/sched/sched_wakeup/
> total 0
> drwxr-xr-x. 1 root root 0 Jul 23 16:04 .
> drwxr-xr-x. 1 root root 0 Jul 23 16:04 ..
> -rw-r-----. 1 root root 0 Jul 23 16:19 enable
> -rw-r-----. 1 root root 0 Jul 23 16:19 filter
> -r--r-----. 1 root root 0 Jul 23 16:04 format
> -r--r-----. 1 root root 0 Jul 23 16:19 hist
> -r--r-----. 1 root root 0 Jul 23 16:04 id
> -rw-r-----. 1 root root 0 Jul 23 16:19 trigger
> root@number:~#
>
> Do you know how to take text screen shots in textual?

So there's a built-in screen shot thing. Press ctrl+p to bring up the
inbuilt command palette, then select "Save screenshot" which will save
an SVG screenshot. It should be possible to force a lowly terminal and
then grab the characters, I tried but didn't get very far with it.
There are console recorder apps. My preference has just been to grab
regular screenshots and then cut out a PNG. Attaching any kind of
non-standard character or image to an LKML post I think would cause it
to be bounced. I've posted some images here:

ilist working first on events:
https://fosstodon.org/@irogers/114677152263351891
ilist metrics working on hybrid:
https://fosstodon.org/@irogers/114831660998075850
ilist running on WSL on AMD:
https://fosstodon.org/@irogers/114849910913098482

> Apart from the super minor nits, thanks for working on this:
>
> Tested-by: Arnaldo Carvalho de Melo <acme@redhat.com>

Thanks! I think there are still improvements to be had like improving
the layout of the screen, deduplicating PMUs, etc. nothing that can't
be incrementally added. Probably the biggest thing is what to do for
"make install" and packaging it [1]. I think it is a very nice way to
discover what perf can inform you about, and I think everyone I've
talked to prefers doing it with this app rather than trying to get the
same data from regular `perf list`. For example, I was surprised how
much data I could get from WSL.

Thanks,
Ian

[1] (some thoughts on packaging in reply to Namhyung)
https://lore.kernel.org/lkml/CAP-5=fX1j_MdzjqLTYeNGFTWLaQp8Dmbi093QN98b2pNgFcpBA@mail.gmail.com/

> - Arnaldo

^ permalink raw reply	[flat|nested] 41+ messages in thread

* Re: [PATCH v7 11/16] perf ilist: Add new python ilist command
  2025-07-23 18:33   ` Falcon, Thomas
@ 2025-07-23 21:33     ` Ian Rogers
  0 siblings, 0 replies; 41+ messages in thread
From: Ian Rogers @ 2025-07-23 21:33 UTC (permalink / raw)
  To: Falcon, Thomas
  Cc: alexander.shishkin@linux.intel.com, mhiramat@kernel.org,
	tmricht@linux.ibm.com, xu.yang_2@nxp.com, howardchu95@gmail.com,
	Hunter, Adrian, ak@linux.intel.com, mingo@redhat.com,
	gautam@linux.ibm.com, ctshao@google.com,
	linux-kernel@vger.kernel.org, james.clark@linaro.org,
	collin.funk1@gmail.com, mark.rutland@arm.com,
	peterz@infradead.org, linux@treblig.org, Wang, Weilin,
	yangtiezhu@loongson.cn, acme@kernel.org,
	linux-perf-users@vger.kernel.org, kan.liang@linux.intel.com,
	jolsa@kernel.org, namhyung@kernel.org

On Wed, Jul 23, 2025 at 11:33 AM Falcon, Thomas <thomas.falcon@intel.com> wrote:
>
> On Mon, 2025-07-14 at 09:43 -0700, Ian Rogers wrote:
> > The perf ilist command is a textual app [1] similar to perf list. In
> > the top-left pane a tree of PMUs is displayed. Selecting a PMU expands
> > the events within it. Selecting an event displays the `perf list`
> > style event information in the top-right pane.
> >
> > When an event is selected it is opened and the counters on each CPU
> > the event is for are periodically read. The bottom of the screen
> > contains a scrollable set of sparklines showing the events in total
> > and on each CPU. Scrolling below the sparklines shows the same data as
> > raw counts. The sparklines are small graphs where the height of the
> > bar is in relation to maximum of the other counts in the graph.
> >
> > By default the counts are read with an interval of 0.1 seconds (10
> > times per second). A -I/--interval command line option allows the
> > interval to be changed. The oldest read counts are dropped when the
> > counts fill the line causing the sparkline to move from right to left.
> >
> > A search box can be pulled up with the 's' key. 'n' and 'p' iterate
> > through the search results. As some PMUs have hundreds of events a 'c'
> > key will collapse the events in the current PMU to make navigating the
> > PMUs easier.
> >
> > [1] https://textual.textualize.io/
> >
> > Signed-off-by: Ian Rogers <irogers@google.com>
>
> Hi Ian, I hit a segfault playing around with the ilist search feature. I can recreate it pretty
> reliably by searching for something then holding down 'n' to quickly cycle through the results.
> After a few seconds, the program crashes.
>
> I've attached a backtrace from gdb below.

Thanks! I suspect that maybe you got the app to somehow read from an
event that wasn't opened or enabled or some such. I'll have a go at
reproducing.

Thanks,
Ian

> Thanks,
> Tom
>
> #0  __memset_avx2_unaligned_erms () at ../sysdeps/x86_64/multiarch/memset-vec-unaligned-erms.S:210
> #1  0x00007fffe88121a7 in perf_evsel__read (evsel=0x555557b16390, cpu_map_idx=8, thread=0,
> count=0x0) at evsel.c:403
> #2  0x00007fffe88cbf97 in evsel__read_one (evsel=0x555557b16390, cpu_map_idx=8, thread=0) at
> util/evsel.c:1719
> #3  0x00007fffe88cc794 in evsel__read_counter (evsel=0x555557b16390, cpu_map_idx=8, thread=0) at
> util/evsel.c:1896
> #4  0x00007fffe880c0a8 in prepare_metric (mexp=0x555555d25660, evsel=<optimized out>,
> pctx=0x5555579b5d00, cpu_idx=8, thread_idx=0)
>     at /home/tfalcon/perf-tools-next/tools/perf/util/python.c:1353
> #5  pyrf_evlist__compute_metric (pevlist=<optimized out>, args=<optimized out>, kwargs=<optimized
> out>) at /home/tfalcon/perf-tools-next/tools/perf/util/python.c:1428
> #6  0x00007ffff7978655 in method_vectorcall_VARARGS_KEYWORDS (func=<optimized out>,
> args=0x7ffff7fb1680, nargsf=<optimized out>, kwnames=<optimized out>)
>     at /usr/src/debug/python3.13-3.13.5-1.fc41.x86_64/Objects/descrobject.c:358
> #7  0x00007ffff793f337 in _PyObject_VectorcallTstate (tstate=0x7ffff7d599d0 <_PyRuntime+283024>,
> callable=0x7fffe94f3dd0, args=<optimized out>, nargsf=<optimized out>,
>     kwnames=<optimized out>) at /usr/src/debug/python3.13-3.13.5-
> 1.fc41.x86_64/Include/internal/pycore_call.h:168
> #8  PyObject_Vectorcall (callable=0x7fffe94f3dd0, args=<optimized out>, nargsf=<optimized out>,
> kwnames=<optimized out>)
>     at /usr/src/debug/python3.13-3.13.5-1.fc41.x86_64/Objects/call.c:327
> #9  0x00007ffff794f1c1 in _PyEval_EvalFrameDefault (tstate=<optimized out>, frame=<optimized out>,
> throwflag=<optimized out>)
>     at /usr/src/debug/python3.13-3.13.5-1.fc41.x86_64/Python/generated_cases.c.h:1843
> #10 0x00007ffff79ab59f in _PyEval_EvalFrame (tstate=0x7ffff7d599d0 <_PyRuntime+283024>,
> frame=<optimized out>, throwflag=0)
>     at /usr/src/debug/python3.13-3.13.5-1.fc41.x86_64/Include/internal/pycore_ceval.h:119
> #11 _PyEval_Vector (tstate=0x7ffff7d599d0 <_PyRuntime+283024>, func=0x7fffdde34400, locals=0x0,
> args=0x7fffffffc9a8, argcount=1, kwnames=0x0)
>     at /usr/src/debug/python3.13-3.13.5-1.fc41.x86_64/Python/ceval.c:1816
> #12 _PyFunction_Vectorcall (func=0x7fffdde34400, stack=0x7fffffffc9a8, nargsf=1, kwnames=0x0) at
> /usr/src/debug/python3.13-3.13.5-1.fc41.x86_64/Objects/call.c:413
> #13 _PyObject_VectorcallTstate (tstate=0x7ffff7d599d0 <_PyRuntime+283024>, callable=0x7fffdde34400,
> args=0x7fffffffc9a8, nargsf=1, kwnames=0x0)
>     at /usr/src/debug/python3.13-3.13.5-1.fc41.x86_64/Include/internal/pycore_call.h:168
> #14 method_vectorcall (method=<optimized out>, args=0x7ffff7d2a140 <_PyRuntime+88320>,
> nargsf=<optimized out>, kwnames=<optimized out>)
>     at /usr/src/debug/python3.13-3.13.5-1.fc41.x86_64/Objects/classobject.c:70
> #15 0x00007ffff795369d in PyObject_Call (callable=0x7fffcfc978c0, args=0x7ffff7d2a128
> <_PyRuntime+88296>, kwargs=0x0)
>     at /usr/src/debug/python3.13-3.13.5-1.fc41.x86_64/Objects/call.c:373
> #16 PyCFunction_Call (callable=0x7fffcfc978c0, args=0x7ffff7d2a128 <_PyRuntime+88296>, kwargs=0x0)
> at /usr/src/debug/python3.13-3.13.5-1.fc41.x86_64/Objects/call.c:381
> #17 _PyEval_EvalFrameDefault (tstate=<optimized out>, frame=<optimized out>, throwflag=<optimized
> out>)
>     at /usr/src/debug/python3.13-3.13.5-1.fc41.x86_64/Python/generated_cases.c.h:1355
> #18 0x00007ffff7a3a861 in _PyEval_EvalFrame (tstate=0x7ffff7d599d0 <_PyRuntime+283024>,
> frame=<optimized out>, throwflag=0)
>     at /usr/src/debug/python3.13-3.13.5-1.fc41.x86_64/Include/internal/pycore_ceval.h:119
> #19 gen_send_ex2 (gen=0x7fffdccfcba0, arg=0x7ffff7d0bd30 <_Py_NoneStruct>, presult=0x7fffffffcc68,
> exc=0, closing=<optimized out>)
>     at /usr/src/debug/python3.13-3.13.5-1.fc41.x86_64/Objects/genobject.c:229
> #20 0x00007fffde564149 in task_step_impl (state=state@entry=0x7fffde89dfd0,
> task=task@entry=0x7fffdcd443c0, exc=exc@entry=0x0)
>     at /usr/src/debug/python3.13-3.13.5-1.fc41.x86_64/Modules/_asynciomodule.c:2782
> #21 0x00007fffde5657a5 in task_step (state=0x7fffde89dfd0, task=0x7fffdcd443c0, exc=0x0) at
> /usr/src/debug/python3.13-3.13.5-1.fc41.x86_64/Modules/_asynciomodule.c:3101
> #22 0x00007ffff79700a7 in cfunction_vectorcall_O (func=0x7fffcc0b1ad0, args=0x7fffcc37e860,
> nargsf=<optimized out>, kwnames=<optimized out>)
>     at /usr/src/debug/python3.13-3.13.5-1.fc41.x86_64/Include/cpython/methodobject.h:50
> #23 0x00007ffff7ad6a3f in _PyObject_VectorcallTstate (tstate=0x7ffff7d599d0 <_PyRuntime+283024>,
> callable=0x7fffcc0b1ad0, args=<optimized out>, nargsf=<optimized out>,
>     kwnames=<optimized out>) at /usr/src/debug/python3.13-3.13.5-
> 1.fc41.x86_64/Include/internal/pycore_call.h:168
> #24 0x00007ffff78ef15b in context_run (self=0x7fffddf2a440, args=0x7fffcc37e858, nargs=2,
> kwnames=0x0)
>     at /usr/src/debug/python3.13-3.13.5-1.fc41.x86_64/Python/context.c:664
> #25 0x00007ffff7969b4b in cfunction_vectorcall_FASTCALL_KEYWORDS (func=<optimized out>,
> args=0x7fffcc37e858, nargsf=<optimized out>, kwnames=<optimized out>)
>     at /usr/src/debug/python3.13-3.13.5-1.fc41.x86_64/Objects/methodobject.c:441
> #26 0x00007ffff795369d in PyObject_Call (callable=0x7fffcdff8950, args=0x7fffcc37e840, kwargs=0x0)
> at /usr/src/debug/python3.13-3.13.5-1.fc41.x86_64/Objects/call.c:373
> #27 PyCFunction_Call (callable=0x7fffcdff8950, args=0x7fffcc37e840, kwargs=0x0) at
> /usr/src/debug/python3.13-3.13.5-1.fc41.x86_64/Objects/call.c:381
> #28 _PyEval_EvalFrameDefault (tstate=<optimized out>, frame=<optimized out>, throwflag=<optimized
> out>)
>     at /usr/src/debug/python3.13-3.13.5-1.fc41.x86_64/Python/generated_cases.c.h:1355
> #29 0x00007ffff7a25fcb in PyEval_EvalCode (co=0x5555555d9a90, globals=<optimized out>,
> locals=0x7fffe9634c80)
>     at /usr/src/debug/python3.13-3.13.5-1.fc41.x86_64/Python/ceval.c:604
> #30 0x00007ffff7a640c3 in run_eval_code_obj (tstate=tstate@entry=0x7ffff7d599d0 <_PyRuntime+283024>,
> co=co@entry=0x5555555d9a90, globals=globals@entry=0x7fffe9634c80,
>     locals=locals@entry=0x7fffe9634c80) at /usr/src/debug/python3.13-3.13.5-
> 1.fc41.x86_64/Python/pythonrun.c:1381
> #31 0x00007ffff7a615f3 in run_mod (mod=mod@entry=0x555555710ec8,
> filename=filename@entry=0x7fffe96568e0, globals=globals@entry=0x7fffe9634c80,
>     locals=locals@entry=0x7fffe9634c80, flags=flags@entry=0x7fffffffd298,
> arena=arena@entry=0x7fffe971bdb0, interactive_src=0x0, generate_new_source=0)
>     at /usr/src/debug/python3.13-3.13.5-1.fc41.x86_64/Python/pythonrun.c:1466
> #32 0x00007ffff7a5dfd6 in pyrun_file (fp=fp@entry=0x5555555703a0,
> filename=filename@entry=0x7fffe96568e0, start=start@entry=257, globals=globals@entry=0x7fffe9634c80,
>     locals=locals@entry=0x7fffe9634c80, closeit=closeit@entry=1, flags=0x7fffffffd298) at
> /usr/src/debug/python3.13-3.13.5-1.fc41.x86_64/Python/pythonrun.c:1295
> #33 0x00007ffff7a5dc4f in _PyRun_SimpleFileObject (fp=fp@entry=0x5555555703a0,
> filename=filename@entry=0x7fffe96568e0, closeit=closeit@entry=1,
>     flags=flags@entry=0x7fffffffd298) at /usr/src/debug/python3.13-3.13.5-
> 1.fc41.x86_64/Python/pythonrun.c:517
> #34 0x00007ffff7a5d881 in _PyRun_AnyFileObject (fp=fp@entry=0x5555555703a0,
> filename=filename@entry=0x7fffe96568e0, closeit=closeit@entry=1,
>     flags=flags@entry=0x7fffffffd298) at /usr/src/debug/python3.13-3.13.5-
> 1.fc41.x86_64/Python/pythonrun.c:77
> #35 0x00007ffff7a5beda in pymain_run_file_obj (program_name=0x7fffe9634db0, filename=0x7fffe96568e0,
> skip_source_first_line=0)
>     at /usr/src/debug/python3.13-3.13.5-1.fc41.x86_64/Modules/main.c:410
> #36 pymain_run_file (config=0x7ffff7d2c0c8 <_PyRuntime+96392>) at /usr/src/debug/python3.13-3.13.5-
> 1.fc41.x86_64/Modules/main.c:429
> #37 pymain_run_python (exitcode=0x7fffffffd28c) at /usr/src/debug/python3.13-3.13.5-
> 1.fc41.x86_64/Modules/main.c:696
> #38 Py_RunMain () at /usr/src/debug/python3.13-3.13.5-1.fc41.x86_64/Modules/main.c:775
> #39 0x00007ffff7a1396c in Py_BytesMain (argc=<optimized out>, argv=<optimized out>) at
> /usr/src/debug/python3.13-3.13.5-1.fc41.x86_64/Modules/main.c:829
> #40 0x00007ffff760f488 in __libc_start_call_main (main=main@entry=0x555555555160 <main>,
> argc=argc@entry=2, argv=argv@entry=0x7fffffffd4f8)
>     at ../sysdeps/nptl/libc_start_call_main.h:58
> #41 0x00007ffff760f54b in __libc_start_main_impl (main=0x555555555160 <main>, argc=2,
> argv=0x7fffffffd4f8, init=<optimized out>, fini=<optimized out>,
>     rtld_fini=<optimized out>, stack_end=0x7fffffffd4e8) at ../csu/libc-start.c:360
> #42 0x0000555555555095 in _start ()
>
>
> > ---
> >  tools/perf/python/ilist.py | 392 +++++++++++++++++++++++++++++++++++++
> >  1 file changed, 392 insertions(+)
> >  create mode 100755 tools/perf/python/ilist.py
> >
> > diff --git a/tools/perf/python/ilist.py b/tools/perf/python/ilist.py
> > new file mode 100755
> > index 000000000000..b21f4c93247e
> > --- /dev/null
> > +++ b/tools/perf/python/ilist.py
> > @@ -0,0 +1,392 @@
> > +#!/usr/bin/env python3
> > +# SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause)
> > +"""Interactive perf list."""
> > +
> > +import argparse
> > +from typing import Any, Dict, Tuple
> > +import perf
> > +from textual import on
> > +from textual.app import App, ComposeResult
> > +from textual.binding import Binding
> > +from textual.containers import Horizontal, HorizontalGroup, Vertical, VerticalScroll
> > +from textual.command import SearchIcon
> > +from textual.screen import ModalScreen
> > +from textual.widgets import Button, Footer, Header, Input, Label, Sparkline, Static, Tree
> > +from textual.widgets.tree import TreeNode
> > +
> > +class ErrorScreen(ModalScreen[bool]):
> > +    """Pop up dialog for errors."""
> > +
> > +    CSS="""
> > +    ErrorScreen {
> > +        align: center middle;
> > +    }
> > +    """
> > +    def __init__(self, error: str):
> > +        self.error = error
> > +        super().__init__()
> > +
> > +    def compose(self) -> ComposeResult:
> > +        yield Button(f"Error: {self.error}", variant="primary", id="error")
> > +
> > +    def on_button_pressed(self, event: Button.Pressed) -> None:
> > +        self.dismiss(True)
> > +
> > +
> > +class SearchScreen(ModalScreen[str]):
> > +    """Pop up dialog for search."""
> > +
> > +    CSS="""
> > +    SearchScreen Horizontal {
> > +        align: center middle;
> > +        margin-top: 1;
> > +    }
> > +    SearchScreen Input {
> > +        width: 1fr;
> > +    }
> > +    """
> > +    def compose(self) -> ComposeResult:
> > +        yield Horizontal(SearchIcon(), Input(placeholder="Event name"))
> > +
> > +    def on_input_submitted(self, event: Input.Submitted) -> None:
> > +        """Handle the user pressing Enter in the input field."""
> > +        self.dismiss(event.value)
> > +
> > +
> > +class Counter(HorizontalGroup):
> > +    """Two labels for a CPU and its counter value."""
> > +
> > +    CSS="""
> > +    Label {
> > +        gutter: 1;
> > +    }
> > +    """
> > +
> > +    def __init__(self, cpu: int) -> None:
> > +        self.cpu = cpu
> > +        super().__init__()
> > +
> > +    def compose(self) -> ComposeResult:
> > +        label = f"cpu{self.cpu}" if self.cpu >= 0 else "total"
> > +        yield Label(label + " ")
> > +        yield Label("0", id=f"counter_{label}")
> > +
> > +
> > +class CounterSparkline(HorizontalGroup):
> > +    """A Sparkline for a performance counter."""
> > +
> > +    def __init__(self, cpu: int) -> None:
> > +        self.cpu = cpu
> > +        super().__init__()
> > +
> > +    def compose(self) -> ComposeResult:
> > +        label = f"cpu{self.cpu}" if self.cpu >= 0 else "total"
> > +        yield Label(label)
> > +        yield Sparkline([], summary_function=max, id=f"sparkline_{label}")
> > +
> > +
> > +class IListApp(App):
> > +    TITLE = "Interactive Perf List"
> > +
> > +    BINDINGS = [
> > +        Binding(key="s", action="search", description="Search",
> > +                tooltip="Search events and PMUs"),
> > +        Binding(key="n", action="next", description="Next",
> > +                tooltip="Next search result or item"),
> > +        Binding(key="p", action="prev", description="Previous",
> > +                tooltip="Previous search result or item"),
> > +        Binding(key="c", action="collapse", description="Collapse",
> > +                tooltip="Collapse the current PMU"),
> > +        Binding(key="^q", action="quit", description="Quit",
> > +                tooltip="Quit the app"),
> > +    ]
> > +
> > +    CSS = """
> > +        /* Make the 'total' sparkline a different color. */
> > +        #sparkline_total > .sparkline--min-color {
> > +            color: $accent;
> > +        }
> > +        #sparkline_total > .sparkline--max-color {
> > +            color: $accent 30%;
> > +        }
> > +        /*
> > +         * Make the active_search initially not displayed with the text in
> > +         * the middle of the line.
> > +         */
> > +        #active_search {
> > +            display: none;
> > +            width: 100%;
> > +            text-align: center;
> > +        }
> > +    """
> > +
> > +    def __init__(self, interval: float) -> None:
> > +        self.interval = interval
> > +        self.evlist = None
> > +        self.search_results: list[TreeNode[str]] = []
> > +        self.cur_search_result: TreeNode[str] | None = None
> > +        super().__init__()
> > +
> > +
> > +
> > +    def expand_and_select(self, node: TreeNode[Any]) -> None:
> > +        """Expand select a node in the tree."""
> > +        if node.parent:
> > +            node.parent.expand()
> > +            if node.parent.parent:
> > +                node.parent.parent.expand()
> > +        node.expand()
> > +        node.tree.select_node(node)
> > +        node.tree.scroll_to_node(node)
> > +
> > +
> > +    def set_searched_tree_node(self, previous: bool) -> None:
> > +        """Set the cur_search_result node to either the next or previous."""
> > +        l = len(self.search_results)
> > +
> > +        if l < 1:
> > +            tree: Tree[str] = self.query_one("#pmus", Tree)
> > +            if previous:
> > +                tree.action_cursor_up()
> > +            else:
> > +                tree.action_cursor_down()
> > +            return
> > +
> > +        if self.cur_search_result:
> > +            idx = self.search_results.index(self.cur_search_result)
> > +            if previous:
> > +                idx = idx - 1 if idx > 0 else l - 1
> > +            else:
> > +                idx = idx + 1 if idx < l - 1 else 0
> > +        else:
> > +            idx = l - 1 if previous else 0
> > +
> > +        node = self.search_results[idx]
> > +        if node == self.cur_search_result:
> > +            return
> > +
> > +        self.cur_search_result = node
> > +        self.expand_and_select(node)
> > +
> > +    def action_search(self) -> None:
> > +        """Search was chosen."""
> > +        def set_initial_focus(event: str | None) -> None:
> > +            """Sets the focus after the SearchScreen is dismissed."""
> > +
> > +            search_label = self.query_one("#active_search", Label)
> > +            search_label.display = True if event else False
> > +            if not event:
> > +                return
> > +            event = event.lower()
> > +            search_label.update(f'Searching for events matching "{event}"')
> > +
> > +            tree: Tree[str] = self.query_one("#pmus", Tree)
> > +            def find_search_results(event: str, node: TreeNode[str], \
> > +                                    cursor_seen: bool = False, \
> > +                                    match_after_cursor: TreeNode[str] | None = None) \
> > +                    -> Tuple[bool, TreeNode[str] | None]:
> > +                """Find nodes that match the search remembering the one after the cursor."""
> > +                if not cursor_seen and node == tree.cursor_node:
> > +                    cursor_seen = True
> > +                if node.data and event in node.data:
> > +                    if cursor_seen and not match_after_cursor:
> > +                        match_after_cursor = node
> > +                    self.search_results.append(node)
> > +
> > +                if node.children:
> > +                    for child in node.children:
> > +                        (cursor_seen, match_after_cursor) = \
> > +                            find_search_results(event, child, cursor_seen, match_after_cursor)
> > +                return (cursor_seen, match_after_cursor)
> > +
> > +            self.search_results.clear()
> > +            (_ , self.cur_search_result) = find_search_results(event, tree.root)
> > +            if len(self.search_results) < 1:
> > +                self.push_screen(ErrorScreen(f"Failed to find pmu/event {event}"))
> > +                search_label.display = False
> > +            elif self.cur_search_result:
> > +                self.expand_and_select(self.cur_search_result)
> > +            else:
> > +                self.set_searched_tree_node(previous=False)
> > +
> > +        self.push_screen(SearchScreen(), set_initial_focus)
> > +
> > +
> > +    def action_next(self) -> None:
> > +        """Next was chosen."""
> > +        self.set_searched_tree_node(previous=False)
> > +
> > +
> > +    def action_prev(self) -> None:
> > +        """Previous was chosen."""
> > +        self.set_searched_tree_node(previous=True)
> > +
> > +
> > +    def action_collapse(self) -> None:
> > +        """Collapse the potentially large number of events under a PMU."""
> > +        tree: Tree[str] = self.query_one("#pmus", Tree)
> > +        node = tree.cursor_node
> > +        if node and node.parent and node.parent.parent:
> > +            node.parent.collapse_all()
> > +            node.tree.scroll_to_node(node.parent)
> > +
> > +
> > +    def update_counts(self) -> None:
> > +        """Called every interval to update counts."""
> > +        if not self.evlist:
> > +            return
> > +
> > +        def update_count(cpu: int, count: int):
> > +            # Update the raw count display.
> > +            counter: Label = self.query(f"#counter_cpu{cpu}" if cpu >= 0 else "#counter_total")
> > +            if not counter:
> > +                return
> > +            counter = counter.first(Label)
> > +            counter.update(str(count))
> > +
> > +            # Update the sparkline.
> > +            line: Sparkline = self.query(f"#sparkline_cpu{cpu}" if cpu >= 0 else "#sparkline_total")
> > +            if not line:
> > +                return
> > +            line = line.first(Sparkline)
> > +            # If there are more events than the width, remove the front event.
> > +            if len(line.data) > line.size.width:
> > +                line.data.pop(0)
> > +            line.data.append(count)
> > +            line.mutate_reactive(Sparkline.data)
> > +
> > +        # Update the total and each CPU counts, assume there's just 1 evsel.
> > +        total = 0
> > +        self.evlist.disable()
> > +        for evsel in self.evlist:
> > +            for cpu in evsel.cpus():
> > +                aggr = 0
> > +                for thread in evsel.threads():
> > +                    counts = evsel.read(cpu, thread)
> > +                    aggr += counts.val
> > +                update_count(cpu, aggr)
> > +                total += aggr
> > +        update_count(-1, total)
> > +        self.evlist.enable()
> > +
> > +
> > +    def on_mount(self) -> None:
> > +        """When App starts set up periodic event updating."""
> > +        self.update_counts()
> > +        self.set_interval(self.interval, self.update_counts)
> > +
> > +
> > +    def set_pmu_and_event(self, pmu: str, event: str) -> None:
> > +        """Updates the event/description and starts the counters."""
> > +        # Remove previous event information.
> > +        if self.evlist:
> > +            self.evlist.disable()
> > +            self.evlist.close()
> > +            lines = self.query(CounterSparkline)
> > +            for line in lines:
> > +                line.remove()
> > +            lines = self.query(Counter)
> > +            for line in lines:
> > +                line.remove()
> > +
> > +        def pmu_event_description(pmu: str, event: str) -> str:
> > +            """Find and format event description for {pmu}/{event}/."""
> > +            def get_info(info: Dict[str, str], key: str):
> > +                return (info[key] + "\n") if key in info else ""
> > +
> > +            for p in perf.pmus():
> > +                if p.name() != pmu:
> > +                    continue
> > +                for info in p.events():
> > +                    if "name" not in info or info["name"] != event:
> > +                        continue
> > +
> > +                    desc = get_info(info, "topic")
> > +                    desc += get_info(info, "event_type_desc")
> > +                    desc += get_info(info, "desc")
> > +                    desc += get_info(info, "long_desc")
> > +                    desc += get_info(info, "encoding_desc")
> > +                    return desc
> > +            return "description"
> > +
> > +        # Parse event, update event text and description.
> > +        full_name = event if event.startswith(pmu) or ':' in event else f"{pmu}/{event}/"
> > +        self.query_one("#event_name", Label).update(full_name)
> > +        self.query_one("#event_description", Static).update(pmu_event_description(pmu, event))
> > +
> > +        # Open the event.
> > +        try:
> > +            self.evlist = perf.parse_events(full_name)
> > +            if self.evlist:
> > +                self.evlist.open()
> > +                self.evlist.enable()
> > +        except:
> > +            self.evlist = None
> > +
> > +        if not self.evlist:
> > +            self.push_screen(ErrorScreen(f"Failed to open {full_name}"))
> > +            return
> > +
> > +        # Add spark lines for all the CPUs. Note, must be done after
> > +        # open so that the evlist CPUs have been computed by propagate
> > +        # maps.
> > +        lines = self.query_one("#lines")
> > +        line = CounterSparkline(cpu=-1)
> > +        lines.mount(line)
> > +        for cpu in self.evlist.all_cpus():
> > +            line = CounterSparkline(cpu)
> > +            lines.mount(line)
> > +        line = Counter(cpu=-1)
> > +        lines.mount(line)
> > +        for cpu in self.evlist.all_cpus():
> > +            line = Counter(cpu)
> > +            lines.mount(line)
> > +
> > +
> > +    def compose(self) -> ComposeResult:
> > +        """Draws the app."""
> > +        def pmu_event_tree() -> Tree:
> > +            """Create tree of PMUs with events under."""
> > +            tree: Tree[str] = Tree("PMUs", id="pmus")
> > +            tree.root.expand()
> > +            for pmu in perf.pmus():
> > +                pmu_name = pmu.name().lower()
> > +                pmu_node = tree.root.add(pmu_name, data=pmu_name)
> > +                try:
> > +                    for event in sorted(pmu.events(), key=lambda x: x["name"]):
> > +                        if "name" in event:
> > +                            e = event["name"].lower()
> > +                            if "alias" in event:
> > +                                pmu_node.add_leaf(f'{e} ({event["alias"]})', data=e)
> > +                            else:
> > +                                pmu_node.add_leaf(e, data=e)
> > +                except:
> > +                    # Reading events may fail with EPERM, ignore.
> > +                    pass
> > +            return tree
> > +
> > +        yield Header(id="header")
> > +        yield Horizontal(Vertical(pmu_event_tree(), id="events"),
> > +                         Vertical(Label("event name", id="event_name"),
> > +                                  Static("description", markup=False, id="event_description"),
> > +                                  ))
> > +        yield Label(id="active_search")
> > +        yield VerticalScroll(id="lines")
> > +        yield Footer(id="footer")
> > +
> > +
> > +    @on(Tree.NodeSelected)
> > +    def on_tree_node_selected(self, event: Tree.NodeSelected[str]) -> None:
> > +        """Called when a tree node is selected, selecting the event."""
> > +        if event.node.parent and event.node.parent.parent:
> > +            assert event.node.parent.data is not None
> > +            assert event.node.data is not None
> > +            self.set_pmu_and_event(event.node.parent.data, event.node.data)
> > +
> > +
> > +if __name__ == "__main__":
> > +    ap = argparse.ArgumentParser()
> > +    ap.add_argument('-I', '--interval', help="Counter update interval in seconds", default=0.1)
> > +    args = ap.parse_args()
> > +    app = IListApp(float(args.interval))
> > +    app.run()
>

^ permalink raw reply	[flat|nested] 41+ messages in thread

* Re: [PATCH v7 01/16] perf python: Add more exceptions on error paths
  2025-07-23 18:21     ` Ian Rogers
@ 2025-07-23 22:24       ` Ian Rogers
  0 siblings, 0 replies; 41+ messages in thread
From: Ian Rogers @ 2025-07-23 22:24 UTC (permalink / raw)
  To: Namhyung Kim
  Cc: Peter Zijlstra, Ingo Molnar, Arnaldo Carvalho de Melo,
	Mark Rutland, Alexander Shishkin, Jiri Olsa, Adrian Hunter,
	Kan Liang, James Clark, Xu Yang, Masami Hiramatsu (Google),
	Collin Funk, Howard Chu, Weilin Wang, Andi Kleen,
	Dr. David Alan Gilbert, Thomas Richter, Tiezhu Yang,
	Gautam Menghani, Thomas Falcon, Chun-Tse Shao, linux-kernel,
	linux-perf-users

On Wed, Jul 23, 2025 at 11:21 AM Ian Rogers <irogers@google.com> wrote:
>
> On Wed, Jul 23, 2025 at 11:13 AM Namhyung Kim <namhyung@kernel.org> wrote:
> >
> > On Mon, Jul 14, 2025 at 09:43:49AM -0700, Ian Rogers wrote:
> > > Returning NULL will cause the python interpreter to fail but not
> > > report an error. If none wants to be returned then Py_None needs
> > > returning. Set the error for the cases returning NULL so that more
> > > meaningful interpreter behavior is had.
> >
> > It looks like you are adding error messages for the failure cases, not
> > adding new exceptions, right?  IIUC returning NULL in pyrf_event__new()
> > ends up having PyErr_NoMemory().  Then now it has different messages?
>
> This change doesn't alter the exception if there already is one. There
> are lots of cases where NULL is being returned for an error but that
> causes the python interpreter to fail/crash. This patch is just adding
> the exceptions and still returning NULL, previously set exceptions are
> left alone. With the exceptions returned the python interpreter does
> something more useful than fail/crash :-)
>
> > >
> > > Signed-off-by: Ian Rogers <irogers@google.com>
> > > ---
> > >  tools/perf/util/python.c | 14 +++++++++++---
> > >  1 file changed, 11 insertions(+), 3 deletions(-)
> > >
> > > diff --git a/tools/perf/util/python.c b/tools/perf/util/python.c
> > > index 2f28f71325a8..02544387f39d 100644
> > > --- a/tools/perf/util/python.c
> > > +++ b/tools/perf/util/python.c
> > > @@ -475,13 +475,19 @@ static PyObject *pyrf_event__new(const union perf_event *event)
> > >       if ((event->header.type < PERF_RECORD_MMAP ||
> > >            event->header.type > PERF_RECORD_SAMPLE) &&
> > >           !(event->header.type == PERF_RECORD_SWITCH ||
> > > -           event->header.type == PERF_RECORD_SWITCH_CPU_WIDE))
> > > +           event->header.type == PERF_RECORD_SWITCH_CPU_WIDE)){
> > > +             PyErr_Format(PyExc_TypeError, "Unexpected header type %u",
> > > +                          event->header.type);
> > >               return NULL;
> > > +     }
> > >
> > >       // FIXME this better be dynamic or we need to parse everything
> > >       // before calling perf_mmap__consume(), including tracepoint fields.
> > > -     if (sizeof(pevent->event) < event->header.size)
> > > +     if (sizeof(pevent->event) < event->header.size) {
> > > +             PyErr_Format(PyExc_TypeError, "Unexpected event version: %zd < %u",
> >
> > Maybe "Unexpected event size" instead?
>
> I think size is more accurate to the code, version is more useful to
> the user. I believe there is existing use of the event size being used
> as a quasi version number, so I think this description is consistent.
> If you feel strongly I can change it.

Actually I was thinking of the attribute size, let me fix this.

Thanks,
Ian

> Thanks,
> Ian
>
> > Thanks,
> > Namhyung
> >
> >
> > > +                          sizeof(pevent->event), event->header.size);
> > >               return NULL;
> > > +     }
> > >
> > >       ptype = pyrf_event__type[event->header.type];
> > >       pevent = PyObject_New(struct pyrf_event, ptype);
> > > @@ -1199,8 +1205,10 @@ static PyObject *pyrf_evlist__read_on_cpu(struct pyrf_evlist *pevlist,
> > >               return NULL;
> > >
> > >       md = get_md(evlist, cpu);
> > > -     if (!md)
> > > +     if (!md) {
> > > +             PyErr_Format(PyExc_TypeError, "Unknown CPU '%d'", cpu);
> > >               return NULL;
> > > +     }
> > >
> > >       if (perf_mmap__read_init(&md->core) < 0)
> > >               goto end;
> > > --
> > > 2.50.0.727.gbf7dc18ff4-goog
> > >

^ permalink raw reply	[flat|nested] 41+ messages in thread

* Re: [PATCH v7 02/16] perf jevents: Add common software event json
  2025-07-23 18:24   ` Namhyung Kim
@ 2025-07-23 22:34     ` Ian Rogers
  2025-07-24  0:10       ` Namhyung Kim
  0 siblings, 1 reply; 41+ messages in thread
From: Ian Rogers @ 2025-07-23 22:34 UTC (permalink / raw)
  To: Namhyung Kim
  Cc: Peter Zijlstra, Ingo Molnar, Arnaldo Carvalho de Melo,
	Mark Rutland, Alexander Shishkin, Jiri Olsa, Adrian Hunter,
	Kan Liang, James Clark, Xu Yang, Masami Hiramatsu (Google),
	Collin Funk, Howard Chu, Weilin Wang, Andi Kleen,
	Dr. David Alan Gilbert, Thomas Richter, Tiezhu Yang,
	Gautam Menghani, Thomas Falcon, Chun-Tse Shao, linux-kernel,
	linux-perf-users

On Wed, Jul 23, 2025 at 11:24 AM Namhyung Kim <namhyung@kernel.org> wrote:
>
> On Mon, Jul 14, 2025 at 09:43:50AM -0700, Ian Rogers wrote:
> > Add json for software events so that in perf list the events can have
> > a description.  Common json exists for the tool PMU but it has no
> > sysfs equivalent. Modify the map_for_pmu code to return the common map
> > (rather than an architecture specific one) when a PMU with a common
> > name is being looked for, this allows the events to be found.
>
> Can you please share new output of `perf list sw`?  I'm glad we have
> description for software events.  But I'm also curious what's the side
> effect of having them in JSON - maybe case insensitivity?

The old software event names were matched in the lex code and were
case sensitive. The events in the json are case insensitive and the
case insensitive lex ones are removed in the next patch.

The perf list output looks like:

Before:
```
List of pre-defined events (to be used in -e or -M):

  branch-instructions OR branches                    [Hardware event]
  branch-misses                                      [Hardware event]
  bus-cycles                                         [Hardware event]
  cache-misses                                       [Hardware event]
  cache-references                                   [Hardware event]
  cpu-cycles OR cycles                               [Hardware event]
  instructions                                       [Hardware event]
  ref-cycles                                         [Hardware event]
  alignment-faults                                   [Software event]
  bpf-output                                         [Software event]
  cgroup-switches                                    [Software event]
  context-switches OR cs                             [Software event]
  cpu-clock                                          [Software event]
  cpu-migrations OR migrations                       [Software event]
  dummy                                              [Software event]
  emulation-faults                                   [Software event]
  major-faults                                       [Software event]
  minor-faults                                       [Software event]
  page-faults OR faults                              [Software event]
  task-clock                                         [Software event]
```

After:
```
List of pre-defined events (to be used in -e or -M):

  branch-instructions OR branches                    [Hardware event]
  branch-misses                                      [Hardware event]
  bus-cycles                                         [Hardware event]
  cache-misses                                       [Hardware event]
  cache-references                                   [Hardware event]
  cpu-cycles OR cycles                               [Hardware event]
  instructions                                       [Hardware event]
  ref-cycles                                         [Hardware event]
  alignment-faults                                   [Software event]
  bpf-output                                         [Software event]
  cgroup-switches                                    [Software event]
  context-switches OR cs                             [Software event]
  cpu-clock                                          [Software event]
  cpu-migrations OR migrations                       [Software event]
  dummy                                              [Software event]
  emulation-faults                                   [Software event]
  major-faults                                       [Software event]
  minor-faults                                       [Software event]
  page-faults OR faults                              [Software event]
  task-clock                                         [Software event]
...
software:
  alignment-faults
       [Number of kernel handled memory alignment faults. Unit: software]
  bpf-output
       [An event used by BPF programs to write to the perf ring
buffer. Unit: software]
  cgroup-switches
       [Number of context switches to a task in a different cgroup.
Unit: software]
  context-switches
       [Number of context switches [This event is an alias of cs].
Unit: software]
  cpu-clock
       [Per-CPU high-resolution timer based event. Unit: software]
  cpu-migrations
       [Number of times a process has migrated to a new CPU [This
event is an alias of migrations]. Unit: software]
  cs
       [Number of context switches [This event is an alias of
context-switches]. Unit: software]
  dummy
       [A placeholder event that doesn't count anything. Unit: software]
  emulation-faults
       [Number of kernel handled unimplemented instruction faults
handled through emulation. Unit: software]
  faults
       [Number of page faults [This event is an alias of page-faults].
Unit: software]
  major-faults
       [Number of major page faults. Major faults require I/O to
handle. Unit: software]
  migrations
       [Number of times a process has migrated to a new CPU [This
event is an alias of cpu-migrations]. Unit: software]
  minor-faults
       [Number of minor page faults. Minor faults don't require I/O to
handle. Unit: software]
  page-faults
       [Number of page faults [This event is an alias of faults].
Unit: software]
  task-clock
       [Task based high-resolution timer based event. Unit: software]
...
```
The next patch will make this just:
```
List of pre-defined events (to be used in -e or -M):

  branch-instructions OR branches                    [Hardware event]
  branch-misses                                      [Hardware event]
  bus-cycles                                         [Hardware event]
  cache-misses                                       [Hardware event]
  cache-references                                   [Hardware event]
  cpu-cycles OR cycles                               [Hardware event]
  instructions                                       [Hardware event]
  ref-cycles                                         [Hardware event]
...
software:
  alignment-faults
       [Number of kernel handled memory alignment faults. Unit: software]
  bpf-output
       [An event used by BPF programs to write to the perf ring
buffer. Unit: software]
  cgroup-switches
       [Number of context switches to a task in a different cgroup.
Unit: software]
  context-switches
       [Number of context switches [This event is an alias of cs].
Unit: software]
  cpu-clock
       [Per-CPU high-resolution timer based event. Unit: software]
  cpu-migrations
       [Number of times a process has migrated to a new CPU [This
event is an alias of migrations]. Unit: software]
  cs
       [Number of context switches [This event is an alias of
context-switches]. Unit: software]
  dummy
       [A placeholder event that doesn't count anything. Unit: software]
  emulation-faults
       [Number of kernel handled unimplemented instruction faults
handled through emulation. Unit: software]
  faults
       [Number of page faults [This event is an alias of page-faults].
Unit: software]
  major-faults
       [Number of major page faults. Major faults require I/O to
handle. Unit: software]
  migrations
       [Number of times a process has migrated to a new CPU [This
event is an alias of cpu-migrations]. Unit: software]
  minor-faults
       [Number of minor page faults. Minor faults don't require I/O to
handle. Unit: software]
  page-faults
       [Number of page faults [This event is an alias of faults].
Unit: software]
  task-clock
       [Task based high-resolution timer based event. Unit: software]
...
```
> >
> > Signed-off-by: Ian Rogers <irogers@google.com>
> > ---
> >  .../arch/common/common/software.json          |  92 ++++++
> >  tools/perf/pmu-events/empty-pmu-events.c      | 266 +++++++++++-------
> >  tools/perf/pmu-events/jevents.py              |  15 +-
> >  3 files changed, 264 insertions(+), 109 deletions(-)
> >  create mode 100644 tools/perf/pmu-events/arch/common/common/software.json
> >
> > diff --git a/tools/perf/pmu-events/arch/common/common/software.json b/tools/perf/pmu-events/arch/common/common/software.json
> > new file mode 100644
> > index 000000000000..3af2f565a601
> > --- /dev/null
> > +++ b/tools/perf/pmu-events/arch/common/common/software.json
> > @@ -0,0 +1,92 @@
> > +[
> > +  {
> > +    "Unit": "software",
> > +    "EventName": "cpu-clock",
> > +    "BriefDescription": "Per-CPU high-resolution timer based event",
> > +    "ConfigCode": "0"
> > +  },
> > +  {
> > +    "Unit": "software",
> > +    "EventName": "task-clock",
> > +    "BriefDescription": "Task based high-resolution timer based event",
>
> s/Task based/Per-task/ ?

Will fix it in the next version.

>
> > +    "ConfigCode": "1"
> > +  },
> > +  {
> > +    "Unit": "software",
> > +    "EventName": "faults",
> > +    "BriefDescription": "Number of page faults [This event is an alias of page-faults]",
> > +    "ConfigCode": "2"
>
> It'd be nice if it can handle aliases without adding a new entry.  But I
> guess it requires non-trivial changes.

It is a limitation of the perf json format. There's no reason not to
add some notion of aliases, I believe it was done this way inheriting
from how Intel did it.

Thanks,
Ian

> Thanks,
> Namhyung
>
> > +  },
> > +  {
> > +    "Unit": "software",
> > +    "EventName": "page-faults",
> > +    "BriefDescription": "Number of page faults [This event is an alias of faults]",
> > +    "ConfigCode": "2"
> > +  },
> > +  {
> > +    "Unit": "software",
> > +    "EventName": "context-switches",
> > +    "BriefDescription": "Number of context switches [This event is an alias of cs]",
> > +    "ConfigCode": "3"
> > +  },
> > +  {
> > +    "Unit": "software",
> > +    "EventName": "cs",
> > +    "BriefDescription": "Number of context switches [This event is an alias of context-switches]",
> > +    "ConfigCode": "3"
> > +  },
> > +  {
> > +    "Unit": "software",
> > +    "EventName": "cpu-migrations",
> > +    "BriefDescription": "Number of times a process has migrated to a new CPU [This event is an alias of migrations]",
> > +    "ConfigCode": "4"
> > +  },
> > +  {
> > +    "Unit": "software",
> > +    "EventName": "migrations",
> > +    "BriefDescription": "Number of times a process has migrated to a new CPU [This event is an alias of cpu-migrations]",
> > +    "ConfigCode": "4"
> > +  },
> > +  {
> > +    "Unit": "software",
> > +    "EventName": "minor-faults",
> > +    "BriefDescription": "Number of minor page faults. Minor faults don't require I/O to handle",
> > +    "ConfigCode": "5"
> > +  },
> > +  {
> > +    "Unit": "software",
> > +    "EventName": "major-faults",
> > +    "BriefDescription": "Number of major page faults. Major faults require I/O to handle",
> > +    "ConfigCode": "6"
> > +  },
> > +  {
> > +    "Unit": "software",
> > +    "EventName": "alignment-faults",
> > +    "BriefDescription": "Number of kernel handled memory alignment faults",
> > +    "ConfigCode": "7"
> > +  },
> > +  {
> > +    "Unit": "software",
> > +    "EventName": "emulation-faults",
> > +    "BriefDescription": "Number of kernel handled unimplemented instruction faults handled through emulation",
> > +    "ConfigCode": "8"
> > +  },
> > +  {
> > +    "Unit": "software",
> > +    "EventName": "dummy",
> > +    "BriefDescription": "A placeholder event that doesn't count anything",
> > +    "ConfigCode": "9"
> > +  },
> > +  {
> > +    "Unit": "software",
> > +    "EventName": "bpf-output",
> > +    "BriefDescription": "An event used by BPF programs to write to the perf ring buffer",
> > +    "ConfigCode": "10"
> > +  },
> > +  {
> > +    "Unit": "software",
> > +    "EventName": "cgroup-switches",
> > +    "BriefDescription": "Number of context switches to a task in a different cgroup",
> > +    "ConfigCode": "11"
> > +  }
> > +]
> > diff --git a/tools/perf/pmu-events/empty-pmu-events.c b/tools/perf/pmu-events/empty-pmu-events.c
> > index a4569a74db07..7d179d703ab1 100644
> > --- a/tools/perf/pmu-events/empty-pmu-events.c
> > +++ b/tools/perf/pmu-events/empty-pmu-events.c
> > @@ -19,109 +19,147 @@ struct pmu_table_entry {
> >  };
> >
> >  static const char *const big_c_string =
> > -/* offset=0 */ "tool\000"
> > -/* offset=5 */ "duration_time\000tool\000Wall clock interval time in nanoseconds\000config=1\000\00000\000\000\000\000\000"
> > -/* offset=81 */ "user_time\000tool\000User (non-kernel) time in nanoseconds\000config=2\000\00000\000\000\000\000\000"
> > -/* offset=151 */ "system_time\000tool\000System/kernel time in nanoseconds\000config=3\000\00000\000\000\000\000\000"
> > -/* offset=219 */ "has_pmem\000tool\0001 if persistent memory installed otherwise 0\000config=4\000\00000\000\000\000\000\000"
> > -/* offset=295 */ "num_cores\000tool\000Number of cores. A core consists of 1 or more thread, with each thread being associated with a logical Linux CPU\000config=5\000\00000\000\000\000\000\000"
> > -/* offset=440 */ "num_cpus\000tool\000Number of logical Linux CPUs. There may be multiple such CPUs on a core\000config=6\000\00000\000\000\000\000\000"
> > -/* offset=543 */ "num_cpus_online\000tool\000Number of online logical Linux CPUs. There may be multiple such CPUs on a core\000config=7\000\00000\000\000\000\000\000"
> > -/* offset=660 */ "num_dies\000tool\000Number of dies. Each die has 1 or more cores\000config=8\000\00000\000\000\000\000\000"
> > -/* offset=736 */ "num_packages\000tool\000Number of packages. Each package has 1 or more die\000config=9\000\00000\000\000\000\000\000"
> > -/* offset=822 */ "slots\000tool\000Number of functional units that in parallel can execute parts of an instruction\000config=0xa\000\00000\000\000\000\000\000"
> > -/* offset=932 */ "smt_on\000tool\0001 if simultaneous multithreading (aka hyperthreading) is enable otherwise 0\000config=0xb\000\00000\000\000\000\000\000"
> > -/* offset=1039 */ "system_tsc_freq\000tool\000The amount a Time Stamp Counter (TSC) increases per second\000config=0xc\000\00000\000\000\000\000\000"
> > -/* offset=1138 */ "default_core\000"
> > -/* offset=1151 */ "bp_l1_btb_correct\000branch\000L1 BTB Correction\000event=0x8a\000\00000\000\000\000\000\000"
> > -/* offset=1213 */ "bp_l2_btb_correct\000branch\000L2 BTB Correction\000event=0x8b\000\00000\000\000\000\000\000"
> > -/* offset=1275 */ "l3_cache_rd\000cache\000L3 cache access, read\000event=0x40\000\00000\000\000\000\000Attributable Level 3 cache access, read\000"
> > -/* offset=1373 */ "segment_reg_loads.any\000other\000Number of segment register loads\000event=6,period=200000,umask=0x80\000\00000\000\000\000\000\000"
> > -/* offset=1475 */ "dispatch_blocked.any\000other\000Memory cluster signals to block micro-op dispatch for any reason\000event=9,period=200000,umask=0x20\000\00000\000\000\000\000\000"
> > -/* offset=1608 */ "eist_trans\000other\000Number of Enhanced Intel SpeedStep(R) Technology (EIST) transitions\000event=0x3a,period=200000\000\00000\000\000\000\000\000"
> > -/* offset=1726 */ "hisi_sccl,ddrc\000"
> > -/* offset=1741 */ "uncore_hisi_ddrc.flux_wcmd\000uncore\000DDRC write commands\000event=2\000\00000\000\000\000\000\000"
> > -/* offset=1811 */ "uncore_cbox\000"
> > -/* offset=1823 */ "unc_cbo_xsnp_response.miss_eviction\000uncore\000A cross-core snoop resulted from L3 Eviction which misses in some processor core\000event=0x22,umask=0x81\000\00000\000\000\000\000\000"
> > -/* offset=1977 */ "event-hyphen\000uncore\000UNC_CBO_HYPHEN\000event=0xe0\000\00000\000\000\000\000\000"
> > -/* offset=2031 */ "event-two-hyph\000uncore\000UNC_CBO_TWO_HYPH\000event=0xc0\000\00000\000\000\000\000\000"
> > -/* offset=2089 */ "hisi_sccl,l3c\000"
> > -/* offset=2103 */ "uncore_hisi_l3c.rd_hit_cpipe\000uncore\000Total read hits\000event=7\000\00000\000\000\000\000\000"
> > -/* offset=2171 */ "uncore_imc_free_running\000"
> > -/* offset=2195 */ "uncore_imc_free_running.cache_miss\000uncore\000Total cache misses\000event=0x12\000\00000\000\000\000\000\000"
> > -/* offset=2275 */ "uncore_imc\000"
> > -/* offset=2286 */ "uncore_imc.cache_hits\000uncore\000Total cache hits\000event=0x34\000\00000\000\000\000\000\000"
> > -/* offset=2351 */ "uncore_sys_ddr_pmu\000"
> > -/* offset=2370 */ "sys_ddr_pmu.write_cycles\000uncore\000ddr write-cycles event\000event=0x2b\000v8\00000\000\000\000\000\000"
> > -/* offset=2446 */ "uncore_sys_ccn_pmu\000"
> > -/* offset=2465 */ "sys_ccn_pmu.read_cycles\000uncore\000ccn read-cycles event\000config=0x2c\0000x01\00000\000\000\000\000\000"
> > -/* offset=2542 */ "uncore_sys_cmn_pmu\000"
> > -/* offset=2561 */ "sys_cmn_pmu.hnf_cache_miss\000uncore\000Counts total cache misses in first lookup result (high priority)\000eventid=1,type=5\000(434|436|43c|43a).*\00000\000\000\000\000\000"
> > -/* offset=2704 */ "CPI\000\0001 / IPC\000\000\000\000\000\000\000\00000"
> > -/* offset=2726 */ "IPC\000group1\000inst_retired.any / cpu_clk_unhalted.thread\000\000\000\000\000\000\000\00000"
> > -/* offset=2789 */ "Frontend_Bound_SMT\000\000idq_uops_not_delivered.core / (4 * (cpu_clk_unhalted.thread / 2 * (1 + cpu_clk_unhalted.one_thread_active / cpu_clk_unhalted.ref_xclk)))\000\000\000\000\000\000\000\00000"
> > -/* offset=2955 */ "dcache_miss_cpi\000\000l1d\\-loads\\-misses / inst_retired.any\000\000\000\000\000\000\000\00000"
> > -/* offset=3019 */ "icache_miss_cycles\000\000l1i\\-loads\\-misses / inst_retired.any\000\000\000\000\000\000\000\00000"
> > -/* offset=3086 */ "cache_miss_cycles\000group1\000dcache_miss_cpi + icache_miss_cycles\000\000\000\000\000\000\000\00000"
> > -/* offset=3157 */ "DCache_L2_All_Hits\000\000l2_rqsts.demand_data_rd_hit + l2_rqsts.pf_hit + l2_rqsts.rfo_hit\000\000\000\000\000\000\000\00000"
> > -/* offset=3251 */ "DCache_L2_All_Miss\000\000max(l2_rqsts.all_demand_data_rd - l2_rqsts.demand_data_rd_hit, 0) + l2_rqsts.pf_miss + l2_rqsts.rfo_miss\000\000\000\000\000\000\000\00000"
> > -/* offset=3385 */ "DCache_L2_All\000\000DCache_L2_All_Hits + DCache_L2_All_Miss\000\000\000\000\000\000\000\00000"
> > -/* offset=3449 */ "DCache_L2_Hits\000\000d_ratio(DCache_L2_All_Hits, DCache_L2_All)\000\000\000\000\000\000\000\00000"
> > -/* offset=3517 */ "DCache_L2_Misses\000\000d_ratio(DCache_L2_All_Miss, DCache_L2_All)\000\000\000\000\000\000\000\00000"
> > -/* offset=3587 */ "M1\000\000ipc + M2\000\000\000\000\000\000\000\00000"
> > -/* offset=3609 */ "M2\000\000ipc + M1\000\000\000\000\000\000\000\00000"
> > -/* offset=3631 */ "M3\000\0001 / M3\000\000\000\000\000\000\000\00000"
> > -/* offset=3651 */ "L1D_Cache_Fill_BW\000\00064 * l1d.replacement / 1e9 / duration_time\000\000\000\000\000\000\000\00000"
> > +/* offset=0 */ "software\000"
> > +/* offset=9 */ "cpu-clock\000software\000Per-CPU high-resolution timer based event\000config=0\000\00000\000\000\000\000\000"
> > +/* offset=87 */ "task-clock\000software\000Task based high-resolution timer based event\000config=1\000\00000\000\000\000\000\000"
> > +/* offset=169 */ "faults\000software\000Number of page faults [This event is an alias of page-faults]\000config=2\000\00000\000\000\000\000\000"
> > +/* offset=264 */ "page-faults\000software\000Number of page faults [This event is an alias of faults]\000config=2\000\00000\000\000\000\000\000"
> > +/* offset=359 */ "context-switches\000software\000Number of context switches [This event is an alias of cs]\000config=3\000\00000\000\000\000\000\000"
> > +/* offset=460 */ "cs\000software\000Number of context switches [This event is an alias of context-switches]\000config=3\000\00000\000\000\000\000\000"
> > +/* offset=561 */ "cpu-migrations\000software\000Number of times a process has migrated to a new CPU [This event is an alias of migrations]\000config=4\000\00000\000\000\000\000\000"
> > +/* offset=693 */ "migrations\000software\000Number of times a process has migrated to a new CPU [This event is an alias of cpu-migrations]\000config=4\000\00000\000\000\000\000\000"
> > +/* offset=825 */ "minor-faults\000software\000Number of minor page faults. Minor faults don't require I/O to handle\000config=5\000\00000\000\000\000\000\000"
> > +/* offset=934 */ "major-faults\000software\000Number of major page faults. Major faults require I/O to handle\000config=6\000\00000\000\000\000\000\000"
> > +/* offset=1037 */ "alignment-faults\000software\000Number of kernel handled memory alignment faults\000config=7\000\00000\000\000\000\000\000"
> > +/* offset=1129 */ "emulation-faults\000software\000Number of kernel handled unimplemented instruction faults handled through emulation\000config=8\000\00000\000\000\000\000\000"
> > +/* offset=1256 */ "dummy\000software\000A placeholder event that doesn't count anything\000config=9\000\00000\000\000\000\000\000"
> > +/* offset=1336 */ "bpf-output\000software\000An event used by BPF programs to write to the perf ring buffer\000config=0xa\000\00000\000\000\000\000\000"
> > +/* offset=1438 */ "cgroup-switches\000software\000Number of context switches to a task in a different cgroup\000config=0xb\000\00000\000\000\000\000\000"
> > +/* offset=1541 */ "tool\000"
> > +/* offset=1546 */ "duration_time\000tool\000Wall clock interval time in nanoseconds\000config=1\000\00000\000\000\000\000\000"
> > +/* offset=1622 */ "user_time\000tool\000User (non-kernel) time in nanoseconds\000config=2\000\00000\000\000\000\000\000"
> > +/* offset=1692 */ "system_time\000tool\000System/kernel time in nanoseconds\000config=3\000\00000\000\000\000\000\000"
> > +/* offset=1760 */ "has_pmem\000tool\0001 if persistent memory installed otherwise 0\000config=4\000\00000\000\000\000\000\000"
> > +/* offset=1836 */ "num_cores\000tool\000Number of cores. A core consists of 1 or more thread, with each thread being associated with a logical Linux CPU\000config=5\000\00000\000\000\000\000\000"
> > +/* offset=1981 */ "num_cpus\000tool\000Number of logical Linux CPUs. There may be multiple such CPUs on a core\000config=6\000\00000\000\000\000\000\000"
> > +/* offset=2084 */ "num_cpus_online\000tool\000Number of online logical Linux CPUs. There may be multiple such CPUs on a core\000config=7\000\00000\000\000\000\000\000"
> > +/* offset=2201 */ "num_dies\000tool\000Number of dies. Each die has 1 or more cores\000config=8\000\00000\000\000\000\000\000"
> > +/* offset=2277 */ "num_packages\000tool\000Number of packages. Each package has 1 or more die\000config=9\000\00000\000\000\000\000\000"
> > +/* offset=2363 */ "slots\000tool\000Number of functional units that in parallel can execute parts of an instruction\000config=0xa\000\00000\000\000\000\000\000"
> > +/* offset=2473 */ "smt_on\000tool\0001 if simultaneous multithreading (aka hyperthreading) is enable otherwise 0\000config=0xb\000\00000\000\000\000\000\000"
> > +/* offset=2580 */ "system_tsc_freq\000tool\000The amount a Time Stamp Counter (TSC) increases per second\000config=0xc\000\00000\000\000\000\000\000"
> > +/* offset=2679 */ "default_core\000"
> > +/* offset=2692 */ "bp_l1_btb_correct\000branch\000L1 BTB Correction\000event=0x8a\000\00000\000\000\000\000\000"
> > +/* offset=2754 */ "bp_l2_btb_correct\000branch\000L2 BTB Correction\000event=0x8b\000\00000\000\000\000\000\000"
> > +/* offset=2816 */ "l3_cache_rd\000cache\000L3 cache access, read\000event=0x40\000\00000\000\000\000\000Attributable Level 3 cache access, read\000"
> > +/* offset=2914 */ "segment_reg_loads.any\000other\000Number of segment register loads\000event=6,period=200000,umask=0x80\000\00000\000\000\000\000\000"
> > +/* offset=3016 */ "dispatch_blocked.any\000other\000Memory cluster signals to block micro-op dispatch for any reason\000event=9,period=200000,umask=0x20\000\00000\000\000\000\000\000"
> > +/* offset=3149 */ "eist_trans\000other\000Number of Enhanced Intel SpeedStep(R) Technology (EIST) transitions\000event=0x3a,period=200000\000\00000\000\000\000\000\000"
> > +/* offset=3267 */ "hisi_sccl,ddrc\000"
> > +/* offset=3282 */ "uncore_hisi_ddrc.flux_wcmd\000uncore\000DDRC write commands\000event=2\000\00000\000\000\000\000\000"
> > +/* offset=3352 */ "uncore_cbox\000"
> > +/* offset=3364 */ "unc_cbo_xsnp_response.miss_eviction\000uncore\000A cross-core snoop resulted from L3 Eviction which misses in some processor core\000event=0x22,umask=0x81\000\00000\000\000\000\000\000"
> > +/* offset=3518 */ "event-hyphen\000uncore\000UNC_CBO_HYPHEN\000event=0xe0\000\00000\000\000\000\000\000"
> > +/* offset=3572 */ "event-two-hyph\000uncore\000UNC_CBO_TWO_HYPH\000event=0xc0\000\00000\000\000\000\000\000"
> > +/* offset=3630 */ "hisi_sccl,l3c\000"
> > +/* offset=3644 */ "uncore_hisi_l3c.rd_hit_cpipe\000uncore\000Total read hits\000event=7\000\00000\000\000\000\000\000"
> > +/* offset=3712 */ "uncore_imc_free_running\000"
> > +/* offset=3736 */ "uncore_imc_free_running.cache_miss\000uncore\000Total cache misses\000event=0x12\000\00000\000\000\000\000\000"
> > +/* offset=3816 */ "uncore_imc\000"
> > +/* offset=3827 */ "uncore_imc.cache_hits\000uncore\000Total cache hits\000event=0x34\000\00000\000\000\000\000\000"
> > +/* offset=3892 */ "uncore_sys_ddr_pmu\000"
> > +/* offset=3911 */ "sys_ddr_pmu.write_cycles\000uncore\000ddr write-cycles event\000event=0x2b\000v8\00000\000\000\000\000\000"
> > +/* offset=3987 */ "uncore_sys_ccn_pmu\000"
> > +/* offset=4006 */ "sys_ccn_pmu.read_cycles\000uncore\000ccn read-cycles event\000config=0x2c\0000x01\00000\000\000\000\000\000"
> > +/* offset=4083 */ "uncore_sys_cmn_pmu\000"
> > +/* offset=4102 */ "sys_cmn_pmu.hnf_cache_miss\000uncore\000Counts total cache misses in first lookup result (high priority)\000eventid=1,type=5\000(434|436|43c|43a).*\00000\000\000\000\000\000"
> > +/* offset=4245 */ "CPI\000\0001 / IPC\000\000\000\000\000\000\000\00000"
> > +/* offset=4267 */ "IPC\000group1\000inst_retired.any / cpu_clk_unhalted.thread\000\000\000\000\000\000\000\00000"
> > +/* offset=4330 */ "Frontend_Bound_SMT\000\000idq_uops_not_delivered.core / (4 * (cpu_clk_unhalted.thread / 2 * (1 + cpu_clk_unhalted.one_thread_active / cpu_clk_unhalted.ref_xclk)))\000\000\000\000\000\000\000\00000"
> > +/* offset=4496 */ "dcache_miss_cpi\000\000l1d\\-loads\\-misses / inst_retired.any\000\000\000\000\000\000\000\00000"
> > +/* offset=4560 */ "icache_miss_cycles\000\000l1i\\-loads\\-misses / inst_retired.any\000\000\000\000\000\000\000\00000"
> > +/* offset=4627 */ "cache_miss_cycles\000group1\000dcache_miss_cpi + icache_miss_cycles\000\000\000\000\000\000\000\00000"
> > +/* offset=4698 */ "DCache_L2_All_Hits\000\000l2_rqsts.demand_data_rd_hit + l2_rqsts.pf_hit + l2_rqsts.rfo_hit\000\000\000\000\000\000\000\00000"
> > +/* offset=4792 */ "DCache_L2_All_Miss\000\000max(l2_rqsts.all_demand_data_rd - l2_rqsts.demand_data_rd_hit, 0) + l2_rqsts.pf_miss + l2_rqsts.rfo_miss\000\000\000\000\000\000\000\00000"
> > +/* offset=4926 */ "DCache_L2_All\000\000DCache_L2_All_Hits + DCache_L2_All_Miss\000\000\000\000\000\000\000\00000"
> > +/* offset=4990 */ "DCache_L2_Hits\000\000d_ratio(DCache_L2_All_Hits, DCache_L2_All)\000\000\000\000\000\000\000\00000"
> > +/* offset=5058 */ "DCache_L2_Misses\000\000d_ratio(DCache_L2_All_Miss, DCache_L2_All)\000\000\000\000\000\000\000\00000"
> > +/* offset=5128 */ "M1\000\000ipc + M2\000\000\000\000\000\000\000\00000"
> > +/* offset=5150 */ "M2\000\000ipc + M1\000\000\000\000\000\000\000\00000"
> > +/* offset=5172 */ "M3\000\0001 / M3\000\000\000\000\000\000\000\00000"
> > +/* offset=5192 */ "L1D_Cache_Fill_BW\000\00064 * l1d.replacement / 1e9 / duration_time\000\000\000\000\000\000\000\00000"
> >  ;
> >
> > +static const struct compact_pmu_event pmu_events__common_software[] = {
> > +{ 1037 }, /* alignment-faults\000software\000Number of kernel handled memory alignment faults\000config=7\000\00000\000\000\000\000\000 */
> > +{ 1336 }, /* bpf-output\000software\000An event used by BPF programs to write to the perf ring buffer\000config=0xa\000\00000\000\000\000\000\000 */
> > +{ 1438 }, /* cgroup-switches\000software\000Number of context switches to a task in a different cgroup\000config=0xb\000\00000\000\000\000\000\000 */
> > +{ 359 }, /* context-switches\000software\000Number of context switches [This event is an alias of cs]\000config=3\000\00000\000\000\000\000\000 */
> > +{ 9 }, /* cpu-clock\000software\000Per-CPU high-resolution timer based event\000config=0\000\00000\000\000\000\000\000 */
> > +{ 561 }, /* cpu-migrations\000software\000Number of times a process has migrated to a new CPU [This event is an alias of migrations]\000config=4\000\00000\000\000\000\000\000 */
> > +{ 460 }, /* cs\000software\000Number of context switches [This event is an alias of context-switches]\000config=3\000\00000\000\000\000\000\000 */
> > +{ 1256 }, /* dummy\000software\000A placeholder event that doesn't count anything\000config=9\000\00000\000\000\000\000\000 */
> > +{ 1129 }, /* emulation-faults\000software\000Number of kernel handled unimplemented instruction faults handled through emulation\000config=8\000\00000\000\000\000\000\000 */
> > +{ 169 }, /* faults\000software\000Number of page faults [This event is an alias of page-faults]\000config=2\000\00000\000\000\000\000\000 */
> > +{ 934 }, /* major-faults\000software\000Number of major page faults. Major faults require I/O to handle\000config=6\000\00000\000\000\000\000\000 */
> > +{ 693 }, /* migrations\000software\000Number of times a process has migrated to a new CPU [This event is an alias of cpu-migrations]\000config=4\000\00000\000\000\000\000\000 */
> > +{ 825 }, /* minor-faults\000software\000Number of minor page faults. Minor faults don't require I/O to handle\000config=5\000\00000\000\000\000\000\000 */
> > +{ 264 }, /* page-faults\000software\000Number of page faults [This event is an alias of faults]\000config=2\000\00000\000\000\000\000\000 */
> > +{ 87 }, /* task-clock\000software\000Task based high-resolution timer based event\000config=1\000\00000\000\000\000\000\000 */
> > +};
> >  static const struct compact_pmu_event pmu_events__common_tool[] = {
> > -{ 5 }, /* duration_time\000tool\000Wall clock interval time in nanoseconds\000config=1\000\00000\000\000\000\000\000 */
> > -{ 219 }, /* has_pmem\000tool\0001 if persistent memory installed otherwise 0\000config=4\000\00000\000\000\000\000\000 */
> > -{ 295 }, /* num_cores\000tool\000Number of cores. A core consists of 1 or more thread, with each thread being associated with a logical Linux CPU\000config=5\000\00000\000\000\000\000\000 */
> > -{ 440 }, /* num_cpus\000tool\000Number of logical Linux CPUs. There may be multiple such CPUs on a core\000config=6\000\00000\000\000\000\000\000 */
> > -{ 543 }, /* num_cpus_online\000tool\000Number of online logical Linux CPUs. There may be multiple such CPUs on a core\000config=7\000\00000\000\000\000\000\000 */
> > -{ 660 }, /* num_dies\000tool\000Number of dies. Each die has 1 or more cores\000config=8\000\00000\000\000\000\000\000 */
> > -{ 736 }, /* num_packages\000tool\000Number of packages. Each package has 1 or more die\000config=9\000\00000\000\000\000\000\000 */
> > -{ 822 }, /* slots\000tool\000Number of functional units that in parallel can execute parts of an instruction\000config=0xa\000\00000\000\000\000\000\000 */
> > -{ 932 }, /* smt_on\000tool\0001 if simultaneous multithreading (aka hyperthreading) is enable otherwise 0\000config=0xb\000\00000\000\000\000\000\000 */
> > -{ 151 }, /* system_time\000tool\000System/kernel time in nanoseconds\000config=3\000\00000\000\000\000\000\000 */
> > -{ 1039 }, /* system_tsc_freq\000tool\000The amount a Time Stamp Counter (TSC) increases per second\000config=0xc\000\00000\000\000\000\000\000 */
> > -{ 81 }, /* user_time\000tool\000User (non-kernel) time in nanoseconds\000config=2\000\00000\000\000\000\000\000 */
> > +{ 1546 }, /* duration_time\000tool\000Wall clock interval time in nanoseconds\000config=1\000\00000\000\000\000\000\000 */
> > +{ 1760 }, /* has_pmem\000tool\0001 if persistent memory installed otherwise 0\000config=4\000\00000\000\000\000\000\000 */
> > +{ 1836 }, /* num_cores\000tool\000Number of cores. A core consists of 1 or more thread, with each thread being associated with a logical Linux CPU\000config=5\000\00000\000\000\000\000\000 */
> > +{ 1981 }, /* num_cpus\000tool\000Number of logical Linux CPUs. There may be multiple such CPUs on a core\000config=6\000\00000\000\000\000\000\000 */
> > +{ 2084 }, /* num_cpus_online\000tool\000Number of online logical Linux CPUs. There may be multiple such CPUs on a core\000config=7\000\00000\000\000\000\000\000 */
> > +{ 2201 }, /* num_dies\000tool\000Number of dies. Each die has 1 or more cores\000config=8\000\00000\000\000\000\000\000 */
> > +{ 2277 }, /* num_packages\000tool\000Number of packages. Each package has 1 or more die\000config=9\000\00000\000\000\000\000\000 */
> > +{ 2363 }, /* slots\000tool\000Number of functional units that in parallel can execute parts of an instruction\000config=0xa\000\00000\000\000\000\000\000 */
> > +{ 2473 }, /* smt_on\000tool\0001 if simultaneous multithreading (aka hyperthreading) is enable otherwise 0\000config=0xb\000\00000\000\000\000\000\000 */
> > +{ 1692 }, /* system_time\000tool\000System/kernel time in nanoseconds\000config=3\000\00000\000\000\000\000\000 */
> > +{ 2580 }, /* system_tsc_freq\000tool\000The amount a Time Stamp Counter (TSC) increases per second\000config=0xc\000\00000\000\000\000\000\000 */
> > +{ 1622 }, /* user_time\000tool\000User (non-kernel) time in nanoseconds\000config=2\000\00000\000\000\000\000\000 */
> >
> >  };
> >
> >  const struct pmu_table_entry pmu_events__common[] = {
> > +{
> > +     .entries = pmu_events__common_software,
> > +     .num_entries = ARRAY_SIZE(pmu_events__common_software),
> > +     .pmu_name = { 0 /* software\000 */ },
> > +},
> >  {
> >       .entries = pmu_events__common_tool,
> >       .num_entries = ARRAY_SIZE(pmu_events__common_tool),
> > -     .pmu_name = { 0 /* tool\000 */ },
> > +     .pmu_name = { 1541 /* tool\000 */ },
> >  },
> >  };
> >
> >  static const struct compact_pmu_event pmu_events__test_soc_cpu_default_core[] = {
> > -{ 1151 }, /* bp_l1_btb_correct\000branch\000L1 BTB Correction\000event=0x8a\000\00000\000\000\000\000\000 */
> > -{ 1213 }, /* bp_l2_btb_correct\000branch\000L2 BTB Correction\000event=0x8b\000\00000\000\000\000\000\000 */
> > -{ 1475 }, /* dispatch_blocked.any\000other\000Memory cluster signals to block micro-op dispatch for any reason\000event=9,period=200000,umask=0x20\000\00000\000\000\000\000\000 */
> > -{ 1608 }, /* eist_trans\000other\000Number of Enhanced Intel SpeedStep(R) Technology (EIST) transitions\000event=0x3a,period=200000\000\00000\000\000\000\000\000 */
> > -{ 1275 }, /* l3_cache_rd\000cache\000L3 cache access, read\000event=0x40\000\00000\000\000\000\000Attributable Level 3 cache access, read\000 */
> > -{ 1373 }, /* segment_reg_loads.any\000other\000Number of segment register loads\000event=6,period=200000,umask=0x80\000\00000\000\000\000\000\000 */
> > +{ 2692 }, /* bp_l1_btb_correct\000branch\000L1 BTB Correction\000event=0x8a\000\00000\000\000\000\000\000 */
> > +{ 2754 }, /* bp_l2_btb_correct\000branch\000L2 BTB Correction\000event=0x8b\000\00000\000\000\000\000\000 */
> > +{ 3016 }, /* dispatch_blocked.any\000other\000Memory cluster signals to block micro-op dispatch for any reason\000event=9,period=200000,umask=0x20\000\00000\000\000\000\000\000 */
> > +{ 3149 }, /* eist_trans\000other\000Number of Enhanced Intel SpeedStep(R) Technology (EIST) transitions\000event=0x3a,period=200000\000\00000\000\000\000\000\000 */
> > +{ 2816 }, /* l3_cache_rd\000cache\000L3 cache access, read\000event=0x40\000\00000\000\000\000\000Attributable Level 3 cache access, read\000 */
> > +{ 2914 }, /* segment_reg_loads.any\000other\000Number of segment register loads\000event=6,period=200000,umask=0x80\000\00000\000\000\000\000\000 */
> >  };
> >  static const struct compact_pmu_event pmu_events__test_soc_cpu_hisi_sccl_ddrc[] = {
> > -{ 1741 }, /* uncore_hisi_ddrc.flux_wcmd\000uncore\000DDRC write commands\000event=2\000\00000\000\000\000\000\000 */
> > +{ 3282 }, /* uncore_hisi_ddrc.flux_wcmd\000uncore\000DDRC write commands\000event=2\000\00000\000\000\000\000\000 */
> >  };
> >  static const struct compact_pmu_event pmu_events__test_soc_cpu_hisi_sccl_l3c[] = {
> > -{ 2103 }, /* uncore_hisi_l3c.rd_hit_cpipe\000uncore\000Total read hits\000event=7\000\00000\000\000\000\000\000 */
> > +{ 3644 }, /* uncore_hisi_l3c.rd_hit_cpipe\000uncore\000Total read hits\000event=7\000\00000\000\000\000\000\000 */
> >  };
> >  static const struct compact_pmu_event pmu_events__test_soc_cpu_uncore_cbox[] = {
> > -{ 1977 }, /* event-hyphen\000uncore\000UNC_CBO_HYPHEN\000event=0xe0\000\00000\000\000\000\000\000 */
> > -{ 2031 }, /* event-two-hyph\000uncore\000UNC_CBO_TWO_HYPH\000event=0xc0\000\00000\000\000\000\000\000 */
> > -{ 1823 }, /* unc_cbo_xsnp_response.miss_eviction\000uncore\000A cross-core snoop resulted from L3 Eviction which misses in some processor core\000event=0x22,umask=0x81\000\00000\000\000\000\000\000 */
> > +{ 3518 }, /* event-hyphen\000uncore\000UNC_CBO_HYPHEN\000event=0xe0\000\00000\000\000\000\000\000 */
> > +{ 3572 }, /* event-two-hyph\000uncore\000UNC_CBO_TWO_HYPH\000event=0xc0\000\00000\000\000\000\000\000 */
> > +{ 3364 }, /* unc_cbo_xsnp_response.miss_eviction\000uncore\000A cross-core snoop resulted from L3 Eviction which misses in some processor core\000event=0x22,umask=0x81\000\00000\000\000\000\000\000 */
> >  };
> >  static const struct compact_pmu_event pmu_events__test_soc_cpu_uncore_imc[] = {
> > -{ 2286 }, /* uncore_imc.cache_hits\000uncore\000Total cache hits\000event=0x34\000\00000\000\000\000\000\000 */
> > +{ 3827 }, /* uncore_imc.cache_hits\000uncore\000Total cache hits\000event=0x34\000\00000\000\000\000\000\000 */
> >  };
> >  static const struct compact_pmu_event pmu_events__test_soc_cpu_uncore_imc_free_running[] = {
> > -{ 2195 }, /* uncore_imc_free_running.cache_miss\000uncore\000Total cache misses\000event=0x12\000\00000\000\000\000\000\000 */
> > +{ 3736 }, /* uncore_imc_free_running.cache_miss\000uncore\000Total cache misses\000event=0x12\000\00000\000\000\000\000\000 */
> >
> >  };
> >
> > @@ -129,51 +167,51 @@ const struct pmu_table_entry pmu_events__test_soc_cpu[] = {
> >  {
> >       .entries = pmu_events__test_soc_cpu_default_core,
> >       .num_entries = ARRAY_SIZE(pmu_events__test_soc_cpu_default_core),
> > -     .pmu_name = { 1138 /* default_core\000 */ },
> > +     .pmu_name = { 2679 /* default_core\000 */ },
> >  },
> >  {
> >       .entries = pmu_events__test_soc_cpu_hisi_sccl_ddrc,
> >       .num_entries = ARRAY_SIZE(pmu_events__test_soc_cpu_hisi_sccl_ddrc),
> > -     .pmu_name = { 1726 /* hisi_sccl,ddrc\000 */ },
> > +     .pmu_name = { 3267 /* hisi_sccl,ddrc\000 */ },
> >  },
> >  {
> >       .entries = pmu_events__test_soc_cpu_hisi_sccl_l3c,
> >       .num_entries = ARRAY_SIZE(pmu_events__test_soc_cpu_hisi_sccl_l3c),
> > -     .pmu_name = { 2089 /* hisi_sccl,l3c\000 */ },
> > +     .pmu_name = { 3630 /* hisi_sccl,l3c\000 */ },
> >  },
> >  {
> >       .entries = pmu_events__test_soc_cpu_uncore_cbox,
> >       .num_entries = ARRAY_SIZE(pmu_events__test_soc_cpu_uncore_cbox),
> > -     .pmu_name = { 1811 /* uncore_cbox\000 */ },
> > +     .pmu_name = { 3352 /* uncore_cbox\000 */ },
> >  },
> >  {
> >       .entries = pmu_events__test_soc_cpu_uncore_imc,
> >       .num_entries = ARRAY_SIZE(pmu_events__test_soc_cpu_uncore_imc),
> > -     .pmu_name = { 2275 /* uncore_imc\000 */ },
> > +     .pmu_name = { 3816 /* uncore_imc\000 */ },
> >  },
> >  {
> >       .entries = pmu_events__test_soc_cpu_uncore_imc_free_running,
> >       .num_entries = ARRAY_SIZE(pmu_events__test_soc_cpu_uncore_imc_free_running),
> > -     .pmu_name = { 2171 /* uncore_imc_free_running\000 */ },
> > +     .pmu_name = { 3712 /* uncore_imc_free_running\000 */ },
> >  },
> >  };
> >
> >  static const struct compact_pmu_event pmu_metrics__test_soc_cpu_default_core[] = {
> > -{ 2704 }, /* CPI\000\0001 / IPC\000\000\000\000\000\000\000\00000 */
> > -{ 3385 }, /* DCache_L2_All\000\000DCache_L2_All_Hits + DCache_L2_All_Miss\000\000\000\000\000\000\000\00000 */
> > -{ 3157 }, /* DCache_L2_All_Hits\000\000l2_rqsts.demand_data_rd_hit + l2_rqsts.pf_hit + l2_rqsts.rfo_hit\000\000\000\000\000\000\000\00000 */
> > -{ 3251 }, /* DCache_L2_All_Miss\000\000max(l2_rqsts.all_demand_data_rd - l2_rqsts.demand_data_rd_hit, 0) + l2_rqsts.pf_miss + l2_rqsts.rfo_miss\000\000\000\000\000\000\000\00000 */
> > -{ 3449 }, /* DCache_L2_Hits\000\000d_ratio(DCache_L2_All_Hits, DCache_L2_All)\000\000\000\000\000\000\000\00000 */
> > -{ 3517 }, /* DCache_L2_Misses\000\000d_ratio(DCache_L2_All_Miss, DCache_L2_All)\000\000\000\000\000\000\000\00000 */
> > -{ 2789 }, /* Frontend_Bound_SMT\000\000idq_uops_not_delivered.core / (4 * (cpu_clk_unhalted.thread / 2 * (1 + cpu_clk_unhalted.one_thread_active / cpu_clk_unhalted.ref_xclk)))\000\000\000\000\000\000\000\00000 */
> > -{ 2726 }, /* IPC\000group1\000inst_retired.any / cpu_clk_unhalted.thread\000\000\000\000\000\000\000\00000 */
> > -{ 3651 }, /* L1D_Cache_Fill_BW\000\00064 * l1d.replacement / 1e9 / duration_time\000\000\000\000\000\000\000\00000 */
> > -{ 3587 }, /* M1\000\000ipc + M2\000\000\000\000\000\000\000\00000 */
> > -{ 3609 }, /* M2\000\000ipc + M1\000\000\000\000\000\000\000\00000 */
> > -{ 3631 }, /* M3\000\0001 / M3\000\000\000\000\000\000\000\00000 */
> > -{ 3086 }, /* cache_miss_cycles\000group1\000dcache_miss_cpi + icache_miss_cycles\000\000\000\000\000\000\000\00000 */
> > -{ 2955 }, /* dcache_miss_cpi\000\000l1d\\-loads\\-misses / inst_retired.any\000\000\000\000\000\000\000\00000 */
> > -{ 3019 }, /* icache_miss_cycles\000\000l1i\\-loads\\-misses / inst_retired.any\000\000\000\000\000\000\000\00000 */
> > +{ 4245 }, /* CPI\000\0001 / IPC\000\000\000\000\000\000\000\00000 */
> > +{ 4926 }, /* DCache_L2_All\000\000DCache_L2_All_Hits + DCache_L2_All_Miss\000\000\000\000\000\000\000\00000 */
> > +{ 4698 }, /* DCache_L2_All_Hits\000\000l2_rqsts.demand_data_rd_hit + l2_rqsts.pf_hit + l2_rqsts.rfo_hit\000\000\000\000\000\000\000\00000 */
> > +{ 4792 }, /* DCache_L2_All_Miss\000\000max(l2_rqsts.all_demand_data_rd - l2_rqsts.demand_data_rd_hit, 0) + l2_rqsts.pf_miss + l2_rqsts.rfo_miss\000\000\000\000\000\000\000\00000 */
> > +{ 4990 }, /* DCache_L2_Hits\000\000d_ratio(DCache_L2_All_Hits, DCache_L2_All)\000\000\000\000\000\000\000\00000 */
> > +{ 5058 }, /* DCache_L2_Misses\000\000d_ratio(DCache_L2_All_Miss, DCache_L2_All)\000\000\000\000\000\000\000\00000 */
> > +{ 4330 }, /* Frontend_Bound_SMT\000\000idq_uops_not_delivered.core / (4 * (cpu_clk_unhalted.thread / 2 * (1 + cpu_clk_unhalted.one_thread_active / cpu_clk_unhalted.ref_xclk)))\000\000\000\000\000\000\000\00000 */
> > +{ 4267 }, /* IPC\000group1\000inst_retired.any / cpu_clk_unhalted.thread\000\000\000\000\000\000\000\00000 */
> > +{ 5192 }, /* L1D_Cache_Fill_BW\000\00064 * l1d.replacement / 1e9 / duration_time\000\000\000\000\000\000\000\00000 */
> > +{ 5128 }, /* M1\000\000ipc + M2\000\000\000\000\000\000\000\00000 */
> > +{ 5150 }, /* M2\000\000ipc + M1\000\000\000\000\000\000\000\00000 */
> > +{ 5172 }, /* M3\000\0001 / M3\000\000\000\000\000\000\000\00000 */
> > +{ 4627 }, /* cache_miss_cycles\000group1\000dcache_miss_cpi + icache_miss_cycles\000\000\000\000\000\000\000\00000 */
> > +{ 4496 }, /* dcache_miss_cpi\000\000l1d\\-loads\\-misses / inst_retired.any\000\000\000\000\000\000\000\00000 */
> > +{ 4560 }, /* icache_miss_cycles\000\000l1i\\-loads\\-misses / inst_retired.any\000\000\000\000\000\000\000\00000 */
> >
> >  };
> >
> > @@ -181,18 +219,18 @@ const struct pmu_table_entry pmu_metrics__test_soc_cpu[] = {
> >  {
> >       .entries = pmu_metrics__test_soc_cpu_default_core,
> >       .num_entries = ARRAY_SIZE(pmu_metrics__test_soc_cpu_default_core),
> > -     .pmu_name = { 1138 /* default_core\000 */ },
> > +     .pmu_name = { 2679 /* default_core\000 */ },
> >  },
> >  };
> >
> >  static const struct compact_pmu_event pmu_events__test_soc_sys_uncore_sys_ccn_pmu[] = {
> > -{ 2465 }, /* sys_ccn_pmu.read_cycles\000uncore\000ccn read-cycles event\000config=0x2c\0000x01\00000\000\000\000\000\000 */
> > +{ 4006 }, /* sys_ccn_pmu.read_cycles\000uncore\000ccn read-cycles event\000config=0x2c\0000x01\00000\000\000\000\000\000 */
> >  };
> >  static const struct compact_pmu_event pmu_events__test_soc_sys_uncore_sys_cmn_pmu[] = {
> > -{ 2561 }, /* sys_cmn_pmu.hnf_cache_miss\000uncore\000Counts total cache misses in first lookup result (high priority)\000eventid=1,type=5\000(434|436|43c|43a).*\00000\000\000\000\000\000 */
> > +{ 4102 }, /* sys_cmn_pmu.hnf_cache_miss\000uncore\000Counts total cache misses in first lookup result (high priority)\000eventid=1,type=5\000(434|436|43c|43a).*\00000\000\000\000\000\000 */
> >  };
> >  static const struct compact_pmu_event pmu_events__test_soc_sys_uncore_sys_ddr_pmu[] = {
> > -{ 2370 }, /* sys_ddr_pmu.write_cycles\000uncore\000ddr write-cycles event\000event=0x2b\000v8\00000\000\000\000\000\000 */
> > +{ 3911 }, /* sys_ddr_pmu.write_cycles\000uncore\000ddr write-cycles event\000event=0x2b\000v8\00000\000\000\000\000\000 */
> >
> >  };
> >
> > @@ -200,17 +238,17 @@ const struct pmu_table_entry pmu_events__test_soc_sys[] = {
> >  {
> >       .entries = pmu_events__test_soc_sys_uncore_sys_ccn_pmu,
> >       .num_entries = ARRAY_SIZE(pmu_events__test_soc_sys_uncore_sys_ccn_pmu),
> > -     .pmu_name = { 2446 /* uncore_sys_ccn_pmu\000 */ },
> > +     .pmu_name = { 3987 /* uncore_sys_ccn_pmu\000 */ },
> >  },
> >  {
> >       .entries = pmu_events__test_soc_sys_uncore_sys_cmn_pmu,
> >       .num_entries = ARRAY_SIZE(pmu_events__test_soc_sys_uncore_sys_cmn_pmu),
> > -     .pmu_name = { 2542 /* uncore_sys_cmn_pmu\000 */ },
> > +     .pmu_name = { 4083 /* uncore_sys_cmn_pmu\000 */ },
> >  },
> >  {
> >       .entries = pmu_events__test_soc_sys_uncore_sys_ddr_pmu,
> >       .num_entries = ARRAY_SIZE(pmu_events__test_soc_sys_uncore_sys_ddr_pmu),
> > -     .pmu_name = { 2351 /* uncore_sys_ddr_pmu\000 */ },
> > +     .pmu_name = { 3892 /* uncore_sys_ddr_pmu\000 */ },
> >  },
> >  };
> >
> > @@ -632,8 +670,20 @@ static const struct pmu_events_map *map_for_pmu(struct perf_pmu *pmu)
> >  {
> >          struct perf_cpu cpu = {-1};
> >
> > -        if (pmu)
> > +        if (pmu) {
> > +                for (size_t i=0; i < ARRAY_SIZE(pmu_events__common); i++) {
> > +                        const char *pmu_name = &big_c_string[pmu_events__common[i].pmu_name.offset];
> > +
> > +                        if (!strcmp(pmu_name, pmu->name)) {
> > +                                const struct pmu_events_map *map = &pmu_events_map[0];
> > +
> > +                                while (strcmp("common", map->arch))
> > +                                        map++;
> > +                                return map;
> > +                        }
> > +                }
> >                  cpu = perf_cpu_map__min(pmu->cpus);
> > +        }
> >          return map_for_cpu(cpu);
> >  }
> >
> > diff --git a/tools/perf/pmu-events/jevents.py b/tools/perf/pmu-events/jevents.py
> > index e821155151ec..76c1e7b0bc22 100755
> > --- a/tools/perf/pmu-events/jevents.py
> > +++ b/tools/perf/pmu-events/jevents.py
> > @@ -295,6 +295,7 @@ class JsonEvent:
> >            'cpu_atom': 'cpu_atom',
> >            'ali_drw': 'ali_drw',
> >            'arm_cmn': 'arm_cmn',
> > +          'software': 'software',
> >            'tool': 'tool',
> >        }
> >        return table[unit] if unit in table else f'uncore_{unit.lower()}'
> > @@ -1158,8 +1159,20 @@ static const struct pmu_events_map *map_for_pmu(struct perf_pmu *pmu)
> >  {
> >          struct perf_cpu cpu = {-1};
> >
> > -        if (pmu)
> > +        if (pmu) {
> > +                for (size_t i=0; i < ARRAY_SIZE(pmu_events__common); i++) {
> > +                        const char *pmu_name = &big_c_string[pmu_events__common[i].pmu_name.offset];
> > +
> > +                        if (!strcmp(pmu_name, pmu->name)) {
> > +                                const struct pmu_events_map *map = &pmu_events_map[0];
> > +
> > +                                while (strcmp("common", map->arch))
> > +                                        map++;
> > +                                return map;
> > +                        }
> > +                }
> >                  cpu = perf_cpu_map__min(pmu->cpus);
> > +        }
> >          return map_for_cpu(cpu);
> >  }
> >
> > --
> > 2.50.0.727.gbf7dc18ff4-goog
> >

^ permalink raw reply	[flat|nested] 41+ messages in thread

* Re: [PATCH v7 02/16] perf jevents: Add common software event json
  2025-07-23 22:34     ` Ian Rogers
@ 2025-07-24  0:10       ` Namhyung Kim
  2025-07-24  1:47         ` Ian Rogers
  0 siblings, 1 reply; 41+ messages in thread
From: Namhyung Kim @ 2025-07-24  0:10 UTC (permalink / raw)
  To: Ian Rogers
  Cc: Peter Zijlstra, Ingo Molnar, Arnaldo Carvalho de Melo,
	Mark Rutland, Alexander Shishkin, Jiri Olsa, Adrian Hunter,
	Kan Liang, James Clark, Xu Yang, Masami Hiramatsu (Google),
	Collin Funk, Howard Chu, Weilin Wang, Andi Kleen,
	Dr. David Alan Gilbert, Thomas Richter, Tiezhu Yang,
	Gautam Menghani, Thomas Falcon, Chun-Tse Shao, linux-kernel,
	linux-perf-users

On Wed, Jul 23, 2025 at 03:34:07PM -0700, Ian Rogers wrote:
> On Wed, Jul 23, 2025 at 11:24 AM Namhyung Kim <namhyung@kernel.org> wrote:
> >
> > On Mon, Jul 14, 2025 at 09:43:50AM -0700, Ian Rogers wrote:
> > > Add json for software events so that in perf list the events can have
> > > a description.  Common json exists for the tool PMU but it has no
> > > sysfs equivalent. Modify the map_for_pmu code to return the common map
> > > (rather than an architecture specific one) when a PMU with a common
> > > name is being looked for, this allows the events to be found.
> >
> > Can you please share new output of `perf list sw`?  I'm glad we have
> > description for software events.  But I'm also curious what's the side
> > effect of having them in JSON - maybe case insensitivity?
> 
> The old software event names were matched in the lex code and were
> case sensitive. The events in the json are case insensitive and the
> case insensitive lex ones are removed in the next patch.

And then it'd also use wildcard match, right?

> 
> The perf list output looks like:
> 
> Before:
> ```
> List of pre-defined events (to be used in -e or -M):
> 
>   branch-instructions OR branches                    [Hardware event]
>   branch-misses                                      [Hardware event]
>   bus-cycles                                         [Hardware event]
>   cache-misses                                       [Hardware event]
>   cache-references                                   [Hardware event]
>   cpu-cycles OR cycles                               [Hardware event]
>   instructions                                       [Hardware event]
>   ref-cycles                                         [Hardware event]
>   alignment-faults                                   [Software event]
>   bpf-output                                         [Software event]
>   cgroup-switches                                    [Software event]
>   context-switches OR cs                             [Software event]
>   cpu-clock                                          [Software event]
>   cpu-migrations OR migrations                       [Software event]
>   dummy                                              [Software event]
>   emulation-faults                                   [Software event]
>   major-faults                                       [Software event]
>   minor-faults                                       [Software event]
>   page-faults OR faults                              [Software event]
>   task-clock                                         [Software event]
> ```
> 
> After:
> ```
> List of pre-defined events (to be used in -e or -M):
> 
>   branch-instructions OR branches                    [Hardware event]
>   branch-misses                                      [Hardware event]
>   bus-cycles                                         [Hardware event]
>   cache-misses                                       [Hardware event]
>   cache-references                                   [Hardware event]
>   cpu-cycles OR cycles                               [Hardware event]
>   instructions                                       [Hardware event]
>   ref-cycles                                         [Hardware event]
>   alignment-faults                                   [Software event]
>   bpf-output                                         [Software event]
>   cgroup-switches                                    [Software event]
>   context-switches OR cs                             [Software event]
>   cpu-clock                                          [Software event]
>   cpu-migrations OR migrations                       [Software event]
>   dummy                                              [Software event]
>   emulation-faults                                   [Software event]
>   major-faults                                       [Software event]
>   minor-faults                                       [Software event]
>   page-faults OR faults                              [Software event]
>   task-clock                                         [Software event]
> ...
> software:
>   alignment-faults
>        [Number of kernel handled memory alignment faults. Unit: software]
>   bpf-output
>        [An event used by BPF programs to write to the perf ring
> buffer. Unit: software]
>   cgroup-switches
>        [Number of context switches to a task in a different cgroup.
> Unit: software]
>   context-switches
>        [Number of context switches [This event is an alias of cs].
> Unit: software]
>   cpu-clock
>        [Per-CPU high-resolution timer based event. Unit: software]
>   cpu-migrations
>        [Number of times a process has migrated to a new CPU [This
> event is an alias of migrations]. Unit: software]
>   cs
>        [Number of context switches [This event is an alias of
> context-switches]. Unit: software]
>   dummy
>        [A placeholder event that doesn't count anything. Unit: software]
>   emulation-faults
>        [Number of kernel handled unimplemented instruction faults
> handled through emulation. Unit: software]
>   faults
>        [Number of page faults [This event is an alias of page-faults].
> Unit: software]
>   major-faults
>        [Number of major page faults. Major faults require I/O to
> handle. Unit: software]
>   migrations
>        [Number of times a process has migrated to a new CPU [This
> event is an alias of cpu-migrations]. Unit: software]
>   minor-faults
>        [Number of minor page faults. Minor faults don't require I/O to
> handle. Unit: software]
>   page-faults
>        [Number of page faults [This event is an alias of faults].
> Unit: software]
>   task-clock
>        [Task based high-resolution timer based event. Unit: software]
> ...
> ```
> The next patch will make this just:
> ```
> List of pre-defined events (to be used in -e or -M):
> 
>   branch-instructions OR branches                    [Hardware event]
>   branch-misses                                      [Hardware event]
>   bus-cycles                                         [Hardware event]
>   cache-misses                                       [Hardware event]
>   cache-references                                   [Hardware event]
>   cpu-cycles OR cycles                               [Hardware event]
>   instructions                                       [Hardware event]
>   ref-cycles                                         [Hardware event]
> ...
> software:
>   alignment-faults
>        [Number of kernel handled memory alignment faults. Unit: software]
>   bpf-output
>        [An event used by BPF programs to write to the perf ring
> buffer. Unit: software]
>   cgroup-switches
>        [Number of context switches to a task in a different cgroup.
> Unit: software]
>   context-switches
>        [Number of context switches [This event is an alias of cs].

Hmm.. can we just use parentheses for the alias?


> Unit: software]
>   cpu-clock
>        [Per-CPU high-resolution timer based event. Unit: software]
>   cpu-migrations
>        [Number of times a process has migrated to a new CPU [This
> event is an alias of migrations]. Unit: software]
>   cs
>        [Number of context switches [This event is an alias of
> context-switches]. Unit: software]
>   dummy
>        [A placeholder event that doesn't count anything. Unit: software]
>   emulation-faults
>        [Number of kernel handled unimplemented instruction faults
> handled through emulation. Unit: software]
>   faults
>        [Number of page faults [This event is an alias of page-faults].
> Unit: software]
>   major-faults
>        [Number of major page faults. Major faults require I/O to
> handle. Unit: software]
>   migrations
>        [Number of times a process has migrated to a new CPU [This
> event is an alias of cpu-migrations]. Unit: software]
>   minor-faults
>        [Number of minor page faults. Minor faults don't require I/O to
> handle. Unit: software]
>   page-faults
>        [Number of page faults [This event is an alias of faults].
> Unit: software]
>   task-clock
>        [Task based high-resolution timer based event. Unit: software]
> ...
> ```

Will `perf list sw` include these output?  And please add this to the
commit message.

> > >
> > > Signed-off-by: Ian Rogers <irogers@google.com>
> > > ---
> > >  .../arch/common/common/software.json          |  92 ++++++
> > >  tools/perf/pmu-events/empty-pmu-events.c      | 266 +++++++++++-------
> > >  tools/perf/pmu-events/jevents.py              |  15 +-
> > >  3 files changed, 264 insertions(+), 109 deletions(-)
> > >  create mode 100644 tools/perf/pmu-events/arch/common/common/software.json
> > >
> > > diff --git a/tools/perf/pmu-events/arch/common/common/software.json b/tools/perf/pmu-events/arch/common/common/software.json
> > > new file mode 100644
> > > index 000000000000..3af2f565a601
> > > --- /dev/null
> > > +++ b/tools/perf/pmu-events/arch/common/common/software.json
> > > @@ -0,0 +1,92 @@
> > > +[
> > > +  {
> > > +    "Unit": "software",
> > > +    "EventName": "cpu-clock",
> > > +    "BriefDescription": "Per-CPU high-resolution timer based event",
> > > +    "ConfigCode": "0"
> > > +  },
> > > +  {
> > > +    "Unit": "software",
> > > +    "EventName": "task-clock",
> > > +    "BriefDescription": "Task based high-resolution timer based event",
> >
> > s/Task based/Per-task/ ?
> 
> Will fix it in the next version.
> 
> >
> > > +    "ConfigCode": "1"
> > > +  },
> > > +  {
> > > +    "Unit": "software",
> > > +    "EventName": "faults",
> > > +    "BriefDescription": "Number of page faults [This event is an alias of page-faults]",
> > > +    "ConfigCode": "2"
> >
> > It'd be nice if it can handle aliases without adding a new entry.  But I
> > guess it requires non-trivial changes.
> 
> It is a limitation of the perf json format. There's no reason not to
> add some notion of aliases, I believe it was done this way inheriting
> from how Intel did it.

Ok, I think it's fine for now.

Thanks,
Namhyung

> >
> > > +  },
> > > +  {
> > > +    "Unit": "software",
> > > +    "EventName": "page-faults",
> > > +    "BriefDescription": "Number of page faults [This event is an alias of faults]",
> > > +    "ConfigCode": "2"
> > > +  },
> > > +  {
> > > +    "Unit": "software",
> > > +    "EventName": "context-switches",
> > > +    "BriefDescription": "Number of context switches [This event is an alias of cs]",
> > > +    "ConfigCode": "3"
> > > +  },
> > > +  {
> > > +    "Unit": "software",
> > > +    "EventName": "cs",
> > > +    "BriefDescription": "Number of context switches [This event is an alias of context-switches]",
> > > +    "ConfigCode": "3"
> > > +  },
> > > +  {
> > > +    "Unit": "software",
> > > +    "EventName": "cpu-migrations",
> > > +    "BriefDescription": "Number of times a process has migrated to a new CPU [This event is an alias of migrations]",
> > > +    "ConfigCode": "4"
> > > +  },
> > > +  {
> > > +    "Unit": "software",
> > > +    "EventName": "migrations",
> > > +    "BriefDescription": "Number of times a process has migrated to a new CPU [This event is an alias of cpu-migrations]",
> > > +    "ConfigCode": "4"
> > > +  },
> > > +  {
> > > +    "Unit": "software",
> > > +    "EventName": "minor-faults",
> > > +    "BriefDescription": "Number of minor page faults. Minor faults don't require I/O to handle",
> > > +    "ConfigCode": "5"
> > > +  },
> > > +  {
> > > +    "Unit": "software",
> > > +    "EventName": "major-faults",
> > > +    "BriefDescription": "Number of major page faults. Major faults require I/O to handle",
> > > +    "ConfigCode": "6"
> > > +  },
> > > +  {
> > > +    "Unit": "software",
> > > +    "EventName": "alignment-faults",
> > > +    "BriefDescription": "Number of kernel handled memory alignment faults",
> > > +    "ConfigCode": "7"
> > > +  },
> > > +  {
> > > +    "Unit": "software",
> > > +    "EventName": "emulation-faults",
> > > +    "BriefDescription": "Number of kernel handled unimplemented instruction faults handled through emulation",
> > > +    "ConfigCode": "8"
> > > +  },
> > > +  {
> > > +    "Unit": "software",
> > > +    "EventName": "dummy",
> > > +    "BriefDescription": "A placeholder event that doesn't count anything",
> > > +    "ConfigCode": "9"
> > > +  },
> > > +  {
> > > +    "Unit": "software",
> > > +    "EventName": "bpf-output",
> > > +    "BriefDescription": "An event used by BPF programs to write to the perf ring buffer",
> > > +    "ConfigCode": "10"
> > > +  },
> > > +  {
> > > +    "Unit": "software",
> > > +    "EventName": "cgroup-switches",
> > > +    "BriefDescription": "Number of context switches to a task in a different cgroup",
> > > +    "ConfigCode": "11"
> > > +  }
> > > +]
> > > diff --git a/tools/perf/pmu-events/empty-pmu-events.c b/tools/perf/pmu-events/empty-pmu-events.c
> > > index a4569a74db07..7d179d703ab1 100644
> > > --- a/tools/perf/pmu-events/empty-pmu-events.c
> > > +++ b/tools/perf/pmu-events/empty-pmu-events.c
> > > @@ -19,109 +19,147 @@ struct pmu_table_entry {
> > >  };
> > >
> > >  static const char *const big_c_string =
> > > -/* offset=0 */ "tool\000"
> > > -/* offset=5 */ "duration_time\000tool\000Wall clock interval time in nanoseconds\000config=1\000\00000\000\000\000\000\000"
> > > -/* offset=81 */ "user_time\000tool\000User (non-kernel) time in nanoseconds\000config=2\000\00000\000\000\000\000\000"
> > > -/* offset=151 */ "system_time\000tool\000System/kernel time in nanoseconds\000config=3\000\00000\000\000\000\000\000"
> > > -/* offset=219 */ "has_pmem\000tool\0001 if persistent memory installed otherwise 0\000config=4\000\00000\000\000\000\000\000"
> > > -/* offset=295 */ "num_cores\000tool\000Number of cores. A core consists of 1 or more thread, with each thread being associated with a logical Linux CPU\000config=5\000\00000\000\000\000\000\000"
> > > -/* offset=440 */ "num_cpus\000tool\000Number of logical Linux CPUs. There may be multiple such CPUs on a core\000config=6\000\00000\000\000\000\000\000"
> > > -/* offset=543 */ "num_cpus_online\000tool\000Number of online logical Linux CPUs. There may be multiple such CPUs on a core\000config=7\000\00000\000\000\000\000\000"
> > > -/* offset=660 */ "num_dies\000tool\000Number of dies. Each die has 1 or more cores\000config=8\000\00000\000\000\000\000\000"
> > > -/* offset=736 */ "num_packages\000tool\000Number of packages. Each package has 1 or more die\000config=9\000\00000\000\000\000\000\000"
> > > -/* offset=822 */ "slots\000tool\000Number of functional units that in parallel can execute parts of an instruction\000config=0xa\000\00000\000\000\000\000\000"
> > > -/* offset=932 */ "smt_on\000tool\0001 if simultaneous multithreading (aka hyperthreading) is enable otherwise 0\000config=0xb\000\00000\000\000\000\000\000"
> > > -/* offset=1039 */ "system_tsc_freq\000tool\000The amount a Time Stamp Counter (TSC) increases per second\000config=0xc\000\00000\000\000\000\000\000"
> > > -/* offset=1138 */ "default_core\000"
> > > -/* offset=1151 */ "bp_l1_btb_correct\000branch\000L1 BTB Correction\000event=0x8a\000\00000\000\000\000\000\000"
> > > -/* offset=1213 */ "bp_l2_btb_correct\000branch\000L2 BTB Correction\000event=0x8b\000\00000\000\000\000\000\000"
> > > -/* offset=1275 */ "l3_cache_rd\000cache\000L3 cache access, read\000event=0x40\000\00000\000\000\000\000Attributable Level 3 cache access, read\000"
> > > -/* offset=1373 */ "segment_reg_loads.any\000other\000Number of segment register loads\000event=6,period=200000,umask=0x80\000\00000\000\000\000\000\000"
> > > -/* offset=1475 */ "dispatch_blocked.any\000other\000Memory cluster signals to block micro-op dispatch for any reason\000event=9,period=200000,umask=0x20\000\00000\000\000\000\000\000"
> > > -/* offset=1608 */ "eist_trans\000other\000Number of Enhanced Intel SpeedStep(R) Technology (EIST) transitions\000event=0x3a,period=200000\000\00000\000\000\000\000\000"
> > > -/* offset=1726 */ "hisi_sccl,ddrc\000"
> > > -/* offset=1741 */ "uncore_hisi_ddrc.flux_wcmd\000uncore\000DDRC write commands\000event=2\000\00000\000\000\000\000\000"
> > > -/* offset=1811 */ "uncore_cbox\000"
> > > -/* offset=1823 */ "unc_cbo_xsnp_response.miss_eviction\000uncore\000A cross-core snoop resulted from L3 Eviction which misses in some processor core\000event=0x22,umask=0x81\000\00000\000\000\000\000\000"
> > > -/* offset=1977 */ "event-hyphen\000uncore\000UNC_CBO_HYPHEN\000event=0xe0\000\00000\000\000\000\000\000"
> > > -/* offset=2031 */ "event-two-hyph\000uncore\000UNC_CBO_TWO_HYPH\000event=0xc0\000\00000\000\000\000\000\000"
> > > -/* offset=2089 */ "hisi_sccl,l3c\000"
> > > -/* offset=2103 */ "uncore_hisi_l3c.rd_hit_cpipe\000uncore\000Total read hits\000event=7\000\00000\000\000\000\000\000"
> > > -/* offset=2171 */ "uncore_imc_free_running\000"
> > > -/* offset=2195 */ "uncore_imc_free_running.cache_miss\000uncore\000Total cache misses\000event=0x12\000\00000\000\000\000\000\000"
> > > -/* offset=2275 */ "uncore_imc\000"
> > > -/* offset=2286 */ "uncore_imc.cache_hits\000uncore\000Total cache hits\000event=0x34\000\00000\000\000\000\000\000"
> > > -/* offset=2351 */ "uncore_sys_ddr_pmu\000"
> > > -/* offset=2370 */ "sys_ddr_pmu.write_cycles\000uncore\000ddr write-cycles event\000event=0x2b\000v8\00000\000\000\000\000\000"
> > > -/* offset=2446 */ "uncore_sys_ccn_pmu\000"
> > > -/* offset=2465 */ "sys_ccn_pmu.read_cycles\000uncore\000ccn read-cycles event\000config=0x2c\0000x01\00000\000\000\000\000\000"
> > > -/* offset=2542 */ "uncore_sys_cmn_pmu\000"
> > > -/* offset=2561 */ "sys_cmn_pmu.hnf_cache_miss\000uncore\000Counts total cache misses in first lookup result (high priority)\000eventid=1,type=5\000(434|436|43c|43a).*\00000\000\000\000\000\000"
> > > -/* offset=2704 */ "CPI\000\0001 / IPC\000\000\000\000\000\000\000\00000"
> > > -/* offset=2726 */ "IPC\000group1\000inst_retired.any / cpu_clk_unhalted.thread\000\000\000\000\000\000\000\00000"
> > > -/* offset=2789 */ "Frontend_Bound_SMT\000\000idq_uops_not_delivered.core / (4 * (cpu_clk_unhalted.thread / 2 * (1 + cpu_clk_unhalted.one_thread_active / cpu_clk_unhalted.ref_xclk)))\000\000\000\000\000\000\000\00000"
> > > -/* offset=2955 */ "dcache_miss_cpi\000\000l1d\\-loads\\-misses / inst_retired.any\000\000\000\000\000\000\000\00000"
> > > -/* offset=3019 */ "icache_miss_cycles\000\000l1i\\-loads\\-misses / inst_retired.any\000\000\000\000\000\000\000\00000"
> > > -/* offset=3086 */ "cache_miss_cycles\000group1\000dcache_miss_cpi + icache_miss_cycles\000\000\000\000\000\000\000\00000"
> > > -/* offset=3157 */ "DCache_L2_All_Hits\000\000l2_rqsts.demand_data_rd_hit + l2_rqsts.pf_hit + l2_rqsts.rfo_hit\000\000\000\000\000\000\000\00000"
> > > -/* offset=3251 */ "DCache_L2_All_Miss\000\000max(l2_rqsts.all_demand_data_rd - l2_rqsts.demand_data_rd_hit, 0) + l2_rqsts.pf_miss + l2_rqsts.rfo_miss\000\000\000\000\000\000\000\00000"
> > > -/* offset=3385 */ "DCache_L2_All\000\000DCache_L2_All_Hits + DCache_L2_All_Miss\000\000\000\000\000\000\000\00000"
> > > -/* offset=3449 */ "DCache_L2_Hits\000\000d_ratio(DCache_L2_All_Hits, DCache_L2_All)\000\000\000\000\000\000\000\00000"
> > > -/* offset=3517 */ "DCache_L2_Misses\000\000d_ratio(DCache_L2_All_Miss, DCache_L2_All)\000\000\000\000\000\000\000\00000"
> > > -/* offset=3587 */ "M1\000\000ipc + M2\000\000\000\000\000\000\000\00000"
> > > -/* offset=3609 */ "M2\000\000ipc + M1\000\000\000\000\000\000\000\00000"
> > > -/* offset=3631 */ "M3\000\0001 / M3\000\000\000\000\000\000\000\00000"
> > > -/* offset=3651 */ "L1D_Cache_Fill_BW\000\00064 * l1d.replacement / 1e9 / duration_time\000\000\000\000\000\000\000\00000"
> > > +/* offset=0 */ "software\000"
> > > +/* offset=9 */ "cpu-clock\000software\000Per-CPU high-resolution timer based event\000config=0\000\00000\000\000\000\000\000"
> > > +/* offset=87 */ "task-clock\000software\000Task based high-resolution timer based event\000config=1\000\00000\000\000\000\000\000"
> > > +/* offset=169 */ "faults\000software\000Number of page faults [This event is an alias of page-faults]\000config=2\000\00000\000\000\000\000\000"
> > > +/* offset=264 */ "page-faults\000software\000Number of page faults [This event is an alias of faults]\000config=2\000\00000\000\000\000\000\000"
> > > +/* offset=359 */ "context-switches\000software\000Number of context switches [This event is an alias of cs]\000config=3\000\00000\000\000\000\000\000"
> > > +/* offset=460 */ "cs\000software\000Number of context switches [This event is an alias of context-switches]\000config=3\000\00000\000\000\000\000\000"
> > > +/* offset=561 */ "cpu-migrations\000software\000Number of times a process has migrated to a new CPU [This event is an alias of migrations]\000config=4\000\00000\000\000\000\000\000"
> > > +/* offset=693 */ "migrations\000software\000Number of times a process has migrated to a new CPU [This event is an alias of cpu-migrations]\000config=4\000\00000\000\000\000\000\000"
> > > +/* offset=825 */ "minor-faults\000software\000Number of minor page faults. Minor faults don't require I/O to handle\000config=5\000\00000\000\000\000\000\000"
> > > +/* offset=934 */ "major-faults\000software\000Number of major page faults. Major faults require I/O to handle\000config=6\000\00000\000\000\000\000\000"
> > > +/* offset=1037 */ "alignment-faults\000software\000Number of kernel handled memory alignment faults\000config=7\000\00000\000\000\000\000\000"
> > > +/* offset=1129 */ "emulation-faults\000software\000Number of kernel handled unimplemented instruction faults handled through emulation\000config=8\000\00000\000\000\000\000\000"
> > > +/* offset=1256 */ "dummy\000software\000A placeholder event that doesn't count anything\000config=9\000\00000\000\000\000\000\000"
> > > +/* offset=1336 */ "bpf-output\000software\000An event used by BPF programs to write to the perf ring buffer\000config=0xa\000\00000\000\000\000\000\000"
> > > +/* offset=1438 */ "cgroup-switches\000software\000Number of context switches to a task in a different cgroup\000config=0xb\000\00000\000\000\000\000\000"
> > > +/* offset=1541 */ "tool\000"
> > > +/* offset=1546 */ "duration_time\000tool\000Wall clock interval time in nanoseconds\000config=1\000\00000\000\000\000\000\000"
> > > +/* offset=1622 */ "user_time\000tool\000User (non-kernel) time in nanoseconds\000config=2\000\00000\000\000\000\000\000"
> > > +/* offset=1692 */ "system_time\000tool\000System/kernel time in nanoseconds\000config=3\000\00000\000\000\000\000\000"
> > > +/* offset=1760 */ "has_pmem\000tool\0001 if persistent memory installed otherwise 0\000config=4\000\00000\000\000\000\000\000"
> > > +/* offset=1836 */ "num_cores\000tool\000Number of cores. A core consists of 1 or more thread, with each thread being associated with a logical Linux CPU\000config=5\000\00000\000\000\000\000\000"
> > > +/* offset=1981 */ "num_cpus\000tool\000Number of logical Linux CPUs. There may be multiple such CPUs on a core\000config=6\000\00000\000\000\000\000\000"
> > > +/* offset=2084 */ "num_cpus_online\000tool\000Number of online logical Linux CPUs. There may be multiple such CPUs on a core\000config=7\000\00000\000\000\000\000\000"
> > > +/* offset=2201 */ "num_dies\000tool\000Number of dies. Each die has 1 or more cores\000config=8\000\00000\000\000\000\000\000"
> > > +/* offset=2277 */ "num_packages\000tool\000Number of packages. Each package has 1 or more die\000config=9\000\00000\000\000\000\000\000"
> > > +/* offset=2363 */ "slots\000tool\000Number of functional units that in parallel can execute parts of an instruction\000config=0xa\000\00000\000\000\000\000\000"
> > > +/* offset=2473 */ "smt_on\000tool\0001 if simultaneous multithreading (aka hyperthreading) is enable otherwise 0\000config=0xb\000\00000\000\000\000\000\000"
> > > +/* offset=2580 */ "system_tsc_freq\000tool\000The amount a Time Stamp Counter (TSC) increases per second\000config=0xc\000\00000\000\000\000\000\000"
> > > +/* offset=2679 */ "default_core\000"
> > > +/* offset=2692 */ "bp_l1_btb_correct\000branch\000L1 BTB Correction\000event=0x8a\000\00000\000\000\000\000\000"
> > > +/* offset=2754 */ "bp_l2_btb_correct\000branch\000L2 BTB Correction\000event=0x8b\000\00000\000\000\000\000\000"
> > > +/* offset=2816 */ "l3_cache_rd\000cache\000L3 cache access, read\000event=0x40\000\00000\000\000\000\000Attributable Level 3 cache access, read\000"
> > > +/* offset=2914 */ "segment_reg_loads.any\000other\000Number of segment register loads\000event=6,period=200000,umask=0x80\000\00000\000\000\000\000\000"
> > > +/* offset=3016 */ "dispatch_blocked.any\000other\000Memory cluster signals to block micro-op dispatch for any reason\000event=9,period=200000,umask=0x20\000\00000\000\000\000\000\000"
> > > +/* offset=3149 */ "eist_trans\000other\000Number of Enhanced Intel SpeedStep(R) Technology (EIST) transitions\000event=0x3a,period=200000\000\00000\000\000\000\000\000"
> > > +/* offset=3267 */ "hisi_sccl,ddrc\000"
> > > +/* offset=3282 */ "uncore_hisi_ddrc.flux_wcmd\000uncore\000DDRC write commands\000event=2\000\00000\000\000\000\000\000"
> > > +/* offset=3352 */ "uncore_cbox\000"
> > > +/* offset=3364 */ "unc_cbo_xsnp_response.miss_eviction\000uncore\000A cross-core snoop resulted from L3 Eviction which misses in some processor core\000event=0x22,umask=0x81\000\00000\000\000\000\000\000"
> > > +/* offset=3518 */ "event-hyphen\000uncore\000UNC_CBO_HYPHEN\000event=0xe0\000\00000\000\000\000\000\000"
> > > +/* offset=3572 */ "event-two-hyph\000uncore\000UNC_CBO_TWO_HYPH\000event=0xc0\000\00000\000\000\000\000\000"
> > > +/* offset=3630 */ "hisi_sccl,l3c\000"
> > > +/* offset=3644 */ "uncore_hisi_l3c.rd_hit_cpipe\000uncore\000Total read hits\000event=7\000\00000\000\000\000\000\000"
> > > +/* offset=3712 */ "uncore_imc_free_running\000"
> > > +/* offset=3736 */ "uncore_imc_free_running.cache_miss\000uncore\000Total cache misses\000event=0x12\000\00000\000\000\000\000\000"
> > > +/* offset=3816 */ "uncore_imc\000"
> > > +/* offset=3827 */ "uncore_imc.cache_hits\000uncore\000Total cache hits\000event=0x34\000\00000\000\000\000\000\000"
> > > +/* offset=3892 */ "uncore_sys_ddr_pmu\000"
> > > +/* offset=3911 */ "sys_ddr_pmu.write_cycles\000uncore\000ddr write-cycles event\000event=0x2b\000v8\00000\000\000\000\000\000"
> > > +/* offset=3987 */ "uncore_sys_ccn_pmu\000"
> > > +/* offset=4006 */ "sys_ccn_pmu.read_cycles\000uncore\000ccn read-cycles event\000config=0x2c\0000x01\00000\000\000\000\000\000"
> > > +/* offset=4083 */ "uncore_sys_cmn_pmu\000"
> > > +/* offset=4102 */ "sys_cmn_pmu.hnf_cache_miss\000uncore\000Counts total cache misses in first lookup result (high priority)\000eventid=1,type=5\000(434|436|43c|43a).*\00000\000\000\000\000\000"
> > > +/* offset=4245 */ "CPI\000\0001 / IPC\000\000\000\000\000\000\000\00000"
> > > +/* offset=4267 */ "IPC\000group1\000inst_retired.any / cpu_clk_unhalted.thread\000\000\000\000\000\000\000\00000"
> > > +/* offset=4330 */ "Frontend_Bound_SMT\000\000idq_uops_not_delivered.core / (4 * (cpu_clk_unhalted.thread / 2 * (1 + cpu_clk_unhalted.one_thread_active / cpu_clk_unhalted.ref_xclk)))\000\000\000\000\000\000\000\00000"
> > > +/* offset=4496 */ "dcache_miss_cpi\000\000l1d\\-loads\\-misses / inst_retired.any\000\000\000\000\000\000\000\00000"
> > > +/* offset=4560 */ "icache_miss_cycles\000\000l1i\\-loads\\-misses / inst_retired.any\000\000\000\000\000\000\000\00000"
> > > +/* offset=4627 */ "cache_miss_cycles\000group1\000dcache_miss_cpi + icache_miss_cycles\000\000\000\000\000\000\000\00000"
> > > +/* offset=4698 */ "DCache_L2_All_Hits\000\000l2_rqsts.demand_data_rd_hit + l2_rqsts.pf_hit + l2_rqsts.rfo_hit\000\000\000\000\000\000\000\00000"
> > > +/* offset=4792 */ "DCache_L2_All_Miss\000\000max(l2_rqsts.all_demand_data_rd - l2_rqsts.demand_data_rd_hit, 0) + l2_rqsts.pf_miss + l2_rqsts.rfo_miss\000\000\000\000\000\000\000\00000"
> > > +/* offset=4926 */ "DCache_L2_All\000\000DCache_L2_All_Hits + DCache_L2_All_Miss\000\000\000\000\000\000\000\00000"
> > > +/* offset=4990 */ "DCache_L2_Hits\000\000d_ratio(DCache_L2_All_Hits, DCache_L2_All)\000\000\000\000\000\000\000\00000"
> > > +/* offset=5058 */ "DCache_L2_Misses\000\000d_ratio(DCache_L2_All_Miss, DCache_L2_All)\000\000\000\000\000\000\000\00000"
> > > +/* offset=5128 */ "M1\000\000ipc + M2\000\000\000\000\000\000\000\00000"
> > > +/* offset=5150 */ "M2\000\000ipc + M1\000\000\000\000\000\000\000\00000"
> > > +/* offset=5172 */ "M3\000\0001 / M3\000\000\000\000\000\000\000\00000"
> > > +/* offset=5192 */ "L1D_Cache_Fill_BW\000\00064 * l1d.replacement / 1e9 / duration_time\000\000\000\000\000\000\000\00000"
> > >  ;
> > >
> > > +static const struct compact_pmu_event pmu_events__common_software[] = {
> > > +{ 1037 }, /* alignment-faults\000software\000Number of kernel handled memory alignment faults\000config=7\000\00000\000\000\000\000\000 */
> > > +{ 1336 }, /* bpf-output\000software\000An event used by BPF programs to write to the perf ring buffer\000config=0xa\000\00000\000\000\000\000\000 */
> > > +{ 1438 }, /* cgroup-switches\000software\000Number of context switches to a task in a different cgroup\000config=0xb\000\00000\000\000\000\000\000 */
> > > +{ 359 }, /* context-switches\000software\000Number of context switches [This event is an alias of cs]\000config=3\000\00000\000\000\000\000\000 */
> > > +{ 9 }, /* cpu-clock\000software\000Per-CPU high-resolution timer based event\000config=0\000\00000\000\000\000\000\000 */
> > > +{ 561 }, /* cpu-migrations\000software\000Number of times a process has migrated to a new CPU [This event is an alias of migrations]\000config=4\000\00000\000\000\000\000\000 */
> > > +{ 460 }, /* cs\000software\000Number of context switches [This event is an alias of context-switches]\000config=3\000\00000\000\000\000\000\000 */
> > > +{ 1256 }, /* dummy\000software\000A placeholder event that doesn't count anything\000config=9\000\00000\000\000\000\000\000 */
> > > +{ 1129 }, /* emulation-faults\000software\000Number of kernel handled unimplemented instruction faults handled through emulation\000config=8\000\00000\000\000\000\000\000 */
> > > +{ 169 }, /* faults\000software\000Number of page faults [This event is an alias of page-faults]\000config=2\000\00000\000\000\000\000\000 */
> > > +{ 934 }, /* major-faults\000software\000Number of major page faults. Major faults require I/O to handle\000config=6\000\00000\000\000\000\000\000 */
> > > +{ 693 }, /* migrations\000software\000Number of times a process has migrated to a new CPU [This event is an alias of cpu-migrations]\000config=4\000\00000\000\000\000\000\000 */
> > > +{ 825 }, /* minor-faults\000software\000Number of minor page faults. Minor faults don't require I/O to handle\000config=5\000\00000\000\000\000\000\000 */
> > > +{ 264 }, /* page-faults\000software\000Number of page faults [This event is an alias of faults]\000config=2\000\00000\000\000\000\000\000 */
> > > +{ 87 }, /* task-clock\000software\000Task based high-resolution timer based event\000config=1\000\00000\000\000\000\000\000 */
> > > +};
> > >  static const struct compact_pmu_event pmu_events__common_tool[] = {
> > > -{ 5 }, /* duration_time\000tool\000Wall clock interval time in nanoseconds\000config=1\000\00000\000\000\000\000\000 */
> > > -{ 219 }, /* has_pmem\000tool\0001 if persistent memory installed otherwise 0\000config=4\000\00000\000\000\000\000\000 */
> > > -{ 295 }, /* num_cores\000tool\000Number of cores. A core consists of 1 or more thread, with each thread being associated with a logical Linux CPU\000config=5\000\00000\000\000\000\000\000 */
> > > -{ 440 }, /* num_cpus\000tool\000Number of logical Linux CPUs. There may be multiple such CPUs on a core\000config=6\000\00000\000\000\000\000\000 */
> > > -{ 543 }, /* num_cpus_online\000tool\000Number of online logical Linux CPUs. There may be multiple such CPUs on a core\000config=7\000\00000\000\000\000\000\000 */
> > > -{ 660 }, /* num_dies\000tool\000Number of dies. Each die has 1 or more cores\000config=8\000\00000\000\000\000\000\000 */
> > > -{ 736 }, /* num_packages\000tool\000Number of packages. Each package has 1 or more die\000config=9\000\00000\000\000\000\000\000 */
> > > -{ 822 }, /* slots\000tool\000Number of functional units that in parallel can execute parts of an instruction\000config=0xa\000\00000\000\000\000\000\000 */
> > > -{ 932 }, /* smt_on\000tool\0001 if simultaneous multithreading (aka hyperthreading) is enable otherwise 0\000config=0xb\000\00000\000\000\000\000\000 */
> > > -{ 151 }, /* system_time\000tool\000System/kernel time in nanoseconds\000config=3\000\00000\000\000\000\000\000 */
> > > -{ 1039 }, /* system_tsc_freq\000tool\000The amount a Time Stamp Counter (TSC) increases per second\000config=0xc\000\00000\000\000\000\000\000 */
> > > -{ 81 }, /* user_time\000tool\000User (non-kernel) time in nanoseconds\000config=2\000\00000\000\000\000\000\000 */
> > > +{ 1546 }, /* duration_time\000tool\000Wall clock interval time in nanoseconds\000config=1\000\00000\000\000\000\000\000 */
> > > +{ 1760 }, /* has_pmem\000tool\0001 if persistent memory installed otherwise 0\000config=4\000\00000\000\000\000\000\000 */
> > > +{ 1836 }, /* num_cores\000tool\000Number of cores. A core consists of 1 or more thread, with each thread being associated with a logical Linux CPU\000config=5\000\00000\000\000\000\000\000 */
> > > +{ 1981 }, /* num_cpus\000tool\000Number of logical Linux CPUs. There may be multiple such CPUs on a core\000config=6\000\00000\000\000\000\000\000 */
> > > +{ 2084 }, /* num_cpus_online\000tool\000Number of online logical Linux CPUs. There may be multiple such CPUs on a core\000config=7\000\00000\000\000\000\000\000 */
> > > +{ 2201 }, /* num_dies\000tool\000Number of dies. Each die has 1 or more cores\000config=8\000\00000\000\000\000\000\000 */
> > > +{ 2277 }, /* num_packages\000tool\000Number of packages. Each package has 1 or more die\000config=9\000\00000\000\000\000\000\000 */
> > > +{ 2363 }, /* slots\000tool\000Number of functional units that in parallel can execute parts of an instruction\000config=0xa\000\00000\000\000\000\000\000 */
> > > +{ 2473 }, /* smt_on\000tool\0001 if simultaneous multithreading (aka hyperthreading) is enable otherwise 0\000config=0xb\000\00000\000\000\000\000\000 */
> > > +{ 1692 }, /* system_time\000tool\000System/kernel time in nanoseconds\000config=3\000\00000\000\000\000\000\000 */
> > > +{ 2580 }, /* system_tsc_freq\000tool\000The amount a Time Stamp Counter (TSC) increases per second\000config=0xc\000\00000\000\000\000\000\000 */
> > > +{ 1622 }, /* user_time\000tool\000User (non-kernel) time in nanoseconds\000config=2\000\00000\000\000\000\000\000 */
> > >
> > >  };
> > >
> > >  const struct pmu_table_entry pmu_events__common[] = {
> > > +{
> > > +     .entries = pmu_events__common_software,
> > > +     .num_entries = ARRAY_SIZE(pmu_events__common_software),
> > > +     .pmu_name = { 0 /* software\000 */ },
> > > +},
> > >  {
> > >       .entries = pmu_events__common_tool,
> > >       .num_entries = ARRAY_SIZE(pmu_events__common_tool),
> > > -     .pmu_name = { 0 /* tool\000 */ },
> > > +     .pmu_name = { 1541 /* tool\000 */ },
> > >  },
> > >  };
> > >
> > >  static const struct compact_pmu_event pmu_events__test_soc_cpu_default_core[] = {
> > > -{ 1151 }, /* bp_l1_btb_correct\000branch\000L1 BTB Correction\000event=0x8a\000\00000\000\000\000\000\000 */
> > > -{ 1213 }, /* bp_l2_btb_correct\000branch\000L2 BTB Correction\000event=0x8b\000\00000\000\000\000\000\000 */
> > > -{ 1475 }, /* dispatch_blocked.any\000other\000Memory cluster signals to block micro-op dispatch for any reason\000event=9,period=200000,umask=0x20\000\00000\000\000\000\000\000 */
> > > -{ 1608 }, /* eist_trans\000other\000Number of Enhanced Intel SpeedStep(R) Technology (EIST) transitions\000event=0x3a,period=200000\000\00000\000\000\000\000\000 */
> > > -{ 1275 }, /* l3_cache_rd\000cache\000L3 cache access, read\000event=0x40\000\00000\000\000\000\000Attributable Level 3 cache access, read\000 */
> > > -{ 1373 }, /* segment_reg_loads.any\000other\000Number of segment register loads\000event=6,period=200000,umask=0x80\000\00000\000\000\000\000\000 */
> > > +{ 2692 }, /* bp_l1_btb_correct\000branch\000L1 BTB Correction\000event=0x8a\000\00000\000\000\000\000\000 */
> > > +{ 2754 }, /* bp_l2_btb_correct\000branch\000L2 BTB Correction\000event=0x8b\000\00000\000\000\000\000\000 */
> > > +{ 3016 }, /* dispatch_blocked.any\000other\000Memory cluster signals to block micro-op dispatch for any reason\000event=9,period=200000,umask=0x20\000\00000\000\000\000\000\000 */
> > > +{ 3149 }, /* eist_trans\000other\000Number of Enhanced Intel SpeedStep(R) Technology (EIST) transitions\000event=0x3a,period=200000\000\00000\000\000\000\000\000 */
> > > +{ 2816 }, /* l3_cache_rd\000cache\000L3 cache access, read\000event=0x40\000\00000\000\000\000\000Attributable Level 3 cache access, read\000 */
> > > +{ 2914 }, /* segment_reg_loads.any\000other\000Number of segment register loads\000event=6,period=200000,umask=0x80\000\00000\000\000\000\000\000 */
> > >  };
> > >  static const struct compact_pmu_event pmu_events__test_soc_cpu_hisi_sccl_ddrc[] = {
> > > -{ 1741 }, /* uncore_hisi_ddrc.flux_wcmd\000uncore\000DDRC write commands\000event=2\000\00000\000\000\000\000\000 */
> > > +{ 3282 }, /* uncore_hisi_ddrc.flux_wcmd\000uncore\000DDRC write commands\000event=2\000\00000\000\000\000\000\000 */
> > >  };
> > >  static const struct compact_pmu_event pmu_events__test_soc_cpu_hisi_sccl_l3c[] = {
> > > -{ 2103 }, /* uncore_hisi_l3c.rd_hit_cpipe\000uncore\000Total read hits\000event=7\000\00000\000\000\000\000\000 */
> > > +{ 3644 }, /* uncore_hisi_l3c.rd_hit_cpipe\000uncore\000Total read hits\000event=7\000\00000\000\000\000\000\000 */
> > >  };
> > >  static const struct compact_pmu_event pmu_events__test_soc_cpu_uncore_cbox[] = {
> > > -{ 1977 }, /* event-hyphen\000uncore\000UNC_CBO_HYPHEN\000event=0xe0\000\00000\000\000\000\000\000 */
> > > -{ 2031 }, /* event-two-hyph\000uncore\000UNC_CBO_TWO_HYPH\000event=0xc0\000\00000\000\000\000\000\000 */
> > > -{ 1823 }, /* unc_cbo_xsnp_response.miss_eviction\000uncore\000A cross-core snoop resulted from L3 Eviction which misses in some processor core\000event=0x22,umask=0x81\000\00000\000\000\000\000\000 */
> > > +{ 3518 }, /* event-hyphen\000uncore\000UNC_CBO_HYPHEN\000event=0xe0\000\00000\000\000\000\000\000 */
> > > +{ 3572 }, /* event-two-hyph\000uncore\000UNC_CBO_TWO_HYPH\000event=0xc0\000\00000\000\000\000\000\000 */
> > > +{ 3364 }, /* unc_cbo_xsnp_response.miss_eviction\000uncore\000A cross-core snoop resulted from L3 Eviction which misses in some processor core\000event=0x22,umask=0x81\000\00000\000\000\000\000\000 */
> > >  };
> > >  static const struct compact_pmu_event pmu_events__test_soc_cpu_uncore_imc[] = {
> > > -{ 2286 }, /* uncore_imc.cache_hits\000uncore\000Total cache hits\000event=0x34\000\00000\000\000\000\000\000 */
> > > +{ 3827 }, /* uncore_imc.cache_hits\000uncore\000Total cache hits\000event=0x34\000\00000\000\000\000\000\000 */
> > >  };
> > >  static const struct compact_pmu_event pmu_events__test_soc_cpu_uncore_imc_free_running[] = {
> > > -{ 2195 }, /* uncore_imc_free_running.cache_miss\000uncore\000Total cache misses\000event=0x12\000\00000\000\000\000\000\000 */
> > > +{ 3736 }, /* uncore_imc_free_running.cache_miss\000uncore\000Total cache misses\000event=0x12\000\00000\000\000\000\000\000 */
> > >
> > >  };
> > >
> > > @@ -129,51 +167,51 @@ const struct pmu_table_entry pmu_events__test_soc_cpu[] = {
> > >  {
> > >       .entries = pmu_events__test_soc_cpu_default_core,
> > >       .num_entries = ARRAY_SIZE(pmu_events__test_soc_cpu_default_core),
> > > -     .pmu_name = { 1138 /* default_core\000 */ },
> > > +     .pmu_name = { 2679 /* default_core\000 */ },
> > >  },
> > >  {
> > >       .entries = pmu_events__test_soc_cpu_hisi_sccl_ddrc,
> > >       .num_entries = ARRAY_SIZE(pmu_events__test_soc_cpu_hisi_sccl_ddrc),
> > > -     .pmu_name = { 1726 /* hisi_sccl,ddrc\000 */ },
> > > +     .pmu_name = { 3267 /* hisi_sccl,ddrc\000 */ },
> > >  },
> > >  {
> > >       .entries = pmu_events__test_soc_cpu_hisi_sccl_l3c,
> > >       .num_entries = ARRAY_SIZE(pmu_events__test_soc_cpu_hisi_sccl_l3c),
> > > -     .pmu_name = { 2089 /* hisi_sccl,l3c\000 */ },
> > > +     .pmu_name = { 3630 /* hisi_sccl,l3c\000 */ },
> > >  },
> > >  {
> > >       .entries = pmu_events__test_soc_cpu_uncore_cbox,
> > >       .num_entries = ARRAY_SIZE(pmu_events__test_soc_cpu_uncore_cbox),
> > > -     .pmu_name = { 1811 /* uncore_cbox\000 */ },
> > > +     .pmu_name = { 3352 /* uncore_cbox\000 */ },
> > >  },
> > >  {
> > >       .entries = pmu_events__test_soc_cpu_uncore_imc,
> > >       .num_entries = ARRAY_SIZE(pmu_events__test_soc_cpu_uncore_imc),
> > > -     .pmu_name = { 2275 /* uncore_imc\000 */ },
> > > +     .pmu_name = { 3816 /* uncore_imc\000 */ },
> > >  },
> > >  {
> > >       .entries = pmu_events__test_soc_cpu_uncore_imc_free_running,
> > >       .num_entries = ARRAY_SIZE(pmu_events__test_soc_cpu_uncore_imc_free_running),
> > > -     .pmu_name = { 2171 /* uncore_imc_free_running\000 */ },
> > > +     .pmu_name = { 3712 /* uncore_imc_free_running\000 */ },
> > >  },
> > >  };
> > >
> > >  static const struct compact_pmu_event pmu_metrics__test_soc_cpu_default_core[] = {
> > > -{ 2704 }, /* CPI\000\0001 / IPC\000\000\000\000\000\000\000\00000 */
> > > -{ 3385 }, /* DCache_L2_All\000\000DCache_L2_All_Hits + DCache_L2_All_Miss\000\000\000\000\000\000\000\00000 */
> > > -{ 3157 }, /* DCache_L2_All_Hits\000\000l2_rqsts.demand_data_rd_hit + l2_rqsts.pf_hit + l2_rqsts.rfo_hit\000\000\000\000\000\000\000\00000 */
> > > -{ 3251 }, /* DCache_L2_All_Miss\000\000max(l2_rqsts.all_demand_data_rd - l2_rqsts.demand_data_rd_hit, 0) + l2_rqsts.pf_miss + l2_rqsts.rfo_miss\000\000\000\000\000\000\000\00000 */
> > > -{ 3449 }, /* DCache_L2_Hits\000\000d_ratio(DCache_L2_All_Hits, DCache_L2_All)\000\000\000\000\000\000\000\00000 */
> > > -{ 3517 }, /* DCache_L2_Misses\000\000d_ratio(DCache_L2_All_Miss, DCache_L2_All)\000\000\000\000\000\000\000\00000 */
> > > -{ 2789 }, /* Frontend_Bound_SMT\000\000idq_uops_not_delivered.core / (4 * (cpu_clk_unhalted.thread / 2 * (1 + cpu_clk_unhalted.one_thread_active / cpu_clk_unhalted.ref_xclk)))\000\000\000\000\000\000\000\00000 */
> > > -{ 2726 }, /* IPC\000group1\000inst_retired.any / cpu_clk_unhalted.thread\000\000\000\000\000\000\000\00000 */
> > > -{ 3651 }, /* L1D_Cache_Fill_BW\000\00064 * l1d.replacement / 1e9 / duration_time\000\000\000\000\000\000\000\00000 */
> > > -{ 3587 }, /* M1\000\000ipc + M2\000\000\000\000\000\000\000\00000 */
> > > -{ 3609 }, /* M2\000\000ipc + M1\000\000\000\000\000\000\000\00000 */
> > > -{ 3631 }, /* M3\000\0001 / M3\000\000\000\000\000\000\000\00000 */
> > > -{ 3086 }, /* cache_miss_cycles\000group1\000dcache_miss_cpi + icache_miss_cycles\000\000\000\000\000\000\000\00000 */
> > > -{ 2955 }, /* dcache_miss_cpi\000\000l1d\\-loads\\-misses / inst_retired.any\000\000\000\000\000\000\000\00000 */
> > > -{ 3019 }, /* icache_miss_cycles\000\000l1i\\-loads\\-misses / inst_retired.any\000\000\000\000\000\000\000\00000 */
> > > +{ 4245 }, /* CPI\000\0001 / IPC\000\000\000\000\000\000\000\00000 */
> > > +{ 4926 }, /* DCache_L2_All\000\000DCache_L2_All_Hits + DCache_L2_All_Miss\000\000\000\000\000\000\000\00000 */
> > > +{ 4698 }, /* DCache_L2_All_Hits\000\000l2_rqsts.demand_data_rd_hit + l2_rqsts.pf_hit + l2_rqsts.rfo_hit\000\000\000\000\000\000\000\00000 */
> > > +{ 4792 }, /* DCache_L2_All_Miss\000\000max(l2_rqsts.all_demand_data_rd - l2_rqsts.demand_data_rd_hit, 0) + l2_rqsts.pf_miss + l2_rqsts.rfo_miss\000\000\000\000\000\000\000\00000 */
> > > +{ 4990 }, /* DCache_L2_Hits\000\000d_ratio(DCache_L2_All_Hits, DCache_L2_All)\000\000\000\000\000\000\000\00000 */
> > > +{ 5058 }, /* DCache_L2_Misses\000\000d_ratio(DCache_L2_All_Miss, DCache_L2_All)\000\000\000\000\000\000\000\00000 */
> > > +{ 4330 }, /* Frontend_Bound_SMT\000\000idq_uops_not_delivered.core / (4 * (cpu_clk_unhalted.thread / 2 * (1 + cpu_clk_unhalted.one_thread_active / cpu_clk_unhalted.ref_xclk)))\000\000\000\000\000\000\000\00000 */
> > > +{ 4267 }, /* IPC\000group1\000inst_retired.any / cpu_clk_unhalted.thread\000\000\000\000\000\000\000\00000 */
> > > +{ 5192 }, /* L1D_Cache_Fill_BW\000\00064 * l1d.replacement / 1e9 / duration_time\000\000\000\000\000\000\000\00000 */
> > > +{ 5128 }, /* M1\000\000ipc + M2\000\000\000\000\000\000\000\00000 */
> > > +{ 5150 }, /* M2\000\000ipc + M1\000\000\000\000\000\000\000\00000 */
> > > +{ 5172 }, /* M3\000\0001 / M3\000\000\000\000\000\000\000\00000 */
> > > +{ 4627 }, /* cache_miss_cycles\000group1\000dcache_miss_cpi + icache_miss_cycles\000\000\000\000\000\000\000\00000 */
> > > +{ 4496 }, /* dcache_miss_cpi\000\000l1d\\-loads\\-misses / inst_retired.any\000\000\000\000\000\000\000\00000 */
> > > +{ 4560 }, /* icache_miss_cycles\000\000l1i\\-loads\\-misses / inst_retired.any\000\000\000\000\000\000\000\00000 */
> > >
> > >  };
> > >
> > > @@ -181,18 +219,18 @@ const struct pmu_table_entry pmu_metrics__test_soc_cpu[] = {
> > >  {
> > >       .entries = pmu_metrics__test_soc_cpu_default_core,
> > >       .num_entries = ARRAY_SIZE(pmu_metrics__test_soc_cpu_default_core),
> > > -     .pmu_name = { 1138 /* default_core\000 */ },
> > > +     .pmu_name = { 2679 /* default_core\000 */ },
> > >  },
> > >  };
> > >
> > >  static const struct compact_pmu_event pmu_events__test_soc_sys_uncore_sys_ccn_pmu[] = {
> > > -{ 2465 }, /* sys_ccn_pmu.read_cycles\000uncore\000ccn read-cycles event\000config=0x2c\0000x01\00000\000\000\000\000\000 */
> > > +{ 4006 }, /* sys_ccn_pmu.read_cycles\000uncore\000ccn read-cycles event\000config=0x2c\0000x01\00000\000\000\000\000\000 */
> > >  };
> > >  static const struct compact_pmu_event pmu_events__test_soc_sys_uncore_sys_cmn_pmu[] = {
> > > -{ 2561 }, /* sys_cmn_pmu.hnf_cache_miss\000uncore\000Counts total cache misses in first lookup result (high priority)\000eventid=1,type=5\000(434|436|43c|43a).*\00000\000\000\000\000\000 */
> > > +{ 4102 }, /* sys_cmn_pmu.hnf_cache_miss\000uncore\000Counts total cache misses in first lookup result (high priority)\000eventid=1,type=5\000(434|436|43c|43a).*\00000\000\000\000\000\000 */
> > >  };
> > >  static const struct compact_pmu_event pmu_events__test_soc_sys_uncore_sys_ddr_pmu[] = {
> > > -{ 2370 }, /* sys_ddr_pmu.write_cycles\000uncore\000ddr write-cycles event\000event=0x2b\000v8\00000\000\000\000\000\000 */
> > > +{ 3911 }, /* sys_ddr_pmu.write_cycles\000uncore\000ddr write-cycles event\000event=0x2b\000v8\00000\000\000\000\000\000 */
> > >
> > >  };
> > >
> > > @@ -200,17 +238,17 @@ const struct pmu_table_entry pmu_events__test_soc_sys[] = {
> > >  {
> > >       .entries = pmu_events__test_soc_sys_uncore_sys_ccn_pmu,
> > >       .num_entries = ARRAY_SIZE(pmu_events__test_soc_sys_uncore_sys_ccn_pmu),
> > > -     .pmu_name = { 2446 /* uncore_sys_ccn_pmu\000 */ },
> > > +     .pmu_name = { 3987 /* uncore_sys_ccn_pmu\000 */ },
> > >  },
> > >  {
> > >       .entries = pmu_events__test_soc_sys_uncore_sys_cmn_pmu,
> > >       .num_entries = ARRAY_SIZE(pmu_events__test_soc_sys_uncore_sys_cmn_pmu),
> > > -     .pmu_name = { 2542 /* uncore_sys_cmn_pmu\000 */ },
> > > +     .pmu_name = { 4083 /* uncore_sys_cmn_pmu\000 */ },
> > >  },
> > >  {
> > >       .entries = pmu_events__test_soc_sys_uncore_sys_ddr_pmu,
> > >       .num_entries = ARRAY_SIZE(pmu_events__test_soc_sys_uncore_sys_ddr_pmu),
> > > -     .pmu_name = { 2351 /* uncore_sys_ddr_pmu\000 */ },
> > > +     .pmu_name = { 3892 /* uncore_sys_ddr_pmu\000 */ },
> > >  },
> > >  };
> > >
> > > @@ -632,8 +670,20 @@ static const struct pmu_events_map *map_for_pmu(struct perf_pmu *pmu)
> > >  {
> > >          struct perf_cpu cpu = {-1};
> > >
> > > -        if (pmu)
> > > +        if (pmu) {
> > > +                for (size_t i=0; i < ARRAY_SIZE(pmu_events__common); i++) {
> > > +                        const char *pmu_name = &big_c_string[pmu_events__common[i].pmu_name.offset];
> > > +
> > > +                        if (!strcmp(pmu_name, pmu->name)) {
> > > +                                const struct pmu_events_map *map = &pmu_events_map[0];
> > > +
> > > +                                while (strcmp("common", map->arch))
> > > +                                        map++;
> > > +                                return map;
> > > +                        }
> > > +                }
> > >                  cpu = perf_cpu_map__min(pmu->cpus);
> > > +        }
> > >          return map_for_cpu(cpu);
> > >  }
> > >
> > > diff --git a/tools/perf/pmu-events/jevents.py b/tools/perf/pmu-events/jevents.py
> > > index e821155151ec..76c1e7b0bc22 100755
> > > --- a/tools/perf/pmu-events/jevents.py
> > > +++ b/tools/perf/pmu-events/jevents.py
> > > @@ -295,6 +295,7 @@ class JsonEvent:
> > >            'cpu_atom': 'cpu_atom',
> > >            'ali_drw': 'ali_drw',
> > >            'arm_cmn': 'arm_cmn',
> > > +          'software': 'software',
> > >            'tool': 'tool',
> > >        }
> > >        return table[unit] if unit in table else f'uncore_{unit.lower()}'
> > > @@ -1158,8 +1159,20 @@ static const struct pmu_events_map *map_for_pmu(struct perf_pmu *pmu)
> > >  {
> > >          struct perf_cpu cpu = {-1};
> > >
> > > -        if (pmu)
> > > +        if (pmu) {
> > > +                for (size_t i=0; i < ARRAY_SIZE(pmu_events__common); i++) {
> > > +                        const char *pmu_name = &big_c_string[pmu_events__common[i].pmu_name.offset];
> > > +
> > > +                        if (!strcmp(pmu_name, pmu->name)) {
> > > +                                const struct pmu_events_map *map = &pmu_events_map[0];
> > > +
> > > +                                while (strcmp("common", map->arch))
> > > +                                        map++;
> > > +                                return map;
> > > +                        }
> > > +                }
> > >                  cpu = perf_cpu_map__min(pmu->cpus);
> > > +        }
> > >          return map_for_cpu(cpu);
> > >  }
> > >
> > > --
> > > 2.50.0.727.gbf7dc18ff4-goog
> > >

^ permalink raw reply	[flat|nested] 41+ messages in thread

* Re: [PATCH v7 03/16] perf parse-events: Remove non-json software events
  2025-07-14 16:43 ` [PATCH v7 03/16] perf parse-events: Remove non-json software events Ian Rogers
@ 2025-07-24  0:20   ` Namhyung Kim
  0 siblings, 0 replies; 41+ messages in thread
From: Namhyung Kim @ 2025-07-24  0:20 UTC (permalink / raw)
  To: Ian Rogers
  Cc: Peter Zijlstra, Ingo Molnar, Arnaldo Carvalho de Melo,
	Mark Rutland, Alexander Shishkin, Jiri Olsa, Adrian Hunter,
	Kan Liang, James Clark, Xu Yang, Masami Hiramatsu (Google),
	Collin Funk, Howard Chu, Weilin Wang, Andi Kleen,
	Dr. David Alan Gilbert, Thomas Richter, Tiezhu Yang,
	Gautam Menghani, Thomas Falcon, Chun-Tse Shao, linux-kernel,
	linux-perf-users

On Mon, Jul 14, 2025 at 09:43:51AM -0700, Ian Rogers wrote:
> Remove the hard coded encodings from parse-events. This has the
> consequence that software events are matched using the sysfs/json
> priority, will be case insensitive and will be wildcarded across PMUs.
> As there were software and hardware types in the parsing code, the
> removal means software vs hardware logic can be removed and hardware
> assumed.
> 
> Now the perf json provides detailed descriptions of software events,
> remove the previous listing support that didn't contain event
> descriptions. When globbing is required for the "sw" option in perf
> list, use string PMU globbing as was done previously for the tool PMU.

Oh, you explained the issues here.  Great, I've seen you posted v8.
Will continue there.

Thanks,
Namhyung

> 
> Signed-off-by: Ian Rogers <irogers@google.com>
> ---
>  tools/perf/builtin-list.c      | 19 ++++++-------
>  tools/perf/util/parse-events.c | 51 ----------------------------------
>  tools/perf/util/parse-events.h |  1 -
>  tools/perf/util/parse-events.l | 38 +++++++++----------------
>  tools/perf/util/parse-events.y | 29 ++++++++-----------
>  tools/perf/util/print-events.c |  2 --
>  6 files changed, 33 insertions(+), 107 deletions(-)
> 
> diff --git a/tools/perf/builtin-list.c b/tools/perf/builtin-list.c
> index e9b595d75df2..674bb0afbf93 100644
> --- a/tools/perf/builtin-list.c
> +++ b/tools/perf/builtin-list.c
> @@ -623,16 +623,17 @@ int cmd_list(int argc, const char **argv)
>  		else if (strcmp(argv[i], "sw") == 0 ||
>  			 strcmp(argv[i], "software") == 0) {
>  			char *old_pmu_glob = default_ps.pmu_glob;
> +			static const char * const sw_globs[] = { "software", "tool" };
>  
> -			print_symbol_events(&print_cb, ps, PERF_TYPE_SOFTWARE,
> -					event_symbols_sw, PERF_COUNT_SW_MAX);
> -			default_ps.pmu_glob = strdup("tool");
> -			if (!default_ps.pmu_glob) {
> -				ret = -1;
> -				goto out;
> +			for (size_t j = 0; j < ARRAY_SIZE(sw_globs); j++) {
> +				default_ps.pmu_glob = strdup(sw_globs[j]);
> +				if (!default_ps.pmu_glob) {
> +					ret = -1;
> +					goto out;
> +				}
> +				perf_pmus__print_pmu_events(&print_cb, ps);
> +				zfree(&default_ps.pmu_glob);
>  			}
> -			perf_pmus__print_pmu_events(&print_cb, ps);
> -			zfree(&default_ps.pmu_glob);
>  			default_ps.pmu_glob = old_pmu_glob;
>  		} else if (strcmp(argv[i], "cache") == 0 ||
>  			 strcmp(argv[i], "hwcache") == 0)
> @@ -679,8 +680,6 @@ int cmd_list(int argc, const char **argv)
>  			default_ps.event_glob = s;
>  			print_symbol_events(&print_cb, ps, PERF_TYPE_HARDWARE,
>  					event_symbols_hw, PERF_COUNT_HW_MAX);
> -			print_symbol_events(&print_cb, ps, PERF_TYPE_SOFTWARE,
> -					event_symbols_sw, PERF_COUNT_SW_MAX);
>  			print_hwcache_events(&print_cb, ps);
>  			perf_pmus__print_pmu_events(&print_cb, ps);
>  			print_tracepoint_events(&print_cb, ps);
> diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c
> index a59ae5ca0f89..1ae481c9802b 100644
> --- a/tools/perf/util/parse-events.c
> +++ b/tools/perf/util/parse-events.c
> @@ -84,57 +84,6 @@ const struct event_symbol event_symbols_hw[PERF_COUNT_HW_MAX] = {
>  	},
>  };
>  
> -const struct event_symbol event_symbols_sw[PERF_COUNT_SW_MAX] = {
> -	[PERF_COUNT_SW_CPU_CLOCK] = {
> -		.symbol = "cpu-clock",
> -		.alias  = "",
> -	},
> -	[PERF_COUNT_SW_TASK_CLOCK] = {
> -		.symbol = "task-clock",
> -		.alias  = "",
> -	},
> -	[PERF_COUNT_SW_PAGE_FAULTS] = {
> -		.symbol = "page-faults",
> -		.alias  = "faults",
> -	},
> -	[PERF_COUNT_SW_CONTEXT_SWITCHES] = {
> -		.symbol = "context-switches",
> -		.alias  = "cs",
> -	},
> -	[PERF_COUNT_SW_CPU_MIGRATIONS] = {
> -		.symbol = "cpu-migrations",
> -		.alias  = "migrations",
> -	},
> -	[PERF_COUNT_SW_PAGE_FAULTS_MIN] = {
> -		.symbol = "minor-faults",
> -		.alias  = "",
> -	},
> -	[PERF_COUNT_SW_PAGE_FAULTS_MAJ] = {
> -		.symbol = "major-faults",
> -		.alias  = "",
> -	},
> -	[PERF_COUNT_SW_ALIGNMENT_FAULTS] = {
> -		.symbol = "alignment-faults",
> -		.alias  = "",
> -	},
> -	[PERF_COUNT_SW_EMULATION_FAULTS] = {
> -		.symbol = "emulation-faults",
> -		.alias  = "",
> -	},
> -	[PERF_COUNT_SW_DUMMY] = {
> -		.symbol = "dummy",
> -		.alias  = "",
> -	},
> -	[PERF_COUNT_SW_BPF_OUTPUT] = {
> -		.symbol = "bpf-output",
> -		.alias  = "",
> -	},
> -	[PERF_COUNT_SW_CGROUP_SWITCHES] = {
> -		.symbol = "cgroup-switches",
> -		.alias  = "",
> -	},
> -};
> -
>  static const char *const event_types[] = {
>  	[PERF_TYPE_HARDWARE]	= "hardware",
>  	[PERF_TYPE_SOFTWARE]	= "software",
> diff --git a/tools/perf/util/parse-events.h b/tools/perf/util/parse-events.h
> index b47bf2810112..62dc7202e3ba 100644
> --- a/tools/perf/util/parse-events.h
> +++ b/tools/perf/util/parse-events.h
> @@ -264,7 +264,6 @@ struct event_symbol {
>  	const char	*alias;
>  };
>  extern const struct event_symbol event_symbols_hw[];
> -extern const struct event_symbol event_symbols_sw[];
>  
>  char *parse_events_formats_error_string(char *additional_terms);
>  
> diff --git a/tools/perf/util/parse-events.l b/tools/perf/util/parse-events.l
> index 4af7b9c1f44d..2034590eb789 100644
> --- a/tools/perf/util/parse-events.l
> +++ b/tools/perf/util/parse-events.l
> @@ -117,12 +117,12 @@ do {								\
>  	yyless(0);						\
>  } while (0)
>  
> -static int sym(yyscan_t scanner, int type, int config)
> +static int sym(yyscan_t scanner, int config)
>  {
>  	YYSTYPE *yylval = parse_events_get_lval(scanner);
>  
> -	yylval->num = (type << 16) + config;
> -	return type == PERF_TYPE_HARDWARE ? PE_VALUE_SYM_HW : PE_VALUE_SYM_SW;
> +	yylval->num = config;
> +	return PE_VALUE_SYM_HW;
>  }
>  
>  static int term(yyscan_t scanner, enum parse_events__term_type type)
> @@ -391,28 +391,16 @@ r0x{num_raw_hex}	{ return str(yyscanner, PE_RAW); }
>  <<EOF>>			{ BEGIN(INITIAL); }
>  }
>  
> -cpu-cycles|cycles				{ return sym(yyscanner, PERF_TYPE_HARDWARE, PERF_COUNT_HW_CPU_CYCLES); }
> -stalled-cycles-frontend|idle-cycles-frontend	{ return sym(yyscanner, PERF_TYPE_HARDWARE, PERF_COUNT_HW_STALLED_CYCLES_FRONTEND); }
> -stalled-cycles-backend|idle-cycles-backend	{ return sym(yyscanner, PERF_TYPE_HARDWARE, PERF_COUNT_HW_STALLED_CYCLES_BACKEND); }
> -instructions					{ return sym(yyscanner, PERF_TYPE_HARDWARE, PERF_COUNT_HW_INSTRUCTIONS); }
> -cache-references				{ return sym(yyscanner, PERF_TYPE_HARDWARE, PERF_COUNT_HW_CACHE_REFERENCES); }
> -cache-misses					{ return sym(yyscanner, PERF_TYPE_HARDWARE, PERF_COUNT_HW_CACHE_MISSES); }
> -branch-instructions|branches			{ return sym(yyscanner, PERF_TYPE_HARDWARE, PERF_COUNT_HW_BRANCH_INSTRUCTIONS); }
> -branch-misses					{ return sym(yyscanner, PERF_TYPE_HARDWARE, PERF_COUNT_HW_BRANCH_MISSES); }
> -bus-cycles					{ return sym(yyscanner, PERF_TYPE_HARDWARE, PERF_COUNT_HW_BUS_CYCLES); }
> -ref-cycles					{ return sym(yyscanner, PERF_TYPE_HARDWARE, PERF_COUNT_HW_REF_CPU_CYCLES); }
> -cpu-clock					{ return sym(yyscanner, PERF_TYPE_SOFTWARE, PERF_COUNT_SW_CPU_CLOCK); }
> -task-clock					{ return sym(yyscanner, PERF_TYPE_SOFTWARE, PERF_COUNT_SW_TASK_CLOCK); }
> -page-faults|faults				{ return sym(yyscanner, PERF_TYPE_SOFTWARE, PERF_COUNT_SW_PAGE_FAULTS); }
> -minor-faults					{ return sym(yyscanner, PERF_TYPE_SOFTWARE, PERF_COUNT_SW_PAGE_FAULTS_MIN); }
> -major-faults					{ return sym(yyscanner, PERF_TYPE_SOFTWARE, PERF_COUNT_SW_PAGE_FAULTS_MAJ); }
> -context-switches|cs				{ return sym(yyscanner, PERF_TYPE_SOFTWARE, PERF_COUNT_SW_CONTEXT_SWITCHES); }
> -cpu-migrations|migrations			{ return sym(yyscanner, PERF_TYPE_SOFTWARE, PERF_COUNT_SW_CPU_MIGRATIONS); }
> -alignment-faults				{ return sym(yyscanner, PERF_TYPE_SOFTWARE, PERF_COUNT_SW_ALIGNMENT_FAULTS); }
> -emulation-faults				{ return sym(yyscanner, PERF_TYPE_SOFTWARE, PERF_COUNT_SW_EMULATION_FAULTS); }
> -dummy						{ return sym(yyscanner, PERF_TYPE_SOFTWARE, PERF_COUNT_SW_DUMMY); }
> -bpf-output					{ return sym(yyscanner, PERF_TYPE_SOFTWARE, PERF_COUNT_SW_BPF_OUTPUT); }
> -cgroup-switches					{ return sym(yyscanner, PERF_TYPE_SOFTWARE, PERF_COUNT_SW_CGROUP_SWITCHES); }
> +cpu-cycles|cycles				{ return sym(yyscanner, PERF_COUNT_HW_CPU_CYCLES); }
> +stalled-cycles-frontend|idle-cycles-frontend	{ return sym(yyscanner, PERF_COUNT_HW_STALLED_CYCLES_FRONTEND); }
> +stalled-cycles-backend|idle-cycles-backend	{ return sym(yyscanner, PERF_COUNT_HW_STALLED_CYCLES_BACKEND); }
> +instructions					{ return sym(yyscanner, PERF_COUNT_HW_INSTRUCTIONS); }
> +cache-references				{ return sym(yyscanner, PERF_COUNT_HW_CACHE_REFERENCES); }
> +cache-misses					{ return sym(yyscanner, PERF_COUNT_HW_CACHE_MISSES); }
> +branch-instructions|branches			{ return sym(yyscanner, PERF_COUNT_HW_BRANCH_INSTRUCTIONS); }
> +branch-misses					{ return sym(yyscanner, PERF_COUNT_HW_BRANCH_MISSES); }
> +bus-cycles					{ return sym(yyscanner, PERF_COUNT_HW_BUS_CYCLES); }
> +ref-cycles					{ return sym(yyscanner, PERF_COUNT_HW_REF_CPU_CYCLES); }
>  
>  {lc_type}			{ return str(yyscanner, PE_LEGACY_CACHE); }
>  {lc_type}-{lc_op_result}	{ return str(yyscanner, PE_LEGACY_CACHE); }
> diff --git a/tools/perf/util/parse-events.y b/tools/perf/util/parse-events.y
> index f888cbb076d6..a2361c0040d7 100644
> --- a/tools/perf/util/parse-events.y
> +++ b/tools/perf/util/parse-events.y
> @@ -55,7 +55,7 @@ static void free_list_evsel(struct list_head* list_evsel)
>  %}
>  
>  %token PE_START_EVENTS PE_START_TERMS
> -%token PE_VALUE PE_VALUE_SYM_HW PE_VALUE_SYM_SW PE_TERM
> +%token PE_VALUE PE_VALUE_SYM_HW PE_TERM
>  %token PE_EVENT_NAME
>  %token PE_RAW PE_NAME
>  %token PE_MODIFIER_EVENT PE_MODIFIER_BP PE_BP_COLON PE_BP_SLASH
> @@ -66,10 +66,8 @@ static void free_list_evsel(struct list_head* list_evsel)
>  %token PE_TERM_HW
>  %type <num> PE_VALUE
>  %type <num> PE_VALUE_SYM_HW
> -%type <num> PE_VALUE_SYM_SW
>  %type <mod> PE_MODIFIER_EVENT
>  %type <term_type> PE_TERM
> -%type <num> value_sym
>  %type <str> PE_RAW
>  %type <str> PE_NAME
>  %type <str> PE_LEGACY_CACHE
> @@ -306,24 +304,19 @@ PE_NAME sep_dc
>  	$$ = list;
>  }
>  
> -value_sym:
> -PE_VALUE_SYM_HW
> -|
> -PE_VALUE_SYM_SW
> -
>  event_legacy_symbol:
> -value_sym '/' event_config '/'
> +PE_VALUE_SYM_HW '/' event_config '/'
>  {
>  	struct list_head *list;
> -	int type = $1 >> 16;
> -	int config = $1 & 255;
>  	int err;
> -	bool wildcard = (type == PERF_TYPE_HARDWARE || type == PERF_TYPE_HW_CACHE);
>  
>  	list = alloc_list();
>  	if (!list)
>  		YYNOMEM;
> -	err = parse_events_add_numeric(_parse_state, list, type, config, $3, wildcard);
> +	err = parse_events_add_numeric(_parse_state, list,
> +				       PERF_TYPE_HARDWARE, $1,
> +				       $3,
> +				       /*wildcard=*/true);
>  	parse_events_terms__delete($3);
>  	if (err) {
>  		free_list_evsel(list);
> @@ -332,18 +325,18 @@ value_sym '/' event_config '/'
>  	$$ = list;
>  }
>  |
> -value_sym sep_slash_slash_dc
> +PE_VALUE_SYM_HW sep_slash_slash_dc
>  {
>  	struct list_head *list;
> -	int type = $1 >> 16;
> -	int config = $1 & 255;
> -	bool wildcard = (type == PERF_TYPE_HARDWARE || type == PERF_TYPE_HW_CACHE);
>  	int err;
>  
>  	list = alloc_list();
>  	if (!list)
>  		YYNOMEM;
> -	err = parse_events_add_numeric(_parse_state, list, type, config, /*head_config=*/NULL, wildcard);
> +	err = parse_events_add_numeric(_parse_state, list,
> +				       PERF_TYPE_HARDWARE, $1,
> +				       /*head_config=*/NULL,
> +				       /*wildcard=*/true);
>  	if (err)
>  		PE_ABORT(err);
>  	$$ = list;
> diff --git a/tools/perf/util/print-events.c b/tools/perf/util/print-events.c
> index e233bacaa641..c1a8708b55ab 100644
> --- a/tools/perf/util/print-events.c
> +++ b/tools/perf/util/print-events.c
> @@ -521,8 +521,6 @@ void print_events(const struct print_callbacks *print_cb, void *print_state)
>  {
>  	print_symbol_events(print_cb, print_state, PERF_TYPE_HARDWARE,
>  			event_symbols_hw, PERF_COUNT_HW_MAX);
> -	print_symbol_events(print_cb, print_state, PERF_TYPE_SOFTWARE,
> -			event_symbols_sw, PERF_COUNT_SW_MAX);
>  
>  	print_hwcache_events(print_cb, print_state);
>  
> -- 
> 2.50.0.727.gbf7dc18ff4-goog
> 

^ permalink raw reply	[flat|nested] 41+ messages in thread

* Re: [PATCH v7 02/16] perf jevents: Add common software event json
  2025-07-24  0:10       ` Namhyung Kim
@ 2025-07-24  1:47         ` Ian Rogers
  2025-07-24 16:58           ` Namhyung Kim
  0 siblings, 1 reply; 41+ messages in thread
From: Ian Rogers @ 2025-07-24  1:47 UTC (permalink / raw)
  To: Namhyung Kim
  Cc: Peter Zijlstra, Ingo Molnar, Arnaldo Carvalho de Melo,
	Mark Rutland, Alexander Shishkin, Jiri Olsa, Adrian Hunter,
	Kan Liang, James Clark, Xu Yang, Masami Hiramatsu (Google),
	Collin Funk, Howard Chu, Weilin Wang, Andi Kleen,
	Dr. David Alan Gilbert, Thomas Richter, Tiezhu Yang,
	Gautam Menghani, Thomas Falcon, Chun-Tse Shao, linux-kernel,
	linux-perf-users

On Wed, Jul 23, 2025 at 5:10 PM Namhyung Kim <namhyung@kernel.org> wrote:
>
> On Wed, Jul 23, 2025 at 03:34:07PM -0700, Ian Rogers wrote:
> > On Wed, Jul 23, 2025 at 11:24 AM Namhyung Kim <namhyung@kernel.org> wrote:
> > >
> > > On Mon, Jul 14, 2025 at 09:43:50AM -0700, Ian Rogers wrote:
> > > > Add json for software events so that in perf list the events can have
> > > > a description.  Common json exists for the tool PMU but it has no
> > > > sysfs equivalent. Modify the map_for_pmu code to return the common map
> > > > (rather than an architecture specific one) when a PMU with a common
> > > > name is being looked for, this allows the events to be found.
> > >
> > > Can you please share new output of `perf list sw`?  I'm glad we have
> > > description for software events.  But I'm also curious what's the side
> > > effect of having them in JSON - maybe case insensitivity?
> >
> > The old software event names were matched in the lex code and were
> > case sensitive. The events in the json are case insensitive and the
> > case insensitive lex ones are removed in the next patch.
>
> And then it'd also use wildcard match, right?

Yes. So for example, the old behavior would allow:

  $ perf stat -e faults -a sleep 1

this can now be:

  $ perf stat -e software/faults/ -a sleep 1
  $ perf stat -e Faults -a sleep 1
..

and if a PMU has an event named 'faults' then with the wildcarding
both the software PMU faults event and the other PMU's faults event
would be opened and read, sampled, etc. If the event can't be sampled
then this could make `perf record` fail in just the same way as is
fixed in (unmerged):
https://lore.kernel.org/lkml/20250416045117.876775-1-irogers@google.com/
which was particularly problematic on ARM CPUs.

> >
> > The perf list output looks like:
> >
> > Before:
> > ```
> > List of pre-defined events (to be used in -e or -M):
> >
> >   branch-instructions OR branches                    [Hardware event]
> >   branch-misses                                      [Hardware event]
> >   bus-cycles                                         [Hardware event]
> >   cache-misses                                       [Hardware event]
> >   cache-references                                   [Hardware event]
> >   cpu-cycles OR cycles                               [Hardware event]
> >   instructions                                       [Hardware event]
> >   ref-cycles                                         [Hardware event]
> >   alignment-faults                                   [Software event]
> >   bpf-output                                         [Software event]
> >   cgroup-switches                                    [Software event]
> >   context-switches OR cs                             [Software event]
> >   cpu-clock                                          [Software event]
> >   cpu-migrations OR migrations                       [Software event]
> >   dummy                                              [Software event]
> >   emulation-faults                                   [Software event]
> >   major-faults                                       [Software event]
> >   minor-faults                                       [Software event]
> >   page-faults OR faults                              [Software event]
> >   task-clock                                         [Software event]
> > ```
> >
> > After:
> > ```
> > List of pre-defined events (to be used in -e or -M):
> >
> >   branch-instructions OR branches                    [Hardware event]
> >   branch-misses                                      [Hardware event]
> >   bus-cycles                                         [Hardware event]
> >   cache-misses                                       [Hardware event]
> >   cache-references                                   [Hardware event]
> >   cpu-cycles OR cycles                               [Hardware event]
> >   instructions                                       [Hardware event]
> >   ref-cycles                                         [Hardware event]
> >   alignment-faults                                   [Software event]
> >   bpf-output                                         [Software event]
> >   cgroup-switches                                    [Software event]
> >   context-switches OR cs                             [Software event]
> >   cpu-clock                                          [Software event]
> >   cpu-migrations OR migrations                       [Software event]
> >   dummy                                              [Software event]
> >   emulation-faults                                   [Software event]
> >   major-faults                                       [Software event]
> >   minor-faults                                       [Software event]
> >   page-faults OR faults                              [Software event]
> >   task-clock                                         [Software event]
> > ...
> > software:
> >   alignment-faults
> >        [Number of kernel handled memory alignment faults. Unit: software]
> >   bpf-output
> >        [An event used by BPF programs to write to the perf ring
> > buffer. Unit: software]
> >   cgroup-switches
> >        [Number of context switches to a task in a different cgroup.
> > Unit: software]
> >   context-switches
> >        [Number of context switches [This event is an alias of cs].
> > Unit: software]
> >   cpu-clock
> >        [Per-CPU high-resolution timer based event. Unit: software]
> >   cpu-migrations
> >        [Number of times a process has migrated to a new CPU [This
> > event is an alias of migrations]. Unit: software]
> >   cs
> >        [Number of context switches [This event is an alias of
> > context-switches]. Unit: software]
> >   dummy
> >        [A placeholder event that doesn't count anything. Unit: software]
> >   emulation-faults
> >        [Number of kernel handled unimplemented instruction faults
> > handled through emulation. Unit: software]
> >   faults
> >        [Number of page faults [This event is an alias of page-faults].
> > Unit: software]
> >   major-faults
> >        [Number of major page faults. Major faults require I/O to
> > handle. Unit: software]
> >   migrations
> >        [Number of times a process has migrated to a new CPU [This
> > event is an alias of cpu-migrations]. Unit: software]
> >   minor-faults
> >        [Number of minor page faults. Minor faults don't require I/O to
> > handle. Unit: software]
> >   page-faults
> >        [Number of page faults [This event is an alias of faults].
> > Unit: software]
> >   task-clock
> >        [Task based high-resolution timer based event. Unit: software]
> > ...
> > ```
> > The next patch will make this just:
> > ```
> > List of pre-defined events (to be used in -e or -M):
> >
> >   branch-instructions OR branches                    [Hardware event]
> >   branch-misses                                      [Hardware event]
> >   bus-cycles                                         [Hardware event]
> >   cache-misses                                       [Hardware event]
> >   cache-references                                   [Hardware event]
> >   cpu-cycles OR cycles                               [Hardware event]
> >   instructions                                       [Hardware event]
> >   ref-cycles                                         [Hardware event]
> > ...
> > software:
> >   alignment-faults
> >        [Number of kernel handled memory alignment faults. Unit: software]
> >   bpf-output
> >        [An event used by BPF programs to write to the perf ring
> > buffer. Unit: software]
> >   cgroup-switches
> >        [Number of context switches to a task in a different cgroup.
> > Unit: software]
> >   context-switches
> >        [Number of context switches [This event is an alias of cs].
>
> Hmm.. can we just use parentheses for the alias?

We could, I was looking for consistency with what is already done by Intel:
```
$ perf list
...
  l2_request.all
      [All accesses to L2 cache [This event is alias to
L2_RQSTS.REFERENCES]. Unit: cpu_core]
  l2_request.miss
      [Read requests with true-miss in L2 cache. [This event is alias
to L2_RQSTS.MISS]. Unit:
       cpu_core]
...
```
I wouldn't want to modify Intel's convention, we could have 2 conventions. Wdyt?


>
> > Unit: software]
> >   cpu-clock
> >        [Per-CPU high-resolution timer based event. Unit: software]
> >   cpu-migrations
> >        [Number of times a process has migrated to a new CPU [This
> > event is an alias of migrations]. Unit: software]
> >   cs
> >        [Number of context switches [This event is an alias of
> > context-switches]. Unit: software]
> >   dummy
> >        [A placeholder event that doesn't count anything. Unit: software]
> >   emulation-faults
> >        [Number of kernel handled unimplemented instruction faults
> > handled through emulation. Unit: software]
> >   faults
> >        [Number of page faults [This event is an alias of page-faults].
> > Unit: software]
> >   major-faults
> >        [Number of major page faults. Major faults require I/O to
> > handle. Unit: software]
> >   migrations
> >        [Number of times a process has migrated to a new CPU [This
> > event is an alias of cpu-migrations]. Unit: software]
> >   minor-faults
> >        [Number of minor page faults. Minor faults don't require I/O to
> > handle. Unit: software]
> >   page-faults
> >        [Number of page faults [This event is an alias of faults].
> > Unit: software]
> >   task-clock
> >        [Task based high-resolution timer based event. Unit: software]
> > ...
> > ```
>
> Will `perf list sw` include these output?  And please add this to the
> commit message.

This is in the next patch, basically the PMU name matching glob is
used so that for the "sw" perf list option only the "software" and
"tool" PMUs are displayed.
I can add the output to the next patch (then I don't need to worry
about the half-way state that exists after this patch).

Thanks,
Ian

> > > >
> > > > Signed-off-by: Ian Rogers <irogers@google.com>
> > > > ---
> > > >  .../arch/common/common/software.json          |  92 ++++++
> > > >  tools/perf/pmu-events/empty-pmu-events.c      | 266 +++++++++++-------
> > > >  tools/perf/pmu-events/jevents.py              |  15 +-
> > > >  3 files changed, 264 insertions(+), 109 deletions(-)
> > > >  create mode 100644 tools/perf/pmu-events/arch/common/common/software.json
> > > >
> > > > diff --git a/tools/perf/pmu-events/arch/common/common/software.json b/tools/perf/pmu-events/arch/common/common/software.json
> > > > new file mode 100644
> > > > index 000000000000..3af2f565a601
> > > > --- /dev/null
> > > > +++ b/tools/perf/pmu-events/arch/common/common/software.json
> > > > @@ -0,0 +1,92 @@
> > > > +[
> > > > +  {
> > > > +    "Unit": "software",
> > > > +    "EventName": "cpu-clock",
> > > > +    "BriefDescription": "Per-CPU high-resolution timer based event",
> > > > +    "ConfigCode": "0"
> > > > +  },
> > > > +  {
> > > > +    "Unit": "software",
> > > > +    "EventName": "task-clock",
> > > > +    "BriefDescription": "Task based high-resolution timer based event",
> > >
> > > s/Task based/Per-task/ ?
> >
> > Will fix it in the next version.
> >
> > >
> > > > +    "ConfigCode": "1"
> > > > +  },
> > > > +  {
> > > > +    "Unit": "software",
> > > > +    "EventName": "faults",
> > > > +    "BriefDescription": "Number of page faults [This event is an alias of page-faults]",
> > > > +    "ConfigCode": "2"
> > >
> > > It'd be nice if it can handle aliases without adding a new entry.  But I
> > > guess it requires non-trivial changes.
> >
> > It is a limitation of the perf json format. There's no reason not to
> > add some notion of aliases, I believe it was done this way inheriting
> > from how Intel did it.
>
> Ok, I think it's fine for now.
>
> Thanks,
> Namhyung
>
> > >
> > > > +  },
> > > > +  {
> > > > +    "Unit": "software",
> > > > +    "EventName": "page-faults",
> > > > +    "BriefDescription": "Number of page faults [This event is an alias of faults]",
> > > > +    "ConfigCode": "2"
> > > > +  },
> > > > +  {
> > > > +    "Unit": "software",
> > > > +    "EventName": "context-switches",
> > > > +    "BriefDescription": "Number of context switches [This event is an alias of cs]",
> > > > +    "ConfigCode": "3"
> > > > +  },
> > > > +  {
> > > > +    "Unit": "software",
> > > > +    "EventName": "cs",
> > > > +    "BriefDescription": "Number of context switches [This event is an alias of context-switches]",
> > > > +    "ConfigCode": "3"
> > > > +  },
> > > > +  {
> > > > +    "Unit": "software",
> > > > +    "EventName": "cpu-migrations",
> > > > +    "BriefDescription": "Number of times a process has migrated to a new CPU [This event is an alias of migrations]",
> > > > +    "ConfigCode": "4"
> > > > +  },
> > > > +  {
> > > > +    "Unit": "software",
> > > > +    "EventName": "migrations",
> > > > +    "BriefDescription": "Number of times a process has migrated to a new CPU [This event is an alias of cpu-migrations]",
> > > > +    "ConfigCode": "4"
> > > > +  },
> > > > +  {
> > > > +    "Unit": "software",
> > > > +    "EventName": "minor-faults",
> > > > +    "BriefDescription": "Number of minor page faults. Minor faults don't require I/O to handle",
> > > > +    "ConfigCode": "5"
> > > > +  },
> > > > +  {
> > > > +    "Unit": "software",
> > > > +    "EventName": "major-faults",
> > > > +    "BriefDescription": "Number of major page faults. Major faults require I/O to handle",
> > > > +    "ConfigCode": "6"
> > > > +  },
> > > > +  {
> > > > +    "Unit": "software",
> > > > +    "EventName": "alignment-faults",
> > > > +    "BriefDescription": "Number of kernel handled memory alignment faults",
> > > > +    "ConfigCode": "7"
> > > > +  },
> > > > +  {
> > > > +    "Unit": "software",
> > > > +    "EventName": "emulation-faults",
> > > > +    "BriefDescription": "Number of kernel handled unimplemented instruction faults handled through emulation",
> > > > +    "ConfigCode": "8"
> > > > +  },
> > > > +  {
> > > > +    "Unit": "software",
> > > > +    "EventName": "dummy",
> > > > +    "BriefDescription": "A placeholder event that doesn't count anything",
> > > > +    "ConfigCode": "9"
> > > > +  },
> > > > +  {
> > > > +    "Unit": "software",
> > > > +    "EventName": "bpf-output",
> > > > +    "BriefDescription": "An event used by BPF programs to write to the perf ring buffer",
> > > > +    "ConfigCode": "10"
> > > > +  },
> > > > +  {
> > > > +    "Unit": "software",
> > > > +    "EventName": "cgroup-switches",
> > > > +    "BriefDescription": "Number of context switches to a task in a different cgroup",
> > > > +    "ConfigCode": "11"
> > > > +  }
> > > > +]
> > > > diff --git a/tools/perf/pmu-events/empty-pmu-events.c b/tools/perf/pmu-events/empty-pmu-events.c
> > > > index a4569a74db07..7d179d703ab1 100644
> > > > --- a/tools/perf/pmu-events/empty-pmu-events.c
> > > > +++ b/tools/perf/pmu-events/empty-pmu-events.c
> > > > @@ -19,109 +19,147 @@ struct pmu_table_entry {
> > > >  };
> > > >
> > > >  static const char *const big_c_string =
> > > > -/* offset=0 */ "tool\000"
> > > > -/* offset=5 */ "duration_time\000tool\000Wall clock interval time in nanoseconds\000config=1\000\00000\000\000\000\000\000"
> > > > -/* offset=81 */ "user_time\000tool\000User (non-kernel) time in nanoseconds\000config=2\000\00000\000\000\000\000\000"
> > > > -/* offset=151 */ "system_time\000tool\000System/kernel time in nanoseconds\000config=3\000\00000\000\000\000\000\000"
> > > > -/* offset=219 */ "has_pmem\000tool\0001 if persistent memory installed otherwise 0\000config=4\000\00000\000\000\000\000\000"
> > > > -/* offset=295 */ "num_cores\000tool\000Number of cores. A core consists of 1 or more thread, with each thread being associated with a logical Linux CPU\000config=5\000\00000\000\000\000\000\000"
> > > > -/* offset=440 */ "num_cpus\000tool\000Number of logical Linux CPUs. There may be multiple such CPUs on a core\000config=6\000\00000\000\000\000\000\000"
> > > > -/* offset=543 */ "num_cpus_online\000tool\000Number of online logical Linux CPUs. There may be multiple such CPUs on a core\000config=7\000\00000\000\000\000\000\000"
> > > > -/* offset=660 */ "num_dies\000tool\000Number of dies. Each die has 1 or more cores\000config=8\000\00000\000\000\000\000\000"
> > > > -/* offset=736 */ "num_packages\000tool\000Number of packages. Each package has 1 or more die\000config=9\000\00000\000\000\000\000\000"
> > > > -/* offset=822 */ "slots\000tool\000Number of functional units that in parallel can execute parts of an instruction\000config=0xa\000\00000\000\000\000\000\000"
> > > > -/* offset=932 */ "smt_on\000tool\0001 if simultaneous multithreading (aka hyperthreading) is enable otherwise 0\000config=0xb\000\00000\000\000\000\000\000"
> > > > -/* offset=1039 */ "system_tsc_freq\000tool\000The amount a Time Stamp Counter (TSC) increases per second\000config=0xc\000\00000\000\000\000\000\000"
> > > > -/* offset=1138 */ "default_core\000"
> > > > -/* offset=1151 */ "bp_l1_btb_correct\000branch\000L1 BTB Correction\000event=0x8a\000\00000\000\000\000\000\000"
> > > > -/* offset=1213 */ "bp_l2_btb_correct\000branch\000L2 BTB Correction\000event=0x8b\000\00000\000\000\000\000\000"
> > > > -/* offset=1275 */ "l3_cache_rd\000cache\000L3 cache access, read\000event=0x40\000\00000\000\000\000\000Attributable Level 3 cache access, read\000"
> > > > -/* offset=1373 */ "segment_reg_loads.any\000other\000Number of segment register loads\000event=6,period=200000,umask=0x80\000\00000\000\000\000\000\000"
> > > > -/* offset=1475 */ "dispatch_blocked.any\000other\000Memory cluster signals to block micro-op dispatch for any reason\000event=9,period=200000,umask=0x20\000\00000\000\000\000\000\000"
> > > > -/* offset=1608 */ "eist_trans\000other\000Number of Enhanced Intel SpeedStep(R) Technology (EIST) transitions\000event=0x3a,period=200000\000\00000\000\000\000\000\000"
> > > > -/* offset=1726 */ "hisi_sccl,ddrc\000"
> > > > -/* offset=1741 */ "uncore_hisi_ddrc.flux_wcmd\000uncore\000DDRC write commands\000event=2\000\00000\000\000\000\000\000"
> > > > -/* offset=1811 */ "uncore_cbox\000"
> > > > -/* offset=1823 */ "unc_cbo_xsnp_response.miss_eviction\000uncore\000A cross-core snoop resulted from L3 Eviction which misses in some processor core\000event=0x22,umask=0x81\000\00000\000\000\000\000\000"
> > > > -/* offset=1977 */ "event-hyphen\000uncore\000UNC_CBO_HYPHEN\000event=0xe0\000\00000\000\000\000\000\000"
> > > > -/* offset=2031 */ "event-two-hyph\000uncore\000UNC_CBO_TWO_HYPH\000event=0xc0\000\00000\000\000\000\000\000"
> > > > -/* offset=2089 */ "hisi_sccl,l3c\000"
> > > > -/* offset=2103 */ "uncore_hisi_l3c.rd_hit_cpipe\000uncore\000Total read hits\000event=7\000\00000\000\000\000\000\000"
> > > > -/* offset=2171 */ "uncore_imc_free_running\000"
> > > > -/* offset=2195 */ "uncore_imc_free_running.cache_miss\000uncore\000Total cache misses\000event=0x12\000\00000\000\000\000\000\000"
> > > > -/* offset=2275 */ "uncore_imc\000"
> > > > -/* offset=2286 */ "uncore_imc.cache_hits\000uncore\000Total cache hits\000event=0x34\000\00000\000\000\000\000\000"
> > > > -/* offset=2351 */ "uncore_sys_ddr_pmu\000"
> > > > -/* offset=2370 */ "sys_ddr_pmu.write_cycles\000uncore\000ddr write-cycles event\000event=0x2b\000v8\00000\000\000\000\000\000"
> > > > -/* offset=2446 */ "uncore_sys_ccn_pmu\000"
> > > > -/* offset=2465 */ "sys_ccn_pmu.read_cycles\000uncore\000ccn read-cycles event\000config=0x2c\0000x01\00000\000\000\000\000\000"
> > > > -/* offset=2542 */ "uncore_sys_cmn_pmu\000"
> > > > -/* offset=2561 */ "sys_cmn_pmu.hnf_cache_miss\000uncore\000Counts total cache misses in first lookup result (high priority)\000eventid=1,type=5\000(434|436|43c|43a).*\00000\000\000\000\000\000"
> > > > -/* offset=2704 */ "CPI\000\0001 / IPC\000\000\000\000\000\000\000\00000"
> > > > -/* offset=2726 */ "IPC\000group1\000inst_retired.any / cpu_clk_unhalted.thread\000\000\000\000\000\000\000\00000"
> > > > -/* offset=2789 */ "Frontend_Bound_SMT\000\000idq_uops_not_delivered.core / (4 * (cpu_clk_unhalted.thread / 2 * (1 + cpu_clk_unhalted.one_thread_active / cpu_clk_unhalted.ref_xclk)))\000\000\000\000\000\000\000\00000"
> > > > -/* offset=2955 */ "dcache_miss_cpi\000\000l1d\\-loads\\-misses / inst_retired.any\000\000\000\000\000\000\000\00000"
> > > > -/* offset=3019 */ "icache_miss_cycles\000\000l1i\\-loads\\-misses / inst_retired.any\000\000\000\000\000\000\000\00000"
> > > > -/* offset=3086 */ "cache_miss_cycles\000group1\000dcache_miss_cpi + icache_miss_cycles\000\000\000\000\000\000\000\00000"
> > > > -/* offset=3157 */ "DCache_L2_All_Hits\000\000l2_rqsts.demand_data_rd_hit + l2_rqsts.pf_hit + l2_rqsts.rfo_hit\000\000\000\000\000\000\000\00000"
> > > > -/* offset=3251 */ "DCache_L2_All_Miss\000\000max(l2_rqsts.all_demand_data_rd - l2_rqsts.demand_data_rd_hit, 0) + l2_rqsts.pf_miss + l2_rqsts.rfo_miss\000\000\000\000\000\000\000\00000"
> > > > -/* offset=3385 */ "DCache_L2_All\000\000DCache_L2_All_Hits + DCache_L2_All_Miss\000\000\000\000\000\000\000\00000"
> > > > -/* offset=3449 */ "DCache_L2_Hits\000\000d_ratio(DCache_L2_All_Hits, DCache_L2_All)\000\000\000\000\000\000\000\00000"
> > > > -/* offset=3517 */ "DCache_L2_Misses\000\000d_ratio(DCache_L2_All_Miss, DCache_L2_All)\000\000\000\000\000\000\000\00000"
> > > > -/* offset=3587 */ "M1\000\000ipc + M2\000\000\000\000\000\000\000\00000"
> > > > -/* offset=3609 */ "M2\000\000ipc + M1\000\000\000\000\000\000\000\00000"
> > > > -/* offset=3631 */ "M3\000\0001 / M3\000\000\000\000\000\000\000\00000"
> > > > -/* offset=3651 */ "L1D_Cache_Fill_BW\000\00064 * l1d.replacement / 1e9 / duration_time\000\000\000\000\000\000\000\00000"
> > > > +/* offset=0 */ "software\000"
> > > > +/* offset=9 */ "cpu-clock\000software\000Per-CPU high-resolution timer based event\000config=0\000\00000\000\000\000\000\000"
> > > > +/* offset=87 */ "task-clock\000software\000Task based high-resolution timer based event\000config=1\000\00000\000\000\000\000\000"
> > > > +/* offset=169 */ "faults\000software\000Number of page faults [This event is an alias of page-faults]\000config=2\000\00000\000\000\000\000\000"
> > > > +/* offset=264 */ "page-faults\000software\000Number of page faults [This event is an alias of faults]\000config=2\000\00000\000\000\000\000\000"
> > > > +/* offset=359 */ "context-switches\000software\000Number of context switches [This event is an alias of cs]\000config=3\000\00000\000\000\000\000\000"
> > > > +/* offset=460 */ "cs\000software\000Number of context switches [This event is an alias of context-switches]\000config=3\000\00000\000\000\000\000\000"
> > > > +/* offset=561 */ "cpu-migrations\000software\000Number of times a process has migrated to a new CPU [This event is an alias of migrations]\000config=4\000\00000\000\000\000\000\000"
> > > > +/* offset=693 */ "migrations\000software\000Number of times a process has migrated to a new CPU [This event is an alias of cpu-migrations]\000config=4\000\00000\000\000\000\000\000"
> > > > +/* offset=825 */ "minor-faults\000software\000Number of minor page faults. Minor faults don't require I/O to handle\000config=5\000\00000\000\000\000\000\000"
> > > > +/* offset=934 */ "major-faults\000software\000Number of major page faults. Major faults require I/O to handle\000config=6\000\00000\000\000\000\000\000"
> > > > +/* offset=1037 */ "alignment-faults\000software\000Number of kernel handled memory alignment faults\000config=7\000\00000\000\000\000\000\000"
> > > > +/* offset=1129 */ "emulation-faults\000software\000Number of kernel handled unimplemented instruction faults handled through emulation\000config=8\000\00000\000\000\000\000\000"
> > > > +/* offset=1256 */ "dummy\000software\000A placeholder event that doesn't count anything\000config=9\000\00000\000\000\000\000\000"
> > > > +/* offset=1336 */ "bpf-output\000software\000An event used by BPF programs to write to the perf ring buffer\000config=0xa\000\00000\000\000\000\000\000"
> > > > +/* offset=1438 */ "cgroup-switches\000software\000Number of context switches to a task in a different cgroup\000config=0xb\000\00000\000\000\000\000\000"
> > > > +/* offset=1541 */ "tool\000"
> > > > +/* offset=1546 */ "duration_time\000tool\000Wall clock interval time in nanoseconds\000config=1\000\00000\000\000\000\000\000"
> > > > +/* offset=1622 */ "user_time\000tool\000User (non-kernel) time in nanoseconds\000config=2\000\00000\000\000\000\000\000"
> > > > +/* offset=1692 */ "system_time\000tool\000System/kernel time in nanoseconds\000config=3\000\00000\000\000\000\000\000"
> > > > +/* offset=1760 */ "has_pmem\000tool\0001 if persistent memory installed otherwise 0\000config=4\000\00000\000\000\000\000\000"
> > > > +/* offset=1836 */ "num_cores\000tool\000Number of cores. A core consists of 1 or more thread, with each thread being associated with a logical Linux CPU\000config=5\000\00000\000\000\000\000\000"
> > > > +/* offset=1981 */ "num_cpus\000tool\000Number of logical Linux CPUs. There may be multiple such CPUs on a core\000config=6\000\00000\000\000\000\000\000"
> > > > +/* offset=2084 */ "num_cpus_online\000tool\000Number of online logical Linux CPUs. There may be multiple such CPUs on a core\000config=7\000\00000\000\000\000\000\000"
> > > > +/* offset=2201 */ "num_dies\000tool\000Number of dies. Each die has 1 or more cores\000config=8\000\00000\000\000\000\000\000"
> > > > +/* offset=2277 */ "num_packages\000tool\000Number of packages. Each package has 1 or more die\000config=9\000\00000\000\000\000\000\000"
> > > > +/* offset=2363 */ "slots\000tool\000Number of functional units that in parallel can execute parts of an instruction\000config=0xa\000\00000\000\000\000\000\000"
> > > > +/* offset=2473 */ "smt_on\000tool\0001 if simultaneous multithreading (aka hyperthreading) is enable otherwise 0\000config=0xb\000\00000\000\000\000\000\000"
> > > > +/* offset=2580 */ "system_tsc_freq\000tool\000The amount a Time Stamp Counter (TSC) increases per second\000config=0xc\000\00000\000\000\000\000\000"
> > > > +/* offset=2679 */ "default_core\000"
> > > > +/* offset=2692 */ "bp_l1_btb_correct\000branch\000L1 BTB Correction\000event=0x8a\000\00000\000\000\000\000\000"
> > > > +/* offset=2754 */ "bp_l2_btb_correct\000branch\000L2 BTB Correction\000event=0x8b\000\00000\000\000\000\000\000"
> > > > +/* offset=2816 */ "l3_cache_rd\000cache\000L3 cache access, read\000event=0x40\000\00000\000\000\000\000Attributable Level 3 cache access, read\000"
> > > > +/* offset=2914 */ "segment_reg_loads.any\000other\000Number of segment register loads\000event=6,period=200000,umask=0x80\000\00000\000\000\000\000\000"
> > > > +/* offset=3016 */ "dispatch_blocked.any\000other\000Memory cluster signals to block micro-op dispatch for any reason\000event=9,period=200000,umask=0x20\000\00000\000\000\000\000\000"
> > > > +/* offset=3149 */ "eist_trans\000other\000Number of Enhanced Intel SpeedStep(R) Technology (EIST) transitions\000event=0x3a,period=200000\000\00000\000\000\000\000\000"
> > > > +/* offset=3267 */ "hisi_sccl,ddrc\000"
> > > > +/* offset=3282 */ "uncore_hisi_ddrc.flux_wcmd\000uncore\000DDRC write commands\000event=2\000\00000\000\000\000\000\000"
> > > > +/* offset=3352 */ "uncore_cbox\000"
> > > > +/* offset=3364 */ "unc_cbo_xsnp_response.miss_eviction\000uncore\000A cross-core snoop resulted from L3 Eviction which misses in some processor core\000event=0x22,umask=0x81\000\00000\000\000\000\000\000"
> > > > +/* offset=3518 */ "event-hyphen\000uncore\000UNC_CBO_HYPHEN\000event=0xe0\000\00000\000\000\000\000\000"
> > > > +/* offset=3572 */ "event-two-hyph\000uncore\000UNC_CBO_TWO_HYPH\000event=0xc0\000\00000\000\000\000\000\000"
> > > > +/* offset=3630 */ "hisi_sccl,l3c\000"
> > > > +/* offset=3644 */ "uncore_hisi_l3c.rd_hit_cpipe\000uncore\000Total read hits\000event=7\000\00000\000\000\000\000\000"
> > > > +/* offset=3712 */ "uncore_imc_free_running\000"
> > > > +/* offset=3736 */ "uncore_imc_free_running.cache_miss\000uncore\000Total cache misses\000event=0x12\000\00000\000\000\000\000\000"
> > > > +/* offset=3816 */ "uncore_imc\000"
> > > > +/* offset=3827 */ "uncore_imc.cache_hits\000uncore\000Total cache hits\000event=0x34\000\00000\000\000\000\000\000"
> > > > +/* offset=3892 */ "uncore_sys_ddr_pmu\000"
> > > > +/* offset=3911 */ "sys_ddr_pmu.write_cycles\000uncore\000ddr write-cycles event\000event=0x2b\000v8\00000\000\000\000\000\000"
> > > > +/* offset=3987 */ "uncore_sys_ccn_pmu\000"
> > > > +/* offset=4006 */ "sys_ccn_pmu.read_cycles\000uncore\000ccn read-cycles event\000config=0x2c\0000x01\00000\000\000\000\000\000"
> > > > +/* offset=4083 */ "uncore_sys_cmn_pmu\000"
> > > > +/* offset=4102 */ "sys_cmn_pmu.hnf_cache_miss\000uncore\000Counts total cache misses in first lookup result (high priority)\000eventid=1,type=5\000(434|436|43c|43a).*\00000\000\000\000\000\000"
> > > > +/* offset=4245 */ "CPI\000\0001 / IPC\000\000\000\000\000\000\000\00000"
> > > > +/* offset=4267 */ "IPC\000group1\000inst_retired.any / cpu_clk_unhalted.thread\000\000\000\000\000\000\000\00000"
> > > > +/* offset=4330 */ "Frontend_Bound_SMT\000\000idq_uops_not_delivered.core / (4 * (cpu_clk_unhalted.thread / 2 * (1 + cpu_clk_unhalted.one_thread_active / cpu_clk_unhalted.ref_xclk)))\000\000\000\000\000\000\000\00000"
> > > > +/* offset=4496 */ "dcache_miss_cpi\000\000l1d\\-loads\\-misses / inst_retired.any\000\000\000\000\000\000\000\00000"
> > > > +/* offset=4560 */ "icache_miss_cycles\000\000l1i\\-loads\\-misses / inst_retired.any\000\000\000\000\000\000\000\00000"
> > > > +/* offset=4627 */ "cache_miss_cycles\000group1\000dcache_miss_cpi + icache_miss_cycles\000\000\000\000\000\000\000\00000"
> > > > +/* offset=4698 */ "DCache_L2_All_Hits\000\000l2_rqsts.demand_data_rd_hit + l2_rqsts.pf_hit + l2_rqsts.rfo_hit\000\000\000\000\000\000\000\00000"
> > > > +/* offset=4792 */ "DCache_L2_All_Miss\000\000max(l2_rqsts.all_demand_data_rd - l2_rqsts.demand_data_rd_hit, 0) + l2_rqsts.pf_miss + l2_rqsts.rfo_miss\000\000\000\000\000\000\000\00000"
> > > > +/* offset=4926 */ "DCache_L2_All\000\000DCache_L2_All_Hits + DCache_L2_All_Miss\000\000\000\000\000\000\000\00000"
> > > > +/* offset=4990 */ "DCache_L2_Hits\000\000d_ratio(DCache_L2_All_Hits, DCache_L2_All)\000\000\000\000\000\000\000\00000"
> > > > +/* offset=5058 */ "DCache_L2_Misses\000\000d_ratio(DCache_L2_All_Miss, DCache_L2_All)\000\000\000\000\000\000\000\00000"
> > > > +/* offset=5128 */ "M1\000\000ipc + M2\000\000\000\000\000\000\000\00000"
> > > > +/* offset=5150 */ "M2\000\000ipc + M1\000\000\000\000\000\000\000\00000"
> > > > +/* offset=5172 */ "M3\000\0001 / M3\000\000\000\000\000\000\000\00000"
> > > > +/* offset=5192 */ "L1D_Cache_Fill_BW\000\00064 * l1d.replacement / 1e9 / duration_time\000\000\000\000\000\000\000\00000"
> > > >  ;
> > > >
> > > > +static const struct compact_pmu_event pmu_events__common_software[] = {
> > > > +{ 1037 }, /* alignment-faults\000software\000Number of kernel handled memory alignment faults\000config=7\000\00000\000\000\000\000\000 */
> > > > +{ 1336 }, /* bpf-output\000software\000An event used by BPF programs to write to the perf ring buffer\000config=0xa\000\00000\000\000\000\000\000 */
> > > > +{ 1438 }, /* cgroup-switches\000software\000Number of context switches to a task in a different cgroup\000config=0xb\000\00000\000\000\000\000\000 */
> > > > +{ 359 }, /* context-switches\000software\000Number of context switches [This event is an alias of cs]\000config=3\000\00000\000\000\000\000\000 */
> > > > +{ 9 }, /* cpu-clock\000software\000Per-CPU high-resolution timer based event\000config=0\000\00000\000\000\000\000\000 */
> > > > +{ 561 }, /* cpu-migrations\000software\000Number of times a process has migrated to a new CPU [This event is an alias of migrations]\000config=4\000\00000\000\000\000\000\000 */
> > > > +{ 460 }, /* cs\000software\000Number of context switches [This event is an alias of context-switches]\000config=3\000\00000\000\000\000\000\000 */
> > > > +{ 1256 }, /* dummy\000software\000A placeholder event that doesn't count anything\000config=9\000\00000\000\000\000\000\000 */
> > > > +{ 1129 }, /* emulation-faults\000software\000Number of kernel handled unimplemented instruction faults handled through emulation\000config=8\000\00000\000\000\000\000\000 */
> > > > +{ 169 }, /* faults\000software\000Number of page faults [This event is an alias of page-faults]\000config=2\000\00000\000\000\000\000\000 */
> > > > +{ 934 }, /* major-faults\000software\000Number of major page faults. Major faults require I/O to handle\000config=6\000\00000\000\000\000\000\000 */
> > > > +{ 693 }, /* migrations\000software\000Number of times a process has migrated to a new CPU [This event is an alias of cpu-migrations]\000config=4\000\00000\000\000\000\000\000 */
> > > > +{ 825 }, /* minor-faults\000software\000Number of minor page faults. Minor faults don't require I/O to handle\000config=5\000\00000\000\000\000\000\000 */
> > > > +{ 264 }, /* page-faults\000software\000Number of page faults [This event is an alias of faults]\000config=2\000\00000\000\000\000\000\000 */
> > > > +{ 87 }, /* task-clock\000software\000Task based high-resolution timer based event\000config=1\000\00000\000\000\000\000\000 */
> > > > +};
> > > >  static const struct compact_pmu_event pmu_events__common_tool[] = {
> > > > -{ 5 }, /* duration_time\000tool\000Wall clock interval time in nanoseconds\000config=1\000\00000\000\000\000\000\000 */
> > > > -{ 219 }, /* has_pmem\000tool\0001 if persistent memory installed otherwise 0\000config=4\000\00000\000\000\000\000\000 */
> > > > -{ 295 }, /* num_cores\000tool\000Number of cores. A core consists of 1 or more thread, with each thread being associated with a logical Linux CPU\000config=5\000\00000\000\000\000\000\000 */
> > > > -{ 440 }, /* num_cpus\000tool\000Number of logical Linux CPUs. There may be multiple such CPUs on a core\000config=6\000\00000\000\000\000\000\000 */
> > > > -{ 543 }, /* num_cpus_online\000tool\000Number of online logical Linux CPUs. There may be multiple such CPUs on a core\000config=7\000\00000\000\000\000\000\000 */
> > > > -{ 660 }, /* num_dies\000tool\000Number of dies. Each die has 1 or more cores\000config=8\000\00000\000\000\000\000\000 */
> > > > -{ 736 }, /* num_packages\000tool\000Number of packages. Each package has 1 or more die\000config=9\000\00000\000\000\000\000\000 */
> > > > -{ 822 }, /* slots\000tool\000Number of functional units that in parallel can execute parts of an instruction\000config=0xa\000\00000\000\000\000\000\000 */
> > > > -{ 932 }, /* smt_on\000tool\0001 if simultaneous multithreading (aka hyperthreading) is enable otherwise 0\000config=0xb\000\00000\000\000\000\000\000 */
> > > > -{ 151 }, /* system_time\000tool\000System/kernel time in nanoseconds\000config=3\000\00000\000\000\000\000\000 */
> > > > -{ 1039 }, /* system_tsc_freq\000tool\000The amount a Time Stamp Counter (TSC) increases per second\000config=0xc\000\00000\000\000\000\000\000 */
> > > > -{ 81 }, /* user_time\000tool\000User (non-kernel) time in nanoseconds\000config=2\000\00000\000\000\000\000\000 */
> > > > +{ 1546 }, /* duration_time\000tool\000Wall clock interval time in nanoseconds\000config=1\000\00000\000\000\000\000\000 */
> > > > +{ 1760 }, /* has_pmem\000tool\0001 if persistent memory installed otherwise 0\000config=4\000\00000\000\000\000\000\000 */
> > > > +{ 1836 }, /* num_cores\000tool\000Number of cores. A core consists of 1 or more thread, with each thread being associated with a logical Linux CPU\000config=5\000\00000\000\000\000\000\000 */
> > > > +{ 1981 }, /* num_cpus\000tool\000Number of logical Linux CPUs. There may be multiple such CPUs on a core\000config=6\000\00000\000\000\000\000\000 */
> > > > +{ 2084 }, /* num_cpus_online\000tool\000Number of online logical Linux CPUs. There may be multiple such CPUs on a core\000config=7\000\00000\000\000\000\000\000 */
> > > > +{ 2201 }, /* num_dies\000tool\000Number of dies. Each die has 1 or more cores\000config=8\000\00000\000\000\000\000\000 */
> > > > +{ 2277 }, /* num_packages\000tool\000Number of packages. Each package has 1 or more die\000config=9\000\00000\000\000\000\000\000 */
> > > > +{ 2363 }, /* slots\000tool\000Number of functional units that in parallel can execute parts of an instruction\000config=0xa\000\00000\000\000\000\000\000 */
> > > > +{ 2473 }, /* smt_on\000tool\0001 if simultaneous multithreading (aka hyperthreading) is enable otherwise 0\000config=0xb\000\00000\000\000\000\000\000 */
> > > > +{ 1692 }, /* system_time\000tool\000System/kernel time in nanoseconds\000config=3\000\00000\000\000\000\000\000 */
> > > > +{ 2580 }, /* system_tsc_freq\000tool\000The amount a Time Stamp Counter (TSC) increases per second\000config=0xc\000\00000\000\000\000\000\000 */
> > > > +{ 1622 }, /* user_time\000tool\000User (non-kernel) time in nanoseconds\000config=2\000\00000\000\000\000\000\000 */
> > > >
> > > >  };
> > > >
> > > >  const struct pmu_table_entry pmu_events__common[] = {
> > > > +{
> > > > +     .entries = pmu_events__common_software,
> > > > +     .num_entries = ARRAY_SIZE(pmu_events__common_software),
> > > > +     .pmu_name = { 0 /* software\000 */ },
> > > > +},
> > > >  {
> > > >       .entries = pmu_events__common_tool,
> > > >       .num_entries = ARRAY_SIZE(pmu_events__common_tool),
> > > > -     .pmu_name = { 0 /* tool\000 */ },
> > > > +     .pmu_name = { 1541 /* tool\000 */ },
> > > >  },
> > > >  };
> > > >
> > > >  static const struct compact_pmu_event pmu_events__test_soc_cpu_default_core[] = {
> > > > -{ 1151 }, /* bp_l1_btb_correct\000branch\000L1 BTB Correction\000event=0x8a\000\00000\000\000\000\000\000 */
> > > > -{ 1213 }, /* bp_l2_btb_correct\000branch\000L2 BTB Correction\000event=0x8b\000\00000\000\000\000\000\000 */
> > > > -{ 1475 }, /* dispatch_blocked.any\000other\000Memory cluster signals to block micro-op dispatch for any reason\000event=9,period=200000,umask=0x20\000\00000\000\000\000\000\000 */
> > > > -{ 1608 }, /* eist_trans\000other\000Number of Enhanced Intel SpeedStep(R) Technology (EIST) transitions\000event=0x3a,period=200000\000\00000\000\000\000\000\000 */
> > > > -{ 1275 }, /* l3_cache_rd\000cache\000L3 cache access, read\000event=0x40\000\00000\000\000\000\000Attributable Level 3 cache access, read\000 */
> > > > -{ 1373 }, /* segment_reg_loads.any\000other\000Number of segment register loads\000event=6,period=200000,umask=0x80\000\00000\000\000\000\000\000 */
> > > > +{ 2692 }, /* bp_l1_btb_correct\000branch\000L1 BTB Correction\000event=0x8a\000\00000\000\000\000\000\000 */
> > > > +{ 2754 }, /* bp_l2_btb_correct\000branch\000L2 BTB Correction\000event=0x8b\000\00000\000\000\000\000\000 */
> > > > +{ 3016 }, /* dispatch_blocked.any\000other\000Memory cluster signals to block micro-op dispatch for any reason\000event=9,period=200000,umask=0x20\000\00000\000\000\000\000\000 */
> > > > +{ 3149 }, /* eist_trans\000other\000Number of Enhanced Intel SpeedStep(R) Technology (EIST) transitions\000event=0x3a,period=200000\000\00000\000\000\000\000\000 */
> > > > +{ 2816 }, /* l3_cache_rd\000cache\000L3 cache access, read\000event=0x40\000\00000\000\000\000\000Attributable Level 3 cache access, read\000 */
> > > > +{ 2914 }, /* segment_reg_loads.any\000other\000Number of segment register loads\000event=6,period=200000,umask=0x80\000\00000\000\000\000\000\000 */
> > > >  };
> > > >  static const struct compact_pmu_event pmu_events__test_soc_cpu_hisi_sccl_ddrc[] = {
> > > > -{ 1741 }, /* uncore_hisi_ddrc.flux_wcmd\000uncore\000DDRC write commands\000event=2\000\00000\000\000\000\000\000 */
> > > > +{ 3282 }, /* uncore_hisi_ddrc.flux_wcmd\000uncore\000DDRC write commands\000event=2\000\00000\000\000\000\000\000 */
> > > >  };
> > > >  static const struct compact_pmu_event pmu_events__test_soc_cpu_hisi_sccl_l3c[] = {
> > > > -{ 2103 }, /* uncore_hisi_l3c.rd_hit_cpipe\000uncore\000Total read hits\000event=7\000\00000\000\000\000\000\000 */
> > > > +{ 3644 }, /* uncore_hisi_l3c.rd_hit_cpipe\000uncore\000Total read hits\000event=7\000\00000\000\000\000\000\000 */
> > > >  };
> > > >  static const struct compact_pmu_event pmu_events__test_soc_cpu_uncore_cbox[] = {
> > > > -{ 1977 }, /* event-hyphen\000uncore\000UNC_CBO_HYPHEN\000event=0xe0\000\00000\000\000\000\000\000 */
> > > > -{ 2031 }, /* event-two-hyph\000uncore\000UNC_CBO_TWO_HYPH\000event=0xc0\000\00000\000\000\000\000\000 */
> > > > -{ 1823 }, /* unc_cbo_xsnp_response.miss_eviction\000uncore\000A cross-core snoop resulted from L3 Eviction which misses in some processor core\000event=0x22,umask=0x81\000\00000\000\000\000\000\000 */
> > > > +{ 3518 }, /* event-hyphen\000uncore\000UNC_CBO_HYPHEN\000event=0xe0\000\00000\000\000\000\000\000 */
> > > > +{ 3572 }, /* event-two-hyph\000uncore\000UNC_CBO_TWO_HYPH\000event=0xc0\000\00000\000\000\000\000\000 */
> > > > +{ 3364 }, /* unc_cbo_xsnp_response.miss_eviction\000uncore\000A cross-core snoop resulted from L3 Eviction which misses in some processor core\000event=0x22,umask=0x81\000\00000\000\000\000\000\000 */
> > > >  };
> > > >  static const struct compact_pmu_event pmu_events__test_soc_cpu_uncore_imc[] = {
> > > > -{ 2286 }, /* uncore_imc.cache_hits\000uncore\000Total cache hits\000event=0x34\000\00000\000\000\000\000\000 */
> > > > +{ 3827 }, /* uncore_imc.cache_hits\000uncore\000Total cache hits\000event=0x34\000\00000\000\000\000\000\000 */
> > > >  };
> > > >  static const struct compact_pmu_event pmu_events__test_soc_cpu_uncore_imc_free_running[] = {
> > > > -{ 2195 }, /* uncore_imc_free_running.cache_miss\000uncore\000Total cache misses\000event=0x12\000\00000\000\000\000\000\000 */
> > > > +{ 3736 }, /* uncore_imc_free_running.cache_miss\000uncore\000Total cache misses\000event=0x12\000\00000\000\000\000\000\000 */
> > > >
> > > >  };
> > > >
> > > > @@ -129,51 +167,51 @@ const struct pmu_table_entry pmu_events__test_soc_cpu[] = {
> > > >  {
> > > >       .entries = pmu_events__test_soc_cpu_default_core,
> > > >       .num_entries = ARRAY_SIZE(pmu_events__test_soc_cpu_default_core),
> > > > -     .pmu_name = { 1138 /* default_core\000 */ },
> > > > +     .pmu_name = { 2679 /* default_core\000 */ },
> > > >  },
> > > >  {
> > > >       .entries = pmu_events__test_soc_cpu_hisi_sccl_ddrc,
> > > >       .num_entries = ARRAY_SIZE(pmu_events__test_soc_cpu_hisi_sccl_ddrc),
> > > > -     .pmu_name = { 1726 /* hisi_sccl,ddrc\000 */ },
> > > > +     .pmu_name = { 3267 /* hisi_sccl,ddrc\000 */ },
> > > >  },
> > > >  {
> > > >       .entries = pmu_events__test_soc_cpu_hisi_sccl_l3c,
> > > >       .num_entries = ARRAY_SIZE(pmu_events__test_soc_cpu_hisi_sccl_l3c),
> > > > -     .pmu_name = { 2089 /* hisi_sccl,l3c\000 */ },
> > > > +     .pmu_name = { 3630 /* hisi_sccl,l3c\000 */ },
> > > >  },
> > > >  {
> > > >       .entries = pmu_events__test_soc_cpu_uncore_cbox,
> > > >       .num_entries = ARRAY_SIZE(pmu_events__test_soc_cpu_uncore_cbox),
> > > > -     .pmu_name = { 1811 /* uncore_cbox\000 */ },
> > > > +     .pmu_name = { 3352 /* uncore_cbox\000 */ },
> > > >  },
> > > >  {
> > > >       .entries = pmu_events__test_soc_cpu_uncore_imc,
> > > >       .num_entries = ARRAY_SIZE(pmu_events__test_soc_cpu_uncore_imc),
> > > > -     .pmu_name = { 2275 /* uncore_imc\000 */ },
> > > > +     .pmu_name = { 3816 /* uncore_imc\000 */ },
> > > >  },
> > > >  {
> > > >       .entries = pmu_events__test_soc_cpu_uncore_imc_free_running,
> > > >       .num_entries = ARRAY_SIZE(pmu_events__test_soc_cpu_uncore_imc_free_running),
> > > > -     .pmu_name = { 2171 /* uncore_imc_free_running\000 */ },
> > > > +     .pmu_name = { 3712 /* uncore_imc_free_running\000 */ },
> > > >  },
> > > >  };
> > > >
> > > >  static const struct compact_pmu_event pmu_metrics__test_soc_cpu_default_core[] = {
> > > > -{ 2704 }, /* CPI\000\0001 / IPC\000\000\000\000\000\000\000\00000 */
> > > > -{ 3385 }, /* DCache_L2_All\000\000DCache_L2_All_Hits + DCache_L2_All_Miss\000\000\000\000\000\000\000\00000 */
> > > > -{ 3157 }, /* DCache_L2_All_Hits\000\000l2_rqsts.demand_data_rd_hit + l2_rqsts.pf_hit + l2_rqsts.rfo_hit\000\000\000\000\000\000\000\00000 */
> > > > -{ 3251 }, /* DCache_L2_All_Miss\000\000max(l2_rqsts.all_demand_data_rd - l2_rqsts.demand_data_rd_hit, 0) + l2_rqsts.pf_miss + l2_rqsts.rfo_miss\000\000\000\000\000\000\000\00000 */
> > > > -{ 3449 }, /* DCache_L2_Hits\000\000d_ratio(DCache_L2_All_Hits, DCache_L2_All)\000\000\000\000\000\000\000\00000 */
> > > > -{ 3517 }, /* DCache_L2_Misses\000\000d_ratio(DCache_L2_All_Miss, DCache_L2_All)\000\000\000\000\000\000\000\00000 */
> > > > -{ 2789 }, /* Frontend_Bound_SMT\000\000idq_uops_not_delivered.core / (4 * (cpu_clk_unhalted.thread / 2 * (1 + cpu_clk_unhalted.one_thread_active / cpu_clk_unhalted.ref_xclk)))\000\000\000\000\000\000\000\00000 */
> > > > -{ 2726 }, /* IPC\000group1\000inst_retired.any / cpu_clk_unhalted.thread\000\000\000\000\000\000\000\00000 */
> > > > -{ 3651 }, /* L1D_Cache_Fill_BW\000\00064 * l1d.replacement / 1e9 / duration_time\000\000\000\000\000\000\000\00000 */
> > > > -{ 3587 }, /* M1\000\000ipc + M2\000\000\000\000\000\000\000\00000 */
> > > > -{ 3609 }, /* M2\000\000ipc + M1\000\000\000\000\000\000\000\00000 */
> > > > -{ 3631 }, /* M3\000\0001 / M3\000\000\000\000\000\000\000\00000 */
> > > > -{ 3086 }, /* cache_miss_cycles\000group1\000dcache_miss_cpi + icache_miss_cycles\000\000\000\000\000\000\000\00000 */
> > > > -{ 2955 }, /* dcache_miss_cpi\000\000l1d\\-loads\\-misses / inst_retired.any\000\000\000\000\000\000\000\00000 */
> > > > -{ 3019 }, /* icache_miss_cycles\000\000l1i\\-loads\\-misses / inst_retired.any\000\000\000\000\000\000\000\00000 */
> > > > +{ 4245 }, /* CPI\000\0001 / IPC\000\000\000\000\000\000\000\00000 */
> > > > +{ 4926 }, /* DCache_L2_All\000\000DCache_L2_All_Hits + DCache_L2_All_Miss\000\000\000\000\000\000\000\00000 */
> > > > +{ 4698 }, /* DCache_L2_All_Hits\000\000l2_rqsts.demand_data_rd_hit + l2_rqsts.pf_hit + l2_rqsts.rfo_hit\000\000\000\000\000\000\000\00000 */
> > > > +{ 4792 }, /* DCache_L2_All_Miss\000\000max(l2_rqsts.all_demand_data_rd - l2_rqsts.demand_data_rd_hit, 0) + l2_rqsts.pf_miss + l2_rqsts.rfo_miss\000\000\000\000\000\000\000\00000 */
> > > > +{ 4990 }, /* DCache_L2_Hits\000\000d_ratio(DCache_L2_All_Hits, DCache_L2_All)\000\000\000\000\000\000\000\00000 */
> > > > +{ 5058 }, /* DCache_L2_Misses\000\000d_ratio(DCache_L2_All_Miss, DCache_L2_All)\000\000\000\000\000\000\000\00000 */
> > > > +{ 4330 }, /* Frontend_Bound_SMT\000\000idq_uops_not_delivered.core / (4 * (cpu_clk_unhalted.thread / 2 * (1 + cpu_clk_unhalted.one_thread_active / cpu_clk_unhalted.ref_xclk)))\000\000\000\000\000\000\000\00000 */
> > > > +{ 4267 }, /* IPC\000group1\000inst_retired.any / cpu_clk_unhalted.thread\000\000\000\000\000\000\000\00000 */
> > > > +{ 5192 }, /* L1D_Cache_Fill_BW\000\00064 * l1d.replacement / 1e9 / duration_time\000\000\000\000\000\000\000\00000 */
> > > > +{ 5128 }, /* M1\000\000ipc + M2\000\000\000\000\000\000\000\00000 */
> > > > +{ 5150 }, /* M2\000\000ipc + M1\000\000\000\000\000\000\000\00000 */
> > > > +{ 5172 }, /* M3\000\0001 / M3\000\000\000\000\000\000\000\00000 */
> > > > +{ 4627 }, /* cache_miss_cycles\000group1\000dcache_miss_cpi + icache_miss_cycles\000\000\000\000\000\000\000\00000 */
> > > > +{ 4496 }, /* dcache_miss_cpi\000\000l1d\\-loads\\-misses / inst_retired.any\000\000\000\000\000\000\000\00000 */
> > > > +{ 4560 }, /* icache_miss_cycles\000\000l1i\\-loads\\-misses / inst_retired.any\000\000\000\000\000\000\000\00000 */
> > > >
> > > >  };
> > > >
> > > > @@ -181,18 +219,18 @@ const struct pmu_table_entry pmu_metrics__test_soc_cpu[] = {
> > > >  {
> > > >       .entries = pmu_metrics__test_soc_cpu_default_core,
> > > >       .num_entries = ARRAY_SIZE(pmu_metrics__test_soc_cpu_default_core),
> > > > -     .pmu_name = { 1138 /* default_core\000 */ },
> > > > +     .pmu_name = { 2679 /* default_core\000 */ },
> > > >  },
> > > >  };
> > > >
> > > >  static const struct compact_pmu_event pmu_events__test_soc_sys_uncore_sys_ccn_pmu[] = {
> > > > -{ 2465 }, /* sys_ccn_pmu.read_cycles\000uncore\000ccn read-cycles event\000config=0x2c\0000x01\00000\000\000\000\000\000 */
> > > > +{ 4006 }, /* sys_ccn_pmu.read_cycles\000uncore\000ccn read-cycles event\000config=0x2c\0000x01\00000\000\000\000\000\000 */
> > > >  };
> > > >  static const struct compact_pmu_event pmu_events__test_soc_sys_uncore_sys_cmn_pmu[] = {
> > > > -{ 2561 }, /* sys_cmn_pmu.hnf_cache_miss\000uncore\000Counts total cache misses in first lookup result (high priority)\000eventid=1,type=5\000(434|436|43c|43a).*\00000\000\000\000\000\000 */
> > > > +{ 4102 }, /* sys_cmn_pmu.hnf_cache_miss\000uncore\000Counts total cache misses in first lookup result (high priority)\000eventid=1,type=5\000(434|436|43c|43a).*\00000\000\000\000\000\000 */
> > > >  };
> > > >  static const struct compact_pmu_event pmu_events__test_soc_sys_uncore_sys_ddr_pmu[] = {
> > > > -{ 2370 }, /* sys_ddr_pmu.write_cycles\000uncore\000ddr write-cycles event\000event=0x2b\000v8\00000\000\000\000\000\000 */
> > > > +{ 3911 }, /* sys_ddr_pmu.write_cycles\000uncore\000ddr write-cycles event\000event=0x2b\000v8\00000\000\000\000\000\000 */
> > > >
> > > >  };
> > > >
> > > > @@ -200,17 +238,17 @@ const struct pmu_table_entry pmu_events__test_soc_sys[] = {
> > > >  {
> > > >       .entries = pmu_events__test_soc_sys_uncore_sys_ccn_pmu,
> > > >       .num_entries = ARRAY_SIZE(pmu_events__test_soc_sys_uncore_sys_ccn_pmu),
> > > > -     .pmu_name = { 2446 /* uncore_sys_ccn_pmu\000 */ },
> > > > +     .pmu_name = { 3987 /* uncore_sys_ccn_pmu\000 */ },
> > > >  },
> > > >  {
> > > >       .entries = pmu_events__test_soc_sys_uncore_sys_cmn_pmu,
> > > >       .num_entries = ARRAY_SIZE(pmu_events__test_soc_sys_uncore_sys_cmn_pmu),
> > > > -     .pmu_name = { 2542 /* uncore_sys_cmn_pmu\000 */ },
> > > > +     .pmu_name = { 4083 /* uncore_sys_cmn_pmu\000 */ },
> > > >  },
> > > >  {
> > > >       .entries = pmu_events__test_soc_sys_uncore_sys_ddr_pmu,
> > > >       .num_entries = ARRAY_SIZE(pmu_events__test_soc_sys_uncore_sys_ddr_pmu),
> > > > -     .pmu_name = { 2351 /* uncore_sys_ddr_pmu\000 */ },
> > > > +     .pmu_name = { 3892 /* uncore_sys_ddr_pmu\000 */ },
> > > >  },
> > > >  };
> > > >
> > > > @@ -632,8 +670,20 @@ static const struct pmu_events_map *map_for_pmu(struct perf_pmu *pmu)
> > > >  {
> > > >          struct perf_cpu cpu = {-1};
> > > >
> > > > -        if (pmu)
> > > > +        if (pmu) {
> > > > +                for (size_t i=0; i < ARRAY_SIZE(pmu_events__common); i++) {
> > > > +                        const char *pmu_name = &big_c_string[pmu_events__common[i].pmu_name.offset];
> > > > +
> > > > +                        if (!strcmp(pmu_name, pmu->name)) {
> > > > +                                const struct pmu_events_map *map = &pmu_events_map[0];
> > > > +
> > > > +                                while (strcmp("common", map->arch))
> > > > +                                        map++;
> > > > +                                return map;
> > > > +                        }
> > > > +                }
> > > >                  cpu = perf_cpu_map__min(pmu->cpus);
> > > > +        }
> > > >          return map_for_cpu(cpu);
> > > >  }
> > > >
> > > > diff --git a/tools/perf/pmu-events/jevents.py b/tools/perf/pmu-events/jevents.py
> > > > index e821155151ec..76c1e7b0bc22 100755
> > > > --- a/tools/perf/pmu-events/jevents.py
> > > > +++ b/tools/perf/pmu-events/jevents.py
> > > > @@ -295,6 +295,7 @@ class JsonEvent:
> > > >            'cpu_atom': 'cpu_atom',
> > > >            'ali_drw': 'ali_drw',
> > > >            'arm_cmn': 'arm_cmn',
> > > > +          'software': 'software',
> > > >            'tool': 'tool',
> > > >        }
> > > >        return table[unit] if unit in table else f'uncore_{unit.lower()}'
> > > > @@ -1158,8 +1159,20 @@ static const struct pmu_events_map *map_for_pmu(struct perf_pmu *pmu)
> > > >  {
> > > >          struct perf_cpu cpu = {-1};
> > > >
> > > > -        if (pmu)
> > > > +        if (pmu) {
> > > > +                for (size_t i=0; i < ARRAY_SIZE(pmu_events__common); i++) {
> > > > +                        const char *pmu_name = &big_c_string[pmu_events__common[i].pmu_name.offset];
> > > > +
> > > > +                        if (!strcmp(pmu_name, pmu->name)) {
> > > > +                                const struct pmu_events_map *map = &pmu_events_map[0];
> > > > +
> > > > +                                while (strcmp("common", map->arch))
> > > > +                                        map++;
> > > > +                                return map;
> > > > +                        }
> > > > +                }
> > > >                  cpu = perf_cpu_map__min(pmu->cpus);
> > > > +        }
> > > >          return map_for_cpu(cpu);
> > > >  }
> > > >
> > > > --
> > > > 2.50.0.727.gbf7dc18ff4-goog
> > > >

^ permalink raw reply	[flat|nested] 41+ messages in thread

* Re: [PATCH v7 02/16] perf jevents: Add common software event json
  2025-07-24  1:47         ` Ian Rogers
@ 2025-07-24 16:58           ` Namhyung Kim
  0 siblings, 0 replies; 41+ messages in thread
From: Namhyung Kim @ 2025-07-24 16:58 UTC (permalink / raw)
  To: Ian Rogers
  Cc: Peter Zijlstra, Ingo Molnar, Arnaldo Carvalho de Melo,
	Mark Rutland, Alexander Shishkin, Jiri Olsa, Adrian Hunter,
	Kan Liang, James Clark, Xu Yang, Masami Hiramatsu (Google),
	Collin Funk, Howard Chu, Weilin Wang, Andi Kleen,
	Dr. David Alan Gilbert, Thomas Richter, Tiezhu Yang,
	Gautam Menghani, Thomas Falcon, Chun-Tse Shao, linux-kernel,
	linux-perf-users

Hi Ian,

On Wed, Jul 23, 2025 at 06:47:38PM -0700, Ian Rogers wrote:
> On Wed, Jul 23, 2025 at 5:10 PM Namhyung Kim <namhyung@kernel.org> wrote:
> >
> > On Wed, Jul 23, 2025 at 03:34:07PM -0700, Ian Rogers wrote:
> > > On Wed, Jul 23, 2025 at 11:24 AM Namhyung Kim <namhyung@kernel.org> wrote:
> > > >
> > > > On Mon, Jul 14, 2025 at 09:43:50AM -0700, Ian Rogers wrote:
> > > > > Add json for software events so that in perf list the events can have
> > > > > a description.  Common json exists for the tool PMU but it has no
> > > > > sysfs equivalent. Modify the map_for_pmu code to return the common map
> > > > > (rather than an architecture specific one) when a PMU with a common
> > > > > name is being looked for, this allows the events to be found.
> > > >
> > > > Can you please share new output of `perf list sw`?  I'm glad we have
> > > > description for software events.  But I'm also curious what's the side
> > > > effect of having them in JSON - maybe case insensitivity?
> > >
> > > The old software event names were matched in the lex code and were
> > > case sensitive. The events in the json are case insensitive and the
> > > case insensitive lex ones are removed in the next patch.
> >
> > And then it'd also use wildcard match, right?
> 
> Yes. So for example, the old behavior would allow:
> 
>   $ perf stat -e faults -a sleep 1
> 
> this can now be:
> 
>   $ perf stat -e software/faults/ -a sleep 1
>   $ perf stat -e Faults -a sleep 1
> ..

I see, thanks.

> 
> and if a PMU has an event named 'faults' then with the wildcarding
> both the software PMU faults event and the other PMU's faults event
> would be opened and read, sampled, etc. If the event can't be sampled
> then this could make `perf record` fail in just the same way as is
> fixed in (unmerged):
> https://lore.kernel.org/lkml/20250416045117.876775-1-irogers@google.com/
> which was particularly problematic on ARM CPUs.

Yeah, I think we need a logic to skip the failed events at least.  But I
think it's fine for now as we didn't touch the the default hardware
events yet.  Probably we can convert them to JSON as well later.  Let's
see if people would like this change or not. :)

> 
> > >
> > > The perf list output looks like:
> > >
> > > Before:
> > > ```
> > > List of pre-defined events (to be used in -e or -M):
> > >
> > >   branch-instructions OR branches                    [Hardware event]
> > >   branch-misses                                      [Hardware event]
> > >   bus-cycles                                         [Hardware event]
> > >   cache-misses                                       [Hardware event]
> > >   cache-references                                   [Hardware event]
> > >   cpu-cycles OR cycles                               [Hardware event]
> > >   instructions                                       [Hardware event]
> > >   ref-cycles                                         [Hardware event]
> > >   alignment-faults                                   [Software event]
> > >   bpf-output                                         [Software event]
> > >   cgroup-switches                                    [Software event]
> > >   context-switches OR cs                             [Software event]
> > >   cpu-clock                                          [Software event]
> > >   cpu-migrations OR migrations                       [Software event]
> > >   dummy                                              [Software event]
> > >   emulation-faults                                   [Software event]
> > >   major-faults                                       [Software event]
> > >   minor-faults                                       [Software event]
> > >   page-faults OR faults                              [Software event]
> > >   task-clock                                         [Software event]
> > > ```
> > >
> > > After:
> > > ```
> > > List of pre-defined events (to be used in -e or -M):
> > >
> > >   branch-instructions OR branches                    [Hardware event]
> > >   branch-misses                                      [Hardware event]
> > >   bus-cycles                                         [Hardware event]
> > >   cache-misses                                       [Hardware event]
> > >   cache-references                                   [Hardware event]
> > >   cpu-cycles OR cycles                               [Hardware event]
> > >   instructions                                       [Hardware event]
> > >   ref-cycles                                         [Hardware event]
> > >   alignment-faults                                   [Software event]
> > >   bpf-output                                         [Software event]
> > >   cgroup-switches                                    [Software event]
> > >   context-switches OR cs                             [Software event]
> > >   cpu-clock                                          [Software event]
> > >   cpu-migrations OR migrations                       [Software event]
> > >   dummy                                              [Software event]
> > >   emulation-faults                                   [Software event]
> > >   major-faults                                       [Software event]
> > >   minor-faults                                       [Software event]
> > >   page-faults OR faults                              [Software event]
> > >   task-clock                                         [Software event]
> > > ...
> > > software:
> > >   alignment-faults
> > >        [Number of kernel handled memory alignment faults. Unit: software]
> > >   bpf-output
> > >        [An event used by BPF programs to write to the perf ring
> > > buffer. Unit: software]
> > >   cgroup-switches
> > >        [Number of context switches to a task in a different cgroup.
> > > Unit: software]
> > >   context-switches
> > >        [Number of context switches [This event is an alias of cs].
> > > Unit: software]
> > >   cpu-clock
> > >        [Per-CPU high-resolution timer based event. Unit: software]
> > >   cpu-migrations
> > >        [Number of times a process has migrated to a new CPU [This
> > > event is an alias of migrations]. Unit: software]
> > >   cs
> > >        [Number of context switches [This event is an alias of
> > > context-switches]. Unit: software]
> > >   dummy
> > >        [A placeholder event that doesn't count anything. Unit: software]
> > >   emulation-faults
> > >        [Number of kernel handled unimplemented instruction faults
> > > handled through emulation. Unit: software]
> > >   faults
> > >        [Number of page faults [This event is an alias of page-faults].
> > > Unit: software]
> > >   major-faults
> > >        [Number of major page faults. Major faults require I/O to
> > > handle. Unit: software]
> > >   migrations
> > >        [Number of times a process has migrated to a new CPU [This
> > > event is an alias of cpu-migrations]. Unit: software]
> > >   minor-faults
> > >        [Number of minor page faults. Minor faults don't require I/O to
> > > handle. Unit: software]
> > >   page-faults
> > >        [Number of page faults [This event is an alias of faults].
> > > Unit: software]
> > >   task-clock
> > >        [Task based high-resolution timer based event. Unit: software]
> > > ...
> > > ```
> > > The next patch will make this just:
> > > ```
> > > List of pre-defined events (to be used in -e or -M):
> > >
> > >   branch-instructions OR branches                    [Hardware event]
> > >   branch-misses                                      [Hardware event]
> > >   bus-cycles                                         [Hardware event]
> > >   cache-misses                                       [Hardware event]
> > >   cache-references                                   [Hardware event]
> > >   cpu-cycles OR cycles                               [Hardware event]
> > >   instructions                                       [Hardware event]
> > >   ref-cycles                                         [Hardware event]
> > > ...
> > > software:
> > >   alignment-faults
> > >        [Number of kernel handled memory alignment faults. Unit: software]
> > >   bpf-output
> > >        [An event used by BPF programs to write to the perf ring
> > > buffer. Unit: software]
> > >   cgroup-switches
> > >        [Number of context switches to a task in a different cgroup.
> > > Unit: software]
> > >   context-switches
> > >        [Number of context switches [This event is an alias of cs].
> >
> > Hmm.. can we just use parentheses for the alias?
> 
> We could, I was looking for consistency with what is already done by Intel:
> ```
> $ perf list
> ...
>   l2_request.all
>       [All accesses to L2 cache [This event is alias to
> L2_RQSTS.REFERENCES]. Unit: cpu_core]
>   l2_request.miss
>       [Read requests with true-miss in L2 cache. [This event is alias
> to L2_RQSTS.MISS]. Unit:
>        cpu_core]
> ...
> ```
> I wouldn't want to modify Intel's convention, we could have 2 conventions. Wdyt?

Oh, I didn't know that.  Ok, it makes sense.  Hopefully we can change
that later.

> 
> 
> >
> > > Unit: software]
> > >   cpu-clock
> > >        [Per-CPU high-resolution timer based event. Unit: software]
> > >   cpu-migrations
> > >        [Number of times a process has migrated to a new CPU [This
> > > event is an alias of migrations]. Unit: software]
> > >   cs
> > >        [Number of context switches [This event is an alias of
> > > context-switches]. Unit: software]
> > >   dummy
> > >        [A placeholder event that doesn't count anything. Unit: software]
> > >   emulation-faults
> > >        [Number of kernel handled unimplemented instruction faults
> > > handled through emulation. Unit: software]
> > >   faults
> > >        [Number of page faults [This event is an alias of page-faults].
> > > Unit: software]
> > >   major-faults
> > >        [Number of major page faults. Major faults require I/O to
> > > handle. Unit: software]
> > >   migrations
> > >        [Number of times a process has migrated to a new CPU [This
> > > event is an alias of cpu-migrations]. Unit: software]
> > >   minor-faults
> > >        [Number of minor page faults. Minor faults don't require I/O to
> > > handle. Unit: software]
> > >   page-faults
> > >        [Number of page faults [This event is an alias of faults].
> > > Unit: software]
> > >   task-clock
> > >        [Task based high-resolution timer based event. Unit: software]
> > > ...
> > > ```
> >
> > Will `perf list sw` include these output?  And please add this to the
> > commit message.
> 
> This is in the next patch, basically the PMU name matching glob is
> used so that for the "sw" perf list option only the "software" and
> "tool" PMUs are displayed.
> I can add the output to the next patch (then I don't need to worry
> about the half-way state that exists after this patch).

Yeah I saw the patch 3 and thanks for the explanation.

Namhyung

> 
> > > > >
> > > > > Signed-off-by: Ian Rogers <irogers@google.com>
> > > > > ---
> > > > >  .../arch/common/common/software.json          |  92 ++++++
> > > > >  tools/perf/pmu-events/empty-pmu-events.c      | 266 +++++++++++-------
> > > > >  tools/perf/pmu-events/jevents.py              |  15 +-
> > > > >  3 files changed, 264 insertions(+), 109 deletions(-)
> > > > >  create mode 100644 tools/perf/pmu-events/arch/common/common/software.json
> > > > >
> > > > > diff --git a/tools/perf/pmu-events/arch/common/common/software.json b/tools/perf/pmu-events/arch/common/common/software.json
> > > > > new file mode 100644
> > > > > index 000000000000..3af2f565a601
> > > > > --- /dev/null
> > > > > +++ b/tools/perf/pmu-events/arch/common/common/software.json
> > > > > @@ -0,0 +1,92 @@
> > > > > +[
> > > > > +  {
> > > > > +    "Unit": "software",
> > > > > +    "EventName": "cpu-clock",
> > > > > +    "BriefDescription": "Per-CPU high-resolution timer based event",
> > > > > +    "ConfigCode": "0"
> > > > > +  },
> > > > > +  {
> > > > > +    "Unit": "software",
> > > > > +    "EventName": "task-clock",
> > > > > +    "BriefDescription": "Task based high-resolution timer based event",
> > > >
> > > > s/Task based/Per-task/ ?
> > >
> > > Will fix it in the next version.
> > >
> > > >
> > > > > +    "ConfigCode": "1"
> > > > > +  },
> > > > > +  {
> > > > > +    "Unit": "software",
> > > > > +    "EventName": "faults",
> > > > > +    "BriefDescription": "Number of page faults [This event is an alias of page-faults]",
> > > > > +    "ConfigCode": "2"
> > > >
> > > > It'd be nice if it can handle aliases without adding a new entry.  But I
> > > > guess it requires non-trivial changes.
> > >
> > > It is a limitation of the perf json format. There's no reason not to
> > > add some notion of aliases, I believe it was done this way inheriting
> > > from how Intel did it.
> >
> > Ok, I think it's fine for now.
> >
> > Thanks,
> > Namhyung
> >
> > > >
> > > > > +  },
> > > > > +  {
> > > > > +    "Unit": "software",
> > > > > +    "EventName": "page-faults",
> > > > > +    "BriefDescription": "Number of page faults [This event is an alias of faults]",
> > > > > +    "ConfigCode": "2"
> > > > > +  },
> > > > > +  {
> > > > > +    "Unit": "software",
> > > > > +    "EventName": "context-switches",
> > > > > +    "BriefDescription": "Number of context switches [This event is an alias of cs]",
> > > > > +    "ConfigCode": "3"
> > > > > +  },
> > > > > +  {
> > > > > +    "Unit": "software",
> > > > > +    "EventName": "cs",
> > > > > +    "BriefDescription": "Number of context switches [This event is an alias of context-switches]",
> > > > > +    "ConfigCode": "3"
> > > > > +  },
> > > > > +  {
> > > > > +    "Unit": "software",
> > > > > +    "EventName": "cpu-migrations",
> > > > > +    "BriefDescription": "Number of times a process has migrated to a new CPU [This event is an alias of migrations]",
> > > > > +    "ConfigCode": "4"
> > > > > +  },
> > > > > +  {
> > > > > +    "Unit": "software",
> > > > > +    "EventName": "migrations",
> > > > > +    "BriefDescription": "Number of times a process has migrated to a new CPU [This event is an alias of cpu-migrations]",
> > > > > +    "ConfigCode": "4"
> > > > > +  },
> > > > > +  {
> > > > > +    "Unit": "software",
> > > > > +    "EventName": "minor-faults",
> > > > > +    "BriefDescription": "Number of minor page faults. Minor faults don't require I/O to handle",
> > > > > +    "ConfigCode": "5"
> > > > > +  },
> > > > > +  {
> > > > > +    "Unit": "software",
> > > > > +    "EventName": "major-faults",
> > > > > +    "BriefDescription": "Number of major page faults. Major faults require I/O to handle",
> > > > > +    "ConfigCode": "6"
> > > > > +  },
> > > > > +  {
> > > > > +    "Unit": "software",
> > > > > +    "EventName": "alignment-faults",
> > > > > +    "BriefDescription": "Number of kernel handled memory alignment faults",
> > > > > +    "ConfigCode": "7"
> > > > > +  },
> > > > > +  {
> > > > > +    "Unit": "software",
> > > > > +    "EventName": "emulation-faults",
> > > > > +    "BriefDescription": "Number of kernel handled unimplemented instruction faults handled through emulation",
> > > > > +    "ConfigCode": "8"
> > > > > +  },
> > > > > +  {
> > > > > +    "Unit": "software",
> > > > > +    "EventName": "dummy",
> > > > > +    "BriefDescription": "A placeholder event that doesn't count anything",
> > > > > +    "ConfigCode": "9"
> > > > > +  },
> > > > > +  {
> > > > > +    "Unit": "software",
> > > > > +    "EventName": "bpf-output",
> > > > > +    "BriefDescription": "An event used by BPF programs to write to the perf ring buffer",
> > > > > +    "ConfigCode": "10"
> > > > > +  },
> > > > > +  {
> > > > > +    "Unit": "software",
> > > > > +    "EventName": "cgroup-switches",
> > > > > +    "BriefDescription": "Number of context switches to a task in a different cgroup",
> > > > > +    "ConfigCode": "11"
> > > > > +  }
> > > > > +]
> > > > > diff --git a/tools/perf/pmu-events/empty-pmu-events.c b/tools/perf/pmu-events/empty-pmu-events.c
> > > > > index a4569a74db07..7d179d703ab1 100644
> > > > > --- a/tools/perf/pmu-events/empty-pmu-events.c
> > > > > +++ b/tools/perf/pmu-events/empty-pmu-events.c
> > > > > @@ -19,109 +19,147 @@ struct pmu_table_entry {
> > > > >  };
> > > > >
> > > > >  static const char *const big_c_string =
> > > > > -/* offset=0 */ "tool\000"
> > > > > -/* offset=5 */ "duration_time\000tool\000Wall clock interval time in nanoseconds\000config=1\000\00000\000\000\000\000\000"
> > > > > -/* offset=81 */ "user_time\000tool\000User (non-kernel) time in nanoseconds\000config=2\000\00000\000\000\000\000\000"
> > > > > -/* offset=151 */ "system_time\000tool\000System/kernel time in nanoseconds\000config=3\000\00000\000\000\000\000\000"
> > > > > -/* offset=219 */ "has_pmem\000tool\0001 if persistent memory installed otherwise 0\000config=4\000\00000\000\000\000\000\000"
> > > > > -/* offset=295 */ "num_cores\000tool\000Number of cores. A core consists of 1 or more thread, with each thread being associated with a logical Linux CPU\000config=5\000\00000\000\000\000\000\000"
> > > > > -/* offset=440 */ "num_cpus\000tool\000Number of logical Linux CPUs. There may be multiple such CPUs on a core\000config=6\000\00000\000\000\000\000\000"
> > > > > -/* offset=543 */ "num_cpus_online\000tool\000Number of online logical Linux CPUs. There may be multiple such CPUs on a core\000config=7\000\00000\000\000\000\000\000"
> > > > > -/* offset=660 */ "num_dies\000tool\000Number of dies. Each die has 1 or more cores\000config=8\000\00000\000\000\000\000\000"
> > > > > -/* offset=736 */ "num_packages\000tool\000Number of packages. Each package has 1 or more die\000config=9\000\00000\000\000\000\000\000"
> > > > > -/* offset=822 */ "slots\000tool\000Number of functional units that in parallel can execute parts of an instruction\000config=0xa\000\00000\000\000\000\000\000"
> > > > > -/* offset=932 */ "smt_on\000tool\0001 if simultaneous multithreading (aka hyperthreading) is enable otherwise 0\000config=0xb\000\00000\000\000\000\000\000"
> > > > > -/* offset=1039 */ "system_tsc_freq\000tool\000The amount a Time Stamp Counter (TSC) increases per second\000config=0xc\000\00000\000\000\000\000\000"
> > > > > -/* offset=1138 */ "default_core\000"
> > > > > -/* offset=1151 */ "bp_l1_btb_correct\000branch\000L1 BTB Correction\000event=0x8a\000\00000\000\000\000\000\000"
> > > > > -/* offset=1213 */ "bp_l2_btb_correct\000branch\000L2 BTB Correction\000event=0x8b\000\00000\000\000\000\000\000"
> > > > > -/* offset=1275 */ "l3_cache_rd\000cache\000L3 cache access, read\000event=0x40\000\00000\000\000\000\000Attributable Level 3 cache access, read\000"
> > > > > -/* offset=1373 */ "segment_reg_loads.any\000other\000Number of segment register loads\000event=6,period=200000,umask=0x80\000\00000\000\000\000\000\000"
> > > > > -/* offset=1475 */ "dispatch_blocked.any\000other\000Memory cluster signals to block micro-op dispatch for any reason\000event=9,period=200000,umask=0x20\000\00000\000\000\000\000\000"
> > > > > -/* offset=1608 */ "eist_trans\000other\000Number of Enhanced Intel SpeedStep(R) Technology (EIST) transitions\000event=0x3a,period=200000\000\00000\000\000\000\000\000"
> > > > > -/* offset=1726 */ "hisi_sccl,ddrc\000"
> > > > > -/* offset=1741 */ "uncore_hisi_ddrc.flux_wcmd\000uncore\000DDRC write commands\000event=2\000\00000\000\000\000\000\000"
> > > > > -/* offset=1811 */ "uncore_cbox\000"
> > > > > -/* offset=1823 */ "unc_cbo_xsnp_response.miss_eviction\000uncore\000A cross-core snoop resulted from L3 Eviction which misses in some processor core\000event=0x22,umask=0x81\000\00000\000\000\000\000\000"
> > > > > -/* offset=1977 */ "event-hyphen\000uncore\000UNC_CBO_HYPHEN\000event=0xe0\000\00000\000\000\000\000\000"
> > > > > -/* offset=2031 */ "event-two-hyph\000uncore\000UNC_CBO_TWO_HYPH\000event=0xc0\000\00000\000\000\000\000\000"
> > > > > -/* offset=2089 */ "hisi_sccl,l3c\000"
> > > > > -/* offset=2103 */ "uncore_hisi_l3c.rd_hit_cpipe\000uncore\000Total read hits\000event=7\000\00000\000\000\000\000\000"
> > > > > -/* offset=2171 */ "uncore_imc_free_running\000"
> > > > > -/* offset=2195 */ "uncore_imc_free_running.cache_miss\000uncore\000Total cache misses\000event=0x12\000\00000\000\000\000\000\000"
> > > > > -/* offset=2275 */ "uncore_imc\000"
> > > > > -/* offset=2286 */ "uncore_imc.cache_hits\000uncore\000Total cache hits\000event=0x34\000\00000\000\000\000\000\000"
> > > > > -/* offset=2351 */ "uncore_sys_ddr_pmu\000"
> > > > > -/* offset=2370 */ "sys_ddr_pmu.write_cycles\000uncore\000ddr write-cycles event\000event=0x2b\000v8\00000\000\000\000\000\000"
> > > > > -/* offset=2446 */ "uncore_sys_ccn_pmu\000"
> > > > > -/* offset=2465 */ "sys_ccn_pmu.read_cycles\000uncore\000ccn read-cycles event\000config=0x2c\0000x01\00000\000\000\000\000\000"
> > > > > -/* offset=2542 */ "uncore_sys_cmn_pmu\000"
> > > > > -/* offset=2561 */ "sys_cmn_pmu.hnf_cache_miss\000uncore\000Counts total cache misses in first lookup result (high priority)\000eventid=1,type=5\000(434|436|43c|43a).*\00000\000\000\000\000\000"
> > > > > -/* offset=2704 */ "CPI\000\0001 / IPC\000\000\000\000\000\000\000\00000"
> > > > > -/* offset=2726 */ "IPC\000group1\000inst_retired.any / cpu_clk_unhalted.thread\000\000\000\000\000\000\000\00000"
> > > > > -/* offset=2789 */ "Frontend_Bound_SMT\000\000idq_uops_not_delivered.core / (4 * (cpu_clk_unhalted.thread / 2 * (1 + cpu_clk_unhalted.one_thread_active / cpu_clk_unhalted.ref_xclk)))\000\000\000\000\000\000\000\00000"
> > > > > -/* offset=2955 */ "dcache_miss_cpi\000\000l1d\\-loads\\-misses / inst_retired.any\000\000\000\000\000\000\000\00000"
> > > > > -/* offset=3019 */ "icache_miss_cycles\000\000l1i\\-loads\\-misses / inst_retired.any\000\000\000\000\000\000\000\00000"
> > > > > -/* offset=3086 */ "cache_miss_cycles\000group1\000dcache_miss_cpi + icache_miss_cycles\000\000\000\000\000\000\000\00000"
> > > > > -/* offset=3157 */ "DCache_L2_All_Hits\000\000l2_rqsts.demand_data_rd_hit + l2_rqsts.pf_hit + l2_rqsts.rfo_hit\000\000\000\000\000\000\000\00000"
> > > > > -/* offset=3251 */ "DCache_L2_All_Miss\000\000max(l2_rqsts.all_demand_data_rd - l2_rqsts.demand_data_rd_hit, 0) + l2_rqsts.pf_miss + l2_rqsts.rfo_miss\000\000\000\000\000\000\000\00000"
> > > > > -/* offset=3385 */ "DCache_L2_All\000\000DCache_L2_All_Hits + DCache_L2_All_Miss\000\000\000\000\000\000\000\00000"
> > > > > -/* offset=3449 */ "DCache_L2_Hits\000\000d_ratio(DCache_L2_All_Hits, DCache_L2_All)\000\000\000\000\000\000\000\00000"
> > > > > -/* offset=3517 */ "DCache_L2_Misses\000\000d_ratio(DCache_L2_All_Miss, DCache_L2_All)\000\000\000\000\000\000\000\00000"
> > > > > -/* offset=3587 */ "M1\000\000ipc + M2\000\000\000\000\000\000\000\00000"
> > > > > -/* offset=3609 */ "M2\000\000ipc + M1\000\000\000\000\000\000\000\00000"
> > > > > -/* offset=3631 */ "M3\000\0001 / M3\000\000\000\000\000\000\000\00000"
> > > > > -/* offset=3651 */ "L1D_Cache_Fill_BW\000\00064 * l1d.replacement / 1e9 / duration_time\000\000\000\000\000\000\000\00000"
> > > > > +/* offset=0 */ "software\000"
> > > > > +/* offset=9 */ "cpu-clock\000software\000Per-CPU high-resolution timer based event\000config=0\000\00000\000\000\000\000\000"
> > > > > +/* offset=87 */ "task-clock\000software\000Task based high-resolution timer based event\000config=1\000\00000\000\000\000\000\000"
> > > > > +/* offset=169 */ "faults\000software\000Number of page faults [This event is an alias of page-faults]\000config=2\000\00000\000\000\000\000\000"
> > > > > +/* offset=264 */ "page-faults\000software\000Number of page faults [This event is an alias of faults]\000config=2\000\00000\000\000\000\000\000"
> > > > > +/* offset=359 */ "context-switches\000software\000Number of context switches [This event is an alias of cs]\000config=3\000\00000\000\000\000\000\000"
> > > > > +/* offset=460 */ "cs\000software\000Number of context switches [This event is an alias of context-switches]\000config=3\000\00000\000\000\000\000\000"
> > > > > +/* offset=561 */ "cpu-migrations\000software\000Number of times a process has migrated to a new CPU [This event is an alias of migrations]\000config=4\000\00000\000\000\000\000\000"
> > > > > +/* offset=693 */ "migrations\000software\000Number of times a process has migrated to a new CPU [This event is an alias of cpu-migrations]\000config=4\000\00000\000\000\000\000\000"
> > > > > +/* offset=825 */ "minor-faults\000software\000Number of minor page faults. Minor faults don't require I/O to handle\000config=5\000\00000\000\000\000\000\000"
> > > > > +/* offset=934 */ "major-faults\000software\000Number of major page faults. Major faults require I/O to handle\000config=6\000\00000\000\000\000\000\000"
> > > > > +/* offset=1037 */ "alignment-faults\000software\000Number of kernel handled memory alignment faults\000config=7\000\00000\000\000\000\000\000"
> > > > > +/* offset=1129 */ "emulation-faults\000software\000Number of kernel handled unimplemented instruction faults handled through emulation\000config=8\000\00000\000\000\000\000\000"
> > > > > +/* offset=1256 */ "dummy\000software\000A placeholder event that doesn't count anything\000config=9\000\00000\000\000\000\000\000"
> > > > > +/* offset=1336 */ "bpf-output\000software\000An event used by BPF programs to write to the perf ring buffer\000config=0xa\000\00000\000\000\000\000\000"
> > > > > +/* offset=1438 */ "cgroup-switches\000software\000Number of context switches to a task in a different cgroup\000config=0xb\000\00000\000\000\000\000\000"
> > > > > +/* offset=1541 */ "tool\000"
> > > > > +/* offset=1546 */ "duration_time\000tool\000Wall clock interval time in nanoseconds\000config=1\000\00000\000\000\000\000\000"
> > > > > +/* offset=1622 */ "user_time\000tool\000User (non-kernel) time in nanoseconds\000config=2\000\00000\000\000\000\000\000"
> > > > > +/* offset=1692 */ "system_time\000tool\000System/kernel time in nanoseconds\000config=3\000\00000\000\000\000\000\000"
> > > > > +/* offset=1760 */ "has_pmem\000tool\0001 if persistent memory installed otherwise 0\000config=4\000\00000\000\000\000\000\000"
> > > > > +/* offset=1836 */ "num_cores\000tool\000Number of cores. A core consists of 1 or more thread, with each thread being associated with a logical Linux CPU\000config=5\000\00000\000\000\000\000\000"
> > > > > +/* offset=1981 */ "num_cpus\000tool\000Number of logical Linux CPUs. There may be multiple such CPUs on a core\000config=6\000\00000\000\000\000\000\000"
> > > > > +/* offset=2084 */ "num_cpus_online\000tool\000Number of online logical Linux CPUs. There may be multiple such CPUs on a core\000config=7\000\00000\000\000\000\000\000"
> > > > > +/* offset=2201 */ "num_dies\000tool\000Number of dies. Each die has 1 or more cores\000config=8\000\00000\000\000\000\000\000"
> > > > > +/* offset=2277 */ "num_packages\000tool\000Number of packages. Each package has 1 or more die\000config=9\000\00000\000\000\000\000\000"
> > > > > +/* offset=2363 */ "slots\000tool\000Number of functional units that in parallel can execute parts of an instruction\000config=0xa\000\00000\000\000\000\000\000"
> > > > > +/* offset=2473 */ "smt_on\000tool\0001 if simultaneous multithreading (aka hyperthreading) is enable otherwise 0\000config=0xb\000\00000\000\000\000\000\000"
> > > > > +/* offset=2580 */ "system_tsc_freq\000tool\000The amount a Time Stamp Counter (TSC) increases per second\000config=0xc\000\00000\000\000\000\000\000"
> > > > > +/* offset=2679 */ "default_core\000"
> > > > > +/* offset=2692 */ "bp_l1_btb_correct\000branch\000L1 BTB Correction\000event=0x8a\000\00000\000\000\000\000\000"
> > > > > +/* offset=2754 */ "bp_l2_btb_correct\000branch\000L2 BTB Correction\000event=0x8b\000\00000\000\000\000\000\000"
> > > > > +/* offset=2816 */ "l3_cache_rd\000cache\000L3 cache access, read\000event=0x40\000\00000\000\000\000\000Attributable Level 3 cache access, read\000"
> > > > > +/* offset=2914 */ "segment_reg_loads.any\000other\000Number of segment register loads\000event=6,period=200000,umask=0x80\000\00000\000\000\000\000\000"
> > > > > +/* offset=3016 */ "dispatch_blocked.any\000other\000Memory cluster signals to block micro-op dispatch for any reason\000event=9,period=200000,umask=0x20\000\00000\000\000\000\000\000"
> > > > > +/* offset=3149 */ "eist_trans\000other\000Number of Enhanced Intel SpeedStep(R) Technology (EIST) transitions\000event=0x3a,period=200000\000\00000\000\000\000\000\000"
> > > > > +/* offset=3267 */ "hisi_sccl,ddrc\000"
> > > > > +/* offset=3282 */ "uncore_hisi_ddrc.flux_wcmd\000uncore\000DDRC write commands\000event=2\000\00000\000\000\000\000\000"
> > > > > +/* offset=3352 */ "uncore_cbox\000"
> > > > > +/* offset=3364 */ "unc_cbo_xsnp_response.miss_eviction\000uncore\000A cross-core snoop resulted from L3 Eviction which misses in some processor core\000event=0x22,umask=0x81\000\00000\000\000\000\000\000"
> > > > > +/* offset=3518 */ "event-hyphen\000uncore\000UNC_CBO_HYPHEN\000event=0xe0\000\00000\000\000\000\000\000"
> > > > > +/* offset=3572 */ "event-two-hyph\000uncore\000UNC_CBO_TWO_HYPH\000event=0xc0\000\00000\000\000\000\000\000"
> > > > > +/* offset=3630 */ "hisi_sccl,l3c\000"
> > > > > +/* offset=3644 */ "uncore_hisi_l3c.rd_hit_cpipe\000uncore\000Total read hits\000event=7\000\00000\000\000\000\000\000"
> > > > > +/* offset=3712 */ "uncore_imc_free_running\000"
> > > > > +/* offset=3736 */ "uncore_imc_free_running.cache_miss\000uncore\000Total cache misses\000event=0x12\000\00000\000\000\000\000\000"
> > > > > +/* offset=3816 */ "uncore_imc\000"
> > > > > +/* offset=3827 */ "uncore_imc.cache_hits\000uncore\000Total cache hits\000event=0x34\000\00000\000\000\000\000\000"
> > > > > +/* offset=3892 */ "uncore_sys_ddr_pmu\000"
> > > > > +/* offset=3911 */ "sys_ddr_pmu.write_cycles\000uncore\000ddr write-cycles event\000event=0x2b\000v8\00000\000\000\000\000\000"
> > > > > +/* offset=3987 */ "uncore_sys_ccn_pmu\000"
> > > > > +/* offset=4006 */ "sys_ccn_pmu.read_cycles\000uncore\000ccn read-cycles event\000config=0x2c\0000x01\00000\000\000\000\000\000"
> > > > > +/* offset=4083 */ "uncore_sys_cmn_pmu\000"
> > > > > +/* offset=4102 */ "sys_cmn_pmu.hnf_cache_miss\000uncore\000Counts total cache misses in first lookup result (high priority)\000eventid=1,type=5\000(434|436|43c|43a).*\00000\000\000\000\000\000"
> > > > > +/* offset=4245 */ "CPI\000\0001 / IPC\000\000\000\000\000\000\000\00000"
> > > > > +/* offset=4267 */ "IPC\000group1\000inst_retired.any / cpu_clk_unhalted.thread\000\000\000\000\000\000\000\00000"
> > > > > +/* offset=4330 */ "Frontend_Bound_SMT\000\000idq_uops_not_delivered.core / (4 * (cpu_clk_unhalted.thread / 2 * (1 + cpu_clk_unhalted.one_thread_active / cpu_clk_unhalted.ref_xclk)))\000\000\000\000\000\000\000\00000"
> > > > > +/* offset=4496 */ "dcache_miss_cpi\000\000l1d\\-loads\\-misses / inst_retired.any\000\000\000\000\000\000\000\00000"
> > > > > +/* offset=4560 */ "icache_miss_cycles\000\000l1i\\-loads\\-misses / inst_retired.any\000\000\000\000\000\000\000\00000"
> > > > > +/* offset=4627 */ "cache_miss_cycles\000group1\000dcache_miss_cpi + icache_miss_cycles\000\000\000\000\000\000\000\00000"
> > > > > +/* offset=4698 */ "DCache_L2_All_Hits\000\000l2_rqsts.demand_data_rd_hit + l2_rqsts.pf_hit + l2_rqsts.rfo_hit\000\000\000\000\000\000\000\00000"
> > > > > +/* offset=4792 */ "DCache_L2_All_Miss\000\000max(l2_rqsts.all_demand_data_rd - l2_rqsts.demand_data_rd_hit, 0) + l2_rqsts.pf_miss + l2_rqsts.rfo_miss\000\000\000\000\000\000\000\00000"
> > > > > +/* offset=4926 */ "DCache_L2_All\000\000DCache_L2_All_Hits + DCache_L2_All_Miss\000\000\000\000\000\000\000\00000"
> > > > > +/* offset=4990 */ "DCache_L2_Hits\000\000d_ratio(DCache_L2_All_Hits, DCache_L2_All)\000\000\000\000\000\000\000\00000"
> > > > > +/* offset=5058 */ "DCache_L2_Misses\000\000d_ratio(DCache_L2_All_Miss, DCache_L2_All)\000\000\000\000\000\000\000\00000"
> > > > > +/* offset=5128 */ "M1\000\000ipc + M2\000\000\000\000\000\000\000\00000"
> > > > > +/* offset=5150 */ "M2\000\000ipc + M1\000\000\000\000\000\000\000\00000"
> > > > > +/* offset=5172 */ "M3\000\0001 / M3\000\000\000\000\000\000\000\00000"
> > > > > +/* offset=5192 */ "L1D_Cache_Fill_BW\000\00064 * l1d.replacement / 1e9 / duration_time\000\000\000\000\000\000\000\00000"
> > > > >  ;
> > > > >
> > > > > +static const struct compact_pmu_event pmu_events__common_software[] = {
> > > > > +{ 1037 }, /* alignment-faults\000software\000Number of kernel handled memory alignment faults\000config=7\000\00000\000\000\000\000\000 */
> > > > > +{ 1336 }, /* bpf-output\000software\000An event used by BPF programs to write to the perf ring buffer\000config=0xa\000\00000\000\000\000\000\000 */
> > > > > +{ 1438 }, /* cgroup-switches\000software\000Number of context switches to a task in a different cgroup\000config=0xb\000\00000\000\000\000\000\000 */
> > > > > +{ 359 }, /* context-switches\000software\000Number of context switches [This event is an alias of cs]\000config=3\000\00000\000\000\000\000\000 */
> > > > > +{ 9 }, /* cpu-clock\000software\000Per-CPU high-resolution timer based event\000config=0\000\00000\000\000\000\000\000 */
> > > > > +{ 561 }, /* cpu-migrations\000software\000Number of times a process has migrated to a new CPU [This event is an alias of migrations]\000config=4\000\00000\000\000\000\000\000 */
> > > > > +{ 460 }, /* cs\000software\000Number of context switches [This event is an alias of context-switches]\000config=3\000\00000\000\000\000\000\000 */
> > > > > +{ 1256 }, /* dummy\000software\000A placeholder event that doesn't count anything\000config=9\000\00000\000\000\000\000\000 */
> > > > > +{ 1129 }, /* emulation-faults\000software\000Number of kernel handled unimplemented instruction faults handled through emulation\000config=8\000\00000\000\000\000\000\000 */
> > > > > +{ 169 }, /* faults\000software\000Number of page faults [This event is an alias of page-faults]\000config=2\000\00000\000\000\000\000\000 */
> > > > > +{ 934 }, /* major-faults\000software\000Number of major page faults. Major faults require I/O to handle\000config=6\000\00000\000\000\000\000\000 */
> > > > > +{ 693 }, /* migrations\000software\000Number of times a process has migrated to a new CPU [This event is an alias of cpu-migrations]\000config=4\000\00000\000\000\000\000\000 */
> > > > > +{ 825 }, /* minor-faults\000software\000Number of minor page faults. Minor faults don't require I/O to handle\000config=5\000\00000\000\000\000\000\000 */
> > > > > +{ 264 }, /* page-faults\000software\000Number of page faults [This event is an alias of faults]\000config=2\000\00000\000\000\000\000\000 */
> > > > > +{ 87 }, /* task-clock\000software\000Task based high-resolution timer based event\000config=1\000\00000\000\000\000\000\000 */
> > > > > +};
> > > > >  static const struct compact_pmu_event pmu_events__common_tool[] = {
> > > > > -{ 5 }, /* duration_time\000tool\000Wall clock interval time in nanoseconds\000config=1\000\00000\000\000\000\000\000 */
> > > > > -{ 219 }, /* has_pmem\000tool\0001 if persistent memory installed otherwise 0\000config=4\000\00000\000\000\000\000\000 */
> > > > > -{ 295 }, /* num_cores\000tool\000Number of cores. A core consists of 1 or more thread, with each thread being associated with a logical Linux CPU\000config=5\000\00000\000\000\000\000\000 */
> > > > > -{ 440 }, /* num_cpus\000tool\000Number of logical Linux CPUs. There may be multiple such CPUs on a core\000config=6\000\00000\000\000\000\000\000 */
> > > > > -{ 543 }, /* num_cpus_online\000tool\000Number of online logical Linux CPUs. There may be multiple such CPUs on a core\000config=7\000\00000\000\000\000\000\000 */
> > > > > -{ 660 }, /* num_dies\000tool\000Number of dies. Each die has 1 or more cores\000config=8\000\00000\000\000\000\000\000 */
> > > > > -{ 736 }, /* num_packages\000tool\000Number of packages. Each package has 1 or more die\000config=9\000\00000\000\000\000\000\000 */
> > > > > -{ 822 }, /* slots\000tool\000Number of functional units that in parallel can execute parts of an instruction\000config=0xa\000\00000\000\000\000\000\000 */
> > > > > -{ 932 }, /* smt_on\000tool\0001 if simultaneous multithreading (aka hyperthreading) is enable otherwise 0\000config=0xb\000\00000\000\000\000\000\000 */
> > > > > -{ 151 }, /* system_time\000tool\000System/kernel time in nanoseconds\000config=3\000\00000\000\000\000\000\000 */
> > > > > -{ 1039 }, /* system_tsc_freq\000tool\000The amount a Time Stamp Counter (TSC) increases per second\000config=0xc\000\00000\000\000\000\000\000 */
> > > > > -{ 81 }, /* user_time\000tool\000User (non-kernel) time in nanoseconds\000config=2\000\00000\000\000\000\000\000 */
> > > > > +{ 1546 }, /* duration_time\000tool\000Wall clock interval time in nanoseconds\000config=1\000\00000\000\000\000\000\000 */
> > > > > +{ 1760 }, /* has_pmem\000tool\0001 if persistent memory installed otherwise 0\000config=4\000\00000\000\000\000\000\000 */
> > > > > +{ 1836 }, /* num_cores\000tool\000Number of cores. A core consists of 1 or more thread, with each thread being associated with a logical Linux CPU\000config=5\000\00000\000\000\000\000\000 */
> > > > > +{ 1981 }, /* num_cpus\000tool\000Number of logical Linux CPUs. There may be multiple such CPUs on a core\000config=6\000\00000\000\000\000\000\000 */
> > > > > +{ 2084 }, /* num_cpus_online\000tool\000Number of online logical Linux CPUs. There may be multiple such CPUs on a core\000config=7\000\00000\000\000\000\000\000 */
> > > > > +{ 2201 }, /* num_dies\000tool\000Number of dies. Each die has 1 or more cores\000config=8\000\00000\000\000\000\000\000 */
> > > > > +{ 2277 }, /* num_packages\000tool\000Number of packages. Each package has 1 or more die\000config=9\000\00000\000\000\000\000\000 */
> > > > > +{ 2363 }, /* slots\000tool\000Number of functional units that in parallel can execute parts of an instruction\000config=0xa\000\00000\000\000\000\000\000 */
> > > > > +{ 2473 }, /* smt_on\000tool\0001 if simultaneous multithreading (aka hyperthreading) is enable otherwise 0\000config=0xb\000\00000\000\000\000\000\000 */
> > > > > +{ 1692 }, /* system_time\000tool\000System/kernel time in nanoseconds\000config=3\000\00000\000\000\000\000\000 */
> > > > > +{ 2580 }, /* system_tsc_freq\000tool\000The amount a Time Stamp Counter (TSC) increases per second\000config=0xc\000\00000\000\000\000\000\000 */
> > > > > +{ 1622 }, /* user_time\000tool\000User (non-kernel) time in nanoseconds\000config=2\000\00000\000\000\000\000\000 */
> > > > >
> > > > >  };
> > > > >
> > > > >  const struct pmu_table_entry pmu_events__common[] = {
> > > > > +{
> > > > > +     .entries = pmu_events__common_software,
> > > > > +     .num_entries = ARRAY_SIZE(pmu_events__common_software),
> > > > > +     .pmu_name = { 0 /* software\000 */ },
> > > > > +},
> > > > >  {
> > > > >       .entries = pmu_events__common_tool,
> > > > >       .num_entries = ARRAY_SIZE(pmu_events__common_tool),
> > > > > -     .pmu_name = { 0 /* tool\000 */ },
> > > > > +     .pmu_name = { 1541 /* tool\000 */ },
> > > > >  },
> > > > >  };
> > > > >
> > > > >  static const struct compact_pmu_event pmu_events__test_soc_cpu_default_core[] = {
> > > > > -{ 1151 }, /* bp_l1_btb_correct\000branch\000L1 BTB Correction\000event=0x8a\000\00000\000\000\000\000\000 */
> > > > > -{ 1213 }, /* bp_l2_btb_correct\000branch\000L2 BTB Correction\000event=0x8b\000\00000\000\000\000\000\000 */
> > > > > -{ 1475 }, /* dispatch_blocked.any\000other\000Memory cluster signals to block micro-op dispatch for any reason\000event=9,period=200000,umask=0x20\000\00000\000\000\000\000\000 */
> > > > > -{ 1608 }, /* eist_trans\000other\000Number of Enhanced Intel SpeedStep(R) Technology (EIST) transitions\000event=0x3a,period=200000\000\00000\000\000\000\000\000 */
> > > > > -{ 1275 }, /* l3_cache_rd\000cache\000L3 cache access, read\000event=0x40\000\00000\000\000\000\000Attributable Level 3 cache access, read\000 */
> > > > > -{ 1373 }, /* segment_reg_loads.any\000other\000Number of segment register loads\000event=6,period=200000,umask=0x80\000\00000\000\000\000\000\000 */
> > > > > +{ 2692 }, /* bp_l1_btb_correct\000branch\000L1 BTB Correction\000event=0x8a\000\00000\000\000\000\000\000 */
> > > > > +{ 2754 }, /* bp_l2_btb_correct\000branch\000L2 BTB Correction\000event=0x8b\000\00000\000\000\000\000\000 */
> > > > > +{ 3016 }, /* dispatch_blocked.any\000other\000Memory cluster signals to block micro-op dispatch for any reason\000event=9,period=200000,umask=0x20\000\00000\000\000\000\000\000 */
> > > > > +{ 3149 }, /* eist_trans\000other\000Number of Enhanced Intel SpeedStep(R) Technology (EIST) transitions\000event=0x3a,period=200000\000\00000\000\000\000\000\000 */
> > > > > +{ 2816 }, /* l3_cache_rd\000cache\000L3 cache access, read\000event=0x40\000\00000\000\000\000\000Attributable Level 3 cache access, read\000 */
> > > > > +{ 2914 }, /* segment_reg_loads.any\000other\000Number of segment register loads\000event=6,period=200000,umask=0x80\000\00000\000\000\000\000\000 */
> > > > >  };
> > > > >  static const struct compact_pmu_event pmu_events__test_soc_cpu_hisi_sccl_ddrc[] = {
> > > > > -{ 1741 }, /* uncore_hisi_ddrc.flux_wcmd\000uncore\000DDRC write commands\000event=2\000\00000\000\000\000\000\000 */
> > > > > +{ 3282 }, /* uncore_hisi_ddrc.flux_wcmd\000uncore\000DDRC write commands\000event=2\000\00000\000\000\000\000\000 */
> > > > >  };
> > > > >  static const struct compact_pmu_event pmu_events__test_soc_cpu_hisi_sccl_l3c[] = {
> > > > > -{ 2103 }, /* uncore_hisi_l3c.rd_hit_cpipe\000uncore\000Total read hits\000event=7\000\00000\000\000\000\000\000 */
> > > > > +{ 3644 }, /* uncore_hisi_l3c.rd_hit_cpipe\000uncore\000Total read hits\000event=7\000\00000\000\000\000\000\000 */
> > > > >  };
> > > > >  static const struct compact_pmu_event pmu_events__test_soc_cpu_uncore_cbox[] = {
> > > > > -{ 1977 }, /* event-hyphen\000uncore\000UNC_CBO_HYPHEN\000event=0xe0\000\00000\000\000\000\000\000 */
> > > > > -{ 2031 }, /* event-two-hyph\000uncore\000UNC_CBO_TWO_HYPH\000event=0xc0\000\00000\000\000\000\000\000 */
> > > > > -{ 1823 }, /* unc_cbo_xsnp_response.miss_eviction\000uncore\000A cross-core snoop resulted from L3 Eviction which misses in some processor core\000event=0x22,umask=0x81\000\00000\000\000\000\000\000 */
> > > > > +{ 3518 }, /* event-hyphen\000uncore\000UNC_CBO_HYPHEN\000event=0xe0\000\00000\000\000\000\000\000 */
> > > > > +{ 3572 }, /* event-two-hyph\000uncore\000UNC_CBO_TWO_HYPH\000event=0xc0\000\00000\000\000\000\000\000 */
> > > > > +{ 3364 }, /* unc_cbo_xsnp_response.miss_eviction\000uncore\000A cross-core snoop resulted from L3 Eviction which misses in some processor core\000event=0x22,umask=0x81\000\00000\000\000\000\000\000 */
> > > > >  };
> > > > >  static const struct compact_pmu_event pmu_events__test_soc_cpu_uncore_imc[] = {
> > > > > -{ 2286 }, /* uncore_imc.cache_hits\000uncore\000Total cache hits\000event=0x34\000\00000\000\000\000\000\000 */
> > > > > +{ 3827 }, /* uncore_imc.cache_hits\000uncore\000Total cache hits\000event=0x34\000\00000\000\000\000\000\000 */
> > > > >  };
> > > > >  static const struct compact_pmu_event pmu_events__test_soc_cpu_uncore_imc_free_running[] = {
> > > > > -{ 2195 }, /* uncore_imc_free_running.cache_miss\000uncore\000Total cache misses\000event=0x12\000\00000\000\000\000\000\000 */
> > > > > +{ 3736 }, /* uncore_imc_free_running.cache_miss\000uncore\000Total cache misses\000event=0x12\000\00000\000\000\000\000\000 */
> > > > >
> > > > >  };
> > > > >
> > > > > @@ -129,51 +167,51 @@ const struct pmu_table_entry pmu_events__test_soc_cpu[] = {
> > > > >  {
> > > > >       .entries = pmu_events__test_soc_cpu_default_core,
> > > > >       .num_entries = ARRAY_SIZE(pmu_events__test_soc_cpu_default_core),
> > > > > -     .pmu_name = { 1138 /* default_core\000 */ },
> > > > > +     .pmu_name = { 2679 /* default_core\000 */ },
> > > > >  },
> > > > >  {
> > > > >       .entries = pmu_events__test_soc_cpu_hisi_sccl_ddrc,
> > > > >       .num_entries = ARRAY_SIZE(pmu_events__test_soc_cpu_hisi_sccl_ddrc),
> > > > > -     .pmu_name = { 1726 /* hisi_sccl,ddrc\000 */ },
> > > > > +     .pmu_name = { 3267 /* hisi_sccl,ddrc\000 */ },
> > > > >  },
> > > > >  {
> > > > >       .entries = pmu_events__test_soc_cpu_hisi_sccl_l3c,
> > > > >       .num_entries = ARRAY_SIZE(pmu_events__test_soc_cpu_hisi_sccl_l3c),
> > > > > -     .pmu_name = { 2089 /* hisi_sccl,l3c\000 */ },
> > > > > +     .pmu_name = { 3630 /* hisi_sccl,l3c\000 */ },
> > > > >  },
> > > > >  {
> > > > >       .entries = pmu_events__test_soc_cpu_uncore_cbox,
> > > > >       .num_entries = ARRAY_SIZE(pmu_events__test_soc_cpu_uncore_cbox),
> > > > > -     .pmu_name = { 1811 /* uncore_cbox\000 */ },
> > > > > +     .pmu_name = { 3352 /* uncore_cbox\000 */ },
> > > > >  },
> > > > >  {
> > > > >       .entries = pmu_events__test_soc_cpu_uncore_imc,
> > > > >       .num_entries = ARRAY_SIZE(pmu_events__test_soc_cpu_uncore_imc),
> > > > > -     .pmu_name = { 2275 /* uncore_imc\000 */ },
> > > > > +     .pmu_name = { 3816 /* uncore_imc\000 */ },
> > > > >  },
> > > > >  {
> > > > >       .entries = pmu_events__test_soc_cpu_uncore_imc_free_running,
> > > > >       .num_entries = ARRAY_SIZE(pmu_events__test_soc_cpu_uncore_imc_free_running),
> > > > > -     .pmu_name = { 2171 /* uncore_imc_free_running\000 */ },
> > > > > +     .pmu_name = { 3712 /* uncore_imc_free_running\000 */ },
> > > > >  },
> > > > >  };
> > > > >
> > > > >  static const struct compact_pmu_event pmu_metrics__test_soc_cpu_default_core[] = {
> > > > > -{ 2704 }, /* CPI\000\0001 / IPC\000\000\000\000\000\000\000\00000 */
> > > > > -{ 3385 }, /* DCache_L2_All\000\000DCache_L2_All_Hits + DCache_L2_All_Miss\000\000\000\000\000\000\000\00000 */
> > > > > -{ 3157 }, /* DCache_L2_All_Hits\000\000l2_rqsts.demand_data_rd_hit + l2_rqsts.pf_hit + l2_rqsts.rfo_hit\000\000\000\000\000\000\000\00000 */
> > > > > -{ 3251 }, /* DCache_L2_All_Miss\000\000max(l2_rqsts.all_demand_data_rd - l2_rqsts.demand_data_rd_hit, 0) + l2_rqsts.pf_miss + l2_rqsts.rfo_miss\000\000\000\000\000\000\000\00000 */
> > > > > -{ 3449 }, /* DCache_L2_Hits\000\000d_ratio(DCache_L2_All_Hits, DCache_L2_All)\000\000\000\000\000\000\000\00000 */
> > > > > -{ 3517 }, /* DCache_L2_Misses\000\000d_ratio(DCache_L2_All_Miss, DCache_L2_All)\000\000\000\000\000\000\000\00000 */
> > > > > -{ 2789 }, /* Frontend_Bound_SMT\000\000idq_uops_not_delivered.core / (4 * (cpu_clk_unhalted.thread / 2 * (1 + cpu_clk_unhalted.one_thread_active / cpu_clk_unhalted.ref_xclk)))\000\000\000\000\000\000\000\00000 */
> > > > > -{ 2726 }, /* IPC\000group1\000inst_retired.any / cpu_clk_unhalted.thread\000\000\000\000\000\000\000\00000 */
> > > > > -{ 3651 }, /* L1D_Cache_Fill_BW\000\00064 * l1d.replacement / 1e9 / duration_time\000\000\000\000\000\000\000\00000 */
> > > > > -{ 3587 }, /* M1\000\000ipc + M2\000\000\000\000\000\000\000\00000 */
> > > > > -{ 3609 }, /* M2\000\000ipc + M1\000\000\000\000\000\000\000\00000 */
> > > > > -{ 3631 }, /* M3\000\0001 / M3\000\000\000\000\000\000\000\00000 */
> > > > > -{ 3086 }, /* cache_miss_cycles\000group1\000dcache_miss_cpi + icache_miss_cycles\000\000\000\000\000\000\000\00000 */
> > > > > -{ 2955 }, /* dcache_miss_cpi\000\000l1d\\-loads\\-misses / inst_retired.any\000\000\000\000\000\000\000\00000 */
> > > > > -{ 3019 }, /* icache_miss_cycles\000\000l1i\\-loads\\-misses / inst_retired.any\000\000\000\000\000\000\000\00000 */
> > > > > +{ 4245 }, /* CPI\000\0001 / IPC\000\000\000\000\000\000\000\00000 */
> > > > > +{ 4926 }, /* DCache_L2_All\000\000DCache_L2_All_Hits + DCache_L2_All_Miss\000\000\000\000\000\000\000\00000 */
> > > > > +{ 4698 }, /* DCache_L2_All_Hits\000\000l2_rqsts.demand_data_rd_hit + l2_rqsts.pf_hit + l2_rqsts.rfo_hit\000\000\000\000\000\000\000\00000 */
> > > > > +{ 4792 }, /* DCache_L2_All_Miss\000\000max(l2_rqsts.all_demand_data_rd - l2_rqsts.demand_data_rd_hit, 0) + l2_rqsts.pf_miss + l2_rqsts.rfo_miss\000\000\000\000\000\000\000\00000 */
> > > > > +{ 4990 }, /* DCache_L2_Hits\000\000d_ratio(DCache_L2_All_Hits, DCache_L2_All)\000\000\000\000\000\000\000\00000 */
> > > > > +{ 5058 }, /* DCache_L2_Misses\000\000d_ratio(DCache_L2_All_Miss, DCache_L2_All)\000\000\000\000\000\000\000\00000 */
> > > > > +{ 4330 }, /* Frontend_Bound_SMT\000\000idq_uops_not_delivered.core / (4 * (cpu_clk_unhalted.thread / 2 * (1 + cpu_clk_unhalted.one_thread_active / cpu_clk_unhalted.ref_xclk)))\000\000\000\000\000\000\000\00000 */
> > > > > +{ 4267 }, /* IPC\000group1\000inst_retired.any / cpu_clk_unhalted.thread\000\000\000\000\000\000\000\00000 */
> > > > > +{ 5192 }, /* L1D_Cache_Fill_BW\000\00064 * l1d.replacement / 1e9 / duration_time\000\000\000\000\000\000\000\00000 */
> > > > > +{ 5128 }, /* M1\000\000ipc + M2\000\000\000\000\000\000\000\00000 */
> > > > > +{ 5150 }, /* M2\000\000ipc + M1\000\000\000\000\000\000\000\00000 */
> > > > > +{ 5172 }, /* M3\000\0001 / M3\000\000\000\000\000\000\000\00000 */
> > > > > +{ 4627 }, /* cache_miss_cycles\000group1\000dcache_miss_cpi + icache_miss_cycles\000\000\000\000\000\000\000\00000 */
> > > > > +{ 4496 }, /* dcache_miss_cpi\000\000l1d\\-loads\\-misses / inst_retired.any\000\000\000\000\000\000\000\00000 */
> > > > > +{ 4560 }, /* icache_miss_cycles\000\000l1i\\-loads\\-misses / inst_retired.any\000\000\000\000\000\000\000\00000 */
> > > > >
> > > > >  };
> > > > >
> > > > > @@ -181,18 +219,18 @@ const struct pmu_table_entry pmu_metrics__test_soc_cpu[] = {
> > > > >  {
> > > > >       .entries = pmu_metrics__test_soc_cpu_default_core,
> > > > >       .num_entries = ARRAY_SIZE(pmu_metrics__test_soc_cpu_default_core),
> > > > > -     .pmu_name = { 1138 /* default_core\000 */ },
> > > > > +     .pmu_name = { 2679 /* default_core\000 */ },
> > > > >  },
> > > > >  };
> > > > >
> > > > >  static const struct compact_pmu_event pmu_events__test_soc_sys_uncore_sys_ccn_pmu[] = {
> > > > > -{ 2465 }, /* sys_ccn_pmu.read_cycles\000uncore\000ccn read-cycles event\000config=0x2c\0000x01\00000\000\000\000\000\000 */
> > > > > +{ 4006 }, /* sys_ccn_pmu.read_cycles\000uncore\000ccn read-cycles event\000config=0x2c\0000x01\00000\000\000\000\000\000 */
> > > > >  };
> > > > >  static const struct compact_pmu_event pmu_events__test_soc_sys_uncore_sys_cmn_pmu[] = {
> > > > > -{ 2561 }, /* sys_cmn_pmu.hnf_cache_miss\000uncore\000Counts total cache misses in first lookup result (high priority)\000eventid=1,type=5\000(434|436|43c|43a).*\00000\000\000\000\000\000 */
> > > > > +{ 4102 }, /* sys_cmn_pmu.hnf_cache_miss\000uncore\000Counts total cache misses in first lookup result (high priority)\000eventid=1,type=5\000(434|436|43c|43a).*\00000\000\000\000\000\000 */
> > > > >  };
> > > > >  static const struct compact_pmu_event pmu_events__test_soc_sys_uncore_sys_ddr_pmu[] = {
> > > > > -{ 2370 }, /* sys_ddr_pmu.write_cycles\000uncore\000ddr write-cycles event\000event=0x2b\000v8\00000\000\000\000\000\000 */
> > > > > +{ 3911 }, /* sys_ddr_pmu.write_cycles\000uncore\000ddr write-cycles event\000event=0x2b\000v8\00000\000\000\000\000\000 */
> > > > >
> > > > >  };
> > > > >
> > > > > @@ -200,17 +238,17 @@ const struct pmu_table_entry pmu_events__test_soc_sys[] = {
> > > > >  {
> > > > >       .entries = pmu_events__test_soc_sys_uncore_sys_ccn_pmu,
> > > > >       .num_entries = ARRAY_SIZE(pmu_events__test_soc_sys_uncore_sys_ccn_pmu),
> > > > > -     .pmu_name = { 2446 /* uncore_sys_ccn_pmu\000 */ },
> > > > > +     .pmu_name = { 3987 /* uncore_sys_ccn_pmu\000 */ },
> > > > >  },
> > > > >  {
> > > > >       .entries = pmu_events__test_soc_sys_uncore_sys_cmn_pmu,
> > > > >       .num_entries = ARRAY_SIZE(pmu_events__test_soc_sys_uncore_sys_cmn_pmu),
> > > > > -     .pmu_name = { 2542 /* uncore_sys_cmn_pmu\000 */ },
> > > > > +     .pmu_name = { 4083 /* uncore_sys_cmn_pmu\000 */ },
> > > > >  },
> > > > >  {
> > > > >       .entries = pmu_events__test_soc_sys_uncore_sys_ddr_pmu,
> > > > >       .num_entries = ARRAY_SIZE(pmu_events__test_soc_sys_uncore_sys_ddr_pmu),
> > > > > -     .pmu_name = { 2351 /* uncore_sys_ddr_pmu\000 */ },
> > > > > +     .pmu_name = { 3892 /* uncore_sys_ddr_pmu\000 */ },
> > > > >  },
> > > > >  };
> > > > >
> > > > > @@ -632,8 +670,20 @@ static const struct pmu_events_map *map_for_pmu(struct perf_pmu *pmu)
> > > > >  {
> > > > >          struct perf_cpu cpu = {-1};
> > > > >
> > > > > -        if (pmu)
> > > > > +        if (pmu) {
> > > > > +                for (size_t i=0; i < ARRAY_SIZE(pmu_events__common); i++) {
> > > > > +                        const char *pmu_name = &big_c_string[pmu_events__common[i].pmu_name.offset];
> > > > > +
> > > > > +                        if (!strcmp(pmu_name, pmu->name)) {
> > > > > +                                const struct pmu_events_map *map = &pmu_events_map[0];
> > > > > +
> > > > > +                                while (strcmp("common", map->arch))
> > > > > +                                        map++;
> > > > > +                                return map;
> > > > > +                        }
> > > > > +                }
> > > > >                  cpu = perf_cpu_map__min(pmu->cpus);
> > > > > +        }
> > > > >          return map_for_cpu(cpu);
> > > > >  }
> > > > >
> > > > > diff --git a/tools/perf/pmu-events/jevents.py b/tools/perf/pmu-events/jevents.py
> > > > > index e821155151ec..76c1e7b0bc22 100755
> > > > > --- a/tools/perf/pmu-events/jevents.py
> > > > > +++ b/tools/perf/pmu-events/jevents.py
> > > > > @@ -295,6 +295,7 @@ class JsonEvent:
> > > > >            'cpu_atom': 'cpu_atom',
> > > > >            'ali_drw': 'ali_drw',
> > > > >            'arm_cmn': 'arm_cmn',
> > > > > +          'software': 'software',
> > > > >            'tool': 'tool',
> > > > >        }
> > > > >        return table[unit] if unit in table else f'uncore_{unit.lower()}'
> > > > > @@ -1158,8 +1159,20 @@ static const struct pmu_events_map *map_for_pmu(struct perf_pmu *pmu)
> > > > >  {
> > > > >          struct perf_cpu cpu = {-1};
> > > > >
> > > > > -        if (pmu)
> > > > > +        if (pmu) {
> > > > > +                for (size_t i=0; i < ARRAY_SIZE(pmu_events__common); i++) {
> > > > > +                        const char *pmu_name = &big_c_string[pmu_events__common[i].pmu_name.offset];
> > > > > +
> > > > > +                        if (!strcmp(pmu_name, pmu->name)) {
> > > > > +                                const struct pmu_events_map *map = &pmu_events_map[0];
> > > > > +
> > > > > +                                while (strcmp("common", map->arch))
> > > > > +                                        map++;
> > > > > +                                return map;
> > > > > +                        }
> > > > > +                }
> > > > >                  cpu = perf_cpu_map__min(pmu->cpus);
> > > > > +        }
> > > > >          return map_for_cpu(cpu);
> > > > >  }
> > > > >
> > > > > --
> > > > > 2.50.0.727.gbf7dc18ff4-goog
> > > > >

^ permalink raw reply	[flat|nested] 41+ messages in thread

end of thread, other threads:[~2025-07-24 16:58 UTC | newest]

Thread overview: 41+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-07-14 16:43 [PATCH v7 00/16] New perf ilist app Ian Rogers
2025-07-14 16:43 ` [PATCH v7 01/16] perf python: Add more exceptions on error paths Ian Rogers
2025-07-23 16:48   ` Arnaldo Carvalho de Melo
2025-07-23 18:12   ` Namhyung Kim
2025-07-23 18:21     ` Ian Rogers
2025-07-23 22:24       ` Ian Rogers
2025-07-14 16:43 ` [PATCH v7 02/16] perf jevents: Add common software event json Ian Rogers
2025-07-23 16:52   ` Arnaldo Carvalho de Melo
2025-07-23 18:24   ` Namhyung Kim
2025-07-23 22:34     ` Ian Rogers
2025-07-24  0:10       ` Namhyung Kim
2025-07-24  1:47         ` Ian Rogers
2025-07-24 16:58           ` Namhyung Kim
2025-07-14 16:43 ` [PATCH v7 03/16] perf parse-events: Remove non-json software events Ian Rogers
2025-07-24  0:20   ` Namhyung Kim
2025-07-14 16:43 ` [PATCH v7 04/16] perf tp_pmu: Factor existing tracepoint logic to new file Ian Rogers
2025-07-23 16:57   ` Arnaldo Carvalho de Melo
2025-07-14 16:43 ` [PATCH v7 05/16] perf tp_pmu: Add event APIs Ian Rogers
2025-07-23 18:57   ` Arnaldo Carvalho de Melo
2025-07-14 16:43 ` [PATCH v7 06/16] perf list: Remove tracepoint printing code Ian Rogers
2025-07-14 16:43 ` [PATCH v7 07/16] perf list: Skip ABI PMUs when printing pmu values Ian Rogers
2025-07-14 16:43 ` [PATCH v7 08/16] perf python: Improve the tracepoint function if no libtraceevent Ian Rogers
2025-07-14 16:43 ` [PATCH v7 09/16] perf python: Add basic PMU abstraction and pmus sequence Ian Rogers
2025-07-14 16:43 ` [PATCH v7 10/16] perf python: Add function returning dictionary of all events on a PMU Ian Rogers
2025-07-14 16:43 ` [PATCH v7 11/16] perf ilist: Add new python ilist command Ian Rogers
2025-07-21  7:32   ` Gautam Menghani
2025-07-21 13:41     ` Ian Rogers
2025-07-23 18:33   ` Falcon, Thomas
2025-07-23 21:33     ` Ian Rogers
2025-07-14 16:44 ` [PATCH v7 12/16] perf python: Add parse_metrics function Ian Rogers
2025-07-14 16:44 ` [PATCH v7 13/16] perf python: Add evlist metrics function Ian Rogers
2025-07-14 16:44 ` [PATCH v7 14/16] perf python: Add evlist compute_metric Ian Rogers
2025-07-14 16:44 ` [PATCH v7 15/16] perf python: Add metrics function Ian Rogers
2025-07-14 16:44 ` [PATCH v7 16/16] perf ilist: Add support for metrics Ian Rogers
2025-07-23 15:32 ` [PATCH v7 00/16] New perf ilist app Ian Rogers
2025-07-23 18:00   ` Namhyung Kim
2025-07-23 18:15     ` Ian Rogers
2025-07-23 19:08     ` Arnaldo Carvalho de Melo
2025-07-23 19:11       ` Arnaldo Carvalho de Melo
2025-07-23 19:24         ` Arnaldo Carvalho de Melo
2025-07-23 21:30           ` Ian Rogers

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).