- NDK 0.98, now with versionned headers. Too many changes to list, see the TinyKRNL...
[reactos.git] / reactos / ntoskrnl / ke / i386 / exp.c
index 9667945..27db6a3 100644 (file)
@@ -1,13 +1,22 @@
 /*
  * COPYRIGHT:       See COPYING in the top level directory
- * PROJECT:         ReactOS kernel
+ * PROJECT:         ReactOS Kernel
  * FILE:            ntoskrnl/ke/i386/exp.c
- * PURPOSE:         Handling exceptions
- *
- * PROGRAMMERS:     David Welch (welch@cwcom.net)
+ * PURPOSE:         Exception Support Code
+ * PROGRAMMERS:     Alex Ionescu (alex@relsoft.net)
+ *                  Gregor Anich
+ *                  David Welch (welch@cwcom.net)
  *                  Skywing (skywing@valhallalegends.com)
  */
 
+/*
+ * FIXMES:
+ *  - Clean up file (remove all stack functions and use RtlWalkFrameChain/RtlCaptureStackBacktrace)
+ *  - Sanitize some context fields.
+ *  - Add PSEH handler when an exception occurs in an exception (KiCopyExceptionRecord).
+ *  - Forward exceptions to user-mode debugger.
+ */
+
 /* INCLUDES *****************************************************************/
 
 #include <ntoskrnl.h>
 #define NDEBUG
 #include <internal/debug.h>
 
-/*
- * FIXMES:
- *  - Put back VEH.
- *  - Clean up file.
- *  - Sanitize some context fields.
- *  - Add PSEH handler when an exception occurs in an exception (KiCopyExceptionRecord).
- *  - Implement official stack trace functions (exported) and remove stuff here.
- *  - Forward exceptions to user-mode debugger.
- */
+#if defined (ALLOC_PRAGMA)
+#pragma alloc_text(INIT, KeInitExceptions)
+#endif
 
 VOID
 NTAPI
-Ki386AdjustEsp0(IN PKTRAP_FRAME TrapFrame);
+Ki386AdjustEsp0(
+    IN PKTRAP_FRAME TrapFrame
+);
+
+extern KIDTENTRY KiIdt[];
 
 /* GLOBALS *****************************************************************/
 
@@ -40,31 +47,6 @@ Ki386AdjustEsp0(IN PKTRAP_FRAME TrapFrame);
 # define ARRAY_SIZE(x) (sizeof (x) / sizeof (x[0]))
 #endif
 
-extern void KiSystemService(void);
-extern void KiDebugService(void);
-
-extern VOID KiTrap0(VOID);
-extern VOID KiTrap1(VOID);
-extern VOID KiTrap2(VOID);
-extern VOID KiTrap3(VOID);
-extern VOID KiTrap4(VOID);
-extern VOID KiTrap5(VOID);
-extern VOID KiTrap6(VOID);
-extern VOID KiTrap7(VOID);
-extern VOID KiTrap8(VOID);
-extern VOID KiTrap9(VOID);
-extern VOID KiTrap10(VOID);
-extern VOID KiTrap11(VOID);
-extern VOID KiTrap12(VOID);
-extern VOID KiTrap13(VOID);
-extern VOID KiTrap14(VOID);
-extern VOID KiTrap15(VOID);
-extern VOID KiTrap16(VOID);
-extern VOID KiTrap17(VOID);
-extern VOID KiTrap18(VOID);
-extern VOID KiTrap19(VOID);
-extern VOID KiTrapUnknown(VOID);
-
 extern ULONG init_stack;
 extern ULONG init_stack_top;
 
