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-11178

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>
[
  mb: partial rewrite. We don't want to backport all the commits to keep the
  code base sane. That is why save_stack_trace*() functions have to be preserved
  regardless ARCH_STACKWALK being enabled.
]
Acked-by: Miroslav Benes <mbenes@suse.cz>
---
 arch/s390/Kconfig             |    1 
 arch/s390/kernel/stacktrace.c |   13 +++++++++++
 include/linux/stacktrace.h    |   49 ++++++++++++++++++++----------------------
 3 files changed, 38 insertions(+), 25 deletions(-)

--- a/arch/s390/Kconfig
+++ b/arch/s390/Kconfig
@@ -111,6 +111,7 @@ config S390
 	select ARCH_INLINE_WRITE_UNLOCK_IRQ
 	select ARCH_INLINE_WRITE_UNLOCK_IRQRESTORE
 	select ARCH_SAVE_PAGE_KEYS if HIBERNATION
+	select ARCH_STACKWALK
 	select ARCH_SUPPORTS_ATOMIC_RMW
 	select ARCH_SUPPORTS_DEFERRED_STRUCT_PAGE_INIT
 	select ARCH_SUPPORTS_NUMA_BALANCING
--- a/arch/s390/kernel/stacktrace.c
+++ b/arch/s390/kernel/stacktrace.c
@@ -13,6 +13,19 @@
 #include <asm/stacktrace.h>
 #include <asm/unwind.h>
 
+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, task, regs, 0) {
+		addr = unwind_get_return_address(&state);
+		if (!addr || !consume_entry(cookie, addr, false))
+			break;
+	}
+}
+
 void save_stack_trace(struct stack_trace *trace)
 {
 	struct unwind_state state;
--- a/include/linux/stacktrace.h
+++ b/include/linux/stacktrace.h
@@ -21,6 +21,30 @@ unsigned int stack_trace_save_regs(struc
 				   unsigned int size, unsigned int skipnr);
 unsigned int stack_trace_save_user(unsigned long *store, unsigned int size);
 
+struct stack_trace {
+	unsigned int nr_entries, max_entries;
+	unsigned long *entries;
+	int skip;	/* input argument: How many entries to skip */
+};
+
+extern void save_stack_trace(struct stack_trace *trace);
+extern void save_stack_trace_regs(struct pt_regs *regs,
+				  struct stack_trace *trace);
+extern void save_stack_trace_tsk(struct task_struct *tsk,
+				struct stack_trace *trace);
+extern int save_stack_trace_tsk_reliable(struct task_struct *tsk,
+					 struct stack_trace *trace);
+
+extern void print_stack_trace(struct stack_trace *trace, int spaces);
+extern int snprint_stack_trace(char *buf, size_t size,
+			struct stack_trace *trace, int spaces);
+
+#ifdef CONFIG_USER_STACKTRACE_SUPPORT
+extern void save_stack_trace_user(struct stack_trace *trace);
+#else
+# define save_stack_trace_user(trace)              do { } while (0)
+#endif
+
 /* Internal interfaces. Do not use in generic code */
 #ifdef CONFIG_ARCH_STACKWALK
 
@@ -59,31 +83,6 @@ int arch_stack_walk_reliable(stack_trace
 void arch_stack_walk_user(stack_trace_consume_fn consume_entry, void *cookie,
 			  const struct pt_regs *regs);
 
-#else /* CONFIG_ARCH_STACKWALK */
-struct stack_trace {
-	unsigned int nr_entries, max_entries;
-	unsigned long *entries;
-	int skip;	/* input argument: How many entries to skip */
-};
-
-extern void save_stack_trace(struct stack_trace *trace);
-extern void save_stack_trace_regs(struct pt_regs *regs,
-				  struct stack_trace *trace);
-extern void save_stack_trace_tsk(struct task_struct *tsk,
-				struct stack_trace *trace);
-extern int save_stack_trace_tsk_reliable(struct task_struct *tsk,
-					 struct stack_trace *trace);
-
-extern void print_stack_trace(struct stack_trace *trace, int spaces);
-extern int snprint_stack_trace(char *buf, size_t size,
-			struct stack_trace *trace, int spaces);
-
-#ifdef CONFIG_USER_STACKTRACE_SUPPORT
-extern void save_stack_trace_user(struct stack_trace *trace);
-#else
-# define save_stack_trace_user(trace)              do { } while (0)
-#endif
-
 #endif /* !CONFIG_ARCH_STACKWALK */
 
 #else /* !CONFIG_STACKTRACE */