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
,
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
;
51 trace
->entries
[trace
->nr_entries
++] = addr
;
54 if (trace
->nr_entries
>= trace
->max_entries
)
61 void save_stack_trace(struct stack_trace
*trace
)
63 register unsigned long sp
asm ("15");
64 unsigned long orig_sp
, new_sp
;
66 orig_sp
= sp
& PSW_ADDR_INSN
;
67 new_sp
= save_context_stack(trace
, orig_sp
,
68 S390_lowcore
.panic_stack
- PAGE_SIZE
,
69 S390_lowcore
.panic_stack
);
70 if (new_sp
!= orig_sp
)
72 new_sp
= save_context_stack(trace
, new_sp
,
73 S390_lowcore
.async_stack
- ASYNC_SIZE
,
74 S390_lowcore
.async_stack
);
75 if (new_sp
!= orig_sp
)
77 save_context_stack(trace
, new_sp
,
78 S390_lowcore
.thread_info
,
79 S390_lowcore
.thread_info
+ THREAD_SIZE
);