mirror of
https://github.com/reactos/reactos.git
synced 2025-02-24 01:15:09 +00:00
[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:
parent
de74279d5b
commit
597c140370
9 changed files with 1354 additions and 322 deletions
|
@ -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
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in a new issue