- Fix some nasty context switch bugs:
  * We did not update the KPCR's stacklimit/initialstack with the new thread's stacklimit/initialstack.
  * We always assumed V86 frame bias in KeInitializeThreadContext.
  * We did not properly update ESP0 during context switch, to make space for the NPX frame and V86 bias.
  * We did not update fs:18h to point to the new TEB.
  * We did not clear out GS when switching processes, nor update the TSS's cr3.
  * If a new LDT was being updated, we over-wrote EBP (which was supposed to point to the TSS) by the GDT pointer.
  * We used a push/pop esp0 hack which hid the fact we never updated esp0.
Modified: trunk/reactos/ntoskrnl/ke/i386/ctxswitch.S
Modified: trunk/reactos/ntoskrnl/ke/i386/thread.c

Modified: trunk/reactos/ntoskrnl/ke/i386/ctxswitch.S
--- trunk/reactos/ntoskrnl/ke/i386/ctxswitch.S	2006-01-15 22:26:10 UTC (rev 20910)
+++ trunk/reactos/ntoskrnl/ke/i386/ctxswitch.S	2006-01-16 02:21:22 UTC (rev 20911)
@@ -57,7 +57,7 @@
 .globl _KiThreadStartup@156
 _KiThreadStartup@156:
 
-    /* 
+    /*
      * Clear all the non-volatile registers, so the thread won't be tempted to
      * expect any static data (like some badly coded usermode/win9x apps do)
      */
@@ -65,11 +65,11 @@
     xor esi, esi
     xor edi, edi
     xor ebp, ebp
-    
+
     /* It's now safe to go to APC */
     mov ecx, APC_LEVEL
     call @KfLowerIrql@4
-    
+
     /* 
      * Call the System Routine which is right on our stack now.
      * After we pop the pointer, the Start Routine/Context will be on the 
@@ -77,18 +77,18 @@
      */
     pop eax
     call eax
-    
+
     /* The thread returned... was it a user-thread? */
     pop ecx
     or ecx, ecx
     jz BadThread
-    
+
     /* Yes it was, set our trapframe for the System Call Exit Dispatcher */
     mov ebp, esp
-    
+
     /* Exit back to user-mode */
     jmp _KiServiceExit2
-    
+
 BadThread:
 
     /* A system thread returned...this is very bad! */
@@ -114,10 +114,6 @@
  *--*/
 .globl @KiSwapContextInternal@0
 @KiSwapContextInternal@0:
-#ifdef KDBG
-    //jmp SaveTrapFrameForKDB
-SaveTrapFrameForKDB_Return:
-#endif
 
     /* Get the PCR. It's faster to use ebx+offset then fs:offset */
     mov ebx, [fs:KPCR_SELF]
@@ -132,24 +128,36 @@
     cli
 
     /* Save the initial stack in EAX */
-    mov eax, [edi+KTHREAD_INITIAL_STACK]
+    mov eax, [esi+KTHREAD_INITIAL_STACK]
 
+    /* Save the stack limit in ecx */
+    mov ecx, [esi+KTHREAD_STACK_LIMIT]
+
+    /* Make space for the NPX Frame */
+    sub eax, NPX_FRAME_LENGTH
+
+    /* Set the KPCR stack values */
+    mov [ebx+KPCR_INITIAL_STACK], eax
+    mov [ebx+KPCR_STACK_LIMIT], ecx
+
 #ifdef CONFIG_SMP
     /* Save FPU state if the thread has used it. */
+    mov ecx, [edi+KTHREAD_INITIAL_STACK]
+    sub ecx, NPX_FRAME_LENGTH
     mov dword ptr [ebx+KPCR_NPX_THREAD], 0
     test byte ptr [edi+KTHREAD_NPX_STATE], NPX_STATE_DIRTY
     jz 3f
     cmp dword ptr _KeI386FxsrPresent, 0
     je 1f
-    fxsave [eax-SIZEOF_FX_SAVE_AREA]
+    fxsave [ecx]
     jmp 2f
 1:
-    fnsave [eax-SIZEOF_FX_SAVE_AREA]
+    fnsave [ecx]
 2:
     mov byte ptr [edi+KTHREAD_NPX_STATE], NPX_STATE_VALID
 3:
 #endif /* CONFIG_SMP */