@@ -136,7 +118,7 @@ KiRosPrintAddress(PVOID address)
      while (current_entry != &ModuleListHead)
        {
           current =
-            CONTAINING_RECORD(current_entry, LDR_DATA_TABLE_ENTRY, InLoadOrderModuleList);
+            CONTAINING_RECORD(current_entry, LDR_DATA_TABLE_ENTRY, InLoadOrderLinks);
 
           if (address >= (PVOID)current->DllBase &&
               address < (PVOID)((ULONG_PTR)current->DllBase + current->SizeOfImage))
@@ -167,7 +149,7 @@ KiKernelTrapHandler(PKTRAP_FRAME Tf, ULONG ExceptionNr, PVOID Cr2)
     {
       Er.ExceptionCode = STATUS_ACCESS_VIOLATION;
       Er.NumberParameters = 2;
-      Er.ExceptionInformation[0] = Tf->ErrorCode & 0x1;
+      Er.ExceptionInformation[0] = Tf->ErrCode & 0x1;
       Er.ExceptionInformation[1] = (ULONG)Cr2;
     }
   else
@@ -194,6 +176,7 @@ KiKernelTrapHandler(PKTRAP_FRAME Tf, ULONG ExceptionNr, PVOID Cr2)
 VOID
 KiDoubleFaultHandler(VOID)
 {
+#if 0
   unsigned int cr2;
   ULONG StackLimit;
   ULONG StackBase;
@@ -212,7 +195,7 @@ KiDoubleFaultHandler(VOID)
 #endif
 
   OldTss = KeGetCurrentKPCR()->TSS;
-  Esp0 = OldTss->Esp;
+  Esp0 = OldTss->Esp0;
 
   /* Get CR2 */
   cr2 = Ke386GetCr2();
@@ -274,7 +257,7 @@ KiDoubleFaultHandler(VOID)
    DbgPrint("EDX: %.8x   EBP: %.8x   ESI: %.8x\nESP: %.8x ", OldTss->Edx,
            OldTss->Ebp, OldTss->Esi, Esp0);
    DbgPrint("EDI: %.8x   EFLAGS: %.8x ", OldTss->Edi, OldTss->Eflags);
-   if (OldTss->Cs == KERNEL_CS)
+   if (OldTss->Cs == KGDT_R0_CODE)
      {
        DbgPrint("kESP %.8x ", Esp0);
        if (PsGetCurrentThread() != NULL)
@@ -288,7 +271,7 @@ KiDoubleFaultHandler(VOID)
      {
        DbgPrint("User ESP %.8x\n", OldTss->Esp);
      }
-  if ((OldTss->Cs & 0xffff) == KERNEL_CS)
+  if ((OldTss->Cs & 0xffff) == KGDT_R0_CODE)
     {
       if (PsGetCurrentThread() != NULL)
        {
@@ -382,8 +365,8 @@ KiDoubleFaultHandler(VOID)
              DbgPrint("{");
              if (StackRepeatLength[i] == 0)
                {
-                 for(;;);
-               }
+   for(;;);
+}
              for (j = 0; j < StackRepeatLength[i]; j++)
                {
                  KeRosPrintAddress(StackTrace[i + j]);
@@ -394,19 +377,20 @@ KiDoubleFaultHandler(VOID)
        }
 #endif
     }
-
+#endif
    DbgPrint("\n");
    for(;;);
 }
 
 VOID
+NTAPI
 KiDumpTrapFrame(PKTRAP_FRAME Tf, ULONG Parameter1, ULONG Parameter2)
 {
   ULONG cr3_;
   ULONG StackLimit;
   ULONG Esp0;
-  ULONG ExceptionNr = (ULONG)Tf->DebugArgMark;
-  ULONG cr2 = (ULONG)Tf->DebugPointer;
+  ULONG ExceptionNr = (ULONG)Tf->DbgArgMark;
+  ULONG cr2 = (ULONG)Tf->DbgArgPointer;
 
   Esp0 = (ULONG)Tf;
 
@@ -416,14 +400,14 @@ KiDumpTrapFrame(PKTRAP_FRAME Tf, ULONG Parameter1, ULONG Parameter2)
    if (ExceptionNr < ARRAY_SIZE(ExceptionTypeStrings))
      {
        DbgPrint("%s Exception: %d(%x)\n", ExceptionTypeStrings[ExceptionNr],
-                ExceptionNr, Tf->ErrorCode&0xffff);
+                ExceptionNr, Tf->ErrCode&0xffff);
      }
    else
      {
-       DbgPrint("Exception: %d(%x)\n", ExceptionNr, Tf->ErrorCode&0xffff);
+       DbgPrint("Exception: %d(%x)\n", ExceptionNr, Tf->ErrCode&0xffff);
      }
    DbgPrint("Processor: %d CS:EIP %x:%x ", KeGetCurrentProcessorNumber(),
-           Tf->Cs&0xffff, Tf->Eip);
+           Tf->SegCs&0xffff, Tf->Eip);
    KeRosPrintAddress((PVOID)Tf->Eip);
    DbgPrint("\n");
    Ke386GetPageTableDirectory(cr3_);
@@ -441,13 +425,13 @@ KiDumpTrapFrame(PKTRAP_FRAME Tf, ULONG Parameter1, ULONG Parameter2)
                 PsGetCurrentThread()->Cid.UniqueThread);
      }
    DbgPrint("\n");
-   DbgPrint("DS %x ES %x FS %x GS %x\n", Tf->Ds&0xffff, Tf->Es&0xffff,
-           Tf->Fs&0xffff, Tf->Gs&0xfff);
+   DbgPrint("DS %x ES %x FS %x GS %x\n", Tf->SegDs&0xffff, Tf->SegEs&0xffff,
+           Tf->SegFs&0xffff, Tf->SegGs&0xfff);
    DbgPrint("EAX: %.8x   EBX: %.8x   ECX: %.8x\n", Tf->Eax, Tf->Ebx, Tf->Ecx);
    DbgPrint("EDX: %.8x   EBP: %.8x   ESI: %.8x   ESP: %.8x\n", Tf->Edx,
            Tf->Ebp, Tf->Esi, Esp0);
