- Fix KiDispatchException to unmask KI_EXCEPTION_INTERNAL when setting the exception...
[reactos.git] / reactos / ntoskrnl / ke / i386 / trap.s
index cb17cd4..abb36b7 100644 (file)
 #include <internal/i386/asmmacro.S>
 .intel_syntax noprefix
 
+#define Running 2
+#define WrDispatchInt 0x1F
+
 /* GLOBALS *******************************************************************/
 
+.data
 .globl _KiIdt
 _KiIdt:
 /* This is the Software Interrupt Table that we handle in this file:        */
@@ -86,107 +90,62 @@ _KiUnexpectedEntrySize:
 _UnexpectedMsg:
     .asciz "\n\x7\x7!!! Unexpected Interrupt %02lx !!!\n"
 
-Broken:
-    .asciz "\n\x7\x7!!! Broken TrapFrame. Magic: %08lx MagicB: %08lx!!!\n"
+_UnhandledMsg:
+    .asciz "\n\x7\x7!!! Unhandled or Unexpected Code at line: %lx!!!\n"
+
+_KiTrapPrefixTable:
+    .byte 0xF2                      /* REP                                  */
+    .byte 0xF3                      /* REP INS/OUTS                         */
+    .byte 0x67                      /* ADDR                                 */
+    .byte 0xF0                      /* LOCK                                 */
+    .byte 0x66                      /* OP                                   */
+    .byte 0x2E                      /* SEG                                  */
+    .byte 0x3E                      /* DS                                   */
+    .byte 0x26                      /* ES                                   */
+    .byte 0x64                      /* FS                                   */
+    .byte 0x65                      /* GS                                   */
+    .byte 0x36                      /* SS                                   */
+
+_KiTrapIoTable:
+    .byte 0xE4                      /* IN                                   */
+    .byte 0xE5                      /* IN                                   */
+    .byte 0xEC                      /* IN                                   */
+    .byte 0xED                      /* IN                                   */
+    .byte 0x6C                      /* INS                                  */
+    .byte 0x6D                      /* INS                                  */
+    .byte 0xE6                      /* OUT                                  */
+    .byte 0xE7                      /* OUT                                  */
+    .byte 0xEE                      /* OUT                                  */
+    .byte 0xEF                      /* OUT                                  */
+    .byte 0x6E                      /* OUTS                                 */
+    .byte 0x6F                      /* OUTS                                 */
 
 /* SOFTWARE INTERRUPT SERVICES ***********************************************/
+.text
 
 _KiGetTickCount:
 _KiCallbackReturn:
 _KiRaiseAssertion:
-    int 3
+    /* FIXME: TODO */
+    UNHANDLED_PATH
 
 .func KiSystemService
+Dr_kss: DR_TRAP_FIXUP
 _KiSystemService:
 
     /* Enter the shared system call prolog */
-    SYSCALL_PROLOG
+    SYSCALL_PROLOG kss
 
     /* Jump to the actual handler */
     jmp SharedCode
 .endfunc
 
 .func KiFastCallEntry
+Dr_FastCallDrSave: DR_TRAP_FIXUP
 _KiFastCallEntry:
 
-    /* Set FS to PCR */
-    mov ecx, KGDT_R0_PCR
-    mov fs, cx
-
-    /* Set DS/ES to User Selector */
-    mov ecx, KGDT_R3_DATA | RPL_MASK
-    mov ds, cx
-    mov es, cx
-
-    /* Set the current stack to Kernel Stack */
-    mov ecx, [fs:KPCR_TSS]
-    mov esp, ss:[ecx+KTSS_ESP0]
-
-    /* Set up a fake INT Stack. */
-    push KGDT_R3_DATA + RPL_MASK
-    push edx                            /* Ring 3 SS:ESP */
-    pushf                               /* Ring 3 EFLAGS */
-    push 2                              /* Ring 0 EFLAGS */
-    add edx, 8                          /* Skip user parameter list */
-    popf                                /* Set our EFLAGS */
-    or dword ptr [esp], EFLAGS_INTERRUPT_MASK   /* Re-enable IRQs in EFLAGS, to fake INT */
-    push KGDT_R3_CODE + RPL_MASK
-    push KUSER_SHARED_SYSCALL_RET
-
-    /* Setup the Trap Frame stack */
-    push 0
-    push ebp
-    push ebx
-    push esi
-    push edi
-    push KGDT_R3_TEB + RPL_MASK
-
-    /* Save pointer to our PCR */
-    mov ebx, [fs:KPCR_SELF]
-
-    /* Get a pointer to the current thread */
-    mov esi, [ebx+KPCR_CURRENT_THREAD]
-
-    /* Set the exception handler chain terminator */
-    push [ebx+KPCR_EXCEPTION_LIST]
-    mov dword ptr [ebx+KPCR_EXCEPTION_LIST], -1
-
-    /* Use the thread's stack */
-    mov ebp, [esi+KTHREAD_INITIAL_STACK]
-
-    /* Push previous mode */
-    push UserMode
-
-    /* Skip the other registers */
-    sub esp, 0x48
-
-    /* Make space for us on the stack */
-    sub ebp, 0x29C
-
-    /* Write the previous mode */
-    mov byte ptr [esi+KTHREAD_PREVIOUS_MODE], UserMode
-
-    /* Sanity check */
-    cmp ebp, esp
-    jnz BadStack
-
-    /* Flush DR7 */
-    and dword ptr [ebp+KTRAP_FRAME_DR7], 0
-
-    /* Check if the thread was being debugged */
-    test byte ptr [esi+KTHREAD_DEBUG_ACTIVE], 0xFF
-
-    /* Set the thread's trap frame */
-    mov [esi+KTHREAD_TRAP_FRAME], ebp
-
-    /* Save DR registers if needed */
-    //jnz Dr_FastCallDrSave
-
-    /* Set the trap frame debug header */
-    SET_TF_DEBUG_HEADER
-
-    /* Enable interrupts */
-    sti
+    /* Enter the fast system call prolog */
+    FASTCALL_PROLOG FastCallDrSave
 
 SharedCode:
 
