Loading arch/arm64/kernel/traps.c +23 −0 Original line number Diff line number Diff line Loading @@ -102,6 +102,9 @@ void dump_backtrace(struct pt_regs *regs, struct task_struct *tsk) { struct stackframe frame; int skip; long cur_state = 0; unsigned long cur_sp = 0; unsigned long cur_fp = 0; pr_debug("%s(regs = %p tsk = %p)\n", __func__, regs, tsk); Loading @@ -120,6 +123,9 @@ void dump_backtrace(struct pt_regs *regs, struct task_struct *tsk) */ frame.fp = thread_saved_fp(tsk); frame.pc = thread_saved_pc(tsk); cur_state = tsk->state; cur_sp = thread_saved_sp(tsk); cur_fp = frame.fp; } #ifdef CONFIG_FUNCTION_GRAPH_TRACER frame.graph = tsk->curr_ret_stack; Loading @@ -128,6 +134,23 @@ void dump_backtrace(struct pt_regs *regs, struct task_struct *tsk) skip = !!regs; printk("Call trace:\n"); do { if (tsk != current && (cur_state != tsk->state /* * We would not be printing backtrace for the task * that has changed state from uninterruptible to * running before hitting the do-while loop but after * saving the current state. If task is in running * state before saving the state, then we may print * wrong call trace or end up in infinite while loop * if *(fp) and *(fp+8) are same. While the situation * will stop print when that task schedule out. */ || cur_sp != thread_saved_sp(tsk) || cur_fp != thread_saved_fp(tsk))) { printk("The task:%s had been rescheduled!\n", tsk->comm); break; } /* skip until specified stack frame */ if (!skip) { dump_backtrace_entry(frame.pc); Loading Loading
arch/arm64/kernel/traps.c +23 −0 Original line number Diff line number Diff line Loading @@ -102,6 +102,9 @@ void dump_backtrace(struct pt_regs *regs, struct task_struct *tsk) { struct stackframe frame; int skip; long cur_state = 0; unsigned long cur_sp = 0; unsigned long cur_fp = 0; pr_debug("%s(regs = %p tsk = %p)\n", __func__, regs, tsk); Loading @@ -120,6 +123,9 @@ void dump_backtrace(struct pt_regs *regs, struct task_struct *tsk) */ frame.fp = thread_saved_fp(tsk); frame.pc = thread_saved_pc(tsk); cur_state = tsk->state; cur_sp = thread_saved_sp(tsk); cur_fp = frame.fp; } #ifdef CONFIG_FUNCTION_GRAPH_TRACER frame.graph = tsk->curr_ret_stack; Loading @@ -128,6 +134,23 @@ void dump_backtrace(struct pt_regs *regs, struct task_struct *tsk) skip = !!regs; printk("Call trace:\n"); do { if (tsk != current && (cur_state != tsk->state /* * We would not be printing backtrace for the task * that has changed state from uninterruptible to * running before hitting the do-while loop but after * saving the current state. If task is in running * state before saving the state, then we may print * wrong call trace or end up in infinite while loop * if *(fp) and *(fp+8) are same. While the situation * will stop print when that task schedule out. */ || cur_sp != thread_saved_sp(tsk) || cur_fp != thread_saved_fp(tsk))) { printk("The task:%s had been rescheduled!\n", tsk->comm); break; } /* skip until specified stack frame */ if (!skip) { dump_backtrace_entry(frame.pc); Loading