All of lore.kernel.org
 help / color / mirror / Atom feed
From: Steven Rostedt <rostedt@goodmis.org>
To: linux-kernel@vger.kernel.org, linux-trace-kernel@vger.kernel.org,
	bpf@vger.kernel.org, x86@kernel.org
Cc: Masami Hiramatsu <mhiramat@kernel.org>,
	Mathieu Desnoyers <mathieu.desnoyers@efficios.com>,
	Josh Poimboeuf <jpoimboe@kernel.org>,
	Peter Zijlstra <peterz@infradead.org>,
	Ingo Molnar <mingo@kernel.org>, Jiri Olsa <jolsa@kernel.org>,
	Namhyung Kim <namhyung@kernel.org>,
	Thomas Gleixner <tglx@linutronix.de>,
	Andrii Nakryiko <andrii@kernel.org>,
	Indu Bhagat <indu.bhagat@oracle.com>,
	"Jose E. Marchesi" <jemarch@gnu.org>,
	Beau Belgrave <beaub@linux.microsoft.com>,
	Jens Remus <jremus@linux.ibm.com>,
	Linus Torvalds <torvalds@linux-foundation.org>,
	Andrew Morton <akpm@linux-foundation.org>
Subject: [PATCH v10 05/14] unwind_user/deferred: Add unwind cache
Date: Tue, 10 Jun 2025 20:54:26 -0400	[thread overview]
Message-ID: <20250611010428.603778772@goodmis.org> (raw)
In-Reply-To: 20250611005421.144238328@goodmis.org

From: Josh Poimboeuf <jpoimboe@kernel.org>

Cache the results of the unwind to ensure the unwind is only performed
once, even when called by multiple tracers.

The cache nr_entries gets cleared every time the task exits the kernel.
When a stacktrace is requested, nr_entries gets set to the number of
entries in the stacktrace. If another stacktrace is requested, if
nr_entries is not zero, then it contains the same stacktrace that would be
retrieved so it is not processed again and the entries is given to the
caller.

Co-developed-by: Steven Rostedt (Google) <rostedt@goodmis.org>
Signed-off-by: Josh Poimboeuf <jpoimboe@kernel.org>
Signed-off-by: Steven Rostedt (Google) <rostedt@goodmis.org>
---
 include/linux/entry-common.h          |  2 ++
 include/linux/unwind_deferred.h       |  8 ++++++++
 include/linux/unwind_deferred_types.h |  7 ++++++-
 kernel/unwind/deferred.c              | 26 ++++++++++++++++++++------
 4 files changed, 36 insertions(+), 7 deletions(-)

diff --git a/include/linux/entry-common.h b/include/linux/entry-common.h
index f94f3fdf15fc..6e850c9d3f0c 100644
--- a/include/linux/entry-common.h
+++ b/include/linux/entry-common.h
@@ -12,6 +12,7 @@
 #include <linux/resume_user_mode.h>
 #include <linux/tick.h>
 #include <linux/kmsan.h>
+#include <linux/unwind_deferred.h>
 
 #include <asm/entry-common.h>
 #include <asm/syscall.h>
@@ -362,6 +363,7 @@ static __always_inline void exit_to_user_mode(void)
 	lockdep_hardirqs_on_prepare();
 	instrumentation_end();
 
+	unwind_exit_to_user_mode();
 	user_enter_irqoff();
 	arch_exit_to_user_mode();
 	lockdep_hardirqs_on(CALLER_ADDR0);
diff --git a/include/linux/unwind_deferred.h b/include/linux/unwind_deferred.h
index 5064ebe38c4f..7d6cb2ffd084 100644
--- a/include/linux/unwind_deferred.h
+++ b/include/linux/unwind_deferred.h
@@ -12,6 +12,12 @@ void unwind_task_free(struct task_struct *task);
 
 int unwind_deferred_trace(struct unwind_stacktrace *trace);
 
+static __always_inline void unwind_exit_to_user_mode(void)
+{
+	if (unlikely(current->unwind_info.cache))
+		current->unwind_info.cache->nr_entries = 0;
+}
+
 #else /* !CONFIG_UNWIND_USER */
 
 static inline void unwind_task_init(struct task_struct *task) {}
@@ -19,6 +25,8 @@ static inline void unwind_task_free(struct task_struct *task) {}
 
 static inline int unwind_deferred_trace(struct unwind_stacktrace *trace) { return -ENOSYS; }
 
+static inline void unwind_exit_to_user_mode(void) {}
+
 #endif /* !CONFIG_UNWIND_USER */
 
 #endif /* _LINUX_UNWIND_USER_DEFERRED_H */
