Blob Blame History Raw
From: Vasily Gorbik <gor@linux.ibm.com>
Date: Wed, 14 Aug 2019 14:27:44 +0200
Subject: s390/stacktrace: use common arch_stack_walk infrastructure
Git-commit: e991e5bb11d6eacf8a49867ff9d4ec6e1cde3718
Patch-mainline: v5.4-rc1
References: jsc#SLE-11050

Use common arch_stack_walk infrastructure to avoid duplicated code and
avoid taking care of the stack storage and filtering.

Common code also uses try_get_task_stack/put_task_stack when needed which
have been missing in our code, which also solves potential problem for us.

Signed-off-by: Vasily Gorbik <gor@linux.ibm.com>
Acked-by: Miroslav Benes <mbenes@suse.cz>
---
 arch/s390/Kconfig             |  1 +
 arch/s390/kernel/stacktrace.c | 50 ++++++-------------------------------------
 2 files changed, 7 insertions(+), 44 deletions(-)

diff --git a/arch/s390/Kconfig b/arch/s390/Kconfig
index a4ad2733eedf..3289cc243d92 100644
--- a/arch/s390/Kconfig
+++ b/arch/s390/Kconfig
@@ -105,6 +105,7 @@ config S390
 	select ARCH_INLINE_WRITE_UNLOCK_IRQRESTORE
 	select ARCH_KEEP_MEMBLOCK
 	select ARCH_SAVE_PAGE_KEYS if HIBERNATION
+	select ARCH_STACKWALK
 	select ARCH_SUPPORTS_ATOMIC_RMW
 	select ARCH_SUPPORTS_NUMA_BALANCING
 	select ARCH_USE_BUILTIN_BSWAP
diff --git a/arch/s390/kernel/stacktrace.c b/arch/s390/kernel/stacktrace.c
index f6a620f854e1..f8fc4f8aef9b 100644
--- a/arch/s390/kernel/stacktrace.c
+++ b/arch/s390/kernel/stacktrace.c
@@ -6,57 +6,19 @@
  *  Author(s): Heiko Carstens <heiko.carstens@de.ibm.com>
  */
 
-#include <linux/sched.h>
-#include <linux/sched/debug.h>
 #include <linux/stacktrace.h>
-#include <linux/kallsyms.h>
-#include <linux/export.h>
 #include <asm/stacktrace.h>
 #include <asm/unwind.h>
 
-void save_stack_trace(struct stack_trace *trace)
+void arch_stack_walk(stack_trace_consume_fn consume_entry, void *cookie,
+		     struct task_struct *task, struct pt_regs *regs)
 {
 	struct unwind_state state;
+	unsigned long addr;
 
-	unwind_for_each_frame(&state, current, NULL, 0) {
-		if (trace->nr_entries >= trace->max_entries)
+	unwind_for_each_frame(&state, task, regs, 0) {
+		addr = unwind_get_return_address(&state);
+		if (!addr || !consume_entry(cookie, addr, false))
 			break;
-		if (trace->skip > 0)
-			trace->skip--;
-		else
-			trace->entries[trace->nr_entries++] = state.ip;
 	}
 }
-EXPORT_SYMBOL_GPL(save_stack_trace);
-
-void save_stack_trace_tsk(struct task_struct *tsk, struct stack_trace *trace)
-{
-	struct unwind_state state;
-
-	unwind_for_each_frame(&state, tsk, NULL, 0) {
-		if (trace->nr_entries >= trace->max_entries)
-			break;
-		if (in_sched_functions(state.ip))
-			continue;
-		if (trace->skip > 0)
-			trace->skip--;
-		else
-			trace->entries[trace->nr_entries++] = state.ip;
-	}
-}
-EXPORT_SYMBOL_GPL(save_stack_trace_tsk);
-
-void save_stack_trace_regs(struct pt_regs *regs, struct stack_trace *trace)
-{
-	struct unwind_state state;
-
-	unwind_for_each_frame(&state, current, regs, 0) {
-		if (trace->nr_entries >= trace->max_entries)
-			break;
-		if (trace->skip > 0)
-			trace->skip--;
-		else
-			trace->entries[trace->nr_entries++] = state.ip;
-	}
-}
-EXPORT_SYMBOL_GPL(save_stack_trace_regs);