Author: ion Date: Sun Aug 20 23:55:32 2006 New Revision: 23621
URL: http://svn.reactos.org/svn/reactos?rev=23621&view=rev Log: - Add support for APC-delivery after context-switch (not yet programmed) - Detect and crash if context switch is done inside a DPC. - Switch kernel stack a bit earlier - Don't switch address space if we're still in the same process, and fix some duplicated code that was mixed up together. - Move LDT setup out-of-line.
Modified: trunk/reactos/include/ndk/asm.h trunk/reactos/ntoskrnl/ke/i386/ctxswitch.S trunk/reactos/ntoskrnl/ke/i386/thread.c
Modified: trunk/reactos/include/ndk/asm.h URL: http://svn.reactos.org/svn/reactos/trunk/reactos/include/ndk/asm.h?rev=23621... ============================================================================== --- trunk/reactos/include/ndk/asm.h (original) +++ trunk/reactos/include/ndk/asm.h Sun Aug 20 23:55:32 2006 @@ -148,6 +148,7 @@ #define KPCR_DR6 0x428 #define KPCR_DR7 0x42C #define KPCR_SYSTEM_CALLS 0x6B8 +#define KPCR_PRCB_DPC_ROUTINE_ACTIVE 0x994
// // KGDTENTRY Offsets @@ -383,6 +384,7 @@ #define APC_INDEX_MISMATCH 0x01 #define IRQL_GT_ZERO_AT_SYSTEM_SERVICE 0x4A #define UNEXPECTED_KERNEL_MODE_TRAP 0x7F +#define ATTEMPTED_SWITCH_FROM_DPC 0xB8 #endif
//
Modified: trunk/reactos/ntoskrnl/ke/i386/ctxswitch.S URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/ke/i386/ctxswitch.... ============================================================================== --- trunk/reactos/ntoskrnl/ke/i386/ctxswitch.S (original) +++ trunk/reactos/ntoskrnl/ke/i386/ctxswitch.S Sun Aug 20 23:55:32 2006 @@ -115,19 +115,30 @@ .globl @KiSwapContextInternal@0 @KiSwapContextInternal@0:
+ /* Save WaitIrql APC-bypass in EFLAGS */ + or cl, cl + /* Set the Thread to running */ mov byte ptr [esi+KTHREAD_STATE], Running
+ /* Save the flags */ + pushf + /* Save the Exception list */ push [ebx+KPCR_EXCEPTION_LIST] - + + /* DPC shouldn't be active */ + cmp byte ptr [ebx+KPCR_PRCB_DPC_ROUTINE_ACTIVE], 0 + jnz BugCheckDpc + /* Switching, disable interrupts now */ cli
- /* Save the initial stack in EAX */ + /* Update kernel stack */ + mov [edi+KTHREAD_KERNEL_STACK], esp + + /* Get stack pointers */ mov eax, [esi+KTHREAD_INITIAL_STACK] - - /* Save the stack limit in ecx */ mov ecx, [esi+KTHREAD_STACK_LIMIT]
/* Make space for the NPX Frame */ @@ -137,8 +148,7 @@ mov [ebx+KPCR_INITIAL_STACK], eax mov [ebx+KPCR_STACK_LIMIT], ecx
- /* Save the stack pointer in this processors TSS */ - mov ebp, [ebx+KPCR_TSS] + /* FIXME Check and update CR0 */
/* 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 @@ -150,38 +160,22 @@ NoAdjust:
/* Set new ESP0 */ - mov [ebp+KTSS_ESP0], eax + mov ecx, [ebx+KPCR_TSS] + mov [ecx+KTSS_ESP0], eax + + /* Switch to new stack */ + mov esp, [esi+KTHREAD_KERNEL_STACK]
/* Set TEB pointer */ mov eax, [esi+KTHREAD_TEB] mov [ebx+KPCR_TEB], eax
+ /* Stack is OK, safe to enable interrupts now */ + sti + /* Check if address space switch is needed */ mov eax, [esi+KTHREAD_APCSTATE_PROCESS] cmp eax, [edi+KTHREAD_APCSTATE_PROCESS] - mov eax, [eax+KPROCESS_DIRECTORY_TABLE_BASE] - - /* 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 - mov [ebp+KTSS_CR3], eax - -NoAddressSpaceSwitch: - - /* Stack is OK, safe to enable interrupts now */ - 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. */ @@ -190,31 +184,31 @@ /* Check if we need an LDT */ xor eax, eax cmp [edi+KPROCESS_LDT_DESCRIPTOR0], eax - jz NoLdt - - /* Write the LDT Selector */ - mov ecx, [ebx+KPCR_GDT] - mov eax, [edi+KPROCESS_LDT_DESCRIPTOR0] - mov [ecx+KGDT_LDT], eax - mov eax, [edi+KPROCESS_LDT_DESCRIPTOR1] - mov [ecx+KGDT_LDT+4], eax - - /* Save LDT Selector */ - mov eax, KGDT_LDT - -NoLdt: - + jnz LdtStuff + +LoadLdt: /* Load LDT */ lldt ax
- /* Get the IOPM */ + /* Clear gs */ + xor eax, eax + mov gs, ax + + /* Get the address space */ + mov eax, [edi+KPROCESS_DIRECTORY_TABLE_BASE] + + /* Get the IOPM and TSS */ + mov ebp, [ebx+KPCR_TSS] mov ecx, [edi+KPROCESS_IOPM_OFFSET] + + /* Switch address space */ + mov [ebp+KTSS_CR3], eax + mov cr3, eax
/* 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,12 +219,34 @@
/* Increase context switches */ inc dword ptr [esi+KTHREAD_CONTEXT_SWITCHES] + //inc dword ptr [esi+KPRC_PRCB_CONTEXT_SWITCHES]
/* Restore exception list */ pop [ebx+KPCR_EXCEPTION_LIST]
- /* Return */ + /* Retore EFLAGS */ + popf + + /* Return no APC pending */ + xor eax, eax ret + +LdtStuff: + + /* Write the LDT Selector */ + mov ecx, [ebx+KPCR_GDT] + mov eax, [edi+KPROCESS_LDT_DESCRIPTOR0] + mov [ecx+KGDT_LDT], eax + mov eax, [edi+KPROCESS_LDT_DESCRIPTOR1] + mov [ecx+KGDT_LDT+4], eax + + /* Save LDT Selector */ + mov eax, KGDT_LDT + jmp LoadLdt + +BugCheckDpc: + push ATTEMPTED_SWITCH_FROM_DPC + call _KeBugCheck@4
/*++ * KiSwapContext @@ -275,11 +291,11 @@ /* Get the New Thread */ mov esi, edx
+ /* Save it as Current thread */ + mov fs:[KPCR_CURRENT_THREAD], esi + /* Get the wait IRQL */ movzx ecx, byte ptr [edi+KTHREAD_WAIT_IRQL] - - /* Save it as Current thread */ - mov fs:[KPCR_CURRENT_THREAD], esi
/* Do the swap with the registers correctly setup */ call @KiSwapContextInternal@0
Modified: trunk/reactos/ntoskrnl/ke/i386/thread.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/ke/i386/thread.c?r... ============================================================================== --- trunk/reactos/ntoskrnl/ke/i386/thread.c (original) +++ trunk/reactos/ntoskrnl/ke/i386/thread.c Sun Aug 20 23:55:32 2006 @@ -15,6 +15,7 @@ typedef struct _KSHARED_CTXSWITCH_FRAME { PVOID ExceptionList; + ULONG Flags; PVOID RetEip; } KSHARED_CTXSWITCH_FRAME, *PKSHARED_CTXSWITCH_FRAME;
@@ -230,6 +231,7 @@
/* And set up the Context Switch Frame */ CtxSwitchFrame->RetEip = KiThreadStartup; + CtxSwitchFrame->Flags = EFLAGS_INTERRUPT_MASK; CtxSwitchFrame->ExceptionList = (PVOID)0xFFFFFFFF;
/* Save back the new value of the kernel stack. */