-   DbgPrint("EDI: %.8x   EFLAGS: %.8x ", Tf->Edi, Tf->Eflags);
-   if ((Tf->Cs&0xffff) == KERNEL_CS)
+   DbgPrint("EDI: %.8x   EFLAGS: %.8x ", Tf->Edi, Tf->EFlags);
+   if ((Tf->SegCs&0xffff) == KGDT_R0_CODE)
      {
        DbgPrint("kESP %.8x ", Esp0);
        if (PsGetCurrentThread() != NULL)
@@ -488,22 +472,19 @@ KiTrapHandler(PKTRAP_FRAME Tf, ULONG ExceptionNr)
 
    ASSERT(ExceptionNr != 14);
 
-   /* Store the exception number in an unused field in the trap frame. */
-   Tf->DebugArgMark = ExceptionNr;
-
    /* Use the address of the trap frame as approximation to the ring0 esp */
    Esp0 = (ULONG)&Tf->Eip;
 
    /* Get CR2 */
    cr2 = Ke386GetCr2();
-   Tf->DebugPointer = cr2;
+   Tf->DbgArgPointer = cr2;
 
    /*
     * If this was a V86 mode exception then handle it specially
     */
-   if (Tf->Eflags & (1 << 17))
+   if (Tf->EFlags & (1 << 17))
      {
-       DPRINT("Tf->Eflags, %x, Tf->Eip %x, ExceptionNr: %d\n", Tf->Eflags, Tf->Eip, ExceptionNr);
+       DPRINT("Tf->Eflags, %x, Tf->Eip %x, ExceptionNr: %d\n", Tf->EFlags, Tf->Eip, ExceptionNr);
        return(KeV86Exception(ExceptionNr, Tf, cr2));
      }
 
@@ -527,7 +508,6 @@ KiTrapHandler(PKTRAP_FRAME Tf, ULONG ExceptionNr)
         *   in the early boot phase in apic mode (using the smp build). I've looked to the linux
         *   sources. Linux does ignore this exception.
         *
-        *   Hartmut Birr
         */
        DPRINT1("Ignoring P6 Local APIC Spurious Interrupt Bug...\n");
        return(0);
@@ -560,7 +540,7 @@ KiTrapHandler(PKTRAP_FRAME Tf, ULONG ExceptionNr)
    /*
     * Handle user exceptions differently
     */
-   if ((Tf->Cs & 0xFFFF) == USER_CS)
+   if ((Tf->SegCs & 0xFFFF) == (KGDT_R3_CODE | RPL_MASK))
      {
        return(KiUserTrapHandler(Tf, ExceptionNr, (PVOID)cr2));
      }
@@ -575,15 +555,15 @@ NTAPI
 KiEspFromTrapFrame(IN PKTRAP_FRAME TrapFrame)
 {
     /* Check if this is user-mode or V86 */
-    if ((TrapFrame->Cs & 1) || (TrapFrame->Eflags & X86_EFLAGS_VM))
+    if ((TrapFrame->SegCs & MODE_MASK) || (TrapFrame->EFlags & X86_EFLAGS_VM))
     {
         /* Return it directly */
-        return TrapFrame->Esp;
+        return TrapFrame->HardwareEsp;
     }
     else
     {
         /* Edited frame */
-        if (!(TrapFrame->Cs & FRAME_EDITED))
+        if (!(TrapFrame->SegCs & FRAME_EDITED))
         {
             /* Return edited value */
             return TrapFrame->TempEsp;
@@ -591,7 +571,7 @@ KiEspFromTrapFrame(IN PKTRAP_FRAME TrapFrame)
         else
         {
             /* Virgin frame, calculate */
-            return (ULONG)&TrapFrame->Esp;
+            return (ULONG)&TrapFrame->HardwareEsp;
         }
     }
 }
@@ -604,10 +584,10 @@ KiEspToTrapFrame(IN PKTRAP_FRAME TrapFrame,
     ULONG Previous = KiEspFromTrapFrame(TrapFrame);
 
     /* Check if this is user-mode or V86 */
-    if ((TrapFrame->Cs & 1) || (TrapFrame->Eflags & X86_EFLAGS_VM))
+    if ((TrapFrame->SegCs & MODE_MASK) || (TrapFrame->EFlags & X86_EFLAGS_VM))
     {
         /* Write it directly */
-        TrapFrame->Esp = Esp;
+        TrapFrame->HardwareEsp = Esp;
     }
     else
     {
@@ -618,7 +598,7 @@ KiEspToTrapFrame(IN PKTRAP_FRAME TrapFrame,
         }
 
         /* Create an edit frame, check if it was alrady */
-        if (!(TrapFrame->Cs & FRAME_EDITED))
+        if (!(TrapFrame->SegCs & FRAME_EDITED))
         {
             /* Update the value */
             TrapFrame->TempEsp = Esp;
@@ -629,8 +609,8 @@ KiEspToTrapFrame(IN PKTRAP_FRAME TrapFrame,
             if (Previous != Esp)
             {
                 /* Save CS */
-                TrapFrame->TempCs = TrapFrame->Cs;
-                TrapFrame->Cs &= ~FRAME_EDITED;
+                TrapFrame->TempSegCs = TrapFrame->SegCs;
+                TrapFrame->SegCs &= ~FRAME_EDITED;
 
                 /* Save ESP */
                 TrapFrame->TempEsp = Esp;
@@ -644,20 +624,20 @@ NTAPI
 KiSsFromTrapFrame(IN PKTRAP_FRAME TrapFrame)
 {
     /* If this was V86 Mode */
-    if (TrapFrame->Eflags & X86_EFLAGS_VM)
+    if (TrapFrame->EFlags & X86_EFLAGS_VM)
     {
         /* Just return it */
-        return TrapFrame->Ss;
+        return TrapFrame->HardwareSegSs;
     }
-    else if (TrapFrame->Cs & 1)
+    else if (TrapFrame->SegCs & MODE_MASK)
     {
         /* Usermode, return the User SS */
-        return TrapFrame->Ss | 3;
+        return TrapFrame->HardwareSegSs | RPL_MASK;
     }
     else
     {
         /* Kernel mode */
-        return KERNEL_DS;
+        return KGDT_R0_DATA;
     }
 }
 
@@ -670,61 +650,64 @@ KiSsToTrapFrame(IN PKTRAP_FRAME TrapFrame,
     Ss &= 0xFFFF;
 
     /* If this was V86 Mode */
-    if (TrapFrame->Eflags & X86_EFLAGS_VM)
+    if (TrapFrame->EFlags & X86_EFLAGS_VM)
     {
         /* Just write it */
-        TrapFrame->Ss = Ss;
+        TrapFrame->HardwareSegSs = Ss;
     }
-    else if (TrapFrame->Cs & 1)
+    else if (TrapFrame->SegCs & MODE_MASK)
     {
         /* Usermode, save the User SS */
-        TrapFrame->Ss = Ss | 3;
+        TrapFrame->HardwareSegSs = Ss | RPL_MASK;
     }
 }
 
-BOOLEAN
+VOID
 NTAPI
 KeContextToTrapFrame(IN PCONTEXT Context,
                      IN OUT PKEXCEPTION_FRAME ExceptionFrame,
                      IN OUT PKTRAP_FRAME TrapFrame,
+                     IN ULONG ContextFlags,
                      IN KPROCESSOR_MODE PreviousMode)
 {
+    PFX_SAVE_AREA FxSaveArea;
+    //ULONG i; Future Use
     BOOLEAN V86Switch = FALSE;
 
     /* Start with the basic Registers */
-    if ((Context->ContextFlags & CONTEXT_CONTROL) == CONTEXT_CONTROL)
+    if ((ContextFlags & CONTEXT_CONTROL) == CONTEXT_CONTROL)
     {
         /* Check if we went through a V86 switch */
         if ((Context->EFlags & X86_EFLAGS_VM) !=
-            (TrapFrame->Eflags & X86_EFLAGS_VM))
+            (TrapFrame->EFlags & X86_EFLAGS_VM))
         {
             /* We did, remember this for later */
             V86Switch = TRUE;
         }
 
         /* Copy EFLAGS. FIXME: Needs to be sanitized */
-        TrapFrame->Eflags = Context->EFlags;
+        TrapFrame->EFlags = Context->EFlags;
 
         /* Copy EBP and EIP */
         TrapFrame->Ebp = Context->Ebp;
         TrapFrame->Eip = Context->Eip;
 
         /* Check if we were in V86 Mode */
-        if (TrapFrame->Eflags & X86_EFLAGS_VM)
+        if (TrapFrame->EFlags & X86_EFLAGS_VM)
         {
             /* Simply copy the CS value */
-            TrapFrame->Cs = Context->SegCs;
+            TrapFrame->SegCs = Context->SegCs;
         }
         else
         {
             /* We weren't in V86, so sanitize the CS (FIXME!) */
-            TrapFrame->Cs = Context->SegCs;
+            TrapFrame->SegCs = Context->SegCs;
 
             /* Don't let it under 8, that's invalid */
-            if ((PreviousMode !=KernelMode) && (TrapFrame->Cs < 8))
+            if ((PreviousMode != KernelMode) && (TrapFrame->SegCs < 8))
             {
                 /* Force it to User CS */
-                TrapFrame->Cs = USER_CS;
+                TrapFrame->SegCs = (KGDT_R3_CODE | RPL_MASK);
             }
         }
 
@@ -739,7 +722,7 @@ KeContextToTrapFrame(IN PCONTEXT Context,
     }
 
     /* Process the Integer Registers */
-    if ((Context->ContextFlags & CONTEXT_INTEGER) == CONTEXT_INTEGER)
+    if ((ContextFlags & CONTEXT_INTEGER) == CONTEXT_INTEGER)
     {
         TrapFrame->Eax = Context->Eax;
         TrapFrame->Ebx = Context->Ebx;
@@ -750,48 +733,82 @@ KeContextToTrapFrame(IN PCONTEXT Context,
     }
 
     /* Process the Context Segments */
-    if ((Context->ContextFlags & CONTEXT_SEGMENTS) == CONTEXT_SEGMENTS)
+    if ((ContextFlags & CONTEXT_SEGMENTS) == CONTEXT_SEGMENTS)
     {
         /* Check if we were in V86 Mode */
-        if (TrapFrame->Eflags & X86_EFLAGS_VM)
+        if (TrapFrame->EFlags & X86_EFLAGS_VM)
         {
             /* Copy the V86 Segments directlry */
-            TrapFrame->V86_Ds = Context->SegDs;
-            TrapFrame->V86_Es = Context->SegEs;
-            TrapFrame->V86_Fs = Context->SegFs;
-            TrapFrame->V86_Gs = Context->SegGs;
+            TrapFrame->V86Ds = Context->SegDs;
+            TrapFrame->V86Es = Context->SegEs;
+            TrapFrame->V86Fs = Context->SegFs;
+            TrapFrame->V86Gs = Context->SegGs;
         }
-        else if (!(TrapFrame->Cs & 1))
+        else if (!(TrapFrame->SegCs & MODE_MASK))
         {
-            /* For user mode, write the values directly */
-            TrapFrame->Ds = USER_DS;
-            TrapFrame->Es = USER_DS;
-            TrapFrame->Fs = Context->SegFs;
-            TrapFrame->Gs = 0;
+            /* For kernel mode, write the standard values */
+            TrapFrame->SegDs = KGDT_R3_DATA | RPL_MASK;
+            TrapFrame->SegEs = KGDT_R3_DATA | RPL_MASK;
+            TrapFrame->SegFs = Context->SegFs;
+            TrapFrame->SegGs = 0;
         }
         else
         {
-            /* For kernel-mode, return the values */
-            TrapFrame->Ds = Context->SegDs;
-            TrapFrame->Es = Context->SegEs;
-            TrapFrame->Fs = Context->SegFs;
+            /* For user mode, return the values directlry */
+            TrapFrame->SegDs = Context->SegDs;
+            TrapFrame->SegEs = Context->SegEs;
+            TrapFrame->SegFs = Context->SegFs;
 
             /* Handle GS specially */
-            if (TrapFrame->Cs == USER_CS)
+            if (TrapFrame->SegCs == (KGDT_R3_CODE | RPL_MASK))
             {
                 /* Don't use it, if user */
-                TrapFrame->Gs = 0;
+                TrapFrame->SegGs = 0;
             }
             else
             {
                 /* Copy it if kernel */
-                TrapFrame->Gs = Context->SegGs;
+                TrapFrame->SegGs = Context->SegGs;
             }
         }
     }
 
+    /* Handle the extended registers */
+    if (((ContextFlags & CONTEXT_EXTENDED_REGISTERS) ==
+        CONTEXT_EXTENDED_REGISTERS) &&
+        ((TrapFrame->SegCs & MODE_MASK) == UserMode))
+    {
+        /* Get the FX Area */
+        FxSaveArea = (PFX_SAVE_AREA)(TrapFrame + 1);
+
+        /* Check if NPX is present */
+        if (KeI386NpxPresent)
+        {
+            /* Future use */
+        }
+    }
+
+    /* Handle the floating point state */
+    if (((ContextFlags & CONTEXT_FLOATING_POINT) ==
+        CONTEXT_FLOATING_POINT) &&
+        ((TrapFrame->SegCs & MODE_MASK) == UserMode))
+    {
+        /* Get the FX Area */
+        FxSaveArea = (PFX_SAVE_AREA)(TrapFrame + 1);
+
+        /* Check if NPX is present */
+        if (KeI386NpxPresent)
+        {
+            /* Future use */
+        }
+        else
+        {
+            /* Future use */
+        }
+    }
+
     /* Handle the Debug Registers */
-    if ((Context->ContextFlags & CONTEXT_DEBUG_REGISTERS) == CONTEXT_DEBUG_REGISTERS)
+    if ((ContextFlags & CONTEXT_DEBUG_REGISTERS) == CONTEXT_DEBUG_REGISTERS)
     {
         /* FIXME: All these should be sanitized */
         TrapFrame->Dr0 = Context->Dr0;
@@ -805,12 +822,13 @@ KeContextToTrapFrame(IN PCONTEXT Context,
         if (PreviousMode != KernelMode)
         {
             /* Set the Debug Flag */
-            KeGetCurrentThread()->DebugActive = (Context->Dr7 & DR7_ACTIVE);
+            KeGetCurrentThread()->DispatcherHeader.DebugActive =
+                (Context->Dr7 & DR7_ACTIVE);
         }
     }
 
     /* Handle FPU and Extended Registers */
-    return KiContextToFxSaveArea((PFX_SAVE_AREA)(TrapFrame + 1), Context);
+    KiContextToFxSaveArea((PFX_SAVE_AREA)(TrapFrame + 1), Context);
 }
 
 VOID
@@ -819,25 +837,27 @@ KeTrapFrameToContext(IN PKTRAP_FRAME TrapFrame,
                      IN PKEXCEPTION_FRAME ExceptionFrame,
                      IN OUT PCONTEXT Context)
 {
+    PFX_SAVE_AREA FxSaveArea = NULL;
+
     /* Start with the Control flags */
     if ((Context->ContextFlags & CONTEXT_CONTROL) == CONTEXT_CONTROL)
     {
         /* EBP, EIP and EFLAGS */
         Context->Ebp = TrapFrame->Ebp;
         Context->Eip = TrapFrame->Eip;
-        Context->EFlags = TrapFrame->Eflags;
+        Context->EFlags = TrapFrame->EFlags;
 
         /* Return the correct CS */
-        if (!(TrapFrame->Cs & FRAME_EDITED) &&
-            !(TrapFrame->Eflags & X86_EFLAGS_VM))
+        if (!(TrapFrame->SegCs & FRAME_EDITED) &&
+            !(TrapFrame->EFlags & X86_EFLAGS_VM))
         {
             /* Get it from the Temp location */
-            Context->SegCs = TrapFrame->TempCs & 0xFFFF;
+            Context->SegCs = TrapFrame->TempSegCs & 0xFFFF;
         }
         else
         {
             /* Return it directly */
-            Context->SegCs = TrapFrame->Cs & 0xFFFF;
+            Context->SegCs = TrapFrame->SegCs & 0xFFFF;
         }
 
         /* Get the Ss and ESP */
@@ -849,31 +869,31 @@ KeTrapFrameToContext(IN PKTRAP_FRAME TrapFrame,
     if ((Context->ContextFlags & CONTEXT_SEGMENTS) == CONTEXT_SEGMENTS)
     {
         /* Do V86 Mode first */
-        if (TrapFrame->Eflags & X86_EFLAGS_VM)
+        if (TrapFrame->EFlags & X86_EFLAGS_VM)
         {
             /* Return from the V86 location */
-            Context->SegGs = TrapFrame->V86_Gs & 0xFFFF;
-            Context->SegFs = TrapFrame->V86_Fs & 0xFFFF;
-            Context->SegEs = TrapFrame->V86_Es & 0xFFFF;
-            Context->SegDs = TrapFrame->V86_Ds & 0xFFFF;
+            Context->SegGs = TrapFrame->V86Gs & 0xFFFF;
+            Context->SegFs = TrapFrame->V86Fs & 0xFFFF;
+            Context->SegEs = TrapFrame->V86Es & 0xFFFF;
+            Context->SegDs = TrapFrame->V86Ds & 0xFFFF;
         }
         else
         {
             /* Check if this was a Kernel Trap */
-            if (TrapFrame->Cs == KERNEL_CS)
+            if (TrapFrame->SegCs == KGDT_R0_CODE)
             {
                 /* Set valid selectors */
-                TrapFrame->Gs = 0;
-                TrapFrame->Fs = PCR_SELECTOR;
-                TrapFrame->Es = USER_DS;
-                TrapFrame->Ds = USER_DS;
+                TrapFrame->SegGs = 0;
+                TrapFrame->SegFs = KGDT_R0_PCR;
+                TrapFrame->SegEs = KGDT_R3_DATA | RPL_MASK;
+                TrapFrame->SegDs = KGDT_R3_DATA | RPL_MASK;
             }
 
             /* Return the segments */
-            Context->SegGs = TrapFrame->Gs & 0xFFFF;
-            Context->SegFs = TrapFrame->Fs & 0xFFFF;
-            Context->SegEs = TrapFrame->Es & 0xFFFF;
-            Context->SegDs = TrapFrame->Ds & 0xFFFF;
+            Context->SegGs = TrapFrame->SegGs & 0xFFFF;
+            Context->SegFs = TrapFrame->SegFs & 0xFFFF;
+            Context->SegEs = TrapFrame->SegEs & 0xFFFF;
+            Context->SegDs = TrapFrame->SegDs & 0xFFFF;
         }
     }
 
@@ -889,43 +909,92 @@ KeTrapFrameToContext(IN PKTRAP_FRAME TrapFrame,
         Context->Edi = TrapFrame->Edi;
     }
 
-   if ((Context->ContextFlags & CONTEXT_DEBUG_REGISTERS) == CONTEXT_DEBUG_REGISTERS)
-   {
-       /*
-        * FIXME: Implement this case
-        */
-       Context->ContextFlags &= (~CONTEXT_DEBUG_REGISTERS) | CONTEXT_i386;
-     }
-   if ((Context->ContextFlags & CONTEXT_FLOATING_POINT) == CONTEXT_FLOATING_POINT)
-   {
-       /*
-        * FIXME: Implement this case
-        *
-        * I think this should only be filled for FPU exceptions, otherwise I
-         * would not know where to get it from as it can be the current state
-        * of the FPU or already saved in the thread's FPU save area.
-        *  -blight
-        */
-       Context->ContextFlags &= (~CONTEXT_FLOATING_POINT) | CONTEXT_i386;
-     }
-#if 0
-   if ((Context->ContextFlags & CONTEXT_EXTENDED_REGISTERS) == CONTEXT_EXTENDED_REGISTERS)
-   {
-       /*
-        * FIXME: Investigate this
-        *
-        * This is the XMM state (first 512 bytes of FXSAVE_FORMAT/FX_SAVE_AREA)
-        * This should only be filled in case of a SIMD exception I think, so
-        * this is not the right place (like for FPU the state could already be
-        * saved in the thread's FX_SAVE_AREA or still be in the CPU)
-        *  -blight
-        */
-        Context->ContextFlags &= ~CONTEXT_EXTENDED_REGISTERS;
-     }
-#endif
+    /* Handle extended registers */
+    if (((Context->ContextFlags & CONTEXT_EXTENDED_REGISTERS) ==
+        CONTEXT_EXTENDED_REGISTERS) &&
+        ((TrapFrame->SegCs & MODE_MASK) == UserMode))
+    {
+        /* Get the FX Save Area */
+        FxSaveArea = (PFX_SAVE_AREA)(TrapFrame + 1);
+
+        /* Make sure NPX is present */
+        if (KeI386NpxPresent)
+        {
+            /* Future use */
+        }
+
+        /* Old code */
+        FxSaveArea = KiGetFpuState(KeGetCurrentThread());
+        if (FxSaveArea != NULL)
+        {
+            memcpy(Context->ExtendedRegisters, &FxSaveArea->U.FxArea,
+                   min(sizeof (Context->ExtendedRegisters), sizeof (FxSaveArea->U.FxArea)) );
+        }
+        else
+        {
+            Context->ContextFlags &= (~CONTEXT_EXTENDED_REGISTERS) | CONTEXT_i386;
+        }
+    }
+
+    /* Handle Floating Point */
+    if (((Context->ContextFlags & CONTEXT_FLOATING_POINT) ==
+        CONTEXT_FLOATING_POINT) &&
+        ((TrapFrame->SegCs & MODE_MASK) == UserMode))
+    {
+        /* Get the FX Save Area */
+        FxSaveArea = (PFX_SAVE_AREA)(TrapFrame + 1);
+
+        /* Make sure we have an NPX */
+        if (KeI386NpxPresent)
+        {
+            /* Future use */
+        }
+        else
+        {
+            /* Future Use */
+        }
+
+        /* Old code */
+        FxSaveArea = KiGetFpuState(KeGetCurrentThread());
+        if (FxSaveArea != NULL)
+        {
+            KiFxSaveAreaToFloatingSaveArea(&Context->FloatSave, FxSaveArea);
+        }
+        else
+        {
+            Context->ContextFlags &= (~CONTEXT_FLOATING_POINT) | CONTEXT_i386;
+        }
+    }
+
+    /* Handle debug registers */
+    if ((Context->ContextFlags & CONTEXT_DEBUG_REGISTERS) ==
+        CONTEXT_DEBUG_REGISTERS)
+    {
+        /* Copy the debug registers */
+        Context->Dr0 = TrapFrame->Dr0;
+        Context->Dr1 = TrapFrame->Dr1;
+        Context->Dr2 = TrapFrame->Dr2;
+        Context->Dr3 = TrapFrame->Dr3;
+        Context->Dr6 = TrapFrame->Dr6;
+
+        /* For user-mode, only set DR7 if a debugger is active */
+        if (((TrapFrame->SegCs & MODE_MASK) ||
+            (TrapFrame->EFlags & EFLAGS_V86_MASK)) &&
+            (KeGetCurrentThread()->DispatcherHeader.DebugActive))
+        {
+            /* Copy it over */
+            Context->Dr7 = TrapFrame->Dr7;
+        }
+        else
+        {
+            /* Clear it */
+            Context->Dr7 = 0;
+        }
+    }
 }
 
 VOID
+NTAPI
 KeDumpStackFrames(PULONG Frame)
 {
        PULONG StackBase, StackEnd;
@@ -986,7 +1055,7 @@ KeRosDumpStackFrames ( PULONG Frame, ULONG FrameCount )
                if ( !Frame )
                {
 #if defined __GNUC__
-                       __asm__("mov %%ebp, %%ebx" : "=b" (Frame) : );
+                       __asm__("mov %%ebp, %0" : "=r" (Frame) : );
 #elif defined(_MSC_VER)
                        __asm mov [Frame], ebp
 #endif
@@ -1040,7 +1109,7 @@ KeRosGetStackFrames ( PULONG Frames, ULONG FrameCount )
        _SEH_TRY
        {
 #if defined __GNUC__
-               __asm__("mov %%ebp, %%ebx" : "=b" (Frame) : );
+               __asm__("mov %%ebp, %0" : "=r" (Frame) : );
 #elif defined(_MSC_VER)
                __asm mov [Frame], ebp
 #endif
@@ -1075,81 +1144,24 @@ KeRosGetStackFrames ( PULONG Frames, ULONG FrameCount )
        return Count;
 }
 
-static void
-set_system_call_gate(unsigned int sel, unsigned int func)
-{
-   DPRINT("sel %x %d\n",sel,sel);
-   KiIdt[sel].a = (((int)func)&0xffff) +
-     (KERNEL_CS << 16);
-   KiIdt[sel].b = 0xef00 + (((int)func)&0xffff0000);
-   DPRINT("idt[sel].b %x\n",KiIdt[sel].b);
-}
-
-static void set_interrupt_gate(unsigned int sel, unsigned int func)
-{
-   DPRINT("set_interrupt_gate(sel %d, func %x)\n",sel,func);
-   KiIdt[sel].a = (((int)func)&0xffff) +
-     (KERNEL_CS << 16);
-   KiIdt[sel].b = 0x8e00 + (((int)func)&0xffff0000);
-}
-
-static void set_trap_gate(unsigned int sel, unsigned int func, unsigned int dpl)
-{
-   DPRINT("set_trap_gate(sel %d, func %x, dpl %d)\n",sel, func, dpl);
-   ASSERT(dpl <= 3);
-   KiIdt[sel].a = (((int)func)&0xffff) +
-     (KERNEL_CS << 16);
-   KiIdt[sel].b = 0x8f00 + (dpl << 13) + (((int)func)&0xffff0000);
-}
-
-static void
-set_task_gate(unsigned int sel, unsigned task_sel)
-{
-  KiIdt[sel].a = task_sel << 16;
-  KiIdt[sel].b = 0x8500;
-}
-
-VOID INIT_FUNCTION
+VOID
+INIT_FUNCTION
+NTAPI
 KeInitExceptions(VOID)
-/*
- * FUNCTION: Initalize CPU exception handling
- */
 {
-   int i;
-
-   DPRINT("KeInitExceptions()\n");
+    ULONG i;
+    USHORT FlippedSelector;
 
-   /*
-    * Set up the other gates
-    */
-   set_trap_gate(0, (ULONG)KiTrap0, 0);
-   set_trap_gate(1, (ULONG)KiTrap1, 0);
-   set_trap_gate(2, (ULONG)KiTrap2, 0);
-   set_trap_gate(3, (ULONG)KiTrap3, 3);
-   set_trap_gate(4, (ULONG)KiTrap4, 0);
-   set_trap_gate(5, (ULONG)KiTrap5, 0);
-   set_trap_gate(6, (ULONG)KiTrap6, 0);
-   set_trap_gate(7, (ULONG)KiTrap7, 0);
-   set_task_gate(8, TRAP_TSS_SELECTOR);
-   set_trap_gate(9, (ULONG)KiTrap9, 0);
-   set_trap_gate(10, (ULONG)KiTrap10, 0);
-   set_trap_gate(11, (ULONG)KiTrap11, 0);
-   set_trap_gate(12, (ULONG)KiTrap12, 0);
-   set_trap_gate(13, (ULONG)KiTrap13, 0);
-   set_interrupt_gate(14, (ULONG)KiTrap14);
-   set_trap_gate(15, (ULONG)KiTrap15, 0);
-   set_trap_gate(16, (ULONG)KiTrap16, 0);
-   set_trap_gate(17, (ULONG)KiTrap17, 0);
-   set_trap_gate(18, (ULONG)KiTrap18, 0);
-   set_trap_gate(19, (ULONG)KiTrap19, 0);
-
-   for (i = 20; i < 256; i++)
-     {
-        set_trap_gate(i,(int)KiTrapUnknown, 0);
-     }
+    /* Loop the IDT */
+    for (i = 0; i <= MAXIMUM_IDTVECTOR; i ++)
+    {
+        /* Save the current Selector */
+        FlippedSelector = KiIdt[i].Selector;
 
-   set_system_call_gate(0x2d,(int)KiDebugService);
-   set_system_call_gate(0x2e,(int)KiSystemService);
+        /* Flip Selector and Extended Offset */
+        KiIdt[i].Selector = KiIdt[i].ExtendedOffset;
+        KiIdt[i].ExtendedOffset = FlippedSelector;
+    }
 }
 
 VOID
@@ -1178,6 +1190,7 @@ KiDispatchException(PEXCEPTION_RECORD ExceptionRecord,
     {
         /* Add the FPU Flag */
         Context.ContextFlags |= CONTEXT_FLOATING_POINT;
+        if (KeI386FxsrPresent) Context.ContextFlags |= CONTEXT_EXTENDED_REGISTERS;
     }
 
     /* Get a Context */
@@ -1238,7 +1251,7 @@ KiDispatchException(PEXCEPTION_RECORD ExceptionRecord,
                                                &Context,
                                                TrapFrame,
                                                TRUE,
-                                               FALSE);
+                                               TRUE);
 
             /* Exit if we're continuing */
             if (Action == kdContinue) goto Handled;
@@ -1255,7 +1268,7 @@ KiDispatchException(PEXCEPTION_RECORD ExceptionRecord,
 
                 /* Probe stack and copy Context */
                 ProbeForWrite((PVOID)Stack, Size, sizeof(ULONG));
-                RtlMoveMemory((PVOID)Stack, &Context, sizeof(CONTEXT));
+                RtlCopyMemory((PVOID)Stack, &Context, sizeof(CONTEXT));
 
                 /* Align exception record size and get stack pointer */
                 Size = (sizeof(EXCEPTION_RECORD) - 
@@ -1268,7 +1281,7 @@ KiDispatchException(PEXCEPTION_RECORD ExceptionRecord,
                 ProbeForWrite((PVOID)(NewStack - 2 * sizeof(ULONG_PTR)),
                               Size +  2 * sizeof(ULONG_PTR),
                               sizeof(ULONG));
-                RtlMoveMemory((PVOID)NewStack, ExceptionRecord, Size);
+                RtlCopyMemory((PVOID)NewStack, ExceptionRecord, Size);
 
                 /* Now write the two params for the user-mode dispatcher */
                 *(PULONG_PTR)(NewStack - 1 * sizeof(ULONG_PTR)) = Stack;
@@ -1307,27 +1320,42 @@ KiDispatchException(PEXCEPTION_RECORD ExceptionRecord,
 
 Handled:
     /* Convert the context back into Trap/Exception Frames */
-    KeContextToTrapFrame(&Context, NULL, TrapFrame, PreviousMode);
+    KeContextToTrapFrame(&Context,
+                         NULL,
+                         TrapFrame,
+                         Context.ContextFlags,
+                         PreviousMode);
     return;
 }
 
 /*
  * @implemented
  */
-NTSTATUS STDCALL
+NTSTATUS
+NTAPI
 KeRaiseUserException(IN NTSTATUS ExceptionCode)
 {
    ULONG OldEip;
    PKTHREAD Thread = KeGetCurrentThread();
 
-    _SEH_TRY {
+   /* Make sure we can access the TEB */
+    _SEH_TRY
+    {
         Thread->Teb->ExceptionCode = ExceptionCode;
-    } _SEH_HANDLE {
+    }
+    _SEH_HANDLE
+    {
         return(ExceptionCode);
-    } _SEH_END;
+    }
+    _SEH_END;
+
+    /* Get the old EIP */
+    OldEip = Thread->TrapFrame->Eip;
+
+    /* Change it to the user-mode dispatcher */
+    Thread->TrapFrame->Eip = (ULONG_PTR)KeRaiseUserExceptionDispatcher;
 
-   OldEip = Thread->TrapFrame->Eip;
-   Thread->TrapFrame->Eip = (ULONG_PTR)KeRaiseUserExceptionDispatcher;
-   return((NTSTATUS)OldEip);
+    /* Return the old EIP */
+    return((NTSTATUS)OldEip);
 }