Blame view

arch/x86/kernel/dumpstack_64.c 7.35 KB
6fcbede3f   Alexander van Heukelum   x86_64: split out...
1
2
3
4
5
6
7
  /*
   *  Copyright (C) 1991, 1992  Linus Torvalds
   *  Copyright (C) 2000, 2001, 2002 Andi Kleen, SuSE Labs
   */
  #include <linux/kallsyms.h>
  #include <linux/kprobes.h>
  #include <linux/uaccess.h>
6fcbede3f   Alexander van Heukelum   x86_64: split out...
8
9
10
11
12
  #include <linux/hardirq.h>
  #include <linux/kdebug.h>
  #include <linux/module.h>
  #include <linux/ptrace.h>
  #include <linux/kexec.h>
b80309061   Ingo Molnar   x86: dumpstack: C...
13
  #include <linux/sysfs.h>
6fcbede3f   Alexander van Heukelum   x86_64: split out...
14
15
16
17
  #include <linux/bug.h>
  #include <linux/nmi.h>
  
  #include <asm/stacktrace.h>
6fcbede3f   Alexander van Heukelum   x86_64: split out...
18

b80309061   Ingo Molnar   x86: dumpstack: C...
19
20
  #define N_EXCEPTION_STACKS_END \
  		(N_EXCEPTION_STACKS + DEBUG_STKSZ/EXCEPTION_STKSZ - 2)
0406ca6d8   Frederic Weisbecker   perf_counter: Ign...
21
22
  
  static char x86_stack_ids[][8] = {
b80309061   Ingo Molnar   x86: dumpstack: C...
23
24
25
26
27
  		[ DEBUG_STACK-1			]	= "#DB",
  		[ NMI_STACK-1			]	= "NMI",
  		[ DOUBLEFAULT_STACK-1		]	= "#DF",
  		[ STACKFAULT_STACK-1		]	= "#SS",
  		[ MCE_STACK-1			]	= "#MC",
6fcbede3f   Alexander van Heukelum   x86_64: split out...
28
  #if DEBUG_STKSZ > EXCEPTION_STKSZ
b80309061   Ingo Molnar   x86: dumpstack: C...
29
30
  		[ N_EXCEPTION_STACKS ...
  		  N_EXCEPTION_STACKS_END	]	= "#DB[?]"
6fcbede3f   Alexander van Heukelum   x86_64: split out...
31
  #endif
b80309061   Ingo Molnar   x86: dumpstack: C...
32
  };
0406ca6d8   Frederic Weisbecker   perf_counter: Ign...
33

0406ca6d8   Frederic Weisbecker   perf_counter: Ign...
34
  static unsigned long *in_exception_stack(unsigned cpu, unsigned long stack,
b80309061   Ingo Molnar   x86: dumpstack: C...
35
  					 unsigned *usedp, char **idp)
0406ca6d8   Frederic Weisbecker   perf_counter: Ign...
36
  {
6fcbede3f   Alexander van Heukelum   x86_64: split out...
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
  	unsigned k;
  
  	/*
  	 * Iterate over all exception stacks, and figure out whether
  	 * 'stack' is in one of them:
  	 */
  	for (k = 0; k < N_EXCEPTION_STACKS; k++) {
  		unsigned long end = per_cpu(orig_ist, cpu).ist[k];
  		/*
  		 * Is 'stack' above this exception frame's end?
  		 * If yes then skip to the next frame.
  		 */
  		if (stack >= end)
  			continue;
  		/*
  		 * Is 'stack' above this exception frame's start address?
  		 * If yes then we found the right frame.
  		 */
  		if (stack >= end - EXCEPTION_STKSZ) {
  			/*
  			 * Make sure we only iterate through an exception
  			 * stack once. If it comes up for the second time
  			 * then there's something wrong going on - just
  			 * break out and return NULL:
  			 */
  			if (*usedp & (1U << k))
  				break;
  			*usedp |= 1U << k;
0406ca6d8   Frederic Weisbecker   perf_counter: Ign...
65
  			*idp = x86_stack_ids[k];
6fcbede3f   Alexander van Heukelum   x86_64: split out...
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
  			return (unsigned long *)end;
  		}
  		/*
  		 * If this is a debug stack, and if it has a larger size than
  		 * the usual exception stacks, then 'stack' might still
  		 * be within the lower portion of the debug stack:
  		 */
  #if DEBUG_STKSZ > EXCEPTION_STKSZ
  		if (k == DEBUG_STACK - 1 && stack >= end - DEBUG_STKSZ) {
  			unsigned j = N_EXCEPTION_STACKS - 1;
  
  			/*
  			 * Black magic. A large debug stack is composed of
  			 * multiple exception stack entries, which we
  			 * iterate through now. Dont look:
  			 */
  			do {
  				++j;
  				end -= EXCEPTION_STKSZ;
0406ca6d8   Frederic Weisbecker   perf_counter: Ign...
85
86
  				x86_stack_ids[j][4] = '1' +
  						(j - N_EXCEPTION_STACKS);
6fcbede3f   Alexander van Heukelum   x86_64: split out...
87
88
89
90
  			} while (stack < end - EXCEPTION_STKSZ);
  			if (*usedp & (1U << j))
  				break;
  			*usedp |= 1U << j;
0406ca6d8   Frederic Weisbecker   perf_counter: Ign...
91
  			*idp = x86_stack_ids[j];
6fcbede3f   Alexander van Heukelum   x86_64: split out...
92
93
94
95
96
97
  			return (unsigned long *)end;
  		}
  #endif
  	}
  	return NULL;
  }