@@ -219,6 +178,7 @@ SharedCode:
 
     /* Check if we should flush the User Batch */
     xor ebx, ebx
+ReadBatch:
     or ebx, [ecx+TEB_GDI_BATCH_COUNT]
     jz NotWin32K
 
@@ -507,17 +467,19 @@ V86_Exit:
     iret
 
 AbiosExit:
-    /* Not yet supported */
-    int 3
+    /* FIXME: TODO */
+    UNHANDLED_PATH
 
 .func KiDebugService
+Dr_kids:    DR_TRAP_FIXUP
+V86_kids:   V86_TRAP_FIXUP
 _KiDebugService:
 
     /* Push error code */
     push 0
 
     /* Enter trap */
-    TRAP_PROLOG(kids)
+    TRAP_PROLOG kids
 
     /* Increase EIP so we skip the INT3 */
     //inc dword ptr [ebp+KTRAP_FRAME_EIP]
@@ -525,7 +487,7 @@ _KiDebugService:
     /* Call debug service dispatcher */
     mov eax, [ebp+KTRAP_FRAME_EAX]
     mov ecx, [ebp+KTRAP_FRAME_ECX]
-    mov edx, [ebp+KTRAP_FRAME_EAX]
+    mov edx, [ebp+KTRAP_FRAME_EDX]
 
     /* Check for V86 mode */
     test dword ptr [ebp+KTRAP_FRAME_EFLAGS], EFLAGS_V86_MASK
@@ -680,7 +642,7 @@ _CommonDispatchException:
     mov [esp+EXCEPTION_RECORD_NUMBER_PARAMETERS], ecx
 
     /* Check parameter count */
-    cmp eax, 0
+    cmp ecx, 0
     jz NoParams
 
     /* Get information */
@@ -702,9 +664,11 @@ NoParams:
 
 SetPreviousMode:
 
-    /* Calculate the previous mode */
+    /* Get the caller's CS */
     mov eax, [ebp+KTRAP_FRAME_CS]
+
 MaskMode:
+    /* Check if it was user-mode or kernel-mode */
     and eax, MODE_MASK
 
     /* Dispatch the exception */
@@ -745,13 +709,22 @@ _DispatchTwoParam:
 
 /* HARDWARE TRAP HANDLERS ****************************************************/
 
+.func KiFixupFrame
+_KiFixupFrame:
+
+    /* TODO: Routine to fixup a KTRAP_FRAME when faulting from a syscall. */
+    UNHANDLED_PATH
+.endfunc
+
 .func KiTrap0
+Dr_kit0:    DR_TRAP_FIXUP
+V86_kit0:   V86_TRAP_FIXUP
 _KiTrap0:
     /* Push error code */
     push 0
 
     /* Enter trap */
-    TRAP_PROLOG(0)
+    TRAP_PROLOG kit0
 
     /* Check for V86 */
     test dword ptr [ebp+KTRAP_FRAME_EFLAGS], EFLAGS_V86_MASK
@@ -781,16 +754,19 @@ VdmCheck:
 
     /* We don't support this yet! */
 V86Int0:
-    int 3
+    /* FIXME: TODO */
+    UNHANDLED_PATH
 .endfunc
 
 .func KiTrap1
+Dr_kit1:    DR_TRAP_FIXUP
+V86_kit1:   V86_TRAP_FIXUP
 _KiTrap1:
     /* Push error code */
     push 0
 
     /* Enter trap */
-    TRAP_PROLOG(1)
+    TRAP_PROLOG kit1
 
     /* Check for V86 */
     test dword ptr [ebp+KTRAP_FRAME_EFLAGS], EFLAGS_V86_MASK
@@ -823,7 +799,7 @@ V86Int1:
     jz EnableInterrupts
 
     /* We don't support VDM! */
-    int 3
+    UNHANDLED_PATH
 .endfunc
 
 .globl _KiTrap2
@@ -836,12 +812,14 @@ _KiTrap2:
 .endfunc
 
 .func KiTrap3
+Dr_kit3:    DR_TRAP_FIXUP
+V86_kit3:   V86_TRAP_FIXUP
 _KiTrap3:
     /* Push error code */
     push 0
 
     /* Enter trap */
-    TRAP_PROLOG(3)
+    TRAP_PROLOG kit3
 
     /* Check for V86 */
     test dword ptr [ebp+KTRAP_FRAME_EFLAGS], EFLAGS_V86_MASK
@@ -868,8 +846,8 @@ PrepInt3:
     /* Setup EIP, NTSTATUS and parameter count, then dispatch */
     mov ebx, [ebp+KTRAP_FRAME_EIP]
     dec ebx
-    mov eax, STATUS_BREAKPOINT
     mov ecx, 3
+    mov eax, STATUS_BREAKPOINT
     call _CommonDispatchException
 
 V86Int3:
@@ -880,16 +858,18 @@ V86Int3:
     jz EnableInterrupts3
 
     /* We don't support VDM! */
-    int 3
+    UNHANDLED_PATH
 .endfunc
 
 .func KiTrap4
+Dr_kit4:    DR_TRAP_FIXUP
+V86_kit4:   V86_TRAP_FIXUP
 _KiTrap4:
     /* Push error code */
     push 0
 
     /* Enter trap */
-    TRAP_PROLOG(4)
+    TRAP_PROLOG kit4
 
     /* Check for V86 */
     test dword ptr [ebp+KTRAP_FRAME_EFLAGS], EFLAGS_V86_MASK
@@ -920,16 +900,18 @@ VdmCheck4:
 
     /* We don't support this yet! */
 V86Int4:
