aboutsummaryrefslogtreecommitdiffstats
path: root/arch/xtensa/kernel
diff options
context:
space:
mode:
authorJohannes Weiner <jw@emlix.com>2009-05-11 09:43:33 -0400
committerChris Zankel <chris@zankel.net>2009-05-12 00:59:43 -0400
commit586411dcd1935f91796d5e8a29aa3cfdf01a01f4 (patch)
treefac1b05ad8c5a708080251b17d4a3fc0b9018c4f /arch/xtensa/kernel
parent7dbe5c542464a511f0ea6a14e3ff08874d7e21d5 (diff)
xtensa: always use correct stack pointer for stack traces
Commit '28a0ce7 xtensa: use correct stack pointer for stack traces' changed the stack tracer from always reading the stack pointer register to always using the saved value in the task descriptor. The author was too dense to consider the fact that the saved stack value is stale for a running process und thus unusable for 'current'. What we do now is to use the stack pointer register (a1) for when the task is unknown - we can't help it then - or when the task is 'current'. For everything else use the saved stack pointer value contained in the task descriptor. Signed-off-by: Johannes Weiner <jw@emlix.com> Signed-off-by: Chris Zankel <chris@zankel.net>
Diffstat (limited to 'arch/xtensa/kernel')
-rw-r--r--arch/xtensa/kernel/traps.c16
1 files changed, 14 insertions, 2 deletions
diff --git a/arch/xtensa/kernel/traps.c b/arch/xtensa/kernel/traps.c
index 9f0b71189e94..ba9ab9349782 100644
--- a/arch/xtensa/kernel/traps.c
+++ b/arch/xtensa/kernel/traps.c
@@ -369,6 +369,18 @@ void show_regs(struct pt_regs * regs)
369 regs->syscall); 369 regs->syscall);
370} 370}
371 371
372static __always_inline unsigned long *stack_pointer(struct task_struct *task)
373{
374 unsigned long *sp;
375
376 if (!task || task == current)
377 __asm__ __volatile__ ("mov %0, a1\n" : "=a"(sp));
378 else
379 sp = (unsigned long *)task->thread.sp;
380
381 return sp;
382}
383
372void show_trace(struct task_struct *task, unsigned long *sp) 384void show_trace(struct task_struct *task, unsigned long *sp)
373{ 385{
374 unsigned long a0, a1, pc; 386 unsigned long a0, a1, pc;
@@ -377,7 +389,7 @@ void show_trace(struct task_struct *task, unsigned long *sp)
377 if (sp) 389 if (sp)
378 a1 = (unsigned long)sp; 390 a1 = (unsigned long)sp;
379 else 391 else
380 a1 = task->thread.sp; 392 a1 = (unsigned long)stack_pointer(task);
381 393
382 sp_start = a1 & ~(THREAD_SIZE-1); 394 sp_start = a1 & ~(THREAD_SIZE-1);
383 sp_end = sp_start + THREAD_SIZE; 395 sp_end = sp_start + THREAD_SIZE;
@@ -420,7 +432,7 @@ void show_stack(struct task_struct *task, unsigned long *sp)
420 unsigned long *stack; 432 unsigned long *stack;
421 433
422 if (!sp) 434 if (!sp)
423 sp = (unsigned long *)task->thread.sp; 435 sp = stack_pointer(task);
424 stack = sp; 436 stack = sp;
425 437
426 printk("\nStack: "); 438 printk("\nStack: ");