Memory protection and page fault handling
[akaros.git] / kern / trap.c
index efe3a5b..3c168a9 100644 (file)
@@ -58,7 +58,30 @@ idt_init(void)
 {
        extern struct Segdesc gdt[];
        
-       // LAB 3: Your code here.
+       // This table is made in trapentry.S by each macro in that file.
+       // It is layed out such that the ith entry is the ith's traphandler's
+       // (uint32_t) trap addr, then (uint32_t) trap number
+       struct trapinfo { uint32_t trapaddr; uint32_t trapnumber; };
+       extern struct trapinfo trap_tbl[];
+       extern struct trapinfo trap_tbl_end[];
+       int i, trap_tbl_size = trap_tbl_end - trap_tbl;
+       extern void ISR_default(void);
+
+       // set all to default, to catch everything
+       for(i = 0; i < 256; i++)
+               SETGATE(idt[i], 1, GD_KT, &ISR_default, 0);
+       
+       // set all entries that have real trap handlers
+       // we need to stop short of the last one, since the last is the default
+       // handler with a fake interrupt number (500) that is out of bounds of
+       // the idt[]
+       for(i = 0; i < trap_tbl_size - 1; i++)
+               SETGATE(idt[trap_tbl[i].trapnumber], 1, GD_KT, trap_tbl[i].trapaddr, 0);
+
+       // turn on syscall handling and other user-accessible ints
+       // DPL 3 means this can be triggered by the int instruction
+       idt[T_SYSCALL].gd_dpl = 3;
+       idt[T_BRKPT].gd_dpl = 3;
 
        // Setup a TSS so that we get the right stack
        // when we trap to the kernel.
@@ -110,17 +133,36 @@ static void
 trap_dispatch(struct Trapframe *tf)
 {
        // Handle processor exceptions.
-       // LAB 3: Your code here.
        
-
-       // Unexpected trap: The user process or the kernel has a bug.
-       print_trapframe(tf);
-       if (tf->tf_cs == GD_KT)
-               panic("unhandled trap in kernel");
-       else {
-               env_destroy(curenv);
-               return;
+       switch(tf->tf_trapno) {
+               case T_BRKPT:
+                       while (1)
+                               monitor(tf);
+                       // never get to this
+                       assert(0);
+               case T_PGFLT:
+                       page_fault_handler(tf);
+                       break;
+               case T_SYSCALL:
+                       // check for userspace, for now
+                       assert(tf->tf_cs != GD_KT);
+                       tf->tf_regs.reg_eax = 
+                               syscall(tf->tf_regs.reg_eax, tf->tf_regs.reg_edx, 
+                                       tf->tf_regs.reg_ecx, tf->tf_regs.reg_ebx, 
+                                       tf->tf_regs.reg_edi, tf->tf_regs.reg_esi);
+                       env_run(curenv);
+                       break;
+               default:
+                       // Unexpected trap: The user process or the kernel has a bug.
+                       print_trapframe(tf);
+                       if (tf->tf_cs == GD_KT)
+                               panic("Damn Damn!  Unhandled trap in the kernel!");
+                       else {
+                               env_destroy(curenv);
+                               return;
+                       }
        }
+       return;
 }
 
 void
@@ -128,6 +170,9 @@ trap(struct Trapframe *tf)
 {
        cprintf("Incoming TRAP frame at %p\n", tf);
 
+       if ((tf->tf_cs & ~3) != GD_UT && (tf->tf_cs & ~3) != GD_KT)
+               panic("Trapframe with invalid CS!");
+
        if ((tf->tf_cs & 3) == 3) {
                // Trapped from user mode.
                // Copy trap frame (which is currently on the stack)
@@ -142,6 +187,9 @@ trap(struct Trapframe *tf)
        // Dispatch based on what type of trap occurred
        trap_dispatch(tf);
 
+       // should this be if == 3?  Sort out later when we handle traps.
+       // so far we never get here
+       assert(0);
         // Return to the current environment, which should be runnable.
         assert(curenv && curenv->env_status == ENV_RUNNABLE);
         env_run(curenv);
@@ -158,7 +206,9 @@ page_fault_handler(struct Trapframe *tf)
 
        // Handle kernel-mode page faults.
        
-       // LAB 3: Your code here.
+       // TODO - one day, we'll want to handle this.
+       if ((tf->tf_cs & 3) == 0)
+               panic("Page Fault in the Kernel!");
 
        // We've already handled kernel-mode exceptions, so if we get here,
        // the page fault happened in user mode.