|
@@ -147,17 +147,14 @@ static void dump_backtrace(struct pt_regs *regs, struct task_struct *tsk)
|
|
|
{
|
|
|
struct stackframe frame;
|
|
|
unsigned long irq_stack_ptr = IRQ_STACK_PTR(smp_processor_id());
|
|
|
+ int skip;
|
|
|
|
|
|
pr_debug("%s(regs = %p tsk = %p)\n", __func__, regs, tsk);
|
|
|
|
|
|
if (!tsk)
|
|
|
tsk = current;
|
|
|
|
|
|
- if (regs) {
|
|
|
- frame.fp = regs->regs[29];
|
|
|
- frame.sp = regs->sp;
|
|
|
- frame.pc = regs->pc;
|
|
|
- } else if (tsk == current) {
|
|
|
+ if (tsk == current) {
|
|
|
frame.fp = (unsigned long)__builtin_frame_address(0);
|
|
|
frame.sp = current_stack_pointer;
|
|
|
frame.pc = (unsigned long)dump_backtrace;
|
|
@@ -169,14 +166,31 @@ static void dump_backtrace(struct pt_regs *regs, struct task_struct *tsk)
|
|
|
frame.sp = thread_saved_sp(tsk);
|
|
|
frame.pc = thread_saved_pc(tsk);
|
|
|
}
|
|
|
+#ifdef CONFIG_FUNCTION_GRAPH_TRACER
|
|
|
+ frame.graph = tsk->curr_ret_stack;
|
|
|
+#endif
|
|
|
|
|
|
+ skip = !!regs;
|
|
|
pr_emerg("Call trace:\n");
|
|
|
while (1) {
|
|
|
unsigned long where = frame.pc;
|
|
|
unsigned long stack;
|
|
|
int ret;
|
|
|
|
|
|
- dump_backtrace_entry(where);
|
|
|
+ /* skip until specified stack frame */
|
|
|
+ if (!skip) {
|
|
|
+ dump_backtrace_entry(where);
|
|
|
+ } else if (frame.fp == regs->regs[29]) {
|
|
|
+ skip = 0;
|
|
|
+ /*
|
|
|
+ * Mostly, this is the case where this function is
|
|
|
+ * called in panic/abort. As exception handler's
|
|
|
+ * stack frame does not contain the corresponding pc
|
|
|
+ * at which an exception has taken place, use regs->pc
|
|
|
+ * instead.
|
|
|
+ */
|
|
|
+ dump_backtrace_entry(regs->pc);
|
|
|
+ }
|
|
|
ret = unwind_frame(tsk, &frame);
|
|
|
if (ret < 0)
|
|
|
break;
|