idt.c

Go to the documentation of this file.
00001 /*****************************************************************************************
00002  Copyright (c) 2002-2005 The UbixOS Project
00003  All rights reserved.
00004 
00005  Redistribution and use in source and binary forms, with or without modification, are
00006  permitted provided that the following conditions are met:
00007 
00008  Redistributions of source code must retain the above copyright notice, this list of
00009  conditions, the following disclaimer and the list of authors.  Redistributions in binary
00010  form must reproduce the above copyright notice, this list of conditions, the following
00011  disclaimer and the list of authors in the documentation and/or other materials provided
00012  with the distribution. Neither the name of the UbixOS Project nor the names of its
00013  contributors may be used to endorse or promote products derived from this software
00014  without specific prior written permission.
00015 
00016  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
00017  EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
00018  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
00019  THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
00020  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
00021  OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
00022  HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
00023  TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
00024  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00025 
00026  $Id: idt_8c-source.html 88 2016-01-12 00:11:29Z reddawg $
00027 
00028 *****************************************************************************************/
00029 
00030 #include <sys/idt.h>
00031 #include <sys/gdt.h>
00032 #include <sys/io.h>
00033 #include <ubixos/sched.h>
00034 #include <isa/8259.h>
00035 #include <lib/kprintf.h>
00036 #include <lib/kmalloc.h>
00037 #include <vmm/vmm.h>
00038 #include <ubixos/syscall.h>
00039 #include <ubixos/kpanic.h>
00040 #include <ubixos/endtask.h>
00041 #include <string.h>
00042 
00043 #define FP_TO_LINEAR(seg, off) ((void*) ((((uInt16) (seg)) << 4) + ((uInt16) (off))))
00044 
00045 static ubixDescriptorTable(ubixIDT, 256) { };
00046 
00047 static struct {
00048   unsigned short limit __attribute__((packed));
00049   union descriptorTableUnion *idt __attribute__((packed));
00050   } loadidt = {
00051     (256 * sizeof(union descriptorTableUnion) - 1), ubixIDT
00052     };
00053 
00054 /************************************************************************
00055 
00056 Function: int idtInit()
00057 Description: This function is used to enable our IDT subsystem
00058 Notes:
00059 
00060 02/20/2004 - Approved for quality
00061 
00062 ************************************************************************/
00063 int idt_init() {
00064   int i = 0x0;
00065 
00066   struct tssStruct *sfTSS  = (struct tssStruct *)0x6200;
00067   struct tssStruct *gpfTSS = (struct tssStruct *)0x4200;
00068 
00069   /* Set up default vector table for all possible 256 interrupts */
00070 
00071   for (i = 0x0; i < 256; i++) {
00072     setVector(intNull, i, dPresent + dInt + dDpl3);
00073     }
00074 
00075   /* Load the IDT into the system */
00076   asm volatile(
00077     "cli                      \n"
00078     "lidt (%0)                \n"  /* Load the IDT                */
00079     "pushfl                   \n"  /* Clear the NT flag           */
00080     "andl $0xffffbfff,(%%esp)  \n"
00081     "popfl                    \n"
00082     "sti                      \n"
00083     :
00084     : "r" ((char *)&loadidt)
00085     );
00086 
00087   /* Set up the basic vectors for the reserved ints */
00088   setVector(_int0, 0, dPresent + dInt + dDpl0);
00089   setVector(_int1, 1, dPresent + dInt + dDpl0);
00090   setVector(_int2, 2, dPresent + dInt + dDpl0);
00091   setVector(_int3, 3, dPresent + dInt + dDpl0);
00092   setVector(_int4, 4, dPresent + dInt + dDpl0);
00093   setVector(_int5, 5, dPresent + dInt + dDpl0);
00094   setVector(_int6, 6, dPresent + dInt + dDpl0);
00095   setVector(_int7,7,dPresent + dInt + dDpl0);
00096   setTaskVector(8,dPresent + dTask + dDpl0, 0x40);
00097   setVector(_int9, 9, dPresent + dInt + dDpl0);
00098   setVector(_int10, 10, dPresent + dInt + dDpl0);
00099   setVector(_int11, 11, dPresent + dInt + dDpl0);
00100   setVector(_int12, 12, dPresent + dInt + dDpl0);
00101   setTaskVector(13, dPresent + dTask + dDpl0, 0x38);
00102   setVector(_vmm_pageFault, 14, dPresent + dInt + dDpl0);
00103   setVector(_sysCall, 128, dPresent + dTrap + dDpl3);
00104   setVector(_sysCall_new, 0x81, dPresent + dTrap + dDpl3);
00105   //setVector(_sysCallNew, 0x90, dPresent + dTrap + dDpl3);
00106   setVector(timerInt, 0x68, (dInt + dPresent + dDpl0));
00107 
00108 
00109   gpfTSS->back_link    = 0x0;
00110   gpfTSS->esp0         = 0x0;
00111   gpfTSS->ss0          = 0x0;
00112   gpfTSS->esp1         = 0x0;
00113   gpfTSS->ss1          = 0x0;
00114   gpfTSS->esp2         = 0x0;
00115   gpfTSS->ss2          = 0x0;
00116   gpfTSS->cr3          = (unsigned int)kernelPageDirectory;
00117   gpfTSS->eip          = (unsigned int)&_int13;
00118   gpfTSS->eflags       = 0x206;
00119   gpfTSS->esp          = 0x1D000;
00120   gpfTSS->ebp          = 0x1D000;
00121   gpfTSS->esi          = 0x0;
00122   gpfTSS->edi          = 0x0;
00123   gpfTSS->es           = 0x10;
00124   gpfTSS->cs           = 0x08;
00125   gpfTSS->ss           = 0x10;
00126   gpfTSS->ds           = 0x10;
00127   gpfTSS->fs           = 0x10;
00128   gpfTSS->gs           = 0x10;
00129   gpfTSS->ldt          = 0x0;
00130   gpfTSS->trace_bitmap = 0x0000;
00131   gpfTSS->io_map       = 0x8000;
00132   
00133   memset(sfTSS,0x0,sizeof(struct tssStruct));
00134   sfTSS->cr3           = (unsigned int)kernelPageDirectory;
00135   sfTSS->eip           = (unsigned int)&_int8;
00136   sfTSS->eflags        = 0x206;
00137   sfTSS->esp           = 0x1C000;
00138   sfTSS->ebp           = 0x1C000;
00139   sfTSS->es            = 0x10;
00140   sfTSS->cs            = 0x08;
00141   sfTSS->ss            = 0x10;
00142   sfTSS->ds            = 0x10;
00143   sfTSS->fs            = 0x10;
00144   sfTSS->gs            = 0x10;
00145   sfTSS->io_map        = 0x8000;
00146 
00147   /* Print out information for the IDT */
00148   kprintf("idt0 - Address: [0x%X]\n", &ubixIDT);
00149 
00150   /* Return so we know all went well */
00151   return (0x0);
00152   }
00153 
00154 
00155 /* Sets Up IDT Vector */
00156 void setVector(void *handler, unsigned char interrupt, unsigned short controlMajor) {
00157   unsigned short  codesegment = 0x08;
00158   asm             volatile ("movw %%cs,%0":"=g" (codesegment));
00159 
00160   ubixIDT[interrupt].gate.offsetLow = (unsigned short)(((unsigned long)handler) & 0xffff);
00161   ubixIDT[interrupt].gate.selector = codesegment;
00162   ubixIDT[interrupt].gate.access = controlMajor;
00163   ubixIDT[interrupt].gate.offsetHigh = (unsigned short)(((unsigned long)handler) >> 16);
00164 }
00165 
00166 /************************************************************************
00167 
00168 Function: void setTaskVector(uInt8,uInt16,uInt8);
00169 Description: This Function Sets Up An IDT Task Vector
00170 Notes:
00171 
00172 ************************************************************************/
00173 void 
00174 setTaskVector(uInt8 interrupt, uInt16 controlMajor, uInt8 selector)
00175 {
00176   uInt16          codesegment = 0x08;
00177   asm             volatile ("movw %%cs,%0":"=g" (codesegment));
00178 
00179   ubixIDT[interrupt].gate.offsetLow = 0x0;
00180   ubixIDT[interrupt].gate.selector = selector;
00181   ubixIDT[interrupt].gate.access = controlMajor;
00182   ubixIDT[interrupt].gate.offsetHigh = 0x0;
00183 }
00184 
00185 
00186 /* Null Intterupt Descriptor */
00187 void intNull() {
00188   kprintf("Invalid Interrupt[%i]\n",_current->id);
00189 /*
00190   kpanic("Invalid Interrupt[%i]\n",_current->id);
00191   while (1);
00192   endTask(_current->id);
00193   sched_yield();
00194 */
00195   }
00196 
00197 void _int0() {
00198   kpanic("int0: Divide-by-Zero [%i]\n",_current->id);
00199   endTask(_current->id);
00200   sched_yield();
00201   }
00202 
00203 void _int1() {
00204   kpanic("int1: Debug exception [%i]\n",_current->id);
00205   endTask(_current->id);
00206   sched_yield();
00207   }
00208 
00209 void _int2() {
00210   kpanic("int2: unknown error [%i]\n",_current->id);
00211   endTask(_current->id);
00212   sched_yield();
00213   }
00214 
00215 void _int3() {
00216   kpanic("int3: Breakpoint [%i]\n",_current->id);
00217   endTask(_current->id);
00218   sched_yield();
00219   }
00220 
00221 void _int4(){
00222   kpanic("int4: Overflow [%i]\n",_current->id);
00223   endTask(_current->id);
00224   sched_yield();
00225   }
00226 
00227 void  _int5() {
00228   kpanic("int5: Bounds check [%i]\n",_current->id);
00229   endTask(_current->id);
00230   sched_yield();
00231   }
00232 
00233 void _int6() {
00234   kpanic("int6: Invalid opcode! [%i]\n",_current->id);
00235   endTask(_current->id);
00236   sched_yield();
00237   }
00238 
00239 void _int8() {
00240   struct tssStruct *sfTSS  = (struct tssStruct *)0x6200;
00241   kpanic("int8: Double Fault! [%i]\n",_current->id);
00242   sfTSS->cr3           = (unsigned int)kernelPageDirectory;
00243   sfTSS->eip           = (unsigned int)&_int8;
00244   sfTSS->eflags        = 0x206;
00245   sfTSS->esp           = 0x1C000;
00246   sfTSS->ebp           = 0x1C000;
00247   sfTSS->es            = 0x10;
00248   sfTSS->cs            = 0x08;
00249   sfTSS->ss            = 0x10;
00250   sfTSS->ds            = 0x10;
00251   sfTSS->fs            = 0x10;
00252   sfTSS->gs            = 0x10;
00253   sfTSS->io_map        = 0x8000;
00254   while (1);
00255  }
00256 
00257 void _int9() {
00258   kpanic("int9: Coprocessor Segment Overrun! [%i]\n",_current->id);
00259   endTask(_current->id);
00260   sched_yield();
00261   }
00262 
00263 void _int10() {
00264   kpanic("int10: Invalid TSS! [%i]\n",_current->id);
00265   endTask(_current->id);
00266   sched_yield();
00267   }
00268 
00269 void _int11() {
00270   kpanic("int11: Segment Not Present! [%i]\n",_current->id);
00271   endTask(_current->id);
00272   sched_yield();
00273   }
00274 
00275 void _int12() {
00276   kpanic("int12: Stack-Segment Fault! [%i]\n",_current->id);
00277   endTask(_current->id);
00278   sched_yield();
00279   }
00280 
00281 void _int13() {
00282   uInt8          *ip = 0x0;
00283   uInt16         *stack = 0x0, *ivt = 0x0;
00284   uInt32         *stack32 = 0x0;
00285   bool            isOperand32 = FALSE, isAddress32 = FALSE;
00286   struct tssStruct *gpfTSS = (struct tssStruct *)0x4200;
00287 
00288   irqDisable(0x0);
00289   
00290   gpfTSS->eip            = (unsigned int)&_int13;
00291   gpfTSS->esp            = 0x1D000;
00292   gpfTSS->ebp            = 0x1D000;
00293   gpfTSS->eflags         = 0x206;
00294   
00295   ip      = FP_TO_LINEAR(_current->tss.cs, _current->tss.eip);
00296   ivt = (uInt16 *) 0x0;
00297   stack   = (uInt16 *) FP_TO_LINEAR(_current->tss.ss,_current->tss.esp);
00298   stack32 = (uInt32 *) stack;
00299 
00300 gpfStart:
00301   switch (ip[0]) {
00302   case 0xCD:                    /* INT n */
00303     switch (ip[1]) {
00304     case 0x69:
00305       kprintf("Exit Bios [0x%X]\n",_current->id);
00306       _current->state = DEAD;
00307       break;
00308     case 0x20:
00309     case 0x21:
00310       kpanic("GPF OP 0x20/0x21\n");
00311       break;
00312     default:
00313       stack -= 3;
00314       _current->tss.esp = ((_current->tss.esp & 0xffff) - 6) & 0xffff;
00315       stack[0] = (uInt16) (_current->tss.eip + 2);
00316       stack[1] = _current->tss.cs; stack[2] = (uInt16) _current->tss.eflags;
00317       if (_current->oInfo.v86If)
00318         stack[2] |= EFLAG_IF;
00319       else
00320         stack[2] &= ~EFLAG_IF;
00321       _current->tss.cs  = ivt[ip[1] * 2 + 1] & 0xFFFF;
00322       _current->tss.eip    = ivt[ip[1] * 2] & 0xFFFF;
00323       break;
00324     }
00325     break;
00326   case 0x66:
00327     isOperand32 = TRUE;
00328     ip++;
00329     _current->tss.eip = (uInt16) (_current->tss.eip + 1); 
00330     goto gpfStart;
00331     break;
00332   case 0x67:
00333     isAddress32 = TRUE;
00334     ip++;
00335     _current->tss.eip = (uInt16) (_current->tss.eip + 1);
00336     goto gpfStart;
00337     break;
00338   case 0xF0:
00339     _current->tss.eip = (uInt16) (_current->tss.eip + 1);
00340     kpanic("GPF OP 0xF0\n");
00341     break;
00342   case 0x9C:
00343     if (isOperand32 == TRUE) {
00344       _current->tss.esp = ((_current->tss.esp & 0xffff) - 4) & 0xffff;
00345       stack32--;
00346      stack32[0] = _current->tss.eflags & 0xDFF;
00347      if (_current->oInfo.v86If == TRUE) 
00348        stack32[0] |= EFLAG_IF;
00349      else stack32[0] &= ~EFLAG_IF;
00350     } else {
00351       _current->tss.esp = ((_current->tss.esp & 0xffff) - 2) & 0xffff;
00352       stack--;
00353 
00354        stack[0] = (uInt16) _current->tss.eflags;
00355        if (_current->oInfo.v86If == TRUE) stack[0] |= EFLAG_IF;
00356        else stack[0] &= ~EFLAG_IF;
00357        _current->tss.eip = (uInt16) (_current->tss.eip + 1);
00358        
00359     }
00360     break;
00361   case 0x9D:
00362     if (isOperand32 == TRUE) {
00363       _current->tss.eflags = EFLAG_IF | EFLAG_VM | (stack32[0] & 0xDFF);
00364       _current->oInfo.v86If = (stack32[0] & EFLAG_IF) != 0;
00365       _current->tss.esp = ((_current->tss.esp & 0xffff) + 4) & 0xffff;
00366     } else {
00367       _current->tss.eflags = EFLAG_IF | EFLAG_VM | stack[0];
00368       _current->oInfo.v86If = (stack[0] & EFLAG_IF) != 0;
00369       _current->tss.esp = ((_current->tss.esp & 0xffff) + 2) & 0xffff;
00370     }
00371     _current->tss.eip = (uInt16) (_current->tss.eip + 1);
00372     /* kprintf("popf [0x%X]\n",_current->id); */
00373     break;
00374   case 0xFA:
00375     _current->oInfo.v86If = FALSE;
00376     _current->tss.eflags &= ~EFLAG_IF;
00377     _current->tss.eip = (uInt16) (_current->tss.eip + 1);
00378     _current->oInfo.timer = 0x1;
00379     break;
00380   case 0xFB:
00381     _current->oInfo.v86If = TRUE;
00382     _current->tss.eflags |= EFLAG_IF;
00383     _current->tss.eip = (uInt16) (_current->tss.eip + 1);
00384     _current->oInfo.timer = 0x0;
00385     /* kprintf("sti [0x%X]\n",_current->id); */
00386     break;
00387   case 0xCF:
00388     _current->tss.eip = stack[0];
00389     _current->tss.cs = stack[1];
00390     _current->tss.eflags = EFLAG_IF | EFLAG_VM | stack[2];
00391     _current->oInfo.v86If = (stack[2] & EFLAG_IF) != 0;
00392     _current->tss.esp = ((_current->tss.esp & 0xffff) + 6) & 0xffff;
00393     /* kprintf("iret [0x%X]\n",_current->id); */
00394     break;
00395   case 0xEC:                    /* IN AL,DX */
00396     _current->tss.eax = (_current->tss.eax & ~0xFF) | inportByte(_current->tss.edx);
00397     _current->tss.eip = (uInt16) (_current->tss.eip + 1);
00398     break;
00399   case 0xED:                    /* IN AX,DX */
00400     _current->tss.eax = (_current->tss.eax & ~0xFFFF) | inportWord(_current->tss.edx);
00401     _current->tss.eip = (uInt16) (_current->tss.eip + 1);
00402     break;
00403   case 0xEE:                    /* OUT DX,AL */
00404     outportByte(_current->tss.edx, _current->tss.eax & 0xFF);
00405     _current->tss.eip = (uInt16) (_current->tss.eip + 1);
00406     break;
00407   case 0xEF:
00408     outportWord(_current->tss.edx, _current->tss.eax);
00409     _current->tss.eip = (uInt16) (_current->tss.eip + 1);
00410     break;
00411   case 0xF4:
00412     _current->tss.eip = (uInt16) (_current->tss.eip + 1);
00413     break;
00414   default:                      /* something wrong */
00415      kprintf("NonHandled OpCode [0x%X:0x%X]\n",_current->id,ip[0]);
00416      _current->state = DEAD;
00417     break;
00418     }
00419   irqEnable(0);
00420   while (1);
00421   }
00422 
00423 /* Removed static however this is the only place it's called from */
00424 void mathStateRestore() {
00425   if (_usedMath != 0x0) {
00426     asm(
00427       "fnsave %0"
00428       :
00429       : "m" (_usedMath->i387)
00430       );
00431     }
00432   if (_current->usedMath != 0x0) {
00433     asm(
00434       "frstor %0"
00435       :
00436       : "m" (_current->i387)
00437       );
00438     }
00439   else {
00440     asm("fninit");
00441     _current->usedMath = 0x1;
00442     }
00443 
00444   _usedMath=_current;
00445 
00446   //Return
00447   }
00448 
00449 void _int7();
00450 asm(
00451   ".globl _int7              \n"
00452   "_int7:                    \n"
00453   "  pushl %eax              \n"
00454   "  clts                    \n"
00455   "  movl _current,%eax      \n"
00456   "  cmpl _usedMath,%eax     \n"
00457   "  je mathDone             \n"
00458   "  call mathStateRestore   \n"
00459   "mathDone:                 \n"
00460   "  popl %eax               \n"
00461   "  iret                    \n"
00462   );
00463 
00464 /***
00465  END
00466  ***/

Generated on Fri Dec 15 11:18:55 2006 for UbixOS V2 by  doxygen 1.4.7