[NTOS:KE] Use multi-processor-aware KeGetPcr() instead of the legacy PCR.
[reactos.git] / ntoskrnl / ke / i386 / traphdlr.c
index 835d8e7..6f26ac9 100644 (file)
 #define NDEBUG
 #include <debug.h>
 
+VOID __cdecl KiFastCallEntry(VOID);
+VOID __cdecl KiFastCallEntryWithSingleStep(VOID);
+
+extern PVOID KeUserPopEntrySListFault;
+extern PVOID KeUserPopEntrySListResume;
+extern PVOID FrRestore;
+VOID FASTCALL Ke386LoadFpuState(IN PFX_SAVE_AREA SaveArea);
+
 /* GLOBALS ********************************************************************/
 
 UCHAR KiTrapPrefixTable[] =
@@ -46,19 +54,19 @@ UCHAR KiTrapIoTable[] =
 };
 
 PFAST_SYSTEM_CALL_EXIT KiFastCallExitHandler;
-#if DBG && !defined(_WINKD_)
+#if DBG && defined(_M_IX86) && !defined(_WINKD_)
 PKDBG_PRESERVICEHOOK KeWin32PreServiceHook = NULL;
 PKDBG_POSTSERVICEHOOK KeWin32PostServiceHook = NULL;
 #endif
-#if TRAP_DEBUG
+#if DBG
 BOOLEAN StopChecking = FALSE;
 #endif
 
 
 /* TRAP EXIT CODE *************************************************************/
 
-BOOLEAN
 FORCEINLINE
+BOOLEAN
 KiVdmTrap(IN PKTRAP_FRAME TrapFrame)
 {
     /* Either the V8086 flag is on, or this is user-mode with a VDM */
@@ -66,16 +74,16 @@ KiVdmTrap(IN PKTRAP_FRAME TrapFrame)
             ((KiUserTrap(TrapFrame)) && (PsGetCurrentProcess()->VdmObjects)));
 }
 
-BOOLEAN
 FORCEINLINE
+BOOLEAN
 KiV86Trap(IN PKTRAP_FRAME TrapFrame)
 {
     /* Check if the V8086 flag is on */
     return ((TrapFrame->EFlags & EFLAGS_V86_MASK) != 0);
 }
 
-BOOLEAN
 FORCEINLINE