-    int 3
+    UNHANDLED_PATH
 .endfunc
 
 .func KiTrap5
+Dr_kit5:    DR_TRAP_FIXUP
+V86_kit5:   V86_TRAP_FIXUP
 _KiTrap5:
     /* Push error code */
     push 0
 
     /* Enter trap */
-    TRAP_PROLOG(5)
+    TRAP_PROLOG kit5
 
     /* Check for V86 */
     test dword ptr [ebp+KTRAP_FRAME_EFLAGS], EFLAGS_V86_MASK
@@ -964,32 +946,133 @@ VdmCheck5:
 
     /* We don't support this yet! */
 V86Int5:
-    int 3
+    UNHANDLED_PATH
 .endfunc
 
 .func KiTrap6
+Dr_kit6:    DR_TRAP_FIXUP
+V86_kit6:   V86_TRAP_FIXUP
 _KiTrap6:
+
+    /* It this a V86 GPF? */
+    test dword ptr [esp+8], EFLAGS_V86_MASK
+    jz NotV86UD
+
+    /* Enter V86 Trap */
+    V86_TRAP_PROLOG kit6
+
+    /* Not yet supported (Invalid OPCODE from V86) */
+    UNHANDLED_PATH
+
+NotV86UD:
     /* Push error code */
     push 0
 
     /* Enter trap */
-    TRAP_PROLOG(6)
+    TRAP_PROLOG kit6
 
-    /* Not yet supported */
-    int 3
-    jmp $
+    /* Check if this happened in kernel mode */
+    test byte ptr [ebp+KTRAP_FRAME_CS], MODE_MASK
+    jz KmodeOpcode
+
+    /* Check for VDM */
+    cmp word ptr [ebp+KTRAP_FRAME_CS], KGDT_R3_CODE + RPL_MASK
+    jz UmodeOpcode
+
+    /* Check if the process is vDM */
+    mov ebx, fs:[KPCR_CURRENT_THREAD]
+    mov ebx, [ebx+KTHREAD_APCSTATE_PROCESS]
+    cmp dword ptr [ebx+EPROCESS_VDM_OBJECTS], 0
+    jnz IsVdmOpcode
+
+UmodeOpcode:
+    /* Get EIP and enable interrupts at this point */
+    mov esi, [ebp+KTRAP_FRAME_EIP]
+    sti
+
+    /* Set intruction prefix length */
+    mov ecx, 4
+
+    /* Setup a SEH frame */
+    push ebp
+    push OpcodeSEH
+    push fs:[KPCR_EXCEPTION_LIST]
+    mov fs:[KPCR_EXCEPTION_LIST], esp
+
+OpcodeLoop:
+    /* Get the instruction and check if it's LOCK */
+    mov al, [esi]
+    cmp al, 0xF0
+    jz LockCrash
+
+    /* Keep moving */
+    add esi, 1
+    loop OpcodeLoop
+
+    /* Undo SEH frame */
+    pop fs:[KPCR_EXCEPTION_LIST]
+    add esp, 8
+
+KmodeOpcode:
+
+    /* Re-enable interrupts */
+    sti
+
+    /* Setup illegal instruction exception and dispatch it */
+    mov ebx, [ebp+KTRAP_FRAME_EIP]
+    mov eax, STATUS_ILLEGAL_INSTRUCTION
+    jmp _DispatchNoParam
+
+LockCrash:
+
+    /* Undo SEH Frame */
+    pop fs:[KPCR_EXCEPTION_LIST]
+    add esp, 8
+
+    /* Setup invalid lock exception and dispatch it */
+    mov ebx, [ebp+KTRAP_FRAME_EIP]
+    mov eax, STATUS_INVALID_LOCK_SEQUENCE
+    jmp _DispatchNoParam
+
+IsVdmOpcode:
+
+    /* Unhandled yet */
+    UNHANDLED_PATH
 
     /* Return to caller */
     jmp _Kei386EoiHelper@0
+
+OpcodeSEH:
+
+    /* Get SEH frame */
+    mov esp, [esp+8]
+    pop fs:[KPCR_EXCEPTION_LIST]
+    add esp, 4
+    pop ebp
+
+    /* Check if this was user mode */
+    test dword ptr [ebp+KTRAP_FRAME_CS], MODE_MASK
+    jnz KmodeOpcode
+
+    /* Do a bugcheck */
+    push ebp
+    push 0
+    push 0
+    push 0
+    push 0
+    push KMODE_EXCEPTION_NOT_HANDLED
+    call _KeBugCheckWithTf@24
 .endfunc
 
 .func KiTrap7
+Dr_kit7:    DR_TRAP_FIXUP
+V86_kit7:   V86_TRAP_FIXUP
 _KiTrap7:
     /* Push error code */
     push 0
 
     /* Enter trap */
-    TRAP_PROLOG(7)
+    TRAP_PROLOG kit7
 
     /* Get the current thread and stack */
 StartTrapHandle:
@@ -1074,13 +1157,195 @@ AfterRestore:
     cli
     jmp StartTrapHandle
 
+KernelNpx:
+
+    /* Set delayed error */
+    or dword ptr [ecx+FN_CR0_NPX_STATE], CR0_TS
+
+    /* Check if this happened during restore */
+    cmp dword ptr [ebp+KTRAP_FRAME_EIP], offset FrRestore
+    jnz UserNpx
+
+    /* Skip instruction and dispatch the exception */
+    add dword ptr [ebp+KTRAP_FRAME_EIP], 3
+    jmp _Kei386EoiHelper@0
+
 IsLoaded:
     /* Check if TS is set */
     test bl, CR0_TS
     jnz TsSetOnLoadedState
 