af2d8289f   Frederic Weisbecker   x86: Fixup wrong ...
98
99
100
101
102
103
104
105
  static inline int
  in_irq_stack(unsigned long *stack, unsigned long *irq_stack,
  	     unsigned long *irq_stack_end)
  {
  	return (stack >= irq_stack && stack < irq_stack_end);
  }
  
  /*
6fcbede3f   Alexander van Heukelum   x86_64: split out...
106
107
108
109
110
   * x86-64 can have up to three kernel stacks:
   * process stack
   * interrupt stack
   * severe exception (double fault, nmi, stack fault, debug, mce) hardware stack
   */
e8e999cf3   Namhyung Kim   x86, dumpstack: C...
111
112
  void dump_trace(struct task_struct *task, struct pt_regs *regs,
  		unsigned long *stack, unsigned long bp,
6fcbede3f   Alexander van Heukelum   x86_64: split out...
113
114
115
  		const struct stacktrace_ops *ops, void *data)
  {
  	const unsigned cpu = get_cpu();
26f80bd6a   Brian Gerst   x86-64: Convert i...
116
117
  	unsigned long *irq_stack_end =
  		(unsigned long *)per_cpu(irq_stack_ptr, cpu);
6fcbede3f   Alexander van Heukelum   x86_64: split out...
118
119
  	unsigned used = 0;
  	struct thread_info *tinfo;
7ee991fbc   Steven Rostedt   ftrace: print rea...
120
  	int graph = 0;
2e5aa6824   Jesper Juhl   x86-64: Don't use...
121
  	unsigned long dummy;
6fcbede3f   Alexander van Heukelum   x86_64: split out...
122
123
124
125
126
  
  	if (!task)
  		task = current;
  
  	if (!stack) {
47ce11a2b   Frederic Weisbecker   x86: Fetch stack ...
127
128
129
  		if (regs)
  			stack = (unsigned long *)regs->sp;
  		else if (task && task != current)
6fcbede3f   Alexander van Heukelum   x86_64: split out...
130
  			stack = (unsigned long *)task->thread.sp;
47ce11a2b   Frederic Weisbecker   x86: Fetch stack ...
131
132
  		else
  			stack = &dummy;
6fcbede3f   Alexander van Heukelum   x86_64: split out...
133
  	}
e8e999cf3   Namhyung Kim   x86, dumpstack: C...
134
135
  	if (!bp)
  		bp = stack_frame(task, regs);
6fcbede3f   Alexander van Heukelum   x86_64: split out...
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
  	/*
  	 * Print function call entries in all stacks, starting at the
  	 * current stack address. If the stacks consist of nested
  	 * exceptions
  	 */
  	tinfo = task_thread_info(task);
  	for (;;) {
  		char *id;
  		unsigned long *estack_end;
  		estack_end = in_exception_stack(cpu, (unsigned long)stack,
  						&used, &id);
  
  		if (estack_end) {
  			if (ops->stack(data, id) < 0)
  				break;
61c1917f4   Frederic Weisbecker   perf events, x86/...
151
152
  			bp = ops->walk_stack(tinfo, stack, bp, ops,
  					     data, estack_end, &graph);
6fcbede3f   Alexander van Heukelum   x86_64: split out...
153
154
155
156
157
158
159
160
161
  			ops->stack(data, "<EOE>");
  			/*
  			 * We link to the next stack via the
  			 * second-to-last pointer (index -2 to end) in the
  			 * exception stack:
  			 */
  			stack = (unsigned long *) estack_end[-2];
  			continue;
  		}
26f80bd6a   Brian Gerst   x86-64: Convert i...
162
163
164
165
  		if (irq_stack_end) {
  			unsigned long *irq_stack;
  			irq_stack = irq_stack_end -
  				(IRQ_STACK_SIZE - 64) / sizeof(*irq_stack);
6fcbede3f   Alexander van Heukelum   x86_64: split out...
166

af2d8289f   Frederic Weisbecker   x86: Fixup wrong ...
167
  			if (in_irq_stack(stack, irq_stack, irq_stack_end)) {
6fcbede3f   Alexander van Heukelum   x86_64: split out...
168
169
  				if (ops->stack(data, "IRQ") < 0)
  					break;
61e67fb9d   Frederic Weisbecker   perf/x86-64: Use ...
170
  				bp = ops->walk_stack(tinfo, stack, bp,
26f80bd6a   Brian Gerst   x86-64: Convert i...
171
  					ops, data, irq_stack_end, &graph);
6fcbede3f   Alexander van Heukelum   x86_64: split out...
172
173
174
175
176
  				/*
  				 * We link to the next stack (which would be
  				 * the process stack normally) the last
  				 * pointer (index -1 to end) in the IRQ stack:
  				 */
26f80bd6a   Brian Gerst   x86-64: Convert i...
177
178
  				stack = (unsigned long *) (irq_stack_end[-1]);
  				irq_stack_end = NULL;
6fcbede3f   Alexander van Heukelum   x86_64: split out...
179
180
181
182
183
184
185
186
187
188
  				ops->stack(data, "EOI");
  				continue;
  			}
  		}
  		break;
  	}
  
  	/*
  	 * This handles the process stack:
  	 */
61e67fb9d   Frederic Weisbecker   perf/x86-64: Use ...
189
  	bp = ops->walk_stack(tinfo, stack, bp, ops, data, NULL, &graph);
6fcbede3f   Alexander van Heukelum   x86_64: split out...
190
191
192
  	put_cpu();
  }
  EXPORT_SYMBOL(dump_trace);
