diff options
author | Johannes Weiner <jw@emlix.com> | 2009-05-11 09:43:33 -0400 |
---|---|---|
committer | Chris Zankel <chris@zankel.net> | 2009-05-12 00:59:43 -0400 |
commit | 586411dcd1935f91796d5e8a29aa3cfdf01a01f4 (patch) | |
tree | fac1b05ad8c5a708080251b17d4a3fc0b9018c4f /arch/xtensa | |
parent | 7dbe5c542464a511f0ea6a14e3ff08874d7e21d5 (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')
-rw-r--r-- | arch/xtensa/kernel/traps.c | 16 |
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 | ||
372 | static __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 | |||
372 | void show_trace(struct task_struct *task, unsigned long *sp) | 384 | void 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: "); |