Linux Trace Kernel
 help / color / mirror / Atom feed
* [PATCH v1 05/23] dma-buf: Switch to use %ptSp
From: Andy Shevchenko @ 2025-11-10 18:40 UTC (permalink / raw)
  To: Corey Minyard, Christian König, Dr. David Alan Gilbert,
	Alex Deucher, Thomas Zimmermann, Dmitry Baryshkov, Rob Clark,
	Matthew Brost, Hans Verkuil, Laurent Pinchart, Ulf Hansson,
	Andy Shevchenko, Vitaly Lifshits, Manivannan Sadhasivam,
	Niklas Cassel, Calvin Owens, Sagi Maimon, Martin K. Petersen,
	Karan Tilak Kumar, Casey Schaufler, Steven Rostedt, Petr Mladek,
	Max Kellermann, Takashi Iwai, linux-doc, linux-kernel,
	openipmi-developer, linux-media, dri-devel, linaro-mm-sig,
	amd-gfx, linux-arm-msm, freedreno, intel-xe, linux-mmc, netdev,
	intel-wired-lan, linux-pci, linux-s390, linux-scsi, linux-staging,
	ceph-devel, linux-trace-kernel, linux-sound
  Cc: Rasmus Villemoes, Sergey Senozhatsky, Jonathan Corbet,
	Sumit Semwal, Gustavo Padovan, David Airlie, Simona Vetter,
	Maarten Lankhorst, Maxime Ripard, Dmitry Baryshkov, Abhinav Kumar,
	Jessica Zhang, Sean Paul, Marijn Suijten, Konrad Dybcio,
	Lucas De Marchi, Thomas Hellström, Rodrigo Vivi,
	Mauro Carvalho Chehab, Vladimir Oltean, Andrew Lunn,
	David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
	Tony Nguyen, Przemek Kitszel, Krzysztof Wilczyński,
	Kishon Vijay Abraham I, Bjorn Helgaas, Rodolfo Giometti,
	Jonathan Lemon, Vadim Fedorenko, Richard Cochran,
	Stefan Haberland, Jan Hoeppner, Heiko Carstens, Vasily Gorbik,
	Alexander Gordeev, Christian Borntraeger, Sven Schnelle,
	Satish Kharat, Sesidhar Baddela, James E.J. Bottomley,
	Greg Kroah-Hartman, Xiubo Li, Ilya Dryomov, Masami Hiramatsu,
	Mathieu Desnoyers, Andrew Morton, Jaroslav Kysela, Takashi Iwai
In-Reply-To: <20251110184727.666591-1-andriy.shevchenko@linux.intel.com>

Use %ptSp instead of open coded variants to print content of
struct timespec64 in human readable format.

Signed-off-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
---
 drivers/dma-buf/sync_debug.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/dma-buf/sync_debug.c b/drivers/dma-buf/sync_debug.c
index 67cd69551e42..9e5d662cd4e8 100644
--- a/drivers/dma-buf/sync_debug.c
+++ b/drivers/dma-buf/sync_debug.c
@@ -59,7 +59,7 @@ static void sync_print_fence(struct seq_file *s,
 		struct timespec64 ts64 =
 			ktime_to_timespec64(fence->timestamp);
 
-		seq_printf(s, "@%lld.%09ld", (s64)ts64.tv_sec, ts64.tv_nsec);
+		seq_printf(s, "@%ptSp", &ts64);
 	}
 
 	seq_printf(s, ": %lld", fence->seqno);
-- 
2.50.1


^ permalink raw reply related

* [PATCH v1 04/23] libceph: Switch to use %ptSp
From: Andy Shevchenko @ 2025-11-10 18:40 UTC (permalink / raw)
  To: Corey Minyard, Christian König, Dr. David Alan Gilbert,
	Alex Deucher, Thomas Zimmermann, Dmitry Baryshkov, Rob Clark,
	Matthew Brost, Hans Verkuil, Laurent Pinchart, Ulf Hansson,
	Andy Shevchenko, Vitaly Lifshits, Manivannan Sadhasivam,
	Niklas Cassel, Calvin Owens, Sagi Maimon, Martin K. Petersen,
	Karan Tilak Kumar, Casey Schaufler, Steven Rostedt, Petr Mladek,
	Max Kellermann, Takashi Iwai, linux-doc, linux-kernel,
	openipmi-developer, linux-media, dri-devel, linaro-mm-sig,
	amd-gfx, linux-arm-msm, freedreno, intel-xe, linux-mmc, netdev,
	intel-wired-lan, linux-pci, linux-s390, linux-scsi, linux-staging,
	ceph-devel, linux-trace-kernel, linux-sound
  Cc: Rasmus Villemoes, Sergey Senozhatsky, Jonathan Corbet,
	Sumit Semwal, Gustavo Padovan, David Airlie, Simona Vetter,
	Maarten Lankhorst, Maxime Ripard, Dmitry Baryshkov, Abhinav Kumar,
	Jessica Zhang, Sean Paul, Marijn Suijten, Konrad Dybcio,
	Lucas De Marchi, Thomas Hellström, Rodrigo Vivi,
	Mauro Carvalho Chehab, Vladimir Oltean, Andrew Lunn,
	David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
	Tony Nguyen, Przemek Kitszel, Krzysztof Wilczyński,
	Kishon Vijay Abraham I, Bjorn Helgaas, Rodolfo Giometti,
	Jonathan Lemon, Vadim Fedorenko, Richard Cochran,
	Stefan Haberland, Jan Hoeppner, Heiko Carstens, Vasily Gorbik,
	Alexander Gordeev, Christian Borntraeger, Sven Schnelle,
	Satish Kharat, Sesidhar Baddela, James E.J. Bottomley,
	Greg Kroah-Hartman, Xiubo Li, Ilya Dryomov, Masami Hiramatsu,
	Mathieu Desnoyers, Andrew Morton, Jaroslav Kysela, Takashi Iwai
In-Reply-To: <20251110184727.666591-1-andriy.shevchenko@linux.intel.com>

Use %ptSp instead of open coded variants to print content of
struct timespec64 in human readable format.

Signed-off-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
---
 net/ceph/messenger_v2.c | 6 ++----
 1 file changed, 2 insertions(+), 4 deletions(-)

diff --git a/net/ceph/messenger_v2.c b/net/ceph/messenger_v2.c
index 9e39378eda00..6e676e2d4ba0 100644
--- a/net/ceph/messenger_v2.c
+++ b/net/ceph/messenger_v2.c
@@ -1535,8 +1535,7 @@ static int prepare_keepalive2(struct ceph_connection *con)
 	struct timespec64 now;
 
 	ktime_get_real_ts64(&now);
-	dout("%s con %p timestamp %lld.%09ld\n", __func__, con, now.tv_sec,
-	     now.tv_nsec);
+	dout("%s con %p timestamp %ptSp\n", __func__, con, &now);
 
 	ceph_encode_timespec64(ts, &now);
 
