[ros-dev] Re: [ros-diffs] [ion] 20911: - Fix some nasty context
switch bugs:
Hartmut Birr
osexpert at googlemail.com
Mon Jan 16 18:28:56 CET 2006
ion at 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 at 0
> @KiSwapContextInternal at 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
More information about the Ros-dev
mailing list