diff mbox series

[5/5] ARM: stacktrace: Convert stacktrace to generic ARCH_STACKWALK

Message ID 20220712021527.109921-6-lihuafei1@huawei.com (mailing list archive)
State New, archived
Headers show
Series ARM: Convert to ARCH_STACKWALK | expand

Commit Message

Li Huafei July 12, 2022, 2:15 a.m. UTC
This patch converts ARM stacktrace to the generic ARCH_STACKWALK
implemented by commit 214d8ca6ee85 ("stacktrace: Provide common
infrastructure").

Signed-off-by: Li Huafei <lihuafei1@huawei.com>
---
 arch/arm/Kconfig             |   1 +
 arch/arm/kernel/stacktrace.c | 114 ++++++++++-------------------------
 2 files changed, 33 insertions(+), 82 deletions(-)

Comments

Linus Walleij July 18, 2022, 9:12 a.m. UTC | #1
On Tue, Jul 12, 2022 at 4:19 AM Li Huafei <lihuafei1@huawei.com> wrote:

> This patch converts ARM stacktrace to the generic ARCH_STACKWALK
> implemented by commit 214d8ca6ee85 ("stacktrace: Provide common
> infrastructure").
>
> Signed-off-by: Li Huafei <lihuafei1@huawei.com>

Looks good to me:
Reviewed-by: Linus Walleij <linus.walleij@linaro.org>

What I want to know is if this commit will avoid the problem mentioned
in review of commit 3? I.e. the generic stackwalk code will make sure we are
not running the task on another CPU, so that is why we could remove
that check?

Yours,
Linus Walleij
Li Huafei July 26, 2022, 9:15 a.m. UTC | #2
On 2022/7/18 17:12, Linus Walleij wrote:
> On Tue, Jul 12, 2022 at 4:19 AM Li Huafei <lihuafei1@huawei.com> wrote:
> 
>> This patch converts ARM stacktrace to the generic ARCH_STACKWALK
>> implemented by commit 214d8ca6ee85 ("stacktrace: Provide common
>> infrastructure").
>>
>> Signed-off-by: Li Huafei <lihuafei1@huawei.com>
> 
> Looks good to me:
> Reviewed-by: Linus Walleij <linus.walleij@linaro.org>
> 
> What I want to know is if this commit will avoid the problem mentioned
> in review of commit 3? I.e. the generic stackwalk code will make sure we are
> not running the task on another CPU, so that is why we could remove
> that check?
> 

It was explained in commit 3, thank you very much.

Thanks,
Huafei

> Yours,
> Linus Walleij
> .
>
Li Huafei July 27, 2022, 6:29 a.m. UTC | #3
Hi Linus,

On 2022/7/18 17:12, Linus Walleij wrote:
> On Tue, Jul 12, 2022 at 4:19 AM Li Huafei <lihuafei1@huawei.com> wrote:
> 
>> This patch converts ARM stacktrace to the generic ARCH_STACKWALK
>> implemented by commit 214d8ca6ee85 ("stacktrace: Provide common
>> infrastructure").
>>
>> Signed-off-by: Li Huafei <lihuafei1@huawei.com>
> 
> Looks good to me:
> Reviewed-by: Linus Walleij <linus.walleij@linaro.org>
> 
> What I want to know is if this commit will avoid the problem mentioned
> in review of commit 3? I.e. the generic stackwalk code will make sure we are
> not running the task on another CPU, so that is why we could remove
> that check?
> 

In v3, I removed patch 3 of v1 and kept that check, see

  https://lore.kernel.org/lkml/20220727040022.139387-1-lihuafei1@huawei.com/

Given this change, I did not add your reviewed-by to patch 4 of v3. If 
you think patch 4 of v3 is still ok, please do let me know. Thank you 
very much!

Thanks,
Huafei

> Yours,
> Linus Walleij
> .
>
diff mbox series

Patch

diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index 7630ba9cb6cc..8da192853562 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -18,6 +18,7 @@  config ARM
 	select ARCH_HAS_PHYS_TO_DMA
 	select ARCH_HAS_SETUP_DMA_OPS
 	select ARCH_HAS_SET_MEMORY
+	select ARCH_STACKWALK
 	select ARCH_HAS_STRICT_KERNEL_RWX if MMU && !XIP_KERNEL
 	select ARCH_HAS_STRICT_MODULE_RWX if MMU
 	select ARCH_HAS_SYNC_DMA_FOR_DEVICE if SWIOTLB || !MMU
diff --git a/arch/arm/kernel/stacktrace.c b/arch/arm/kernel/stacktrace.c
index ec0ca3192775..1b9c91e14d2e 100644
--- a/arch/arm/kernel/stacktrace.c
+++ b/arch/arm/kernel/stacktrace.c
@@ -136,98 +136,48 @@  void notrace walk_stackframe(struct stackframe *frame,
 EXPORT_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)
-{
-	struct stack_trace_data *data = d;
-	struct stack_trace *trace = data->trace;
-
-	if (data->no_sched_functions && in_sched_functions(addr))
-		return true;
-	if (data->skip) {
-		data->skip--;
-		return true;
-	}
-
-	trace->entries[trace->nr_entries++] = addr;
-	return trace->nr_entries < trace->max_entries;
-}
-
-/* This must be noinline to so that our skip calculation works correctly */
-static noinline void __save_stack_trace(struct task_struct *tsk,
-	struct stack_trace *trace, unsigned int nosched)
+static void start_stack_trace(struct stackframe *frame, struct task_struct *task,
+			      unsigned long fp, unsigned long sp,
+			      unsigned long lr, unsigned long pc)
 {
-	struct stack_trace_data data;
-	struct stackframe frame;
-
-	data.trace = trace;
-	data.skip = trace->skip;
-	data.no_sched_functions = nosched;
-
-	if (tsk != current) {
-		/* task blocked in __switch_to */
-		frame.fp = thread_saved_fp(tsk);
-		frame.sp = thread_saved_sp(tsk);
-		frame.lr = 0;		/* recovered from the stack */
-		frame.pc = thread_saved_pc(tsk);
-	} else {
-		/* We don't want this function nor the caller */
-		data.skip += 2;
-		frame.fp = (unsigned long)__builtin_frame_address(0);
-		frame.sp = current_stack_pointer;
-		frame.lr = (unsigned long)__builtin_return_address(0);
-here:
-		frame.pc = (unsigned long)&&here;
-	}
+	frame->fp = fp;
+	frame->sp = sp;
+	frame->lr = lr;
+	frame->pc = pc;
 #ifdef CONFIG_KRETPROBES
-	frame.kr_cur = NULL;
-	frame.tsk = tsk;
+	frame->kr_cur = NULL;
+	frame->tsk = task;
 #endif
 #ifdef CONFIG_UNWINDER_FRAME_POINTER
-	frame.ex_frame = false;
+	frame->ex_frame = in_entry_text(frame->pc) ? true : false;
 #endif
-
-	walk_stackframe(&frame, save_trace, &data);
 }
 
-void save_stack_trace_regs(struct pt_regs *regs, 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 stack_trace_data data;
 	struct stackframe frame;
 
-	data.trace = trace;
-	data.skip = trace->skip;
-	data.no_sched_functions = 0;
-
-	frame.fp = regs->ARM_fp;
-	frame.sp = regs->ARM_sp;
-	frame.lr = regs->ARM_lr;
-	frame.pc = regs->ARM_pc;
-#ifdef CONFIG_KRETPROBES
-	frame.kr_cur = NULL;
-	frame.tsk = current;
-#endif
-#ifdef CONFIG_UNWINDER_FRAME_POINTER
-	frame.ex_frame = in_entry_text(frame.pc) ? true : false;
-#endif
-
-	walk_stackframe(&frame, save_trace, &data);
-}
-
-void save_stack_trace_tsk(struct task_struct *tsk, struct stack_trace *trace)
-{
-	__save_stack_trace(tsk, trace, 1);
-}
-EXPORT_SYMBOL(save_stack_trace_tsk);
+	if (regs) {
+		start_stack_trace(&frame, NULL, regs->ARM_fp, regs->ARM_sp,
+				  regs->ARM_lr, regs->ARM_pc);
+	} else if (task != current) {
+		/* task blocked in __switch_to */
+		start_stack_trace(&frame, task, thread_saved_fp(task),
+				  thread_saved_sp(task), 0,
+				  thread_saved_pc(task));
+	} else {
+here:
+		start_stack_trace(&frame, task,
+				  (unsigned long)__builtin_frame_address(0),
+				  current_stack_pointer,
+				  (unsigned long)__builtin_return_address(0),
+				  (unsigned long)&&here);
+		/* skip this function */
+		if (unwind_frame(&frame))
+			return;
+	}
 
-void save_stack_trace(struct stack_trace *trace)
-{
-	__save_stack_trace(current, trace, 0);
+	walk_stackframe(&frame, consume_entry, cookie);
 }
-EXPORT_SYMBOL_GPL(save_stack_trace);
 #endif