@@ -2729,8 +2728,7 @@ static int process_keepalive2_ack(struct ceph_connection *con,
 	ceph_decode_need(&p, end, sizeof(struct ceph_timespec), bad);
 	ceph_decode_timespec64(&con->last_keepalive_ack, p);
 
-	dout("%s con %p timestamp %lld.%09ld\n", __func__, con,
-	     con->last_keepalive_ack.tv_sec, con->last_keepalive_ack.tv_nsec);
+	dout("%s con %p timestamp %ptSp\n", __func__, con, &con->last_keepalive_ack);
 
 	return 0;
 
-- 
2.50.1


^ permalink raw reply related

* [PATCH v1 06/23] drm/amdgpu: Switch to use %ptSp
From: Andy Shevchenko @ 2025-11-10 18:40 UTC (permalink / raw)
  To: Corey Minyard, Christian König, Dr. David Alan Gilbert,
	Alex Deucher, Thomas Zimmermann, Dmitry Baryshkov, Rob Clark,
	Matthew Brost, Hans Verkuil, Laurent Pinchart, Ulf Hansson,
	Andy Shevchenko, Vitaly Lifshits, Manivannan Sadhasivam,
	Niklas Cassel, Calvin Owens, Sagi Maimon, Martin K. Petersen,
	Karan Tilak Kumar, Casey Schaufler, Steven Rostedt, Petr Mladek,
	Max Kellermann, Takashi Iwai, linux-doc, linux-kernel,
	openipmi-developer, linux-media, dri-devel, linaro-mm-sig,
	amd-gfx, linux-arm-msm, freedreno, intel-xe, linux-mmc, netdev,
	intel-wired-lan, linux-pci, linux-s390, linux-scsi, linux-staging,
	ceph-devel, linux-trace-kernel, linux-sound
  Cc: Rasmus Villemoes, Sergey Senozhatsky, Jonathan Corbet,
	Sumit Semwal, Gustavo Padovan, David Airlie, Simona Vetter,
	Maarten Lankhorst, Maxime Ripard, Dmitry Baryshkov, Abhinav Kumar,
	Jessica Zhang, Sean Paul, Marijn Suijten, Konrad Dybcio,
	Lucas De Marchi, Thomas Hellström, Rodrigo Vivi,
	Mauro Carvalho Chehab, Vladimir Oltean, Andrew Lunn,
	David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
	Tony Nguyen, Przemek Kitszel, Krzysztof Wilczyński,
	Kishon Vijay Abraham I, Bjorn Helgaas, Rodolfo Giometti,
	Jonathan Lemon, Vadim Fedorenko, Richard Cochran,
	Stefan Haberland, Jan Hoeppner, Heiko Carstens, Vasily Gorbik,
	Alexander Gordeev, Christian Borntraeger, Sven Schnelle,
	Satish Kharat, Sesidhar Baddela, James E.J. Bottomley,
	Greg Kroah-Hartman, Xiubo Li, Ilya Dryomov, Masami Hiramatsu,
	Mathieu Desnoyers, Andrew Morton, Jaroslav Kysela, Takashi Iwai
In-Reply-To: <20251110184727.666591-1-andriy.shevchenko@linux.intel.com>

Use %ptSp instead of open coded variants to print content of
struct timespec64 in human readable format.

Signed-off-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
---
 drivers/gpu/drm/amd/amdgpu/amdgpu_dev_coredump.c | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_dev_coredump.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_dev_coredump.c
index 8a026bc9ea44..4e2fe6674db8 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_dev_coredump.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_dev_coredump.c
@@ -217,8 +217,7 @@ amdgpu_devcoredump_read(char *buffer, loff_t offset, size_t count,
 	drm_printf(&p, "version: " AMDGPU_COREDUMP_VERSION "\n");
 	drm_printf(&p, "kernel: " UTS_RELEASE "\n");
 	drm_printf(&p, "module: " KBUILD_MODNAME "\n");
-	drm_printf(&p, "time: %lld.%09ld\n", coredump->reset_time.tv_sec,
-		   coredump->reset_time.tv_nsec);
+	drm_printf(&p, "time: %ptSp\n", &coredump->reset_time);
 
 	if (coredump->reset_task_info.task.pid)
 		drm_printf(&p, "process_name: %s PID: %d\n",
-- 
2.50.1


^ permalink raw reply related

* [PATCH v1 02/23] ALSA: seq: Switch to use %ptSp
From: Andy Shevchenko @ 2025-11-10 18:40 UTC (permalink / raw)
  To: Corey Minyard, Christian König, Dr. David Alan Gilbert,
	Alex Deucher, Thomas Zimmermann, Dmitry Baryshkov, Rob Clark,
	Matthew Brost, Hans Verkuil, Laurent Pinchart, Ulf Hansson,
	Andy Shevchenko, Vitaly Lifshits, Manivannan Sadhasivam,
	Niklas Cassel, Calvin Owens, Sagi Maimon, Martin K. Petersen,
	Karan Tilak Kumar, Casey Schaufler, Steven Rostedt, Petr Mladek,
	Max Kellermann, Takashi Iwai, linux-doc, linux-kernel,
	openipmi-developer, linux-media, dri-devel, linaro-mm-sig,
	amd-gfx, linux-arm-msm, freedreno, intel-xe, linux-mmc, netdev,
	intel-wired-lan, linux-pci, linux-s390, linux-scsi, linux-staging,
	ceph-devel, linux-trace-kernel, linux-sound
  Cc: Rasmus Villemoes, Sergey Senozhatsky, Jonathan Corbet,
	Sumit Semwal, Gustavo Padovan, David Airlie, Simona Vetter,
	Maarten Lankhorst, Maxime Ripard, Dmitry Baryshkov, Abhinav Kumar,
	Jessica Zhang, Sean Paul, Marijn Suijten, Konrad Dybcio,
	Lucas De Marchi, Thomas Hellström, Rodrigo Vivi,
	Mauro Carvalho Chehab, Vladimir Oltean, Andrew Lunn,
	David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
	Tony Nguyen, Przemek Kitszel, Krzysztof Wilczyński,
	Kishon Vijay Abraham I, Bjorn Helgaas, Rodolfo Giometti,
	Jonathan Lemon, Vadim Fedorenko, Richard Cochran,
	Stefan Haberland, Jan Hoeppner, Heiko Carstens, Vasily Gorbik,
	Alexander Gordeev, Christian Borntraeger, Sven Schnelle,
	Satish Kharat, Sesidhar Baddela, James E.J. Bottomley,
	Greg Kroah-Hartman, Xiubo Li, Ilya Dryomov, Masami Hiramatsu,
	Mathieu Desnoyers, Andrew Morton, Jaroslav Kysela, Takashi Iwai
In-Reply-To: <20251110184727.666591-1-andriy.shevchenko@linux.intel.com>

Use %ptSp instead of open coded variants to print content of
struct timespec64 in human readable format.

Signed-off-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
---
 sound/core/seq/seq_queue.c | 2 +-
 sound/core/seq/seq_timer.c | 6 +++---
 2 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/sound/core/seq/seq_queue.c b/sound/core/seq/seq_queue.c
index f5c0e401c8ae..f6e86cbf38bc 100644
--- a/sound/core/seq/seq_queue.c
+++ b/sound/core/seq/seq_queue.c
@@ -699,7 +699,7 @@ void snd_seq_info_queues_read(struct snd_info_entry *entry,
 		snd_iprintf(buffer, "current tempo      : %d\n", tmr->tempo);
 		snd_iprintf(buffer, "tempo base         : %d ns\n", tmr->tempo_base);
 		snd_iprintf(buffer, "current BPM        : %d\n", bpm);
-		snd_iprintf(buffer, "current time       : %d.%09d s\n", tmr->cur_time.tv_sec, tmr->cur_time.tv_nsec);
+		snd_iprintf(buffer, "current time       : %ptSp s\n", &tmr->cur_time);
 		snd_iprintf(buffer, "current tick       : %d\n", tmr->tick.cur_tick);
 		snd_iprintf(buffer, "\n");
 	}
diff --git a/sound/core/seq/seq_timer.c b/sound/core/seq/seq_timer.c
index 29b018a212fc..06074d822bae 100644
--- a/sound/core/seq/seq_timer.c
+++ b/sound/core/seq/seq_timer.c
@@ -442,7 +442,7 @@ void snd_seq_info_timer_read(struct snd_info_entry *entry,
 	int idx;
 	struct snd_seq_timer *tmr;
 	struct snd_timer_instance *ti;
-	unsigned long resolution;
+	struct timespec64 resolution;
 	
 	for (idx = 0; idx < SNDRV_SEQ_MAX_QUEUES; idx++) {
 		struct snd_seq_queue *q __free(snd_seq_queue) = queueptr(idx);
@@ -457,8 +457,8 @@ void snd_seq_info_timer_read(struct snd_info_entry *entry,
 			if (!ti)
 				break;
 			snd_iprintf(buffer, "Timer for queue %i : %s\n", q->queue, ti->timer->name);
-			resolution = snd_timer_resolution(ti) * tmr->ticks;
-			snd_iprintf(buffer, "  Period time : %lu.%09lu\n", resolution / 1000000000, resolution % 1000000000);
+			resolution = ns_to_timespec64(snd_timer_resolution(ti) * tmr->ticks);
+			snd_iprintf(buffer, "  Period time : %ptSp\n", &resolution);
 			snd_iprintf(buffer, "  Skew : %u / %u\n", tmr->skew, tmr->skew_base);
 		}
  	}
-- 
2.50.1


^ permalink raw reply related

* [PATCH v1 01/23] lib/vsprintf: Add specifier for printing struct timespec64
From: Andy Shevchenko @ 2025-11-10 18:40 UTC (permalink / raw)
  To: Corey Minyard, Christian König, Dr. David Alan Gilbert,
	Alex Deucher, Thomas Zimmermann, Dmitry Baryshkov, Rob Clark,
	Matthew Brost, Hans Verkuil, Laurent Pinchart, Ulf Hansson,
	Andy Shevchenko, Vitaly Lifshits, Manivannan Sadhasivam,
	Niklas Cassel, Calvin Owens, Sagi Maimon, Martin K. Petersen,
	Karan Tilak Kumar, Casey Schaufler, Steven Rostedt, Petr Mladek,
	Max Kellermann, Takashi Iwai, linux-doc, linux-kernel,
	openipmi-developer, linux-media, dri-devel, linaro-mm-sig,
	amd-gfx, linux-arm-msm, freedreno, intel-xe, linux-mmc, netdev,
	intel-wired-lan, linux-pci, linux-s390, linux-scsi, linux-staging,
	ceph-devel, linux-trace-kernel, linux-sound
  Cc: Rasmus Villemoes, Sergey Senozhatsky, Jonathan Corbet,
	Sumit Semwal, Gustavo Padovan, David Airlie, Simona Vetter,
	Maarten Lankhorst, Maxime Ripard, Dmitry Baryshkov, Abhinav Kumar,
	Jessica Zhang, Sean Paul, Marijn Suijten, Konrad Dybcio,
	Lucas De Marchi, Thomas Hellström, Rodrigo Vivi,
	Mauro Carvalho Chehab, Vladimir Oltean, Andrew Lunn,
	David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
	Tony Nguyen, Przemek Kitszel, Krzysztof Wilczyński,
	Kishon Vijay Abraham I, Bjorn Helgaas, Rodolfo Giometti,
	Jonathan Lemon, Vadim Fedorenko, Richard Cochran,
	Stefan Haberland, Jan Hoeppner, Heiko Carstens, Vasily Gorbik,
	Alexander Gordeev, Christian Borntraeger, Sven Schnelle,
	Satish Kharat, Sesidhar Baddela, James E.J. Bottomley,
	Greg Kroah-Hartman, Xiubo Li, Ilya Dryomov, Masami Hiramatsu,
	Mathieu Desnoyers, Andrew Morton, Jaroslav Kysela, Takashi Iwai
In-Reply-To: <20251110184727.666591-1-andriy.shevchenko@linux.intel.com>

A handful drivers want to print a content of the struct timespec64
in a format of %lld:%09ld. In order to make their lives easier, add
the respecting specifier directly to the printf() implementation.

Signed-off-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
---
 Documentation/core-api/printk-formats.rst | 11 ++++++++--
 lib/tests/printf_kunit.c                  |  4 ++++
 lib/vsprintf.c                            | 25 +++++++++++++++++++++++
 3 files changed, 38 insertions(+), 2 deletions(-)

diff --git a/Documentation/core-api/printk-formats.rst b/Documentation/core-api/printk-formats.rst
index 7f2f11b48286..6fdb417f5140 100644
--- a/Documentation/core-api/printk-formats.rst
+++ b/Documentation/core-api/printk-formats.rst
@@ -547,11 +547,13 @@ Time and date
 	%pt[RT]s		YYYY-mm-dd HH:MM:SS
 	%pt[RT]d		YYYY-mm-dd
 	%pt[RT]t		HH:MM:SS
-	%pt[RT][dt][r][s]
+	%ptSp			<seconds>.<nanoseconds>
+	%pt[RST][dt][r][s]
 
 For printing date and time as represented by::
 
-	R  struct rtc_time structure
+	R  content of struct rtc_time
+	S  content of struct timespec64
 	T  time64_t type
 
 in human readable format.
@@ -563,6 +565,11 @@ The %pt[RT]s (space) will override ISO 8601 separator by using ' ' (space)
 instead of 'T' (Capital T) between date and time. It won't have any effect
 when date or time is omitted.
 
+The %ptSp is equivalent to %lld.%09ld for the content of the struct timespec64.
+When the other specifiers given, it becomes the respective equivalent of
+%ptT[dt][r][s].%09ld. In other words, the seconds are being printed in the
+human readable format followed by dot and nanoseconds.
+
 Passed by reference.
 
 struct clk
diff --git a/lib/tests/printf_kunit.c b/lib/tests/printf_kunit.c
index bc54cca2d7a6..7617e5b8b02c 100644
--- a/lib/tests/printf_kunit.c
+++ b/lib/tests/printf_kunit.c
@@ -504,6 +504,7 @@ time_and_date(struct kunit *kunittest)
 	};
 	/* 2019-01-04T15:32:23 */
 	time64_t t = 1546615943;
+	struct timespec64 ts = { .tv_sec = t, .tv_nsec = 11235813 };
 
 	test("(%pt?)", "%pt", &tm);
 	test("2018-11-26T05:35:43", "%ptR", &tm);
@@ -522,6 +523,9 @@ time_and_date(struct kunit *kunittest)
 	test("0119-00-04 15:32:23", "%ptTsr", &t);
 	test("15:32:23|2019-01-04", "%ptTts|%ptTds", &t, &t);
 	test("15:32:23|0119-00-04", "%ptTtrs|%ptTdrs", &t, &t);
+
+	test("2019-01-04T15:32:23.011235813", "%ptS", &ts);
+	test("1546615943.011235813", "%ptSp", &ts);
 }
 
 static void
diff --git a/lib/vsprintf.c b/lib/vsprintf.c
index 3f99834fd788..f29eb6368891 100644
--- a/lib/vsprintf.c
+++ b/lib/vsprintf.c
@@ -1989,6 +1989,28 @@ char *time64_str(char *buf, char *end, const time64_t time,
 	return rtc_str(buf, end, &rtc_time, spec, fmt);
 }
 
+static noinline_for_stack
+char *timespec64_str(char *buf, char *end, const struct timespec64 *ts,
+                     struct printf_spec spec, const char *fmt)
+{
+	static const struct printf_spec default_dec09_spec = {
+		.base = 10,
+		.field_width = 9,
+		.precision = -1,
+		.flags = ZEROPAD,
+	};
+
+	if (fmt[2] == 'p')
+		buf = number(buf, end, ts->tv_sec, default_dec_spec);
+	else
+		buf = time64_str(buf, end, ts->tv_sec, spec, fmt);
+	if (buf < end)
+		*buf = '.';
+	buf++;
+
+	return number(buf, end, ts->tv_nsec, default_dec09_spec);
+}
+
 static noinline_for_stack
 char *time_and_date(char *buf, char *end, void *ptr, struct printf_spec spec,
 		    const char *fmt)
@@ -1999,6 +2021,8 @@ char *time_and_date(char *buf, char *end, void *ptr, struct printf_spec spec,
 	switch (fmt[1]) {
 	case 'R':
 		return rtc_str(buf, end, (const struct rtc_time *)ptr, spec, fmt);
+	case 'S':
+		return timespec64_str(buf, end, (const struct timespec64 *)ptr, spec, fmt);
 	case 'T':
 		return time64_str(buf, end, *(const time64_t *)ptr, spec, fmt);
 	default:
@@ -2464,6 +2488,7 @@ early_param("no_hash_pointers", no_hash_pointers_enable);
  * - 'g' For block_device name (gendisk + partition number)
  * - 't[RT][dt][r][s]' For time and date as represented by:
  *      R    struct rtc_time
+ *      S    struct timespec64
  *      T    time64_t
  * - 'C' For a clock, it prints the name (Common Clock Framework) or address
  *       (legacy clock framework) of the clock
-- 
2.50.1


^ permalink raw reply related

* [PATCH v1 00/23] treewide: Introduce %ptS for struct timespec64 and convert users
From: Andy Shevchenko @ 2025-11-10 18:40 UTC (permalink / raw)
  To: Corey Minyard, Christian König, Dr. David Alan Gilbert,
	Alex Deucher, Thomas Zimmermann, Dmitry Baryshkov, Rob Clark,
	Matthew Brost, Hans Verkuil, Laurent Pinchart, Ulf Hansson,
	Andy Shevchenko, Vitaly Lifshits, Manivannan Sadhasivam,
	Niklas Cassel, Calvin Owens, Sagi Maimon, Martin K. Petersen,
	Karan Tilak Kumar, Casey Schaufler, Steven Rostedt, Petr Mladek,
	Max Kellermann, Takashi Iwai, linux-doc, linux-kernel,
	openipmi-developer, linux-media, dri-devel, linaro-mm-sig,
	amd-gfx, linux-arm-msm, freedreno, intel-xe, linux-mmc, netdev,
	intel-wired-lan, linux-pci, linux-s390, linux-scsi, linux-staging,
	ceph-devel, linux-trace-kernel, linux-sound
  Cc: Rasmus Villemoes, Sergey Senozhatsky, Jonathan Corbet,
	Sumit Semwal, Gustavo Padovan, David Airlie, Simona Vetter,
	Maarten Lankhorst, Maxime Ripard, Dmitry Baryshkov, Abhinav Kumar,
	Jessica Zhang, Sean Paul, Marijn Suijten, Konrad Dybcio,
	Lucas De Marchi, Thomas Hellström, Rodrigo Vivi,
	Mauro Carvalho Chehab, Vladimir Oltean, Andrew Lunn,
	David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
	Tony Nguyen, Przemek Kitszel, Krzysztof Wilczyński,
	Kishon Vijay Abraham I, Bjorn Helgaas, Rodolfo Giometti,
	Jonathan Lemon, Vadim Fedorenko, Richard Cochran,
	Stefan Haberland, Jan Hoeppner, Heiko Carstens, Vasily Gorbik,
	Alexander Gordeev, Christian Borntraeger, Sven Schnelle,
	Satish Kharat, Sesidhar Baddela, James E.J. Bottomley,
	Greg Kroah-Hartman, Xiubo Li, Ilya Dryomov, Masami Hiramatsu,
	Mathieu Desnoyers, Andrew Morton, Jaroslav Kysela, Takashi Iwai


Here is the third part of unification time printing in the kernel.
This time for struct timespec64. The first patch brings support
into printf() implementation (test cases and documentation update
included) followed by the treewide conversion of the current users.

The idea is to have one or a few biggest users included, the rest
can be taken next release cycle on the subsystem basis, but I won't
object if the respective maintainers already give their tags. Depending
on the tags received it may go via dedicated subsystem or via PRINTK
tree.

Note, not everything was compile-tested. Kunit test has been passed, though.

Andy Shevchenko (23):
  lib/vsprintf: Add specifier for printing struct timespec64
  ALSA: seq: Switch to use %ptSp
  ceph: Switch to use %ptSp
  libceph: Switch to use %ptSp
  dma-buf: Switch to use %ptSp
  drm/amdgpu: Switch to use %ptSp
  drm/msm: Switch to use %ptSp
  drm/vblank: Switch to use %ptSp
  drm/xe: Switch to use %ptSp
  e1000e: Switch to use %ptSp
  igb: Switch to use %ptSp
  ipmi: Switch to use %ptSp
  media: av7110: Switch to use %ptSp
  media: v4l2-ioctl: Switch to use %ptSp
  mmc: mmc_test: Switch to use %ptSp
  net: dsa: sja1105: Switch to use %ptSp
  PCI: epf-test: Switch to use %ptSp
  pps: Switch to use %ptSp
  ptp: ocp: Switch to use %ptSp
  s390/dasd: Switch to use %ptSp
  scsi: fnic: Switch to use %ptS
  scsi: snic: Switch to use %ptSp
  tracing: Switch to use %ptSp

 Documentation/core-api/printk-formats.rst     | 11 ++++-
 drivers/char/ipmi/ipmi_si_intf.c              |  3 +-
 drivers/char/ipmi/ipmi_ssif.c                 |  6 +--
 drivers/dma-buf/sync_debug.c                  |  2 +-
 .../gpu/drm/amd/amdgpu/amdgpu_dev_coredump.c  |  3 +-
 drivers/gpu/drm/drm_vblank.c                  |  6 +--
 .../gpu/drm/msm/disp/msm_disp_snapshot_util.c |  3 +-
 drivers/gpu/drm/msm/msm_gpu.c                 |  3 +-
 drivers/gpu/drm/xe/xe_devcoredump.c           |  4 +-
 drivers/media/v4l2-core/v4l2-ioctl.c          |  5 +-
 drivers/mmc/core/mmc_test.c                   | 18 +++----
 drivers/net/dsa/sja1105/sja1105_tas.c         |  8 ++--
 drivers/net/ethernet/intel/e1000e/ptp.c       |  7 +--
 drivers/net/ethernet/intel/igb/igb_ptp.c      |  7 +--
 drivers/pci/endpoint/functions/pci-epf-test.c |  5 +-
 drivers/pps/generators/pps_gen_parport.c      |  3 +-
 drivers/pps/kapi.c                            |  3 +-
 drivers/ptp/ptp_ocp.c                         | 15 +++---
 drivers/s390/block/dasd.c                     |  3 +-
 drivers/scsi/fnic/fnic_trace.c                | 46 ++++++++----------
 drivers/scsi/snic/snic_debugfs.c              | 10 ++--
 drivers/scsi/snic/snic_trc.c                  |  5 +-
 drivers/staging/media/av7110/av7110.c         |  2 +-
 fs/ceph/dir.c                                 |  5 +-
 fs/ceph/inode.c                               | 47 ++++++-------------
 fs/ceph/xattr.c                               |  6 +--
 kernel/trace/trace_output.c                   |  6 +--
 lib/tests/printf_kunit.c                      |  4 ++
 lib/vsprintf.c                                | 25 ++++++++++
 net/ceph/messenger_v2.c                       |  6 +--
 sound/core/seq/seq_queue.c                    |  2 +-
 sound/core/seq/seq_timer.c                    |  6 +--
 32 files changed, 131 insertions(+), 154 deletions(-)

-- 
2.50.1


^ permalink raw reply

* Re: [PATCH v3 2/8] mm: add atomic VMA flags and set VM_MAYBE_GUARD as such
From: Lorenzo Stoakes @ 2025-11-10 17:59 UTC (permalink / raw)
  To: Andrew Morton
  Cc: Jonathan Corbet, David Hildenbrand, Liam R . Howlett,
	Vlastimil Babka, Mike Rapoport, Suren Baghdasaryan, Michal Hocko,
	Steven Rostedt, Masami Hiramatsu, Mathieu Desnoyers, Jann Horn,
	Pedro Falcato, Zi Yan, Baolin Wang, Nico Pache, Ryan Roberts,
	Dev Jain, Barry Song, Lance Yang, linux-kernel, linux-fsdevel,
	linux-doc, linux-mm, linux-trace-kernel, linux-kselftest,
	Andrei Vagin
In-Reply-To: <cda9d4c073d773ef6c2cf2939d66cf80544cff40.1762531708.git.lorenzo.stoakes@oracle.com>

Hi Andrew,

OK take 2 here :) please apply this fix-patch which both makes sparse happy and
avoids a clang compilation error on this commit.

Cheers, Lorenzo

----8<----
From 553fb3f0fc9f3c351bddf956b00d1dfaa2a32920 Mon Sep 17 00:00:00 2001
From: Lorenzo Stoakes <lorenzo.stoakes@oracle.com>
Date: Mon, 10 Nov 2025 17:35:11 +0000
Subject: [PATCH] fixup

Signed-off-by: Lorenzo Stoakes <lorenzo.stoakes@oracle.com>
---
 include/linux/mm.h | 6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/include/linux/mm.h b/include/linux/mm.h
index 699566c21ff7..a9b8f6205204 100644
--- a/include/linux/mm.h
+++ b/include/linux/mm.h
@@ -886,7 +886,7 @@ static inline void vma_flag_set_atomic(struct vm_area_struct *vma, int bit)
 		vma_assert_locked(vma);

 	if (__vma_flag_atomic_valid(vma, bit))
-		set_bit(bit, &vma->__vm_flags);
+		set_bit(bit, &ACCESS_PRIVATE(vma, __vm_flags));
 }

 /*
@@ -899,7 +899,9 @@ static inline void vma_flag_set_atomic(struct vm_area_struct *vma, int bit)
 static inline bool vma_flag_test_atomic(struct vm_area_struct *vma, int bit)
 {
 	if (__vma_flag_atomic_valid(vma, bit))
-		return test_bit(bit, &vma->__vm_flags);
+		return test_bit(bit, &vma->vm_flags);
+
+	return false;
 }

 static inline void vma_set_anonymous(struct vm_area_struct *vma)
--
2.51.0

^ permalink raw reply related

* Re: [PATCH v3 2/8] mm: add atomic VMA flags and set VM_MAYBE_GUARD as such
From: Lorenzo Stoakes @ 2025-11-10 17:49 UTC (permalink / raw)
  To: Andrew Morton
  Cc: Jonathan Corbet, David Hildenbrand, Liam R . Howlett,
	Vlastimil Babka, Mike Rapoport, Suren Baghdasaryan, Michal Hocko,
	Steven Rostedt, Masami Hiramatsu, Mathieu Desnoyers, Jann Horn,
	Pedro Falcato, Zi Yan, Baolin Wang, Nico Pache, Ryan Roberts,
	Dev Jain, Barry Song, Lance Yang, linux-kernel, linux-fsdevel,
	linux-doc, linux-mm, linux-trace-kernel, linux-kselftest,
	Andrei Vagin
In-Reply-To: <00f05e58-b10b-4a66-bd6e-41dfa60ec364@lucifer.local>

Andrew - actually please ignore this, let me send another that'll fold this in
and make sparse happy too.

Cheers, Lorenzo

On Mon, Nov 10, 2025 at 05:36:29PM +0000, Lorenzo Stoakes wrote:
> Hi Andrew,
>
> Please apply this trivial fix-patch.
>
> Thanks, Lorenzo
>
> ----8<----
>
> From e73da6d99f6e32c959c7a852a90f03c9c76816c6 Mon Sep 17 00:00:00 2001
> From: Lorenzo Stoakes <lorenzo.stoakes@oracle.com>
> Date: Mon, 10 Nov 2025 17:35:11 +0000
> Subject: [PATCH] fixup
>
> Signed-off-by: Lorenzo Stoakes <lorenzo.stoakes@oracle.com>
> ---
>  include/linux/mm.h | 2 ++
>  1 file changed, 2 insertions(+)
>
> diff --git a/include/linux/mm.h b/include/linux/mm.h
> index 699566c21ff7..e94005f2b985 100644
> --- a/include/linux/mm.h
> +++ b/include/linux/mm.h
> @@ -900,6 +900,8 @@ static inline bool vma_flag_test_atomic(struct vm_area_struct *vma, int bit)
>  {
>  	if (__vma_flag_atomic_valid(vma, bit))
>  		return test_bit(bit, &vma->__vm_flags);
> +
> +	return false;
>  }
>
>  static inline void vma_set_anonymous(struct vm_area_struct *vma)
> --
> 2.51.0

^ permalink raw reply

* Re: [PATCH v3 5/8] mm: set the VM_MAYBE_GUARD flag on guard region install
From: Lorenzo Stoakes @ 2025-11-10 17:43 UTC (permalink / raw)
  To: Andrew Morton
  Cc: Jonathan Corbet, David Hildenbrand, Liam R . Howlett,
	Vlastimil Babka, Mike Rapoport, Suren Baghdasaryan, Michal Hocko,
	Steven Rostedt, Masami Hiramatsu, Mathieu Desnoyers, Jann Horn,
	Pedro Falcato, Zi Yan, Baolin Wang, Nico Pache, Ryan Roberts,
	Dev Jain, Barry Song, Lance Yang, linux-kernel, linux-fsdevel,
	linux-doc, linux-mm, linux-trace-kernel, linux-kselftest,
	Andrei Vagin
In-Reply-To: <99ce6131e27592c92b43ac866da48b4c2a568298.1762531708.git.lorenzo.stoakes@oracle.com>

Hi Andrew,

Please apply this trivial comment fixup fix-patch.

Thanks, Lorenzo

----8<----
From ed78447f613dc9ef16ce9d7a7e43de993379d9f5 Mon Sep 17 00:00:00 2001
From: Lorenzo Stoakes <lorenzo.stoakes@oracle.com>
Date: Mon, 10 Nov 2025 17:41:15 +0000
Subject: [PATCH] fixup

Signed-off-by: Lorenzo Stoakes <lorenzo.stoakes@oracle.com>
---
 mm/khugepaged.c | 5 ++---
 1 file changed, 2 insertions(+), 3 deletions(-)

diff --git a/mm/khugepaged.c b/mm/khugepaged.c
index c75afeac4bbb..742b47e0fb75 100644
--- a/mm/khugepaged.c
+++ b/mm/khugepaged.c
@@ -1806,9 +1806,8 @@ static void retract_page_tables(struct address_space *mapping, pgoff_t pgoff)
 		* userfaultfd_wp() vmas.  But since the mmap_lock is not held,
 		* it is still possible for a racing userfaultfd_ioctl() or
 		* madvise() to have inserted ptes or markers.  Now that we hold
-		* ptlock, repeating the anon_vma check protects from one
-		* category, and repeating the userfaultfd_wp() check from
-		* another.
+		* ptlock, repeating the retractable checks protects us from
+		* races against the prior checks.
 		*/
 		if (likely(file_backed_vma_is_retractable(vma))) {
 			pgt_pmd = pmdp_collapse_flush(vma, addr, pmd);
--
2.51.0

^ permalink raw reply related

* Re: [PATCH v3 5/8] mm: set the VM_MAYBE_GUARD flag on guard region install
From: Lorenzo Stoakes @ 2025-11-10 17:37 UTC (permalink / raw)
  To: Vlastimil Babka
  Cc: Andrew Morton, Jonathan Corbet, David Hildenbrand,
	Liam R . Howlett, Mike Rapoport, Suren Baghdasaryan, Michal Hocko,
	Steven Rostedt, Masami Hiramatsu, Mathieu Desnoyers, Jann Horn,
	Pedro Falcato, Zi Yan, Baolin Wang, Nico Pache, Ryan Roberts,
	Dev Jain, Barry Song, Lance Yang, linux-kernel, linux-fsdevel,
	linux-doc, linux-mm, linux-trace-kernel, linux-kselftest,
	Andrei Vagin
In-Reply-To: <2bbccc79-d64e-4ace-a528-37295e3f8a4d@suse.cz>

On Mon, Nov 10, 2025 at 05:17:13PM +0100, Vlastimil Babka wrote:
> On 11/7/25 17:11, Lorenzo Stoakes wrote:
> > Now we have established the VM_MAYBE_GUARD flag and added the capacity to
> > set it atomically, do so upon MADV_GUARD_INSTALL.
> >
> > The places where this flag is used currently and matter are:
> >
> > * VMA merge - performed under mmap/VMA write lock, therefore excluding
> >   racing writes.
> >
> > * /proc/$pid/smaps - can race the write, however this isn't meaningful as
> >   the flag write is performed at the point of the guard region being
> >   established, and thus an smaps reader can't reasonably expect to avoid
> >   races. Due to atomicity, a reader will observe either the flag being set
> >   or not. Therefore consistency will be maintained.
> >
> > In all other cases the flag being set is irrelevant and atomicity
> > guarantees other flags will be read correctly.
> >
> > Note that non-atomic updates of unrelated flags do not cause an issue with
> > this flag being set atomically, as writes of other flags are performed
> > under mmap/VMA write lock, and these atomic writes are performed under
> > mmap/VMA read lock, which excludes the write, avoiding RMW races.
> >
> > Note that we do not encounter issues with KCSAN by adjusting this flag
> > atomically, as we are only updating a single bit in the flag bitmap and
> > therefore we do not need to annotate these changes.
> >
> > We intentionally set this flag in advance of actually updating the page
> > tables, to ensure that any racing atomic read of this flag will only return
> > false prior to page tables being updated, to allow for serialisation via
> > page table locks.
> >
> > Note that we set vma->anon_vma for anonymous mappings. This is because the
> > expectation for anonymous mappings is that an anon_vma is established
> > should they possess any page table mappings. This is also consistent with
> > what we were doing prior to this patch (unconditionally setting anon_vma on
> > guard region installation).
> >
> > We also need to update retract_page_tables() to ensure that madvise(...,
> > MADV_COLLAPSE) doesn't incorrectly collapse file-backed ranges contain
> > guard regions.
> >
> > This was previously guarded by anon_vma being set to catch MAP_PRIVATE
> > cases, but the introduction of VM_MAYBE_GUARD necessitates that we check
> > this flag instead.
> >
> > We utilise vma_flag_test_atomic() to do so - we first perform an optimistic
> > check, then after the PTE page table lock is held, we can check again
> > safely, as upon guard marker install the flag is set atomically prior to
> > the page table lock being taken to actually apply it.
> >
> > So if the initial check fails either:
> >
> > * Page table retraction acquires page table lock prior to VM_MAYBE_GUARD
> >   being set - guard marker installation will be blocked until page table
> >   retraction is complete.
> >
> > OR:
> >
> > * Guard marker installation acquires page table lock after setting
> >   VM_MAYBE_GUARD, which raced and didn't pick this up in the initial
> >   optimistic check, blocking page table retraction until the guard regions
> >   are installed - the second VM_MAYBE_GUARD check will prevent page table
> >   retraction.
> >
> > Either way we're safe.
> >
> > We refactor the retraction checks into a single
> > file_backed_vma_is_retractable(), there doesn't seem to be any reason that
> > the checks were separated as before.
> >
> > Note that VM_MAYBE_GUARD being set atomically remains correct as
> > vma_needs_copy() is invoked with the mmap and VMA write locks held,
> > excluding any race with madvise_guard_install().
> >
> > Signed-off-by: Lorenzo Stoakes <lorenzo.stoakes@oracle.com>
>
> Reviewed-by: Vlastimil Babka <vbabka@suse.cz>

Thanks

>
> Small nit below:
>
> > @@ -1778,15 +1801,16 @@ static void retract_page_tables(struct address_space *mapping, pgoff_t pgoff)
> >  			spin_lock_nested(ptl, SINGLE_DEPTH_NESTING);
> >
> >  		/*
> > -		 * Huge page lock is still held, so normally the page table
> > -		 * must remain empty; and we have already skipped anon_vma
> > -		 * and userfaultfd_wp() vmas.  But since the mmap_lock is not
> > -		 * held, it is still possible for a racing userfaultfd_ioctl()
> > -		 * to have inserted ptes or markers.  Now that we hold ptlock,
> > -		 * repeating the anon_vma check protects from one category,
> > -		 * and repeating the userfaultfd_wp() check from another.
> > +		 * Huge page lock is still held, so normally the page table must
> > +		 * remain empty; and we have already skipped anon_vma and
> > +		 * userfaultfd_wp() vmas.  But since the mmap_lock is not held,
> > +		 * it is still possible for a racing userfaultfd_ioctl() or
> > +		 * madvise() to have inserted ptes or markers.  Now that we hold
> > +		 * ptlock, repeating the anon_vma check protects from one
> > +		 * category, and repeating the userfaultfd_wp() check from
> > +		 * another.
>
> The last part of the comment is unchanged and mentions anon_vma check and
> userfaultfd_wp() check which were there explicitly originally, but now it's
> a file_backed_vma_is_retractable() check that also includes the guard region
> check, so maybe could be updated?

OK will send fix-patch.

>
> >  		 */
> > -		if (likely(!vma->anon_vma && !userfaultfd_wp(vma))) {
> > +		if (likely(file_backed_vma_is_retractable(vma))) {
> >  			pgt_pmd = pmdp_collapse_flush(vma, addr, pmd);
> >  			pmdp_get_lockless_sync();
> >  			success = true;
> > diff --git a/mm/madvise.c b/mm/madvise.c
> > index 67bdfcb315b3..de918b107cfc 100644
> > --- a/mm/madvise.c
> > +++ b/mm/madvise.c
> > @@ -1139,15 +1139,21 @@ static long madvise_guard_install(struct madvise_behavior *madv_behavior)
> >  		return -EINVAL;
> >
> >  	/*
> > -	 * If we install guard markers, then the range is no longer
> > -	 * empty from a page table perspective and therefore it's
> > -	 * appropriate to have an anon_vma.
> > -	 *
> > -	 * This ensures that on fork, we copy page tables correctly.
> > +	 * Set atomically under read lock. All pertinent readers will need to
> > +	 * acquire an mmap/VMA write lock to read it. All remaining readers may
> > +	 * or may not see the flag set, but we don't care.
> > +	 */
> > +	vma_flag_set_atomic(vma, VM_MAYBE_GUARD_BIT);
> > +
> > +	/*
> > +	 * If anonymous and we are establishing page tables the VMA ought to
> > +	 * have an anon_vma associated with it.
> >  	 */
> > -	err = anon_vma_prepare(vma);
> > -	if (err)
> > -		return err;
> > +	if (vma_is_anonymous(vma)) {
> > +		err = anon_vma_prepare(vma);
> > +		if (err)
> > +			return err;
> > +	}
> >
> >  	/*
> >  	 * Optimistically try to install the guard marker pages first. If any
>

^ permalink raw reply

* Re: [PATCH v3 2/8] mm: add atomic VMA flags and set VM_MAYBE_GUARD as such
From: Lorenzo Stoakes @ 2025-11-10 17:36 UTC (permalink / raw)
  To: Andrew Morton
  Cc: Jonathan Corbet, David Hildenbrand, Liam R . Howlett,
	Vlastimil Babka, Mike Rapoport, Suren Baghdasaryan, Michal Hocko,
	Steven Rostedt, Masami Hiramatsu, Mathieu Desnoyers, Jann Horn,
	Pedro Falcato, Zi Yan, Baolin Wang, Nico Pache, Ryan Roberts,
	Dev Jain, Barry Song, Lance Yang, linux-kernel, linux-fsdevel,
	linux-doc, linux-mm, linux-trace-kernel, linux-kselftest,
	Andrei Vagin
In-Reply-To: <cda9d4c073d773ef6c2cf2939d66cf80544cff40.1762531708.git.lorenzo.stoakes@oracle.com>

Hi Andrew,

Please apply this trivial fix-patch.

Thanks, Lorenzo

----8<----

From e73da6d99f6e32c959c7a852a90f03c9c76816c6 Mon Sep 17 00:00:00 2001
From: Lorenzo Stoakes <lorenzo.stoakes@oracle.com>
Date: Mon, 10 Nov 2025 17:35:11 +0000
Subject: [PATCH] fixup

Signed-off-by: Lorenzo Stoakes <lorenzo.stoakes@oracle.com>
---
 include/linux/mm.h | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/include/linux/mm.h b/include/linux/mm.h
index 699566c21ff7..e94005f2b985 100644
--- a/include/linux/mm.h
+++ b/include/linux/mm.h
@@ -900,6 +900,8 @@ static inline bool vma_flag_test_atomic(struct vm_area_struct *vma, int bit)
 {
 	if (__vma_flag_atomic_valid(vma, bit))
 		return test_bit(bit, &vma->__vm_flags);
+
+	return false;
 }

 static inline void vma_set_anonymous(struct vm_area_struct *vma)
--
2.51.0

^ permalink raw reply related

* Re: [PATCH v3 2/8] mm: add atomic VMA flags and set VM_MAYBE_GUARD as such
From: Lorenzo Stoakes @ 2025-11-10 17:34 UTC (permalink / raw)
  To: Vlastimil Babka
  Cc: Andrew Morton, Jonathan Corbet, David Hildenbrand,
	Liam R . Howlett, Mike Rapoport, Suren Baghdasaryan, Michal Hocko,
	Steven Rostedt, Masami Hiramatsu, Mathieu Desnoyers, Jann Horn,
	Pedro Falcato, Zi Yan, Baolin Wang, Nico Pache, Ryan Roberts,
	Dev Jain, Barry Song, Lance Yang, linux-kernel, linux-fsdevel,
	linux-doc, linux-mm, linux-trace-kernel, linux-kselftest,
	Andrei Vagin
In-Reply-To: <945fbe45-1ee7-4108-b01a-a8d2b0bb9cfe@suse.cz>

On Mon, Nov 10, 2025 at 04:51:27PM +0100, Vlastimil Babka wrote:
> On 11/7/25 17:11, Lorenzo Stoakes wrote:
> > This patch adds the ability to atomically set VMA flags with only the mmap
> > read/VMA read lock held.
> >
> > As this could be hugely problematic for VMA flags in general given that all
> > other accesses are non-atomic and serialised by the mmap/VMA locks, we
> > implement this with a strict allow-list - that is, only designated flags
> > are allowed to do this.
> >
> > We make VM_MAYBE_GUARD one of these flags.
> >
> > Reviewed-by: Pedro Falcato <pfalcato@suse.de>
> > Reviewed-by: Vlastimil Babka <vbabka@suse.cz>
> > Signed-off-by: Lorenzo Stoakes <lorenzo.stoakes@oracle.com>
> > ---
> >  include/linux/mm.h | 42 ++++++++++++++++++++++++++++++++++++++++++
> >  1 file changed, 42 insertions(+)
> >
> > diff --git a/include/linux/mm.h b/include/linux/mm.h
> > index 2a5516bff75a..699566c21ff7 100644
> > --- a/include/linux/mm.h
> > +++ b/include/linux/mm.h
> > @@ -518,6 +518,9 @@ extern unsigned int kobjsize(const void *objp);
> >  /* This mask represents all the VMA flag bits used by mlock */
> >  #define VM_LOCKED_MASK	(VM_LOCKED | VM_LOCKONFAULT)
> >
> > +/* These flags can be updated atomically via VMA/mmap read lock. */
> > +#define VM_ATOMIC_SET_ALLOWED VM_MAYBE_GUARD
> > +
> >  /* Arch-specific flags to clear when updating VM flags on protection change */
> >  #ifndef VM_ARCH_CLEAR
> >  # define VM_ARCH_CLEAR	VM_NONE
> > @@ -860,6 +863,45 @@ static inline void vm_flags_mod(struct vm_area_struct *vma,
> >  	__vm_flags_mod(vma, set, clear);
> >  }
> >
> > +static inline bool __vma_flag_atomic_valid(struct vm_area_struct *vma,
> > +				       int bit)
> > +{
> > +	const vm_flags_t mask = BIT(bit);
> > +
> > +	/* Only specific flags are permitted */
> > +	if (WARN_ON_ONCE(!(mask & VM_ATOMIC_SET_ALLOWED)))
> > +		return false;
> > +
> > +	return true;
> > +}
> > +
> > +/*
> > + * Set VMA flag atomically. Requires only VMA/mmap read lock. Only specific
> > + * valid flags are allowed to do this.
> > + */
> > +static inline void vma_flag_set_atomic(struct vm_area_struct *vma, int bit)
> > +{
> > +	/* mmap read lock/VMA read lock must be held. */
> > +	if (!rwsem_is_locked(&vma->vm_mm->mmap_lock))
> > +		vma_assert_locked(vma);
> > +
> > +	if (__vma_flag_atomic_valid(vma, bit))
> > +		set_bit(bit, &vma->__vm_flags);
> > +}
> > +
> > +/*
> > + * Test for VMA flag atomically. Requires no locks. Only specific valid flags
> > + * are allowed to do this.
> > + *
> > + * This is necessarily racey, so callers must ensure that serialisation is
> > + * achieved through some other means, or that races are permissible.
> > + */
> > +static inline bool vma_flag_test_atomic(struct vm_area_struct *vma, int bit)
> > +{
> > +	if (__vma_flag_atomic_valid(vma, bit))
> > +		return test_bit(bit, &vma->__vm_flags);
> > +}
>
> Hm clang is unhappy here.
>
> ./include/linux/mm.h:932:1: error: non-void function does not return a value in all control paths [-Werror,-Wreturn-type]
>   932 | }
>       | ^
> 1 error generated.

Yeah fun that gcc doesn't highlight this, god knows why not.

I thought I had fixed this (I remember it coming up in testing) but clearly I
fixed at the wrong commit.

>
> I don't have CONFIG_WERROR enabled though, so not sure why it's not just a
> warning, as the function is unused until patch 5/8 which adds a "return
> false" here. So it's just a potential bisection annoyance with clang.
>
> Andrew could you move that hunk from to this patch? Thanks.

I don't think this is the right solution.

Let's just add a return false. Will send a fix-patch.

>
> > +
> >  static inline void vma_set_anonymous(struct vm_area_struct *vma)
> >  {
> >  	vma->vm_ops = NULL;
>

Cheers, Lorenzo

^ permalink raw reply

* Re: [PATCH v8 00/27] mm/ksw: Introduce KStackWatch debugging tool
From: Matthew Wilcox @ 2025-11-10 17:33 UTC (permalink / raw)
  To: Jinchao Wang
  Cc: Andrew Morton, Masami Hiramatsu (Google), Peter Zijlstra,
	Randy Dunlap, Marco Elver, Mike Rapoport, Alexander Potapenko,
	Adrian Hunter, Alexander Shishkin, Alice Ryhl, Andrey Konovalov,
	Andrey Ryabinin, Andrii Nakryiko, Ard Biesheuvel,
	Arnaldo Carvalho de Melo, Ben Segall, Bill Wendling,
	Borislav Petkov, Catalin Marinas, Dave Hansen, David Hildenbrand,
	David Kaplan, David S. Miller, Dietmar Eggemann, Dmitry Vyukov,
	H. Peter Anvin, Ian Rogers, Ingo Molnar, James Clark, Jinjie Ruan,
	Jiri Olsa, Jonathan Corbet, Juri Lelli, Justin Stitt, kasan-dev,
	Kees Cook, Liam R. Howlett, Liang Kan, Linus Walleij,
	linux-arm-kernel, linux-doc, linux-kernel, linux-mm,
	linux-perf-users, linux-trace-kernel, llvm, Lorenzo Stoakes,
	Mark Rutland, Masahiro Yamada, Mathieu Desnoyers, Mel Gorman,
	Michal Hocko, Miguel Ojeda, Nam Cao, Namhyung Kim,
	Nathan Chancellor, Naveen N Rao, Nick Desaulniers, Rong Xu,
	Sami Tolvanen, Steven Rostedt, Suren Baghdasaryan,
	Thomas Gleixner, Thomas Weißschuh, Valentin Schneider,
	Vincent Guittot, Vincenzo Frascino, Vlastimil Babka, Will Deacon,
	workflows, x86
In-Reply-To: <20251110163634.3686676-1-wangjinchao600@gmail.com>

On Tue, Nov 11, 2025 at 12:35:55AM +0800, Jinchao Wang wrote:
> Earlier this year, I debugged a stack corruption panic that revealed the
> limitations of existing debugging tools. The bug persisted for 739 days
> before being fixed (CVE-2025-22036), and my reproduction scenario
> differed from the CVE report—highlighting how unpredictably these bugs
> manifest.

Well, this demonstrates the dangers of keeping this problem siloed
within your own exfat group.  The fix made in 1bb7ff4204b6 is wrong!
It was fixed properly in 7375f22495e7 which lists its Fixes: as
Linux-2.6.12-rc2, but that's simply the beginning of git history.
It's actually been there since v2.4.6.4 where it's documented as simply:

      - some subtle fs/buffer.c race conditions (Andrew Morton, me)

As far as I can tell the changes made in 1bb7ff4204b6 should be
reverted.

> Initially, I enabled KASAN, but the bug did not reproduce. Reviewing the
> code in __blk_flush_plug(), I found it difficult to trace all logic
> paths due to indirect function calls through function pointers.

So why is the solution here not simply to fix KASAN instead of this
giant patch series?

^ permalink raw reply

* Re: [PATCH 1/2] mm/khugepaged: do synchronous writeback for MADV_COLLAPSE
From: Zi Yan @ 2025-11-10 16:55 UTC (permalink / raw)
  To: Garg, Shivank, Lorenzo Stoakes
  Cc: Andrew Morton, David Hildenbrand, Baolin Wang, Liam R . Howlett,
	Nico Pache, Ryan Roberts, Dev Jain, Barry Song, Lance Yang,
	Steven Rostedt, Masami Hiramatsu, Mathieu Desnoyers,
	Zach O'Keefe, linux-mm, linux-kernel, linux-trace-kernel,
	Branden Moore
In-Reply-To: <e9a0ec60-6e8c-474f-931e-2f97e5bb60c0@lucifer.local>

On 10 Nov 2025, at 11:06, Lorenzo Stoakes wrote:

> On Mon, Nov 10, 2025 at 01:22:16PM +0000, Lorenzo Stoakes wrote:
>> On Mon, Nov 10, 2025 at 06:37:58PM +0530, Garg, Shivank wrote:
>>>
>>>
>>> On 11/10/2025 5:31 PM, Lorenzo Stoakes wrote:
>>>> On Mon, Nov 10, 2025 at 11:32:53AM +0000, Shivank Garg wrote:
>>>>> When MADV_COLLAPSE is called on file-backed mappings (e.g., executable
>>>
>>>>> ---
>>>>> Applies cleanly on:
>>>>> 6.18-rc5
>>>>> mm-stable:e9a6fb0bc
>>>>
>>>> Please base on mm-unstable. mm-stable is usually out of date until very close to
>>>> merge window.
>>>
>>> I'm observing issues when testing with kselftest on mm-unstable and mm-new branches that prevent
>>> proper testing for my patches:
>>>
>>> On mm-unstable (without my patches):
>>>
>>> # # running ./transhuge-stress -d 20
>>> # # --------------------------------
>>> # # TAP version 13
>>> # # 1..1
>>> # # transhuge-stress: allocate 220271 transhuge pages, using 440543 MiB virtual memory and 1720 MiB of ram
>>>
>>>
>>> [  367.225667] RIP: 0010:swap_cache_get_folio+0x2d/0xc0
>>> [  367.230635] Code: 00 00 48 89 f9 49 89 f9 48 89 fe 48 c1 e1 06 49 c1 e9 3a 48 c1 e9 0f 48 c1 e1 05 4a 8b 04 cd c0 2e 5b 99 48 8b 78 60 48 01 cf <48> 8b 47 08 48 85 c0 74 20 48 89 f2 81 e2 ff 01 00 00 48 8d 04 d0
>>> [  367.249378] RSP: 0000:ffffcde32943fba8 EFLAGS: 00010282
>>> [  367.254605] RAX: ffff8bd1668fdc00 RBX: 00007ffc15df5000 RCX: 00003fffffffffe0
>>> [  367.261736] RDX: ffffffff995cb530 RSI: 0003ffffffffffff RDI: ffffcbd1560dffe0
>>> [  367.268862] RBP: 0003ffffffffffff R08: ffffcde32943fc47 R09: 0000000000000000
>>> [  367.275994] R10: 0000000000000000 R11: 0000000000000000 R12: 0000000000000000
>>> [  367.283129] R13: 0000000000000000 R14: ffff8bd1668fdc00 R15: 0000000000100cca
>>> [  367.290260] FS:  00007ff600af5b80(0000) GS:ffff8c4e9ec7e000(0000) knlGS:0000000000000000
>>> [  367.298344] CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
>>> [  367.304083] CR2: ffffcbd1560dffe8 CR3: 00000001280e9001 CR4: 0000000000770ef0
>>> [  367.311216] PKRU: 55555554
>>> [  367.313929] Call Trace:
>>> [  367.316375]  <TASK>
>>> [  367.318479]  __read_swap_cache_async+0x8e/0x1b0
>>> [  367.323014]  swap_vma_readahead+0x23d/0x430
>>> [  367.327198]  swapin_readahead+0xb0/0xc0
>>> [  367.331039]  do_swap_page+0x5bc/0x1260
>>> [  367.334789]  ? rseq_ip_fixup+0x6f/0x190
>>> [  367.338631]  ? __pfx_default_wake_function+0x10/0x10
>>> [  367.343596]  __handle_mm_fault+0x49a/0x760
>>> [  367.347696]  handle_mm_fault+0x188/0x300
>>> [  367.351620]  do_user_addr_fault+0x15b/0x6c0
>>> [  367.355807]  exc_page_fault+0x60/0x100
>>> [  367.359562]  asm_exc_page_fault+0x22/0x30
>>> [  367.363574] RIP: 0033:0x7ff60091ba99
>>> [  367.367153] Code: f7 d8 64 89 02 b8 ff ff ff ff eb bd e8 40 c4 01 00 f3 0f 1e fa 80 3d b5 f5 0e 00 00 74 13 31 c0 0f 05 48 3d 00 f0 ff ff 77 4f <c3> 66 0f 1f 44 00 00 55 48 89 e5 48 83 ec 20 48 89 55 e8 48 89 75
>>> [  367.385897] RSP: 002b:00007ffc15df1118 EFLAGS: 00010203
>>> [  367.391124] RAX: 0000000000000001 RBX: 000055941fb672a0 RCX: 00007ff60091ba91
>>> [  367.398256] RDX: 0000000000000001 RSI: 000055941fb813e0 RDI: 0000000000000000
>>> [  367.405387] RBP: 00007ffc15df21e0 R08: 0000000000000000 R09: 0000000000000007
>>> [  367.412513] R10: 000055941fb97cb0 R11: 0000000000000246 R12: 000055941fb813e0
>>> [  367.419646] R13: 0000000000000000 R14: 0000000000000000 R15: 0000000000000000
>>> [  367.426781]  </TASK>
>>> [  367.428970] Modules linked in: xfrm_user xfrm_algo xt_addrtype xt_CHECKSUM xt_MASQUERADE xt_conntrack ipt_REJECT nf_reject_ipv4 nft_compat nft_chain_nat nf_nat nf_conntrack nf_defrag_ipv6 nf_defrag_ipv4 nf_tables overlay bridge stp llc cfg80211 rfkill binfmt_misc ipmi_ssif amd_atl intel_rapl_msr intel_rapl_common wmi_bmof amd64_edac edac_mce_amd mgag200 rapl drm_client_lib i2c_algo_bit drm_shmem_helper drm_kms_helper acpi_cpufreq i2c_piix4 ptdma k10temp i2c_smbus wmi acpi_power_meter ipmi_si acpi_ipmi ipmi_devintf ipmi_msghandler sg dm_multipath drm fuse dm_mod nfnetlink ext4 crc16 mbcache jbd2 raid10 raid456 async_raid6_recov async_memcpy async_pq async_xor xor async_tx raid6_pq raid1 raid0 kvm_amd sd_mod ahci nvme libahci kvm libata nvme_core tg3 ccp megaraid_sas irqbypass
>>> [  367.497528] CR2: ffffcbd1560dffe8
>>> [  367.500846] ---[ end trace 0000000000000000 ]---
>>
>> Yikes, oopsies!
>>
>> I'll try running tests locally on threadripper, but ran tests against yours
>> previously and seemed fine, strange. Maybe fixed since but let me try, maybe
>> because swap is not enabled locally for me?
>>
>> Likely this actually...
>
> I have tried on swap-enabled setup and no issue with mm-unstable.
>
> So this is odd, I know you have limited time (_totally sympathise_) but is it at
> all possible if you get a moment to bisect against tip mm-unstable/mm-new?
>
> Obviously we want to make sure buggy swap code doesn't get merged to mainline!

I could not reproduce locally either.

Shivank, can you share your config file and machine config?

>
>>
>>>
>>>
>>>
>>> -----------------
>>> On mm-new (without my patches):
>>>
>>> [  394.144770] get_swap_device: Bad swap offset entry 3ffffffffffff
>>>
>>> dmesg | grep "get_swap_device: Bad swap offset entry" | wc -l
>>> 359
>>>
>>>
>>> Additionally, kexec triggers an oops and crash during swapoff:
>>>
>>>
>>>          Deactivating swap   704.854238] BUG: unable to handle page fault for address: ffffcbe2de8dffe8
>>> [  704.861524] #PF: supervisor read access in kernel mode
>>> ;39mswap.img.swa[  704.866666] #PF: error_code(0x0000) - not-present page
>>> [  704.873253] PGD 0 P4D 0
>>> p - /swap.im[  704.875790] Oops: Oops: 0000 [#1] SMP NOPTI
>>> g...
>>> [  704.881354] CPU: 122 UID: 0 PID: 107680 Comm: swapoff Kdump: loaded Not tainted 6.18.0-rc5+ #11 NONE
>>> [  704.891283] Hardware name: Dell Inc. PowerEdge R6525/024PW1, BIOS 2.16.2 07/09/2024
>>> [  704.898930] RIP: 0010:swap_cache_get_folio+0x2d/0xc0
>>> [  704.903907] Code: 00 00 48 89 f9 49 89 f9 48 89 fe 48 c1 e1 06 49 c1 e9 3a 48 c1 e9 0f 48 c1 e1 05 4a 8b 04 cd c0 2e 7b 95 48 8b 78 60 48 01 cf <48> 8b 47 08 48 85 c0 74 20 48 89 f2 81 e2 ff 01 00 00 48 8d 04 d0
>>> [  704.922720] RSP: 0018:ffffcf1227b1fc08 EFLAGS: 00010282
>>> [  704.928035] RAX: ffff8be2cefb3c00 RBX: 0000555c65a5c000 RCX: 00003fffffffffe0
>>> [  704.928036] RDX: 0003ffffffffffff RSI: 0003ffffffffffff RDI: ffffcbe2de8dffe0
>>> [  704.928037] RBP: 0000000000000000 R08: ffff8be2de8e0520 R09: 0000000000000000
>>>          Unmount[  704.928038] R10: 000000000000ffff R11: ffffcf12236f4000 R12: ffff8be2d5b8d968
>>> [  704.928039] R13: 0003ffffffffffff R14: fffff3eec85eb000 R15: 0000555c65a51000
>>> [  704.928039] FS:  00007f41fcab3800(0000) GS:ffff8c602b6fe000(0000) knlGS:0000000000000000
>>> [  704.928040] CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
>>> [  704.928041] CR2: ffffcbe2de8dffe8 CR3: 00000074981af004 CR4: 0000000000770ef0
>>> [  704.928041] PKRU: 55555554
>>> [  704.928042] Call Trace:
>>> [  704.928043]  <TASK>
>>> [  704.928044]  unuse_pte_range+0x10b/0x290
>>> [  704.928047]  unuse_pud_range.isra.0+0x149/0x190
>>> [  704.928048]  unuse_vma+0x1a6/0x220
>>> [  704.928050]  unuse_mm+0x9b/0x110
>>> [  704.928052]  try_to_unuse+0xc5/0x260
>>> [  704.928053]  __do_sys_swapoff+0x244/0x670
>>> ing boo[  705.016662]  do_syscall_64+0x67/0xc50
>>> [  705.016667]  ? do_user_addr_fault+0x15b/0x6c0
>>> t.mount - /b[  705.026100]  ? exc_page_fault+0x60/0x100
>>> [  705.031498]  ? irqentry_exit_to_user_mode+0x20/0xe0
>>> oot...
>>> [  705.036377]  entry_SYSCALL_64_after_hwframe+0x76/0x7e
>>> [  705.042200] RIP: 0033:0x7f41fc9271bb
>>> [  705.045780] Code: 0f 1e fa 48 83 fe 01 48 8b 15 59 bc 0d 00 19 c0 83 e0 f0 83 c0 26 64 89 02 b8 ff ff ff ff c3 f3 0f 1e fa b8 a8 00 00 00 0f 05 <48> 3d 01 f0 ff ff 73 01 c3 48 8b 0d 2d bc 0d 00 f7 d8 64 89 01 48
>>> [  705.064807] RSP: 002b:00007ffd14b5b6e8 EFLAGS: 00000202 ORIG_RAX: 00000000000000a8
>>> [  705.064809] RAX: ffffffffffffffda RBX: 00007ffd14b5cf30 RCX: 00007f41fc9271bb
>>> [  705.064810] RDX: 0000000000000001 RSI: 0000000000000c00 RDI: 000055d48f533a40
>>> [  705.064810] RBP: 00007ffd14b5b750 R08: 00007f41fca03b20 R09: 0000000000000000
>>> [  705.064811] R10: 0000000000000001 R11: 0000000000000202 R12: 0000000000000000
>>> [  705.064811] R13: 0000000000000000 R14: 000055d4584f1479 R15: 000055d4584f2b20
>>> [  705.064813]  </TASK>
>>> [  705.064814] Modules linked in: xfrm_user xfrm_algo xt_addrtype xt_CHECKSUM xt_MASQUERADE xt_conntrack ipt_REJECT nf_reject_ipv4 nft_compat nft_chain_nat nf_nat nf_conntrack nf_defrag_ipv6 nf_defrag_ipv4 nf_tables overlay bridge stp llc cfg80211 rfkill binfmt_misc ipmi_ssif amd_atl intel_rapl_msr intel_rapl_common wmi_bmof amd64_edac edac_mce_amd rapl mgag200 drm_client_lib i2c_algo_bit drm_shmem_helper drm_kms_helper acpi_cpufreq i2c_piix4 ptdma ipmi_si k10temp i2c_smbus acpi_power_meter wmi acpi_ipmi ipmi_msghandler sg dm_multipath fuse drm dm_mod nfnetlink ext4 crc16 mbcache jbd2 raid10 raid456 async_raid6_recov async_memcpy async_pq async_xor xor async_tx raid6_pq raid1 raid0 sd_mod kvm_amd ahci libahci kvm nvme tg3 libata ccp irqbypass nvme_core megaraid_sas [last unloaded: ipmi_devintf]
>>> [  705.180420] CR2: ffffcbe2de8dffe8
>>> [  705.183852] ---[ end trace 0000000000000000 ]---
>>>
>>>
>>> I haven't had cycles to dig into this yet and been swamped with other things.
>>
>> Fully understand, I'm _very_ familiar with this situation :)
>>
>> I need more cores... ;)
>
> Oh it's nice to have more :) I am bankrupt now, but it's nice to have more ;)
>
> Cheers, Lorenzo


Best Regards,
Yan, Zi

^ permalink raw reply

* Re: [PATCH 2/2] tracing: Use switch statement instead of ifs in set_tracer_flag()
From: Steven Rostedt @ 2025-11-10 16:42 UTC (permalink / raw)
  To: Masami Hiramatsu (Google)
  Cc: Steven Rostedt, linux-kernel, linux-trace-kernel, Mark Rutland,
	Mathieu Desnoyers, Andrew Morton
In-Reply-To: <20251110144826.8d92d83af67efebac2a3ecf5@kernel.org>

On Mon, 10 Nov 2025 14:48:26 +0900
Masami Hiramatsu (Google) <mhiramat@kernel.org> wrote:

> BTW, set_tracer_flag() seems to expect to modify only one bit.
> If we can count the number of its in @mask and reject if it is
> not 1, we can use bit-mask instead of the first switch()?
> 
> 	if (!mask ||	/* mask has no bit */
> 	    (mask & ~(1 << (ffs64(mask) - 1))))	/* mask has more than 2 bits */
> 		return -EINVAL;

Well, this has been around for over a decade without any issues. I don't
think a check would be of much use. Not to mention, invalid masks are OK to
pass in.

If anything, I would have liked to pass in the bit number and not a mask.
But that's something we could do another time.

-- Steve

^ permalink raw reply

* [PATCH v8 27/27] MAINTAINERS: add entry for KStackWatch
From: Jinchao Wang @ 2025-11-10 16:36 UTC (permalink / raw)
  To: Andrew Morton, Masami Hiramatsu (Google), Peter Zijlstra,
	Randy Dunlap, Marco Elver, Mike Rapoport, Alexander Potapenko,
	Adrian Hunter, Alexander Shishkin, Alice Ryhl, Andrey Konovalov,
	Andrey Ryabinin, Andrii Nakryiko, Ard Biesheuvel,
	Arnaldo Carvalho de Melo, Ben Segall, Bill Wendling,
	Borislav Petkov, Catalin Marinas, Dave Hansen, David Hildenbrand,
	David Kaplan, David S. Miller, Dietmar Eggemann, Dmitry Vyukov,
	H. Peter Anvin, Ian Rogers, Ingo Molnar, James Clark,
	Jinchao Wang, Jinjie Ruan, Jiri Olsa, Jonathan Corbet, Juri Lelli,
	Justin Stitt, kasan-dev, Kees Cook, Liam R. Howlett, Liang Kan,
	Linus Walleij, linux-arm-kernel, linux-doc, linux-kernel,
	linux-mm, linux-perf-users, linux-trace-kernel, llvm,
	Lorenzo Stoakes, Mark Rutland, Masahiro Yamada, Mathieu Desnoyers,
	Mel Gorman, Michal Hocko, Miguel Ojeda, Nam Cao, Namhyung Kim,
	Nathan Chancellor, Naveen N Rao, Nick Desaulniers, Rong Xu,
	Sami Tolvanen, Steven Rostedt, Suren Baghdasaryan,
	Thomas Gleixner, Thomas Weißschuh, Valentin Schneider,
	Vincent Guittot, Vincenzo Frascino, Vlastimil Babka, Will Deacon,
	workflows, x86
In-Reply-To: <20251110163634.3686676-1-wangjinchao600@gmail.com>

Add a maintainer entry for Kernel Stack Watch.

Signed-off-by: Jinchao Wang <wangjinchao600@gmail.com>
---
 MAINTAINERS | 9 +++++++++
 1 file changed, 9 insertions(+)

diff --git a/MAINTAINERS b/MAINTAINERS
index ddecf1ef3bed..9757775de515 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -13615,6 +13615,15 @@ F:	Documentation/filesystems/smb/ksmbd.rst
 F:	fs/smb/common/
 F:	fs/smb/server/
 
+KERNEL STACK WATCH
+M:	Jinchao Wang <wangjinchao600@gmail.com>
+S:	Maintained
+F:	Documentation/dev-tools/kstackwatch.rst
+F:	include/linux/kstackwatch.h
+F:	include/linux/kstackwatch_types.h
+F:	mm/kstackwatch/
+F:	tools/kstackwatch/
+
 KERNEL UNIT TESTING FRAMEWORK (KUnit)
 M:	Brendan Higgins <brendan.higgins@linux.dev>
 M:	David Gow <davidgow@google.com>
-- 
2.43.0


^ permalink raw reply related

* [PATCH v8 26/27] docs: add KStackWatch document
From: Jinchao Wang @ 2025-11-10 16:36 UTC (permalink / raw)
  To: Andrew Morton, Masami Hiramatsu (Google), Peter Zijlstra,
	Randy Dunlap, Marco Elver, Mike Rapoport, Alexander Potapenko,
	Adrian Hunter, Alexander Shishkin, Alice Ryhl, Andrey Konovalov,
	Andrey Ryabinin, Andrii Nakryiko, Ard Biesheuvel,
	Arnaldo Carvalho de Melo, Ben Segall, Bill Wendling,
	Borislav Petkov, Catalin Marinas, Dave Hansen, David Hildenbrand,
	David Kaplan, David S. Miller, Dietmar Eggemann, Dmitry Vyukov,
	H. Peter Anvin, Ian Rogers, Ingo Molnar, James Clark,
	Jinchao Wang, Jinjie Ruan, Jiri Olsa, Jonathan Corbet, Juri Lelli,
	Justin Stitt, kasan-dev, Kees Cook, Liam R. Howlett, Liang Kan,
	Linus Walleij, linux-arm-kernel, linux-doc, linux-kernel,
	linux-mm, linux-perf-users, linux-trace-kernel, llvm,
	Lorenzo Stoakes, Mark Rutland, Masahiro Yamada, Mathieu Desnoyers,
	Mel Gorman, Michal Hocko, Miguel Ojeda, Nam Cao, Namhyung Kim,
	Nathan Chancellor, Naveen N Rao, Nick Desaulniers, Rong Xu,
	Sami Tolvanen, Steven Rostedt, Suren Baghdasaryan,
	Thomas Gleixner, Thomas Weißschuh, Valentin Schneider,
	Vincent Guittot, Vincenzo Frascino, Vlastimil Babka, Will Deacon,
	workflows, x86
In-Reply-To: <20251110163634.3686676-1-wangjinchao600@gmail.com>

Add documentation for KStackWatch under Documentation/.

It provides an overview, main features, usage details, configuration
parameters, and example scenarios with test cases. The document also
explains how to locate function offsets and interpret logs.

Signed-off-by: Jinchao Wang <wangjinchao600@gmail.com>
---
 Documentation/dev-tools/index.rst       |   1 +
 Documentation/dev-tools/kstackwatch.rst | 377 ++++++++++++++++++++++++
 2 files changed, 378 insertions(+)
 create mode 100644 Documentation/dev-tools/kstackwatch.rst

diff --git a/Documentation/dev-tools/index.rst b/Documentation/dev-tools/index.rst
index 4b8425e348ab..272ae9b76863 100644
--- a/Documentation/dev-tools/index.rst
+++ b/Documentation/dev-tools/index.rst
@@ -32,6 +32,7 @@ Documentation/process/debugging/index.rst
    lkmm/index
    kfence
    kselftest
+   kstackwatch
    kunit/index
    ktap
    checkuapi
diff --git a/Documentation/dev-tools/kstackwatch.rst b/Documentation/dev-tools/kstackwatch.rst
new file mode 100644
index 000000000000..9b710b90e512
--- /dev/null
+++ b/Documentation/dev-tools/kstackwatch.rst
@@ -0,0 +1,377 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+=================================
+Kernel Stack Watch (KStackWatch)
+=================================
+
+Overview
+========
+
+KStackWatch is a lightweight debugging tool designed to detect kernel stack
+corruption in real time. It installs a hardware breakpoint (watchpoint) at a
+function's specified offset using *kprobe.post_handler* and removes it in
+*fprobe.exit_handler*. This covers the full execution window and reports
+corruption immediately with time, location, and call stack.
+
+Main features:
+
+* Immediate and precise stack corruption detection
+* Support for multiple concurrent watchpoints with configurable limits
+* Lockless design, usable in any context
+* Depth filter for recursive calls
+* Low overhead of memory and CPU
+* Flexible debugfs configuration with key=val syntax
+* Architecture support: x86_64 and arm64
+* Auto-canary detection to simplify configuration
+
+Performance Impact
+==================
+
+Runtime overhead was measured on Intel Core Ultra 5 125H @ 3 GHz running
+kernel 6.17, using test4:
+
++------------------------+-------------+---------+
+| Type                   | Time (ns)   | Cycles  |
++========================+=============+=========+
+| entry with watch       | 10892       | 32620   |
++------------------------+-------------+---------+
+| entry without watch    | 159         | 466     |
++------------------------+-------------+---------+
+| exit with watch        | 12541       | 37556   |
++------------------------+-------------+---------+
+| exit without watch     | 124         | 369     |
++------------------------+-------------+---------+
+
+From a broader perspective, the overall comparison is as follows:
+
++----------------------------+----------------------+-------------------------+
+| Mode                       | CPU Overhead (add)   | Memory Overhead (add)   |
++============================+======================+=========================+
+| Compiled but not enabled   | None                 | ~20 B per task          |
++----------------------------+----------------------+-------------------------+
+| Enabled, no function hit   | None                 | ~few hundred B          |
++----------------------------+----------------------+-------------------------+
+| Func hit, HWBP not toggled | ~140 ns per call     | None                    |
++----------------------------+----------------------+-------------------------+
+| Func hit, HWBP toggled     | ~11–12 µs per call   | None                    |
++----------------------------+----------------------+-------------------------+
+
+The overhead is minimal, making KStackWatch suitable for production
+environments where stack corruption is suspected but kernel rebuilds are not
+feasible.
+
+Kconfig Options
+===============
+
+The following configuration options control KStackWatch builds:
+
+- CONFIG_KSTACKWATCH
+
+  Builds the kernel with KStackWatch enabled.
+
+- CONFIG_KSTACKWATCH_PROFILING
+
+  Measures probe runtime overhead for performance analysis and tuning.
+
+- CONFIG_KSTACKWATCH_TEST
+
+  Builds a test module to validate KStackWatch functionality.
+
+Usage
+=====
+
+KStackWatch provides optional configurations for different use cases.
+CONFIG_KSTACKWATCH enables real-time stack corruption detection using hardware breakpoints and probes.
+CONFIG_KSTACKWATCH_PROFILING allows measurement of probe latency and overhead for performance analysis.
+CONFIG_KSTACKWATCH_TEST builds a test module for validating KStackWatch functionality under controlled conditions.
+
+KStackWatch is configured through */sys/kernel/debug/kstackwatch/config* using a
+key=value format. Both long and short forms are supported. Writing an empty
+string disables the watch.
+
+.. code-block:: bash
+
+	# long form
+	echo func_name=? func_offset=? ... > /sys/kernel/debug/kstackwatch/config
+
+	# short form
+	echo fn=? fo=? ... > /sys/kernel/debug/kstackwatch/config
+
+	# disable
+	echo > /sys/kernel/debug/kstackwatch/config
+
+The func_name and the func_offset where the watchpoint should be placed must be
+known. This information can be obtained from *objdump* or other tools.
+
+Required parameters
+--------------------
+
++--------------+--------+-----------------------------------------+
+| Parameter    | Short  | Description                             |
++==============+========+=========================================+
+| func_name    | fn     | Name of the target function             |
++--------------+--------+-----------------------------------------+
+| func_offset  | fo     | Instruction pointer offset              |
++--------------+--------+-----------------------------------------+
+
+Optional parameters
+--------------------
+
+Default 0 and can be omitted.
+Both decimal and hexadecimal are supported.
+
++--------------+--------+------------------------------------------------+
+| Parameter    | Short  | Description                                    |
++==============+========+================================================+
+| auto_canary  | ac     | Automatically calculated canary sp_offset      |
++--------------+--------+------------------------------------------------+
+| depth        | dp     | Recursion depth filter                         |
++--------------+--------+------------------------------------------------+
+|              |        | Maximum number of concurrent watchpoints       |
+| max_watch    | mw     | (default 0, capped by available hardware       |
+|              |        | breakpoints)                                   |
++--------------+--------+------------------------------------------------+
+| panic_hit    | ph     | Panic system on watchpoint hit (default 0)     |
++--------------+--------+------------------------------------------------+
+| sp_offset    | so     | Watching addr offset from stack pointer        |
++--------------+--------+------------------------------------------------+
+| watch_len    | wl     | Watch length in bytes (1, 2, 4, 8 onX86_64)    |
++--------------+--------+------------------------------------------------+
+
+
+Workflow Example
+================
+
+Silent corruption
+-----------------
+
+Consider *test3* in *kstackwatch_test.sh*. Run it directly:
+
+.. code-block:: bash
+
+	echo test3 >/sys/kernel/debug/kstackwatch/test
+
+Sometimes, *test_mthread_victim()* may report as unhappy:
+
+.. code-block:: bash
+
+	[    7.807082] kstackwatch_test: victim[0][11]: unhappy buf[8]=0xabcdabcd
+
+Its source code is:
+
+.. code-block:: c
+
+	static void test_mthread_victim(int thread_id, int seq_id, u64 start_ns)
+	{
+		ulong buf[BUFFER_SIZE];
+
+		for (int j = 0; j < BUFFER_SIZE; j++)
+			buf[j] = 0xdeadbeef + seq_id;
+
+		if (start_ns)
+			silent_wait_us(start_ns, VICTIM_MINIOR_WAIT_NS);
+
+		for (int j = 0; j < BUFFER_SIZE; j++) {
+			if (buf[j] != (0xdeadbeef + seq_id)) {
+				pr_warn("victim[%d][%d]: unhappy buf[%d]=0x%lx\n",
+					thread_id, seq_id, j, buf[j]);
+				return;
+			}
+		}
+
+		pr_info("victim[%d][%d]: happy\n", thread_id, seq_id);
+	}
+
+From the source code, the report indicates buf[8] was unexpectedly modified,
+a case of silent corruption.
+
+Configuration
+-------------
+
+Since buf[8] is the corrupted variable, the following configuration shows
+how to use KStackWatch to detect its corruption.
+
+func_name
+~~~~~~~~~~~
+
+As seen, buf[8] is initialized and modified in *test_mthread_victim*\(\) ,
+which sets *func_name*.
+
+func_offset & sp_offset
+~~~~~~~~~~~~~~~~~~~~~~~~~
+The watchpoint should be set after the assignment and as close as
+possible, which sets *func_offset*.
+
+The watchpoint should be set to watch buf[8], which sets *sp_offset*.
+
+Use the objdump output to disassemble the function:
+
+.. code-block:: bash
+
+	objdump -S --disassemble=test_mthread_victim vmlinux
+
+A shortened output is:
+
+.. code-block:: text
+
+	static void test_mthread_victim(int thread_id, int seq_id, u64 start_ns)
+	{
+	ffffffff815cb4e0:       e8 5b 9b ca ff          call   ffffffff81275040 <__fentry__>
+	ffffffff815cb4e5:       55                      push   %rbp
+	ffffffff815cb4e6:       53                      push   %rbx
+	ffffffff815cb4e7:       48 81 ec 08 01 00 00    sub    $0x108,%rsp
+	ffffffff815cb4ee:       89 fd                   mov    %edi,%ebp
+	ffffffff815cb4f0:       89 f3                   mov    %esi,%ebx
+	ffffffff815cb4f2:       49 89 d0                mov    %rdx,%r8
+	ffffffff815cb4f5:       65 48 8b 05 0b cb 80    mov    %gs:0x280cb0b(%rip),%rax        # ffffffff83dd8008 <__stack_chk_guard>
+	ffffffff815cb4fc:       02
+	ffffffff815cb4fd:       48 89 84 24 00 01 00    mov    %rax,0x100(%rsp)
+	ffffffff815cb504:       00
+	ffffffff815cb505:       31 c0                   xor    %eax,%eax
+		ulong buf[BUFFER_SIZE];
+	ffffffff815cb507:       48 89 e2                mov    %rsp,%rdx
+	ffffffff815cb50a:       b9 20 00 00 00          mov    $0x20,%ecx
+	ffffffff815cb50f:       48 89 d7                mov    %rdx,%rdi
+	ffffffff815cb512:       f3 48 ab                rep stos %rax,%es:(%rdi)
+
+		for (int j = 0; j < BUFFER_SIZE; j++)
+	ffffffff815cb515:       eb 10                   jmp    ffffffff815cb527 <test_mthread_victim+0x47>
+			buf[j] = 0xdeadbeef + seq_id;
+	ffffffff815cb517:       8d 93 ef be ad de       lea    -0x21524111(%rbx),%edx
+	ffffffff815cb51d:       48 63 c8                movslq %eax,%rcx
+	ffffffff815cb520:       48 89 14 cc             mov    %rdx,(%rsp,%rcx,8)
+	ffffffff815cb524:       83 c0 01                add    $0x1,%eax
+	ffffffff815cb527:       83 f8 1f                cmp    $0x1f,%eax
+	ffffffff815cb52a:       7e eb                   jle    ffffffff815cb517 <test_mthread_victim+0x37>
+		if (start_ns)
+	ffffffff815cb52c:       4d 85 c0                test   %r8,%r8
+	ffffffff815cb52f:       75 21                   jne    ffffffff815cb552 <test_mthread_victim+0x72>
+			silent_wait_us(start_ns, VICTIM_MINIOR_WAIT_NS);
+	...
+	ffffffff815cb571:       48 8b 84 24 00 01 00    mov    0x100(%rsp),%rax
+	ffffffff815cb579:       65 48 2b 05 87 ca 80    sub    %gs:0x280ca87(%rip),%rax        # ffffffff83dd8008 <__stack_chk_guard>
+	...
+	ffffffff815cb5a1:       eb ce                   jmp    ffffffff815cb571 <test_mthread_victim+0x91>
+	}
+	ffffffff815cb5a3:       e8 d8 86 f1 00          call   ffffffff824e3c80 <__stack_chk_fail>
+
+
+func_offset
+^^^^^^^^^^^
+
+The function begins at ffffffff815cb4e0. The *buf* array is initialized in a loop.
+The instruction storing values into the array is at ffffffff815cb520, and the
+first instruction after the loop is at ffffffff815cb52c.
+
+Because KStackWatch uses *kprobe.post_handler*, the watchpoint can be
+set right after ffffffff815cb520. However, this will cause false positive
+because the watchpoint is active before buf[8] is assigned.
+
+An alternative is to place the watchpoint at ffffffff815cb52c, right
+after the loop. This avoids false positives but leaves a small window
+for false negatives.
+
+In this document, ffffffff815cb52c is chosen for cleaner logs. If false
+negatives are suspected, repeat the test to catch the corruption.
+
+The required offset is calculated from the function start:
+
+*func_offset* is 0x4c (ffffffff815cb52c - ffffffff815cb4e0).
+
+sp_offset
+^^^^^^^^^^^
+
+From the disassembly, the buf array is at the top of the stack,
+meaning buf == rsp. Therefore, buf[8] sits at rsp + 8 * sizeof(ulong) =
+rsp + 64. Thus, *sp_offset* is 64.
+
+Other parameters
+~~~~~~~~~~~~~~~~~~
+
+* *depth* is 0, as test_mthread_victim is not recursive
+* *max_watch* is 0 to use all available hwbps
+* *watch_len* is 8, the size of a ulong on x86_64
+
+Parameters with a value of 0 can be omitted as defaults.
+
+Configure the watch:
+
+.. code-block:: bash
+
+	echo "fn=test_mthread_victim fo=0x4c so=64 wl=8" > /sys/kernel/debug/kstackwatch/config
+
+Now rerun the test:
+
+.. code-block:: bash
+
+	echo test3 >/sys/kernel/debug/kstackwatch/test
+
+The dmesg log shows:
+
+.. code-block:: text
+
+	[    7.607074] kstackwatch: ========== KStackWatch: Caught stack corruption =======
+	[    7.607077] kstackwatch: config fn=test_mthread_victim fo=0x4c so=64 wl=8
+	[    7.607080] CPU: 2 UID: 0 PID: 347 Comm: corrupting Not tainted 6.17.0-rc7-00022-g90270f3db80a-dirty #509 PREEMPT(voluntary)
+	[    7.607083] Call Trace:
+	[    7.607084]  <#DB>
+	[    7.607085]  dump_stack_lvl+0x66/0xa0
+	[    7.607091]  ksw_watch_handler.part.0+0x2b/0x60
+	[    7.607094]  ksw_watch_handler+0xba/0xd0
+	[    7.607095]  ? test_mthread_corrupting+0x48/0xd0
+	[    7.607097]  ? kthread+0x10d/0x210
+	[    7.607099]  ? ret_from_fork+0x187/0x1e0
+	[    7.607102]  ? ret_from_fork_asm+0x1a/0x30
+	[    7.607105]  __perf_event_overflow+0x154/0x570
+	[    7.607108]  perf_bp_event+0xb4/0xc0
+	[    7.607112]  ? look_up_lock_class+0x59/0x150
+	[    7.607115]  hw_breakpoint_exceptions_notify+0xf7/0x110
+	[    7.607117]  notifier_call_chain+0x44/0x110
+	[    7.607119]  atomic_notifier_call_chain+0x5f/0x110
+	[    7.607121]  notify_die+0x4c/0xb0
+	[    7.607123]  exc_debug_kernel+0xaf/0x170
+	[    7.607126]  asm_exc_debug+0x1e/0x40
+	[    7.607127] RIP: 0010:test_mthread_corrupting+0x48/0xd0
+	[    7.607129] Code: c7 80 0a 24 83 e8 48 f1 f1 00 48 85 c0 74 dd eb 30 bb 00 00 00 00 eb 59 48 63 c2 48 c1 e0 03 48 03 03 be cd ab cd ab 48 89 30 <83> c2 01 b8 20 00 00 00 29 c8 39 d0 7f e0 48 8d 7b 10 e8 d1 86 d4
+	[    7.607130] RSP: 0018:ffffc90000acfee0 EFLAGS: 00000286
+	[    7.607132] RAX: ffffc90000a13de8 RBX: ffff888102d57580 RCX: 0000000000000008
+	[    7.607132] RDX: 0000000000000008 RSI: 00000000abcdabcd RDI: ffffc90000acfe00
+	[    7.607133] RBP: ffff8881085bc800 R08: 0000000000000001 R09: 0000000000000000
+	[    7.607133] R10: 0000000000000001 R11: 0000000000000000 R12: ffff888105398000
+	[    7.607134] R13: ffff8881085bc800 R14: ffffffff815cb660 R15: 0000000000000000
+	[    7.607134]  ? __pfx_test_mthread_corrupting+0x10/0x10
+	[    7.607137]  </#DB>
+	[    7.607138]  <TASK>
+	[    7.607138]  kthread+0x10d/0x210
+	[    7.607140]  ? __pfx_kthread+0x10/0x10
+	[    7.607141]  ret_from_fork+0x187/0x1e0
+	[    7.607143]  ? __pfx_kthread+0x10/0x10
+	[    7.607144]  ret_from_fork_asm+0x1a/0x30
+	[    7.607147]  </TASK>
+	[    7.607147] kstackwatch: =================== KStackWatch End ===================
+	[    7.807082] kstackwatch_test: victim[0][11]: unhappy buf[8]=0xabcdabcd
+
+The line ``RIP: 0010:test_mthread_corrupting+0x48/0xd0`` shows the exact
+location where the corruption occurred. Now that the ``corrupting()`` function has
+been identified, it is straightforward to trace back to ``buggy()`` and fix the bug.
+
+
+More usage examples and corruption scenarios are provided in
+``kstackwatch_test.sh`` and ``mm/kstackwatch/test.c``.
+
+Limitations
+===========
+
+* Limited by available hardware breakpoints
+* Only one function can be watched at a time
+* Canary search limited to 128 * sizeof(ulong) from the current stack
+  pointer. This is sufficient for most cases, but has three limitations:
+
+  - If the stack frame is larger, the search may fail.
+  - If the function does not have a canary, the search may fail.
+  - If stack memory occasionally contains the same value as the canary,
+    it may be incorrectly matched.
+
+  In these cases, the user can provide the canary location using
+  ``sp_offset``, or treat any memory in the function prologue
+  as the canary.
-- 
2.43.0


^ permalink raw reply related

* [PATCH v8 25/27] tools/ksw: add arch-specific test script
From: Jinchao Wang @ 2025-11-10 16:36 UTC (permalink / raw)
  To: Andrew Morton, Masami Hiramatsu (Google), Peter Zijlstra,
	Randy Dunlap, Marco Elver, Mike Rapoport, Alexander Potapenko,
	Adrian Hunter, Alexander Shishkin, Alice Ryhl, Andrey Konovalov,
	Andrey Ryabinin, Andrii Nakryiko, Ard Biesheuvel,
	Arnaldo Carvalho de Melo, Ben Segall, Bill Wendling,
	Borislav Petkov, Catalin Marinas, Dave Hansen, David Hildenbrand,
	David Kaplan, David S. Miller, Dietmar Eggemann, Dmitry Vyukov,
	H. Peter Anvin, Ian Rogers, Ingo Molnar, James Clark,
	Jinchao Wang, Jinjie Ruan, Jiri Olsa, Jonathan Corbet, Juri Lelli,
	Justin Stitt, kasan-dev, Kees Cook, Liam R. Howlett, Liang Kan,
	Linus Walleij, linux-arm-kernel, linux-doc, linux-kernel,
	linux-mm, linux-perf-users, linux-trace-kernel, llvm,
	Lorenzo Stoakes, Mark Rutland, Masahiro Yamada, Mathieu Desnoyers,
	Mel Gorman, Michal Hocko, Miguel Ojeda, Nam Cao, Namhyung Kim,
	Nathan Chancellor, Naveen N Rao, Nick Desaulniers, Rong Xu,
	Sami Tolvanen, Steven Rostedt, Suren Baghdasaryan,
	Thomas Gleixner, Thomas Weißschuh, Valentin Schneider,
	Vincent Guittot, Vincenzo Frascino, Vlastimil Babka, Will Deacon,
	workflows, x86
In-Reply-To: <20251110163634.3686676-1-wangjinchao600@gmail.com>

Add a shell script under tools/kstackwatch to run self-tests such as
canary overflow and recursive depth. The script supports both x86_64
and arm64, selecting parameters automatically based on uname -m.

Signed-off-by: Jinchao Wang <wangjinchao600@gmail.com>
---
 tools/kstackwatch/kstackwatch_test.sh | 85 +++++++++++++++++++++++++++
 1 file changed, 85 insertions(+)
 create mode 100755 tools/kstackwatch/kstackwatch_test.sh

diff --git a/tools/kstackwatch/kstackwatch_test.sh b/tools/kstackwatch/kstackwatch_test.sh
new file mode 100755
index 000000000000..6e83397d3213
--- /dev/null
+++ b/tools/kstackwatch/kstackwatch_test.sh
@@ -0,0 +1,85 @@
+#!/bin/bash
+# SPDX-License-Identifier: GPL-2.0
+
+echo "IMPORTANT: Before running, make sure you have updated the config values!"
+
+usage() {
+	echo "Usage: $0 [0-5]"
+	echo "  0  - test watch fire"
+	echo "  1  - test canary overflow"
+	echo "  2  - test recursive depth"
+	echo "  3  - test silent corruption"
+	echo "  4  - test multi-threaded silent corruption"
+	echo "  5  - test multi-threaded overflow"
+}
+
+run_test_x86_64() {
+	local test_num=$1
+	case "$test_num" in
+	0) echo fn=test_watch_fire fo=0x29 ac=1 >/sys/kernel/debug/kstackwatch/config
+	   echo test0 > /sys/kernel/debug/kstackwatch/test
+	   ;;
+	1) echo fn=test_canary_overflow fo=0x14 >/sys/kernel/debug/kstackwatch/config
+	   echo test1 >/sys/kernel/debug/kstackwatch/test
+	   ;;
+	2) echo fn=test_recursive_depth fo=0x2f dp=3 wl=8 so=0 >/sys/kernel/debug/kstackwatch/config
+	   echo test2 >/sys/kernel/debug/kstackwatch/test
+	   ;;
+	3) echo fn=test_mthread_victim fo=0x4c so=64 wl=8 >/sys/kernel/debug/kstackwatch/config
+	   echo test3 >/sys/kernel/debug/kstackwatch/test
+	   ;;
+	4) echo fn=test_mthread_victim fo=0x4c so=64 wl=8 >/sys/kernel/debug/kstackwatch/config
+	   echo test4 >/sys/kernel/debug/kstackwatch/test
+	   ;;
+	5) echo fn=test_mthread_buggy fo=0x16 so=0x100 wl=8 >/sys/kernel/debug/kstackwatch/config
+	   echo test5 >/sys/kernel/debug/kstackwatch/test
+	   ;;
+	*) usage
+	   exit 1 ;;
+	esac
+	# Reset watch after test
+	echo >/sys/kernel/debug/kstackwatch/config
+}
+
+run_test_arm64() {
+	local test_num=$1
+	case "$test_num" in
+	0) echo fn=test_watch_fire fo=0x50 ac=1 >/sys/kernel/debug/kstackwatch/config
+	   echo test0 > /sys/kernel/debug/kstackwatch/test
+	   ;;
+	1) echo fn=test_canary_overflow fo=0x20 so=264 >/sys/kernel/debug/kstackwatch/config
+	   echo test1 >/sys/kernel/debug/kstackwatch/test
+	   ;;
+	2) echo fn=test_recursive_depth fo=0x34 dp=3 wl=8 so=8 >/sys/kernel/debug/kstackwatch/config
+	   echo test2 >/sys/kernel/debug/kstackwatch/test
+	   ;;
+	3) echo fn=test_mthread_victim fo=0x6c so=0x48 wl=8 >/sys/kernel/debug/kstackwatch/config
+	   echo test3 >/sys/kernel/debug/kstackwatch/test
+	   ;;
+	4) echo fn=test_mthread_victim fo=0x6c so=0x48 wl=8 >/sys/kernel/debug/kstackwatch/config
+	   echo test4 >/sys/kernel/debug/kstackwatch/test
+	   ;;
+	5) echo fn=test_mthread_buggy fo=0x20 so=264 >/sys/kernel/debug/kstackwatch/config
+	   echo test5 >/sys/kernel/debug/kstackwatch/test
+	   ;;
+	*) usage
+	   exit 1 ;;
+	esac
+	# Reset watch after test
+	echo >/sys/kernel/debug/kstackwatch/config
+}
+
+# Check root and module
+[ "$EUID" -ne 0 ] && echo "Run as root" && exit 1
+for f in /sys/kernel/debug/kstackwatch/config /sys/kernel/debug/kstackwatch/test; do
+	[ ! -f "$f" ] && echo "$f not found" && exit 1
+done
+
+# Run
+[ -z "$1" ] && { usage; exit 0; }
+
+arch=$(uname -m)
+case "$arch" in
+	x86_64|aarch64) run_test_${arch} "$1" ;;
+	*) echo "Unsupported architecture: $arch" && exit 1 ;;
+esac
-- 
2.43.0


