mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
From: Ian Rogers <irogers@google.com>
To: Peter Zijlstra <peterz@infradead.org>,
	Ingo Molnar <mingo@redhat.com>,
	 Arnaldo Carvalho de Melo <acme@kernel.org>,
	Namhyung Kim <namhyung@kernel.org>, Jiri Olsa <jolsa@kernel.org>,
	 Ian Rogers <irogers@google.com>,
	Adrian Hunter <adrian.hunter@intel.com>,
	 James Clark <james.clark@linaro.org>,
	Thomas Falcon <thomas.falcon@intel.com>,
	 Thomas Richter <tmricht@linux.ibm.com>,
	linux-perf-users@vger.kernel.org,  linux-kernel@vger.kernel.org
Cc: Andi Kleen <ak@linux.intel.com>
Subject: [PATCH v2 1/4] perf tool_pmu: Add memory events
Date: Fri, 13 Nov 2026 15:37:36 -0800	[thread overview]
Message-ID: <20261113233739.3626499-2-irogers@google.com> (raw)
In-Reply-To: <20261113233739.3626499-1-irogers@google.com>

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, &times);
-		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


  reply	other threads:[~2026-11-13 23:37 UTC|newest]

Thread overview: 5+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
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 [this message]
2026-11-13 23:37 ` [PATCH v2 2/4] perf tool_pmu: Add network events 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

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20261113233739.3626499-2-irogers@google.com \
    --to=irogers@google.com \
    --cc=acme@kernel.org \
    --cc=adrian.hunter@intel.com \
    --cc=ak@linux.intel.com \
    --cc=james.clark@linaro.org \
    --cc=jolsa@kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-perf-users@vger.kernel.org \
    --cc=mingo@redhat.com \
    --cc=namhyung@kernel.org \
    --cc=peterz@infradead.org \
    --cc=thomas.falcon@intel.com \
    --cc=tmricht@linux.ibm.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®