mirror of
https://github.com/reactos/reactos.git
synced 2025-08-05 02:25:40 +00:00
[NTOS]: Zeroed pages should go at the front, not the back of the zero list. Going to the back is a special boot-only case on MP, which isn't supported. Implement zero-only version of MiInsertPageInList, remove MiInsertZeroPageAtBack.
[NTOS]: Remove many other deprecated functions. Physical memory consistency should now be higher than in the past. svn path=/trunk/; revision=48919
This commit is contained in:
parent
354ad6b9eb
commit
5b9cd7fcae
6 changed files with 82 additions and 430 deletions
|
@ -444,10 +444,8 @@ MmMapLockedPagesSpecifyCache(IN PMDL Mdl,
|
||||||
return Base;
|
return Base;
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
UNIMPLEMENTED;
|
||||||
// In user-mode, let ReactOS do it
|
return NULL;
|
||||||
//
|
|
||||||
return MiMapLockedPagesInUserSpace(Mdl, Base, CacheType, BaseAddress);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -557,10 +555,7 @@ MmUnmapLockedPages(IN PVOID BaseAddress,
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
//
|
UNIMPLEMENTED;
|
||||||
// Let ReactOS handle it
|
|
||||||
//
|
|
||||||
MiUnmapLockedPagesInUserSpace(BaseAddress, Mdl);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -920,15 +920,9 @@ MiUnmapLockedPagesInUserSpace(
|
||||||
|
|
||||||
VOID
|
VOID
|
||||||
NTAPI
|
NTAPI
|
||||||
MiInsertInListTail(
|
MiInsertPageInList(
|
||||||
IN PMMPFNLIST ListHead,
|
IN PMMPFNLIST ListHead,
|
||||||
IN PMMPFN Entry
|
IN PFN_NUMBER PageFrameIndex
|
||||||
);
|
|
||||||
|
|
||||||
VOID
|
|
||||||
NTAPI
|
|
||||||
MiInsertZeroListAtBack(
|
|
||||||
IN PFN_NUMBER PageIndex
|
|
||||||
);
|
);
|
||||||
|
|
||||||
VOID
|
VOID
|
||||||
|
|
|
@ -71,137 +71,6 @@ MiZeroPhysicalPage(IN PFN_NUMBER PageFrameIndex)
|
||||||
MiUnmapPageInHyperSpace(Process, VirtualAddress, OldIrql);
|
MiUnmapPageInHyperSpace(Process, VirtualAddress, OldIrql);
|
||||||
}
|
}
|
||||||
|
|
||||||
VOID
|
|
||||||
NTAPI
|
|
||||||
MiInsertInListTail(IN PMMPFNLIST ListHead,
|
|
||||||
IN PMMPFN Entry)
|
|
||||||
{
|
|
||||||
PFN_NUMBER OldBlink, EntryIndex = MiGetPfnEntryIndex(Entry);
|
|
||||||
ASSERT(KeGetCurrentIrql() == DISPATCH_LEVEL);
|
|
||||||
ASSERT_LIST_INVARIANT(ListHead);
|
|
||||||
|
|
||||||
/* Get the back link */
|
|
||||||
OldBlink = ListHead->Blink;
|
|
||||||
if (OldBlink != LIST_HEAD)
|
|
||||||
{
|
|
||||||
/* Set the back pointer to point to us now */
|
|
||||||
MiGetPfnEntry(OldBlink)->u1.Flink = EntryIndex;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* Set the list to point to us */
|
|
||||||
ListHead->Flink = EntryIndex;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Set the entry to point to the list head forwards, and the old page backwards */
|
|
||||||
Entry->u1.Flink = LIST_HEAD;
|
|
||||||
Entry->u2.Blink = OldBlink;
|
|
||||||
|
|
||||||
/* And now the head points back to us, since we are last */
|
|
||||||
ListHead->Blink = EntryIndex;
|
|
||||||
ListHead->Total++;
|
|
||||||
ASSERT_LIST_INVARIANT(ListHead);
|
|
||||||
}
|
|
||||||
|
|
||||||
VOID
|
|
||||||
NTAPI
|
|
||||||
MiInsertZeroListAtBack(IN PFN_NUMBER EntryIndex)
|
|
||||||
{
|
|
||||||
PFN_NUMBER OldBlink;
|
|
||||||
PMMPFNLIST ListHead;
|
|
||||||
PMMPFN Pfn1;
|
|
||||||
#if 0
|
|
||||||
PMMPFN Blink;
|
|
||||||
ULONG Color;
|
|
||||||
PMMCOLOR_TABLES ColorHead;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Make sure the PFN lock is held */
|
|
||||||
ASSERT(KeGetCurrentIrql() == DISPATCH_LEVEL);
|
|
||||||
|
|
||||||
/* Get the descriptor */
|
|
||||||
Pfn1 = MiGetPfnEntry(EntryIndex);
|
|
||||||
ASSERT(Pfn1->u3.e2.ReferenceCount == 0);
|
|
||||||
ASSERT(Pfn1->u4.MustBeCached == 0);
|
|
||||||
ASSERT(Pfn1->u3.e1.Rom == 0);
|
|
||||||
ASSERT(Pfn1->u3.e1.RemovalRequested == 0);
|
|
||||||
ASSERT(Pfn1->u4.InPageError == 0);
|
|
||||||
|
|
||||||
/* Use the zero list */
|
|
||||||
ListHead = &MmZeroedPageListHead;
|
|
||||||
ASSERT_LIST_INVARIANT(ListHead);
|
|
||||||
ListHead->Total++;
|
|
||||||
|
|
||||||
/* Get the back link */
|
|
||||||
OldBlink = ListHead->Blink;
|
|
||||||
if (OldBlink != LIST_HEAD)
|
|
||||||
{
|
|
||||||
/* Set the back pointer to point to us now */
|
|
||||||
MiGetPfnEntry(OldBlink)->u1.Flink = EntryIndex;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* Set the list to point to us */
|
|
||||||
ListHead->Flink = EntryIndex;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Set the entry to point to the list head forwards, and the old page backwards */
|
|
||||||
Pfn1->u1.Flink = LIST_HEAD;
|
|
||||||
Pfn1->u2.Blink = OldBlink;
|
|
||||||
|
|
||||||
/* 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;
|
|
||||||
|
|
||||||
/* Update the available page count */
|
|
||||||
MmAvailablePages++;
|
|
||||||
|
|
||||||
/* Check if we've reached the configured low memory threshold */
|
|
||||||
if (MmAvailablePages == MmLowMemoryThreshold)
|
|
||||||
{
|
|
||||||
/* Clear the event, because now we're ABOVE the threshold */
|
|
||||||
KeClearEvent(MiLowMemoryEvent);
|
|
||||||
}
|
|
||||||
else if (MmAvailablePages == MmHighMemoryThreshold)
|
|
||||||
{
|
|
||||||
/* 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;
|
|
||||||
|
|
||||||
/* Get the first page on the color list */
|
|
||||||
ColorHead = &MmFreePagesByColor[ZeroedPageList][Color];
|
|
||||||
if (ColorHead->Flink == LIST_HEAD)
|
|
||||||
{
|
|
||||||
/* The list is empty, so we are the first page */
|
|
||||||
Pfn1->u4.PteFrame = -1;
|
|
||||||
ColorHead->Flink = EntryIndex;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* Get the previous page */
|
|
||||||
Blink = (PMMPFN)ColorHead->Blink;
|
|
||||||
|
|
||||||
/* Make it link to us */
|
|
||||||
Pfn1->u4.PteFrame = MiGetPfnEntryIndex(Blink);
|
|
||||||
Blink->OriginalPte.u.Long = EntryIndex;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Now initialize our own list pointers */
|
|
||||||
ColorHead->Blink = Pfn1;
|
|
||||||
Pfn1->OriginalPte.u.Long = LIST_HEAD;
|
|
||||||
|
|
||||||
/* And increase the count in the colored list */
|
|
||||||
ColorHead->Count++;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
VOID
|
VOID
|
||||||
NTAPI
|
NTAPI
|
||||||
MiUnlinkFreeOrZeroedPage(IN PMMPFN Entry)
|
MiUnlinkFreeOrZeroedPage(IN PMMPFN Entry)
|
||||||
|
@ -527,45 +396,6 @@ MiRemoveZeroPage(IN ULONG Color)
|
||||||
/* Return the page */
|
/* Return the page */
|
||||||
return PageIndex;
|
return PageIndex;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
PMMPFN
|
|
||||||
NTAPI
|
|
||||||
MiRemoveHeadList(IN PMMPFNLIST ListHead)
|
|
||||||
{
|
|
||||||
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);
|
|
||||||
|
|
||||||
/* Make the list point to the entry following the first one */
|
|
||||||
Flink = Pfn1->u1.Flink;
|
|
||||||
ListHead->Flink = Flink;
|
|
||||||
|
|
||||||
/* Check if the next entry is actually the list head */
|
|
||||||
if (ListHead->Flink != LIST_HEAD)
|
|
||||||
{
|
|
||||||
/* It isn't, so therefore whoever is coming next points back to the head */
|
|
||||||
MiGetPfnEntry(Flink)->u2.Blink = LIST_HEAD;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* Then the list is empty, so the backlink should point back to us */
|
|
||||||
ListHead->Blink = LIST_HEAD;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 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;
|
|
||||||
}
|
|
||||||
|
|
||||||
extern KEVENT ZeroPageThreadEvent;
|
extern KEVENT ZeroPageThreadEvent;
|
||||||
|
|
||||||
|
@ -684,6 +514,82 @@ MiInsertPageInFreeList(IN PFN_NUMBER PageFrameIndex)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Note: This function is hardcoded only for the zeroed page list, for now */
|
||||||
|
VOID
|
||||||
|
NTAPI
|
||||||
|
MiInsertPageInList(IN PMMPFNLIST ListHead,
|
||||||
|
IN PFN_NUMBER PageFrameIndex)
|
||||||
|
{
|
||||||
|
PFN_NUMBER Flink;
|
||||||
|
PMMPFN Pfn1, Pfn2;
|
||||||
|
MMLISTS ListName;
|
||||||
|
|
||||||
|
/* For free pages, use MiInsertPageInFreeList */
|
||||||
|
ASSERT(ListHead != &MmFreePageListHead);
|
||||||
|
|
||||||
|
/* Make sure the lock is held */
|
||||||
|
ASSERT(KeGetCurrentIrql() == DISPATCH_LEVEL);
|
||||||
|
|
||||||
|
/* Make sure the PFN is valid */
|
||||||
|
ASSERT((PageFrameIndex) &&
|
||||||
|
(PageFrameIndex <= MmHighestPhysicalPage) &&
|
||||||
|
(PageFrameIndex >= MmLowestPhysicalPage));
|
||||||
|
|
||||||
|
/* Page should be unused */
|
||||||
|
Pfn1 = MiGetPfnEntry(PageFrameIndex);
|
||||||
|
ASSERT(Pfn1->u3.e2.ReferenceCount == 0);
|
||||||
|
ASSERT(Pfn1->u3.e1.Rom != 1);
|
||||||
|
|
||||||
|
/* Only used for zero pages in ReactOS */
|
||||||
|
ListName = ListHead->ListName;
|
||||||
|
ASSERT(ListName == ZeroedPageList);
|
||||||
|
ListHead->Total++;
|
||||||
|
|
||||||
|
/* Don't handle bad pages yet yet */
|
||||||
|
ASSERT(Pfn1->u3.e1.RemovalRequested == 0);
|
||||||
|
|
||||||
|
/* Make the head of the list point to this page now */
|
||||||
|
Flink = ListHead->Flink;
|
||||||
|
ListHead->Flink = PageFrameIndex;
|
||||||
|
|
||||||
|
/* Make the page point to the previous head, and back to the list */
|
||||||
|
Pfn1->u1.Flink = Flink;
|
||||||
|
Pfn1->u2.Blink = LIST_HEAD;
|
||||||
|
|
||||||
|
/* Was the list empty? */
|
||||||
|
if (Flink != LIST_HEAD)
|
||||||
|
{
|
||||||
|
/* It wasn't, so update the backlink of the previous head page */
|
||||||
|
Pfn2 = MiGetPfnEntry(Flink);
|
||||||
|
Pfn2->u2.Blink = PageFrameIndex;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* It was empty, so have it loop back around to this new page */
|
||||||
|
ListHead->Blink = PageFrameIndex;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Move the page onto its new location */
|
||||||
|
Pfn1->u3.e1.PageLocation = ListName;
|
||||||
|
|
||||||
|
/* One more page on the system */
|
||||||
|
MmAvailablePages++;
|
||||||
|
|
||||||
|
/* Check if we've reached the configured low memory threshold */
|
||||||
|
if (MmAvailablePages == MmLowMemoryThreshold)
|
||||||
|
{
|
||||||
|
/* Clear the event, because now we're ABOVE the threshold */
|
||||||
|
KeClearEvent(MiLowMemoryEvent);
|
||||||
|
}
|
||||||
|
else if (MmAvailablePages == MmHighMemoryThreshold)
|
||||||
|
{
|
||||||
|
/* Otherwise check if we reached the high threshold and signal the event */
|
||||||
|
KeSetEvent(MiHighMemoryEvent, 0, FALSE);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* FIXME: Color code handling */
|
||||||
|
}
|
||||||
|
|
||||||
VOID
|
VOID
|
||||||
NTAPI
|
NTAPI
|
||||||
MiInitializePfn(IN PFN_NUMBER PageFrameIndex,
|
MiInitializePfn(IN PFN_NUMBER PageFrameIndex,
|
||||||
|
|
|
@ -682,7 +682,7 @@ MmZeroPageThreadMain(PVOID Ignored)
|
||||||
|
|
||||||
oldIrql = KeAcquireQueuedSpinLock(LockQueuePfnLock);
|
oldIrql = KeAcquireQueuedSpinLock(LockQueuePfnLock);
|
||||||
|
|
||||||
MiInsertZeroListAtBack(PageIndex);
|
MiInsertPageInList(&MmZeroedPageListHead, PageIndex);
|
||||||
Count++;
|
Count++;
|
||||||
}
|
}
|
||||||
DPRINT("Zeroed %d pages.\n", Count);
|
DPRINT("Zeroed %d pages.\n", Count);
|
||||||
|
|
|
@ -52,140 +52,6 @@ MmInitializeRmapList(VOID)
|
||||||
50);
|
50);
|
||||||
}
|
}
|
||||||
|
|
||||||
NTSTATUS
|
|
||||||
NTAPI
|
|
||||||
MmWritePagePhysicalAddress(PFN_NUMBER Page)
|
|
||||||
{
|
|
||||||
PMM_RMAP_ENTRY entry;
|
|
||||||
PMEMORY_AREA MemoryArea;
|
|
||||||
PMMSUPPORT AddressSpace;
|
|
||||||
ULONG Type;
|
|
||||||
PVOID Address;
|
|
||||||
PEPROCESS Process;
|
|
||||||
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);
|
|
||||||
entry = MmGetRmapListHeadPage(Page);
|
|
||||||
if (entry == NULL)
|
|
||||||
{
|
|
||||||
ExReleaseFastMutex(&RmapListLock);
|
|
||||||
return(STATUS_UNSUCCESSFUL);
|
|
||||||
}
|
|
||||||
Process = entry->Process;
|
|
||||||
Address = entry->Address;
|
|
||||||
if ((((ULONG_PTR)Address) & 0xFFF) != 0)
|
|
||||||
{
|
|
||||||
KeBugCheck(MEMORY_MANAGEMENT);
|
|
||||||
}
|
|
||||||
if (Address < MmSystemRangeStart)
|
|
||||||
{
|
|
||||||
Status = ObReferenceObjectByPointer(Process, PROCESS_ALL_ACCESS, NULL, KernelMode);
|
|
||||||
ExReleaseFastMutex(&RmapListLock);
|
|
||||||
if (!NT_SUCCESS(Status))
|
|
||||||
{
|
|
||||||
return Status;
|
|
||||||
}
|
|
||||||
AddressSpace = &Process->Vm;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
ExReleaseFastMutex(&RmapListLock);
|
|
||||||
AddressSpace = MmGetKernelAddressSpace();
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* 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(AddressSpace);
|
|
||||||
MemoryArea = MmLocateMemoryAreaByAddress(AddressSpace, Address);
|
|
||||||
if (MemoryArea == NULL || MemoryArea->DeleteInProgress)
|
|
||||||
{
|
|
||||||
MmUnlockAddressSpace(AddressSpace);
|
|
||||||
if (Address < MmSystemRangeStart)
|
|
||||||
{
|
|
||||||
ObDereferenceObject(Process);
|
|
||||||
}
|
|
||||||
return(STATUS_UNSUCCESSFUL);
|
|
||||||
}
|
|
||||||
|
|
||||||
Type = MemoryArea->Type;
|
|
||||||
if (Type == MEMORY_AREA_SECTION_VIEW)
|
|
||||||
{
|
|
||||||
Offset = (ULONG_PTR)Address - (ULONG_PTR)MemoryArea->StartingAddress
|
|
||||||
+ MemoryArea->Data.SectionData.ViewOffset;
|
|
||||||
/*
|
|
||||||
* Get or create a pageop
|
|
||||||
*/
|
|
||||||
PageOp = MmGetPageOp(MemoryArea, NULL, 0,
|
|
||||||
MemoryArea->Data.SectionData.Segment,
|
|
||||||
Offset, MM_PAGEOP_PAGEOUT, TRUE);
|
|
||||||
|
|
||||||
if (PageOp == NULL)
|
|
||||||
{
|
|
||||||
MmUnlockAddressSpace(AddressSpace);
|
|
||||||
if (Address < MmSystemRangeStart)
|
|
||||||
{
|
|
||||||
ObDereferenceObject(Process);
|
|
||||||
}
|
|
||||||
return(STATUS_UNSUCCESSFUL);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Release locks now we have a page op.
|
|
||||||
*/
|
|
||||||
MmUnlockAddressSpace(AddressSpace);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Do the actual page out work.
|
|
||||||
*/
|
|
||||||
Status = MmWritePageSectionView(AddressSpace, MemoryArea,
|
|
||||||
Address, PageOp);
|
|
||||||
}
|
|
||||||
else if (Type == MEMORY_AREA_VIRTUAL_MEMORY)
|
|
||||||
{
|
|
||||||
PageOp = MmGetPageOp(MemoryArea, Address < MmSystemRangeStart ? Process->UniqueProcessId : NULL,
|
|
||||||
Address, NULL, 0, MM_PAGEOP_PAGEOUT, TRUE);
|
|
||||||
|
|
||||||
if (PageOp == NULL)
|
|
||||||
{
|
|
||||||
MmUnlockAddressSpace(AddressSpace);
|
|
||||||
if (Address < MmSystemRangeStart)
|
|
||||||
{
|
|
||||||
ObDereferenceObject(Process);
|
|
||||||
}
|
|
||||||
return(STATUS_UNSUCCESSFUL);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Release locks now we have a page op.
|
|
||||||
*/
|
|
||||||
MmUnlockAddressSpace(AddressSpace);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Do the actual page out work.
|
|
||||||
*/
|
|
||||||
Status = MmWritePageVirtualMemory(AddressSpace, MemoryArea,
|
|
||||||
Address, PageOp);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
KeBugCheck(MEMORY_MANAGEMENT);
|
|
||||||
}
|
|
||||||
if (Address < MmSystemRangeStart)
|
|
||||||
{
|
|
||||||
ObDereferenceObject(Process);
|
|
||||||
}
|
|
||||||
return(Status);
|
|
||||||
}
|
|
||||||
|
|
||||||
NTSTATUS
|
NTSTATUS
|
||||||
NTAPI
|
NTAPI
|
||||||
MmPageOutPhysicalAddress(PFN_NUMBER Page)
|
MmPageOutPhysicalAddress(PFN_NUMBER Page)
|
||||||
|
|
|
@ -162,115 +162,6 @@ MiProtectVirtualMemory(IN PEPROCESS Process,
|
||||||
return Status;
|
return Status;
|
||||||
}
|
}
|
||||||
|
|
||||||
PVOID
|
|
||||||
NTAPI
|
|
||||||
MiMapLockedPagesInUserSpace(IN PMDL Mdl,
|
|
||||||
IN PVOID BaseVa,
|
|
||||||
IN MEMORY_CACHING_TYPE CacheType,
|
|
||||||
IN PVOID BaseAddress)
|
|
||||||
{
|
|
||||||
PVOID Base;
|
|
||||||
PPFN_NUMBER MdlPages;
|
|
||||||
ULONG PageCount;
|
|
||||||
PEPROCESS CurrentProcess;
|
|
||||||
NTSTATUS Status;
|
|
||||||
ULONG Protect;
|
|
||||||
MEMORY_AREA *Result;
|
|
||||||
LARGE_INTEGER BoundaryAddressMultiple;
|
|
||||||
|
|
||||||
/* Calculate the number of pages required. */
|
|
||||||
MdlPages = (PPFN_NUMBER)(Mdl + 1);
|
|
||||||
PageCount = PAGE_ROUND_UP(Mdl->ByteCount + Mdl->ByteOffset) / PAGE_SIZE;
|
|
||||||
|
|
||||||
/* Set default page protection */
|
|
||||||
Protect = PAGE_READWRITE;
|
|
||||||
if (CacheType == MmNonCached) Protect |= PAGE_NOCACHE;
|
|
||||||
|
|
||||||
BoundaryAddressMultiple.QuadPart = 0;
|
|
||||||
Base = BaseAddress;
|
|
||||||
|
|
||||||
CurrentProcess = PsGetCurrentProcess();
|
|
||||||
|
|
||||||
MmLockAddressSpace(&CurrentProcess->Vm);
|
|
||||||
Status = MmCreateMemoryArea(&CurrentProcess->Vm,
|
|
||||||
MEMORY_AREA_MDL_MAPPING,
|
|
||||||
&Base,
|
|
||||||
PageCount * PAGE_SIZE,
|
|
||||||
Protect,
|
|
||||||
&Result,
|
|
||||||
(Base != NULL),
|
|
||||||
0,
|
|
||||||
BoundaryAddressMultiple);
|
|
||||||
MmUnlockAddressSpace(&CurrentProcess->Vm);
|
|
||||||
if (!NT_SUCCESS(Status))
|
|
||||||
{
|
|
||||||
if (Mdl->MdlFlags & MDL_MAPPING_CAN_FAIL)
|
|
||||||
{
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Throw exception */
|
|
||||||
ExRaiseStatus(STATUS_ACCESS_VIOLATION);
|
|
||||||
ASSERT(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Set the virtual mappings for the MDL pages. */
|
|
||||||
if (Mdl->MdlFlags & MDL_IO_SPACE)
|
|
||||||
{
|
|
||||||
/* Map the pages */
|
|
||||||
Status = MmCreateVirtualMappingUnsafe(CurrentProcess,
|
|
||||||
Base,
|
|
||||||
Protect,
|
|
||||||
MdlPages,
|
|
||||||
PageCount);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* Map the pages */
|
|
||||||
Status = MmCreateVirtualMapping(CurrentProcess,
|
|
||||||
Base,
|
|
||||||
Protect,
|
|
||||||
MdlPages,
|
|
||||||
PageCount);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Check if the mapping suceeded */
|
|
||||||
if (!NT_SUCCESS(Status))
|
|
||||||
{
|
|
||||||
/* If it can fail, return NULL */
|
|
||||||
if (Mdl->MdlFlags & MDL_MAPPING_CAN_FAIL) return NULL;
|
|
||||||
|
|
||||||
/* Throw exception */
|
|
||||||
ExRaiseStatus(STATUS_ACCESS_VIOLATION);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Return the base */
|
|
||||||
Base = (PVOID)((ULONG_PTR)Base + Mdl->ByteOffset);
|
|
||||||
return Base;
|
|
||||||
}
|
|
||||||
|
|
||||||
VOID
|
|
||||||
NTAPI
|
|
||||||
MiUnmapLockedPagesInUserSpace(IN PVOID BaseAddress,
|
|
||||||
IN PMDL Mdl)
|
|
||||||
{
|
|
||||||
PMEMORY_AREA MemoryArea;
|
|
||||||
|
|
||||||
/* Sanity check */
|
|
||||||
ASSERT(Mdl->Process == PsGetCurrentProcess());
|
|
||||||
|
|
||||||
/* Find the memory area */
|
|
||||||
MemoryArea = MmLocateMemoryAreaByAddress(&Mdl->Process->Vm,
|
|
||||||
BaseAddress);
|
|
||||||
ASSERT(MemoryArea);
|
|
||||||
|
|
||||||
/* Free it */
|
|
||||||
MmFreeMemoryArea(&Mdl->Process->Vm,
|
|
||||||
MemoryArea,
|
|
||||||
NULL,
|
|
||||||
NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* SYSTEM CALLS ***************************************************************/
|
/* SYSTEM CALLS ***************************************************************/
|
||||||
|
|
||||||
NTSTATUS NTAPI
|
NTSTATUS NTAPI
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue