summaryrefslogtreecommitdiff
path: root/arch/s390/kernel/stacktrace.c
diff options
context:
space:
mode:
authorHeiko Carstens <hca@linux.ibm.com>2024-04-29 15:28:44 +0300
committerAlexander Gordeev <agordeev@linux.ibm.com>2024-05-14 14:37:06 +0300
commitebd912ff9919a10609511383d94942362234c077 (patch)
tree9a2855b26b7ec7cd60723dc3ac08fb511a58bf2d /arch/s390/kernel/stacktrace.c
parent185445c7c137822ad856aae91a41e199370cb534 (diff)
downloadlinux-ebd912ff9919a10609511383d94942362234c077.tar.xz
s390/stacktrace: Merge perf_callchain_user() and arch_stack_walk_user()
The two functions perf_callchain_user() and arch_stack_walk_user() are nearly identical. Reduce code duplication and add a common helper which can be called by both functions. Fixes: aa44433ac4ee ("s390: add USER_STACKTRACE support") Reviewed-by: Jens Remus <jremus@linux.ibm.com> Signed-off-by: Heiko Carstens <hca@linux.ibm.com> Signed-off-by: Alexander Gordeev <agordeev@linux.ibm.com>
Diffstat (limited to 'arch/s390/kernel/stacktrace.c')
-rw-r--r--arch/s390/kernel/stacktrace.c33
1 files changed, 28 insertions, 5 deletions
diff --git a/arch/s390/kernel/stacktrace.c b/arch/s390/kernel/stacktrace.c
index 7c294da45bf5..e580d4cd2729 100644
--- a/arch/s390/kernel/stacktrace.c
+++ b/arch/s390/kernel/stacktrace.c
@@ -5,6 +5,7 @@
* Copyright IBM Corp. 2006
*/
+#include <linux/perf_event.h>
#include <linux/stacktrace.h>
#include <linux/uaccess.h>
#include <linux/compat.h>
@@ -62,8 +63,23 @@ int arch_stack_walk_reliable(stack_trace_consume_fn consume_entry,
return 0;
}
-void arch_stack_walk_user(stack_trace_consume_fn consume_entry, void *cookie,
- const struct pt_regs *regs)
+static inline bool store_ip(stack_trace_consume_fn consume_entry, void *cookie,
+ struct perf_callchain_entry_ctx *entry, bool perf,
+ unsigned long ip)
+{
+#ifdef CONFIG_PERF_EVENTS
+ if (perf) {
+ if (perf_callchain_store(entry, ip))
+ return false;
+ return true;
+ }
+#endif
+ return consume_entry(cookie, ip);
+}
+
+void arch_stack_walk_user_common(stack_trace_consume_fn consume_entry, void *cookie,
+ struct perf_callchain_entry_ctx *entry,
+ const struct pt_regs *regs, bool perf)
{
struct stack_frame_user __user *sf;
unsigned long ip, sp;
@@ -71,7 +87,8 @@ void arch_stack_walk_user(stack_trace_consume_fn consume_entry, void *cookie,
if (is_compat_task())
return;
- if (!consume_entry(cookie, instruction_pointer(regs)))
+ ip = instruction_pointer(regs);
+ if (!store_ip(consume_entry, cookie, entry, perf, ip))
return;
sf = (void __user *)user_stack_pointer(regs);
pagefault_disable();
@@ -91,8 +108,8 @@ void arch_stack_walk_user(stack_trace_consume_fn consume_entry, void *cookie,
else
break;
}
- if (!consume_entry(cookie, ip))
- break;
+ if (!store_ip(consume_entry, cookie, entry, perf, ip))
+ return;
/* Sanity check: ABI requires SP to be aligned 8 bytes. */
if (!sp || sp & 0x7)
break;
@@ -102,6 +119,12 @@ void arch_stack_walk_user(stack_trace_consume_fn consume_entry, void *cookie,
pagefault_enable();
}
+void arch_stack_walk_user(stack_trace_consume_fn consume_entry, void *cookie,
+ const struct pt_regs *regs)
+{
+ arch_stack_walk_user_common(consume_entry, cookie, NULL, regs, false);
+}
+
unsigned long return_address(unsigned int n)
{
struct unwind_state state;