mirror of
https://github.com/reactos/reactos.git
synced 2024-12-28 18:15:11 +00:00
[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! svn path=/trunk/; revision=45141
This commit is contained in:
parent
bf8b9467dc
commit
aba18024bd
6 changed files with 173 additions and 90 deletions
|
@ -6,8 +6,6 @@
|
|||
#include "intrin_i.h"
|
||||
#include "v86m.h"
|
||||
|
||||
extern ULONG Ke386CacheAlignment;
|
||||
|
||||
//
|
||||
// Thread Dispatcher Header DebugActive Mask
|
||||
//
|
||||
|
@ -288,15 +286,9 @@ ULONG
|
|||
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
|
||||
KiThreadStartup(VOID);
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
|
@ -438,6 +430,8 @@ extern ULONG KeI386FxsrPresent;
|
|||
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);
|
||||
|
|
|
@ -932,6 +932,12 @@ KiEndUnexpectedRange(
|
|||
VOID
|
||||
);
|
||||
|
||||
VOID
|
||||
FASTCALL
|
||||
KiServiceExit2(
|
||||
IN PKTRAP_FRAME TrapFrame
|
||||
);
|
||||
|
||||
#ifndef HAL_INTERRUPT_SUPPORT_IN_C
|
||||
VOID
|
||||
NTAPI
|
||||
|
|
|
@ -205,6 +205,93 @@ KiDispatchException2Args(IN NTSTATUS Code,
|
|||
KiDispatchExceptionFromTrapFrame(Code, Address, 2, P1, P2, 0, TrapFrame);
|
||||
}
|
||||
|
||||
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)
|
||||
|
|
|
@ -248,77 +248,6 @@ Return:
|
|||
|
||||
.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
|
||||
*
|
||||
|
|
|
@ -44,6 +44,32 @@ typedef struct _KKINIT_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
|
||||
KiInitializeContextThread(IN PKTHREAD Thread,
|
||||
|
|
|
@ -62,9 +62,8 @@ KiExitTrap(IN PKTRAP_FRAME TrapFrame,
|
|||
/* Check if the previous mode must be restored */
|
||||
if (__builtin_expect(!SkipBits.SkipPreviousMode, 0)) /* More INTS than SYSCALLs */
|
||||
{
|
||||
/* Not handled yet */
|
||||
UNIMPLEMENTED;
|
||||
while (TRUE);
|
||||
/* Restore it */
|
||||
KeGetCurrentThread()->PreviousMode = TrapFrame->PreviousPreviousMode;
|
||||
}
|
||||
|
||||
/* Check if there are active debug registers */
|
||||
|
@ -72,6 +71,8 @@ KiExitTrap(IN PKTRAP_FRAME TrapFrame,
|
|||
{
|
||||
/* Not handled yet */
|
||||
UNIMPLEMENTED;
|
||||
DbgBreakPoint();
|
||||
KiDumpTrapFrame(TrapFrame);
|
||||
while (TRUE);
|
||||
}
|
||||
|
||||
|
@ -83,6 +84,8 @@ KiExitTrap(IN PKTRAP_FRAME TrapFrame,
|
|||
{
|
||||
/* Not handled yet */
|
||||
UNIMPLEMENTED;
|
||||
KiDumpTrapFrame(TrapFrame);
|
||||
DbgBreakPoint();
|
||||
while (TRUE);
|
||||
}
|
||||
|
||||
|
@ -114,13 +117,37 @@ KiExitTrap(IN PKTRAP_FRAME TrapFrame,
|
|||
/* 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
|
||||
{
|
||||
|
@ -187,6 +214,20 @@ KiEoiHelper(IN PKTRAP_FRAME TrapFrame)
|
|||
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 ************************************************************/
|
||||
|
||||
VOID
|
||||
|
|
Loading…
Reference in a new issue