mirror of
https://github.com/reactos/reactos.git
synced 2024-12-28 10:04:49 +00:00
[NTOS:KE:X64] Change the logic of KeSwitchKernelStack and friends to be standards conforming
The previous version (like the x86 one) used a combination of C and asm code, called from C code to switch the stack. This is problematic, since there is no guarantee what assumptions C code makes about the stack (i.e. it can place any kind of stack pointers into registers or on the stack itself.) The new algorithm returns back to the systemcall entry point in asm, which then calls KiConvertToGuiThread, which is also asm and calls KeSwitchKernelStack ...
This commit is contained in:
parent
18b1aafd82
commit
c86c55ace7
2 changed files with 57 additions and 12 deletions
|
@ -13,6 +13,10 @@
|
|||
#define NDEBUG
|
||||
#include <debug.h>
|
||||
|
||||
ULONG ProcessCount;
|
||||
BOOLEAN CcPfEnablePrefetcher;
|
||||
SIZE_T KeXStateLength = sizeof(XSAVE_FORMAT);
|
||||
|
||||
VOID
|
||||
KiRetireDpcListInDpcStack(
|
||||
PKPRCB Prcb,
|
||||
|
@ -96,14 +100,28 @@ KiSwitchKernelStackHelper(
|
|||
LONG_PTR StackOffset,
|
||||
PVOID OldStackBase);
|
||||
|
||||
/*
|
||||
* Kernel stack layout (example pointers):
|
||||
* 0xFFFFFC0F'2D008000 KTHREAD::StackBase
|
||||
* [XSAVE_AREA size == KeXStateLength = 0x440]
|
||||
* 0xFFFFFC0F'2D007BC0 KTHREAD::StateSaveArea _XSAVE_FORMAT
|
||||
* 0xFFFFFC0F'2D007B90 KTHREAD::InitialStack
|
||||
* [0x190 bytes KTRAP_FRAME]
|
||||
* 0xFFFFFC0F'2D007A00 KTHREAD::TrapFrame
|
||||
* [KSTART_FRAME] or ...
|
||||
* [KSWITCH_FRAME]
|
||||
* 0xFFFFFC0F'2D007230 KTHREAD::KernelStack
|
||||
*/
|
||||
|
||||
PVOID
|
||||
NTAPI
|
||||
KeSwitchKernelStack(PVOID StackBase, PVOID StackLimit)
|
||||
KiSwitchKernelStack(PVOID StackBase, PVOID StackLimit)
|
||||
{
|
||||
PKTHREAD CurrentThread;
|
||||
PVOID OldStackBase;
|
||||
LONG_PTR StackOffset;
|
||||
SIZE_T StackSize;
|
||||
PKIPCR Pcr;
|
||||
|
||||
/* Get the current thread */
|
||||
CurrentThread = KeGetCurrentThread();
|
||||
|
@ -139,20 +157,17 @@ KeSwitchKernelStack(PVOID StackBase, PVOID StackLimit)
|
|||
CurrentThread->StackLimit = (ULONG_PTR)StackLimit;
|
||||
CurrentThread->LargeStack = TRUE;
|
||||
|
||||
/* Adjust the PCR fields */
|
||||
__addgsqword(FIELD_OFFSET(KPCR, NtTib.StackBase), StackOffset);
|
||||
__addgsqword(FIELD_OFFSET(KIPCR, Prcb.RspBase), StackOffset);
|
||||
/* Adjust RspBase in the PCR */
|
||||
Pcr = (PKIPCR)KeGetPcr();
|
||||
Pcr->Prcb.RspBase += StackOffset;
|
||||
|
||||
/* Finally switch RSP to the new stack.
|
||||
We pass OldStackBase to make sure it is not lost. */
|
||||
OldStackBase = KiSwitchKernelStackHelper(StackOffset, OldStackBase);
|
||||
|
||||
/* Reenable interrupts */
|
||||
_enable();
|
||||
/* Adjust Rsp0 in the TSS */
|
||||
Pcr->TssBase->Rsp0 += StackOffset;
|
||||
|
||||
return OldStackBase;
|
||||
}
|
||||
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
KeUserModeCallback(IN ULONG RoutineIndex,
|
||||
|
|
|
@ -22,7 +22,6 @@ EXTERN KiDeliverApc:PROC
|
|||
EXTERN KiDpcInterruptHandler:PROC
|
||||
EXTERN PsConvertToGuiThread:PROC
|
||||
EXTERN MmCreateKernelStack:PROC
|
||||
EXTERN KeSwitchKernelStack:PROC
|
||||
EXTERN MmDeleteKernelStack:PROC
|
||||
|
||||
#ifdef _WINKD_
|
||||
|
@ -774,7 +773,7 @@ PUBLIC KiSystemCallEntry64
|
|||
|
||||
.PROC KiSystemCall64Again
|
||||
|
||||
/* Old stack pointer is in rcx, lie and say we saved it in rbp */
|
||||
/* Old stack pointer is in rcx, lie and say we saved it in rbp */
|
||||
.setframe rbp, 0
|
||||
.endprolog
|
||||
|
||||
|
@ -1023,6 +1022,37 @@ KiSwitchKernelStackHelper:
|
|||
mov rax, rdx
|
||||
ret
|
||||
|
||||
EXTERN KiSwitchKernelStack:PROC
|
||||
|
||||
PUBLIC KeSwitchKernelStack
|
||||
FUNC KeSwitchKernelStack
|
||||
|
||||
sub rsp, 40
|
||||
.allocstack 40
|
||||
|
||||
; Save rcx
|
||||
mov [rsp], rcx
|
||||
.savereg rcx, 0
|
||||
.endprolog
|
||||
|
||||
; Call the C handler, which returns the old stack in rax
|
||||
call KiSwitchKernelStack
|
||||
|
||||
; Restore rcx (StackBase)
|
||||
mov rcx, [rsp]
|
||||
|
||||
; Switch to new stack: RSP += (StackBase - OldStackBase)
|
||||
sub rcx, rax
|
||||
add rsp, rcx
|
||||
|
||||
; Deallocate the home frame
|
||||
add rsp, 40
|
||||
ret
|
||||
|
||||
ENDFUNC
|
||||
|
||||
|
||||
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#undef lgdt
|
||||
|
|
Loading…
Reference in a new issue