blob: edaa9fe654dce5a978aad027f7cc4f2c8c8dccbb [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
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>
akpm@osdl.org35faa712005-04-16 15:24:54 -070031#include <linux/nmi.h>
Prasanna S Panchamukhi0f2fbdc2005-09-06 15:19:28 -070032#include <linux/kprobes.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070033
34#include <asm/system.h>
35#include <asm/uaccess.h>
36#include <asm/io.h>
37#include <asm/atomic.h>
38#include <asm/debugreg.h>
39#include <asm/desc.h>
40#include <asm/i387.h>
41#include <asm/kdebug.h>
42#include <asm/processor.h>
43
44#include <asm/smp.h>
45#include <asm/pgalloc.h>
46#include <asm/pda.h>
47#include <asm/proto.h>
48#include <asm/nmi.h>
49
Linus Torvalds1da177e2005-04-16 15:20:36 -070050asmlinkage void divide_error(void);
51asmlinkage void debug(void);
52asmlinkage void nmi(void);
53asmlinkage void int3(void);
54asmlinkage void overflow(void);
55asmlinkage void bounds(void);
56asmlinkage void invalid_op(void);
57asmlinkage void device_not_available(void);
58asmlinkage void double_fault(void);
59asmlinkage void coprocessor_segment_overrun(void);
60asmlinkage void invalid_TSS(void);
61asmlinkage void segment_not_present(void);
62asmlinkage void stack_segment(void);
63asmlinkage void general_protection(void);
64asmlinkage void page_fault(void);
65asmlinkage void coprocessor_error(void);
66asmlinkage void simd_coprocessor_error(void);
67asmlinkage void reserved(void);
68asmlinkage void alignment_check(void);
69asmlinkage void machine_check(void);
70asmlinkage void spurious_interrupt_bug(void);
Linus Torvalds1da177e2005-04-16 15:20:36 -070071
Alan Sterne041c682006-03-27 01:16:30 -080072ATOMIC_NOTIFIER_HEAD(die_chain);
Linus Torvalds1da177e2005-04-16 15:20:36 -070073
74int register_die_notifier(struct notifier_block *nb)
75{
Jan Beulich8c914cb2006-03-25 16:29:40 +010076 vmalloc_sync_all();
Alan Sterne041c682006-03-27 01:16:30 -080077 return atomic_notifier_chain_register(&die_chain, nb);
Linus Torvalds1da177e2005-04-16 15:20:36 -070078}
Alan Sterne041c682006-03-27 01:16:30 -080079EXPORT_SYMBOL(register_die_notifier);
80
81int unregister_die_notifier(struct notifier_block *nb)
82{
83 return atomic_notifier_chain_unregister(&die_chain, nb);
84}
85EXPORT_SYMBOL(unregister_die_notifier);
Linus Torvalds1da177e2005-04-16 15:20:36 -070086
87static inline void conditional_sti(struct pt_regs *regs)
88{
89 if (regs->eflags & X86_EFLAGS_IF)
90 local_irq_enable();
91}
92
John Blackwooda65d17c2006-02-12 14:34:58 -080093static inline void preempt_conditional_sti(struct pt_regs *regs)
94{
95 preempt_disable();
96 if (regs->eflags & X86_EFLAGS_IF)
97 local_irq_enable();
98}
99
100static inline void preempt_conditional_cli(struct pt_regs *regs)
101{
102 if (regs->eflags & X86_EFLAGS_IF)
103 local_irq_disable();
104 preempt_enable_no_resched();
105}
106
Linus Torvalds1da177e2005-04-16 15:20:36 -0700107static int kstack_depth_to_print = 10;
108
109#ifdef CONFIG_KALLSYMS
110#include <linux/kallsyms.h>
111int printk_address(unsigned long address)
112{
113 unsigned long offset = 0, symsize;
114 const char *symname;
115 char *modname;
116 char *delim = ":";
117 char namebuf[128];
118
119 symname = kallsyms_lookup(address, &symsize, &offset, &modname, namebuf);
120 if (!symname)
121 return printk("[<%016lx>]", address);
122 if (!modname)
123 modname = delim = "";
124 return printk("<%016lx>{%s%s%s%s%+ld}",
Roberto Nibali2b692a82006-03-25 16:29:55 +0100125 address, delim, modname, delim, symname, offset);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700126}
127#else
128int printk_address(unsigned long address)
129{
130 return printk("[<%016lx>]", address);
131}
132#endif
133
Andi Kleen0a658002005-04-16 15:25:17 -0700134static unsigned long *in_exception_stack(unsigned cpu, unsigned long stack,
135 unsigned *usedp, const char **idp)
136{
Jan Beulichb556b352006-01-11 22:43:00 +0100137 static char ids[][8] = {
Andi Kleen0a658002005-04-16 15:25:17 -0700138 [DEBUG_STACK - 1] = "#DB",
139 [NMI_STACK - 1] = "NMI",
140 [DOUBLEFAULT_STACK - 1] = "#DF",
141 [STACKFAULT_STACK - 1] = "#SS",
142 [MCE_STACK - 1] = "#MC",
Jan Beulichb556b352006-01-11 22:43:00 +0100143#if DEBUG_STKSZ > EXCEPTION_STKSZ
144 [N_EXCEPTION_STACKS ... N_EXCEPTION_STACKS + DEBUG_STKSZ / EXCEPTION_STKSZ - 2] = "#DB[?]"
145#endif
Andi Kleen0a658002005-04-16 15:25:17 -0700146 };
147 unsigned k;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700148
Andi Kleen0a658002005-04-16 15:25:17 -0700149 for (k = 0; k < N_EXCEPTION_STACKS; k++) {
150 unsigned long end;
151
Jan Beulichb556b352006-01-11 22:43:00 +0100152 switch (k + 1) {
153#if DEBUG_STKSZ > EXCEPTION_STKSZ
154 case DEBUG_STACK:
Ravikiran G Thirumalaidf79efd2006-01-11 22:45:39 +0100155 end = cpu_pda(cpu)->debugstack + DEBUG_STKSZ;
Jan Beulichb556b352006-01-11 22:43:00 +0100156 break;
157#endif
158 default:
159 end = per_cpu(init_tss, cpu).ist[k];
160 break;
161 }
Andi Kleen0a658002005-04-16 15:25:17 -0700162 if (stack >= end)
163 continue;
164 if (stack >= end - EXCEPTION_STKSZ) {
165 if (*usedp & (1U << k))
166 break;
167 *usedp |= 1U << k;
168 *idp = ids[k];
169 return (unsigned long *)end;
170 }
Jan Beulichb556b352006-01-11 22:43:00 +0100171#if DEBUG_STKSZ > EXCEPTION_STKSZ
172 if (k == DEBUG_STACK - 1 && stack >= end - DEBUG_STKSZ) {
173 unsigned j = N_EXCEPTION_STACKS - 1;
174
175 do {
176 ++j;
177 end -= EXCEPTION_STKSZ;
178 ids[j][4] = '1' + (j - N_EXCEPTION_STACKS);
179 } while (stack < end - EXCEPTION_STKSZ);
180 if (*usedp & (1U << j))
181 break;
182 *usedp |= 1U << j;
183 *idp = ids[j];
184 return (unsigned long *)end;
185 }
186#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -0700187 }
188 return NULL;
Andi Kleen0a658002005-04-16 15:25:17 -0700189}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700190
191/*
192 * x86-64 can have upto three kernel stacks:
193 * process stack
194 * interrupt stack
Andi Kleen0a658002005-04-16 15:25:17 -0700195 * severe exception (double fault, nmi, stack fault, debug, mce) hardware stack
Linus Torvalds1da177e2005-04-16 15:20:36 -0700196 */
197
198void show_trace(unsigned long *stack)
199{
Andi Kleen0a658002005-04-16 15:25:17 -0700200 const unsigned cpu = safe_smp_processor_id();
Ravikiran G Thirumalaidf79efd2006-01-11 22:45:39 +0100201 unsigned long *irqstack_end = (unsigned long *)cpu_pda(cpu)->irqstackptr;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700202 int i;
Andi Kleen0a658002005-04-16 15:25:17 -0700203 unsigned used = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700204
205 printk("\nCall Trace:");
Andi Kleen0a658002005-04-16 15:25:17 -0700206
207#define HANDLE_STACK(cond) \
208 do while (cond) { \
Jan Beulich1b2f6302006-01-11 22:46:45 +0100209 unsigned long addr = *stack++; \
Andi Kleen0a658002005-04-16 15:25:17 -0700210 if (kernel_text_address(addr)) { \
Jan Beulich1b2f6302006-01-11 22:46:45 +0100211 if (i > 50) { \
212 printk("\n "); \
213 i = 0; \
214 } \
215 else \
216 i += printk(" "); \
Andi Kleen0a658002005-04-16 15:25:17 -0700217 /* \
218 * If the address is either in the text segment of the \
219 * kernel, or in the region which contains vmalloc'ed \
220 * memory, it *may* be the address of a calling \
221 * routine; if so, print it so that someone tracing \
222 * down the cause of the crash will be able to figure \
223 * out the call path that was taken. \
224 */ \
225 i += printk_address(addr); \
Andi Kleen0a658002005-04-16 15:25:17 -0700226 } \
227 } while (0)
228
Jan Beulich1b2f6302006-01-11 22:46:45 +0100229 for(i = 11; ; ) {
Andi Kleen0a658002005-04-16 15:25:17 -0700230 const char *id;
231 unsigned long *estack_end;
232 estack_end = in_exception_stack(cpu, (unsigned long)stack,
233 &used, &id);
234
235 if (estack_end) {
Jan Beulich1b2f6302006-01-11 22:46:45 +0100236 i += printk(" <%s>", id);
Andi Kleen0a658002005-04-16 15:25:17 -0700237 HANDLE_STACK (stack < estack_end);
Jan Beulich1b2f6302006-01-11 22:46:45 +0100238 i += printk(" <EOE>");
Andi Kleen0a658002005-04-16 15:25:17 -0700239 stack = (unsigned long *) estack_end[-2];
240 continue;
241 }
242 if (irqstack_end) {
243 unsigned long *irqstack;
244 irqstack = irqstack_end -
245 (IRQSTACKSIZE - 64) / sizeof(*irqstack);
246
247 if (stack >= irqstack && stack < irqstack_end) {
Jan Beulich1b2f6302006-01-11 22:46:45 +0100248 i += printk(" <IRQ>");
Andi Kleen0a658002005-04-16 15:25:17 -0700249 HANDLE_STACK (stack < irqstack_end);
250 stack = (unsigned long *) (irqstack_end[-1]);
251 irqstack_end = NULL;
Jan Beulich1b2f6302006-01-11 22:46:45 +0100252 i += printk(" <EOI>");
Andi Kleen0a658002005-04-16 15:25:17 -0700253 continue;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700254 }
255 }
Andi Kleen0a658002005-04-16 15:25:17 -0700256 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700257 }
Andi Kleen0a658002005-04-16 15:25:17 -0700258
259 HANDLE_STACK (((long) stack & (THREAD_SIZE-1)) != 0);
260#undef HANDLE_STACK
Linus Torvalds1da177e2005-04-16 15:20:36 -0700261 printk("\n");
262}
263
264void show_stack(struct task_struct *tsk, unsigned long * rsp)
265{
266 unsigned long *stack;
267 int i;
268 const int cpu = safe_smp_processor_id();
Ravikiran G Thirumalaidf79efd2006-01-11 22:45:39 +0100269 unsigned long *irqstack_end = (unsigned long *) (cpu_pda(cpu)->irqstackptr);
270 unsigned long *irqstack = (unsigned long *) (cpu_pda(cpu)->irqstackptr - IRQSTACKSIZE);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700271
272 // debugging aid: "show_stack(NULL, NULL);" prints the
273 // back trace for this cpu.
274
275 if (rsp == NULL) {
276 if (tsk)
277 rsp = (unsigned long *)tsk->thread.rsp;
278 else
279 rsp = (unsigned long *)&rsp;
280 }
281
282 stack = rsp;
283 for(i=0; i < kstack_depth_to_print; i++) {
284 if (stack >= irqstack && stack <= irqstack_end) {
285 if (stack == irqstack_end) {
286 stack = (unsigned long *) (irqstack_end[-1]);
287 printk(" <EOI> ");
288 }
289 } else {
290 if (((long) stack & (THREAD_SIZE-1)) == 0)
291 break;
292 }
293 if (i && ((i % 4) == 0))
294 printk("\n ");
295 printk("%016lx ", *stack++);
akpm@osdl.org35faa712005-04-16 15:24:54 -0700296 touch_nmi_watchdog();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700297 }
298 show_trace((unsigned long *)rsp);
299}
300
301/*
302 * The architecture-independent dump_stack generator
303 */
304void dump_stack(void)
305{
306 unsigned long dummy;
307 show_trace(&dummy);
308}
309
310EXPORT_SYMBOL(dump_stack);
311
312void show_registers(struct pt_regs *regs)
313{
314 int i;
Vincent Hanquez76381fe2005-06-23 00:08:46 -0700315 int in_kernel = !user_mode(regs);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700316 unsigned long rsp;
317 const int cpu = safe_smp_processor_id();
Ravikiran G Thirumalaidf79efd2006-01-11 22:45:39 +0100318 struct task_struct *cur = cpu_pda(cpu)->pcurrent;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700319
320 rsp = regs->rsp;
321
322 printk("CPU %d ", cpu);
323 __show_regs(regs);
324 printk("Process %s (pid: %d, threadinfo %p, task %p)\n",
Al Viroe4f17c42006-01-12 01:05:38 -0800325 cur->comm, cur->pid, task_thread_info(cur), cur);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700326
327 /*
328 * When in-kernel, we also print out the stack and code at the
329 * time of the fault..
330 */
331 if (in_kernel) {
332
333 printk("Stack: ");
334 show_stack(NULL, (unsigned long*)rsp);
335
336 printk("\nCode: ");
Roberto Nibali2b692a82006-03-25 16:29:55 +0100337 if (regs->rip < PAGE_OFFSET)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700338 goto bad;
339
Roberto Nibali2b692a82006-03-25 16:29:55 +0100340 for (i=0; i<20; i++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700341 unsigned char c;
Roberto Nibali2b692a82006-03-25 16:29:55 +0100342 if (__get_user(c, &((unsigned char*)regs->rip)[i])) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700343bad:
344 printk(" Bad RIP value.");
345 break;
346 }
347 printk("%02x ", c);
348 }
349 }
350 printk("\n");
351}
352
353void handle_BUG(struct pt_regs *regs)
354{
355 struct bug_frame f;
Jan Beulich5f1d1892006-01-11 22:46:48 +0100356 long len;
357 const char *prefix = "";
Linus Torvalds1da177e2005-04-16 15:20:36 -0700358
Vincent Hanquez76381fe2005-06-23 00:08:46 -0700359 if (user_mode(regs))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700360 return;
Stephen Hemminger77a75332006-01-11 22:46:30 +0100361 if (__copy_from_user(&f, (const void __user *) regs->rip,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700362 sizeof(struct bug_frame)))
363 return;
Jan Beulich049cdef2005-09-12 18:49:25 +0200364 if (f.filename >= 0 ||
Linus Torvalds1da177e2005-04-16 15:20:36 -0700365 f.ud2[0] != 0x0f || f.ud2[1] != 0x0b)
366 return;
Jan Beulich5f1d1892006-01-11 22:46:48 +0100367 len = __strnlen_user((char *)(long)f.filename, PATH_MAX) - 1;
368 if (len < 0 || len >= PATH_MAX)
Jan Beulich049cdef2005-09-12 18:49:25 +0200369 f.filename = (int)(long)"unmapped filename";
Jan Beulich5f1d1892006-01-11 22:46:48 +0100370 else if (len > 50) {
371 f.filename += len - 50;
372 prefix = "...";
373 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700374 printk("----------- [cut here ] --------- [please bite here ] ---------\n");
Jan Beulich5f1d1892006-01-11 22:46:48 +0100375 printk(KERN_ALERT "Kernel BUG at %s%.50s:%d\n", prefix, (char *)(long)f.filename, f.line);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700376}
377
Alexander Nyberg4f60fdf2005-05-25 12:31:28 -0700378#ifdef CONFIG_BUG
Linus Torvalds1da177e2005-04-16 15:20:36 -0700379void out_of_line_bug(void)
380{
381 BUG();
382}
Alexander Nyberg4f60fdf2005-05-25 12:31:28 -0700383#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -0700384
385static DEFINE_SPINLOCK(die_lock);
386static int die_owner = -1;
387
Andi Kleeneddb6fb2006-02-03 21:50:41 +0100388unsigned __kprobes long oops_begin(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700389{
Jan Beulich12091402005-09-12 18:49:24 +0200390 int cpu = safe_smp_processor_id();
391 unsigned long flags;
392
393 /* racy, but better than risking deadlock. */
394 local_irq_save(flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700395 if (!spin_trylock(&die_lock)) {
396 if (cpu == die_owner)
397 /* nested oops. should stop eventually */;
398 else
Jan Beulich12091402005-09-12 18:49:24 +0200399 spin_lock(&die_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700400 }
Jan Beulich12091402005-09-12 18:49:24 +0200401 die_owner = cpu;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700402 console_verbose();
Jan Beulich12091402005-09-12 18:49:24 +0200403 bust_spinlocks(1);
404 return flags;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700405}
406
Andi Kleeneddb6fb2006-02-03 21:50:41 +0100407void __kprobes oops_end(unsigned long flags)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700408{
409 die_owner = -1;
Jan Beulich12091402005-09-12 18:49:24 +0200410 bust_spinlocks(0);
411 spin_unlock_irqrestore(&die_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700412 if (panic_on_oops)
Jan Beulich12091402005-09-12 18:49:24 +0200413 panic("Oops");
414}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700415
Andi Kleeneddb6fb2006-02-03 21:50:41 +0100416void __kprobes __die(const char * str, struct pt_regs * regs, long err)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700417{
418 static int die_counter;
419 printk(KERN_EMERG "%s: %04lx [%u] ", str, err & 0xffff,++die_counter);
420#ifdef CONFIG_PREEMPT
421 printk("PREEMPT ");
422#endif
423#ifdef CONFIG_SMP
424 printk("SMP ");
425#endif
426#ifdef CONFIG_DEBUG_PAGEALLOC
427 printk("DEBUG_PAGEALLOC");
428#endif
429 printk("\n");
Jan Beulich6e3f3612006-01-11 22:42:14 +0100430 notify_die(DIE_OOPS, str, regs, err, current->thread.trap_no, SIGSEGV);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700431 show_registers(regs);
432 /* Executive summary in case the oops scrolled away */
433 printk(KERN_ALERT "RIP ");
434 printk_address(regs->rip);
435 printk(" RSP <%016lx>\n", regs->rsp);
436}
437
438void die(const char * str, struct pt_regs * regs, long err)
439{
Jan Beulich12091402005-09-12 18:49:24 +0200440 unsigned long flags = oops_begin();
441
Linus Torvalds1da177e2005-04-16 15:20:36 -0700442 handle_BUG(regs);
443 __die(str, regs, err);
Jan Beulich12091402005-09-12 18:49:24 +0200444 oops_end(flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700445 do_exit(SIGSEGV);
446}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700447
Andi Kleeneddb6fb2006-02-03 21:50:41 +0100448void __kprobes die_nmi(char *str, struct pt_regs *regs)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700449{
Jan Beulich12091402005-09-12 18:49:24 +0200450 unsigned long flags = oops_begin();
451
Linus Torvalds1da177e2005-04-16 15:20:36 -0700452 /*
453 * We are in trouble anyway, lets at least try
454 * to get a message out.
455 */
456 printk(str, safe_smp_processor_id());
457 show_registers(regs);
458 if (panic_on_timeout || panic_on_oops)
459 panic("nmi watchdog");
460 printk("console shuts up ...\n");
Jan Beulich12091402005-09-12 18:49:24 +0200461 oops_end(flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700462 do_exit(SIGSEGV);
463}
464
Prasanna S Panchamukhi0f2fbdc2005-09-06 15:19:28 -0700465static void __kprobes do_trap(int trapnr, int signr, char *str,
466 struct pt_regs * regs, long error_code,
467 siginfo_t *info)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700468{
Jan Beulich6e3f3612006-01-11 22:42:14 +0100469 struct task_struct *tsk = current;
470
Linus Torvalds1da177e2005-04-16 15:20:36 -0700471 conditional_sti(regs);
472
Jan Beulich6e3f3612006-01-11 22:42:14 +0100473 tsk->thread.error_code = error_code;
474 tsk->thread.trap_no = trapnr;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700475
Jan Beulich6e3f3612006-01-11 22:42:14 +0100476 if (user_mode(regs)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700477 if (exception_trace && unhandled_signal(tsk, signr))
478 printk(KERN_INFO
479 "%s[%d] trap %s rip:%lx rsp:%lx error:%lx\n",
480 tsk->comm, tsk->pid, str,
Roberto Nibali2b692a82006-03-25 16:29:55 +0100481 regs->rip, regs->rsp, error_code);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700482
Linus Torvalds1da177e2005-04-16 15:20:36 -0700483 if (info)
484 force_sig_info(signr, info, tsk);
485 else
486 force_sig(signr, tsk);
487 return;
488 }
489
490
491 /* kernel trap */
492 {
493 const struct exception_table_entry *fixup;
494 fixup = search_exception_tables(regs->rip);
Roberto Nibali2b692a82006-03-25 16:29:55 +0100495 if (fixup)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700496 regs->rip = fixup->fixup;
Roberto Nibali2b692a82006-03-25 16:29:55 +0100497 else
Linus Torvalds1da177e2005-04-16 15:20:36 -0700498 die(str, regs, error_code);
499 return;
500 }
501}
502
503#define DO_ERROR(trapnr, signr, str, name) \
504asmlinkage void do_##name(struct pt_regs * regs, long error_code) \
505{ \
506 if (notify_die(DIE_TRAP, str, regs, error_code, trapnr, signr) \
507 == NOTIFY_STOP) \
508 return; \
509 do_trap(trapnr, signr, str, regs, error_code, NULL); \
510}
511
512#define DO_ERROR_INFO(trapnr, signr, str, name, sicode, siaddr) \
513asmlinkage void do_##name(struct pt_regs * regs, long error_code) \
514{ \
515 siginfo_t info; \
516 info.si_signo = signr; \
517 info.si_errno = 0; \
518 info.si_code = sicode; \
519 info.si_addr = (void __user *)siaddr; \
520 if (notify_die(DIE_TRAP, str, regs, error_code, trapnr, signr) \
521 == NOTIFY_STOP) \
522 return; \
523 do_trap(trapnr, signr, str, regs, error_code, &info); \
524}
525
526DO_ERROR_INFO( 0, SIGFPE, "divide error", divide_error, FPE_INTDIV, regs->rip)
527DO_ERROR( 4, SIGSEGV, "overflow", overflow)
528DO_ERROR( 5, SIGSEGV, "bounds", bounds)
Chuck Ebbert100c0e32006-01-11 22:46:00 +0100529DO_ERROR_INFO( 6, SIGILL, "invalid opcode", invalid_op, ILL_ILLOPN, regs->rip)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700530DO_ERROR( 7, SIGSEGV, "device not available", device_not_available)
531DO_ERROR( 9, SIGFPE, "coprocessor segment overrun", coprocessor_segment_overrun)
532DO_ERROR(10, SIGSEGV, "invalid TSS", invalid_TSS)
533DO_ERROR(11, SIGBUS, "segment not present", segment_not_present)
534DO_ERROR_INFO(17, SIGBUS, "alignment check", alignment_check, BUS_ADRALN, 0)
535DO_ERROR(18, SIGSEGV, "reserved", reserved)
Andi Kleen6fefb0d2005-04-16 15:25:03 -0700536DO_ERROR(12, SIGBUS, "stack segment", stack_segment)
Jan Beulicheca37c12006-01-11 22:42:17 +0100537
538asmlinkage void do_double_fault(struct pt_regs * regs, long error_code)
539{
540 static const char str[] = "double fault";
541 struct task_struct *tsk = current;
542
543 /* Return not checked because double check cannot be ignored */
544 notify_die(DIE_TRAP, str, regs, error_code, 8, SIGSEGV);
545
546 tsk->thread.error_code = error_code;
547 tsk->thread.trap_no = 8;
548
549 /* This is always a kernel trap and never fixable (and thus must
550 never return). */
551 for (;;)
552 die(str, regs, error_code);
553}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700554
Prasanna S Panchamukhi0f2fbdc2005-09-06 15:19:28 -0700555asmlinkage void __kprobes do_general_protection(struct pt_regs * regs,
556 long error_code)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700557{
Jan Beulich6e3f3612006-01-11 22:42:14 +0100558 struct task_struct *tsk = current;
559
Linus Torvalds1da177e2005-04-16 15:20:36 -0700560 conditional_sti(regs);
561
Jan Beulich6e3f3612006-01-11 22:42:14 +0100562 tsk->thread.error_code = error_code;
563 tsk->thread.trap_no = 13;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700564
Jan Beulich6e3f3612006-01-11 22:42:14 +0100565 if (user_mode(regs)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700566 if (exception_trace && unhandled_signal(tsk, SIGSEGV))
567 printk(KERN_INFO
568 "%s[%d] general protection rip:%lx rsp:%lx error:%lx\n",
569 tsk->comm, tsk->pid,
Roberto Nibali2b692a82006-03-25 16:29:55 +0100570 regs->rip, regs->rsp, error_code);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700571
Linus Torvalds1da177e2005-04-16 15:20:36 -0700572 force_sig(SIGSEGV, tsk);
573 return;
574 }
575
576 /* kernel gp */
577 {
578 const struct exception_table_entry *fixup;
579 fixup = search_exception_tables(regs->rip);
580 if (fixup) {
581 regs->rip = fixup->fixup;
582 return;
583 }
584 if (notify_die(DIE_GPF, "general protection fault", regs,
585 error_code, 13, SIGSEGV) == NOTIFY_STOP)
586 return;
587 die("general protection fault", regs, error_code);
588 }
589}
590
Andi Kleeneddb6fb2006-02-03 21:50:41 +0100591static __kprobes void
592mem_parity_error(unsigned char reason, struct pt_regs * regs)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700593{
594 printk("Uhhuh. NMI received. Dazed and confused, but trying to continue\n");
595 printk("You probably have a hardware problem with your RAM chips\n");
596
597 /* Clear and disable the memory parity error line. */
598 reason = (reason & 0xf) | 4;
599 outb(reason, 0x61);
600}
601
Andi Kleeneddb6fb2006-02-03 21:50:41 +0100602static __kprobes void
603io_check_error(unsigned char reason, struct pt_regs * regs)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700604{
605 printk("NMI: IOCK error (debug interrupt?)\n");
606 show_registers(regs);
607
608 /* Re-enable the IOCK line, wait for a few seconds */
609 reason = (reason & 0xf) | 8;
610 outb(reason, 0x61);
611 mdelay(2000);
612 reason &= ~8;
613 outb(reason, 0x61);
614}
615
Andi Kleeneddb6fb2006-02-03 21:50:41 +0100616static __kprobes void
617unknown_nmi_error(unsigned char reason, struct pt_regs * regs)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700618{ printk("Uhhuh. NMI received for unknown reason %02x.\n", reason);
619 printk("Dazed and confused, but trying to continue\n");
620 printk("Do you have a strange power saving mode enabled?\n");
621}
622
Andi Kleen6fefb0d2005-04-16 15:25:03 -0700623/* Runs on IST stack. This code must keep interrupts off all the time.
624 Nested NMIs are prevented by the CPU. */
Andi Kleeneddb6fb2006-02-03 21:50:41 +0100625asmlinkage __kprobes void default_do_nmi(struct pt_regs *regs)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700626{
627 unsigned char reason = 0;
Ashok Raj76e4f662005-06-25 14:55:00 -0700628 int cpu;
629
630 cpu = smp_processor_id();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700631
632 /* Only the BSP gets external NMIs from the system. */
Ashok Raj76e4f662005-06-25 14:55:00 -0700633 if (!cpu)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700634 reason = get_nmi_reason();
635
636 if (!(reason & 0xc0)) {
Jan Beulich6e3f3612006-01-11 22:42:14 +0100637 if (notify_die(DIE_NMI_IPI, "nmi_ipi", regs, reason, 2, SIGINT)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700638 == NOTIFY_STOP)
639 return;
640#ifdef CONFIG_X86_LOCAL_APIC
641 /*
642 * Ok, so this is none of the documented NMI sources,
643 * so it must be the NMI watchdog.
644 */
645 if (nmi_watchdog > 0) {
646 nmi_watchdog_tick(regs,reason);
647 return;
648 }
649#endif
650 unknown_nmi_error(reason, regs);
651 return;
652 }
Jan Beulich6e3f3612006-01-11 22:42:14 +0100653 if (notify_die(DIE_NMI, "nmi", regs, reason, 2, SIGINT) == NOTIFY_STOP)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700654 return;
655
656 /* AK: following checks seem to be broken on modern chipsets. FIXME */
657
658 if (reason & 0x80)
659 mem_parity_error(reason, regs);
660 if (reason & 0x40)
661 io_check_error(reason, regs);
662}
663
Jan Beulichb556b352006-01-11 22:43:00 +0100664/* runs on IST stack. */
Prasanna S Panchamukhi0f2fbdc2005-09-06 15:19:28 -0700665asmlinkage void __kprobes do_int3(struct pt_regs * regs, long error_code)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700666{
667 if (notify_die(DIE_INT3, "int3", regs, error_code, 3, SIGTRAP) == NOTIFY_STOP) {
668 return;
669 }
670 do_trap(3, SIGTRAP, "int3", regs, error_code, NULL);
671 return;
672}
673
Andi Kleen6fefb0d2005-04-16 15:25:03 -0700674/* Help handler running on IST stack to switch back to user stack
675 for scheduling or signal handling. The actual stack switch is done in
676 entry.S */
Andi Kleeneddb6fb2006-02-03 21:50:41 +0100677asmlinkage __kprobes struct pt_regs *sync_regs(struct pt_regs *eregs)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700678{
Andi Kleen6fefb0d2005-04-16 15:25:03 -0700679 struct pt_regs *regs = eregs;
680 /* Did already sync */
681 if (eregs == (struct pt_regs *)eregs->rsp)
682 ;
683 /* Exception from user space */
Vincent Hanquez76381fe2005-06-23 00:08:46 -0700684 else if (user_mode(eregs))
Al Virobb049232006-01-12 01:05:38 -0800685 regs = task_pt_regs(current);
Andi Kleen6fefb0d2005-04-16 15:25:03 -0700686 /* Exception from kernel and interrupts are enabled. Move to
687 kernel process stack. */
688 else if (eregs->eflags & X86_EFLAGS_IF)
689 regs = (struct pt_regs *)(eregs->rsp -= sizeof(struct pt_regs));
690 if (eregs != regs)
691 *regs = *eregs;
692 return regs;
693}
694
695/* runs on IST stack. */
Prasanna S Panchamukhi0f2fbdc2005-09-06 15:19:28 -0700696asmlinkage void __kprobes do_debug(struct pt_regs * regs,
697 unsigned long error_code)
Andi Kleen6fefb0d2005-04-16 15:25:03 -0700698{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700699 unsigned long condition;
700 struct task_struct *tsk = current;
701 siginfo_t info;
702
Vincent Hanqueze9129e52005-06-23 00:08:46 -0700703 get_debugreg(condition, 6);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700704
705 if (notify_die(DIE_DEBUG, "debug", regs, condition, error_code,
Andi Kleendaeeafe2005-04-16 15:25:13 -0700706 SIGTRAP) == NOTIFY_STOP)
Andi Kleen6fefb0d2005-04-16 15:25:03 -0700707 return;
Andi Kleendaeeafe2005-04-16 15:25:13 -0700708
John Blackwooda65d17c2006-02-12 14:34:58 -0800709 preempt_conditional_sti(regs);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700710
711 /* Mask out spurious debug traps due to lazy DR7 setting */
712 if (condition & (DR_TRAP0|DR_TRAP1|DR_TRAP2|DR_TRAP3)) {
713 if (!tsk->thread.debugreg7) {
714 goto clear_dr7;
715 }
716 }
717
718 tsk->thread.debugreg6 = condition;
719
720 /* Mask out spurious TF errors due to lazy TF clearing */
Andi Kleendaeeafe2005-04-16 15:25:13 -0700721 if (condition & DR_STEP) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700722 /*
723 * The TF error should be masked out only if the current
724 * process is not traced and if the TRAP flag has been set
725 * previously by a tracing process (condition detected by
726 * the PT_DTRACE flag); remember that the i386 TRAP flag
727 * can be modified by the process itself in user mode,
728 * allowing programs to debug themselves without the ptrace()
729 * interface.
730 */
Vincent Hanquez76381fe2005-06-23 00:08:46 -0700731 if (!user_mode(regs))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700732 goto clear_TF_reenable;
Andi Kleenbe61bff2005-04-16 15:24:57 -0700733 /*
734 * Was the TF flag set by a debugger? If so, clear it now,
735 * so that register information is correct.
736 */
737 if (tsk->ptrace & PT_DTRACE) {
738 regs->eflags &= ~TF_MASK;
739 tsk->ptrace &= ~PT_DTRACE;
740 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700741 }
742
743 /* Ok, finally something we can handle */
744 tsk->thread.trap_no = 1;
745 tsk->thread.error_code = error_code;
746 info.si_signo = SIGTRAP;
747 info.si_errno = 0;
748 info.si_code = TRAP_BRKPT;
John Blackwood01b8faa2006-01-11 22:44:15 +0100749 info.si_addr = user_mode(regs) ? (void __user *)regs->rip : NULL;
750 force_sig_info(SIGTRAP, &info, tsk);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700751
Linus Torvalds1da177e2005-04-16 15:20:36 -0700752clear_dr7:
Vincent Hanqueze9129e52005-06-23 00:08:46 -0700753 set_debugreg(0UL, 7);
John Blackwooda65d17c2006-02-12 14:34:58 -0800754 preempt_conditional_cli(regs);
Andi Kleen6fefb0d2005-04-16 15:25:03 -0700755 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700756
757clear_TF_reenable:
758 set_tsk_thread_flag(tsk, TIF_SINGLESTEP);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700759 regs->eflags &= ~TF_MASK;
John Blackwooda65d17c2006-02-12 14:34:58 -0800760 preempt_conditional_cli(regs);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700761}
762
Jan Beulich6e3f3612006-01-11 22:42:14 +0100763static int kernel_math_error(struct pt_regs *regs, const char *str, int trapnr)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700764{
765 const struct exception_table_entry *fixup;
766 fixup = search_exception_tables(regs->rip);
767 if (fixup) {
768 regs->rip = fixup->fixup;
769 return 1;
770 }
Jan Beulich6e3f3612006-01-11 22:42:14 +0100771 notify_die(DIE_GPF, str, regs, 0, trapnr, SIGFPE);
Andi Kleen3a848f62005-04-16 15:25:06 -0700772 /* Illegal floating point operation in the kernel */
Jan Beulich6e3f3612006-01-11 22:42:14 +0100773 current->thread.trap_no = trapnr;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700774 die(str, regs, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700775 return 0;
776}
777
778/*
779 * Note that we play around with the 'TS' bit in an attempt to get
780 * the correct behaviour even in the presence of the asynchronous
781 * IRQ13 behaviour
782 */
783asmlinkage void do_coprocessor_error(struct pt_regs *regs)
784{
785 void __user *rip = (void __user *)(regs->rip);
786 struct task_struct * task;
787 siginfo_t info;
788 unsigned short cwd, swd;
789
790 conditional_sti(regs);
Vincent Hanquez76381fe2005-06-23 00:08:46 -0700791 if (!user_mode(regs) &&
Jan Beulich6e3f3612006-01-11 22:42:14 +0100792 kernel_math_error(regs, "kernel x87 math error", 16))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700793 return;
794
795 /*
796 * Save the info for the exception handler and clear the error.
797 */
798 task = current;
799 save_init_fpu(task);
800 task->thread.trap_no = 16;
801 task->thread.error_code = 0;
802 info.si_signo = SIGFPE;
803 info.si_errno = 0;
804 info.si_code = __SI_FAULT;
805 info.si_addr = rip;
806 /*
807 * (~cwd & swd) will mask out exceptions that are not set to unmasked
808 * status. 0x3f is the exception bits in these regs, 0x200 is the
809 * C1 reg you need in case of a stack fault, 0x040 is the stack
810 * fault bit. We should only be taking one exception at a time,
811 * so if this combination doesn't produce any single exception,
812 * then we have a bad program that isn't synchronizing its FPU usage
813 * and it will suffer the consequences since we won't be able to
814 * fully reproduce the context of the exception
815 */
816 cwd = get_fpu_cwd(task);
817 swd = get_fpu_swd(task);
Chuck Ebbertff347b22005-09-12 18:49:25 +0200818 switch (swd & ~cwd & 0x3f) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700819 case 0x000:
820 default:
821 break;
822 case 0x001: /* Invalid Op */
Chuck Ebbertff347b22005-09-12 18:49:25 +0200823 /*
824 * swd & 0x240 == 0x040: Stack Underflow
825 * swd & 0x240 == 0x240: Stack Overflow
826 * User must clear the SF bit (0x40) if set
827 */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700828 info.si_code = FPE_FLTINV;
829 break;
830 case 0x002: /* Denormalize */
831 case 0x010: /* Underflow */
832 info.si_code = FPE_FLTUND;
833 break;
834 case 0x004: /* Zero Divide */
835 info.si_code = FPE_FLTDIV;
836 break;
837 case 0x008: /* Overflow */
838 info.si_code = FPE_FLTOVF;
839 break;
840 case 0x020: /* Precision */
841 info.si_code = FPE_FLTRES;
842 break;
843 }
844 force_sig_info(SIGFPE, &info, task);
845}
846
847asmlinkage void bad_intr(void)
848{
849 printk("bad interrupt");
850}
851
852asmlinkage void do_simd_coprocessor_error(struct pt_regs *regs)
853{
854 void __user *rip = (void __user *)(regs->rip);
855 struct task_struct * task;
856 siginfo_t info;
857 unsigned short mxcsr;
858
859 conditional_sti(regs);
Vincent Hanquez76381fe2005-06-23 00:08:46 -0700860 if (!user_mode(regs) &&
Jan Beulich6e3f3612006-01-11 22:42:14 +0100861 kernel_math_error(regs, "kernel simd math error", 19))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700862 return;
863
864 /*
865 * Save the info for the exception handler and clear the error.
866 */
867 task = current;
868 save_init_fpu(task);
869 task->thread.trap_no = 19;
870 task->thread.error_code = 0;
871 info.si_signo = SIGFPE;
872 info.si_errno = 0;
873 info.si_code = __SI_FAULT;
874 info.si_addr = rip;
875 /*
876 * The SIMD FPU exceptions are handled a little differently, as there
877 * is only a single status/control register. Thus, to determine which
878 * unmasked exception was caught we must mask the exception mask bits
879 * at 0x1f80, and then use these to mask the exception bits at 0x3f.
880 */
881 mxcsr = get_fpu_mxcsr(task);
882 switch (~((mxcsr & 0x1f80) >> 7) & (mxcsr & 0x3f)) {
883 case 0x000:
884 default:
885 break;
886 case 0x001: /* Invalid Op */
887 info.si_code = FPE_FLTINV;
888 break;
889 case 0x002: /* Denormalize */
890 case 0x010: /* Underflow */
891 info.si_code = FPE_FLTUND;
892 break;
893 case 0x004: /* Zero Divide */
894 info.si_code = FPE_FLTDIV;
895 break;
896 case 0x008: /* Overflow */
897 info.si_code = FPE_FLTOVF;
898 break;
899 case 0x020: /* Precision */
900 info.si_code = FPE_FLTRES;
901 break;
902 }
903 force_sig_info(SIGFPE, &info, task);
904}
905
906asmlinkage void do_spurious_interrupt_bug(struct pt_regs * regs)
907{
908}
909
910asmlinkage void __attribute__((weak)) smp_thermal_interrupt(void)
911{
912}
913
Jacob Shin89b831e2005-11-05 17:25:53 +0100914asmlinkage void __attribute__((weak)) mce_threshold_interrupt(void)
915{
916}
917
Linus Torvalds1da177e2005-04-16 15:20:36 -0700918/*
919 * 'math_state_restore()' saves the current math information in the
920 * old math state array, and gets the new ones from the current task
921 *
922 * Careful.. There are problems with IBM-designed IRQ13 behaviour.
923 * Don't touch unless you *really* know how it works.
924 */
925asmlinkage void math_state_restore(void)
926{
927 struct task_struct *me = current;
928 clts(); /* Allow maths ops (or we recurse) */
929
930 if (!used_math())
931 init_fpu(me);
932 restore_fpu_checking(&me->thread.i387.fxsave);
Al Viroe4f17c42006-01-12 01:05:38 -0800933 task_thread_info(me)->status |= TS_USEDFPU;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700934}
935
Linus Torvalds1da177e2005-04-16 15:20:36 -0700936void __init trap_init(void)
937{
938 set_intr_gate(0,&divide_error);
939 set_intr_gate_ist(1,&debug,DEBUG_STACK);
940 set_intr_gate_ist(2,&nmi,NMI_STACK);
Jan Beulichb556b352006-01-11 22:43:00 +0100941 set_system_gate_ist(3,&int3,DEBUG_STACK); /* int3 can be called from all */
Jan Beulich0a521582006-01-11 22:42:08 +0100942 set_system_gate(4,&overflow); /* int4 can be called from all */
943 set_intr_gate(5,&bounds);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700944 set_intr_gate(6,&invalid_op);
945 set_intr_gate(7,&device_not_available);
946 set_intr_gate_ist(8,&double_fault, DOUBLEFAULT_STACK);
947 set_intr_gate(9,&coprocessor_segment_overrun);
948 set_intr_gate(10,&invalid_TSS);
949 set_intr_gate(11,&segment_not_present);
950 set_intr_gate_ist(12,&stack_segment,STACKFAULT_STACK);
951 set_intr_gate(13,&general_protection);
952 set_intr_gate(14,&page_fault);
953 set_intr_gate(15,&spurious_interrupt_bug);
954 set_intr_gate(16,&coprocessor_error);
955 set_intr_gate(17,&alignment_check);
956#ifdef CONFIG_X86_MCE
957 set_intr_gate_ist(18,&machine_check, MCE_STACK);
958#endif
959 set_intr_gate(19,&simd_coprocessor_error);
960
961#ifdef CONFIG_IA32_EMULATION
962 set_system_gate(IA32_SYSCALL_VECTOR, ia32_syscall);
963#endif
964
Linus Torvalds1da177e2005-04-16 15:20:36 -0700965 /*
966 * Should be a barrier for any external CPU state.
967 */
968 cpu_init();
969}
970
971
972/* Actual parsing is done early in setup.c. */
973static int __init oops_dummy(char *s)
974{
975 panic_on_oops = 1;
976 return -1;
977}
978__setup("oops=", oops_dummy);
979
980static int __init kstack_setup(char *s)
981{
982 kstack_depth_to_print = simple_strtoul(s,NULL,0);
983 return 0;
984}
985__setup("kstack=", kstack_setup);
986