-    /* Check if the trap came from user-mode */
-    int 3
+HandleNpxFault:
+    /* Check if the trap came from V86 mode */
+    test dword ptr [ebp+KTRAP_FRAME_EFLAGS], EFLAGS_V86_MASK
+    jnz V86Npx
+
+    /* Check if it came from kernel mode */
+    test byte ptr [ebp+KTRAP_FRAME_CS], MODE_MASK
+    jz KernelNpx
+
+    /* Check if it came from a VDM */
+    cmp word ptr [ebp+KTRAP_FRAME_CS], KGDT_R3_CODE + RPL_MASK
+    jne V86Npx
+
+UserNpx:
+    /* Get the current thread */
+    mov eax, fs:[KPCR_CURRENT_THREAD]
+
+    /* Check NPX state */
+    cmp byte ptr [eax+KTHREAD_NPX_STATE], NPX_STATE_NOT_LOADED
+
+    /* Get the NPX save area */
+    mov ecx, [eax+KTHREAD_INITIAL_STACK]
+    lea ecx, [ecx-NPX_FRAME_LENGTH]
+    jz NoSaveRestore
+
+HandleUserNpx:
+
+    /* Set new CR0 */
+    mov ebx, cr0
+    and ebx, ~(CR0_MP + CR0_EM + CR0_TS)
+    mov cr0, ebx
+
+    /* Check if we have FX support */
+    test byte ptr _KeI386FxsrPresent, 1
+    jz FnSave2
+
+    /* Save the state */
+    fxsave [ecx]
+    jmp MakeCr0Dirty
+FnSave2:
+    fnsave [ecx]
+    wait
+
+MakeCr0Dirty:
+    /* Make CR0 state not loaded */
+    or ebx, NPX_STATE_NOT_LOADED
+    or ebx, [ecx+FN_CR0_NPX_STATE]
+    mov cr0, ebx
+
+    /* Update NPX state */
+    mov byte ptr [eax+KTHREAD_NPX_STATE], NPX_STATE_NOT_LOADED
+    mov dword ptr fs:[KPCR_NPX_THREAD], 0
+
+NoSaveRestore:
+    /* Clear the TS bit and re-enable interrupts */
+    and dword ptr [ecx+FN_CR0_NPX_STATE], ~CR0_TS
+    sti
+
+    /* Check if we have FX support */
+    test byte ptr _KeI386FxsrPresent, 1
+    jz FnError
+
+    /* Get error offset, control and status words */
+    mov ebx, [ecx+FX_ERROR_OFFSET]
+    movzx eax, word ptr [ecx+FX_CONTROL_WORD]
+    movzx edx, word ptr [ecx+FX_STATUS_WORD]
+
+    /* Get the faulting opcode */
+    mov esi, [ecx+FX_DATA_OFFSET]
+    jmp CheckError
+
+FnError:
+    /* Get error offset, control and status words */
+    mov ebx, [ecx+FP_ERROR_OFFSET]
+    movzx eax, word ptr [ecx+FP_CONTROL_WORD]
+    movzx edx, word ptr [ecx+FP_STATUS_WORD]
+
+    /* Get the faulting opcode */
+    mov esi, [ecx+FP_DATA_OFFSET]
+
+CheckError:
+    /* Mask exceptions */
+    and eax, 0x3F
+    not eax
+    and eax, edx
+
+    /* Check if what's left is invalid */
+    test al, 1
+    jz ValidNpxOpcode
+
+    /* Check if it was a stack fault */
+    test al, 64
+    jnz InvalidStack
+
+    /* Raise exception */
+    mov eax, STATUS_FLOAT_INVALID_OPERATION
+    jmp _DispatchOneParam
+
+InvalidStack:
+
+    /* Raise exception */
+    mov eax, STATUS_FLOAT_STACK_CHECK
+    jmp _DispatchTwoParam
+
+ValidNpxOpcode:
+
+    /* Check for divide by 0 */
+    test al, 4
+    jz 1f
+
+    /* Raise exception */
+    mov eax, STATUS_FLOAT_DIVIDE_BY_ZERO
+    jmp _DispatchOneParam
+
+1:
+    /* Check for denormal */
+    test al, 2
+    jz 1f
+
+    /* Raise exception */
+    mov eax, STATUS_FLOAT_INVALID_OPERATION
+    jmp _DispatchOneParam
+
+1:
+    /* Check for overflow */
+    test al, 8
+    jz 1f
+
+    /* Raise exception */
+    mov eax, STATUS_FLOAT_OVERFLOW
+    jmp _DispatchOneParam
+
+1:
+    /* Check for underflow */
+    test al, 16
+    jz 1f
+
+    /* Raise exception */
+    mov eax, STATUS_FLOAT_UNDERFLOW
+    jmp _DispatchOneParam
+
+1:
+    /* Check for precision fault */
+    test al, 32
+    jz UnexpectedNpx
+
+    /* Raise exception */
+    mov eax, STATUS_FLOAT_INEXACT_RESULT
+    jmp _DispatchOneParam
+
+UnexpectedNpx:
+
+    /* Strange result, bugcheck the OS */
+    sti
+    push ebp
+    push 0
+    push 0
+    push eax
+    push 1
+    push TRAP_CAUSE_UNKNOWN
+    call _KeBugCheckWithTf@24
+
+V86Npx:
+    /* Check if this is a VDM */
+    mov eax, fs:[KPCR_CURRENT_THREAD]
+    mov ebx, [eax+KTHREAD_APCSTATE_PROCESS]
+    cmp dword ptr [ebx+EPROCESS_VDM_OBJECTS], 0
+    jz HandleUserNpx
+
+    /* V86 NPX not handled */
+    UNHANDLED_PATH
 
 EmulationEnabled:
     /* Did this come from kernel-mode? */
@@ -1089,7 +1354,7 @@ EmulationEnabled:
 
     /* It came from user-mode, so this would only be valid inside a VDM */
     /* Since we don't actually have VDMs in ROS, bugcheck. */