-    
+
     /* Save the stack pointer in this processors TSS */
     mov ebp, [ebx+KPCR_TSS]
 
@@ -158,12 +166,17 @@
     jnz NoAdjust
 
     /* Bias esp */
-    //sub dword ptr ss:[ebp+KTSS_ESP0], KTRAP_FRAME_V86_GS - KTRAP_FRAME_SS
+    sub eax, KTRAP_FRAME_V86_GS - KTRAP_FRAME_SS
 
 NoAdjust:
-    /* Push ESP0 Value */
-    push ss:[ebp+KTSS_ESP0]
 
+    /* Set new ESP0 */
+    mov [ebp+KTSS_ESP0], eax
+
+    /* Set TEB pointer */
+    mov eax, [esi+KTHREAD_TEB]
+    mov [ebx+KPCR_TEB], eax
+
     /* Check if address space switch is needed */
     mov eax, [esi+KTHREAD_APCSTATE_PROCESS]
     cmp eax, [edi+KTHREAD_APCSTATE_PROCESS]
@@ -172,52 +185,57 @@
     /* Switch stacks */
     mov [edi+KTHREAD_KERNEL_STACK], esp
     mov esp, [esi+KTHREAD_KERNEL_STACK]
-    
+
     jz	NoAddressSpaceSwitch
-    
+
+    /* Clear gs */
+    xor ecx, ecx
+    mov gs, cx
+
     /* Switch address space */
     mov cr3, eax
-   
-NoAddressSpaceSwitch:   
-   
+    mov [ebp+KTSS_CR3], eax
+
+NoAddressSpaceSwitch:
+
     /* Stack is OK, safe to enable interrupts now */
-    sti 
+    sti
 
     /* Check if address space switch is needed (the result from above is valid) */
     /* If they match, then use the fast-path and skip all this */
     jz SameProcess
-    
+
     /* Get the new Process. */
     mov edi, [esi+KTHREAD_APCSTATE_PROCESS]
-    
+
     /* Check if we need an LDT */
     xor eax, eax
     cmp [edi+KPROCESS_LDT_DESCRIPTOR0], eax
     jz NoLdt
-    
+
     /* Write the LDT Selector */
-    mov ebp, [ebx+KPCR_GDT]
+    mov ecx, [ebx+KPCR_GDT]
     mov eax, [edi+KPROCESS_LDT_DESCRIPTOR0]
-    mov [ebp+KGDT_LDT], eax
+    mov [ecx+KGDT_LDT], eax
     mov eax, [edi+KPROCESS_LDT_DESCRIPTOR1]
-    mov [ebp+KGDT_LDT+4], eax
-    
+    mov [ecx+KGDT_LDT+4], eax
+
     /* Save LDT Selector */
     mov eax, KGDT_LDT
-        
+
 NoLdt:
-    
+
     /* Load LDT */
     lldt ax
-  
+
     /* Get the IOPM */
     mov ecx, [edi+KPROCESS_IOPM_OFFSET]
 
     /* Set current IOPM offset in the TSS */
     mov [ebp+KTSS_IOMAPBASE], cx
-    
+
 SameProcess:
-    
+
     /* Set the TEB */
     mov eax, [esi+KTHREAD_TEB]
     mov ecx, [ebx+KPCR_GDT]
@@ -225,10 +243,10 @@
     shr eax, 16
     mov [ecx+0x3C], al
     mov [ecx+0x3F], ah
-    
+
     /* Increase context switches */
     inc dword ptr [esi+KTHREAD_CONTEXT_SWITCHES]
-    
+
     /* Set TS in cr0 to catch FPU code and load the FPU state when needed */
 #ifndef CONFIG_SMP
     cmp [ebx+KPCR_NPX_THREAD], esi
@@ -238,10 +256,7 @@
     or eax, X86_CR0_TS
     mov cr0, eax
 4:
-    
-    /* Restore the stack pointer in this processors TSS */
-    pop ss:[ebp+KTSS_ESP0]
-    
+
     /* Restore exception list */
     pop [ebx+KPCR_EXCEPTION_LIST]
 
@@ -307,106 +322,4 @@
     /* Clean stack */
     add esp, 4 * 4
     ret
-    
-#ifdef KDBG
 
