# 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  ***/