-    jmp BogusTrap2
+    jmp UnexpectedNpx
 
 TsSetOnLoadedState:
     /* TS shouldn't be set, unless this we don't have a Math Processor */
@@ -1100,16 +1365,6 @@ TsSetOnLoadedState:
     clts
     jmp _Kei386EoiHelper@0
 
-BogusTrap2:
-    /* Cause a bugcheck */
-    sti
-    push 0
-    push 0
-    push eax
-    push 1
-    push TRAP_CAUSE_UNKNOWN
-    call _KeBugCheckEx@20
-
 BogusTrap:
     /* Cause a bugcheck */
     push 0
@@ -1130,12 +1385,14 @@ _KiTrap8:
 .endfunc
 
 .func KiTrap9
+Dr_kit9:    DR_TRAP_FIXUP
+V86_kit9:   V86_TRAP_FIXUP
 _KiTrap9:
     /* Push error code */
     push 0
 
     /* Enter trap */
-    TRAP_PROLOG(9)
+    TRAP_PROLOG kit9
 
     /* Enable interrupts and bugcheck */
     sti
@@ -1144,9 +1401,11 @@ _KiTrap9:
 .endfunc
 
 .func KiTrap10
+Dr_kit10:   DR_TRAP_FIXUP
+V86_kit10:  V86_TRAP_FIXUP
 _KiTrap10:
     /* Enter trap */
-    TRAP_PROLOG(10)
+    TRAP_PROLOG kit10
 
     /* Check for V86 */
     test dword ptr [ebp+KTRAP_FRAME_EFLAGS], EFLAGS_V86_MASK
@@ -1173,9 +1432,11 @@ Fatal:
 .endfunc
 
 .func KiTrap11
+Dr_kit11:   DR_TRAP_FIXUP
+V86_kit11:  V86_TRAP_FIXUP
 _KiTrap11:
     /* Enter trap */
-    TRAP_PROLOG(11)
+    TRAP_PROLOG kit11
 
     /* FIXME: ROS Doesn't handle segment faults yet */
     mov eax, 11
@@ -1183,16 +1444,43 @@ _KiTrap11:
 .endfunc
 
 .func KiTrap12
+Dr_kit12:   DR_TRAP_FIXUP
+V86_kit12:  V86_TRAP_FIXUP
 _KiTrap12:
     /* Enter trap */
-    TRAP_PROLOG(12)
+    TRAP_PROLOG kit12
 
     /* FIXME: ROS Doesn't handle stack faults yet */
     mov eax, 12
     jmp _KiSystemFatalException
 .endfunc
 
+.func KiTrapExceptHandler
+_KiTrapExceptHandler:
+
+    /* Setup SEH handler frame */
+    mov esp, [esp+8]
+    pop fs:[KPCR_EXCEPTION_LIST]
+    add esp, 4
+    pop ebp
+
+    /* Check if the fault came from user mode */
+    test dword ptr [ebp+KTRAP_FRAME_CS], MODE_MASK
+    jnz SetException
+
+    /* Kernel fault, bugcheck */
+    push ebp
+    push 0
+    push 0
+    push 0
+    push 0
+    push KMODE_EXCEPTION_NOT_HANDLED
+    call _KeBugCheckWithTf@24
+.endfunc
+
 .func KiTrap13
+Dr_kitd:    DR_TRAP_FIXUP
+V86_kitd:   V86_TRAP_FIXUP
 _KiTrap13:
 
     /* It this a V86 GPF? */
@@ -1233,7 +1521,7 @@ RaiseIrql:
     jnz NoReflect
 
     /* FIXME: TODO */
-    int 3
+    UNHANDLED_PATH
 
 NoReflect:
 
@@ -1256,15 +1544,27 @@ NotV86Trap:
 
 NotV86:
     /* Enter trap */
-    TRAP_PROLOG(13)
+    TRAP_PROLOG kitd
 
     /* Check if this was from kernel-mode */
     test dword ptr [ebp+KTRAP_FRAME_CS], MODE_MASK
     jnz UserModeGpf
 
-    /* FIXME: Check for GPF during GPF */
+    /* Check if we have a VDM alert */
+    cmp dword ptr fs:[KPCR_VDM_ALERT], 0
+    jnz VdmAlertGpf
+
+    /* Check for GPF during GPF */
+    mov eax, [ebp+KTRAP_FRAME_EIP]
+    cmp eax, offset CheckPrivilegedInstruction
+    jbe KmodeGpf
+    cmp eax, offset CheckPrivilegedInstruction2
+
+    /* FIXME: TODO */
+    UNHANDLED_PATH
 
     /* Get the opcode and trap frame */
+KmodeGpf:
     mov eax, [ebp+KTRAP_FRAME_EIP]
     mov eax, [eax]
     mov edx, [ebp+KTRAP_FRAME_EBP]
@@ -1350,8 +1650,7 @@ TrapCopy:
 MsrCheck:
 
     /* FIXME: Handle RDMSR/WRMSR */
-    int 3
-    jmp $
+    UNHANDLED_PATH
 
 NotIretGpf:
 
@@ -1397,33 +1696,344 @@ ExitGpfTrap:
 
 UserModeGpf:
 
