[NTOSKRNL/KE/AMD64]

- Fix stack alignment in KiSwitchToBootStack
- Handle ExceptionFrame == NULL in KeContextToTrapFrame and KeTrapFrameToContext
- Implement KiSwapContextInternal
- Fix KiSwapContext and KiThreadStartup
- Implement dispatching of user mode exceptions including in-paging of module data used by the kernel-debugger
- Implement KeInitializeInterrupt, KeConnectInterrupt, KeSynchronizeExecution
- Don't zero more than the actual PCR size in KiInitializePcr
- Add asm function KiInitializeSegments to initialize the segment selectors to proper values
- Initialize system call entrypoints in KiInitializeCpu
- Implement KiDpcInterruptHandler, KiIdleLoop, KiInitializeUserApc, KiSwapProcess, KiSystemCallHandler, KiInitializeContextThread, KiSwapContextResume
- Implement asm functions KiRetireDpcList, KiInterruptDispatch, KiSystemCallEntry64, KiZwSystemService

svn path=/trunk/; revision=55405
This commit is contained in:
Timo Kreuzer 2012-02-04 11:32:13 +00:00
parent de74279d5b
commit 597c140370
9 changed files with 1354 additions and 322 deletions

View file

@ -31,7 +31,9 @@ PUBLIC KiSwitchToBootStack
mov ax, HEX(18)
mov ss, ax
mov rsp, rcx
sub rsp, HEX(300) // FIXME
// Note: 8 bytes extra to compensate for the missing return address on
// the stack. On function entry the stack is unaligned by 8!!
sub rsp, HEX(308) // FIXME
.ENDPROLOG
jmp KiSystemStartupBootStack

View file

