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=2362…
==============================================================================
--- 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?…
==============================================================================
--- 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. */