878719e83   Neil Horman   x86: unify approp...
193
  void
6fcbede3f   Alexander van Heukelum   x86_64: split out...
194
  show_stack_log_lvl(struct task_struct *task, struct pt_regs *regs,
e8e999cf3   Namhyung Kim   x86, dumpstack: C...
195
  		   unsigned long *sp, unsigned long bp, char *log_lvl)
6fcbede3f   Alexander van Heukelum   x86_64: split out...
196
  {
67f2de0bf   Ingo Molnar   x86: dumpstack, 6...
197
198
  	unsigned long *irq_stack_end;
  	unsigned long *irq_stack;
6fcbede3f   Alexander van Heukelum   x86_64: split out...
199
  	unsigned long *stack;
67f2de0bf   Ingo Molnar   x86: dumpstack, 6...
200
  	int cpu;
6fcbede3f   Alexander van Heukelum   x86_64: split out...
201
  	int i;
67f2de0bf   Ingo Molnar   x86: dumpstack, 6...
202
203
204
205
206
207
  
  	preempt_disable();
  	cpu = smp_processor_id();
  
  	irq_stack_end	= (unsigned long *)(per_cpu(irq_stack_ptr, cpu));
  	irq_stack	= (unsigned long *)(per_cpu(irq_stack_ptr, cpu) - IRQ_STACK_SIZE);
6fcbede3f   Alexander van Heukelum   x86_64: split out...
208
209
  
  	/*
67f2de0bf   Ingo Molnar   x86: dumpstack, 6...
210
211
  	 * Debugging aid: "show_stack(NULL, NULL);" prints the
  	 * back trace for this cpu:
6fcbede3f   Alexander van Heukelum   x86_64: split out...
212
  	 */
6fcbede3f   Alexander van Heukelum   x86_64: split out...
213
214
215
216
217
218
219
220
221
  	if (sp == NULL) {
  		if (task)
  			sp = (unsigned long *)task->thread.sp;
  		else
  			sp = (unsigned long *)&sp;
  	}
  
  	stack = sp;
  	for (i = 0; i < kstack_depth_to_print; i++) {
26f80bd6a   Brian Gerst   x86-64: Convert i...
222
223
224
  		if (stack >= irq_stack && stack <= irq_stack_end) {
  			if (stack == irq_stack_end) {
  				stack = (unsigned long *) (irq_stack_end[-1]);
e4072a9a9   Jiri Slaby   x86, printk: Get ...
225
  				printk(KERN_CONT " <EOI> ");
6fcbede3f   Alexander van Heukelum   x86_64: split out...
226
227
228
229
230
  			}
  		} else {
  		if (((long) stack & (THREAD_SIZE-1)) == 0)
  			break;
  		}
8a541665b   Alexander van Heukelum   dumpstack: x86: v...
231
  		if (i && ((i % STACKSLOTS_PER_LINE) == 0))
e4072a9a9   Jiri Slaby   x86, printk: Get ...
232
233
234
  			printk(KERN_CONT "
  ");
  		printk(KERN_CONT " %016lx", *stack++);
6fcbede3f   Alexander van Heukelum   x86_64: split out...
235
236
  		touch_nmi_watchdog();
  	}
67f2de0bf   Ingo Molnar   x86: dumpstack, 6...
237
  	preempt_enable();
e4072a9a9   Jiri Slaby   x86, printk: Get ...
238
239
  	printk(KERN_CONT "
  ");
e8e999cf3   Namhyung Kim   x86, dumpstack: C...
240
  	show_trace_log_lvl(task, regs, sp, bp, log_lvl);
6fcbede3f   Alexander van Heukelum   x86_64: split out...
241
  }
6fcbede3f   Alexander van Heukelum   x86_64: split out...
242
243
244
245
246
  void show_registers(struct pt_regs *regs)
  {
  	int i;
  	unsigned long sp;
  	const int cpu = smp_processor_id();
c6f5e0acd   Brian Gerst   x86-64: Move curr...
247
  	struct task_struct *cur = current;
6fcbede3f   Alexander van Heukelum   x86_64: split out...
248
249
250
  
  	sp = regs->sp;
  	printk("CPU %d ", cpu);
f266d7f5f   Alexey Dobriyan   x86_64: Print mod...
251
  	print_modules();
6fcbede3f   Alexander van Heukelum   x86_64: split out...
252
253
254
255
256
257
258
259
260
261
262
263
264
265
  	__show_regs(regs, 1);
  	printk("Process %s (pid: %d, threadinfo %p, task %p)
  ",
  		cur->comm, cur->pid, task_thread_info(cur), cur);
  
  	/*
  	 * When in-kernel, we also print out the stack and code at the
  	 * time of the fault..
  	 */
  	if (!user_mode(regs)) {
  		unsigned int code_prologue = code_bytes * 43 / 64;
  		unsigned int code_len = code_bytes;
  		unsigned char c;
  		u8 *ip;
ca0a81640   Alexander van Heukelum   dumpstack: x86: u...
266
267
  		printk(KERN_EMERG "Stack:
  ");
6fcbede3f   Alexander van Heukelum   x86_64: split out...
268
  		show_stack_log_lvl(NULL, regs, (unsigned long *)sp,
e8e999cf3   Namhyung Kim   x86, dumpstack: C...
269
  				   0, KERN_EMERG);
6fcbede3f   Alexander van Heukelum   x86_64: split out...
270
271
272
273
274
  
  		printk(KERN_EMERG "Code: ");
  
  		ip = (u8 *)regs->ip - code_prologue;
  		if (ip < (u8 *)PAGE_OFFSET || probe_kernel_address(ip, c)) {
8a541665b   Alexander van Heukelum   dumpstack: x86: v...
275
  			/* try starting at IP */
6fcbede3f   Alexander van Heukelum   x86_64: split out...
276
277
278
279
280
281
  			ip = (u8 *)regs->ip;
  			code_len = code_len - code_prologue + 1;
  		}
  		for (i = 0; i < code_len; i++, ip++) {
  			if (ip < (u8 *)PAGE_OFFSET ||
  					probe_kernel_address(ip, c)) {
13f541c10   Clemens Ladisch   x86, dumpstack: F...
282
  				printk(KERN_CONT " Bad RIP value.");
6fcbede3f   Alexander van Heukelum   x86_64: split out...
283
284
285
  				break;
  			}
  			if (ip == (u8 *)regs->ip)
13f541c10   Clemens Ladisch   x86, dumpstack: F...
286
  				printk(KERN_CONT "<%02x> ", c);
6fcbede3f   Alexander van Heukelum   x86_64: split out...
287
  			else
13f541c10   Clemens Ladisch   x86, dumpstack: F...
288
  				printk(KERN_CONT "%02x ", c);
6fcbede3f   Alexander van Heukelum   x86_64: split out...
289
290
  		}
  	}
13f541c10   Clemens Ladisch   x86, dumpstack: F...
291
292
  	printk(KERN_CONT "
  ");
6fcbede3f   Alexander van Heukelum   x86_64: split out...
293
294
295
296
297
298
299
300
301
302
303
  }
  
  int is_valid_bugaddr(unsigned long ip)
  {
  	unsigned short ud2;
  
  	if (__copy_from_user(&ud2, (const void __user *) ip, sizeof(ud2)))
  		return 0;
  
  	return ud2 == 0x0b0f;
  }