root/kernel/traps.c

/* [previous][next][first][last][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. die_if_kernel
  2. do_double_fault
  3. do_general_protection
  4. do_alignment_check
  5. do_divide_error
  6. do_int3
  7. do_nmi
  8. do_debug
  9. do_overflow
  10. do_bounds
  11. do_invalid_op
  12. do_device_not_available
  13. do_coprocessor_segment_overrun
  14. do_invalid_TSS
  15. do_segment_not_present
  16. do_stack_segment
  17. do_coprocessor_error
  18. do_reserved
  19. trap_init

   1 /*
   2  *  linux/kernel/traps.c
   3  *
   4  *  Copyright (C) 1991, 1992  Linus Torvalds
   5  */
   6 
   7 /*
   8  * 'Traps.c' handles hardware traps and faults after we have saved some
   9  * state in 'asm.s'. Currently mostly a debugging-aid, will be extended
  10  * to mainly kill the offending process (probably by giving it a signal,
  11  * but possibly by killing it outright if necessary).
  12  */
  13 #include <linux/head.h>
  14 #include <linux/sched.h>
  15 #include <linux/kernel.h>
  16 #include <linux/string.h>
  17 #include <linux/errno.h>
  18 #include <linux/segment.h>
  19 #include <linux/ptrace.h>
  20 
  21 #include <asm/system.h>
  22 #include <asm/segment.h>
  23 #include <asm/io.h>
  24 
  25 #define get_seg_byte(seg,addr) ({ \
  26 register char __res; \
  27 __asm__("push %%fs;mov %%ax,%%fs;movb %%fs:%2,%%al;pop %%fs" \
  28         :"=a" (__res):"0" (seg),"m" (*(addr))); \
  29 __res;})
  30 
  31 #define get_seg_long(seg,addr) ({ \
  32 register unsigned long __res; \
  33 __asm__("push %%fs;mov %%ax,%%fs;movl %%fs:%2,%%eax;pop %%fs" \
  34         :"=a" (__res):"0" (seg),"m" (*(addr))); \
  35 __res;})
  36 
  37 #define _fs() ({ \
  38 register unsigned short __res; \
  39 __asm__("mov %%fs,%%ax":"=a" (__res):); \
  40 __res;})
  41 
  42 void page_exception(void);
  43 
  44 void divide_error(void);
  45 void debug(void);
  46 void nmi(void);
  47 void int3(void);
  48 void overflow(void);
  49 void bounds(void);
  50 void invalid_op(void);
  51 void device_not_available(void);
  52 void double_fault(void);
  53 void coprocessor_segment_overrun(void);
  54 void invalid_TSS(void);
  55 void segment_not_present(void);
  56 void stack_segment(void);
  57 void general_protection(void);
  58 void page_fault(void);
  59 void coprocessor_error(void);
  60 void reserved(void);
  61 void alignment_check(void);
  62 
  63 /*static*/ void die_if_kernel(char * str, struct pt_regs * regs, long err)
     /* [previous][next][first][last][top][bottom][index][help] */
  64 {
  65         int i;
  66 
  67         if ((regs->eflags & VM_MASK) || ((0xffff & regs->cs) == USER_CS))
  68                 return;
  69         printk("%s: %04x\n", str, err & 0xffff);
  70         printk("EIP:    %04x:%p\nEFLAGS: %p\n", 0xffff & regs->cs,regs->eip,regs->eflags);
  71         printk("eax: %08x   ebx: %08x   ecx: %08x   edx: %08x\n",
  72                 regs->eax, regs->ebx, regs->ecx, regs->edx);
  73         printk("esi: %08x   edi: %08x   ebp: %08x\n",
  74                 regs->esi, regs->edi, regs->ebp);
  75         printk("ds: %04x   es: %04x   fs: %04x   gs: %04x\n",
  76                 regs->ds, regs->es, regs->fs, regs->gs);
  77         store_TR(i);
  78         printk("Pid: %d, process nr: %d\n", current->pid, 0xffff & i);
  79         for(i=0;i<10;i++)
  80                 printk("%02x ",0xff & get_seg_byte(regs->cs,(i+(char *)regs->eip)));
  81         printk("\n");
  82         do_exit(SIGSEGV);
  83 }
  84 
  85 void do_double_fault(struct pt_regs * regs, long error_code)
     /* [previous][next][first][last][top][bottom][index][help] */
  86 {
  87         send_sig(SIGSEGV, current, 1);
  88         die_if_kernel("double fault",regs,error_code);
  89 }
  90 
  91 void do_general_protection(struct pt_regs * regs, long error_code)
     /* [previous][next][first][last][top][bottom][index][help] */
  92 {
  93         send_sig(SIGSEGV, current, 1);
  94         die_if_kernel("general protection",regs,error_code);
  95 }
  96 
  97 void do_alignment_check(struct pt_regs * regs, long error_code)
     /* [previous][next][first][last][top][bottom][index][help] */
  98 {
  99         send_sig(SIGSEGV, current, 1);
 100         die_if_kernel("alignment check",regs,error_code);
 101 }
 102 
 103 void do_divide_error(struct pt_regs * regs, long error_code)
     /* [previous][next][first][last][top][bottom][index][help] */
 104 {
 105         send_sig(SIGFPE, current, 1);
 106         die_if_kernel("divide error",regs,error_code);
 107 }
 108 
 109 void do_int3(struct pt_regs * regs, long error_code)
     /* [previous][next][first][last][top][bottom][index][help] */
 110 {
 111         if (current->flags & PF_PTRACED)
 112                 current->blocked &= ~(1 << (SIGTRAP-1));
 113         send_sig(SIGTRAP, current, 1);
 114         die_if_kernel("int3",regs,error_code);
 115 }
 116 
 117 void do_nmi(struct pt_regs * regs, long error_code)
     /* [previous][next][first][last][top][bottom][index][help] */
 118 {
 119         printk("Uhhuh. NMI received. Dazed and confused, but trying to continue\n");
 120 }
 121 
 122 void do_debug(struct pt_regs * regs, long error_code)
     /* [previous][next][first][last][top][bottom][index][help] */
 123 {
 124         if (current->flags & PF_PTRACED)
 125                 current->blocked &= ~(1 << (SIGTRAP-1));
 126         send_sig(SIGTRAP, current, 1);
 127         die_if_kernel("debug",regs,error_code);
 128 }
 129 
 130 void do_overflow(struct pt_regs * regs, long error_code)
     /* [previous][next][first][last][top][bottom][index][help] */
 131 {
 132         send_sig(SIGSEGV, current, 1);
 133         die_if_kernel("overflow",regs,error_code);
 134 }
 135 
 136 void do_bounds(struct pt_regs * regs, long error_code)
     /* [previous][next][first][last][top][bottom][index][help] */
 137 {
 138         send_sig(SIGSEGV, current, 1);
 139         die_if_kernel("bounds",regs,error_code);
 140 }
 141 
 142 void do_invalid_op(struct pt_regs * regs, long error_code)
     /* [previous][next][first][last][top][bottom][index][help] */
 143 {
 144         send_sig(SIGILL, current, 1);
 145         die_if_kernel("invalid operand",regs,error_code);
 146 }
 147 
 148 void do_device_not_available(struct pt_regs * regs, long error_code)
     /* [previous][next][first][last][top][bottom][index][help] */
 149 {
 150         send_sig(SIGSEGV, current, 1);
 151         die_if_kernel("device not available",regs,error_code);
 152 }
 153 
 154 void do_coprocessor_segment_overrun(struct pt_regs * regs, long error_code)
     /* [previous][next][first][last][top][bottom][index][help] */
 155 {
 156         send_sig(SIGFPE, last_task_used_math, 1);
 157         die_if_kernel("coprocessor segment overrun",regs,error_code);
 158 }
 159 
 160 void do_invalid_TSS(struct pt_regs * regs,long error_code)
     /* [previous][next][first][last][top][bottom][index][help] */
 161 {
 162         send_sig(SIGSEGV, current, 1);
 163         die_if_kernel("invalid TSS",regs,error_code);
 164 }
 165 
 166 void do_segment_not_present(struct pt_regs * regs,long error_code)
     /* [previous][next][first][last][top][bottom][index][help] */
 167 {
 168         send_sig(SIGSEGV, current, 1);
 169         die_if_kernel("segment not present",regs,error_code);
 170 }
 171 
 172 void do_stack_segment(struct pt_regs * regs,long error_code)
     /* [previous][next][first][last][top][bottom][index][help] */
 173 {
 174         send_sig(SIGSEGV, current, 1);
 175         die_if_kernel("stack segment",regs,error_code);
 176 }
 177 
 178 void do_coprocessor_error(struct pt_regs * regs, long error_code)
     /* [previous][next][first][last][top][bottom][index][help] */
 179 {
 180   /*
 181     Allow the process which triggered the interrupt to recover the error
 182     condition.
 183     The status word is saved in the cs selector.
 184     The tag word is saved in the operand selector.
 185     The status word is then cleared and the tags all set to Empty.
 186     This will give sufficient information for complete recovery provided that
 187     the affected process knows or can deduce the code and data segments
 188     which were in force when the exception condition arose.
 189     */
 190         #define FPU_ENV (*(struct i387_hard_struct *)env)
 191         char env[28];
 192 
 193         ignore_irq13 = 1;
 194         send_sig(SIGFPE, last_task_used_math, 1);
 195 
 196         __asm__ __volatile__("fnstenv %0; fnclex": "=m" (FPU_ENV));
 197         FPU_ENV.fcs = (FPU_ENV.swd & 0x0000ffff) | (FPU_ENV.fcs & 0xffff0000);
 198         FPU_ENV.fos = FPU_ENV.twd;
 199         FPU_ENV.swd &= 0xffff0000;
 200         FPU_ENV.twd = 0xffffffff;
 201         __asm__ __volatile__("fldenv %0"::"m" (FPU_ENV));
 202 }
 203 
 204 void do_reserved(struct pt_regs * regs, long error_code)
     /* [previous][next][first][last][top][bottom][index][help] */
 205 {
 206         send_sig(SIGSEGV, current, 1);
 207         die_if_kernel("reserved (15,17-47) error",regs,error_code);
 208 }
 209 
 210 void trap_init(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 211 {
 212         int i;
 213 
 214         set_trap_gate(0,&divide_error);
 215         set_trap_gate(1,&debug);
 216         set_trap_gate(2,&nmi);
 217         set_system_gate(3,&int3);       /* int3-5 can be called from all */
 218         set_system_gate(4,&overflow);
 219         set_system_gate(5,&bounds);
 220         set_trap_gate(6,&invalid_op);
 221         set_trap_gate(7,&device_not_available);
 222         set_trap_gate(8,&double_fault);
 223         set_trap_gate(9,&coprocessor_segment_overrun);
 224         set_trap_gate(10,&invalid_TSS);
 225         set_trap_gate(11,&segment_not_present);
 226         set_trap_gate(12,&stack_segment);
 227         set_trap_gate(13,&general_protection);
 228         set_trap_gate(14,&page_fault);
 229         set_trap_gate(15,&reserved);
 230         set_trap_gate(16,&coprocessor_error);
 231         set_trap_gate(17,&alignment_check);
 232         for (i=18;i<48;i++)
 233                 set_trap_gate(i,&reserved);
 234 }

/* [previous][next][first][last][top][bottom][index][help] */