^ permalink raw reply related

* [PATCH v8 24/27] mm/ksw: add multi-thread corruption test cases
From: Jinchao Wang @ 2025-11-10 16:36 UTC (permalink / raw)
  To: Andrew Morton, Masami Hiramatsu (Google), Peter Zijlstra,
	Randy Dunlap, Marco Elver, Mike Rapoport, Alexander Potapenko,
	Adrian Hunter, Alexander Shishkin, Alice Ryhl, Andrey Konovalov,
	Andrey Ryabinin, Andrii Nakryiko, Ard Biesheuvel,
	Arnaldo Carvalho de Melo, Ben Segall, Bill Wendling,
	Borislav Petkov, Catalin Marinas, Dave Hansen, David Hildenbrand,
	David Kaplan, David S. Miller, Dietmar Eggemann, Dmitry Vyukov,
	H. Peter Anvin, Ian Rogers, Ingo Molnar, James Clark,
	Jinchao Wang, Jinjie Ruan, Jiri Olsa, Jonathan Corbet, Juri Lelli,
	Justin Stitt, kasan-dev, Kees Cook, Liam R. Howlett, Liang Kan,
	Linus Walleij, linux-arm-kernel, linux-doc, linux-kernel,
	linux-mm, linux-perf-users, linux-trace-kernel, llvm,
	Lorenzo Stoakes, Mark Rutland, Masahiro Yamada, Mathieu Desnoyers,
	Mel Gorman, Michal Hocko, Miguel Ojeda, Nam Cao, Namhyung Kim,
	Nathan Chancellor, Naveen N Rao, Nick Desaulniers, Rong Xu,
	Sami Tolvanen, Steven Rostedt, Suren Baghdasaryan,
	Thomas Gleixner, Thomas Weißschuh, Valentin Schneider,
	Vincent Guittot, Vincenzo Frascino, Vlastimil Babka, Will Deacon,
	workflows, x86