diff --git a/include/linux/unwind_deferred_types.h b/include/linux/unwind_deferred_types.h
index aa32db574e43..db5b54b18828 100644
--- a/include/linux/unwind_deferred_types.h
+++ b/include/linux/unwind_deferred_types.h
@@ -2,8 +2,13 @@
 #ifndef _LINUX_UNWIND_USER_DEFERRED_TYPES_H
 #define _LINUX_UNWIND_USER_DEFERRED_TYPES_H
 
+struct unwind_cache {
+	unsigned int		nr_entries;
+	unsigned long		entries[];
+};
+
 struct unwind_task_info {
-	unsigned long		*entries;
+	struct unwind_cache	*cache;
 };
 
 #endif /* _LINUX_UNWIND_USER_DEFERRED_TYPES_H */
diff --git a/kernel/unwind/deferred.c b/kernel/unwind/deferred.c
index 0bafb95e6336..e3913781c8c6 100644
--- a/kernel/unwind/deferred.c
+++ b/kernel/unwind/deferred.c
@@ -24,6 +24,7 @@
 int unwind_deferred_trace(struct unwind_stacktrace *trace)
 {
 	struct unwind_task_info *info = &current->unwind_info;
+	struct unwind_cache *cache;
 
 	/* Should always be called from faultable context */
 	might_fault();
@@ -31,17 +32,30 @@ int unwind_deferred_trace(struct unwind_stacktrace *trace)
 	if (current->flags & PF_EXITING)
 		return -EINVAL;
 
-	if (!info->entries) {
-		info->entries = kmalloc_array(UNWIND_MAX_ENTRIES, sizeof(long),
-					      GFP_KERNEL);
-		if (!info->entries)
+	if (!info->cache) {
+		info->cache = kzalloc(struct_size(cache, entries, UNWIND_MAX_ENTRIES),
+				      GFP_KERNEL);
+		if (!info->cache)
 			return -ENOMEM;
 	}
 
+	cache = info->cache;
+	trace->entries = cache->entries;
+
+	if (cache->nr_entries) {
+		/*
+		 * The user stack has already been previously unwound in this
+		 * entry context.  Skip the unwind and use the cache.
+		 */
+		trace->nr = cache->nr_entries;
+		return 0;
+	}
+
 	trace->nr = 0;
-	trace->entries = info->entries;
 	unwind_user(trace, UNWIND_MAX_ENTRIES);
 
+	cache->nr_entries = trace->nr;
+
 	return 0;
 }
 
@@ -56,5 +70,5 @@ void unwind_task_free(struct task_struct *task)
 {
 	struct unwind_task_info *info = &task->unwind_info;
 
-	kfree(info->entries);
+	kfree(info->cache);
 }
-- 
2.47.2



  parent reply	other threads:[~2025-06-11  1:03 UTC|newest]

Thread overview: 79+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2025-06-11  0:54 [PATCH v10 00/14] unwind_user: x86: Deferred unwinding infrastructure Steven Rostedt
2025-06-11  0:54 ` [PATCH v10 01/14] unwind_user: Add user space unwinding API Steven Rostedt
2025-06-18 13:49   ` Peter Zijlstra
2025-06-11  0:54 ` [PATCH v10 02/14] unwind_user: Add frame pointer support Steven Rostedt
2025-06-18 13:52   ` Peter Zijlstra
2025-06-18 15:09     ` Steven Rostedt
2025-06-23 16:31       ` Indu Bhagat
2025-06-24 20:30         ` Steven Rostedt
2025-06-11  0:54 ` [PATCH v10 03/14] unwind_user: Add compat mode " Steven Rostedt
2025-06-18 13:46   ` Peter Zijlstra
2025-06-18 15:10     ` Steven Rostedt
2025-06-18 17:52       ` Linus Torvalds
2025-06-18 18:37         ` Steven Rostedt
2025-06-18 13:47   ` Peter Zijlstra
2025-06-18 15:18     ` Steven Rostedt
2025-06-19  7:51       ` Peter Zijlstra
2025-06-19  8:39         ` Steven Rostedt
2025-06-11  0:54 ` [PATCH v10 04/14] unwind_user/deferred: Add unwind_deferred_trace() Steven Rostedt
2025-06-18 13:54   ` Peter Zijlstra
2025-06-18 13:59   ` Peter Zijlstra
2025-06-18 15:20     ` Steven Rostedt
2025-06-18 16:26       ` Steven Rostedt
2025-06-18 14:01   ` Peter Zijlstra
2025-06-18 15:23     ` Steven Rostedt
2025-06-18 14:02   ` Peter Zijlstra
2025-06-18 15:29     ` Steven Rostedt
2025-06-19  7:54       ` Peter Zijlstra
2025-06-19  8:44         ` Steven Rostedt
2025-06-11  0:54 ` Steven Rostedt [this message]
2025-06-18 14:13   ` [PATCH v10 05/14] unwind_user/deferred: Add unwind cache Peter Zijlstra
2025-06-18 15:33     ` Steven Rostedt
2025-06-19  7:56       ` Peter Zijlstra
2025-06-19  8:47         ` Steven Rostedt
2025-06-19  9:04           ` Peter Zijlstra
2025-06-19  9:12             ` Steven Rostedt
2025-06-11  0:54 ` [PATCH v10 06/14] unwind_user/deferred: Add deferred unwinding interface Steven Rostedt
2025-06-18 14:20   ` Peter Zijlstra
2025-06-18 15:37     ` Steven Rostedt
2025-06-18 15:38       ` Steven Rostedt
2025-06-19  8:01       ` Peter Zijlstra
2025-06-19  8:49         ` Steven Rostedt
2025-06-18 18:46   ` Peter Zijlstra
2025-06-18 19:09     ` Steven Rostedt
2025-06-18 19:36       ` Steven Rostedt
2025-06-19  7:50       ` Peter Zijlstra
2025-06-19  8:56         ` Steven Rostedt
2025-06-19  9:11           ` Peter Zijlstra
2025-06-24 14:03             ` Steven Rostedt
2025-06-24 22:36     ` Steven Rostedt
2025-06-11  0:54 ` [PATCH v10 07/14] unwind_user/deferred: Make unwind deferral requests NMI-safe Steven Rostedt
2025-06-19  8:34   ` Peter Zijlstra
2025-06-19  8:37     ` Steven Rostedt
2025-06-19  8:44       ` Peter Zijlstra
2025-06-19  8:48         ` Peter Zijlstra
2025-06-19  9:10           ` Steven Rostedt
2025-06-19  9:24             ` Peter Zijlstra
2025-06-19  8:57   ` Peter Zijlstra
2025-06-19  9:07     ` Steven Rostedt
2025-06-19  9:32       ` Peter Zijlstra
2025-06-19  9:34         ` Peter Zijlstra
2025-06-19  9:42         ` Steven Rostedt
2025-06-19  9:45           ` Peter Zijlstra
2025-06-19 10:19             ` Steven Rostedt
2025-06-19 10:39               ` Peter Zijlstra
2025-06-19 13:04                 ` Steven Rostedt
2025-06-11  0:54 ` [PATCH v10 08/14] unwind deferred: Use bitmask to determine which callbacks to call Steven Rostedt
2025-06-20  8:15   ` Peter Zijlstra
2025-06-24 14:55     ` Steven Rostedt
2025-06-24 15:00       ` Peter Zijlstra
2025-06-24 16:36         ` Steven Rostedt
2025-06-11  0:54 ` [PATCH v10 09/14] unwind deferred: Use SRCU unwind_deferred_task_work() Steven Rostedt
2025-06-11  0:54 ` [PATCH v10 10/14] unwind: Clear unwind_mask on exit back to user space Steven Rostedt
2025-06-11  0:54 ` [PATCH v10 11/14] unwind: Finish up unwind when a task exits Steven Rostedt
2025-06-11  0:54 ` [PATCH v10 12/14] unwind_user/x86: Enable frame pointer unwinding on x86 Steven Rostedt
2025-06-11  0:54 ` [PATCH v10 13/14] perf/x86: Rename and move get_segment_base() and make it global Steven Rostedt
2025-06-11  0:54 ` [PATCH v10 14/14] unwind_user/x86: Enable compat mode frame pointer unwinding on x86 Steven Rostedt
2025-06-12 21:44 ` [PATCH v10 00/14] unwind_user: x86: Deferred unwinding infrastructure Andrii Nakryiko
2025-06-12 22:02   ` Josh Poimboeuf
2025-06-12 23:30     ` Andrii Nakryiko

Reply instructions:

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

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

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

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

  git send-email \
    --in-reply-to=20250611010428.603778772@goodmis.org \
    --to=rostedt@goodmis.org \
    --cc=akpm@linux-foundation.org \
    --cc=andrii@kernel.org \
    --cc=beaub@linux.microsoft.com \
    --cc=bpf@vger.kernel.org \
    --cc=indu.bhagat@oracle.com \
    --cc=jemarch@gnu.org \
    --cc=jolsa@kernel.org \
    --cc=jpoimboe@kernel.org \
    --cc=jremus@linux.ibm.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-trace-kernel@vger.kernel.org \
    --cc=mathieu.desnoyers@efficios.com \
    --cc=mhiramat@kernel.org \
    --cc=mingo@kernel.org \
    --cc=namhyung@kernel.org \
    --cc=peterz@infradead.org \
    --cc=tglx@linutronix.de \
    --cc=torvalds@linux-foundation.org \
    --cc=x86@kernel.org \
    /path/to/YOUR_REPLY

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

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