Main Page   Modules   Alphabetical List   Data Structures   File List   Data Fields   Globals   Related Pages  

exception.c

Go to the documentation of this file.
00001 /*!     \file arch/i386/kernel/exception.c
00002  *      \brief Exceptions manager.
00003  *      \author Andrea Righi <drizzt@inwind.it>
00004  *      \date Last update: 2004-01-24
00005  *      \note Copyright (&copy;) 2003 Andrea Righi
00006  *
00007  * \n<b>From: &lt;INTEL 80386 PROGRAMMER'S REFERENCE MANUAL 1986&gt;</b>
00008  * <table>
00009  * <tr><td><b>Identifier</b></td><td><b>Description</b></td></tr>
00010  *
00011  * <tr><td align="center">0</td><td>Divide error</td>
00012  * <tr><td align="center">1</td><td>Debug exception</td>
00013  * <tr><td align="center">2</td><td>Nonmaskable interrupt</td>
00014  * <tr><td align="center">3</td><td>Breakpoint (one-byte INT 3 instruction)</td>
00015  * <tr><td align="center">4</td><td>Overflow (INTO instruction)</td>
00016  * <tr><td align="center">5</td><td>Bounds check (BOUND instruction)</td>
00017  * <tr><td align="center">6</td><td>Invalid opcode</td>
00018  * <tr><td align="center">7</td><td>Coprocessor not available</td>
00019  * <tr><td align="center">8</td><td>Double fault</td>
00020  * <tr><td align="center">9</td><td>(reserved)</td>
00021  * <tr><td align="center">10</td><td>Invalid TSS</td>
00022  * <tr><td align="center">11</td><td>Segment not present</td>
00023  * <tr><td align="center">12</td><td>Stack exception</td>
00024  * <tr><td align="center">13</td><td>General protection</td>
00025  * <tr><td align="center">14</td><td>Page fault</td>
00026  * <tr><td align="center">15</td><td>(reserved)</td>
00027  * <tr><td align="center">16</td><td>Coprecessor error</td>
00028  *
00029  * <tr><td align="center">17-31</td><td>(reserved)</td>
00030  * <tr><td align="center">32-255</td><td>Available for external interrupts via INTR pin</td>
00031  *
00032  * </table>
00033  */
00034 
00035 #include <const.h>
00036 
00037 #include <kernel/console.h>
00038 #include <kernel/task.h>
00039 
00040 #include <arch/i386.h>
00041 #include <arch/interrupt.h>
00042 #include <arch/mem.h>
00043 #include <arch/paging.h>
00044 #include <arch/v86.h>
00045 
00046 #include <arch/exception.h>
00047 
00048 /** \ingroup Kernel
00049  *  \defgroup KException Exception Manager
00050  *  The exception manager.
00051  *  @{
00052  */
00053 
00054 //! \brief Panic routine.
00055 /**
00056  *      The task that calls this routine must be killed.
00057  *      If it is invoked by the kernel we can only halt
00058  *      the system!
00059  */
00060 void panic()
00061 {
00062         // The task should be killed.
00063         kprintf("\n\rTask [%s] (%i) killed!\n\r", get_pname(), get_pid());
00064         if ( get_pid() )
00065                 auto_kill( 1 );
00066         else
00067                 halt();
00068 }
00069 
00070 //! \brief
00071 //!     Dump the CPU registers.
00072 //! \param c The context of the current task after an exception.
00073 static __inline__ void dump_registers( exc_context_t *c )
00074 {
00075         register uint16_t ss;
00076         register uint32_t cr0, cr2, cr3, cr4;
00077 
00078         // Save stack segment register.
00079         __asm__ __volatile__ ("movw %%ss, %0": "=&r"(ss) : );
00080 
00081         // Save control registers.
00082         __asm__ __volatile__ ("movl %%cr0, %0" : "=&r"(cr0) : );
00083         __asm__ __volatile__ ("movl %%cr2, %0" : "=&r"(cr2) : );
00084         __asm__ __volatile__ ("movl %%cr3, %0" : "=&r"(cr3) : );
00085         __asm__ __volatile__ ("movl %%cr2, %0" : "=&r"(cr4) : );
00086 
00087         // Dump registers.
00088         kprintf("\n\reax = %#010x  ds = %#010x  cr0 = %#010x  esp    = %#010x", c->eax, c->ds, cr0, c->esp);
00089         kprintf("\n\rebx = %#010x  es = %#010x  cr2 = %#010x  ebp    = %#010x", c->ebx, c->es, cr2, c->ebp);
00090         kprintf("\n\recx = %#010x  fs = %#010x  cr3 = %#010x  eip    = %#010x", c->ecx, c->fs, cr3, c->eip);
00091         kprintf("\n\redx = %#010x  gs = %#010x  cr4 = %#010x  eflags = %#010x", c->edx, c->gs, cr4, c->eflags);
00092         kprintf("\n\resi = %#010x  ss = %#010x  exc = %#010x", c->esi, ss, c->EXC);
00093         kprintf("\n\redi = %#010x  cs = %#010x  err = %#010x", c->edi, c->cs, c->err_code);
00094 }
00095 
00096 //! \brief
00097 //!     This is the default exception handler. It is invoked
00098 //!     every time an exception occurs. The kernel must route the
00099 //!     exececution to the opportune procedures to correctly manage
00100 //!     the exception.
00101 //! \param c The context of the current task after an exception.
00102 void default_exception(exc_context_t *c)
00103 {
00104         switch( c->EXC )
00105         {
00106                 case 0x00:
00107                 kprintf("\n\rException 00: DIVISION BY ZERO\n\r");
00108                 break;
00109 
00110                 case 0x01:
00111                 kprintf("\n\rException 01: DEBUG EXCEPTION DETECTED\n\r");
00112                 break;
00113 
00114                 case 0x02:
00115                 kprintf("\n\rException 02: NON MASKABLE INTERRUPT\n\r");
00116                 break;
00117 
00118                 case 0x03:
00119                 kprintf("\n\rException 03: BREAKPOINT INSTRUCTION DETECTED\n\r");
00120                 dump_registers( c );
00121                 kprintf("\n\rBreakpoint from task [%s] (%i)\n\r", get_pname(), get_pid());
00122                 // After a breakpoint we can restore execution.
00123                 return;
00124                 break;
00125 
00126                 case 0x04:
00127                 kprintf("\n\rException 04: INTO DETECTED OVERFLOW\n\r");
00128                 break;
00129 
00130                 case 0x05:
00131                 kprintf("\n\rException 05: BOUND RANGE EXCEEDED\n\r");
00132                 break;
00133 
00134                 case 0x06:
00135                 kprintf("\n\rException 06: INVALID OPCODE\n\r");
00136                 break;
00137 
00138                 case 0x07:
00139                 kprintf("\n\rException 07: PROCESSOR EXTENSION NOT AVAILABLE\n\r");
00140                 break;
00141 
00142                 case 0x08:
00143                 kprintf("\n\rException 08: DOUBLE FAULT DETECTED\n\r");
00144                 break;
00145 
00146                 case 0x09:
00147                 kprintf("\n\rException 09: PROCESSOR EXTENSION PROTECTION FAULT\n\r");
00148                 break;
00149 
00150                 case 0x0A:
00151                 kprintf("\n\rException 0A: INVALID TASK STATE SEGMENT\n\r");
00152                 break;
00153 
00154                 case 0x0B:
00155                 kprintf("\n\rException 0B: SEGMENT NOT PRESENT\n\r");
00156                 break;
00157 
00158                 case 0x0C:
00159                 kprintf("\n\rException 0C: STACK FAULT\n\r");
00160                 break;
00161 
00162                 case 0x0D:
00163                 if ((c->eflags & EFLAGS_VM) == EFLAGS_VM)
00164                 {
00165                         v86_monitor();
00166                         return;
00167                 }
00168                 kprintf("\n\rException 0D: GENERAL PROTECTION FAULT\n\r");
00169                 break;
00170 
00171                 case 0x0E:
00172                 if ((c->err_code & P_PRESENT) != P_PRESENT)
00173                 {
00174                         register uint32_t cr2;
00175                         __asm__ __volatile__ ("movl %%cr2, %0" : "=&r"(cr2));
00176                         if ( !page_fault_handler(c->err_code, cr2) )
00177                                 return;
00178                 }
00179                 kprintf(        "\n\rException 0E: PAGE FAULT (protection fault)!\n\r");
00180                 break;
00181 
00182                 case 0x0F:
00183                 kprintf("\n\rException 0F: UNKNOWN EXCEPTION\n\r");
00184                 break;
00185 
00186                 default:
00187                 kprintf("\n\rException %02X: UNEXPECTED !!!\n\r", c->EXC);
00188                 break;
00189         }
00190 
00191         // Dump the CPU registers.
00192         dump_registers( c );
00193         panic();
00194 }
00195 
00196 /** @} */ // end of KException

Generated on Fri Feb 20 15:32:15 2004 for Minirighi by doxygen1.2.18