--- zzzz-none-000/linux-3.10.107/arch/arc/kernel/stacktrace.c 2017-06-27 09:49:32.000000000 +0000 +++ scorpion-7490-727/linux-3.10.107/arch/arc/kernel/stacktrace.c 2021-02-04 17:41:59.000000000 +0000 @@ -43,6 +43,10 @@ struct pt_regs *regs, struct unwind_frame_info *frame_info) { + /* + * synchronous unwinding (e.g. dump_stack) + * - uses current values of SP and friends + */ if (tsk == NULL && regs == NULL) { unsigned long fp, sp, blink, ret; frame_info->task = current; @@ -61,12 +65,17 @@ frame_info->regs.r63 = ret; frame_info->call_frame = 0; } else if (regs == NULL) { + /* + * Asynchronous unwinding of sleeping task + * - Gets SP etc from task's pt_regs (saved bottom of kernel + * mode stack of task) + */ frame_info->task = tsk; - frame_info->regs.r27 = KSTK_FP(tsk); - frame_info->regs.r28 = KSTK_ESP(tsk); - frame_info->regs.r31 = KSTK_BLINK(tsk); + frame_info->regs.r27 = TSK_K_FP(tsk); + frame_info->regs.r28 = TSK_K_ESP(tsk); + frame_info->regs.r31 = TSK_K_BLINK(tsk); frame_info->regs.r63 = (unsigned int)__switch_to; /* In the prologue of __switch_to, first FP is saved on stack @@ -79,10 +88,14 @@ * assembly code */ frame_info->regs.r27 = 0; - frame_info->regs.r28 += 64; + frame_info->regs.r28 += 60; frame_info->call_frame = 0; } else { + /* + * Asynchronous unwinding of intr/exception + * - Just uses the pt_regs passed + */ frame_info->task = tsk; frame_info->regs.r27 = regs->fp; @@ -95,7 +108,7 @@ #endif -static noinline unsigned int +notrace noinline unsigned int arc_unwind_core(struct task_struct *tsk, struct pt_regs *regs, int (*consumer_fn) (unsigned int, void *), void *arg) { @@ -109,19 +122,17 @@ while (1) { address = UNW_PC(&frame_info); - if (address && __kernel_text_address(address)) { - if (consumer_fn(address, arg) == -1) - break; - } + if (!address || !__kernel_text_address(address)) + break; + + if (consumer_fn(address, arg) == -1) + break; ret = arc_unwind(&frame_info); - - if (ret == 0) { - frame_info.regs.r63 = frame_info.regs.r31; - continue; - } else { + if (ret) break; - } + + frame_info.regs.r63 = frame_info.regs.r31; } return address; /* return the last address it saw */ @@ -237,11 +248,14 @@ */ void save_stack_trace_tsk(struct task_struct *tsk, struct stack_trace *trace) { + /* Assumes @tsk is sleeping so unwinds from __switch_to */ arc_unwind_core(tsk, NULL, __collect_all_but_sched, trace); } void save_stack_trace(struct stack_trace *trace) { - arc_unwind_core(current, NULL, __collect_all, trace); + /* Pass NULL for task so it unwinds the current call frame */ + arc_unwind_core(NULL, NULL, __collect_all, trace); } +EXPORT_SYMBOL_GPL(save_stack_trace); #endif