ion@svn.reactos.org wrote:
- 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* @@ -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]
Now eax points to the trap frame of the thread we will switch to.
- /* 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
The compare operation uses eax which points to the thread we will switch to. We must use the trap frame from the thread we will switch from.
/* 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
Eax points to the wrong stack. See above.
NoAdjust:
- /* Push ESP0 Value */
- push ss:[ebp+KTSS_ESP0]
- /* Set new ESP0 */
- mov [ebp+KTSS_ESP0], eax
Now, we are using the wrong kernel stack on the next exception.
- Hartmut