mirror of
https://github.com/reactos/reactos.git
synced 2025-08-06 10:12:58 +00:00
[NTOS:KE] Fix NtRaiseException and NtContinue on x64
- Implement KiExceptionExit, which works like KiServiceExit2, but takes an exception frame as 2nd parameter - Add a local exception frame to NtRaiseException and NtContinue, which is needed to exit with a full context on x64 and arm - Use KeContextToTrapFrame again instead of KiSetTrapContext, since we have a proper exception frame now.
This commit is contained in:
parent
dc3b208625
commit
4bc591c6f0
5 changed files with 85 additions and 73 deletions
|
@ -480,6 +480,12 @@ VOID
|
||||||
KiUserCallbackExit(
|
KiUserCallbackExit(
|
||||||
_In_ PKTRAP_FRAME TrapFrame);
|
_In_ PKTRAP_FRAME TrapFrame);
|
||||||
|
|
||||||
|
DECLSPEC_NORETURN
|
||||||
|
VOID
|
||||||
|
KiExceptionExit(
|
||||||
|
_In_ PKTRAP_FRAME TrapFrame,
|
||||||
|
_In_ PKEXCEPTION_FRAME ExceptionFrame);
|
||||||
|
|
||||||
BOOLEAN
|
BOOLEAN
|
||||||
KiProcessorFreezeHandler(
|
KiProcessorFreezeHandler(
|
||||||
_In_ PKTRAP_FRAME TrapFrame,
|
_In_ PKTRAP_FRAME TrapFrame,
|
||||||
|
|
|
@ -668,6 +668,31 @@ KiConvertToGuiThread(
|
||||||
VOID
|
VOID
|
||||||
);
|
);
|
||||||
|
|
||||||
|
DECLSPEC_NORETURN
|
||||||
|
VOID
|
||||||
|
FASTCALL
|
||||||
|
KiServiceExit(
|
||||||
|
IN PKTRAP_FRAME TrapFrame,
|
||||||
|
IN NTSTATUS Status
|
||||||
|
);
|
||||||
|
|
||||||
|
DECLSPEC_NORETURN
|
||||||
|
VOID
|
||||||
|
FASTCALL
|
||||||
|
KiServiceExit2(
|
||||||
|
IN PKTRAP_FRAME TrapFrame
|
||||||
|
);
|
||||||
|
|
||||||
|
FORCEINLINE
|
||||||
|
DECLSPEC_NORETURN
|
||||||
|
VOID
|
||||||
|
KiExceptionExit(
|
||||||
|
_In_ PKTRAP_FRAME TrapFrame,
|
||||||
|
_In_ PKEXCEPTION_FRAME ExceptionFrame)
|
||||||
|
{
|
||||||
|
KiServiceExit2(TrapFrame);
|
||||||
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Global x86 only Kernel data
|
// Global x86 only Kernel data
|
||||||
//
|
//
|
||||||
|
|
|
@ -883,21 +883,6 @@ KiContinue(
|
||||||
IN PKTRAP_FRAME TrapFrame
|
IN PKTRAP_FRAME TrapFrame
|
||||||
);
|
);
|
||||||
|
|
||||||
DECLSPEC_NORETURN
|
|
||||||
VOID
|
|
||||||
FASTCALL
|
|
||||||
KiServiceExit(
|
|
||||||
IN PKTRAP_FRAME TrapFrame,
|
|
||||||
IN NTSTATUS Status
|
|
||||||
);
|
|
||||||
|
|
||||||
DECLSPEC_NORETURN
|
|
||||||
VOID
|
|
||||||
FASTCALL
|
|
||||||
KiServiceExit2(
|
|
||||||
IN PKTRAP_FRAME TrapFrame
|
|
||||||
);
|
|
||||||
|
|
||||||
#ifndef _M_AMD64
|
#ifndef _M_AMD64
|
||||||
VOID
|
VOID
|
||||||
FASTCALL
|
FASTCALL
|
||||||
|
|
|
@ -944,62 +944,50 @@ NoUserApcPending:
|
||||||
/*!
|
/*!
|
||||||
* VOID
|
* VOID
|
||||||
* DECLSPEC_NORETURN
|
* DECLSPEC_NORETURN
|
||||||
* KiServiceExit(IN PKTRAP_FRAME TrapFrame, IN NTSTATUS Status));
|
* KiExceptionExit(
|
||||||
|
* _In_ PKTRAP_FRAME TrapFrame@<rcx>,
|
||||||
|
* _In_ PKEXCEPTION_FRAME ExceptionFrame@<rdx>);
|
||||||
*/
|
*/
|
||||||
PUBLIC KiServiceExit
|
PUBLIC KiExceptionExit
|
||||||
.PROC KiServiceExit
|
KiExceptionExit:
|
||||||
.endprolog
|
|
||||||
|
|
||||||
lea rsp, [rcx - MAX_SYSCALL_PARAM_SIZE]
|
/* Restore registers from exception frame */
|
||||||
jmp KiSystemServiceExit
|
movaps xmm6, [rdx + ExXmm6]
|
||||||
|
movaps xmm7, [rdx + ExXmm7]
|
||||||
.ENDP
|
movaps xmm8, [rdx + ExXmm8]
|
||||||
|
movaps xmm9, [rdx + ExXmm9]
|
||||||
|
movaps xmm10, [rdx + ExXmm10]
|
||||||
/*!
|
movaps xmm11, [rdx + ExXmm11]
|
||||||
* VOID
|
movaps xmm12, [rdx + ExXmm12]
|
||||||
* DECLSPEC_NORETURN
|
movaps xmm13, [rdx + ExXmm13]
|
||||||
* KiServiceExit2(IN PKTRAP_FRAME TrapFrame);
|
movaps xmm14, [rdx + ExXmm14]
|
||||||
*/
|
movaps xmm15, [rdx + ExXmm15]
|
||||||
PUBLIC KiServiceExit2
|
mov rbx, [rdx + ExRbx]
|
||||||
.PROC KiServiceExit2
|
mov rdi, [rdx + ExRdi]
|
||||||
.ENDPROLOG
|
mov rsi, [rdx + ExRsi]
|
||||||
|
mov r12, [rdx + ExR12]
|
||||||
// FIXME: this should probably also restore an exception frame
|
mov r13, [rdx + ExR13]
|
||||||
|
mov r14, [rdx + ExR14]
|
||||||
|
mov r15, [rdx + ExR15]
|
||||||
|
|
||||||
|
/* Point rsp at the trap frame */
|
||||||
mov rsp, rcx
|
mov rsp, rcx
|
||||||
.ENDP
|
/* Fall through */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Internal function. Exits to user-mode with rsp pointing to the trap frame.
|
||||||
|
* All non-volatile register context must be set up already.
|
||||||
|
* Used by KiInitializeContextThread to set up the init path for a new thread.
|
||||||
|
*/
|
||||||
PUBLIC KiServiceExit3
|
PUBLIC KiServiceExit3
|
||||||
.PROC KiServiceExit3
|
.PROC KiServiceExit3
|
||||||
.PUSHFRAME
|
.PUSHFRAME
|
||||||
.ALLOCSTACK (KTRAP_FRAME_LENGTH - MachineFrameLength)
|
.ALLOCSTACK (KTRAP_FRAME_LENGTH - MachineFrameLength)
|
||||||
.ENDPROLOG
|
.ENDPROLOG
|
||||||
|
|
||||||
#if DBG
|
|
||||||
/* Get the current IRQL and compare it to the trap frame */
|
|
||||||
mov rax, cr8
|
|
||||||
cmp byte ptr [rsp + KTRAP_FRAME_PreviousIrql], al
|
|
||||||
je KiServiceExit2_ok1
|
|
||||||
int HEX(2C)
|
|
||||||
|
|
||||||
KiServiceExit2_ok1:
|
|
||||||
/* Check if this is a user mode exit */
|
|
||||||
mov ah, byte ptr [rsp + KTRAP_FRAME_SegCs]
|
|
||||||
test ah, 1
|
|
||||||
jz KiServiceExit2_kernel
|
|
||||||
|
|
||||||
/* Validate that we are at PASSIVE_LEVEL */
|
|
||||||
test al, al
|
|
||||||
jz KiServiceExit2_kernel
|
|
||||||
int HEX(2C)
|
|
||||||
|
|
||||||
KiServiceExit2_kernel:
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Return */
|
/* Return */
|
||||||
mov rbp, rsp
|
mov rbp, rsp
|
||||||
ExitTrap TF_SAVE_ALL
|
ExitTrap (TF_SEGMENTS or TF_CHECKUSERAPC)
|
||||||
.ENDP
|
.ENDP
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -28,16 +28,12 @@ KiContinuePreviousModeUser(IN PCONTEXT Context,
|
||||||
RtlCopyMemory(&LocalContext, Context, sizeof(CONTEXT));
|
RtlCopyMemory(&LocalContext, Context, sizeof(CONTEXT));
|
||||||
Context = &LocalContext;
|
Context = &LocalContext;
|
||||||
|
|
||||||
#ifdef _M_AMD64
|
|
||||||
KiSetTrapContext(TrapFrame, &LocalContext, UserMode);
|
|
||||||
#else
|
|
||||||
/* Convert the context into Exception/Trap Frames */
|
/* Convert the context into Exception/Trap Frames */
|
||||||
KeContextToTrapFrame(&LocalContext,
|
KeContextToTrapFrame(&LocalContext,
|
||||||
ExceptionFrame,
|
ExceptionFrame,
|
||||||
TrapFrame,
|
TrapFrame,
|
||||||
LocalContext.ContextFlags,
|
LocalContext.ContextFlags,
|
||||||
UserMode);
|
UserMode);
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
NTSTATUS
|
NTSTATUS
|
||||||
|
@ -66,16 +62,12 @@ KiContinue(IN PCONTEXT Context,
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
#ifdef _M_AMD64
|
|
||||||
KiSetTrapContext(TrapFrame, Context, KernelMode);
|
|
||||||
#else
|
|
||||||
/* Convert the context into Exception/Trap Frames */
|
/* Convert the context into Exception/Trap Frames */
|
||||||
KeContextToTrapFrame(Context,
|
KeContextToTrapFrame(Context,
|
||||||
ExceptionFrame,
|
ExceptionFrame,
|
||||||
TrapFrame,
|
TrapFrame,
|
||||||
Context->ContextFlags,
|
Context->ContextFlags,
|
||||||
KernelMode);
|
KernelMode);
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
|
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
|
||||||
|
@ -183,8 +175,14 @@ NtRaiseException(IN PEXCEPTION_RECORD ExceptionRecord,
|
||||||
NTSTATUS Status;
|
NTSTATUS Status;
|
||||||
PKTHREAD Thread;
|
PKTHREAD Thread;
|
||||||
PKTRAP_FRAME TrapFrame;
|
PKTRAP_FRAME TrapFrame;
|
||||||
|
#ifdef _M_IX86
|
||||||
|
PKEXCEPTION_FRAME ExceptionFrame = NULL;
|
||||||
|
#else
|
||||||
|
KEXCEPTION_FRAME LocalExceptionFrame;
|
||||||
|
PKEXCEPTION_FRAME ExceptionFrame = &LocalExceptionFrame;
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Get trap frame and link previous one*/
|
/* Get trap frame and link previous one */
|
||||||
Thread = KeGetCurrentThread();
|
Thread = KeGetCurrentThread();
|
||||||
TrapFrame = Thread->TrapFrame;
|
TrapFrame = Thread->TrapFrame;
|
||||||
Thread->TrapFrame = KiGetLinkedTrapFrame(TrapFrame);
|
Thread->TrapFrame = KiGetLinkedTrapFrame(TrapFrame);
|
||||||
|
@ -197,21 +195,23 @@ NtRaiseException(IN PEXCEPTION_RECORD ExceptionRecord,
|
||||||
/* Raise the exception */
|
/* Raise the exception */
|
||||||
Status = KiRaiseException(ExceptionRecord,
|
Status = KiRaiseException(ExceptionRecord,
|
||||||
Context,
|
Context,
|
||||||
NULL,
|
ExceptionFrame,
|
||||||
TrapFrame,
|
TrapFrame,
|
||||||
FirstChance);
|
FirstChance);
|
||||||
if (NT_SUCCESS(Status))
|
if (NT_SUCCESS(Status))
|
||||||
{
|
{
|
||||||
/* It was handled, so exit restoring all state */
|
/* It was handled, so exit restoring all state */
|
||||||
KiServiceExit2(TrapFrame);
|
KiExceptionExit(TrapFrame, ExceptionFrame);
|
||||||
}
|
}
|
||||||
|
#ifdef _M_IX86
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* Exit with error */
|
/* Exit with error */
|
||||||
KiServiceExit(TrapFrame, Status);
|
KiServiceExit(TrapFrame, Status);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/* We don't actually make it here */
|
/* Return to the caller */
|
||||||
return Status;
|
return Status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -223,6 +223,12 @@ NtContinue(IN PCONTEXT Context,
|
||||||
PKTHREAD Thread;
|
PKTHREAD Thread;
|
||||||
NTSTATUS Status;
|
NTSTATUS Status;
|
||||||
PKTRAP_FRAME TrapFrame;
|
PKTRAP_FRAME TrapFrame;
|
||||||
|
#ifdef _M_IX86
|
||||||
|
PKEXCEPTION_FRAME ExceptionFrame = NULL;
|
||||||
|
#else
|
||||||
|
KEXCEPTION_FRAME LocalExceptionFrame;
|
||||||
|
PKEXCEPTION_FRAME ExceptionFrame = &LocalExceptionFrame;
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Get trap frame and link previous one*/
|
/* Get trap frame and link previous one*/
|
||||||
Thread = KeGetCurrentThread();
|
Thread = KeGetCurrentThread();
|
||||||
|
@ -230,22 +236,24 @@ NtContinue(IN PCONTEXT Context,
|
||||||
Thread->TrapFrame = KiGetLinkedTrapFrame(TrapFrame);
|
Thread->TrapFrame = KiGetLinkedTrapFrame(TrapFrame);
|
||||||
|
|
||||||
/* Continue from this point on */
|
/* Continue from this point on */
|
||||||
Status = KiContinue(Context, NULL, TrapFrame);
|
Status = KiContinue(Context, ExceptionFrame, TrapFrame);
|
||||||
if (NT_SUCCESS(Status))
|
if (NT_SUCCESS(Status))
|
||||||
{
|
{
|
||||||
/* Check if alert was requested */
|
/* Check if alert was requested */
|
||||||
if (TestAlert) KeTestAlertThread(Thread->PreviousMode);
|
if (TestAlert) KeTestAlertThread(Thread->PreviousMode);
|
||||||
|
|
||||||
/* Exit to new trap frame */
|
/* Exit to new trap frame */
|
||||||
KiServiceExit2(TrapFrame);
|
KiExceptionExit(TrapFrame, ExceptionFrame);
|
||||||
}
|
}
|
||||||
|
#ifdef _M_IX86
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* Exit with an error */
|
/* Exit with an error */
|
||||||
KiServiceExit(TrapFrame, Status);
|
KiServiceExit(TrapFrame, Status);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/* We don't actually make it here */
|
/* Return to the caller */
|
||||||
return Status;
|
return Status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue