Author: sir_richard
Date: Tue Jan 19 07:34:15 2010
New Revision: 45141
URL:
http://svn.reactos.org/svn/reactos?rev=45141&view=rev
Log:
[NTOS]: Implement KiServiceExit2, C Version. This is used for exiting to user-mode with
full state restore (as in NtContinue, thread startup, NtRaiseException...).
[NTOS]: Implement system service exit (for system calls or KiServiceExit2) in KiExitTrap.
Both iret (for user calls), jmp (for kernel calls) and sysexit (for user fast calls) are
implemented.
[NTOS]: Implement KiThreadStartup in C instead of ASM. It is the first caller of the new
KiServiceExit2. Threads now start up in C!
Modified:
trunk/reactos/ntoskrnl/include/internal/i386/ke.h
trunk/reactos/ntoskrnl/include/internal/ke.h
trunk/reactos/ntoskrnl/include/internal/trap_x.h
trunk/reactos/ntoskrnl/ke/i386/ctxswitch.S
trunk/reactos/ntoskrnl/ke/i386/thrdini.c
trunk/reactos/ntoskrnl/ke/i386/traphdlr.c
Modified: trunk/reactos/ntoskrnl/include/internal/i386/ke.h
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/include/internal/…
==============================================================================
--- trunk/reactos/ntoskrnl/include/internal/i386/ke.h [iso-8859-1] (original)
+++ trunk/reactos/ntoskrnl/include/internal/i386/ke.h [iso-8859-1] Tue Jan 19 07:34:15
2010
@@ -5,8 +5,6 @@
#include "intrin_i.h"
#include "v86m.h"
-
-extern ULONG Ke386CacheAlignment;
//
// Thread Dispatcher Header DebugActive Mask
@@ -288,15 +286,9 @@
NTAPI
KiGetFeatureBits(VOID);
-#ifdef _NTOSKRNL_ /* FIXME: Move flags above to NDK instead of here */
-VOID
-NTAPI
-KiThreadStartup(PKSYSTEM_ROUTINE SystemRoutine,
- PKSTART_ROUTINE StartRoutine,
- PVOID StartContext,
- BOOLEAN UserThread,
- KTRAP_FRAME TrapFrame);
-#endif
+VOID
+NTAPI
+KiThreadStartup(VOID);
NTSTATUS
NTAPI
@@ -438,6 +430,8 @@
extern ULONG KiMXCsrMask;
extern ULONG KeI386CpuType;
extern ULONG KeI386CpuStep;
+extern ULONG Ke386CacheAlignment;
+extern ULONG KiFastSystemCallDisable;
extern UCHAR KiDebugRegisterTrapOffsets[9];
extern UCHAR KiDebugRegisterContextOffsets[9];
extern VOID __cdecl KiTrap02(VOID);
Modified: trunk/reactos/ntoskrnl/include/internal/ke.h
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/include/internal/…
==============================================================================
--- trunk/reactos/ntoskrnl/include/internal/ke.h [iso-8859-1] (original)
+++ trunk/reactos/ntoskrnl/include/internal/ke.h [iso-8859-1] Tue Jan 19 07:34:15 2010
@@ -932,6 +932,12 @@
VOID
);
+VOID
+FASTCALL
+KiServiceExit2(
+ IN PKTRAP_FRAME TrapFrame
+);
+
#ifndef HAL_INTERRUPT_SUPPORT_IN_C
VOID
NTAPI
Modified: trunk/reactos/ntoskrnl/include/internal/trap_x.h
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/include/internal/…
==============================================================================
--- trunk/reactos/ntoskrnl/include/internal/trap_x.h [iso-8859-1] (original)
+++ trunk/reactos/ntoskrnl/include/internal/trap_x.h [iso-8859-1] Tue Jan 19 07:34:15
2010
@@ -207,6 +207,93 @@
FORCEINLINE
VOID
+KiSystemCallReturn(IN PKTRAP_FRAME TrapFrame)
+{
+ /* Restore nonvolatiles, EAX, and do a "jump" back to the kernel caller */
+ __asm__ __volatile__
+ (
+ "movl %0, %%esp\n"
+ "movl %c[b](%%esp), %%ebx\n"
+ "movl %c[s](%%esp), %%esi\n"
+ "movl %c[i](%%esp), %%edi\n"
+ "movl %c[p](%%esp), %%ebp\n"
+ "movl %c[a](%%esp), %%eax\n"
+ "movl %c[e](%%esp), %%edx\n"
+ "addl $%c[v],%%esp\n" /* A WHOLE *KERNEL* frame since we're not
IRET'ing */
+ "jmp *%%edx\n"
+ :
+ : "r"(TrapFrame),
+ [b] "i"(KTRAP_FRAME_EBX),
+ [s] "i"(KTRAP_FRAME_ESI),
+ [i] "i"(KTRAP_FRAME_EDI),
+ [p] "i"(KTRAP_FRAME_EBP),
+ [a] "i"(KTRAP_FRAME_EAX),
+ [e] "i"(KTRAP_FRAME_EIP),
+ [v] "i"(KTRAP_FRAME_ESP)
+ : "%esp"
+ );
+}
+
+FORCEINLINE
+VOID
+KiSystemCallTrapReturn(IN PKTRAP_FRAME TrapFrame)
+{
+ /* Regular interrupt exit, but we only restore EAX as a volatile */
+ __asm__ __volatile__
+ (
+ "movl %0, %%esp\n"
+ "movl %c[b](%%esp), %%ebx\n"
+ "movl %c[s](%%esp), %%esi\n"
+ "movl %c[i](%%esp), %%edi\n"
+ "movl %c[p](%%esp), %%ebp\n"
+ "movl %c[a](%%esp), %%eax\n"
+ "addl $%c[e],%%esp\n"
+ "iret\n"
+ :
+ : "r"(TrapFrame),
+ [b] "i"(KTRAP_FRAME_EBX),
+ [s] "i"(KTRAP_FRAME_ESI),
+ [i] "i"(KTRAP_FRAME_EDI),
+ [p] "i"(KTRAP_FRAME_EBP),
+ [a] "i"(KTRAP_FRAME_EAX),
+ [e] "i"(KTRAP_FRAME_EIP)
+ : "%esp"
+ );
+}
+
+FORCEINLINE
+VOID
+KiSystemCallSysExitReturn(IN PKTRAP_FRAME TrapFrame)
+{
+ /* Restore nonvolatiles, EAX, and do a SYSEXIT back to the user caller */
+ __asm__ __volatile__
+ (
+ "movl %0, %%esp\n"
+ "movl %c[s](%%esp), %%esi\n"
+ "movl %c[b](%%esp), %%ebx\n"
+ "movl %c[i](%%esp), %%edi\n"
+ "movl %c[p](%%esp), %%ebp\n"
+ "movl %c[a](%%esp), %%eax\n"
+ "movl %c[e](%%esp), %%edx\n" /* SYSEXIT says EIP in EDX */
+ "movl %c[x](%%esp), %%ecx\n" /* SYSEXIT says ESP in ECX */
+ "addl $%c[v],%%esp\n" /* A WHOLE *USER* frame since we're not
IRET'ing */
+ "sti\nsysexit\n"
+ :
+ : "r"(TrapFrame),
+ [b] "i"(KTRAP_FRAME_EBX),
+ [s] "i"(KTRAP_FRAME_ESI),
+ [i] "i"(KTRAP_FRAME_EDI),
+ [p] "i"(KTRAP_FRAME_EBP),
+ [a] "i"(KTRAP_FRAME_EAX),
+ [e] "i"(KTRAP_FRAME_EIP),
+ [x] "i"(KTRAP_FRAME_ESP),
+ [v] "i"(KTRAP_FRAME_V86_ES)
+ : "%esp"
+ );
+}
+
+FORCEINLINE
+VOID
KiTrapReturn(IN PKTRAP_FRAME TrapFrame)
{
/* Regular interrupt exit */
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 [iso-8859-1] (original)
+++ trunk/reactos/ntoskrnl/ke/i386/ctxswitch.S [iso-8859-1] Tue Jan 19 07:34:15 2010
@@ -249,77 +249,6 @@
.endfunc
/*++
- * KiThreadStartup
- *
- * The KiThreadStartup routine is the beginning of any thread.
- *
- * Params:
- * SystemRoutine - Pointer to the System Startup Routine. Either
- * PspUserThreadStartup or PspSystemThreadStartup
- *
- * StartRoutine - For Kernel Threads only, specifies the starting execution
- * point of the new thread.
- *
- * StartContext - For Kernel Threads only, specifies a pointer to variable
- * context data to be sent to the StartRoutine above.
- *
- * UserThread - Indicates whether or not this is a user thread. This tells
- * us if the thread has a context or not.
- *
- * TrapFrame - Pointer to the KTHREAD to which the caller wishes to
- * switch from.
- *
- * Returns:
- * Should never return for a system thread. Returns through the System Call
- * Exit Dispatcher for a user thread.
- *
- * Remarks:
- * If a return from a system thread is detected, a bug check will occur.
- *
- *--*/
- .func KiThreadStartup@156
-.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)
- */
- xor ebx, ebx
- 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
- * stack, as parameters to the System Routine
- */
- 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! */
- int 3
-.endfunc
-
-/*++
* KiSwapContextInternal
*
* The KiSwapContextInternal routine switches context to another thread.
Modified: trunk/reactos/ntoskrnl/ke/i386/thrdini.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/ke/i386/thrdini.c…
==============================================================================
--- trunk/reactos/ntoskrnl/ke/i386/thrdini.c [iso-8859-1] (original)
+++ trunk/reactos/ntoskrnl/ke/i386/thrdini.c [iso-8859-1] Tue Jan 19 07:34:15 2010
@@ -43,6 +43,32 @@
} KKINIT_FRAME, *PKKINIT_FRAME;
/* FUNCTIONS *****************************************************************/
+
+VOID
+NTAPI
+KiThreadStartup(VOID)
+{
+ PKTRAP_FRAME TrapFrame;
+ PKSTART_FRAME StartFrame;
+ PKUINIT_FRAME InitFrame;
+
+ /* Get the start and trap frames */
+ InitFrame = KeGetCurrentThread()->KernelStack;
+ StartFrame = &InitFrame->StartFrame;
+ TrapFrame = &InitFrame->TrapFrame;
+
+ /* Lower to APC level */
+ KfLowerIrql(APC_LEVEL);
+
+ /* Call the system routine */
+ StartFrame->SystemRoutine(StartFrame->StartRoutine,
StartFrame->StartContext);
+
+ /* If we returned, we better be a user thread */
+ if (!StartFrame->UserThread) DbgBreakPoint();
+
+ /* Exit to user-mode */
+ KiServiceExit2(TrapFrame);
+}
VOID
NTAPI
Modified: trunk/reactos/ntoskrnl/ke/i386/traphdlr.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/ke/i386/traphdlr.…
==============================================================================
--- trunk/reactos/ntoskrnl/ke/i386/traphdlr.c [iso-8859-1] (original)
+++ trunk/reactos/ntoskrnl/ke/i386/traphdlr.c [iso-8859-1] Tue Jan 19 07:34:15 2010
@@ -62,27 +62,30 @@
/* Check if the previous mode must be restored */
if (__builtin_expect(!SkipBits.SkipPreviousMode, 0)) /* More INTS than SYSCALLs */
{
+ /* Restore it */
+ KeGetCurrentThread()->PreviousMode = TrapFrame->PreviousPreviousMode;
+ }
+
+ /* Check if there are active debug registers */
+ if (__builtin_expect(TrapFrame->Dr7 & ~DR7_RESERVED_MASK, 0))
+ {
/* Not handled yet */
UNIMPLEMENTED;
+ DbgBreakPoint();
+ KiDumpTrapFrame(TrapFrame);
while (TRUE);
}
-
- /* Check if there are active debug registers */
- if (__builtin_expect(TrapFrame->Dr7 & ~DR7_RESERVED_MASK, 0))
+
+ /* Check if this was a V8086 trap */
+ if (__builtin_expect(TrapFrame->EFlags & EFLAGS_V86_MASK, 0))
KiTrapReturn(TrapFrame);
+
+ /* Check if the trap frame was edited */
+ if (__builtin_expect(!(TrapFrame->SegCs & FRAME_EDITED), 0))
{
/* Not handled yet */
UNIMPLEMENTED;
- while (TRUE);
- }
-
- /* Check if this was a V8086 trap */
- if (__builtin_expect(TrapFrame->EFlags & EFLAGS_V86_MASK, 0))
KiTrapReturn(TrapFrame);
-
- /* Check if the trap frame was edited */
- if (__builtin_expect(!(TrapFrame->SegCs & FRAME_EDITED), 0))
- {
- /* Not handled yet */
- UNIMPLEMENTED;
+ KiDumpTrapFrame(TrapFrame);
+ DbgBreakPoint();
while (TRUE);
}
@@ -114,13 +117,37 @@
/* Check for system call -- a system call skips volatiles! */
if (__builtin_expect(SkipBits.SkipVolatiles, 0)) /* More INTs than SYSCALLs */
{
- /* Not handled yet */
- /*
- * When we do the system call handler through this path, we need
- * to have some sort to restore the kernel EAX instead of pushing
- * back the user EAX. We'll figure it out...
- */
- DPRINT1("Warning: caller doesn't want volatiles restored\n");
+ /* Kernel call or user call? */
+ if (__builtin_expect(KiUserTrap(TrapFrame), 1)) /* More Ring 3 than 0 */
+ {
+ /* Is SYSENTER supported and/or enabled, or are we stepping code? */
+ if (__builtin_expect((KiFastSystemCallDisable) ||
+ (TrapFrame->EFlags & EFLAGS_TF), 0))
+ {
+ /* Exit normally */
+ KiSystemCallTrapReturn(TrapFrame);
+ }
+ else
+ {
+ /* Restore user FS */
+ Ke386SetFs(KGDT_R3_TEB | RPL_MASK);
+
+ /* Remove interrupt flag */
+ TrapFrame->EFlags &= ~EFLAGS_INTERRUPT_MASK;
+ __writeeflags(TrapFrame->EFlags);
+
+ /* Exit through SYSEXIT */
+ KiSystemCallSysExitReturn(TrapFrame);
+ }
+ }
+ else
+ {
+ /* Restore EFLags */
+ __writeeflags(TrapFrame->EFlags);
+
+ /* Call is kernel, so do a jump back since this wasn't a real INT */
+ KiSystemCallReturn(TrapFrame);
+ }
}
else
{
@@ -185,6 +212,20 @@
/* Now exit the trap for real */
KiExitTrap(TrapFrame, KTE_SKIP_PM_BIT);
+}
+
+VOID
+FASTCALL
+KiServiceExit2(IN PKTRAP_FRAME TrapFrame)
+{
+ /* Disable interrupts until we return */
+ _disable();
+
+ /* Check for APC delivery */
+ KiCheckForApcDelivery(TrapFrame);
+
+ /* Now exit the trap for real */
+ KiExitTrap(TrapFrame, 0);
}
/* TRAP ENTRY CODE ************************************************************/