2 * arch/mips/kernel/stacktrace.c
4 * Stack trace management functions
6 * Copyright (C) 2006 Atsushi Nemoto <anemo@mba.ocn.ne.jp>
8 #include <linux/sched.h>
9 #include <linux/stacktrace.h>
10 #include <asm/stacktrace.h>
13 * Save stack-backtrace addresses into a stack_trace buffer:
15 static void save_raw_context_stack(struct stack_trace
*trace
,
18 unsigned long *sp
= (unsigned long *)reg29
;
21 while (!kstack_end(sp
)) {
23 if (__kernel_text_address(addr
)) {
27 trace
->entries
[trace
->nr_entries
++] = addr
;
28 if (trace
->nr_entries
>= trace
->max_entries
)
34 static void save_context_stack(struct stack_trace
*trace
,
35 struct task_struct
*task
, struct pt_regs
*regs
)
37 unsigned long sp
= regs
->regs
[29];
38 #ifdef CONFIG_KALLSYMS
39 unsigned long ra
= regs
->regs
[31];
40 unsigned long pc
= regs
->cp0_epc
;
42 if (raw_show_trace
|| !__kernel_text_address(pc
)) {
43 unsigned long stack_page
=
44 (unsigned long)task_stack_page(task
);
45 if (stack_page
&& sp
>= stack_page
&&
46 sp
<= stack_page
+ THREAD_SIZE
- 32)
47 save_raw_context_stack(trace
, sp
);
54 trace
->entries
[trace
->nr_entries
++] = pc
;
55 if (trace
->nr_entries
>= trace
->max_entries
)
57 pc
= unwind_stack(task
, &sp
, pc
, &ra
);
60 save_raw_context_stack(trace
, sp
);
65 * Save stack-backtrace addresses into a stack_trace buffer.
67 void save_stack_trace(struct stack_trace
*trace
, struct task_struct
*task
)
69 struct pt_regs dummyregs
;
70 struct pt_regs
*regs
= &dummyregs
;
72 WARN_ON(trace
->nr_entries
|| !trace
->max_entries
);
74 if (task
&& task
!= current
) {
75 regs
->regs
[29] = task
->thread
.reg29
;
77 regs
->cp0_epc
= task
->thread
.reg31
;
81 prepare_frametrace(regs
);
84 save_context_stack(trace
, task
, regs
);