// Update the low level state
 
-  if (intr_pending(&(info->intr_state))) {
-
-    switch (get_intr_type(&(info->intr_state))) {
-    case EXTERNAL_IRQ:
-      guest_ctrl->EVENTINJ.vector = get_intr_number(&(info->intr_state));
-      guest_ctrl->EVENTINJ.valid = 1;
-      guest_ctrl->EVENTINJ.type = SVM_INJECTION_EXTERNAL_INTR;
-      
-      break;
+  if (intr_pending(info)) {
+
+    switch (get_intr_type(info)) {
+    case EXTERNAL_IRQ: 
+      {
+       uint_t irq = get_intr_number(info);
+       guest_ctrl->EVENTINJ.vector = irq;
+       guest_ctrl->EVENTINJ.valid = 1;
+       guest_ctrl->EVENTINJ.type = SVM_INJECTION_EXTERNAL_INTR;
+       
+       injecting_intr(info, irq, EXTERNAL_IRQ);
+       
+       break;
+      }
     case NMI:
       guest_ctrl->EVENTINJ.type = SVM_INJECTION_NMI;
       break;
     case EXCEPTION:
-      guest_ctrl->EVENTINJ.type = SVM_INJECTION_EXCEPTION;
-      guest_ctrl->EVENTINJ.error_code = info->intr_state.excp_error_code;
-      break;
+      {
+       uint_t excp = get_intr_number(info);
+
+       guest_ctrl->EVENTINJ.type = SVM_INJECTION_EXCEPTION;
+       
+       if (info->intr_state.excp_error_code) {
+         guest_ctrl->EVENTINJ.error_code = info->intr_state.excp_error_code;
+         guest_ctrl->EVENTINJ.ev = 1;
+       }
+       
+       guest_ctrl->EVENTINJ.vector = excp;
+       
+       injecting_intr(info, excp, EXCEPTION);
+       break;
+      }
     case SOFTWARE:
       guest_ctrl->EVENTINJ.type = SVM_INJECTION_SOFT_INTR;
       break;
 
 
     PrintDebug("Injecting Interrupt %d (EIP=%x)\n", guest_ctrl->EVENTINJ.vector, info->rip);
- 
+
 
     // IMPORTANT TODO
     // We need to figure out stack parameters....
 
 }
 
 
+
+
+
+
+
+
+
+int hook_irq(struct guest_info * info, int irq) {
+  extern struct vmm_os_hooks * os_hooks;
+
+  return os_hooks->hook_interrupt(info, irq);
+}
+
+int raise_exception_with_error(struct guest_info * info, uint_t excp, uint_t error_code) {
+  struct vm_intr * intr_state = &(info->intr_state);
+
+  if (intr_state->excp_pending) {
+    intr_state->excp_pending = 1;
+    intr_state->excp_num = excp;
+    intr_state->excp_error_code = error_code;
+    intr_state->excp_error_code_valid = 1;
+  } else {
+    return -1;
+  }
+
+  return 0;
+}
+
 int raise_exception(struct guest_info * info, uint_t excp) {
+  struct vm_intr * intr_state = &(info->intr_state);
 
-  /* We can't stack exceptions, 
-     but do we need to have some sort of priority?
-  */
-  if (info->intr_state.excp_pending) {
-    info->intr_state.excp_pending = 1;
-    info->intr_state.excp_num = excp;
+  if (intr_state->excp_pending == 0) {
+    intr_state->excp_pending = 1;
+    intr_state->excp_num = excp;
+    intr_state->excp_error_code = 0;
+    intr_state->excp_error_code_valid = 0;
   } else {
     return -1;
   }
 }
 
 
-int intr_pending(struct vm_intr * intr) {
-  if (intr->excp_pending) {
+
+
+
+
+
+
+
+
+
+int intr_pending(struct guest_info * info) {
+  struct vm_intr * intr_state = &(info->intr_state);
+
+  if (intr_state->excp_pending) {
     return 1;
-  } else if (intr->controller->intr_pending(intr->controller_state)) {
+  } else if (intr_state->controller->intr_pending(intr_state->controller_state)) {
     return 1;
   }
 
 }
 
 
-uint_t get_intr_number(struct vm_intr * intr) {
-  if (intr->excp_pending) {
-    return intr->excp_num;
-  } else if (intr->controller->intr_pending(intr->controller_state)) {
-    return intr->controller->get_intr_number(intr->controller_state);
+uint_t get_intr_number(struct guest_info * info) {
+  struct vm_intr * intr_state = &(info->intr_state);
+
+  if (intr_state->excp_pending) {
+    return intr_state->excp_num;
+  } else if (intr_state->controller->intr_pending(intr_state->controller_state)) {
+    return intr_state->controller->get_intr_number(intr_state->controller_state);
   }
 
   /* someway to get the [A]PIC intr */
 }
 
 
-uint_t get_intr_type(struct vm_intr * intr) {
-  if (intr->excp_pending) {
+intr_type_t get_intr_type(struct guest_info * info) {
+ struct vm_intr * intr_state = &(info->intr_state);
+
+  if (intr_state->excp_pending) {
     return EXCEPTION;
-  } else if (intr->controller->intr_pending(intr->controller_state)) {
+  } else if (intr_state->controller->intr_pending(intr_state->controller_state)) {
     return EXTERNAL_IRQ;
   }
 
   return INVALID_INTR;
 }
 
-int hook_irq(struct guest_info * info, int irq) {
-  extern struct vmm_os_hooks * os_hooks;
 
-  return os_hooks->hook_interrupt(info, irq);
+
+
+
+
+int injecting_intr(struct guest_info * info, uint_t intr_num, intr_type_t type) {
+  struct vm_intr * intr_state = &(info->intr_state);
+
+  if (type == EXCEPTION) {
+
+    intr_state->excp_pending = 0;
+    intr_state->excp_num = 0;
+    intr_state->excp_error_code = 0;
+    intr_state->excp_error_code_valid = 0;
+    
+  } else if (type == EXTERNAL_IRQ) {
+    return intr_state->controller->begin_irq(intr_state->controller_state, intr_num);
+  }
+
+  return 0;
 }
 
   guest_pde_access = can_access_pde32(guest_pde, fault_addr, error_code);
 
   if (guest_pde_access != PT_ACCESS_OK) {
-
-    //
     // inject page fault to the guest (Guest PDE fault)
-    //
 
-    PrintDebug("Guest Page fault (currently not handled)\n");
-    return -1;
+    info->ctrl_regs.cr2 = fault_addr;
+    raise_exception_with_error(info, PF_EXCEPTION, *(uint_t *)&error_code);
+
+    return 0;
   }
 
   shadow_pde_access = can_access_pde32(shadow_pde, fault_addr, error_code);
     
     if (guest_pa_to_host_va(info, PDE32_T_ADDR((*guest_pde_entry)), (addr_t*)&guest_pte) == -1) {
       PrintDebug("Invalid Guest PTE Address: 0x%x\n", PDE32_T_ADDR((*guest_pde_entry)));
-      return -1;
+      // Machine check the guest
+
+      raise_exception(info, MC_EXCEPTION);
+      
+      return 0;
     }
 
 
     }
 
  } else {
-    PrintDebug("Unknown Error\n");
+    // Unknown error raise page fault in guest
+    info->ctrl_regs.cr2 = fault_addr;
+    raise_exception_with_error(info, PF_EXCEPTION, *(uint_t *)&error_code);
+
+    // For debugging we will return an error here for the time being, 
+    // this probably shouldn't ever happen
+    PrintDebug("Unknown Error occurred\n");
+    PrintDebug("Manual Says to inject page fault into guest\n");
     return -1;
   }
 
 /* 
  * We assume the the guest pte pointer has already been translated to a host virtual address
  */
-int handle_shadow_pte32_fault(struct guest_info* info, 
+int handle_shadow_pte32_fault(struct guest_info * info, 
                              addr_t fault_addr, 
                              pf_error_t error_code,
                              pte32_t * shadow_pte, 
   // Check the guest page permissions
   guest_pte_access = can_access_pte32(guest_pte, fault_addr, error_code);
 
+  
   if (guest_pte_access != PT_ACCESS_OK) {
-
-    //
-    // Inject page fault into the guest                
-    //
-
-    PrintDebug("Guest Page fault (currently not handled)\n");
-    return -1;
+    // Inject page fault into the guest        
+    
+    info->ctrl_regs.cr2 = fault_addr;
+    raise_exception_with_error(info, PF_EXCEPTION, *(uint_t *)&error_code);
+    
+    return 0;
   }
-
+  
+  
   shadow_pte_access = can_access_pte32(shadow_pte, fault_addr, error_code);
 
-  if (shadow_pte_access == PT_ENTRY_NOT_PRESENT) {
+  if (shadow_pte_access == PT_ACCESS_OK) {
+    // Inconsistent state...
+    // Guest Re-Entry will flush page tables and everything should now work
+    return 0;
+  } else if (shadow_pte_access == PT_ENTRY_NOT_PRESENT) {
     addr_t shadow_pa;
     addr_t guest_pa = PTE32_T_ADDR((*guest_pte_entry));
 
     // Page Table Entry Not Present
 
     if (get_shadow_addr_type(info, guest_pa) == HOST_REGION_INVALID) {
-
-      //
       // Inject a machine check in the guest
-      //
+
+      raise_exception(info, MC_EXCEPTION);
 
       PrintDebug("Invalid Guest Address in page table (0x%x)\n", guest_pa);
-      return -1;
+      return 0;
     }
 
     shadow_pa = get_shadow_addr(info, guest_pa);
       shadow_pte_entry->writable = 0;
     }
 
-  } else if (shadow_pte_access == PT_WRITE_ERROR) {
-
-    //
-    // Page Table Entry marked read-only
-    //
-
-    PrintDebug("Shadow Paging Write Error\n");
-    return -1;
-  } else if (shadow_pte_access == PT_USER_ERROR) {
+  } else if ((shadow_pte_access == PT_WRITE_ERROR) &&
+            (guest_pte_entry->dirty == 0)) {
+    guest_pte_entry->dirty = 1;
+    shadow_pte_entry->writable = guest_pte_entry->writable;
 
-    //
-    // Page Table Entry marked non-user
-    //
-
-    PrintDebug("Shadow Paging User access error\n");
-    return -1;
-  } else if (shadow_pte_access == PT_ACCESS_OK) {
-
-    PrintDebug("Page Fault occurred for No Reason\n");
-    return -1;
+    return 0;
   } else {
-    PrintDebug("Unknown Error\n");
+    // Inject page fault into the guest        
+       
+    info->ctrl_regs.cr2 = fault_addr;
+    raise_exception_with_error(info, PF_EXCEPTION, *(uint_t *)&error_code);
+
+    PrintDebug("PTE Page fault fell through... Not sure if this should ever happen\n");
+    PrintDebug("Manual Says to inject page fault into guest\n");
     return -1;
   }