Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/arch/s390/kernel/dumpstack.c
26489 views
1
// SPDX-License-Identifier: GPL-2.0
2
/*
3
* Stack dumping functions
4
*
5
* Copyright IBM Corp. 1999, 2013
6
*/
7
8
#include <linux/kallsyms.h>
9
#include <linux/hardirq.h>
10
#include <linux/kprobes.h>
11
#include <linux/utsname.h>
12
#include <linux/export.h>
13
#include <linux/kdebug.h>
14
#include <linux/ptrace.h>
15
#include <linux/mm.h>
16
#include <linux/module.h>
17
#include <linux/sched.h>
18
#include <linux/sched/debug.h>
19
#include <linux/sched/task_stack.h>
20
#include <asm/asm-offsets.h>
21
#include <asm/processor.h>
22
#include <asm/debug.h>
23
#include <asm/dis.h>
24
#include <asm/ipl.h>
25
#include <asm/unwind.h>
26
27
const char *stack_type_name(enum stack_type type)
28
{
29
switch (type) {
30
case STACK_TYPE_TASK:
31
return "task";
32
case STACK_TYPE_IRQ:
33
return "irq";
34
case STACK_TYPE_NODAT:
35
return "nodat";
36
case STACK_TYPE_RESTART:
37
return "restart";
38
default:
39
return "unknown";
40
}
41
}
42
EXPORT_SYMBOL_GPL(stack_type_name);
43
44
static inline bool in_stack(unsigned long sp, struct stack_info *info,
45
enum stack_type type, unsigned long stack)
46
{
47
if (sp < stack || sp >= stack + THREAD_SIZE)
48
return false;
49
info->type = type;
50
info->begin = stack;
51
info->end = stack + THREAD_SIZE;
52
return true;
53
}
54
55
static bool in_task_stack(unsigned long sp, struct task_struct *task,
56
struct stack_info *info)
57
{
58
unsigned long stack = (unsigned long)task_stack_page(task);
59
60
return in_stack(sp, info, STACK_TYPE_TASK, stack);
61
}
62
63
static bool in_irq_stack(unsigned long sp, struct stack_info *info)
64
{
65
unsigned long stack = get_lowcore()->async_stack - STACK_INIT_OFFSET;
66
67
return in_stack(sp, info, STACK_TYPE_IRQ, stack);
68
}
69
70
static bool in_nodat_stack(unsigned long sp, struct stack_info *info)
71
{
72
unsigned long stack = get_lowcore()->nodat_stack - STACK_INIT_OFFSET;
73
74
return in_stack(sp, info, STACK_TYPE_NODAT, stack);
75
}
76
77
static bool in_mcck_stack(unsigned long sp, struct stack_info *info)
78
{
79
unsigned long stack = get_lowcore()->mcck_stack - STACK_INIT_OFFSET;
80
81
return in_stack(sp, info, STACK_TYPE_MCCK, stack);
82
}
83
84
static bool in_restart_stack(unsigned long sp, struct stack_info *info)
85
{
86
unsigned long stack = get_lowcore()->restart_stack - STACK_INIT_OFFSET;
87
88
return in_stack(sp, info, STACK_TYPE_RESTART, stack);
89
}
90
91
int get_stack_info(unsigned long sp, struct task_struct *task,
92
struct stack_info *info, unsigned long *visit_mask)
93
{
94
if (!sp)
95
goto unknown;
96
97
/* Sanity check: ABI requires SP to be aligned 8 bytes. */
98
if (sp & 0x7)
99
goto unknown;
100
101
/* Check per-task stack */
102
if (in_task_stack(sp, task, info))
103
goto recursion_check;
104
105
if (task != current)
106
goto unknown;
107
108
/* Check per-cpu stacks */
109
if (!in_irq_stack(sp, info) &&
110
!in_nodat_stack(sp, info) &&
111
!in_restart_stack(sp, info) &&
112
!in_mcck_stack(sp, info))
113
goto unknown;
114
115
recursion_check:
116
/*
117
* Make sure we don't iterate through any given stack more than once.
118
* If it comes up a second time then there's something wrong going on:
119
* just break out and report an unknown stack type.
120
*/
121
if (*visit_mask & (1UL << info->type))
122
goto unknown;
123
*visit_mask |= 1UL << info->type;
124
return 0;
125
unknown:
126
info->type = STACK_TYPE_UNKNOWN;
127
return -EINVAL;
128
}
129
130
void show_stack(struct task_struct *task, unsigned long *stack,
131
const char *loglvl)
132
{
133
struct unwind_state state;
134
135
printk("%sCall Trace:\n", loglvl);
136
unwind_for_each_frame(&state, task, NULL, (unsigned long) stack)
137
printk(state.reliable ? "%s [<%016lx>] %pSR \n" :
138
"%s([<%016lx>] %pSR)\n",
139
loglvl, state.ip, (void *) state.ip);
140
debug_show_held_locks(task ? : current);
141
}
142
143
static void show_last_breaking_event(struct pt_regs *regs)
144
{
145
printk("Last Breaking-Event-Address:\n");
146
printk(" [<%016lx>] ", regs->last_break);
147
if (user_mode(regs)) {
148
print_vma_addr(KERN_CONT, regs->last_break);
149
pr_cont("\n");
150
} else {
151
pr_cont("%pSR\n", (void *)regs->last_break);
152
}
153
}
154
155
void show_registers(struct pt_regs *regs)
156
{
157
struct psw_bits *psw = &psw_bits(regs->psw);
158
char *mode;
159
160
mode = user_mode(regs) ? "User" : "Krnl";
161
printk("%s PSW : %px %px", mode, (void *)regs->psw.mask, (void *)regs->psw.addr);
162
if (!user_mode(regs))
163
pr_cont(" (%pSR)", (void *)regs->psw.addr);
164
pr_cont("\n");
165
printk(" R:%x T:%x IO:%x EX:%x Key:%x M:%x W:%x "
166
"P:%x AS:%x CC:%x PM:%x", psw->per, psw->dat, psw->io, psw->ext,
167
psw->key, psw->mcheck, psw->wait, psw->pstate, psw->as, psw->cc, psw->pm);
168
pr_cont(" RI:%x EA:%x\n", psw->ri, psw->eaba);
169
printk("%s GPRS: %016lx %016lx %016lx %016lx\n", mode,
170
regs->gprs[0], regs->gprs[1], regs->gprs[2], regs->gprs[3]);
171
printk(" %016lx %016lx %016lx %016lx\n",
172
regs->gprs[4], regs->gprs[5], regs->gprs[6], regs->gprs[7]);
173
printk(" %016lx %016lx %016lx %016lx\n",
174
regs->gprs[8], regs->gprs[9], regs->gprs[10], regs->gprs[11]);
175
printk(" %016lx %016lx %016lx %016lx\n",
176
regs->gprs[12], regs->gprs[13], regs->gprs[14], regs->gprs[15]);
177
show_code(regs);
178
}
179
180
void show_regs(struct pt_regs *regs)
181
{
182
show_regs_print_info(KERN_DEFAULT);
183
show_registers(regs);
184
/* Show stack backtrace if pt_regs is from kernel mode */
185
if (!user_mode(regs))
186
show_stack(NULL, (unsigned long *) regs->gprs[15], KERN_DEFAULT);
187
show_last_breaking_event(regs);
188
}
189
190
static DEFINE_SPINLOCK(die_lock);
191
192
void __noreturn die(struct pt_regs *regs, const char *str)
193
{
194
static int die_counter;
195
196
oops_enter();
197
lgr_info_log();
198
debug_stop_all();
199
console_verbose();
200
spin_lock_irq(&die_lock);
201
bust_spinlocks(1);
202
printk("%s: %04x ilc:%d [#%d]", str, regs->int_code & 0xffff,
203
regs->int_code >> 17, ++die_counter);
204
pr_cont("SMP ");
205
if (debug_pagealloc_enabled())
206
pr_cont("DEBUG_PAGEALLOC");
207
pr_cont("\n");
208
notify_die(DIE_OOPS, str, regs, 0, regs->int_code & 0xffff, SIGSEGV);
209
print_modules();
210
show_regs(regs);
211
bust_spinlocks(0);
212
add_taint(TAINT_DIE, LOCKDEP_NOW_UNRELIABLE);
213
spin_unlock_irq(&die_lock);
214
if (in_interrupt())
215
panic("Fatal exception in interrupt");
216
if (panic_on_oops)
217
panic("Fatal exception: panic_on_oops");
218
oops_exit();
219
make_task_dead(SIGSEGV);
220
}
221
222