Some work-in-progress improvements and rethought of system-level code...notable impro...
authorAlex Ionescu <aionescu@gmail.com>
Tue, 13 Sep 2005 19:33:49 +0000 (19:33 +0000)
committerAlex Ionescu <aionescu@gmail.com>
Tue, 13 Sep 2005 19:33:49 +0000 (19:33 +0000)
svn path=/trunk/; revision=17838

18 files changed:
reactos/lib/ntdll/ldr/startup.c
reactos/lib/rtl/i386/exception.c
reactos/ntoskrnl/ex/init.c
reactos/ntoskrnl/include/internal/i386/ke.h
reactos/ntoskrnl/include/internal/ke.h
reactos/ntoskrnl/kd/wrappers/gdbstub.c
reactos/ntoskrnl/kdbg/kdb.c
reactos/ntoskrnl/kdbg/kdb_cli.c
reactos/ntoskrnl/ke/apc.c
reactos/ntoskrnl/ke/exception.c
reactos/ntoskrnl/ke/i386/ctxswitch.S
reactos/ntoskrnl/ke/i386/exp.c
reactos/ntoskrnl/ke/i386/fpu.c
reactos/ntoskrnl/ke/i386/syscall.S
reactos/ntoskrnl/ke/i386/thread.c
reactos/ntoskrnl/ke/i386/trap.s
reactos/ntoskrnl/mm/i386/pfault.c
reactos/ntoskrnl/ps/debug.c

