2008-03-09 14:11:42 +00:00
|
|
|
/*
|
2005-01-26 13:58:37 +00:00
|
|
|
* COPYRIGHT: See COPYING in the top directory
|
2005-05-09 01:38:29 +00:00
|
|
|
* PROJECT: ReactOS kernel
|
2005-01-26 13:58:37 +00:00
|
|
|
* FILE: ntoskrnl/mm/rmap.c
|
|
|
|
* PURPOSE: Kernel memory managment functions
|
2005-05-09 01:38:29 +00:00
|
|
|
*
|
2005-01-26 13:58:37 +00:00
|
|
|
* PROGRAMMERS: David Welch (welch@cwcom.net)
|
2001-12-31 01:53:46 +00:00
|
|
|
*/
|
|
|
|
|
|
|
|
/* INCLUDES *****************************************************************/
|
|
|
|
|
2004-08-15 16:39:12 +00:00
|
|
|
#include <ntoskrnl.h>
|
2001-12-31 01:53:46 +00:00
|
|
|
#define NDEBUG
|
2008-08-30 16:31:06 +00:00
|
|
|
#include <debug.h>
|
2001-12-31 01:53:46 +00:00
|
|
|
|
2005-11-28 23:25:31 +00:00
|
|
|
#if defined (ALLOC_PRAGMA)
|
|
|
|
#pragma alloc_text(INIT, MmInitializeRmapList)
|
|
|
|
#endif
|
|
|
|
|
2001-12-31 01:53:46 +00:00
|
|
|
/* TYPES ********************************************************************/
|
|
|
|
|
|
|
|
typedef struct _MM_RMAP_ENTRY
|
|
|
|
{
|
2004-04-10 22:36:07 +00:00
|
|
|
struct _MM_RMAP_ENTRY* Next;
|
|
|
|
PEPROCESS Process;
|
|
|
|
PVOID Address;
|
2009-06-17 12:44:05 +00:00
|
|
|
#if DBG
|
2005-08-16 20:36:03 +00:00
|
|
|
PVOID Caller;
|
|
|
|
#endif
|
2004-04-10 22:36:07 +00:00
|
|
|
}
|
|
|
|
MM_RMAP_ENTRY, *PMM_RMAP_ENTRY;
|
2001-12-31 01:53:46 +00:00
|
|
|
|
|
|
|
/* GLOBALS ******************************************************************/
|
|
|
|
|
2002-05-14 21:19:21 +00:00
|
|
|
static FAST_MUTEX RmapListLock;
|
2003-01-11 15:28:18 +00:00
|
|
|
static NPAGED_LOOKASIDE_LIST RmapLookasideList;
|
2001-12-31 01:53:46 +00:00
|
|
|
|
|
|
|
/* FUNCTIONS ****************************************************************/
|
|
|
|
|
2005-09-14 01:05:50 +00:00
|
|
|
VOID
|
|
|
|
INIT_FUNCTION
|
|
|
|
NTAPI
|
2001-12-31 01:53:46 +00:00
|
|
|
MmInitializeRmapList(VOID)
|
|
|
|
{
|
2004-04-10 22:36:07 +00:00
|
|
|
ExInitializeFastMutex(&RmapListLock);
|
|
|
|
ExInitializeNPagedLookasideList (&RmapLookasideList,
|
|
|
|
NULL,
|
|
|
|
NULL,
|
|
|
|
0,
|
|
|
|
sizeof(MM_RMAP_ENTRY),
|
|
|
|
TAG_RMAP,
|
|
|
|
50);
|
2001-12-31 01:53:46 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
NTSTATUS
|
2005-09-14 01:05:50 +00:00
|
|
|
NTAPI
|
2004-08-01 07:24:59 +00:00
|
|
|
MmWritePagePhysicalAddress(PFN_TYPE Page)
|
2001-12-31 01:53:46 +00:00
|
|
|
{
|
2004-04-10 22:36:07 +00:00
|
|
|
PMM_RMAP_ENTRY entry;
|
|
|
|
PMEMORY_AREA MemoryArea;
|
2009-04-27 10:12:57 +00:00
|
|
|
PMMSUPPORT AddressSpace;
|
2004-04-10 22:36:07 +00:00
|
|
|
ULONG Type;
|
|
|
|
PVOID Address;
|
2006-05-18 20:32:17 +00:00
|
|
|
PEPROCESS Process;
|
2004-04-10 22:36:07 +00:00
|
|
|
PMM_PAGEOP PageOp;
|
|
|
|
ULONG Offset;
|
|
|
|
NTSTATUS Status = STATUS_SUCCESS;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Check that the address still has a valid rmap; then reference the
|
|
|
|
* process so it isn't freed while we are working.
|
|
|
|
*/
|
|
|
|
ExAcquireFastMutex(&RmapListLock);
|
2004-08-01 07:24:59 +00:00
|
|
|
entry = MmGetRmapListHeadPage(Page);
|
2004-04-10 22:36:07 +00:00
|
|
|
if (entry == NULL)
|
|
|
|
{
|
2002-05-14 21:19:21 +00:00
|
|
|
ExReleaseFastMutex(&RmapListLock);
|
2001-12-31 01:53:46 +00:00
|
|
|
return(STATUS_UNSUCCESSFUL);
|
2004-04-10 22:36:07 +00:00
|
|
|
}
|
2006-05-18 20:32:17 +00:00
|
|
|
Process = entry->Process;
|
2004-04-10 22:36:07 +00:00
|
|
|
Address = entry->Address;
|
2005-01-02 17:55:06 +00:00
|
|
|
if ((((ULONG_PTR)Address) & 0xFFF) != 0)
|
2004-04-10 22:36:07 +00:00
|
|
|
{
|
2008-12-07 18:05:28 +00:00
|
|
|
KeBugCheck(MEMORY_MANAGEMENT);
|
2004-04-10 22:36:07 +00:00
|
|
|
}
|
2005-07-06 08:20:26 +00:00
|
|
|
if (Address < MmSystemRangeStart)
|
2004-04-10 22:36:07 +00:00
|
|
|
{
|
2003-05-17 13:46:05 +00:00
|
|
|
Status = ObReferenceObjectByPointer(Process, PROCESS_ALL_ACCESS, NULL, KernelMode);
|
|
|
|
ExReleaseFastMutex(&RmapListLock);
|
|
|
|
if (!NT_SUCCESS(Status))
|
2004-04-10 22:36:07 +00:00
|
|
|
{
|
|
|
|
return Status;
|
|
|
|
}
|
2009-04-27 10:12:57 +00:00
|
|
|
AddressSpace = &Process->Vm;
|
2004-04-10 22:36:07 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2003-05-19 15:58:09 +00:00
|
|
|
ExReleaseFastMutex(&RmapListLock);
|
2003-05-17 13:46:05 +00:00
|
|
|
AddressSpace = MmGetKernelAddressSpace();
|
2004-04-10 22:36:07 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Lock the address space; then check that the address we are using
|
|
|
|
* still corresponds to a valid memory area (the page might have been
|
2005-05-09 01:38:29 +00:00
|
|
|
* freed or paged out after we read the rmap entry.)
|
2004-04-10 22:36:07 +00:00
|
|
|
*/
|
|
|
|
MmLockAddressSpace(AddressSpace);
|
2005-01-02 19:14:52 +00:00
|
|
|
MemoryArea = MmLocateMemoryAreaByAddress(AddressSpace, Address);
|
2004-04-10 22:36:07 +00:00
|
|
|
if (MemoryArea == NULL || MemoryArea->DeleteInProgress)
|
|
|
|
{
|
2003-05-17 13:46:05 +00:00
|
|
|
MmUnlockAddressSpace(AddressSpace);
|
2005-07-06 08:20:26 +00:00
|
|
|
if (Address < MmSystemRangeStart)
|
2004-04-10 22:36:07 +00:00
|
|
|
{
|
|
|
|
ObDereferenceObject(Process);
|
|
|
|
}
|
2002-08-17 14:14:20 +00:00
|
|
|
return(STATUS_UNSUCCESSFUL);
|
2004-04-10 22:36:07 +00:00
|
|
|
}
|
2002-08-17 14:14:20 +00:00
|
|
|
|
2004-04-10 22:36:07 +00:00
|
|
|
Type = MemoryArea->Type;
|
|
|
|
if (Type == MEMORY_AREA_SECTION_VIEW)
|
|
|
|
{
|
2007-10-19 23:21:45 +00:00
|
|
|
Offset = (ULONG_PTR)Address - (ULONG_PTR)MemoryArea->StartingAddress
|
2005-08-16 20:36:03 +00:00
|
|
|
+ MemoryArea->Data.SectionData.ViewOffset;
|
2001-12-31 01:53:46 +00:00
|
|
|
/*
|
|
|
|
* Get or create a pageop
|
|
|
|
*/
|
2005-01-26 00:03:05 +00:00
|
|
|
PageOp = MmGetPageOp(MemoryArea, NULL, 0,
|
2004-04-10 22:36:07 +00:00
|
|
|
MemoryArea->Data.SectionData.Segment,
|
|
|
|
Offset, MM_PAGEOP_PAGEOUT, TRUE);
|
2001-12-31 01:53:46 +00:00
|
|
|
|
2004-03-05 11:31:59 +00:00
|
|
|
if (PageOp == NULL)
|
2004-04-10 22:36:07 +00:00
|
|
|
{
|
|
|
|
MmUnlockAddressSpace(AddressSpace);
|
2005-07-06 08:20:26 +00:00
|
|
|
if (Address < MmSystemRangeStart)
|
2004-04-10 22:36:07 +00:00
|
|
|
{
|
|
|
|
ObDereferenceObject(Process);
|
|
|
|
}
|
|
|
|
return(STATUS_UNSUCCESSFUL);
|
|
|
|
}
|
|
|
|
|
2002-08-14 20:58:39 +00:00
|
|
|
/*
|
|
|
|
* Release locks now we have a page op.
|
|
|
|
*/
|
2004-04-10 22:36:07 +00:00
|
|
|
MmUnlockAddressSpace(AddressSpace);
|
2002-08-14 20:58:39 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Do the actual page out work.
|
|
|
|
*/
|
2004-04-10 22:36:07 +00:00
|
|
|
Status = MmWritePageSectionView(AddressSpace, MemoryArea,
|
|
|
|
Address, PageOp);
|
|
|
|
}
|
2005-05-17 18:04:23 +00:00
|
|
|
else if ((Type == MEMORY_AREA_VIRTUAL_MEMORY) || (Type == MEMORY_AREA_PEB_OR_TEB))
|
2004-04-10 22:36:07 +00:00
|
|
|
{
|
2005-07-06 08:20:26 +00:00
|
|
|
PageOp = MmGetPageOp(MemoryArea, Address < MmSystemRangeStart ? Process->UniqueProcessId : NULL,
|
2004-04-10 22:36:07 +00:00
|
|
|
Address, NULL, 0, MM_PAGEOP_PAGEOUT, TRUE);
|
|
|
|
|
2004-03-05 11:31:59 +00:00
|
|
|
if (PageOp == NULL)
|
2004-04-10 22:36:07 +00:00
|
|
|
{
|
|
|
|
MmUnlockAddressSpace(AddressSpace);
|
2005-07-06 08:20:26 +00:00
|
|
|
if (Address < MmSystemRangeStart)
|
2004-04-10 22:36:07 +00:00
|
|
|
{
|
|
|
|
ObDereferenceObject(Process);
|
|
|
|
}
|
|
|
|
return(STATUS_UNSUCCESSFUL);
|
|
|
|
}
|
2002-08-14 20:58:39 +00:00
|
|
|
|
2001-12-31 01:53:46 +00:00
|
|
|
/*
|
|
|
|
* Release locks now we have a page op.
|
|
|
|
*/
|
2003-05-17 13:46:05 +00:00
|
|
|
MmUnlockAddressSpace(AddressSpace);
|
2002-08-14 20:58:39 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Do the actual page out work.
|
|
|
|
*/
|
2004-04-10 22:36:07 +00:00
|
|
|
Status = MmWritePageVirtualMemory(AddressSpace, MemoryArea,
|
|
|
|
Address, PageOp);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2008-12-07 18:05:28 +00:00
|
|
|
KeBugCheck(MEMORY_MANAGEMENT);
|
2004-04-10 22:36:07 +00:00
|
|
|
}
|
2005-07-06 08:20:26 +00:00
|
|
|
if (Address < MmSystemRangeStart)
|
2004-04-10 22:36:07 +00:00
|
|
|
{
|
2003-05-17 13:46:05 +00:00
|
|
|
ObDereferenceObject(Process);
|
2004-04-10 22:36:07 +00:00
|
|
|
}
|
|
|
|
return(Status);
|
2002-08-14 20:58:39 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
NTSTATUS
|
2005-09-14 01:05:50 +00:00
|
|
|
NTAPI
|
2004-08-01 07:24:59 +00:00
|
|
|
MmPageOutPhysicalAddress(PFN_TYPE Page)
|
2002-08-14 20:58:39 +00:00
|
|
|
{
|
2004-04-10 22:36:07 +00:00
|
|
|
PMM_RMAP_ENTRY entry;
|
|
|
|
PMEMORY_AREA MemoryArea;
|
2009-04-27 10:12:57 +00:00
|
|
|
PMMSUPPORT AddressSpace;
|
2004-04-10 22:36:07 +00:00
|
|
|
ULONG Type;
|
|
|
|
PVOID Address;
|
2006-05-18 20:32:17 +00:00
|
|
|
PEPROCESS Process;
|
2004-04-10 22:36:07 +00:00
|
|
|
PMM_PAGEOP PageOp;
|
|
|
|
ULONG Offset;
|
|
|
|
NTSTATUS Status = STATUS_SUCCESS;
|
|
|
|
|
|
|
|
ExAcquireFastMutex(&RmapListLock);
|
2004-08-01 07:24:59 +00:00
|
|
|
entry = MmGetRmapListHeadPage(Page);
|
2010-02-11 18:41:45 +00:00
|
|
|
if (entry == NULL)
|
2004-04-10 22:36:07 +00:00
|
|
|
{
|
2002-05-14 21:19:21 +00:00
|
|
|
ExReleaseFastMutex(&RmapListLock);
|
2002-08-14 20:58:39 +00:00
|
|
|
return(STATUS_UNSUCCESSFUL);
|
2004-04-10 22:36:07 +00:00
|
|
|
}
|
2006-05-18 20:32:17 +00:00
|
|
|
Process = entry->Process;
|
2004-04-10 22:36:07 +00:00
|
|
|
Address = entry->Address;
|
2005-01-02 17:55:06 +00:00
|
|
|
if ((((ULONG_PTR)Address) & 0xFFF) != 0)
|
2004-04-10 22:36:07 +00:00
|
|
|
{
|
2008-12-07 18:05:28 +00:00
|
|
|
KeBugCheck(MEMORY_MANAGEMENT);
|
2004-04-10 22:36:07 +00:00
|
|
|
}
|
2002-08-14 20:58:39 +00:00
|
|
|
|
2005-07-06 08:20:26 +00:00
|
|
|
if (Address < MmSystemRangeStart)
|
2004-04-10 22:36:07 +00:00
|
|
|
{
|
2003-05-17 13:46:05 +00:00
|
|
|
Status = ObReferenceObjectByPointer(Process, PROCESS_ALL_ACCESS, NULL, KernelMode);
|
|
|
|
ExReleaseFastMutex(&RmapListLock);
|
|
|
|
if (!NT_SUCCESS(Status))
|
2004-04-10 22:36:07 +00:00
|
|
|
{
|
|
|
|
return Status;
|
|
|
|
}
|
2009-04-27 10:12:57 +00:00
|
|
|
AddressSpace = &Process->Vm;
|
2004-04-10 22:36:07 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2003-05-19 15:58:09 +00:00
|
|
|
ExReleaseFastMutex(&RmapListLock);
|
2003-05-17 13:46:05 +00:00
|
|
|
AddressSpace = MmGetKernelAddressSpace();
|
2004-04-10 22:36:07 +00:00
|
|
|
}
|
2003-05-17 13:46:05 +00:00
|
|
|
|
2004-04-10 22:36:07 +00:00
|
|
|
MmLockAddressSpace(AddressSpace);
|
2005-01-02 19:14:52 +00:00
|
|
|
MemoryArea = MmLocateMemoryAreaByAddress(AddressSpace, Address);
|
2004-04-10 22:36:07 +00:00
|
|
|
if (MemoryArea == NULL || MemoryArea->DeleteInProgress)
|
|
|
|
{
|
2003-07-15 19:31:27 +00:00
|
|
|
MmUnlockAddressSpace(AddressSpace);
|
2005-07-06 08:20:26 +00:00
|
|
|
if (Address < MmSystemRangeStart)
|
2004-04-10 22:36:07 +00:00
|
|
|
{
|
|
|
|
ObDereferenceObject(Process);
|
|
|
|
}
|
2003-07-15 19:31:27 +00:00
|
|
|
return(STATUS_UNSUCCESSFUL);
|
2004-04-10 22:36:07 +00:00
|
|
|
}
|
|
|
|
Type = MemoryArea->Type;
|
|
|
|
if (Type == MEMORY_AREA_SECTION_VIEW)
|
|
|
|
{
|
2007-10-19 23:21:45 +00:00
|
|
|
Offset = (ULONG_PTR)Address - (ULONG_PTR)MemoryArea->StartingAddress
|
2008-12-25 12:27:47 +00:00
|
|
|
+ MemoryArea->Data.SectionData.ViewOffset;
|
2002-08-14 20:58:39 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Get or create a pageop
|
|
|
|
*/
|
2005-01-26 00:03:05 +00:00
|
|
|
PageOp = MmGetPageOp(MemoryArea, NULL, 0,
|
2004-04-10 22:36:07 +00:00
|
|
|
MemoryArea->Data.SectionData.Segment,
|
|
|
|
Offset, MM_PAGEOP_PAGEOUT, TRUE);
|
2002-08-14 20:58:39 +00:00
|
|
|
if (PageOp == NULL)
|
2004-04-10 22:36:07 +00:00
|
|
|
{
|
|
|
|
MmUnlockAddressSpace(AddressSpace);
|
2005-07-06 08:20:26 +00:00
|
|
|
if (Address < MmSystemRangeStart)
|
2004-04-10 22:36:07 +00:00
|
|
|
{
|
|
|
|
ObDereferenceObject(Process);
|
|
|
|
}
|
|
|
|
return(STATUS_UNSUCCESSFUL);
|
|
|
|
}
|
|
|
|
|
2002-08-14 20:58:39 +00:00
|
|
|
/*
|
|
|
|
* Release locks now we have a page op.
|
|
|
|
*/
|
2003-05-17 13:46:05 +00:00
|
|
|
MmUnlockAddressSpace(AddressSpace);
|
2001-12-31 01:53:46 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Do the actual page out work.
|
|
|
|
*/
|
2004-04-10 22:36:07 +00:00
|
|
|
Status = MmPageOutSectionView(AddressSpace, MemoryArea,
|
|
|
|
Address, PageOp);
|
|
|
|
}
|
2005-05-17 18:04:23 +00:00
|
|
|
else if ((Type == MEMORY_AREA_VIRTUAL_MEMORY) || (Type == MEMORY_AREA_PEB_OR_TEB))
|
2004-04-10 22:36:07 +00:00
|
|
|
{
|
2005-07-06 08:20:26 +00:00
|
|
|
PageOp = MmGetPageOp(MemoryArea, Address < MmSystemRangeStart ? Process->UniqueProcessId : NULL,
|
2004-04-10 22:36:07 +00:00
|
|
|
Address, NULL, 0, MM_PAGEOP_PAGEOUT, TRUE);
|
2004-03-05 11:31:59 +00:00
|
|
|
if (PageOp == NULL)
|
2004-04-10 22:36:07 +00:00
|
|
|
{
|
|
|
|
MmUnlockAddressSpace(AddressSpace);
|
2005-07-06 08:20:26 +00:00
|
|
|
if (Address < MmSystemRangeStart)
|
2004-04-10 22:36:07 +00:00
|
|
|
{
|
|
|
|
ObDereferenceObject(Process);
|
|
|
|
}
|
|
|
|
return(STATUS_UNSUCCESSFUL);
|
|
|
|
}
|
2001-12-31 01:53:46 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Release locks now we have a page op.
|
|
|
|
*/
|
2003-05-17 13:46:05 +00:00
|
|
|
MmUnlockAddressSpace(AddressSpace);
|
2001-12-31 01:53:46 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Do the actual page out work.
|
|
|
|
*/
|
2004-04-10 22:36:07 +00:00
|
|
|
Status = MmPageOutVirtualMemory(AddressSpace, MemoryArea,
|
|
|
|
Address, PageOp);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2008-12-07 18:05:28 +00:00
|
|
|
KeBugCheck(MEMORY_MANAGEMENT);
|
2004-04-10 22:36:07 +00:00
|
|
|
}
|
2005-07-06 08:20:26 +00:00
|
|
|
if (Address < MmSystemRangeStart)
|
2004-04-10 22:36:07 +00:00
|
|
|
{
|
2003-05-17 13:46:05 +00:00
|
|
|
ObDereferenceObject(Process);
|
2004-04-10 22:36:07 +00:00
|
|
|
}
|
|
|
|
return(Status);
|
2001-12-31 01:53:46 +00:00
|
|
|
}
|
|
|
|
|
2002-08-14 20:58:39 +00:00
|
|
|
VOID
|
2005-09-14 01:05:50 +00:00
|
|
|
NTAPI
|
2004-08-01 07:24:59 +00:00
|
|
|
MmSetCleanAllRmaps(PFN_TYPE Page)
|
2002-08-14 20:58:39 +00:00
|
|
|
{
|
2004-04-10 22:36:07 +00:00
|
|
|
PMM_RMAP_ENTRY current_entry;
|
2002-08-14 20:58:39 +00:00
|
|
|
|
2004-04-10 22:36:07 +00:00
|
|
|
ExAcquireFastMutex(&RmapListLock);
|
2004-08-01 07:24:59 +00:00
|
|
|
current_entry = MmGetRmapListHeadPage(Page);
|
2004-04-10 22:36:07 +00:00
|
|
|
if (current_entry == NULL)
|
|
|
|
{
|
2002-08-14 20:58:39 +00:00
|
|
|
DPRINT1("MmIsDirtyRmap: No rmaps.\n");
|
2008-12-07 18:05:28 +00:00
|
|
|
KeBugCheck(MEMORY_MANAGEMENT);
|
2004-04-10 22:36:07 +00:00
|
|
|
}
|
|
|
|
while (current_entry != NULL)
|
|
|
|
{
|
2006-05-18 20:32:17 +00:00
|
|
|
MmSetCleanPage(current_entry->Process, current_entry->Address);
|
2002-08-14 20:58:39 +00:00
|
|
|
current_entry = current_entry->Next;
|
2004-04-10 22:36:07 +00:00
|
|
|
}
|
|
|
|
ExReleaseFastMutex(&RmapListLock);
|
2002-08-14 20:58:39 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
VOID
|
2005-09-14 01:05:50 +00:00
|
|
|
NTAPI
|
2004-08-01 07:24:59 +00:00
|
|
|
MmSetDirtyAllRmaps(PFN_TYPE Page)
|
2002-08-14 20:58:39 +00:00
|
|
|
{
|
2004-04-10 22:36:07 +00:00
|
|
|
PMM_RMAP_ENTRY current_entry;
|
2002-08-14 20:58:39 +00:00
|
|
|
|
2004-04-10 22:36:07 +00:00
|
|
|
ExAcquireFastMutex(&RmapListLock);
|
2004-08-01 07:24:59 +00:00
|
|
|
current_entry = MmGetRmapListHeadPage(Page);
|
2004-04-10 22:36:07 +00:00
|
|
|
if (current_entry == NULL)
|
|
|
|
{
|
2002-08-14 20:58:39 +00:00
|
|
|
DPRINT1("MmIsDirtyRmap: No rmaps.\n");
|
2008-12-07 18:05:28 +00:00
|
|
|
KeBugCheck(MEMORY_MANAGEMENT);
|
2004-04-10 22:36:07 +00:00
|
|
|
}
|
|
|
|
while (current_entry != NULL)
|
|
|
|
{
|
2006-05-18 20:32:17 +00:00
|
|
|
MmSetDirtyPage(current_entry->Process, current_entry->Address);
|
2002-08-14 20:58:39 +00:00
|
|
|
current_entry = current_entry->Next;
|
2004-04-10 22:36:07 +00:00
|
|
|
}
|
|
|
|
ExReleaseFastMutex(&RmapListLock);
|
2002-08-14 20:58:39 +00:00
|
|
|
}
|
|
|
|
|
2006-01-08 06:23:17 +00:00
|
|
|
BOOLEAN
|
2005-09-14 01:05:50 +00:00
|
|
|
NTAPI
|
2004-08-01 07:24:59 +00:00
|
|
|
MmIsDirtyPageRmap(PFN_TYPE Page)
|
2002-08-14 20:58:39 +00:00
|
|
|
{
|
2004-04-10 22:36:07 +00:00
|
|
|
PMM_RMAP_ENTRY current_entry;
|
2002-08-14 20:58:39 +00:00
|
|
|
|
2004-04-10 22:36:07 +00:00
|
|
|
ExAcquireFastMutex(&RmapListLock);
|
2004-08-01 07:24:59 +00:00
|
|
|
current_entry = MmGetRmapListHeadPage(Page);
|
2004-04-10 22:36:07 +00:00
|
|
|
if (current_entry == NULL)
|
|
|
|
{
|
2002-08-14 20:58:39 +00:00
|
|
|
ExReleaseFastMutex(&RmapListLock);
|
|
|
|
return(FALSE);
|
2004-04-10 22:36:07 +00:00
|
|
|
}
|
|
|
|
while (current_entry != NULL)
|
|
|
|
{
|
2006-05-18 20:32:17 +00:00
|
|
|
if (MmIsDirtyPage(current_entry->Process, current_entry->Address))
|
2004-04-10 22:36:07 +00:00
|
|
|
{
|
|
|
|
ExReleaseFastMutex(&RmapListLock);
|
|
|
|
return(TRUE);
|
|
|
|
}
|
2002-08-14 20:58:39 +00:00
|
|
|
current_entry = current_entry->Next;
|
2004-04-10 22:36:07 +00:00
|
|
|
}
|
|
|
|
ExReleaseFastMutex(&RmapListLock);
|
|
|
|
return(FALSE);
|
2002-08-14 20:58:39 +00:00
|
|
|
}
|
|
|
|
|
2002-05-13 18:10:41 +00:00
|
|
|
VOID
|
2005-09-14 01:05:50 +00:00
|
|
|
NTAPI
|
2006-05-18 20:32:17 +00:00
|
|
|
MmInsertRmap(PFN_TYPE Page, PEPROCESS Process,
|
2004-04-10 22:36:07 +00:00
|
|
|
PVOID Address)
|
2002-05-13 18:10:41 +00:00
|
|
|
{
|
2004-04-10 22:36:07 +00:00
|
|
|
PMM_RMAP_ENTRY current_entry;
|
|
|
|
PMM_RMAP_ENTRY new_entry;
|
2004-10-02 10:16:10 +00:00
|
|
|
ULONG PrevSize;
|
2002-05-13 18:10:41 +00:00
|
|
|
|
2004-04-10 22:36:07 +00:00
|
|
|
Address = (PVOID)PAGE_ROUND_DOWN(Address);
|
2002-05-13 18:10:41 +00:00
|
|
|
|
2004-04-10 22:36:07 +00:00
|
|
|
new_entry = ExAllocateFromNPagedLookasideList(&RmapLookasideList);
|
|
|
|
if (new_entry == NULL)
|
|
|
|
{
|
2008-12-07 18:05:28 +00:00
|
|
|
KeBugCheck(MEMORY_MANAGEMENT);
|
2004-04-10 22:36:07 +00:00
|
|
|
}
|
|
|
|
new_entry->Address = Address;
|
2006-05-10 17:47:44 +00:00
|
|
|
new_entry->Process = (PEPROCESS)Process;
|
2009-06-17 12:44:05 +00:00
|
|
|
#if DBG
|
2007-03-26 20:28:13 +00:00
|
|
|
#ifdef __GNUC__
|
2005-08-16 20:36:03 +00:00
|
|
|
new_entry->Caller = __builtin_return_address(0);
|
2007-03-02 18:25:23 +00:00
|
|
|
#else
|
|
|
|
new_entry->Caller = _ReturnAddress();
|
|
|
|
#endif
|
2007-10-19 23:21:45 +00:00
|
|
|
#endif
|
2002-05-13 18:10:41 +00:00
|
|
|
|
2004-08-01 07:24:59 +00:00
|
|
|
if (MmGetPfnForProcess(Process, Address) != Page)
|
2004-04-10 22:36:07 +00:00
|
|
|
{
|
2002-05-14 21:19:21 +00:00
|
|
|
DPRINT1("Insert rmap (%d, 0x%.8X) 0x%.8X which doesn't match physical "
|
2004-04-10 22:36:07 +00:00
|
|
|
"address 0x%.8X\n", Process->UniqueProcessId, Address,
|
2004-08-01 07:24:59 +00:00
|
|
|
MmGetPfnForProcess(Process, Address) << PAGE_SHIFT,
|
|
|
|
Page << PAGE_SHIFT);
|
2008-12-07 18:05:28 +00:00
|
|
|
KeBugCheck(MEMORY_MANAGEMENT);
|
2004-04-10 22:36:07 +00:00
|
|
|
}
|
2001-12-31 01:53:46 +00:00
|
|
|
|
2004-04-10 22:36:07 +00:00
|
|
|
ExAcquireFastMutex(&RmapListLock);
|
2004-08-01 07:24:59 +00:00
|
|
|
current_entry = MmGetRmapListHeadPage(Page);
|
2004-04-10 22:36:07 +00:00
|
|
|
new_entry->Next = current_entry;
|
2009-06-17 12:44:05 +00:00
|
|
|
#if DBG
|
2005-08-16 20:36:03 +00:00
|
|
|
while (current_entry)
|
|
|
|
{
|
|
|
|
if (current_entry->Address == new_entry->Address && current_entry->Process == new_entry->Process)
|
|
|
|
{
|
2007-10-19 23:21:45 +00:00
|
|
|
DbgPrint("MmInsertRmap tries to add a second rmap entry for address %p\n current caller ",
|
2005-08-16 20:36:03 +00:00
|
|
|
current_entry->Address);
|
2007-03-03 04:39:25 +00:00
|
|
|
DbgPrint("%p", new_entry->Caller);
|
2005-08-16 20:36:03 +00:00
|
|
|
DbgPrint("\n previous caller ");
|
2007-03-03 04:39:25 +00:00
|
|
|
DbgPrint("%p", current_entry->Caller);
|
2005-08-16 20:36:03 +00:00
|
|
|
DbgPrint("\n");
|
2008-12-07 18:05:28 +00:00
|
|
|
KeBugCheck(MEMORY_MANAGEMENT);
|
2005-08-16 20:36:03 +00:00
|
|
|
}
|
|
|
|
current_entry = current_entry->Next;
|
|
|
|
}
|
|
|
|
#endif
|
2004-08-01 07:24:59 +00:00
|
|
|
MmSetRmapListHeadPage(Page, new_entry);
|
2004-04-10 22:36:07 +00:00
|
|
|
ExReleaseFastMutex(&RmapListLock);
|
2004-10-02 10:16:10 +00:00
|
|
|
if (Process == NULL)
|
|
|
|
{
|
2006-05-18 20:32:17 +00:00
|
|
|
Process = PsInitialSystemProcess;
|
2004-10-02 10:16:10 +00:00
|
|
|
}
|
|
|
|
if (Process)
|
|
|
|
{
|
2004-12-24 17:07:00 +00:00
|
|
|
PrevSize = InterlockedExchangeAddUL(&Process->Vm.WorkingSetSize, PAGE_SIZE);
|
2004-10-02 10:16:10 +00:00
|
|
|
if (PrevSize >= Process->Vm.PeakWorkingSetSize)
|
|
|
|
{
|
|
|
|
Process->Vm.PeakWorkingSetSize = PrevSize + PAGE_SIZE;
|
|
|
|
}
|
|
|
|
}
|
2001-12-31 01:53:46 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
VOID
|
2005-09-14 01:05:50 +00:00
|
|
|
NTAPI
|
2004-08-01 07:24:59 +00:00
|
|
|
MmDeleteAllRmaps(PFN_TYPE Page, PVOID Context,
|
2006-05-18 20:32:17 +00:00
|
|
|
VOID (*DeleteMapping)(PVOID Context, PEPROCESS Process,
|
2004-04-10 22:36:07 +00:00
|
|
|
PVOID Address))
|
2001-12-31 01:53:46 +00:00
|
|
|
{
|
2004-04-10 22:36:07 +00:00
|
|
|
PMM_RMAP_ENTRY current_entry;
|
|
|
|
PMM_RMAP_ENTRY previous_entry;
|
2004-10-02 10:16:10 +00:00
|
|
|
PEPROCESS Process;
|
2001-12-31 01:53:46 +00:00
|
|
|
|
2004-04-10 22:36:07 +00:00
|
|
|
ExAcquireFastMutex(&RmapListLock);
|
2004-08-01 07:24:59 +00:00
|
|
|
current_entry = MmGetRmapListHeadPage(Page);
|
2004-04-10 22:36:07 +00:00
|
|
|
if (current_entry == NULL)
|
|
|
|
{
|
2002-01-08 00:49:02 +00:00
|
|
|
DPRINT1("MmDeleteAllRmaps: No rmaps.\n");
|
2008-12-07 18:05:28 +00:00
|
|
|
KeBugCheck(MEMORY_MANAGEMENT);
|
2004-04-10 22:36:07 +00:00
|
|
|
}
|
2004-08-01 07:24:59 +00:00
|
|
|
MmSetRmapListHeadPage(Page, NULL);
|
2005-12-06 18:39:17 +00:00
|
|
|
ExReleaseFastMutex(&RmapListLock);
|
2004-04-10 22:36:07 +00:00
|
|
|
while (current_entry != NULL)
|
|
|
|
{
|
2001-12-31 01:53:46 +00:00
|
|
|
previous_entry = current_entry;
|
|
|
|
current_entry = current_entry->Next;
|
|
|
|
if (DeleteMapping)
|
2004-04-10 22:36:07 +00:00
|
|
|
{
|
2006-05-18 20:32:17 +00:00
|
|
|
DeleteMapping(Context, previous_entry->Process,
|
2004-04-10 22:36:07 +00:00
|
|
|
previous_entry->Address);
|
|
|
|
}
|
2004-10-02 10:16:10 +00:00
|
|
|
Process = previous_entry->Process;
|
2003-01-11 15:28:18 +00:00
|
|
|
ExFreeToNPagedLookasideList(&RmapLookasideList, previous_entry);
|
2004-10-02 10:16:10 +00:00
|
|
|
if (Process == NULL)
|
|
|
|
{
|
|
|
|
Process = PsInitialSystemProcess;
|
|
|
|
}
|
|
|
|
if (Process)
|
|
|
|
{
|
2006-03-04 17:27:40 +00:00
|
|
|
(void)InterlockedExchangeAddUL(&Process->Vm.WorkingSetSize, -PAGE_SIZE);
|
2004-10-02 10:16:10 +00:00
|
|
|
}
|
2004-04-10 22:36:07 +00:00
|
|
|
}
|
2001-12-31 01:53:46 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
VOID
|
2005-09-14 01:05:50 +00:00
|
|
|
NTAPI
|
2006-05-18 20:32:17 +00:00
|
|
|
MmDeleteRmap(PFN_TYPE Page, PEPROCESS Process,
|
2004-04-10 22:36:07 +00:00
|
|
|
PVOID Address)
|
2001-12-31 01:53:46 +00:00
|
|
|
{
|
2004-04-10 22:36:07 +00:00
|
|
|
PMM_RMAP_ENTRY current_entry, previous_entry;
|
|
|
|
|
|
|
|
ExAcquireFastMutex(&RmapListLock);
|
|
|
|
previous_entry = NULL;
|
2004-08-01 07:24:59 +00:00
|
|
|
current_entry = MmGetRmapListHeadPage(Page);
|
2004-04-10 22:36:07 +00:00
|
|
|
while (current_entry != NULL)
|
|
|
|
{
|
2006-05-10 17:47:44 +00:00
|
|
|
if (current_entry->Process == (PEPROCESS)Process &&
|
2004-04-10 22:36:07 +00:00
|
|
|
current_entry->Address == Address)
|
|
|
|
{
|
|
|
|
if (previous_entry == NULL)
|
|
|
|
{
|
2004-08-01 07:24:59 +00:00
|
|
|
MmSetRmapListHeadPage(Page, current_entry->Next);
|
2004-04-10 22:36:07 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
previous_entry->Next = current_entry->Next;
|
|
|
|
}
|
|
|
|
ExReleaseFastMutex(&RmapListLock);
|
|
|
|
ExFreeToNPagedLookasideList(&RmapLookasideList, current_entry);
|
2004-10-02 10:16:10 +00:00
|
|
|
if (Process == NULL)
|
|
|
|
{
|
2006-05-18 20:32:17 +00:00
|
|
|
Process = PsInitialSystemProcess;
|
2004-10-02 10:16:10 +00:00
|
|
|
}
|
|
|
|
if (Process)
|
|
|
|
{
|
2006-03-04 17:27:40 +00:00
|
|
|
(void)InterlockedExchangeAddUL(&Process->Vm.WorkingSetSize, -PAGE_SIZE);
|
2004-10-02 10:16:10 +00:00
|
|
|
}
|
2004-04-10 22:36:07 +00:00
|
|
|
return;
|
|
|
|
}
|
2002-05-14 21:19:21 +00:00
|
|
|
previous_entry = current_entry;
|
|
|
|
current_entry = current_entry->Next;
|
2004-04-10 22:36:07 +00:00
|
|
|
}
|
2008-12-07 18:05:28 +00:00
|
|
|
KeBugCheck(MEMORY_MANAGEMENT);
|
2001-12-31 01:53:46 +00:00
|
|
|
}
|