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>
13 #include <linux/module.h>
15 static unsigned long save_context_stack(struct stack_trace
*trace
,
21 struct stack_frame
*sf
;
27 if (sp
< low
|| sp
> high
)
29 sf
= (struct stack_frame
*)sp
;
31 addr
= sf
->gprs
[8] & PSW_ADDR_INSN
;
33 trace
->entries
[trace
->nr_entries
++] = addr
;
36 if (trace
->nr_entries
>= trace
->max_entries
)
39 sp
= sf
->back_chain
& PSW_ADDR_INSN
;
42 if (sp
<= low
|| sp
> high
- sizeof(*sf
))
44 sf
= (struct stack_frame
*)sp
;
46 /* Zero backchain detected, check for interrupt frame. */
47 sp
= (unsigned long)(sf
+ 1);
48 if (sp
<= low
|| sp
> high
- sizeof(*regs
))
50 regs
= (struct pt_regs
*)sp
;
51 addr
= regs
->psw
.addr
& PSW_ADDR_INSN
;
52 if (savesched
|| !in_sched_functions(addr
)) {
54 trace
->entries
[trace
->nr_entries
++] = addr
;
58 if (trace
->nr_entries
>= trace
->max_entries
)
65 void save_stack_trace(struct stack_trace
*trace
)
67 register unsigned long sp
asm ("15");
68 unsigned long orig_sp
, new_sp
;
70 orig_sp
= sp
& PSW_ADDR_INSN
;
71 new_sp
= save_context_stack(trace
, orig_sp
,
72 S390_lowcore
.panic_stack
- PAGE_SIZE
,
73 S390_lowcore
.panic_stack
, 1);
74 if (new_sp
!= orig_sp
)
76 new_sp
= save_context_stack(trace
, new_sp
,
77 S390_lowcore
.async_stack
- ASYNC_SIZE
,
78 S390_lowcore
.async_stack
, 1);
79 if (new_sp
!= orig_sp
)
81 save_context_stack(trace
, new_sp
,
82 S390_lowcore
.thread_info
,
83 S390_lowcore
.thread_info
+ THREAD_SIZE
, 1);
85 EXPORT_SYMBOL_GPL(save_stack_trace
);
87 void save_stack_trace_tsk(struct task_struct
*tsk
, struct stack_trace
*trace
)
89 unsigned long sp
, low
, high
;
91 sp
= tsk
->thread
.ksp
& PSW_ADDR_INSN
;
92 low
= (unsigned long) task_stack_page(tsk
);
93 high
= (unsigned long) task_pt_regs(tsk
);
94 save_context_stack(trace
, sp
, low
, high
, 0);
95 if (trace
->nr_entries
< trace
->max_entries
)
96 trace
->entries
[trace
->nr_entries
++] = ULONG_MAX
;
98 EXPORT_SYMBOL_GPL(save_stack_trace_tsk
);