PVOID Address;
} MM_RMAP_ENTRY, *PMM_RMAP_ENTRY;
+#define TAG_RMAP TAG('R', 'M', 'A', 'P')
+
/* GLOBALS ******************************************************************/
static FAST_MUTEX RmapListLock;
+static NPAGED_LOOKASIDE_LIST RmapLookasideList;
/* FUNCTIONS ****************************************************************/
MmInitializeRmapList(VOID)
{
ExInitializeFastMutex(&RmapListLock);
+ ExInitializeNPagedLookasideList (&RmapLookasideList,
+ NULL,
+ NULL,
+ 0,
+ sizeof(MM_RMAP_ENTRY),
+ TAG_RMAP,
+ 50);
}
NTSTATUS
{
PMM_RMAP_ENTRY entry;
PMEMORY_AREA MemoryArea;
+ PMADDRESS_SPACE AddressSpace;
ULONG Type;
PVOID Address;
PEPROCESS Process;
PMM_PAGEOP PageOp;
- LARGE_INTEGER Offset;
- NTSTATUS Status;
+ ULONG Offset;
+ NTSTATUS Status = STATUS_SUCCESS;
/*
* Check that the address still has a valid rmap; then reference the
Address = entry->Address;
if ((((ULONG)Address) & 0xFFF) != 0)
{
- KeBugCheck(0);
+ KEBUGCHECK(0);
+ }
+ if (Address < (PVOID)KERNEL_BASE)
+ {
+ Status = ObReferenceObjectByPointer(Process, PROCESS_ALL_ACCESS, NULL, KernelMode);
+ ExReleaseFastMutex(&RmapListLock);
+ if (!NT_SUCCESS(Status))
+ {
+ return Status;
+ }
+ AddressSpace = &Process->AddressSpace;
+ }
+ else
+ {
+ ExReleaseFastMutex(&RmapListLock);
+ AddressSpace = MmGetKernelAddressSpace();
}
- Status = ObReferenceObjectByPointer(Process, PROCESS_ALL_ACCESS, NULL, KernelMode);
- ExReleaseFastMutex(&RmapListLock);
- if (!NT_SUCCESS(Status))
- {
- return Status;
- }
/*
* Lock the address space; then check that the address we are using
* still corresponds to a valid memory area (the page might have been
* freed or paged out after we read the rmap entry.)
*/
- MmLockAddressSpace(&Process->AddressSpace);
- MemoryArea = MmOpenMemoryAreaByAddress(&Process->AddressSpace, Address);
- if (MemoryArea == NULL)
+ MmLockAddressSpace(AddressSpace);
+ MemoryArea = MmOpenMemoryAreaByAddress(AddressSpace, Address);
+ if (MemoryArea == NULL || MemoryArea->DeleteInProgress)
{
- ObDereferenceObject(Process);
+ MmUnlockAddressSpace(AddressSpace);
+ if (Address < (PVOID)KERNEL_BASE)
+ {
+ ObDereferenceObject(Process);
+ }
return(STATUS_UNSUCCESSFUL);
}
Type = MemoryArea->Type;
if (Type == MEMORY_AREA_SECTION_VIEW)
{
- Offset.QuadPart = (ULONG)((Address - (ULONG)MemoryArea->BaseAddress) +
- MemoryArea->Data.SectionData.ViewOffset);
+ Offset = (ULONG)(Address - (ULONG)MemoryArea->BaseAddress);
/*
* Get or create a pageop
*/
PageOp = MmGetPageOp(MemoryArea, 0, 0,
MemoryArea->Data.SectionData.Segment,
- Offset.u.LowPart, MM_PAGEOP_PAGEOUT);
+ Offset, MM_PAGEOP_PAGEOUT);
if (PageOp == NULL)
{
DPRINT1("MmGetPageOp failed\n");
- KeBugCheck(0);
+ KEBUGCHECK(0);
}
if (PageOp->Thread != PsGetCurrentThread())
{
+ MmUnlockAddressSpace(AddressSpace);
+ Status = KeWaitForSingleObject(&PageOp->CompletionEvent,
+ 0,
+ KernelMode,
+ FALSE,
+ NULL);
+ KeSetEvent(&PageOp->CompletionEvent, IO_NO_INCREMENT, FALSE);
MmReleasePageOp(PageOp);
- MmUnlockAddressSpace(&Process->AddressSpace);
- ObDereferenceObject(Process);
+ if (Address < (PVOID)KERNEL_BASE)
+ {
+ ObDereferenceObject(Process);
+ }
return(STATUS_UNSUCCESSFUL);
}
/*
* Release locks now we have a page op.
*/
- MmUnlockAddressSpace(&Process->AddressSpace);
+ MmUnlockAddressSpace(AddressSpace);
/*
* Do the actual page out work.
*/
- Status = MmWritePageSectionView(&Process->AddressSpace, MemoryArea,
+ Status = MmWritePageSectionView(AddressSpace, MemoryArea,
Address, PageOp);
}
else if (Type == MEMORY_AREA_VIRTUAL_MEMORY)
{
- PageOp = MmGetPageOp(MemoryArea, Process->UniqueProcessId,
+ PageOp = MmGetPageOp(MemoryArea, Address < (PVOID)KERNEL_BASE ? Process->UniqueProcessId : 0,
Address, NULL, 0, MM_PAGEOP_PAGEOUT);
-
if (PageOp->Thread != PsGetCurrentThread())
{
MmReleasePageOp(PageOp);
- MmUnlockAddressSpace(&Process->AddressSpace);
- ObDereferenceObject(Process);
+ MmUnlockAddressSpace(AddressSpace);
+ if (Address < (PVOID)KERNEL_BASE)
+ {
+ ObDereferenceObject(Process);
+ }
return(STATUS_UNSUCCESSFUL);
}
/*
* Release locks now we have a page op.
*/
- MmUnlockAddressSpace(&Process->AddressSpace);
+ MmUnlockAddressSpace(AddressSpace);
/*
* Do the actual page out work.
*/
- Status = MmWritePageVirtualMemory(&Process->AddressSpace, MemoryArea,
+ Status = MmWritePageVirtualMemory(AddressSpace, MemoryArea,
Address, PageOp);
}
else
{
- KeBugCheck(0);
+ KEBUGCHECK(0);
}
- ObDereferenceObject(Process);
+ if (Address < (PVOID)KERNEL_BASE)
+ {
+ ObDereferenceObject(Process);
+ }
return(Status);
}
{
PMM_RMAP_ENTRY entry;
PMEMORY_AREA MemoryArea;
+ PMADDRESS_SPACE AddressSpace;
ULONG Type;
PVOID Address;
PEPROCESS Process;
PMM_PAGEOP PageOp;
- LARGE_INTEGER Offset;
- NTSTATUS Status;
+ ULONG Offset;
+ NTSTATUS Status = STATUS_SUCCESS;
ExAcquireFastMutex(&RmapListLock);
entry = MmGetRmapListHeadPage(PhysicalAddress);
Address = entry->Address;
if ((((ULONG)Address) & 0xFFF) != 0)
{
- KeBugCheck(0);
+ KEBUGCHECK(0);
}
- Status = ObReferenceObjectByPointer(Process, PROCESS_ALL_ACCESS, NULL, KernelMode);
- ExReleaseFastMutex(&RmapListLock);
- if (!NT_SUCCESS(Status))
- {
- return Status;
- }
- MmLockAddressSpace(&Process->AddressSpace);
- MemoryArea = MmOpenMemoryAreaByAddress(&Process->AddressSpace, Address);
+ if (Address < (PVOID)KERNEL_BASE)
+ {
+ Status = ObReferenceObjectByPointer(Process, PROCESS_ALL_ACCESS, NULL, KernelMode);
+ ExReleaseFastMutex(&RmapListLock);
+ if (!NT_SUCCESS(Status))
+ {
+ return Status;
+ }
+ AddressSpace = &Process->AddressSpace;
+ }
+ else
+ {
+ ExReleaseFastMutex(&RmapListLock);
+ AddressSpace = MmGetKernelAddressSpace();
+ }
+
+ MmLockAddressSpace(AddressSpace);
+ MemoryArea = MmOpenMemoryAreaByAddress(AddressSpace, Address);
+ if (MemoryArea == NULL || MemoryArea->DeleteInProgress)
+ {
+ MmUnlockAddressSpace(AddressSpace);
+ if (Address < (PVOID)KERNEL_BASE)
+ {
+ ObDereferenceObject(Process);
+ }
+ return(STATUS_UNSUCCESSFUL);
+ }
Type = MemoryArea->Type;
if (Type == MEMORY_AREA_SECTION_VIEW)
{
- Offset.QuadPart = (ULONG)((Address - (ULONG)MemoryArea->BaseAddress) +
- MemoryArea->Data.SectionData.ViewOffset);
+ Offset = (ULONG)(Address - (ULONG)MemoryArea->BaseAddress);
/*
* Get or create a pageop
*/
PageOp = MmGetPageOp(MemoryArea, 0, 0,
MemoryArea->Data.SectionData.Segment,
- Offset.u.LowPart, MM_PAGEOP_PAGEOUT);
+ Offset, MM_PAGEOP_PAGEOUT);
if (PageOp == NULL)
{
DPRINT1("MmGetPageOp failed\n");
- KeBugCheck(0);
+ KEBUGCHECK(0);
}
if (PageOp->Thread != PsGetCurrentThread())
{
MmReleasePageOp(PageOp);
- MmUnlockAddressSpace(&Process->AddressSpace);
- ObDereferenceObject(Process);
+ MmUnlockAddressSpace(AddressSpace);
+ if (Address < (PVOID)KERNEL_BASE)
+ {
+ ObDereferenceObject(Process);
+ }
return(STATUS_UNSUCCESSFUL);
}
/*
* Release locks now we have a page op.
*/
- MmUnlockAddressSpace(&Process->AddressSpace);
+ MmUnlockAddressSpace(AddressSpace);
/*
* Do the actual page out work.
*/
- Status = MmPageOutSectionView(&Process->AddressSpace, MemoryArea,
+ Status = MmPageOutSectionView(AddressSpace, MemoryArea,
Address, PageOp);
}
else if (Type == MEMORY_AREA_VIRTUAL_MEMORY)
{
- PageOp = MmGetPageOp(MemoryArea, Process->UniqueProcessId,
+ PageOp = MmGetPageOp(MemoryArea, Address < (PVOID)KERNEL_BASE ? Process->UniqueProcessId : 0,
Address, NULL, 0, MM_PAGEOP_PAGEOUT);
if (PageOp->Thread != PsGetCurrentThread())
{
+ MmUnlockAddressSpace(AddressSpace);
+ Status = KeWaitForSingleObject(&PageOp->CompletionEvent,
+ 0,
+ KernelMode,
+ FALSE,
+ NULL);
+ KeSetEvent(&PageOp->CompletionEvent, IO_NO_INCREMENT, FALSE);
MmReleasePageOp(PageOp);
- MmUnlockAddressSpace(&Process->AddressSpace);
- ObDereferenceObject(Process);
+ if (Address < (PVOID)KERNEL_BASE)
+ {
+ ObDereferenceObject(Process);
+ }
return(STATUS_UNSUCCESSFUL);
}
/*
* Release locks now we have a page op.
*/
- MmUnlockAddressSpace(&Process->AddressSpace);
+ MmUnlockAddressSpace(AddressSpace);
/*
* Do the actual page out work.
*/
- Status = MmPageOutVirtualMemory(&Process->AddressSpace, MemoryArea,
+ Status = MmPageOutVirtualMemory(AddressSpace, MemoryArea,
Address, PageOp);
}
else
{
- KeBugCheck(0);
+ KEBUGCHECK(0);
+ }
+ if (Address < (PVOID)KERNEL_BASE)
+ {
+ ObDereferenceObject(Process);
}
- ObDereferenceObject(Process);
return(Status);
}
if (current_entry == NULL)
{
DPRINT1("MmIsDirtyRmap: No rmaps.\n");
- KeBugCheck(0);
+ KEBUGCHECK(0);
}
while (current_entry != NULL)
{
if (current_entry == NULL)
{
DPRINT1("MmIsDirtyRmap: No rmaps.\n");
- KeBugCheck(0);
+ KEBUGCHECK(0);
}
while (current_entry != NULL)
{
Address = (PVOID)PAGE_ROUND_DOWN(Address);
- new_entry = ExAllocatePool(NonPagedPool, sizeof(MM_RMAP_ENTRY));
+ new_entry = ExAllocateFromNPagedLookasideList(&RmapLookasideList);
if (new_entry == NULL)
{
- KeBugCheck(0);
+ KEBUGCHECK(0);
}
new_entry->Address = Address;
new_entry->Process = Process;
"address 0x%.8X\n", Process->UniqueProcessId, Address,
MmGetPhysicalAddressForProcess(Process, Address),
PhysicalAddress)
- KeBugCheck(0);
+ KEBUGCHECK(0);
}
ExAcquireFastMutex(&RmapListLock);
if (current_entry == NULL)
{
DPRINT1("MmDeleteAllRmaps: No rmaps.\n");
- KeBugCheck(0);
+ KEBUGCHECK(0);
}
+ MmSetRmapListHeadPage(PhysicalAddress, NULL);
while (current_entry != NULL)
{
previous_entry = current_entry;
DeleteMapping(Context, previous_entry->Process,
previous_entry->Address);
}
- ExFreePool(previous_entry);
+ ExFreeToNPagedLookasideList(&RmapLookasideList, previous_entry);
}
- MmSetRmapListHeadPage(PhysicalAddress, NULL);
ExReleaseFastMutex(&RmapListLock);
}
if (previous_entry == NULL)
{
MmSetRmapListHeadPage(PhysicalAddress, current_entry->Next);
- ExReleaseFastMutex(&RmapListLock);
- ExFreePool(current_entry);
}
else
{
previous_entry->Next = current_entry->Next;
- ExReleaseFastMutex(&RmapListLock);
- ExFreePool(current_entry);
}
+ ExReleaseFastMutex(&RmapListLock);
+ ExFreeToNPagedLookasideList(&RmapLookasideList, current_entry);
return;
}
previous_entry = current_entry;
current_entry = current_entry->Next;
}
- KeBugCheck(0);
+ KEBUGCHECK(0);
}