* [PATCH v2 1/4] perf tool_pmu: Add memory events
2026-11-13 23:37 [PATCH v2 0/4] perf tool_pmu: Add procfs memory, network and schedstat events Ian Rogers
@ 2026-11-13 23:37 ` Ian Rogers
2026-11-13 23:37 ` [PATCH v2 2/4] perf tool_pmu: Add network events Ian Rogers
` (2 subsequent siblings)
3 siblings, 0 replies; 5+ messages in thread
From: Ian Rogers @ 2026-11-13 23:37 UTC (permalink / raw)
To: Peter Zijlstra, Ingo Molnar, Arnaldo Carvalho de Melo,
Namhyung Kim, Jiri Olsa, Ian Rogers, Adrian Hunter, James Clark,
Thomas Falcon, Thomas Richter, linux-perf-users, linux-kernel
Cc: Andi Kleen
Add tool PMU events to report memory usage information exposed by
/proc/pid/smaps_rollup and /proc/pid/statm.
The following events are added:
- memory_anon_huge_pages: Anonymous Huge Pages memory in bytes.
- memory_anonymous: Anonymous (non-file-backed) memory in bytes.
- memory_data: Data and stack segment memory in bytes.
- memory_file_pmd_mapped: File-backed PMD-mapped memory in bytes.
- memory_ksm: Kernel Samepage Merging (KSM) memory in bytes.
- memory_lazyfree: LazyFree marked memory in bytes.
- memory_locked: RAM-locked memory in bytes.
- memory_private_clean: Private clean memory in bytes.
- memory_private_dirty: Private dirty memory in bytes.
- memory_private_hugetlb: Private Huge Pages memory in bytes.
- memory_pss: Proportional Set Size (PSS) in bytes.
- memory_pss_anon: Anonymous PSS memory in bytes.
- memory_pss_dirty: Dirty PSS memory in bytes.
- memory_pss_file: File-backed PSS memory in bytes.
- memory_pss_shmem: Shared PSS memory in bytes.
- memory_referenced: Referenced/accessed memory in bytes.
- memory_rss: Resident Set Size (RSS) in bytes.
- memory_shared_clean: Shared clean memory in bytes.
- memory_shared_dirty: Shared dirty memory in bytes.
- memory_shared_hugetlb: Shared Huge Pages memory in bytes.
- memory_shmem_pmd_mapped: Shared PMD-mapped memory in bytes.
- memory_size: Virtual memory size in bytes.
- memory_swap: Swapped-out memory in bytes.
- memory_swap_pss: Proportional swap memory (SwapPss) in bytes.
- memory_text: Code (text segment) memory in bytes.
- memory_uss: Unique Set Size (USS) in bytes.
The events are aggregated across processes in system-wide mode, or
reported per-process when monitoring specific tasks. In per-process mode,
open a /proc/<pid> directory descriptor and resolve statm or smaps_rollup
on each read so post-exec address spaces are observed without PID-reuse
races, and deduplicate sibling threads sharing a Tgid so multi-threaded
processes are not multiplied by thread count.
Because /proc/<pid>/statm and /proc/<pid>/smaps_rollup require a live
mm_struct at counter read time, non-memory_rss per-process events require
an active target at read time (such as -p <pid> or -I interval mode while
a workload runs). For memory_rss, fall back to wait4 rusage ru_maxrss
when a forked workload has already terminated at counter read time.
Example per-process and system-wide output:
$ perf stat -e memory_size,memory_rss,memory_pss,memory_uss \
-e memory_data,memory_text -p 3558512 -- sleep 0.1
Performance counter stats for process id '3558512':
7,520,256 memory_size
4,542,464 memory_rss
585,728 memory_pss
356,352 memory_uss
458,752 memory_data
892,928 memory_text
0.101111221 seconds time elapsed
$ perf stat -a -e memory_size,memory_rss,memory_pss,memory_uss sleep 0.1
Performance counter stats for 'system wide':
104,040,572,162,048 memory_size
40,880,496,640 memory_rss
24,085,870,592 memory_pss
22,840,549,376 memory_uss
0.101068461 seconds time elapsed
Signed-off-by: Ian Rogers <irogers@google.com>
---
tools/perf/builtin-stat.c | 81 ++-
.../pmu-events/arch/common/common/tool.json | 156 +++++
tools/perf/pmu-events/empty-pmu-events.c | 326 +++++++----
tools/perf/util/tool_pmu.c | 552 ++++++++++++++++--
tools/perf/util/tool_pmu.h | 26 +
5 files changed, 954 insertions(+), 187 deletions(-)
diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c
index 37752d6bfef4..d2c8c0ccea49 100644
--- a/tools/perf/builtin-stat.c
+++ b/tools/perf/builtin-stat.c
@@ -139,6 +139,7 @@ static const char *output_name;
static int output_fd;
static char *metrics;
static struct rusage_stats ru_stats;
+static bool ru_stats_valid;
struct perf_stat {
bool record;
@@ -283,12 +284,13 @@ static int read_single_counter(struct evsel *counter, int cpu_map_idx, int threa
int err = evsel__read_counter(counter, cpu_map_idx, thread);
/*
- * Reading user and system time will fail when the process
- * terminates. Use the wait4 values in that case.
+ * Reading user, system time and memory_rss will fail when a forked
+ * workload terminates. Use the wait4 values in that case.
*/
- if (err && cpu_map_idx == 0 &&
+ if (err && cpu_map_idx == 0 && thread == 0 && ru_stats_valid &&
(evsel__tool_event(counter) == TOOL_PMU__EVENT_USER_TIME ||
- evsel__tool_event(counter) == TOOL_PMU__EVENT_SYSTEM_TIME)) {
+ evsel__tool_event(counter) == TOOL_PMU__EVENT_SYSTEM_TIME ||
+ evsel__tool_event(counter) == TOOL_PMU__EVENT_MEMORY_RSS)) {
struct perf_counts_values *count =
perf_counts(counter->counts, cpu_map_idx, thread);
struct perf_counts_values *old_count = NULL;
@@ -299,10 +301,15 @@ static int read_single_counter(struct evsel *counter, int cpu_map_idx, int threa
if (evsel__tool_event(counter) == TOOL_PMU__EVENT_USER_TIME)
val = ru_stats.ru_utime_usec_stat.mean;
- else
+ else if (evsel__tool_event(counter) == TOOL_PMU__EVENT_SYSTEM_TIME)
val = ru_stats.ru_stime_usec_stat.mean;
+ else
+ val = (u64)stat_config.ru_data.ru_maxrss * 1024ULL;
- count->val = val;
+ if (evsel__tool_event(counter) == TOOL_PMU__EVENT_MEMORY_RSS && old_count)
+ count->val = old_count->val + val;
+ else
+ count->val = val;
if (old_count) {
count->run = old_count->run + 1;
count->ena = old_count->ena + 1;
@@ -612,6 +619,34 @@ static void compute_tts(struct timespec *time_start, struct timespec *time_stop,
*time_to_sleep = tts;
}
+static void update_rusage_stats(const struct rusage *rusage)
+{
+ const u64 us_to_ns = 1000;
+ const u64 s_to_ns = 1000000000;
+
+ update_stats(&ru_stats.ru_utime_usec_stat,
+ (rusage->ru_utime.tv_usec * us_to_ns + rusage->ru_utime.tv_sec * s_to_ns));
+ update_stats(&ru_stats.ru_stime_usec_stat,
+ (rusage->ru_stime.tv_usec * us_to_ns + rusage->ru_stime.tv_sec * s_to_ns));
+ ru_stats_valid = true;
+}
+
+static bool reap_workload(int *status, int options)
+{
+ pid_t pid = evlist__workload_pid(evsel_list);
+
+ if (pid <= 0)
+ return false;
+
+ if (wait4(pid, status, options, &stat_config.ru_data) <= 0)
+ return false;
+
+ child_pid = -1;
+ evlist__set_workload_pid(evsel_list, -1);
+ update_rusage_stats(&stat_config.ru_data);
+ return true;
+}
+
static int dispatch_events(bool forks, int timeout, int interval, int *times)
{
int child_exited = 0, status = 0;
@@ -628,18 +663,20 @@ static int dispatch_events(bool forks, int timeout, int interval, int *times)
time_to_sleep = sleep_time;
while (!done) {
- if (forks) {
- child_exited = waitpid(child_pid, &status, WNOHANG);
- } else {
+ if (forks)
+ child_exited = reap_workload(&status, WNOHANG) ? 1 : 0;
+ else
child_exited = !is_target_alive(&target,
evlist__core(evsel_list)->threads) ? 1 : 0;
- }
+
if (child_exited)
break;
clock_gettime(CLOCK_MONOTONIC, &time_start);
if (!(evlist__poll(evsel_list, time_to_sleep) > 0)) { /* poll timeout or EINTR */
- if (timeout || handle_interval(interval, times))
+ if (forks && reap_workload(&status, WNOHANG))
+ child_exited = 1;
+ if (timeout || handle_interval(interval, times) || child_exited)
break;
time_to_sleep = sleep_time;
} else { /* fd revent */
@@ -761,17 +798,6 @@ static int create_perf_stat_counter(struct evsel *evsel,
evsel->core.threads);
}
-static void update_rusage_stats(const struct rusage *rusage)
-{
- const u64 us_to_ns = 1000;
- const u64 s_to_ns = 1000000000;
-
- update_stats(&ru_stats.ru_utime_usec_stat,
- (rusage->ru_utime.tv_usec * us_to_ns + rusage->ru_utime.tv_sec * s_to_ns));
- update_stats(&ru_stats.ru_stime_usec_stat,
- (rusage->ru_stime.tv_usec * us_to_ns + rusage->ru_stime.tv_sec * s_to_ns));
-}
-
static int __run_perf_stat(int argc, const char **argv, int run_idx)
{
int interval = stat_config.interval;
@@ -787,6 +813,8 @@ static int __run_perf_stat(int argc, const char **argv, int run_idx)
int err, open_err = 0;
bool second_pass = false, has_supported_counters;
+ ru_stats_valid = false;
+
if (forks) {
if (evlist__prepare_workload(evsel_list, &target, argv, is_pipe,
workload_exec_failed_signal) < 0) {
@@ -979,11 +1007,9 @@ static int __run_perf_stat(int argc, const char **argv, int run_idx)
if (forks) {
if (interval || timeout || evlist__ctlfd_initialized(evsel_list))
status = dispatch_events(forks, timeout, interval, ×);
- if (child_pid != -1) {
- if (timeout)
- kill(child_pid, SIGTERM);
- wait4(child_pid, &status, 0, &stat_config.ru_data);
- }
+ if (child_pid != -1 && timeout)
+ kill(child_pid, SIGTERM);
+ reap_workload(&status, 0);
if (workload_exec_errno) {
errno = workload_exec_errno;
@@ -1026,7 +1052,6 @@ static int __run_perf_stat(int argc, const char **argv, int run_idx)
evlist__reset_aggr_stats(evsel_list);
} else {
update_stats(stat_config.walltime_nsecs_stats, t1 - t0);
- update_rusage_stats(&stat_config.ru_data);
}
/*
diff --git a/tools/perf/pmu-events/arch/common/common/tool.json b/tools/perf/pmu-events/arch/common/common/tool.json
index 14d0d60a1976..9e0e89553847 100644
--- a/tools/perf/pmu-events/arch/common/common/tool.json
+++ b/tools/perf/pmu-events/arch/common/common/tool.json
@@ -82,5 +82,161 @@
"EventName": "target_cpu",
"BriefDescription": "1 if CPUs being analyzed, 0 if threads/processes",
"ConfigCode": "14"
+ },
+ {
+ "Unit": "tool",
+ "EventName": "memory_anon_huge_pages",
+ "BriefDescription": "Memory backed by anonymous huge pages in bytes",
+ "ConfigCode": "15"
+ },
+ {
+ "Unit": "tool",
+ "EventName": "memory_anonymous",
+ "BriefDescription": "Memory not mapped to a file (anonymous) in bytes",
+ "ConfigCode": "16"
+ },
+ {
+ "Unit": "tool",
+ "EventName": "memory_data",
+ "BriefDescription": "Memory dedicated to data and stack in bytes",
+ "ConfigCode": "17"
+ },
+ {
+ "Unit": "tool",
+ "EventName": "memory_file_pmd_mapped",
+ "BriefDescription": "Memory backed by file and mapped with Page Middle Directory (PMD) in bytes",
+ "ConfigCode": "18"
+ },
+ {
+ "Unit": "tool",
+ "EventName": "memory_ksm",
+ "BriefDescription": "Memory shared via Kernel Samepage Merging (KSM) in bytes",
+ "ConfigCode": "19"
+ },
+ {
+ "Unit": "tool",
+ "EventName": "memory_lazyfree",
+ "BriefDescription": "Memory marked as LazyFree in bytes",
+ "ConfigCode": "20"
+ },
+ {
+ "Unit": "tool",
+ "EventName": "memory_locked",
+ "BriefDescription": "Memory locked in RAM in bytes",
+ "ConfigCode": "21"
+ },
+ {
+ "Unit": "tool",
+ "EventName": "memory_private_clean",
+ "BriefDescription": "Private clean memory (not shared, not modified) in bytes",
+ "ConfigCode": "22"
+ },
+ {
+ "Unit": "tool",
+ "EventName": "memory_private_dirty",
+ "BriefDescription": "Private dirty memory (not shared, modified) in bytes",
+ "ConfigCode": "23"
+ },
+ {
+ "Unit": "tool",
+ "EventName": "memory_private_hugetlb",
+ "BriefDescription": "Private memory backed by huge pages in bytes",
+ "ConfigCode": "24"
+ },
+ {
+ "Unit": "tool",
+ "EventName": "memory_pss",
+ "BriefDescription": "Proportional Share Size (PSS) in bytes",
+ "ConfigCode": "25"
+ },
+ {
+ "Unit": "tool",
+ "EventName": "memory_pss_anon",
+ "BriefDescription": "Proportional Share Size (PSS) for anonymous memory in bytes",
+ "ConfigCode": "26"
+ },
+ {
+ "Unit": "tool",
+ "EventName": "memory_pss_dirty",
+ "BriefDescription": "Proportional Share Size (PSS) for dirty memory in bytes",
+ "ConfigCode": "27"
+ },
+ {
+ "Unit": "tool",
+ "EventName": "memory_pss_file",
+ "BriefDescription": "Proportional Share Size (PSS) for file-backed memory in bytes",
+ "ConfigCode": "28"
+ },
+ {
+ "Unit": "tool",
+ "EventName": "memory_pss_shmem",
+ "BriefDescription": "Proportional Share Size (PSS) for shared memory in bytes",
+ "ConfigCode": "29"
+ },
+ {
+ "Unit": "tool",
+ "EventName": "memory_referenced",
+ "BriefDescription": "Memory marked as referenced/accessed in bytes",
+ "ConfigCode": "30"
+ },
+ {
+ "Unit": "tool",
+ "EventName": "memory_rss",
+ "BriefDescription": "Resident Set Size (RSS) in bytes",
+ "ConfigCode": "31"
+ },
+ {
+ "Unit": "tool",
+ "EventName": "memory_shared_clean",
+ "BriefDescription": "Shared clean memory (shared with other processes, not modified) in bytes",
+ "ConfigCode": "32"
+ },
+ {
+ "Unit": "tool",
+ "EventName": "memory_shared_dirty",
+ "BriefDescription": "Shared dirty memory (shared with other processes, modified) in bytes",
+ "ConfigCode": "33"
+ },
+ {
+ "Unit": "tool",
+ "EventName": "memory_shared_hugetlb",
+ "BriefDescription": "Shared memory backed by huge pages in bytes",
+ "ConfigCode": "34"
+ },
+ {
+ "Unit": "tool",
+ "EventName": "memory_shmem_pmd_mapped",
+ "BriefDescription": "Shared memory mapped with Page Middle Directory (PMD) in bytes",
+ "ConfigCode": "35"
+ },
+ {
+ "Unit": "tool",
+ "EventName": "memory_size",
+ "BriefDescription": "Virtual memory size in bytes",
+ "ConfigCode": "36"
+ },
+ {
+ "Unit": "tool",
+ "EventName": "memory_swap",
+ "BriefDescription": "Memory swapped out to disk in bytes",
+ "ConfigCode": "37"
+ },
+ {
+ "Unit": "tool",
+ "EventName": "memory_swap_pss",
+ "BriefDescription": "Proportional Share Size (PSS) for swap memory in bytes",
+ "ConfigCode": "38"
+ },
+ {
+ "Unit": "tool",
+ "EventName": "memory_text",
+ "BriefDescription": "Memory dedicated to code (text segment) in bytes",
+ "ConfigCode": "39"
+ },
+ {
+ "Unit": "tool",
+ "EventName": "memory_uss",
+ "BriefDescription": "Unique Set Size (USS) in bytes",
+ "ConfigCode": "40"
}
]
diff --git a/tools/perf/pmu-events/empty-pmu-events.c b/tools/perf/pmu-events/empty-pmu-events.c
index 7df1552403e7..8d1b9e9b4f58 100644
--- a/tools/perf/pmu-events/empty-pmu-events.c
+++ b/tools/perf/pmu-events/empty-pmu-events.c
@@ -2544,116 +2544,168 @@ static const char *const big_c_string =
/* offset=126320 */
"target_cpu\000tool\0001 if CPUs being analyzed, 0 if threads/processes\000config=0xe\000\00000\000\000\000\000\000"
/* offset=126404 */
+"memory_anon_huge_pages\000tool\000Memory backed by anonymous huge pages in bytes\000config=0xf\000\00000\000\000\000\000\000"
+/* offset=126498 */
+"memory_anonymous\000tool\000Memory not mapped to a file (anonymous) in bytes\000config=0x10\000\00000\000\000\000\000\000"
+/* offset=126589 */
+"memory_data\000tool\000Memory dedicated to data and stack in bytes\000config=0x11\000\00000\000\000\000\000\000"
+/* offset=126670 */
+"memory_file_pmd_mapped\000tool\000Memory backed by file and mapped with Page Middle Directory (PMD) in bytes\000config=0x12\000\00000\000\000\000\000\000"
+/* offset=126793 */
+"memory_ksm\000tool\000Memory shared via Kernel Samepage Merging (KSM) in bytes\000config=0x13\000\00000\000\000\000\000\000"
+/* offset=126886 */
+"memory_lazyfree\000tool\000Memory marked as LazyFree in bytes\000config=0x14\000\00000\000\000\000\000\000"
+/* offset=126962 */
+"memory_locked\000tool\000Memory locked in RAM in bytes\000config=0x15\000\00000\000\000\000\000\000"
+/* offset=127031 */
+"memory_private_clean\000tool\000Private clean memory (not shared, not modified) in bytes\000config=0x16\000\00000\000\000\000\000\000"
+/* offset=127134 */
+"memory_private_dirty\000tool\000Private dirty memory (not shared, modified) in bytes\000config=0x17\000\00000\000\000\000\000\000"
+/* offset=127233 */
+"memory_private_hugetlb\000tool\000Private memory backed by huge pages in bytes\000config=0x18\000\00000\000\000\000\000\000"
+/* offset=127326 */
+"memory_pss\000tool\000Proportional Share Size (PSS) in bytes\000config=0x19\000\00000\000\000\000\000\000"
+/* offset=127401 */
+"memory_pss_anon\000tool\000Proportional Share Size (PSS) for anonymous memory in bytes\000config=0x1a\000\00000\000\000\000\000\000"
+/* offset=127502 */
+"memory_pss_dirty\000tool\000Proportional Share Size (PSS) for dirty memory in bytes\000config=0x1b\000\00000\000\000\000\000\000"
+/* offset=127600 */
+"memory_pss_file\000tool\000Proportional Share Size (PSS) for file-backed memory in bytes\000config=0x1c\000\00000\000\000\000\000\000"
+/* offset=127703 */
+"memory_pss_shmem\000tool\000Proportional Share Size (PSS) for shared memory in bytes\000config=0x1d\000\00000\000\000\000\000\000"
+/* offset=127802 */
+"memory_referenced\000tool\000Memory marked as referenced/accessed in bytes\000config=0x1e\000\00000\000\000\000\000\000"
+/* offset=127891 */
+"memory_rss\000tool\000Resident Set Size (RSS) in bytes\000config=0x1f\000\00000\000\000\000\000\000"
+/* offset=127960 */
+"memory_shared_clean\000tool\000Shared clean memory (shared with other processes, not modified) in bytes\000config=0x20\000\00000\000\000\000\000\000"
+/* offset=128078 */
+"memory_shared_dirty\000tool\000Shared dirty memory (shared with other processes, modified) in bytes\000config=0x21\000\00000\000\000\000\000\000"
+/* offset=128192 */
+"memory_shared_hugetlb\000tool\000Shared memory backed by huge pages in bytes\000config=0x22\000\00000\000\000\000\000\000"
+/* offset=128283 */
+"memory_shmem_pmd_mapped\000tool\000Shared memory mapped with Page Middle Directory (PMD) in bytes\000config=0x23\000\00000\000\000\000\000\000"
+/* offset=128395 */
+"memory_size\000tool\000Virtual memory size in bytes\000config=0x24\000\00000\000\000\000\000\000"
+/* offset=128461 */
+"memory_swap\000tool\000Memory swapped out to disk in bytes\000config=0x25\000\00000\000\000\000\000\000"
+/* offset=128534 */
+"memory_swap_pss\000tool\000Proportional Share Size (PSS) for swap memory in bytes\000config=0x26\000\00000\000\000\000\000\000"
+/* offset=128630 */
+"memory_text\000tool\000Memory dedicated to code (text segment) in bytes\000config=0x27\000\00000\000\000\000\000\000"
+/* offset=128716 */
+"memory_uss\000tool\000Unique Set Size (USS) in bytes\000config=0x28\000\00000\000\000\000\000\000"
+/* offset=128783 */
"bp_l1_btb_correct\000branch\000L1 BTB Correction\000event=0x8a\000\00000\000\000\000\000\000"
-/* offset=126466 */
+/* offset=128845 */
"bp_l2_btb_correct\000branch\000L2 BTB Correction\000event=0x8b\000\00000\000\000\000\000\000"
-/* offset=126528 */
+/* offset=128907 */
"l3_cache_rd\000cache\000L3 cache access, read\000event=0x40\000\00000\000\000\000\000Attributable Level 3 cache access, read\000"
-/* offset=126626 */
+/* offset=129005 */
"segment_reg_loads.any\000other\000Number of segment register loads\000event=6,period=200000,umask=0x80\000\00000\000\000\000\000\000"
-/* offset=126728 */
+/* offset=129107 */
"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=126861 */
+/* offset=129240 */
"eist_trans\000other\000Number of Enhanced Intel SpeedStep(R) Technology (EIST) transitions\000event=0x3a,period=200000\000\00000\000\000\000\000\000"
-/* offset=126979 */
+/* offset=129358 */
"hisi_sccl,ddrc\000"
-/* offset=126994 */
+/* offset=129373 */
"uncore_hisi_ddrc.flux_wcmd\000uncore\000DDRC write commands\000event=2\000\00000\000\000\000\000\000"
-/* offset=127064 */
+/* offset=129443 */
"uncore_cbox\000"
-/* offset=127076 */
+/* offset=129455 */
"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=127230 */
+/* offset=129609 */
"event-hyphen\000uncore\000UNC_CBO_HYPHEN\000event=0xe0\000\00000\000\000\000\000\000"
-/* offset=127284 */
+/* offset=129663 */
"event-two-hyph\000uncore\000UNC_CBO_TWO_HYPH\000event=0xc0\000\00000\000\000\000\000\000"
-/* offset=127342 */
+/* offset=129721 */
"hisi_sccl,l3c\000"
-/* offset=127356 */
+/* offset=129735 */
"uncore_hisi_l3c.rd_hit_cpipe\000uncore\000Total read hits\000event=7\000\00000\000\000\000\000\000"
-/* offset=127424 */
+/* offset=129803 */
"uncore_imc_free_running\000"
-/* offset=127448 */
+/* offset=129827 */
"uncore_imc_free_running.cache_miss\000uncore\000Total cache misses\000event=0x12\000\00000\000\000\000\000\000"
-/* offset=127528 */
+/* offset=129907 */
"uncore_imc\000"
-/* offset=127539 */
+/* offset=129918 */
"uncore_imc.cache_hits\000uncore\000Total cache hits\000event=0x34\000\00000\000\000\000\000\000"
-/* offset=127604 */
+/* offset=129983 */
"uncore_sys_ddr_pmu\000"
-/* offset=127623 */
+/* offset=130002 */
"sys_ddr_pmu.write_cycles\000uncore\000ddr write-cycles event\000event=0x2b\000v8\00000\000\000\000\000\000"
-/* offset=127699 */
+/* offset=130078 */
"uncore_sys_ccn_pmu\000"
-/* offset=127718 */
+/* offset=130097 */
"sys_ccn_pmu.read_cycles\000uncore\000ccn read-cycles event\000config=0x2c\0000x01\00000\000\000\000\000\000"
-/* offset=127795 */
+/* offset=130174 */
"uncore_sys_cmn_pmu\000"
-/* offset=127814 */
+/* offset=130193 */
"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=127957 */
+/* offset=130336 */
"CPUs_utilized\000Default\000(software@cpu\\-clock\\,name\\=cpu\\-clock@ if #target_cpu else software@task\\-clock\\,name\\=task\\-clock@) / (duration_time * 1e9)\000\000Average CPU utilization\000\0001CPUs\000\000\000\000011"
-/* offset=128143 */
+/* offset=130522 */
"cs_per_second\000Default\000software@context\\-switches\\,name\\=context\\-switches@ * 1e9 / (software@cpu\\-clock\\,name\\=cpu\\-clock@ if #target_cpu else software@task\\-clock\\,name\\=task\\-clock@)\000\000Context switches per CPU second\000\0001cs/sec\000\000\000\000011"
-/* offset=128376 */
+/* offset=130755 */
"migrations_per_second\000Default\000software@cpu\\-migrations\\,name\\=cpu\\-migrations@ * 1e9 / (software@cpu\\-clock\\,name\\=cpu\\-clock@ if #target_cpu else software@task\\-clock\\,name\\=task\\-clock@)\000\000Process migrations to a new CPU per CPU second\000\0001migrations/sec\000\000\000\000011"
-/* offset=128636 */
+/* offset=131015 */
"page_faults_per_second\000Default\000software@page\\-faults\\,name\\=page\\-faults@ * 1e9 / (software@cpu\\-clock\\,name\\=cpu\\-clock@ if #target_cpu else software@task\\-clock\\,name\\=task\\-clock@)\000\000Page faults per CPU second\000\0001faults/sec\000\000\000\000011"
-/* offset=128867 */
+/* offset=131246 */
"insn_per_cycle\000Default\000instructions / cpu\\-cycles\000insn_per_cycle < 1\000Instructions Per Cycle\000\0001instructions\000\000\000\000001"
-/* offset=128980 */
+/* offset=131359 */
"stalled_cycles_per_instruction\000Default\000(max(stalled\\-cycles\\-frontend, stalled\\-cycles\\-backend) / instructions if has_event(stalled\\-cycles\\-frontend) & has_event(stalled\\-cycles\\-backend) else (stalled\\-cycles\\-frontend / instructions if has_event(stalled\\-cycles\\-frontend) else (stalled\\-cycles\\-backend / instructions if has_event(stalled\\-cycles\\-backend) else 0)))\000\000Max front or backend stalls per instruction\000\000\000\000\000\000001"
-/* offset=129405 */
+/* offset=131784 */
"frontend_cycles_idle\000Default\000(stalled\\-cycles\\-frontend / cpu\\-cycles if has_event(stalled\\-cycles\\-frontend) else 0)\000frontend_cycles_idle > 0.1\000Frontend stalls per cycle\000\000\000\000\000\000001"
-/* offset=129584 */
+/* offset=131963 */
"backend_cycles_idle\000Default\000(stalled\\-cycles\\-backend / cpu\\-cycles if has_event(stalled\\-cycles\\-backend) else 0)\000backend_cycles_idle > 0.2\000Backend stalls per cycle\000\000\000\000\000\000001"
-/* offset=129758 */
+/* offset=132137 */
"cycles_frequency\000Default\000cpu\\-cycles / (software@cpu\\-clock\\,name\\=cpu\\-clock@ if #target_cpu else software@task\\-clock\\,name\\=task\\-clock@)\000\000Cycles per CPU second\000\0001GHz\000\000\000\000011"
-/* offset=129934 */
+/* offset=132313 */
"branch_frequency\000Default\000branches / (software@cpu\\-clock\\,name\\=cpu\\-clock@ if #target_cpu else software@task\\-clock\\,name\\=task\\-clock@)\000\000Branches per CPU second\000\0001000M/sec\000\000\000\000011"
-/* offset=130114 */
+/* offset=132493 */
"branch_miss_rate\000Default\000branch\\-misses / branches\000branch_miss_rate > 0.05\000Branch miss rate\000\000100%\000\000\000\000001"
-/* offset=130218 */
+/* offset=132597 */
"l1d_miss_rate\000Default2\000L1\\-dcache\\-load\\-misses / L1\\-dcache\\-loads\000l1d_miss_rate > 0.05\000L1D miss rate\000\000100%\000\000\000\000001"
-/* offset=130334 */
+/* offset=132713 */
"llc_miss_rate\000Default2\000LLC\\-load\\-misses / LLC\\-loads\000llc_miss_rate > 0.05\000LLC miss rate\000\000100%\000\000\000\000001"
-/* offset=130435 */
+/* offset=132814 */
"l1i_miss_rate\000Default3\000L1\\-icache\\-load\\-misses / L1\\-icache\\-loads\000l1i_miss_rate > 0.05\000L1I miss rate\000\000100%\000\000\000\000001"
-/* offset=130550 */
+/* offset=132929 */
"dtlb_miss_rate\000Default3\000dTLB\\-load\\-misses / dTLB\\-loads\000dtlb_miss_rate > 0.05\000dTLB miss rate\000\000100%\000\000\000\000001"
-/* offset=130656 */
+/* offset=133035 */
"itlb_miss_rate\000Default3\000iTLB\\-load\\-misses / iTLB\\-loads\000itlb_miss_rate > 0.05\000iTLB miss rate\000\000100%\000\000\000\000001"
-/* offset=130762 */
+/* offset=133141 */
"l1_prefetch_miss_rate\000Default4\000L1\\-dcache\\-prefetch\\-misses / L1\\-dcache\\-prefetches\000l1_prefetch_miss_rate > 0.05\000L1 prefetch miss rate\000\000100%\000\000\000\000001"
-/* offset=130910 */
+/* offset=133289 */
"CPI\000\0001 / IPC\000\000\000\000\000\000\000\000000"
-/* offset=130933 */
+/* offset=133312 */
"IPC\000group1\000inst_retired.any / cpu_clk_unhalted.thread\000\000\000\000\000\000\000\000000"
-/* offset=130997 */
+/* offset=133376 */
"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\000000"
-/* offset=131164 */
+/* offset=133543 */
"dcache_miss_cpi\000\000l1d\\-loads\\-misses / inst_retired.any\000\000\000\000\000\000\000\000000"
-/* offset=131229 */
+/* offset=133608 */
"icache_miss_cycles\000\000l1i\\-loads\\-misses / inst_retired.any\000\000\000\000\000\000\000\000000"
-/* offset=131297 */
+/* offset=133676 */
"cache_miss_cycles\000group1\000dcache_miss_cpi + icache_miss_cycles\000\000\000\000\000\000\000\000000"
-/* offset=131369 */
+/* offset=133748 */
"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\000000"
-/* offset=131464 */
+/* offset=133843 */
"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\000000"
-/* offset=131599 */
+/* offset=133978 */
"DCache_L2_All\000\000DCache_L2_All_Hits + DCache_L2_All_Miss\000\000\000\000\000\000\000\000000"
-/* offset=131664 */
+/* offset=134043 */
"DCache_L2_Hits\000\000d_ratio(DCache_L2_All_Hits, DCache_L2_All)\000\000\000\000\000\000\000\000000"
-/* offset=131733 */
+/* offset=134112 */
"DCache_L2_Misses\000\000d_ratio(DCache_L2_All_Miss, DCache_L2_All)\000\000\000\000\000\000\000\000000"
-/* offset=131804 */
+/* offset=134183 */
"M1\000\000ipc + M2\000\000\000\000\000\000\000\000000"
-/* offset=131827 */
+/* offset=134206 */
"M2\000\000ipc + M1\000\000\000\000\000\000\000\000000"
-/* offset=131850 */
+/* offset=134229 */
"M3\000\0001 / M3\000\000\000\000\000\000\000\000000"
-/* offset=131871 */
+/* offset=134250 */
"L1D_Cache_Fill_BW\000\00064 * l1d.replacement / 1e9 / duration_time\000\000\000\000\000\000\000\000000"
;
@@ -5158,6 +5210,58 @@ static const struct compact_pmu_event pmu_events__common_tool[] = {
{ 125073 },
/* has_pmem\000tool\0001 if persistent memory installed otherwise 0\000config=4\000... */
{ 125287 },
+ /* memory_anon_huge_pages\000tool\000Memory backed by anonymous huge pages in bytes... */
+ { 126404 },
+ /* memory_anonymous\000tool\000Memory not mapped to a file (anonymous) in bytes\000... */
+ { 126498 },
+ /* memory_data\000tool\000Memory dedicated to data and stack in bytes\000config=0x1... */
+ { 126589 },
+ /* memory_file_pmd_mapped\000tool\000Memory backed by file and mapped with Page Mid... */
+ { 126670 },
+ /* memory_ksm\000tool\000Memory shared via Kernel Samepage Merging (KSM) in bytes\0... */
+ { 126793 },
+ /* memory_lazyfree\000tool\000Memory marked as LazyFree in bytes\000config=0x14\000... */
+ { 126886 },
+ /* memory_locked\000tool\000Memory locked in RAM in bytes\000config=0x15\000\00000\... */
+ { 126962 },
+ /* memory_private_clean\000tool\000Private clean memory (not shared, not modified) ... */
+ { 127031 },
+ /* memory_private_dirty\000tool\000Private dirty memory (not shared, modified) in b... */
+ { 127134 },
+ /* memory_private_hugetlb\000tool\000Private memory backed by huge pages in bytes\0... */
+ { 127233 },
+ /* memory_pss\000tool\000Proportional Share Size (PSS) in bytes\000config=0x19\000\... */
+ { 127326 },
+ /* memory_pss_anon\000tool\000Proportional Share Size (PSS) for anonymous memory in... */
+ { 127401 },
+ /* memory_pss_dirty\000tool\000Proportional Share Size (PSS) for dirty memory in by... */
+ { 127502 },
+ /* memory_pss_file\000tool\000Proportional Share Size (PSS) for file-backed memory ... */
+ { 127600 },
+ /* memory_pss_shmem\000tool\000Proportional Share Size (PSS) for shared memory in b... */
+ { 127703 },
+ /* memory_referenced\000tool\000Memory marked as referenced/accessed in bytes\000co... */
+ { 127802 },
+ /* memory_rss\000tool\000Resident Set Size (RSS) in bytes\000config=0x1f\000\00000\... */
+ { 127891 },
+ /* memory_shared_clean\000tool\000Shared clean memory (shared with other processes,... */
+ { 127960 },
+ /* memory_shared_dirty\000tool\000Shared dirty memory (shared with other processes,... */
+ { 128078 },
+ /* memory_shared_hugetlb\000tool\000Shared memory backed by huge pages in bytes\000... */
+ { 128192 },
+ /* memory_shmem_pmd_mapped\000tool\000Shared memory mapped with Page Middle Directo... */
+ { 128283 },
+ /* memory_size\000tool\000Virtual memory size in bytes\000config=0x24\000\00000\000... */
+ { 128395 },
+ /* memory_swap\000tool\000Memory swapped out to disk in bytes\000config=0x25\000\00... */
+ { 128461 },
+ /* memory_swap_pss\000tool\000Proportional Share Size (PSS) for swap memory in byte... */
+ { 128534 },
+ /* memory_text\000tool\000Memory dedicated to code (text segment) in bytes\000confi... */
+ { 128630 },
+ /* memory_uss\000tool\000Unique Set Size (USS) in bytes\000config=0x28\000\00000\00... */
+ { 128716 },
/* num_cores\000tool\000Number of cores. A core consists of 1 or more thread, with ... */
{ 125363 },
/* num_cpus\000tool\000Number of logical Linux CPUs. There may be multiple such CPU... */
@@ -5203,39 +5307,39 @@ static const struct pmu_table_entry pmu_events__common[] = {
static const struct compact_pmu_event pmu_metrics__common_default_core[] = {
/* CPUs_utilized\000Default\000(software@cpu\\-clock\\,name\\=cpu\\-clock@ if #targ... */
- { 127957 },
+ { 130336 },
/* backend_cycles_idle\000Default\000(stalled\\-cycles\\-backend / cpu\\-cycles if ... */
- { 129584 },
+ { 131963 },
/* branch_frequency\000Default\000branches / (software@cpu\\-clock\\,name\\=cpu\\-c... */
- { 129934 },
+ { 132313 },
/* branch_miss_rate\000Default\000branch\\-misses / branches\000branch_miss_rate > ... */
- { 130114 },
+ { 132493 },
/* cs_per_second\000Default\000software@context\\-switches\\,name\\=context\\-switc... */
- { 128143 },
+ { 130522 },
/* cycles_frequency\000Default\000cpu\\-cycles / (software@cpu\\-clock\\,name\\=cpu... */
- { 129758 },
+ { 132137 },
/* dtlb_miss_rate\000Default3\000dTLB\\-load\\-misses / dTLB\\-loads\000dtlb_miss_r... */
- { 130550 },
+ { 132929 },
/* frontend_cycles_idle\000Default\000(stalled\\-cycles\\-frontend / cpu\\-cycles i... */
- { 129405 },
+ { 131784 },
/* insn_per_cycle\000Default\000instructions / cpu\\-cycles\000insn_per_cycle < 1\0... */
- { 128867 },
+ { 131246 },
/* itlb_miss_rate\000Default3\000iTLB\\-load\\-misses / iTLB\\-loads\000itlb_miss_r... */
- { 130656 },
+ { 133035 },
/* l1_prefetch_miss_rate\000Default4\000L1\\-dcache\\-prefetch\\-misses / L1\\-dcac... */
- { 130762 },
+ { 133141 },
/* l1d_miss_rate\000Default2\000L1\\-dcache\\-load\\-misses / L1\\-dcache\\-loads\0... */
- { 130218 },
+ { 132597 },
/* l1i_miss_rate\000Default3\000L1\\-icache\\-load\\-misses / L1\\-icache\\-loads\0... */
- { 130435 },
+ { 132814 },
/* llc_miss_rate\000Default2\000LLC\\-load\\-misses / LLC\\-loads\000llc_miss_rate ... */
- { 130334 },
+ { 132713 },
/* migrations_per_second\000Default\000software@cpu\\-migrations\\,name\\=cpu\\-mig... */
- { 128376 },
+ { 130755 },
/* page_faults_per_second\000Default\000software@page\\-faults\\,name\\=page\\-faul... */
- { 128636 },
+ { 131015 },
/* stalled_cycles_per_instruction\000Default\000(max(stalled\\-cycles\\-frontend, s... */
- { 128980 },
+ { 131359 },
};
@@ -5249,41 +5353,41 @@ static const struct pmu_table_entry pmu_metrics__common[] = {
static const struct compact_pmu_event pmu_events__test_soc_cpu_default_core[] = {
/* bp_l1_btb_correct\000branch\000L1 BTB Correction\000event=0x8a\000\00000\000\000... */
- { 126404 },
+ { 128783 },
/* bp_l2_btb_correct\000branch\000L2 BTB Correction\000event=0x8b\000\00000\000\000... */
- { 126466 },
+ { 128845 },
/* dispatch_blocked.any\000other\000Memory cluster signals to block micro-op dispat... */
- { 126728 },
+ { 129107 },
/* eist_trans\000other\000Number of Enhanced Intel SpeedStep(R) Technology (EIST) t... */
- { 126861 },
+ { 129240 },
/* l3_cache_rd\000cache\000L3 cache access, read\000event=0x40\000\00000\000\000\00... */
- { 126528 },
+ { 128907 },
/* segment_reg_loads.any\000other\000Number of segment register loads\000event=6,pe... */
- { 126626 },
+ { 129005 },
};
static const struct compact_pmu_event pmu_events__test_soc_cpu_hisi_sccl_ddrc[] = {
/* uncore_hisi_ddrc.flux_wcmd\000uncore\000DDRC write commands\000event=2\000\00000... */
- { 126994 },
+ { 129373 },
};
static const struct compact_pmu_event pmu_events__test_soc_cpu_hisi_sccl_l3c[] = {
/* uncore_hisi_l3c.rd_hit_cpipe\000uncore\000Total read hits\000event=7\000\00000\0... */
- { 127356 },
+ { 129735 },
};
static const struct compact_pmu_event pmu_events__test_soc_cpu_uncore_cbox[] = {
/* event-hyphen\000uncore\000UNC_CBO_HYPHEN\000event=0xe0\000\00000\000\000\000\000... */
- { 127230 },
+ { 129609 },
/* event-two-hyph\000uncore\000UNC_CBO_TWO_HYPH\000event=0xc0\000\00000\000\000\000... */
- { 127284 },
+ { 129663 },
/* unc_cbo_xsnp_response.miss_eviction\000uncore\000A cross-core snoop resulted fro... */
- { 127076 },
+ { 129455 },
};
static const struct compact_pmu_event pmu_events__test_soc_cpu_uncore_imc[] = {
/* uncore_imc.cache_hits\000uncore\000Total cache hits\000event=0x34\000\00000\000\... */
- { 127539 },
+ { 129918 },
};
static const struct compact_pmu_event pmu_events__test_soc_cpu_uncore_imc_free_running[] = {
/* uncore_imc_free_running.cache_miss\000uncore\000Total cache misses\000event=0x12... */
- { 127448 },
+ { 129827 },
};
@@ -5296,61 +5400,61 @@ static const struct pmu_table_entry pmu_events__test_soc_cpu[] = {
{
.entries = pmu_events__test_soc_cpu_hisi_sccl_ddrc,
.num_entries = ARRAY_SIZE(pmu_events__test_soc_cpu_hisi_sccl_ddrc),
- .pmu_name = { 126979 /* hisi_sccl,ddrc\000 */ },
+ .pmu_name = { 129358 /* 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 = { 127342 /* hisi_sccl,l3c\000 */ },
+ .pmu_name = { 129721 /* 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 = { 127064 /* uncore_cbox\000 */ },
+ .pmu_name = { 129443 /* uncore_cbox\000 */ },
},
{
.entries = pmu_events__test_soc_cpu_uncore_imc,
.num_entries = ARRAY_SIZE(pmu_events__test_soc_cpu_uncore_imc),
- .pmu_name = { 127528 /* uncore_imc\000 */ },
+ .pmu_name = { 129907 /* 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 = { 127424 /* uncore_imc_free_running\000 */ },
+ .pmu_name = { 129803 /* uncore_imc_free_running\000 */ },
},
};
static const struct compact_pmu_event pmu_metrics__test_soc_cpu_default_core[] = {
/* CPI\000\0001 / IPC\000\000\000\000\000\000\000\000000 */
- { 130910 },
+ { 133289 },
/* DCache_L2_All\000\000DCache_L2_All_Hits + DCache_L2_All_Miss\000\000\000\000\000... */
- { 131599 },
+ { 133978 },
/* DCache_L2_All_Hits\000\000l2_rqsts.demand_data_rd_hit + l2_rqsts.pf_hit + l2_rqs... */
- { 131369 },
+ { 133748 },
/* DCache_L2_All_Miss\000\000max(l2_rqsts.all_demand_data_rd - l2_rqsts.demand_data... */
- { 131464 },
+ { 133843 },
/* DCache_L2_Hits\000\000d_ratio(DCache_L2_All_Hits, DCache_L2_All)\000\000\000\000... */
- { 131664 },
+ { 134043 },
/* DCache_L2_Misses\000\000d_ratio(DCache_L2_All_Miss, DCache_L2_All)\000\000\000\0... */
- { 131733 },
+ { 134112 },
/* Frontend_Bound_SMT\000\000idq_uops_not_delivered.core / (4 * (cpu_clk_unhalted.t... */
- { 130997 },
+ { 133376 },
/* IPC\000group1\000inst_retired.any / cpu_clk_unhalted.thread\000\000\000\000\000\... */
- { 130933 },
+ { 133312 },
/* L1D_Cache_Fill_BW\000\00064 * l1d.replacement / 1e9 / duration_time\000\000\000\... */
- { 131871 },
+ { 134250 },
/* M1\000\000ipc + M2\000\000\000\000\000\000\000\000000 */
- { 131804 },
+ { 134183 },
/* M2\000\000ipc + M1\000\000\000\000\000\000\000\000000 */
- { 131827 },
+ { 134206 },
/* M3\000\0001 / M3\000\000\000\000\000\000\000\000000 */
- { 131850 },
+ { 134229 },
/* cache_miss_cycles\000group1\000dcache_miss_cpi + icache_miss_cycles\000\000\000\... */
- { 131297 },
+ { 133676 },
/* dcache_miss_cpi\000\000l1d\\-loads\\-misses / inst_retired.any\000\000\000\000\0... */
- { 131164 },
+ { 133543 },
/* icache_miss_cycles\000\000l1i\\-loads\\-misses / inst_retired.any\000\000\000\00... */
- { 131229 },
+ { 133608 },
};
@@ -5364,15 +5468,15 @@ static const struct pmu_table_entry pmu_metrics__test_soc_cpu[] = {
static const struct compact_pmu_event pmu_events__test_soc_sys_uncore_sys_ccn_pmu[] = {
/* sys_ccn_pmu.read_cycles\000uncore\000ccn read-cycles event\000config=0x2c\0000x0... */
- { 127718 },
+ { 130097 },
};
static const struct compact_pmu_event pmu_events__test_soc_sys_uncore_sys_cmn_pmu[] = {
/* sys_cmn_pmu.hnf_cache_miss\000uncore\000Counts total cache misses in first looku... */
- { 127814 },
+ { 130193 },
};
static const struct compact_pmu_event pmu_events__test_soc_sys_uncore_sys_ddr_pmu[] = {
/* sys_ddr_pmu.write_cycles\000uncore\000ddr write-cycles event\000event=0x2b\000v8... */
- { 127623 },
+ { 130002 },
};
@@ -5380,17 +5484,17 @@ static 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 = { 127699 /* uncore_sys_ccn_pmu\000 */ },
+ .pmu_name = { 130078 /* 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 = { 127795 /* uncore_sys_cmn_pmu\000 */ },
+ .pmu_name = { 130174 /* 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 = { 127604 /* uncore_sys_ddr_pmu\000 */ },
+ .pmu_name = { 129983 /* uncore_sys_ddr_pmu\000 */ },
},
};
diff --git a/tools/perf/util/tool_pmu.c b/tools/perf/util/tool_pmu.c
index d2f7591747d9..0ae08cd910bc 100644
--- a/tools/perf/util/tool_pmu.c
+++ b/tools/perf/util/tool_pmu.c
@@ -12,10 +12,17 @@
#include "tsc.h"
#include <api/fs/fs.h>
#include <api/io.h>
+#include <api/io_dir.h>
#include <internal/threadmap.h>
#include <perf/threadmap.h>
+#include <ctype.h>
+#include <errno.h>
#include <fcntl.h>
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
#include <strings.h>
+#include <unistd.h>
#define INVALID_START_TIME ~0ULL
@@ -35,6 +42,32 @@ static const char *const tool_pmu__event_names[TOOL_PMU__EVENT_MAX] = {
"system_tsc_freq",
"core_wide",
"target_cpu",
+ "memory_anon_huge_pages",
+ "memory_anonymous",
+ "memory_data",
+ "memory_file_pmd_mapped",
+ "memory_ksm",
+ "memory_lazyfree",
+ "memory_locked",
+ "memory_private_clean",
+ "memory_private_dirty",
+ "memory_private_hugetlb",
+ "memory_pss",
+ "memory_pss_anon",
+ "memory_pss_dirty",
+ "memory_pss_file",
+ "memory_pss_shmem",
+ "memory_referenced",
+ "memory_rss",
+ "memory_shared_clean",
+ "memory_shared_dirty",
+ "memory_shared_hugetlb",
+ "memory_shmem_pmd_mapped",
+ "memory_size",
+ "memory_swap",
+ "memory_swap_pss",
+ "memory_text",
+ "memory_uss",
};
bool tool_pmu__skip_event(const char *name __maybe_unused)
@@ -203,6 +236,205 @@ static int read_pid_stat_field(int fd, int field, __u64 *val)
return -EINVAL;
}
+static bool tool_pmu__is_memory_event(enum tool_pmu_event ev)
+{
+ return ev >= TOOL_PMU__EVENT_MEMORY_ANON_HUGE_PAGES &&
+ ev <= TOOL_PMU__EVENT_MEMORY_USS;
+}
+
+static const char *tool_pmu__memory_event_to_key(enum tool_pmu_event ev)
+{
+ switch (ev) {
+ case TOOL_PMU__EVENT_MEMORY_ANON_HUGE_PAGES: return "AnonHugePages:";
+ case TOOL_PMU__EVENT_MEMORY_ANONYMOUS: return "Anonymous:";
+ case TOOL_PMU__EVENT_MEMORY_FILE_PMD_MAPPED: return "FilePmdMapped:";
+ case TOOL_PMU__EVENT_MEMORY_KSM: return "KSM:";
+ case TOOL_PMU__EVENT_MEMORY_LAZYFREE: return "LazyFree:";
+ case TOOL_PMU__EVENT_MEMORY_LOCKED: return "Locked:";
+ case TOOL_PMU__EVENT_MEMORY_PRIVATE_CLEAN: return "Private_Clean:";
+ case TOOL_PMU__EVENT_MEMORY_PRIVATE_DIRTY: return "Private_Dirty:";
+ case TOOL_PMU__EVENT_MEMORY_PRIVATE_HUGETLB: return "Private_Hugetlb:";
+ case TOOL_PMU__EVENT_MEMORY_PSS: return "Pss:";
+ case TOOL_PMU__EVENT_MEMORY_PSS_ANON: return "Pss_Anon:";
+ case TOOL_PMU__EVENT_MEMORY_PSS_DIRTY: return "Pss_Dirty:";
+ case TOOL_PMU__EVENT_MEMORY_PSS_FILE: return "Pss_File:";
+ case TOOL_PMU__EVENT_MEMORY_PSS_SHMEM: return "Pss_Shmem:";
+ case TOOL_PMU__EVENT_MEMORY_REFERENCED: return "Referenced:";
+ case TOOL_PMU__EVENT_MEMORY_RSS: return "Rss:";
+ case TOOL_PMU__EVENT_MEMORY_SHARED_CLEAN: return "Shared_Clean:";
+ case TOOL_PMU__EVENT_MEMORY_SHARED_DIRTY: return "Shared_Dirty:";
+ case TOOL_PMU__EVENT_MEMORY_SHARED_HUGETLB: return "Shared_Hugetlb:";
+ case TOOL_PMU__EVENT_MEMORY_SHMEM_PMD_MAPPED: return "ShmemPmdMapped:";
+ case TOOL_PMU__EVENT_MEMORY_SWAP: return "Swap:";
+ case TOOL_PMU__EVENT_MEMORY_SWAP_PSS: return "SwapPss:";
+ case TOOL_PMU__EVENT_MEMORY_DATA:
+ case TOOL_PMU__EVENT_MEMORY_SIZE:
+ case TOOL_PMU__EVENT_MEMORY_TEXT:
+ case TOOL_PMU__EVENT_MEMORY_USS:
+ case TOOL_PMU__EVENT_DURATION_TIME:
+ case TOOL_PMU__EVENT_USER_TIME:
+ case TOOL_PMU__EVENT_SYSTEM_TIME:
+ case TOOL_PMU__EVENT_HAS_PMEM:
+ case TOOL_PMU__EVENT_NUM_CORES:
+ case TOOL_PMU__EVENT_NUM_CPUS:
+ case TOOL_PMU__EVENT_NUM_CPUS_ONLINE:
+ case TOOL_PMU__EVENT_NUM_DIES:
+ case TOOL_PMU__EVENT_NUM_PACKAGES:
+ case TOOL_PMU__EVENT_SLOTS:
+ case TOOL_PMU__EVENT_SMT_ON:
+ case TOOL_PMU__EVENT_SYSTEM_TSC_FREQ:
+ case TOOL_PMU__EVENT_CORE_WIDE:
+ case TOOL_PMU__EVENT_TARGET_CPU:
+ case TOOL_PMU__EVENT_NONE:
+ case TOOL_PMU__EVENT_MAX:
+ default: return NULL;
+ }
+}
+
+static int read_proc_status_u64(struct io *io, const char *key, u64 *val)
+{
+ int ch;
+
+ while ((ch = io__get_char(io)) != -1) {
+ /* Check if line starts with key */
+ if (ch == key[0]) {
+ const char *k = key + 1;
+
+ while (*k && (ch = io__get_char(io)) == *k)
+ k++;
+
+ if (!*k) {
+ /* Found key, skip whitespace */
+ while ((ch = io__get_char(io)) == ' ' || ch == '\t')
+ ;
+ /* Read value */
+ if (ch >= '0' && ch <= '9') {
+ *val = ch - '0';
+ while ((ch = io__get_char(io)) >= '0' && ch <= '9')
+ *val = *val * 10 + (ch - '0');
+ if (ch != '\n' && ch != -1)
+ read_until_char(io, '\n');
+ return 0;
+ }
+ }
+ }
+ /* Skip rest of line */
+ if (ch != '\n' && ch != -1)
+ read_until_char(io, '\n');
+ }
+ return -EINVAL;
+}
+
+static int read_pid_tgid(int dir_fd, int *tgid)
+{
+ char buf[1024];
+ struct io io;
+ u64 val;
+ int fd, ret;
+
+ fd = openat(dir_fd, "status", O_RDONLY);
+ if (fd < 0)
+ return -errno;
+
+ io__init(&io, fd, buf, sizeof(buf));
+ ret = read_proc_status_u64(&io, "Tgid:", &val);
+ close(fd);
+ if (!ret)
+ *tgid = (int)val;
+ return ret;
+}
+
+static int read_smaps_rollup_field(struct io *io, const char *key, u64 *val)
+{
+ int ret = read_proc_status_u64(io, key, val);
+
+ if (!ret)
+ *val *= 1024; /* Convert kB to bytes */
+ return ret;
+}
+
+static int read_smaps_rollup(int fd, enum tool_pmu_event ev, u64 *val)
+{
+ char buf[4096];
+ struct io io;
+
+ lseek(fd, 0, SEEK_SET);
+ io__init(&io, fd, buf, sizeof(buf));
+
+ if (ev == TOOL_PMU__EVENT_MEMORY_USS) {
+ u64 pc, pd;
+ int ret;
+
+ ret = read_smaps_rollup_field(&io, "Private_Clean:", &pc);
+ if (ret)
+ return ret;
+ ret = read_smaps_rollup_field(&io, "Private_Dirty:", &pd);
+ if (ret) {
+ lseek(fd, 0, SEEK_SET);
+ io__init(&io, fd, buf, sizeof(buf));
+ ret = read_smaps_rollup_field(&io, "Private_Dirty:", &pd);
+ if (ret)
+ return ret;
+ }
+ *val = pc + pd;
+ return 0;
+ }
+
+ return read_smaps_rollup_field(&io, tool_pmu__memory_event_to_key(ev), val);
+}
+
+static int read_statm(int fd, enum tool_pmu_event ev, u64 *val)
+{
+ long page_sz = sysconf(_SC_PAGE_SIZE);
+ char buf[128];
+ struct io io;
+ __u64 v;
+
+ if (page_sz <= 0)
+ return -EINVAL;
+
+ io__init(&io, fd, buf, sizeof(buf));
+ lseek(fd, 0, SEEK_SET);
+
+ /* Size */
+ if (io__get_dec(&io, &v) != ' ')
+ return -EINVAL;
+ if (ev == TOOL_PMU__EVENT_MEMORY_SIZE) {
+ *val = v * page_sz;
+ return 0;
+ }
+
+ /* Resident */
+ if (io__get_dec(&io, &v) != ' ') /* Skip */
+ return -EINVAL;
+
+ /* Shared */
+ if (io__get_dec(&io, &v) != ' ') /* Skip */
+ return -EINVAL;
+
+ /* Text */
+ if (io__get_dec(&io, &v) != ' ')
+ return -EINVAL;
+ if (ev == TOOL_PMU__EVENT_MEMORY_TEXT) {
+ *val = v * page_sz;
+ return 0;
+ }
+
+ /* Lib */
+ if (io__get_dec(&io, &v) != ' ') /* Skip */
+ return -EINVAL;
+
+ /* Data */
+ if (io__get_dec(&io, &v) < 0)
+ return -EINVAL;
+ if (ev == TOOL_PMU__EVENT_MEMORY_DATA) {
+ *val = v * page_sz;
+ return 0;
+ }
+
+ return -EINVAL;
+}
+
int evsel__tool_pmu_prepare_open(struct evsel *evsel,
struct perf_cpu_map *cpus,
int nthreads)
@@ -258,19 +490,138 @@ static int tool_pmu__read_stat(struct evsel *evsel, int cpu_map_idx, int thread,
return err;
}
+static int open_memory_pid_dir(enum tool_pmu_event ev, int pid,
+ int *seen_tgids, int *nr_seen_tgids, int *out_fd)
+{
+ const char *file = "smaps_rollup";
+ int dir_fd, test_fd, tgid = -1;
+ char buf[PATH_MAX];
+
+ *out_fd = -1;
+ snprintf(buf, sizeof(buf), "%s/%d", procfs__mountpoint(), pid);
+ dir_fd = open(buf, O_RDONLY | O_DIRECTORY);
+ if (dir_fd < 0)
+ return -errno;
+
+ if (seen_tgids) {
+ int err = read_pid_tgid(dir_fd, &tgid);
+
+ if (err) {
+ close(dir_fd);
+ return err;
+ }
+ for (int i = 0; i < *nr_seen_tgids; i++) {
+ if (seen_tgids[i] == tgid) {
+ close(dir_fd);
+ return 0;
+ }
+ }
+ }
+
+ if (ev == TOOL_PMU__EVENT_MEMORY_SIZE ||
+ ev == TOOL_PMU__EVENT_MEMORY_DATA ||
+ ev == TOOL_PMU__EVENT_MEMORY_TEXT)
+ file = "statm";
+
+ test_fd = openat(dir_fd, file, O_RDONLY);
+ if (test_fd < 0) {
+ int err = -errno;
+
+ close(dir_fd);
+ return err;
+ }
+ close(test_fd);
+
+ if (seen_tgids)
+ seen_tgids[(*nr_seen_tgids)++] = tgid;
+
+ *out_fd = dir_fd;
+ return 0;
+}
+
+static int evsel__tool_pmu_open_one(struct evsel *evsel, enum tool_pmu_event ev,
+ int pid, int idx, int thread,
+ int *seen_tgids, int *nr_seen_tgids)
+{
+ if (ev == TOOL_PMU__EVENT_USER_TIME || ev == TOOL_PMU__EVENT_SYSTEM_TIME) {
+ __u64 *start_time = NULL;
+ __u64 *accumulated_time = NULL;
+ char buf[PATH_MAX];
+ int fd, err;
+
+ if (pid > -1) {
+ snprintf(buf, sizeof(buf), "%s/%d/stat", procfs__mountpoint(), pid);
+ evsel->pid_stat = true;
+ } else {
+ snprintf(buf, sizeof(buf), "%s/stat", procfs__mountpoint());
+ }
+ fd = open(buf, O_RDONLY);
+ FD(evsel, idx, thread) = fd;
+ if (fd < 0)
+ return -errno;
+
+ start_time = xyarray__entry(evsel->process_time.start_times, idx, thread);
+ accumulated_time = xyarray__entry(evsel->process_time.accumulated_times,
+ idx, thread);
+ *accumulated_time = 0;
+
+ if (evsel->core.attr.disabled) {
+ evsel->disabled = true;
+ *start_time = INVALID_START_TIME;
+ } else {
+ evsel->disabled = false;
+ err = tool_pmu__read_stat(evsel, idx, thread, start_time);
+ if (err) {
+ close(fd);
+ FD(evsel, idx, thread) = -1;
+ return err;
+ }
+ }
+ } else if (tool_pmu__is_memory_event(ev)) {
+ int fd = -1;
+
+ if (evsel->cgrp)
+ return -EINVAL;
+
+ evsel->disabled = evsel->core.attr.disabled;
+ if (pid > -1) {
+ evsel->pid_stat = true;
+ if (idx == 0) {
+ int err = open_memory_pid_dir(ev, pid, seen_tgids,
+ nr_seen_tgids, &fd);
+
+ if (err)
+ return err;
+ }
+ }
+ /*
+ * For per-process, FD holds /proc/<pid> directory fd so
+ * smaps_rollup/statm are opened on read (avoiding caching a
+ * pre-exec mm_struct), or -1 for deduplicated sibling threads.
+ * For system-wide (pid == -1), we aggregate in read().
+ */
+ FD(evsel, idx, thread) = fd;
+ }
+ return 0;
+}
+
int evsel__tool_pmu_open(struct evsel *evsel,
struct perf_thread_map *threads,
int start_cpu_map_idx, int end_cpu_map_idx)
{
enum tool_pmu_event ev = evsel__tool_event(evsel);
- int pid = -1, idx = 0, thread = 0, nthreads, err = 0, old_errno;
+ int pid = -1, idx = 0, thread = 0, nthreads, err = 0;
+ int *seen_tgids = NULL, nr_seen_tgids = 0;
+
+ if (evsel->core.attr.sample_period) { /* no sampling */
+ errno = EINVAL;
+ return -EINVAL;
+ }
if (ev == TOOL_PMU__EVENT_NUM_CPUS)
return 0;
if (ev == TOOL_PMU__EVENT_DURATION_TIME) {
- if (evsel->core.attr.sample_period) /* no sampling */
- return -EINVAL;
evsel->duration_time.accumulated_time = 0;
if (evsel->core.attr.disabled) {
evsel->disabled = true;
@@ -286,62 +637,33 @@ int evsel__tool_pmu_open(struct evsel *evsel,
pid = evsel->cgrp->fd;
nthreads = perf_thread_map__nr(threads);
+ if (tool_pmu__is_memory_event(ev) && !evsel->cgrp && !evsel->core.system_wide &&
+ nthreads > 1 && start_cpu_map_idx == 0 && end_cpu_map_idx > 0) {
+ seen_tgids = calloc(nthreads, sizeof(*seen_tgids));
+ if (!seen_tgids) {
+ errno = ENOMEM;
+ return -ENOMEM;
+ }
+ }
+
for (idx = start_cpu_map_idx; idx < end_cpu_map_idx; idx++) {
for (thread = 0; thread < nthreads; thread++) {
if (!evsel->cgrp && !evsel->core.system_wide)
pid = perf_thread_map__pid(threads, thread);
- if (ev == TOOL_PMU__EVENT_USER_TIME || ev == TOOL_PMU__EVENT_SYSTEM_TIME) {
- __u64 *start_time = NULL;
- __u64 *accumulated_time = NULL;
- int fd;
-
- if (evsel->core.attr.sample_period) {
- /* no sampling */
- err = -EINVAL;
- goto out_close;
- }
- if (pid > -1) {
- char buf[64];
-
- snprintf(buf, sizeof(buf), "/proc/%d/stat", pid);
- fd = open(buf, O_RDONLY);
- evsel->pid_stat = true;
- } else {
- fd = open("/proc/stat", O_RDONLY);
- }
- FD(evsel, idx, thread) = fd;
- if (fd < 0) {
- err = -errno;
- goto out_close;
- }
- start_time = xyarray__entry(evsel->process_time.start_times, idx,
- thread);
- accumulated_time = xyarray__entry(
- evsel->process_time.accumulated_times, idx, thread);
- *accumulated_time = 0;
-
- if (evsel->core.attr.disabled) {
- evsel->disabled = true;
- *start_time = INVALID_START_TIME;
- } else {
- evsel->disabled = false;
- err = tool_pmu__read_stat(evsel, idx, thread, start_time);
- if (err) {
- close(fd);
- FD(evsel, idx, thread) = -1;
- goto out_close;
- }
- }
- }
+ err = evsel__tool_pmu_open_one(evsel, ev, pid, idx, thread,
+ seen_tgids, &nr_seen_tgids);
+ if (err)
+ goto out_close;
}
}
+ free(seen_tgids);
return 0;
out_close:
+ free(seen_tgids);
if (err)
threads->err_thread = thread;
- old_errno = errno;
do {
while (--thread >= 0) {
if (FD(evsel, idx, thread) >= 0)
@@ -350,7 +672,7 @@ int evsel__tool_pmu_open(struct evsel *evsel,
}
thread = nthreads;
} while (--idx >= start_cpu_map_idx);
- errno = old_errno;
+ errno = -err;
return err;
}
@@ -486,6 +808,32 @@ bool tool_pmu__read_event(enum tool_pmu_event ev,
*result = system_wide || (user_requested_cpu_list != NULL) ? 1 : 0;
return true;
+ case TOOL_PMU__EVENT_MEMORY_SIZE:
+ case TOOL_PMU__EVENT_MEMORY_RSS:
+ case TOOL_PMU__EVENT_MEMORY_PSS:
+ case TOOL_PMU__EVENT_MEMORY_SHARED_CLEAN:
+ case TOOL_PMU__EVENT_MEMORY_SHARED_DIRTY:
+ case TOOL_PMU__EVENT_MEMORY_PRIVATE_CLEAN:
+ case TOOL_PMU__EVENT_MEMORY_PRIVATE_DIRTY:
+ case TOOL_PMU__EVENT_MEMORY_USS:
+ case TOOL_PMU__EVENT_MEMORY_SWAP:
+ case TOOL_PMU__EVENT_MEMORY_SWAP_PSS:
+ case TOOL_PMU__EVENT_MEMORY_PSS_DIRTY:
+ case TOOL_PMU__EVENT_MEMORY_PSS_ANON:
+ case TOOL_PMU__EVENT_MEMORY_PSS_FILE:
+ case TOOL_PMU__EVENT_MEMORY_PSS_SHMEM:
+ case TOOL_PMU__EVENT_MEMORY_REFERENCED:
+ case TOOL_PMU__EVENT_MEMORY_ANONYMOUS:
+ case TOOL_PMU__EVENT_MEMORY_KSM:
+ case TOOL_PMU__EVENT_MEMORY_LAZYFREE:
+ case TOOL_PMU__EVENT_MEMORY_ANON_HUGE_PAGES:
+ case TOOL_PMU__EVENT_MEMORY_SHMEM_PMD_MAPPED:
+ case TOOL_PMU__EVENT_MEMORY_FILE_PMD_MAPPED:
+ case TOOL_PMU__EVENT_MEMORY_SHARED_HUGETLB:
+ case TOOL_PMU__EVENT_MEMORY_PRIVATE_HUGETLB:
+ case TOOL_PMU__EVENT_MEMORY_LOCKED:
+ case TOOL_PMU__EVENT_MEMORY_DATA:
+ case TOOL_PMU__EVENT_MEMORY_TEXT:
case TOOL_PMU__EVENT_NONE:
case TOOL_PMU__EVENT_DURATION_TIME:
case TOOL_PMU__EVENT_USER_TIME:
@@ -517,6 +865,55 @@ static void perf_counts__update(struct perf_counts_values *count,
count->lost = 0;
}
}
+
+static int tool_pmu__aggregate_memory_event(enum tool_pmu_event ev, u64 *val)
+{
+ struct io_dir iod;
+ struct io_dirent64 *ent;
+ char buf[PATH_MAX];
+ int fd, proc_fd;
+ u64 pid_val;
+
+ *val = 0;
+ proc_fd = open(procfs__mountpoint(), O_DIRECTORY | O_RDONLY);
+ if (proc_fd < 0)
+ return -errno;
+
+ io_dir__init(&iod, proc_fd);
+
+ while ((ent = io_dir__readdir(&iod)) != NULL) {
+ if (!isdigit((unsigned char)ent->d_name[0]))
+ continue;
+
+ if (!io_dir__is_dir(&iod, ent))
+ continue;
+
+ if (ev == TOOL_PMU__EVENT_MEMORY_SIZE ||
+ ev == TOOL_PMU__EVENT_MEMORY_DATA ||
+ ev == TOOL_PMU__EVENT_MEMORY_TEXT)
+ snprintf(buf, sizeof(buf), "%s/statm", ent->d_name);
+ else
+ snprintf(buf, sizeof(buf), "%s/smaps_rollup", ent->d_name);
+
+ fd = openat(proc_fd, buf, O_RDONLY);
+ if (fd < 0)
+ continue;
+
+ if (ev == TOOL_PMU__EVENT_MEMORY_SIZE ||
+ ev == TOOL_PMU__EVENT_MEMORY_DATA ||
+ ev == TOOL_PMU__EVENT_MEMORY_TEXT) {
+ if (!read_statm(fd, ev, &pid_val))
+ *val += pid_val;
+ } else {
+ if (!read_smaps_rollup(fd, ev, &pid_val))
+ *val += pid_val;
+ }
+ close(fd);
+ }
+ close(proc_fd);
+ return 0;
+}
+
int evsel__tool_pmu_enable_cpu(struct evsel *evsel, int cpu_map_idx)
{
enum tool_pmu_event ev = evsel__tool_event(evsel);
@@ -690,6 +1087,65 @@ int evsel__tool_pmu_read(struct evsel *evsel, int cpu_map_idx, int thread)
adjust = true;
break;
}
+ case TOOL_PMU__EVENT_MEMORY_SIZE:
+ case TOOL_PMU__EVENT_MEMORY_RSS:
+ case TOOL_PMU__EVENT_MEMORY_PSS:
+ case TOOL_PMU__EVENT_MEMORY_SHARED_CLEAN:
+ case TOOL_PMU__EVENT_MEMORY_SHARED_DIRTY:
+ case TOOL_PMU__EVENT_MEMORY_PRIVATE_CLEAN:
+ case TOOL_PMU__EVENT_MEMORY_PRIVATE_DIRTY:
+ case TOOL_PMU__EVENT_MEMORY_USS:
+ case TOOL_PMU__EVENT_MEMORY_SWAP:
+ case TOOL_PMU__EVENT_MEMORY_SWAP_PSS:
+ case TOOL_PMU__EVENT_MEMORY_PSS_DIRTY:
+ case TOOL_PMU__EVENT_MEMORY_PSS_ANON:
+ case TOOL_PMU__EVENT_MEMORY_PSS_FILE:
+ case TOOL_PMU__EVENT_MEMORY_PSS_SHMEM:
+ case TOOL_PMU__EVENT_MEMORY_REFERENCED:
+ case TOOL_PMU__EVENT_MEMORY_ANONYMOUS:
+ case TOOL_PMU__EVENT_MEMORY_KSM:
+ case TOOL_PMU__EVENT_MEMORY_LAZYFREE:
+ case TOOL_PMU__EVENT_MEMORY_ANON_HUGE_PAGES:
+ case TOOL_PMU__EVENT_MEMORY_SHMEM_PMD_MAPPED:
+ case TOOL_PMU__EVENT_MEMORY_FILE_PMD_MAPPED:
+ case TOOL_PMU__EVENT_MEMORY_SHARED_HUGETLB:
+ case TOOL_PMU__EVENT_MEMORY_PRIVATE_HUGETLB:
+ case TOOL_PMU__EVENT_MEMORY_LOCKED:
+ case TOOL_PMU__EVENT_MEMORY_DATA:
+ case TOOL_PMU__EVENT_MEMORY_TEXT: {
+ u64 val = 0;
+
+ if (evsel->pid_stat) {
+ if (cpu_map_idx == 0) {
+ int dir_fd = FD(evsel, 0, thread);
+
+ if (dir_fd >= 0) {
+ bool is_statm = ev == TOOL_PMU__EVENT_MEMORY_SIZE ||
+ ev == TOOL_PMU__EVENT_MEMORY_DATA ||
+ ev == TOOL_PMU__EVENT_MEMORY_TEXT;
+ int fd = openat(dir_fd,
+ is_statm ? "statm" : "smaps_rollup",
+ O_RDONLY);
+ int ret;
+
+ if (fd < 0)
+ return -errno;
+ ret = is_statm ? read_statm(fd, ev, &val)
+ : read_smaps_rollup(fd, ev, &val);
+ close(fd);
+ if (ret)
+ return ret;
+ }
+ }
+ } else if (cpu_map_idx == 0 && thread == 0) {
+ int ret = tool_pmu__aggregate_memory_event(ev, &val);
+
+ if (ret)
+ return ret;
+ }
+ perf_counts__update(count, old_count, /*raw=*/false, val);
+ return 0;
+ }
case TOOL_PMU__EVENT_NONE:
case TOOL_PMU__EVENT_MAX:
default:
diff --git a/tools/perf/util/tool_pmu.h b/tools/perf/util/tool_pmu.h
index f66d24cf3502..99a2ea1548f8 100644
--- a/tools/perf/util/tool_pmu.h
+++ b/tools/perf/util/tool_pmu.h
@@ -24,6 +24,32 @@ enum tool_pmu_event {
TOOL_PMU__EVENT_SYSTEM_TSC_FREQ,
TOOL_PMU__EVENT_CORE_WIDE,
TOOL_PMU__EVENT_TARGET_CPU,
+ TOOL_PMU__EVENT_MEMORY_ANON_HUGE_PAGES,
+ TOOL_PMU__EVENT_MEMORY_ANONYMOUS,
+ TOOL_PMU__EVENT_MEMORY_DATA,
+ TOOL_PMU__EVENT_MEMORY_FILE_PMD_MAPPED,
+ TOOL_PMU__EVENT_MEMORY_KSM,
+ TOOL_PMU__EVENT_MEMORY_LAZYFREE,
+ TOOL_PMU__EVENT_MEMORY_LOCKED,
+ TOOL_PMU__EVENT_MEMORY_PRIVATE_CLEAN,
+ TOOL_PMU__EVENT_MEMORY_PRIVATE_DIRTY,
+ TOOL_PMU__EVENT_MEMORY_PRIVATE_HUGETLB,
+ TOOL_PMU__EVENT_MEMORY_PSS,
+ TOOL_PMU__EVENT_MEMORY_PSS_ANON,
+ TOOL_PMU__EVENT_MEMORY_PSS_DIRTY,
+ TOOL_PMU__EVENT_MEMORY_PSS_FILE,
+ TOOL_PMU__EVENT_MEMORY_PSS_SHMEM,
+ TOOL_PMU__EVENT_MEMORY_REFERENCED,
+ TOOL_PMU__EVENT_MEMORY_RSS,
+ TOOL_PMU__EVENT_MEMORY_SHARED_CLEAN,
+ TOOL_PMU__EVENT_MEMORY_SHARED_DIRTY,
+ TOOL_PMU__EVENT_MEMORY_SHARED_HUGETLB,
+ TOOL_PMU__EVENT_MEMORY_SHMEM_PMD_MAPPED,
+ TOOL_PMU__EVENT_MEMORY_SIZE,
+ TOOL_PMU__EVENT_MEMORY_SWAP,
+ TOOL_PMU__EVENT_MEMORY_SWAP_PSS,
+ TOOL_PMU__EVENT_MEMORY_TEXT,
+ TOOL_PMU__EVENT_MEMORY_USS,
TOOL_PMU__EVENT_MAX,
};
--
2.56.1.703.gf848ed807c-goog
^ permalink raw reply [flat|nested] 5+ messages in thread* [PATCH v2 2/4] perf tool_pmu: Add network events
2026-11-13 23:37 [PATCH v2 0/4] perf tool_pmu: Add procfs memory, network and schedstat events Ian Rogers
2026-11-13 23:37 ` [PATCH v2 1/4] perf tool_pmu: Add memory events Ian Rogers
@ 2026-11-13 23:37 ` Ian Rogers
2026-11-13 23:37 ` [PATCH v2 3/4] perf tool_pmu: Add schedstat events Ian Rogers
2026-11-13 23:37 ` [PATCH v2 4/4] perf test tool_pmu: Add memory, network and schedstat tests Ian Rogers
3 siblings, 0 replies; 5+ messages in thread
From: Ian Rogers @ 2026-11-13 23:37 UTC (permalink / raw)
To: Peter Zijlstra, Ingo Molnar, Arnaldo Carvalho de Melo,
Namhyung Kim, Jiri Olsa, Ian Rogers, Adrian Hunter, James Clark,
Thomas Falcon, Thomas Richter, linux-perf-users, linux-kernel
Cc: Andi Kleen
Add system-wide tool PMU events to report network statistics from
/proc/net/dev. Since /proc/pid/net/dev reports statistics for the entire
network namespace rather than an individual process, reject opening
these events in per-process or cgroup mode.
The following events are added for both RX (receive) and TX (transmit):
- bytes
- packets
- errors
- drop
- fifo
- frame (RX only) / colls (TX only)
- compressed
- multicast (RX only) / carrier (TX only)
Track initial and accumulated values across enable/disable transitions so
perf stat reports deltas over the measurement period rather than
cumulative totals since boot. Also honor the group leader's
attr.disabled state when opening grouped tool events and map CPU indices
safely in evsel__enable_cpu(), evsel__disable_cpu(), and tool_pmu xyarray
lookups when single-CPU tool events are grouped with per-CPU events.
Example output:
$ perf stat -a -e net_rx_bytes,net_rx_packets,net_tx_bytes \
-e net_tx_packets -- sleep 0.02
Performance counter stats for 'system wide':
16,971 net_rx_bytes
10 net_rx_packets
17,214 net_tx_bytes
10 net_tx_packets
0.017721776 seconds time elapsed
Signed-off-by: Ian Rogers <irogers@google.com>
---
.../pmu-events/arch/common/common/tool.json | 96 ++++++
tools/perf/pmu-events/empty-pmu-events.c | 286 +++++++++++-------
tools/perf/util/evsel.c | 53 +++-
tools/perf/util/tool_pmu.c | 263 ++++++++++++++--
tools/perf/util/tool_pmu.h | 17 ++
5 files changed, 571 insertions(+), 144 deletions(-)
diff --git a/tools/perf/pmu-events/arch/common/common/tool.json b/tools/perf/pmu-events/arch/common/common/tool.json
index 9e0e89553847..a332cbf842f7 100644
--- a/tools/perf/pmu-events/arch/common/common/tool.json
+++ b/tools/perf/pmu-events/arch/common/common/tool.json
@@ -238,5 +238,101 @@
"EventName": "memory_uss",
"BriefDescription": "Unique Set Size (USS) in bytes",
"ConfigCode": "40"
+ },
+ {
+ "Unit": "tool",
+ "EventName": "net_rx_bytes",
+ "BriefDescription": "System-wide network received bytes",
+ "ConfigCode": "41"
+ },
+ {
+ "Unit": "tool",
+ "EventName": "net_rx_packets",
+ "BriefDescription": "System-wide network received packets",
+ "ConfigCode": "42"
+ },
+ {
+ "Unit": "tool",
+ "EventName": "net_rx_errors",
+ "BriefDescription": "System-wide network received errors",
+ "ConfigCode": "43"
+ },
+ {
+ "Unit": "tool",
+ "EventName": "net_rx_drop",
+ "BriefDescription": "System-wide network received dropped packets",
+ "ConfigCode": "44"
+ },
+ {
+ "Unit": "tool",
+ "EventName": "net_rx_fifo",
+ "BriefDescription": "System-wide network received fifo overruns",
+ "ConfigCode": "45"
+ },
+ {
+ "Unit": "tool",
+ "EventName": "net_rx_frame",
+ "BriefDescription": "System-wide network received framing errors",
+ "ConfigCode": "46"
+ },
+ {
+ "Unit": "tool",
+ "EventName": "net_rx_compressed",
+ "BriefDescription": "System-wide network received compressed packets",
+ "ConfigCode": "47"
+ },
+ {
+ "Unit": "tool",
+ "EventName": "net_rx_multicast",
+ "BriefDescription": "System-wide network received multicast packets",
+ "ConfigCode": "48"
+ },
+ {
+ "Unit": "tool",
+ "EventName": "net_tx_bytes",
+ "BriefDescription": "System-wide network transmitted bytes",
+ "ConfigCode": "49"
+ },
+ {
+ "Unit": "tool",
+ "EventName": "net_tx_packets",
+ "BriefDescription": "System-wide network transmitted packets",
+ "ConfigCode": "50"
+ },
+ {
+ "Unit": "tool",
+ "EventName": "net_tx_errors",
+ "BriefDescription": "System-wide network transmitted errors",
+ "ConfigCode": "51"
+ },
+ {
+ "Unit": "tool",
+ "EventName": "net_tx_drop",
+ "BriefDescription": "System-wide network transmitted dropped packets",
+ "ConfigCode": "52"
+ },
+ {
+ "Unit": "tool",
+ "EventName": "net_tx_fifo",
+ "BriefDescription": "System-wide network transmitted fifo overruns",
+ "ConfigCode": "53"
+ },
+ {
+ "Unit": "tool",
+ "EventName": "net_tx_colls",
+ "BriefDescription": "System-wide network transmitted collisions",
+ "ConfigCode": "54"
+ },
+ {
+ "Unit": "tool",
+ "EventName": "net_tx_carrier",
+ "BriefDescription": "System-wide network transmitted carrier losses",
+ "ConfigCode": "55"
+ },
+ {
+ "Unit": "tool",
+ "EventName": "net_tx_compressed",
+ "BriefDescription": "System-wide network transmitted compressed packets",
+ "ConfigCode": "56"
}
]
diff --git a/tools/perf/pmu-events/empty-pmu-events.c b/tools/perf/pmu-events/empty-pmu-events.c
index 8d1b9e9b4f58..8705f32563a6 100644
--- a/tools/perf/pmu-events/empty-pmu-events.c
+++ b/tools/perf/pmu-events/empty-pmu-events.c
@@ -2596,116 +2596,148 @@ static const char *const big_c_string =
/* offset=128716 */
"memory_uss\000tool\000Unique Set Size (USS) in bytes\000config=0x28\000\00000\000\000\000\000\000"
/* offset=128783 */
+"net_rx_bytes\000tool\000System-wide network received bytes\000config=0x29\000\00000\000\000\000\000\000"
+/* offset=128856 */
+"net_rx_packets\000tool\000System-wide network received packets\000config=0x2a\000\00000\000\000\000\000\000"
+/* offset=128933 */
+"net_rx_errors\000tool\000System-wide network received errors\000config=0x2b\000\00000\000\000\000\000\000"
+/* offset=129008 */
+"net_rx_drop\000tool\000System-wide network received dropped packets\000config=0x2c\000\00000\000\000\000\000\000"
+/* offset=129090 */
+"net_rx_fifo\000tool\000System-wide network received fifo overruns\000config=0x2d\000\00000\000\000\000\000\000"
+/* offset=129170 */
+"net_rx_frame\000tool\000System-wide network received framing errors\000config=0x2e\000\00000\000\000\000\000\000"
+/* offset=129252 */
+"net_rx_compressed\000tool\000System-wide network received compressed packets\000config=0x2f\000\00000\000\000\000\000\000"
+/* offset=129343 */
+"net_rx_multicast\000tool\000System-wide network received multicast packets\000config=0x30\000\00000\000\000\000\000\000"
+/* offset=129432 */
+"net_tx_bytes\000tool\000System-wide network transmitted bytes\000config=0x31\000\00000\000\000\000\000\000"
+/* offset=129508 */
+"net_tx_packets\000tool\000System-wide network transmitted packets\000config=0x32\000\00000\000\000\000\000\000"
+/* offset=129588 */
+"net_tx_errors\000tool\000System-wide network transmitted errors\000config=0x33\000\00000\000\000\000\000\000"
+/* offset=129666 */
+"net_tx_drop\000tool\000System-wide network transmitted dropped packets\000config=0x34\000\00000\000\000\000\000\000"
+/* offset=129751 */
+"net_tx_fifo\000tool\000System-wide network transmitted fifo overruns\000config=0x35\000\00000\000\000\000\000\000"
+/* offset=129834 */
+"net_tx_colls\000tool\000System-wide network transmitted collisions\000config=0x36\000\00000\000\000\000\000\000"
+/* offset=129915 */
+"net_tx_carrier\000tool\000System-wide network transmitted carrier losses\000config=0x37\000\00000\000\000\000\000\000"
+/* offset=130002 */
+"net_tx_compressed\000tool\000System-wide network transmitted compressed packets\000config=0x38\000\00000\000\000\000\000\000"
+/* offset=130096 */
"bp_l1_btb_correct\000branch\000L1 BTB Correction\000event=0x8a\000\00000\000\000\000\000\000"
-/* offset=128845 */
+/* offset=130158 */
"bp_l2_btb_correct\000branch\000L2 BTB Correction\000event=0x8b\000\00000\000\000\000\000\000"
-/* offset=128907 */
+/* offset=130220 */
"l3_cache_rd\000cache\000L3 cache access, read\000event=0x40\000\00000\000\000\000\000Attributable Level 3 cache access, read\000"
-/* offset=129005 */
+/* offset=130318 */
"segment_reg_loads.any\000other\000Number of segment register loads\000event=6,period=200000,umask=0x80\000\00000\000\000\000\000\000"
-/* offset=129107 */
+/* offset=130420 */
"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=129240 */
+/* offset=130553 */
"eist_trans\000other\000Number of Enhanced Intel SpeedStep(R) Technology (EIST) transitions\000event=0x3a,period=200000\000\00000\000\000\000\000\000"
-/* offset=129358 */
+/* offset=130671 */
"hisi_sccl,ddrc\000"
-/* offset=129373 */
+/* offset=130686 */
"uncore_hisi_ddrc.flux_wcmd\000uncore\000DDRC write commands\000event=2\000\00000\000\000\000\000\000"
-/* offset=129443 */
+/* offset=130756 */
"uncore_cbox\000"
-/* offset=129455 */
+/* offset=130768 */
"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=129609 */
+/* offset=130922 */
"event-hyphen\000uncore\000UNC_CBO_HYPHEN\000event=0xe0\000\00000\000\000\000\000\000"
-/* offset=129663 */
+/* offset=130976 */
"event-two-hyph\000uncore\000UNC_CBO_TWO_HYPH\000event=0xc0\000\00000\000\000\000\000\000"
-/* offset=129721 */
+/* offset=131034 */
"hisi_sccl,l3c\000"
-/* offset=129735 */
+/* offset=131048 */
"uncore_hisi_l3c.rd_hit_cpipe\000uncore\000Total read hits\000event=7\000\00000\000\000\000\000\000"
-/* offset=129803 */
+/* offset=131116 */
"uncore_imc_free_running\000"
-/* offset=129827 */
+/* offset=131140 */
"uncore_imc_free_running.cache_miss\000uncore\000Total cache misses\000event=0x12\000\00000\000\000\000\000\000"
-/* offset=129907 */
+/* offset=131220 */
"uncore_imc\000"
-/* offset=129918 */
+/* offset=131231 */
"uncore_imc.cache_hits\000uncore\000Total cache hits\000event=0x34\000\00000\000\000\000\000\000"
-/* offset=129983 */
+/* offset=131296 */
"uncore_sys_ddr_pmu\000"
-/* offset=130002 */
+/* offset=131315 */
"sys_ddr_pmu.write_cycles\000uncore\000ddr write-cycles event\000event=0x2b\000v8\00000\000\000\000\000\000"
-/* offset=130078 */
+/* offset=131391 */
"uncore_sys_ccn_pmu\000"
-/* offset=130097 */
+/* offset=131410 */
"sys_ccn_pmu.read_cycles\000uncore\000ccn read-cycles event\000config=0x2c\0000x01\00000\000\000\000\000\000"
-/* offset=130174 */
+/* offset=131487 */
"uncore_sys_cmn_pmu\000"
-/* offset=130193 */
+/* offset=131506 */
"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=130336 */
+/* offset=131649 */
"CPUs_utilized\000Default\000(software@cpu\\-clock\\,name\\=cpu\\-clock@ if #target_cpu else software@task\\-clock\\,name\\=task\\-clock@) / (duration_time * 1e9)\000\000Average CPU utilization\000\0001CPUs\000\000\000\000011"
-/* offset=130522 */
+/* offset=131835 */
"cs_per_second\000Default\000software@context\\-switches\\,name\\=context\\-switches@ * 1e9 / (software@cpu\\-clock\\,name\\=cpu\\-clock@ if #target_cpu else software@task\\-clock\\,name\\=task\\-clock@)\000\000Context switches per CPU second\000\0001cs/sec\000\000\000\000011"
-/* offset=130755 */
+/* offset=132068 */
"migrations_per_second\000Default\000software@cpu\\-migrations\\,name\\=cpu\\-migrations@ * 1e9 / (software@cpu\\-clock\\,name\\=cpu\\-clock@ if #target_cpu else software@task\\-clock\\,name\\=task\\-clock@)\000\000Process migrations to a new CPU per CPU second\000\0001migrations/sec\000\000\000\000011"
-/* offset=131015 */
+/* offset=132328 */
"page_faults_per_second\000Default\000software@page\\-faults\\,name\\=page\\-faults@ * 1e9 / (software@cpu\\-clock\\,name\\=cpu\\-clock@ if #target_cpu else software@task\\-clock\\,name\\=task\\-clock@)\000\000Page faults per CPU second\000\0001faults/sec\000\000\000\000011"
-/* offset=131246 */
+/* offset=132559 */
"insn_per_cycle\000Default\000instructions / cpu\\-cycles\000insn_per_cycle < 1\000Instructions Per Cycle\000\0001instructions\000\000\000\000001"
-/* offset=131359 */
+/* offset=132672 */
"stalled_cycles_per_instruction\000Default\000(max(stalled\\-cycles\\-frontend, stalled\\-cycles\\-backend) / instructions if has_event(stalled\\-cycles\\-frontend) & has_event(stalled\\-cycles\\-backend) else (stalled\\-cycles\\-frontend / instructions if has_event(stalled\\-cycles\\-frontend) else (stalled\\-cycles\\-backend / instructions if has_event(stalled\\-cycles\\-backend) else 0)))\000\000Max front or backend stalls per instruction\000\000\000\000\000\000001"
-/* offset=131784 */
+/* offset=133097 */
"frontend_cycles_idle\000Default\000(stalled\\-cycles\\-frontend / cpu\\-cycles if has_event(stalled\\-cycles\\-frontend) else 0)\000frontend_cycles_idle > 0.1\000Frontend stalls per cycle\000\000\000\000\000\000001"
-/* offset=131963 */
+/* offset=133276 */
"backend_cycles_idle\000Default\000(stalled\\-cycles\\-backend / cpu\\-cycles if has_event(stalled\\-cycles\\-backend) else 0)\000backend_cycles_idle > 0.2\000Backend stalls per cycle\000\000\000\000\000\000001"
-/* offset=132137 */
+/* offset=133450 */
"cycles_frequency\000Default\000cpu\\-cycles / (software@cpu\\-clock\\,name\\=cpu\\-clock@ if #target_cpu else software@task\\-clock\\,name\\=task\\-clock@)\000\000Cycles per CPU second\000\0001GHz\000\000\000\000011"
-/* offset=132313 */
+/* offset=133626 */
"branch_frequency\000Default\000branches / (software@cpu\\-clock\\,name\\=cpu\\-clock@ if #target_cpu else software@task\\-clock\\,name\\=task\\-clock@)\000\000Branches per CPU second\000\0001000M/sec\000\000\000\000011"
-/* offset=132493 */
+/* offset=133806 */
"branch_miss_rate\000Default\000branch\\-misses / branches\000branch_miss_rate > 0.05\000Branch miss rate\000\000100%\000\000\000\000001"
-/* offset=132597 */
+/* offset=133910 */
"l1d_miss_rate\000Default2\000L1\\-dcache\\-load\\-misses / L1\\-dcache\\-loads\000l1d_miss_rate > 0.05\000L1D miss rate\000\000100%\000\000\000\000001"
-/* offset=132713 */
+/* offset=134026 */
"llc_miss_rate\000Default2\000LLC\\-load\\-misses / LLC\\-loads\000llc_miss_rate > 0.05\000LLC miss rate\000\000100%\000\000\000\000001"
-/* offset=132814 */
+/* offset=134127 */
"l1i_miss_rate\000Default3\000L1\\-icache\\-load\\-misses / L1\\-icache\\-loads\000l1i_miss_rate > 0.05\000L1I miss rate\000\000100%\000\000\000\000001"
-/* offset=132929 */
+/* offset=134242 */
"dtlb_miss_rate\000Default3\000dTLB\\-load\\-misses / dTLB\\-loads\000dtlb_miss_rate > 0.05\000dTLB miss rate\000\000100%\000\000\000\000001"
-/* offset=133035 */
+/* offset=134348 */
"itlb_miss_rate\000Default3\000iTLB\\-load\\-misses / iTLB\\-loads\000itlb_miss_rate > 0.05\000iTLB miss rate\000\000100%\000\000\000\000001"
-/* offset=133141 */
+/* offset=134454 */
"l1_prefetch_miss_rate\000Default4\000L1\\-dcache\\-prefetch\\-misses / L1\\-dcache\\-prefetches\000l1_prefetch_miss_rate > 0.05\000L1 prefetch miss rate\000\000100%\000\000\000\000001"
-/* offset=133289 */
+/* offset=134602 */
"CPI\000\0001 / IPC\000\000\000\000\000\000\000\000000"
-/* offset=133312 */
+/* offset=134625 */
"IPC\000group1\000inst_retired.any / cpu_clk_unhalted.thread\000\000\000\000\000\000\000\000000"
-/* offset=133376 */
+/* offset=134689 */
"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\000000"
-/* offset=133543 */
+/* offset=134856 */
"dcache_miss_cpi\000\000l1d\\-loads\\-misses / inst_retired.any\000\000\000\000\000\000\000\000000"
-/* offset=133608 */
+/* offset=134921 */
"icache_miss_cycles\000\000l1i\\-loads\\-misses / inst_retired.any\000\000\000\000\000\000\000\000000"
-/* offset=133676 */
+/* offset=134989 */
"cache_miss_cycles\000group1\000dcache_miss_cpi + icache_miss_cycles\000\000\000\000\000\000\000\000000"
-/* offset=133748 */
+/* offset=135061 */
"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\000000"
-/* offset=133843 */
+/* offset=135156 */
"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\000000"
-/* offset=133978 */
+/* offset=135291 */
"DCache_L2_All\000\000DCache_L2_All_Hits + DCache_L2_All_Miss\000\000\000\000\000\000\000\000000"
-/* offset=134043 */
+/* offset=135356 */
"DCache_L2_Hits\000\000d_ratio(DCache_L2_All_Hits, DCache_L2_All)\000\000\000\000\000\000\000\000000"
-/* offset=134112 */
+/* offset=135425 */
"DCache_L2_Misses\000\000d_ratio(DCache_L2_All_Miss, DCache_L2_All)\000\000\000\000\000\000\000\000000"
-/* offset=134183 */
+/* offset=135496 */
"M1\000\000ipc + M2\000\000\000\000\000\000\000\000000"
-/* offset=134206 */
+/* offset=135519 */
"M2\000\000ipc + M1\000\000\000\000\000\000\000\000000"
-/* offset=134229 */
+/* offset=135542 */
"M3\000\0001 / M3\000\000\000\000\000\000\000\000000"
-/* offset=134250 */
+/* offset=135563 */
"L1D_Cache_Fill_BW\000\00064 * l1d.replacement / 1e9 / duration_time\000\000\000\000\000\000\000\000000"
;
@@ -5262,6 +5294,38 @@ static const struct compact_pmu_event pmu_events__common_tool[] = {
{ 128630 },
/* memory_uss\000tool\000Unique Set Size (USS) in bytes\000config=0x28\000\00000\00... */
{ 128716 },
+ /* net_rx_bytes\000tool\000System-wide network received bytes\000config=0x29\000\00... */
+ { 128783 },
+ /* net_rx_compressed\000tool\000System-wide network received compressed packets\000... */
+ { 129252 },
+ /* net_rx_drop\000tool\000System-wide network received dropped packets\000config=0x... */
+ { 129008 },
+ /* net_rx_errors\000tool\000System-wide network received errors\000config=0x2b\000\... */
+ { 128933 },
+ /* net_rx_fifo\000tool\000System-wide network received fifo overruns\000config=0x2d... */
+ { 129090 },
+ /* net_rx_frame\000tool\000System-wide network received framing errors\000config=0x... */
+ { 129170 },
+ /* net_rx_multicast\000tool\000System-wide network received multicast packets\000co... */
+ { 129343 },
+ /* net_rx_packets\000tool\000System-wide network received packets\000config=0x2a\00... */
+ { 128856 },
+ /* net_tx_bytes\000tool\000System-wide network transmitted bytes\000config=0x31\000... */
+ { 129432 },
+ /* net_tx_carrier\000tool\000System-wide network transmitted carrier losses\000conf... */
+ { 129915 },
+ /* net_tx_colls\000tool\000System-wide network transmitted collisions\000config=0x3... */
+ { 129834 },
+ /* net_tx_compressed\000tool\000System-wide network transmitted compressed packets\... */
+ { 130002 },
+ /* net_tx_drop\000tool\000System-wide network transmitted dropped packets\000config... */
+ { 129666 },
+ /* net_tx_errors\000tool\000System-wide network transmitted errors\000config=0x33\0... */
+ { 129588 },
+ /* net_tx_fifo\000tool\000System-wide network transmitted fifo overruns\000config=0... */
+ { 129751 },
+ /* net_tx_packets\000tool\000System-wide network transmitted packets\000config=0x32... */
+ { 129508 },
/* num_cores\000tool\000Number of cores. A core consists of 1 or more thread, with ... */
{ 125363 },
/* num_cpus\000tool\000Number of logical Linux CPUs. There may be multiple such CPU... */
@@ -5307,39 +5371,39 @@ static const struct pmu_table_entry pmu_events__common[] = {
static const struct compact_pmu_event pmu_metrics__common_default_core[] = {
/* CPUs_utilized\000Default\000(software@cpu\\-clock\\,name\\=cpu\\-clock@ if #targ... */
- { 130336 },
+ { 131649 },
/* backend_cycles_idle\000Default\000(stalled\\-cycles\\-backend / cpu\\-cycles if ... */
- { 131963 },
+ { 133276 },
/* branch_frequency\000Default\000branches / (software@cpu\\-clock\\,name\\=cpu\\-c... */
- { 132313 },
+ { 133626 },
/* branch_miss_rate\000Default\000branch\\-misses / branches\000branch_miss_rate > ... */
- { 132493 },
+ { 133806 },
/* cs_per_second\000Default\000software@context\\-switches\\,name\\=context\\-switc... */
- { 130522 },
+ { 131835 },
/* cycles_frequency\000Default\000cpu\\-cycles / (software@cpu\\-clock\\,name\\=cpu... */
- { 132137 },
+ { 133450 },
/* dtlb_miss_rate\000Default3\000dTLB\\-load\\-misses / dTLB\\-loads\000dtlb_miss_r... */
- { 132929 },
+ { 134242 },
/* frontend_cycles_idle\000Default\000(stalled\\-cycles\\-frontend / cpu\\-cycles i... */
- { 131784 },
+ { 133097 },
/* insn_per_cycle\000Default\000instructions / cpu\\-cycles\000insn_per_cycle < 1\0... */
- { 131246 },
+ { 132559 },
/* itlb_miss_rate\000Default3\000iTLB\\-load\\-misses / iTLB\\-loads\000itlb_miss_r... */
- { 133035 },
+ { 134348 },
/* l1_prefetch_miss_rate\000Default4\000L1\\-dcache\\-prefetch\\-misses / L1\\-dcac... */
- { 133141 },
+ { 134454 },
/* l1d_miss_rate\000Default2\000L1\\-dcache\\-load\\-misses / L1\\-dcache\\-loads\0... */
- { 132597 },
+ { 133910 },
/* l1i_miss_rate\000Default3\000L1\\-icache\\-load\\-misses / L1\\-icache\\-loads\0... */
- { 132814 },
+ { 134127 },
/* llc_miss_rate\000Default2\000LLC\\-load\\-misses / LLC\\-loads\000llc_miss_rate ... */
- { 132713 },
+ { 134026 },
/* migrations_per_second\000Default\000software@cpu\\-migrations\\,name\\=cpu\\-mig... */
- { 130755 },
+ { 132068 },
/* page_faults_per_second\000Default\000software@page\\-faults\\,name\\=page\\-faul... */
- { 131015 },
+ { 132328 },
/* stalled_cycles_per_instruction\000Default\000(max(stalled\\-cycles\\-frontend, s... */
- { 131359 },
+ { 132672 },
};
@@ -5353,41 +5417,41 @@ static const struct pmu_table_entry pmu_metrics__common[] = {
static const struct compact_pmu_event pmu_events__test_soc_cpu_default_core[] = {
/* bp_l1_btb_correct\000branch\000L1 BTB Correction\000event=0x8a\000\00000\000\000... */
- { 128783 },
+ { 130096 },
/* bp_l2_btb_correct\000branch\000L2 BTB Correction\000event=0x8b\000\00000\000\000... */
- { 128845 },
+ { 130158 },
/* dispatch_blocked.any\000other\000Memory cluster signals to block micro-op dispat... */
- { 129107 },
+ { 130420 },
/* eist_trans\000other\000Number of Enhanced Intel SpeedStep(R) Technology (EIST) t... */
- { 129240 },
+ { 130553 },
/* l3_cache_rd\000cache\000L3 cache access, read\000event=0x40\000\00000\000\000\00... */
- { 128907 },
+ { 130220 },
/* segment_reg_loads.any\000other\000Number of segment register loads\000event=6,pe... */
- { 129005 },
+ { 130318 },
};
static const struct compact_pmu_event pmu_events__test_soc_cpu_hisi_sccl_ddrc[] = {
/* uncore_hisi_ddrc.flux_wcmd\000uncore\000DDRC write commands\000event=2\000\00000... */
- { 129373 },
+ { 130686 },
};
static const struct compact_pmu_event pmu_events__test_soc_cpu_hisi_sccl_l3c[] = {
/* uncore_hisi_l3c.rd_hit_cpipe\000uncore\000Total read hits\000event=7\000\00000\0... */
- { 129735 },
+ { 131048 },
};
static const struct compact_pmu_event pmu_events__test_soc_cpu_uncore_cbox[] = {
/* event-hyphen\000uncore\000UNC_CBO_HYPHEN\000event=0xe0\000\00000\000\000\000\000... */
- { 129609 },
+ { 130922 },
/* event-two-hyph\000uncore\000UNC_CBO_TWO_HYPH\000event=0xc0\000\00000\000\000\000... */
- { 129663 },
+ { 130976 },
/* unc_cbo_xsnp_response.miss_eviction\000uncore\000A cross-core snoop resulted fro... */
- { 129455 },
+ { 130768 },
};
static const struct compact_pmu_event pmu_events__test_soc_cpu_uncore_imc[] = {
/* uncore_imc.cache_hits\000uncore\000Total cache hits\000event=0x34\000\00000\000\... */
- { 129918 },
+ { 131231 },
};
static const struct compact_pmu_event pmu_events__test_soc_cpu_uncore_imc_free_running[] = {
/* uncore_imc_free_running.cache_miss\000uncore\000Total cache misses\000event=0x12... */
- { 129827 },
+ { 131140 },
};
@@ -5400,61 +5464,61 @@ static const struct pmu_table_entry pmu_events__test_soc_cpu[] = {
{
.entries = pmu_events__test_soc_cpu_hisi_sccl_ddrc,
.num_entries = ARRAY_SIZE(pmu_events__test_soc_cpu_hisi_sccl_ddrc),
- .pmu_name = { 129358 /* hisi_sccl,ddrc\000 */ },
+ .pmu_name = { 130671 /* 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 = { 129721 /* hisi_sccl,l3c\000 */ },
+ .pmu_name = { 131034 /* 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 = { 129443 /* uncore_cbox\000 */ },
+ .pmu_name = { 130756 /* uncore_cbox\000 */ },
},
{
.entries = pmu_events__test_soc_cpu_uncore_imc,
.num_entries = ARRAY_SIZE(pmu_events__test_soc_cpu_uncore_imc),
- .pmu_name = { 129907 /* uncore_imc\000 */ },
+ .pmu_name = { 131220 /* 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 = { 129803 /* uncore_imc_free_running\000 */ },
+ .pmu_name = { 131116 /* uncore_imc_free_running\000 */ },
},
};
static const struct compact_pmu_event pmu_metrics__test_soc_cpu_default_core[] = {
/* CPI\000\0001 / IPC\000\000\000\000\000\000\000\000000 */
- { 133289 },
+ { 134602 },
/* DCache_L2_All\000\000DCache_L2_All_Hits + DCache_L2_All_Miss\000\000\000\000\000... */
- { 133978 },
+ { 135291 },
/* DCache_L2_All_Hits\000\000l2_rqsts.demand_data_rd_hit + l2_rqsts.pf_hit + l2_rqs... */
- { 133748 },
+ { 135061 },
/* DCache_L2_All_Miss\000\000max(l2_rqsts.all_demand_data_rd - l2_rqsts.demand_data... */
- { 133843 },
+ { 135156 },
/* DCache_L2_Hits\000\000d_ratio(DCache_L2_All_Hits, DCache_L2_All)\000\000\000\000... */
- { 134043 },
+ { 135356 },
/* DCache_L2_Misses\000\000d_ratio(DCache_L2_All_Miss, DCache_L2_All)\000\000\000\0... */
- { 134112 },
+ { 135425 },
/* Frontend_Bound_SMT\000\000idq_uops_not_delivered.core / (4 * (cpu_clk_unhalted.t... */
- { 133376 },
+ { 134689 },
/* IPC\000group1\000inst_retired.any / cpu_clk_unhalted.thread\000\000\000\000\000\... */
- { 133312 },
+ { 134625 },
/* L1D_Cache_Fill_BW\000\00064 * l1d.replacement / 1e9 / duration_time\000\000\000\... */
- { 134250 },
+ { 135563 },
/* M1\000\000ipc + M2\000\000\000\000\000\000\000\000000 */
- { 134183 },
+ { 135496 },
/* M2\000\000ipc + M1\000\000\000\000\000\000\000\000000 */
- { 134206 },
+ { 135519 },
/* M3\000\0001 / M3\000\000\000\000\000\000\000\000000 */
- { 134229 },
+ { 135542 },
/* cache_miss_cycles\000group1\000dcache_miss_cpi + icache_miss_cycles\000\000\000\... */
- { 133676 },
+ { 134989 },
/* dcache_miss_cpi\000\000l1d\\-loads\\-misses / inst_retired.any\000\000\000\000\0... */
- { 133543 },
+ { 134856 },
/* icache_miss_cycles\000\000l1i\\-loads\\-misses / inst_retired.any\000\000\000\00... */
- { 133608 },
+ { 134921 },
};
@@ -5468,15 +5532,15 @@ static const struct pmu_table_entry pmu_metrics__test_soc_cpu[] = {
static const struct compact_pmu_event pmu_events__test_soc_sys_uncore_sys_ccn_pmu[] = {
/* sys_ccn_pmu.read_cycles\000uncore\000ccn read-cycles event\000config=0x2c\0000x0... */
- { 130097 },
+ { 131410 },
};
static const struct compact_pmu_event pmu_events__test_soc_sys_uncore_sys_cmn_pmu[] = {
/* sys_cmn_pmu.hnf_cache_miss\000uncore\000Counts total cache misses in first looku... */
- { 130193 },
+ { 131506 },
};
static const struct compact_pmu_event pmu_events__test_soc_sys_uncore_sys_ddr_pmu[] = {
/* sys_ddr_pmu.write_cycles\000uncore\000ddr write-cycles event\000event=0x2b\000v8... */
- { 130002 },
+ { 131315 },
};
@@ -5484,17 +5548,17 @@ static 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 = { 130078 /* uncore_sys_ccn_pmu\000 */ },
+ .pmu_name = { 131391 /* 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 = { 130174 /* uncore_sys_cmn_pmu\000 */ },
+ .pmu_name = { 131487 /* 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 = { 129983 /* uncore_sys_ddr_pmu\000 */ },
+ .pmu_name = { 131296 /* uncore_sys_ddr_pmu\000 */ },
},
};
diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c
index 6d69f63b7fb1..a508e438bb03 100644
--- a/tools/perf/util/evsel.c
+++ b/tools/perf/util/evsel.c
@@ -1899,6 +1899,46 @@ int evsel__append_addr_filter(struct evsel *evsel, const char *filter)
return evsel__append_filter(evsel, "%s,%s", filter);
}
+static int evsel__group_member_cpu_action(struct evsel *leader, struct evsel *member,
+ int cpu_map_idx, bool enable)
+{
+ struct perf_cpu cpu;
+ int m_idx;
+
+ if (perf_cpu_map__equal(leader->core.cpus, member->core.cpus))
+ return enable ? evsel__enable_cpu(member, cpu_map_idx)
+ : evsel__disable_cpu(member, cpu_map_idx);
+
+ if (member->core.reads_only_on_cpu_idx0) {
+ if (cpu_map_idx == 0 && perf_cpu_map__nr(member->core.cpus) > 0)
+ return enable ? evsel__enable_cpu(member, 0)
+ : evsel__disable_cpu(member, 0);
+ return 0;
+ }
+
+ if (leader->core.reads_only_on_cpu_idx0) {
+ if (cpu_map_idx == 0) {
+ int nr = perf_cpu_map__nr(member->core.cpus);
+
+ for (m_idx = 0; m_idx < nr; m_idx++) {
+ int err = enable ? evsel__enable_cpu(member, m_idx)
+ : evsel__disable_cpu(member, m_idx);
+
+ if (err)
+ return err;
+ }
+ }
+ return 0;
+ }
+
+ cpu = perf_cpu_map__cpu(leader->core.cpus, cpu_map_idx);
+ m_idx = perf_cpu_map__idx(member->core.cpus, cpu);
+ if (m_idx >= 0)
+ return enable ? evsel__enable_cpu(member, m_idx)
+ : evsel__disable_cpu(member, m_idx);
+ return 0;
+}
+
/* Caller has to clear disabled after going through all CPUs. */
int evsel__enable_cpu(struct evsel *evsel, int cpu_map_idx)
{
@@ -1922,7 +1962,8 @@ int evsel__enable_cpu(struct evsel *evsel, int cpu_map_idx)
* group leader. We must manually enable them in
* userspace.
*/
- int mem_err = evsel__enable_cpu(member, cpu_map_idx);
+ int mem_err = evsel__group_member_cpu_action(evsel, member,
+ cpu_map_idx, true);
if (mem_err)
return mem_err;
@@ -1991,7 +2032,8 @@ int evsel__disable_cpu(struct evsel *evsel, int cpu_map_idx)
* kernel when disabling the group leader. We must
* manually disable them in userspace.
*/
- int mem_err = evsel__disable_cpu(member, cpu_map_idx);
+ int mem_err = evsel__group_member_cpu_action(evsel, member,
+ cpu_map_idx, false);
if (mem_err)
return mem_err;
@@ -2099,11 +2141,8 @@ static void evsel__exit(struct evsel *evsel)
if (evsel__priv_destructor)
evsel__priv_destructor(evsel->priv);
perf_evsel__object.fini(evsel);
- if (evsel__tool_event(evsel) == TOOL_PMU__EVENT_SYSTEM_TIME ||
- evsel__tool_event(evsel) == TOOL_PMU__EVENT_USER_TIME) {
- xyarray__delete(evsel->process_time.start_times);
- xyarray__delete(evsel->process_time.accumulated_times);
- }
+ if (evsel__is_tool(evsel))
+ evsel__tool_pmu_exit(evsel);
}
void evsel__put(struct evsel *evsel)
diff --git a/tools/perf/util/tool_pmu.c b/tools/perf/util/tool_pmu.c
index 0ae08cd910bc..655b22104320 100644
--- a/tools/perf/util/tool_pmu.c
+++ b/tools/perf/util/tool_pmu.c
@@ -68,6 +68,22 @@ static const char *const tool_pmu__event_names[TOOL_PMU__EVENT_MAX] = {
"memory_swap_pss",
"memory_text",
"memory_uss",
+ "net_rx_bytes",
+ "net_rx_packets",
+ "net_rx_errors",
+ "net_rx_drop",
+ "net_rx_fifo",
+ "net_rx_frame",
+ "net_rx_compressed",
+ "net_rx_multicast",
+ "net_tx_bytes",
+ "net_tx_packets",
+ "net_tx_errors",
+ "net_tx_drop",
+ "net_tx_fifo",
+ "net_tx_colls",
+ "net_tx_carrier",
+ "net_tx_compressed",
};
bool tool_pmu__skip_event(const char *name __maybe_unused)
@@ -271,6 +287,22 @@ static const char *tool_pmu__memory_event_to_key(enum tool_pmu_event ev)
case TOOL_PMU__EVENT_MEMORY_SIZE:
case TOOL_PMU__EVENT_MEMORY_TEXT:
case TOOL_PMU__EVENT_MEMORY_USS:
+ case TOOL_PMU__EVENT_NET_RX_BYTES:
+ case TOOL_PMU__EVENT_NET_RX_PACKETS:
+ case TOOL_PMU__EVENT_NET_RX_ERRORS:
+ case TOOL_PMU__EVENT_NET_RX_DROP:
+ case TOOL_PMU__EVENT_NET_RX_FIFO:
+ case TOOL_PMU__EVENT_NET_RX_FRAME:
+ case TOOL_PMU__EVENT_NET_RX_COMPRESSED:
+ case TOOL_PMU__EVENT_NET_RX_MULTICAST:
+ case TOOL_PMU__EVENT_NET_TX_BYTES:
+ case TOOL_PMU__EVENT_NET_TX_PACKETS:
+ case TOOL_PMU__EVENT_NET_TX_ERRORS:
+ case TOOL_PMU__EVENT_NET_TX_DROP:
+ case TOOL_PMU__EVENT_NET_TX_FIFO:
+ case TOOL_PMU__EVENT_NET_TX_COLLS:
+ case TOOL_PMU__EVENT_NET_TX_CARRIER:
+ case TOOL_PMU__EVENT_NET_TX_COMPRESSED:
case TOOL_PMU__EVENT_DURATION_TIME:
case TOOL_PMU__EVENT_USER_TIME:
case TOOL_PMU__EVENT_SYSTEM_TIME:
@@ -435,13 +467,110 @@ static int read_statm(int fd, enum tool_pmu_event ev, u64 *val)
return -EINVAL;
}
+static bool tool_pmu__is_net_event(enum tool_pmu_event ev)
+{
+ return ev >= TOOL_PMU__EVENT_NET_RX_BYTES &&
+ ev <= TOOL_PMU__EVENT_NET_TX_COMPRESSED;
+}
+
+static bool tool_pmu__has_start_times(enum tool_pmu_event ev)
+{
+ return ev == TOOL_PMU__EVENT_USER_TIME ||
+ ev == TOOL_PMU__EVENT_SYSTEM_TIME ||
+ tool_pmu__is_net_event(ev);
+}
+
+static int read_net_dev_col(struct io *io, __u64 *val, int *term)
+{
+ int ch;
+
+ do {
+ ch = io__get_char(io);
+ if (ch == -1 || ch == '\n') {
+ *term = ch;
+ return -EINVAL;
+ }
+ } while (ch == ' ' || ch == '\t');
+
+ if (ch < '0' || ch > '9') {
+ *term = ch;
+ return -EINVAL;
+ }
+
+ *val = ch - '0';
+ while (true) {
+ ch = io__get_char(io);
+ if (ch >= '0' && ch <= '9') {
+ *val = (*val * 10) + (ch - '0');
+ } else {
+ *term = ch;
+ return 0;
+ }
+ }
+}
+
+static int read_net_dev(int fd, enum tool_pmu_event ev, __u64 *val)
+{
+ struct io io;
+ char buf[4096];
+ int index = ev - TOOL_PMU__EVENT_NET_RX_BYTES;
+
+ io__init(&io, fd, buf, sizeof(buf));
+ lseek(fd, 0, SEEK_SET);
+
+ /*
+ * Drop two header lines:
+ * Inter-| Receive | Transmit
+ * face |bytes packets errs drop fifo frame compressed multicast|bytes ...
+ */
+ if (!read_until_char(&io, '\n'))
+ return -EINVAL;
+ if (!read_until_char(&io, '\n'))
+ return -EINVAL;
+
+ *val = 0;
+ while (true) {
+ int ch = io__get_char(&io);
+ int i, term = 0;
+ __u64 v;
+
+ if (ch == -1)
+ break;
+ while (ch == ' ' || ch == '\t')
+ ch = io__get_char(&io);
+ if (ch == -1)
+ break;
+ while (ch != ':' && ch != -1 && ch != '\n')
+ ch = io__get_char(&io);
+ if (ch != ':') {
+ if (ch == '\n')
+ continue;
+ if (ch == -1)
+ break;
+ read_until_char(&io, '\n');
+ continue;
+ }
+ for (i = 0; i < index; i++) {
+ if (read_net_dev_col(&io, &v, &term))
+ break;
+ }
+ if (i == index && !read_net_dev_col(&io, &v, &term))
+ *val += v;
+ if (term != '\n' && term != -1)
+ read_until_char(&io, '\n');
+ if (term == -1)
+ break;
+ }
+ return 0;
+}
+
int evsel__tool_pmu_prepare_open(struct evsel *evsel,
struct perf_cpu_map *cpus,
int nthreads)
{
enum tool_pmu_event ev = evsel__tool_event(evsel);
- if (ev == TOOL_PMU__EVENT_SYSTEM_TIME || ev == TOOL_PMU__EVENT_USER_TIME) {
+ if (tool_pmu__has_start_times(ev)) {
if (!evsel->process_time.start_times) {
evsel->process_time.start_times =
xyarray__new(perf_cpu_map__nr(cpus), nthreads, sizeof(__u64));
@@ -464,7 +593,8 @@ static int tool_pmu__read_stat(struct evsel *evsel, int cpu_map_idx, int thread,
{
enum tool_pmu_event ev = evsel__tool_event(evsel);
bool system = ev == TOOL_PMU__EVENT_SYSTEM_TIME;
- int fd = FD(evsel, cpu_map_idx, thread);
+ int *fd_ptr = evsel->core.fd ? xyarray__entry(evsel->core.fd, cpu_map_idx, thread) : NULL;
+ int fd = fd_ptr ? *fd_ptr : -1;
int err = 0;
if (fd < 0) {
@@ -472,6 +602,13 @@ static int tool_pmu__read_stat(struct evsel *evsel, int cpu_map_idx, int thread,
return 0;
}
+ if (tool_pmu__is_net_event(ev)) {
+ if (cpu_map_idx == 0 && thread == 0)
+ return read_net_dev(fd, ev, val);
+ *val = 0;
+ return 0;
+ }
+
lseek(fd, 0, SEEK_SET);
if (evsel->pid_stat) {
if (cpu_map_idx == 0)
@@ -539,40 +676,58 @@ static int open_memory_pid_dir(enum tool_pmu_event ev, int pid,
return 0;
}
+static bool tool_pmu__is_initially_disabled(const struct evsel *evsel)
+{
+ const struct evsel *leader = evsel__leader(evsel);
+
+ return evsel->core.attr.disabled || (leader && leader->core.attr.disabled);
+}
+
static int evsel__tool_pmu_open_one(struct evsel *evsel, enum tool_pmu_event ev,
int pid, int idx, int thread,
int *seen_tgids, int *nr_seen_tgids)
{
- if (ev == TOOL_PMU__EVENT_USER_TIME || ev == TOOL_PMU__EVENT_SYSTEM_TIME) {
+ if (tool_pmu__has_start_times(ev)) {
__u64 *start_time = NULL;
__u64 *accumulated_time = NULL;
char buf[PATH_MAX];
- int fd, err;
-
- if (pid > -1) {
- snprintf(buf, sizeof(buf), "%s/%d/stat", procfs__mountpoint(), pid);
- evsel->pid_stat = true;
+ int fd = -1, err;
+
+ if (tool_pmu__is_net_event(ev)) {
+ if (pid > -1 || evsel->cgrp)
+ return -EINVAL;
+ if (idx == 0 && thread == 0) {
+ snprintf(buf, sizeof(buf), "%s/net/dev", procfs__mountpoint());
+ fd = open(buf, O_RDONLY);
+ if (fd < 0)
+ return -errno;
+ }
} else {
- snprintf(buf, sizeof(buf), "%s/stat", procfs__mountpoint());
+ if (pid > -1) {
+ snprintf(buf, sizeof(buf), "%s/%d/stat", procfs__mountpoint(), pid);
+ evsel->pid_stat = true;
+ } else {
+ snprintf(buf, sizeof(buf), "%s/stat", procfs__mountpoint());
+ }
+ fd = open(buf, O_RDONLY);
+ if (fd < 0)
+ return -errno;
}
- fd = open(buf, O_RDONLY);
FD(evsel, idx, thread) = fd;
- if (fd < 0)
- return -errno;
-
start_time = xyarray__entry(evsel->process_time.start_times, idx, thread);
accumulated_time = xyarray__entry(evsel->process_time.accumulated_times,
idx, thread);
*accumulated_time = 0;
- if (evsel->core.attr.disabled) {
+ if (tool_pmu__is_initially_disabled(evsel)) {
evsel->disabled = true;
*start_time = INVALID_START_TIME;
} else {
evsel->disabled = false;
err = tool_pmu__read_stat(evsel, idx, thread, start_time);
if (err) {
- close(fd);
+ if (fd >= 0)
+ close(fd);
FD(evsel, idx, thread) = -1;
return err;
}
@@ -583,7 +738,7 @@ static int evsel__tool_pmu_open_one(struct evsel *evsel, enum tool_pmu_event ev,
if (evsel->cgrp)
return -EINVAL;
- evsel->disabled = evsel->core.attr.disabled;
+ evsel->disabled = tool_pmu__is_initially_disabled(evsel);
if (pid > -1) {
evsel->pid_stat = true;
if (idx == 0) {
@@ -623,7 +778,7 @@ int evsel__tool_pmu_open(struct evsel *evsel,
if (ev == TOOL_PMU__EVENT_DURATION_TIME) {
evsel->duration_time.accumulated_time = 0;
- if (evsel->core.attr.disabled) {
+ if (tool_pmu__is_initially_disabled(evsel)) {
evsel->disabled = true;
evsel->duration_time.start_time = INVALID_START_TIME;
} else {
@@ -834,6 +989,22 @@ bool tool_pmu__read_event(enum tool_pmu_event ev,
case TOOL_PMU__EVENT_MEMORY_LOCKED:
case TOOL_PMU__EVENT_MEMORY_DATA:
case TOOL_PMU__EVENT_MEMORY_TEXT:
+ case TOOL_PMU__EVENT_NET_RX_BYTES:
+ case TOOL_PMU__EVENT_NET_RX_PACKETS:
+ case TOOL_PMU__EVENT_NET_RX_ERRORS:
+ case TOOL_PMU__EVENT_NET_RX_DROP:
+ case TOOL_PMU__EVENT_NET_RX_FIFO:
+ case TOOL_PMU__EVENT_NET_RX_FRAME:
+ case TOOL_PMU__EVENT_NET_RX_COMPRESSED:
+ case TOOL_PMU__EVENT_NET_RX_MULTICAST:
+ case TOOL_PMU__EVENT_NET_TX_BYTES:
+ case TOOL_PMU__EVENT_NET_TX_PACKETS:
+ case TOOL_PMU__EVENT_NET_TX_ERRORS:
+ case TOOL_PMU__EVENT_NET_TX_DROP:
+ case TOOL_PMU__EVENT_NET_TX_FIFO:
+ case TOOL_PMU__EVENT_NET_TX_COLLS:
+ case TOOL_PMU__EVENT_NET_TX_CARRIER:
+ case TOOL_PMU__EVENT_NET_TX_COMPRESSED:
case TOOL_PMU__EVENT_NONE:
case TOOL_PMU__EVENT_DURATION_TIME:
case TOOL_PMU__EVENT_USER_TIME:
@@ -928,7 +1099,11 @@ int evsel__tool_pmu_enable_cpu(struct evsel *evsel, int cpu_map_idx)
return 0;
}
- if (ev == TOOL_PMU__EVENT_USER_TIME || ev == TOOL_PMU__EVENT_SYSTEM_TIME) {
+ if (tool_pmu__has_start_times(ev)) {
+ if (!evsel->process_time.start_times || cpu_map_idx < 0 ||
+ cpu_map_idx >= xyarray__max_x(evsel->process_time.start_times))
+ return 0;
+
nthreads = xyarray__max_y(evsel->process_time.start_times);
for (thread = 0; thread < nthreads; thread++) {
__u64 *start_time = xyarray__entry(evsel->process_time.start_times,
@@ -979,7 +1154,12 @@ int evsel__tool_pmu_disable_cpu(struct evsel *evsel, int cpu_map_idx)
return 0;
}
- if (ev == TOOL_PMU__EVENT_USER_TIME || ev == TOOL_PMU__EVENT_SYSTEM_TIME) {
+ if (tool_pmu__has_start_times(ev)) {
+ if (!evsel->process_time.start_times || !evsel->process_time.accumulated_times ||
+ cpu_map_idx < 0 ||
+ cpu_map_idx >= xyarray__max_x(evsel->process_time.start_times))
+ return 0;
+
nthreads = xyarray__max_y(evsel->process_time.start_times);
for (thread = 0; thread < nthreads; thread++) {
__u64 *start_time = xyarray__entry(evsel->process_time.start_times,
@@ -1065,11 +1245,29 @@ int evsel__tool_pmu_read(struct evsel *evsel, int cpu_map_idx, int thread)
}
break;
case TOOL_PMU__EVENT_USER_TIME:
- case TOOL_PMU__EVENT_SYSTEM_TIME: {
- __u64 accumulated = *(__u64 *)xyarray__entry(evsel->process_time.accumulated_times,
- cpu_map_idx, thread);
-
- if (evsel->disabled) {
+ case TOOL_PMU__EVENT_SYSTEM_TIME:
+ case TOOL_PMU__EVENT_NET_RX_BYTES:
+ case TOOL_PMU__EVENT_NET_RX_PACKETS:
+ case TOOL_PMU__EVENT_NET_RX_ERRORS:
+ case TOOL_PMU__EVENT_NET_RX_DROP:
+ case TOOL_PMU__EVENT_NET_RX_FIFO:
+ case TOOL_PMU__EVENT_NET_RX_FRAME:
+ case TOOL_PMU__EVENT_NET_RX_COMPRESSED:
+ case TOOL_PMU__EVENT_NET_RX_MULTICAST:
+ case TOOL_PMU__EVENT_NET_TX_BYTES:
+ case TOOL_PMU__EVENT_NET_TX_PACKETS:
+ case TOOL_PMU__EVENT_NET_TX_ERRORS:
+ case TOOL_PMU__EVENT_NET_TX_DROP:
+ case TOOL_PMU__EVENT_NET_TX_FIFO:
+ case TOOL_PMU__EVENT_NET_TX_COLLS:
+ case TOOL_PMU__EVENT_NET_TX_CARRIER:
+ case TOOL_PMU__EVENT_NET_TX_COMPRESSED: {
+ __u64 *accumulated_ptr = evsel->process_time.accumulated_times ?
+ xyarray__entry(evsel->process_time.accumulated_times, cpu_map_idx, thread) :
+ NULL;
+ __u64 accumulated = accumulated_ptr ? *accumulated_ptr : 0;
+
+ if (!accumulated_ptr || evsel->disabled) {
delta_start = accumulated;
} else {
__u64 *start_time = xyarray__entry(evsel->process_time.start_times,
@@ -1078,13 +1276,14 @@ int evsel__tool_pmu_read(struct evsel *evsel, int cpu_map_idx, int thread)
err = tool_pmu__read_stat(evsel, cpu_map_idx, thread, &cur_time);
if (!err) {
- if (*start_time != INVALID_START_TIME && cur_time >= *start_time)
+ if (start_time && *start_time != INVALID_START_TIME &&
+ cur_time >= *start_time)
delta_start = accumulated + (cur_time - *start_time);
else
delta_start = accumulated;
}
}
- adjust = true;
+ adjust = (ev == TOOL_PMU__EVENT_USER_TIME || ev == TOOL_PMU__EVENT_SYSTEM_TIME);
break;
}
case TOOL_PMU__EVENT_MEMORY_SIZE:
@@ -1163,6 +1362,18 @@ int evsel__tool_pmu_read(struct evsel *evsel, int cpu_map_idx, int thread)
return 0;
}
+void evsel__tool_pmu_exit(struct evsel *evsel)
+{
+ enum tool_pmu_event ev = evsel__tool_event(evsel);
+
+ if (tool_pmu__has_start_times(ev)) {
+ xyarray__delete(evsel->process_time.start_times);
+ xyarray__delete(evsel->process_time.accumulated_times);
+ evsel->process_time.start_times = NULL;
+ evsel->process_time.accumulated_times = NULL;
+ }
+}
+
struct perf_pmu *tool_pmu__new(void)
{
struct perf_pmu *tool = zalloc(sizeof(struct perf_pmu));
diff --git a/tools/perf/util/tool_pmu.h b/tools/perf/util/tool_pmu.h
index 99a2ea1548f8..f972995bb8ed 100644
--- a/tools/perf/util/tool_pmu.h
+++ b/tools/perf/util/tool_pmu.h
@@ -50,6 +50,22 @@ enum tool_pmu_event {
TOOL_PMU__EVENT_MEMORY_SWAP_PSS,
TOOL_PMU__EVENT_MEMORY_TEXT,
TOOL_PMU__EVENT_MEMORY_USS,
+ TOOL_PMU__EVENT_NET_RX_BYTES,
+ TOOL_PMU__EVENT_NET_RX_PACKETS,
+ TOOL_PMU__EVENT_NET_RX_ERRORS,
+ TOOL_PMU__EVENT_NET_RX_DROP,
+ TOOL_PMU__EVENT_NET_RX_FIFO,
+ TOOL_PMU__EVENT_NET_RX_FRAME,
+ TOOL_PMU__EVENT_NET_RX_COMPRESSED,
+ TOOL_PMU__EVENT_NET_RX_MULTICAST,
+ TOOL_PMU__EVENT_NET_TX_BYTES,
+ TOOL_PMU__EVENT_NET_TX_PACKETS,
+ TOOL_PMU__EVENT_NET_TX_ERRORS,
+ TOOL_PMU__EVENT_NET_TX_DROP,
+ TOOL_PMU__EVENT_NET_TX_FIFO,
+ TOOL_PMU__EVENT_NET_TX_COLLS,
+ TOOL_PMU__EVENT_NET_TX_CARRIER,
+ TOOL_PMU__EVENT_NET_TX_COMPRESSED,
TOOL_PMU__EVENT_MAX,
};
@@ -87,6 +103,7 @@ int evsel__tool_pmu_enable(struct evsel *evsel);
int evsel__tool_pmu_disable_cpu(struct evsel *evsel, int cpu_map_idx);
int evsel__tool_pmu_disable(struct evsel *evsel);
int evsel__tool_pmu_read(struct evsel *evsel, int cpu_map_idx, int thread);
+void evsel__tool_pmu_exit(struct evsel *evsel);
struct perf_pmu *tool_pmu__new(void);
--
2.56.1.703.gf848ed807c-goog
^ permalink raw reply [flat|nested] 5+ messages in thread* [PATCH v2 3/4] perf tool_pmu: Add schedstat events
2026-11-13 23:37 [PATCH v2 0/4] perf tool_pmu: Add procfs memory, network and schedstat events Ian Rogers
2026-11-13 23:37 ` [PATCH v2 1/4] perf tool_pmu: Add memory events Ian Rogers
2026-11-13 23:37 ` [PATCH v2 2/4] perf tool_pmu: Add network events Ian Rogers
@ 2026-11-13 23:37 ` Ian Rogers
2026-11-13 23:37 ` [PATCH v2 4/4] perf test tool_pmu: Add memory, network and schedstat tests Ian Rogers
3 siblings, 0 replies; 5+ messages in thread
From: Ian Rogers @ 2026-11-13 23:37 UTC (permalink / raw)
To: Peter Zijlstra, Ingo Molnar, Arnaldo Carvalho de Melo,
Namhyung Kim, Jiri Olsa, Ian Rogers, Adrian Hunter, James Clark,
Thomas Falcon, Thomas Richter, linux-perf-users, linux-kernel
Cc: Andi Kleen
Add per-CPU tool PMU events backed by /proc/schedstat runqueue
statistics:
- schedstat_yield: Calls to sched_yield().
- schedstat_schedule: Calls to schedule().
- schedstat_schedule_idle: Calls to schedule() leaving the CPU idle.
- schedstat_wake: Calls to try_to_wake_up().
- schedstat_wake_local: Calls to try_to_wake_up() for the local CPU.
- schedstat_runtime: Task runtime on this CPU in nanoseconds.
- schedstat_wait: Task runqueue wait time on this CPU in nanoseconds.
- schedstat_timeslices: Number of timeslices run on this CPU.
Because /proc/schedstat reports per-CPU runqueue counters, reject
per-process and cgroup modes, exclude schedstat events from
perf_pmu__reads_only_on_cpu_idx0(), and update should_skip_zero_counter()
so zero-valued per-CPU tool events are not suppressed on CPUs > 0. Track
initial and accumulated values across enable/disable transitions to
report deltas over the measurement interval.
Example system-wide and per-CPU output:
$ perf stat -a -e schedstat_yield,schedstat_schedule \
-e schedstat_runtime,schedstat_wait,schedstat_timeslices sleep 0.1
Performance counter stats for 'system wide':
0 schedstat_yield
0 schedstat_schedule
455,566,105 schedstat_runtime
348,262 schedstat_wait
63,336 schedstat_timeslices
0.112807668 seconds time elapsed
$ perf stat -A -C 0,1 -e schedstat_schedule,schedstat_runtime \
-e schedstat_wait,schedstat_timeslices sleep 0.1
Performance counter stats for 'CPU(s) 0,1':
CPU0 0 tool/schedstat_schedule/
CPU1 0 tool/schedstat_schedule/
CPU0 6,217,341 tool/schedstat_runtime/
CPU1 25,243,949 tool/schedstat_runtime/
CPU0 11,005 tool/schedstat_wait/
CPU1 20,921 tool/schedstat_wait/
CPU0 115 tool/schedstat_timeslices/
CPU1 3,535 tool/schedstat_timeslices/
0.101808548 seconds time elapsed
Signed-off-by: Ian Rogers <irogers@google.com>
---
.../pmu-events/arch/common/common/tool.json | 48 ++++
tools/perf/pmu-events/empty-pmu-events.c | 254 ++++++++++--------
tools/perf/util/pmu.c | 4 +-
tools/perf/util/stat-display.c | 8 +-
tools/perf/util/tool_pmu.c | 133 ++++++++-
tools/perf/util/tool_pmu.h | 9 +
6 files changed, 340 insertions(+), 116 deletions(-)
diff --git a/tools/perf/pmu-events/arch/common/common/tool.json b/tools/perf/pmu-events/arch/common/common/tool.json
index a332cbf842f7..7c6e03055ca3 100644
--- a/tools/perf/pmu-events/arch/common/common/tool.json
+++ b/tools/perf/pmu-events/arch/common/common/tool.json
@@ -334,5 +334,53 @@
"EventName": "net_tx_compressed",
"BriefDescription": "System-wide network transmitted compressed packets",
"ConfigCode": "56"
+ },
+ {
+ "Unit": "tool",
+ "EventName": "schedstat_yield",
+ "BriefDescription": "Number of times sched_yield() was called",
+ "ConfigCode": "57"
+ },
+ {
+ "Unit": "tool",
+ "EventName": "schedstat_schedule",
+ "BriefDescription": "Number of times schedule() was called",
+ "ConfigCode": "58"
+ },
+ {
+ "Unit": "tool",
+ "EventName": "schedstat_schedule_idle",
+ "BriefDescription": "Number of times schedule() left the processor idle",
+ "ConfigCode": "59"
+ },
+ {
+ "Unit": "tool",
+ "EventName": "schedstat_wake",
+ "BriefDescription": "Number of times try_to_wake_up() was called",
+ "ConfigCode": "60"
+ },
+ {
+ "Unit": "tool",
+ "EventName": "schedstat_wake_local",
+ "BriefDescription": "Number of times try_to_wake_up() was called to wake up the local cpu",
+ "ConfigCode": "61"
+ },
+ {
+ "Unit": "tool",
+ "EventName": "schedstat_runtime",
+ "BriefDescription": "Sum of all time spent running by tasks on this processor (in nanoseconds)",
+ "ConfigCode": "62"
+ },
+ {
+ "Unit": "tool",
+ "EventName": "schedstat_wait",
+ "BriefDescription": "Sum of all time spent waiting to run by tasks on this processor (in nanoseconds)",
+ "ConfigCode": "63"
+ },
+ {
+ "Unit": "tool",
+ "EventName": "schedstat_timeslices",
+ "BriefDescription": "Number of timeslices run on this cpu",
+ "ConfigCode": "64"
}
]
diff --git a/tools/perf/pmu-events/empty-pmu-events.c b/tools/perf/pmu-events/empty-pmu-events.c
index 8705f32563a6..49e2d3f8b3f1 100644
--- a/tools/perf/pmu-events/empty-pmu-events.c
+++ b/tools/perf/pmu-events/empty-pmu-events.c
@@ -2628,116 +2628,132 @@ static const char *const big_c_string =
/* offset=130002 */
"net_tx_compressed\000tool\000System-wide network transmitted compressed packets\000config=0x38\000\00000\000\000\000\000\000"
/* offset=130096 */
+"schedstat_yield\000tool\000Number of times sched_yield() was called\000config=0x39\000\00000\000\000\000\000\000"
+/* offset=130178 */
+"schedstat_schedule\000tool\000Number of times schedule() was called\000config=0x3a\000\00000\000\000\000\000\000"
+/* offset=130260 */
+"schedstat_schedule_idle\000tool\000Number of times schedule() left the processor idle\000config=0x3b\000\00000\000\000\000\000\000"
+/* offset=130360 */
+"schedstat_wake\000tool\000Number of times try_to_wake_up() was called\000config=0x3c\000\00000\000\000\000\000\000"
+/* offset=130444 */
+"schedstat_wake_local\000tool\000Number of times try_to_wake_up() was called to wake up the local cpu\000config=0x3d\000\00000\000\000\000\000\000"
+/* offset=130559 */
+"schedstat_runtime\000tool\000Sum of all time spent running by tasks on this processor (in nanoseconds)\000config=0x3e\000\00000\000\000\000\000\000"
+/* offset=130676 */
+"schedstat_wait\000tool\000Sum of all time spent waiting to run by tasks on this processor (in nanoseconds)\000config=0x3f\000\00000\000\000\000\000\000"
+/* offset=130797 */
+"schedstat_timeslices\000tool\000Number of timeslices run on this cpu\000config=0x40\000\00000\000\000\000\000\000"
+/* offset=130880 */
"bp_l1_btb_correct\000branch\000L1 BTB Correction\000event=0x8a\000\00000\000\000\000\000\000"
-/* offset=130158 */
+/* offset=130942 */
"bp_l2_btb_correct\000branch\000L2 BTB Correction\000event=0x8b\000\00000\000\000\000\000\000"
-/* offset=130220 */
+/* offset=131004 */
"l3_cache_rd\000cache\000L3 cache access, read\000event=0x40\000\00000\000\000\000\000Attributable Level 3 cache access, read\000"
-/* offset=130318 */
+/* offset=131102 */
"segment_reg_loads.any\000other\000Number of segment register loads\000event=6,period=200000,umask=0x80\000\00000\000\000\000\000\000"
-/* offset=130420 */
+/* offset=131204 */
"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=130553 */
+/* offset=131337 */
"eist_trans\000other\000Number of Enhanced Intel SpeedStep(R) Technology (EIST) transitions\000event=0x3a,period=200000\000\00000\000\000\000\000\000"
-/* offset=130671 */
+/* offset=131455 */
"hisi_sccl,ddrc\000"
-/* offset=130686 */
+/* offset=131470 */
"uncore_hisi_ddrc.flux_wcmd\000uncore\000DDRC write commands\000event=2\000\00000\000\000\000\000\000"
-/* offset=130756 */
+/* offset=131540 */
"uncore_cbox\000"
-/* offset=130768 */
+/* offset=131552 */
"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=130922 */
+/* offset=131706 */
"event-hyphen\000uncore\000UNC_CBO_HYPHEN\000event=0xe0\000\00000\000\000\000\000\000"
-/* offset=130976 */
+/* offset=131760 */
"event-two-hyph\000uncore\000UNC_CBO_TWO_HYPH\000event=0xc0\000\00000\000\000\000\000\000"
-/* offset=131034 */
+/* offset=131818 */
"hisi_sccl,l3c\000"
-/* offset=131048 */
+/* offset=131832 */
"uncore_hisi_l3c.rd_hit_cpipe\000uncore\000Total read hits\000event=7\000\00000\000\000\000\000\000"
-/* offset=131116 */
+/* offset=131900 */
"uncore_imc_free_running\000"
-/* offset=131140 */
+/* offset=131924 */
"uncore_imc_free_running.cache_miss\000uncore\000Total cache misses\000event=0x12\000\00000\000\000\000\000\000"
-/* offset=131220 */
+/* offset=132004 */
"uncore_imc\000"
-/* offset=131231 */
+/* offset=132015 */
"uncore_imc.cache_hits\000uncore\000Total cache hits\000event=0x34\000\00000\000\000\000\000\000"
-/* offset=131296 */
+/* offset=132080 */
"uncore_sys_ddr_pmu\000"
-/* offset=131315 */
+/* offset=132099 */
"sys_ddr_pmu.write_cycles\000uncore\000ddr write-cycles event\000event=0x2b\000v8\00000\000\000\000\000\000"
-/* offset=131391 */
+/* offset=132175 */
"uncore_sys_ccn_pmu\000"
-/* offset=131410 */
+/* offset=132194 */
"sys_ccn_pmu.read_cycles\000uncore\000ccn read-cycles event\000config=0x2c\0000x01\00000\000\000\000\000\000"
-/* offset=131487 */
+/* offset=132271 */
"uncore_sys_cmn_pmu\000"
-/* offset=131506 */
+/* offset=132290 */
"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=131649 */
+/* offset=132433 */
"CPUs_utilized\000Default\000(software@cpu\\-clock\\,name\\=cpu\\-clock@ if #target_cpu else software@task\\-clock\\,name\\=task\\-clock@) / (duration_time * 1e9)\000\000Average CPU utilization\000\0001CPUs\000\000\000\000011"
-/* offset=131835 */
+/* offset=132619 */
"cs_per_second\000Default\000software@context\\-switches\\,name\\=context\\-switches@ * 1e9 / (software@cpu\\-clock\\,name\\=cpu\\-clock@ if #target_cpu else software@task\\-clock\\,name\\=task\\-clock@)\000\000Context switches per CPU second\000\0001cs/sec\000\000\000\000011"
-/* offset=132068 */
+/* offset=132852 */
"migrations_per_second\000Default\000software@cpu\\-migrations\\,name\\=cpu\\-migrations@ * 1e9 / (software@cpu\\-clock\\,name\\=cpu\\-clock@ if #target_cpu else software@task\\-clock\\,name\\=task\\-clock@)\000\000Process migrations to a new CPU per CPU second\000\0001migrations/sec\000\000\000\000011"
-/* offset=132328 */
+/* offset=133112 */
"page_faults_per_second\000Default\000software@page\\-faults\\,name\\=page\\-faults@ * 1e9 / (software@cpu\\-clock\\,name\\=cpu\\-clock@ if #target_cpu else software@task\\-clock\\,name\\=task\\-clock@)\000\000Page faults per CPU second\000\0001faults/sec\000\000\000\000011"
-/* offset=132559 */
+/* offset=133343 */
"insn_per_cycle\000Default\000instructions / cpu\\-cycles\000insn_per_cycle < 1\000Instructions Per Cycle\000\0001instructions\000\000\000\000001"
-/* offset=132672 */
+/* offset=133456 */
"stalled_cycles_per_instruction\000Default\000(max(stalled\\-cycles\\-frontend, stalled\\-cycles\\-backend) / instructions if has_event(stalled\\-cycles\\-frontend) & has_event(stalled\\-cycles\\-backend) else (stalled\\-cycles\\-frontend / instructions if has_event(stalled\\-cycles\\-frontend) else (stalled\\-cycles\\-backend / instructions if has_event(stalled\\-cycles\\-backend) else 0)))\000\000Max front or backend stalls per instruction\000\000\000\000\000\000001"
-/* offset=133097 */
+/* offset=133881 */
"frontend_cycles_idle\000Default\000(stalled\\-cycles\\-frontend / cpu\\-cycles if has_event(stalled\\-cycles\\-frontend) else 0)\000frontend_cycles_idle > 0.1\000Frontend stalls per cycle\000\000\000\000\000\000001"
-/* offset=133276 */
+/* offset=134060 */
"backend_cycles_idle\000Default\000(stalled\\-cycles\\-backend / cpu\\-cycles if has_event(stalled\\-cycles\\-backend) else 0)\000backend_cycles_idle > 0.2\000Backend stalls per cycle\000\000\000\000\000\000001"
-/* offset=133450 */
+/* offset=134234 */
"cycles_frequency\000Default\000cpu\\-cycles / (software@cpu\\-clock\\,name\\=cpu\\-clock@ if #target_cpu else software@task\\-clock\\,name\\=task\\-clock@)\000\000Cycles per CPU second\000\0001GHz\000\000\000\000011"
-/* offset=133626 */
+/* offset=134410 */
"branch_frequency\000Default\000branches / (software@cpu\\-clock\\,name\\=cpu\\-clock@ if #target_cpu else software@task\\-clock\\,name\\=task\\-clock@)\000\000Branches per CPU second\000\0001000M/sec\000\000\000\000011"
-/* offset=133806 */
+/* offset=134590 */
"branch_miss_rate\000Default\000branch\\-misses / branches\000branch_miss_rate > 0.05\000Branch miss rate\000\000100%\000\000\000\000001"
-/* offset=133910 */
+/* offset=134694 */
"l1d_miss_rate\000Default2\000L1\\-dcache\\-load\\-misses / L1\\-dcache\\-loads\000l1d_miss_rate > 0.05\000L1D miss rate\000\000100%\000\000\000\000001"
-/* offset=134026 */
+/* offset=134810 */
"llc_miss_rate\000Default2\000LLC\\-load\\-misses / LLC\\-loads\000llc_miss_rate > 0.05\000LLC miss rate\000\000100%\000\000\000\000001"
-/* offset=134127 */
+/* offset=134911 */
"l1i_miss_rate\000Default3\000L1\\-icache\\-load\\-misses / L1\\-icache\\-loads\000l1i_miss_rate > 0.05\000L1I miss rate\000\000100%\000\000\000\000001"
-/* offset=134242 */
+/* offset=135026 */
"dtlb_miss_rate\000Default3\000dTLB\\-load\\-misses / dTLB\\-loads\000dtlb_miss_rate > 0.05\000dTLB miss rate\000\000100%\000\000\000\000001"
-/* offset=134348 */
+/* offset=135132 */
"itlb_miss_rate\000Default3\000iTLB\\-load\\-misses / iTLB\\-loads\000itlb_miss_rate > 0.05\000iTLB miss rate\000\000100%\000\000\000\000001"
-/* offset=134454 */
+/* offset=135238 */
"l1_prefetch_miss_rate\000Default4\000L1\\-dcache\\-prefetch\\-misses / L1\\-dcache\\-prefetches\000l1_prefetch_miss_rate > 0.05\000L1 prefetch miss rate\000\000100%\000\000\000\000001"
-/* offset=134602 */
+/* offset=135386 */
"CPI\000\0001 / IPC\000\000\000\000\000\000\000\000000"
-/* offset=134625 */
+/* offset=135409 */
"IPC\000group1\000inst_retired.any / cpu_clk_unhalted.thread\000\000\000\000\000\000\000\000000"
-/* offset=134689 */
+/* offset=135473 */
"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\000000"
-/* offset=134856 */
+/* offset=135640 */
"dcache_miss_cpi\000\000l1d\\-loads\\-misses / inst_retired.any\000\000\000\000\000\000\000\000000"
-/* offset=134921 */
+/* offset=135705 */
"icache_miss_cycles\000\000l1i\\-loads\\-misses / inst_retired.any\000\000\000\000\000\000\000\000000"
-/* offset=134989 */
+/* offset=135773 */
"cache_miss_cycles\000group1\000dcache_miss_cpi + icache_miss_cycles\000\000\000\000\000\000\000\000000"
-/* offset=135061 */
+/* offset=135845 */
"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\000000"
-/* offset=135156 */
+/* offset=135940 */
"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\000000"
-/* offset=135291 */
+/* offset=136075 */
"DCache_L2_All\000\000DCache_L2_All_Hits + DCache_L2_All_Miss\000\000\000\000\000\000\000\000000"
-/* offset=135356 */
+/* offset=136140 */
"DCache_L2_Hits\000\000d_ratio(DCache_L2_All_Hits, DCache_L2_All)\000\000\000\000\000\000\000\000000"
-/* offset=135425 */
+/* offset=136209 */
"DCache_L2_Misses\000\000d_ratio(DCache_L2_All_Miss, DCache_L2_All)\000\000\000\000\000\000\000\000000"
-/* offset=135496 */
+/* offset=136280 */
"M1\000\000ipc + M2\000\000\000\000\000\000\000\000000"
-/* offset=135519 */
+/* offset=136303 */
"M2\000\000ipc + M1\000\000\000\000\000\000\000\000000"
-/* offset=135542 */
+/* offset=136326 */
"M3\000\0001 / M3\000\000\000\000\000\000\000\000000"
-/* offset=135563 */
+/* offset=136347 */
"L1D_Cache_Fill_BW\000\00064 * l1d.replacement / 1e9 / duration_time\000\000\000\000\000\000\000\000000"
;
@@ -5336,6 +5352,22 @@ static const struct compact_pmu_event pmu_events__common_tool[] = {
{ 125728 },
/* num_packages\000tool\000Number of packages. Each package has 1 or more die\000co... */
{ 125804 },
+ /* schedstat_runtime\000tool\000Sum of all time spent running by tasks on this proc... */
+ { 130559 },
+ /* schedstat_schedule\000tool\000Number of times schedule() was called\000config=0x... */
+ { 130178 },
+ /* schedstat_schedule_idle\000tool\000Number of times schedule() left the processor... */
+ { 130260 },
+ /* schedstat_timeslices\000tool\000Number of timeslices run on this cpu\000config=0... */
+ { 130797 },
+ /* schedstat_wait\000tool\000Sum of all time spent waiting to run by tasks on this ... */
+ { 130676 },
+ /* schedstat_wake\000tool\000Number of times try_to_wake_up() was called\000config=... */
+ { 130360 },
+ /* schedstat_wake_local\000tool\000Number of times try_to_wake_up() was called to w... */
+ { 130444 },
+ /* schedstat_yield\000tool\000Number of times sched_yield() was called\000config=0x... */
+ { 130096 },
/* slots\000tool\000Number of functional units that in parallel can execute parts o... */
{ 125890 },
/* smt_on\000tool\0001 if simultaneous multithreading (aka hyperthreading) is enabl... */
@@ -5371,39 +5403,39 @@ static const struct pmu_table_entry pmu_events__common[] = {
static const struct compact_pmu_event pmu_metrics__common_default_core[] = {
/* CPUs_utilized\000Default\000(software@cpu\\-clock\\,name\\=cpu\\-clock@ if #targ... */
- { 131649 },
+ { 132433 },
/* backend_cycles_idle\000Default\000(stalled\\-cycles\\-backend / cpu\\-cycles if ... */
- { 133276 },
+ { 134060 },
/* branch_frequency\000Default\000branches / (software@cpu\\-clock\\,name\\=cpu\\-c... */
- { 133626 },
+ { 134410 },
/* branch_miss_rate\000Default\000branch\\-misses / branches\000branch_miss_rate > ... */
- { 133806 },
+ { 134590 },
/* cs_per_second\000Default\000software@context\\-switches\\,name\\=context\\-switc... */
- { 131835 },
+ { 132619 },
/* cycles_frequency\000Default\000cpu\\-cycles / (software@cpu\\-clock\\,name\\=cpu... */
- { 133450 },
+ { 134234 },
/* dtlb_miss_rate\000Default3\000dTLB\\-load\\-misses / dTLB\\-loads\000dtlb_miss_r... */
- { 134242 },
+ { 135026 },
/* frontend_cycles_idle\000Default\000(stalled\\-cycles\\-frontend / cpu\\-cycles i... */
- { 133097 },
+ { 133881 },
/* insn_per_cycle\000Default\000instructions / cpu\\-cycles\000insn_per_cycle < 1\0... */
- { 132559 },
+ { 133343 },
/* itlb_miss_rate\000Default3\000iTLB\\-load\\-misses / iTLB\\-loads\000itlb_miss_r... */
- { 134348 },
+ { 135132 },
/* l1_prefetch_miss_rate\000Default4\000L1\\-dcache\\-prefetch\\-misses / L1\\-dcac... */
- { 134454 },
+ { 135238 },
/* l1d_miss_rate\000Default2\000L1\\-dcache\\-load\\-misses / L1\\-dcache\\-loads\0... */
- { 133910 },
+ { 134694 },
/* l1i_miss_rate\000Default3\000L1\\-icache\\-load\\-misses / L1\\-icache\\-loads\0... */
- { 134127 },
+ { 134911 },
/* llc_miss_rate\000Default2\000LLC\\-load\\-misses / LLC\\-loads\000llc_miss_rate ... */
- { 134026 },
+ { 134810 },
/* migrations_per_second\000Default\000software@cpu\\-migrations\\,name\\=cpu\\-mig... */
- { 132068 },
+ { 132852 },
/* page_faults_per_second\000Default\000software@page\\-faults\\,name\\=page\\-faul... */
- { 132328 },
+ { 133112 },
/* stalled_cycles_per_instruction\000Default\000(max(stalled\\-cycles\\-frontend, s... */
- { 132672 },
+ { 133456 },
};
@@ -5417,41 +5449,41 @@ static const struct pmu_table_entry pmu_metrics__common[] = {
static const struct compact_pmu_event pmu_events__test_soc_cpu_default_core[] = {
/* bp_l1_btb_correct\000branch\000L1 BTB Correction\000event=0x8a\000\00000\000\000... */
- { 130096 },
+ { 130880 },
/* bp_l2_btb_correct\000branch\000L2 BTB Correction\000event=0x8b\000\00000\000\000... */
- { 130158 },
+ { 130942 },
/* dispatch_blocked.any\000other\000Memory cluster signals to block micro-op dispat... */
- { 130420 },
+ { 131204 },
/* eist_trans\000other\000Number of Enhanced Intel SpeedStep(R) Technology (EIST) t... */
- { 130553 },
+ { 131337 },
/* l3_cache_rd\000cache\000L3 cache access, read\000event=0x40\000\00000\000\000\00... */
- { 130220 },
+ { 131004 },
/* segment_reg_loads.any\000other\000Number of segment register loads\000event=6,pe... */
- { 130318 },
+ { 131102 },
};
static const struct compact_pmu_event pmu_events__test_soc_cpu_hisi_sccl_ddrc[] = {
/* uncore_hisi_ddrc.flux_wcmd\000uncore\000DDRC write commands\000event=2\000\00000... */
- { 130686 },
+ { 131470 },
};
static const struct compact_pmu_event pmu_events__test_soc_cpu_hisi_sccl_l3c[] = {
/* uncore_hisi_l3c.rd_hit_cpipe\000uncore\000Total read hits\000event=7\000\00000\0... */
- { 131048 },
+ { 131832 },
};
static const struct compact_pmu_event pmu_events__test_soc_cpu_uncore_cbox[] = {
/* event-hyphen\000uncore\000UNC_CBO_HYPHEN\000event=0xe0\000\00000\000\000\000\000... */
- { 130922 },
+ { 131706 },
/* event-two-hyph\000uncore\000UNC_CBO_TWO_HYPH\000event=0xc0\000\00000\000\000\000... */
- { 130976 },
+ { 131760 },
/* unc_cbo_xsnp_response.miss_eviction\000uncore\000A cross-core snoop resulted fro... */
- { 130768 },
+ { 131552 },
};
static const struct compact_pmu_event pmu_events__test_soc_cpu_uncore_imc[] = {
/* uncore_imc.cache_hits\000uncore\000Total cache hits\000event=0x34\000\00000\000\... */
- { 131231 },
+ { 132015 },
};
static const struct compact_pmu_event pmu_events__test_soc_cpu_uncore_imc_free_running[] = {
/* uncore_imc_free_running.cache_miss\000uncore\000Total cache misses\000event=0x12... */
- { 131140 },
+ { 131924 },
};
@@ -5464,61 +5496,61 @@ static const struct pmu_table_entry pmu_events__test_soc_cpu[] = {
{
.entries = pmu_events__test_soc_cpu_hisi_sccl_ddrc,
.num_entries = ARRAY_SIZE(pmu_events__test_soc_cpu_hisi_sccl_ddrc),
- .pmu_name = { 130671 /* hisi_sccl,ddrc\000 */ },
+ .pmu_name = { 131455 /* 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 = { 131034 /* hisi_sccl,l3c\000 */ },
+ .pmu_name = { 131818 /* 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 = { 130756 /* uncore_cbox\000 */ },
+ .pmu_name = { 131540 /* uncore_cbox\000 */ },
},
{
.entries = pmu_events__test_soc_cpu_uncore_imc,
.num_entries = ARRAY_SIZE(pmu_events__test_soc_cpu_uncore_imc),
- .pmu_name = { 131220 /* uncore_imc\000 */ },
+ .pmu_name = { 132004 /* 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 = { 131116 /* uncore_imc_free_running\000 */ },
+ .pmu_name = { 131900 /* uncore_imc_free_running\000 */ },
},
};
static const struct compact_pmu_event pmu_metrics__test_soc_cpu_default_core[] = {
/* CPI\000\0001 / IPC\000\000\000\000\000\000\000\000000 */
- { 134602 },
+ { 135386 },
/* DCache_L2_All\000\000DCache_L2_All_Hits + DCache_L2_All_Miss\000\000\000\000\000... */
- { 135291 },
+ { 136075 },
/* DCache_L2_All_Hits\000\000l2_rqsts.demand_data_rd_hit + l2_rqsts.pf_hit + l2_rqs... */
- { 135061 },
+ { 135845 },
/* DCache_L2_All_Miss\000\000max(l2_rqsts.all_demand_data_rd - l2_rqsts.demand_data... */
- { 135156 },
+ { 135940 },
/* DCache_L2_Hits\000\000d_ratio(DCache_L2_All_Hits, DCache_L2_All)\000\000\000\000... */
- { 135356 },
+ { 136140 },
/* DCache_L2_Misses\000\000d_ratio(DCache_L2_All_Miss, DCache_L2_All)\000\000\000\0... */
- { 135425 },
+ { 136209 },
/* Frontend_Bound_SMT\000\000idq_uops_not_delivered.core / (4 * (cpu_clk_unhalted.t... */
- { 134689 },
+ { 135473 },
/* IPC\000group1\000inst_retired.any / cpu_clk_unhalted.thread\000\000\000\000\000\... */
- { 134625 },
+ { 135409 },
/* L1D_Cache_Fill_BW\000\00064 * l1d.replacement / 1e9 / duration_time\000\000\000\... */
- { 135563 },
+ { 136347 },
/* M1\000\000ipc + M2\000\000\000\000\000\000\000\000000 */
- { 135496 },
+ { 136280 },
/* M2\000\000ipc + M1\000\000\000\000\000\000\000\000000 */
- { 135519 },
+ { 136303 },
/* M3\000\0001 / M3\000\000\000\000\000\000\000\000000 */
- { 135542 },
+ { 136326 },
/* cache_miss_cycles\000group1\000dcache_miss_cpi + icache_miss_cycles\000\000\000\... */
- { 134989 },
+ { 135773 },
/* dcache_miss_cpi\000\000l1d\\-loads\\-misses / inst_retired.any\000\000\000\000\0... */
- { 134856 },
+ { 135640 },
/* icache_miss_cycles\000\000l1i\\-loads\\-misses / inst_retired.any\000\000\000\00... */
- { 134921 },
+ { 135705 },
};
@@ -5532,15 +5564,15 @@ static const struct pmu_table_entry pmu_metrics__test_soc_cpu[] = {
static const struct compact_pmu_event pmu_events__test_soc_sys_uncore_sys_ccn_pmu[] = {
/* sys_ccn_pmu.read_cycles\000uncore\000ccn read-cycles event\000config=0x2c\0000x0... */
- { 131410 },
+ { 132194 },
};
static const struct compact_pmu_event pmu_events__test_soc_sys_uncore_sys_cmn_pmu[] = {
/* sys_cmn_pmu.hnf_cache_miss\000uncore\000Counts total cache misses in first looku... */
- { 131506 },
+ { 132290 },
};
static const struct compact_pmu_event pmu_events__test_soc_sys_uncore_sys_ddr_pmu[] = {
/* sys_ddr_pmu.write_cycles\000uncore\000ddr write-cycles event\000event=0x2b\000v8... */
- { 131315 },
+ { 132099 },
};
@@ -5548,17 +5580,17 @@ static 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 = { 131391 /* uncore_sys_ccn_pmu\000 */ },
+ .pmu_name = { 132175 /* 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 = { 131487 /* uncore_sys_cmn_pmu\000 */ },
+ .pmu_name = { 132271 /* 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 = { 131296 /* uncore_sys_ddr_pmu\000 */ },
+ .pmu_name = { 132080 /* uncore_sys_ddr_pmu\000 */ },
},
};
diff --git a/tools/perf/util/pmu.c b/tools/perf/util/pmu.c
index 01753d5c69d1..f4560a0ec1db 100644
--- a/tools/perf/util/pmu.c
+++ b/tools/perf/util/pmu.c
@@ -2830,5 +2830,7 @@ bool perf_pmu__reads_only_on_cpu_idx0(const struct perf_event_attr *attr)
return false;
event = (enum tool_pmu_event)attr->config;
- return event != TOOL_PMU__EVENT_USER_TIME && event != TOOL_PMU__EVENT_SYSTEM_TIME;
+ return event != TOOL_PMU__EVENT_USER_TIME &&
+ event != TOOL_PMU__EVENT_SYSTEM_TIME &&
+ !tool_pmu__is_sched_stat_event(event);
}
diff --git a/tools/perf/util/stat-display.c b/tools/perf/util/stat-display.c
index b337cc23f413..6671403c587c 100644
--- a/tools/perf/util/stat-display.c
+++ b/tools/perf/util/stat-display.c
@@ -929,9 +929,13 @@ static bool should_skip_zero_counter(struct perf_stat_config *config,
* system_time, but for many the first index is the only one used, for
* example num_cores. Don't skip for the first index.
*/
- if (evsel__is_tool(counter)) {
+ if (evsel__is_tool(counter) &&
+ (counter->core.reads_only_on_cpu_idx0 || counter->pid_stat)) {
+ struct perf_cpu first_cpu = perf_cpu_map__cpu(counter->core.cpus, 0);
struct aggr_cpu_id own_id =
- config->aggr_get_id(config, (struct perf_cpu){ .cpu = 0 });
+ config->aggr_get_id(config,
+ first_cpu.cpu >= 0 ? first_cpu
+ : (struct perf_cpu){ .cpu = 0 });
return !aggr_cpu_id__equal(id, &own_id);
}
diff --git a/tools/perf/util/tool_pmu.c b/tools/perf/util/tool_pmu.c
index 655b22104320..b92aaf0d7671 100644
--- a/tools/perf/util/tool_pmu.c
+++ b/tools/perf/util/tool_pmu.c
@@ -84,6 +84,14 @@ static const char *const tool_pmu__event_names[TOOL_PMU__EVENT_MAX] = {
"net_tx_colls",
"net_tx_carrier",
"net_tx_compressed",
+ "schedstat_yield",
+ "schedstat_schedule",
+ "schedstat_schedule_idle",
+ "schedstat_wake",
+ "schedstat_wake_local",
+ "schedstat_runtime",
+ "schedstat_wait",
+ "schedstat_timeslices",
};
bool tool_pmu__skip_event(const char *name __maybe_unused)
@@ -205,6 +213,83 @@ static int read_stat_field(int fd, struct perf_cpu cpu, int field, __u64 *val)
return -EINVAL;
}
+bool tool_pmu__is_sched_stat_event(enum tool_pmu_event ev)
+{
+ return ev >= TOOL_PMU__EVENT_SCHEDSTAT_YIELD &&
+ ev <= TOOL_PMU__EVENT_SCHEDSTAT_TIMESLICES;
+}
+
+static int sched_stat_event_to_field(enum tool_pmu_event ev)
+{
+ if (!tool_pmu__is_sched_stat_event(ev))
+ return -EINVAL;
+ if (ev == TOOL_PMU__EVENT_SCHEDSTAT_YIELD)
+ return 1;
+ /* Field 2 is legacy 0 in /proc/schedstat v15+. */
+ return (ev - TOOL_PMU__EVENT_SCHEDSTAT_YIELD) + 2;
+}
+
+static int read_sched_stat(int fd, struct perf_cpu cpu, enum tool_pmu_event ev, __u64 *val)
+{
+ int field = sched_stat_event_to_field(ev);
+ char buf[4096];
+ struct io io;
+ int ch;
+
+ if (field < 0)
+ return field;
+
+ io__init(&io, fd, buf, sizeof(buf));
+ lseek(fd, 0, SEEK_SET);
+
+ /* Search for "cpu<N> " */
+ while ((ch = io__get_char(&io)) != -1) {
+ __u64 cpu_num;
+ int i = 1, c;
+
+ if (ch != 'c') {
+ if (ch != '\n')
+ read_until_char(&io, '\n');
+ continue;
+ }
+ c = io__get_char(&io);
+ if (c != 'p') {
+ if (c != '\n' && c != -1)
+ read_until_char(&io, '\n');
+ continue;
+ }
+ c = io__get_char(&io);
+ if (c != 'u') {
+ if (c != '\n' && c != -1)
+ read_until_char(&io, '\n');
+ continue;
+ }
+ c = io__get_dec(&io, &cpu_num);
+ if (c != ' ' || (int)cpu_num != cpu.cpu) {
+ if (c != '\n' && c != -1)
+ read_until_char(&io, '\n');
+ continue;
+ }
+
+ /* Found our CPU. Now read the field. */
+ while (true) {
+ __u64 v;
+ int sep = io__get_dec(&io, &v);
+
+ if (sep < 0)
+ return -EINVAL;
+ if (i == field) {
+ *val = v;
+ return 0;
+ }
+ if (sep == '\n')
+ return -EINVAL; /* Field not found on line */
+ i++;
+ }
+ }
+ return -EINVAL;
+}
+
static int read_pid_stat_field(int fd, int field, __u64 *val)
{
char buf[256];
@@ -303,6 +388,14 @@ static const char *tool_pmu__memory_event_to_key(enum tool_pmu_event ev)
case TOOL_PMU__EVENT_NET_TX_COLLS:
case TOOL_PMU__EVENT_NET_TX_CARRIER:
case TOOL_PMU__EVENT_NET_TX_COMPRESSED:
+ case TOOL_PMU__EVENT_SCHEDSTAT_YIELD:
+ case TOOL_PMU__EVENT_SCHEDSTAT_SCHEDULE:
+ case TOOL_PMU__EVENT_SCHEDSTAT_SCHEDULE_IDLE:
+ case TOOL_PMU__EVENT_SCHEDSTAT_WAKE:
+ case TOOL_PMU__EVENT_SCHEDSTAT_WAKE_LOCAL:
+ case TOOL_PMU__EVENT_SCHEDSTAT_RUNTIME:
+ case TOOL_PMU__EVENT_SCHEDSTAT_WAIT:
+ case TOOL_PMU__EVENT_SCHEDSTAT_TIMESLICES:
case TOOL_PMU__EVENT_DURATION_TIME:
case TOOL_PMU__EVENT_USER_TIME:
case TOOL_PMU__EVENT_SYSTEM_TIME:
@@ -477,7 +570,8 @@ static bool tool_pmu__has_start_times(enum tool_pmu_event ev)
{
return ev == TOOL_PMU__EVENT_USER_TIME ||
ev == TOOL_PMU__EVENT_SYSTEM_TIME ||
- tool_pmu__is_net_event(ev);
+ tool_pmu__is_net_event(ev) ||
+ tool_pmu__is_sched_stat_event(ev);
}
static int read_net_dev_col(struct io *io, __u64 *val, int *term)
@@ -609,6 +703,16 @@ static int tool_pmu__read_stat(struct evsel *evsel, int cpu_map_idx, int thread,
return 0;
}
+ if (tool_pmu__is_sched_stat_event(ev)) {
+ if (thread == 0) {
+ struct perf_cpu cpu = perf_cpu_map__cpu(evsel->core.cpus, cpu_map_idx);
+
+ return read_sched_stat(fd, cpu, ev, val);
+ }
+ *val = 0;
+ return 0;
+ }
+
lseek(fd, 0, SEEK_SET);
if (evsel->pid_stat) {
if (cpu_map_idx == 0)
@@ -702,6 +806,15 @@ static int evsel__tool_pmu_open_one(struct evsel *evsel, enum tool_pmu_event ev,
if (fd < 0)
return -errno;
}
+ } else if (tool_pmu__is_sched_stat_event(ev)) {
+ if (pid > -1 || evsel->cgrp)
+ return -EINVAL;
+ if (thread == 0) {
+ snprintf(buf, sizeof(buf), "%s/schedstat", procfs__mountpoint());
+ fd = open(buf, O_RDONLY);
+ if (fd < 0)
+ return -errno;
+ }
} else {
if (pid > -1) {
snprintf(buf, sizeof(buf), "%s/%d/stat", procfs__mountpoint(), pid);
@@ -1005,6 +1118,14 @@ bool tool_pmu__read_event(enum tool_pmu_event ev,
case TOOL_PMU__EVENT_NET_TX_COLLS:
case TOOL_PMU__EVENT_NET_TX_CARRIER:
case TOOL_PMU__EVENT_NET_TX_COMPRESSED:
+ case TOOL_PMU__EVENT_SCHEDSTAT_YIELD:
+ case TOOL_PMU__EVENT_SCHEDSTAT_SCHEDULE:
+ case TOOL_PMU__EVENT_SCHEDSTAT_SCHEDULE_IDLE:
+ case TOOL_PMU__EVENT_SCHEDSTAT_WAKE:
+ case TOOL_PMU__EVENT_SCHEDSTAT_WAKE_LOCAL:
+ case TOOL_PMU__EVENT_SCHEDSTAT_RUNTIME:
+ case TOOL_PMU__EVENT_SCHEDSTAT_WAIT:
+ case TOOL_PMU__EVENT_SCHEDSTAT_TIMESLICES:
case TOOL_PMU__EVENT_NONE:
case TOOL_PMU__EVENT_DURATION_TIME:
case TOOL_PMU__EVENT_USER_TIME:
@@ -1261,7 +1382,15 @@ int evsel__tool_pmu_read(struct evsel *evsel, int cpu_map_idx, int thread)
case TOOL_PMU__EVENT_NET_TX_FIFO:
case TOOL_PMU__EVENT_NET_TX_COLLS:
case TOOL_PMU__EVENT_NET_TX_CARRIER:
- case TOOL_PMU__EVENT_NET_TX_COMPRESSED: {
+ case TOOL_PMU__EVENT_NET_TX_COMPRESSED:
+ case TOOL_PMU__EVENT_SCHEDSTAT_YIELD:
+ case TOOL_PMU__EVENT_SCHEDSTAT_SCHEDULE:
+ case TOOL_PMU__EVENT_SCHEDSTAT_SCHEDULE_IDLE:
+ case TOOL_PMU__EVENT_SCHEDSTAT_WAKE:
+ case TOOL_PMU__EVENT_SCHEDSTAT_WAKE_LOCAL:
+ case TOOL_PMU__EVENT_SCHEDSTAT_RUNTIME:
+ case TOOL_PMU__EVENT_SCHEDSTAT_WAIT:
+ case TOOL_PMU__EVENT_SCHEDSTAT_TIMESLICES: {
__u64 *accumulated_ptr = evsel->process_time.accumulated_times ?
xyarray__entry(evsel->process_time.accumulated_times, cpu_map_idx, thread) :
NULL;
diff --git a/tools/perf/util/tool_pmu.h b/tools/perf/util/tool_pmu.h
index f972995bb8ed..5a290a9e7555 100644
--- a/tools/perf/util/tool_pmu.h
+++ b/tools/perf/util/tool_pmu.h
@@ -66,6 +66,14 @@ enum tool_pmu_event {
TOOL_PMU__EVENT_NET_TX_COLLS,
TOOL_PMU__EVENT_NET_TX_CARRIER,
TOOL_PMU__EVENT_NET_TX_COMPRESSED,
+ TOOL_PMU__EVENT_SCHEDSTAT_YIELD,
+ TOOL_PMU__EVENT_SCHEDSTAT_SCHEDULE,
+ TOOL_PMU__EVENT_SCHEDSTAT_SCHEDULE_IDLE,
+ TOOL_PMU__EVENT_SCHEDSTAT_WAKE,
+ TOOL_PMU__EVENT_SCHEDSTAT_WAKE_LOCAL,
+ TOOL_PMU__EVENT_SCHEDSTAT_RUNTIME,
+ TOOL_PMU__EVENT_SCHEDSTAT_WAIT,
+ TOOL_PMU__EVENT_SCHEDSTAT_TIMESLICES,
TOOL_PMU__EVENT_MAX,
};
@@ -77,6 +85,7 @@ const char *tool_pmu__event_to_str(enum tool_pmu_event ev);
enum tool_pmu_event tool_pmu__str_to_event(const char *str);
bool tool_pmu__skip_event(const char *name);
int tool_pmu__num_skip_events(void);
+bool tool_pmu__is_sched_stat_event(enum tool_pmu_event ev);
bool tool_pmu__read_event(enum tool_pmu_event ev,
struct evsel *evsel,
--
2.56.1.703.gf848ed807c-goog
^ permalink raw reply [flat|nested] 5+ messages in thread* [PATCH v2 4/4] perf test tool_pmu: Add memory, network and schedstat tests
2026-11-13 23:37 [PATCH v2 0/4] perf tool_pmu: Add procfs memory, network and schedstat events Ian Rogers
` (2 preceding siblings ...)
2026-11-13 23:37 ` [PATCH v2 3/4] perf tool_pmu: Add schedstat events Ian Rogers
@ 2026-11-13 23:37 ` Ian Rogers
3 siblings, 0 replies; 5+ messages in thread
From: Ian Rogers @ 2026-11-13 23:37 UTC (permalink / raw)
To: Peter Zijlstra, Ingo Molnar, Arnaldo Carvalho de Melo,
Namhyung Kim, Jiri Olsa, Ian Rogers, Adrian Hunter, James Clark,
Thomas Falcon, Thomas Richter, linux-perf-users, linux-kernel
Cc: Andi Kleen
Extend the Tool PMU unit test suite with subtests covering:
- Per-process, multi-threaded Tgid deduplication, and system-wide reading
of memory events (smaps_rollup and statm).
- Per-process open rejection (-EINVAL) and synthetic /proc/net/dev
parsing (including space-padded and unpadded columns) across
enable/disable transitions for network events.
- Per-process open rejection (-EINVAL) and per-CPU synthetic
/proc/schedstat delta accumulation across enable/disable transitions
for schedstat events.
- Mixed CPU-map tool groups ({schedstat_yield,net_rx_bytes} and
{net_rx_bytes,schedstat_yield}) across evlist__enable() and
evlist__disable().
Signed-off-by: Ian Rogers <irogers@google.com>
---
tools/perf/tests/tool_pmu.c | 689 ++++++++++++++++++++++++++++++++++++
1 file changed, 689 insertions(+)
diff --git a/tools/perf/tests/tool_pmu.c b/tools/perf/tests/tool_pmu.c
index 667160f9e2cd..783aa13abe40 100644
--- a/tools/perf/tests/tool_pmu.c
+++ b/tools/perf/tests/tool_pmu.c
@@ -1,14 +1,20 @@
// SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause)
#include <errno.h>
#include <fcntl.h>
+#include <pthread.h>
+#include <stdio.h>
+#include <stdlib.h>
#include <string.h>
+#include <sys/types.h>
#include <unistd.h>
#include <internal/xyarray.h>
+#include "counts.h"
#include "cpumap.h"
#include "debug.h"
#include "evlist.h"
#include "evsel.h"
#include "parse-events.h"
+#include "target.h"
#include "tests.h"
#include "thread_map.h"
#include "tool_pmu.h"
@@ -178,10 +184,693 @@ static int test__tool_pmu_incremental_open_unwind(struct test_suite *test __mayb
return ret;
}
+static int write_temp_file(int fd, const char *contents)
+{
+ size_t len = strlen(contents);
+
+ if (ftruncate(fd, 0) < 0)
+ return -1;
+ if (lseek(fd, 0, SEEK_SET) < 0)
+ return -1;
+ if ((size_t)write(fd, contents, len) != len)
+ return -1;
+ return 0;
+}
+
+struct sleeper_thread_args {
+ int ready_fd;
+ int stop_fd;
+};
+
+static void *sleeper_thread_fn(void *arg)
+{
+ struct sleeper_thread_args *args = arg;
+ char ch = '1';
+
+ if (write(args->ready_fd, &ch, 1) == 1) {
+ while (read(args->stop_fd, &ch, 1) < 0 && errno == EINTR)
+ ;
+ }
+ return NULL;
+}
+
+static int check_multithread_memory_dedup(struct perf_cpu_map *cpus)
+{
+ struct evlist *evlist = NULL;
+ struct perf_thread_map *mt_threads = NULL;
+ struct parse_events_error err;
+ struct sleeper_thread_args args;
+ struct evsel *evsel;
+ int ready_pipe[2] = { -1, -1 }, stop_pipe[2] = { -1, -1 };
+ pthread_t th;
+ bool th_started = false;
+ int nthreads, non_zero = 0, ret = TEST_FAIL;
+ u64 total_rss = 0;
+ char ch;
+
+ if (pipe(ready_pipe) < 0 || pipe(stop_pipe) < 0)
+ goto out;
+
+ args.ready_fd = ready_pipe[1];
+ args.stop_fd = stop_pipe[0];
+ if (pthread_create(&th, NULL, sleeper_thread_fn, &args) != 0)
+ goto out;
+ th_started = true;
+
+ if (read(ready_pipe[0], &ch, 1) != 1)
+ goto out;
+
+ mt_threads = thread_map__new_by_pid(getpid());
+ nthreads = perf_thread_map__nr(mt_threads);
+ if (!mt_threads || nthreads < 2) {
+ pr_debug("Expected >= 2 threads for getpid(), got %d\n", nthreads);
+ goto out;
+ }
+
+ evlist = evlist__new();
+ if (!evlist)
+ goto out;
+
+ parse_events_error__init(&err);
+ if (parse_events(evlist, "memory_rss", &err)) {
+ parse_events_error__exit(&err);
+ goto out;
+ }
+ parse_events_error__exit(&err);
+
+ perf_evlist__set_maps(evlist__core(evlist), cpus, mt_threads);
+ evsel = evlist__first(evlist);
+ if (evsel__alloc_counts(evsel) < 0 ||
+ evsel__open(evsel, cpus, mt_threads) < 0)
+ goto out;
+
+ for (int t = 0; t < nthreads; t++) {
+ u64 val;
+
+ if (evsel__read_counter(evsel, 0, t) < 0)
+ goto out;
+ val = perf_counts(evsel->counts, 0, t)->val;
+ if (val > 0)
+ non_zero++;
+ total_rss += val;
+ }
+
+ if (non_zero != 1 || total_rss == 0) {
+ pr_debug("Expected 1 non-zero thread slot for memory_rss, got %d (sum=%llu)\n",
+ non_zero, (unsigned long long)total_rss);
+ goto out;
+ }
+
+ ret = TEST_OK;
+out:
+ if (stop_pipe[1] >= 0) {
+ close(stop_pipe[1]);
+ stop_pipe[1] = -1;
+ }
+ if (th_started)
+ pthread_join(th, NULL);
+ if (ready_pipe[0] >= 0)
+ close(ready_pipe[0]);
+ if (ready_pipe[1] >= 0)
+ close(ready_pipe[1]);
+ if (stop_pipe[0] >= 0)
+ close(stop_pipe[0]);
+ if (evlist) {
+ evlist__for_each_entry(evlist, evsel)
+ evsel__close(evsel);
+ evlist__put(evlist);
+ }
+ perf_thread_map__put(mt_threads);
+ return ret;
+}
+
+static int test__tool_pmu_memory_events(struct test_suite *test __maybe_unused,
+ int subtest __maybe_unused)
+{
+ struct evlist *evlist = evlist__new();
+ struct parse_events_error err;
+ struct perf_cpu_map *cpus = NULL;
+ struct perf_thread_map *threads = NULL, *sys_threads = NULL;
+ struct evsel *evsel;
+ u64 pid_rss = 0, pid_uss = 0, pid_size = 0, pid_text = 0, pid_data = 0;
+ u64 sys_size = 0;
+ const char *events =
+ "memory_rss,memory_uss,memory_size,memory_text,memory_data";
+ int ret = TEST_FAIL;
+
+ if (!evlist)
+ return TEST_FAIL;
+
+ parse_events_error__init(&err);
+ if (parse_events(evlist, events, &err)) {
+ parse_events_error__exit(&err);
+ evlist__put(evlist);
+ return TEST_FAIL;
+ }
+ parse_events_error__exit(&err);
+
+ cpus = perf_cpu_map__new_int(0);
+ threads = thread_map__new_by_tid(getpid());
+ if (!cpus || !threads)
+ goto out;
+ perf_evlist__set_maps(evlist__core(evlist), cpus, threads);
+
+ evlist__for_each_entry(evlist, evsel) {
+ enum tool_pmu_event ev = evsel__tool_event(evsel);
+ struct perf_counts_values *count;
+
+ if (evsel__alloc_counts(evsel) < 0)
+ goto out;
+ if (evsel__open(evsel, cpus, threads) < 0) {
+ pr_debug("Failed to open %s per-process\n", evsel__name(evsel));
+ goto out;
+ }
+ if (evsel__read_counter(evsel, 0, 0) < 0) {
+ pr_debug("Failed to read %s per-process\n", evsel__name(evsel));
+ goto out;
+ }
+ count = perf_counts(evsel->counts, 0, 0);
+ if (ev == TOOL_PMU__EVENT_MEMORY_RSS)
+ pid_rss = count->val;
+ else if (ev == TOOL_PMU__EVENT_MEMORY_USS)
+ pid_uss = count->val;
+ else if (ev == TOOL_PMU__EVENT_MEMORY_SIZE)
+ pid_size = count->val;
+ else if (ev == TOOL_PMU__EVENT_MEMORY_TEXT)
+ pid_text = count->val;
+ else if (ev == TOOL_PMU__EVENT_MEMORY_DATA)
+ pid_data = count->val;
+ else
+ goto out;
+ evsel__close(evsel);
+ }
+
+ if (pid_rss == 0 || pid_size < pid_rss || pid_uss > pid_rss ||
+ pid_text == 0 || pid_data == 0) {
+ pr_debug("Unexpected per-pid memory values: rss=%llu uss=%llu size=%llu text=%llu data=%llu\n",
+ (unsigned long long)pid_rss, (unsigned long long)pid_uss,
+ (unsigned long long)pid_size, (unsigned long long)pid_text,
+ (unsigned long long)pid_data);
+ goto out;
+ }
+
+ /* Verify system-wide aggregation on memory_size. */
+ sys_threads = perf_thread_map__new_dummy();
+ if (!sys_threads)
+ goto out;
+
+ evlist__for_each_entry(evlist, evsel) {
+ if (evsel__tool_event(evsel) != TOOL_PMU__EVENT_MEMORY_SIZE)
+ continue;
+ evsel->pid_stat = false;
+ evsel->core.system_wide = true;
+ if (evsel__open(evsel, cpus, sys_threads) < 0)
+ goto out;
+ if (evsel__read_counter(evsel, 0, 0) < 0)
+ goto out;
+ sys_size = perf_counts(evsel->counts, 0, 0)->val;
+ evsel__close(evsel);
+ }
+
+ if (sys_size < pid_size) {
+ pr_debug("System-wide memory_size (%llu) < pid memory_size (%llu)\n",
+ (unsigned long long)sys_size, (unsigned long long)pid_size);
+ goto out;
+ }
+
+ if (check_multithread_memory_dedup(cpus) != TEST_OK)
+ goto out;
+
+ ret = TEST_OK;
+out:
+ evlist__for_each_entry(evlist, evsel)
+ evsel__close(evsel);
+ perf_thread_map__put(sys_threads);
+ perf_thread_map__put(threads);
+ perf_cpu_map__put(cpus);
+ evlist__put(evlist);
+ return ret;
+}
+
+static int test__tool_pmu_net_events(struct test_suite *test __maybe_unused,
+ int subtest __maybe_unused)
+{
+ static const char snap1[] =
+ "Inter-| Receive | Transmit\n"
+ " face |bytes packets errs drop fifo frame compressed multicast|bytes packets...\n"
+ " lo: 1000 10 0 0 0 0 0 0 2000 20 0 0 0 0 0 5\n"
+ " eth0:123456789012 100 0 0 0 0 0 0 3000 30 0 0 0 0 0 7\n";
+ static const char snap2[] =
+ "Inter-| Receive | Transmit\n"
+ " face |bytes packets errs drop fifo frame compressed multicast|bytes packets...\n"
+ " lo: 1500 12 0 0 0 0 0 0 2250 20 0 0 0 0 0 8\n"
+ " eth0:123456789612 105 0 0 0 0 0 0 3750 30 0 0 0 0 0 11\n";
+ static const char snap3[] =
+ "Inter-| Receive | Transmit\n"
+ " face |bytes packets errs drop fifo frame compressed multicast|bytes packets...\n"
+ " lo: 9999 99 0 0 0 0 0 0 9999 99 0 0 0 0 0 99\n"
+ " eth0:123456799999 999 0 0 0 0 0 0 9999 99 0 0 0 0 0 99\n";
+ const char *events =
+ "net_rx_bytes,net_rx_packets,net_tx_bytes,net_tx_compressed";
+ char tmp_path[] = "/tmp/perf-tool-net-XXXXXX";
+ struct evlist *evlist = evlist__new();
+ struct parse_events_error err;
+ struct perf_cpu_map *cpus = NULL;
+ struct perf_thread_map *pid_threads = NULL, *sys_threads = NULL;
+ struct evsel *evsel;
+ int ret = TEST_FAIL, tmp_fd = -1;
+
+ if (!evlist)
+ return TEST_FAIL;
+
+ parse_events_error__init(&err);
+ if (parse_events(evlist, events, &err)) {
+ parse_events_error__exit(&err);
+ evlist__put(evlist);
+ return TEST_FAIL;
+ }
+ parse_events_error__exit(&err);
+
+ cpus = perf_cpu_map__new_int(0);
+ pid_threads = thread_map__new_by_tid(getpid());
+ sys_threads = perf_thread_map__new_dummy();
+ if (!cpus || !pid_threads || !sys_threads)
+ goto out;
+
+ /* Per-process open must fail with EINVAL. */
+ evsel = evlist__first(evlist);
+ errno = 0;
+ if (evsel__open(evsel, cpus, pid_threads) != -EINVAL || errno != EINVAL) {
+ pr_debug("Expected -EINVAL opening net_rx_bytes per-process\n");
+ goto out;
+ }
+
+ if (access("/proc/net/dev", R_OK) != 0) {
+ ret = TEST_SKIP;
+ goto out;
+ }
+
+ tmp_fd = mkstemp(tmp_path);
+ if (tmp_fd < 0)
+ goto out;
+ unlink(tmp_path);
+
+ if (write_temp_file(tmp_fd, snap1) < 0)
+ goto out;
+
+ evlist__for_each_entry(evlist, evsel) {
+ int fd;
+
+ evsel->supported = true;
+ evsel->core.system_wide = true;
+ evsel->core.attr.disabled = 1;
+ perf_cpu_map__put(evsel->core.cpus);
+ evsel->core.cpus = perf_cpu_map__get(cpus);
+ perf_thread_map__put(evsel->core.threads);
+ evsel->core.threads = perf_thread_map__get(sys_threads);
+ if (evsel__alloc_counts(evsel) < 0)
+ goto out;
+ if (evsel__open(evsel, cpus, sys_threads) < 0)
+ goto out;
+ fd = *(int *)xyarray__entry(evsel->core.fd, 0, 0);
+ if (fd < 0 || dup2(tmp_fd, fd) < 0)
+ goto out;
+
+ /* Reading while initially disabled must return 0. */
+ if (evsel__read_counter(evsel, 0, 0) < 0 ||
+ perf_counts(evsel->counts, 0, 0)->val != 0)
+ goto out;
+ if (evsel__enable(evsel) < 0)
+ goto out;
+ }
+
+ if (write_temp_file(tmp_fd, snap2) < 0)
+ goto out;
+
+ evlist__for_each_entry(evlist, evsel) {
+ if (evsel__disable(evsel) < 0)
+ goto out;
+ }
+
+ /* Traffic occurring while disabled must not change accumulated counts. */
+ if (write_temp_file(tmp_fd, snap3) < 0)
+ goto out;
+
+ evlist__for_each_entry(evlist, evsel) {
+ enum tool_pmu_event ev = evsel__tool_event(evsel);
+ u64 got, expected;
+
+ if (evsel__read_counter(evsel, 0, 0) < 0)
+ goto out;
+ got = perf_counts(evsel->counts, 0, 0)->val;
+ if (ev == TOOL_PMU__EVENT_NET_RX_BYTES)
+ expected = 1100;
+ else if (ev == TOOL_PMU__EVENT_NET_RX_PACKETS)
+ expected = 7;
+ else if (ev == TOOL_PMU__EVENT_NET_TX_BYTES)
+ expected = 1000;
+ else if (ev == TOOL_PMU__EVENT_NET_TX_COMPRESSED)
+ expected = 7;
+ else
+ goto out;
+ if (got != expected) {
+ pr_debug("Mismatch for %s: got %llu, expected %llu\n",
+ evsel__name(evsel), (unsigned long long)got,
+ (unsigned long long)expected);
+ goto out;
+ }
+ }
+
+ ret = TEST_OK;
+out:
+ if (tmp_fd >= 0)
+ close(tmp_fd);
+ evlist__for_each_entry(evlist, evsel)
+ evsel__close(evsel);
+ perf_thread_map__put(sys_threads);
+ perf_thread_map__put(pid_threads);
+ perf_cpu_map__put(cpus);
+ evlist__put(evlist);
+ return ret;
+}
+
+static int test__tool_pmu_schedstat_events(struct test_suite *test __maybe_unused,
+ int subtest __maybe_unused)
+{
+ static const char snap1[] =
+ "version 17\n"
+ "timestamp 4295733968\n"
+ "cpu0 10 0 100 50 80 40 1000000 200000 300\n"
+ "domain0 SMT 0000003 0 0 0\n"
+ "cpu1 20 0 200 60 90 45 5000000 400000 700\n";
+ static const char snap2[] =
+ "version 17\n"
+ "timestamp 4295734068\n"
+ "cpu0 13 0 110 55 85 42 1250000 210000 315\n"
+ "domain0 SMT 0000003 0 0 0\n"
+ "cpu1 20 0 220 70 95 48 5750000 420000 725\n";
+ char tmp_path[] = "/tmp/perf-tool-sched-XXXXXX";
+ struct evlist *evlist = evlist__new();
+ struct parse_events_error err;
+ struct perf_cpu_map *cpus = NULL;
+ struct perf_thread_map *pid_threads = NULL, *sys_threads = NULL;
+ struct evsel *evsel;
+ const char *events =
+ "tool/schedstat_yield/,tool/schedstat_runtime/,tool/schedstat_timeslices/";
+ int ret = TEST_FAIL, tmp_fd = -1;
+
+ if (!evlist)
+ return TEST_FAIL;
+
+ parse_events_error__init(&err);
+ if (parse_events(evlist, events, &err)) {
+ parse_events_error__exit(&err);
+ evlist__put(evlist);
+ return TEST_FAIL;
+ }
+ parse_events_error__exit(&err);
+
+ cpus = perf_cpu_map__new("0,1");
+ pid_threads = thread_map__new_by_tid(getpid());
+ sys_threads = perf_thread_map__new_dummy();
+ if (!cpus || !pid_threads || !sys_threads)
+ goto out;
+
+ /* Per-process open must fail with EINVAL. */
+ evsel = evlist__first(evlist);
+ errno = 0;
+ if (evsel__open(evsel, cpus, pid_threads) != -EINVAL || errno != EINVAL) {
+ pr_debug("Expected -EINVAL opening schedstat_yield per-process\n");
+ goto out;
+ }
+
+ if (access("/proc/schedstat", R_OK) != 0) {
+ ret = TEST_SKIP;
+ goto out;
+ }
+
+ tmp_fd = mkstemp(tmp_path);
+ if (tmp_fd < 0)
+ goto out;
+ unlink(tmp_path);
+
+ if (write_temp_file(tmp_fd, snap1) < 0)
+ goto out;
+
+ evlist__for_each_entry(evlist, evsel) {
+ evsel->supported = true;
+ evsel->core.system_wide = true;
+ evsel->core.attr.disabled = 1;
+ perf_cpu_map__put(evsel->core.cpus);
+ evsel->core.cpus = perf_cpu_map__get(cpus);
+ perf_thread_map__put(evsel->core.threads);
+ evsel->core.threads = perf_thread_map__get(sys_threads);
+ if (evsel__alloc_counts(evsel) < 0)
+ goto out;
+ if (evsel__open(evsel, cpus, sys_threads) < 0)
+ goto out;
+ for (int cpu_idx = 0; cpu_idx < 2; cpu_idx++) {
+ int fd = *(int *)xyarray__entry(evsel->core.fd, cpu_idx, 0);
+
+ if (fd < 0 || dup2(tmp_fd, fd) < 0)
+ goto out;
+ }
+ if (evsel__enable(evsel) < 0)
+ goto out;
+ }
+
+ if (write_temp_file(tmp_fd, snap2) < 0)
+ goto out;
+
+ evlist__for_each_entry(evlist, evsel) {
+ enum tool_pmu_event ev = evsel__tool_event(evsel);
+ u64 c0, c1, exp0, exp1;
+
+ if (evsel__disable(evsel) < 0)
+ goto out;
+ if (evsel__read_counter(evsel, 0, 0) < 0 ||
+ evsel__read_counter(evsel, 1, 0) < 0)
+ goto out;
+ c0 = perf_counts(evsel->counts, 0, 0)->val;
+ c1 = perf_counts(evsel->counts, 1, 0)->val;
+ if (ev == TOOL_PMU__EVENT_SCHEDSTAT_YIELD) {
+ exp0 = 3;
+ exp1 = 0;
+ } else if (ev == TOOL_PMU__EVENT_SCHEDSTAT_RUNTIME) {
+ exp0 = 250000;
+ exp1 = 750000;
+ } else if (ev == TOOL_PMU__EVENT_SCHEDSTAT_TIMESLICES) {
+ exp0 = 15;
+ exp1 = 25;
+ } else {
+ goto out;
+ }
+ if (c0 != exp0 || c1 != exp1) {
+ pr_debug("Mismatch for %s: got (%llu, %llu), expected (%llu, %llu)\n",
+ evsel__name(evsel),
+ (unsigned long long)c0, (unsigned long long)c1,
+ (unsigned long long)exp0, (unsigned long long)exp1);
+ goto out;
+ }
+ }
+
+ ret = TEST_OK;
+out:
+ if (tmp_fd >= 0)
+ close(tmp_fd);
+ evlist__for_each_entry(evlist, evsel)
+ evsel__close(evsel);
+ perf_thread_map__put(sys_threads);
+ perf_thread_map__put(pid_threads);
+ perf_cpu_map__put(cpus);
+ evlist__put(evlist);
+ return ret;
+}
+
+static int run_mixed_group_case(const char *group_str, const char *cpu_list,
+ int c0, int c1, int net_fd, int sched_fd)
+{
+ static const char net_snap1[] =
+ "Inter-| Receive | Transmit\n"
+ " face |bytes packets errs drop fifo frame compressed multicast|bytes packets...\n"
+ " lo: 1000 10 0 0 0 0 0 0 2000 20 0 0 0 0 0 0\n";
+ static const char net_snap2[] =
+ "Inter-| Receive | Transmit\n"
+ " face |bytes packets errs drop fifo frame compressed multicast|bytes packets...\n"
+ " lo: 1600 15 0 0 0 0 0 0 2000 20 0 0 0 0 0 0\n";
+ struct target target = {
+ .system_wide = true,
+ .cpu_list = cpu_list,
+ };
+ struct evlist *evlist = evlist__new();
+ struct parse_events_error err;
+ struct evsel *evsel, *net_evsel = NULL, *sched_evsel = NULL;
+ char sched_snap1[256], sched_snap2[256];
+ int ret = TEST_FAIL;
+
+ if (!evlist)
+ return TEST_FAIL;
+
+ snprintf(sched_snap1, sizeof(sched_snap1),
+ "version 17\ncpu%d 10 0 0 0 0 0 0 0 0\ncpu%d 20 0 0 0 0 0 0 0 0\n",
+ c0, c1);
+ snprintf(sched_snap2, sizeof(sched_snap2),
+ "version 17\ncpu%d 13 0 0 0 0 0 0 0 0\ncpu%d 27 0 0 0 0 0 0 0 0\n",
+ c0, c1);
+
+ parse_events_error__init(&err);
+ if (parse_events(evlist, group_str, &err)) {
+ parse_events_error__exit(&err);
+ goto out;
+ }
+ parse_events_error__exit(&err);
+
+ if (evlist__create_maps(evlist, &target) < 0)
+ goto out;
+
+ if (write_temp_file(net_fd, net_snap1) < 0 ||
+ write_temp_file(sched_fd, sched_snap1) < 0)
+ goto out;
+
+ evlist__for_each_entry(evlist, evsel) {
+ enum tool_pmu_event ev = evsel__tool_event(evsel);
+
+ evsel->supported = true;
+ evsel->core.system_wide = true;
+ /* Only group leaders set attr.disabled = 1 in perf stat/evsel__config. */
+ if (evsel__is_group_leader(evsel))
+ evsel->core.attr.disabled = 1;
+ if (evsel__alloc_counts(evsel) < 0 ||
+ evsel__open(evsel, evsel->core.cpus, evsel->core.threads) < 0)
+ goto out;
+ if (!evsel->disabled)
+ goto out;
+
+ if (ev == TOOL_PMU__EVENT_NET_RX_BYTES) {
+ int fd;
+
+ net_evsel = evsel;
+ if (perf_cpu_map__nr(evsel->core.cpus) != 1)
+ goto out;
+ fd = *(int *)xyarray__entry(evsel->core.fd, 0, 0);
+ if (fd < 0 || dup2(net_fd, fd) < 0)
+ goto out;
+ } else if (ev == TOOL_PMU__EVENT_SCHEDSTAT_YIELD) {
+ sched_evsel = evsel;
+ if (perf_cpu_map__nr(evsel->core.cpus) != 2)
+ goto out;
+ for (int idx = 0; idx < 2; idx++) {
+ int fd = *(int *)xyarray__entry(evsel->core.fd, idx, 0);
+
+ if (fd < 0 || dup2(sched_fd, fd) < 0)
+ goto out;
+ }
+ } else {
+ goto out;
+ }
+ }
+
+ if (!net_evsel || !sched_evsel)
+ goto out;
+
+ /* Both leader and member must read 0 while the group is still disabled. */
+ if (evsel__read_counter(net_evsel, 0, 0) < 0 ||
+ evsel__read_counter(sched_evsel, 0, 0) < 0 ||
+ evsel__read_counter(sched_evsel, 1, 0) < 0 ||
+ perf_counts(net_evsel->counts, 0, 0)->val != 0 ||
+ perf_counts(sched_evsel->counts, 0, 0)->val != 0 ||
+ perf_counts(sched_evsel->counts, 1, 0)->val != 0)
+ goto out;
+
+ evlist__enable(evlist);
+
+ if (write_temp_file(net_fd, net_snap2) < 0 ||
+ write_temp_file(sched_fd, sched_snap2) < 0)
+ goto out;
+
+ evlist__disable(evlist);
+
+ if (evsel__read_counter(net_evsel, 0, 0) < 0 ||
+ evsel__read_counter(sched_evsel, 0, 0) < 0 ||
+ evsel__read_counter(sched_evsel, 1, 0) < 0)
+ goto out;
+
+ if (perf_counts(net_evsel->counts, 0, 0)->val != 600 ||
+ perf_counts(sched_evsel->counts, 0, 0)->val != 3 ||
+ perf_counts(sched_evsel->counts, 1, 0)->val != 7) {
+ pr_debug("Unexpected mixed group counts for %s: net=%llu sched=(%llu, %llu)\n",
+ group_str,
+ (unsigned long long)perf_counts(net_evsel->counts, 0, 0)->val,
+ (unsigned long long)perf_counts(sched_evsel->counts, 0, 0)->val,
+ (unsigned long long)perf_counts(sched_evsel->counts, 1, 0)->val);
+ goto out;
+ }
+
+ ret = TEST_OK;
+out:
+ evlist__for_each_entry(evlist, evsel)
+ evsel__close(evsel);
+ evlist__put(evlist);
+ return ret;
+}
+
+static int test__tool_pmu_mixed_group_events(struct test_suite *test __maybe_unused,
+ int subtest __maybe_unused)
+{
+ char net_path[] = "/tmp/perf-tool-grp-net-XXXXXX";
+ char sched_path[] = "/tmp/perf-tool-grp-sched-XXXXXX";
+ struct perf_cpu_map *online = NULL;
+ char cpu_list[64];
+ int net_fd = -1, sched_fd = -1, c0, c1, ret = TEST_FAIL;
+
+ if (access("/proc/net/dev", R_OK) != 0 ||
+ access("/proc/schedstat", R_OK) != 0)
+ return TEST_SKIP;
+
+ online = cpu_map__online();
+ if (!online || perf_cpu_map__nr(online) < 2) {
+ perf_cpu_map__put(online);
+ return TEST_SKIP;
+ }
+ c0 = perf_cpu_map__cpu(online, 0).cpu;
+ c1 = perf_cpu_map__cpu(online, 1).cpu;
+ perf_cpu_map__put(online);
+ snprintf(cpu_list, sizeof(cpu_list), "%d,%d", c0, c1);
+
+ net_fd = mkstemp(net_path);
+ if (net_fd < 0)
+ goto out;
+ unlink(net_path);
+
+ sched_fd = mkstemp(sched_path);
+ if (sched_fd < 0)
+ goto out;
+ unlink(sched_path);
+
+ if (run_mixed_group_case("{schedstat_yield,net_rx_bytes}",
+ cpu_list, c0, c1, net_fd, sched_fd) != TEST_OK)
+ goto out;
+ if (run_mixed_group_case("{net_rx_bytes,schedstat_yield}",
+ cpu_list, c0, c1, net_fd, sched_fd) != TEST_OK)
+ goto out;
+
+ ret = TEST_OK;
+out:
+ if (net_fd >= 0)
+ close(net_fd);
+ if (sched_fd >= 0)
+ close(sched_fd);
+ return ret;
+}
+
static struct test_case tests__tool_pmu[] = {
TEST_CASE("Parsing without PMU name", tool_pmu_without_pmu),
TEST_CASE("Parsing with PMU name", tool_pmu_with_pmu),
TEST_CASE("Incremental open error unwind boundary", tool_pmu_incremental_open_unwind),
+ TEST_CASE("Memory events", tool_pmu_memory_events),
+ TEST_CASE("Network events", tool_pmu_net_events),
+ TEST_CASE("Schedstat events", tool_pmu_schedstat_events),
+ TEST_CASE("Mixed CPU-map tool groups", tool_pmu_mixed_group_events),
{ .name = NULL, }
};
--
2.56.1.703.gf848ed807c-goog
^ permalink raw reply [flat|nested] 5+ messages in thread