Author: sir_richard
Date: Mon Sep 27 17:36:54 2010
New Revision: 48910
URL: http://svn.reactos.org/svn/reactos?rev=48910&view=rev
Log:
[NTOS]: Adding colored page lists means we need to start using the OriginalPte field as a forward/back link. This is shared with AweReferenceCount, which ReactOS uses as the RMAP list head. However, RMAPped pages shoudl never be free/zero, and non-free-zero pages will never have a color backlink in OriginalPte, so it should theoretically be safe to do this. However, it's possible for the RMAP "get" function to be called on a free/zero page (which would normally return NULL), but with color chaining enabled, the "get" function would misinterpret the backlink as an RMAP entry. Therefore, we overload the ParityError bit to signify "there is an RMAP". The get/set functions now handle this, and the color linkage will ASSERT this later. This way, a colorlink with ParityError == FALSE is not treated as an rmap list head.
Modified:
trunk/reactos/ntoskrnl/mm/freelist.c
Modified: trunk/reactos/ntoskrnl/mm/freelist.c
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/mm/freelist.c?rev…
==============================================================================
--- trunk/reactos/ntoskrnl/mm/freelist.c [iso-8859-1] (original)
+++ trunk/reactos/ntoskrnl/mm/freelist.c [iso-8859-1] Mon Sep 27 17:36:54 2010
@@ -432,25 +432,68 @@
NTAPI
MmSetRmapListHeadPage(PFN_NUMBER Pfn, struct _MM_RMAP_ENTRY* ListHead)
{
- KIRQL oldIrql;
-
- oldIrql = KeAcquireQueuedSpinLock(LockQueuePfnLock);
- MiGetPfnEntry(Pfn)->RmapListHead = (LONG)ListHead;
- KeReleaseQueuedSpinLock(LockQueuePfnLock, oldIrql);
+ KIRQL oldIrql;
+ PMMPFN Pfn1;
+
+ oldIrql = KeAcquireQueuedSpinLock(LockQueuePfnLock);
+ Pfn1 = MiGetPfnEntry(Pfn);
+ if (ListHead)
+ {
+ /* Should not be trying to insert an RMAP for a non-active page */
+ ASSERT(MiIsPfnInUse(Pfn1) == TRUE);
+
+ /* Set the list head address */
+ Pfn1->RmapListHead = (LONG)ListHead;
+
+ /* Mark that the page has an actual RMAP, not a residual color link */
+ Pfn1->u3.e1.ParityError = TRUE;
+ }
+ else
+ {
+ /* ReactOS semantics dictate the page is STILL active right now */
+ ASSERT(MiIsPfnInUse(Pfn1) == TRUE);
+
+ /* In this case, the RMAP is actually being removed, so clear field */
+ Pfn1->RmapListHead = 0;
+
+ /* Mark that the page has no RMAP, not a residual color link */
+ Pfn1->u3.e1.ParityError = FALSE;
+
+ /* ReactOS semantics will now release the page, which will make it free and enter a colored list */
+ }
+
+ KeReleaseQueuedSpinLock(LockQueuePfnLock, oldIrql);
}
struct _MM_RMAP_ENTRY*
NTAPI
MmGetRmapListHeadPage(PFN_NUMBER Pfn)
{
- KIRQL oldIrql;
- struct _MM_RMAP_ENTRY* ListHead;
-
- oldIrql = KeAcquireQueuedSpinLock(LockQueuePfnLock);
- ListHead = (struct _MM_RMAP_ENTRY*)MiGetPfnEntry(Pfn)->RmapListHead;
- KeReleaseQueuedSpinLock(LockQueuePfnLock, oldIrql);
-
- return(ListHead);
+ KIRQL oldIrql;
+ struct _MM_RMAP_ENTRY* ListHead;
+ PMMPFN Pfn1;
+
+ /* Lock PFN database */
+ oldIrql = KeAcquireQueuedSpinLock(LockQueuePfnLock);
+
+ /* Get the entry */
+ Pfn1 = MiGetPfnEntry(Pfn);
+
+ /* Check if the page doesn't really have an RMAP */
+ if (Pfn1->u3.e1.ParityError == FALSE)
+ {
+ KeReleaseQueuedSpinLock(LockQueuePfnLock, oldIrql);
+ return NULL;
+ }
+
+ ListHead = (struct _MM_RMAP_ENTRY*)Pfn1->RmapListHead;
+
+ /* Should not have an RMAP for a non-active page */
+ ASSERT(MiIsPfnInUse(Pfn1) == TRUE);
+
+ /* Release PFN database and return rmap list head */
+ KeReleaseQueuedSpinLock(LockQueuePfnLock, oldIrql);
+ return ListHead;
}
VOID
Author: sir_richard
Date: Mon Sep 27 17:09:33 2010
New Revision: 48909
URL: http://svn.reactos.org/svn/reactos?rev=48909&view=rev
Log:
[NTOS]: Don't use dangerous MiRemoveHeadList in MDL page allocation, use MiRemoveAnyPage instead.
[NTOS]: Don't repurpose pages from the zero/free page list without actually unlinking the page first! This should fix even more corruptions.
Modified:
trunk/reactos/ntoskrnl/mm/freelist.c
Modified: trunk/reactos/ntoskrnl/mm/freelist.c
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/mm/freelist.c?rev…
==============================================================================
--- trunk/reactos/ntoskrnl/mm/freelist.c [iso-8859-1] (original)
+++ trunk/reactos/ntoskrnl/mm/freelist.c [iso-8859-1] Mon Sep 27 17:09:33 2010
@@ -229,32 +229,18 @@
//
while (PagesFound < PageCount)
{
- //
- // Do we have zeroed pages?
- //
- if (MmZeroedPageListHead.Total)
+ /* Grab a page */
+ Page = MiRemoveAnyPage(0);
+ if (Page == 0)
{
- //
- // Grab a zero page
- //
- Pfn1 = MiRemoveHeadList(&MmZeroedPageListHead);
- }
- else if (MmFreePageListHead.Total)
- {
- //
- // Nope, grab an unzeroed page
- //
- Pfn1 = MiRemoveHeadList(&MmFreePageListHead);
- }
- else
- {
- //
- // This is not good... hopefully we have at least SOME pages
- //
+ /* This is not good... hopefully we have at least SOME pages */
ASSERT(PagesFound);
break;
}
+ /* Grab the page entry for it */
+ Pfn1 = MiGetPfnEntry(Page);
+
//
// Make sure it's really free
//
@@ -266,11 +252,6 @@
Pfn1->u3.e1.StartOfAllocation = 1;
Pfn1->u3.e1.EndOfAllocation = 1;
Pfn1->u3.e2.ReferenceCount = 1;
-
- //
- // Decrease available pages
- //
- MmAvailablePages--;
//
// Save it into the MDL
@@ -303,6 +284,9 @@
if (MiIsPfnInUse(Pfn1)) continue;
if ((Pfn1->u3.e1.PageLocation == ZeroedPageList) != LookForZeroedPages) continue;
+ /* Remove the page from the free or zero list */
+ MiUnlinkFreeOrZeroedPage(Pfn1);
+
//
// Sanity checks
//
@@ -314,11 +298,6 @@
Pfn1->u3.e2.ReferenceCount = 1;
Pfn1->u3.e1.StartOfAllocation = 1;
Pfn1->u3.e1.EndOfAllocation = 1;
-
- //
- // Decrease available pages
- //
- MmAvailablePages--;
//
// Save this page into the MDL