arm64: stacktrace: Convert to ARCH_STACKWALK
authorMark Brown <broonie@kernel.org>
Mon, 14 Sep 2020 15:34:09 +0000 (16:34 +0100)
committerWill Deacon <will@kernel.org>
Fri, 18 Sep 2020 13:24:16 +0000 (14:24 +0100)
Historically architectures have had duplicated code in their stack trace
implementations for filtering what gets traced. In order to avoid this
duplication some generic code has been provided using a new interface
arch_stack_walk(), enabled by selecting ARCH_STACKWALK in Kconfig, which
factors all this out into the generic stack trace code. Convert arm64
to use this common infrastructure.

Signed-off-by: Mark Brown <broonie@kernel.org>
Reviewed-by: Miroslav Benes <mbenes@suse.cz>
Link: https://lore.kernel.org/r/20200914153409.25097-4-broonie@kernel.org
Signed-off-by: Will Deacon <will@kernel.org>
arch/arm64/Kconfig
arch/arm64/kernel/stacktrace.c

index 6d232837cbeee8abb0c5a9c37b05c8566260156f..d1ba52e4b976c08a95812add814e9e0bfa49847c 100644 (file)
@@ -29,6 +29,7 @@ config ARM64
        select ARCH_HAS_SETUP_DMA_OPS
        select ARCH_HAS_SET_DIRECT_MAP
        select ARCH_HAS_SET_MEMORY
+       select ARCH_STACKWALK
        select ARCH_HAS_STRICT_KERNEL_RWX
        select ARCH_HAS_STRICT_MODULE_RWX
        select ARCH_HAS_SYNC_DMA_FOR_DEVICE
index 05eaba21fd46833ab85ea003dd590a6726d0fe9f..804d076b02cb81d356cb6d216fc5cdbac004d163 100644 (file)
@@ -133,82 +133,23 @@ void notrace walk_stackframe(struct task_struct *tsk, struct stackframe *frame,
 NOKPROBE_SYMBOL(walk_stackframe);
 
 #ifdef CONFIG_STACKTRACE
-struct stack_trace_data {
-       struct stack_trace *trace;
-       unsigned int no_sched_functions;
-       unsigned int skip;
-};
 
-static bool save_trace(void *d, unsigned long addr)
+void arch_stack_walk(stack_trace_consume_fn consume_entry, void *cookie,
+                    struct task_struct *task, struct pt_regs *regs)
 {
-       struct stack_trace_data *data = d;
-       struct stack_trace *trace = data->trace;
-
-       if (data->no_sched_functions && in_sched_functions(addr))
-               return false;
-       if (data->skip) {
-               data->skip--;
-               return false;
-       }
-
-       trace->entries[trace->nr_entries++] = addr;
-
-       return trace->nr_entries >= trace->max_entries;
-}
-
-void save_stack_trace_regs(struct pt_regs *regs, struct stack_trace *trace)
-{
-       struct stack_trace_data data;
-       struct stackframe frame;
-
-       data.trace = trace;
-       data.skip = trace->skip;
-       data.no_sched_functions = 0;
-
-       start_backtrace(&frame, regs->regs[29], regs->pc);
-       walk_stackframe(current, &frame, save_trace, &data);
-}
-EXPORT_SYMBOL_GPL(save_stack_trace_regs);
-
-static noinline void __save_stack_trace(struct task_struct *tsk,
-       struct stack_trace *trace, unsigned int nosched)
-{
-       struct stack_trace_data data;
        struct stackframe frame;
 
-       if (!try_get_task_stack(tsk))
-               return;
-
-       data.trace = trace;
-       data.skip = trace->skip;
-       data.no_sched_functions = nosched;
-
-       if (tsk != current) {
-               start_backtrace(&frame, thread_saved_fp(tsk),
-                               thread_saved_pc(tsk));
-       } else {
-               /* We don't want this function nor the caller */
-               data.skip += 2;
+       if (regs)
+               start_backtrace(&frame, regs->regs[29], regs->pc);
+       else if (task == current)
                start_backtrace(&frame,
                                (unsigned long)__builtin_frame_address(0),
-                               (unsigned long)__save_stack_trace);
-       }
-
-       walk_stackframe(tsk, &frame, save_trace, &data);
+                               (unsigned long)arch_stack_walk);
+       else
+               start_backtrace(&frame, thread_saved_fp(task),
+                               thread_saved_pc(task));
 
-       put_task_stack(tsk);
-}
-
-void save_stack_trace_tsk(struct task_struct *tsk, struct stack_trace *trace)
-{
-       __save_stack_trace(tsk, trace, 1);
-}
-EXPORT_SYMBOL_GPL(save_stack_trace_tsk);
-
-void save_stack_trace(struct stack_trace *trace)
-{
-       __save_stack_trace(current, trace, 0);
+       walk_stackframe(task, &frame, consume_entry, cookie);
 }
 
-EXPORT_SYMBOL_GPL(save_stack_trace);
 #endif