summaryrefslogtreecommitdiffstats
path: root/arch/csky/kernel/process.c
diff options
context:
space:
mode:
authorGuo Ren <ren_guo@c-sky.com>2018-12-09 14:18:05 +0800
committerGuo Ren <ren_guo@c-sky.com>2018-12-31 23:12:22 +0800
commit0ea2dc7cd668be5475babecaf6fdeaa464e2847b (patch)
tree733fef9d2126b7323d4ec80e62e0c3ea583e01f7 /arch/csky/kernel/process.c
parent859e5f45cbb33fe5d591a8e429667f0b7d4f4be8 (diff)
downloadlinux-stable-0ea2dc7cd668be5475babecaf6fdeaa464e2847b.tar.gz
linux-stable-0ea2dc7cd668be5475babecaf6fdeaa464e2847b.tar.bz2
linux-stable-0ea2dc7cd668be5475babecaf6fdeaa464e2847b.zip
csky: stacktrace supported.
The gcc option "-mbacktrace" will push fp(r8),lr into stack and we could unwind the stack with: fp = *fp lr = (unsigned int *)fp[1] Signed-off-by: Guo Ren <ren_guo@c-sky.com>
Diffstat (limited to 'arch/csky/kernel/process.c')
-rw-r--r--arch/csky/kernel/process.c29
1 files changed, 17 insertions, 12 deletions
diff --git a/arch/csky/kernel/process.c b/arch/csky/kernel/process.c
index 8ed20028b160..e555740c0be5 100644
--- a/arch/csky/kernel/process.c
+++ b/arch/csky/kernel/process.c
@@ -93,26 +93,31 @@ int dump_task_regs(struct task_struct *tsk, elf_gregset_t *pr_regs)
unsigned long get_wchan(struct task_struct *p)
{
- unsigned long esp, pc;
- unsigned long stack_page;
+ unsigned long lr;
+ unsigned long *fp, *stack_start, *stack_end;
int count = 0;
if (!p || p == current || p->state == TASK_RUNNING)
return 0;
- stack_page = (unsigned long)p;
- esp = p->thread.esp0;
+ stack_start = (unsigned long *)end_of_stack(p);
+ stack_end = (unsigned long *)(task_stack_page(p) + THREAD_SIZE);
+
+ fp = (unsigned long *) thread_saved_fp(p);
do {
- if (esp < stack_page+sizeof(struct task_struct) ||
- esp >= 8184+stack_page)
+ if (fp < stack_start || fp > stack_end)
return 0;
- /*FIXME: There's may be error here!*/
- pc = ((unsigned long *)esp)[1];
- /* FIXME: This depends on the order of these functions. */
- if (!in_sched_functions(pc))
- return pc;
- esp = *(unsigned long *) esp;
+#ifdef CONFIG_STACKTRACE
+ lr = fp[1];
+ fp = (unsigned long *)fp[0];
+#else
+ lr = *fp++;
+#endif
+ if (!in_sched_functions(lr) &&
+ __kernel_text_address(lr))
+ return lr;
} while (count++ < 16);
+
return 0;
}
EXPORT_SYMBOL(get_wchan);