2 * arch/s390/kernel/stacktrace.c
4 * Stack trace management functions
6 * Copyright (C) IBM Corp. 2006
7 * Author(s): Heiko Carstens <heiko.carstens@de.ibm.com>
10 #include <linux/sched.h>
11 #include <linux/stacktrace.h>
12 #include <linux/kallsyms.h>
14 static unsigned long save_context_stack(struct stack_trace
*trace
,
20 struct stack_frame
*sf
;
26 if (sp
< low
|| sp
> high
)
28 sf
= (struct stack_frame
*)sp
;
30 addr
= sf
->gprs
[8] & PSW_ADDR_INSN
;
32 trace
->entries
[trace
->nr_entries
++] = addr
;
35 if (trace
->nr_entries
>= trace
->max_entries
)
38 sp
= sf
->back_chain
& PSW_ADDR_INSN
;
41 if (sp
<= low
|| sp
> high
- sizeof(*sf
))
43 sf
= (struct stack_frame
*)sp
;
45 /* Zero backchain detected, check for interrupt frame. */
46 sp
= (unsigned long)(sf
+ 1);
47 if (sp
<= low
|| sp
> high
- sizeof(*regs
))
49 regs
= (struct pt_regs
*)sp
;
50 addr
= regs
->psw
.addr
& PSW_ADDR_INSN
;
51 if (savesched
|| !in_sched_functions(addr
)) {
53 trace
->entries
[trace
->nr_entries
++] = addr
;
57 if (trace
->nr_entries
>= trace
->max_entries
)
64 void save_stack_trace(struct stack_trace
*trace
)
66 register unsigned long sp
asm ("15");
67 unsigned long orig_sp
, new_sp
;
69 orig_sp
= sp
& PSW_ADDR_INSN
;
70 new_sp
= save_context_stack(trace
, orig_sp
,
71 S390_lowcore
.panic_stack
- PAGE_SIZE
,
72 S390_lowcore
.panic_stack
, 1);
73 if (new_sp
!= orig_sp
)
75 new_sp
= save_context_stack(trace
, new_sp
,
76 S390_lowcore
.async_stack
- ASYNC_SIZE
,
77 S390_lowcore
.async_stack
, 1);
78 if (new_sp
!= orig_sp
)
80 save_context_stack(trace
, new_sp
,
81 S390_lowcore
.thread_info
,
82 S390_lowcore
.thread_info
+ THREAD_SIZE
, 1);
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
;