#define MODULE_INVOLVED_IN_ARM3
#include "../ARM3/miarm.h"
+#if DBG
+#define ASSERT_LIST_INVARIANT(x) \
+do { \
+ ASSERT(((x)->Total == 0 && \
+ (x)->Flink == LIST_HEAD && \
+ (x)->Blink == LIST_HEAD) || \
+ ((x)->Total != 0 && \
+ (x)->Flink != LIST_HEAD && \
+ (x)->Blink != LIST_HEAD)); \
+} while (0)
+#else
+#define ASSERT_LIST_INVARIANT(x)
+#endif
+
/* GLOBALS ********************************************************************/
BOOLEAN MmDynamicPfn;
IN PMMPFN Entry)
{
PFN_NUMBER OldBlink, EntryIndex = MiGetPfnEntryIndex(Entry);
+ ASSERT(KeGetCurrentIrql() == DISPATCH_LEVEL);
+ ASSERT_LIST_INVARIANT(ListHead);
/* Get the back link */
OldBlink = ListHead->Blink;
/* And now the head points back to us, since we are last */
ListHead->Blink = EntryIndex;
ListHead->Total++;
+ ASSERT_LIST_INVARIANT(ListHead);
}
VOID
/* Use the zero list */
ListHead = &MmZeroedPageListHead;
+ ASSERT_LIST_INVARIANT(ListHead);
ListHead->Total++;
/* Get the back link */
/* And now the head points back to us, since we are last */
ListHead->Blink = EntryIndex;
+ ASSERT_LIST_INVARIANT(ListHead);
/* Update the page location */
Pfn1->u3.e1.PageLocation = ZeroedPageList;
/* Otherwise check if we reached the high threshold and signal the event */
KeSetEvent(MiHighMemoryEvent, 0, FALSE);
}
+
#if 0
/* Get the page color */
Color = EntryIndex & MmSecondaryColorMask;
/* Make sure the PFN lock is held */
ASSERT(KeGetCurrentIrql() == DISPATCH_LEVEL);
-
+
/* Make sure the PFN entry isn't in-use */
ASSERT(Entry->u3.e1.WriteInProgress == 0);
ASSERT(Entry->u3.e1.ReadInProgress == 0);
ListName = ListHead->ListName;
ASSERT(ListHead != NULL);
ASSERT(ListName <= FreePageList);
-
+ ASSERT_LIST_INVARIANT(ListHead);
+
/* Remove one count */
ASSERT(ListHead->Total != 0);
ListHead->Total--;
else
{
/* Set the list head's backlink instead */
- ListHead->Blink = OldFlink;
+ ListHead->Blink = OldBlink;
}
/* Check if the back entry is the list head */
/* We are not on a list anymore */
Entry->u1.Flink = Entry->u2.Blink = 0;
-
+ ASSERT_LIST_INVARIANT(ListHead);
+
/* FIXME: Deal with color list */
/* See if we hit any thresholds */
/* Could be either on free or zero list */
ListHead = MmPageLocationList[Pfn1->u3.e1.PageLocation];
+ ASSERT_LIST_INVARIANT(ListHead);
ListName = ListHead->ListName;
ASSERT(ListName <= FreePageList);
}
/* We are not on a list anymore */
+ ASSERT_LIST_INVARIANT(ListHead);
Pfn1->u1.Flink = Pfn1->u2.Blink = 0;
/* Zero flags but restore color and cache */
Pfn1->u3.e2.ShortFlags = 0;
Pfn1->u3.e1.PageColor = OldColor;
Pfn1->u3.e1.CacheAttribute = OldCache;
+
#if 0 // When switching to ARM3
/* Get the first page on the color list */
ColorTable = &MmFreePagesByColor[ListName][Color];
{
#endif
/* Check the free list */
+ ASSERT_LIST_INVARIANT(&MmFreePageListHead);
PageIndex = MmFreePageListHead.Flink;
Color = PageIndex & MmSecondaryColorMask;
if (PageIndex == LIST_HEAD)
{
/* Check the zero list */
- ASSERT(MmFreePageListHead.Total == 0);
+ ASSERT_LIST_INVARIANT(&MmZeroedPageListHead);
PageIndex = MmZeroedPageListHead.Flink;
Color = PageIndex & MmSecondaryColorMask;
ASSERT(PageIndex != LIST_HEAD);
(Pfn1->u3.e1.PageLocation == ZeroedPageList));
ASSERT(Pfn1->u3.e2.ReferenceCount == 0);
ASSERT(Pfn1->u2.ShareCount == 0);
+ ASSERT_LIST_INVARIANT(&MmFreePageListHead);
+ ASSERT_LIST_INVARIANT(&MmZeroedPageListHead);
/* Return the page */
return PageIndex;
{
PFN_NUMBER Entry, Flink;
PMMPFN Pfn1;
-
+ ASSERT(KeGetCurrentIrql() == DISPATCH_LEVEL);
+ ASSERT_LIST_INVARIANT(ListHead);
+
/* Get the entry that's currently first on the list */
Entry = ListHead->Flink;
Pfn1 = MiGetPfnEntry(Entry);
/* We are not on a list anymore */
Pfn1->u1.Flink = Pfn1->u2.Blink = 0;
ListHead->Total--;
-
+ ASSERT_LIST_INVARIANT(ListHead);
+
/* Return the head element */
return Pfn1;
}
PMMCOLOR_TABLES ColorTable;
#endif
/* Make sure the page index is valid */
+ ASSERT(KeGetCurrentIrql() >= DISPATCH_LEVEL);
ASSERT((PageFrameIndex != 0) &&
(PageFrameIndex <= MmHighestPhysicalPage) &&
(PageFrameIndex >= MmLowestPhysicalPage));
/* Get the free page list and increment its count */
ListHead = &MmFreePageListHead;
+ ASSERT_LIST_INVARIANT(ListHead);
ListHead->Total++;
/* Get the last page on the list */
/* Now make the list head point back to us (since we go at the end) */
ListHead->Blink = PageFrameIndex;
-
+ ASSERT_LIST_INVARIANT(ListHead);
+
/* And initialize our own list pointers */
Pfn1->u1.Flink = LIST_HEAD;
Pfn1->u2.Blink = LastPage;
/* Set the list name and default priority */
Pfn1->u3.e1.PageLocation = FreePageList;
Pfn1->u4.Priority = 3;
-
+
/* Clear some status fields */
Pfn1->u4.InPageError = 0;
Pfn1->u4.AweAllocation = 0;
Pfn1->u2.ShareCount++;
}
+PFN_NUMBER
+NTAPI
+MiAllocatePfn(IN PMMPTE PointerPte,
+ IN ULONG Protection)
+{
+ KIRQL OldIrql;
+ PFN_NUMBER PageFrameIndex;
+ MMPTE TempPte;
+
+ /* Make an empty software PTE */
+ MI_MAKE_SOFTWARE_PTE(&TempPte, MM_READWRITE);
+
+ /* Lock the PFN database */
+ OldIrql = KeAcquireQueuedSpinLock(LockQueuePfnLock);
+
+ /* Check if we're running low on pages */
+ if (MmAvailablePages < 128)
+ {
+ DPRINT1("Warning, running low on memory: %d pages left\n", MmAvailablePages);
+ //MiEnsureAvailablePageOrWait(NULL, OldIrql);
+ }
+
+ /* Grab a page */
+ ASSERT_LIST_INVARIANT(&MmFreePageListHead);
+ ASSERT_LIST_INVARIANT(&MmZeroedPageListHead);
+ PageFrameIndex = MiRemoveAnyPage(0);
+
+ /* Write the software PTE */
+ ASSERT(PointerPte->u.Hard.Valid == 0);
+ *PointerPte = TempPte;
+ PointerPte->u.Soft.Protection |= Protection;
+
+ /* Initialize its PFN entry */
+ MiInitializePfn(PageFrameIndex, PointerPte, TRUE);
+
+ /* Release the PFN lock and return the page */
+ ASSERT_LIST_INVARIANT(&MmFreePageListHead);
+ ASSERT_LIST_INVARIANT(&MmZeroedPageListHead);
+ KeReleaseQueuedSpinLock(LockQueuePfnLock, OldIrql);
+ return PageFrameIndex;
+}
+
VOID
NTAPI
MiDecrementShareCount(IN PMMPFN Pfn1,
}
}
+VOID
+NTAPI
+MiInitializePfnForOtherProcess(IN PFN_NUMBER PageFrameIndex,
+ IN PMMPTE PointerPte,
+ IN PFN_NUMBER PteFrame)
+{
+ PMMPFN Pfn1;
+
+ /* Setup the PTE */
+ Pfn1 = MiGetPfnEntry(PageFrameIndex);
+ Pfn1->PteAddress = PointerPte;
+
+#if 0 // When using ARM3 PFN
+ /* Make this a software PTE */
+ MI_MAKE_SOFTWARE_PTE(&Pfn1->OriginalPte, MM_READWRITE);
+#endif
+
+ /* Setup the page */
+ ASSERT(Pfn1->u3.e2.ReferenceCount == 0);
+ Pfn1->u3.e2.ReferenceCount = 1;
+ Pfn1->u2.ShareCount = 1;
+ Pfn1->u3.e1.PageLocation = ActiveAndValid;
+ Pfn1->u3.e1.Modified = TRUE;
+ Pfn1->u4.InPageError = FALSE;
+
+ /* Did we get a PFN for the page table */
+ if (PteFrame)
+ {
+ /* Store it */
+ Pfn1->u4.PteFrame = PteFrame;
+
+ /* Increase its share count so we don't get rid of it */
+ Pfn1 = MiGetPfnEntry(PageFrameIndex);
+ Pfn1->u2.ShareCount++;
+ }
+}
+
/* EOF */