~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

Linux Cross Reference
Linux/arch/i386/kernel/traps.c

Version: ~ [ 2.2.5 ] ~ [ 2.4.1 ] ~ [ 2.4.9 ] ~ [ 2.6.17.10 ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 /*
  2  *  linux/arch/i386/traps.c
  3  *
  4  *  Copyright (C) 1991, 1992  Linus Torvalds
  5  *
  6  *  Pentium III FXSR, SSE support
  7  *      Gareth Hughes <gareth@valinux.com>, May 2000
  8  */
  9 
 10 /*
 11  * 'Traps.c' handles hardware traps and faults after we have saved some
 12  * state in 'asm.s'.
 13  */
 14 #include <linux/config.h>
 15 #include <linux/sched.h>
 16 #include <linux/kernel.h>
 17 #include <linux/string.h>
 18 #include <linux/errno.h>
 19 #include <linux/ptrace.h>
 20 #include <linux/timer.h>
 21 #include <linux/mm.h>
 22 #include <linux/init.h>
 23 #include <linux/delay.h>
 24 #include <linux/spinlock.h>
 25 #include <linux/interrupt.h>
 26 #include <linux/highmem.h>
 27 
 28 #ifdef CONFIG_MCA
 29 #include <linux/mca.h>
 30 #include <asm/processor.h>
 31 #endif
 32 
 33 #include <asm/system.h>
 34 #include <asm/uaccess.h>
 35 #include <asm/io.h>
 36 #include <asm/atomic.h>
 37 #include <asm/debugreg.h>
 38 #include <asm/desc.h>
 39 #include <asm/i387.h>
 40 
 41 #include <asm/smp.h>
 42 #include <asm/pgalloc.h>
 43 
 44 #ifdef CONFIG_X86_VISWS_APIC
 45 #include <asm/fixmap.h>
 46 #include <asm/cobalt.h>
 47 #include <asm/lithium.h>
 48 #endif
 49 
 50 #include <linux/irq.h>
 51 
 52 asmlinkage int system_call(void);
 53 asmlinkage void lcall7(void);
 54 asmlinkage void lcall27(void);
 55 
 56 struct desc_struct default_ldt[] = { { 0, 0 }, { 0, 0 }, { 0, 0 },
 57                 { 0, 0 }, { 0, 0 } };
 58 
 59 /*
 60  * The IDT has to be page-aligned to simplify the Pentium
 61  * F0 0F bug workaround.. We have a special link segment
 62  * for this.
 63  */
 64 struct desc_struct idt_table[256] __attribute__((__section__(".data.idt"))) = { {0, 0}, };
 65 
 66 extern void bust_spinlocks(void);
 67 
 68 asmlinkage void divide_error(void);
 69 asmlinkage void debug(void);
 70 asmlinkage void nmi(void);
 71 asmlinkage void int3(void);
 72 asmlinkage void overflow(void);
 73 asmlinkage void bounds(void);
 74 asmlinkage void invalid_op(void);
 75 asmlinkage void device_not_available(void);
 76 asmlinkage void double_fault(void);
 77 asmlinkage void coprocessor_segment_overrun(void);
 78 asmlinkage void invalid_TSS(void);
 79 asmlinkage void segment_not_present(void);
 80 asmlinkage void stack_segment(void);
 81 asmlinkage void general_protection(void);
 82 asmlinkage void page_fault(void);
 83 asmlinkage void coprocessor_error(void);
 84 asmlinkage void simd_coprocessor_error(void);
 85 asmlinkage void alignment_check(void);
 86 asmlinkage void spurious_interrupt_bug(void);
 87 asmlinkage void machine_check(void);
 88 
 89 int kstack_depth_to_print = 24;
 90 
 91 /*
 92  * These constants are for searching for possible module text
 93  * segments.
 94  */
 95 
 96 void show_trace(unsigned long * stack)
 97 {
 98         int i;
 99         unsigned long addr, module_start, module_end;
100 
101         if (!stack)
102                 stack = (unsigned long*)&stack;
103 
104         printk("Call Trace: ");
105         i = 1;
106         module_start = VMALLOC_START;
107         module_end = VMALLOC_END;
108         while (((long) stack & (THREAD_SIZE-1)) != 0) {
109                 addr = *stack++;
110                 /*
111                  * If the address is either in the text segment of the
112                  * kernel, or in the region which contains vmalloc'ed
113                  * memory, it *may* be the address of a calling
114                  * routine; if so, print it so that someone tracing
115                  * down the cause of the crash will be able to figure
116                  * out the call path that was taken.
117                  */
118                 if (((addr >= (unsigned long) &_stext) &&
119                      (addr <= (unsigned long) &_etext)) ||
120                     ((addr >= module_start) && (addr <= module_end))) {
121                         if (i && ((i % 8) == 0))
122                                 printk("\n       ");
123                         printk("[<%08lx>] ", addr);
124                         i++;
125                 }
126         }
127         printk("\n");
128 }
129 
130 void show_stack(unsigned long * esp)
131 {
132         unsigned long *stack;
133         int i;
134 
135         // debugging aid: "show_stack(NULL);" prints the
136         // back trace for this cpu.
137 
138         if(esp==NULL)
139                 esp=(unsigned long*)&esp;
140 
141         stack = esp;
142         for(i=0; i < kstack_depth_to_print; i++) {
143                 if (((long) stack & (THREAD_SIZE-1)) == 0)
144                         break;
145                 if (i && ((i % 8) == 0))
146                         printk("\n       ");
147                 printk("%08lx ", *stack++);
148         }
149         printk("\n");
150         show_trace(esp);
151 }
152 
153 static void show_registers(struct pt_regs *regs)
154 {
155         int i;
156         int in_kernel = 1;
157         unsigned long esp;
158         unsigned short ss;
159 
160         esp = (unsigned long) (&regs->esp);
161         ss = __KERNEL_DS;
162         if (regs->xcs & 3) {
163                 in_kernel = 0;
164                 esp = regs->esp;
165                 ss = regs->xss & 0xffff;
166         }
167         printk("CPU:    %d\nEIP:    %04x:[<%08lx>]\nEFLAGS: %08lx\n",
168                 smp_processor_id(), 0xffff & regs->xcs, regs->eip, regs->eflags);
169         printk("eax: %08lx   ebx: %08lx   ecx: %08lx   edx: %08lx\n",
170                 regs->eax, regs->ebx, regs->ecx, regs->edx);
171         printk("esi: %08lx   edi: %08lx   ebp: %08lx   esp: %08lx\n",
172                 regs->esi, regs->edi, regs->ebp, esp);
173         printk("ds: %04x   es: %04x   ss: %04x\n",
174                 regs->xds & 0xffff, regs->xes & 0xffff, ss);
175         printk("Process %s (pid: %d, stackpage=%08lx)",
176                 current->comm, current->pid, 4096+(unsigned long)current);
177         /*
178          * When in-kernel, we also print out the stack and code at the
179          * time of the fault..
180          */
181         if (in_kernel) {
182 
183                 printk("\nStack: ");
184                 show_stack((unsigned long*)esp);
185 
186                 printk("\nCode: ");
187                 if(regs->eip < PAGE_OFFSET)
188                         goto bad;
189 
190                 for(i=0;i<20;i++)
191                 {
192                         unsigned char c;
193                         if(__get_user(c, &((unsigned char*)regs->eip)[i])) {
194 bad:
195                                 printk(" Bad EIP value.");
196                                 break;
197                         }
198                         printk("%02x ", c);
199                 }
200         }
201         printk("\n");
202 }       
203 
204 spinlock_t die_lock = SPIN_LOCK_UNLOCKED;
205 
206 void die(const char * str, struct pt_regs * regs, long err)
207 {
208         console_verbose();
209         spin_lock_irq(&die_lock);
210         printk("%s: %04lx\n", str, err & 0xffff);
211         show_registers(regs);
212 
213         spin_unlock_irq(&die_lock);
214         do_exit(SIGSEGV);
215 }
216 
217 static inline void die_if_kernel(const char * str, struct pt_regs * regs, long err)
218 {
219         if (!(regs->eflags & VM_MASK) && !(3 & regs->xcs))
220                 die(str, regs, err);
221 }
222 
223 static inline unsigned long get_cr2(void)
224 {
225         unsigned long address;
226 
227         /* get the address */
228         __asm__("movl %%cr2,%0":"=r" (address));
229         return address;
230 }
231 
232 static void inline do_trap(int trapnr, int signr, char *str, int vm86,
233                            struct pt_regs * regs, long error_code, siginfo_t *info)
234 {
235         if (vm86 && regs->eflags & VM_MASK)
236                 goto vm86_trap;
237         if (!(regs->xcs & 3))
238                 goto kernel_trap;
239 
240         trap_signal: {
241                 struct task_struct *tsk = current;
242                 tsk->thread.error_code = error_code;
243                 tsk->thread.trap_no = trapnr;
244                 if (info)
245                         force_sig_info(signr, info, tsk);
246                 else
247                         force_sig(signr, tsk);
248                 return;
249         }
250 
251         kernel_trap: {
252                 unsigned long fixup = search_exception_table(regs->eip);
253                 if (fixup)
254                         regs->eip = fixup;
255                 else    
256                         die(str, regs, error_code);
257                 return;
258         }
259 
260         vm86_trap: {
261                 int ret = handle_vm86_trap((struct kernel_vm86_regs *) regs, error_code, trapnr);
262                 if (ret) goto trap_signal;
263                 return;
264         }
265 }
266 
267 #define DO_ERROR(trapnr, signr, str, name) \
268 asmlinkage void do_##name(struct pt_regs * regs, long error_code) \
269 { \
270         do_trap(trapnr, signr, str, 0, regs, error_code, NULL); \
271 }
272 
273 #define DO_ERROR_INFO(trapnr, signr, str, name, sicode, siaddr) \
274 asmlinkage void do_##name(struct pt_regs * regs, long error_code) \
275 { \
276         siginfo_t info; \
277         info.si_signo = signr; \
278         info.si_errno = 0; \
279         info.si_code = sicode; \
280         info.si_addr = (void *)siaddr; \
281         do_trap(trapnr, signr, str, 0, regs, error_code, &info); \
282 }
283 
284 #define DO_VM86_ERROR(trapnr, signr, str, name) \
285 asmlinkage void do_##name(struct pt_regs * regs, long error_code) \
286 { \
287         do_trap(trapnr, signr, str, 1, regs, error_code, NULL); \
288 }
289 
290 #define DO_VM86_ERROR_INFO(trapnr, signr, str, name, sicode, siaddr) \
291 asmlinkage void do_##name(struct pt_regs * regs, long error_code) \
292 { \
293         siginfo_t info; \
294         info.si_signo = signr; \
295         info.si_errno = 0; \
296         info.si_code = sicode; \
297         info.si_addr = (void *)siaddr; \
298         do_trap(trapnr, signr, str, 1, regs, error_code, &info); \
299 }
300 
301 DO_VM86_ERROR_INFO( 0, SIGFPE,  "divide error", divide_error, FPE_INTDIV, regs->eip)
302 DO_VM86_ERROR( 3, SIGTRAP, "int3", int3)
303 DO_VM86_ERROR( 4, SIGSEGV, "overflow", overflow)
304 DO_VM86_ERROR( 5, SIGSEGV, "bounds", bounds)
305 DO_ERROR_INFO( 6, SIGILL,  "invalid operand", invalid_op, ILL_ILLOPN, regs->eip)
306 DO_VM86_ERROR( 7, SIGSEGV, "device not available", device_not_available)
307 DO_ERROR( 8, SIGSEGV, "double fault", double_fault)
308 DO_ERROR( 9, SIGFPE,  "coprocessor segment overrun", coprocessor_segment_overrun)
309 DO_ERROR(10, SIGSEGV, "invalid TSS", invalid_TSS)
310 DO_ERROR(11, SIGBUS,  "segment not present", segment_not_present)
311 DO_ERROR(12, SIGBUS,  "stack segment", stack_segment)
312 DO_ERROR_INFO(17, SIGBUS, "alignment check", alignment_check, BUS_ADRALN, get_cr2())
313 
314 asmlinkage void do_general_protection(struct pt_regs * regs, long error_code)
315 {
316         if (regs->eflags & VM_MASK)
317                 goto gp_in_vm86;
318 
319         if (!(regs->xcs & 3))
320                 goto gp_in_kernel;
321 
322         current->thread.error_code = error_code;
323         current->thread.trap_no = 13;
324         force_sig(SIGSEGV, current);
325         return;
326 
327 gp_in_vm86:
328         handle_vm86_fault((struct kernel_vm86_regs *) regs, error_code);
329         return;
330 
331 gp_in_kernel:
332         {
333                 unsigned long fixup;
334                 fixup = search_exception_table(regs->eip);
335                 if (fixup) {
336                         regs->eip = fixup;
337                         return;
338                 }
339                 die("general protection fault", regs, error_code);
340         }
341 }
342 
343 static void mem_parity_error(unsigned char reason, struct pt_regs * regs)
344 {
345         printk("Uhhuh. NMI received. Dazed and confused, but trying to continue\n");
346         printk("You probably have a hardware problem with your RAM chips\n");
347 
348         /* Clear and disable the memory parity error line. */
349         reason = (reason & 0xf) | 4;
350         outb(reason, 0x61);
351 }
352 
353 static void io_check_error(unsigned char reason, struct pt_regs * regs)
354 {
355         unsigned long i;
356 
357         printk("NMI: IOCK error (debug interrupt?)\n");
358         show_registers(regs);
359 
360         /* Re-enable the IOCK line, wait for a few seconds */
361         reason = (reason & 0xf) | 8;
362         outb(reason, 0x61);
363         i = 2000;
364         while (--i) udelay(1000);
365         reason &= ~8;
366         outb(reason, 0x61);
367 }
368 
369 static void unknown_nmi_error(unsigned char reason, struct pt_regs * regs)
370 {
371 #ifdef CONFIG_MCA
372         /* Might actually be able to figure out what the guilty party
373         * is. */
374         if( MCA_bus ) {
375                 mca_handle_nmi();
376                 return;
377         }
378 #endif
379         printk("Uhhuh. NMI received for unknown reason %02x.\n", reason);
380         printk("Dazed and confused, but trying to continue\n");
381         printk("Do you have a strange power saving mode enabled?\n");
382 }
383 
384 #if CONFIG_X86_IO_APIC
385 
386 int nmi_watchdog = 1;
387 
388 static int __init setup_nmi_watchdog(char *str)
389 {
390         get_option(&str, &nmi_watchdog);
391         return 1;
392 }
393 
394 __setup("nmi_watchdog=", setup_nmi_watchdog);
395 
396 static spinlock_t nmi_print_lock = SPIN_LOCK_UNLOCKED;
397 
398 inline void nmi_watchdog_tick(struct pt_regs * regs)
399 {
400         /*
401          * the best way to detect wether a CPU has a 'hard lockup' problem
402          * is to check it's local APIC timer IRQ counts. If they are not
403          * changing then that CPU has some problem.
404          *
405          * as these watchdog NMI IRQs are broadcasted to every CPU, here
406          * we only have to check the current processor.
407          *
408          * since NMIs dont listen to _any_ locks, we have to be extremely
409          * careful not to rely on unsafe variables. The printk might lock
410          * up though, so we have to break up console_lock first ...
411          * [when there will be more tty-related locks, break them up
412          *  here too!]
413          */
414 
415         static unsigned int last_irq_sums [NR_CPUS],
416                                 alert_counter [NR_CPUS];
417 
418         /*
419          * Since current-> is always on the stack, and we always switch
420          * the stack NMI-atomically, it's safe to use smp_processor_id().
421          */
422         int sum, cpu = smp_processor_id();
423 
424         sum = apic_timer_irqs[cpu];
425 
426         if (last_irq_sums[cpu] == sum) {
427                 /*
428                  * Ayiee, looks like this CPU is stuck ...
429                  * wait a few IRQs (5 seconds) before doing the oops ...
430                  */
431                 alert_counter[cpu]++;
432                 if (alert_counter[cpu] == 5*HZ) {
433                         spin_lock(&nmi_print_lock);
434                         /*
435                          * We are in trouble anyway, lets at least try
436                          * to get a message out.
437                          */
438                         bust_spinlocks();
439                         printk("NMI Watchdog detected LOCKUP on CPU%d, registers:\n", cpu);
440                         show_registers(regs);
441                         printk("console shuts up ...\n");
442                         console_silent();
443                         spin_unlock(&nmi_print_lock);
444                         do_exit(SIGSEGV);
445                 }
446         } else {
447                 last_irq_sums[cpu] = sum;
448                 alert_counter[cpu] = 0;
449         }
450 }
451 #endif
452 
453 asmlinkage void do_nmi(struct pt_regs * regs, long error_code)
454 {
455         unsigned char reason = inb(0x61);
456 
457 
458         ++nmi_count(smp_processor_id());
459         if (!(reason & 0xc0)) {
460 #if CONFIG_X86_IO_APIC
461                 /*
462                  * Ok, so this is none of the documented NMI sources,
463                  * so it must be the NMI watchdog.
464                  */
465                 if (nmi_watchdog) {
466                         nmi_watchdog_tick(regs);
467                         return;
468                 } else
469                         unknown_nmi_error(reason, regs);
470 #else
471                 unknown_nmi_error(reason, regs);
472 #endif
473                 return;
474         }
475         if (reason & 0x80)
476                 mem_parity_error(reason, regs);
477         if (reason & 0x40)
478                 io_check_error(reason, regs);
479         /*
480          * Reassert NMI in case it became active meanwhile
481          * as it's edge-triggered.
482          */
483         outb(0x8f, 0x70);
484         inb(0x71);              /* dummy */
485         outb(0x0f, 0x70);
486         inb(0x71);              /* dummy */
487 }
488 
489 /*
490  * Our handling of the processor debug registers is non-trivial.
491  * We do not clear them on entry and exit from the kernel. Therefore
492  * it is possible to get a watchpoint trap here from inside the kernel.
493  * However, the code in ./ptrace.c has ensured that the user can
494  * only set watchpoints on userspace addresses. Therefore the in-kernel
495  * watchpoint trap can only occur in code which is reading/writing
496  * from user space. Such code must not hold kernel locks (since it
497  * can equally take a page fault), therefore it is safe to call
498  * force_sig_info even though that claims and releases locks.
499  * 
500  * Code in ./signal.c ensures that the debug control register
501  * is restored before we deliver any signal, and therefore that
502  * user code runs with the correct debug control register even though
503  * we clear it here.
504  *
505  * Being careful here means that we don't have to be as careful in a
506  * lot of more complicated places (task switching can be a bit lazy
507  * about restoring all the debug state, and ptrace doesn't have to
508  * find every occurrence of the TF bit that could be saved away even
509  * by user code)
510  */
511 asmlinkage void do_debug(struct pt_regs * regs, long error_code)
512 {
513         unsigned int condition;
514         struct task_struct *tsk = current;
515         siginfo_t info;
516 
517         __asm__ __volatile__("movl %%db6,%0" : "=r" (condition));
518 
519         /* Mask out spurious debug traps due to lazy DR7 setting */
520         if (condition & (DR_TRAP0|DR_TRAP1|DR_TRAP2|DR_TRAP3)) {
521                 if (!tsk->thread.debugreg[7])
522                         goto clear_dr7;
523         }
524 
525         if (regs->eflags & VM_MASK)
526                 goto debug_vm86;
527 
528         /* Save debug status register where ptrace can see it */
529         tsk->thread.debugreg[6] = condition;
530 
531         /* Mask out spurious TF errors due to lazy TF clearing */
532         if (condition & DR_STEP) {
533                 /*
534                  * The TF error should be masked out only if the current
535                  * process is not traced and if the TRAP flag has been set
536                  * previously by a tracing process (condition detected by
537                  * the PT_DTRACE flag); remember that the i386 TRAP flag
538                  * can be modified by the process itself in user mode,
539                  * allowing programs to debug themselves without the ptrace()
540                  * interface.
541                  */
542                 if ((tsk->ptrace & (PT_DTRACE|PT_PTRACED)) == PT_DTRACE)
543                         goto clear_TF;
544         }
545 
546         /* Ok, finally something we can handle */
547         tsk->thread.trap_no = 1;
548         tsk->thread.error_code = error_code;
549         info.si_signo = SIGTRAP;
550         info.si_errno = 0;
551         info.si_code = TRAP_BRKPT;
552         
553         /* If this is a kernel mode trap, save the user PC on entry to 
554          * the kernel, that's what the debugger can make sense of.
555          */
556         info.si_addr = ((regs->xcs & 3) == 0) ? (void *)tsk->thread.eip : 
557                                                 (void *)regs->eip;
558         force_sig_info(SIGTRAP, &info, tsk);
559 
560         /* Disable additional traps. They'll be re-enabled when
561          * the signal is delivered.
562          */
563 clear_dr7:
564         __asm__("movl %0,%%db7"
565                 : /* no output */
566                 : "r" (0));
567         return;
568 
569 debug_vm86:
570         handle_vm86_trap((struct kernel_vm86_regs *) regs, error_code, 1);
571         return;
572 
573 clear_TF:
574         regs->eflags &= ~TF_MASK;
575         return;
576 }
577 
578 /*
579  * Note that we play around with the 'TS' bit in an attempt to get
580  * the correct behaviour even in the presence of the asynchronous
581  * IRQ13 behaviour
582  */
583 void math_error(void *eip)
584 {
585         struct task_struct * task;
586         siginfo_t info;
587         unsigned short cwd, swd;
588 
589         /*
590          * Save the info for the exception handler and clear the error.
591          */
592         task = current;
593         save_init_fpu(task);
594         task->thread.trap_no = 16;
595         task->thread.error_code = 0;
596         info.si_signo = SIGFPE;
597         info.si_errno = 0;
598         info.si_code = __SI_FAULT;
599         info.si_addr = eip;
600         /*
601          * (~cwd & swd) will mask out exceptions that are not set to unmasked
602          * status.  0x3f is the exception bits in these regs, 0x200 is the
603          * C1 reg you need in case of a stack fault, 0x040 is the stack
604          * fault bit.  We should only be taking one exception at a time,
605          * so if this combination doesn't produce any single exception,
606          * then we have a bad program that isn't syncronizing its FPU usage
607          * and it will suffer the consequences since we won't be able to
608          * fully reproduce the context of the exception
609          */
610         cwd = get_fpu_cwd(task);
611         swd = get_fpu_swd(task);
612         switch (((~cwd) & swd & 0x3f) | (swd & 0x240)) {
613                 case 0x000:
614                 default:
615                         break;
616                 case 0x001: /* Invalid Op */
617                 case 0x040: /* Stack Fault */
618                 case 0x240: /* Stack Fault | Direction */
619                         info.si_code = FPE_FLTINV;
620                         break;
621                 case 0x002: /* Denormalize */
622                 case 0x010: /* Underflow */
623                         info.si_code = FPE_FLTUND;
624                         break;
625                 case 0x004: /* Zero Divide */
626                         info.si_code = FPE_FLTDIV;
627                         break;
628                 case 0x008: /* Overflow */
629                         info.si_code = FPE_FLTOVF;
630                         break;
631                 case 0x020: /* Precision */
632                         info.si_code = FPE_FLTRES;
633                         break;
634         }
635         force_sig_info(SIGFPE, &info, task);
636 }
637 
638 asmlinkage void do_coprocessor_error(struct pt_regs * regs, long error_code)
639 {
640         ignore_irq13 = 1;
641         math_error((void *)regs->eip);
642 }
643 
644 void simd_math_error(void *eip)
645 {
646         struct task_struct * task;
647         siginfo_t info;
648         unsigned short mxcsr;
649 
650         /*
651          * Save the info for the exception handler and clear the error.
652          */
653         task = current;
654         save_init_fpu(task);
655         task->thread.trap_no = 19;
656         task->thread.error_code = 0;
657         info.si_signo = SIGFPE;
658         info.si_errno = 0;
659         info.si_code = __SI_FAULT;
660         info.si_addr = eip;
661         /*
662          * The SIMD FPU exceptions are handled a little differently, as there
663          * is only a single status/control register.  Thus, to determine which
664          * unmasked exception was caught we must mask the exception mask bits
665          * at 0x1f80, and then use these to mask the exception bits at 0x3f.
666          */
667         mxcsr = get_fpu_mxcsr(task);
668         switch (~((mxcsr & 0x1f80) >> 7) & (mxcsr & 0x3f)) {
669                 case 0x000:
670                 default:
671                         break;
672                 case 0x001: /* Invalid Op */
673                         info.si_code = FPE_FLTINV;
674                         break;
675                 case 0x002: /* Denormalize */
676                 case 0x010: /* Underflow */
677                         info.si_code = FPE_FLTUND;
678                         break;
679                 case 0x004: /* Zero Divide */
680                         info.si_code = FPE_FLTDIV;
681                         break;
682                 case 0x008: /* Overflow */
683                         info.si_code = FPE_FLTOVF;
684                         break;
685                 case 0x020: /* Precision */
686                         info.si_code = FPE_FLTRES;
687                         break;
688         }
689         force_sig_info(SIGFPE, &info, task);
690 }
691 
692 asmlinkage void do_simd_coprocessor_error(struct pt_regs * regs,
693                                           long error_code)
694 {
695         if (cpu_has_xmm) {
696                 /* Handle SIMD FPU exceptions on PIII+ processors. */
697                 ignore_irq13 = 1;
698                 simd_math_error((void *)regs->eip);
699         } else {
700                 /*
701                  * Handle strange cache flush from user space exception
702                  * in all other cases.  This is undocumented behaviour.
703                  */
704                 if (regs->eflags & VM_MASK) {
705                         handle_vm86_fault((struct kernel_vm86_regs *)regs,
706                                           error_code);
707                         return;
708                 }
709                 die_if_kernel("cache flush denied", regs, error_code);
710                 current->thread.trap_no = 19;
711                 current->thread.error_code = error_code;
712                 force_sig(SIGSEGV, current);
713         }
714 }
715 
716 asmlinkage void do_spurious_interrupt_bug(struct pt_regs * regs,
717                                           long error_code)
718 {
719 #if 0
720         /* No need to warn about this any longer. */
721         printk("Ignoring P6 Local APIC Spurious Interrupt Bug...\n");
722 #endif
723 }
724 
725 /*
726  *  'math_state_restore()' saves the current math information in the
727  * old math state array, and gets the new ones from the current task
728  *
729  * Careful.. There are problems with IBM-designed IRQ13 behaviour.
730  * Don't touch unless you *really* know how it works.
731  */
732 asmlinkage void math_state_restore(struct pt_regs regs)
733 {
734         __asm__ __volatile__("clts");           /* Allow maths ops (or we recurse) */
735 
736         if (current->used_math) {
737                 restore_fpu(current);
738         } else {
739                 init_fpu();
740         }
741         current->flags |= PF_USEDFPU;   /* So we fnsave on switch_to() */
742 }
743 
744 #ifndef CONFIG_MATH_EMULATION
745 
746 asmlinkage void math_emulate(long arg)
747 {
748         printk("math-emulation not enabled and no coprocessor found.\n");
749         printk("killing %s.\n",current->comm);
750         force_sig(SIGFPE,current);
751         schedule();
752 }
753 
754 #endif /* CONFIG_MATH_EMULATION */
755 
756 #ifndef CONFIG_M686
757 void __init trap_init_f00f_bug(void)
758 {
759         unsigned long page;
760         pgd_t * pgd;
761         pmd_t * pmd;
762         pte_t * pte;
763 
764         /*
765          * Allocate a new page in virtual address space, 
766          * move the IDT into it and write protect this page.
767          */
768         page = (unsigned long) vmalloc(PAGE_SIZE);
769         pgd = pgd_offset(&init_mm, page);
770         pmd = pmd_offset(pgd, page);
771         pte = pte_offset(pmd, page);
772         __free_page(pte_page(*pte));
773         *pte = mk_pte_phys(__pa(&idt_table), PAGE_KERNEL_RO);
774         /*
775          * Not that any PGE-capable kernel should have the f00f bug ...
776          */
777         __flush_tlb_all();
778 
779         /*
780          * "idt" is magic - it overlaps the idt_descr
781          * variable so that updating idt will automatically
782          * update the idt descriptor..
783          */
784         idt = (struct desc_struct *)page;
785         __asm__ __volatile__("lidt %0": "=m" (idt_descr));
786 }
787 #endif
788 
789 #define _set_gate(gate_addr,type,dpl,addr) \
790 do { \
791   int __d0, __d1; \
792   __asm__ __volatile__ ("movw %%dx,%%ax\n\t" \
793         "movw %4,%%dx\n\t" \
794         "movl %%eax,%0\n\t" \
795         "movl %%edx,%1" \
796         :"=m" (*((long *) (gate_addr))), \
797          "=m" (*(1+(long *) (gate_addr))), "=&a" (__d0), "=&d" (__d1) \
798         :"i" ((short) (0x8000+(dpl<<13)+(type<<8))), \
799          "3" ((char *) (addr)),"2" (__KERNEL_CS << 16)); \
800 } while (0)
801 
802 
803 /*
804  * This needs to use 'idt_table' rather than 'idt', and
805  * thus use the _nonmapped_ version of the IDT, as the
806  * Pentium F0 0F bugfix can have resulted in the mapped
807  * IDT being write-protected.
808  */
809 void set_intr_gate(unsigned int n, void *addr)
810 {
811         _set_gate(idt_table+n,14,0,addr);
812 }
813 
814 static void __init set_trap_gate(unsigned int n, void *addr)
815 {
816         _set_gate(idt_table+n,15,0,addr);
817 }
818 
819 static void __init set_system_gate(unsigned int n, void *addr)
820 {
821         _set_gate(idt_table+n,15,3,addr);
822 }
823 
824 static void __init set_call_gate(void *a, void *addr)
825 {
826         _set_gate(a,12,3,addr);
827 }
828 
829 #define _set_seg_desc(gate_addr,type,dpl,base,limit) {\
830         *((gate_addr)+1) = ((base) & 0xff000000) | \
831                 (((base) & 0x00ff0000)>>16) | \
832                 ((limit) & 0xf0000) | \
833                 ((dpl)<<13) | \
834                 (0x00408000) | \
835                 ((type)<<8); \
836         *(gate_addr) = (((base) & 0x0000ffff)<<16) | \
837                 ((limit) & 0x0ffff); }
838 
839 #define _set_tssldt_desc(n,addr,limit,type) \
840 __asm__ __volatile__ ("movw %w3,0(%2)\n\t" \
841         "movw %%ax,2(%2)\n\t" \
842         "rorl $16,%%eax\n\t" \
843         "movb %%al,4(%2)\n\t" \
844         "movb %4,5(%2)\n\t" \
845         "movb $0,6(%2)\n\t" \
846         "movb %%ah,7(%2)\n\t" \
847         "rorl $16,%%eax" \
848         : "=m"(*(n)) : "a" (addr), "r"(n), "ir"(limit), "i"(type))
849 
850 void set_tss_desc(unsigned int n, void *addr)
851 {
852         _set_tssldt_desc(gdt_table+__TSS(n), (int)addr, 235, 0x89);
853 }
854 
855 void set_ldt_desc(unsigned int n, void *addr, unsigned int size)
856 {
857         _set_tssldt_desc(gdt_table+__LDT(n), (int)addr, ((size << 3)-1), 0x82);
858 }
859 
860 #ifdef CONFIG_X86_VISWS_APIC
861 
862 /*
863  * On Rev 005 motherboards legacy device interrupt lines are wired directly
864  * to Lithium from the 307.  But the PROM leaves the interrupt type of each
865  * 307 logical device set appropriate for the 8259.  Later we'll actually use
866  * the 8259, but for now we have to flip the interrupt types to
867  * level triggered, active lo as required by Lithium.
868  */
869 
870 #define REG     0x2e    /* The register to read/write */
871 #define DEV     0x07    /* Register: Logical device select */
872 #define VAL     0x2f    /* The value to read/write */
873 
874 static void
875 superio_outb(int dev, int reg, int val)
876 {
877         outb(DEV, REG);
878         outb(dev, VAL);
879         outb(reg, REG);
880         outb(val, VAL);
881 }
882 
883 static int __attribute__ ((unused))
884 superio_inb(int dev, int reg)
885 {
886         outb(DEV, REG);
887         outb(dev, VAL);
888         outb(reg, REG);
889         return inb(VAL);
890 }
891 
892 #define FLOP    3       /* floppy logical device */
893 #define PPORT   4       /* parallel logical device */
894 #define UART5   5       /* uart2 logical device (not wired up) */
895 #define UART6   6       /* uart1 logical device (THIS is the serial port!) */
896 #define IDEST   0x70    /* int. destination (which 307 IRQ line) reg. */
897 #define ITYPE   0x71    /* interrupt type register */
898 
899 /* interrupt type bits */
900 #define LEVEL   0x01    /* bit 0, 0 == edge triggered */
901 #define ACTHI   0x02    /* bit 1, 0 == active lo */
902 
903 static void
904 superio_init(void)
905 {
906         if (visws_board_type == VISWS_320 && visws_board_rev == 5) {
907                 superio_outb(UART6, IDEST, 0);  /* 0 means no intr propagated */
908                 printk("SGI 320 rev 5: disabling 307 uart1 interrupt\n");
909         }
910 }
911 
912 static void
913 lithium_init(void)
914 {
915         set_fixmap(FIX_LI_PCIA, LI_PCI_A_PHYS);
916         printk("Lithium PCI Bridge A, Bus Number: %d\n",
917                                 li_pcia_read16(LI_PCI_BUSNUM) & 0xff);
918         set_fixmap(FIX_LI_PCIB, LI_PCI_B_PHYS);
919         printk("Lithium PCI Bridge B (PIIX4), Bus Number: %d\n",
920                                 li_pcib_read16(LI_PCI_BUSNUM) & 0xff);
921 
922         /* XXX blindly enables all interrupts */
923         li_pcia_write16(LI_PCI_INTEN, 0xffff);
924         li_pcib_write16(LI_PCI_INTEN, 0xffff);
925 }
926 
927 static void
928 cobalt_init(void)
929 {
930         /*
931          * On normal SMP PC this is used only with SMP, but we have to
932          * use it and set it up here to start the Cobalt clock
933          */
934         set_fixmap(FIX_APIC_BASE, APIC_DEFAULT_PHYS_BASE);
935         printk("Local APIC ID %lx\n", apic_read(APIC_ID));
936         printk("Local APIC Version %lx\n", apic_read(APIC_LVR));
937 
938         set_fixmap(FIX_CO_CPU, CO_CPU_PHYS);
939         printk("Cobalt Revision %lx\n", co_cpu_read(CO_CPU_REV));
940 
941         set_fixmap(FIX_CO_APIC, CO_APIC_PHYS);
942         printk("Cobalt APIC ID %lx\n", co_apic_read(CO_APIC_ID));
943 
944         /* Enable Cobalt APIC being careful to NOT change the ID! */
945         co_apic_write(CO_APIC_ID, co_apic_read(CO_APIC_ID)|CO_APIC_ENABLE);
946 
947         printk("Cobalt APIC enabled: ID reg %lx\n", co_apic_read(CO_APIC_ID));
948 }
949 #endif
950 void __init trap_init(void)
951 {
952 #ifdef CONFIG_EISA
953         if (isa_readl(0x0FFFD9) == 'E'+('I'<<8)+('S'<<16)+('A'<<24))
954                 EISA_bus = 1;
955 #endif
956 
957         set_trap_gate(0,&divide_error);
958         set_trap_gate(1,&debug);
959         set_intr_gate(2,&nmi);
960         set_system_gate(3,&int3);       /* int3-5 can be called from all */
961         set_system_gate(4,&overflow);
962         set_system_gate(5,&bounds);
963         set_trap_gate(6,&invalid_op);
964         set_trap_gate(7,&device_not_available);
965         set_trap_gate(8,&double_fault);
966         set_trap_gate(9,&coprocessor_segment_overrun);
967         set_trap_gate(10,&invalid_TSS);
968         set_trap_gate(11,&segment_not_present);
969         set_trap_gate(12,&stack_segment);
970         set_trap_gate(13,&general_protection);
971         set_trap_gate(14,&page_fault);
972         set_trap_gate(15,&spurious_interrupt_bug);
973         set_trap_gate(16,&coprocessor_error);
974         set_trap_gate(17,&alignment_check);
975         set_trap_gate(18,&machine_check);
976         set_trap_gate(19,&simd_coprocessor_error);
977 
978         set_system_gate(SYSCALL_VECTOR,&system_call);
979 
980         /*
981          * default LDT is a single-entry callgate to lcall7 for iBCS
982          * and a callgate to lcall27 for Solaris/x86 binaries
983          */
984         set_call_gate(&default_ldt[0],lcall7);
985         set_call_gate(&default_ldt[4],lcall27);
986 
987         /*
988          * Should be a barrier for any external CPU state.
989          */
990         cpu_init();
991 
992 #ifdef CONFIG_X86_VISWS_APIC
993         superio_init();
994         lithium_init();
995         cobalt_init();
996 #endif
997 }
998 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

This page was automatically generated by the LXR engine.
Visit the LXR main site for more information.