-    /* FIXME: Unhandled */
-    int 3
-    jmp $
+    /* If the previous mode was kernel, raise a fatal exception */
+    mov eax, 13
+    test byte ptr [ebp+KTRAP_FRAME_CS], MODE_MASK
+    jz _KiSystemFatalException
+
+    /* Get the process and check which CS this came from */
+    mov ebx, fs:[KPCR_CURRENT_THREAD]
+    mov ebx, [ebx+KTHREAD_APCSTATE_PROCESS]
+    cmp word ptr [ebp+KTRAP_FRAME_CS], KGDT_R3_CODE + RPL_MASK
+    jz CheckVdmGpf
+
+    /* Check if this is a VDM */
+    cmp dword ptr [ebx+EPROCESS_VDM_OBJECTS], 0
+    jnz DispatchV86Gpf
+
+    /* Enable interrupts and check if we have an error code */
+    sti
+    cmp word ptr [ebp+KTRAP_FRAME_ERROR_CODE], 0
+    jnz SetException
+    jmp CheckPrivilegedInstruction
+
+HandleSegPop2:
+    /* Update EIP (will be updated below again) */
+    add dword ptr [ebp+KTRAP_FRAME_EIP], 1
+
+HandleEsPop:
+    /* Clear the segment, update EIP and ESP */
+    mov dword ptr [edx], 0
+    add dword ptr [ebp+KTRAP_FRAME_EIP], 1
+    add dword ptr [ebp+KTRAP_FRAME_ESP], 4
+    jmp _Kei386EoiHelper@0
+
+CheckVdmGpf:
+    /* Check if this is a VDM */
+    cmp dword ptr [ebx+EPROCESS_VDM_OBJECTS], 0
+    jz CheckPrivilegedInstruction
+
+    /* Bring interrupts back */
+    sti
+
+    /* Check what kind of instruction this is */
+    mov eax, [ebp+KTRAP_FRAME_EIP]
+    mov eax, [eax]
+
+    /* FIXME: Check for BOP4 */
+
+    /* Check if this is POP ES */
+    mov edx, ebp
+    add edx, KTRAP_FRAME_ES
+    cmp al, 0x07
+    jz HandleEsPop
+
+    /* Check if this is POP FS */
+    add edx, KTRAP_FRAME_FS - KTRAP_FRAME_ES
+    cmp ax, 0xA10F
+    jz HandleSegPop2
+
+    /* Check if this is POP GS */
+    add edx, KTRAP_FRAME_GS - KTRAP_FRAME_FS
+    cmp ax, 0xA90F
+    jz HandleSegPop2
+
+CheckPrivilegedInstruction:
+    /* Bring interrupts back */
+    sti
+
+    /* Setup a SEH handler */
+    push ebp
+    push offset _KiTrapExceptHandler
+    push fs:[KPCR_EXCEPTION_LIST]
+    mov fs:[KPCR_EXCEPTION_LIST], esp
+
+    /* Get EIP */
+    mov esi, [ebp+KTRAP_FRAME_EIP]
+
+    /* Setup loop count */
+    mov ecx, 15
+
+InstLoop:
+    /* Save loop count */
+    push ecx
+
+    /* Get the instruction */
+    lods byte ptr [esi]
+
+    /* Now lookup in the prefix table */
+    mov ecx, 11
+    mov edi, offset _KiTrapPrefixTable
+    repnz scasb
+
+    /* Restore loop count */
+    pop ecx
+
+    /* If it's not a prefix byte, check other instructions */
+    jnz NotPrefixByte
+
+    /* FIXME */
+    UNHANDLED_PATH
+
+NotPrefixByte:
+    /* FIXME: Check if it's a HLT */
+
+    /* Check if the instruction has two bytes */
+    cmp al, 0xF
+    jne CheckRing3Io
+
+    /* FIXME */
+    UNHANDLED_PATH
+
+CheckRing3Io:
+    /* Get EFLAGS and IOPL */
+    mov ebx, [ebp+KTRAP_FRAME_EFLAGS]
+    and ebx, 0x3000
+    shr ebx, 12
+
+    /* Check the CS's RPL mask */
+    mov ecx, [ebp+KTRAP_FRAME_CS]
+    and ecx, RPL_MASK
+    cmp ebx, ecx
+    jge NotIoViolation
+
+CheckPrivilegedInstruction2:
+    /* Check if this is a CLI or STI */
+    cmp al, 0xFA
+    je IsPrivInstruction
+    cmp al, 0xFB
+    je IsPrivInstruction
+
+    /* Setup I/O table lookup */
+    mov ecx, 13
+    mov edi, offset _KiTrapIoTable
+
+    /* Loopup in the table */
+    repnz scasb
+    jnz NotIoViolation
+
+    /* FIXME: Check IOPM!!! */
+
+IsPrivInstruction:
+    /* Cleanup the SEH frame */
+    pop fs:[KPCR_EXCEPTION_LIST]
+    add esp, 8
+
+    /* Setup the exception */
+    mov ebx, [ebp+KTRAP_FRAME_EIP]
+    mov eax, STATUS_PRIVILEGED_INSTRUCTION
+    jmp _DispatchNoParam
+
+NotIoViolation:
+    /* Cleanup the SEH frame */
+    pop fs:[KPCR_EXCEPTION_LIST]
+    add esp, 8
+
+SetException:
+    /* Setup the exception */
+    mov ebx, [ebp+KTRAP_FRAME_EIP]
+    mov esi, -1
+    mov eax, STATUS_ACCESS_VIOLATION
+    jmp _DispatchTwoParam
+
+DispatchV86Gpf:
+    /* FIXME */
+    UNHANDLED_PATH
 .endfunc
 
 .func KiTrap14
+Dr_kit14:   DR_TRAP_FIXUP
+V86_kit14:  V86_TRAP_FIXUP
 _KiTrap14:
+
     /* Enter trap */
-    TRAP_PROLOG(14)
+    TRAP_PROLOG kit14
+
+    /* Check if we have a VDM alert */
+    cmp dword ptr fs:[KPCR_VDM_ALERT], 0
+    jnz VdmAlertGpf
 
