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
;
52 trace
->entries
[trace
->nr_entries
++] = addr
;
55 if (trace
->nr_entries
>= trace
->max_entries
)
62 void save_stack_trace(struct stack_trace
*trace
)
64 register unsigned long sp
asm ("15");
65 unsigned long orig_sp
, new_sp
;
67 orig_sp
= sp
& PSW_ADDR_INSN
;
69 new_sp
= save_context_stack(trace
, &trace
->skip
, orig_sp
,
70 S390_lowcore
.panic_stack
- PAGE_SIZE
,
71 S390_lowcore
.panic_stack
);
72 if (new_sp
!= orig_sp
)
74 new_sp
= save_context_stack(trace
, &trace
->skip
, new_sp
,
75 S390_lowcore
.async_stack
- ASYNC_SIZE
,
76 S390_lowcore
.async_stack
);
77 if (new_sp
!= orig_sp
)
80 save_context_stack(trace
, &trace
->skip
, new_sp
,
81 S390_lowcore
.thread_info
,
82 S390_lowcore
.thread_info
+ THREAD_SIZE
);