-SaveTrapFrameForKDB:
-    /* Set up a trap frame */
-    pushf                                        // 0x70
-    push cs                                      // 0x6C
-    push 0             /* Error Code */          // 0x64
-    push ebp                                     // 0x60
-    push ebx
-    
-    /* Fake Interrupt Stack */
-    mov ebp, [esp+20]  /* Eip */
-    mov ebx, [esp+16]  /* Eflags */
-    mov [esp+20], ebx
-    mov ebx, [esp+12]  /* Cs */
-    mov [esp+16], ebx
-    mov [esp+12], ebp
-    
-    push esi
-    push edi
-    push fs
-    push -1            /* Exception List */      // 0x4C
-    push 0             /* Previous Mode */       // 0x48
-    push eax
-    push ecx
-    push edx
-    push ds
-    push es
-    push gs                                      // 0x30
-
-    mov eax, dr7
-    push eax           /* Dr7 */
-    /* Clear breakpoint enables in dr7. */
-    and eax, 0xffff0000
-    mov dr7, eax
-    mov eax, dr6
-    push eax           /* Dr6 */
-    mov eax, dr3
-    push eax           /* Dr3 */
-    mov eax, dr2
-    push eax           /* Dr2 */
-    mov eax, dr1
-    push eax           /* Dr1 */
-    mov eax, dr0
-    push eax           /* Dr0 */
-        
-    lea eax, [esp+0x58]
-    push eax           /* TempEsp */
-    push ss            /* TempSegSs */
-    push 0             /* DebugPointer */
-    push -1            /* DebugArgMark */
-    push [esp+60]      /* Debug EIP */           // 0x4
-    push ebp           /* Debug EBP */           // 0x0
-    
-    /* Set Stack */
-    mov ebp, esp
-    
-    /* Push old Trap Frame */
-    push [edi+KTHREAD_TRAP_FRAME]
-    
-    /* Save new one */
-    mov [edi+KTHREAD_TRAP_FRAME], ebp
-    
-    /* Restore EBP, EBX and EAX */
-    mov ebp, [ebp+KTRAP_FRAME_EBP]
-    mov ebx, [ebp+KTRAP_FRAME_EBX]
-    mov eax, [ebp+KTRAP_FRAME_EAX]
-    
-    /* Return EIP */
-    push offset RestoreTrapFrameForKDB
-        
-    /* Jump to normal code */
-    jmp SaveTrapFrameForKDB_Return
-
-RestoreTrapFrameForKDB:
-  
-    /* Restore the old trapframe */
-    pop [esi+KTHREAD_TRAP_FRAME]
-        
-    /* Pop unused portions of the trap frame */
-    add esp, 0x30
-
-    /* Restore registers from Trap frame */
-    pop gs
-    pop es
-    pop ds
-    pop edx
-    pop ecx
-    pop eax
-    add esp, 8           /* ExceptionList and PreviousMode */
-    pop fs
-    pop edi
-    pop esi
-    pop ebx
-    pop ebp
-    add esp, 4           /* ErrorCode */
-
-    /* Return to the caller. */
-    iret
-#endif /* KDBG */
-
-

Modified: trunk/reactos/ntoskrnl/ke/i386/thread.c
--- trunk/reactos/ntoskrnl/ke/i386/thread.c	2006-01-15 22:26:10 UTC (rev 20910)
+++ trunk/reactos/ntoskrnl/ke/i386/thread.c	2006-01-16 02:21:22 UTC (rev 20911)
@@ -14,7 +14,6 @@
 
 typedef struct _KSHARED_CTXSWITCH_FRAME
 {
-    ULONG Esp0;
     PVOID ExceptionList;
     PVOID RetEip;
 } KSHARED_CTXSWITCH_FRAME, *PKSHARED_CTXSWITCH_FRAME;
@@ -232,9 +231,6 @@
 
     /* And set up the Context Switch Frame */
     CtxSwitchFrame->RetEip = KiThreadStartup;
-    CtxSwitchFrame->Esp0 = (ULONG_PTR)Thread->InitialStack -
-                                      sizeof(FX_SAVE_AREA) -
-                                      0x10;
     CtxSwitchFrame->ExceptionList = (PVOID)0xFFFFFFFF;
 
     /* Save back the new value of the kernel stack. */