-    /* Call the C exception handler */
-    push 14
+    /* Get the current thread */
+    mov edi, fs:[KPCR_CURRENT_THREAD]
+
+    /* Get the stack address of the frame */
+    lea eax, [esp+KTRAP_FRAME_LENGTH+NPX_FRAME_LENGTH]
+    sub eax, [edi+KTHREAD_INITIAL_STACK]
+    jz NoFixUp
+
+    /* This isn't the base frame, check if it's the second */
+    cmp eax, -KTRAP_FRAME_EFLAGS
+    jb NoFixUp
+
+    /* Check if we have a TEB */
+    mov eax, fs:[KPCR_TEB]
+    or eax, eax
+    jle NoFixUp
+
+    /* Fixup the frame */
+    call _KiFixupFrame
+
+    /* Save CR2 */
+NoFixUp:
+    mov edi, cr2
+
+    /* ROS HACK: Sometimes we get called with INTS DISABLED! WTF? */
+    test dword ptr [ebp+KTRAP_FRAME_EFLAGS], EFLAGS_INTERRUPT_MASK
+    je HandlePf
+
+    /* Enable interrupts and check if we got here with interrupts disabled */
+    sti
+    test dword ptr [ebp+KTRAP_FRAME_EFLAGS], EFLAGS_INTERRUPT_MASK
+    jz IllegalState
+
+HandlePf:
+    /* Send trap frame and check if this is kernel-mode or usermode */
     push ebp
-    call _KiPageFaultHandler
-    add esp, 8
+    mov eax, [ebp+KTRAP_FRAME_CS]
+    and eax, MODE_MASK
+    push eax
 
-    /* Return to caller */
+    /* Send faulting address and check if this is read or write */
+    push edi
+    mov eax, [ebp+KTRAP_FRAME_ERROR_CODE]
+    and eax, 1
+    push eax
+
+    /* Call the access fault handler */
+    call _MmAccessFault@16
+    test eax, eax
+    jl AccessFail
+
+    /* Access fault handled, return to caller */
     jmp _Kei386EoiHelper@0
+
+AccessFail:
+    /* First check if this is a fault in the S-LIST functions */
+    mov ecx, offset _ExpInterlockedPopEntrySListFault@0
+    cmp [ebp+KTRAP_FRAME_EIP], ecx
+    jz SlistFault
+
+    /* Check if this is a fault in the syscall handler */
+    mov ecx, offset CopyParams
+    cmp [ebp+KTRAP_FRAME_EIP], ecx
+    jz SysCallCopyFault
+    mov ecx, offset ReadBatch
+    cmp [ebp+KTRAP_FRAME_EIP], ecx
+    jnz CheckVdmPf
+
+    /* FIXME: TODO */
+    UNHANDLED_PATH
+    jmp _Kei386EoiHelper@0
+
+SysCallCopyFault:
+    /* FIXME: TODO */
+    UNHANDLED_PATH
+    jmp _Kei386EoiHelper@0
+
+    /* Check if the fault occured in a V86 mode */
+CheckVdmPf:
+    mov ecx, [ebp+KTRAP_FRAME_ERROR_CODE]
+    and ecx, 1
+    shr ecx, 1
+    test dword ptr [ebp+KTRAP_FRAME_EFLAGS], EFLAGS_V86_MASK
+    jnz VdmPF
+
+    /* Check if the fault occured in a VDM */
+    mov esi, fs:[KPCR_CURRENT_THREAD]
+    mov esi, [esi+KTHREAD_APCSTATE_PROCESS]
+    cmp dword ptr [esi+EPROCESS_VDM_OBJECTS], 0
+    jz CheckStatus
+
+    /* Check if we this was in kernel-mode */
+    test byte ptr [ebp+KTRAP_FRAME_CS], MODE_MASK
+    jz CheckStatus
+    cmp word ptr [ebp+KTRAP_FRAME_CS], KGDT_R3_CODE + RPL_MASK
+    jz CheckStatus
+
+VdmPF:
+    /* FIXME: TODO */
+    UNHANDLED_PATH
+
+    /* Save EIP and check what kind of status failure we got */
+CheckStatus:
+    mov esi, [ebp+KTRAP_FRAME_EIP]
+    cmp eax, STATUS_ACCESS_VIOLATION
+    je AccessViol
+    cmp eax, STATUS_GUARD_PAGE_VIOLATION
+    je SpecialCode
+    cmp eax, STATUS_STACK_OVERFLOW
+    je SpecialCode
+
+    /* Setup an in-page exception to dispatch */
+    mov edx, ecx
+    mov ebx, esi
+    mov esi, edi
+    mov ecx, 3
+    mov edi, eax
+    mov eax, STATUS_IN_PAGE_ERROR
+    call _CommonDispatchException
+
+AccessViol:
+    /* Use more proper status code */
+    mov eax, KI_EXCEPTION_ACCESS_VIOLATION
+
+SpecialCode:
+    /* Setup a normal page fault exception */
+    mov ebx, esi
+    mov edx, ecx
+    mov esi, edi
+    jmp _DispatchTwoParam
+
+SlistFault:
+    /* FIXME: TODO */
+    UNHANDLED_PATH
+
+IllegalState:
+
+    /* This is completely illegal, bugcheck the system */
+    push ebp
+    push esi
+    push ecx
+    push eax
+    push edi
+    push IRQL_NOT_LESS_OR_EQUAL
+    call _KeBugCheckWithTf@24
+
+VdmAlertGpf:
+
+    /* FIXME: NOT SUPPORTED */
+    UNHANDLED_PATH
 .endfunc
 
 .func KiTrap0F
+Dr_kit15:   DR_TRAP_FIXUP
+V86_kit15:  V86_TRAP_FIXUP
 _KiTrap0F:
     /* Push error code */
     push 0
 
     /* Enter trap */
-    TRAP_PROLOG(15)
+    TRAP_PROLOG kit15
     sti
 
     /* Raise a fatal exception */
@@ -1432,25 +2042,41 @@ _KiTrap0F:
 .endfunc
 
 .func KiTrap16
+Dr_kit16:   DR_TRAP_FIXUP
+V86_kit16:  V86_TRAP_FIXUP
 _KiTrap16:
     /* Push error code */
     push 0
 
     /* Enter trap */
