https://git.reactos.org/?p=reactos.git;a=commitdiff;h=dd73d1b6d414660a42d07…
commit dd73d1b6d414660a42d07598ad040357fd40019d
Author: Timo Kreuzer <timo.kreuzer(a)reactos.org>
AuthorDate: Sun Feb 4 13:30:47 2018 +0100
Commit: Timo Kreuzer <timo.kreuzer(a)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;
}
}