From: Kunwu Chan <kunwu.chan@gmail.com>
To: sj@kernel.org, akpm@linux-foundation.org
Cc: damon@lists.linux.dev, linux-mm@kvack.org,
linux-kernel@vger.kernel.org, linux-trace-kernel@vger.kernel.org,
linux-kselftest@vger.kernel.org, rostedt@goodmis.org,
mhiramat@kernel.org, mathieu.desnoyers@efficios.com,
shuah@kernel.org, lianux.mm@gmail.com,
Kunwu Chan <kunwu.chan@gmail.com>
Subject: [RFC PATCH 3/7] mm/damon/perf: add debugfs statistics interface
Date: Tue, 18 Aug 2026 14:10:27 +0800 [thread overview]
Message-ID: <20260818061031.827057-4-kunwu.chan@linux.dev> (raw)
In-Reply-To: <20260818061031.827057-1-kunwu.chan@linux.dev>
From: Lian Wang <lianux.mm@gmail.com>
Expose the aggregated per-CPU counters and the global event-stage in a
debug-only debugfs perf_stats file. The format is explicitly unstable;
tracepoints are the stable diagnostic interface.
Co-developed-by: Kunwu Chan <kunwu.chan@gmail.com>
Signed-off-by: Kunwu Chan <kunwu.chan@gmail.com>
Signed-off-by: Lian Wang <lianux.mm@gmail.com>
---
mm/damon/perf/Makefile | 2 +-
mm/damon/perf/debugfs.c | 142 ++++++++++++++++++++++++++++++++++++++++
mm/damon/perf/stats.c | 2 +-
3 files changed, 144 insertions(+), 2 deletions(-)
create mode 100644 mm/damon/perf/debugfs.c
diff --git a/mm/damon/perf/Makefile b/mm/damon/perf/Makefile
index 5c46d3da7ef8..150cbaa875fa 100644
--- a/mm/damon/perf/Makefile
+++ b/mm/damon/perf/Makefile
@@ -2,4 +2,4 @@
# Observability: per-CPU counters, tracepoints, debugfs perf_stats
obj-$(CONFIG_DAMON_PERF_OBSERVE) += damon-perf.o
-damon-perf-objs := stats.o
+damon-perf-objs := stats.o debugfs.o
diff --git a/mm/damon/perf/debugfs.c b/mm/damon/perf/debugfs.c
new file mode 100644
index 000000000000..c54dd7644ac3
--- /dev/null
+++ b/mm/damon/perf/debugfs.c
@@ -0,0 +1,142 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * DAMON Perf Observability — debugfs Interface
+ *
+ * Exposes one file under /sys/kernel/debug/damon/:
+ *
+ * perf_stats — per-CPU pipeline statistics in tabular form
+ *
+ * DEBUG ONLY — format may change without notice; do not parse in
+ * scripts. For stable diagnostics, use the tracepoints under
+ * /sys/kernel/debug/tracing/events/damon/
+ */
+
+#include <linux/cpu.h>
+#include <linux/cpumask.h>
+#include <linux/debugfs.h>
+#include <linux/seq_file.h>
+
+#include "perf.h"
+
+static struct dentry *damon_debugfs_dir;
+
+/*
+ * perf_stats
+ */
+
+static const char *state_name(int s)
+{
+ switch (s) {
+ case DAMON_PERF_STATE_UNINIT: return "UNINIT";
+ case DAMON_PERF_STATE_CREATED: return "CREATED";
+ case DAMON_PERF_STATE_BOUND: return "BOUND";
+ case DAMON_PERF_STATE_ENABLED: return "ENABLED";
+ case DAMON_PERF_STATE_RUNNING: return "RUNNING";
+ case DAMON_PERF_STATE_ERROR: return "ERROR";
+ default: return "?";
+ }
+}
+
+static int perf_stats_show(struct seq_file *m, void *v)
+{
+ struct damon_perf_stats agg, st;
+ int cpu;
+ bool first = true;
+
+ damon_perf_stats_aggregate(&agg);
+
+ seq_puts(m, " -------------- ----------\n");
+ seq_puts(m, " Counter Value\n");
+ seq_puts(m, " -------------- ----------\n");
+
+#define STAT_ROW(label, field) \
+ seq_printf(m, " %-12s %8llu\n", label, agg.field)
+
+ STAT_ROW("callback", callback);
+ STAT_ROW("valid", sample_valid);
+ STAT_ROW("null", sample_null);
+ STAT_ROW("addr_zero", sample_addr_zero);
+ STAT_ROW("kernel", sample_kernel);
+ STAT_ROW("inv_phys", sample_invalid_phys);
+ STAT_ROW("enqueue", enqueue);
+ STAT_ROW("dequeue", dequeue);
+ STAT_ROW("overflow", overflow);
+ STAT_ROW("ring_peak", ring_peak);
+ STAT_ROW("match", match);
+ STAT_ROW("miss_tgid", miss_tgid);
+ STAT_ROW("miss_region", miss_region);
+ STAT_ROW("miss_bound", miss_boundary);
+ STAT_ROW("update", update);
+
+#undef STAT_ROW
+
+ seq_puts(m, " -------------- ----------\n\n");
+
+ /* Per-CPU breakdown */
+ cpus_read_lock();
+ for_each_online_cpu(cpu) {
+ damon_perf_stats_snapshot(cpu, &st);
+
+ /* Skip truly idle CPUs */
+ if (st.cpu_state == DAMON_PERF_STATE_UNINIT &&
+ !st.callback && !st.enqueue && !st.dequeue)
+ continue;
+
+ if (first) {
+ seq_puts(m, " Per-CPU (non-zero / non-UNINIT):\n");
+ first = false;
+ }
+
+ seq_printf(m, " CPU%02d: st=%-7s cb=%llu enq=%llu deq=%llu ovf=%llu match=%llu tgid=%llu noreg=%llu bound=%llu upd=%llu\n",
+ cpu, state_name(st.cpu_state),
+ st.callback, st.enqueue, st.dequeue,
+ st.overflow, st.match,
+ st.miss_tgid, st.miss_region, st.miss_boundary,
+ st.update);
+ }
+ cpus_read_unlock();
+
+ return 0;
+}
+
+static int perf_stats_open(struct inode *inode, struct file *file)
+{
+ return single_open(file, perf_stats_show, NULL);
+}
+
+static const struct file_operations perf_stats_fops = {
+ .open = perf_stats_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = single_release,
+};
+
+/*
+ * Init / teardown
+ */
+
+int damon_perf_debugfs_init(void)
+{
+ if (!debugfs_initialized())
+ return -ENODEV;
+
+ /*
+ * Create the "damon" directory first. debugfs_create_dir() mounts
+ * debugfs via simple_pin_fs() before touching debugfs_mount, so it
+ * is safe to call during initcall time -- unlike debugfs_lookup(),
+ * which dereferences debugfs_mount unconditionally and crashes with
+ * a NULL mount. If the directory already exists (created by another
+ * DAMON interface) debugfs_create_dir() returns -EEXIST; fall back
+ * to debugfs_lookup(), which is now safe because the mount exists.
+ */
+ damon_debugfs_dir = debugfs_create_dir("damon", NULL);
+ if (damon_debugfs_dir == ERR_PTR(-EEXIST))
+ damon_debugfs_dir = debugfs_lookup("damon", NULL);
+ if (IS_ERR(damon_debugfs_dir))
+ return PTR_ERR(damon_debugfs_dir);
+
+ debugfs_create_file("perf_stats", 0400, damon_debugfs_dir,
+ NULL, &perf_stats_fops);
+
+ return 0;
+}
diff --git a/mm/damon/perf/stats.c b/mm/damon/perf/stats.c
index a869f115bb26..ae5b0037a31d 100644
--- a/mm/damon/perf/stats.c
+++ b/mm/damon/perf/stats.c
@@ -291,5 +291,5 @@ void damon_perf_stats_aggregate(struct damon_perf_stats *dst)
int damon_perf_framework_init(void)
{
- return 0;
+ return damon_perf_debugfs_init();
}
--
2.43.0
next prev parent reply other threads:[~2026-08-18 6:11 UTC|newest]
Thread overview: 8+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-08-18 6:10 [RFC PATCH 0/7] mm/damon/perf: observability framework for hardware-sampled access reports Kunwu Chan
2026-08-18 6:10 ` [RFC PATCH 1/7] mm/damon/perf: add observability framework with tracepoints and CONFIG switch Kunwu Chan
2026-08-18 6:10 ` [RFC PATCH 2/7] mm/damon/perf: implement observe API and per-CPU statistics engine Kunwu Chan
2026-08-18 6:10 ` Kunwu Chan [this message]
2026-08-18 6:10 ` [RFC PATCH 4/7] mm/damon: integrate observe API into vaddr overflow handlers and core drain Kunwu Chan
2026-08-18 6:10 ` [RFC PATCH 5/7] selftests/damon: add automated layer-by-layer observability test Kunwu Chan
2026-08-18 6:10 ` [RFC PATCH 6/7] Docs/mm/damon: document the perf observability framework Kunwu Chan
2026-08-18 6:10 ` [RFC PATCH 7/7] mm/damon/perf: add CONFIG_DAMON_PERF_DEBUG and pipeline health check Kunwu Chan
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=20260818061031.827057-4-kunwu.chan@linux.dev \
--to=kunwu.chan@gmail.com \
--cc=akpm@linux-foundation.org \
--cc=damon@lists.linux.dev \
--cc=lianux.mm@gmail.com \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-kselftest@vger.kernel.org \
--cc=linux-mm@kvack.org \
--cc=linux-trace-kernel@vger.kernel.org \
--cc=mathieu.desnoyers@efficios.com \
--cc=mhiramat@kernel.org \
--cc=rostedt@goodmis.org \
--cc=shuah@kernel.org \
--cc=sj@kernel.org \
/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