-    TRAP_PROLOG(16)
+    TRAP_PROLOG kit16
 
-    /* FIXME: ROS Doesn't handle FPU faults yet */
-    mov eax, 16
-    jmp _KiSystemFatalException
+    /* Check if this is the NPX Thread */
+    mov eax, fs:[KPCR_CURRENT_THREAD]
+    cmp eax, fs:[KPCR_NPX_THREAD]
+
+    /* Get the initial stack and NPX frame */
+    mov ecx, [eax+KTHREAD_INITIAL_STACK]
+    lea ecx, [ecx-NPX_FRAME_LENGTH]
+
+    /* If this is a valid fault, handle it */
+    jz HandleNpxFault
+
+    /* Otherwise, re-enable interrupts and set delayed error */
+    sti
+    or dword ptr [ecx+FN_CR0_NPX_STATE], CR0_TS
+    jmp _Kei386EoiHelper@0
 .endfunc
 
 .func KiTrap17
+Dr_kit17:   DR_TRAP_FIXUP
+V86_kit17:  V86_TRAP_FIXUP
 _KiTrap17:
     /* Push error code */
     push 0
 
     /* Enter trap */
-    TRAP_PROLOG(17)
+    TRAP_PROLOG kit17
 
     /* FIXME: ROS Doesn't handle alignment faults yet */
     mov eax, 17
@@ -1497,6 +2123,21 @@ _KiCoprocessorError@0:
     ret
 .endfunc
 
+.func Ki16BitStackException
+_Ki16BitStackException:
+
+    /* Save stack */
+    push ss
+    push esp
+
+    /* Go to kernel mode thread stack */
+    mov eax, fs:[KPCR_CURRENT_THREAD]
+    add esp, [eax+KTHREAD_INITIAL_STACK]
+
+    /* Switch to good stack segment */
+    UNHANDLED_PATH
+.endfunc
+
 /* UNEXPECTED INTERRUPT HANDLERS **********************************************/
 
 .globl _KiStartUnexpectedRange@0
@@ -1509,6 +2150,8 @@ _KiEndUnexpectedRange@0:
     jmp _KiUnexpectedInterruptTail
 
 .func KiUnexpectedInterruptTail
+V86_kui: V86_TRAP_FIXUP
+Dr_kui:  DR_TRAP_FIXUP
 _KiUnexpectedInterruptTail:
 
     /* Enter interrupt trap */
@@ -1555,7 +2198,7 @@ Handled:
 _KiUnexpectedInterrupt:
 
     /* Bugcheck with invalid interrupt code */
-    push 0x12
+    push TRAP_CAUSE_UNKNOWN
     call _KeBugCheck@4
 
 /* INTERRUPT HANDLERS ********************************************************/
@@ -1589,7 +2232,7 @@ _KiDispatchInterrupt@0:
 
     /* Restore stack and exception list */
     pop esp
-    pop dword ptr [ebx]
+    pop dword ptr [ebx+KPCR_EXCEPTION_LIST]
     pop ebp
 
 CheckQuantum:
@@ -1603,10 +2246,44 @@ CheckQuantum:
 
     /* Check if we have a thread to swap to */
     cmp byte ptr [ebx+KPCR_PRCB_NEXT_THREAD], 0
-    jz Return
+    je Return
 
-    /* FIXME: Schedule new thread */
-    int 3
+    /* Make space on the stack to save registers */
+    sub esp, 3 * 4
+    mov [esp+8], esi
+    mov [esp+4], edi
+    mov [esp+0], ebp
+
+    /* Get the current thread */
+    mov edi, [ebx+KPCR_CURRENT_THREAD]
+
+#ifdef CONFIG_SMP
+    #error SMP Interrupt not handled!
+#endif
+
+    /* Get the next thread and clear it */
+    mov esi, [ebx+KPCR_PRCB_NEXT_THREAD]
+    and dword ptr [ebx+KPCR_PRCB_NEXT_THREAD], 0
+
+    /* Set us as the current running thread */
+    mov [ebx+KPCR_CURRENT_THREAD], esi
+    mov byte ptr [esi+KTHREAD_STATE], Running
+    mov byte ptr [edi+KTHREAD_WAIT_REASON], WrDispatchInt
+
+    /* Put thread in ECX and get the PRCB in EDX */
+    mov ecx, edi
+    lea edx, [ebx+KPCR_PRCB_DATA]
+    call @KiQueueReadyThread@8
+
+    /* Set APC_LEVEL and do the swap */
+    mov cl, APC_LEVEL
+    call @KiSwapContextInternal@0
+
+    /* Restore registers */
+    mov ebp, [esp+0]
+    mov edi, [esp+4]
+    mov esi, [esp+8]
+    add esp, 3*4
 
 Return:
     /* All done */
@@ -1620,6 +2297,8 @@ QuantumEnd:
 .endfunc
 
 .func KiInterruptTemplate
+V86_kit: V86_TRAP_FIXUP
+Dr_kit:  DR_TRAP_FIXUP
 _KiInterruptTemplate:
 
     /* Enter interrupt trap */
@@ -1641,7 +2320,7 @@ _KiInterruptTemplateDispatch:
 _KiChainedDispatch2ndLvl@0:
 
     /* Not yet supported */
-    int 3
+    UNHANDLED_PATH
 .endfunc
 
 .func KiChainedDispatch@0
@@ -1723,7 +2402,6 @@ GetIntLock:
     RELEASE_SPINLOCK(esi)
 
     /* Exit the interrupt */
-    mov esi, $
     cli
     call _HalEndSystemInterrupt@8
     jmp _Kei386EoiHelper@0
@@ -1731,7 +2409,6 @@ GetIntLock:
 SpuriousInt:
     /* Exit the interrupt */
     add esp, 8
-    mov esi, $
     jmp _Kei386EoiHelper@0
 
 #ifdef CONFIG_SMP