diff options
Diffstat (limited to 'arch/x86_64/kernel/traps.c')
-rw-r--r-- | arch/x86_64/kernel/traps.c | 948 |
1 files changed, 948 insertions, 0 deletions
diff --git a/arch/x86_64/kernel/traps.c b/arch/x86_64/kernel/traps.c new file mode 100644 index 000000000000..d87ac6496cc2 --- /dev/null +++ b/arch/x86_64/kernel/traps.c | |||
@@ -0,0 +1,948 @@ | |||
1 | /* | ||
2 | * linux/arch/x86-64/traps.c | ||
3 | * | ||
4 | * Copyright (C) 1991, 1992 Linus Torvalds | ||
5 | * Copyright (C) 2000, 2001, 2002 Andi Kleen, SuSE Labs | ||
6 | * | ||
7 | * Pentium III FXSR, SSE support | ||
8 | * Gareth Hughes <gareth@valinux.com>, May 2000 | ||
9 | * | ||
10 | * $Id: traps.c,v 1.36 2002/03/24 11:09:10 ak Exp $ | ||
11 | */ | ||
12 | |||
13 | /* | ||
14 | * 'Traps.c' handles hardware traps and faults after we have saved some | ||
15 | * state in 'entry.S'. | ||
16 | */ | ||
17 | #include <linux/config.h> | ||
18 | #include <linux/sched.h> | ||
19 | #include <linux/kernel.h> | ||
20 | #include <linux/string.h> | ||
21 | #include <linux/errno.h> | ||
22 | #include <linux/ptrace.h> | ||
23 | #include <linux/timer.h> | ||
24 | #include <linux/mm.h> | ||
25 | #include <linux/init.h> | ||
26 | #include <linux/delay.h> | ||
27 | #include <linux/spinlock.h> | ||
28 | #include <linux/interrupt.h> | ||
29 | #include <linux/module.h> | ||
30 | #include <linux/moduleparam.h> | ||
31 | |||
32 | #include <asm/system.h> | ||
33 | #include <asm/uaccess.h> | ||
34 | #include <asm/io.h> | ||
35 | #include <asm/atomic.h> | ||
36 | #include <asm/debugreg.h> | ||
37 | #include <asm/desc.h> | ||
38 | #include <asm/i387.h> | ||
39 | #include <asm/kdebug.h> | ||
40 | #include <asm/processor.h> | ||
41 | |||
42 | #include <asm/smp.h> | ||
43 | #include <asm/pgalloc.h> | ||
44 | #include <asm/pda.h> | ||
45 | #include <asm/proto.h> | ||
46 | #include <asm/nmi.h> | ||
47 | |||
48 | #include <linux/irq.h> | ||
49 | |||
50 | |||
51 | extern struct gate_struct idt_table[256]; | ||
52 | |||
53 | asmlinkage void divide_error(void); | ||
54 | asmlinkage void debug(void); | ||
55 | asmlinkage void nmi(void); | ||
56 | asmlinkage void int3(void); | ||
57 | asmlinkage void overflow(void); | ||
58 | asmlinkage void bounds(void); | ||
59 | asmlinkage void invalid_op(void); | ||
60 | asmlinkage void device_not_available(void); | ||
61 | asmlinkage void double_fault(void); | ||
62 | asmlinkage void coprocessor_segment_overrun(void); | ||
63 | asmlinkage void invalid_TSS(void); | ||
64 | asmlinkage void segment_not_present(void); | ||
65 | asmlinkage void stack_segment(void); | ||
66 | asmlinkage void general_protection(void); | ||
67 | asmlinkage void page_fault(void); | ||
68 | asmlinkage void coprocessor_error(void); | ||
69 | asmlinkage void simd_coprocessor_error(void); | ||
70 | asmlinkage void reserved(void); | ||
71 | asmlinkage void alignment_check(void); | ||
72 | asmlinkage void machine_check(void); | ||
73 | asmlinkage void spurious_interrupt_bug(void); | ||
74 | asmlinkage void call_debug(void); | ||
75 | |||
76 | struct notifier_block *die_chain; | ||
77 | static DEFINE_SPINLOCK(die_notifier_lock); | ||
78 | |||
79 | int register_die_notifier(struct notifier_block *nb) | ||
80 | { | ||
81 | int err = 0; | ||
82 | unsigned long flags; | ||
83 | spin_lock_irqsave(&die_notifier_lock, flags); | ||
84 | err = notifier_chain_register(&die_chain, nb); | ||
85 | spin_unlock_irqrestore(&die_notifier_lock, flags); | ||
86 | return err; | ||
87 | } | ||
88 | |||
89 | static inline void conditional_sti(struct pt_regs *regs) | ||
90 | { | ||
91 | if (regs->eflags & X86_EFLAGS_IF) | ||
92 | local_irq_enable(); | ||
93 | } | ||
94 | |||
95 | static int kstack_depth_to_print = 10; | ||
96 | |||
97 | #ifdef CONFIG_KALLSYMS | ||
98 | #include <linux/kallsyms.h> | ||
99 | int printk_address(unsigned long address) | ||
100 | { | ||
101 | unsigned long offset = 0, symsize; | ||
102 | const char *symname; | ||
103 | char *modname; | ||
104 | char *delim = ":"; | ||
105 | char namebuf[128]; | ||
106 | |||
107 | symname = kallsyms_lookup(address, &symsize, &offset, &modname, namebuf); | ||
108 | if (!symname) | ||
109 | return printk("[<%016lx>]", address); | ||
110 | if (!modname) | ||
111 | modname = delim = ""; | ||
112 | return printk("<%016lx>{%s%s%s%s%+ld}", | ||
113 | address,delim,modname,delim,symname,offset); | ||
114 | } | ||
115 | #else | ||
116 | int printk_address(unsigned long address) | ||
117 | { | ||
118 | return printk("[<%016lx>]", address); | ||
119 | } | ||
120 | #endif | ||
121 | |||
122 | unsigned long *in_exception_stack(int cpu, unsigned long stack) | ||
123 | { | ||
124 | int k; | ||
125 | for (k = 0; k < N_EXCEPTION_STACKS; k++) { | ||
126 | struct tss_struct *tss = &per_cpu(init_tss, cpu); | ||
127 | unsigned long start = tss->ist[k] - EXCEPTION_STKSZ; | ||
128 | |||
129 | if (stack >= start && stack < tss->ist[k]) | ||
130 | return (unsigned long *)tss->ist[k]; | ||
131 | } | ||
132 | return NULL; | ||
133 | } | ||
134 | |||
135 | /* | ||
136 | * x86-64 can have upto three kernel stacks: | ||
137 | * process stack | ||
138 | * interrupt stack | ||
139 | * severe exception (double fault, nmi, stack fault) hardware stack | ||
140 | * Check and process them in order. | ||
141 | */ | ||
142 | |||
143 | void show_trace(unsigned long *stack) | ||
144 | { | ||
145 | unsigned long addr; | ||
146 | unsigned long *irqstack, *irqstack_end, *estack_end; | ||
147 | const int cpu = safe_smp_processor_id(); | ||
148 | int i; | ||
149 | |||
150 | printk("\nCall Trace:"); | ||
151 | i = 0; | ||
152 | |||
153 | estack_end = in_exception_stack(cpu, (unsigned long)stack); | ||
154 | if (estack_end) { | ||
155 | while (stack < estack_end) { | ||
156 | addr = *stack++; | ||
157 | if (__kernel_text_address(addr)) { | ||
158 | i += printk_address(addr); | ||
159 | i += printk(" "); | ||
160 | if (i > 50) { | ||
161 | printk("\n"); | ||
162 | i = 0; | ||
163 | } | ||
164 | } | ||
165 | } | ||
166 | i += printk(" <EOE> "); | ||
167 | i += 7; | ||
168 | stack = (unsigned long *) estack_end[-2]; | ||
169 | } | ||
170 | |||
171 | irqstack_end = (unsigned long *) (cpu_pda[cpu].irqstackptr); | ||
172 | irqstack = (unsigned long *) (cpu_pda[cpu].irqstackptr - IRQSTACKSIZE + 64); | ||
173 | |||
174 | if (stack >= irqstack && stack < irqstack_end) { | ||
175 | printk("<IRQ> "); | ||
176 | while (stack < irqstack_end) { | ||
177 | addr = *stack++; | ||
178 | /* | ||
179 | * If the address is either in the text segment of the | ||
180 | * kernel, or in the region which contains vmalloc'ed | ||
181 | * memory, it *may* be the address of a calling | ||
182 | * routine; if so, print it so that someone tracing | ||
183 | * down the cause of the crash will be able to figure | ||
184 | * out the call path that was taken. | ||
185 | */ | ||
186 | if (__kernel_text_address(addr)) { | ||
187 | i += printk_address(addr); | ||
188 | i += printk(" "); | ||
189 | if (i > 50) { | ||
190 | printk("\n "); | ||
191 | i = 0; | ||
192 | } | ||
193 | } | ||
194 | } | ||
195 | stack = (unsigned long *) (irqstack_end[-1]); | ||
196 | printk(" <EOI> "); | ||
197 | i += 7; | ||
198 | } | ||
199 | |||
200 | while (((long) stack & (THREAD_SIZE-1)) != 0) { | ||
201 | addr = *stack++; | ||
202 | if (__kernel_text_address(addr)) { | ||
203 | i += printk_address(addr); | ||
204 | i += printk(" "); | ||
205 | if (i > 50) { | ||
206 | printk("\n "); | ||
207 | i = 0; | ||
208 | } | ||
209 | } | ||
210 | } | ||
211 | printk("\n"); | ||
212 | } | ||
213 | |||
214 | void show_stack(struct task_struct *tsk, unsigned long * rsp) | ||
215 | { | ||
216 | unsigned long *stack; | ||
217 | int i; | ||
218 | const int cpu = safe_smp_processor_id(); | ||
219 | unsigned long *irqstack_end = (unsigned long *) (cpu_pda[cpu].irqstackptr); | ||
220 | unsigned long *irqstack = (unsigned long *) (cpu_pda[cpu].irqstackptr - IRQSTACKSIZE); | ||
221 | |||
222 | // debugging aid: "show_stack(NULL, NULL);" prints the | ||
223 | // back trace for this cpu. | ||
224 | |||
225 | if (rsp == NULL) { | ||
226 | if (tsk) | ||
227 | rsp = (unsigned long *)tsk->thread.rsp; | ||
228 | else | ||
229 | rsp = (unsigned long *)&rsp; | ||
230 | } | ||
231 | |||
232 | stack = rsp; | ||
233 | for(i=0; i < kstack_depth_to_print; i++) { | ||
234 | if (stack >= irqstack && stack <= irqstack_end) { | ||
235 | if (stack == irqstack_end) { | ||
236 | stack = (unsigned long *) (irqstack_end[-1]); | ||
237 | printk(" <EOI> "); | ||
238 | } | ||
239 | } else { | ||
240 | if (((long) stack & (THREAD_SIZE-1)) == 0) | ||
241 | break; | ||
242 | } | ||
243 | if (i && ((i % 4) == 0)) | ||
244 | printk("\n "); | ||
245 | printk("%016lx ", *stack++); | ||
246 | } | ||
247 | show_trace((unsigned long *)rsp); | ||
248 | } | ||
249 | |||
250 | /* | ||
251 | * The architecture-independent dump_stack generator | ||
252 | */ | ||
253 | void dump_stack(void) | ||
254 | { | ||
255 | unsigned long dummy; | ||
256 | show_trace(&dummy); | ||
257 | } | ||
258 | |||
259 | EXPORT_SYMBOL(dump_stack); | ||
260 | |||
261 | void show_registers(struct pt_regs *regs) | ||
262 | { | ||
263 | int i; | ||
264 | int in_kernel = (regs->cs & 3) == 0; | ||
265 | unsigned long rsp; | ||
266 | const int cpu = safe_smp_processor_id(); | ||
267 | struct task_struct *cur = cpu_pda[cpu].pcurrent; | ||
268 | |||
269 | rsp = regs->rsp; | ||
270 | |||
271 | printk("CPU %d ", cpu); | ||
272 | __show_regs(regs); | ||
273 | printk("Process %s (pid: %d, threadinfo %p, task %p)\n", | ||
274 | cur->comm, cur->pid, cur->thread_info, cur); | ||
275 | |||
276 | /* | ||
277 | * When in-kernel, we also print out the stack and code at the | ||
278 | * time of the fault.. | ||
279 | */ | ||
280 | if (in_kernel) { | ||
281 | |||
282 | printk("Stack: "); | ||
283 | show_stack(NULL, (unsigned long*)rsp); | ||
284 | |||
285 | printk("\nCode: "); | ||
286 | if(regs->rip < PAGE_OFFSET) | ||
287 | goto bad; | ||
288 | |||
289 | for(i=0;i<20;i++) | ||
290 | { | ||
291 | unsigned char c; | ||
292 | if(__get_user(c, &((unsigned char*)regs->rip)[i])) { | ||
293 | bad: | ||
294 | printk(" Bad RIP value."); | ||
295 | break; | ||
296 | } | ||
297 | printk("%02x ", c); | ||
298 | } | ||
299 | } | ||
300 | printk("\n"); | ||
301 | } | ||
302 | |||
303 | void handle_BUG(struct pt_regs *regs) | ||
304 | { | ||
305 | struct bug_frame f; | ||
306 | char tmp; | ||
307 | |||
308 | if (regs->cs & 3) | ||
309 | return; | ||
310 | if (__copy_from_user(&f, (struct bug_frame *) regs->rip, | ||
311 | sizeof(struct bug_frame))) | ||
312 | return; | ||
313 | if ((unsigned long)f.filename < __PAGE_OFFSET || | ||
314 | f.ud2[0] != 0x0f || f.ud2[1] != 0x0b) | ||
315 | return; | ||
316 | if (__get_user(tmp, f.filename)) | ||
317 | f.filename = "unmapped filename"; | ||
318 | printk("----------- [cut here ] --------- [please bite here ] ---------\n"); | ||
319 | printk(KERN_ALERT "Kernel BUG at %.50s:%d\n", f.filename, f.line); | ||
320 | } | ||
321 | |||
322 | void out_of_line_bug(void) | ||
323 | { | ||
324 | BUG(); | ||
325 | } | ||
326 | |||
327 | static DEFINE_SPINLOCK(die_lock); | ||
328 | static int die_owner = -1; | ||
329 | |||
330 | void oops_begin(void) | ||
331 | { | ||
332 | int cpu = safe_smp_processor_id(); | ||
333 | /* racy, but better than risking deadlock. */ | ||
334 | local_irq_disable(); | ||
335 | if (!spin_trylock(&die_lock)) { | ||
336 | if (cpu == die_owner) | ||
337 | /* nested oops. should stop eventually */; | ||
338 | else | ||
339 | spin_lock(&die_lock); | ||
340 | } | ||
341 | die_owner = cpu; | ||
342 | console_verbose(); | ||
343 | bust_spinlocks(1); | ||
344 | } | ||
345 | |||
346 | void oops_end(void) | ||
347 | { | ||
348 | die_owner = -1; | ||
349 | bust_spinlocks(0); | ||
350 | spin_unlock(&die_lock); | ||
351 | if (panic_on_oops) | ||
352 | panic("Oops"); | ||
353 | } | ||
354 | |||
355 | void __die(const char * str, struct pt_regs * regs, long err) | ||
356 | { | ||
357 | static int die_counter; | ||
358 | printk(KERN_EMERG "%s: %04lx [%u] ", str, err & 0xffff,++die_counter); | ||
359 | #ifdef CONFIG_PREEMPT | ||
360 | printk("PREEMPT "); | ||
361 | #endif | ||
362 | #ifdef CONFIG_SMP | ||
363 | printk("SMP "); | ||
364 | #endif | ||
365 | #ifdef CONFIG_DEBUG_PAGEALLOC | ||
366 | printk("DEBUG_PAGEALLOC"); | ||
367 | #endif | ||
368 | printk("\n"); | ||
369 | notify_die(DIE_OOPS, (char *)str, regs, err, 255, SIGSEGV); | ||
370 | show_registers(regs); | ||
371 | /* Executive summary in case the oops scrolled away */ | ||
372 | printk(KERN_ALERT "RIP "); | ||
373 | printk_address(regs->rip); | ||
374 | printk(" RSP <%016lx>\n", regs->rsp); | ||
375 | } | ||
376 | |||
377 | void die(const char * str, struct pt_regs * regs, long err) | ||
378 | { | ||
379 | oops_begin(); | ||
380 | handle_BUG(regs); | ||
381 | __die(str, regs, err); | ||
382 | oops_end(); | ||
383 | do_exit(SIGSEGV); | ||
384 | } | ||
385 | static inline void die_if_kernel(const char * str, struct pt_regs * regs, long err) | ||
386 | { | ||
387 | if (!(regs->eflags & VM_MASK) && (regs->cs == __KERNEL_CS)) | ||
388 | die(str, regs, err); | ||
389 | } | ||
390 | |||
391 | void die_nmi(char *str, struct pt_regs *regs) | ||
392 | { | ||
393 | oops_begin(); | ||
394 | /* | ||
395 | * We are in trouble anyway, lets at least try | ||
396 | * to get a message out. | ||
397 | */ | ||
398 | printk(str, safe_smp_processor_id()); | ||
399 | show_registers(regs); | ||
400 | if (panic_on_timeout || panic_on_oops) | ||
401 | panic("nmi watchdog"); | ||
402 | printk("console shuts up ...\n"); | ||
403 | oops_end(); | ||
404 | do_exit(SIGSEGV); | ||
405 | } | ||
406 | |||
407 | static void do_trap(int trapnr, int signr, char *str, | ||
408 | struct pt_regs * regs, long error_code, siginfo_t *info) | ||
409 | { | ||
410 | conditional_sti(regs); | ||
411 | |||
412 | #ifdef CONFIG_CHECKING | ||
413 | { | ||
414 | unsigned long gs; | ||
415 | struct x8664_pda *pda = cpu_pda + safe_smp_processor_id(); | ||
416 | rdmsrl(MSR_GS_BASE, gs); | ||
417 | if (gs != (unsigned long)pda) { | ||
418 | wrmsrl(MSR_GS_BASE, pda); | ||
419 | printk("%s: wrong gs %lx expected %p rip %lx\n", str, gs, pda, | ||
420 | regs->rip); | ||
421 | } | ||
422 | } | ||
423 | #endif | ||
424 | |||
425 | if ((regs->cs & 3) != 0) { | ||
426 | struct task_struct *tsk = current; | ||
427 | |||
428 | if (exception_trace && unhandled_signal(tsk, signr)) | ||
429 | printk(KERN_INFO | ||
430 | "%s[%d] trap %s rip:%lx rsp:%lx error:%lx\n", | ||
431 | tsk->comm, tsk->pid, str, | ||
432 | regs->rip,regs->rsp,error_code); | ||
433 | |||
434 | tsk->thread.error_code = error_code; | ||
435 | tsk->thread.trap_no = trapnr; | ||
436 | if (info) | ||
437 | force_sig_info(signr, info, tsk); | ||
438 | else | ||
439 | force_sig(signr, tsk); | ||
440 | return; | ||
441 | } | ||
442 | |||
443 | |||
444 | /* kernel trap */ | ||
445 | { | ||
446 | const struct exception_table_entry *fixup; | ||
447 | fixup = search_exception_tables(regs->rip); | ||
448 | if (fixup) { | ||
449 | regs->rip = fixup->fixup; | ||
450 | } else | ||
451 | die(str, regs, error_code); | ||
452 | return; | ||
453 | } | ||
454 | } | ||
455 | |||
456 | #define DO_ERROR(trapnr, signr, str, name) \ | ||
457 | asmlinkage void do_##name(struct pt_regs * regs, long error_code) \ | ||
458 | { \ | ||
459 | if (notify_die(DIE_TRAP, str, regs, error_code, trapnr, signr) \ | ||
460 | == NOTIFY_STOP) \ | ||
461 | return; \ | ||
462 | do_trap(trapnr, signr, str, regs, error_code, NULL); \ | ||
463 | } | ||
464 | |||
465 | #define DO_ERROR_INFO(trapnr, signr, str, name, sicode, siaddr) \ | ||
466 | asmlinkage void do_##name(struct pt_regs * regs, long error_code) \ | ||
467 | { \ | ||
468 | siginfo_t info; \ | ||
469 | info.si_signo = signr; \ | ||
470 | info.si_errno = 0; \ | ||
471 | info.si_code = sicode; \ | ||
472 | info.si_addr = (void __user *)siaddr; \ | ||
473 | if (notify_die(DIE_TRAP, str, regs, error_code, trapnr, signr) \ | ||
474 | == NOTIFY_STOP) \ | ||
475 | return; \ | ||
476 | do_trap(trapnr, signr, str, regs, error_code, &info); \ | ||
477 | } | ||
478 | |||
479 | DO_ERROR_INFO( 0, SIGFPE, "divide error", divide_error, FPE_INTDIV, regs->rip) | ||
480 | DO_ERROR( 4, SIGSEGV, "overflow", overflow) | ||
481 | DO_ERROR( 5, SIGSEGV, "bounds", bounds) | ||
482 | DO_ERROR_INFO( 6, SIGILL, "invalid operand", invalid_op, ILL_ILLOPN, regs->rip) | ||
483 | DO_ERROR( 7, SIGSEGV, "device not available", device_not_available) | ||
484 | DO_ERROR( 9, SIGFPE, "coprocessor segment overrun", coprocessor_segment_overrun) | ||
485 | DO_ERROR(10, SIGSEGV, "invalid TSS", invalid_TSS) | ||
486 | DO_ERROR(11, SIGBUS, "segment not present", segment_not_present) | ||
487 | DO_ERROR_INFO(17, SIGBUS, "alignment check", alignment_check, BUS_ADRALN, 0) | ||
488 | DO_ERROR(18, SIGSEGV, "reserved", reserved) | ||
489 | |||
490 | #define DO_ERROR_STACK(trapnr, signr, str, name) \ | ||
491 | asmlinkage void *do_##name(struct pt_regs * regs, long error_code) \ | ||
492 | { \ | ||
493 | struct pt_regs *pr = ((struct pt_regs *)(current->thread.rsp0))-1; \ | ||
494 | if (notify_die(DIE_TRAP, str, regs, error_code, trapnr, signr) \ | ||
495 | == NOTIFY_STOP) \ | ||
496 | return regs; \ | ||
497 | if (regs->cs & 3) { \ | ||
498 | memcpy(pr, regs, sizeof(struct pt_regs)); \ | ||
499 | regs = pr; \ | ||
500 | } \ | ||
501 | do_trap(trapnr, signr, str, regs, error_code, NULL); \ | ||
502 | return regs; \ | ||
503 | } | ||
504 | |||
505 | DO_ERROR_STACK(12, SIGBUS, "stack segment", stack_segment) | ||
506 | DO_ERROR_STACK( 8, SIGSEGV, "double fault", double_fault) | ||
507 | |||
508 | asmlinkage void do_general_protection(struct pt_regs * regs, long error_code) | ||
509 | { | ||
510 | conditional_sti(regs); | ||
511 | |||
512 | #ifdef CONFIG_CHECKING | ||
513 | { | ||
514 | unsigned long gs; | ||
515 | struct x8664_pda *pda = cpu_pda + safe_smp_processor_id(); | ||
516 | rdmsrl(MSR_GS_BASE, gs); | ||
517 | if (gs != (unsigned long)pda) { | ||
518 | wrmsrl(MSR_GS_BASE, pda); | ||
519 | oops_in_progress++; | ||
520 | printk("general protection handler: wrong gs %lx expected %p\n", gs, pda); | ||
521 | oops_in_progress--; | ||
522 | } | ||
523 | } | ||
524 | #endif | ||
525 | |||
526 | if ((regs->cs & 3)!=0) { | ||
527 | struct task_struct *tsk = current; | ||
528 | |||
529 | if (exception_trace && unhandled_signal(tsk, SIGSEGV)) | ||
530 | printk(KERN_INFO | ||
531 | "%s[%d] general protection rip:%lx rsp:%lx error:%lx\n", | ||
532 | tsk->comm, tsk->pid, | ||
533 | regs->rip,regs->rsp,error_code); | ||
534 | |||
535 | tsk->thread.error_code = error_code; | ||
536 | tsk->thread.trap_no = 13; | ||
537 | force_sig(SIGSEGV, tsk); | ||
538 | return; | ||
539 | } | ||
540 | |||
541 | /* kernel gp */ | ||
542 | { | ||
543 | const struct exception_table_entry *fixup; | ||
544 | fixup = search_exception_tables(regs->rip); | ||
545 | if (fixup) { | ||
546 | regs->rip = fixup->fixup; | ||
547 | return; | ||
548 | } | ||
549 | if (notify_die(DIE_GPF, "general protection fault", regs, | ||
550 | error_code, 13, SIGSEGV) == NOTIFY_STOP) | ||
551 | return; | ||
552 | die("general protection fault", regs, error_code); | ||
553 | } | ||
554 | } | ||
555 | |||
556 | static void mem_parity_error(unsigned char reason, struct pt_regs * regs) | ||
557 | { | ||
558 | printk("Uhhuh. NMI received. Dazed and confused, but trying to continue\n"); | ||
559 | printk("You probably have a hardware problem with your RAM chips\n"); | ||
560 | |||
561 | /* Clear and disable the memory parity error line. */ | ||
562 | reason = (reason & 0xf) | 4; | ||
563 | outb(reason, 0x61); | ||
564 | } | ||
565 | |||
566 | static void io_check_error(unsigned char reason, struct pt_regs * regs) | ||
567 | { | ||
568 | printk("NMI: IOCK error (debug interrupt?)\n"); | ||
569 | show_registers(regs); | ||
570 | |||
571 | /* Re-enable the IOCK line, wait for a few seconds */ | ||
572 | reason = (reason & 0xf) | 8; | ||
573 | outb(reason, 0x61); | ||
574 | mdelay(2000); | ||
575 | reason &= ~8; | ||
576 | outb(reason, 0x61); | ||
577 | } | ||
578 | |||
579 | static void unknown_nmi_error(unsigned char reason, struct pt_regs * regs) | ||
580 | { printk("Uhhuh. NMI received for unknown reason %02x.\n", reason); | ||
581 | printk("Dazed and confused, but trying to continue\n"); | ||
582 | printk("Do you have a strange power saving mode enabled?\n"); | ||
583 | } | ||
584 | |||
585 | asmlinkage void default_do_nmi(struct pt_regs *regs) | ||
586 | { | ||
587 | unsigned char reason = 0; | ||
588 | |||
589 | /* Only the BSP gets external NMIs from the system. */ | ||
590 | if (!smp_processor_id()) | ||
591 | reason = get_nmi_reason(); | ||
592 | |||
593 | if (!(reason & 0xc0)) { | ||
594 | if (notify_die(DIE_NMI_IPI, "nmi_ipi", regs, reason, 0, SIGINT) | ||
595 | == NOTIFY_STOP) | ||
596 | return; | ||
597 | #ifdef CONFIG_X86_LOCAL_APIC | ||
598 | /* | ||
599 | * Ok, so this is none of the documented NMI sources, | ||
600 | * so it must be the NMI watchdog. | ||
601 | */ | ||
602 | if (nmi_watchdog > 0) { | ||
603 | nmi_watchdog_tick(regs,reason); | ||
604 | return; | ||
605 | } | ||
606 | #endif | ||
607 | unknown_nmi_error(reason, regs); | ||
608 | return; | ||
609 | } | ||
610 | if (notify_die(DIE_NMI, "nmi", regs, reason, 0, SIGINT) == NOTIFY_STOP) | ||
611 | return; | ||
612 | |||
613 | /* AK: following checks seem to be broken on modern chipsets. FIXME */ | ||
614 | |||
615 | if (reason & 0x80) | ||
616 | mem_parity_error(reason, regs); | ||
617 | if (reason & 0x40) | ||
618 | io_check_error(reason, regs); | ||
619 | } | ||
620 | |||
621 | asmlinkage void do_int3(struct pt_regs * regs, long error_code) | ||
622 | { | ||
623 | if (notify_die(DIE_INT3, "int3", regs, error_code, 3, SIGTRAP) == NOTIFY_STOP) { | ||
624 | return; | ||
625 | } | ||
626 | do_trap(3, SIGTRAP, "int3", regs, error_code, NULL); | ||
627 | return; | ||
628 | } | ||
629 | |||
630 | /* runs on IST stack. */ | ||
631 | asmlinkage void *do_debug(struct pt_regs * regs, unsigned long error_code) | ||
632 | { | ||
633 | struct pt_regs *pr; | ||
634 | unsigned long condition; | ||
635 | struct task_struct *tsk = current; | ||
636 | siginfo_t info; | ||
637 | |||
638 | pr = (struct pt_regs *)(current->thread.rsp0)-1; | ||
639 | if (regs->cs & 3) { | ||
640 | memcpy(pr, regs, sizeof(struct pt_regs)); | ||
641 | regs = pr; | ||
642 | } | ||
643 | |||
644 | #ifdef CONFIG_CHECKING | ||
645 | { | ||
646 | /* RED-PEN interaction with debugger - could destroy gs */ | ||
647 | unsigned long gs; | ||
648 | struct x8664_pda *pda = cpu_pda + safe_smp_processor_id(); | ||
649 | rdmsrl(MSR_GS_BASE, gs); | ||
650 | if (gs != (unsigned long)pda) { | ||
651 | wrmsrl(MSR_GS_BASE, pda); | ||
652 | printk("debug handler: wrong gs %lx expected %p\n", gs, pda); | ||
653 | } | ||
654 | } | ||
655 | #endif | ||
656 | |||
657 | asm("movq %%db6,%0" : "=r" (condition)); | ||
658 | |||
659 | if (notify_die(DIE_DEBUG, "debug", regs, condition, error_code, | ||
660 | SIGTRAP) == NOTIFY_STOP) { | ||
661 | return regs; | ||
662 | } | ||
663 | conditional_sti(regs); | ||
664 | |||
665 | /* Mask out spurious debug traps due to lazy DR7 setting */ | ||
666 | if (condition & (DR_TRAP0|DR_TRAP1|DR_TRAP2|DR_TRAP3)) { | ||
667 | if (!tsk->thread.debugreg7) { | ||
668 | goto clear_dr7; | ||
669 | } | ||
670 | } | ||
671 | |||
672 | tsk->thread.debugreg6 = condition; | ||
673 | |||
674 | /* Mask out spurious TF errors due to lazy TF clearing */ | ||
675 | if ((condition & DR_STEP) && | ||
676 | (notify_die(DIE_DEBUGSTEP, "debugstep", regs, condition, | ||
677 | 1, SIGTRAP) != NOTIFY_STOP)) { | ||
678 | /* | ||
679 | * The TF error should be masked out only if the current | ||
680 | * process is not traced and if the TRAP flag has been set | ||
681 | * previously by a tracing process (condition detected by | ||
682 | * the PT_DTRACE flag); remember that the i386 TRAP flag | ||
683 | * can be modified by the process itself in user mode, | ||
684 | * allowing programs to debug themselves without the ptrace() | ||
685 | * interface. | ||
686 | */ | ||
687 | if ((regs->cs & 3) == 0) | ||
688 | goto clear_TF_reenable; | ||
689 | if ((tsk->ptrace & (PT_DTRACE|PT_PTRACED)) == PT_DTRACE) | ||
690 | goto clear_TF; | ||
691 | } | ||
692 | |||
693 | /* Ok, finally something we can handle */ | ||
694 | tsk->thread.trap_no = 1; | ||
695 | tsk->thread.error_code = error_code; | ||
696 | info.si_signo = SIGTRAP; | ||
697 | info.si_errno = 0; | ||
698 | info.si_code = TRAP_BRKPT; | ||
699 | if ((regs->cs & 3) == 0) | ||
700 | goto clear_dr7; | ||
701 | |||
702 | info.si_addr = (void __user *)regs->rip; | ||
703 | force_sig_info(SIGTRAP, &info, tsk); | ||
704 | clear_dr7: | ||
705 | asm volatile("movq %0,%%db7"::"r"(0UL)); | ||
706 | notify_die(DIE_DEBUG, "debug", regs, condition, 1, SIGTRAP); | ||
707 | return regs; | ||
708 | |||
709 | clear_TF_reenable: | ||
710 | set_tsk_thread_flag(tsk, TIF_SINGLESTEP); | ||
711 | |||
712 | clear_TF: | ||
713 | /* RED-PEN could cause spurious errors */ | ||
714 | if (notify_die(DIE_DEBUG, "debug2", regs, condition, 1, SIGTRAP) | ||
715 | != NOTIFY_STOP) | ||
716 | regs->eflags &= ~TF_MASK; | ||
717 | return regs; | ||
718 | } | ||
719 | |||
720 | static int kernel_math_error(struct pt_regs *regs, char *str) | ||
721 | { | ||
722 | const struct exception_table_entry *fixup; | ||
723 | fixup = search_exception_tables(regs->rip); | ||
724 | if (fixup) { | ||
725 | regs->rip = fixup->fixup; | ||
726 | return 1; | ||
727 | } | ||
728 | notify_die(DIE_GPF, str, regs, 0, 16, SIGFPE); | ||
729 | #if 0 | ||
730 | /* This should be a die, but warn only for now */ | ||
731 | die(str, regs, 0); | ||
732 | #else | ||
733 | printk(KERN_DEBUG "%s: %s at ", current->comm, str); | ||
734 | printk_address(regs->rip); | ||
735 | printk("\n"); | ||
736 | #endif | ||
737 | return 0; | ||
738 | } | ||
739 | |||
740 | /* | ||
741 | * Note that we play around with the 'TS' bit in an attempt to get | ||
742 | * the correct behaviour even in the presence of the asynchronous | ||
743 | * IRQ13 behaviour | ||
744 | */ | ||
745 | asmlinkage void do_coprocessor_error(struct pt_regs *regs) | ||
746 | { | ||
747 | void __user *rip = (void __user *)(regs->rip); | ||
748 | struct task_struct * task; | ||
749 | siginfo_t info; | ||
750 | unsigned short cwd, swd; | ||
751 | |||
752 | conditional_sti(regs); | ||
753 | if ((regs->cs & 3) == 0 && | ||
754 | kernel_math_error(regs, "kernel x87 math error")) | ||
755 | return; | ||
756 | |||
757 | /* | ||
758 | * Save the info for the exception handler and clear the error. | ||
759 | */ | ||
760 | task = current; | ||
761 | save_init_fpu(task); | ||
762 | task->thread.trap_no = 16; | ||
763 | task->thread.error_code = 0; | ||
764 | info.si_signo = SIGFPE; | ||
765 | info.si_errno = 0; | ||
766 | info.si_code = __SI_FAULT; | ||
767 | info.si_addr = rip; | ||
768 | /* | ||
769 | * (~cwd & swd) will mask out exceptions that are not set to unmasked | ||
770 | * status. 0x3f is the exception bits in these regs, 0x200 is the | ||
771 | * C1 reg you need in case of a stack fault, 0x040 is the stack | ||
772 | * fault bit. We should only be taking one exception at a time, | ||
773 | * so if this combination doesn't produce any single exception, | ||
774 | * then we have a bad program that isn't synchronizing its FPU usage | ||
775 | * and it will suffer the consequences since we won't be able to | ||
776 | * fully reproduce the context of the exception | ||
777 | */ | ||
778 | cwd = get_fpu_cwd(task); | ||
779 | swd = get_fpu_swd(task); | ||
780 | switch (((~cwd) & swd & 0x3f) | (swd & 0x240)) { | ||
781 | case 0x000: | ||
782 | default: | ||
783 | break; | ||
784 | case 0x001: /* Invalid Op */ | ||
785 | case 0x041: /* Stack Fault */ | ||
786 | case 0x241: /* Stack Fault | Direction */ | ||
787 | info.si_code = FPE_FLTINV; | ||
788 | break; | ||
789 | case 0x002: /* Denormalize */ | ||
790 | case 0x010: /* Underflow */ | ||
791 | info.si_code = FPE_FLTUND; | ||
792 | break; | ||
793 | case 0x004: /* Zero Divide */ | ||
794 | info.si_code = FPE_FLTDIV; | ||
795 | break; | ||
796 | case 0x008: /* Overflow */ | ||
797 | info.si_code = FPE_FLTOVF; | ||
798 | break; | ||
799 | case 0x020: /* Precision */ | ||
800 | info.si_code = FPE_FLTRES; | ||
801 | break; | ||
802 | } | ||
803 | force_sig_info(SIGFPE, &info, task); | ||
804 | } | ||
805 | |||
806 | asmlinkage void bad_intr(void) | ||
807 | { | ||
808 | printk("bad interrupt"); | ||
809 | } | ||
810 | |||
811 | asmlinkage void do_simd_coprocessor_error(struct pt_regs *regs) | ||
812 | { | ||
813 | void __user *rip = (void __user *)(regs->rip); | ||
814 | struct task_struct * task; | ||
815 | siginfo_t info; | ||
816 | unsigned short mxcsr; | ||
817 | |||
818 | conditional_sti(regs); | ||
819 | if ((regs->cs & 3) == 0 && | ||
820 | kernel_math_error(regs, "simd math error")) | ||
821 | return; | ||
822 | |||
823 | /* | ||
824 | * Save the info for the exception handler and clear the error. | ||
825 | */ | ||
826 | task = current; | ||
827 | save_init_fpu(task); | ||
828 | task->thread.trap_no = 19; | ||
829 | task->thread.error_code = 0; | ||
830 | info.si_signo = SIGFPE; | ||
831 | info.si_errno = 0; | ||
832 | info.si_code = __SI_FAULT; | ||
833 | info.si_addr = rip; | ||
834 | /* | ||
835 | * The SIMD FPU exceptions are handled a little differently, as there | ||
836 | * is only a single status/control register. Thus, to determine which | ||
837 | * unmasked exception was caught we must mask the exception mask bits | ||
838 | * at 0x1f80, and then use these to mask the exception bits at 0x3f. | ||
839 | */ | ||
840 | mxcsr = get_fpu_mxcsr(task); | ||
841 | switch (~((mxcsr & 0x1f80) >> 7) & (mxcsr & 0x3f)) { | ||
842 | case 0x000: | ||
843 | default: | ||
844 | break; | ||
845 | case 0x001: /* Invalid Op */ | ||
846 | info.si_code = FPE_FLTINV; | ||
847 | break; | ||
848 | case 0x002: /* Denormalize */ | ||
849 | case 0x010: /* Underflow */ | ||
850 | info.si_code = FPE_FLTUND; | ||
851 | break; | ||
852 | case 0x004: /* Zero Divide */ | ||
853 | info.si_code = FPE_FLTDIV; | ||
854 | break; | ||
855 | case 0x008: /* Overflow */ | ||
856 | info.si_code = FPE_FLTOVF; | ||
857 | break; | ||
858 | case 0x020: /* Precision */ | ||
859 | info.si_code = FPE_FLTRES; | ||
860 | break; | ||
861 | } | ||
862 | force_sig_info(SIGFPE, &info, task); | ||
863 | } | ||
864 | |||
865 | asmlinkage void do_spurious_interrupt_bug(struct pt_regs * regs) | ||
866 | { | ||
867 | } | ||
868 | |||
869 | asmlinkage void __attribute__((weak)) smp_thermal_interrupt(void) | ||
870 | { | ||
871 | } | ||
872 | |||
873 | /* | ||
874 | * 'math_state_restore()' saves the current math information in the | ||
875 | * old math state array, and gets the new ones from the current task | ||
876 | * | ||
877 | * Careful.. There are problems with IBM-designed IRQ13 behaviour. | ||
878 | * Don't touch unless you *really* know how it works. | ||
879 | */ | ||
880 | asmlinkage void math_state_restore(void) | ||
881 | { | ||
882 | struct task_struct *me = current; | ||
883 | clts(); /* Allow maths ops (or we recurse) */ | ||
884 | |||
885 | if (!used_math()) | ||
886 | init_fpu(me); | ||
887 | restore_fpu_checking(&me->thread.i387.fxsave); | ||
888 | me->thread_info->status |= TS_USEDFPU; | ||
889 | } | ||
890 | |||
891 | void do_call_debug(struct pt_regs *regs) | ||
892 | { | ||
893 | notify_die(DIE_CALL, "debug call", regs, 0, 255, SIGINT); | ||
894 | } | ||
895 | |||
896 | void __init trap_init(void) | ||
897 | { | ||
898 | set_intr_gate(0,÷_error); | ||
899 | set_intr_gate_ist(1,&debug,DEBUG_STACK); | ||
900 | set_intr_gate_ist(2,&nmi,NMI_STACK); | ||
901 | set_system_gate(3,&int3); | ||
902 | set_system_gate(4,&overflow); /* int4-5 can be called from all */ | ||
903 | set_system_gate(5,&bounds); | ||
904 | set_intr_gate(6,&invalid_op); | ||
905 | set_intr_gate(7,&device_not_available); | ||
906 | set_intr_gate_ist(8,&double_fault, DOUBLEFAULT_STACK); | ||
907 | set_intr_gate(9,&coprocessor_segment_overrun); | ||
908 | set_intr_gate(10,&invalid_TSS); | ||
909 | set_intr_gate(11,&segment_not_present); | ||
910 | set_intr_gate_ist(12,&stack_segment,STACKFAULT_STACK); | ||
911 | set_intr_gate(13,&general_protection); | ||
912 | set_intr_gate(14,&page_fault); | ||
913 | set_intr_gate(15,&spurious_interrupt_bug); | ||
914 | set_intr_gate(16,&coprocessor_error); | ||
915 | set_intr_gate(17,&alignment_check); | ||
916 | #ifdef CONFIG_X86_MCE | ||
917 | set_intr_gate_ist(18,&machine_check, MCE_STACK); | ||
918 | #endif | ||
919 | set_intr_gate(19,&simd_coprocessor_error); | ||
920 | |||
921 | #ifdef CONFIG_IA32_EMULATION | ||
922 | set_system_gate(IA32_SYSCALL_VECTOR, ia32_syscall); | ||
923 | #endif | ||
924 | |||
925 | set_intr_gate(KDB_VECTOR, call_debug); | ||
926 | |||
927 | /* | ||
928 | * Should be a barrier for any external CPU state. | ||
929 | */ | ||
930 | cpu_init(); | ||
931 | } | ||
932 | |||
933 | |||
934 | /* Actual parsing is done early in setup.c. */ | ||
935 | static int __init oops_dummy(char *s) | ||
936 | { | ||
937 | panic_on_oops = 1; | ||
938 | return -1; | ||
939 | } | ||
940 | __setup("oops=", oops_dummy); | ||
941 | |||
942 | static int __init kstack_setup(char *s) | ||
943 | { | ||
944 | kstack_depth_to_print = simple_strtoul(s,NULL,0); | ||
945 | return 0; | ||
946 | } | ||
947 | __setup("kstack=", kstack_setup); | ||
948 | |||