In-Reply-To: <20251110163634.3686676-1-wangjinchao600@gmail.com>

These tests share a common structure and are grouped together.

- buggy():
  exposes the stack address to corrupting(); may omit waiting
- corrupting():
  reads the exposed pointer and modifies memory;
  if buggy() omits waiting, victim()'s buffer is corrupted
- victim():
  initializes a local buffer and later verifies it;
  reports an error if the buffer was unexpectedly modified

buggy() and victim() run in worker() thread, with similar stack frame sizes
to simplify testing. By adjusting fence_size in corrupting(), the test can
trigger either silent corruption or overflow across threads.

- Test 3: one worker, 20 loops, silent corruption
- Test 4: 20 workers, one loop each, silent corruption
- Test 5: one worker, one loop, overflow corruption

Test 4 also exercises multiple watchpoint instances.

Signed-off-by: Jinchao Wang <wangjinchao600@gmail.com>

mm/ksw: add KSTACKWATCH_PROFILING to measure probe cost

Introduce CONFIG_KSTACKWATCH_PROFILING to enable optional runtime
profiling in KStackWatch. When enabled, it records entry and exit
probe latencies (in nanoseconds and CPU cycles) and reports averaged
statistics at module exit.

Signed-off-by: Jinchao Wang <wangjinchao600@gmail.com>
---
 mm/kstackwatch/test.c | 186 +++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 185 insertions(+), 1 deletion(-)

