2022-07-12 02:27:46

by Li Huafei

[permalink] [raw]
Subject: [PATCH 5/5] ARM: stacktrace: Convert stacktrace to generic ARCH_STACKWALK

This patch converts ARM stacktrace to the generic ARCH_STACKWALK
implemented by commit 214d8ca6ee85 ("stacktrace: Provide common
infrastructure").

Signed-off-by: Li Huafei <[email protected]>
---
arch/arm/Kconfig | 1 +
arch/arm/kernel/stacktrace.c | 114 ++++++++++-------------------------
2 files changed, 33 insertions(+), 82 deletions(-)

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


2022-07-18 09:26:12

by Linus Walleij

[permalink] [raw]
Subject: Re: [PATCH 5/5] ARM: stacktrace: Convert stacktrace to generic ARCH_STACKWALK

On Tue, Jul 12, 2022 at 4:19 AM Li Huafei <[email protected]> wrote:

> This patch converts ARM stacktrace to the generic ARCH_STACKWALK
> implemented by commit 214d8ca6ee85 ("stacktrace: Provide common
> infrastructure").
>
> Signed-off-by: Li Huafei <[email protected]>

Looks good to me:
Reviewed-by: Linus Walleij <[email protected]>

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

2022-07-26 09:39:47

by Li Huafei

[permalink] [raw]
Subject: Re: [PATCH 5/5] ARM: stacktrace: Convert stacktrace to generic ARCH_STACKWALK



On 2022/7/18 17:12, Linus Walleij wrote:
> On Tue, Jul 12, 2022 at 4:19 AM Li Huafei <[email protected]> wrote:
>
>> This patch converts ARM stacktrace to the generic ARCH_STACKWALK
>> implemented by commit 214d8ca6ee85 ("stacktrace: Provide common
>> infrastructure").
>>
>> Signed-off-by: Li Huafei <[email protected]>
>
> Looks good to me:
> Reviewed-by: Linus Walleij <[email protected]>
>
> 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
> .
>

2022-07-27 06:44:22

by Li Huafei

[permalink] [raw]
Subject: Re: [PATCH 5/5] ARM: stacktrace: Convert stacktrace to generic ARCH_STACKWALK


Hi Linus,

On 2022/7/18 17:12, Linus Walleij wrote:
> On Tue, Jul 12, 2022 at 4:19 AM Li Huafei <[email protected]> wrote:
>
>> This patch converts ARM stacktrace to the generic ARCH_STACKWALK
>> implemented by commit 214d8ca6ee85 ("stacktrace: Provide common
>> infrastructure").
>>
>> Signed-off-by: Li Huafei <[email protected]>
>
> Looks good to me:
> Reviewed-by: Linus Walleij <[email protected]>
>
> 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/[email protected]/

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