@ -24,12 +24,16 @@ KeContextToTrapFrame(IN PCONTEXT Context,
{
KIRQL OldIrql;
/* Make sure we have an amd64 context, then remove the flag */
ASSERT(ContextFlags & CONTEXT_AMD64);
ContextFlags &= ~CONTEXT_AMD64;
/* Do this at APC_LEVEL */
OldIrql = KeGetCurrentIrql();
if (OldIrql < APC_LEVEL) KeRaiseIrql(APC_LEVEL, &OldIrql);
/* Handle integer registers */
if ((Context->ContextFlags & CONTEXT_INTEGER) == CONTEXT_INTEGER)
if (ContextFlags & CONTEXT_INTEGER)
{
TrapFrame->Rax = Context->Rax;
TrapFrame->Rbx = Context->Rbx;
@ -42,15 +46,18 @@ KeContextToTrapFrame(IN PCONTEXT Context,
TrapFrame->R9 = Context->R9;
TrapFrame->R10 = Context->R10;
TrapFrame->R11 = Context->R11;
ExceptionFrame->R12 = Context->R12;
ExceptionFrame->R13 = Context->R13;
ExceptionFrame->R14 = Context->R14;
ExceptionFrame->R15 = Context->R15;
if (ExceptionFrame)
{
ExceptionFrame->R12 = Context->R12;
ExceptionFrame->R13 = Context->R13;
ExceptionFrame->R14 = Context->R14;
ExceptionFrame->R15 = Context->R15;
}
}
/* Handle floating point registers */
if (((Context->ContextFlags & CONTEXT_FLOATING_POINT) ==
CONTEXT_FLOATING_POINT) && (Context->SegCs & MODE_MASK))
if ((ContextFlags & CONTEXT_FLOATING_POINT) &&
(Context->SegCs & MODE_MASK))
{
TrapFrame->Xmm0 = Context->Xmm0;
TrapFrame->Xmm1 = Context->Xmm1;
@ -58,20 +65,23 @@ KeContextToTrapFrame(IN PCONTEXT Context,
TrapFrame->Xmm3 = Context->Xmm3;
TrapFrame->Xmm4 = Context->Xmm4;
TrapFrame->Xmm5 = Context->Xmm5;
ExceptionFrame->Xmm6 = Context->Xmm6;
ExceptionFrame->Xmm7 = Context->Xmm7;
ExceptionFrame->Xmm8 = Context->Xmm8;
ExceptionFrame->Xmm9 = Context->Xmm9;
ExceptionFrame->Xmm10 = Context->Xmm10;
ExceptionFrame->Xmm11 = Context->Xmm11;
ExceptionFrame->Xmm12 = Context->Xmm12;
ExceptionFrame->Xmm13 = Context->Xmm13;
ExceptionFrame->Xmm14 = Context->Xmm14;
ExceptionFrame->Xmm15 = Context->Xmm15;
if (ExceptionFrame)
{
ExceptionFrame->Xmm6 = Context->Xmm6;
ExceptionFrame->Xmm7 = Context->Xmm7;
ExceptionFrame->Xmm8 = Context->Xmm8;
ExceptionFrame->Xmm9 = Context->Xmm9;
ExceptionFrame->Xmm10 = Context->Xmm10;
ExceptionFrame->Xmm11 = Context->Xmm11;
ExceptionFrame->Xmm12 = Context->Xmm12;
ExceptionFrame->Xmm13 = Context->Xmm13;
ExceptionFrame->Xmm14 = Context->Xmm14;
ExceptionFrame->Xmm15 = Context->Xmm15;
}
}
/* Handle control registers */
if ((Context->ContextFlags & CONTEXT_CONTROL) == CONTEXT_CONTROL)
if (ContextFlags & CONTEXT_CONTROL)
{
/* Check if this was a Kernel Trap */
if (Context->SegCs == KGDT64_R0_CODE)
@ -94,7 +104,7 @@ KeContextToTrapFrame(IN PCONTEXT Context,
}
/* Handle segment selectors */
if ((Context->ContextFlags & CONTEXT_SEGMENTS) == CONTEXT_SEGMENTS)
if (ContextFlags & CONTEXT_SEGMENTS)
{
/* Check if this was a Kernel Trap */
if (Context->SegCs == KGDT64_R0_CODE)
@ -116,8 +126,7 @@ KeContextToTrapFrame(IN PCONTEXT Context,
}
/* Handle debug registers */
if ((Context->ContextFlags & CONTEXT_DEBUG_REGISTERS) ==
CONTEXT_DEBUG_REGISTERS)
if (ContextFlags & CONTEXT_DEBUG_REGISTERS)
{
/* Copy the debug registers */
TrapFrame->Dr0 = Context->Dr0;
@ -158,10 +167,14 @@ KeTrapFrameToContext(IN PKTRAP_FRAME TrapFrame,
Context->R9 = TrapFrame->R9;
Context->R10 = TrapFrame->R10;
Context->R11 = TrapFrame->R11;
Context->R12 = ExceptionFrame->R12;
Context->R13 = ExceptionFrame->R13;
Context->R14 = ExceptionFrame->R14;
Context->R15 = ExceptionFrame->R15;
if (ExceptionFrame)
{
Context->R12 = ExceptionFrame->R12;
Context->R13 = ExceptionFrame->R13;
Context->R14 = ExceptionFrame->R14;
Context->R15 = ExceptionFrame->R15;
}
}
/* Handle floating point registers */
@ -174,16 +187,19 @@ KeTrapFrameToContext(IN PKTRAP_FRAME TrapFrame,
Context->Xmm3 = TrapFrame->Xmm3;
Context->Xmm4 = TrapFrame->Xmm4;
Context->Xmm5 = TrapFrame->Xmm5;
Context->Xmm6 = ExceptionFrame->Xmm6;
Context->Xmm7 = ExceptionFrame->Xmm7;
Context->Xmm8 = ExceptionFrame->Xmm8;
Context->Xmm9 = ExceptionFrame->Xmm9;
Context->Xmm10 = ExceptionFrame->Xmm10;
Context->Xmm11 = ExceptionFrame->Xmm11;
Context->Xmm12 = ExceptionFrame->Xmm12;
Context->Xmm13 = ExceptionFrame->Xmm13;
Context->Xmm14 = ExceptionFrame->Xmm14;
Context->Xmm15 = ExceptionFrame->Xmm15;
if (ExceptionFrame)
{
Context->Xmm6 = ExceptionFrame->Xmm6;
Context->Xmm7 = ExceptionFrame->Xmm7;
Context->Xmm8 = ExceptionFrame->Xmm8;
Context->Xmm9 = ExceptionFrame->Xmm9;
Context->Xmm10 = ExceptionFrame->Xmm10;
Context->Xmm11 = ExceptionFrame->Xmm11;
Context->Xmm12 = ExceptionFrame->Xmm12;
Context->Xmm13 = ExceptionFrame->Xmm13;
Context->Xmm14 = ExceptionFrame->Xmm14;
Context->Xmm15 = ExceptionFrame->Xmm15;
}
}
/* Handle control registers */

View file

@ -3,7 +3,7 @@
* PROJECT: ReactOS kernel
* FILE: ntoskrnl/ke/amd64/ctxswitch.S
* PURPOSE: Thread Context Switching
*
*
* PROGRAMMER: Timo kreuzer (timo.kreuzer@reactos.org)
*/
@ -12,46 +12,66 @@
#include <asm.inc>
#include <ksamd64.inc>
EXTERN KiSwapContextResume:PROC
/* FUNCTIONS ****************************************************************/
.code64
/*++
* KiThreadStartup
/*!
* \name KiThreadStartup
*
* \brief
* The KiThreadStartup routine is the beginning of any thread.
*
* Params:
* SystemRoutine - Pointer to the System Startup Routine. Either
* PspUserThreadStartup or PspSystemThreadStartup
* VOID
* KiThreadStartup(
* IN PKSTART_ROUTINE StartRoutine<rcx>,
* IN PVOID StartContext<rdx>,
* IN PVOID P3<r8>,
* IN PVOID P4<r9>,
* IN PVOID SystemRoutine);
*
* StartRoutine - For Kernel Threads only, specifies the starting execution
* point of the new thread.
* \param 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.
* \param 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.
* \param P3, P4 - not used atm
*
* TrapFrame - Pointer to the KTHREAD to which the caller wishes to
* switch from.
* \param SystemRoutine
* Pointer to the System Startup Routine.
* Either PspUserThreadStartup or PspSystemThreadStartup
*
* Returns:
* \return
* Should never return for a system thread. Returns through the System Call
* Exit Dispatcher for a user thread.
*
* Remarks:
* \remarks
* If a return from a system thread is detected, a bug check will occur.
*
*--*/
PUBLIC KiThreadStartup
KiThreadStartup:
/*
* 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)
.PROC KiThreadStartup
/* KSTART_FRAME is already on the stack when we enter here.
* The virtual prolog looks like this:
* sub rsp, 5 * 8
* mov [rsp + SfP1Home], rcx
* mov [rsp + SfP2Home], rdx
* mov [rsp + SfP3Home], r8
* mov [rsp + SfP4Home], r9
*/
/* Terminate the unwind chain, by setting rbp as frame pointer,
which contains 0 */
.setframe rbp, 0
.endprolog
/* 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 rbx, rbx
xor rsi, rsi
xor rdi, rdi
@ -67,73 +87,107 @@ KiThreadStartup:
mov rax, APC_LEVEL
mov cr8, rax
/*
* Call the System Routine which is right on our stack now.
* After we pop the pointer, the Start Routine/Context is on the
* stack, we pop it as parameters to the System Routine into rcx
*/
pop rax
pop rcx
call rax
/* We have the KSTART_FRAME on the stack, P1Home and P2Home are preloaded
* with the parameters for the system routine. The address of the system
* routine is stored in P4Home. */
mov rcx, [rsp + SfP1Home] /* StartRoutine */
mov rdx, [rsp + SfP2Home] /* StartContext */
mov r8, [rsp + SfP3Home] /* ? */
call qword ptr [rsp + SfP4Home] /* SystemRoutine */
/* The thread returned... was it a user-thread? */
pop rcx
/* The thread returned. If it was a user-thread, we have a return address
and all is well, otherwise this is very bad. */
mov rcx, [rsp + SfReturn]
or rcx, rcx
jz BadThread
/* Yes it was, set our trapframe for the System Call Exit Dispatcher */
mov ebp, esp
/* Exit back to user-mode */
// jmp _KiServiceExit2
UNIMPLEMENTED KiThreadStartup_KiServiceExit2
BadThread:
jnz .leave
/* A system thread returned...this is very bad! */
int 3
.leave:
/* It was a user thread, set our trapframe for the System Call Exit Dispatcher */
lea rcx, [rsp + 6 * 8 + KEXCEPTION_FRAME_LENGTH]
/*++
* KiSwapContextInternal
/* Return to the trap exit code */
add rsp, 5 * 8
ret
.ENDP
/*!
* \name KiSwapContextInternal
*
* \brief
* The KiSwapContextInternal routine switches context to another thread.
*
* Params:
* ESI - Pointer to the KTHREAD to which the caller wishes to
* switch to.
* EDI - Pointer to the KTHREAD to which the caller wishes to
* switch from.
* \param rcx
* Pointer to the KTHREAD to which the caller wishes to switch to.
*
* Returns:
* \param rdx
* Pointer to the KTHREAD to which the caller wishes to switch from.
*
* \param r8b
* APC bypass
*
* \return
* None.
*
* Remarks:
* Absolutely all registers except ESP can be trampled here for maximum code flexibility.
* \remarks
* ...
*
*--*/
PUBLIC KiSwapContextInternal
KiSwapContextInternal:
UNIMPLEMENTED KiSwapContextInternal
.PROC KiSwapContextInternal
push rbp
.pushreg rbp
sub rsp, 6 * 8
.allocstack 6 * 8
.endprolog
/* Save APC bypass */
mov [rsp + SwApcBypass], r8b
/* Save kernel stack of old thread */
mov [rdx + KTHREAD_KernelStack], rsp
/* Save new thread in rbp */
mov rbp, rcx
//call KiSwapContextSuspend
/* Load stack of new thread */
mov rsp, [rbp + KTHREAD_KernelStack]
/* Reload APC bypass */
mov r8b, [rsp + SwApcBypass]
call KiSwapContextResume
/* Cleanup and return */
add rsp, 6 * 8
pop rbp
ret
.ENDP
/**
/*!
* KiSwapContext
*
* \brief
* The KiSwapContext routine switches context to another thread.
*
* BOOLEAN
* KiSwapContext(PKTHREAD CurrentThread, PKTHREAD TargetThread);
* KiSwapContext(KIRQL WaitIrql, PKTHREAD CurrentThread);
*
* \param CurrentThread
* \param WaitIrql <rcx>
* ...
*
* \param CurrentThread <rdx>
* Pointer to the KTHREAD of the current thread.
*
* \param TargetThread
* Pointer to the KTHREAD to which the caller wishes to switch to.
*
* \returns
* \return
* The WaitStatus of the Target Thread.
*
* \remarks
@ -141,59 +195,74 @@ KiSwapContextInternal:
* non-volatile registers so that the Internal function can use all of
* them. It will also save the old current thread and set the new one.
*
* The calling thread does not return after KiSwapContextInternal until
* The calling thread does not return after KiSwapContextInternal until
* another thread switches to IT.
*
*--*/
PUBLIC KiSwapContext
KiSwapContext:
.PROC KiSwapContext
/* Save 10 registers */
sub rsp, 10 * 8
/* Allocate a KEXCEPTION_FRAME on the stack (+8 for proper alignment) */
sub rsp, KEXCEPTION_FRAME_LENGTH + 8
.allocstack KEXCEPTION_FRAME_LENGTH + 8
/* Save all the non-volatile ones */
mov [rsp+72], r15
mov [rsp+64], r14
mov [rsp+56], r13
mov [rsp+48], r12
mov [rsp+40], r11
mov [rsp+32], r10
mov [rsp+24], rbx
mov [rsp+16], rsi
mov [rsp+8], rdi
mov [rsp+0], rbp
/* Get the PCR */
mov rbx, gs:[PcSelf]
/* Get the current thread */
mov rdi, rcx
/* Get the New Thread */
mov rsi, rdx
/* Get the wait IRQL */
movzx ecx, byte ptr [edi+KTHREAD_WAIT_IRQL]
/* save non-volatiles in KEXCEPTION_FRAME */
mov [rsp + KEXCEPTION_FRAME_Rbp], rbp
.savereg rbp, KEXCEPTION_FRAME_Rbp
mov [rsp + KEXCEPTION_FRAME_Rbx], rbx
.savereg rbx, KEXCEPTION_FRAME_Rbx
mov [rsp + KEXCEPTION_FRAME_Rdi], rdi
.savereg rdi, KEXCEPTION_FRAME_Rdi
mov [rsp + KEXCEPTION_FRAME_Rsi], rsi
.savereg rsi, KEXCEPTION_FRAME_Rsi
mov [rsp + KEXCEPTION_FRAME_R12], r12
.savereg r12, KEXCEPTION_FRAME_R12
mov [rsp + KEXCEPTION_FRAME_R13], r13
.savereg r13, KEXCEPTION_FRAME_R13
mov [rsp + KEXCEPTION_FRAME_R14], r14
.savereg r14, KEXCEPTION_FRAME_R14
mov [rsp + KEXCEPTION_FRAME_R15], r15
.savereg r15, KEXCEPTION_FRAME_R15
movdqa [rsp + KEXCEPTION_FRAME_Xmm6], xmm6
movdqa [rsp + KEXCEPTION_FRAME_Xmm7], xmm7
movdqa [rsp + KEXCEPTION_FRAME_Xmm8], xmm8
movdqa [rsp + KEXCEPTION_FRAME_Xmm9], xmm9
movdqa [rsp + KEXCEPTION_FRAME_Xmm10], xmm10
movdqa [rsp + KEXCEPTION_FRAME_Xmm11], xmm11
movdqa [rsp + KEXCEPTION_FRAME_Xmm12], xmm12
movdqa [rsp + KEXCEPTION_FRAME_Xmm13], xmm13
movdqa [rsp + KEXCEPTION_FRAME_Xmm14], xmm14
movdqa [rsp + KEXCEPTION_FRAME_Xmm15], xmm15
// KEXCEPTION_FRAME_MxCsr
.endprolog
/* Do the swap with the registers correctly setup */
mov rcx, gs:[PcCurrentThread] /* Pointer to the new thread */
call KiSwapContextInternal
/* Restore the registers */
mov rbp, [rsp+0]
mov rdi, [rsp+8]
mov rsi, [rsp+16]
mov rbx, [rsp+24]
/* restore non-volatile registers */
mov rbp, [rsp + KEXCEPTION_FRAME_Rbp]
mov rbx, [rsp + KEXCEPTION_FRAME_Rbx]
mov rdi, [rsp + KEXCEPTION_FRAME_Rdi]
mov rsi, [rsp + KEXCEPTION_FRAME_Rsi]
mov r12, [rsp + KEXCEPTION_FRAME_R12]
mov r13, [rsp + KEXCEPTION_FRAME_R13]
mov r14, [rsp + KEXCEPTION_FRAME_R14]
mov r15, [rsp + KEXCEPTION_FRAME_R15]
movdqa xmm6, [rsp + KEXCEPTION_FRAME_Xmm6]
movdqa xmm7, [rsp + KEXCEPTION_FRAME_Xmm7]
movdqa xmm8, [rsp + KEXCEPTION_FRAME_Xmm8]
movdqa xmm9, [rsp + KEXCEPTION_FRAME_Xmm9]
movdqa xmm10, [rsp + KEXCEPTION_FRAME_Xmm10]
movdqa xmm11, [rsp + KEXCEPTION_FRAME_Xmm11]
movdqa xmm12, [rsp + KEXCEPTION_FRAME_Xmm12]
movdqa xmm13, [rsp + KEXCEPTION_FRAME_Xmm13]
movdqa xmm14, [rsp + KEXCEPTION_FRAME_Xmm14]
movdqa xmm15, [rsp + KEXCEPTION_FRAME_Xmm15]
mov r10, [rsp+32]
mov r11, [rsp+40]
mov r12, [rsp+48]
mov r13, [rsp+56]
mov r14, [rsp+64]
mov r15, [rsp+72]
/* Clean stack */
add esp, 10 * 8
/* Clean stack and return */
add rsp, KEXCEPTION_FRAME_LENGTH + 8
ret
.ENDP
END

View file

@ -13,7 +13,7 @@
#define NDEBUG
#include <debug.h>
extern ULONG64 InterruptDispatchTable[256];
extern KI_INTERRUPT_DISPATCH_ENTRY KiUnexpectedRange[256];
/* GLOBALS *******************************************************************/
@ -74,7 +74,7 @@ KeInitExceptions(VOID)
}
else
{
Offset = (ULONG64)&InterruptDispatchTable[i];
Offset = (ULONG64)&KiUnexpectedRange[i]._Op_push;
KiIdt[i].Dpl = 0;
KiIdt[i].IstIndex = 0;
}
@ -92,6 +92,146 @@ KeInitExceptions(VOID)
__lidt(&KiIdtDescriptor.Limit);
}
static
VOID
KiDispatchExceptionToUser(
IN PKTRAP_FRAME TrapFrame,
IN PCONTEXT Context,
IN PEXCEPTION_RECORD ExceptionRecord)
{
EXCEPTION_RECORD LocalExceptRecord;
ULONG Size;
ULONG64 UserRsp;
PCONTEXT UserContext;
PEXCEPTION_RECORD UserExceptionRecord;
/* Make sure we have a valid SS */
if (TrapFrame->SegSs != (KGDT64_R3_DATA | RPL_MASK))
{
/* Raise an access violation instead */
LocalExceptRecord.ExceptionCode = STATUS_ACCESS_VIOLATION;
LocalExceptRecord.ExceptionFlags = 0;
LocalExceptRecord.NumberParameters = 0;
ExceptionRecord = &LocalExceptRecord;
}
/* Calculate the size of the exception record */
Size = FIELD_OFFSET(EXCEPTION_RECORD, ExceptionInformation) +
ExceptionRecord->NumberParameters * sizeof(ULONG64);
/* Get new stack pointer and align it to 16 bytes */
UserRsp = (Context->Rsp - Size - sizeof(CONTEXT)) & ~15;
/* Get pointers to the usermode context and exception record */
UserContext = (PVOID)UserRsp;
UserExceptionRecord = (PVOID)(UserRsp + sizeof(CONTEXT));
/* Set up the user-stack */
_SEH2_TRY
{
/* Probe stack and copy Context */
ProbeForWrite(UserContext, sizeof(CONTEXT), sizeof(ULONG64));
*UserContext = *Context;
/* Probe stack and copy exception record */
ProbeForWrite(UserExceptionRecord, Size, sizeof(ULONG64));
*UserExceptionRecord = *ExceptionRecord;
}
_SEH2_EXCEPT((LocalExceptRecord = *_SEH2_GetExceptionInformation()->ExceptionRecord),
EXCEPTION_EXECUTE_HANDLER)
{
// FIXNE: handle stack overflow
/* Nothing we can do here */
_SEH2_YIELD(return);
}
_SEH2_END;
/* Now set the two params for the user-mode dispatcher */
TrapFrame->Rcx = (ULONG64)UserContext;
TrapFrame->Rdx = (ULONG64)UserExceptionRecord;
/* Set new Stack Pointer */
TrapFrame->Rsp = UserRsp;
/* Force correct segments */
TrapFrame->SegCs = KGDT64_R3_CODE | RPL_MASK;
TrapFrame->SegDs = KGDT64_R3_DATA | RPL_MASK;
TrapFrame->SegEs = KGDT64_R3_DATA | RPL_MASK;
TrapFrame->SegFs = KGDT64_R3_CMTEB | RPL_MASK;
TrapFrame->SegGs = KGDT64_R3_DATA | RPL_MASK;
TrapFrame->SegSs = KGDT64_R3_DATA | RPL_MASK;
/* Set RIP to the User-mode Dispatcher */
TrapFrame->Rip = (ULONG64)KeUserExceptionDispatcher;
/* Exit to usermode */
KiServiceExit2(TrapFrame);
}
static
VOID
KiPageInDirectory(PVOID ImageBase, USHORT Directory)
{
volatile CHAR *Pointer;
ULONG Size;
/* Get a pointer to the debug directory */
Pointer = RtlImageDirectoryEntryToData(ImageBase, 1, Directory, &Size);
if (!Pointer) return;
/* Loop all pages */
while ((LONG)Size > 0)
{
/* Touch it, to page it in */
(void)*Pointer;
Pointer += PAGE_SIZE;
Size -= PAGE_SIZE;
}
}
VOID
KiPrepareUserDebugData(void)
{
PLDR_DATA_TABLE_ENTRY LdrEntry;
PPEB_LDR_DATA PebLdr;
PLIST_ENTRY ListEntry;
PTEB Teb;
/* Get the Teb for this process */
Teb = KeGetCurrentThread()->Teb;
if (!Teb) return;
_SEH2_TRY
{
/* Get a pointer to the loader data */
PebLdr = Teb->ProcessEnvironmentBlock->Ldr;
if (!PebLdr) _SEH2_YIELD(return);
/* Now loop all entries in the module list */
for (ListEntry = PebLdr->InLoadOrderModuleList.Flink;
ListEntry != &PebLdr->InLoadOrderModuleList;
ListEntry = ListEntry->Flink)
{
/* Get the loader entry */
LdrEntry = CONTAINING_RECORD(ListEntry,
LDR_DATA_TABLE_ENTRY,
InLoadOrderLinks);
KiPageInDirectory((PVOID)LdrEntry->DllBase,
IMAGE_DIRECTORY_ENTRY_DEBUG);
KiPageInDirectory((PVOID)LdrEntry->DllBase,
IMAGE_DIRECTORY_ENTRY_EXCEPTION);
}
}
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
{
}
_SEH2_END
}
VOID
NTAPI
KiDispatchException(IN PEXCEPTION_RECORD ExceptionRecord,
@ -102,9 +242,6 @@ KiDispatchException(IN PEXCEPTION_RECORD ExceptionRecord,
{
CONTEXT Context;
// FrLdrDbgPrint("KiDispatchException(%p, %p, %p, %d, %d)\n",
// ExceptionRecord, ExceptionFrame, TrapFrame, PreviousMode, FirstChance);
/* Increase number of Exception Dispatches */
KeGetCurrentPrcb()->KeExceptionDispatchCount++;
@ -179,8 +316,66 @@ KiDispatchException(IN PEXCEPTION_RECORD ExceptionRecord,
}
else
{
/* FIXME: user-mode exception handling unimplemented */
ASSERT(FALSE);
/* User mode exception, was it first-chance? */
if (FirstChance)
{
/*
* Break into the kernel debugger unless a user mode debugger
* is present or user mode exceptions are ignored, except if this
* is a debug service which we must always pass to KD
*/
if ((!(PsGetCurrentProcess()->DebugPort) &&
!(KdIgnoreUmExceptions)) ||
(KdIsThisAKdTrap(ExceptionRecord, &Context, PreviousMode)))
{
/* Make sure the debugger can access debug directories */
KiPrepareUserDebugData();
/* Call the kernel debugger */
if (KiDebugRoutine(TrapFrame,
ExceptionFrame,
ExceptionRecord,
&Context,
PreviousMode,
FALSE))
{
/* Exception was handled */
goto Handled;
}
}
/* Forward exception to user mode debugger */
if (DbgkForwardException(ExceptionRecord, TRUE, FALSE)) return;
//KiDispatchExceptionToUser()
__debugbreak();
}
/* Try second chance */
if (DbgkForwardException(ExceptionRecord, TRUE, TRUE))
{
/* Handled, get out */
return;
}
else if (DbgkForwardException(ExceptionRecord, FALSE, TRUE))
{
/* Handled, get out */
return;
}
/* 3rd strike, kill the process */
DPRINT1("Kill %.16s, ExceptionCode: %lx, ExceptionAddress: %lx, BaseAddress: %lx\n",
PsGetCurrentProcess()->ImageFileName,
ExceptionRecord->ExceptionCode,
ExceptionRecord->ExceptionAddress,
PsGetCurrentProcess()->SectionBaseAddress);
ZwTerminateProcess(NtCurrentProcess(), ExceptionRecord->ExceptionCode);
KeBugCheckEx(KMODE_EXCEPTION_NOT_HANDLED,
ExceptionRecord->ExceptionCode,
(ULONG_PTR)ExceptionRecord->ExceptionAddress,
(ULONG_PTR)TrapFrame,
0);
}
Handled:

View file

@ -6,7 +6,8 @@
* for the purpopses of connecting, disconnecting and setting
* up ISRs for drivers. The backend behind the Io* Interrupt
* routines.
* PROGRAMMERS: Timo Kreuzer (timo.kreuzer@web.de)
* PROGRAMMERS: Timo Kreuzer (timo.kreuzer@reactos.org)
* Alex Ionescu (alex.ionescu@reactos.org)
*/
/* INCLUDES *****************************************************************/
@ -15,30 +16,151 @@
#define NDEBUG
#include <debug.h>
extern UCHAR KiInterruptDispatchTemplate[16];
extern UCHAR KiUnexpectedRange[];
extern UCHAR KiUnexpectedRangeEnd[];
void KiInterruptDispatch(void);
/* FUNCTIONS ****************************************************************/
VOID
NTAPI
KeInitializeInterrupt(
IN PKINTERRUPT Interrupt,
IN PKSERVICE_ROUTINE ServiceRoutine,
IN PVOID ServiceContext,
IN PKSPIN_LOCK SpinLock,
IN ULONG Vector,
IN KIRQL Irql,
IN KIRQL SynchronizeIrql,
IN KINTERRUPT_MODE InterruptMode,
IN BOOLEAN ShareVector,
IN CHAR ProcessorNumber,
IN BOOLEAN FloatingSave)
{
/* Initialize the header */
Interrupt->Type = InterruptObject;
Interrupt->Size = sizeof(KINTERRUPT);
/* If no Spinlock is given, use the internal */
if (!SpinLock) SpinLock = &Interrupt->SpinLock;
KeInitializeSpinLock(&Interrupt->SpinLock);
/* Set the given parameters */
Interrupt->ServiceRoutine = ServiceRoutine;
Interrupt->ServiceContext = ServiceContext;
Interrupt->ActualLock = SpinLock;
Interrupt->Vector = Vector;
Interrupt->Irql = Irql;
Interrupt->SynchronizeIrql = SynchronizeIrql;
Interrupt->Mode = InterruptMode;
Interrupt->ShareVector = ShareVector;
Interrupt->Number = ProcessorNumber;
Interrupt->FloatingSave = FloatingSave;
/* Set initial values */
Interrupt->TickCount = 0;
Interrupt->Connected = FALSE;
Interrupt->ServiceCount = 0;
Interrupt->DispatchCount = 0;
Interrupt->TrapFrame = NULL;
Interrupt->Reserved = 0;
/* Copy the dispatch code (its location independent, no need to patch it) */
RtlCopyMemory(Interrupt->DispatchCode,
KiInterruptDispatchTemplate,
sizeof(Interrupt->DispatchCode));
Interrupt->DispatchAddress = 0;
}
BOOLEAN
NTAPI
KeConnectInterrupt(IN PKINTERRUPT Interrupt)
{
PVOID CurrentHandler;
ASSERT(Interrupt->Vector <= MAXIMUM_IDTVECTOR);
ASSERT(Interrupt->Number < KeNumberProcessors);
ASSERT(Interrupt->Irql <= HIGH_LEVEL);
/* Check if its already connected */
if (Interrupt->Connected) return TRUE;
/* Query the current handler */
CurrentHandler = KeQueryInterruptHandler(Interrupt->Vector);
/* Check if the vector is already unused */
if ((CurrentHandler >= (PVOID)KiUnexpectedRange) &&
(CurrentHandler <= (PVOID)KiUnexpectedRangeEnd))
{
/* Initialize the list for chained interrupts */
InitializeListHead(&Interrupt->InterruptListEntry);
/* Set normal dispatch address */
Interrupt->DispatchAddress = KiInterruptDispatch;
/* Set the new handler */
KeRegisterInterruptHandler(Interrupt->Vector,
Interrupt->DispatchCode);
if (!HalEnableSystemInterrupt(Interrupt->Vector,
Interrupt->Irql,
Interrupt->Mode))
{
/* Didn't work, restore old handler */
DPRINT1("HalEnableSystemInterrupt failed\n");
KeRegisterInterruptHandler(Interrupt->Vector, CurrentHandler);
return FALSE;
}
/* Mark as connected */
Interrupt->Connected = TRUE;
}
else
{
// later
__debugbreak();
}
return TRUE;
}
BOOLEAN
NTAPI
KeDisconnectInterrupt(IN PKINTERRUPT Interrupt)
{
UNIMPLEMENTED;
__debugbreak();
return FALSE;
}
VOID
BOOLEAN
NTAPI
KeInitializeInterrupt(IN PKINTERRUPT Interrupt,
IN PKSERVICE_ROUTINE ServiceRoutine,
IN PVOID ServiceContext,
IN PKSPIN_LOCK SpinLock,
IN ULONG Vector,
IN KIRQL Irql,
IN KIRQL SynchronizeIrql,
IN KINTERRUPT_MODE InterruptMode,
IN BOOLEAN ShareVector,
IN CHAR ProcessorNumber,
IN BOOLEAN FloatingSave)
KeSynchronizeExecution(IN OUT PKINTERRUPT Interrupt,
IN PKSYNCHRONIZE_ROUTINE SynchronizeRoutine,
IN PVOID SynchronizeContext OPTIONAL)
{
UNIMPLEMENTED;
}
BOOLEAN Success;
KIRQL OldIrql;
/* Raise IRQL */
OldIrql = KfRaiseIrql(Interrupt->SynchronizeIrql);
/* Acquire interrupt spinlock */
KeAcquireSpinLockAtDpcLevel(Interrupt->ActualLock);
/* Call the routine */
Success = SynchronizeRoutine(SynchronizeContext);
/* Release lock */
KeReleaseSpinLockFromDpcLevel(Interrupt->ActualLock);
/* Lower IRQL */
KeLowerIrql(OldIrql);
/* Return status */
return Success;
}

View file

@ -33,6 +33,10 @@ UCHAR DECLSPEC_ALIGN(16) KiDoubleFaultStackData[KERNEL_STACK_SIZE] = {0};
ULONG_PTR P0BootStack = (ULONG_PTR)&P0BootStackData[KERNEL_STACK_SIZE];
ULONG_PTR KiDoubleFaultStack = (ULONG_PTR)&KiDoubleFaultStackData[KERNEL_STACK_SIZE];
void KiInitializeSegments();
void KiSystemCallEntry64();
void KiSystemCallEntry32();
/* FUNCTIONS *****************************************************************/
VOID
@ -91,7 +95,7 @@ KiInitializePcr(IN PKIPCR Pcr,
USHORT Tr = 0;
/* Zero out the PCR */
RtlZeroMemory(Pcr, PAGE_SIZE);
RtlZeroMemory(Pcr, sizeof(KIPCR));
/* Set pointers to ourselves */
Pcr->Self = (PKPCR)Pcr;
@ -152,18 +156,21 @@ KiInitializePcr(IN PKIPCR Pcr,
/* Start us out at PASSIVE_LEVEL */
Pcr->Irql = PASSIVE_LEVEL;
KeSetCurrentIrql(PASSIVE_LEVEL);
/* Set GS base */
__writemsr(X86_MSR_GSBASE, (ULONG64)Pcr);
__writemsr(X86_MSR_KERNEL_GSBASE, (ULONG64)Pcr);
}
VOID
NTAPI
KiInitializeCpu(PKPRCB Prcb)
KiInitializeCpu(PKIPCR Pcr)
{
ULONG FeatureBits;
/* Initialize gs */
KiInitializeSegments();
/* Set GS base */
__writemsr(MSR_GS_BASE, (ULONG64)Pcr);
__writemsr(MSR_GS_SWAP, (ULONG64)Pcr);
/* Detect and set the CPU Type */
KiSetProcessorType();
@ -184,7 +191,7 @@ KiInitializeCpu(PKPRCB Prcb)
FeatureBits |= KF_NX_ENABLED;
/* Save feature bits */
Prcb->FeatureBits = FeatureBits;
Pcr->Prcb.FeatureBits = FeatureBits;
/* Enable fx save restore support */
__writecr4(__readcr4() | CR4_FXSR);
@ -203,6 +210,19 @@ KiInitializeCpu(PKPRCB Prcb)
/* LDT is unused */
__lldt(0);
/* Set the systemcall entry points */
__writemsr(MSR_LSTAR, (ULONG64)KiSystemCallEntry64);
__writemsr(MSR_CSTAR, (ULONG64)KiSystemCallEntry32);
__writemsr(MSR_STAR, ((ULONG64)KGDT64_R0_CODE << 32) |
((ULONG64)(KGDT64_R3_CMCODE|RPL_MASK) << 48));
/* Set the flags to be cleared when doing a syscall */
__writemsr(MSR_SYSCALL_MASK, EFLAGS_IF_MASK | EFLAGS_TF | EFLAGS_DF);
/* Enable syscall instruction */
__writemsr(MSR_EFER, __readmsr(MSR_EFER) | MSR_SCE);
}
VOID
@ -339,7 +359,7 @@ KiSystemStartup(IN PLOADER_PARAMETER_BLOCK LoaderBlock)
/* HACK */
FrLdrDbgPrint = LoaderBlock->u.I386.CommonDataArea;
FrLdrDbgPrint("Hello from KiSystemStartup!!!\n");
//FrLdrDbgPrint("Hello from KiSystemStartup!!!\n");
/* Save the loader block */
KeLoaderBlock = LoaderBlock;
@ -350,7 +370,6 @@ KiSystemStartup(IN PLOADER_PARAMETER_BLOCK LoaderBlock)
/* LoaderBlock initialization for Cpu 0 */
if (Cpu == 0)
{
FrLdrDbgPrint("LoaderBlock->Prcb=%p\n", LoaderBlock->Prcb);
/* Set the initial stack, idle thread and process */
LoaderBlock->KernelStack = (ULONG_PTR)P0BootStack;
LoaderBlock->Thread = (ULONG_PTR)&KiInitialThread;
@ -378,7 +397,7 @@ KiSystemStartup(IN PLOADER_PARAMETER_BLOCK LoaderBlock)
KiInitializePcr(Pcr, Cpu, InitialThread, (PVOID)KiDoubleFaultStack);
/* Initialize the CPU features */
KiInitializeCpu(&Pcr->Prcb);
KiInitializeCpu(Pcr);
/* Initial setup for the boot CPU */
if (Cpu == 0)

View file

@ -12,14 +12,71 @@
#define NDEBUG
#include <debug.h>
VOID
KiRetireDpcListInDpcStack(
PKPRCB Prcb,
PVOID DpcStack);
VOID
NTAPI
KiDispatchInterrupt(VOID)
KiDpcInterruptHandler(VOID)
{
UNIMPLEMENTED;
__debugbreak();
PKPRCB Prcb = KeGetCurrentPrcb();
PKTHREAD NewThread, OldThread;
KIRQL OldIrql;
/* Raise to DISPATCH_LEVEL */
OldIrql = KfRaiseIrql(DISPATCH_LEVEL);
/* Send an EOI */
KiSendEOI();
/* Check for pending timers, pending DPCs, or pending ready threads */
if ((Prcb->DpcData[0].DpcQueueDepth) ||
(Prcb->TimerRequest) ||
(Prcb->DeferredReadyListHead.Next))
{
/* Retire DPCs while under the DPC stack */
KiRetireDpcListInDpcStack(Prcb, Prcb->DpcStack);
}
/* Enable interrupts */
_enable();
/* Check for quantum end */
if (Prcb->QuantumEnd)
{
/* Handle quantum end */
Prcb->QuantumEnd = FALSE;
KiQuantumEnd();
}
else if (Prcb->NextThread)
{
/* Capture current thread data */
OldThread = Prcb->CurrentThread;
NewThread = Prcb->NextThread;
/* Set new thread data */
Prcb->NextThread = NULL;
Prcb->CurrentThread = NewThread;
/* The thread is now running */
NewThread->State = Running;
OldThread->WaitReason = WrDispatchInt;
/* Make the old thread ready */
KxQueueReadyThread(OldThread, Prcb);
/* Swap to the new thread */
KiSwapContext(APC_LEVEL, OldThread);
}
/* Go back to old irql and disable interrupts */
KeLowerIrql(OldIrql);
_disable();
}
VOID
FASTCALL
KeZeroPages(IN PVOID Address,
@ -29,52 +86,13 @@ KeZeroPages(IN PVOID Address,
RtlZeroMemory(Address, Size);
}
VOID
FASTCALL
DECLSPEC_NORETURN
KiServiceExit(IN PKTRAP_FRAME TrapFrame,
IN NTSTATUS Status)
{
UNIMPLEMENTED;
__debugbreak();
}
VOID
FASTCALL
DECLSPEC_NORETURN
KiServiceExit2(IN PKTRAP_FRAME TrapFrame)
{
UNIMPLEMENTED;
__debugbreak();
}
BOOLEAN
NTAPI
KeConnectInterrupt(IN PKINTERRUPT Interrupt)
{
UNIMPLEMENTED;
__debugbreak();
return FALSE;
}
PVOID
NTAPI
KeSwitchKernelStack(PVOID StackBase, PVOID StackLimit)
{
UNIMPLEMENTED;
return NULL;
}
BOOLEAN
NTAPI
KeSynchronizeExecution(
IN OUT PKINTERRUPT Interrupt,
IN PKSYNCHRONIZE_ROUTINE SynchronizeRoutine,
IN PVOID SynchronizeContext)
{
UNIMPLEMENTED;
__debugbreak();
return FALSE;
return NULL;
}
NTSTATUS
@ -91,12 +109,101 @@ KeUserModeCallback(IN ULONG RoutineIndex,
}
VOID
KiIdleLoop()
FASTCALL
KiIdleLoop(VOID)
{
UNIMPLEMENTED;
for(;;);
PKPRCB Prcb = KeGetCurrentPrcb();
PKTHREAD OldThread, NewThread;
/* Initialize the idle loop: disable interrupts */
_enable();
YieldProcessor();
YieldProcessor();
_disable();
/* Now loop forever */
while (TRUE)
{
/* Check for pending timers, pending DPCs, or pending ready threads */
if ((Prcb->DpcData[0].DpcQueueDepth) ||
(Prcb->TimerRequest) ||
(Prcb->DeferredReadyListHead.Next))
{
/* Quiesce the DPC software interrupt */
HalClearSoftwareInterrupt(DISPATCH_LEVEL);
/* Handle it */
KiRetireDpcList(Prcb);
}
/* Check if a new thread is scheduled for execution */
if (Prcb->NextThread)
{
/* Enable interupts */
_enable();
/* Capture current thread data */
OldThread = Prcb->CurrentThread;
NewThread = Prcb->NextThread;
/* Set new thread data */
Prcb->NextThread = NULL;
Prcb->CurrentThread = NewThread;
/* The thread is now running */
NewThread->State = Running;
/* Do the swap at SYNCH_LEVEL */
KfRaiseIrql(SYNCH_LEVEL);
/* Switch away from the idle thread */
KiSwapContext(APC_LEVEL, OldThread);
/* Go back to DISPATCH_LEVEL */
KeLowerIrql(DISPATCH_LEVEL);
/* We are back in the idle thread -- disable interrupts again */
_enable();
YieldProcessor();
YieldProcessor();
_disable();
}
else
{
/* Continue staying idle. Note the HAL returns with interrupts on */
Prcb->PowerState.IdleFunction(&Prcb->PowerState);
}
}
}
/*! \name KiInitializeUserApc
*
* \brief
* Prepares the current trap frame (which must have come from user mode)
* with the ntdll.KiUserApcDispatcher entrypoint, copying a CONTEXT
* record with the context from the old trap frame to the threads user
* mode stack.
*
* \param ExceptionFrame
* \param TrapFrame
* \param NormalRoutine
* \param NormalContext
* \param SystemArgument1
* \param SystemArgument2
*
* \remarks
* This function is called from KiDeliverApc, when the trap frame came
* from user mode. This happens before a systemcall or interrupt exits back
* to usermode or when a thread is started from PspUserThreadstartup.
* The trap exit code will then leave to KiUserApcDispatcher which in turn
* calls the NormalRoutine, passing NormalContext, SystemArgument1 and
* SystemArgument2 as parameters. When that function returns, it calls
* NtContinue to return back to the kernel, where the old context that was
* saved on the usermode stack is restored and execution is transferred
* back to usermode, where the original trap originated from.
*
*--*/
VOID
NTAPI
KiInitializeUserApc(IN PKEXCEPTION_FRAME ExceptionFrame,
@ -106,8 +213,69 @@ KiInitializeUserApc(IN PKEXCEPTION_FRAME ExceptionFrame,
IN PVOID SystemArgument1,
IN PVOID SystemArgument2)
{
UNIMPLEMENTED;
__debugbreak();
CONTEXT Context;
ULONG64 AlignedRsp, Stack;
EXCEPTION_RECORD SehExceptRecord;
/* Sanity check, that the trap frame is from user mode */
ASSERT((TrapFrame->SegCs & MODE_MASK) != KernelMode);
/* Convert the current trap frame to a context */
Context.ContextFlags = CONTEXT_FULL | CONTEXT_DEBUG_REGISTERS;
KeTrapFrameToContext(TrapFrame, ExceptionFrame, &Context);
/* We jump to KiUserApcDispatcher in ntdll */
TrapFrame->Rip = (ULONG64)KeUserApcDispatcher;
/* Setup Ring 3 segments */
TrapFrame->SegCs = KGDT64_R3_CODE | RPL_MASK;
TrapFrame->SegDs = KGDT64_R3_DATA | RPL_MASK;
TrapFrame->SegEs = KGDT64_R3_DATA | RPL_MASK;
TrapFrame->SegFs = KGDT64_R3_CMTEB | RPL_MASK;
TrapFrame->SegGs = KGDT64_R3_DATA | RPL_MASK;
TrapFrame->SegSs = KGDT64_R3_DATA | RPL_MASK;
/* Sanitize EFLAGS, enable interrupts */
TrapFrame->EFlags = (Context.EFlags & EFLAGS_USER_SANITIZE);
TrapFrame->EFlags |= EFLAGS_INTERRUPT_MASK;
/* Set parameters for KiUserApcDispatcher */
Context.P1Home = (ULONG64)NormalContext;
Context.P2Home = (ULONG64)SystemArgument1;
Context.P3Home = (ULONG64)SystemArgument2;
Context.P4Home = (ULONG64)NormalRoutine;
/* Check if thread has IOPL and force it enabled if so */
//if (KeGetCurrentThread()->Iopl) TrapFrame->EFlags |= EFLAGS_IOPL;
/* Align Stack to 16 bytes and allocate space */
AlignedRsp = Context.Rsp & ~15;
Stack = AlignedRsp - sizeof(CONTEXT);
TrapFrame->Rsp = Stack;
/* The stack must be 16 byte aligned for KiUserApcDispatcher */
ASSERT((Stack & 15) == 0);
/* Protect with SEH */
_SEH2_TRY
{
/* Probe the stack */
ProbeForWrite((PCONTEXT)Stack, sizeof(CONTEXT), 8);
/* Copy the context */
RtlCopyMemory((PCONTEXT)Stack, &Context, sizeof(CONTEXT));
}
_SEH2_EXCEPT((RtlCopyMemory(&SehExceptRecord, _SEH2_GetExceptionInformation()->ExceptionRecord, sizeof(EXCEPTION_RECORD)), EXCEPTION_EXECUTE_HANDLER))
{
/* Dispatch the exception */
SehExceptRecord.ExceptionAddress = (PVOID)TrapFrame->Rip;
KiDispatchException(&SehExceptRecord,
ExceptionFrame,
TrapFrame,
UserMode,
TRUE);
}
_SEH2_END;
}
VOID
@ -115,10 +283,126 @@ NTAPI
KiSwapProcess(IN PKPROCESS NewProcess,
IN PKPROCESS OldProcess)
{
UNIMPLEMENTED;
__debugbreak();
PKIPCR Pcr = (PKIPCR)KeGetPcr();
#ifdef CONFIG_SMP
LONG SetMember;
/* Update active processor mask */
SetMember = (LONG)Pcr->SetMember;
InterlockedXor((PLONG)&NewProcess->ActiveProcessors, SetMember);
InterlockedXor((PLONG)&OldProcess->ActiveProcessors, SetMember);
#endif
/* Update CR3 */
__writecr3(NewProcess->DirectoryTableBase[0]);
/* Update IOPM offset */
Pcr->TssBase->IoMapBase = NewProcess->IopmOffset;
}
#define MAX_SYSCALL_PARAMS 16
NTSTATUS
NtSyscallFailure(void)
{
/* This is the failure function */
return STATUS_ACCESS_VIOLATION;
}
PVOID
KiSystemCallHandler(
IN PKTRAP_FRAME TrapFrame,
IN ULONG64 P2,
IN ULONG64 P3,
IN ULONG64 P4)
{
PKSERVICE_TABLE_DESCRIPTOR DescriptorTable;
PKTHREAD Thread;
PULONG64 KernelParams, UserParams;
ULONG ServiceNumber, Offset, Count;
ULONG64 UserRsp;
DPRINT("Syscall #%ld\n", TrapFrame->Rax);
//__debugbreak();
/* Increase system call count */
__addgsdword(FIELD_OFFSET(KIPCR, Prcb.KeSystemCalls), 1);
/* Get the current thread */
Thread = KeGetCurrentThread();
/* Set previous mode */
Thread->PreviousMode = TrapFrame->PreviousMode = UserMode;
/* Save the old trap frame and set the new */
TrapFrame->TrapFrame = (ULONG64)Thread->TrapFrame;
Thread->TrapFrame = TrapFrame;
/* Before enabling interrupts get the user rsp from the KPCR */
UserRsp = __readgsqword(FIELD_OFFSET(KIPCR, UserRsp));
TrapFrame->Rsp = UserRsp;
/* Enable interrupts */
_enable();
/* If the usermode rsp was not a usermode address, prepare an exception */
if (UserRsp > MmUserProbeAddress) UserRsp = MmUserProbeAddress;
/* Get the address of the usermode and kernelmode parameters */
UserParams = (PULONG64)UserRsp + 1;
KernelParams = (PULONG64)TrapFrame - MAX_SYSCALL_PARAMS;
/* Get the system call number from the trap frame and decode it */
ServiceNumber = (ULONG)TrapFrame->Rax;
Offset = (ServiceNumber >> SERVICE_TABLE_SHIFT) & SERVICE_TABLE_MASK;
ServiceNumber &= SERVICE_NUMBER_MASK;
/* Get descriptor table */
DescriptorTable = (PVOID)((ULONG_PTR)Thread->ServiceTable + Offset);
/* Get stack bytes and calculate argument count */
Count = DescriptorTable->Number[ServiceNumber] / 8;
__try
{
switch (Count)
{
case 16: KernelParams[15] = UserParams[15];
case 15: KernelParams[14] = UserParams[14];
case 14: KernelParams[13] = UserParams[13];
case 13: KernelParams[12] = UserParams[12];
case 12: KernelParams[11] = UserParams[11];
case 11: KernelParams[10] = UserParams[10];
case 10: KernelParams[9] = UserParams[9];
case 9: KernelParams[8] = UserParams[8];
case 8: KernelParams[7] = UserParams[7];
case 7: KernelParams[6] = UserParams[6];
case 6: KernelParams[5] = UserParams[5];
case 5: KernelParams[4] = UserParams[4];
case 4: KernelParams[3] = P4;
case 3: KernelParams[2] = P3;
case 2: KernelParams[1] = P2;
case 1: KernelParams[0] = TrapFrame->R10;
case 0:
break;
default:
__debugbreak();
break;
}
}
__except(1)
{
TrapFrame->Rax = _SEH2_GetExceptionCode();
return (PVOID)NtSyscallFailure;
}
return (PVOID)DescriptorTable->Base[ServiceNumber];
}
// FIXME: we need to
VOID
KiSystemService(IN PKTHREAD Thread,
IN PKTRAP_FRAME TrapFrame,
@ -145,6 +429,7 @@ NtSetLdtEntries
(ULONG Selector1, LDT_ENTRY LdtEntry1, ULONG Selector2, LDT_ENTRY LdtEntry2)
{
UNIMPLEMENTED;
__debugbreak();
return STATUS_UNSUCCESSFUL;
}
@ -153,9 +438,8 @@ NTAPI
NtVdmControl(IN ULONG ControlCode,
IN PVOID ControlData)
{
UNIMPLEMENTED;
__debugbreak();
return STATUS_UNSUCCESSFUL;
/* Not supported */
return STATUS_NOT_IMPLEMENTED;
}
NTSTATUS

View file

@ -2,8 +2,9 @@
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel
* FILE: ntoskrnl/ke/i386/thread.c
* PURPOSE: i386 Thread Context Creation
* PROGRAMMER: Alex Ionescu (alex@relsoft.net)
* PURPOSE: amd64 Thread Context Creation
* PROGRAMMER: Timo Kreuzer (timo.kreuzer@reactos.org)
* Alex Ionescu (alex@relsoft.net)
*/
/* INCLUDES ******************************************************************/
@ -16,6 +17,7 @@ typedef struct _KUINIT_FRAME
{
KSWITCH_FRAME CtxSwitchFrame;
KSTART_FRAME StartFrame;
KEXCEPTION_FRAME ExceptionFrame;
KTRAP_FRAME TrapFrame;
//FX_SAVE_AREA FxSaveArea;
} KUINIT_FRAME, *PKUINIT_FRAME;
@ -35,74 +37,52 @@ KiInitializeContextThread(IN PKTHREAD Thread,
IN PKSYSTEM_ROUTINE SystemRoutine,
IN PKSTART_ROUTINE StartRoutine,
IN PVOID StartContext,
IN PCONTEXT ContextPointer)
IN PCONTEXT Context)
{
//PFX_SAVE_AREA FxSaveArea;
//PFXSAVE_FORMAT FxSaveFormat;
PKSTART_FRAME StartFrame;
PKSWITCH_FRAME CtxSwitchFrame;
PKTRAP_FRAME TrapFrame;
CONTEXT LocalContext;
PCONTEXT Context = NULL;
ULONG ContextFlags;
/* Check if this is a With-Context Thread */
if (ContextPointer)
if (Context)
{
/* Set up the Initial Frame */
PKUINIT_FRAME InitFrame;
InitFrame = (PKUINIT_FRAME)((ULONG_PTR)Thread->InitialStack -
sizeof(KUINIT_FRAME));
/* Copy over the context we got */
RtlCopyMemory(&LocalContext, ContextPointer, sizeof(CONTEXT));
Context = &LocalContext;
ContextFlags = CONTEXT_CONTROL;
/* Set up the Initial Frame */
InitFrame = ((PKUINIT_FRAME)Thread->InitialStack) - 1;
StartFrame = &InitFrame->StartFrame;
CtxSwitchFrame = &InitFrame->CtxSwitchFrame;
/* Zero out the trap frame and save area */
RtlZeroMemory(&InitFrame->TrapFrame,
KTRAP_FRAME_LENGTH);
/* Save back the new value of the kernel stack. */
Thread->KernelStack = (PVOID)InitFrame;
/* Setup the Fx Area */
//FxSaveArea = &InitFrame->FxSaveArea;
/* Tell the thread it will run in User Mode */
Thread->PreviousMode = UserMode;
// /* Get the FX Save Format Area */
// FxSaveFormat = (PFXSAVE_FORMAT)Context->ExtendedRegisters;
//
// /* Set an initial state */
// FxSaveFormat->ControlWord = 0x27F;
// FxSaveFormat->StatusWord = 0;
// FxSaveFormat->TagWord = 0;
// FxSaveFormat->ErrorOffset = 0;
// FxSaveFormat->ErrorSelector = 0;
// FxSaveFormat->DataOffset = 0;
// FxSaveFormat->DataSelector = 0;
// FxSaveFormat->MXCsr = 0x1F80;
/* Set an intial NPX State */
//Context->FloatSave.Cr0NpxState = 0;
//FxSaveArea->Cr0NpxState = 0;
//FxSaveArea->NpxSavedCpu = 0;
/* Now set the context flags depending on XMM support */
//ContextFlags |= (KeI386FxsrPresent) ? CONTEXT_EXTENDED_REGISTERS :
// CONTEXT_FLOATING_POINT;
// FIXME Setup the Fx Area
/* Set the Thread's NPX State */
Thread->NpxState = 0xA;
Thread->Header.NpxIrql = PASSIVE_LEVEL;
/* Disable any debug regiseters */
Context->ContextFlags &= ~CONTEXT_DEBUG_REGISTERS;
/* Make sure, we have control registers, disable debug registers */
ASSERT((Context->ContextFlags & CONTEXT_CONTROL) == CONTEXT_CONTROL);
ContextFlags = Context->ContextFlags & ~CONTEXT_DEBUG_REGISTERS;
/* Setup the Trap Frame */
TrapFrame = &InitFrame->TrapFrame;
/* Zero out the trap frame */
RtlZeroMemory(TrapFrame, sizeof(KTRAP_FRAME));
/* Set up a trap frame from the context. */
KeContextToTrapFrame(Context,
NULL,
TrapFrame,
Context->ContextFlags | ContextFlags,
CONTEXT_AMD64 | ContextFlags,
UserMode);
/* Set SS, DS, ES's RPL Mask properly */
@ -117,60 +97,109 @@ KiInitializeContextThread(IN PKTHREAD Thread,
/* Terminate the Exception Handler List */
TrapFrame->ExceptionFrame = 0;
/* Setup the Stack for KiThreadStartup and Context Switching */
StartFrame = &InitFrame->StartFrame;
CtxSwitchFrame = &InitFrame->CtxSwitchFrame;
/* Tell the thread it will run in User Mode */
Thread->PreviousMode = UserMode;
/* Tell KiThreadStartup of that too */
// StartFrame->UserThread = TRUE;
/* We return to ... */
StartFrame->Return = (ULONG64)KiServiceExit2;
}
else
{
/* Set up the Initial Frame for the system thread */
PKKINIT_FRAME InitFrame;
InitFrame = (PKKINIT_FRAME)((ULONG_PTR)Thread->InitialStack -
sizeof(KKINIT_FRAME));
/* Setup the Fx Area */
//FxSaveArea = &InitFrame->FxSaveArea;
//RtlZeroMemory(FxSaveArea, sizeof(FX_SAVE_AREA));
/* Check if we have Fxsr support */
DPRINT1("FxsrPresent but did nothing\n");
// /* Set the stub FX area */
// FxSaveArea->U.FxArea.ControlWord = 0x27F;
// FxSaveArea->U.FxArea.MXCsr = 0x1F80;
/* No NPX State */
Thread->NpxState = 0xA;
/* Setup the Stack for KiThreadStartup and Context Switching */
/* Set up the Initial Frame for the system thread */
InitFrame = ((PKKINIT_FRAME)Thread->InitialStack) - 1;
StartFrame = &InitFrame->StartFrame;
CtxSwitchFrame = &InitFrame->CtxSwitchFrame;
/* Save back the new value of the kernel stack. */
Thread->KernelStack = (PVOID)InitFrame;
/* Tell the thread it will run in Kernel Mode */
Thread->PreviousMode = KernelMode;
/* Tell KiThreadStartup of that too */
// StartFrame->UserThread = FALSE;
// FIXME Setup the Fx Area
/* No NPX State */
Thread->NpxState = 0xA;
/* We have no return address! */
StartFrame->Return = 0;
}
/* Now setup the remaining data for KiThreadStartup */
// StartFrame->StartContext = StartContext;
// StartFrame->StartRoutine = StartRoutine;
// StartFrame->SystemRoutine = SystemRoutine;
/* Set up the Context Switch Frame */
CtxSwitchFrame->Return = (ULONG64)KiThreadStartup;
CtxSwitchFrame->ApcBypass = FALSE;
/* And set up the Context Switch Frame */
// CtxSwitchFrame->RetAddr = KiThreadStartup;
// CtxSwitchFrame->ApcBypassDisable = TRUE;
// CtxSwitchFrame->ExceptionList = EXCEPTION_CHAIN_END;;
StartFrame->P1Home = (ULONG64)StartRoutine;
StartFrame->P2Home = (ULONG64)StartContext;
StartFrame->P3Home = 0;
StartFrame->P4Home = (ULONG64)SystemRoutine;
StartFrame->P5Home = 0;
/* Save back the new value of the kernel stack. */
Thread->KernelStack = (PVOID)CtxSwitchFrame;
}
BOOLEAN
KiSwapContextResume(
IN PKTHREAD NewThread,
IN PKTHREAD OldThread,
IN BOOLEAN ApcBypass)
{
PKIPCR Pcr = (PKIPCR)KeGetPcr();
PKPROCESS OldProcess, NewProcess;
/* Setup ring 0 stack pointer */
Pcr->TssBase->Rsp0 = (ULONG64)NewThread->InitialStack; // FIXME: NPX save area?
Pcr->Prcb.RspBase = Pcr->TssBase->Rsp0;
/* Now we are the new thread. Check if it's in a new process */
OldProcess = OldThread->ApcState.Process;
NewProcess = NewThread->ApcState.Process;
if (OldProcess != NewProcess)
{
/* Switch address space and flush TLB */
__writecr3(NewProcess->DirectoryTableBase[0]);
/* Set new TSS fields */
//Pcr->TssBase->IoMapBase = NewProcess->IopmOffset;
}
/* Set TEB pointer and GS base */
Pcr->NtTib.Self = (PVOID)NewThread->Teb;
if (NewThread->Teb)
{
/* This will switch the usermode gs */
__writemsr(MSR_GS_SWAP, (ULONG64)NewThread->Teb);
}
/* Increase context switch count */
Pcr->ContextSwitches++;
NewThread->ContextSwitches++;
/* DPCs shouldn't be active */
if (Pcr->Prcb.DpcRoutineActive)
{
/* Crash the machine */
KeBugCheckEx(ATTEMPTED_SWITCH_FROM_DPC,
(ULONG_PTR)OldThread,
(ULONG_PTR)NewThread,
(ULONG_PTR)OldThread->InitialStack,
0);
}
/* Kernel APCs may be pending */
if (NewThread->ApcState.KernelApcPending)
{
/* Are APCs enabled? */
if (!NewThread->SpecialApcDisable)
{
/* Request APC delivery */
if (!ApcBypass)
HalRequestSoftwareInterrupt(APC_LEVEL);
else
return TRUE;
}
}
/* Return stating that no kernel APCs are pending*/
return FALSE;
}
/* EOF */

View file

@ -20,7 +20,7 @@ EXTERN KiNpxNotAvailableFaultHandler:PROC
EXTERN KiGeneralProtectionFaultHandler:PROC
EXTERN KiXmmExceptionHandler:PROC
EXTERN KiDeliverApc:PROC
EXTERN KiDispatchInterrupt:PROC
EXTERN KiDpcInterruptHandler:PROC
/* GLOBALS *******************************************************************/
@ -56,15 +56,35 @@ ENDM
ALIGN 8
PUBLIC InterruptDispatchTable
InterruptDispatchTable:
MACRO(UnexpectedVectorStub, Vector)
/* This nop is to make the relative jmp address 4 bytes aligned and to
make the whole code 8 bytes long */
nop
/* This is a push instruction with 8bit operand. Since the instruction
sign extends the value to 32 bits, we need to offset it */
PUBLIC KxUnexpectedInterrupt&Vector
KxUnexpectedInterrupt&Vector:
push (Vector - 128)
jmp KiUnexpectedInterrupt
ENDM
PUBLIC KiUnexpectedRange
KiUnexpectedRange:
Vector = 0
REPEAT 256
push Vector
jmp KiUnexpectedInterrupt
ALIGN 8
UnexpectedVectorStub %Vector
Vector = Vector+1
ENDR
PUBLIC KiUnexpectedRangeEnd
KiUnexpectedRangeEnd:
PUBLIC KiInterruptDispatchTemplate
KiInterruptDispatchTemplate:
/* This instruction pushes the return address on the stack, which is the
address of the interrupt object's DispatchCode member, then jumps
to the address stored in the interrupt object's DispatchAddress member */
call qword ptr KiInterruptDispatchTemplate[rip - KINTERRUPT_DispatchCode + KINTERRUPT_DispatchAddress]
// rbp = TrapFrame, eax = ExceptionCode, edx = NumParams, r9,r10,r11 = params
.PROC InternalDispatchException
@ -138,7 +158,7 @@ ENDR
.ENDP
/* SOFTWARE INTERRUPT SERVICES ***********************************************/
/* CPU EXCEPTION HANDLERS ****************************************************/
PUBLIC KiDivideErrorFault
FUNC KiDivideErrorFault
@ -195,6 +215,14 @@ FUNC KiBreakpointTrap
/* Push pseudo error code */
EnterTrap TF_SAVE_ALL
/* Check if the frame was from kernelmode */
test word ptr [rbp + KTRAP_FRAME_SegCs], 3
jz KiBreakpointTrapKMode
/* Enable interrupts for user-mode */
sti
KiBreakpointTrapKMode:
/* Dispatch the exception */
DispatchException STATUS_BREAKPOINT, 3, 0, 0, 0
@ -434,7 +462,7 @@ SpecialCode:
PageFaultReturn:
/* Return */
ExitTrap TF_SAVE_ALL
ExitTrap (TF_SAVE_ALL or TF_CHECKUSERAPC)
ENDFUNC
@ -495,6 +523,8 @@ KiXmmExit:
ENDFUNC
/* SOFTWARE INTERRUPT SERVICES ***********************************************/
PUBLIC KiRaiseAssertion
FUNC KiRaiseAssertion
/* We have an error code */
@ -552,29 +582,43 @@ PUBLIC KiApcInterrupt
/* Disable interrupts */
cli
/* Lower IRQL back to PASSIVE */
mov rax, PASSIVE_LEVEL
mov cr8, rax
/* Return */
ExitTrap (TF_VOLATILES or TF_IRQL)
.ENDP
EXTERN KiRetireDpcList:PROC
PUBLIC KiRetireDpcListInDpcStack
.PROC KiRetireDpcListInDpcStack
push rbp
.pushreg rbp
mov rbp, rsp
.setframe rbp, 0
.endprolog
/* Switch stack and call the function */
mov rsp, rdx
sub rsp, 40
call KiRetireDpcList
/* Restore stack, cleanup and return */
mov rsp, rbp
pop rbp
ret
.ENDP
PUBLIC KiDpcInterrupt
.PROC KiDpcInterrupt
/* No error code */
EnterTrap (TF_VOLATILES or TF_IRQL)
/* Raise to DISPATCH_LEVEL */
mov rax, DISPATCH_LEVEL
mov cr8, rax
/* End the interrupt */
mov dword ptr [APIC_EOI], 0
/* Call the worker routine */
sti
call KiDispatchInterrupt
cli
call KiDpcInterruptHandler
/* Return */
/* Return, but don't send an EOI! */
ExitTrap (TF_VOLATILES or TF_IRQL)
.ENDP
@ -618,6 +662,253 @@ FUNC KiUnexpectedInterrupt
ExitTrap TF_SAVE_ALL
ENDFUNC
PUBLIC KiInterruptDispatch
FUNC KiInterruptDispatch
/* The error code is a pointer to the interrupt object's code */
EnterTrap (TF_HAS_ERROR_CODE or TF_SAVE_ALL or TF_IRQL)
/* Increase interrupt count */
inc dword ptr gs:[PcInterruptCount];
/* Load the address of the interrupt object into rcx */
mov rcx, [rbp + KTRAP_FRAME_ErrorCode]
/* Substract offset of the DispatchCode member plus 6 for the call instruction */
sub rcx, KINTERRUPT_DispatchCode + 6
/* Raise IRQL to SynchronizeIrql */
movzx rax, byte ptr [rcx + KINTERRUPT_SynchronizeIrql]
mov cr8, rax
#ifdef CONFIG_SMP
/* Acquire interrupt lock */
mov r8, [rcx + KINTERRUPT_ActualLock]
//KxAcquireSpinLock(Interrupt->ActualLock);
#endif
/* Call the ISR */
mov rdx, [rcx + KINTERRUPT_ServiceContext]
call qword ptr [rcx + KINTERRUPT_ServiceRoutine]
#ifdef CONFIG_SMP
/* Release interrupt lock */
//KxReleaseSpinLock(Interrupt->ActualLock);
#endif
/* Go back to old irql */
movzx rax, byte ptr [rbp + KTRAP_FRAME_PreviousIrql]
mov cr8, rax
/* Return */
ExitTrap (TF_SAVE_ALL or TF_SEND_EOI)
ENDFUNC
#define MAX_SYSCALL_PARAM_SIZE (16 * 8)
#define HOME_SIZE 6*8
#define SYSCALL_ALLOCATION (MAX_SYSCALL_PARAM_SIZE + HOME_SIZE)
EXTERN KiSystemCallHandler:PROC
/*! \name KiSystemCallEntry64
*
* \brief This is the entrypoint for syscalls from 64bit user mode
*
* \param rax - The system call number
* \param rcx - User mode return address, set by the syscall instruction
* \param rdx,r8,r9 - Parameters 2-4 to the service function
* \param r10 - Parameter 1 to the service function
* \param r11 - RFLAGS saved by the syscall instruction
*--*/
PUBLIC KiSystemCallEntry64
.PROC KiSystemCallEntry64
/* Old stack pointer is in rcx, lie and say we saved it in rbp */
.setframe rbp, 0
.endprolog
/* Swap gs to kernel, so we can access the PCR */
swapgs
/* Save the user mode rsp in the PCR */
mov gs:[PcUserRsp], rsp
/* Get the kernel stack from the PCR */
mov rsp, gs:[PcRspBase]
/* Allocate a TRAP_FRAME and space for parameters */
sub rsp, (KTRAP_FRAME_LENGTH + MAX_SYSCALL_PARAM_SIZE + HOME_SIZE)
#if DBG
/* Save rbp and load it with the old stack pointer */
mov [rsp + HOME_SIZE + MAX_SYSCALL_PARAM_SIZE + HOME_SIZE + KTRAP_FRAME_Rbp], rbp
mov rbp, gs:[PcUserRsp]
#endif
/* Save important volatiles in the trap frame */
mov [rsp + HOME_SIZE + MAX_SYSCALL_PARAM_SIZE + KTRAP_FRAME_Rax], rax
mov [rsp + HOME_SIZE + MAX_SYSCALL_PARAM_SIZE + KTRAP_FRAME_Rcx], rcx
mov [rsp + HOME_SIZE + MAX_SYSCALL_PARAM_SIZE + KTRAP_FRAME_R10], r10
mov [rsp + HOME_SIZE + MAX_SYSCALL_PARAM_SIZE + KTRAP_FRAME_R11], r11
/* Set sane segments */
mov ax, (KGDT64_R3_DATA or RPL_MASK)
mov ds, ax
mov es, ax
/* Call the C-handler (will enable interrupts) */
lea rcx, [rsp + SYSCALL_ALLOCATION]
call KiSystemCallHandler
/* Deallocate the handlers home stack frame */
add rsp, HOME_SIZE
/* The return value is the address of the Nt-function */
mov rcx, [rsp + 0]
mov rdx, [rsp + 8]
mov r8, [rsp + 16]
mov r9, [rsp + 24]
call rax
#if DBG
/* Restore rbp */
mov rbp, [rsp + SYSCALL_ALLOCATION + KTRAP_FRAME_Rbp]
#endif
/* Disable interrupts for return */
cli
/* Restore old trap frame */
mov rcx, gs:[PcCurrentThread]
mov rdx, [rsp + MAX_SYSCALL_PARAM_SIZE + KTRAP_FRAME_TrapFrame]
mov [rcx + KTHREAD_TrapFrame], rdx
/* Prepare user mode return address (rcx) and eflags (r11) for sysret */
mov rcx, [rsp + MAX_SYSCALL_PARAM_SIZE + KTRAP_FRAME_Rcx]
mov r11, [rsp + MAX_SYSCALL_PARAM_SIZE + KTRAP_FRAME_R11]
/* Load user mode stack (It was copied to the trap frame) */
mov rsp, [rsp + MAX_SYSCALL_PARAM_SIZE + KTRAP_FRAME_Rsp]
/* Swap gs back to user */
swapgs
/* return to user mode */
.byte HEX(48) // REX prefix to return to long mode
sysret
.ENDP
PUBLIC KiSystemCallEntry32
KiSystemCallEntry32:
swapgs
int 3
PUBLIC KiZwSystemService
FUNC KiZwSystemService
push rbp
.pushreg rbp
sub rsp, KTRAP_FRAME_LENGTH
.allocstack KTRAP_FRAME_LENGTH
mov [rsp + KTRAP_FRAME_Rsi], rsi
.savereg rsi, KTRAP_FRAME_Rsi
mov [rsp + KTRAP_FRAME_Rdi], rdi
.savereg rdi, KTRAP_FRAME_Rdi
mov rbp, rsp
.setframe rbp, 0
.endprolog
/* Get current thread */
mov r11, gs:[PcCurrentThread]
/* Save the old trap frame in TrapFrame.Rdx */
mov rdi, [r11 + KTHREAD_TrapFrame]
mov [rbp + KTRAP_FRAME_Rdx], rdi
/* Set the new trap frame and previous mode */
mov [r11 + ThTrapFrame], rbp
mov byte ptr [r11 + KTHREAD_PreviousMode], 0
/* allocate space for parameters */
sub rsp, r10
and rsp, HEX(0fffffffffffffff0)
/* Save rcx */
mov [rbp + KTRAP_FRAME_Rcx], rcx
/* copy parameters to the new location */
lea rsi, [rbp + KTRAP_FRAME_LENGTH + 16]
lea rdi, [rsp]
mov rcx, r10
shr rcx, 3
rep movsq
/* Restore rcx */
mov rcx, [rbp + KTRAP_FRAME_Rcx]
/* Call the service function */
call rax
/* Restore the old trap frame */
mov r11, gs:[PcCurrentThread]
mov rsi, [rsp + KTRAP_FRAME_Rdx]
mov [r11 + KTHREAD_TrapFrame], rsi
/* Restore rdi and rsi */
mov rsi, [rbp + KTRAP_FRAME_Rsi]
mov rdi, [rbp + KTRAP_FRAME_Rdi]
/* Cleanup the stack and return */
lea rsp, [rbp + KTRAP_FRAME_LENGTH]
pop rbp
ret
ENDFUNC
KiExitToUserApc:
int 3
/*!
* VOID
* DECLSPEC_NORETURN
* KiServiceExit(IN PKTRAP_FRAME TrapFrame, IN NTSTATUS Status));
*/
PUBLIC KiServiceExit
KiServiceExit:
mov [rcx + KTRAP_FRAME_Rax], rdx
mov rbp, rcx
mov rsp, rcx
/* Return */
//ExitTrap TF_SAVE_ALL
/*!
* VOID
* DECLSPEC_NORETURN
* KiServiceExit2(IN PKTRAP_FRAME TrapFrame);
*/
PUBLIC KiServiceExit2
.PROC KiServiceExit2
.ENDPROLOG
mov rbp, rcx
mov rsp, rcx
/* Return */
ExitTrap TF_SAVE_ALL
.ENDP
PUBLIC KiInitializeSegments
KiInitializeSegments:
mov ax, KGDT64_R3_DATA or RPL_MASK
mov gs, ax
swapgs
mov gs, ax
ret
#ifdef _MSC_VER
#undef lgdt
#undef lidt
@ -658,6 +949,11 @@ __str:
str word ptr [rcx]
ret
PUBLIC __swapgs
__swapgs:
swapgs
ret
#endif
END