Prex Home / Browse Source - Prex Version: 0.9.0

root/bsp/hal/x86/arch/trap.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. trap_handler
  2. trap_dump

   1 /*-
   2  * Copyright (c) 2005-2009, Kohsuke Ohtani
   3  * All rights reserved.
   4  *
   5  * Redistribution and use in source and binary forms, with or without
   6  * modification, are permitted provided that the following conditions
   7  * are met:
   8  * 1. Redistributions of source code must retain the above copyright
   9  *    notice, this list of conditions and the following disclaimer.
  10  * 2. Redistributions in binary form must reproduce the above copyright
  11  *    notice, this list of conditions and the following disclaimer in the
  12  *    documentation and/or other materials provided with the distribution.
  13  * 3. Neither the name of the author nor the names of any co-contributors
  14  *    may be used to endorse or promote products derived from this software
  15  *    without specific prior written permission.
  16  *
  17  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
  18  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  19  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  20  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
  21  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  22  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  23  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  24  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  25  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  26  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  27  * SUCH DAMAGE.
  28  */
  29 
  30 /*
  31  * trap.c - called from the trap handler when a processor trap occurs.
  32  */
  33 
  34 #include <sys/signal.h>
  35 #include <kernel.h>
  36 #include <hal.h>
  37 #include <exception.h>
  38 #include <task.h>
  39 #include <cpu.h>
  40 #include <trap.h>
  41 #include <cpufunc.h>
  42 #include <context.h>
  43 #include <locore.h>
  44 
  45 #ifdef DEBUG
  46 /*
  47  * Trap name.
  48  */
  49 static const char *const trap_name[] = {
  50         "Divide error",         /*  0 */
  51         "Debug trap",           /*  1 */
  52         "NMI",                  /*  2 */
  53         "Breakpoint",           /*  3 */
  54         "Overflow",             /*  4 */
  55         "Bounds check",         /*  5 */
  56         "Invalid opecode",      /*  6 */
  57         "Device not available", /*  7 */
  58         "Double fault",         /*  8 */
  59         "Coprocessor overrun",  /*  9 */
  60         "Invalid TSS",          /* 10 */
  61         "Segment not present",  /* 11 */
  62         "Stack bounds",         /* 12 */
  63         "General Protection",   /* 13 */
  64         "Page fault",           /* 14 */
  65         "Reserved",             /* 15 */
  66         "Coprocessor error",    /* 16 */
  67         "Alignment check",      /* 17 */
  68         "Cache flush denied"    /* 18 */
  69 };
  70 #define MAXTRAP (sizeof(trap_name) / sizeof(void *) - 1)
  71 #endif  /* DEBUG */
  72 
  73 /*
  74  * Trap/exception mapping table.
  75  * x86 trap code is translated to the architecture
  76  * independent exception code.
  77  */
  78 static const int exception_map[] = {
  79         SIGFPE,         /*  0: Divide error */
  80         SIGTRAP,        /*  1: Debug trap */
  81         SIGILL,         /*  2: NMI */
  82         SIGTRAP,        /*  3: Breakpoint */
  83         SIGFPE,         /*  4: Overflow */
  84         SIGILL,         /*  5: Bounds check */
  85         SIGILL,         /*  6: Invalid opecode */
  86         SIGFPE,         /*  7: Device not available */
  87         SIGILL,         /*  8: Double fault */
  88         SIGFPE,         /*  9: Coprocessor overrun */
  89         SIGSEGV,        /* 10: Invalid TSS */
  90         SIGSEGV,        /* 11: Segment not present */
  91         SIGSEGV,        /* 12: Stack bounds */
  92         SIGILL,         /* 13: General Protection fault */
  93         SIGSEGV,        /* 14: Page fault */
  94         SIGILL,         /* 15: Reserved */
  95         SIGFPE,         /* 16: Coprocessor error */
  96         SIGILL,         /* 17: Alignment check */
  97         SIGILL,         /* 18: Cache flush denied */
  98 };
  99 
 100 /*
 101  * Trap handler
 102  * Invoke the exception handler if it is needed.
 103  */
 104 void
 105 trap_handler(struct cpu_regs *regs)
 106 {
 107         u_long trap_no = regs->trap_no;
 108 
 109         if (trap_no > 18)
 110                 panic("Unknown trap");
 111         else if (trap_no == 2)
 112                 panic("NMI");
 113 
 114         /*
 115          * Check whether this trap is kernel page fault caused
 116          * by known routine to access user space like copyin().
 117          * If so, we change the return address of this exception.
 118          */
 119         if (trap_no == 14 && regs->cs == KERNEL_CS &&
 120             (regs->eip == (uint32_t)known_fault1 ||
 121              regs->eip == (uint32_t)known_fault2 ||
 122              regs->eip == (uint32_t)known_fault3)) {
 123                 DPRINTF(("\n*** Detect Fault! address=%x task=%s ***\n",
 124                          get_cr2(), curtask->name));
 125                 regs->eip = (uint32_t)copy_fault;
 126                 return;
 127         }
 128 #ifdef DEBUG
 129         printf("============================\n");
 130         printf("Trap %x: %s\n", (u_int)trap_no, trap_name[trap_no]);
 131         if (trap_no == 14)
 132                 printf(" Fault address=%x\n", get_cr2());
 133         printf("============================\n");
 134         trap_dump(regs);
 135         if (regs->cs == KERNEL_CS) {
 136                 printf("Trap in kernel!\n");
 137                 interrupt_mask(0);
 138                 spl0();
 139         }
 140         for (;;) ;
 141 #endif
 142         if (regs->cs == KERNEL_CS)
 143                 panic("Kernel exception");
 144 
 145         exception_mark(exception_map[trap_no]);
 146         exception_deliver();
 147 }
 148 
 149 #ifdef DEBUG
 150 void
 151 trap_dump(struct cpu_regs *r)
 152 {
 153         uint32_t ss, esp, *fp;
 154         u_int i;
 155         int spl;
 156 
 157         /* Get current spl */
 158         spl = splhigh();
 159         splx(spl);
 160 
 161         if (r->cs & 3) {
 162                 ss = r->ss;
 163                 esp = r->esp;
 164         } else {
 165                 ss = r->ds;
 166                 esp = (uint32_t)r;
 167         }
 168         printf("Trap frame %08lx error %x\n", (long)r, r->err_code);
 169         printf(" eax %08x ebx %08x ecx %08x edx %08x esi %08x edi %08x\n",
 170                r->eax, r->ebx, r->ecx, r->edx, r->esi, r->edi);
 171         printf(" eip %08x esp %08x ebp %08x eflags %08x\n",
 172                r->eip, esp, r->ebp, r->eflags);
 173         printf(" cs  %08x ss  %08x ds  %08x es  %08x esp0 %08x\n",
 174                r->cs, ss, r->ds, r->es, tss_get());
 175 
 176         printf(" >> interrupt is %s\n", (spl == 0) ? "enabled" : "disabled");
 177 
 178         printf(" >> task=%s\n", curtask->name);
 179 
 180         if (r->cs == KERNEL_CS) {
 181                 printf("Stack trace:\n");
 182                 fp = (uint32_t *)r->ebp;
 183                 for (i = 0; i < 8; i++) {
 184                         if (user_area(fp))
 185                                 break;
 186                         fp = (uint32_t *)(*fp); /* XXX: may cause fault */
 187                         if (!(*(fp + 1) && *fp))
 188                                 break;
 189                         printf(" %08x\n", *(fp + 1));
 190                 }
 191         }
 192 }
 193 #endif /* !DEBUG */

/* [<][>][^][v][top][bottom][index][help] */