mirror of
https://github.com/reactos/reactos.git
synced 2025-08-05 16:02:56 +00:00
[NTOSKRNL]
Remove PAGEOPs and use the argument to pass relevant information where needed, including generally a section page table entry or a PFN_NUMBER. In its place, the code looks for an MM_WAIT_ENTRY in the appropriate place and waits, returning STATUS_MM_RESTART_OPERATION. Rather than copying the pagein and CoW operations in the PAGEOP contention case, we just punt back and restart the operation, resulting in simpler code. svn path=/trunk/; revision=56441
This commit is contained in:
parent
4d93b7e8d5
commit
b621664add
6 changed files with 128 additions and 379 deletions
|
@ -229,7 +229,6 @@ list(APPEND SOURCE
|
||||||
mm/mmfault.c
|
mm/mmfault.c
|
||||||
mm/mminit.c
|
mm/mminit.c
|
||||||
mm/pagefile.c
|
mm/pagefile.c
|
||||||
mm/pageop.c
|
|
||||||
mm/region.c
|
mm/region.c
|
||||||
mm/rmap.c
|
mm/rmap.c
|
||||||
mm/section.c
|
mm/section.c
|
||||||
|
|
5
reactos/ntoskrnl/cache/section/sptab.c
vendored
5
reactos/ntoskrnl/cache/section/sptab.c
vendored
|
@ -215,8 +215,9 @@ _MmSetPageEntrySectionSegment(PMM_SECTION_SEGMENT Segment,
|
||||||
ASSERT(!Entry || IS_SWAP_FROM_SSE(Entry));
|
ASSERT(!Entry || IS_SWAP_FROM_SSE(Entry));
|
||||||
MmDeleteSectionAssociation(PFN_FROM_SSE(OldEntry));
|
MmDeleteSectionAssociation(PFN_FROM_SSE(OldEntry));
|
||||||
} else if (IS_SWAP_FROM_SSE(Entry)) {
|
} else if (IS_SWAP_FROM_SSE(Entry)) {
|
||||||
ASSERT(!IS_SWAP_FROM_SSE(OldEntry));
|
ASSERT(!IS_SWAP_FROM_SSE(OldEntry) ||
|
||||||
if (OldEntry)
|
SWAPENTRY_FROM_SSE(OldEntry) == MM_WAIT_ENTRY);
|
||||||
|
if (OldEntry && SWAPENTRY_FROM_SSE(OldEntry) != MM_WAIT_ENTRY)
|
||||||
MmDeleteSectionAssociation(PFN_FROM_SSE(OldEntry));
|
MmDeleteSectionAssociation(PFN_FROM_SSE(OldEntry));
|
||||||
} else if (IS_SWAP_FROM_SSE(OldEntry)) {
|
} else if (IS_SWAP_FROM_SSE(OldEntry)) {
|
||||||
ASSERT(!IS_SWAP_FROM_SSE(Entry));
|
ASSERT(!IS_SWAP_FROM_SSE(Entry));
|
||||||
|
|
|
@ -49,7 +49,6 @@ extern PMMPTE MmDebugPte;
|
||||||
struct _KTRAP_FRAME;
|
struct _KTRAP_FRAME;
|
||||||
struct _EPROCESS;
|
struct _EPROCESS;
|
||||||
struct _MM_RMAP_ENTRY;
|
struct _MM_RMAP_ENTRY;
|
||||||
struct _MM_PAGEOP;
|
|
||||||
typedef ULONG_PTR SWAPENTRY;
|
typedef ULONG_PTR SWAPENTRY;
|
||||||
|
|
||||||
//
|
//
|
||||||
|
@ -84,12 +83,6 @@ typedef ULONG_PTR SWAPENTRY;
|
||||||
#define MM_CORE_DUMP_TYPE_MINIMAL (0x1)
|
#define MM_CORE_DUMP_TYPE_MINIMAL (0x1)
|
||||||
#define MM_CORE_DUMP_TYPE_FULL (0x2)
|
#define MM_CORE_DUMP_TYPE_FULL (0x2)
|
||||||
|
|
||||||
#define MM_PAGEOP_PAGEIN (1)
|
|
||||||
#define MM_PAGEOP_PAGEOUT (2)
|
|
||||||
#define MM_PAGEOP_PAGESYNCH (3)
|
|
||||||
#define MM_PAGEOP_ACCESSFAULT (4)
|
|
||||||
#define MM_PAGEOP_CHANGEPROTECT (5)
|
|
||||||
|
|
||||||
/* Number of list heads to use */
|
/* Number of list heads to use */
|
||||||
#define MI_FREE_POOL_LISTS 4
|
#define MI_FREE_POOL_LISTS 4
|
||||||
|
|
||||||
|
@ -415,37 +408,6 @@ extern MMPFNLIST MmStandbyPageListHead;
|
||||||
extern MMPFNLIST MmModifiedPageListHead;
|
extern MMPFNLIST MmModifiedPageListHead;
|
||||||
extern MMPFNLIST MmModifiedNoWritePageListHead;
|
extern MMPFNLIST MmModifiedNoWritePageListHead;
|
||||||
|
|
||||||
typedef struct _MM_PAGEOP
|
|
||||||
{
|
|
||||||
/* Type of operation. */
|
|
||||||
ULONG OpType;
|
|
||||||
/* Number of threads interested in this operation. */
|
|
||||||
ULONG ReferenceCount;
|
|
||||||
/* Event that will be set when the operation is completed. */
|
|
||||||
KEVENT CompletionEvent;
|
|
||||||
/* Status of the operation once it is completed. */
|
|
||||||
NTSTATUS Status;
|
|
||||||
/* TRUE if the operation was abandoned. */
|
|
||||||
BOOLEAN Abandoned;
|
|
||||||
/* The memory area to be affected by the operation. */
|
|
||||||
PMEMORY_AREA MArea;
|
|
||||||
ULONG Hash;
|
|
||||||
struct _MM_PAGEOP* Next;
|
|
||||||
struct _ETHREAD* Thread;
|
|
||||||
/*
|
|
||||||
* These fields are used to identify the operation if it is against a
|
|
||||||
* virtual memory area.
|
|
||||||
*/
|
|
||||||
HANDLE Pid;
|
|
||||||
PVOID Address;
|
|
||||||
/*
|
|
||||||
* These fields are used to identify the operation if it is against a
|
|
||||||
* section mapping.
|
|
||||||
*/
|
|
||||||
PMM_SECTION_SEGMENT Segment;
|
|
||||||
ULONGLONG Offset;
|
|
||||||
} MM_PAGEOP, *PMM_PAGEOP;
|
|
||||||
|
|
||||||
typedef struct _MM_MEMORY_CONSUMER
|
typedef struct _MM_MEMORY_CONSUMER
|
||||||
{
|
{
|
||||||
ULONG PagesUsed;
|
ULONG PagesUsed;
|
||||||
|
@ -937,7 +899,7 @@ MmPageOutVirtualMemory(
|
||||||
PMMSUPPORT AddressSpace,
|
PMMSUPPORT AddressSpace,
|
||||||
PMEMORY_AREA MemoryArea,
|
PMEMORY_AREA MemoryArea,
|
||||||
PVOID Address,
|
PVOID Address,
|
||||||
struct _MM_PAGEOP* PageOp
|
PFN_NUMBER Page
|
||||||
);
|
);
|
||||||
|
|
||||||
NTSTATUS
|
NTSTATUS
|
||||||
|
@ -973,7 +935,7 @@ MmWritePageVirtualMemory(
|
||||||
PMMSUPPORT AddressSpace,
|
PMMSUPPORT AddressSpace,
|
||||||
PMEMORY_AREA MArea,
|
PMEMORY_AREA MArea,
|
||||||
PVOID Address,
|
PVOID Address,
|
||||||
PMM_PAGEOP PageOp
|
PFN_NUMBER Page
|
||||||
);
|
);
|
||||||
|
|
||||||
/* kmap.c ********************************************************************/
|
/* kmap.c ********************************************************************/
|
||||||
|
@ -1007,38 +969,6 @@ PVOID
|
||||||
FASTCALL
|
FASTCALL
|
||||||
MmSafeReadPtr(PVOID Source);
|
MmSafeReadPtr(PVOID Source);
|
||||||
|
|
||||||
/* pageop.c ******************************************************************/
|
|
||||||
|
|
||||||
VOID
|
|
||||||
NTAPI
|
|
||||||
MmReleasePageOp(PMM_PAGEOP PageOp);
|
|
||||||
|
|
||||||
PMM_PAGEOP
|
|
||||||
NTAPI
|
|
||||||
MmGetPageOp(
|
|
||||||
PMEMORY_AREA MArea,
|
|
||||||
HANDLE Pid,
|
|
||||||
PVOID Address,
|
|
||||||
PMM_SECTION_SEGMENT Segment,
|
|
||||||
ULONGLONG Offset,
|
|
||||||
ULONG OpType,
|
|
||||||
BOOLEAN First
|
|
||||||
);
|
|
||||||
|
|
||||||
PMM_PAGEOP
|
|
||||||
NTAPI
|
|
||||||
MmCheckForPageOp(
|
|
||||||
PMEMORY_AREA MArea,
|
|
||||||
HANDLE Pid,
|
|
||||||
PVOID Address,
|
|
||||||
PMM_SECTION_SEGMENT Segment,
|
|
||||||
ULONGLONG Offset
|
|
||||||
);
|
|
||||||
|
|
||||||
VOID
|
|
||||||
NTAPI
|
|
||||||
MmInitializePageOp(VOID);
|
|
||||||
|
|
||||||
/* process.c *****************************************************************/
|
/* process.c *****************************************************************/
|
||||||
|
|
||||||
PVOID
|
PVOID
|
||||||
|
@ -1657,7 +1587,7 @@ MmPageOutSectionView(
|
||||||
PMMSUPPORT AddressSpace,
|
PMMSUPPORT AddressSpace,
|
||||||
PMEMORY_AREA MemoryArea,
|
PMEMORY_AREA MemoryArea,
|
||||||
PVOID Address,
|
PVOID Address,
|
||||||
struct _MM_PAGEOP *PageOp
|
ULONG_PTR Entry
|
||||||
);
|
);
|
||||||
|
|
||||||
NTSTATUS
|
NTSTATUS
|
||||||
|
|
|
@ -419,7 +419,6 @@ MmInitSystem(IN ULONG Phase,
|
||||||
MiInitializeUserPfnBitmap();
|
MiInitializeUserPfnBitmap();
|
||||||
MmInitializeMemoryConsumer(MC_USER, MmTrimUserMemory);
|
MmInitializeMemoryConsumer(MC_USER, MmTrimUserMemory);
|
||||||
MmInitializeRmapList();
|
MmInitializeRmapList();
|
||||||
MmInitializePageOp();
|
|
||||||
MmInitSectionImplementation();
|
MmInitSectionImplementation();
|
||||||
MmInitPagingFile();
|
MmInitPagingFile();
|
||||||
|
|
||||||
|
|
|
@ -52,7 +52,6 @@ MmPageOutPhysicalAddress(PFN_NUMBER Page)
|
||||||
ULONG Type;
|
ULONG Type;
|
||||||
PVOID Address;
|
PVOID Address;
|
||||||
PEPROCESS Process;
|
PEPROCESS Process;
|
||||||
PMM_PAGEOP PageOp;
|
|
||||||
ULONGLONG Offset;
|
ULONGLONG Offset;
|
||||||
NTSTATUS Status = STATUS_SUCCESS;
|
NTSTATUS Status = STATUS_SUCCESS;
|
||||||
|
|
||||||
|
@ -126,17 +125,20 @@ MmPageOutPhysicalAddress(PFN_NUMBER Page)
|
||||||
Type = MemoryArea->Type;
|
Type = MemoryArea->Type;
|
||||||
if (Type == MEMORY_AREA_SECTION_VIEW)
|
if (Type == MEMORY_AREA_SECTION_VIEW)
|
||||||
{
|
{
|
||||||
|
ULONG Entry;
|
||||||
Offset = MemoryArea->Data.SectionData.ViewOffset.QuadPart +
|
Offset = MemoryArea->Data.SectionData.ViewOffset.QuadPart +
|
||||||
((ULONG_PTR)Address - (ULONG_PTR)MemoryArea->StartingAddress);
|
((ULONG_PTR)Address - (ULONG_PTR)MemoryArea->StartingAddress);
|
||||||
|
|
||||||
|
MmLockSectionSegment(MemoryArea->Data.SectionData.Segment);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Get or create a pageop
|
* Get or create a pageop
|
||||||
*/
|
*/
|
||||||
PageOp = MmGetPageOp(MemoryArea, NULL, 0,
|
Entry = MmGetPageEntrySectionSegment
|
||||||
MemoryArea->Data.SectionData.Segment,
|
(MemoryArea->Data.SectionData.Segment, (PLARGE_INTEGER)&Offset);
|
||||||
Offset, MM_PAGEOP_PAGEOUT, TRUE);
|
if (Entry && IS_SWAP_FROM_SSE(Entry) && SWAPENTRY_FROM_SSE(Entry) == MM_WAIT_ENTRY)
|
||||||
if (PageOp == NULL)
|
|
||||||
{
|
{
|
||||||
|
MmUnlockSectionSegment(MemoryArea->Data.SectionData.Segment);
|
||||||
MmUnlockAddressSpace(AddressSpace);
|
MmUnlockAddressSpace(AddressSpace);
|
||||||
if (Address < MmSystemRangeStart)
|
if (Address < MmSystemRangeStart)
|
||||||
{
|
{
|
||||||
|
@ -146,16 +148,18 @@ MmPageOutPhysicalAddress(PFN_NUMBER Page)
|
||||||
return(STATUS_UNSUCCESSFUL);
|
return(STATUS_UNSUCCESSFUL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
MmSetPageEntrySectionSegment(MemoryArea->Data.SectionData.Segment, (PLARGE_INTEGER)&Offset, MAKE_SWAP_SSE(MM_WAIT_ENTRY));
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Release locks now we have a page op.
|
* Release locks now we have a page op.
|
||||||
*/
|
*/
|
||||||
|
MmUnlockSectionSegment(MemoryArea->Data.SectionData.Segment);
|
||||||
MmUnlockAddressSpace(AddressSpace);
|
MmUnlockAddressSpace(AddressSpace);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Do the actual page out work.
|
* Do the actual page out work.
|
||||||
*/
|
*/
|
||||||
Status = MmPageOutSectionView(AddressSpace, MemoryArea,
|
Status = MmPageOutSectionView(AddressSpace, MemoryArea, Address, Entry);
|
||||||
Address, PageOp);
|
|
||||||
}
|
}
|
||||||
else if (Type == MEMORY_AREA_CACHE)
|
else if (Type == MEMORY_AREA_CACHE)
|
||||||
{
|
{
|
||||||
|
|
|
@ -127,6 +127,7 @@ typedef struct
|
||||||
BOOLEAN WasDirty;
|
BOOLEAN WasDirty;
|
||||||
BOOLEAN Private;
|
BOOLEAN Private;
|
||||||
PEPROCESS CallingProcess;
|
PEPROCESS CallingProcess;
|
||||||
|
ULONG_PTR SectionEntry;
|
||||||
}
|
}
|
||||||
MM_SECTION_PAGEOUT_CONTEXT;
|
MM_SECTION_PAGEOUT_CONTEXT;
|
||||||
|
|
||||||
|
@ -704,43 +705,6 @@ l_Return:
|
||||||
return nStatus;
|
return nStatus;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Note: Mmsp prefix denotes "Memory Manager Section Private". */
|
|
||||||
|
|
||||||
/*
|
|
||||||
* FUNCTION: Waits in kernel mode up to ten seconds for an MM_PAGEOP event.
|
|
||||||
* ARGUMENTS: PMM_PAGEOP which event we should wait for.
|
|
||||||
* RETURNS: Status of the wait.
|
|
||||||
*/
|
|
||||||
static NTSTATUS
|
|
||||||
MmspWaitForPageOpCompletionEvent(PMM_PAGEOP PageOp)
|
|
||||||
{
|
|
||||||
LARGE_INTEGER Timeout;
|
|
||||||
#ifdef __GNUC__ /* TODO: Use other macro to check for suffix to use? */
|
|
||||||
|
|
||||||
Timeout.QuadPart = -100000000LL; // 10 sec
|
|
||||||
#else
|
|
||||||
|
|
||||||
Timeout.QuadPart = -100000000; // 10 sec
|
|
||||||
#endif
|
|
||||||
|
|
||||||
return KeWaitForSingleObject(&PageOp->CompletionEvent, 0, KernelMode, FALSE, &Timeout);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* FUNCTION: Sets the page op completion event and releases the page op.
|
|
||||||
* ARGUMENTS: PMM_PAGEOP.
|
|
||||||
* RETURNS: In shorter time than it takes you to even read this
|
|
||||||
* description, so don't even think about geting a mug of coffee.
|
|
||||||
*/
|
|
||||||
static void
|
|
||||||
MmspCompleteAndReleasePageOp(PMM_PAGEOP PageOp)
|
|
||||||
{
|
|
||||||
KeSetEvent(&PageOp->CompletionEvent, IO_NO_INCREMENT, FALSE);
|
|
||||||
MmReleasePageOp(PageOp);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* FUNCTION: Waits in kernel mode indefinitely for a file object lock.
|
* FUNCTION: Waits in kernel mode indefinitely for a file object lock.
|
||||||
* ARGUMENTS: PFILE_OBJECT to wait for.
|
* ARGUMENTS: PFILE_OBJECT to wait for.
|
||||||
|
@ -831,12 +795,12 @@ MmUnsharePageEntrySectionSegment(PROS_SECTION_OBJECT Section,
|
||||||
PMM_SECTION_SEGMENT Segment,
|
PMM_SECTION_SEGMENT Segment,
|
||||||
PLARGE_INTEGER Offset,
|
PLARGE_INTEGER Offset,
|
||||||
BOOLEAN Dirty,
|
BOOLEAN Dirty,
|
||||||
BOOLEAN PageOut)
|
BOOLEAN PageOut,
|
||||||
|
ULONG_PTR *InEntry)
|
||||||
{
|
{
|
||||||
ULONG_PTR Entry;
|
ULONG_PTR Entry = InEntry ? *InEntry : MmGetPageEntrySectionSegment(Segment, Offset);
|
||||||
BOOLEAN IsDirectMapped = FALSE;
|
BOOLEAN IsDirectMapped = FALSE;
|
||||||
|
|
||||||
Entry = MmGetPageEntrySectionSegment(Segment, Offset);
|
|
||||||
if (Entry == 0)
|
if (Entry == 0)
|
||||||
{
|
{
|
||||||
DPRINT1("Entry == 0 for MmUnsharePageEntrySectionSegment\n");
|
DPRINT1("Entry == 0 for MmUnsharePageEntrySectionSegment\n");
|
||||||
|
@ -844,7 +808,7 @@ MmUnsharePageEntrySectionSegment(PROS_SECTION_OBJECT Section,
|
||||||
}
|
}
|
||||||
if (SHARE_COUNT_FROM_SSE(Entry) == 0)
|
if (SHARE_COUNT_FROM_SSE(Entry) == 0)
|
||||||
{
|
{
|
||||||
DPRINT1("Zero share count for unshare\n");
|
DPRINT1("Zero share count for unshare (Seg %p Offset %x Page %x)\n", Segment, Offset->LowPart, PFN_FROM_SSE(Entry));
|
||||||
KeBugCheck(MEMORY_MANAGEMENT);
|
KeBugCheck(MEMORY_MANAGEMENT);
|
||||||
}
|
}
|
||||||
if (IS_SWAP_FROM_SSE(Entry))
|
if (IS_SWAP_FROM_SSE(Entry))
|
||||||
|
@ -913,10 +877,14 @@ MmUnsharePageEntrySectionSegment(PROS_SECTION_OBJECT Section,
|
||||||
* page without a rmap entry.
|
* page without a rmap entry.
|
||||||
*/
|
*/
|
||||||
MmSetPageEntrySectionSegment(Segment, Offset, Entry);
|
MmSetPageEntrySectionSegment(Segment, Offset, Entry);
|
||||||
|
if (InEntry) *InEntry = Entry;
|
||||||
|
MiSetPageEvent(NULL, NULL);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
MmSetPageEntrySectionSegment(Segment, Offset, 0);
|
MmSetPageEntrySectionSegment(Segment, Offset, 0);
|
||||||
|
if (InEntry) *InEntry = 0;
|
||||||
|
MiSetPageEvent(NULL, NULL);
|
||||||
if (!IsDirectMapped)
|
if (!IsDirectMapped)
|
||||||
{
|
{
|
||||||
MmReleasePageMemoryConsumer(MC_USER, Page);
|
MmReleasePageMemoryConsumer(MC_USER, Page);
|
||||||
|
@ -946,7 +914,9 @@ MmUnsharePageEntrySectionSegment(PROS_SECTION_OBJECT Section,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
MmSetPageEntrySectionSegment(Segment, Offset, MAKE_SWAP_SSE(SavedSwapEntry));
|
MmSetPageEntrySectionSegment(Segment, Offset, MAKE_SWAP_SSE(SavedSwapEntry));
|
||||||
|
if (InEntry) *InEntry = MAKE_SWAP_SSE(SavedSwapEntry);
|
||||||
MmSetSavedSwapEntryPage(Page, 0);
|
MmSetSavedSwapEntryPage(Page, 0);
|
||||||
|
MiSetPageEvent(NULL, NULL);
|
||||||
}
|
}
|
||||||
MmReleasePageMemoryConsumer(MC_USER, Page);
|
MmReleasePageMemoryConsumer(MC_USER, Page);
|
||||||
}
|
}
|
||||||
|
@ -959,6 +929,9 @@ MmUnsharePageEntrySectionSegment(PROS_SECTION_OBJECT Section,
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
if (InEntry)
|
||||||
|
*InEntry = Entry;
|
||||||
|
else
|
||||||
MmSetPageEntrySectionSegment(Segment, Offset, Entry);
|
MmSetPageEntrySectionSegment(Segment, Offset, Entry);
|
||||||
}
|
}
|
||||||
return(SHARE_COUNT_FROM_SSE(Entry) > 0);
|
return(SHARE_COUNT_FROM_SSE(Entry) > 0);
|
||||||
|
@ -1232,7 +1205,6 @@ MmNotPresentFaultSectionView(PMMSUPPORT AddressSpace,
|
||||||
ULONG_PTR Entry;
|
ULONG_PTR Entry;
|
||||||
ULONG_PTR Entry1;
|
ULONG_PTR Entry1;
|
||||||
ULONG Attributes;
|
ULONG Attributes;
|
||||||
PMM_PAGEOP PageOp;
|
|
||||||
PMM_REGION Region;
|
PMM_REGION Region;
|
||||||
BOOLEAN HasSwapEntry;
|
BOOLEAN HasSwapEntry;
|
||||||
PVOID PAddress;
|
PVOID PAddress;
|
||||||
|
@ -1270,7 +1242,7 @@ MmNotPresentFaultSectionView(PMMSUPPORT AddressSpace,
|
||||||
* Lock the segment
|
* Lock the segment
|
||||||
*/
|
*/
|
||||||
MmLockSectionSegment(Segment);
|
MmLockSectionSegment(Segment);
|
||||||
|
Entry = MmGetPageEntrySectionSegment(Segment, &Offset);
|
||||||
/*
|
/*
|
||||||
* Check if this page needs to be mapped COW
|
* Check if this page needs to be mapped COW
|
||||||
*/
|
*/
|
||||||
|
@ -1285,112 +1257,42 @@ MmNotPresentFaultSectionView(PMMSUPPORT AddressSpace,
|
||||||
Attributes = Region->Protect;
|
Attributes = Region->Protect;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* Get or create a page operation descriptor
|
|
||||||
*/
|
|
||||||
PageOp = MmGetPageOp(MemoryArea, NULL, 0, Segment, Offset.LowPart, MM_PAGEOP_PAGEIN, FALSE);
|
|
||||||
if (PageOp == NULL)
|
|
||||||
{
|
|
||||||
DPRINT1("MmGetPageOp failed\n");
|
|
||||||
KeBugCheck(MEMORY_MANAGEMENT);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Check if someone else is already handling this fault, if so wait
|
* Check if someone else is already handling this fault, if so wait
|
||||||
* for them
|
* for them
|
||||||
*/
|
*/
|
||||||
if (PageOp->Thread != PsGetCurrentThread())
|
if (Entry && IS_SWAP_FROM_SSE(Entry) && SWAPENTRY_FROM_SSE(Entry) == MM_WAIT_ENTRY)
|
||||||
{
|
{
|
||||||
MmUnlockSectionSegment(Segment);
|
MmUnlockSectionSegment(Segment);
|
||||||
MmUnlockAddressSpace(AddressSpace);
|
MmUnlockAddressSpace(AddressSpace);
|
||||||
Status = MmspWaitForPageOpCompletionEvent(PageOp);
|
MiWaitForPageEvent(NULL, NULL);
|
||||||
/*
|
|
||||||
* Check for various strange conditions
|
|
||||||
*/
|
|
||||||
if (Status != STATUS_SUCCESS)
|
|
||||||
{
|
|
||||||
DPRINT1("Failed to wait for page op, status = %x\n", Status);
|
|
||||||
KeBugCheck(MEMORY_MANAGEMENT);
|
|
||||||
}
|
|
||||||
if (PageOp->Status == STATUS_PENDING)
|
|
||||||
{
|
|
||||||
DPRINT1("Woke for page op before completion\n");
|
|
||||||
KeBugCheck(MEMORY_MANAGEMENT);
|
|
||||||
}
|
|
||||||
MmLockAddressSpace(AddressSpace);
|
MmLockAddressSpace(AddressSpace);
|
||||||
/*
|
|
||||||
* If this wasn't a pagein then restart the operation
|
|
||||||
*/
|
|
||||||
if (PageOp->OpType != MM_PAGEOP_PAGEIN)
|
|
||||||
{
|
|
||||||
MmspCompleteAndReleasePageOp(PageOp);
|
|
||||||
DPRINT("Address 0x%.8X\n", Address);
|
DPRINT("Address 0x%.8X\n", Address);
|
||||||
return(STATUS_MM_RESTART_OPERATION);
|
return(STATUS_MM_RESTART_OPERATION);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* If the thread handling this fault has failed then we don't retry
|
|
||||||
*/
|
|
||||||
if (!NT_SUCCESS(PageOp->Status))
|
|
||||||
{
|
|
||||||
Status = PageOp->Status;
|
|
||||||
MmspCompleteAndReleasePageOp(PageOp);
|
|
||||||
DPRINT("Address 0x%.8X\n", Address);
|
|
||||||
return(Status);
|
|
||||||
}
|
|
||||||
MmLockSectionSegment(Segment);
|
|
||||||
/*
|
|
||||||
* If the completed fault was for another address space then set the
|
|
||||||
* page in this one.
|
|
||||||
*/
|
|
||||||
if (!MmIsPagePresent(Process, Address))
|
|
||||||
{
|
|
||||||
Entry = MmGetPageEntrySectionSegment(Segment, &Offset);
|
|
||||||
HasSwapEntry = MmIsPageSwapEntry(Process, (PVOID)PAddress);
|
|
||||||
|
|
||||||
if (PAGE_FROM_SSE(Entry) == 0 || HasSwapEntry)
|
|
||||||
{
|
|
||||||
/*
|
|
||||||
* The page was a private page in another or in our address space
|
|
||||||
*/
|
|
||||||
MmUnlockSectionSegment(Segment);
|
|
||||||
MmspCompleteAndReleasePageOp(PageOp);
|
|
||||||
return(STATUS_MM_RESTART_OPERATION);
|
|
||||||
}
|
|
||||||
|
|
||||||
Page = PFN_FROM_SSE(Entry);
|
|
||||||
|
|
||||||
MmSharePageEntrySectionSegment(Segment, &Offset);
|
|
||||||
|
|
||||||
/* FIXME: Should we call MmCreateVirtualMappingUnsafe if
|
|
||||||
* (Section->AllocationAttributes & SEC_PHYSICALMEMORY) is true?
|
|
||||||
*/
|
|
||||||
Status = MmCreateVirtualMapping(Process,
|
|
||||||
PAddress,
|
|
||||||
Attributes,
|
|
||||||
&Page,
|
|
||||||
1);
|
|
||||||
if (!NT_SUCCESS(Status))
|
|
||||||
{
|
|
||||||
DPRINT1("Unable to create virtual mapping\n");
|
|
||||||
KeBugCheck(MEMORY_MANAGEMENT);
|
|
||||||
}
|
|
||||||
MmInsertRmap(Page, Process, Address);
|
|
||||||
}
|
|
||||||
MmUnlockSectionSegment(Segment);
|
|
||||||
PageOp->Status = STATUS_SUCCESS;
|
|
||||||
MmspCompleteAndReleasePageOp(PageOp);
|
|
||||||
DPRINT("Address 0x%.8X\n", Address);
|
|
||||||
return(STATUS_SUCCESS);
|
|
||||||
}
|
|
||||||
|
|
||||||
HasSwapEntry = MmIsPageSwapEntry(Process, Address);
|
HasSwapEntry = MmIsPageSwapEntry(Process, Address);
|
||||||
|
|
||||||
if (HasSwapEntry)
|
if (HasSwapEntry)
|
||||||
{
|
{
|
||||||
|
SWAPENTRY SwapEntry;
|
||||||
|
/*
|
||||||
|
* Is it a wait entry?
|
||||||
|
*/
|
||||||
|
MmGetPageFileMapping(Process, Address, &SwapEntry);
|
||||||
|
|
||||||
|
if (SwapEntry == MM_WAIT_ENTRY)
|
||||||
|
{
|
||||||
|
MmUnlockSectionSegment(Segment);
|
||||||
|
MmUnlockAddressSpace(AddressSpace);
|
||||||
|
MiWaitForPageEvent(NULL, NULL);
|
||||||
|
MmLockAddressSpace(AddressSpace);
|
||||||
|
return STATUS_MM_RESTART_OPERATION;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Must be private page we have swapped out.
|
* Must be private page we have swapped out.
|
||||||
*/
|
*/
|
||||||
SWAPENTRY SwapEntry;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Sanity check
|
* Sanity check
|
||||||
|
@ -1445,8 +1347,7 @@ MmNotPresentFaultSectionView(PMMSUPPORT AddressSpace,
|
||||||
/*
|
/*
|
||||||
* Finish the operation
|
* Finish the operation
|
||||||
*/
|
*/
|
||||||
PageOp->Status = STATUS_SUCCESS;
|
MiSetPageEvent(Process, Address);
|
||||||
MmspCompleteAndReleasePageOp(PageOp);
|
|
||||||
DPRINT("Address 0x%.8X\n", Address);
|
DPRINT("Address 0x%.8X\n", Address);
|
||||||
return(STATUS_SUCCESS);
|
return(STATUS_SUCCESS);
|
||||||
}
|
}
|
||||||
|
@ -1476,8 +1377,7 @@ MmNotPresentFaultSectionView(PMMSUPPORT AddressSpace,
|
||||||
/*
|
/*
|
||||||
* Cleanup and release locks
|
* Cleanup and release locks
|
||||||
*/
|
*/
|
||||||
PageOp->Status = STATUS_SUCCESS;
|
MiSetPageEvent(Process, Address);
|
||||||
MmspCompleteAndReleasePageOp(PageOp);
|
|
||||||
DPRINT("Address 0x%.8X\n", Address);
|
DPRINT("Address 0x%.8X\n", Address);
|
||||||
return(STATUS_SUCCESS);
|
return(STATUS_SUCCESS);
|
||||||
}
|
}
|
||||||
|
@ -1518,8 +1418,7 @@ MmNotPresentFaultSectionView(PMMSUPPORT AddressSpace,
|
||||||
/*
|
/*
|
||||||
* Cleanup and release locks
|
* Cleanup and release locks
|
||||||
*/
|
*/
|
||||||
PageOp->Status = STATUS_SUCCESS;
|
MiSetPageEvent(Process, Address);
|
||||||
MmspCompleteAndReleasePageOp(PageOp);
|
|
||||||
DPRINT("Address 0x%.8X\n", Address);
|
DPRINT("Address 0x%.8X\n", Address);
|
||||||
return(STATUS_SUCCESS);
|
return(STATUS_SUCCESS);
|
||||||
}
|
}
|
||||||
|
@ -1539,6 +1438,7 @@ MmNotPresentFaultSectionView(PMMSUPPORT AddressSpace,
|
||||||
/*
|
/*
|
||||||
* Release all our locks and read in the page from disk
|
* Release all our locks and read in the page from disk
|
||||||
*/
|
*/
|
||||||
|
MmSetPageEntrySectionSegment(Segment, &Offset, MAKE_SWAP_SSE(MM_WAIT_ENTRY));
|
||||||
MmUnlockSectionSegment(Segment);
|
MmUnlockSectionSegment(Segment);
|
||||||
MmUnlockAddressSpace(AddressSpace);
|
MmUnlockAddressSpace(AddressSpace);
|
||||||
|
|
||||||
|
@ -1573,32 +1473,17 @@ MmNotPresentFaultSectionView(PMMSUPPORT AddressSpace,
|
||||||
* Cleanup and release locks
|
* Cleanup and release locks
|
||||||
*/
|
*/
|
||||||
MmLockAddressSpace(AddressSpace);
|
MmLockAddressSpace(AddressSpace);
|
||||||
PageOp->Status = Status;
|
MiSetPageEvent(Process, Address);
|
||||||
MmspCompleteAndReleasePageOp(PageOp);
|
|
||||||
DPRINT("Address 0x%.8X\n", Address);
|
DPRINT("Address 0x%.8X\n", Address);
|
||||||
return(Status);
|
return(Status);
|
||||||
}
|
}
|
||||||
/*
|
|
||||||
* Relock the address space and segment
|
|
||||||
*/
|
|
||||||
MmLockAddressSpace(AddressSpace);
|
|
||||||
MmLockSectionSegment(Segment);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Check the entry. No one should change the status of a page
|
|
||||||
* that has a pending page-in.
|
|
||||||
*/
|
|
||||||
Entry1 = MmGetPageEntrySectionSegment(Segment, &Offset);
|
|
||||||
if (Entry != Entry1)
|
|
||||||
{
|
|
||||||
DPRINT1("Someone changed ppte entry while we slept\n");
|
|
||||||
KeBugCheck(MEMORY_MANAGEMENT);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Mark the offset within the section as having valid, in-memory
|
* Mark the offset within the section as having valid, in-memory
|
||||||
* data
|
* data
|
||||||
*/
|
*/
|
||||||
|
MmLockAddressSpace(AddressSpace);
|
||||||
|
MmLockSectionSegment(Segment);
|
||||||
Entry = MAKE_SSE(Page << PAGE_SHIFT, 1);
|
Entry = MAKE_SSE(Page << PAGE_SHIFT, 1);
|
||||||
MmSetPageEntrySectionSegment(Segment, &Offset, Entry);
|
MmSetPageEntrySectionSegment(Segment, &Offset, Entry);
|
||||||
MmUnlockSectionSegment(Segment);
|
MmUnlockSectionSegment(Segment);
|
||||||
|
@ -1615,8 +1500,7 @@ MmNotPresentFaultSectionView(PMMSUPPORT AddressSpace,
|
||||||
}
|
}
|
||||||
MmInsertRmap(Page, Process, Address);
|
MmInsertRmap(Page, Process, Address);
|
||||||
|
|
||||||
PageOp->Status = STATUS_SUCCESS;
|
MiSetPageEvent(Process, Address);
|
||||||
MmspCompleteAndReleasePageOp(PageOp);
|
|
||||||
DPRINT("Address 0x%.8X\n", Address);
|
DPRINT("Address 0x%.8X\n", Address);
|
||||||
return(STATUS_SUCCESS);
|
return(STATUS_SUCCESS);
|
||||||
}
|
}
|
||||||
|
@ -1660,7 +1544,7 @@ MmNotPresentFaultSectionView(PMMSUPPORT AddressSpace,
|
||||||
Entry1 = MmGetPageEntrySectionSegment(Segment, &Offset);
|
Entry1 = MmGetPageEntrySectionSegment(Segment, &Offset);
|
||||||
if (Entry != Entry1)
|
if (Entry != Entry1)
|
||||||
{
|
{
|
||||||
DPRINT1("Someone changed ppte entry while we slept\n");
|
DPRINT1("Someone changed ppte entry while we slept (%x vs %x)\n", Entry, Entry1);
|
||||||
KeBugCheck(MEMORY_MANAGEMENT);
|
KeBugCheck(MEMORY_MANAGEMENT);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1687,8 +1571,7 @@ MmNotPresentFaultSectionView(PMMSUPPORT AddressSpace,
|
||||||
KeBugCheck(MEMORY_MANAGEMENT);
|
KeBugCheck(MEMORY_MANAGEMENT);
|
||||||
}
|
}
|
||||||
MmInsertRmap(Page, Process, Address);
|
MmInsertRmap(Page, Process, Address);
|
||||||
PageOp->Status = STATUS_SUCCESS;
|
MiSetPageEvent(Process, Address);
|
||||||
MmspCompleteAndReleasePageOp(PageOp);
|
|
||||||
DPRINT("Address 0x%.8X\n", Address);
|
DPRINT("Address 0x%.8X\n", Address);
|
||||||
return(STATUS_SUCCESS);
|
return(STATUS_SUCCESS);
|
||||||
}
|
}
|
||||||
|
@ -1715,8 +1598,7 @@ MmNotPresentFaultSectionView(PMMSUPPORT AddressSpace,
|
||||||
KeBugCheck(MEMORY_MANAGEMENT);
|
KeBugCheck(MEMORY_MANAGEMENT);
|
||||||
}
|
}
|
||||||
MmInsertRmap(Page, Process, Address);
|
MmInsertRmap(Page, Process, Address);
|
||||||
PageOp->Status = STATUS_SUCCESS;
|
MiSetPageEvent(Process, Address);
|
||||||
MmspCompleteAndReleasePageOp(PageOp);
|
|
||||||
DPRINT("Address 0x%.8X\n", Address);
|
DPRINT("Address 0x%.8X\n", Address);
|
||||||
return(STATUS_SUCCESS);
|
return(STATUS_SUCCESS);
|
||||||
}
|
}
|
||||||
|
@ -1735,7 +1617,6 @@ MmAccessFaultSectionView(PMMSUPPORT AddressSpace,
|
||||||
NTSTATUS Status;
|
NTSTATUS Status;
|
||||||
PVOID PAddress;
|
PVOID PAddress;
|
||||||
LARGE_INTEGER Offset;
|
LARGE_INTEGER Offset;
|
||||||
PMM_PAGEOP PageOp;
|
|
||||||
PMM_REGION Region;
|
PMM_REGION Region;
|
||||||
ULONG_PTR Entry;
|
ULONG_PTR Entry;
|
||||||
PEPROCESS Process = MmGetAddressSpaceOwner(AddressSpace);
|
PEPROCESS Process = MmGetAddressSpaceOwner(AddressSpace);
|
||||||
|
@ -1799,39 +1680,21 @@ MmAccessFaultSectionView(PMMSUPPORT AddressSpace,
|
||||||
/*
|
/*
|
||||||
* Get or create a pageop
|
* Get or create a pageop
|
||||||
*/
|
*/
|
||||||
PageOp = MmGetPageOp(MemoryArea, NULL, 0, Segment, Offset.LowPart,
|
MmLockSectionSegment(Segment);
|
||||||
MM_PAGEOP_ACCESSFAULT, FALSE);
|
Entry = MmGetPageEntrySectionSegment(Segment, &Offset);
|
||||||
if (PageOp == NULL)
|
|
||||||
{
|
|
||||||
DPRINT1("MmGetPageOp failed\n");
|
|
||||||
KeBugCheck(MEMORY_MANAGEMENT);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Wait for any other operations to complete
|
* Wait for any other operations to complete
|
||||||
*/
|
*/
|
||||||
if (PageOp->Thread != PsGetCurrentThread())
|
if (Entry == SWAPENTRY_FROM_SSE(MM_WAIT_ENTRY))
|
||||||
{
|
{
|
||||||
|
MmUnlockSectionSegment(Segment);
|
||||||
MmUnlockAddressSpace(AddressSpace);
|
MmUnlockAddressSpace(AddressSpace);
|
||||||
Status = MmspWaitForPageOpCompletionEvent(PageOp);
|
MiWaitForPageEvent(NULL, NULL);
|
||||||
/*
|
|
||||||
* Check for various strange conditions
|
|
||||||
*/
|
|
||||||
if (Status == STATUS_TIMEOUT)
|
|
||||||
{
|
|
||||||
DPRINT1("Failed to wait for page op, status = %x\n", Status);
|
|
||||||
KeBugCheck(MEMORY_MANAGEMENT);
|
|
||||||
}
|
|
||||||
if (PageOp->Status == STATUS_PENDING)
|
|
||||||
{
|
|
||||||
DPRINT1("Woke for page op before completion\n");
|
|
||||||
KeBugCheck(MEMORY_MANAGEMENT);
|
|
||||||
}
|
|
||||||
/*
|
/*
|
||||||
* Restart the operation
|
* Restart the operation
|
||||||
*/
|
*/
|
||||||
MmLockAddressSpace(AddressSpace);
|
MmLockAddressSpace(AddressSpace);
|
||||||
MmspCompleteAndReleasePageOp(PageOp);
|
|
||||||
DPRINT("Address 0x%.8X\n", Address);
|
DPRINT("Address 0x%.8X\n", Address);
|
||||||
return(STATUS_MM_RESTART_OPERATION);
|
return(STATUS_MM_RESTART_OPERATION);
|
||||||
}
|
}
|
||||||
|
@ -1839,6 +1702,7 @@ MmAccessFaultSectionView(PMMSUPPORT AddressSpace,
|
||||||
/*
|
/*
|
||||||
* Release locks now we have the pageop
|
* Release locks now we have the pageop
|
||||||
*/
|
*/
|
||||||
|
MmUnlockSectionSegment(Segment);
|
||||||
MmUnlockAddressSpace(AddressSpace);
|
MmUnlockAddressSpace(AddressSpace);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -1890,11 +1754,10 @@ MmAccessFaultSectionView(PMMSUPPORT AddressSpace,
|
||||||
MmDeleteRmap(OldPage, Process, PAddress);
|
MmDeleteRmap(OldPage, Process, PAddress);
|
||||||
MmInsertRmap(NewPage, Process, PAddress);
|
MmInsertRmap(NewPage, Process, PAddress);
|
||||||
MmLockSectionSegment(Segment);
|
MmLockSectionSegment(Segment);
|
||||||
MmUnsharePageEntrySectionSegment(Section, Segment, &Offset, FALSE, FALSE);
|
MmUnsharePageEntrySectionSegment(Section, Segment, &Offset, FALSE, FALSE, NULL);
|
||||||
MmUnlockSectionSegment(Segment);
|
MmUnlockSectionSegment(Segment);
|
||||||
|
|
||||||
PageOp->Status = STATUS_SUCCESS;
|
MiSetPageEvent(Process, Address);
|
||||||
MmspCompleteAndReleasePageOp(PageOp);
|
|
||||||
DPRINT("Address 0x%.8X\n", Address);
|
DPRINT("Address 0x%.8X\n", Address);
|
||||||
return(STATUS_SUCCESS);
|
return(STATUS_SUCCESS);
|
||||||
}
|
}
|
||||||
|
@ -1904,7 +1767,7 @@ MmPageOutDeleteMapping(PVOID Context, PEPROCESS Process, PVOID Address)
|
||||||
{
|
{
|
||||||
MM_SECTION_PAGEOUT_CONTEXT* PageOutContext;
|
MM_SECTION_PAGEOUT_CONTEXT* PageOutContext;
|
||||||
BOOLEAN WasDirty;
|
BOOLEAN WasDirty;
|
||||||
PFN_NUMBER Page;
|
PFN_NUMBER Page = 0;
|
||||||
|
|
||||||
PageOutContext = (MM_SECTION_PAGEOUT_CONTEXT*)Context;
|
PageOutContext = (MM_SECTION_PAGEOUT_CONTEXT*)Context;
|
||||||
if (Process)
|
if (Process)
|
||||||
|
@ -1928,7 +1791,8 @@ MmPageOutDeleteMapping(PVOID Context, PEPROCESS Process, PVOID Address)
|
||||||
PageOutContext->Segment,
|
PageOutContext->Segment,
|
||||||
&PageOutContext->Offset,
|
&PageOutContext->Offset,
|
||||||
PageOutContext->WasDirty,
|
PageOutContext->WasDirty,
|
||||||
TRUE);
|
TRUE,
|
||||||
|
&PageOutContext->SectionEntry);
|
||||||
MmUnlockSectionSegment(PageOutContext->Segment);
|
MmUnlockSectionSegment(PageOutContext->Segment);
|
||||||
}
|
}
|
||||||
if (Process)
|
if (Process)
|
||||||
|
@ -1940,21 +1804,17 @@ MmPageOutDeleteMapping(PVOID Context, PEPROCESS Process, PVOID Address)
|
||||||
{
|
{
|
||||||
MmReleasePageMemoryConsumer(MC_USER, Page);
|
MmReleasePageMemoryConsumer(MC_USER, Page);
|
||||||
}
|
}
|
||||||
|
|
||||||
DPRINT("PhysicalAddress %x, Address %x\n", Page << PAGE_SHIFT, Address);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
NTSTATUS
|
NTSTATUS
|
||||||
NTAPI
|
NTAPI
|
||||||
MmPageOutSectionView(PMMSUPPORT AddressSpace,
|
MmPageOutSectionView(PMMSUPPORT AddressSpace,
|
||||||
MEMORY_AREA* MemoryArea,
|
MEMORY_AREA* MemoryArea,
|
||||||
PVOID Address,
|
PVOID Address, ULONG_PTR Entry)
|
||||||
PMM_PAGEOP PageOp)
|
|
||||||
{
|
{
|
||||||
PFN_NUMBER Page;
|
PFN_NUMBER Page;
|
||||||
MM_SECTION_PAGEOUT_CONTEXT Context;
|
MM_SECTION_PAGEOUT_CONTEXT Context;
|
||||||
SWAPENTRY SwapEntry;
|
SWAPENTRY SwapEntry;
|
||||||
ULONG_PTR Entry;
|
|
||||||
ULONGLONG FileOffset;
|
ULONGLONG FileOffset;
|
||||||
NTSTATUS Status;
|
NTSTATUS Status;
|
||||||
PFILE_OBJECT FileObject;
|
PFILE_OBJECT FileObject;
|
||||||
|
@ -1973,6 +1833,7 @@ MmPageOutSectionView(PMMSUPPORT AddressSpace,
|
||||||
*/
|
*/
|
||||||
Context.Segment = MemoryArea->Data.SectionData.Segment;
|
Context.Segment = MemoryArea->Data.SectionData.Segment;
|
||||||
Context.Section = MemoryArea->Data.SectionData.Section;
|
Context.Section = MemoryArea->Data.SectionData.Section;
|
||||||
|
Context.SectionEntry = Entry;
|
||||||
Context.CallingProcess = Process;
|
Context.CallingProcess = Process;
|
||||||
|
|
||||||
Context.Offset.QuadPart = (ULONG_PTR)Address - (ULONG_PTR)MemoryArea->StartingAddress
|
Context.Offset.QuadPart = (ULONG_PTR)Address - (ULONG_PTR)MemoryArea->StartingAddress
|
||||||
|
@ -1984,6 +1845,8 @@ MmPageOutSectionView(PMMSUPPORT AddressSpace,
|
||||||
FileObject = Context.Section->FileObject;
|
FileObject = Context.Section->FileObject;
|
||||||
DirectMapped = FALSE;
|
DirectMapped = FALSE;
|
||||||
|
|
||||||
|
MmLockSectionSegment(Context.Segment);
|
||||||
|
|
||||||
#ifndef NEWCC
|
#ifndef NEWCC
|
||||||
if (FileObject != NULL &&
|
if (FileObject != NULL &&
|
||||||
!(Context.Segment->Image.Characteristics & IMAGE_SCN_MEM_SHARED))
|
!(Context.Segment->Image.Characteristics & IMAGE_SCN_MEM_SHARED))
|
||||||
|
@ -2035,16 +1898,14 @@ MmPageOutSectionView(PMMSUPPORT AddressSpace,
|
||||||
{
|
{
|
||||||
DPRINT("Cannot page out locked section page: 0x%p (RefCount: %d)\n",
|
DPRINT("Cannot page out locked section page: 0x%p (RefCount: %d)\n",
|
||||||
Page, MmGetReferenceCountPage(Page));
|
Page, MmGetReferenceCountPage(Page));
|
||||||
PageOp->Status = STATUS_UNSUCCESSFUL;
|
MmSetPageEntrySectionSegment(Context.Segment, &Context.Offset, Entry);
|
||||||
MmspCompleteAndReleasePageOp(PageOp);
|
MmUnlockSectionSegment(Context.Segment);
|
||||||
return STATUS_UNSUCCESSFUL;
|
return STATUS_UNSUCCESSFUL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Prepare the context structure for the rmap delete call.
|
* Prepare the context structure for the rmap delete call.
|
||||||
*/
|
*/
|
||||||
MmLockSectionSegment(Context.Segment);
|
|
||||||
Entry = MmGetPageEntrySectionSegment(Context.Segment, &Context.Offset);
|
|
||||||
MmUnlockSectionSegment(Context.Segment);
|
MmUnlockSectionSegment(Context.Segment);
|
||||||
Context.WasDirty = FALSE;
|
Context.WasDirty = FALSE;
|
||||||
if (Context.Segment->Image.Characteristics & IMAGE_SCN_CNT_UNINITIALIZED_DATA ||
|
if (Context.Segment->Image.Characteristics & IMAGE_SCN_CNT_UNINITIALIZED_DATA ||
|
||||||
|
@ -2077,9 +1938,12 @@ MmPageOutSectionView(PMMSUPPORT AddressSpace,
|
||||||
}
|
}
|
||||||
|
|
||||||
MmDeleteAllRmaps(Page, (PVOID)&Context, MmPageOutDeleteMapping);
|
MmDeleteAllRmaps(Page, (PVOID)&Context, MmPageOutDeleteMapping);
|
||||||
MmLockSectionSegment(Context.Segment);
|
|
||||||
Entry = MmGetPageEntrySectionSegment(Context.Segment, &Context.Offset);
|
/* Since we passed in a surrogate, we'll get back the page entry
|
||||||
MmUnlockSectionSegment(Context.Segment);
|
* state in our context. This is intended to make intermediate
|
||||||
|
* decrements of share count not release the wait entry.
|
||||||
|
*/
|
||||||
|
Entry = Context.SectionEntry;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If this wasn't a private page then we should have reduced the entry to
|
* If this wasn't a private page then we should have reduced the entry to
|
||||||
|
@ -2117,8 +1981,7 @@ MmPageOutSectionView(PMMSUPPORT AddressSpace,
|
||||||
MmSetPageEntrySectionSegment(Context.Segment, &Context.Offset, MAKE_SWAP_SSE(SwapEntry));
|
MmSetPageEntrySectionSegment(Context.Segment, &Context.Offset, MAKE_SWAP_SSE(SwapEntry));
|
||||||
MmUnlockSectionSegment(Context.Segment);
|
MmUnlockSectionSegment(Context.Segment);
|
||||||
MmReleasePageMemoryConsumer(MC_USER, Page);
|
MmReleasePageMemoryConsumer(MC_USER, Page);
|
||||||
PageOp->Status = STATUS_SUCCESS;
|
MiSetPageEvent(NULL, NULL);
|
||||||
MmspCompleteAndReleasePageOp(PageOp);
|
|
||||||
return(STATUS_SUCCESS);
|
return(STATUS_SUCCESS);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2140,8 +2003,7 @@ MmPageOutSectionView(PMMSUPPORT AddressSpace,
|
||||||
MmUnlockSectionSegment(Context.Segment);
|
MmUnlockSectionSegment(Context.Segment);
|
||||||
}
|
}
|
||||||
MmReleasePageMemoryConsumer(MC_USER, Page);
|
MmReleasePageMemoryConsumer(MC_USER, Page);
|
||||||
PageOp->Status = STATUS_SUCCESS;
|
MiSetPageEvent(NULL, NULL);
|
||||||
MmspCompleteAndReleasePageOp(PageOp);
|
|
||||||
return(STATUS_SUCCESS);
|
return(STATUS_SUCCESS);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2165,8 +2027,7 @@ MmPageOutSectionView(PMMSUPPORT AddressSpace,
|
||||||
KeBugCheckEx(MEMORY_MANAGEMENT, Status, (ULONG_PTR)Bcb, (ULONG_PTR)FileOffset, (ULONG_PTR)Address);
|
KeBugCheckEx(MEMORY_MANAGEMENT, Status, (ULONG_PTR)Bcb, (ULONG_PTR)FileOffset, (ULONG_PTR)Address);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
PageOp->Status = STATUS_SUCCESS;
|
MiSetPageEvent(NULL, NULL);
|
||||||
MmspCompleteAndReleasePageOp(PageOp);
|
|
||||||
return(STATUS_SUCCESS);
|
return(STATUS_SUCCESS);
|
||||||
}
|
}
|
||||||
else if (!Context.WasDirty && !DirectMapped && !Context.Private)
|
else if (!Context.WasDirty && !DirectMapped && !Context.Private)
|
||||||
|
@ -2178,13 +2039,12 @@ MmPageOutSectionView(PMMSUPPORT AddressSpace,
|
||||||
KeBugCheckEx(MEMORY_MANAGEMENT, SwapEntry, Page, (ULONG_PTR)Process, (ULONG_PTR)Address);
|
KeBugCheckEx(MEMORY_MANAGEMENT, SwapEntry, Page, (ULONG_PTR)Process, (ULONG_PTR)Address);
|
||||||
}
|
}
|
||||||
MmReleasePageMemoryConsumer(MC_USER, Page);
|
MmReleasePageMemoryConsumer(MC_USER, Page);
|
||||||
PageOp->Status = STATUS_SUCCESS;
|
MiSetPageEvent(NULL, NULL);
|
||||||
MmspCompleteAndReleasePageOp(PageOp);
|
|
||||||
return(STATUS_SUCCESS);
|
return(STATUS_SUCCESS);
|
||||||
}
|
}
|
||||||
else if (!Context.WasDirty && Context.Private && SwapEntry != 0)
|
else if (!Context.WasDirty && Context.Private && SwapEntry != 0)
|
||||||
{
|
{
|
||||||
DPRINT1("Not dirty and private and not swapped (%p:%p)\n", Process, Address);
|
DPRINT("Not dirty and private and not swapped (%p:%p)\n", Process, Address);
|
||||||
MmSetSavedSwapEntryPage(Page, 0);
|
MmSetSavedSwapEntryPage(Page, 0);
|
||||||
MmLockAddressSpace(AddressSpace);
|
MmLockAddressSpace(AddressSpace);
|
||||||
Status = MmCreatePageFileMapping(Process,
|
Status = MmCreatePageFileMapping(Process,
|
||||||
|
@ -2197,8 +2057,7 @@ MmPageOutSectionView(PMMSUPPORT AddressSpace,
|
||||||
KeBugCheckEx(MEMORY_MANAGEMENT, Status, (ULONG_PTR)Process, (ULONG_PTR)Address, SwapEntry);
|
KeBugCheckEx(MEMORY_MANAGEMENT, Status, (ULONG_PTR)Process, (ULONG_PTR)Address, SwapEntry);
|
||||||
}
|
}
|
||||||
MmReleasePageMemoryConsumer(MC_USER, Page);
|
MmReleasePageMemoryConsumer(MC_USER, Page);
|
||||||
PageOp->Status = STATUS_SUCCESS;
|
MiSetPageEvent(NULL, NULL);
|
||||||
MmspCompleteAndReleasePageOp(PageOp);
|
|
||||||
return(STATUS_SUCCESS);
|
return(STATUS_SUCCESS);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2253,8 +2112,7 @@ MmPageOutSectionView(PMMSUPPORT AddressSpace,
|
||||||
MmUnlockSectionSegment(Context.Segment);
|
MmUnlockSectionSegment(Context.Segment);
|
||||||
}
|
}
|
||||||
MmUnlockAddressSpace(AddressSpace);
|
MmUnlockAddressSpace(AddressSpace);
|
||||||
PageOp->Status = STATUS_UNSUCCESSFUL;
|
MiSetPageEvent(NULL, NULL);
|
||||||
MmspCompleteAndReleasePageOp(PageOp);
|
|
||||||
return(STATUS_PAGEFILE_QUOTA);
|
return(STATUS_PAGEFILE_QUOTA);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2299,8 +2157,7 @@ MmPageOutSectionView(PMMSUPPORT AddressSpace,
|
||||||
MmSetPageEntrySectionSegment(Context.Segment, &Context.Offset, Entry);
|
MmSetPageEntrySectionSegment(Context.Segment, &Context.Offset, Entry);
|
||||||
}
|
}
|
||||||
MmUnlockAddressSpace(AddressSpace);
|
MmUnlockAddressSpace(AddressSpace);
|
||||||
PageOp->Status = STATUS_UNSUCCESSFUL;
|
MiSetPageEvent(NULL, NULL);
|
||||||
MmspCompleteAndReleasePageOp(PageOp);
|
|
||||||
return(STATUS_UNSUCCESSFUL);
|
return(STATUS_UNSUCCESSFUL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2308,12 +2165,13 @@ MmPageOutSectionView(PMMSUPPORT AddressSpace,
|
||||||
* Otherwise we have succeeded.
|
* Otherwise we have succeeded.
|
||||||
*/
|
*/
|
||||||
DPRINT("MM: Wrote section page 0x%.8X to swap!\n", Page << PAGE_SHIFT);
|
DPRINT("MM: Wrote section page 0x%.8X to swap!\n", Page << PAGE_SHIFT);
|
||||||
MmLockSectionSegment(Context.Segment);
|
|
||||||
MmSetSavedSwapEntryPage(Page, 0);
|
MmSetSavedSwapEntryPage(Page, 0);
|
||||||
if (Context.Segment->Flags & MM_PAGEFILE_SEGMENT ||
|
if (Context.Segment->Flags & MM_PAGEFILE_SEGMENT ||
|
||||||
Context.Segment->Image.Characteristics & IMAGE_SCN_MEM_SHARED)
|
Context.Segment->Image.Characteristics & IMAGE_SCN_MEM_SHARED)
|
||||||
{
|
{
|
||||||
|
MmLockSectionSegment(Context.Segment);
|
||||||
MmSetPageEntrySectionSegment(Context.Segment, &Context.Offset, MAKE_SWAP_SSE(SwapEntry));
|
MmSetPageEntrySectionSegment(Context.Segment, &Context.Offset, MAKE_SWAP_SSE(SwapEntry));
|
||||||
|
MmUnlockSectionSegment(Context.Segment);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -2323,9 +2181,11 @@ MmPageOutSectionView(PMMSUPPORT AddressSpace,
|
||||||
if (Context.Private)
|
if (Context.Private)
|
||||||
{
|
{
|
||||||
MmLockAddressSpace(AddressSpace);
|
MmLockAddressSpace(AddressSpace);
|
||||||
|
MmLockSectionSegment(Context.Segment);
|
||||||
Status = MmCreatePageFileMapping(Process,
|
Status = MmCreatePageFileMapping(Process,
|
||||||
Address,
|
Address,
|
||||||
SwapEntry);
|
SwapEntry);
|
||||||
|
MmUnlockSectionSegment(Context.Segment);
|
||||||
MmUnlockAddressSpace(AddressSpace);
|
MmUnlockAddressSpace(AddressSpace);
|
||||||
if (!NT_SUCCESS(Status))
|
if (!NT_SUCCESS(Status))
|
||||||
{
|
{
|
||||||
|
@ -2335,13 +2195,15 @@ MmPageOutSectionView(PMMSUPPORT AddressSpace,
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
MmLockAddressSpace(AddressSpace);
|
||||||
|
MmLockSectionSegment(Context.Segment);
|
||||||
Entry = MAKE_SWAP_SSE(SwapEntry);
|
Entry = MAKE_SWAP_SSE(SwapEntry);
|
||||||
MmSetPageEntrySectionSegment(Context.Segment, &Context.Offset, Entry);
|
MmSetPageEntrySectionSegment(Context.Segment, &Context.Offset, Entry);
|
||||||
|
MmUnlockSectionSegment(Context.Segment);
|
||||||
|
MmUnlockAddressSpace(AddressSpace);
|
||||||
}
|
}
|
||||||
|
|
||||||
MmUnlockSectionSegment(Context.Segment);
|
MiSetPageEvent(NULL, NULL);
|
||||||
PageOp->Status = STATUS_SUCCESS;
|
|
||||||
MmspCompleteAndReleasePageOp(PageOp);
|
|
||||||
return(STATUS_SUCCESS);
|
return(STATUS_SUCCESS);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2350,7 +2212,7 @@ NTAPI
|
||||||
MmWritePageSectionView(PMMSUPPORT AddressSpace,
|
MmWritePageSectionView(PMMSUPPORT AddressSpace,
|
||||||
PMEMORY_AREA MemoryArea,
|
PMEMORY_AREA MemoryArea,
|
||||||
PVOID Address,
|
PVOID Address,
|
||||||
PMM_PAGEOP PageOp)
|
ULONG PageEntry)
|
||||||
{
|
{
|
||||||
LARGE_INTEGER Offset;
|
LARGE_INTEGER Offset;
|
||||||
PROS_SECTION_OBJECT Section;
|
PROS_SECTION_OBJECT Section;
|
||||||
|
@ -2447,12 +2309,16 @@ MmWritePageSectionView(PMMSUPPORT AddressSpace,
|
||||||
*/
|
*/
|
||||||
if (DirectMapped && !Private)
|
if (DirectMapped && !Private)
|
||||||
{
|
{
|
||||||
|
LARGE_INTEGER SOffset;
|
||||||
ASSERT(SwapEntry == 0);
|
ASSERT(SwapEntry == 0);
|
||||||
|
SOffset.QuadPart = Offset.QuadPart + Segment->Image.FileOffset;
|
||||||
#ifndef NEWCC
|
#ifndef NEWCC
|
||||||
CcRosMarkDirtyCacheSegment(Bcb, (ULONG)(Offset.QuadPart + Segment->Image.FileOffset));
|
CcRosMarkDirtyCacheSegment(Bcb, Offset.LowPart);
|
||||||
#endif
|
#endif
|
||||||
PageOp->Status = STATUS_SUCCESS;
|
MmLockSectionSegment(Segment);
|
||||||
MmspCompleteAndReleasePageOp(PageOp);
|
MmSetPageEntrySectionSegment(Segment, &Offset, PageEntry);
|
||||||
|
MmUnlockSectionSegment(Segment);
|
||||||
|
MiSetPageEvent(NULL, NULL);
|
||||||
return(STATUS_SUCCESS);
|
return(STATUS_SUCCESS);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2465,8 +2331,7 @@ MmWritePageSectionView(PMMSUPPORT AddressSpace,
|
||||||
if (SwapEntry == 0)
|
if (SwapEntry == 0)
|
||||||
{
|
{
|
||||||
MmSetDirtyAllRmaps(Page);
|
MmSetDirtyAllRmaps(Page);
|
||||||
PageOp->Status = STATUS_UNSUCCESSFUL;
|
MiSetPageEvent(NULL, NULL);
|
||||||
MmspCompleteAndReleasePageOp(PageOp);
|
|
||||||
return(STATUS_PAGEFILE_QUOTA);
|
return(STATUS_PAGEFILE_QUOTA);
|
||||||
}
|
}
|
||||||
MmSetSavedSwapEntryPage(Page, SwapEntry);
|
MmSetSavedSwapEntryPage(Page, SwapEntry);
|
||||||
|
@ -2481,8 +2346,7 @@ MmWritePageSectionView(PMMSUPPORT AddressSpace,
|
||||||
DPRINT1("MM: Failed to write to swap page (Status was 0x%.8X)\n",
|
DPRINT1("MM: Failed to write to swap page (Status was 0x%.8X)\n",
|
||||||
Status);
|
Status);
|
||||||
MmSetDirtyAllRmaps(Page);
|
MmSetDirtyAllRmaps(Page);
|
||||||
PageOp->Status = STATUS_UNSUCCESSFUL;
|
MiSetPageEvent(NULL, NULL);
|
||||||
MmspCompleteAndReleasePageOp(PageOp);
|
|
||||||
return(STATUS_UNSUCCESSFUL);
|
return(STATUS_UNSUCCESSFUL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2490,8 +2354,7 @@ MmWritePageSectionView(PMMSUPPORT AddressSpace,
|
||||||
* Otherwise we have succeeded.
|
* Otherwise we have succeeded.
|
||||||
*/
|
*/
|
||||||
DPRINT("MM: Wrote section page 0x%.8X to swap!\n", Page << PAGE_SHIFT);
|
DPRINT("MM: Wrote section page 0x%.8X to swap!\n", Page << PAGE_SHIFT);
|
||||||
PageOp->Status = STATUS_SUCCESS;
|
MiSetPageEvent(NULL, NULL);
|
||||||
MmspCompleteAndReleasePageOp(PageOp);
|
|
||||||
return(STATUS_SUCCESS);
|
return(STATUS_SUCCESS);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4039,8 +3902,6 @@ MmFreeSectionPage(PVOID Context, MEMORY_AREA* MemoryArea, PVOID Address,
|
||||||
PBCB Bcb;
|
PBCB Bcb;
|
||||||
LARGE_INTEGER Offset;
|
LARGE_INTEGER Offset;
|
||||||
SWAPENTRY SavedSwapEntry;
|
SWAPENTRY SavedSwapEntry;
|
||||||
PMM_PAGEOP PageOp;
|
|
||||||
NTSTATUS Status;
|
|
||||||
PROS_SECTION_OBJECT Section;
|
PROS_SECTION_OBJECT Section;
|
||||||
PMM_SECTION_SEGMENT Segment;
|
PMM_SECTION_SEGMENT Segment;
|
||||||
PMMSUPPORT AddressSpace;
|
PMMSUPPORT AddressSpace;
|
||||||
|
@ -4057,27 +3918,18 @@ MmFreeSectionPage(PVOID Context, MEMORY_AREA* MemoryArea, PVOID Address,
|
||||||
Section = MemoryArea->Data.SectionData.Section;
|
Section = MemoryArea->Data.SectionData.Section;
|
||||||
Segment = MemoryArea->Data.SectionData.Segment;
|
Segment = MemoryArea->Data.SectionData.Segment;
|
||||||
|
|
||||||
PageOp = MmCheckForPageOp(MemoryArea, NULL, NULL, Segment, Offset.LowPart);
|
Entry = MmGetPageEntrySectionSegment(Segment, &Offset);
|
||||||
|
while (Entry && IS_SWAP_FROM_SSE(Entry) && SWAPENTRY_FROM_SSE(Entry) == MM_WAIT_ENTRY)
|
||||||
while (PageOp)
|
|
||||||
{
|
{
|
||||||
MmUnlockSectionSegment(Segment);
|
MmUnlockSectionSegment(Segment);
|
||||||
MmUnlockAddressSpace(AddressSpace);
|
MmUnlockAddressSpace(AddressSpace);
|
||||||
|
|
||||||
Status = MmspWaitForPageOpCompletionEvent(PageOp);
|
MiWaitForPageEvent(NULL, NULL);
|
||||||
if (Status != STATUS_SUCCESS)
|
|
||||||
{
|
|
||||||
DPRINT1("Failed to wait for page op, status = %x\n", Status);
|
|
||||||
KeBugCheck(MEMORY_MANAGEMENT);
|
|
||||||
}
|
|
||||||
|
|
||||||
MmLockAddressSpace(AddressSpace);
|
MmLockAddressSpace(AddressSpace);
|
||||||
MmLockSectionSegment(Segment);
|
MmLockSectionSegment(Segment);
|
||||||
MmspCompleteAndReleasePageOp(PageOp);
|
|
||||||
PageOp = MmCheckForPageOp(MemoryArea, NULL, NULL, Segment, Offset.LowPart);
|
|
||||||
}
|
|
||||||
|
|
||||||
Entry = MmGetPageEntrySectionSegment(Segment, &Offset);
|
Entry = MmGetPageEntrySectionSegment(Segment, &Offset);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* For a dirty, datafile, non-private page mark it as dirty in the
|
* For a dirty, datafile, non-private page mark it as dirty in the
|
||||||
|
@ -4136,7 +3988,7 @@ MmFreeSectionPage(PVOID Context, MEMORY_AREA* MemoryArea, PVOID Address,
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
MmDeleteRmap(Page, Process, Address);
|
MmDeleteRmap(Page, Process, Address);
|
||||||
MmUnsharePageEntrySectionSegment(Section, Segment, &Offset, Dirty, FALSE);
|
MmUnsharePageEntrySectionSegment(Section, Segment, &Offset, Dirty, FALSE, NULL);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4208,8 +4060,6 @@ MiRosUnmapViewOfSection(IN PEPROCESS Process,
|
||||||
PMEMORY_AREA MemoryArea;
|
PMEMORY_AREA MemoryArea;
|
||||||
PMMSUPPORT AddressSpace;
|
PMMSUPPORT AddressSpace;
|
||||||
PROS_SECTION_OBJECT Section;
|
PROS_SECTION_OBJECT Section;
|
||||||
PMM_PAGEOP PageOp;
|
|
||||||
ULONG_PTR Offset;
|
|
||||||
PVOID ImageBaseAddress = 0;
|
PVOID ImageBaseAddress = 0;
|
||||||
|
|
||||||
DPRINT("Opening memory area Process %x BaseAddress %x\n",
|
DPRINT("Opening memory area Process %x BaseAddress %x\n",
|
||||||
|
@ -4233,40 +4083,6 @@ MiRosUnmapViewOfSection(IN PEPROCESS Process,
|
||||||
|
|
||||||
MemoryArea->DeleteInProgress = TRUE;
|
MemoryArea->DeleteInProgress = TRUE;
|
||||||
|
|
||||||
while (MemoryArea->PageOpCount)
|
|
||||||
{
|
|
||||||
Offset = PAGE_ROUND_UP((ULONG_PTR)MemoryArea->EndingAddress - (ULONG_PTR)MemoryArea->StartingAddress);
|
|
||||||
|
|
||||||
while (Offset)
|
|
||||||
{
|
|
||||||
Offset -= PAGE_SIZE;
|
|
||||||
PageOp = MmCheckForPageOp(MemoryArea, NULL, NULL,
|
|
||||||
MemoryArea->Data.SectionData.Segment,
|
|
||||||
Offset + MemoryArea->Data.SectionData.ViewOffset.QuadPart);
|
|
||||||
if (PageOp)
|
|
||||||
{
|
|
||||||
MmUnlockAddressSpace(AddressSpace);
|
|
||||||
Status = MmspWaitForPageOpCompletionEvent(PageOp);
|
|
||||||
if (Status != STATUS_SUCCESS)
|
|
||||||
{
|
|
||||||
DPRINT1("Failed to wait for page op, status = %x\n", Status);
|
|
||||||
KeBugCheck(MEMORY_MANAGEMENT);
|
|
||||||
}
|
|
||||||
MmLockAddressSpace(AddressSpace);
|
|
||||||
MmspCompleteAndReleasePageOp(PageOp);
|
|
||||||
MemoryArea = MmLocateMemoryAreaByAddress(AddressSpace,
|
|
||||||
BaseAddress);
|
|
||||||
if (MemoryArea == NULL ||
|
|
||||||
MemoryArea->Type != MEMORY_AREA_SECTION_VIEW)
|
|
||||||
{
|
|
||||||
MmUnlockAddressSpace(AddressSpace);
|
|
||||||
return STATUS_NOT_MAPPED_VIEW;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Section = MemoryArea->Data.SectionData.Section;
|
Section = MemoryArea->Data.SectionData.Section;
|
||||||
|
|
||||||
if (Section->AllocationAttributes & SEC_IMAGE)
|
if (Section->AllocationAttributes & SEC_IMAGE)
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue