- 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. */