https://git.reactos.org/?p=reactos.git;a=commitdiff;h=dd73d1b6d414660a42d075...
commit dd73d1b6d414660a42d07598ad040357fd40019d Author: Timo Kreuzer timo.kreuzer@reactos.org AuthorDate: Sun Feb 4 13:30:47 2018 +0100 Commit: Timo Kreuzer timo.kreuzer@reactos.org CommitDate: Thu Aug 16 16:52:02 2018 +0200
[NTOS:MM] Make SLIST handling for kernel stacks portable
Kernel stacks that re freed, can be placed on an SLIST for quick reuse. The old code was using a member of the PFN of the last stack page as the SLIST_ENTRY. This relies on the following (non-portable) assumptions: - A stack always has a PTE associated with it. - This PTE has a PFN associated with it. - The PFN has an empty field that can be re-used as an SLIST_ENTRY. - The PFN has another field that points back to the PTE, which then can be used to get the stack base.
Specifically: On x64 the PFN field is not 16 bytes aligned, so it cannot be used as an SLIST_ENTRY. (In a "usermode kernel" the other assumptions are also invalid).
The new code does what Windows does (and which seems absolutely obvious to do): Place the SLIST_ENTRY directly on the stack. --- ntoskrnl/mm/ARM3/procsup.c | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-)
diff --git a/ntoskrnl/mm/ARM3/procsup.c b/ntoskrnl/mm/ARM3/procsup.c index 009168eba9..51502b9a5d 100644 --- a/ntoskrnl/mm/ARM3/procsup.c +++ b/ntoskrnl/mm/ARM3/procsup.c @@ -175,6 +175,7 @@ MmDeleteKernelStack(IN PVOID StackBase, PMMPFN Pfn1, Pfn2; ULONG i; KIRQL OldIrql; + PSLIST_ENTRY SListEntry;
// // This should be the guard page, so decrement by one @@ -189,9 +190,8 @@ MmDeleteKernelStack(IN PVOID StackBase, { if (ExQueryDepthSList(&MmDeadStackSListHead) < MmMaximumDeadKernelStacks) { - Pfn1 = MiGetPfnEntry(PointerPte->u.Hard.PageFrameNumber); - InterlockedPushEntrySList(&MmDeadStackSListHead, - (PSLIST_ENTRY)&Pfn1->u1.NextStackPfn); + SListEntry = ((PSLIST_ENTRY)StackBase) - 1; + InterlockedPushEntrySList(&MmDeadStackSListHead, SListEntry); return; } } @@ -265,7 +265,7 @@ MmCreateKernelStack(IN BOOLEAN GuiStack, KIRQL OldIrql; PFN_NUMBER PageFrameIndex; ULONG i; - PMMPFN Pfn1; + PSLIST_ENTRY SListEntry;
// // Calculate pages needed @@ -286,11 +286,10 @@ MmCreateKernelStack(IN BOOLEAN GuiStack, // if (ExQueryDepthSList(&MmDeadStackSListHead)) { - Pfn1 = (PMMPFN)InterlockedPopEntrySList(&MmDeadStackSListHead); - if (Pfn1) + SListEntry = InterlockedPopEntrySList(&MmDeadStackSListHead); + if (SListEntry != NULL) { - PointerPte = Pfn1->PteAddress; - BaseAddress = MiPteToAddress(++PointerPte); + BaseAddress = (SListEntry + 1); return BaseAddress; } }