diff --git a/mm/kstackwatch/test.c b/mm/kstackwatch/test.c
index 1d196f72faba..4bd0e5026fd9 100644
--- a/mm/kstackwatch/test.c
+++ b/mm/kstackwatch/test.c
@@ -19,6 +19,20 @@ static struct dentry *test_file;
 #define BUFFER_SIZE 32
 #define MAX_DEPTH 6
 
+struct work_node {
+	ulong *ptr;
+	u64 start_ns;
+	struct completion done;
+	struct list_head list;
+};
+
+static DECLARE_COMPLETION(work_res);
+static DEFINE_MUTEX(work_mutex);
+static LIST_HEAD(work_list);
+
+static int global_fence_size;
+static int global_loop_count;
+
 static void test_watch_fire(void)
 {
 	u64 buffer[BUFFER_SIZE] = { 0 };
@@ -64,6 +78,164 @@ static void test_recursive_depth(int depth)
 	pr_info("exit of %s depth:%d\n", __func__, depth);
 }
 
+static struct work_node *test_mthread_buggy(int thread_id, int seq_id)
+{
+	ulong buf[BUFFER_SIZE];
+	struct work_node *node;
+	bool trigger;
+
+	node = kmalloc(sizeof(*node), GFP_KERNEL);
+	if (!node)
+		return NULL;
+
+	init_completion(&node->done);
+	node->ptr = buf;
+	node->start_ns = ktime_get_ns();
+	mutex_lock(&work_mutex);
+	list_add(&node->list, &work_list);
+	mutex_unlock(&work_mutex);
+	complete(&work_res);
+
+	trigger = (get_random_u32() % 100) < 10;
+	if (trigger)
+		return node; /* let the caller handle cleanup */
+
+	wait_for_completion(&node->done);
+	kfree(node);
+	return NULL;
+}
+
+#define CORRUPTING_MINIOR_WAIT_NS (100000)
+#define VICTIM_MINIOR_WAIT_NS (300000)
+
+static inline void silent_wait_us(u64 start_ns, u64 min_wait_us)
+{
+	u64 diff_ns, remain_us;
+
+	diff_ns = ktime_get_ns() - start_ns;
+	if (diff_ns < min_wait_us * 1000ULL) {
+		remain_us = min_wait_us - (diff_ns >> 10);
+		usleep_range(remain_us, remain_us + 200);
+	}
+}
+
+static void test_mthread_victim(int thread_id, int seq_id, u64 start_ns)
+{
+	ulong buf[BUFFER_SIZE];
+
+	for (int j = 0; j < BUFFER_SIZE; j++)
+		buf[j] = 0xdeadbeef + seq_id;
+	if (start_ns)
+		silent_wait_us(start_ns, VICTIM_MINIOR_WAIT_NS);
+
+	for (int j = 0; j < BUFFER_SIZE; j++) {
+		if (buf[j] != (0xdeadbeef + seq_id)) {
+			pr_warn("victim[%d][%d]: unhappy buf[%d]=0x%lx\n",
+				thread_id, seq_id, j, buf[j]);
+			return;
+		}
+	}
+
+	pr_info("victim[%d][%d]: happy\n", thread_id, seq_id);
+}
+
+static int test_mthread_corrupting(void *data)
+{
+	struct work_node *node;
+	int fence_size;
+
+	while (!kthread_should_stop()) {
+		if (!wait_for_completion_timeout(&work_res, HZ))
+			continue;
+		while (true) {
+			mutex_lock(&work_mutex);
+			node = list_first_entry_or_null(&work_list,
+							struct work_node, list);
+			if (node)
+				list_del(&node->list);
+			mutex_unlock(&work_mutex);
+
+			if (!node)
+				break; /* no more nodes, exit inner loop */
+			silent_wait_us(node->start_ns,
+				       CORRUPTING_MINIOR_WAIT_NS);
+
+			fence_size = READ_ONCE(global_fence_size);
+			for (int i = fence_size; i < BUFFER_SIZE - fence_size;
+			     i++)
+				node->ptr[i] = 0xabcdabcd;
+
+			complete(&node->done);
+		}
+	}
+
+	return 0;
+}
+
+static int test_mthread_worker(void *data)
+{
+	int thread_id = (long)data;
+	int loop_count;
+	struct work_node *node;
+
+	loop_count = READ_ONCE(global_loop_count);
+
+	for (int i = 0; i < loop_count; i++) {
+		node = test_mthread_buggy(thread_id, i);
+
+		if (node)
+			test_mthread_victim(thread_id, i, node->start_ns);
+		else
+			test_mthread_victim(thread_id, i, 0);
+		if (node) {
+			wait_for_completion(&node->done);
+			kfree(node);
+		}
+	}
+	return 0;
+}
+
+static void test_mthread_case(int num_workers, int loop_count, int fence_size)
+{
+	static struct task_struct *corrupting;
+	static struct task_struct **workers;
+
+	WRITE_ONCE(global_loop_count, loop_count);
+	WRITE_ONCE(global_fence_size, fence_size);
+
+	init_completion(&work_res);
+	workers = kmalloc_array(num_workers, sizeof(void *), GFP_KERNEL);
+	memset(workers, 0, sizeof(struct task_struct *) * num_workers);
+
+	corrupting = kthread_run(test_mthread_corrupting, NULL, "corrupting");
+	if (IS_ERR(corrupting)) {
+		pr_err("failed to create corrupting thread\n");
+		return;
+	}
+
+	for (ulong i = 0; i < num_workers; i++) {
+		workers[i] = kthread_run(test_mthread_worker, (void *)i,
+					 "worker_%ld", i);
+		if (IS_ERR(workers[i])) {
+			pr_err("failto create worker thread %ld", i);
+			workers[i] = NULL;
+		}
+	}
+
+	for (ulong i = 0; i < num_workers; i++) {
+		if (workers[i] && workers[i]->__state != TASK_DEAD) {
+			usleep_range(1000, 2000);
+			i--;
+		}
+	}
+	kfree(workers);
+
+	if (corrupting && !IS_ERR(corrupting)) {
+		kthread_stop(corrupting);
+		corrupting = NULL;
+	}
+}
+
 static ssize_t test_dbgfs_write(struct file *file, const char __user *buffer,
 				size_t count, loff_t *pos)
 {
@@ -92,6 +264,15 @@ static ssize_t test_dbgfs_write(struct file *file, const char __user *buffer,
 		case 2:
 			test_recursive_depth(0);
 			break;
+		case 3:
+			test_mthread_case(1, 20, BUFFER_SIZE / 4);
+			break;
+		case 4:
+			test_mthread_case(200, 1, BUFFER_SIZE / 4);
+			break;
+		case 5:
+			test_mthread_case(1, 1, -3);
+			break;
 		default:
 			pr_err("Unknown test number %d\n", test_num);
 			return -EINVAL;
@@ -114,7 +295,10 @@ static ssize_t test_dbgfs_read(struct file *file, char __user *buffer,
 		"echo test{i} > /sys/kernel/debug/kstackwatch/test\n"
 		" test0 - test watch fire\n"
 		" test1 - test canary overflow\n"
-		" test2 - test recursive func\n";
+		" test2 - test recursive func\n"
+		" test3 - test silent corruption\n"
+		" test4 - test multiple silent corruption\n"
+		" test5 - test prologue corruption\n";
 
 	return simple_read_from_buffer(buffer, count, ppos, usage,
 				       strlen(usage));
-- 
2.43.0


^ permalink raw reply related

* [PATCH v8 23/27] mm/ksw: add recursive depth test
From: Jinchao Wang @ 2025-11-10 16:36 UTC (permalink / raw)
  To: Andrew Morton, Masami Hiramatsu (Google), Peter Zijlstra,
	Randy Dunlap, Marco Elver, Mike Rapoport, Alexander Potapenko,
	Adrian Hunter, Alexander Shishkin, Alice Ryhl, Andrey Konovalov,
	Andrey Ryabinin, Andrii Nakryiko, Ard Biesheuvel,
	Arnaldo Carvalho de Melo, Ben Segall, Bill Wendling,
	Borislav Petkov, Catalin Marinas, Dave Hansen, David Hildenbrand,
	David Kaplan, David S. Miller, Dietmar Eggemann, Dmitry Vyukov,
	H. Peter Anvin, Ian Rogers, Ingo Molnar, James Clark,
	Jinchao Wang, Jinjie Ruan, Jiri Olsa, Jonathan Corbet, Juri Lelli,
	Justin Stitt, kasan-dev, Kees Cook, Liam R. Howlett, Liang Kan,
	Linus Walleij, linux-arm-kernel, linux-doc, linux-kernel,
	linux-mm, linux-perf-users, linux-trace-kernel, llvm,
	Lorenzo Stoakes, Mark Rutland, Masahiro Yamada, Mathieu Desnoyers,
	Mel Gorman, Michal Hocko, Miguel Ojeda, Nam Cao, Namhyung Kim,
	Nathan Chancellor, Naveen N Rao, Nick Desaulniers, Rong Xu,
	Sami Tolvanen, Steven Rostedt, Suren Baghdasaryan,
	Thomas Gleixner, Thomas Weißschuh, Valentin Schneider,
	Vincent Guittot, Vincenzo Frascino, Vlastimil Babka, Will Deacon,
	workflows, x86
In-Reply-To: <20251110163634.3686676-1-wangjinchao600@gmail.com>

Introduce a test that performs stack writes in recursive calls to exercise
stack watch at a specific recursion depth.

Signed-off-by: Jinchao Wang <wangjinchao600@gmail.com>
---
 mm/kstackwatch/test.c | 22 +++++++++++++++++++++-
 1 file changed, 21 insertions(+), 1 deletion(-)

diff --git a/mm/kstackwatch/test.c b/mm/kstackwatch/test.c
index b3f363d9e1e8..1d196f72faba 100644
--- a/mm/kstackwatch/test.c
+++ b/mm/kstackwatch/test.c
@@ -17,6 +17,7 @@
 static struct dentry *test_file;
 
 #define BUFFER_SIZE 32
+#define MAX_DEPTH 6
 
 static void test_watch_fire(void)
 {
@@ -48,6 +49,21 @@ static void test_canary_overflow(void)
 	pr_info("exit of %s\n", __func__);
 }
 
+static void test_recursive_depth(int depth)
+{
+	u64 buffer[BUFFER_SIZE];
+
+	pr_info("entry of %s depth:%d\n", __func__, depth);
+
+	if (depth < MAX_DEPTH)
+		test_recursive_depth(depth + 1);
+
+	buffer[0] = depth;
+	barrier_data(buffer);
+
+	pr_info("exit of %s depth:%d\n", __func__, depth);
+}
+
 static ssize_t test_dbgfs_write(struct file *file, const char __user *buffer,
 				size_t count, loff_t *pos)
 {
@@ -73,6 +89,9 @@ static ssize_t test_dbgfs_write(struct file *file, const char __user *buffer,
 		case 1:
 			test_canary_overflow();
 			break;
+		case 2:
+			test_recursive_depth(0);
+			break;
 		default:
 			pr_err("Unknown test number %d\n", test_num);
 			return -EINVAL;
@@ -94,7 +113,8 @@ static ssize_t test_dbgfs_read(struct file *file, char __user *buffer,
 		"Usage:\n"
 		"echo test{i} > /sys/kernel/debug/kstackwatch/test\n"
 		" test0 - test watch fire\n"
-		" test1 - test canary overflow\n";
+		" test1 - test canary overflow\n"
+		" test2 - test recursive func\n";
 
 	return simple_read_from_buffer(buffer, count, ppos, usage,
 				       strlen(usage));
-- 
2.43.0


^ permalink raw reply related

* [PATCH v8 22/27] mm/ksw: add stack overflow test
From: Jinchao Wang @ 2025-11-10 16:36 UTC (permalink / raw)
  To: Andrew Morton, Masami Hiramatsu (Google), Peter Zijlstra,
	Randy Dunlap, Marco Elver, Mike Rapoport, Alexander Potapenko,
	Adrian Hunter, Alexander Shishkin, Alice Ryhl, Andrey Konovalov,
	Andrey Ryabinin, Andrii Nakryiko, Ard Biesheuvel,
	Arnaldo Carvalho de Melo, Ben Segall, Bill Wendling,
	Borislav Petkov, Catalin Marinas, Dave Hansen, David Hildenbrand,
	David Kaplan, David S. Miller, Dietmar Eggemann, Dmitry Vyukov,
	H. Peter Anvin, Ian Rogers, Ingo Molnar, James Clark,
	Jinchao Wang, Jinjie Ruan, Jiri Olsa, Jonathan Corbet, Juri Lelli,
	Justin Stitt, kasan-dev, Kees Cook, Liam R. Howlett, Liang Kan,
	Linus Walleij, linux-arm-kernel, linux-doc, linux-kernel,
	linux-mm, linux-perf-users, linux-trace-kernel, llvm,
	Lorenzo Stoakes, Mark Rutland, Masahiro Yamada, Mathieu Desnoyers,
	Mel Gorman, Michal Hocko, Miguel Ojeda, Nam Cao, Namhyung Kim,
	Nathan Chancellor, Naveen N Rao, Nick Desaulniers, Rong Xu,
	Sami Tolvanen, Steven Rostedt, Suren Baghdasaryan,
	Thomas Gleixner, Thomas Weißschuh, Valentin Schneider,
	Vincent Guittot, Vincenzo Frascino, Vlastimil Babka, Will Deacon,
	workflows, x86
In-Reply-To: <20251110163634.3686676-1-wangjinchao600@gmail.com>

Extend the test module with a new test case (test1) that intentionally
overflows a local u64 buffer to corrupt the stack canary.

Signed-off-by: Jinchao Wang <wangjinchao600@gmail.com>

show addr of buf and watch_addr of test case
---
 mm/kstackwatch/test.c | 22 +++++++++++++++++++++-
 1 file changed, 21 insertions(+), 1 deletion(-)

diff --git a/mm/kstackwatch/test.c b/mm/kstackwatch/test.c
index 2969564b1a00..b3f363d9e1e8 100644
--- a/mm/kstackwatch/test.c
+++ b/mm/kstackwatch/test.c
@@ -32,6 +32,22 @@ static void test_watch_fire(void)
 	pr_info("exit of %s\n", __func__);
 }
 
+static void test_canary_overflow(void)
+{
+	u64 buffer[BUFFER_SIZE];
+
+	pr_info("entry of %s\n", __func__);
+	ksw_watch_show();
+	pr_info("buf: 0x%px\n", buffer);
+
+	/* intentionally overflow */
+	for (int i = BUFFER_SIZE; i < BUFFER_SIZE + 10; i++)
+		buffer[i] = 0xdeadbeefdeadbeef;
+	barrier_data(buffer);
+
+	pr_info("exit of %s\n", __func__);
+}
+
 static ssize_t test_dbgfs_write(struct file *file, const char __user *buffer,
 				size_t count, loff_t *pos)
 {
@@ -54,6 +70,9 @@ static ssize_t test_dbgfs_write(struct file *file, const char __user *buffer,
 		case 0:
 			test_watch_fire();
 			break;
+		case 1:
+			test_canary_overflow();
+			break;
 		default:
 			pr_err("Unknown test number %d\n", test_num);
 			return -EINVAL;
@@ -74,7 +93,8 @@ static ssize_t test_dbgfs_read(struct file *file, char __user *buffer,
 		"============ usage ===============\n"
 		"Usage:\n"
 		"echo test{i} > /sys/kernel/debug/kstackwatch/test\n"
-		" test0 - test watch fire\n";
+		" test0 - test watch fire\n"
+		" test1 - test canary overflow\n";
 
 	return simple_read_from_buffer(buffer, count, ppos, usage,
 				       strlen(usage));
-- 
2.43.0


^ permalink raw reply related

* [PATCH v8 21/27] mm/ksw: add test module
From: Jinchao Wang @ 2025-11-10 16:36 UTC (permalink / raw)
  To: Andrew Morton, Masami Hiramatsu (Google), Peter Zijlstra,
	Randy Dunlap, Marco Elver, Mike Rapoport, Alexander Potapenko,
	Adrian Hunter, Alexander Shishkin, Alice Ryhl, Andrey Konovalov,
	Andrey Ryabinin, Andrii Nakryiko, Ard Biesheuvel,
	Arnaldo Carvalho de Melo, Ben Segall, Bill Wendling,
	Borislav Petkov, Catalin Marinas, Dave Hansen, David Hildenbrand,
	David Kaplan, David S. Miller, Dietmar Eggemann, Dmitry Vyukov,
	H. Peter Anvin, Ian Rogers, Ingo Molnar, James Clark,
	Jinchao Wang, Jinjie Ruan, Jiri Olsa, Jonathan Corbet, Juri Lelli,
	Justin Stitt, kasan-dev, Kees Cook, Liam R. Howlett, Liang Kan,
	Linus Walleij, linux-arm-kernel, linux-doc, linux-kernel,
	linux-mm, linux-perf-users, linux-trace-kernel, llvm,
	Lorenzo Stoakes, Mark Rutland, Masahiro Yamada, Mathieu Desnoyers,
	Mel Gorman, Michal Hocko, Miguel Ojeda, Nam Cao, Namhyung Kim,
	Nathan Chancellor, Naveen N Rao, Nick Desaulniers, Rong Xu,
	Sami Tolvanen, Steven Rostedt, Suren Baghdasaryan,
	Thomas Gleixner, Thomas Weißschuh, Valentin Schneider,
	Vincent Guittot, Vincenzo Frascino, Vlastimil Babka, Will Deacon,
	workflows, x86
In-Reply-To: <20251110163634.3686676-1-wangjinchao600@gmail.com>

Add a standalone test module for KStackWatch to validate functionality
in controlled scenarios.

The module exposes a simple interface via debugfs
(/sys/kernel/debug/kstackwatch/test), allowing specific test cases to
be triggered with commands such as:

  echo test0 > /sys/kernel/debug/kstackwatch/test

To ensure predictable behavior during testing, the module is built with
optimizations disabled.

Signed-off-by: Jinchao Wang <wangjinchao600@gmail.com>

show addr of buf and watch_addr of test case
---
 include/linux/kstackwatch.h |   2 +
 mm/kstackwatch/Kconfig      |  10 +++
 mm/kstackwatch/Makefile     |   6 ++
 mm/kstackwatch/kernel.c     |   5 ++
 mm/kstackwatch/test.c       | 121 ++++++++++++++++++++++++++++++++++++
 5 files changed, 144 insertions(+)
 create mode 100644 mm/kstackwatch/test.c

diff --git a/include/linux/kstackwatch.h b/include/linux/kstackwatch.h
index 6daded932ba6..7711efe85240 100644
--- a/include/linux/kstackwatch.h
+++ b/include/linux/kstackwatch.h
@@ -40,6 +40,8 @@ struct ksw_config {
 
 // singleton, only modified in kernel.c
 const struct ksw_config *ksw_get_config(void);
+struct dentry *ksw_get_dbgdir(void);
+
 
 /* stack management */
 int ksw_stack_init(void);
diff --git a/mm/kstackwatch/Kconfig b/mm/kstackwatch/Kconfig
index 3c9385a15c33..343b492ddbd3 100644
--- a/mm/kstackwatch/Kconfig
+++ b/mm/kstackwatch/Kconfig
@@ -22,3 +22,13 @@ config KSTACKWATCH_PROFILING
 	  stopping. Useful for performance tuning, not for production use.
 
 	  If unsure, say N.
+
+config KSTACKWATCH_TEST
+	tristate "KStackWatch Test Module"
+	depends on KSTACKWATCH
+	help
+	  This module provides controlled stack corruption scenarios to verify
+	  the functionality of KStackWatch. It is useful for development and
+	  validation of KStackWatch mechanism.
+
+	  If unsure, say N.
diff --git a/mm/kstackwatch/Makefile b/mm/kstackwatch/Makefile
index c99c621eac02..a2c7cd647f69 100644
--- a/mm/kstackwatch/Makefile
+++ b/mm/kstackwatch/Makefile
@@ -1,2 +1,8 @@
 obj-$(CONFIG_KSTACKWATCH)	+= kstackwatch.o
 kstackwatch-y := kernel.o stack.o watch.o
+
+obj-$(CONFIG_KSTACKWATCH_TEST)	+= kstackwatch_test.o
+kstackwatch_test-y := test.o
+CFLAGS_test.o := -fno-inline \
+		-fno-optimize-sibling-calls \
+		-fno-pic -fno-pie -O0 -Og
diff --git a/mm/kstackwatch/kernel.c b/mm/kstackwatch/kernel.c
index a0e676e60692..b25cf6830b15 100644
--- a/mm/kstackwatch/kernel.c
+++ b/mm/kstackwatch/kernel.c
@@ -235,6 +235,11 @@ const struct ksw_config *ksw_get_config(void)
 	return ksw_config;
 }
 
+struct dentry *ksw_get_dbgdir(void)
+{
+	return dbgfs_dir;
+}
+
 static int __init kstackwatch_init(void)
 {
 	int ret = 0;
diff --git a/mm/kstackwatch/test.c b/mm/kstackwatch/test.c
new file mode 100644
index 000000000000..2969564b1a00
--- /dev/null
+++ b/mm/kstackwatch/test.c
@@ -0,0 +1,121 @@
+// SPDX-License-Identifier: GPL-2.0
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/debugfs.h>
+#include <linux/delay.h>
+#include <linux/kthread.h>
+#include <linux/kstackwatch.h>
+#include <linux/list.h>
+#include <linux/module.h>
+#include <linux/prandom.h>
+#include <linux/printk.h>
+#include <linux/random.h>
+#include <linux/spinlock.h>
+#include <linux/string.h>
+#include <linux/uaccess.h>
+
+static struct dentry *test_file;
+
+#define BUFFER_SIZE 32
+
+static void test_watch_fire(void)
+{
+	u64 buffer[BUFFER_SIZE] = { 0 };
+
+	pr_info("entry of %s\n", __func__);
+	ksw_watch_show();
+	pr_info("buf: 0x%px\n", buffer);
+
+	ksw_watch_fire();
+
+	barrier_data(buffer);
+	pr_info("exit of %s\n", __func__);
+}
+
+static ssize_t test_dbgfs_write(struct file *file, const char __user *buffer,
+				size_t count, loff_t *pos)
+{
+	char cmd[256];
+	int test_num;
+
+	if (count >= sizeof(cmd))
+		return -EINVAL;
+
+	if (copy_from_user(cmd, buffer, count))
+		return -EFAULT;
+
+	cmd[count] = '\0';
+	strim(cmd);
+
+	pr_info("received command: %s\n", cmd);
+
+	if (sscanf(cmd, "test%d", &test_num) == 1) {
+		switch (test_num) {
+		case 0:
+			test_watch_fire();
+			break;
+		default:
+			pr_err("Unknown test number %d\n", test_num);
+			return -EINVAL;
+		}
+	} else {
+		pr_err("invalid command format. Use 'testN'.\n");
+		return -EINVAL;
+	}
+
+	return count;
+}
+
+static ssize_t test_dbgfs_read(struct file *file, char __user *buffer,
+			       size_t count, loff_t *ppos)
+{
+	static const char usage[] =
+		"KStackWatch Simplified Test Module\n"
+		"============ usage ===============\n"
+		"Usage:\n"
+		"echo test{i} > /sys/kernel/debug/kstackwatch/test\n"
+		" test0 - test watch fire\n";
+
+	return simple_read_from_buffer(buffer, count, ppos, usage,
+				       strlen(usage));
+}
+
+static const struct file_operations test_dbgfs_fops = {
+	.owner = THIS_MODULE,
+	.read = test_dbgfs_read,
+	.write = test_dbgfs_write,
+	.llseek = noop_llseek,
+};
+
+static int __init kstackwatch_test_init(void)
+{
+	struct dentry *ksw_dir = ksw_get_dbgdir();
+
+	if (!ksw_dir) {
+		pr_err("kstackwatch must be loaded first\n");
+		return -ENODEV;
+	}
+
+	test_file = debugfs_create_file("test", 0600, ksw_dir, NULL,
+					&test_dbgfs_fops);
+	if (!test_file) {
+		pr_err("Failed to create debugfs test file\n");
+		return -ENOMEM;
+	}
+
+	pr_info("module loaded\n");
+	return 0;
+}
+
+static void __exit kstackwatch_test_exit(void)
+{
+	debugfs_remove(test_file);
+	pr_info("module unloaded\n");
+}
+
+module_init(kstackwatch_test_init);
+module_exit(kstackwatch_test_exit);
+
+MODULE_AUTHOR("Jinchao Wang");
+MODULE_DESCRIPTION("KStackWatch Test Module");
+MODULE_LICENSE("GPL");
-- 
2.43.0


^ permalink raw reply related

* [PATCH v8 20/27] mm/ksw: add self-debug helpers
From: Jinchao Wang @ 2025-11-10 16:36 UTC (permalink / raw)
  To: Andrew Morton, Masami Hiramatsu (Google), Peter Zijlstra,
	Randy Dunlap, Marco Elver, Mike Rapoport, Alexander Potapenko,
	Adrian Hunter, Alexander Shishkin, Alice Ryhl, Andrey Konovalov,
	Andrey Ryabinin, Andrii Nakryiko, Ard Biesheuvel,
	Arnaldo Carvalho de Melo, Ben Segall, Bill Wendling,
	Borislav Petkov, Catalin Marinas, Dave Hansen, David Hildenbrand,
	David Kaplan, David S. Miller, Dietmar Eggemann, Dmitry Vyukov,
	H. Peter Anvin, Ian Rogers, Ingo Molnar, James Clark,
	Jinchao Wang, Jinjie Ruan, Jiri Olsa, Jonathan Corbet, Juri Lelli,
	Justin Stitt, kasan-dev, Kees Cook, Liam R. Howlett, Liang Kan,
	Linus Walleij, linux-arm-kernel, linux-doc, linux-kernel,
	linux-mm, linux-perf-users, linux-trace-kernel, llvm,
	Lorenzo Stoakes, Mark Rutland, Masahiro Yamada, Mathieu Desnoyers,
	Mel Gorman, Michal Hocko, Miguel Ojeda, Nam Cao, Namhyung Kim,
	Nathan Chancellor, Naveen N Rao, Nick Desaulniers, Rong Xu,
	Sami Tolvanen, Steven Rostedt, Suren Baghdasaryan,
	Thomas Gleixner, Thomas Weißschuh, Valentin Schneider,
	Vincent Guittot, Vincenzo Frascino, Vlastimil Babka, Will Deacon,
	workflows, x86
In-Reply-To: <20251110163634.3686676-1-wangjinchao600@gmail.com>

Provide two debug helpers:

- ksw_watch_show(): print the current watch target address and length.
- ksw_watch_fire(): intentionally trigger the watchpoint immediately
  by writing to the watched address, useful for testing HWBP behavior.

Signed-off-by: Jinchao Wang <wangjinchao600@gmail.com>
---
 include/linux/kstackwatch.h |  2 ++
 mm/kstackwatch/watch.c      | 34 ++++++++++++++++++++++++++++++++++
 2 files changed, 36 insertions(+)

diff --git a/include/linux/kstackwatch.h b/include/linux/kstackwatch.h
index ce3882acc5dc..6daded932ba6 100644
--- a/include/linux/kstackwatch.h
+++ b/include/linux/kstackwatch.h
@@ -60,5 +60,7 @@ void ksw_watch_exit(void);
 int ksw_watch_get(struct ksw_watchpoint **out_wp);
 int ksw_watch_on(struct ksw_watchpoint *wp, ulong watch_addr, u16 watch_len);
 int ksw_watch_off(struct ksw_watchpoint *wp);
+void ksw_watch_show(void);
+void ksw_watch_fire(void);
 
 #endif /* _KSTACKWATCH_H */
diff --git a/mm/kstackwatch/watch.c b/mm/kstackwatch/watch.c
index c2aa912bf4c4..a298c31848a2 100644
--- a/mm/kstackwatch/watch.c
+++ b/mm/kstackwatch/watch.c
@@ -273,3 +273,37 @@ void ksw_watch_exit(void)
 {
 	ksw_watch_free();
 }
+
+/* self debug function */
+void ksw_watch_show(void)
+{
+	struct ksw_watchpoint *wp = current->ksw_ctx.wp;
+
+	if (!wp) {
+		pr_info("nothing to show\n");
+		return;
+	}
+
+	pr_info("watch target bp_addr: 0x%llx len:%llu\n", wp->attr.bp_addr,
+		wp->attr.bp_len);
+}
+EXPORT_SYMBOL_GPL(ksw_watch_show);
+
+/* self debug function */
+void ksw_watch_fire(void)
+{
+	struct ksw_watchpoint *wp;
+	char *ptr;
+
+	wp = current->ksw_ctx.wp;
+
+	if (!wp) {
+		pr_info("nothing to fire\n");
+		return;
+	}
+
+	ptr = (char *)wp->attr.bp_addr;
+	pr_warn("watch triggered immediately\n");
+	*ptr = 0x42; // This should trigger immediately for any bp_len
+}
+EXPORT_SYMBOL_GPL(ksw_watch_fire);
-- 
2.43.0


^ permalink raw reply related

* [PATCH v8 19/27] arm64/hwbp/ksw: integrate KStackWatch handler support
From: Jinchao Wang @ 2025-11-10 16:36 UTC (permalink / raw)
  To: Andrew Morton, Masami Hiramatsu (Google), Peter Zijlstra,
	Randy Dunlap, Marco Elver, Mike Rapoport, Alexander Potapenko,
	Adrian Hunter, Alexander Shishkin, Alice Ryhl, Andrey Konovalov,
	Andrey Ryabinin, Andrii Nakryiko, Ard Biesheuvel,
	Arnaldo Carvalho de Melo, Ben Segall, Bill Wendling,
	Borislav Petkov, Catalin Marinas, Dave Hansen, David Hildenbrand,
	David Kaplan, David S. Miller, Dietmar Eggemann, Dmitry Vyukov,
	H. Peter Anvin, Ian Rogers, Ingo Molnar, James Clark,
	Jinchao Wang, Jinjie Ruan, Jiri Olsa, Jonathan Corbet, Juri Lelli,
	Justin Stitt, kasan-dev, Kees Cook, Liam R. Howlett, Liang Kan,
	Linus Walleij, linux-arm-kernel, linux-doc, linux-kernel,
	linux-mm, linux-perf-users, linux-trace-kernel, llvm,
	Lorenzo Stoakes, Mark Rutland, Masahiro Yamada, Mathieu Desnoyers,
	Mel Gorman, Michal Hocko, Miguel Ojeda, Nam Cao, Namhyung Kim,
	Nathan Chancellor, Naveen N Rao, Nick Desaulniers, Rong Xu,
	Sami Tolvanen, Steven Rostedt, Suren Baghdasaryan,
	Thomas Gleixner, Thomas Weißschuh, Valentin Schneider,
	Vincent Guittot, Vincenzo Frascino, Vlastimil Babka, Will Deacon,
	workflows, x86
In-Reply-To: <20251110163634.3686676-1-wangjinchao600@gmail.com>

Add support for identifying KStackWatch watchpoints in the ARM64
hardware breakpoint handler. When a watchpoint belongs to KStackWatch,
the handler bypasses single-step re-arming to allow proper recovery.

Introduce is_ksw_watch_handler() to detect KStackWatch-managed
breakpoints and use it in watchpoint_report() under
CONFIG_KSTACKWATCH.

Signed-off-by: Jinchao Wang <wangjinchao600@gmail.com>
---
 arch/arm64/kernel/hw_breakpoint.c | 7 +++++++
 include/linux/kstackwatch.h       | 2 ++
 mm/kstackwatch/watch.c            | 8 ++++++++
 3 files changed, 17 insertions(+)

diff --git a/arch/arm64/kernel/hw_breakpoint.c b/arch/arm64/kernel/hw_breakpoint.c
index bd7d23d7893d..7abcd988c5c2 100644
--- a/arch/arm64/kernel/hw_breakpoint.c
+++ b/arch/arm64/kernel/hw_breakpoint.c
@@ -14,6 +14,9 @@
 #include <linux/errno.h>
 #include <linux/hw_breakpoint.h>
 #include <linux/kprobes.h>
+#ifdef CONFIG_KSTACKWATCH
+#include <linux/kstackwatch.h>
+#endif
 #include <linux/perf_event.h>
 #include <linux/ptrace.h>
 #include <linux/smp.h>
@@ -738,6 +741,10 @@ static int watchpoint_report(struct perf_event *wp, unsigned long addr,
 			     struct pt_regs *regs)
 {
 	int step = is_default_overflow_handler(wp);
+#ifdef CONFIG_KSTACKWATCH
+	if (is_ksw_watch_handler(wp))
+		step = 1;
+#endif
 	struct arch_hw_breakpoint *info = counter_arch_bp(wp);
 
 	info->trigger = addr;
diff --git a/include/linux/kstackwatch.h b/include/linux/kstackwatch.h
index afedd9823de9..ce3882acc5dc 100644
--- a/include/linux/kstackwatch.h
+++ b/include/linux/kstackwatch.h
@@ -53,6 +53,8 @@ struct ksw_watchpoint {
 	struct llist_node node; // for atomic watch_on and off
 	struct list_head list; // for cpu online and offline
 };
+
+bool is_ksw_watch_handler(struct perf_event *event);
 int ksw_watch_init(void);
 void ksw_watch_exit(void);
 int ksw_watch_get(struct ksw_watchpoint **out_wp);
diff --git a/mm/kstackwatch/watch.c b/mm/kstackwatch/watch.c
index 99184f63d7e3..c2aa912bf4c4 100644
--- a/mm/kstackwatch/watch.c
+++ b/mm/kstackwatch/watch.c
@@ -64,6 +64,14 @@ static void ksw_watch_handler(struct perf_event *bp,
 		panic("Stack corruption detected");
 }
 
+bool is_ksw_watch_handler(struct perf_event *event)
+{
+	perf_overflow_handler_t overflow_handler = event->overflow_handler;
+
+	if (unlikely(overflow_handler == ksw_watch_handler))
+		return true;
+	return false;
+}
 static void ksw_watch_on_local_cpu(void *info)
 {
 	struct ksw_watchpoint *wp = info;
-- 
2.43.0


^ permalink raw reply related

* [PATCH v8 18/27] arm64/hw_breakpoint: Add arch_reinstall_hw_breakpoint
From: Jinchao Wang @ 2025-11-10 16:36 UTC (permalink / raw)
  To: Andrew Morton, Masami Hiramatsu (Google), Peter Zijlstra,
	Randy Dunlap, Marco Elver, Mike Rapoport, Alexander Potapenko,
	Adrian Hunter, Alexander Shishkin, Alice Ryhl, Andrey Konovalov,
	Andrey Ryabinin, Andrii Nakryiko, Ard Biesheuvel,
	Arnaldo Carvalho de Melo, Ben Segall, Bill Wendling,
	Borislav Petkov, Catalin Marinas, Dave Hansen, David Hildenbrand,
	David Kaplan, David S. Miller, Dietmar Eggemann, Dmitry Vyukov,
	H. Peter Anvin, Ian Rogers, Ingo Molnar, James Clark,
	Jinchao Wang, Jinjie Ruan, Jiri Olsa, Jonathan Corbet, Juri Lelli,
	Justin Stitt, kasan-dev, Kees Cook, Liam R. Howlett, Liang Kan,
	Linus Walleij, linux-arm-kernel, linux-doc, linux-kernel,
	linux-mm, linux-perf-users, linux-trace-kernel, llvm,
	Lorenzo Stoakes, Mark Rutland, Masahiro Yamada, Mathieu Desnoyers,
	Mel Gorman, Michal Hocko, Miguel Ojeda, Nam Cao, Namhyung Kim,
	Nathan Chancellor, Naveen N Rao, Nick Desaulniers, Rong Xu,
	Sami Tolvanen, Steven Rostedt, Suren Baghdasaryan,
	Thomas Gleixner, Thomas Weißschuh, Valentin Schneider,
	Vincent Guittot, Vincenzo Frascino, Vlastimil Babka, Will Deacon,
	workflows, x86
In-Reply-To: <20251110163634.3686676-1-wangjinchao600@gmail.com>

Add arch_reinstall_hw_breakpoint() to restore a hardware breakpoint
in an atomic context. Unlike the full uninstall and reallocation
path, this lightweight function re-establishes an existing breakpoint
efficiently and safely.

This aligns ARM64 with x86 support for atomic breakpoint reinstalls.
---
 arch/arm64/Kconfig                     | 1 +
 arch/arm64/include/asm/hw_breakpoint.h | 1 +
 arch/arm64/kernel/hw_breakpoint.c      | 5 +++++
 3 files changed, 7 insertions(+)

diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
index 6663ffd23f25..fa35dfa2f5cc 100644
--- a/arch/arm64/Kconfig
+++ b/arch/arm64/Kconfig
@@ -232,6 +232,7 @@ config ARM64
 	select HAVE_HARDLOCKUP_DETECTOR_PERF if PERF_EVENTS && \
 		HW_PERF_EVENTS && HAVE_PERF_EVENTS_NMI
 	select HAVE_HW_BREAKPOINT if PERF_EVENTS
+	select HAVE_REINSTALL_HW_BREAKPOINT if PERF_EVENTS
 	select HAVE_IOREMAP_PROT
 	select HAVE_IRQ_TIME_ACCOUNTING
 	select HAVE_LIVEPATCH
diff --git a/arch/arm64/include/asm/hw_breakpoint.h b/arch/arm64/include/asm/hw_breakpoint.h
index bd81cf17744a..6c98bbbc6aa6 100644
--- a/arch/arm64/include/asm/hw_breakpoint.h
+++ b/arch/arm64/include/asm/hw_breakpoint.h
@@ -119,6 +119,7 @@ extern int hw_breakpoint_exceptions_notify(struct notifier_block *unused,
 					   unsigned long val, void *data);
 
 extern int arch_install_hw_breakpoint(struct perf_event *bp);
+extern int arch_reinstall_hw_breakpoint(struct perf_event *bp);
 extern void arch_uninstall_hw_breakpoint(struct perf_event *bp);
 extern void hw_breakpoint_pmu_read(struct perf_event *bp);
 extern int hw_breakpoint_slots(int type);
diff --git a/arch/arm64/kernel/hw_breakpoint.c b/arch/arm64/kernel/hw_breakpoint.c
index ab76b36dce82..bd7d23d7893d 100644
--- a/arch/arm64/kernel/hw_breakpoint.c
+++ b/arch/arm64/kernel/hw_breakpoint.c
@@ -292,6 +292,11 @@ int arch_install_hw_breakpoint(struct perf_event *bp)
 	return hw_breakpoint_control(bp, HW_BREAKPOINT_INSTALL);
 }
 
+int arch_reinstall_hw_breakpoint(struct perf_event *bp)
+{
+	return hw_breakpoint_control(bp, HW_BREAKPOINT_RESTORE);
+}
+
 void arch_uninstall_hw_breakpoint(struct perf_event *bp)
 {
 	hw_breakpoint_control(bp, HW_BREAKPOINT_UNINSTALL);
-- 
2.43.0


^ permalink raw reply related


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox