aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm64/kernel/traps.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/arm64/kernel/traps.c')
-rw-r--r--arch/arm64/kernel/traps.c52
1 files changed, 39 insertions, 13 deletions
diff --git a/arch/arm64/kernel/traps.c b/arch/arm64/kernel/traps.c
index e9b9b5364393..cbedd724f48e 100644
--- a/arch/arm64/kernel/traps.c
+++ b/arch/arm64/kernel/traps.c
@@ -146,17 +146,15 @@ static void dump_instr(const char *lvl, struct pt_regs *regs)
146static void dump_backtrace(struct pt_regs *regs, struct task_struct *tsk) 146static void dump_backtrace(struct pt_regs *regs, struct task_struct *tsk)
147{ 147{
148 struct stackframe frame; 148 struct stackframe frame;
149 unsigned long irq_stack_ptr = IRQ_STACK_PTR(smp_processor_id());
150 int skip;
149 151
150 pr_debug("%s(regs = %p tsk = %p)\n", __func__, regs, tsk); 152 pr_debug("%s(regs = %p tsk = %p)\n", __func__, regs, tsk);
151 153
152 if (!tsk) 154 if (!tsk)
153 tsk = current; 155 tsk = current;
154 156
155 if (regs) { 157 if (tsk == current) {
156 frame.fp = regs->regs[29];
157 frame.sp = regs->sp;
158 frame.pc = regs->pc;
159 } else if (tsk == current) {
160 frame.fp = (unsigned long)__builtin_frame_address(0); 158 frame.fp = (unsigned long)__builtin_frame_address(0);
161 frame.sp = current_stack_pointer; 159 frame.sp = current_stack_pointer;
162 frame.pc = (unsigned long)dump_backtrace; 160 frame.pc = (unsigned long)dump_backtrace;
@@ -168,21 +166,49 @@ static void dump_backtrace(struct pt_regs *regs, struct task_struct *tsk)
168 frame.sp = thread_saved_sp(tsk); 166 frame.sp = thread_saved_sp(tsk);
169 frame.pc = thread_saved_pc(tsk); 167 frame.pc = thread_saved_pc(tsk);
170 } 168 }
169#ifdef CONFIG_FUNCTION_GRAPH_TRACER
170 frame.graph = tsk->curr_ret_stack;
171#endif
171 172
172 pr_emerg("Call trace:\n"); 173 skip = !!regs;
174 printk("Call trace:\n");
173 while (1) { 175 while (1) {
174 unsigned long where = frame.pc; 176 unsigned long where = frame.pc;
175 unsigned long stack; 177 unsigned long stack;
176 int ret; 178 int ret;
177 179
178 dump_backtrace_entry(where); 180 /* skip until specified stack frame */
179 ret = unwind_frame(&frame); 181 if (!skip) {
182 dump_backtrace_entry(where);
183 } else if (frame.fp == regs->regs[29]) {
184 skip = 0;
185 /*
186 * Mostly, this is the case where this function is
187 * called in panic/abort. As exception handler's
188 * stack frame does not contain the corresponding pc
189 * at which an exception has taken place, use regs->pc
190 * instead.
191 */
192 dump_backtrace_entry(regs->pc);
193 }
194 ret = unwind_frame(tsk, &frame);
180 if (ret < 0) 195 if (ret < 0)
181 break; 196 break;
182 stack = frame.sp; 197 stack = frame.sp;
183 if (in_exception_text(where)) 198 if (in_exception_text(where)) {
199 /*
200 * If we switched to the irq_stack before calling this
201 * exception handler, then the pt_regs will be on the
202 * task stack. The easiest way to tell is if the large
203 * pt_regs would overlap with the end of the irq_stack.
204 */
205 if (stack < irq_stack_ptr &&
206 (stack + sizeof(struct pt_regs)) > irq_stack_ptr)
207 stack = IRQ_STACK_TO_TASK_STACK(irq_stack_ptr);
208
184 dump_mem("", "Exception stack", stack, 209 dump_mem("", "Exception stack", stack,
185 stack + sizeof(struct pt_regs), false); 210 stack + sizeof(struct pt_regs), false);
211 }
186 } 212 }
187} 213}
188 214
@@ -456,22 +482,22 @@ asmlinkage void bad_mode(struct pt_regs *regs, int reason, unsigned int esr)
456 482
457void __pte_error(const char *file, int line, unsigned long val) 483void __pte_error(const char *file, int line, unsigned long val)
458{ 484{
459 pr_crit("%s:%d: bad pte %016lx.\n", file, line, val); 485 pr_err("%s:%d: bad pte %016lx.\n", file, line, val);
460} 486}
461 487
462void __pmd_error(const char *file, int line, unsigned long val) 488void __pmd_error(const char *file, int line, unsigned long val)
463{ 489{
464 pr_crit("%s:%d: bad pmd %016lx.\n", file, line, val); 490 pr_err("%s:%d: bad pmd %016lx.\n", file, line, val);
465} 491}
466 492
467void __pud_error(const char *file, int line, unsigned long val) 493void __pud_error(const char *file, int line, unsigned long val)
468{ 494{
469 pr_crit("%s:%d: bad pud %016lx.\n", file, line, val); 495 pr_err("%s:%d: bad pud %016lx.\n", file, line, val);
470} 496}
471 497
472void __pgd_error(const char *file, int line, unsigned long val) 498void __pgd_error(const char *file, int line, unsigned long val)
473{ 499{
474 pr_crit("%s:%d: bad pgd %016lx.\n", file, line, val); 500 pr_err("%s:%d: bad pgd %016lx.\n", file, line, val);
475} 501}
476 502
477/* GENERIC_BUG traps */ 503/* GENERIC_BUG traps */