Memory protection and page fault handling
[akaros.git] / kern / trap.c
index b1707fa..3c168a9 100644 (file)
@@ -78,9 +78,10 @@ idt_init(void)
        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.  
+       // turn on syscall handling and other user-accessible ints
        // DPL 3 means this can be triggered by the int instruction
-       idt[48].gd_dpl = 3;
+       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.
@@ -132,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
@@ -150,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)
@@ -165,6 +188,8 @@ trap(struct Trapframe *tf)
        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);
@@ -181,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.