aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86_64/kernel/traps.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/x86_64/kernel/traps.c')
-rw-r--r--arch/x86_64/kernel/traps.c54
1 files changed, 48 insertions, 6 deletions
diff --git a/arch/x86_64/kernel/traps.c b/arch/x86_64/kernel/traps.c
index 9f8f1eff4a6c..eb1534ff1f5f 100644
--- a/arch/x86_64/kernel/traps.c
+++ b/arch/x86_64/kernel/traps.c
@@ -29,6 +29,7 @@
29#include <linux/nmi.h> 29#include <linux/nmi.h>
30#include <linux/kprobes.h> 30#include <linux/kprobes.h>
31#include <linux/kexec.h> 31#include <linux/kexec.h>
32#include <linux/unwind.h>
32 33
33#include <asm/system.h> 34#include <asm/system.h>
34#include <asm/uaccess.h> 35#include <asm/uaccess.h>
@@ -39,7 +40,7 @@
39#include <asm/i387.h> 40#include <asm/i387.h>
40#include <asm/kdebug.h> 41#include <asm/kdebug.h>
41#include <asm/processor.h> 42#include <asm/processor.h>
42 43#include <asm/unwind.h>
43#include <asm/smp.h> 44#include <asm/smp.h>
44#include <asm/pgalloc.h> 45#include <asm/pgalloc.h>
45#include <asm/pda.h> 46#include <asm/pda.h>
@@ -189,6 +190,23 @@ static unsigned long *in_exception_stack(unsigned cpu, unsigned long stack,
189 return NULL; 190 return NULL;
190} 191}
191 192
193static void show_trace_unwind(struct unwind_frame_info *info, void *context)
194{
195 int i = 11;
196
197 while (unwind(info) == 0 && UNW_PC(info)) {
198 if (i > 50) {
199 printk("\n ");
200 i = 7;
201 } else
202 i += printk(" ");
203 i += printk_address(UNW_PC(info));
204 if (arch_unw_user_mode(info))
205 break;
206 }
207 printk("\n");
208}
209
192/* 210/*
193 * x86-64 can have upto three kernel stacks: 211 * x86-64 can have upto three kernel stacks:
194 * process stack 212 * process stack
@@ -196,15 +214,34 @@ static unsigned long *in_exception_stack(unsigned cpu, unsigned long stack,
196 * severe exception (double fault, nmi, stack fault, debug, mce) hardware stack 214 * severe exception (double fault, nmi, stack fault, debug, mce) hardware stack
197 */ 215 */
198 216
199void show_trace(unsigned long *stack) 217void show_trace(struct task_struct *tsk, struct pt_regs *regs, unsigned long * stack)
200{ 218{
201 const unsigned cpu = safe_smp_processor_id(); 219 const unsigned cpu = safe_smp_processor_id();
202 unsigned long *irqstack_end = (unsigned long *)cpu_pda(cpu)->irqstackptr; 220 unsigned long *irqstack_end = (unsigned long *)cpu_pda(cpu)->irqstackptr;
203 int i; 221 int i;
204 unsigned used = 0; 222 unsigned used = 0;
223 struct unwind_frame_info info;
205 224
206 printk("\nCall Trace:"); 225 printk("\nCall Trace:");
207 226
227 if (!tsk)
228 tsk = current;
229
230 if (regs) {
231 if (unwind_init_frame_info(&info, tsk, regs) == 0) {
232 show_trace_unwind(&info, NULL);
233 return;
234 }
235 } else if (tsk == current) {
236 if (unwind_init_running(&info, show_trace_unwind, NULL) == 0)
237 return;
238 } else {
239 if (unwind_init_blocked(&info, tsk) == 0) {
240 show_trace_unwind(&info, NULL);
241 return;
242 }
243 }
244
208#define HANDLE_STACK(cond) \ 245#define HANDLE_STACK(cond) \
209 do while (cond) { \ 246 do while (cond) { \
210 unsigned long addr = *stack++; \ 247 unsigned long addr = *stack++; \
@@ -262,7 +299,7 @@ void show_trace(unsigned long *stack)
262 printk("\n"); 299 printk("\n");
263} 300}
264 301
265void show_stack(struct task_struct *tsk, unsigned long * rsp) 302static void _show_stack(struct task_struct *tsk, struct pt_regs *regs, unsigned long * rsp)
266{ 303{
267 unsigned long *stack; 304 unsigned long *stack;
268 int i; 305 int i;
@@ -296,7 +333,12 @@ void show_stack(struct task_struct *tsk, unsigned long * rsp)
296 printk("%016lx ", *stack++); 333 printk("%016lx ", *stack++);
297 touch_nmi_watchdog(); 334 touch_nmi_watchdog();
298 } 335 }
299 show_trace((unsigned long *)rsp); 336 show_trace(tsk, regs, rsp);
337}
338
339void show_stack(struct task_struct *tsk, unsigned long * rsp)
340{
341 _show_stack(tsk, NULL, rsp);
300} 342}
301 343
302/* 344/*
@@ -305,7 +347,7 @@ void show_stack(struct task_struct *tsk, unsigned long * rsp)
305void dump_stack(void) 347void dump_stack(void)
306{ 348{
307 unsigned long dummy; 349 unsigned long dummy;
308 show_trace(&dummy); 350 show_trace(NULL, NULL, &dummy);
309} 351}
310 352
311EXPORT_SYMBOL(dump_stack); 353EXPORT_SYMBOL(dump_stack);
@@ -332,7 +374,7 @@ void show_registers(struct pt_regs *regs)
332 if (in_kernel) { 374 if (in_kernel) {
333 375
334 printk("Stack: "); 376 printk("Stack: ");
335 show_stack(NULL, (unsigned long*)rsp); 377 _show_stack(NULL, regs, (unsigned long*)rsp);
336 378
337 printk("\nCode: "); 379 printk("\nCode: ");
338 if (regs->rip < PAGE_OFFSET) 380 if (regs->rip < PAGE_OFFSET)