[PATCH v8 16/27] mm/ksw: manage probe and HWBP lifecycle via procfs

Jinchao Wang
2025-11-10T16:37:53Z

Allow dynamic enabling/disabling of KStackWatch through user input of proc.
With this patch, the entire system becomes functional.

Signed-off-by: Jinchao Wang <wangjinchao600@gmail.com>
---
mm/kstackwatch/kernel.c | 60 +++++++++++++++++++++++++++++++++++++++--
1 file changed, 58 insertions(+), 2 deletions(-)

diff --git a/mm/kstackwatch/kernel.c b/mm/kstackwatch/kernel.c
index 87fef139f494..a0e676e60692 100644
--- a/mm/kstackwatch/kernel.c
+++ b/mm/kstackwatch/kernel.c
@@ -14,6 +14,43 @@ static struct ksw_config *ksw_config;
static struct dentry *dbgfs_config;
static struct dentry *dbgfs_dir;

+static bool watching_active;
+
+static int ksw_start_watching(void)
+{
+ int ret;
+
+ /*
+ * Watch init will preallocate the HWBP,
+ * so it must happen before stack init
+ */
+ ret = ksw_watch_init();
+ if (ret) {
+ pr_err("ksw_watch_init ret: %d\n", ret);
+ return ret;
+ }
+
+ ret = ksw_stack_init();
+ if (ret) {
+ pr_err("ksw_stack_init ret: %d\n", ret);
+ ksw_watch_exit();
+ return ret;
+ }
+ watching_active = true;
+
+ pr_info("start watching: %s\n", ksw_config->user_input);
+ return 0;
+}
+
+static void ksw_stop_watching(void)
+{
+ ksw_stack_exit();
+ ksw_watch_exit();
+ watching_active = false;
+
+ pr_info("stop watching: %s\n", ksw_config->user_input);
+}
+
struct param_map {
const char *name; /* long name */
const char *short_name; /* short name (2 letters) */
@@ -119,8 +156,18 @@ static int ksw_parse_config(char *buf, struct ksw_config *config)
static ssize_t ksw_dbgfs_read(struct file *file, char __user *buf, size_t count,
loff_t *ppos)
{
- return simple_read_from_buffer(buf, count, ppos, ksw_config->user_input,
- ksw_config->user_input ? strlen(ksw_config->user_input) : 0);
+ const char *out;
+ size_t len;
+
+ if (watching_active && ksw_config->user_input) {
+ out = ksw_config->user_input;
+ len = strlen(out);
+ } else {
+ out = "not watching\n";
+ len = strlen(out);
+ }
+
+ return simple_read_from_buffer(buf, count, ppos, out, len);
}

static ssize_t ksw_dbgfs_write(struct file *file, const char __user *buffer,
@@ -135,6 +182,9 @@ static ssize_t ksw_dbgfs_write(struct file *file, const char __user *buffer,
if (copy_from_user(input, buffer, count))
return -EFAULT;

+ if (watching_active)
+ ksw_stop_watching();
+
input[count] = '\0';
strim(input);

@@ -149,6 +199,12 @@ static ssize_t ksw_dbgfs_write(struct file *file, const char __user *buffer,
return ret;
}

+ ret = ksw_start_watching();
+ if (ret) {
+ pr_err("Failed to start watching with %d\n", ret);
+ return ret;
+ }
+
return count;
}

--
2.43.0