index 8e8c7c2..02347bc 100644 (file)
@@ -256,13 +256,13 @@ LdrpInit(PCONTEXT Context,
    SYSTEM_BASIC_INFORMATION SystemInformation;
    NTSTATUS Status;
 
-   DPRINT("LdrpInit()\n");
+   DPRINT1("LdrpInit()\n");
    if (NtCurrentPeb()->Ldr == NULL || NtCurrentPeb()->Ldr->Initialized == FALSE)
      {
        Peb = (PPEB)(PEB_BASE);
-       DPRINT("Peb %x\n", Peb);
+       DPRINT1("Peb %x\n", Peb);
        ImageBase = Peb->ImageBaseAddress;
-       DPRINT("ImageBase %x\n", ImageBase);
+       DPRINT1("ImageBase %x\n", ImageBase);
        if (ImageBase <= (PVOID)0x1000)
          {
            DPRINT("ImageBase is null\n");
@@ -271,7 +271,7 @@ LdrpInit(PCONTEXT Context,
 
        /*  If MZ header exists  */
        PEDosHeader = (PIMAGE_DOS_HEADER) ImageBase;
-       DPRINT("PEDosHeader %x\n", PEDosHeader);
+       DPRINT1("PEDosHeader %x\n", PEDosHeader);
 
        if (PEDosHeader->e_magic != IMAGE_DOS_SIGNATURE ||
            PEDosHeader->e_lfanew == 0L ||
@@ -294,10 +294,12 @@ LdrpInit(PCONTEXT Context,
        NTHeaders = (PIMAGE_NT_HEADERS)((ULONG_PTR)ImageBase + PEDosHeader->e_lfanew);
 
        /* Get number of processors */
+       DPRINT1("Here\n");
        Status = ZwQuerySystemInformation(SystemBasicInformation,
                                         &SystemInformation,
                                         sizeof(SYSTEM_BASIC_INFORMATION),
                                         NULL);
+        DPRINT1("Here2\n");
        if (!NT_SUCCESS(Status))
          {
           ZwTerminateProcess(NtCurrentProcess(), Status);
index c0d8be1..c563d53 100644 (file)
@@ -165,7 +165,7 @@ RtlDispatchException(IN PEXCEPTION_RECORD ExceptionRecord,
     }
 
     /* Unhandled, return false */
-    DPRINT1("FALSE:(\n");
+    DPRINT1("FALSE\n");
     return FALSE;
 }
 
index fdf708d..ccd545a 100644 (file)
@@ -241,7 +241,6 @@ ExecuteRuntimeAsserts(VOID)
     ASSERT(FIELD_OFFSET(KPROCESS, DirectoryTableBase) == KPROCESS_DIRECTORY_TABLE_BASE);
     ASSERT(FIELD_OFFSET(KPROCESS, IopmOffset) == KPROCESS_IOPM_OFFSET);
     ASSERT(FIELD_OFFSET(KPROCESS, LdtDescriptor) == KPROCESS_LDT_DESCRIPTOR0);
-    ASSERT(FIELD_OFFSET(KTRAP_FRAME, Reserved9) == KTRAP_FRAME_RESERVED9);
     ASSERT(FIELD_OFFSET(KV86M_TRAP_FRAME, SavedExceptionStack) == TF_SAVED_EXCEPTION_STACK);
     ASSERT(FIELD_OFFSET(KV86M_TRAP_FRAME, regs) == TF_REGS);
     ASSERT(FIELD_OFFSET(KV86M_TRAP_FRAME, orig_ebp) == TF_ORIG_EBP);
index 508a55b..7d16153 100644 (file)
 #define X86_EXT_FEATURE_SSE3    0x00000001 /* SSE3 extension present */
 #define X86_EXT_FEATURE_3DNOW   0x40000000 /* 3DNOW! extension present */
 
+#define DR7_ACTIVE              0x00000055  /* If any of these bits are set, a Dr is active */
+
 /* Possible values for KTHREAD's NpxState */
 #define NPX_STATE_INVALID   0x01
 #define NPX_STATE_VALID     0x02
 #define NPX_STATE_DIRTY     0x04
 
+#define FRAME_EDITED        0xFFF8
+
 #ifndef __ASM__
 
 typedef struct _KIRQ_TRAPFRAME
index 43eeccf..a49b938 100644 (file)
@@ -287,7 +287,10 @@ VOID inline FASTCALL KiSatisifyMultipleObjectWaits(PKWAIT_BLOCK WaitBlock);
 VOID FASTCALL KiWaitTest(PDISPATCHER_HEADER Object, KPRIORITY Increment);
 
 PULONG KeGetStackTopThread(struct _ETHREAD* Thread);
-BOOLEAN STDCALL KeContextToTrapFrame(PCONTEXT Context, PKEXCEPTION_FRAME ExeptionFrame, PKTRAP_FRAME TrapFrame);
+BOOLEAN STDCALL KeContextToTrapFrame(PCONTEXT Context,
+                                     PKEXCEPTION_FRAME ExeptionFrame,
+                                     PKTRAP_FRAME TrapFrame,
+                                     KPROCESSOR_MODE PreviousMode);
 VOID STDCALL KiDeliverApc(KPROCESSOR_MODE PreviousMode,
                   PVOID Reserved,
                   PKTRAP_FRAME TrapFrame);
@@ -368,8 +371,11 @@ KiDispatchException(PEXCEPTION_RECORD ExceptionRecord,
             PKTRAP_FRAME Tf,
                    KPROCESSOR_MODE PreviousMode,
                    BOOLEAN SearchFrames);
-VOID KeTrapFrameToContext(PKTRAP_FRAME TrapFrame,
-                         PCONTEXT Context);
+VOID
+NTAPI
+KeTrapFrameToContext(IN PKTRAP_FRAME TrapFrame,
+                     IN PKEXCEPTION_FRAME ExceptionFrame,
+                     IN OUT PCONTEXT Context);
 VOID
 KeApplicationProcessorInit(VOID);
 VOID
index a5b6c30..8e2142a 100644 (file)
@@ -1321,7 +1321,7 @@ KdpGdbEnterDebuggerException(PEXCEPTION_RECORD ExceptionRecord,
 #error Unknown compiler for inline assembler
 #endif
 
-                KeContextToTrapFrame(Context, NULL, TrapFrame);
+                KeContextToTrapFrame(Context, NULL, TrapFrame, KernelMode);
                 return ((SigVal == 5) ? (kdContinue) : (kdHandleException));
                 break;
               }
@@ -1430,11 +1430,11 @@ GspBreakIn(PKINTERRUPT Interrupt,
 
   TrapFrame = PsGetCurrentThread()->Tcb.TrapFrame;
 
-  KeTrapFrameToContext (TrapFrame, &Context);
+  KeTrapFrameToContext (TrapFrame, NULL, &Context);
 
   KdpGdbEnterDebuggerException (NULL, &Context, TrapFrame);
 
-  KeContextToTrapFrame (&Context, NULL, TrapFrame);
+  KeContextToTrapFrame (&Context, NULL, TrapFrame, KernelMode);
 
   KeLowerIrql (OldIrql);
 
index fd67c4e..f7d1456 100644 (file)
 
 /* TYPES *********************************************************************/
 
-/* FIXME: NDK headers */
-#define TempEsp TempEip
-#define TempSegSs TempCs
-
 /* DEFINES *******************************************************************/
 
 #define KDB_STACK_SIZE                   (4096*3)
@@ -108,6 +104,24 @@ STATIC CONST PCHAR ExceptionNrToString[] =
    "SIMD Fault"
 };
 
+ULONG
+NTAPI
+KiSsFromTrapFrame(IN PKTRAP_FRAME TrapFrame);
+
+ULONG
+NTAPI
+KiEspFromTrapFrame(IN PKTRAP_FRAME TrapFrame);
+
+VOID
+NTAPI
+KiSsToTrapFrame(IN PKTRAP_FRAME TrapFrame,
+                IN ULONG Ss);
+
+VOID
+NTAPI
+KiEspToTrapFrame(IN PKTRAP_FRAME TrapFrame,
+                 IN ULONG Esp);
+
 /* FUNCTIONS *****************************************************************/
 
 STATIC VOID
@@ -124,22 +138,11 @@ KdbpTrapFrameToKdbTrapFrame(PKTRAP_FRAME TrapFrame, PKDB_KTRAP_FRAME KdbTrapFram
       "movl %%cr4, %3"    "\n\t"
       : "=r"(KdbTrapFrame->Cr0), "=r"(KdbTrapFrame->Cr2),
         "=r"(KdbTrapFrame->Cr3), "=r"(KdbTrapFrame->Cr4));
-   
-   if (TrapFrame->PreviousMode == KernelMode)
-   {
-      /* If the trapframe is a kmode one use the temp ss:esp */
-      KdbTrapFrame->Tf.Esp = (ULONG)TrapFrame->TempEsp;
-      KdbTrapFrame->Tf.Ss = (USHORT)((ULONG)TrapFrame->TempSegSs & 0xFFFF);
-   }
-   else
-   {
-      /* Otherwise use ss:esp pushed by the CPU */
-      /* FIXME: maybe change all trapframes to always put ss:esp into tempss:tempesp so we
-       *        can handle umode and kmode the same way */
-      KdbTrapFrame->Tf.Esp = TrapFrame->Esp;
-      KdbTrapFrame->Tf.Ss = TrapFrame->Ss;
-   }
-   
+
+    KdbTrapFrame->Tf.Esp = KiEspFromTrapFrame(TrapFrame);
+    KdbTrapFrame->Tf.Ss = (USHORT)(KiSsFromTrapFrame(TrapFrame) & 0xFFFF);
+
+
    /* FIXME: copy v86 registers if TrapFrame is a V86 trapframe */
 }
 
@@ -151,20 +154,8 @@ KdbpKdbTrapFrameToTrapFrame(PKDB_KTRAP_FRAME KdbTrapFrame, PKTRAP_FRAME TrapFram
    
    /* FIXME: write cr0, cr2, cr3 and cr4 (not needed atm) */
    
-   if (TrapFrame->PreviousMode == KernelMode)
-   {
-      /* If the trapframe is a kmode one write to the temp ss:esp */
-      TrapFrame->TempEsp = (PVOID)KdbTrapFrame->Tf.Esp;
-      TrapFrame->TempSegSs = (PVOID)(((ULONG)TrapFrame->TempSegSs & ~0xffff) | KdbTrapFrame->Tf.Ss);
-   }
-   else
-   {
-      /* Otherwise write to ss:esp pushed by the CPU */
-      /* FIXME: maybe change all trap-epilogs to always put temp ss:esp into ss:esp so we
-       *        can handle umode and kmode the same way */
-      TrapFrame->Esp = KdbTrapFrame->Tf.Esp;
-      TrapFrame->Ss = KdbTrapFrame->Tf.Ss;
-   }
+    KiSsToTrapFrame(TrapFrame, KdbTrapFrame->Tf.Ss);
+    KiEspToTrapFrame(TrapFrame, KdbTrapFrame->Tf.Esp);
    
    /* FIXME: copy v86 registers if TrapFrame is a V86 trapframe */
 }
index 1e03341..ca1ebc9 100644 (file)
 
 /* DEFINES *******************************************************************/
 
-/* FIXME: NDK headers */
-#define TempEsp TempEip
-#define TempSegSs TempCs
-
 #define KEY_BS          8
 #define KEY_ESC         27
 #define KEY_DEL         127
index dd7b39f..3bee737 100644 (file)
@@ -812,7 +812,7 @@ KiInitializeUserApc(IN PKEXCEPTION_FRAME ExceptionFrame,
 
     /* Save the full context */
     Context.ContextFlags = CONTEXT_FULL | CONTEXT_DEBUG_REGISTERS;
-    KeTrapFrameToContext(TrapFrame, &Context);
+    KeTrapFrameToContext(TrapFrame, ExceptionFrame, &Context);
 
     /* Protect with SEH */
     _SEH_TRY
index 49ec4fc..872df72 100644 (file)
@@ -28,7 +28,7 @@ KiContinuePreviousModeUser(IN PCONTEXT Context,
     Context = &LocalContext;\r
 \r
     /* Convert the context into Exception/Trap Frames */\r
-    KeContextToTrapFrame(&LocalContext, ExceptionFrame, TrapFrame);\r
+    KeContextToTrapFrame(&LocalContext, ExceptionFrame, TrapFrame, UserMode);\r
 }\r
 \r
 NTSTATUS\r
@@ -62,7 +62,7 @@ KiContinue(IN PCONTEXT Context,
         else\r
         {\r
             /* Convert the context into Exception/Trap Frames */\r
-            KeContextToTrapFrame(Context, ExceptionFrame, TrapFrame);\r
+            KeContextToTrapFrame(Context, ExceptionFrame, TrapFrame, KernelMode);\r
         }\r
     }\r
     _SEH_HANDLE\r
@@ -142,7 +142,7 @@ KiRaiseException(PEXCEPTION_RECORD ExceptionRecord,
     if (NT_SUCCESS(Status))\r
     {\r
         /* Convert the context record */\r
-        KeContextToTrapFrame(Context, ExceptionFrame, TrapFrame);\r
+        KeContextToTrapFrame(Context, ExceptionFrame, TrapFrame, PreviousMode);\r
 \r
         /* Dispatch the exception */\r
         KiDispatchException(ExceptionRecord,\r
index 5fe5451..e3d6f01 100644 (file)
@@ -114,7 +114,7 @@ BadThread:
 .globl @KiSwapContextInternal@0
 @KiSwapContextInternal@0:
 #ifdef KDBG
-    jmp SaveTrapFrameForKDB
+    //jmp SaveTrapFrameForKDB
 SaveTrapFrameForKDB_Return:
 #endif
 
@@ -130,12 +130,14 @@ SaveTrapFrameForKDB_Return:
     /* Switching, disable interrupts now */
     cli
 
+    /* Save the initial stack in EAX */
+    mov eax, [edi+KTHREAD_INITIAL_STACK]
+
 #ifdef CONFIG_SMP
     /* Save FPU state if the thread has used it. */
     mov dword ptr [ebx+KPCR_NPX_THREAD], 0
     test byte ptr [edi+KTHREAD_NPX_STATE], NPX_STATE_DIRTY
     jz 3f
-    mov eax, [edi+KTHREAD_INITIAL_STACK]
     cmp dword ptr _FxsrSupport, 0
     je 1f
     fxsave [eax-SIZEOF_FX_SAVE_AREA]
@@ -149,8 +151,18 @@ SaveTrapFrameForKDB_Return:
     
     /* Save the stack pointer in this processors TSS */
     mov ebp, [ebx+KPCR_TSS]
+
+    /* Check if this isn't V86 Mode, so we can bias the Esp0 */
+    test dword ptr [eax - KTRAP_FRAME_SIZE + KTRAP_FRAME_EFLAGS], X86_EFLAGS_VM
+    jnz NoAdjust
+
+    /* Bias esp */
+    //sub dword ptr ss:[ebp+KTSS_ESP0], KTRAP_FRAME_V86_GS - KTRAP_FRAME_SS
+
+NoAdjust:
+    /* Push ESP0 Value */
     push ss:[ebp+KTSS_ESP0]
-    
+
     /* Check if address space switch is needed */
     mov eax, [esi+KTHREAD_APCSTATE_PROCESS]
     cmp eax, [edi+KTHREAD_APCSTATE_PROCESS]
index 1e2e3b9..04cec11 100644 (file)
 
 /*
  * FIXMES:
+ *  - Put back VEH.
  *  - Clean up file.
- *  - Add more exception frame support for non-i386 compatibility.
+ *  - 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.
- *  - Wrap Ki NTDLL callbacks in SEH.
  */
 
+VOID
+NTAPI
+Ki386AdjustEsp0(IN PKTRAP_FRAME TrapFrame);
+
 /* GLOBALS *****************************************************************/
 
 #define FLAG_IF (1<<9)
@@ -485,14 +489,14 @@ KiTrapHandler(PKTRAP_FRAME Tf, ULONG ExceptionNr)
    ASSERT(ExceptionNr != 14);
 
    /* Store the exception number in an unused field in the trap frame. */
-   Tf->DebugArgMark = (PVOID)ExceptionNr;
+   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 = (PVOID)cr2;
+   Tf->DebugPointer = cr2;
 
    /*
     * If this was a V86 mode exception then handle it specially
@@ -566,21 +570,172 @@ KiTrapHandler(PKTRAP_FRAME Tf, ULONG ExceptionNr)
     }
 }
 
+ULONG
+NTAPI
+KiEspFromTrapFrame(IN PKTRAP_FRAME TrapFrame)
+{
+    /* Check if this is user-mode or V86 */
+    if ((TrapFrame->Cs & 1) || (TrapFrame->Eflags & X86_EFLAGS_VM))
+    {
+        /* Return it directly */
+        return TrapFrame->Esp;
+    }
+    else
+    {
+        /* Edited frame */
+        if (!(TrapFrame->Cs & FRAME_EDITED))
+        {
+            /* Return edited value */
+            return TrapFrame->TempEsp;
+        }
+        else
+        {
+            /* Virgin frame, calculate */
+            return (ULONG)&TrapFrame->Esp;
+        }
+    }
+}
+
+VOID
+NTAPI
+KiEspToTrapFrame(IN PKTRAP_FRAME TrapFrame,
+                 IN ULONG Esp)
+{
+    ULONG Previous = KiEspFromTrapFrame(TrapFrame);
+
+    /* Check if this is user-mode or V86 */
+    if ((TrapFrame->Cs & 1) || (TrapFrame->Eflags & X86_EFLAGS_VM))
+    {
+        /* Write it directly */
+        TrapFrame->Esp = Esp;
+    }
+    else
+    {
+        /* Don't allow ESP to be lowered, this is illegal */
+        if (Esp < Previous)
+        {
+            //KeBugCheck(SET_OF_INVALID_CONTEXT);
+        }
+
+        /* Create an edit frame, check if it was alrady */
+        if (!(TrapFrame->Cs & FRAME_EDITED))
+        {
+            /* Update the value */
+            TrapFrame->TempEsp = Esp;
+        }
+        else
+        {
+            /* Check if ESP changed */
+            if (Previous != Esp)
+            {
+                /* Save CS */
+                TrapFrame->TempCs = TrapFrame->Cs;
+                TrapFrame->Cs &= ~FRAME_EDITED;
+
+                /* Save ESP */
+                TrapFrame->TempEsp = Esp;
+            }
+        }
+    }
+}
+
+ULONG
+NTAPI
+KiSsFromTrapFrame(IN PKTRAP_FRAME TrapFrame)
+{
+    /* If this was V86 Mode */
+    if (TrapFrame->Eflags & X86_EFLAGS_VM)
+    {
+        /* Just return it */
+        return TrapFrame->Ss;
+    }
+    else if (TrapFrame->Cs & 1)
+    {
+        /* Usermode, return the User SS */
+        return TrapFrame->Ss | 3;
+    }
+    else
+    {
+        /* Kernel mode */
+        return KERNEL_DS;
+    }
+}
+
+VOID
+NTAPI
+KiSsToTrapFrame(IN PKTRAP_FRAME TrapFrame,
+                IN ULONG Ss)
+{
+    /* Remove the high-bits */
+    Ss &= 0xFFFF;
+
+    /* If this was V86 Mode */
+    if (TrapFrame->Eflags & X86_EFLAGS_VM)
+    {
+        /* Just write it */
+        TrapFrame->Ss = Ss;
+    }
+    else if (TrapFrame->Cs & 1)
+    {
+        /* Usermode, save the User SS */
+        TrapFrame->Ss = Ss | 3;
+    }
+}
+
 BOOLEAN
-STDCALL
-KeContextToTrapFrame(PCONTEXT Context,
-                     PKEXCEPTION_FRAME ExceptionFrame,
-                     PKTRAP_FRAME TrapFrame)
+NTAPI
+KeContextToTrapFrame(IN PCONTEXT Context,
+                     IN OUT PKEXCEPTION_FRAME ExceptionFrame,
+                     IN OUT PKTRAP_FRAME TrapFrame,
+                     IN KPROCESSOR_MODE PreviousMode)
 {
+    BOOLEAN V86Switch = FALSE;
+
     /* Start with the basic Registers */
     if ((Context->ContextFlags & CONTEXT_CONTROL) == CONTEXT_CONTROL)
     {
-        TrapFrame->Esp = Context->Esp;
-        TrapFrame->Ss = Context->SegSs;
-        TrapFrame->Cs = Context->SegCs;
-        TrapFrame->Eip = Context->Eip;
+        /* Check if we went through a V86 switch */
+        if ((Context->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;
+
+        /* 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)
+        {
+            /* Simply copy the CS value */
+            TrapFrame->Cs = Context->SegCs;
+        }
+        else
+        {
+            /* We weren't in V86, so sanitize the CS (FIXME!) */
+            TrapFrame->Cs = Context->SegCs;
+
+            /* Don't let it under 8, that's invalid */
+            if ((PreviousMode !=KernelMode) && (TrapFrame->Cs < 8))
+            {
+                /* Force it to User CS */
+                TrapFrame->Cs = USER_CS;
+            }
+        }
+
+        /* Handle SS Specially for validation */
+        KiSsToTrapFrame(TrapFrame, Context->SegSs);
+
+        /* Write ESP back; take into account Edited Trap Frames */
+        KiEspToTrapFrame(TrapFrame, Context->Esp);
+
+        /* Handle our V86 Bias if we went through a switch */
+        if (V86Switch) Ki386AdjustEsp0(TrapFrame);
     }
 
     /* Process the Integer Registers */
@@ -597,21 +752,62 @@ KeContextToTrapFrame(PCONTEXT Context,
     /* Process the Context Segments */
     if ((Context->ContextFlags & CONTEXT_SEGMENTS) == CONTEXT_SEGMENTS)
     {
-        TrapFrame->Ds = Context->SegDs;
-        TrapFrame->Es = Context->SegEs;
-        TrapFrame->Fs = Context->SegFs;
-        TrapFrame->Gs = Context->SegGs;
+        /* Check if we were in V86 Mode */
+        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;
+        }
+        else if (!(TrapFrame->Cs & 1))
+        {
+            /* For user mode, write the values directly */
+            TrapFrame->Ds = USER_DS;
+            TrapFrame->Es = USER_DS;
+            TrapFrame->Fs = Context->SegFs;
+            KEBUGCHECK(0);
+            TrapFrame->Gs = 0;
+        }
+        else
+        {
+            /* For kernel-mode, return the values */
+            TrapFrame->Ds = Context->SegDs;
+            TrapFrame->Es = Context->SegEs;
+            TrapFrame->Fs = Context->SegFs;
+
+            /* Handle GS specially */
+            if (TrapFrame->Cs == USER_CS)
+            {
+                /* Don't use it, if user */
+                TrapFrame->Gs = 0;
+            }
+            else
+            {
+                /* Copy it if kernel */
+                TrapFrame->Gs = Context->SegGs;
+            }
+        }
     }
 
     /* Handle the Debug Registers */
     if ((Context->ContextFlags & CONTEXT_DEBUG_REGISTERS) == CONTEXT_DEBUG_REGISTERS)
     {
+        /* FIXME: All these should be sanitized */
         TrapFrame->Dr0 = Context->Dr0;
         TrapFrame->Dr1 = Context->Dr1;
         TrapFrame->Dr2 = Context->Dr2;
         TrapFrame->Dr3 = Context->Dr3;
         TrapFrame->Dr6 = Context->Dr6;
         TrapFrame->Dr7 = Context->Dr7;
+
+        /* Check if usermode */
+        if (PreviousMode != KernelMode)
+        {
+            /* Set the Debug Flag */
+            KeGetCurrentThread()->DebugActive = (Context->Dr7 & DR7_ACTIVE);
+        }
     }
 
     /* Handle FPU and Extended Registers */
@@ -619,51 +815,90 @@ KeContextToTrapFrame(PCONTEXT Context,
 }
 
 VOID
-KeTrapFrameToContext(PKTRAP_FRAME TrapFrame,
-                    PCONTEXT Context)
+NTAPI
+KeTrapFrameToContext(IN PKTRAP_FRAME TrapFrame,
+                     IN PKEXCEPTION_FRAME ExceptionFrame,
+                     IN OUT PCONTEXT Context)
 {
-   if ((Context->ContextFlags & CONTEXT_CONTROL) == CONTEXT_CONTROL)
-     {
-       Context->SegSs = TrapFrame->Ss;
-       Context->Esp = TrapFrame->Esp;
-       Context->SegCs = TrapFrame->Cs;
-       Context->Eip = TrapFrame->Eip;
-       Context->EFlags = TrapFrame->Eflags;
-       Context->Ebp = TrapFrame->Ebp;
-     }
-   if ((Context->ContextFlags & CONTEXT_INTEGER) == CONTEXT_INTEGER)
-     {
-       Context->Eax = TrapFrame->Eax;
-       Context->Ebx = TrapFrame->Ebx;
-       Context->Ecx = TrapFrame->Ecx;
-       /*
-        * NOTE: In the trap frame which is built on entry to a system
-        * call TrapFrame->Edx will actually hold the address of the
-        * previous TrapFrame. I don't believe leaking this information
-        * has security implications. Also EDX holds the address of the
-        * arguments to the system call in progress so it isn't of much
-        * interest to the debugger.
-        */
-       Context->Edx = TrapFrame->Edx;
-       Context->Esi = TrapFrame->Esi;
-       Context->Edi = TrapFrame->Edi;
-     }
-   if ((Context->ContextFlags & CONTEXT_SEGMENTS) == CONTEXT_SEGMENTS)
-     {
-       Context->SegDs = TrapFrame->Ds;
-       Context->SegEs = TrapFrame->Es;
-       Context->SegFs = TrapFrame->Fs;
-       Context->SegGs = TrapFrame->Gs;
-     }
+    /* 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;
+
+        /* Return the correct CS */
+        if (!(TrapFrame->Cs & FRAME_EDITED) &&
+            !(TrapFrame->Eflags & X86_EFLAGS_VM))
+        {
+            /* Get it from the Temp location */
+            Context->SegCs = TrapFrame->TempCs & 0xFFFF;
+        }
+        else
+        {
+            /* Return it directly */
+            Context->SegCs = TrapFrame->Cs & 0xFFFF;
+        }
+
+        /* Get the Ss and ESP */
+        Context->SegSs = KiSsFromTrapFrame(TrapFrame);
+        Context->Esp = KiEspFromTrapFrame(TrapFrame);
+    }
+
+    /* Handle the Segments */
+    if ((Context->ContextFlags & CONTEXT_SEGMENTS) == CONTEXT_SEGMENTS)
+    {
+        /* Do V86 Mode first */
+        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;
+        }
+        else
+        {
+            /* Check if this was a Kernel Trap */
+            if (TrapFrame->Cs == KERNEL_CS)
+            {
+                /* Set valid selectors */
+                TrapFrame->Gs = 0;
+                TrapFrame->Fs = PCR_SELECTOR;
+                TrapFrame->Es = USER_DS;
+                TrapFrame->Ds = USER_DS;
+            }
+
+            /* Return the segments */
+            Context->SegGs = TrapFrame->Gs & 0xFFFF;
+            Context->SegFs = TrapFrame->Fs & 0xFFFF;
+            Context->SegEs = TrapFrame->Es & 0xFFFF;
+            Context->SegDs = TrapFrame->Ds & 0xFFFF;
+        }
+    }
+
+    /* Handle the simple registers */
+    if ((Context->ContextFlags & CONTEXT_INTEGER) == CONTEXT_INTEGER)
+    {
+        /* Return them directly */
+        Context->Eax = TrapFrame->Eax;
+        Context->Ebx = TrapFrame->Ebx;
+        Context->Ecx = TrapFrame->Ecx;
+        Context->Edx = TrapFrame->Edx;
+        Context->Esi = TrapFrame->Esi;
+        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
         *
@@ -676,7 +911,7 @@ KeTrapFrameToContext(PKTRAP_FRAME TrapFrame,
      }
 #if 0
    if ((Context->ContextFlags & CONTEXT_EXTENDED_REGISTERS) == CONTEXT_EXTENDED_REGISTERS)
-     {
+   {
        /*
         * FIXME: Investigate this
         *
@@ -931,7 +1166,7 @@ KiDispatchException(PEXCEPTION_RECORD ExceptionRecord,
     ULONG_PTR Stack, NewStack;
     ULONG Size;
     BOOLEAN UserDispatch = FALSE;
-    DPRINT1("KiDispatchException() called\n");
+    DPRINT("KiDispatchException() called\n");
 
     /* Increase number of Exception Dispatches */
     KeGetCurrentPrcb()->KeExceptionDispatchCount++;
@@ -947,7 +1182,7 @@ KiDispatchException(PEXCEPTION_RECORD ExceptionRecord,
     }
 
     /* Get a Context */
-    KeTrapFrameToContext(TrapFrame, &Context);
+    KeTrapFrameToContext(TrapFrame, ExceptionFrame, &Context);
 
     /* Handle kernel-mode first, it's simpler */
     if (PreviousMode == KernelMode)
@@ -1017,7 +1252,7 @@ KiDispatchException(PEXCEPTION_RECORD ExceptionRecord,
                 /* Align context size and get stack pointer */
                 Size = (sizeof(CONTEXT) + 3) & ~3;
                 Stack = (Context.Esp & ~3) - Size;
-                DPRINT1("Stack: %lx\n", Stack);
+                DPRINT("Stack: %lx\n", Stack);
 
                 /* Probe stack and copy Context */
                 ProbeForWrite((PVOID)Stack, Size, sizeof(ULONG));
@@ -1028,7 +1263,7 @@ KiDispatchException(PEXCEPTION_RECORD ExceptionRecord,
                         (EXCEPTION_MAXIMUM_PARAMETERS - ExceptionRecord->NumberParameters) *
                         sizeof(ULONG) + 3) & ~3;
                 NewStack = Stack - Size;
-                DPRINT1("NewStack: %lx\n", NewStack);
+                DPRINT("NewStack: %lx\n", NewStack);
 
                 /* Probe stack and copy exception record. Don't forget to add the two params */
                 ProbeForWrite((PVOID)(NewStack - 2 * sizeof(ULONG_PTR)),
@@ -1041,7 +1276,7 @@ KiDispatchException(PEXCEPTION_RECORD ExceptionRecord,
                 *(PULONG_PTR)(NewStack - 2 * sizeof(ULONG_PTR)) = NewStack;
 
                 /* Set new Stack Pointer */
-                TrapFrame->Esp = NewStack - 2 * sizeof(ULONG_PTR);
+                KiEspToTrapFrame(TrapFrame, NewStack - 2 * sizeof(ULONG_PTR));
 
                 /* Set EIP to the User-mode Dispathcer */
                 TrapFrame->Eip = (ULONG)KeUserExceptionDispatcher;
@@ -1073,7 +1308,7 @@ KiDispatchException(PEXCEPTION_RECORD ExceptionRecord,
 
 Handled:
     /* Convert the context back into Trap/Exception Frames */
-    KeContextToTrapFrame(&Context, NULL, TrapFrame);
+    KeContextToTrapFrame(&Context, NULL, TrapFrame, PreviousMode);
     return;
 }
 
index c26bb1c..a66badf 100644 (file)
@@ -528,7 +528,7 @@ KiHandleFpuFault(PKTRAP_FRAME Tf, ULONG ExceptionNr)
 
       /* Fill the rest of the context */
       Context->ContextFlags = CONTEXT_FULL;
-      KeTrapFrameToContext(Tf, Context);
+      KeTrapFrameToContext(Tf, NULL, Context);
       Context->ContextFlags |= CONTEXT_FLOATING_POINT | CONTEXT_EXTENDED_REGISTERS;
 
       /* Determine exception code */
index 1854acd..ddc40ff 100644 (file)
@@ -1,13 +1,8 @@
-/* $Id$
- *
+/*
  * FILE:            ntoskrnl/ke/i386/syscall.S
  * COPYRIGHT:       See COPYING in the top level directory
  * PURPOSE:         System Call Handler
  * PROGRAMMER:      Alex Ionescu (alex@relsoft.net)
- * UPDATE HISTORY:
- *                  ??-??-??: Original Version - David Welch(?)
- *                  13-01-05: Complete rewrite, added support for SYSENTER, direct kmode syscalls
- *                            and re-wrote most of handler code. - Alex Ionescu
  */
 
 #include <roscfg.h>
 #include <ndk/i386/segment.h>
 
 #define UserMode  (1)
+#define STATUS_INVALID_SYSTEM_SERVICE 0xC000001C
 
-.globl KeReturnFromSystemCallWithHook
 .globl _KiServiceExit
 .globl _KiServiceExit2
 .globl _KiFastCallEntry
 .globl _KiSystemService
 .globl _KiDebugService
+.intel_syntax noprefix
+
+/*
+ * NOTE: I will create some macros for trap entry and exit,
+ * DR* register restoration, modified frame exit, etc, if GAS
+ * allows it/I find a way how. This would remove a lot of
+ * duplicated code in this file plus the other irq/trap asm files.
+ * I think this is similar to what NT does, if you look at teh
+ * Dr_kit*_a functions which look auto-generated.
+ */
+
+/*
+ * There are 3 main types of Trap Exits:
+ *
+ * - KiServiceExit
+ *     - Clear interrupt flag
+ *     - Common User APC Dispatching
+ *     - Common exit code; segments and volatiles are not restored
+ * You use this for System Call return, when volatiles are irrelevant.
+ * (NtContinue, NtRaiseException, KiCallUserMode and all System Call returns)
+ *
+ * - KiServiceExit2
+ *     - Clear interrupt flag
+ *     - Common User APC Dispatching
+ *     - Common exit code; the entire frame is restored.
+ * You use this when volatiles and other registers need to be restored.
+ * For example, if debugging is active (NtContinue, NtRaiseException).
+ *
+ * - Kei386EoiHelper
+ *     - Clear interrupt flag
+ *     - Common User APC Dispatching
+ *     - Common exit code; the entire frame is restored but *NOT* the Previous Mode
+ * You use this in the same context as KiServiceExit2, but when the Previous Mode
+ * should be tampered with. Clearly, as its name suggests, this routine is mostly
+ * useful for End Of Interrupts.
+ * Note that this routine is EXPORTED.
+ * Note that this routine must called by a JMP, not a CALL.
+ */
+
+/*
+ * The common exit code has 3 modes of operation:
+ *    - Whether or not to restore segments
+ *    - Whether or not to restore volatiles
+ *    - Whether or not to restore the previous mode
+ * All these are exemplified by the 3 trap exits shown above
+ */
+
+/*
+ * There is also common Debug Code present in the common exit code, which
+ * in turn calls common code to save the debug registers
+ */
+ /*
+  * FIXMEs:
+  *         - Fix Win32k Callbacks so we can optimize stack usage.
+  *         - Dig in trap code and see why we need to push/pop the segments,
+  *           which -shouldn't- be needed on syscalls; one of the things
+  *           missing for this to work is lazy loading in the GPF handler,
+  *           but there are other things to consider.
+  *         - Use macros and merge with trap.s nicely
+  */
+
+/*
+ * Entries will be discussed later.
+ */
+ /*** This file is a mess; it is being worked on. Please contact Alex:
+  *** alex@relsoft.net if you want to make any changes to it before this
+  *** message goes away
+  */
+
+/* FUNCTIONS ***************************************************************/
+
+BadStack:
+
+    /* Restore ESP0 stack */
+    mov ecx, [fs:KPCR_TSS]
+    mov esp, ss:[ecx+KTSS_ESP0]
+
+    /* FIXME: Generate Trap 6*/
+    int 3
 
 _KiFastCallEntry:
 
+// ==================== UNIQUE SYSENTER STUB. DO NOT DUPLICATE ============//
     /* Set FS to PCR */
-    movl $PCR_SELECTOR, %ecx
-    movw %cx, %fs
+    mov ecx, PCR_SELECTOR
+    mov fs, cx
+
+    /* Set DS/ES to Kernel Selector */
+    mov ecx, KERNEL_DS
+    mov ds, cx
+    mov es, cx
 
     /* Set the current stack to Kernel Stack */
-    movl %fs:KPCR_TSS, %ecx
-    movl %ss:KTSS_ESP0(%ecx), %ecx
-    movl %ecx, %esp
+    mov ecx, [fs:KPCR_TSS]
+    mov esp, ss:[ecx+KTSS_ESP0]
+    /*
+     * ^^^^^ Normally we should be able to use KTHREAD.InitialStack - sizeof
+     *       KTRAP_FRAME - sizeof(NPX_AREA) and that will give us exactly
+     *       our esp (ie: ebp == esp by the way the system is organized).
+     *       This didn't work until I added v86m trap frame bias, which was
+     *       needed anways. It works NICELY until we hit a Win32K Callback,
+     *       which also messes up a lea esp, [ebp+...] below. It seems the
+     *       stack for callbacks isn't properly set up (it's missing sizeof
+     *       KTRAP_FRAME), which is understandable since the whole code is
+     *       messed up and smashes new stacks instead of using the kernel
+     *       assigned one.
+     */
 
     /* Set up a fake INT Stack. */
-    pushl $USER_DS
-    pushl %edx                  /* Ring 3 SS:ESP */
-    pushfl
-    orl $X86_EFLAGS_IF, (%esp)  /* Re-enable IRQs in EFLAGS, to fake INT */
-    pushl $USER_CS
-    pushl $KUSER_SHARED_SYSCALL_RET
+    push USER_DS
+    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], X86_EFLAGS_IF   /* Re-enable IRQs in EFLAGS, to fake INT */
+    push USER_CS
+    push KUSER_SHARED_SYSCALL_RET
+
+    /* Setup the Trap Frame stack */
+    push 0
+    push ebp
+    push ebx
+    push esi
+    push edi
+    push TEB_SELECTOR
+
+    /* 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
+
+    /* Push previous mode */
+    push UserMode
+
+.att_syntax
+    /* Save other registers */
+    sub $0xC, %esp                                                    // + 0x70
+    pushl $USER_DS                                                          // + 0x40
+    pushl $USER_DS                                                          // + 0x44
+    pushl $0                                                          // + 0x48
+    sub $0x30, %esp                                                    // + 0x70
+.intel_syntax noprefix
 
-    /* User Parameter List */
-    add $8, %edx
+    /* Write the previous mode */
+    mov byte ptr [esi+KTHREAD_PREVIOUS_MODE], UserMode
+
+    /* Go on the Kernel stack frame */
+    mov ebp, esp
+
+    /* 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
+
+    /* Jump to shared code or DR Save */
+    //jnz Dr_FastCallDrSave
+    jmp SharedCode
 
 _KiSystemService:
 
-    /*
-     * Construct a trap frame on the stack.
-     * The following are already on the stack.
-     */
-    // SS                                                                  + 0x0
-    // ESP                                                                 + 0x4
-    // EFLAGS                                                              + 0x8
-    // CS                                                                  + 0xC
-    // EIP                                                                 + 0x10
-    pushl $0                                                            // + 0x14
-    pushl %ebp                                                          // + 0x18
-    pushl %ebx                                                          // + 0x1C
-    pushl %esi                                                          // + 0x20
-    pushl %edi                                                          // + 0x24
-    pushl %fs                                                           // + 0x28
+// ==================== UNIQUE SYSCALL TRAP ENTRY DO NOT DUPLICATE ============//
+    /* Create a trap frame */
+    push 0
+    push ebp
+    push ebx
+    push esi
+    push edi
+    push fs
 
     /* Load PCR Selector into fs */
-    movw $PCR_SELECTOR, %bx
-    movw %bx, %fs
+    mov ebx, PCR_SELECTOR
+    mov fs, bx
+
+    /* Get a pointer to the current thread */
+    mov esi, [fs:KPCR_CURRENT_THREAD]
 
     /* Save the previous exception list */
-    pushl %fs:KPCR_EXCEPTION_LIST                                      // + 0x2C
+    push [fs:KPCR_EXCEPTION_LIST]
 
     /* Set the exception handler chain terminator */
-    movl $0xffffffff, %fs:KPCR_EXCEPTION_LIST
-
-    /* Get a pointer to the current thread */
-    movl %fs:KPCR_CURRENT_THREAD, %esi
+    mov dword ptr [fs:KPCR_EXCEPTION_LIST], -1
 
     /* Save the old previous mode */
-    pushl %ss:KTHREAD_PREVIOUS_MODE(%esi)                              // + 0x30
-
-    /* Set the new previous mode based on the saved CS selector */
-    movl 0x24(%esp), %ebx
-    andl $1, %ebx
-    movb %bl, %ss:KTHREAD_PREVIOUS_MODE(%esi)
-
+    push ss:[esi+KTHREAD_PREVIOUS_MODE]
+    
+.att_syntax
     /* Save other registers */
-    pushl %eax                                                         // + 0x34
-    pushl %ecx                                                         // + 0x38
-    pushl %edx                                                         // + 0x3C
+    sub $0xC, %esp                                                    // + 0x70
     pushl %ds                                                          // + 0x40
     pushl %es                                                          // + 0x44
     pushl %gs                                                          // + 0x48
-    sub $0x28, %esp                                                    // + 0x70
-
-#ifdef DBG
-    /* Trick gdb 6 into backtracing over the system call */
-    mov 0x6c(%esp), %ebx
-    pushl 4(%ebx)    /* DebugEIP */                                    // + 0x74
-#else
-    pushl 0x60(%esp) /* DebugEIP */                                    // + 0x74
-#endif
-    pushl %ebp       /* DebugEBP */                                    // + 0x78
+    sub $0x30, %esp                                                    // + 0x70
+.intel_syntax noprefix
 
-    /* Load the segment registers */
-    sti
-    movw $KERNEL_DS, %bx
-    movw %bx, %ds
-    movw %bx, %es
+    /* Set the new previous mode based on the saved CS selector */
+    mov ebx, [esp+0x6C]
+    and ebx, 1
+    mov byte ptr ss:[esi+KTHREAD_PREVIOUS_MODE], bl
+
+    /* Go on the Kernel stack frame */
+    mov ebp, esp
 
     /* Save the old trap frame pointer where EDX would be saved */
-    movl KTHREAD_TRAP_FRAME(%esi), %ebx
-    movl %ebx, KTRAP_FRAME_EDX(%esp)
+    mov ebx, [esi+KTHREAD_TRAP_FRAME]
+    mov [ebp+KTRAP_FRAME_EDX], ebx
+
+// ==================== COMMON DR SAVE CHECK.AND DEBUG FRAME SETUP ============//
+    /* Flush DR7 */
+    and dword ptr [ebp+KTRAP_FRAME_DR7], 0
 
-    /* Allocate new Kernel stack frame */
-    movl %esp,%ebp
+    /* Check if the thread was being debugged */
+    test byte ptr [esi+KTHREAD_DEBUG_ACTIVE], 0xFF
+    cld
+    //jnz Dr_kss_a
 
     /* Save a pointer to the trap frame in the TCB */
-    movl %ebp, KTHREAD_TRAP_FRAME(%esi)
+SharedCode:
+    mov [esi+KTHREAD_TRAP_FRAME], ebp
 
-CheckValidCall:
+    /* Get the Debug Trap Frame EBP/EIP */
+    mov ebx, [ebp+KTRAP_FRAME_EBP]
+    mov edi, [ebp+KTRAP_FRAME_EIP]
 
-#ifdef DBG
-    /*
-     * GDB thinks the function starts here and
-     * wants a standard prolog, so let's give it
-     */
-    pushl %ebp
-    movl %esp,%ebp
-    popl %ebp
-#endif
+    /* Write the debug data */
+    mov [ebp+KTRAP_FRAME_DEBUGPOINTER], edx
+    mov dword ptr [ebp+KTRAP_FRAME_DEBUGARGMARK], 0xBADB0D00
+    mov [ebp+KTRAP_FRAME_DEBUGEBP], ebx
+    mov [ebp+KTRAP_FRAME_DEBUGEIP], edi
+
+// ============= END OF COMMON DR SAVE CHECK.AND DEBUG FRAME SETUP ============//
+    /* Enable interrupts */
+    sti
+
+CheckValidCall:
 
     /*
      * Find out which table offset to use. Converts 0x1124 into 0x10.
      * The offset is related to the Table Index as such: Offset = TableIndex x 10
      */
-    movl %eax, %edi
-    shrl $8, %edi
-    andl $0x10, %edi
-    movl %edi, %ecx
+    mov edi, eax
+    shr edi, 8
+    and edi, 0x10
+    mov ecx, edi
 
     /* Now add the thread's base system table to the offset */
-    addl KTHREAD_SERVICE_TABLE(%esi), %edi
+    add edi, [esi+KTHREAD_SERVICE_TABLE]
 
     /* Get the true syscall ID and check it */
-    movl %eax, %ebx
-    andl $0x0FFF, %eax
-    cmpl 8(%edi), %eax
+    mov ebx, eax
+    and eax, 0xFFF
+    cmp eax, [edi+8]
 
     /* Invalid ID, try to load Win32K Table */
     jnb KiBBTUnexpectedRange
 
+#if 0 // <== Disabled for two reasons: We don't save TEB in 0x18, but KPCR.
+      // <== We don't have a KeGdiFlushUserBatch callback yet (needs to be
+      //     sent through the PsInitializeWin32Callouts structure)
+    /* Check if this was Win32K */
+    cmp ecx, 0x10
+    jnz NotWin32K
+
+    /* Get the TEB */
+    mov ecx, [fs:KPCR_TEB]
+
+    /* Check if we should flush the User Batch */
+    xor ebx, ebx
+    or ebx, [ecx+TEB_GDI_BATCH_COUNT]
+    jz NoWin32K
+
+    /* Flush it */
+    push edx
+    push eax
+    call [_KeGdiFlushUserBatch]
+    pop eax
+    pop edx
+#endif
+
+NotWin32K:
     /* Users's current stack frame pointer is source */
-    movl %edx, %esi
+    mov esi, edx
 
     /* Allocate room for argument list from kernel stack */
-    movl 12(%edi), %ecx
-    movb (%ecx, %eax), %cl
-    movzx %cl, %ecx
-
-    /* Allocate space on our stack */
-    subl %ecx, %esp
+    mov ebx, [edi+12]
+    xor ecx, ecx
+    mov cl, [eax+ebx]
 
     /* Get pointer to function */
-    movl (%edi), %edi
-    movl (%edi, %eax, 4), %eax
+    mov edi, [edi]
+    mov ebx, [edi+eax*4]
 
-    /* Copy the arguments from the user stack to our stack */
-    shr $2, %ecx
-    movl %esp, %edi
-    cld
+    /* Allocate space on our stack */
+    sub esp, ecx
+
+    /* 
+     * Copy the arguments from the user stack to our stack
+     * FIXME: This needs to be probed with MmSystemRangeStart
+     */
+    shr ecx, 2
+    mov edi, esp
     rep movsd
 
     /* Do the System Call */
-    call *%eax
-    movl %eax, KTRAP_FRAME_EAX(%ebp)
+    call ebx
 
     /* Deallocate the kernel stack frame  */
-    movl %ebp, %esp
+    mov esp, ebp
 
 KeReturnFromSystemCall:
 
     /* Get the Current Thread */
-    movl %fs:KPCR_CURRENT_THREAD, %esi
+    mov ecx, [fs:KPCR_CURRENT_THREAD]
 
     /* Restore the old trap frame pointer */
-    movl KTRAP_FRAME_EDX(%esp), %ebx
-    movl %ebx, KTHREAD_TRAP_FRAME(%esi)
+    mov edx, [ebp+KTRAP_FRAME_EDX]
+    mov [ecx+KTHREAD_TRAP_FRAME], edx
 
 _KiServiceExit:
-
-    /* Get the Current Thread */
+    /* Disable interrupts */
     cli
-    movl %fs:KPCR_CURRENT_THREAD, %esi
+
+// ================= COMMON USER-MODE APC DELIVERY CHECK ============//
+    /* Check for V86 mode */
+    test dword ptr [ebp+KTRAP_FRAME_EFLAGS], X86_EFLAGS_VM
+    jnz ApcLoop
 
     /* Deliver APCs only if we were called from user mode */
-    testb $1, KTRAP_FRAME_CS(%esp)
+    test byte ptr [ebp+KTRAP_FRAME_CS], 1
     je KiRosTrapReturn
 
+    /* Get the current thread */
+ApcLoop:
+    mov ebx, [fs:KPCR_CURRENT_THREAD]
+
+    /* Make it non-alerted */
+    mov byte ptr [ebx+KTHREAD_ALERTED], 0
+
     /* And only if any are actually pending */
-    cmpb $0, KTHREAD_PENDING_USER_APC(%esi)
+    cmp byte ptr [ebx+KTHREAD_PENDING_USER_APC], 0
     je KiRosTrapReturn
 
     /* Save pointer to Trap Frame */
-    movl %esp, %ebx
+    mov ebx, ebp
+
+// ================= PRESENT ONLY IF VOLATILES NEEDED ============//
+    /* Save some stuff that raising IRQL will kill */
+    mov [ebx+KTRAP_FRAME_EAX], eax
+    mov dword ptr [ebx+KTRAP_FRAME_FS], TEB_SELECTOR
+    mov dword ptr [ebx+KTRAP_FRAME_DS], USER_DS
+    mov dword ptr [ebx+KTRAP_FRAME_ES], USER_DS
+    mov dword ptr [ebx+KTRAP_FRAME_GS], 0
+// ============= END PRESENT ONLY IF VOLATILES NEEDED ============//
 
     /* Raise IRQL to APC_LEVEL */
-    movl $1, %ecx
+    mov ecx, 1
     call @KfRaiseIrql@4
 
     /* Save old IRQL */
-    pushl %eax
+    push eax
 
     /* Deliver APCs */
     sti
-    pushl %ebx
-    pushl $0
-    pushl $UserMode
+    push ebx
+    push 0
+    push UserMode
     call _KiDeliverApc@12
-    cli
 
     /* Return to old IRQL */
-    popl %ecx
+    pop ecx
     call @KfLowerIrql@4
+    
+    /* Restore EAX (only in volatile case) */
+    mov eax, [ebx+KTRAP_FRAME_EAX]
+    cli
+    jmp ApcLoop
+// ============== END COMMON USER-MODE APC DELIVERY CHECK ============//
 
 KiRosTrapReturn:
-
+// ========================= COMMON TRAP EXIT CODE ===================//
+    /* Restore exception list */
+    mov edx, [esp+KTRAP_FRAME_EXCEPTION_LIST]
+    mov [fs:KPCR_EXCEPTION_LIST], edx
+
+// ==================== ONLY IF PREVIOUS MODE NEEDED ==================//
+    /* Restore previous mode */
+    mov ecx, [esp+KTRAP_FRAME_PREVIOUS_MODE]
+    mov esi, [fs:KPCR_CURRENT_THREAD]
+    mov byte ptr [esi+KTHREAD_PREVIOUS_MODE], cl
+// ==================== END IF PREVIOUS MODE NEEDED ===================//
+
+    /* Check for V86 */
+    test dword ptr [esp+KTRAP_FRAME_EFLAGS], X86_EFLAGS_VM
+    jnz V86_Exit
+
+    /* Check if the frame was edited */
+    test word ptr [esp+KTRAP_FRAME_CS], FRAME_EDITED
+    jz EditedFrame
+
+// ==================== ONLY IF FULL RESTORE NEEDED ===================//
+    /* Check the old mode */
+    cmp word ptr [esp+KTRAP_FRAME_CS], USER_CS
+    bt word ptr [esp+KTRAP_FRAME_CS], 0
+    cmc
+    ja RestoreAll
+// ==================== END IF FULL RESTORE NEEDED ====================//
+
+ /* Skip debug information and unsaved registers */
+ //badbadbad
+    add esp, 0x30
+    pop gs
+    pop es
+    pop ds
+    add esp, 0x14
+//badbadbad
+
+    /* Restore FS */
+RestoreFs:
+    //lea esp, [ebp+KTRAP_FRAME_FS] <= BUG IN WIN32K CALLBACKS! STACK GETS SMASHED
+    pop fs
+
+CommonStackClean:
     /* Skip debug information and unsaved registers */
-    addl $0x30, %esp                                                   // + 0x48
-    popl %gs                                                           // + 0x44
-    popl %es                                                           // + 0x40
-    popl %ds                                                           // + 0x3C
-    popl %edx                                                          // + 0x38
-    popl %ecx                                                          // + 0x34
-    popl %eax                                                          // + 0x30
-
-    /* Restore the old previous mode */
-    popl %ebx                                                          // + 0x2C
-    movb %bl, %ss:KTHREAD_PREVIOUS_MODE(%esi)
-
-    /* Restore the old exception handler list */
-    popl %fs:KPCR_EXCEPTION_LIST                                       // + 0x28
-
-    /* Restore final registers from trap frame */
-    popl %fs                                                           // + 0x24
-    popl %edi                                                          // + 0x20
-    popl %esi                                                          // + 0x1C
-    popl %ebx                                                          // + 0x18
-    popl %ebp                                                          // + 0x14
-    add $4, %esp                                                       // + 0x10
+    //lea esp, [ebp+KTRAP_FRAME_EDI] <= BUG IN WIN32K CALLBACKS! STACK GETS SMASHED
+    pop edi
+    pop esi
+    pop ebx
+    pop ebp
+
+    /* Check for ABIOS */
+    cmp word ptr [esp+8], 0x80
+    ja AbiosExit
+
+AbiosReturn:
+    /* Pop error code */
+    add esp, 4
 
     /* Check if previous CS is from user-mode */
-    testl $1, 4(%esp)
+    test dword ptr [esp+4], 1
 
     /* It is, so use Fast Exit */
     jnz FastRet
 
-    /*
-     * Restore what the stub pushed, and return back to it.
-     * Note that we were CALLed, so the first thing on our stack is the ret EIP!
-     */
-    pop %edx                                                           // + 0x0C
-    pop %ecx                                                           // + 0x08
-    popf                                                               // + 0x04
-    jmp *%edx
+    /* Jump back to stub */
+    pop edx
+    pop ecx
+    popf
+    jmp edx
 
 IntRet:
 
     iret
 
 FastRet:
-
     /* Is SYSEXIT Supported/Wanted? */
-    cmpl $0, %ss:_KiFastSystemCallDisable
+    cmp dword ptr ss:[_KiFastSystemCallDisable], 0
+    jnz IntRet
+    test dword ptr [esp+8], X86_EFLAGS_TF
     jnz IntRet
 
     /* Restore FS to TIB */
-    mov $TEB_SELECTOR, %ecx
-    mov %ecx, %fs
-
+    mov ecx, TEB_SELECTOR
+    mov fs, ecx
+    
     /* We will be cleaning up the stack ourselves */
-    popl %edx                         /* New Ring 3 EIP */
-    add $0x4, %esp                    /* Skip Ring 3 DS */
-    andl $~X86_EFLAGS_IF, (%esp)      /* Remove IRQ hack from EFLAGS */
-    popfl                             /* Restore old EFLAGS */
-    popl %ecx                         /* Old Ring 3 SS:ESP */
+    pop edx                                 /* New Ring 3 EIP */
+    add esp, 4                              /* Skip Ring 3 DS */
+    and dword ptr [esp], ~X86_EFLAGS_IF     /* Remove IRQ hack from EFLAGS */
+    popf                                    /* Restore old EFLAGS */
+    pop ecx                                 /* Old Ring 3 SS:ESP */
 
     /*
      * At this point:
@@ -294,18 +505,72 @@ FastRet:
     sti
     sysexit
 
+AbiosExit:
+V86_Exit:
+    /* Not yet supported */
+    int 3
+
+RestoreAll:
+    /* Restore EAX */
+    mov eax, [esp+KTRAP_FRAME_EAX]
+
+    /* Skip registers */
+    add esp, 0x30
+
+    /* Restore segments and volatiles */
+    pop gs
+    pop es
+    pop ds
+    pop edx
+    pop ecx
+
+    /* Jump back to mainline code */
+    jmp RestoreFs
+
+EditedFrame:
+     /* Restore real CS value */
+     mov ebx, [esp+KTRAP_FRAME_TEMPCS]
+     mov [esp+KTRAP_FRAME_CS], ebx
+
+    /*
+     * If ESP was modified, then a special interrupt exit stack
+     * must be created to "update" ESP's value in a legal manner
+     */
+    mov ebx, [esp+KTRAP_FRAME_TEMPESP]
+    sub ebx, 0xC
+    mov [esp+KTRAP_FRAME_ERROR_CODE], ebx
+
+    /* Copy Interrupt Stack */
+    mov esi, [esp+KTRAP_FRAME_EFLAGS]
+    mov [ebx+8], esi
+    mov esi, [esp+KTRAP_FRAME_CS]
+    mov [ebx+4], esi
+    mov esi, [esp+KTRAP_FRAME_EIP]
+    mov [ebx], esi
+
+    /* Return */
+    add esp, KTRAP_FRAME_EDI
+    pop edi
+    pop esi
+    pop ebx
+    pop ebp
+    mov esp, [esp]
+    iret
+
 KiBBTUnexpectedRange:
 
     /* If this isn't a Win32K call, fail */
-    cmp $0x10, %ecx
+    cmp ecx, 0x10
     jne InvalidCall
 
     /* Set up Win32K Table */
-    pushl %edx
-    pushl %ebx
+    push edx
+    push ebx
     call _KiServiceCheck
-    popl %eax
-    popl %edx
+
+    /* FIXME: Handle failure */
+    pop eax
+    pop edx
 
     /* Try the Call again */
     jmp CheckValidCall
@@ -313,90 +578,145 @@ KiBBTUnexpectedRange:
 InvalidCall:
 
     /* Invalid System Call */
-    movl $0xC000001C, %eax /* STATUS_INVALID_SYSTEM_SERVICE */
-    movl %eax, KTRAP_FRAME_EAX(%ebp)
-    jmp _KiServiceExit
+    mov eax, STATUS_INVALID_SYSTEM_SERVICE
+    jmp KeReturnFromSystemCall
 
 _KiServiceExit2:
 
-    /* Get the Current Thread */
+    /* Disable interrupts */
     cli
-    movl %fs:KPCR_CURRENT_THREAD, %esi
+
+    /* Check for V86 mode */
+    test dword ptr [ebp+KTRAP_FRAME_EFLAGS], X86_EFLAGS_VM
+    jnz ApcLoop2
 
     /* Deliver APCs only if we were called from user mode */
-    testb $1, KTRAP_FRAME_CS(%esp)
-    je KiRosTrapReturn
+    test byte ptr [ebp+KTRAP_FRAME_CS], 1
+    je KiRosTrapReturn2
+
+    /* Get the current thread */
+ApcLoop2:
+    mov ebx, [fs:KPCR_CURRENT_THREAD]
+
+    /* Make it non-alerted */
+    mov byte ptr [ebx+KTHREAD_ALERTED], 0
 
     /* And only if any are actually pending */
-    cmpb $0, KTHREAD_PENDING_USER_APC(%esi)
-    je KiRosTrapReturn
+    cmp byte ptr [ebx+KTHREAD_PENDING_USER_APC], 0
+    je KiRosTrapReturn2
 
     /* Save pointer to Trap Frame */
-    movl %esp, %ebx
+    mov ebx, ebp
 
     /* Raise IRQL to APC_LEVEL */
-    movl $1, %ecx
+    mov ecx, 1
     call @KfRaiseIrql@4
 
     /* Save old IRQL */
-    pushl %eax
+    push eax
 
     /* Deliver APCs */
     sti
-    pushl %ebx
-    pushl $0
-    pushl $UserMode
+    push ebx
+    push 0
+    push UserMode
     call _KiDeliverApc@12
-    cli
 
     /* Return to old IRQL */
-    popl %ecx
+    pop ecx
     call @KfLowerIrql@4
+    cli
+    jmp ApcLoop2
+
+KiRosTrapReturn2:
+
+    /* Restore exception list */
+    mov edx, [esp+KTRAP_FRAME_EXCEPTION_LIST]
+    mov [fs:KPCR_EXCEPTION_LIST], edx
+
+    /* Restore previous mode */
+    mov ecx, [esp+KTRAP_FRAME_PREVIOUS_MODE]
+    mov esi, [fs:KPCR_CURRENT_THREAD]
+    mov byte ptr [esi+KTHREAD_PREVIOUS_MODE], cl
+
+    /* Check for V86 */
+    test dword ptr [esp+KTRAP_FRAME_EFLAGS], X86_EFLAGS_VM
+    jnz V86_Exit
 
-    /* Skip useless Debug Data */
-    addl $0x18, %esp                                                   // + 0x74
-
-    /* Restore Debug Registers */
-    popl %eax                                                          // + 0x5C
-    movl %eax, %dr0
-    popl %eax                                                          // + 0x58
-    movl %eax, %dr1
-    popl %eax                                                          // + 0x54
-    movl %eax, %dr2
-    popl %eax                                                          // + 0x50
-    movl %eax, %dr3
-    popl %eax                                                          // + 0x4C
-    movl %eax, %dr6
-    popl %eax                                                          // + 0x48
-    movl %eax, %dr7
-
-    /* Restore Registers */
-    popl %gs                                                           // + 0x44
-    popl %es                                                           // + 0x40
-    popl %ds                                                           // + 0x3C
-    popl %edx                                                          // + 0x38
-    popl %ecx                                                          // + 0x34
-    popl %eax                                                          // + 0x30
-
-    /* Restore the old previous mode */
-    popl %ebx                                                          // + 0x2C
-    movb %bl, %ss:KTHREAD_PREVIOUS_MODE(%esi)
-
-    /* Restore the old exception handler list */
-    popl %fs:KPCR_EXCEPTION_LIST                                       // + 0x28
-
-    /* Restore final registers from trap frame */
-    popl %fs                                                           // + 0x24
-    popl %edi                                                          // + 0x20
-    popl %esi                                                          // + 0x1C
-    popl %ebx                                                          // + 0x18
-    popl %ebp                                                          // + 0x14
-    add $4, %esp                                                       // + 0x10
-
-    /* Return to user-mode */
+    /* Check if the frame was edited */
+    test word ptr [esp+KTRAP_FRAME_CS], FRAME_EDITED
+    jz EditedFrame2
+
+    /* Restore volatiles */
+    mov edx, [esp+KTRAP_FRAME_EDX]
+    mov ecx, [esp+KTRAP_FRAME_ECX]
+    mov eax, [esp+KTRAP_FRAME_EAX]
+
+    /* Check if it was kernel */
+    cmp word ptr [ebp+KTRAP_FRAME_CS], KERNEL_CS
+    jz CommonStackClean2
+
+    /* Skip registers */
+    lea esp, [ebp+KTRAP_FRAME_GS]
+
+    /* Restore segments and volatiles */
+    pop gs
+    pop es
+    pop ds
+    lea esp, [ebp+KTRAP_FRAME_FS]
+    pop fs
+
+CommonStackClean2:
+    /* Skip debug information and unsaved registers */
+    lea esp, [ebp+KTRAP_FRAME_EDI]
+    pop edi
+    pop esi
+    pop ebx
+    pop ebp
+
+    /* Check for ABIOS */
+    cmp word ptr [esp+8], 0x80
+    ja AbiosExit
+
+    /* Pop error code and return */
+    add esp, 4
+    iret
+
+EditedFrame2:
+    /* Restore real CS value */
+    mov ebx, [esp+KTRAP_FRAME_TEMPCS]
+    mov [esp+KTRAP_FRAME_CS], ebx
+
+    /*
+     * If ESP was modified, then a special interrupt exit stack
+     * must be created to "update" ESP's value in a legal manner
+     */
+    mov ebx, [esp+KTRAP_FRAME_TEMPESP]
+    sub ebx, 0xC
+    mov [esp+KTRAP_FRAME_ERROR_CODE], ebx
+
+    /* Copy Interrupt Stack */
+    mov esi, [esp+KTRAP_FRAME_EFLAGS]
+    mov [ebx+8], esi
+    mov esi, [esp+KTRAP_FRAME_CS]
+    mov [ebx+4], esi
+    mov esi, [esp+KTRAP_FRAME_EIP]
+    mov [ebx], esi
+
+    /* Restore volatiles */
+    mov eax, [esp+KTRAP_FRAME_EAX]
+    mov edx, [esp+KTRAP_FRAME_EDX]
+    mov ecx, [esp+KTRAP_FRAME_ECX]
+
+    /* Return */
+    add esp, KTRAP_FRAME_EDI
+    pop edi
+    pop esi
+    pop ebx
+    pop ebp
+    mov esp, [esp]
     iret
 
-.intel_syntax noprefix
 _KiDebugService:
 
     /* Create the Trap Frame */
@@ -414,9 +734,8 @@ _KiDebugService:
     /* Save Exception List */
     push fs:[KPCR_EXCEPTION_LIST]
 
-    /* Use Old Previous Mode */
-    mov ebx, fs:[KPCR_CURRENT_THREAD]
-    push [ebx+KTHREAD_PREVIOUS_MODE]
+    /* Traps don't need the previous mode */
+    sub esp, 4
 
     /* Continue building the Trap Frame */
     push eax
@@ -425,39 +744,180 @@ _KiDebugService:
     push ds
     push es
     push gs
+    sub esp, 0x30
 
     /* Switch Segments to Kernel */
-    mov bx, KERNEL_DS
-    mov ds, bx
-    mov es, bx
+    mov ax, KERNEL_DS
+    mov ds, ax
+    mov es, ax
 
-    /* Save Debug Registers */
-    mov ebx, eax
-    mov eax, dr7
-    push eax
-    mov eax, dr6
-    push eax
-    mov eax, dr3
-    push eax
-    mov eax, dr2
-    push eax
-    mov eax, dr1
-    push eax
-    mov eax, dr0
-    push eax
-    mov eax, ebx
+    /* Set up frame */
+    mov ebp, esp
+
+    /* Check if this was from V86 Mode */
+    test dword ptr [ebp+KTRAP_FRAME_EFLAGS], X86_EFLAGS_VM
+    //jnz V86_kids
+
+    /* Get current thread */
+    mov ecx, [fs:KPCR_CURRENT_THREAD]
+    cld
+
+    /* Flush DR7 */
+    and dword ptr [ebp+KTRAP_FRAME_DR7], 0
 
-    /* Skip useless debug data */
-    sub esp, 0x18
+    /* Check if the thread was being debugged */
+    test byte ptr [ecx+KTHREAD_DEBUG_ACTIVE], 0xFF
+    //jnz Dr_kids
+
+    /* Get the Debug Trap Frame EBP/EIP */
+    mov ebx, [ebp+KTRAP_FRAME_EBP]
+    mov edi, [ebp+KTRAP_FRAME_EIP]
+
+    /* Write the debug data */
+    mov [ebp+KTRAP_FRAME_DEBUGPOINTER], edx
+    mov dword ptr [ebp+KTRAP_FRAME_DEBUGARGMARK], 0xBADB0D00
+    mov [ebp+KTRAP_FRAME_DEBUGEBP], ebx
+    mov [ebp+KTRAP_FRAME_DEBUGEIP], edi
 
     /* Call debug service dispatcher */
-    push edx
-    push ecx
-    push eax
+    push [ebp+KTRAP_FRAME_EDX]
+    push [ebp+KTRAP_FRAME_ECX]
+    push [ebp+KTRAP_FRAME_EAX]
     call _KdpServiceDispatcher@12
 
     /* Exit through common routine */
-    jmp _KiServiceExit2
+    jmp Kei386EoiHelper@0
+
+Kei386EoiHelper@0:
+
+    /* Disable interrupts */
+    cli
+
+    /* Check for V86 mode */
+    test dword ptr [ebp+KTRAP_FRAME_EFLAGS], X86_EFLAGS_VM
+    jnz ApcLoop3
+
+    /* Deliver APCs only if we were called from user mode */
+    test byte ptr [ebp+KTRAP_FRAME_CS], 1
+    je KiRosTrapReturn3
+
+    /* Get the current thread */
+ApcLoop3:
+    mov ebx, [fs:KPCR_CURRENT_THREAD]
+
+    /* Make it non-alerted */
+    mov byte ptr [ebx+KTHREAD_ALERTED], 0
+
+    /* And only if any are actually pending */
+    cmp byte ptr [ebx+KTHREAD_PENDING_USER_APC], 0
+    je KiRosTrapReturn3
+
+    /* Save pointer to Trap Frame */
+    mov ebx, ebp
+
+    /* Raise IRQL to APC_LEVEL */
+    mov ecx, 1
+    call @KfRaiseIrql@4
+
+    /* Save old IRQL */
+    push eax
+
+    /* Deliver APCs */
+    sti
+    push ebx
+    push 0
+    push UserMode
+    call _KiDeliverApc@12
+
+    /* Return to old IRQL */
+    pop ecx
+    call @KfLowerIrql@4
+    cli
+    jmp ApcLoop3
+
+KiRosTrapReturn3:
+
+    /* Restore exception list */
+    mov edx, [esp+KTRAP_FRAME_EXCEPTION_LIST]
+    mov [fs:KPCR_EXCEPTION_LIST], edx
+
+    /* Check for V86 */
+    test dword ptr [esp+KTRAP_FRAME_EFLAGS], X86_EFLAGS_VM
+    jnz V86_Exit
+
+    /* Check if the frame was edited */
+    test word ptr [esp+KTRAP_FRAME_CS], FRAME_EDITED
+    jz EditedFrame3
+
+    /* Restore volatiles */
+    mov edx, [esp+KTRAP_FRAME_EDX]
+    mov ecx, [esp+KTRAP_FRAME_ECX]
+    mov eax, [esp+KTRAP_FRAME_EAX]
+
+    /* Check if it was kernel */
+    cmp word ptr [ebp+KTRAP_FRAME_CS], KERNEL_CS
+    jz CommonStackClean3
+
+    /* Skip registers */
+    lea esp, [ebp+KTRAP_FRAME_GS]
+
+    /* Restore segments and volatiles */
+    pop gs
+    pop es
+    pop ds
+    lea esp, [ebp+KTRAP_FRAME_FS]
+    pop fs
+
+CommonStackClean3:
+    /* Skip debug information and unsaved registers */
+    lea esp, [ebp+KTRAP_FRAME_EDI]
+    pop edi
+    pop esi
+    pop ebx
+    pop ebp
+
+    /* Check for ABIOS */
+    cmp word ptr [esp+8], 0x80
+    ja AbiosExit
+
+    /* Pop error code and return */
+    add esp, 4
+    iret
+
+EditedFrame3:
+    /* Restore real CS value */
+    mov ebx, [esp+KTRAP_FRAME_TEMPCS]
+    mov [esp+KTRAP_FRAME_CS], ebx
+
+    /*
+     * If ESP was modified, then a special interrupt exit stack
+     * must be created to "update" ESP's value in a legal manner
+     */
+    mov ebx, [esp+KTRAP_FRAME_TEMPESP]
+    sub ebx, 0xC
+    mov [esp+KTRAP_FRAME_ERROR_CODE], ebx
+
+    /* Copy Interrupt Stack */
+    mov esi, [esp+KTRAP_FRAME_EFLAGS]
+    mov [ebx+8], esi
+    mov esi, [esp+KTRAP_FRAME_CS]
+    mov [ebx+4], esi
+    mov esi, [esp+KTRAP_FRAME_EIP]
+    mov [ebx], esi
+
+    /* Restore volatiles */
+    mov eax, [esp+KTRAP_FRAME_EAX]
+    mov edx, [esp+KTRAP_FRAME_EDX]
+    mov ecx, [esp+KTRAP_FRAME_ECX]
+
+    /* Return */
+    add esp, KTRAP_FRAME_EDI
+    pop edi
+    pop esi
+    pop ebx
+    pop ebp
+    mov esp, [esp]
+    iret
 
 .globl _NtRaiseException@12
 _NtRaiseException@12:
index 2e69149..d0f92e1 100644 (file)
@@ -85,7 +85,7 @@ Ke386InitThreadWithContext(PKTHREAD Thread,
         TrapFrame = &InitFrame->TrapFrame;
 
         /* Set up a trap frame from the context. */
-        if (KeContextToTrapFrame(Context, NULL, TrapFrame))
+        if (KeContextToTrapFrame(Context, NULL, TrapFrame, UserMode))
         {
             Thread->NpxState = NPX_STATE_VALID;
         }
@@ -146,7 +146,9 @@ Ke386InitThreadWithContext(PKTHREAD Thread,
 
     /* And set up the Context Switch Frame */
     CtxSwitchFrame->RetEip = KiThreadStartup;
-    CtxSwitchFrame->Esp0 = (ULONG)Thread->InitialStack - sizeof(FX_SAVE_AREA);
+    CtxSwitchFrame->Esp0 = (ULONG_PTR)Thread->InitialStack -
+                                      sizeof(FX_SAVE_AREA) -
+                                      0x10;
     CtxSwitchFrame->ExceptionList = (PVOID)0xFFFFFFFF;
 
     /* Save back the new value of the kernel stack. */
index b2c34b6..952bdbc 100644 (file)
@@ -10,6 +10,7 @@
 
 #include <roscfg.h>
 #include <ndk/asm.h>
+#include <internal/i386/ke.h>
 #include <ndk/i386/segment.h>
 
 #define KernelMode 0
@@ -374,4 +375,37 @@ _KiCoprocessorError@0:
     /* Return to caller */
     ret
 
+.globl _Ki386AdjustEsp0@4
+_Ki386AdjustEsp0@4:
+
+    /* Get the current thread */
+    mov eax, [fs:KPCR_CURRENT_THREAD]
+
+    /* Get trap frame and stack */
+    mov edx, [esp+4]
+    mov eax, [eax+KTHREAD_INITIAL_STACK]
+
+    /* Check if V86 */
+    test dword ptr [edx+KTRAP_FRAME_EFLAGS], X86_EFLAGS_VM
+    jnz NoAdjust
+
+    /* Bias the stack */
+    sub eax, KTRAP_FRAME_V86_GS - KTRAP_FRAME_SS
+
+NoAdjust:
+    /* Skip FX Save Area */
+    sub eax, SIZEOF_FX_SAVE_AREA
+
+    /* Disable interrupts */
+    pushf
+    cli
+
+    /* Adjust ESP0 */
+    mov edx, [fs:KPCR_TSS]
+    mov ss:[edx+KTSS_ESP0], eax
+
+    /* Enable interrupts and return */
+    popf
+    ret 4
+
 /* EOF */
index 0e1ad6a..08bcadc 100644 (file)
@@ -36,11 +36,11 @@ ULONG KiPageFaultHandler(PKTRAP_FRAME Tf, ULONG ExceptionNr)
    ASSERT(ExceptionNr == 14);
    
    /* Store the exception number in an unused field in the trap frame. */
-   Tf->DebugArgMark = (PVOID)14;
+   Tf->DebugArgMark = 14;
 
    /* get the faulting address */
    cr2 = Ke386GetCr2();
-   Tf->DebugPointer = (PVOID)cr2;
+   Tf->DebugPointer = cr2;
 
    /* it's safe to enable interrupts after cr2 has been saved */
    if (Tf->Eflags & (X86_EFLAGS_VM|X86_EFLAGS_IF))
index 30d6761..9e99424 100644 (file)
@@ -22,6 +22,7 @@ typedef struct _GET_SET_CTX_CONTEXT {
     KAPC Apc;
     KEVENT Event;
     CONTEXT Context;
+    KPROCESSOR_MODE Mode;
 } GET_SET_CTX_CONTEXT, *PGET_SET_CTX_CONTEXT;
 
 
@@ -42,22 +43,24 @@ PspGetOrSetContextKernelRoutine(PKAPC Apc,
     PGET_SET_CTX_CONTEXT GetSetContext;
     PKEVENT Event;
     PCONTEXT Context;
+    KPROCESSOR_MODE Mode;
 
     /* Get the Context Structure */
     GetSetContext = CONTAINING_RECORD(Apc, GET_SET_CTX_CONTEXT, Apc);
     Context = &GetSetContext->Context;
     Event = &GetSetContext->Event;
+    Mode = GetSetContext->Mode;
 
     /* Check if it's a set or get */
     if (SystemArgument1) {
 
         /* Get the Context */
-        KeTrapFrameToContext(KeGetCurrentThread()->TrapFrame, Context);
+        KeTrapFrameToContext(KeGetCurrentThread()->TrapFrame, NULL, Context);
 
     } else {
 
         /* Set the Context */
-        KeContextToTrapFrame(Context, NULL, KeGetCurrentThread()->TrapFrame);
+        KeContextToTrapFrame(Context, NULL, KeGetCurrentThread()->TrapFrame, Mode);
     }
 
     /* Notify the Native API that we are done */
@@ -111,7 +114,7 @@ NtGetContextThread(IN HANDLE ThreadHandle,
              * I don't know if trying to get your own context makes much
              * sense but we can handle it more efficently.
              */
-            KeTrapFrameToContext(Thread->Tcb.TrapFrame, &GetSetContext.Context);
+            KeTrapFrameToContext(Thread->Tcb.TrapFrame, NULL, &GetSetContext.Context);
 
         } else {
 
@@ -120,6 +123,9 @@ NtGetContextThread(IN HANDLE ThreadHandle,
                               NotificationEvent,
                               FALSE);
 
+            /* Set the previous mode */
+            GetSetContext.Mode = PreviousMode;
+
             /* Initialize the APC */
             KeInitializeApc(&GetSetContext.Apc,
                             &Thread->Tcb,
@@ -221,7 +227,7 @@ NtSetContextThread(IN HANDLE ThreadHandle,
              * I don't know if trying to get your own context makes much
              * sense but we can handle it more efficently.
              */
-            KeContextToTrapFrame(&GetSetContext.Context, NULL, Thread->Tcb.TrapFrame);
+            KeContextToTrapFrame(&GetSetContext.Context, NULL, Thread->Tcb.TrapFrame, PreviousMode);
 
         } else {
 
@@ -230,6 +236,9 @@ NtSetContextThread(IN HANDLE ThreadHandle,
                               NotificationEvent,
                               FALSE);
 
+            /* Set the previous mode */
+            GetSetContext.Mode = PreviousMode;
+
             /* Initialize the APC */
             KeInitializeApc(&GetSetContext.Apc,
                             &Thread->Tcb,