/* GLOBALS ****************************************************************/
-//
-//
// ReactOS to NT Physical Page Descriptor Entry Legacy Mapping Definitions
-//
-// REACTOS NT
-//
-#define RmapListHead AweReferenceCount
#define PHYSICAL_PAGE MMPFN
#define PPHYSICAL_PAGE PMMPFN
PFN_NUMBER MmResidentAvailablePages;
PFN_NUMBER MmResidentAvailableAtInit;
-SIZE_T MmTotalCommitLimit;
SIZE_T MmTotalCommittedPages;
SIZE_T MmSharedCommit;
SIZE_T MmDriverCommit;
SIZE_T MmProcessCommit;
SIZE_T MmPagedPoolCommit;
-SIZE_T MmPeakCommitment;
+SIZE_T MmPeakCommitment;
SIZE_T MmtotalCommitLimitMaximum;
-KEVENT ZeroPageThreadEvent;
-static BOOLEAN ZeroPageThreadShouldTerminate = FALSE;
static RTL_BITMAP MiUserPfnBitMap;
/* FUNCTIONS *************************************************************/
/* Initialize it and clear all the bits to begin with */
RtlInitializeBitMap(&MiUserPfnBitMap,
Bitmap,
- MmHighestPhysicalPage + 1);
+ (ULONG)MmHighestPhysicalPage + 1);
RtlClearAllBits(&MiUserPfnBitMap);
}
if (Position == 0xFFFFFFFF) return 0;
/* Return it */
+ ASSERT(Position != 0);
+ ASSERT_IS_ROS_PFN(MiGetPfnEntry(Position));
return Position;
}
KIRQL OldIrql;
/* Set the page as a user page */
+ ASSERT(Pfn != 0);
+ ASSERT_IS_ROS_PFN(MiGetPfnEntry(Pfn));
+ ASSERT(!RtlCheckBit(&MiUserPfnBitMap, (ULONG)Pfn));
OldIrql = KeAcquireQueuedSpinLock(LockQueuePfnLock);
- RtlSetBit(&MiUserPfnBitMap, Pfn);
+ RtlSetBit(&MiUserPfnBitMap, (ULONG)Pfn);
KeReleaseQueuedSpinLock(LockQueuePfnLock, OldIrql);
}
/* Find the next user page */
OldIrql = KeAcquireQueuedSpinLock(LockQueuePfnLock);
- Position = RtlFindSetBits(&MiUserPfnBitMap, 1, PreviousPfn + 1);
+ Position = RtlFindSetBits(&MiUserPfnBitMap, 1, (ULONG)PreviousPfn + 1);
KeReleaseQueuedSpinLock(LockQueuePfnLock, OldIrql);
if (Position == 0xFFFFFFFF) return 0;
/* Return it */
+ ASSERT(Position != 0);
+ ASSERT_IS_ROS_PFN(MiGetPfnEntry(Position));
return Position;
}
NTAPI
MmRemoveLRUUserPage(PFN_NUMBER Page)
{
+ KIRQL OldIrql;
+
/* Unset the page as a user page */
- RtlClearBit(&MiUserPfnBitMap, Page);
+ ASSERT(Page != 0);
+ ASSERT_IS_ROS_PFN(MiGetPfnEntry(Page));
+ ASSERT(RtlCheckBit(&MiUserPfnBitMap, (ULONG)Page));
+ OldIrql = KeAcquireQueuedSpinLock(LockQueuePfnLock);
+ RtlClearBit(&MiUserPfnBitMap, (ULONG)Page);
+ KeReleaseQueuedSpinLock(LockQueuePfnLock, OldIrql);
}
BOOLEAN
KIRQL OldIrql;
PPHYSICAL_PAGE Pfn1;
INT LookForZeroedPages;
- ASSERT (KeGetCurrentIrql() <= APC_LEVEL);
+ ASSERT(KeGetCurrentIrql() <= APC_LEVEL);
//
// Convert the low address into a PFN
//
// Convert, and normalize, the high address into a PFN
//
- HighPage = (PFN_NUMBER)(HighAddress.QuadPart >> PAGE_SHIFT);
+ HighPage = (PFN_NUMBER)(HighAddress.QuadPart >> PAGE_SHIFT);
if (HighPage > MmHighestPhysicalPage) HighPage = MmHighestPhysicalPage;
//
while (PagesFound < PageCount)
{
/* Grab a page */
+ MI_SET_USAGE(MI_USAGE_MDL);
+ MI_SET_PROCESS2("Kernel");
Page = MiRemoveAnyPage(0);
if (Page == 0)
{
//
ASSERT(Pfn1->u3.e2.ReferenceCount == 0);
- //
- // Allocate it and mark it
- //
+ /* Now setup the page and mark it */
+ Pfn1->u3.e2.ReferenceCount = 1;
+ Pfn1->u2.ShareCount = 1;
+ MI_SET_PFN_DELETED(Pfn1);
+ Pfn1->u4.PteFrame = 0x1FFEDCB;
Pfn1->u3.e1.StartOfAllocation = 1;
Pfn1->u3.e1.EndOfAllocation = 1;
- Pfn1->u3.e2.ReferenceCount = 1;
+ Pfn1->u4.VerifierAllocation = 0;
//
// Save it into the MDL
if ((Pfn1->u3.e1.PageLocation == ZeroedPageList) != LookForZeroedPages) continue;
/* Remove the page from the free or zero list */
+ ASSERT(Pfn1->u3.e1.ReadInProgress == 0);
+ MI_SET_USAGE(MI_USAGE_MDL);
+ MI_SET_PROCESS2("Kernel");
MiUnlinkFreeOrZeroedPage(Pfn1);
//
// Now setup the page and mark it
//
Pfn1->u3.e2.ReferenceCount = 1;
+ Pfn1->u2.ShareCount = 1;
+ MI_SET_PFN_DELETED(Pfn1);
+ Pfn1->u4.PteFrame = 0x1FFEDCB;
Pfn1->u3.e1.StartOfAllocation = 1;
Pfn1->u3.e1.EndOfAllocation = 1;
-
+ Pfn1->u4.VerifierAllocation = 0;
+
//
// Save this page into the MDL
//
//
// Terminate the MDL array if there's certain missing pages
//
- if (PagesFound != PageCount) *MdlPage = -1;
+ if (PagesFound != PageCount) *MdlPage = LIST_HEAD;
//
// Now go back and loop over all the MDL pages
// Check if we've reached the end
//
Page = *MdlPage++;
- if (Page == (PFN_NUMBER)-1) break;
+ if (Page == LIST_HEAD) break;
//
// Get the PFN entry for the page and check if we should zero it out
}
//
- // We're done, mark the pages as locked (should we lock them, though???)
+ // We're done, mark the pages as locked
//
Mdl->Process = NULL;
- Mdl->MdlFlags |= MDL_PAGES_LOCKED;
+ Mdl->MdlFlags |= MDL_PAGES_LOCKED;
return Mdl;
}
VOID
NTAPI
-MmDumpPfnDatabase(VOID)
-{
- ULONG i;
- PPHYSICAL_PAGE Pfn1;
- PCHAR State = "????", Type = "Unknown";
- KIRQL OldIrql;
- ULONG Totals[5] = {0}, FreePages = 0;
-
- KeRaiseIrql(HIGH_LEVEL, &OldIrql);
-
- //
- // Loop the PFN database
- //
- for (i = 0; i <= MmHighestPhysicalPage; i++)
- {
- Pfn1 = MiGetPfnEntry(i);
- if (!Pfn1) continue;
-
- //
- // Get the type
- //
- if (MiIsPfnInUse(Pfn1))
- {
- State = "Used";
- }
- else
- {
- State = "Free";
- Type = "Free";
- FreePages++;
- break;
- }
-
- //
- // Pretty-print the page
- //
- DbgPrint("0x%08p:\t%04s\t%20s\t(%02d) [%08p])\n",
- i << PAGE_SHIFT,
- State,
- Type,
- Pfn1->u3.e2.ReferenceCount,
- Pfn1->RmapListHead);
- }
-
- DbgPrint("Nonpaged Pool: %d pages\t[%d KB]\n", Totals[MC_NPPOOL], (Totals[MC_NPPOOL] << PAGE_SHIFT) / 1024);
- DbgPrint("Paged Pool: %d pages\t[%d KB]\n", Totals[MC_PPOOL], (Totals[MC_PPOOL] << PAGE_SHIFT) / 1024);
- DbgPrint("File System Cache: %d pages\t[%d KB]\n", Totals[MC_CACHE], (Totals[MC_CACHE] << PAGE_SHIFT) / 1024);
- DbgPrint("Process Working Set: %d pages\t[%d KB]\n", Totals[MC_USER], (Totals[MC_USER] << PAGE_SHIFT) / 1024);
- DbgPrint("System: %d pages\t[%d KB]\n", Totals[MC_SYSTEM], (Totals[MC_SYSTEM] << PAGE_SHIFT) / 1024);
- DbgPrint("Free: %d pages\t[%d KB]\n", FreePages, (FreePages << PAGE_SHIFT) / 1024);
-
- KeLowerIrql(OldIrql);
-}
-
-VOID
-NTAPI
-MmSetRmapListHeadPage(PFN_NUMBER Pfn, struct _MM_RMAP_ENTRY* ListHead)
+MmSetRmapListHeadPage(PFN_NUMBER Pfn, PMM_RMAP_ENTRY ListHead)
{
KIRQL oldIrql;
PMMPFN Pfn1;
oldIrql = KeAcquireQueuedSpinLock(LockQueuePfnLock);
Pfn1 = MiGetPfnEntry(Pfn);
+ ASSERT(Pfn1);
+ ASSERT_IS_ROS_PFN(Pfn1);
+
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;
+ MI_GET_ROS_DATA(Pfn1)->RmapListHead = ListHead;
}
else
{
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;
-
+ MI_GET_ROS_DATA(Pfn1)->RmapListHead = NULL;
+
/* ReactOS semantics will now release the page, which will make it free and enter a colored list */
}
KeReleaseQueuedSpinLock(LockQueuePfnLock, oldIrql);
}
-struct _MM_RMAP_ENTRY*
+PMM_RMAP_ENTRY
NTAPI
MmGetRmapListHeadPage(PFN_NUMBER Pfn)
{
KIRQL oldIrql;
- struct _MM_RMAP_ENTRY* ListHead;
+ PMM_RMAP_ENTRY ListHead;
PMMPFN Pfn1;
/* Lock PFN database */
/* 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;
+ ASSERT(Pfn1);
+ ASSERT_IS_ROS_PFN(Pfn1);
+
+ /* Get the list head */
+ ListHead = MI_GET_ROS_DATA(Pfn1)->RmapListHead;
/* Should not have an RMAP for a non-active page */
ASSERT(MiIsPfnInUse(Pfn1) == TRUE);
MmSetSavedSwapEntryPage(PFN_NUMBER Pfn, SWAPENTRY SwapEntry)
{
KIRQL oldIrql;
-
+ PPHYSICAL_PAGE Page;
+
+ Page = MiGetPfnEntry(Pfn);
+ ASSERT(Page);
+ ASSERT_IS_ROS_PFN(Page);
+
oldIrql = KeAcquireQueuedSpinLock(LockQueuePfnLock);
- MiGetPfnEntry(Pfn)->u1.WsIndex = SwapEntry;
+ MI_GET_ROS_DATA(Page)->SwapEntry = SwapEntry;
KeReleaseQueuedSpinLock(LockQueuePfnLock, oldIrql);
}
{
SWAPENTRY SwapEntry;
KIRQL oldIrql;
+ PPHYSICAL_PAGE Page;
+
+ Page = MiGetPfnEntry(Pfn);
+ ASSERT(Page);
+ ASSERT_IS_ROS_PFN(Page);
oldIrql = KeAcquireQueuedSpinLock(LockQueuePfnLock);
- SwapEntry = MiGetPfnEntry(Pfn)->u1.WsIndex;
+ SwapEntry = MI_GET_ROS_DATA(Page)->SwapEntry;
KeReleaseQueuedSpinLock(LockQueuePfnLock, oldIrql);
return(SwapEntry);
Page = MiGetPfnEntry(Pfn);
ASSERT(Page);
-
+ ASSERT_IS_ROS_PFN(Page);
+
Page->u3.e2.ReferenceCount++;
}
oldIrql = KeAcquireQueuedSpinLock(LockQueuePfnLock);
Page = MiGetPfnEntry(Pfn);
ASSERT(Page);
+ ASSERT_IS_ROS_PFN(Page);
RCount = Page->u3.e2.ReferenceCount;
return MiIsPfnInUse(MiGetPfnEntry(Pfn));
}
-VOID
-NTAPI
-MiSetConsumer(IN PFN_NUMBER Pfn,
- IN ULONG Type)
-{
- MiGetPfnEntry(Pfn)->u3.e1.PageLocation = ActiveAndValid;
-}
-
VOID
NTAPI
MmDereferencePage(PFN_NUMBER Pfn)
{
PPHYSICAL_PAGE Page;
-
DPRINT("MmDereferencePage(PhysicalAddress %x)\n", Pfn << PAGE_SHIFT);
Page = MiGetPfnEntry(Pfn);
ASSERT(Page);
-
+ ASSERT_IS_ROS_PFN(Page);
+
Page->u3.e2.ReferenceCount--;
if (Page->u3.e2.ReferenceCount == 0)
{
/* Mark the page temporarily as valid, we're going to make it free soon */
Page->u3.e1.PageLocation = ActiveAndValid;
+
+ /* It's not a ROS PFN anymore */
+ Page->u4.AweAllocation = FALSE;
+ ExFreePool(MI_GET_ROS_DATA(Page));
+ Page->RosMmData = 0;
/* Bring it back into the free list */
+ DPRINT("Legacy free: %lx\n", Pfn);
MiInsertPageInFreeList(Pfn);
}
}
PFN_NUMBER PfnOffset;
PMMPFN Pfn1;
- if (Type != MC_SYSTEM)
- {
- PfnOffset = MiRemoveZeroPage(0);
- }
- else
- {
- PfnOffset = MiRemoveAnyPage(0);
- }
+ PfnOffset = MiRemoveZeroPage(MI_GET_NEXT_COLOR());
if (!PfnOffset)
{
return 0;
}
+ DPRINT("Legacy allocate: %lx\n", PfnOffset);
Pfn1 = MiGetPfnEntry(PfnOffset);
Pfn1->u3.e2.ReferenceCount = 1;
Pfn1->u3.e1.PageLocation = ActiveAndValid;
+
+ /* This marks the PFN as a ReactOS PFN */
+ Pfn1->u4.AweAllocation = TRUE;
+
+ /* Allocate the extra ReactOS Data and zero it out */
+ Pfn1->RosMmData = (LONG)ExAllocatePoolWithTag(NonPagedPool, sizeof(MMROSPFN), 'RsPf');
+ ASSERT(MI_GET_ROS_DATA(Pfn1) != NULL);
+ ASSERT_IS_ROS_PFN(Pfn1);
+ MI_GET_ROS_DATA(Pfn1)->SwapEntry = 0;
+ MI_GET_ROS_DATA(Pfn1)->RmapListHead = NULL;
+
return PfnOffset;
}
-NTSTATUS
-NTAPI
-MmZeroPageThreadMain(PVOID Ignored)
-{
- NTSTATUS Status;
- KIRQL oldIrql;
- PMMPFN Pfn1;
- PFN_NUMBER PageIndex, FreePage;
- ULONG Count;
- PVOID ZeroAddress;
-
- /* Free initial kernel memory */
- //MiFreeInitMemory();
-
- /* Set our priority to 0 */
- KeGetCurrentThread()->BasePriority = 0;
- KeSetPriorityThread(KeGetCurrentThread(), 0);
-
- while(1)
- {
- Status = KeWaitForSingleObject(&ZeroPageThreadEvent,
- 0,
- KernelMode,
- FALSE,
- NULL);
-
- if (ZeroPageThreadShouldTerminate)
- {
- DPRINT1("ZeroPageThread: Terminating\n");
- return STATUS_SUCCESS;
- }
- Count = 0;
- oldIrql = KeAcquireQueuedSpinLock(LockQueuePfnLock);
- while (MmFreePageListHead.Total)
- {
- PageIndex = MmFreePageListHead.Flink;
- Pfn1 = MiGetPfnEntry(PageIndex);
- FreePage = MiRemoveAnyPage(0); // FIXME: Use real color
- if (FreePage != PageIndex)
- {
- KeBugCheckEx(PFN_LIST_CORRUPT,
- 0x8F,
- FreePage,
- PageIndex,
- 0);
- }
-
- Pfn1->u1.Flink = LIST_HEAD;
- KeReleaseQueuedSpinLock(LockQueuePfnLock, oldIrql);
-
- ZeroAddress = MiMapPagesToZeroInHyperSpace(Pfn1, 1);
- ASSERT(ZeroAddress);
- RtlZeroMemory(ZeroAddress, PAGE_SIZE);
- MiUnmapPagesInZeroSpace(ZeroAddress, 1);
-
- oldIrql = KeAcquireQueuedSpinLock(LockQueuePfnLock);
-
- MiInsertPageInList(&MmZeroedPageListHead, PageIndex);
- Count++;
- }
- DPRINT("Zeroed %d pages.\n", Count);
- KeResetEvent(&ZeroPageThreadEvent);
- KeReleaseQueuedSpinLock(LockQueuePfnLock, oldIrql);
- }
-
- return STATUS_SUCCESS;
-}
-
/* EOF */