+BOOLEAN
 KiIsFrameEdited(IN PKTRAP_FRAME TrapFrame)
 {
     /* An edited frame changes esp. It is marked by clearing the bits
@@ -83,8 +91,8 @@ KiIsFrameEdited(IN PKTRAP_FRAME TrapFrame)
     return ((TrapFrame->SegCs & FRAME_EDITED) == 0);
 }
 
-VOID
 FORCEINLINE
+VOID
 KiCommonExit(IN PKTRAP_FRAME TrapFrame, BOOLEAN SkipPreviousMode)
 {
     /* Disable interrupts until we return */
@@ -100,7 +108,7 @@ KiCommonExit(IN PKTRAP_FRAME TrapFrame, BOOLEAN SkipPreviousMode)
     if (__builtin_expect(TrapFrame->Dr7 & ~DR7_RESERVED_MASK, 0))
     {
         /* Check if the frame was from user mode or v86 mode */
-        if ((TrapFrame->SegCs & MODE_MASK) ||
+        if (KiUserTrap(TrapFrame) ||
             (TrapFrame->EFlags & EFLAGS_V86_MASK))
         {
             /* Handle debug registers */
@@ -124,13 +132,16 @@ KiEoiHelper(IN PKTRAP_FRAME TrapFrame)
     if (TrapFrame->EFlags & EFLAGS_V86_MASK) KiTrapReturnNoSegments(TrapFrame);
 
     /* Check for user mode exit */
-    if (TrapFrame->SegCs & MODE_MASK) KiTrapReturn(TrapFrame);
+    if (KiUserTrap(TrapFrame)) KiTrapReturn(TrapFrame);
 
     /* Check for edited frame */
     if (KiIsFrameEdited(TrapFrame)) KiEditedTrapReturn(TrapFrame);
 
+    /* Check if we have single stepping enabled */
+    if (TrapFrame->EFlags & EFLAGS_TF) KiTrapReturnNoSegments(TrapFrame);
+
     /* Exit the trap to kernel mode */
-    KiTrapReturnNoSegments(TrapFrame);
+    KiTrapReturnNoSegmentsRet8(TrapFrame);
 }
 
 DECLSPEC_NORETURN
@@ -141,18 +152,18 @@ KiServiceExit(IN PKTRAP_FRAME TrapFrame,
 {
     ASSERT((TrapFrame->EFlags & EFLAGS_V86_MASK) == 0);
     ASSERT(!KiIsFrameEdited(TrapFrame));
-    
+
     /* Copy the status into EAX */
     TrapFrame->Eax = Status;
-    
+
     /* Common trap exit code */
     KiCommonExit(TrapFrame, FALSE);
-    
+
     /* Restore previous mode */
     KeGetCurrentThread()->PreviousMode = (CCHAR)TrapFrame->PreviousPreviousMode;
 
     /* Check for user mode exit */
-    if (TrapFrame->SegCs & MODE_MASK)
+    if (KiUserTrap(TrapFrame))
     {
         /* Check if we were single stepping */
         if (TrapFrame->EFlags & EFLAGS_TF)
@@ -164,6 +175,7 @@ KiServiceExit(IN PKTRAP_FRAME TrapFrame,
         {
             /* We can use the sysexit handler */
             KiFastCallExitHandler(TrapFrame);
+            UNREACHABLE;
         }
     }
 
@@ -178,21 +190,24 @@ KiServiceExit2(IN PKTRAP_FRAME TrapFrame)
 {
     /* Common trap exit code */
     KiCommonExit(TrapFrame, FALSE);
-    
+
     /* Restore previous mode */
     KeGetCurrentThread()->PreviousMode = (CCHAR)TrapFrame->PreviousPreviousMode;
-    
+
     /* Check if this was a V8086 trap */
     if (TrapFrame->EFlags & EFLAGS_V86_MASK) KiTrapReturnNoSegments(TrapFrame);
 
     /* Check for user mode exit */
-    if (TrapFrame->SegCs & MODE_MASK) KiTrapReturn(TrapFrame);
+    if (KiUserTrap(TrapFrame)) KiTrapReturn(TrapFrame);
 
     /* Check for edited frame */
     if (KiIsFrameEdited(TrapFrame)) KiEditedTrapReturn(TrapFrame);
 
+    /* Check if we have single stepping enabled */
+    if (TrapFrame->EFlags & EFLAGS_TF) KiTrapReturnNoSegments(TrapFrame);
+
     /* Exit the trap to kernel mode */
-    KiTrapReturnNoSegments(TrapFrame);
+    KiTrapReturnNoSegmentsRet8(TrapFrame);
 }
 
 
@@ -207,13 +222,14 @@ KiDebugHandler(IN PKTRAP_FRAME TrapFrame,
                IN ULONG Parameter3)
 {
     /* Check for VDM trap */
-    ASSERT((KiVdmTrap(TrapFrame)) == FALSE);
+    ASSERT(KiVdmTrap(TrapFrame) == FALSE);
 
     /* Enable interrupts if the trap came from user-mode */
     if (KiUserTrap(TrapFrame)) _enable();
 
     /* Dispatch the exception  */
     KiDispatchExceptionFromTrapFrame(STATUS_BREAKPOINT,
+                                     0,
                                      TrapFrame->Eip - 1,
                                      3,
                                      Parameter1,
@@ -230,27 +246,27 @@ KiNpxHandler(IN PKTRAP_FRAME TrapFrame,
              IN PFX_SAVE_AREA SaveArea)
 {
     ULONG Cr0, Mask, Error, ErrorOffset, DataOffset;
-    
+
     /* Check for VDM trap */
-    ASSERT((KiVdmTrap(TrapFrame)) == FALSE);
+    ASSERT(KiVdmTrap(TrapFrame) == FALSE);
 
     /* Check for kernel trap */
     if (!KiUserTrap(TrapFrame))
     {
         /* Kernel might've tripped a delayed error */
         SaveArea->Cr0NpxState |= CR0_TS;
-        
+
         /* Only valid if it happened during a restore */
-        //if ((PVOID)TrapFrame->Eip == FrRestore)
+        if ((PVOID)TrapFrame->Eip == FrRestore)
         {
             /* It did, so just skip the instruction */
-            //TrapFrame->Eip += 3; /* sizeof(FRSTOR) */
-            //KiEoiHelper(TrapFrame);
+            TrapFrame->Eip += 3; /* Size of FRSTOR instruction */
+            KiEoiHelper(TrapFrame);
         }
     }
 
-    /* User or kernel trap -- get ready to issue an exception */
-    //if (Thread->NpxState == NPX_STATE_NOT_LOADED)
+    /* User or kernel trap -- check if we need to unload the current state */
+    if (Thread->NpxState == NPX_STATE_LOADED)
     {
         /* Update CR0 */
         Cr0 = __readcr0();
@@ -273,14 +289,14 @@ KiNpxHandler(IN PKTRAP_FRAME TrapFrame,
     /* Clear the TS bit and re-enable interrupts */
     SaveArea->Cr0NpxState &= ~CR0_TS;
     _enable();
-    
+
     /* Check if we should get the FN or FX error */
     if (KeI386FxsrPresent)
     {
         /* Get it from FX */
         Mask = SaveArea->U.FxArea.ControlWord;
         Error = SaveArea->U.FxArea.StatusWord;
-        
+
         /* Get the FPU exception address too */
         ErrorOffset = SaveArea->U.FxArea.ErrorOffset;
         DataOffset = SaveArea->U.FxArea.DataOffset;
@@ -290,15 +306,13 @@ KiNpxHandler(IN PKTRAP_FRAME TrapFrame,
         /* Get it from FN */
         Mask = SaveArea->U.FnArea.ControlWord;
         Error = SaveArea->U.FnArea.StatusWord;
-        
+
         /* Get the FPU exception address too */
         ErrorOffset = SaveArea->U.FnArea.ErrorOffset;
         DataOffset = SaveArea->U.FnArea.DataOffset;
     }
 
     /* Get legal exceptions that software should handle */
-    /* We do this by first masking off from the Mask the bits we need, */
-    /* This is done so we can keep the FSW_STACK_FAULT bit in Error. */
     Mask &= (FSW_INVALID_OPERATION |
              FSW_DENORMAL |
              FSW_ZERO_DIVIDE |
@@ -310,9 +324,10 @@ KiNpxHandler(IN PKTRAP_FRAME TrapFrame,
     /* Check for invalid operation */
     if (Error & FSW_INVALID_OPERATION)
     {
-        /* NOTE: Stack fault is handled differently than any other case. */
-        /* 1. It's only raised for invalid operation. */
-        /* 2. It's only raised if invalid operation is not masked. */
+        /*
+         * Now check if this is actually a Stack Fault. This is needed because
+         * on x86 the Invalid Operation error is set for Stack Check faults as well.
+         */
         if (Error & FSW_STACK_FAULT)
         {
             /* Issue stack check fault */
@@ -322,14 +337,16 @@ KiNpxHandler(IN PKTRAP_FRAME TrapFrame,
                                      DataOffset,
                                      TrapFrame);
         }
-
-        /* Issue fault */
-        KiDispatchException1Args(STATUS_FLOAT_INVALID_OPERATION,
-                                 ErrorOffset,
-                                 0,
-                                 TrapFrame);
+        else
+        {
+            /* This is an invalid operation fault after all, so raise that instead */
+            KiDispatchException1Args(STATUS_FLOAT_INVALID_OPERATION,
+                                     ErrorOffset,
+                                     0,
+                                     TrapFrame);
+        }
     }
-    
+
     /* Check for divide by zero */
     if (Error & FSW_ZERO_DIVIDE)
     {
@@ -339,7 +356,7 @@ KiNpxHandler(IN PKTRAP_FRAME TrapFrame,
                                  0,
                                  TrapFrame);
     }
-    
+
     /* Check for denormal */
     if (Error & FSW_DENORMAL)
     {
@@ -349,7 +366,7 @@ KiNpxHandler(IN PKTRAP_FRAME TrapFrame,
                                  0,
                                  TrapFrame);
     }
-    
+
     /* Check for overflow */
     if (Error & FSW_OVERFLOW)
     {
@@ -359,7 +376,7 @@ KiNpxHandler(IN PKTRAP_FRAME TrapFrame,
                                  0,
                                  TrapFrame);
     }
-    
+
     /* Check for underflow */
     if (Error & FSW_UNDERFLOW)
     {
@@ -379,7 +396,7 @@ KiNpxHandler(IN PKTRAP_FRAME TrapFrame,
                                  0,
                                  TrapFrame);
     }
-    
+
     /* Unknown FPU fault */
     KeBugCheckWithTf(TRAP_CAUSE_UNKNOWN, 1, Error, 0, 0, TrapFrame);
 }
@@ -391,13 +408,13 @@ KiTrap00Handler(IN PKTRAP_FRAME TrapFrame)
 {
     /* Save trap frame */
     KiEnterTrap(TrapFrame);
-    
+
     /* Check for VDM trap */
-    ASSERT((KiVdmTrap(TrapFrame)) == FALSE);
+    ASSERT(KiVdmTrap(TrapFrame) == FALSE);
 
     /*  Enable interrupts */
     _enable();
-    
+
     /* Dispatch the exception */
     KiDispatchException0Args(STATUS_INTEGER_DIVIDE_BY_ZERO,
                              TrapFrame->Eip,
@@ -411,13 +428,26 @@ KiTrap01Handler(IN PKTRAP_FRAME TrapFrame)
 {
     /* Save trap frame */
     KiEnterTrap(TrapFrame);
-    
+
     /* Check for VDM trap */
-    ASSERT((KiVdmTrap(TrapFrame)) == FALSE);
+    ASSERT(KiVdmTrap(TrapFrame) == FALSE);
+
+    /* Check if this was a single step after sysenter */
+    if (TrapFrame->Eip == (ULONG)KiFastCallEntry)
+    {
+        /* Disable single stepping */
+        TrapFrame->EFlags &= ~EFLAGS_TF;
+
+        /* Re-enter at the alternative sysenter entry point */
+        TrapFrame->Eip = (ULONG)KiFastCallEntryWithSingleStep;
+
+        /* End this trap */
+        KiEoiHelper(TrapFrame);
+    }
 
     /* Enable interrupts if the trap came from user-mode */
     if (KiUserTrap(TrapFrame)) _enable();
-    
+
     /*  Mask out trap flag and dispatch the exception */
     TrapFrame->EFlags &= ~EFLAGS_TF;
     KiDispatchException0Args(STATUS_SINGLE_STEP,
@@ -425,10 +455,9 @@ KiTrap01Handler(IN PKTRAP_FRAME TrapFrame)
                              TrapFrame);
 }
 
-DECLSPEC_NORETURN
 VOID
 __cdecl
-KiTrap02(VOID)
+KiTrap02Handler(VOID)
 {
     PKTSS Tss, NmiTss;
     PKTHREAD Thread;
@@ -436,59 +465,53 @@ KiTrap02(VOID)
     PKGDTENTRY TssGdt;
     KTRAP_FRAME TrapFrame;
     KIRQL OldIrql;
-    
-    //
-    // In some sort of strange recursion case, we might end up here with the IF
-    // flag incorrectly on the interrupt frame -- during a normal NMI this would
-    // normally already be set.
-    //
-    // For sanity's sake, make sure interrupts are disabled for sure.
-    // NMIs will already be since the CPU does it for us.
-    //
+
+    /*
+     * In some sort of strange recursion case, we might end up here with the IF
+     * flag incorrectly on the interrupt frame -- during a normal NMI this would
+     * normally already be set.
+     *
+     * For sanity's sake, make sure interrupts are disabled for sure.
+     * NMIs will already be since the CPU does it for us.
+     */
     _disable();
 
-    //
-    // Get the current TSS, thread, and process
-    //
-    Tss = PCR->TSS;
-    Thread = ((PKIPCR)PCR)->PrcbData.CurrentThread;
+    /* Get the current TSS, thread, and process */
+    Tss = KeGetPcr()->TSS;
+    Thread = ((PKIPCR)KeGetPcr())->PrcbData.CurrentThread;
     Process = Thread->ApcState.Process;
-    
-    //
-    // Save data usually not in the TSS
-    //
+
+    /* Save data usually not present in the TSS */
     Tss->CR3 = Process->DirectoryTableBase[0];
     Tss->IoMapBase = Process->IopmOffset;
     Tss->LDT = Process->LdtDescriptor.LimitLow ? KGDT_LDT : 0;
-    
-    //
-    // Now get the base address of the NMI TSS
-    //
+
+    /* Now get the base address of the NMI TSS */
     TssGdt = &((PKIPCR)KeGetPcr())->GDT[KGDT_NMI_TSS / sizeof(KGDTENTRY)];
     NmiTss = (PKTSS)(ULONG_PTR)(TssGdt->BaseLow |
                                 TssGdt->HighWord.Bytes.BaseMid << 16 |
                                 TssGdt->HighWord.Bytes.BaseHi << 24);
-                    
-    //
-    // Switch to it and activate it, masking off the nested flag
-    //
-    // Note that in reality, we are already on the NMI tss -- we just need to
-    // update the PCR to reflect this
-    //
-    PCR->TSS = NmiTss;
+
+    /*
+     * Switch to it and activate it, masking off the nested flag.
+     *
+     * Note that in reality, we are already on the NMI TSS -- we just
+     * need to update the PCR to reflect this.
+     */
+    KeGetPcr()->TSS = NmiTss;
     __writeeflags(__readeflags() &~ EFLAGS_NESTED_TASK);
     TssGdt->HighWord.Bits.Dpl = 0;
     TssGdt->HighWord.Bits.Pres = 1;
     TssGdt->HighWord.Bits.Type = I386_TSS;
-    
-    //
-    // Now build the trap frame based on the original TSS
-    //
-    // The CPU does a hardware "Context switch" / task switch of sorts and so it
-    // takes care of saving our context in the normal TSS.
-    //
-    // We just have to go get the values...
-    //
+
+    /*
+     * Now build the trap frame based on the original TSS.
+     *
+     * The CPU does a hardware "Context switch" / task switch of sorts
+     * and so it takes care of saving our context in the normal TSS.
+     *
+     * We just have to go get the values...
+     */
     RtlZeroMemory(&TrapFrame, sizeof(KTRAP_FRAME));
     TrapFrame.HardwareSegSs = Tss->Ss0;
     TrapFrame.HardwareEsp = Tss->Esp0;
@@ -500,8 +523,8 @@ KiTrap02(VOID)
     TrapFrame.Esi = Tss->Esi;
     TrapFrame.Edi = Tss->Edi;
     TrapFrame.SegFs = Tss->Fs;
-    TrapFrame.ExceptionList = PCR->NtTib.ExceptionList;
-    TrapFrame.PreviousPreviousMode = -1;
+    TrapFrame.ExceptionList = KeGetPcr()->NtTib.ExceptionList;
+    TrapFrame.PreviousPreviousMode = (ULONG)-1;
     TrapFrame.Eax = Tss->Eax;
     TrapFrame.Ecx = Tss->Ecx;
     TrapFrame.Edx = Tss->Edx;
@@ -510,66 +533,51 @@ KiTrap02(VOID)
     TrapFrame.SegGs = Tss->Gs;
     TrapFrame.DbgEip = Tss->Eip;
     TrapFrame.DbgEbp = Tss->Ebp;
-    
-    //
-    // Store the trap frame in the KPRCB
-    //
+
+    /* Store the trap frame in the KPRCB */
     KiSaveProcessorState(&TrapFrame, NULL);
-    
-    //
-    // Call any registered NMI handlers and see if they handled it or not
-    //
+
+    /* Call any registered NMI handlers and see if they handled it or not */
     if (!KiHandleNmi())
     {
-        //
-        // They did not, so call the platform HAL routine to bugcheck the system
-        //
-        // Make sure the HAL believes it's running at HIGH IRQL... we can't use
-        // the normal APIs here as playing with the IRQL could change the system
-        // state
-        //
-        OldIrql = PCR->Irql;
-        PCR->Irql = HIGH_LEVEL;
+        /*
+         * They did not, so call the platform HAL routine to bugcheck the system
+         *
+         * Make sure the HAL believes it's running at HIGH IRQL... we can't use
+         * the normal APIs here as playing with the IRQL could change the system
+         * state.
+         */
+        OldIrql = KeGetPcr()->Irql;
+        KeGetPcr()->Irql = HIGH_LEVEL;
         HalHandleNMI(NULL);
-        PCR->Irql = OldIrql;
+        KeGetPcr()->Irql = OldIrql;
     }
 
-    //
-    // Although the CPU disabled NMIs, we just did a BIOS Call, which could've
-    // totally changed things.
-    //
-    // We have to make sure we're still in our original NMI -- a nested NMI
-    // will point back to the NMI TSS, and in that case we're hosed.
-    //
-    if (PCR->TSS->Backlink != KGDT_NMI_TSS)
+    /*
+     * Although the CPU disabled NMIs, we just did a BIOS call, which could've
+     * totally changed things.
+     *
+     * We have to make sure we're still in our original NMI -- a nested NMI
+     * will point back to the NMI TSS, and in that case we're hosed.
+     */
+    if (KeGetPcr()->TSS->Backlink == KGDT_NMI_TSS)
     {
-        //
-        // Restore original TSS
-        //
-        PCR->TSS = Tss;
-        
-        //
-        // Set it back to busy
-        //
-        TssGdt->HighWord.Bits.Dpl = 0;
-        TssGdt->HighWord.Bits.Pres = 1;
-        TssGdt->HighWord.Bits.Type = I386_ACTIVE_TSS;
-        
-        //
-        // Restore nested flag
-        //
-        __writeeflags(__readeflags() | EFLAGS_NESTED_TASK);
-        
-        //
-        // Handled, return from interrupt
-        //
-        KiIret();
+        /* Unhandled: crash the system */
+        KiSystemFatalException(EXCEPTION_NMI, NULL);
     }
-    
-    //
-    // Unhandled: crash the system
-    //
-    KiSystemFatalException(EXCEPTION_NMI, NULL);
+
+    /* Restore original TSS */
+    KeGetPcr()->TSS = Tss;
+
+    /* Set it back to busy */
+    TssGdt->HighWord.Bits.Dpl = 0;
+    TssGdt->HighWord.Bits.Pres = 1;
+    TssGdt->HighWord.Bits.Type = I386_ACTIVE_TSS;
+
+    /* Restore nested flag */
+    __writeeflags(__readeflags() | EFLAGS_NESTED_TASK);
+
+    /* Handled, return from interrupt */
 }
 
 DECLSPEC_NORETURN
@@ -579,7 +587,7 @@ KiTrap03Handler(IN PKTRAP_FRAME TrapFrame)
 {
     /* Save trap frame */
     KiEnterTrap(TrapFrame);
-    
+
     /* Continue with the common handler */
     KiDebugHandler(TrapFrame, BREAKPOINT_BREAK, 0, 0);
 }
@@ -591,13 +599,13 @@ KiTrap04Handler(IN PKTRAP_FRAME TrapFrame)
 {
     /* Save trap frame */
     KiEnterTrap(TrapFrame);
-    
+
     /* Check for VDM trap */
-    ASSERT((KiVdmTrap(TrapFrame)) == FALSE);
+    ASSERT(KiVdmTrap(TrapFrame) == FALSE);
 
      /* Enable interrupts */
     _enable();
-    
+
     /* Dispatch the exception */
     KiDispatchException0Args(STATUS_INTEGER_OVERFLOW,
                              TrapFrame->Eip - 1,
@@ -611,16 +619,16 @@ KiTrap05Handler(IN PKTRAP_FRAME TrapFrame)
 {
     /* Save trap frame */
     KiEnterTrap(TrapFrame);
-    
+
     /* Check for VDM trap */
-    ASSERT((KiVdmTrap(TrapFrame)) == FALSE);
-    
+    ASSERT(KiVdmTrap(TrapFrame) == FALSE);
+
     /* Check for kernel-mode fault */
     if (!KiUserTrap(TrapFrame)) KiSystemFatalException(EXCEPTION_BOUND_CHECK, TrapFrame);
 
     /* Enable interrupts */
     _enable();
-    
+
     /* Dispatch the exception */
     KiDispatchException0Args(STATUS_ARRAY_BOUNDS_EXCEEDED,
                              TrapFrame->Eip,
@@ -635,57 +643,56 @@ KiTrap06Handler(IN PKTRAP_FRAME TrapFrame)
     PUCHAR Instruction;
     ULONG i;
     KIRQL OldIrql;
-    
+
     /* Check for V86 GPF */
     if (__builtin_expect(KiV86Trap(TrapFrame), 1))
     {
         /* Enter V86 trap */
         KiEnterV86Trap(TrapFrame);
-        
+
         /* Must be a VDM process */
         if (__builtin_expect(!PsGetCurrentProcess()->VdmObjects, 0))
         {
             /* Enable interrupts */
             _enable();
-            
+
             /* Setup illegal instruction fault */
             KiDispatchException0Args(STATUS_ILLEGAL_INSTRUCTION,
                                      TrapFrame->Eip,
                                      TrapFrame);
         }
-        
+
         /* Go to APC level */
-        OldIrql = KfRaiseIrql(APC_LEVEL);
+        KeRaiseIrql(APC_LEVEL, &OldIrql);
         _enable();
-        
+
         /* Check for BOP */
         if (!VdmDispatchBop(TrapFrame))
         {
             /* Should only happen in VDM mode */
-            UNIMPLEMENTED;
-            while (TRUE);
+            UNIMPLEMENTED_FATAL();
         }
-        
+
         /* Bring IRQL back */
-        KfLowerIrql(OldIrql);
+        KeLowerIrql(OldIrql);
         _disable();
-        
+
         /* Do a quick V86 exit if possible */
         KiExitV86Trap(TrapFrame);
     }
 
     /* Save trap frame */
     KiEnterTrap(TrapFrame);
-    
+
     /* Enable interrupts */
     Instruction = (PUCHAR)TrapFrame->Eip;
     _enable();
-        
+
     /* Check for user trap */
     if (KiUserTrap(TrapFrame))
     {
         /* FIXME: Use SEH */
-        
+
         /* Scan next 4 opcodes */
         for (i = 0; i < 4; i++)
         {
@@ -698,15 +705,15 @@ KiTrap06Handler(IN PKTRAP_FRAME TrapFrame)
                                          TrapFrame);
             }
         }
-        
+
         /* FIXME: SEH ends here */
     }
-    
+
     /* Kernel-mode or user-mode fault (but not LOCK) */
     KiDispatchException0Args(STATUS_ILLEGAL_INSTRUCTION,
                              TrapFrame->Eip,
                              TrapFrame);
-    
+
 }
 
 DECLSPEC_NORETURN
@@ -717,12 +724,12 @@ KiTrap07Handler(IN PKTRAP_FRAME TrapFrame)
     PKTHREAD Thread, NpxThread;
     PFX_SAVE_AREA SaveArea, NpxSaveArea;
     ULONG Cr0;
-    
+
     /* Save trap frame */
     KiEnterTrap(TrapFrame);
 
     /* Try to handle NPX delay load */
-    while (TRUE)
+    for (;;)
     {
         /* Get the current thread */
         Thread = KeGetCurrentThread();
@@ -734,10 +741,9 @@ KiTrap07Handler(IN PKTRAP_FRAME TrapFrame)
         if (SaveArea->Cr0NpxState & CR0_EM)
         {
             /* Not implemented */
-            UNIMPLEMENTED;
-            while (TRUE);
+            UNIMPLEMENTED_FATAL();
         }
-    
+
         /* Save CR0 and check NPX state */
         Cr0 = __readcr0();
         if (Thread->NpxState != NPX_STATE_LOADED)
@@ -745,47 +751,46 @@ KiTrap07Handler(IN PKTRAP_FRAME TrapFrame)
             /* Update CR0 */
             Cr0 &= ~(CR0_MP | CR0_EM | CR0_TS);
             __writecr0(Cr0);
-        
+
             /* Get the NPX thread */
             NpxThread = KeGetCurrentPrcb()->NpxThread;
             if (NpxThread)
             {
                 /* Get the NPX frame */
                 NpxSaveArea = KiGetThreadNpxArea(NpxThread);
-                
+
                 /* Save FPU state */
-                DPRINT("FIXME: Save FPU state: %p\n", NpxSaveArea);
-                //Ke386SaveFpuState(NpxSaveArea);
+                Ke386SaveFpuState(NpxSaveArea);
 
                 /* Update NPX state */
-                Thread->NpxState = NPX_STATE_NOT_LOADED;
+                NpxThread->NpxState = NPX_STATE_NOT_LOADED;
            }
-       
+
             /* Load FPU state */
-            //Ke386LoadFpuState(SaveArea);
-        
+            Ke386LoadFpuState(SaveArea);
+
             /* Update NPX state */
             Thread->NpxState = NPX_STATE_LOADED;
             KeGetCurrentPrcb()->NpxThread = Thread;
-        
+
             /* Enable interrupts */
             _enable();
-        
+
             /* Check if CR0 needs to be reloaded due to context switch */
             if (!SaveArea->Cr0NpxState) KiEoiHelper(TrapFrame);
-        
+
             /* Otherwise, we need to reload CR0, disable interrupts */
             _disable();
-        
+
             /* Reload CR0 */
             Cr0 = __readcr0();
             Cr0 |= SaveArea->Cr0NpxState;
             __writecr0(Cr0);
-        
+
             /* Now restore interrupts and check for TS */
             _enable();
             if (Cr0 & CR0_TS) KiEoiHelper(TrapFrame);
-        
+
             /* We're still here -- clear TS and try again */
             __writecr0(__readcr0() &~ CR0_TS);
             _disable();
@@ -796,13 +801,13 @@ KiTrap07Handler(IN PKTRAP_FRAME TrapFrame)
             break;
         }
     }
-    
+
     /* TS should not be set */
     if (Cr0 & CR0_TS)
     {
         /*
          * If it's incorrectly set, then maybe the state is actually still valid
-         * but we could've lock track of that due to a BIOS call.
+         * but we could have lost track of that due to a BIOS call.
          * Make sure MP is still set, which should verify the theory.
          */
         if (Cr0 & CR0_MP)
@@ -811,22 +816,64 @@ KiTrap07Handler(IN PKTRAP_FRAME TrapFrame)
             __writecr0(__readcr0() &~ CR0_TS);
             KiEoiHelper(TrapFrame);
         }
-        
+
         /* Otherwise, something strange is going on */
         KeBugCheckWithTf(TRAP_CAUSE_UNKNOWN, 2, Cr0, 0, 0, TrapFrame);
     }
-    
+
     /* It's not a delayed load, so process this trap as an NPX fault */
     KiNpxHandler(TrapFrame, Thread, SaveArea);
 }
 
 DECLSPEC_NORETURN
 VOID
-FASTCALL
-KiTrap08Handler(IN PKTRAP_FRAME TrapFrame)
+__cdecl
+KiTrap08Handler(VOID)
 {
-    /* FIXME: Not handled */
-    KiSystemFatalException(EXCEPTION_DOUBLE_FAULT, TrapFrame);
+    PKTSS Tss, DfTss;
+    PKTHREAD Thread;
+    PKPROCESS Process;
+    PKGDTENTRY TssGdt;
+
+    /* For sanity's sake, make sure interrupts are disabled */
+    _disable();
+
+    /* Get the current TSS, thread, and process */
+    Tss = KeGetPcr()->TSS;
+    Thread = ((PKIPCR)KeGetPcr())->PrcbData.CurrentThread;
+    Process = Thread->ApcState.Process;
+
+    /* Save data usually not present in the TSS */
+    Tss->CR3 = Process->DirectoryTableBase[0];
+    Tss->IoMapBase = Process->IopmOffset;
+    Tss->LDT = Process->LdtDescriptor.LimitLow ? KGDT_LDT : 0;
+
+    /* Now get the base address of the double-fault TSS */
+    TssGdt = &((PKIPCR)KeGetPcr())->GDT[KGDT_DF_TSS / sizeof(KGDTENTRY)];
+    DfTss  = (PKTSS)(ULONG_PTR)(TssGdt->BaseLow |
+                                TssGdt->HighWord.Bytes.BaseMid << 16 |
+                                TssGdt->HighWord.Bytes.BaseHi << 24);
+
+    /*
+     * Switch to it and activate it, masking off the nested flag.
+     *
+     * Note that in reality, we are already on the double-fault TSS
+     * -- we just need to update the PCR to reflect this.
+     */
+    KeGetPcr()->TSS = DfTss;
+    __writeeflags(__readeflags() &~ EFLAGS_NESTED_TASK);
+    TssGdt->HighWord.Bits.Dpl = 0;
+    TssGdt->HighWord.Bits.Pres = 1;
+    // TssGdt->HighWord.Bits.Type &= ~0x2; /* I386_ACTIVE_TSS --> I386_TSS */
+    TssGdt->HighWord.Bits.Type = I386_TSS; // Busy bit cleared in the TSS selector.
+
+    /* Bugcheck the system */
+    KeBugCheckWithTf(UNEXPECTED_KERNEL_MODE_TRAP,
+                     EXCEPTION_DOUBLE_FAULT,
+                     (ULONG_PTR)Tss,
+                     0,
+                     0,
+                     NULL);
 }
 
 DECLSPEC_NORETURN
@@ -851,7 +898,7 @@ KiTrap0AHandler(IN PKTRAP_FRAME TrapFrame)
     KiEnterTrap(TrapFrame);
 
     /* Check for VDM trap */
-    ASSERT((KiVdmTrap(TrapFrame)) == FALSE);
+    ASSERT(KiVdmTrap(TrapFrame) == FALSE);
 
     /* Kill the system */
     KiSystemFatalException(EXCEPTION_INVALID_TSS, TrapFrame);
@@ -893,45 +940,44 @@ KiTrap0DHandler(IN PKTRAP_FRAME TrapFrame)
     PUCHAR Instructions;
     UCHAR Instruction = 0;
     KIRQL OldIrql;
-    
+
     /* Check for V86 GPF */
     if (__builtin_expect(KiV86Trap(TrapFrame), 1))
     {
         /* Enter V86 trap */
         KiEnterV86Trap(TrapFrame);
-        
+
         /* Must be a VDM process */
         if (__builtin_expect(!PsGetCurrentProcess()->VdmObjects, 0))
         {
             /* Enable interrupts */
             _enable();
-            
+
             /* Setup illegal instruction fault */
             KiDispatchException0Args(STATUS_ILLEGAL_INSTRUCTION,
                                      TrapFrame->Eip,
                                      TrapFrame);
         }
-        
+
         /* Go to APC level */
-        OldIrql = KfRaiseIrql(APC_LEVEL);
+        KeRaiseIrql(APC_LEVEL, &OldIrql);
         _enable();
-        
+
         /* Handle the V86 opcode */
         if (__builtin_expect(Ki386HandleOpcodeV86(TrapFrame) == 0xFF, 0))
         {
             /* Should only happen in VDM mode */
-            UNIMPLEMENTED;
-            while (TRUE);
+            UNIMPLEMENTED_FATAL();
         }
-        
+
         /* Bring IRQL back */
-        KfLowerIrql(OldIrql);
+        KeLowerIrql(OldIrql);
         _disable();
-        
+
         /* Do a quick V86 exit if possible */
         KiExitV86Trap(TrapFrame);
     }
-    
+
     /* Save trap frame */
     KiEnterTrap(TrapFrame);
 
@@ -940,14 +986,14 @@ KiTrap0DHandler(IN PKTRAP_FRAME TrapFrame)
     {
         /* Should not be VDM */
         ASSERT(KiVdmTrap(TrapFrame) == FALSE);
-        
+
         /* Enable interrupts and check error code */
         _enable();
         if (!TrapFrame->ErrCode)
         {
             /* FIXME: Use SEH */
             Instructions = (PUCHAR)TrapFrame->Eip;
-            
+
             /* Scan next 15 bytes */
             for (i = 0; i < 15; i++)
             {
@@ -961,7 +1007,7 @@ KiTrap0DHandler(IN PKTRAP_FRAME TrapFrame)
                         break;
                     }
                 }
-                
+
                 /* Is this NOT any prefix instruction? */
                 if (j == sizeof(KiTrapPrefixTable))
                 {
@@ -970,7 +1016,7 @@ KiTrap0DHandler(IN PKTRAP_FRAME TrapFrame)
                     break;
                 }
             }
-            
+
             /* If all we found was prefixes, then this instruction is too long */
             if (i == 15)
             {
@@ -979,9 +1025,9 @@ KiTrap0DHandler(IN PKTRAP_FRAME TrapFrame)
                                          TrapFrame->Eip,
                                          TrapFrame);
             }
-            
+
             /* Check for privileged instructions */
-            DPRINT("Instruction (%d) at fault: %lx %lx %lx %lx\n",
+            DPRINT("Instruction (%lu) at fault: %lx %lx %lx %lx\n",
                     i,
                     Instructions[i],
                     Instructions[i + 1],
@@ -1046,7 +1092,7 @@ KiTrap0DHandler(IN PKTRAP_FRAME TrapFrame)
                     }
                 }
             }
-            
+
             /* So now... was the instruction privileged or not? */
             if (Privileged)
             {
@@ -1056,7 +1102,7 @@ KiTrap0DHandler(IN PKTRAP_FRAME TrapFrame)
                                          TrapFrame);
             }
         }
-            
+
         /* If we got here, send an access violation */
         KiDispatchException2Args(STATUS_ACCESS_VIOLATION,
                                  TrapFrame->Eip,
@@ -1076,8 +1122,7 @@ KiTrap0DHandler(IN PKTRAP_FRAME TrapFrame)
         ((PVOID)TrapFrame->Eip < (PVOID)KiTrap0DHandler))
     {
         /* Not implemented */
-        UNIMPLEMENTED;
-        while (TRUE);
+        UNIMPLEMENTED_FATAL();
     }
 
     /*
@@ -1105,7 +1150,7 @@ KiTrap0DHandler(IN PKTRAP_FRAME TrapFrame)
      * when the user is purposedly trying to create one from kernel-mode, so
      * we should probably table this for now since it's not a "real" issue.
      */
-     
+
     /*
      * NOTE2: Another scenario is the IRET during a V8086 restore (BIOS Call)
      * which will cause a GPF since the trap frame is a total mess (on purpose)
@@ -1132,11 +1177,10 @@ KiTrap0DHandler(IN PKTRAP_FRAME TrapFrame)
         else
         {
             /* Otherwise, this is another kind of IRET fault */
-            UNIMPLEMENTED;
-            while (TRUE);
+            UNIMPLEMENTED_FATAL();
         }
     }
-     
+
      /* So since we're not dealing with the above case, check for RDMSR/WRMSR */
     if ((Instructions[0] == 0xF) &&            // 2-byte opcode
         ((Instructions[1] == 0x32) ||        // RDMSR
@@ -1164,7 +1208,7 @@ KiTrap0DHandler(IN PKTRAP_FRAME TrapFrame)
         /* Whatever it is, we can't handle it */
         KiSystemFatalException(EXCEPTION_GP_FAULT, TrapFrame);
     }
-    
+
     /* Return to where we came from */
     KiTrapReturn(TrapFrame);
 }
@@ -1175,6 +1219,7 @@ FASTCALL
 KiTrap0EHandler(IN PKTRAP_FRAME TrapFrame)
 {
     PKTHREAD Thread;
+    BOOLEAN StoreInstruction;
     ULONG_PTR Cr2;
     NTSTATUS Status;
 
@@ -1190,33 +1235,71 @@ KiTrap0EHandler(IN PKTRAP_FRAME TrapFrame)
             FIELD_OFFSET(KTRAP_FRAME, EFlags))
         {
             /* The stack is somewhere in between frames, we need to fix it */
-            UNIMPLEMENTED;
-            while (TRUE);
+            UNIMPLEMENTED_FATAL();
         }
     }
 
     /* Save CR2 */
     Cr2 = __readcr2();
 
-    /* Enable interupts */
+    /* Enable interrupts */
     _enable();
 
+    /* Interpret the error code */
+    StoreInstruction = (TrapFrame->ErrCode & 2) != 0;
+
     /* Check if we came in with interrupts disabled */
     if (!(TrapFrame->EFlags & EFLAGS_INTERRUPT_MASK))
     {
         /* This is completely illegal, bugcheck the system */
         KeBugCheckWithTf(IRQL_NOT_LESS_OR_EQUAL,
                          Cr2,
-                         -1,
-                         TrapFrame->ErrCode & 2 ? TRUE : FALSE,
+                         (ULONG_PTR)-1,
+                         TrapFrame->ErrCode,
                          TrapFrame->Eip,
                          TrapFrame);
     }
 
-    /* Check for S-LIST fault in kernel mode */
-    if (TrapFrame->Eip == (ULONG_PTR)ExpInterlockedPopEntrySListFault)
+    /* Check for S-List fault
+
+       Explanation: An S-List fault can occur due to a race condition between 2
+       threads simultaneously trying to pop an element from the S-List. After
+       thread 1 has read the pointer to the top element on the S-List it is
+       preempted and thread 2 calls InterlockedPopEntrySlist on the same S-List,
+       removing the top element and freeing it's memory. After that thread 1
+       resumes and tries to read the address of the Next pointer from the top
+       element, which it assumes will be the next top element.
+       But since that memory has been freed, we get a page fault. To handle this
+       race condition, we let thread 1 repeat the operation.
+       We do NOT invoke the page fault handler in this case, since we do not
+       want to trigger any side effects, like paging or a guard page fault.
+
+       Sequence of operations:
+
+           Thread 1 : mov eax, [ebp] <= eax now points to the first element
+           Thread 1 : mov edx, [ebp + 4] <= edx is loaded with Depth and Sequence
+            *** preempted ***
+           Thread 2 : calls InterlockedPopEntrySlist, changing the top element
+           Thread 2 : frees the memory of the element that was popped
+            *** preempted ***
+           Thread 1 : checks if eax is NULL
+           Thread 1 : InterlockedPopEntrySListFault: mov ebx, [eax] <= faults
+
+        To be sure that we are dealing with exactly the case described above, we
+        check whether the ListHeader has changed. If Thread 2 only popped one
+        entry, the Next field in the S-List-header has changed.
+        If after thread 1 has faulted, thread 2 allocates a new element, by
+        chance getting the same address as the previously freed element and
+        pushes it on the list again, we will see the same top element, but the
+        Sequence member of the S-List header has changed. Therefore we check
+        both fields to make sure we catch any concurrent modification of the
+        S-List-header.
+    */
+    if ((TrapFrame->Eip == (ULONG_PTR)ExpInterlockedPopEntrySListFault) ||
+        (TrapFrame->Eip == (ULONG_PTR)KeUserPopEntrySListFault))
     {
-        PSLIST_HEADER SListHeader;
+        ULARGE_INTEGER SListHeader;
+        PVOID ResumeAddress;
 
         /* Sanity check that the assembly is correct:
            This must be mov ebx, [eax]
@@ -1228,47 +1311,97 @@ KiTrap0EHandler(IN PKTRAP_FRAME TrapFrame)
                (((UCHAR*)TrapFrame->Eip)[4] == 0x4D) &&
                (((UCHAR*)TrapFrame->Eip)[5] == 0x00));
 
-        /* Get the pointer to the SLIST_HEADER */
-        SListHeader = (PSLIST_HEADER)TrapFrame->Ebp;
+        /* Check if this is a user fault */
+        if (TrapFrame->Eip == (ULONG_PTR)KeUserPopEntrySListFault)
+        {
+            /* EBP points to the S-List-header. Copy it inside SEH, to protect
+               against a bogus pointer from user mode */
+            _SEH2_TRY
+            {
+                ProbeForRead((PVOID)TrapFrame->Ebp,
+                             sizeof(ULARGE_INTEGER),
+                             TYPE_ALIGNMENT(SLIST_HEADER));
+                SListHeader = *(PULARGE_INTEGER)TrapFrame->Ebp;
+            }
+            _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+            {
+                /* The S-List pointer is not valid! */
+                goto NotSListFault;
+            }
+            _SEH2_END;
+            ResumeAddress = KeUserPopEntrySListResume;
+        }
+        else
+        {
+            SListHeader = *(PULARGE_INTEGER)TrapFrame->Ebp;
+            ResumeAddress = ExpInterlockedPopEntrySListResume;
+        }
 
-        /* Check if the Next member of the SLIST_HEADER was changed */
-        if (SListHeader->Next.Next != (PSLIST_ENTRY)TrapFrame->Eax)
+        /* Check if either the Next pointer or the Sequence member in the
+           S-List-header has changed. If any of these has changed, we restart
+           the operation. Otherwise we only have a bogus pointer and let the
+           page fault handler deal with it. */
+        if ((SListHeader.LowPart != TrapFrame->Eax) ||
+            (SListHeader.HighPart != TrapFrame->Edx))
         {
+            DPRINT1("*** Got an S-List-Fault ***\n");
+            KeGetCurrentThread()->SListFaultCount++;
+
             /* Restart the operation */
-            TrapFrame->Eip = (ULONG_PTR)ExpInterlockedPopEntrySListResume;
+            TrapFrame->Eip = (ULONG_PTR)ResumeAddress;
 
             /* Continue execution */
             KiEoiHelper(TrapFrame);
         }
     }
+NotSListFault:
 
     /* Call the access fault handler */
-    Status = MmAccessFault(TrapFrame->ErrCode & 1,
+    Status = MmAccessFault(TrapFrame->ErrCode,
                            (PVOID)Cr2,
-                           TrapFrame->SegCs & MODE_MASK,
+                           KiUserTrap(TrapFrame),
                            TrapFrame);
-    if (NT_SUCCESS(Status)) KiEoiHelper(TrapFrame);
-    
+    if (NT_SUCCESS(Status))
+    {
+#ifdef _WINKD_
+        /* Check whether the kernel debugger has owed breakpoints to be inserted */
+        KdSetOwedBreakpoints();
+#endif
+        /* We succeeded, return */
+        KiEoiHelper(TrapFrame);
+    }
+
     /* Check for syscall fault */
 #if 0
     if ((TrapFrame->Eip == (ULONG_PTR)CopyParams) ||
         (TrapFrame->Eip == (ULONG_PTR)ReadBatch))
     {
         /* Not yet implemented */
-        UNIMPLEMENTED;
-        while (TRUE);
+        UNIMPLEMENTED_FATAL();
     }
 #endif
+
     /* Check for VDM trap */
-    ASSERT((KiVdmTrap(TrapFrame)) == FALSE);
-    
+    if (KiVdmTrap(TrapFrame))
+    {
+        DPRINT1("VDM PAGE FAULT at %lx:%lx for address %lx\n",
+                TrapFrame->SegCs, TrapFrame->Eip, Cr2);
+        if (VdmDispatchPageFault(TrapFrame))
+        {
+            /* Return and end VDM execution */
+            DPRINT1("VDM page fault with status 0x%lx resolved\n", Status);
+            KiEoiHelper(TrapFrame);
+        }
+        DPRINT1("VDM page fault with status 0x%lx NOT resolved\n", Status);
+    }
+
     /* Either kernel or user trap (non VDM) so dispatch exception */
     if (Status == STATUS_ACCESS_VIOLATION)
     {
         /* This status code is repurposed so we can recognize it later */
         KiDispatchException2Args(KI_EXCEPTION_ACCESS_VIOLATION,
                                  TrapFrame->Eip,
-                                 TrapFrame->ErrCode & 2 ? TRUE : FALSE,
+                                 StoreInstruction,
                                  Cr2,
                                  TrapFrame);
     }
@@ -1278,16 +1411,17 @@ KiTrap0EHandler(IN PKTRAP_FRAME TrapFrame)
         /* These faults only have two parameters */
         KiDispatchException2Args(Status,
                                  TrapFrame->Eip,
-                                 TrapFrame->ErrCode & 2 ? TRUE : FALSE,
+                                 StoreInstruction,
                                  Cr2,
                                  TrapFrame);
     }
-    
+
     /* Only other choice is an in-page error, with 3 parameters */
     KiDispatchExceptionFromTrapFrame(STATUS_IN_PAGE_ERROR,
+                                     0,
                                      TrapFrame->Eip,
                                      3,
-                                     TrapFrame->ErrCode & 2 ? TRUE : FALSE,
+                                     StoreInstruction,
                                      Cr2,
                                      Status,
                                      TrapFrame);
@@ -1313,7 +1447,7 @@ KiTrap10Handler(IN PKTRAP_FRAME TrapFrame)
 {
     PKTHREAD Thread;
     PFX_SAVE_AREA SaveArea;
-    
+
     /* Save trap frame */
     KiEnterTrap(TrapFrame);
 
@@ -1325,11 +1459,11 @@ KiTrap10Handler(IN PKTRAP_FRAME TrapFrame)
         /* It isn't, enable interrupts and set delayed error */
         _enable();
         SaveArea->Cr0NpxState |= CR0_TS;
-        
+
         /* End trap */
         KiEoiHelper(TrapFrame);
     }
-    
+
     /* Otherwise, proceed with NPX fault handling */
     KiNpxHandler(TrapFrame, Thread, SaveArea);
 }
@@ -1355,7 +1489,7 @@ KiTrap13Handler(IN PKTRAP_FRAME TrapFrame)
     PKTHREAD Thread;
     PFX_SAVE_AREA SaveArea;
     ULONG Cr0, MxCsrMask, Error;
-    
+
     /* Save trap frame */
     KiEnterTrap(TrapFrame);
 
@@ -1371,7 +1505,7 @@ KiTrap13Handler(IN PKTRAP_FRAME TrapFrame)
     SaveArea = KiGetThreadNpxArea(Thread);
 
     /* Check for VDM trap */
-    ASSERT((KiVdmTrap(TrapFrame)) == FALSE);
+    ASSERT(KiVdmTrap(TrapFrame) == FALSE);
 
     /* Check for user trap */
     if (!KiUserTrap(TrapFrame))
@@ -1379,31 +1513,31 @@ KiTrap13Handler(IN PKTRAP_FRAME TrapFrame)
         /* Kernel should not fault on XMMI */
         KeBugCheckWithTf(TRAP_CAUSE_UNKNOWN, 13, 0, 0, 2, TrapFrame);
     }
-    
+
     /* Update CR0 */
     Cr0 = __readcr0();
     Cr0 &= ~(CR0_MP | CR0_EM | CR0_TS);
     __writecr0(Cr0);
-    
+
     /* Save FPU state */
     Ke386SaveFpuState(SaveArea);
-    
+
     /* Mark CR0 state dirty */
     Cr0 |= NPX_STATE_NOT_LOADED;
     Cr0 |= SaveArea->Cr0NpxState;
      __writecr0(Cr0);
-    
+
     /* Update NPX state */
     Thread->NpxState = NPX_STATE_NOT_LOADED;
     KeGetCurrentPrcb()->NpxThread = NULL;
-    
+
     /* Clear the TS bit and re-enable interrupts */
     SaveArea->Cr0NpxState &= ~CR0_TS;
     _enable();
 
     /* Now look at MxCsr to get the mask of errors we should care about */
     MxCsrMask = ~((USHORT)SaveArea->U.FxArea.MXCsr >> 7);
-    
+
     /* Get legal exceptions that software should handle */
     Error = (USHORT)SaveArea->U.FxArea.MXCsr & (FSW_INVALID_OPERATION |
                                                 FSW_DENORMAL |
@@ -1427,27 +1561,98 @@ KiTrap13Handler(IN PKTRAP_FRAME TrapFrame)
                                  0,
                                  TrapFrame);
     }
-    
+
     /* Unknown XMMI fault */
     KeBugCheckWithTf(TRAP_CAUSE_UNKNOWN, 13, 0, 0, 1, TrapFrame);
 }
 
 /* SOFTWARE SERVICES **********************************************************/
 
+VOID
+FASTCALL
+KiRaiseSecurityCheckFailureHandler(IN PKTRAP_FRAME TrapFrame)
+{
+    /* Save trap frame */
+    KiEnterTrap(TrapFrame);
+
+    /* Decrement EIP to point to the INT29 instruction (2 bytes, not 1 like INT3) */
+    TrapFrame->Eip -= 2;
+
+    /* Check if this is a user trap */
+    if (KiUserTrap(TrapFrame))
+    {
+        /* Dispatch exception to user mode */
+        KiDispatchExceptionFromTrapFrame(STATUS_STACK_BUFFER_OVERRUN,
+                                         EXCEPTION_NONCONTINUABLE,
+                                         TrapFrame->Eip,
+                                         1,
+                                         TrapFrame->Ecx,
+                                         0,
+                                         0,
+                                         TrapFrame);
+    }
+    else
+    {
+        EXCEPTION_RECORD ExceptionRecord;
+
+        /* Bugcheck the system */
+        ExceptionRecord.ExceptionCode = STATUS_STACK_BUFFER_OVERRUN;
+        ExceptionRecord.ExceptionFlags = EXCEPTION_NONCONTINUABLE;
+        ExceptionRecord.ExceptionRecord = NULL;
+        ExceptionRecord.ExceptionAddress = (PVOID)TrapFrame->Eip;
+        ExceptionRecord.NumberParameters = 1;
+        ExceptionRecord.ExceptionInformation[0] = TrapFrame->Ecx;
+
+        KeBugCheckWithTf(KERNEL_SECURITY_CHECK_FAILURE,
+                         TrapFrame->Ecx,
+                         (ULONG_PTR)TrapFrame,
+                         (ULONG_PTR)&ExceptionRecord,
+                         0,
+                         TrapFrame);
+    }
+}
+
 VOID
 FASTCALL
 KiGetTickCountHandler(IN PKTRAP_FRAME TrapFrame)
 {
-    UNIMPLEMENTED;
-    while (TRUE);
+    /* Save trap frame */
+    KiEnterTrap(TrapFrame);
+
+    /*
+     * Just fail the request
+     */
+    DbgPrint("INT 0x2A attempted, returning 0 tick count\n");
+    TrapFrame->Eax = 0;
+
+    /* Exit the trap */
+    KiEoiHelper(TrapFrame);
 }
 
 VOID
 FASTCALL
 KiCallbackReturnHandler(IN PKTRAP_FRAME TrapFrame)
 {
-    UNIMPLEMENTED;
-    while (TRUE);
+    PKTHREAD Thread;
+    NTSTATUS Status;
+
+    /* Save the SEH chain, NtCallbackReturn will restore this */
+    TrapFrame->ExceptionList = KeGetPcr()->NtTib.ExceptionList;
+
+    /* Set thread fields */
+    Thread = KeGetCurrentThread();
+    Thread->TrapFrame = TrapFrame;
+    Thread->PreviousMode = KiUserTrap(TrapFrame);
+    ASSERT(Thread->PreviousMode != KernelMode);
+
+    /* Pass the register parameters to NtCallbackReturn.
+       Result pointer is in ecx, result length in edx, status in eax */
+    Status = NtCallbackReturn((PVOID)TrapFrame->Ecx,
+                              TrapFrame->Edx,
+                              TrapFrame->Eax);
+
+    /* If we got here, something went wrong. Return an error to the caller */
+    KiServiceExit(TrapFrame, Status);
 }
 
 DECLSPEC_NORETURN
@@ -1474,10 +1679,10 @@ KiDebugServiceHandler(IN PKTRAP_FRAME TrapFrame)
 {
     /* Save trap frame */
     KiEnterTrap(TrapFrame);
-    
+
     /* Increment EIP to skip the INT3 instruction */
     TrapFrame->Eip++;
-    
+
     /* Continue with the common handler */
     KiDebugHandler(TrapFrame, TrapFrame->Eax, TrapFrame->Ecx, TrapFrame->Edx);
 }
@@ -1506,16 +1711,17 @@ KiDbgPostServiceHook(ULONG SystemCallNumber, ULONG_PTR Result)
 
 DECLSPEC_NORETURN
 VOID
-FORCEINLINE
-KiSystemCall(IN PKTRAP_FRAME TrapFrame,
-             IN PVOID Arguments)
+FASTCALL
+KiSystemServiceHandler(IN PKTRAP_FRAME TrapFrame,
+                       IN PVOID Arguments)
 {
     PKTHREAD Thread;
     PKSERVICE_TABLE_DESCRIPTOR DescriptorTable;
-    ULONG Id, Offset, StackBytes, Result;
+    ULONG Id, Offset, StackBytes;
+    NTSTATUS Status;
     PVOID Handler;
     ULONG SystemCallNumber = TrapFrame->Eax;
-    
+
     /* Get the current thread */
     Thread = KeGetCurrentThread();
 
@@ -1539,7 +1745,7 @@ KiSystemCall(IN PKTRAP_FRAME TrapFrame,
     TrapFrame->Dr7 = 0;
 
     /* Check if the frame was from user mode */
-    if (TrapFrame->SegCs & MODE_MASK)
+    if (KiUserTrap(TrapFrame))
     {
         /* Check for active debugging */
         if (KeGetCurrentThread()->Header.DebugActive & 0xFF)
@@ -1559,7 +1765,7 @@ KiSystemCall(IN PKTRAP_FRAME TrapFrame,
     /* Decode the system call number */
     Offset = (SystemCallNumber >> SERVICE_TABLE_SHIFT) & SERVICE_TABLE_MASK;
     Id = SystemCallNumber & SERVICE_NUMBER_MASK;
-    
+
     /* Get descriptor table */
     DescriptorTable = (PVOID)((ULONG_PTR)Thread->ServiceTable + Offset);
 
@@ -1570,21 +1776,20 @@ KiSystemCall(IN PKTRAP_FRAME TrapFrame,
         if (!(Offset & SERVICE_TABLE_TEST))
         {
             /* Fail the call */
-            Result = STATUS_INVALID_SYSTEM_SERVICE;
+            Status = STATUS_INVALID_SYSTEM_SERVICE;
             goto ExitCall;
         }
 
         /* Convert us to a GUI thread -- must wrap in ASM to get new EBP */
-        Result = KiConvertToGuiThread();
+        Status = KiConvertToGuiThread();
 
         /* Reload trap frame and descriptor table pointer from new stack */
         TrapFrame = *(volatile PVOID*)&Thread->TrapFrame;
         DescriptorTable = (PVOID)(*(volatile ULONG_PTR*)&Thread->ServiceTable + Offset);
 
-        if (!NT_SUCCESS(Result))
+        if (!NT_SUCCESS(Status))
         {
             /* Set the last error and fail */
-            //SetLastWin32Error(RtlNtStatusToDosError(Result));
             goto ExitCall;
         }
 
@@ -1592,86 +1797,60 @@ KiSystemCall(IN PKTRAP_FRAME TrapFrame,
         if (Id >= DescriptorTable->Limit)
         {
             /* Fail the call */
-            Result = STATUS_INVALID_SYSTEM_SERVICE;
+            Status = STATUS_INVALID_SYSTEM_SERVICE;
             goto ExitCall;
         }
     }
-    
+
     /* Check if this is a GUI call */
     if (__builtin_expect(Offset & SERVICE_TABLE_TEST, 0))
     {
         /* Get the batch count and flush if necessary */
         if (NtCurrentTeb()->GdiBatchCount) KeGdiFlushUserBatch();
     }
-    
+
     /* Increase system call count */
     KeGetCurrentPrcb()->KeSystemCalls++;
-    
+
     /* FIXME: Increase individual counts on debug systems */
     //KiIncreaseSystemCallCount(DescriptorTable, Id);
-    
+
     /* Get stack bytes */
     StackBytes = DescriptorTable->Number[Id];
-    
+
     /* Probe caller stack */
     if (__builtin_expect((Arguments < (PVOID)MmUserProbeAddress) && !(KiUserTrap(TrapFrame)), 0))
     {
         /* Access violation */
-        UNIMPLEMENTED;
-        while (TRUE);
+        UNIMPLEMENTED_FATAL();
     }
-    
+
     /* Call pre-service debug hook */
     KiDbgPreServiceHook(SystemCallNumber, Arguments);
 
     /* Get the handler and make the system call */
     Handler = (PVOID)DescriptorTable->Base[Id];
-    Result = KiSystemCallTrampoline(Handler, Arguments, StackBytes);
-    
+    Status = KiSystemCallTrampoline(Handler, Arguments, StackBytes);
+
     /* Call post-service debug hook */
-    Result = KiDbgPostServiceHook(SystemCallNumber, Result);
+    Status = KiDbgPostServiceHook(SystemCallNumber, Status);
 
     /* Make sure we're exiting correctly */
     KiExitSystemCallDebugChecks(Id, TrapFrame);
-    
+
     /* Restore the old trap frame */
 ExitCall:
     Thread->TrapFrame = (PKTRAP_FRAME)TrapFrame->Edx;
 
     /* Exit from system call */
-    KiServiceExit(TrapFrame, Result);
-}
-
-DECLSPEC_NORETURN
-VOID
-FASTCALL
-KiSystemServiceHandler(IN PKTRAP_FRAME TrapFrame,
-                       IN PVOID Arguments)
-{
-    /* Call the shared handler (inline) */
-    KiSystemCall(TrapFrame, Arguments);
+    KiServiceExit(TrapFrame, Status);
 }
 
-DECLSPEC_NORETURN
 VOID
 FASTCALL
-KiFastCallEntryHandler(IN PKTRAP_FRAME TrapFrame,
-                       IN PVOID Arguments)
+KiCheckForSListAddress(IN PKTRAP_FRAME TrapFrame)
 {
-    /* Set up a fake INT Stack and enable interrupts */
-    TrapFrame->HardwareSegSs = KGDT_R3_DATA | RPL_MASK;
-    TrapFrame->HardwareEsp = (ULONG_PTR)Arguments;
-    TrapFrame->EFlags = __readeflags() | EFLAGS_INTERRUPT_MASK;
-    TrapFrame->SegCs = KGDT_R3_CODE | RPL_MASK;
-    TrapFrame->Eip = SharedUserData->SystemCallReturn;
-    TrapFrame->SegFs = KGDT_R3_TEB | RPL_MASK;
-    __writeeflags(0x2);
-    
-    /* Arguments are actually 2 frames down (because of the double indirection) */
-    Arguments = (PVOID)(TrapFrame->HardwareEsp + 8);
-
-    /* Call the shared handler (inline) */
-    KiSystemCall(TrapFrame, Arguments);
+    UNIMPLEMENTED;
 }
 
 /*
@@ -1682,8 +1861,7 @@ NTAPI
 Kei386EoiHelper(VOID)
 {
     /* We should never see this call happening */
-    DPRINT1("Mismatched NT/HAL version");
-    while (TRUE);
+    KeBugCheck(MISMATCHED_HAL);
 }
 
 /* EOF */