Author: sir_richard
Date: Sat May 29 20:33:50 2010
New Revision: 47424
URL:
http://svn.reactos.org/svn/reactos?rev=47424&view=rev
Log:
Testers: Please pay attention to this build and test it fully:
[NTOS]: Implement MiDecrementShareCount (to start replacing MmReleasePageMemoryConsumer
calls for pages that were grabbed through ARM3, not Mm).
[NTOS]: Implement MiInitializePfn (to initialize pages grabbed through
ARM3/MiRemoveAnyPage instead of Mm/MmAllocPage).
[NTOS]: For stack pages, use new ARM3 PFN alloc/free routines, as a first test/beginning
of the new ARM3 ABI.
[NTOS]: Implement and start using the Pending-Deletion PFN flag.
[NTOS]: As a result, for stack pages, the Transition page state will now be seen, and the
new routine for re-inserting pages into the free list will now be used. Tracking of page
table references is also done now for these pages (but we don't free the PT since this
doesn't seem safe yet).
Modified:
trunk/reactos/ntoskrnl/mm/ARM3/contmem.c
trunk/reactos/ntoskrnl/mm/ARM3/miarm.h
trunk/reactos/ntoskrnl/mm/ARM3/pagfault.c
trunk/reactos/ntoskrnl/mm/ARM3/pfnlist.c
trunk/reactos/ntoskrnl/mm/ARM3/procsup.c
Modified: trunk/reactos/ntoskrnl/mm/ARM3/contmem.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/mm/ARM3/contmem.c…
==============================================================================
--- trunk/reactos/ntoskrnl/mm/ARM3/contmem.c [iso-8859-1] (original)
+++ trunk/reactos/ntoskrnl/mm/ARM3/contmem.c [iso-8859-1] Sat May 29 20:33:50 2010
@@ -502,6 +502,9 @@
ASSERT(Pfn1->u4.VerifierAllocation == 0);
ASSERT(Pfn1->u3.e1.PrototypePte == 0);
+ /* Set the special pending delete marker */
+ MI_SET_PFN_DELETED(Pfn1);
+
/* Keep going for assertions */
PointerPte++;
} while (Pfn1++->u3.e1.EndOfAllocation == 0);
@@ -531,12 +534,11 @@
// Loop all the pages
//
LastPage = PageFrameIndex + PageCount;
+ Pfn1 = MiGetPfnEntry(PageFrameIndex);
do
{
- //
- // Free each one, and move on
- //
- MmReleasePageMemoryConsumer(MC_NPPOOL, PageFrameIndex++);
+ /* Decrement the share count and move on */
+ MiDecrementShareCount(Pfn1++, PageFrameIndex++);
} while (PageFrameIndex < LastPage);
//
Modified: trunk/reactos/ntoskrnl/mm/ARM3/miarm.h
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/mm/ARM3/miarm.h?r…
==============================================================================
--- trunk/reactos/ntoskrnl/mm/ARM3/miarm.h [iso-8859-1] (original)
+++ trunk/reactos/ntoskrnl/mm/ARM3/miarm.h [iso-8859-1] Sat May 29 20:33:50 2010
@@ -118,6 +118,12 @@
// Creates a software PTE with the given protection
//
#define MI_MAKE_SOFTWARE_PTE(p, x) ((p)->u.Long = (x <<
MM_PTE_SOFTWARE_PROTECTION_BITS))
+
+//
+// Marks a PTE as deleted
+//
+#define MI_SET_PFN_DELETED(x) ((x)->PteAddress =
(PMMPTE)((ULONG_PTR)(x)->PteAddress | 1))
+#define MI_IS_PFN_DELETED(x) ((ULONG_PTR)((x)->PteAddress) & 1)
//
// Special values for LoadedImports
@@ -585,6 +591,21 @@
IN ULONG Protection
);
+VOID
+NTAPI
+MiInitializePfn(
+ IN PFN_NUMBER PageFrameIndex,
+ IN PMMPTE PointerPte,
+ IN BOOLEAN Modified
+);
+
+VOID
+NTAPI
+MiDecrementShareCount(
+ IN PMMPFN Pfn1,
+ IN PFN_NUMBER PageFrameIndex
+);
+
PFN_NUMBER
NTAPI
MiRemoveAnyPage(
Modified: trunk/reactos/ntoskrnl/mm/ARM3/pagfault.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/mm/ARM3/pagfault.…
==============================================================================
--- trunk/reactos/ntoskrnl/mm/ARM3/pagfault.c [iso-8859-1] (original)
+++ trunk/reactos/ntoskrnl/mm/ARM3/pagfault.c [iso-8859-1] Sat May 29 20:33:50 2010
@@ -91,7 +91,7 @@
{
PFN_NUMBER PageFrameNumber;
MMPTE TempPte;
- DPRINT("ARM3 Demand Zero Page Fault Handler for address: %p in process:
%p\n",
+ DPRINT1("ARM3 Demand Zero Page Fault Handler for address: %p in process:
%p\n",
Address,
Process);
Modified: trunk/reactos/ntoskrnl/mm/ARM3/pfnlist.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/mm/ARM3/pfnlist.c…
==============================================================================
--- trunk/reactos/ntoskrnl/mm/ARM3/pfnlist.c [iso-8859-1] (original)
+++ trunk/reactos/ntoskrnl/mm/ARM3/pfnlist.c [iso-8859-1] Sat May 29 20:33:50 2010
@@ -561,4 +561,126 @@
}
}
+VOID
+NTAPI
+MiInitializePfn(IN PFN_NUMBER PageFrameIndex,
+ IN PMMPTE PointerPte,
+ IN BOOLEAN Modified)
+{
+ PMMPFN Pfn1;
+ NTSTATUS Status;
+ PMMPTE PointerPtePte;
+ ASSERT(KeGetCurrentIrql() == DISPATCH_LEVEL);
+
+ /* Setup the PTE */
+ Pfn1 = MiGetPfnEntry(PageFrameIndex);
+ Pfn1->PteAddress = PointerPte;
+
+ /* Check if this PFN is part of a valid address space */
+ if (PointerPte->u.Hard.Valid == 1)
+ {
+ /* FIXME: TODO */
+ ASSERT(FALSE);
+ }
+
+ /* Otherwise this is a fresh page -- set it up */
+ ASSERT(Pfn1->u3.e2.ReferenceCount == 0);
+ Pfn1->u3.e2.ReferenceCount = 1;
+ Pfn1->u2.ShareCount = 1;
+ Pfn1->u3.e1.PageLocation = ActiveAndValid;
+ ASSERT(Pfn1->u3.e1.Rom == 0);
+ Pfn1->u3.e1.Modified = Modified;
+
+ /* Get the page table for the PTE */
+ PointerPtePte = MiAddressToPte(PointerPte);
+ if (PointerPtePte->u.Hard.Valid == 0)
+ {
+ /* Make sure the PDE gets paged in properly */
+ Status = MiCheckPdeForPagedPool(PointerPte);
+ if (!NT_SUCCESS(Status))
+ {
+ /* Crash */
+ KeBugCheckEx(MEMORY_MANAGEMENT,
+ 0x61940,
+ (ULONG_PTR)PointerPte,
+ (ULONG_PTR)PointerPtePte->u.Long,
+ (ULONG_PTR)MiPteToAddress(PointerPte));
+ }
+ }
+
+ /* Get the PFN for the page table */
+ PageFrameIndex = PFN_FROM_PTE(PointerPtePte);
+ ASSERT(PageFrameIndex != 0);
+ Pfn1->u4.PteFrame = PageFrameIndex;
+
+ /* Increase its share count so we don't get rid of it */
+ Pfn1 = MiGetPfnEntry(PageFrameIndex);
+ Pfn1->u2.ShareCount++;
+}
+
+VOID
+NTAPI
+MiDecrementShareCount(IN PMMPFN Pfn1,
+ IN PFN_NUMBER PageFrameIndex)
+{
+ ASSERT(PageFrameIndex > 0);
+ ASSERT(MiGetPfnEntry(PageFrameIndex) != NULL);
+ ASSERT(Pfn1 == MiGetPfnEntry(PageFrameIndex));
+
+ /* Page must be in-use */
+ if ((Pfn1->u3.e1.PageLocation != ActiveAndValid) &&
+ (Pfn1->u3.e1.PageLocation != StandbyPageList))
+ {
+ /* Otherwise we have PFN corruption */
+ KeBugCheckEx(PFN_LIST_CORRUPT,
+ 0x99,
+ PageFrameIndex,
+ Pfn1->u3.e1.PageLocation,
+ 0);
+ }
+
+ /* Check if the share count is now 0 */
+ ASSERT(Pfn1->u2.ShareCount < 0xF000000);
+ if (!--Pfn1->u2.ShareCount)
+ {
+ /* ReactOS does not handle these */
+ ASSERT(Pfn1->u3.e1.PrototypePte == 0);
+
+ /* Put the page in transition */
+ Pfn1->u3.e1.PageLocation = TransitionPage;
+
+ /* PFN lock must be held */
+ ASSERT(KeGetCurrentIrql() == DISPATCH_LEVEL);
+
+ /* Page should at least have one reference */
+ ASSERT(Pfn1->u3.e2.ReferenceCount != 0);
+ if (Pfn1->u3.e2.ReferenceCount == 1)
+ {
+ /* In ReactOS, this path should always be hit with a deleted PFN */
+ ASSERT(MI_IS_PFN_DELETED(Pfn1) == TRUE);
+
+ /* Clear the last reference */
+ Pfn1->u3.e2.ReferenceCount = 0;
+
+ /*
+ * OriginalPte is used by AweReferenceCount in ReactOS, but either
+ * ways we shouldn't be seeing RMAP entries at this point
+ */
+ ASSERT(Pfn1->OriginalPte.u.Soft.Prototype == 0);
+ ASSERT(Pfn1->OriginalPte.u.Long == 0);
+
+ /* Mark the page temporarily as valid, we're going to make it free soon
*/
+ Pfn1->u3.e1.PageLocation = ActiveAndValid;
+
+ /* Bring it back into the free list */
+ MiInsertPageInFreeList(PageFrameIndex);
+ }
+ else
+ {
+ /* Otherwise, just drop the reference count */
+ InterlockedDecrement16((PSHORT)&Pfn1->u3.e2.ReferenceCount);
+ }
+ }
+}
+
/* EOF */
Modified: trunk/reactos/ntoskrnl/mm/ARM3/procsup.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/mm/ARM3/procsup.c…
==============================================================================
--- trunk/reactos/ntoskrnl/mm/ARM3/procsup.c [iso-8859-1] (original)
+++ trunk/reactos/ntoskrnl/mm/ARM3/procsup.c [iso-8859-1] Sat May 29 20:33:50 2010
@@ -31,8 +31,10 @@
IN BOOLEAN GuiStack)
{
PMMPTE PointerPte;
- PFN_NUMBER StackPages;
+ PFN_NUMBER StackPages, PageFrameNumber;//, PageTableFrameNumber;
+ PMMPFN Pfn1;//, Pfn2;
ULONG i;
+ KIRQL OldIrql;
//
// This should be the guard page, so decrement by one
@@ -46,6 +48,9 @@
StackPages = BYTES_TO_PAGES(GuiStack ?
KERNEL_LARGE_STACK_SIZE : KERNEL_STACK_SIZE);
+ /* Acquire the PFN lock */
+ OldIrql = KeAcquireQueuedSpinLock(LockQueuePfnLock);
+
//
// Loop them
//
@@ -56,10 +61,22 @@
//
if (PointerPte->u.Hard.Valid == 1)
{
- //
- // Nuke it
- //
- MmReleasePageMemoryConsumer(MC_NPPOOL, PFN_FROM_PTE(PointerPte));
+ /* Get the PTE's page */
+ PageFrameNumber = PFN_FROM_PTE(PointerPte);
+ Pfn1 = MiGetPfnEntry(PageFrameNumber);
+#if 0 // ARM3 might not own the page table, so don't take this risk. Leak it
instead!
+ /* Now get the page of the page table mapping it */
+ PageTableFrameNumber = Pfn1->u4.PteFrame;
+ Pfn2 = MiGetPfnEntry(PageTableFrameNumber);
+
+ /* Remove a shared reference, since the page is going away */
+ MiDecrementShareCount(Pfn2, PageTableFrameNumber);
+#endif
+ /* Set the special pending delete marker */
+ Pfn1->PteAddress = (PMMPTE)((ULONG_PTR)Pfn1->PteAddress | 1);
+
+ /* And now delete the actual stack page */
+ MiDecrementShareCount(Pfn1, PageFrameNumber);
}
//
@@ -73,6 +90,9 @@
//
ASSERT(PointerPte->u.Hard.Valid == 0);
+ /* Release the PFN lock */
+ KeReleaseQueuedSpinLock(LockQueuePfnLock, OldIrql);
+
//
// Release the PTEs
//
@@ -154,15 +174,14 @@
//
PointerPte++;
- //
- // Get a page
- //
- PageFrameIndex = MmAllocPage(MC_NPPOOL);
+ /* Get a page */
+ PageFrameIndex = MiRemoveAnyPage(0);
+
+ /* Initialize the PFN entry for this page */
+ MiInitializePfn(PageFrameIndex, PointerPte, 1);
+
+ /* Write the valid PTE */
TempPte.u.Hard.PageFrameNumber = PageFrameIndex;
-
- //
- // Write it
- //
ASSERT(PointerPte->u.Hard.Valid == 0);
ASSERT(TempPte.u.Hard.Valid == 1);
*PointerPte = TempPte;
@@ -250,13 +269,14 @@
//
while (LimitPte >= NewLimitPte)
{
- //
- // Get a page
- //
- PageFrameIndex = MmAllocPage(MC_NPPOOL);
+ /* Get a page */
+ PageFrameIndex = MiRemoveAnyPage(0);
+
+ /* Initialize the PFN entry for this page */
+ MiInitializePfn(PageFrameIndex, LimitPte, 1);
+
+ /* Write the valid PTE */
TempPte.u.Hard.PageFrameNumber = PageFrameIndex;
-
- /* Write the valid PTE */
ASSERT(LimitPte->u.Hard.Valid == 0);
ASSERT(TempPte.u.Hard.Valid == 1);
*LimitPte-- = TempPte;