FAILED: patch "[PATCH] riscv: stacktrace: fix the riscv stacktrace when" failed to apply to 5.10-stable tree
Subsystems (2)
[email protected]
maintainerThe patch below does not apply to the 5.10-stable tree.
If someone wants it applied there, or to any other stable or longterm tree, then please email the backport, including the original git commit id to <[email protected]>.
thanks,
greg k-h
------------------ original commit in Linus's tree ------------------
From eac2f3059e02382d91f8c887462083841d6ea2a3 Mon Sep 17 00:00:00 2001
From: Chen Huang <[email protected]>
Date: Thu, 29 Apr 2021 07:03:48 +0000
Subject: [PATCH] riscv: stacktrace: fix the riscv stacktrace when
CONFIG_FRAME_POINTER enabled
As [1] and [2] said, the arch_stack_walk should not to trace itself, or it will leave the trace unexpectedly when called. The example is when we do "cat /sys/kernel/debug/page_owner", all pages' stack is the same.
arch_stack_walk+0x18/0x20 stack_trace_save+0x40/0x60 register_dummy_stack+0x24/0x5e init_page_owner+0x2e
So we use __builtin_frame_address(1) as the first frame to be walked. And mark the arch_stack_walk() noinline.
We found that pr_cont will affact pages' stack whose task state is RUNNING when testing "echo t > /proc/sysrq-trigger". So move the place of pr_cont and mark the function dump_backtrace() noinline.
Also we move the case when task == NULL into else branch, and test for it in "echo c > /proc/sysrq-trigger".
[1] https://lore.kernel.org/lkml/[email protected]/
[2] https://lore.kernel.org/lkml/[email protected]/
arch/riscv/kernel/stacktrace.c +7 -7
@@ -27,10 +27,10 @@ void notrace walk_stackframe(struct task_struct *task, struct pt_regs *regs, fp =frame_pointer (regs); sp =user_stack_pointer (regs); pc =instruction_pointer (regs); - }else if (task ==NULL || task == current) { - fp = (unsigned long )__builtin_frame_address (0 ); - sp = sp_in_global; - pc = (unsigned long )walk_stackframe; + }else if (task == current) { + fp = (unsigned long )__builtin_frame_address (1 ); + sp = (unsigned long )__builtin_frame_address (0 ); + pc = (unsigned long )__builtin_return_address (0 ); }else {/* task blocked in __switch_to */ fp = task->thread.s[0 ];
@@ -106,15 +106,15 @@ static bool print_trace_address(void *arg, unsigned long pc)return true; } -void dump_backtrace (struct pt_regs *regs,struct task_struct *task, +noinline void dump_backtrace(struct pt_regs *regs, struct task_struct *task,const char *loglvl) { -pr_cont ("%sCall Trace:\n" , loglvl);walk_stackframe (task, regs, print_trace_address, (void *)loglvl); }void show_stack (struct task_struct *task,unsigned long *sp,const char *loglvl) { +pr_cont ("%sCall Trace:\n" , loglvl);dump_backtrace (NULL , task, loglvl); }
@@ -139,7 +139,7 @@ unsigned long get_wchan(struct task_struct *task)#ifdef CONFIG_STACKTRACE -void arch_stack_walk (stack_trace_consume_fn consume_entry,void *cookie, +noinline void arch_stack_walk(stack_trace_consume_fn consume_entry, void *cookie,struct task_struct *task,struct pt_regs *regs) {walk_stackframe (task, regs, consume_entry, cookie);