2 * Stack trace management functions
4 * Copyright IBM Corp. 2006
5 * Author(s): Heiko Carstens <heiko.carstens@de.ibm.com>
8 #include <linux/sched.h>
9 #include <linux/stacktrace.h>
10 #include <linux/kallsyms.h>
11 #include <linux/module.h>
13 static unsigned long save_context_stack(struct stack_trace
*trace
,
19 struct stack_frame
*sf
;
25 if (sp
< low
|| sp
> high
)
27 sf
= (struct stack_frame
*)sp
;
29 addr
= sf
->gprs
[8] & PSW_ADDR_INSN
;
31 trace
->entries
[trace
->nr_entries
++] = addr
;
34 if (trace
->nr_entries
>= trace
->max_entries
)
37 sp
= sf
->back_chain
& PSW_ADDR_INSN
;
40 if (sp
<= low
|| sp
> high
- sizeof(*sf
))
42 sf
= (struct stack_frame
*)sp
;
44 /* Zero backchain detected, check for interrupt frame. */
45 sp
= (unsigned long)(sf
+ 1);
46 if (sp
<= low
|| sp
> high
- sizeof(*regs
))
48 regs
= (struct pt_regs
*)sp
;
49 addr
= regs
->psw
.addr
& PSW_ADDR_INSN
;
50 if (savesched
|| !in_sched_functions(addr
)) {
52 trace
->entries
[trace
->nr_entries
++] = addr
;
56 if (trace
->nr_entries
>= trace
->max_entries
)
63 void save_stack_trace(struct stack_trace
*trace
)
65 register unsigned long sp
asm ("15");
66 unsigned long orig_sp
, new_sp
;
68 orig_sp
= sp
& PSW_ADDR_INSN
;
69 new_sp
= save_context_stack(trace
, orig_sp
,
70 S390_lowcore
.panic_stack
- PAGE_SIZE
,
71 S390_lowcore
.panic_stack
, 1);
72 if (new_sp
!= orig_sp
)
74 new_sp
= save_context_stack(trace
, new_sp
,
75 S390_lowcore
.async_stack
- ASYNC_SIZE
,
76 S390_lowcore
.async_stack
, 1);
77 if (new_sp
!= orig_sp
)
79 save_context_stack(trace
, new_sp
,
80 S390_lowcore
.thread_info
,
81 S390_lowcore
.thread_info
+ THREAD_SIZE
, 1);
83 EXPORT_SYMBOL_GPL(save_stack_trace
);
85 void save_stack_trace_tsk(struct task_struct
*tsk
, struct stack_trace
*trace
)
87 unsigned long sp
, low
, high
;
89 sp
= tsk
->thread
.ksp
& PSW_ADDR_INSN
;
90 low
= (unsigned long) task_stack_page(tsk
);
91 high
= (unsigned long) task_pt_regs(tsk
);
92 save_context_stack(trace
, sp
, low
, high
, 0);
93 if (trace
->nr_entries
< trace
->max_entries
)
94 trace
->entries
[trace
->nr_entries
++] = ULONG_MAX
;
96 EXPORT_SYMBOL_GPL(save_stack_trace_tsk
);