[FORMATTING]

* Improve indentation, remove trailing spaces, apply a consistent style, adjust to 80 col... No code changes.

svn path=/trunk/; revision=56262
This commit is contained in:
Amine Khaldi 2012-03-28 18:39:21 +00:00
parent a13075fb0e
commit 5491e8fbde
7 changed files with 2260 additions and 2040 deletions

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -64,19 +64,18 @@ MmGetDeviceObjectForFile(IN PFILE_OBJECT FileObject)
return IoGetRelatedDeviceObject(FileObject);
}
// Note:
// This completion function is really required. Paging io completion does almost
// nothing, including freeing the mdls.
/* Note:
This completion function is really required. Paging io completion does almost
nothing, including freeing the mdls. */
NTSTATUS
NTAPI
MiSimpleReadComplete
(PDEVICE_OBJECT DeviceObject,
PIRP Irp,
PVOID Context)
MiSimpleReadComplete(PDEVICE_OBJECT DeviceObject,
PIRP Irp,
PVOID Context)
{
PMDL Mdl = Irp->MdlAddress;
/* Unlock MDL Pages, page 167. */
/* Unlock MDL Pages, page 167. */
DPRINT("MiSimpleReadComplete %p\n", Irp);
while (Mdl)
{
@ -98,13 +97,12 @@ MiSimpleReadComplete
NTSTATUS
NTAPI
MiSimpleRead
(PFILE_OBJECT FileObject,
PLARGE_INTEGER FileOffset,
PVOID Buffer,
ULONG Length,
BOOLEAN Paging,
PIO_STATUS_BLOCK ReadStatus)
MiSimpleRead(PFILE_OBJECT FileObject,
PLARGE_INTEGER FileOffset,
PVOID Buffer,
ULONG Length,
BOOLEAN Paging,
PIO_STATUS_BLOCK ReadStatus)
{
NTSTATUS Status;
PIRP Irp = NULL;
@ -118,32 +116,30 @@ MiSimpleRead
ASSERT(ReadStatus);
DeviceObject = MmGetDeviceObjectForFile(FileObject);
ReadStatus->Status = STATUS_INTERNAL_ERROR;
ReadStatus->Information = 0;
ReadStatus->Status = STATUS_INTERNAL_ERROR;
ReadStatus->Information = 0;
ASSERT(DeviceObject);
DPRINT
("PAGING READ: FileObject %p <%wZ> Offset %08x%08x Length %d\n",
FileObject,
&FileObject->FileName,
FileOffset->HighPart,
FileOffset->LowPart,
Length);
DPRINT("PAGING READ: FileObject %p <%wZ> Offset %08x%08x Length %d\n",
FileObject,
&FileObject->FileName,
FileOffset->HighPart,
FileOffset->LowPart,
Length);
KeInitializeEvent(&ReadWait, NotificationEvent, FALSE);
Irp = IoBuildAsynchronousFsdRequest
(IRP_MJ_READ,
DeviceObject,
Buffer,
Length,
FileOffset,
ReadStatus);
Irp = IoBuildAsynchronousFsdRequest(IRP_MJ_READ,
DeviceObject,
Buffer,
Length,
FileOffset,
ReadStatus);
if (!Irp)
{
return STATUS_NO_MEMORY;
return STATUS_NO_MEMORY;
}
Irp->Flags |= (Paging ? IRP_PAGING_IO | IRP_SYNCHRONOUS_PAGING_IO | IRP_NOCACHE : 0) | IRP_SYNCHRONOUS_API;
@ -152,49 +148,44 @@ MiSimpleRead
Irp->Tail.Overlay.OriginalFileObject = FileObject;
Irp->Tail.Overlay.Thread = PsGetCurrentThread();
IrpSp = IoGetNextIrpStackLocation(Irp);
IrpSp->Control |= SL_INVOKE_ON_SUCCESS | SL_INVOKE_ON_ERROR;
IrpSp->Control |= SL_INVOKE_ON_SUCCESS | SL_INVOKE_ON_ERROR;
IrpSp->FileObject = FileObject;
IrpSp->CompletionRoutine = MiSimpleReadComplete;
// Non paging case, the FileObject will be dereferenced at completion
/* Non paging case, the FileObject will be dereferenced at completion */
if (!Paging)
ObReferenceObject(FileObject);
Status = IoCallDriver(DeviceObject, Irp);
if (Status == STATUS_PENDING)
{
DPRINT("KeWaitForSingleObject(&ReadWait)\n");
if (!NT_SUCCESS
(KeWaitForSingleObject
(&ReadWait,
Suspended,
KernelMode,
FALSE,
NULL)))
{
DPRINT1("Warning: Failed to wait for synchronous IRP\n");
ASSERT(FALSE);
return Status;
}
DPRINT("KeWaitForSingleObject(&ReadWait)\n");
if (!NT_SUCCESS(KeWaitForSingleObject(&ReadWait,
Suspended,
KernelMode,
FALSE,
NULL)))
{
DPRINT1("Warning: Failed to wait for synchronous IRP\n");
ASSERT(FALSE);
return Status;
}
}
DPRINT("Paging IO Done: %08x\n", ReadStatus->Status);
Status =
ReadStatus->Status == STATUS_END_OF_FILE ?
STATUS_SUCCESS : ReadStatus->Status;
Status = ReadStatus->Status == STATUS_END_OF_FILE ? STATUS_SUCCESS : ReadStatus->Status;
return Status;
}
NTSTATUS
NTAPI
_MiSimpleWrite
(PFILE_OBJECT FileObject,
PLARGE_INTEGER FileOffset,
PVOID Buffer,
ULONG Length,
PIO_STATUS_BLOCK ReadStatus,
const char *File,
int Line)
_MiSimpleWrite(PFILE_OBJECT FileObject,
PLARGE_INTEGER FileOffset,
PVOID Buffer,
ULONG Length,
PIO_STATUS_BLOCK ReadStatus,
const char *File,
int Line)
{
NTSTATUS Status;
PIRP Irp = NULL;
@ -207,31 +198,29 @@ _MiSimpleWrite
ASSERT(Buffer);
ASSERT(ReadStatus);
DeviceObject = MmGetDeviceObjectForFile(FileObject);
DeviceObject = MmGetDeviceObjectForFile(FileObject);
ASSERT(DeviceObject);
DPRINT
("PAGING WRITE: FileObject %x <%wZ> Offset %x Length %d (%s:%d)\n",
FileObject,
&FileObject->FileName,
FileOffset->LowPart,
Length,
File,
Line);
DPRINT("PAGING WRITE: FileObject %x <%wZ> Offset %x Length %d (%s:%d)\n",
FileObject,
&FileObject->FileName,
FileOffset->LowPart,
Length,
File,
Line);
KeInitializeEvent(&ReadWait, NotificationEvent, FALSE);
Irp = IoBuildAsynchronousFsdRequest
(IRP_MJ_WRITE,
DeviceObject,
Buffer,
Length,
FileOffset,
ReadStatus);
Irp = IoBuildAsynchronousFsdRequest(IRP_MJ_WRITE,
DeviceObject,
Buffer,
Length,
FileOffset,
ReadStatus);
if (!Irp)
{
return STATUS_NO_MEMORY;
return STATUS_NO_MEMORY;
}
Irp->Flags = IRP_PAGING_IO | IRP_SYNCHRONOUS_PAGING_IO | IRP_NOCACHE | IRP_SYNCHRONOUS_API;
@ -240,29 +229,27 @@ _MiSimpleWrite
Irp->Tail.Overlay.OriginalFileObject = FileObject;
Irp->Tail.Overlay.Thread = PsGetCurrentThread();
IrpSp = IoGetNextIrpStackLocation(Irp);
IrpSp->Control |= SL_INVOKE_ON_SUCCESS | SL_INVOKE_ON_ERROR;
IrpSp->Control |= SL_INVOKE_ON_SUCCESS | SL_INVOKE_ON_ERROR;
IrpSp->FileObject = FileObject;
IrpSp->CompletionRoutine = MiSimpleReadComplete;
DPRINT("Call Driver\n");
DPRINT("Call Driver\n");
Status = IoCallDriver(DeviceObject, Irp);
DPRINT("Status %x\n", Status);
DPRINT("Status %x\n", Status);
if (Status == STATUS_PENDING)
{
DPRINT("KeWaitForSingleObject(&ReadWait)\n");
if (!NT_SUCCESS
(KeWaitForSingleObject
(&ReadWait,
Suspended,
KernelMode,
FALSE,
NULL)))
{
DPRINT1("Warning: Failed to wait for synchronous IRP\n");
ASSERT(FALSE);
return Status;
}
DPRINT("KeWaitForSingleObject(&ReadWait)\n");
if (!NT_SUCCESS(KeWaitForSingleObject(&ReadWait,
Suspended,
KernelMode,
FALSE,
NULL)))
{
DPRINT1("Warning: Failed to wait for synchronous IRP\n");
ASSERT(FALSE);
return Status;
}
}
DPRINT("Paging IO Done: %08x\n", ReadStatus->Status);
@ -274,45 +261,49 @@ FAST_MUTEX MiWriteMutex;
NTSTATUS
NTAPI
_MiWriteBackPage
(PFILE_OBJECT FileObject,
PLARGE_INTEGER FileOffset,
ULONG Length,
PFN_NUMBER Page,
const char *File,
int Line)
_MiWriteBackPage(PFILE_OBJECT FileObject,
PLARGE_INTEGER FileOffset,
ULONG Length,
PFN_NUMBER Page,
const char *File,
int Line)
{
NTSTATUS Status;
PVOID Hyperspace;
IO_STATUS_BLOCK Iosb;
KIRQL OldIrql;
PVOID PageBuffer = ExAllocatePool(NonPagedPool, PAGE_SIZE);
NTSTATUS Status;
PVOID Hyperspace;
IO_STATUS_BLOCK Iosb;
KIRQL OldIrql;
PVOID PageBuffer = ExAllocatePool(NonPagedPool, PAGE_SIZE);
if (!PageBuffer) return STATUS_NO_MEMORY;
if (!PageBuffer) return STATUS_NO_MEMORY;
Hyperspace = MiMapPageInHyperSpace(PsGetCurrentProcess(), Page, &OldIrql);
Hyperspace = MiMapPageInHyperSpace(PsGetCurrentProcess(), Page, &OldIrql);
if (!Hyperspace)
{
ExFreePool(PageBuffer);
return STATUS_NO_MEMORY;
}
RtlCopyMemory(PageBuffer, Hyperspace, PAGE_SIZE);
MiUnmapPageInHyperSpace(PsGetCurrentProcess(), Hyperspace, OldIrql);
RtlCopyMemory(PageBuffer, Hyperspace, PAGE_SIZE);
MiUnmapPageInHyperSpace(PsGetCurrentProcess(), Hyperspace, OldIrql);
DPRINT("MiWriteBackPage(%wZ,%08x%08x,%s:%d)\n", &FileObject->FileName, FileOffset->u.HighPart, FileOffset->u.LowPart, File, Line);
Status = MiSimpleWrite
(FileObject,
FileOffset,
PageBuffer,
Length,
&Iosb);
DPRINT("MiWriteBackPage(%wZ,%08x%08x,%s:%d)\n",
&FileObject->FileName,
FileOffset->u.HighPart,
FileOffset->u.LowPart,
File,
Line);
ExFreePool(PageBuffer);
Status = MiSimpleWrite(FileObject,
FileOffset,
PageBuffer,
Length,
&Iosb);
if (!NT_SUCCESS(Status))
{
DPRINT1("MiSimpleWrite failed (%x)\n", Status);
}
ExFreePool(PageBuffer);
return Status;
if (!NT_SUCCESS(Status))
{
DPRINT1("MiSimpleWrite failed (%x)\n", Status);
}
return Status;
}

View file

@ -8,7 +8,7 @@
#define PFN_FROM_SSE(E) ((E) >> PAGE_SHIFT)
#define IS_SWAP_FROM_SSE(E) ((E) & 0x00000001)
#define MM_IS_WAIT_PTE(E) \
(IS_SWAP_FROM_SSE(E) && SWAPENTRY_FROM_SSE(E) == MM_WAIT_ENTRY)
(IS_SWAP_FROM_SSE(E) && SWAPENTRY_FROM_SSE(E) == MM_WAIT_ENTRY)
#define MAKE_PFN_SSE(P) ((P) << PAGE_SHIFT)
#define SWAPENTRY_FROM_SSE(E) ((E) >> 1)
#define MAKE_SWAP_SSE(S) (((ULONG)(S) << 1) | 0x1)
@ -27,19 +27,19 @@
/* Determine what's needed to make paged pool fit in this category.
* it seems that something more is required to satisfy arm3. */
#define BALANCER_CAN_EVICT(Consumer) \
(((Consumer) == MC_USER) || \
((Consumer) == MC_CACHE))
(((Consumer) == MC_USER) || \
((Consumer) == MC_CACHE))
#define SEC_CACHE (0x20000000)
#define MiWaitForPageEvent(Process,Address) do { \
DPRINT("MiWaitForPageEvent %x:%x #\n", Process, Address); \
#define MiWaitForPageEvent(Process,Address) do { \
DPRINT("MiWaitForPageEvent %x:%x #\n", Process, Address); \
KeWaitForSingleObject(&MmWaitPageEvent, 0, KernelMode, FALSE, NULL); \
} while(0)
#define MiSetPageEvent(Process,Address) do { \
DPRINT("MiSetPageEvent %x:%x #\n",Process, Address); \
KeSetEvent(&MmWaitPageEvent, IO_NO_INCREMENT, FALSE); \
#define MiSetPageEvent(Process,Address) do { \
DPRINT("MiSetPageEvent %x:%x #\n",Process, Address); \
KeSetEvent(&MmWaitPageEvent, IO_NO_INCREMENT, FALSE); \
} while(0)
/* We store 8 bits of location with a page association */
@ -47,69 +47,72 @@
extern KEVENT MmWaitPageEvent;
typedef struct _CACHE_SECTION_PAGE_TABLE
typedef struct _CACHE_SECTION_PAGE_TABLE
{
LARGE_INTEGER FileOffset;
PMM_SECTION_SEGMENT Segment;
PMM_SECTION_SEGMENT Segment;
ULONG Refcount;
ULONG PageEntries[ENTRIES_PER_ELEMENT];
} CACHE_SECTION_PAGE_TABLE, *PCACHE_SECTION_PAGE_TABLE;
struct _MM_REQUIRED_RESOURCES;
typedef NTSTATUS (NTAPI * AcquireResource)
(PMMSUPPORT AddressSpace,
struct _MEMORY_AREA *MemoryArea,
struct _MM_REQUIRED_RESOURCES *Required);
typedef NTSTATUS (NTAPI * NotPresentFaultHandler)
(PMMSUPPORT AddressSpace,
struct _MEMORY_AREA *MemoryArea,
PVOID Address,
BOOLEAN Locked,
struct _MM_REQUIRED_RESOURCES *Required);
typedef NTSTATUS (NTAPI * FaultHandler)
(PMMSUPPORT AddressSpace,
struct _MEMORY_AREA *MemoryArea,
PVOID Address,
struct _MM_REQUIRED_RESOURCES *Required);
typedef NTSTATUS (NTAPI * AcquireResource)(
PMMSUPPORT AddressSpace,
struct _MEMORY_AREA *MemoryArea,
struct _MM_REQUIRED_RESOURCES *Required);
typedef NTSTATUS (NTAPI * NotPresentFaultHandler)(
PMMSUPPORT AddressSpace,
struct _MEMORY_AREA *MemoryArea,
PVOID Address,
BOOLEAN Locked,
struct _MM_REQUIRED_RESOURCES *Required);
typedef NTSTATUS (NTAPI * FaultHandler)(
PMMSUPPORT AddressSpace,
struct _MEMORY_AREA *MemoryArea,
PVOID Address,
struct _MM_REQUIRED_RESOURCES *Required);
typedef struct _MM_REQUIRED_RESOURCES
{
ULONG Consumer;
ULONG Amount;
ULONG Offset;
ULONG State;
PVOID Context;
LARGE_INTEGER FileOffset;
AcquireResource DoAcquisition;
PFN_NUMBER Page[2];
PVOID Buffer[2];
SWAPENTRY SwapEntry;
const char *File;
int Line;
ULONG Consumer;
ULONG Amount;
ULONG Offset;
ULONG State;
PVOID Context;
LARGE_INTEGER FileOffset;
AcquireResource DoAcquisition;
PFN_NUMBER Page[2];
PVOID Buffer[2];
SWAPENTRY SwapEntry;
const char *File;
int Line;
} MM_REQUIRED_RESOURCES, *PMM_REQUIRED_RESOURCES;
NTSTATUS
NTAPI
MmCreateCacheSection
(PROS_SECTION_OBJECT *SectionObject,
ACCESS_MASK DesiredAccess,
POBJECT_ATTRIBUTES ObjectAttributes,
PLARGE_INTEGER UMaximumSize,
ULONG SectionPageProtection,
ULONG AllocationAttributes,
PFILE_OBJECT FileObject);
MmCreateCacheSection(PROS_SECTION_OBJECT *SectionObject,
ACCESS_MASK DesiredAccess,
POBJECT_ATTRIBUTES ObjectAttributes,
PLARGE_INTEGER UMaximumSize,
ULONG SectionPageProtection,
ULONG AllocationAttributes,
PFILE_OBJECT FileObject);
PFN_NUMBER
NTAPI
MmWithdrawSectionPage
(PMM_SECTION_SEGMENT Segment, PLARGE_INTEGER FileOffset, BOOLEAN *Dirty);
MmWithdrawSectionPage(PMM_SECTION_SEGMENT Segment,
PLARGE_INTEGER FileOffset,
BOOLEAN *Dirty);
NTSTATUS
NTAPI
MmFinalizeSectionPageOut
(PMM_SECTION_SEGMENT Segment, PLARGE_INTEGER FileOffset, PFN_NUMBER Page,
BOOLEAN Dirty);
MmFinalizeSectionPageOut(PMM_SECTION_SEGMENT Segment,
PLARGE_INTEGER FileOffset,
PFN_NUMBER Page,
BOOLEAN Dirty);
/* sptab.c *******************************************************************/
@ -119,36 +122,43 @@ MiInitializeSectionPageTable(PMM_SECTION_SEGMENT Segment);
NTSTATUS
NTAPI
_MmSetPageEntrySectionSegment
(PMM_SECTION_SEGMENT Segment,
PLARGE_INTEGER Offset,
ULONG Entry, const char *file, int line);
_MmSetPageEntrySectionSegment(PMM_SECTION_SEGMENT Segment,
PLARGE_INTEGER Offset,
ULONG Entry,
const char *file,
int line);
ULONG
NTAPI
_MmGetPageEntrySectionSegment
(PMM_SECTION_SEGMENT Segment,
PLARGE_INTEGER Offset, const char *file, int line);
_MmGetPageEntrySectionSegment(PMM_SECTION_SEGMENT Segment,
PLARGE_INTEGER Offset,
const char *file,
int line);
#define MmSetPageEntrySectionSegment(S,O,E) _MmSetPageEntrySectionSegment(S,O,E,__FILE__,__LINE__)
#define MmGetPageEntrySectionSegment(S,O) _MmGetPageEntrySectionSegment(S,O,__FILE__,__LINE__)
typedef VOID (NTAPI *FREE_SECTION_PAGE_FUN)
(PMM_SECTION_SEGMENT Segment,
PLARGE_INTEGER Offset);
typedef VOID (NTAPI *FREE_SECTION_PAGE_FUN)(
PMM_SECTION_SEGMENT Segment,
PLARGE_INTEGER Offset);
VOID
NTAPI
MmFreePageTablesSectionSegment(PMM_SECTION_SEGMENT Segment, FREE_SECTION_PAGE_FUN FreePage);
MmFreePageTablesSectionSegment(PMM_SECTION_SEGMENT Segment,
FREE_SECTION_PAGE_FUN FreePage);
/* Yields a lock */
PMM_SECTION_SEGMENT
NTAPI
MmGetSectionAssociation(PFN_NUMBER Page, PLARGE_INTEGER Offset);
MmGetSectionAssociation(PFN_NUMBER Page,
PLARGE_INTEGER Offset);
NTSTATUS
NTAPI
MmSetSectionAssociation(PFN_NUMBER Page, PMM_SECTION_SEGMENT Segment, PLARGE_INTEGER Offset);
MmSetSectionAssociation(PFN_NUMBER Page,
PMM_SECTION_SEGMENT Segment,
PLARGE_INTEGER Offset);
VOID
NTAPI
@ -165,36 +175,33 @@ MmspWaitForFileLock(PFILE_OBJECT File);
NTSTATUS
NTAPI
MiSimpleRead
(PFILE_OBJECT FileObject,
PLARGE_INTEGER FileOffset,
PVOID Buffer,
ULONG Length,
BOOLEAN Paging,
PIO_STATUS_BLOCK ReadStatus);
MiSimpleRead(PFILE_OBJECT FileObject,
PLARGE_INTEGER FileOffset,
PVOID Buffer,
ULONG Length,
BOOLEAN Paging,
PIO_STATUS_BLOCK ReadStatus);
NTSTATUS
NTAPI
_MiSimpleWrite
(PFILE_OBJECT FileObject,
PLARGE_INTEGER FileOffset,
PVOID Buffer,
ULONG Length,
PIO_STATUS_BLOCK ReadStatus,
const char *file,
int line);
_MiSimpleWrite(PFILE_OBJECT FileObject,
PLARGE_INTEGER FileOffset,
PVOID Buffer,
ULONG Length,
PIO_STATUS_BLOCK ReadStatus,
const char *file,
int line);
#define MiSimpleWrite(F,O,B,L,R) _MiSimpleWrite(F,O,B,L,R,__FILE__,__LINE__)
NTSTATUS
NTAPI
_MiWriteBackPage
(PFILE_OBJECT FileObject,
PLARGE_INTEGER Offset,
ULONG Length,
PFN_NUMBER Page,
const char *File,
int Line);
_MiWriteBackPage(PFILE_OBJECT FileObject,
PLARGE_INTEGER Offset,
ULONG Length,
PFN_NUMBER Page,
const char *File,
int Line);
#define MiWriteBackPage(F,O,L,P) _MiWriteBackPage(F,O,L,P,__FILE__,__LINE__)
@ -202,88 +209,96 @@ _MiWriteBackPage
NTSTATUS
NTAPI
MmAccessFaultCacheSection
(KPROCESSOR_MODE Mode,
ULONG_PTR Address,
BOOLEAN FromMdl);
MmAccessFaultCacheSection(KPROCESSOR_MODE Mode,
ULONG_PTR Address,
BOOLEAN FromMdl);
NTSTATUS
NTAPI
MiReadFilePage
(PMMSUPPORT AddressSpace,
PMEMORY_AREA MemoryArea,
PMM_REQUIRED_RESOURCES RequiredResources);
MiReadFilePage(PMMSUPPORT AddressSpace,
PMEMORY_AREA MemoryArea,
PMM_REQUIRED_RESOURCES RequiredResources);
NTSTATUS
NTAPI
MiGetOnePage
(PMMSUPPORT AddressSpace,
PMEMORY_AREA MemoryArea,
PMM_REQUIRED_RESOURCES RequiredResources);
MiGetOnePage(PMMSUPPORT AddressSpace,
PMEMORY_AREA MemoryArea,
PMM_REQUIRED_RESOURCES RequiredResources);
NTSTATUS
NTAPI
MiSwapInPage
(PMMSUPPORT AddressSpace,
PMEMORY_AREA MemoryArea,
PMM_REQUIRED_RESOURCES RequiredResources);
MiSwapInPage(PMMSUPPORT AddressSpace,
PMEMORY_AREA MemoryArea,
PMM_REQUIRED_RESOURCES RequiredResources);
NTSTATUS
NTAPI
MiWriteSwapPage
(PMMSUPPORT AddressSpace,
PMEMORY_AREA MemoryArea,
PMM_REQUIRED_RESOURCES Resources);
MiWriteSwapPage(PMMSUPPORT AddressSpace,
PMEMORY_AREA MemoryArea,
PMM_REQUIRED_RESOURCES Resources);
NTSTATUS
NTAPI
MiWriteFilePage
(PMMSUPPORT AddressSpace,
PMEMORY_AREA MemoryArea,
PMM_REQUIRED_RESOURCES Resources);
MiWriteFilePage(PMMSUPPORT AddressSpace,
PMEMORY_AREA MemoryArea,
PMM_REQUIRED_RESOURCES Resources);
VOID
NTAPI
MiFreeSegmentPage
(PMM_SECTION_SEGMENT Segment,
PLARGE_INTEGER FileOffset);
MiFreeSegmentPage(PMM_SECTION_SEGMENT Segment,
PLARGE_INTEGER FileOffset);
NTSTATUS
NTAPI
MiCowCacheSectionPage
(PMMSUPPORT AddressSpace,
PMEMORY_AREA MemoryArea,
PVOID Address,
BOOLEAN Locked,
PMM_REQUIRED_RESOURCES Required);
MiCowCacheSectionPage(PMMSUPPORT AddressSpace,
PMEMORY_AREA MemoryArea,
PVOID Address,
BOOLEAN Locked,
PMM_REQUIRED_RESOURCES Required);
NTSTATUS
NTAPI
MiZeroFillSection(PVOID Address, PLARGE_INTEGER FileOffsetPtr, ULONG Length);
MiZeroFillSection(PVOID Address,
PLARGE_INTEGER FileOffsetPtr,
ULONG Length);
VOID
MmPageOutDeleteMapping(PVOID Context, PEPROCESS Process, PVOID Address);
MmPageOutDeleteMapping(PVOID Context,
PEPROCESS Process,
PVOID Address);
VOID
NTAPI
_MmLockSectionSegment(PMM_SECTION_SEGMENT Segment, const char *file, int line);
_MmLockSectionSegment(PMM_SECTION_SEGMENT Segment,
const char *file,
int line);
#define MmLockSectionSegment(x) _MmLockSectionSegment(x,__FILE__,__LINE__)
VOID
NTAPI
_MmUnlockSectionSegment(PMM_SECTION_SEGMENT Segment, const char *file, int line);
_MmUnlockSectionSegment(PMM_SECTION_SEGMENT Segment,
const char *file,
int line);
#define MmUnlockSectionSegment(x) _MmUnlockSectionSegment(x,__FILE__,__LINE__)
VOID
MmFreeCacheSectionPage
(PVOID Context, MEMORY_AREA* MemoryArea, PVOID Address,
PFN_NUMBER Page, SWAPENTRY SwapEntry, BOOLEAN Dirty);
MmFreeCacheSectionPage(PVOID Context,
MEMORY_AREA* MemoryArea,
PVOID Address,
PFN_NUMBER Page,
SWAPENTRY SwapEntry,
BOOLEAN Dirty);
NTSTATUS
NTAPI
_MiFlushMappedSection(PVOID BaseAddress, PLARGE_INTEGER BaseOffset, PLARGE_INTEGER FileSize, BOOLEAN Dirty, const char *File, int Line);
_MiFlushMappedSection(PVOID BaseAddress,
PLARGE_INTEGER BaseOffset,
PLARGE_INTEGER FileSize,
BOOLEAN Dirty,
const char *File,
int Line);
#define MiFlushMappedSection(A,O,S,D) _MiFlushMappedSection(A,O,S,D,__FILE__,__LINE__)
@ -295,33 +310,32 @@ VOID
NTAPI
MmFreeSectionSegments(PFILE_OBJECT FileObject);
NTSTATUS NTAPI
MmMapCacheViewInSystemSpaceAtOffset
(IN PMM_SECTION_SEGMENT Segment,
OUT PVOID * MappedBase,
IN PLARGE_INTEGER ViewOffset,
IN OUT PULONG ViewSize);
NTSTATUS
NTAPI
MmMapCacheViewInSystemSpaceAtOffset(IN PMM_SECTION_SEGMENT Segment,
OUT PVOID* MappedBase,
IN PLARGE_INTEGER ViewOffset,
IN OUT PULONG ViewSize);
NTSTATUS
NTAPI
_MiMapViewOfSegment
(PMMSUPPORT AddressSpace,
PMM_SECTION_SEGMENT Segment,
PVOID* BaseAddress,
SIZE_T ViewSize,
ULONG Protect,
PLARGE_INTEGER ViewOffset,
ULONG AllocationType,
const char *file,
int line);
_MiMapViewOfSegment(PMMSUPPORT AddressSpace,
PMM_SECTION_SEGMENT Segment,
PVOID* BaseAddress,
SIZE_T ViewSize,
ULONG Protect,
PLARGE_INTEGER ViewOffset,
ULONG AllocationType,
const char *file,
int line);
#define MiMapViewOfSegment(AddressSpace,Segment,BaseAddress,ViewSize,Protect,ViewOffset,AllocationType) _MiMapViewOfSegment(AddressSpace,Segment,BaseAddress,ViewSize,Protect,ViewOffset,AllocationType,__FILE__,__LINE__)
#define MiMapViewOfSegment(AddressSpace,Segment,BaseAddress,ViewSize,Protect,ViewOffset,AllocationType) \
_MiMapViewOfSegment(AddressSpace,Segment,BaseAddress,ViewSize,Protect,ViewOffset,AllocationType,__FILE__,__LINE__)
NTSTATUS
NTAPI
MmUnmapViewOfCacheSegment
(PMMSUPPORT AddressSpace,
PVOID BaseAddress);
MmUnmapViewOfCacheSegment(PMMSUPPORT AddressSpace,
PVOID BaseAddress);
NTSTATUS
NTAPI
@ -329,70 +343,78 @@ MmUnmapCacheViewInSystemSpace(PVOID Address);
NTSTATUS
NTAPI
MmNotPresentFaultCachePage
(PMMSUPPORT AddressSpace,
PMEMORY_AREA MemoryArea,
PVOID Address,
BOOLEAN Locked,
PMM_REQUIRED_RESOURCES Required);
MmNotPresentFaultCachePage(PMMSUPPORT AddressSpace,
PMEMORY_AREA MemoryArea,
PVOID Address,
BOOLEAN Locked,
PMM_REQUIRED_RESOURCES Required);
NTSTATUS
NTAPI
MmPageOutPageFileView
(PMMSUPPORT AddressSpace,
PMEMORY_AREA MemoryArea,
PVOID Address,
PMM_REQUIRED_RESOURCES Required);
MmPageOutPageFileView(PMMSUPPORT AddressSpace,
PMEMORY_AREA MemoryArea,
PVOID Address,
PMM_REQUIRED_RESOURCES Required);
FORCEINLINE
BOOLEAN
_MmTryToLockAddressSpace(IN PMMSUPPORT AddressSpace, const char *file, int line)
_MmTryToLockAddressSpace(IN PMMSUPPORT AddressSpace,
const char *file,
int line)
{
BOOLEAN Result = KeTryToAcquireGuardedMutex(&CONTAINING_RECORD(AddressSpace, EPROCESS, Vm)->AddressCreationLock);
//DbgPrint("(%s:%d) Try Lock Address Space %x -> %s\n", file, line, AddressSpace, Result ? "true" : "false");
return Result;
BOOLEAN Result = KeTryToAcquireGuardedMutex(&CONTAINING_RECORD(AddressSpace, EPROCESS, Vm)->AddressCreationLock);
//DbgPrint("(%s:%d) Try Lock Address Space %x -> %s\n", file, line, AddressSpace, Result ? "true" : "false");
return Result;
}
#define MmTryToLockAddressSpace(x) _MmTryToLockAddressSpace(x,__FILE__,__LINE__)
NTSTATUS
NTAPI
MiWidenSegment
(PMMSUPPORT AddressSpace,
PMEMORY_AREA MemoryArea,
PMM_REQUIRED_RESOURCES RequiredResources);
MiWidenSegment(PMMSUPPORT AddressSpace,
PMEMORY_AREA MemoryArea,
PMM_REQUIRED_RESOURCES RequiredResources);
NTSTATUS
NTAPI
MiSwapInSectionPage
(PMMSUPPORT AddressSpace,
PMEMORY_AREA MemoryArea,
PMM_REQUIRED_RESOURCES RequiredResources);
MiSwapInSectionPage(PMMSUPPORT AddressSpace,
PMEMORY_AREA MemoryArea,
PMM_REQUIRED_RESOURCES RequiredResources);
NTSTATUS
NTAPI
MmExtendCacheSection(PROS_SECTION_OBJECT Section, PLARGE_INTEGER NewSize, BOOLEAN ExtendFile);
MmExtendCacheSection(PROS_SECTION_OBJECT Section,
PLARGE_INTEGER NewSize,
BOOLEAN ExtendFile);
NTSTATUS
NTAPI
_MiFlushMappedSection(PVOID BaseAddress, PLARGE_INTEGER BaseOffset, PLARGE_INTEGER FileSize, BOOLEAN Dirty, const char *File, int Line);
_MiFlushMappedSection(PVOID BaseAddress,
PLARGE_INTEGER BaseOffset,
PLARGE_INTEGER FileSize,
BOOLEAN Dirty,
const char *File,
int Line);
#define MiFlushMappedSection(A,O,S,D) _MiFlushMappedSection(A,O,S,D,__FILE__,__LINE__)
PVOID
NTAPI
MmGetSegmentRmap(PFN_NUMBER Page, PULONG RawOffset);
MmGetSegmentRmap(PFN_NUMBER Page,
PULONG RawOffset);
NTSTATUS
NTAPI
MmNotPresentFaultCacheSection
(KPROCESSOR_MODE Mode,
ULONG_PTR Address,
BOOLEAN FromMdl);
MmNotPresentFaultCacheSection(KPROCESSOR_MODE Mode,
ULONG_PTR Address,
BOOLEAN FromMdl);
ULONG
NTAPI
MiCacheEvictPages(PMM_SECTION_SEGMENT Segment, ULONG Target);
MiCacheEvictPages(PMM_SECTION_SEGMENT Segment,
ULONG Target);
NTSTATUS
MiRosTrimCache(ULONG Target, ULONG Priority, PULONG NrFreed);
MiRosTrimCache(ULONG Target,
ULONG Priority,
PULONG NrFreed);

View file

@ -57,74 +57,73 @@ MmBuildMdlFromPages(PMDL Mdl, PPFN_NUMBER Pages);
NTSTATUS
NTAPI
MiGetOnePage
(PMMSUPPORT AddressSpace,
PMEMORY_AREA MemoryArea,
PMM_REQUIRED_RESOURCES Required)
MiGetOnePage(PMMSUPPORT AddressSpace,
PMEMORY_AREA MemoryArea,
PMM_REQUIRED_RESOURCES Required)
{
int i;
NTSTATUS Status = STATUS_SUCCESS;
int i;
NTSTATUS Status = STATUS_SUCCESS;
for (i = 0; i < Required->Amount; i++)
{
DPRINTC("MiGetOnePage(%s:%d)\n", Required->File, Required->Line);
Status = MmRequestPageMemoryConsumer(Required->Consumer, TRUE, &Required->Page[i]);
if (!NT_SUCCESS(Status))
{
while (i > 0)
{
MmReleasePageMemoryConsumer(Required->Consumer, Required->Page[i-1]);
i--;
}
return Status;
}
}
return Status;
for (i = 0; i < Required->Amount; i++)
{
DPRINTC("MiGetOnePage(%s:%d)\n", Required->File, Required->Line);
Status = MmRequestPageMemoryConsumer(Required->Consumer,
TRUE,
&Required->Page[i]);
if (!NT_SUCCESS(Status))
{
while (i > 0)
{
MmReleasePageMemoryConsumer(Required->Consumer,
Required->Page[i-1]);
i--;
}
return Status;
}
}
return Status;
}
NTSTATUS
NTAPI
MiReadFilePage
(PMMSUPPORT AddressSpace,
PMEMORY_AREA MemoryArea,
PMM_REQUIRED_RESOURCES RequiredResources)
MiReadFilePage(PMMSUPPORT AddressSpace,
PMEMORY_AREA MemoryArea,
PMM_REQUIRED_RESOURCES RequiredResources)
{
PFILE_OBJECT FileObject = RequiredResources->Context;
PPFN_NUMBER Page = &RequiredResources->Page[RequiredResources->Offset];
PLARGE_INTEGER FileOffset = &RequiredResources->FileOffset;
NTSTATUS Status;
PFILE_OBJECT FileObject = RequiredResources->Context;
PPFN_NUMBER Page = &RequiredResources->Page[RequiredResources->Offset];
PLARGE_INTEGER FileOffset = &RequiredResources->FileOffset;
NTSTATUS Status;
PVOID PageBuf = NULL;
KEVENT Event;
IO_STATUS_BLOCK IOSB;
IO_STATUS_BLOCK IOSB;
UCHAR MdlBase[sizeof(MDL) + sizeof(ULONG)];
PMDL Mdl = (PMDL)MdlBase;
KIRQL OldIrql;
DPRINTC
("Pulling page %08x%08x from %wZ to %x\n",
FileOffset->u.HighPart, FileOffset->u.LowPart,
&FileObject->FileName,
Page);
DPRINTC("Pulling page %08x%08x from %wZ to %x\n",
FileOffset->u.HighPart,
FileOffset->u.LowPart,
&FileObject->FileName,
Page);
Status = MmRequestPageMemoryConsumer(RequiredResources->Consumer, TRUE, Page);
if (!NT_SUCCESS(Status))
{
DPRINT1("Status: %x\n", Status);
return Status;
}
Status = MmRequestPageMemoryConsumer(RequiredResources->Consumer,
TRUE,
Page);
if (!NT_SUCCESS(Status))
{
DPRINT1("Status: %x\n", Status);
return Status;
}
MmInitializeMdl(Mdl, NULL, PAGE_SIZE);
MmBuildMdlFromPages(Mdl, Page);
Mdl->MdlFlags |= MDL_PAGES_LOCKED;
KeInitializeEvent(&Event, NotificationEvent, FALSE);
Status = IoPageRead
(FileObject,
Mdl,
FileOffset,
&Event,
&IOSB);
Status = IoPageRead(FileObject, Mdl, FileOffset, &Event, &IOSB);
if (Status == STATUS_PENDING)
{
KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL);
@ -141,65 +140,71 @@ MiReadFilePage
MmReleasePageMemoryConsumer(RequiredResources->Consumer, *Page);
return STATUS_NO_MEMORY;
}
RtlZeroMemory
((PCHAR)PageBuf+RequiredResources->Amount,
PAGE_SIZE-RequiredResources->Amount);
RtlZeroMemory((PCHAR)PageBuf+RequiredResources->Amount,
PAGE_SIZE-RequiredResources->Amount);
MiUnmapPageInHyperSpace(PsGetCurrentProcess(), PageBuf, OldIrql);
DPRINT("Read Status %x (Page %x)\n", Status, *Page);
if (!NT_SUCCESS(Status))
{
MmReleasePageMemoryConsumer(RequiredResources->Consumer, *Page);
DPRINT("Status: %x\n", Status);
return Status;
}
DPRINT("Read Status %x (Page %x)\n", Status, *Page);
return STATUS_SUCCESS;
if (!NT_SUCCESS(Status))
{
MmReleasePageMemoryConsumer(RequiredResources->Consumer, *Page);
DPRINT("Status: %x\n", Status);
return Status;
}
return STATUS_SUCCESS;
}
NTSTATUS
NTAPI
MiSwapInPage
(PMMSUPPORT AddressSpace,
PMEMORY_AREA MemoryArea,
PMM_REQUIRED_RESOURCES Resources)
MiSwapInPage(PMMSUPPORT AddressSpace,
PMEMORY_AREA MemoryArea,
PMM_REQUIRED_RESOURCES Resources)
{
NTSTATUS Status;
NTSTATUS Status;
Status = MmRequestPageMemoryConsumer(Resources->Consumer, TRUE, &Resources->Page[Resources->Offset]);
if (!NT_SUCCESS(Status))
{
DPRINT1("MmRequestPageMemoryConsumer failed, status = %x\n", Status);
return Status;
}
Status = MmReadFromSwapPage(Resources->SwapEntry, Resources->Page[Resources->Offset]);
if (!NT_SUCCESS(Status))
{
DPRINT1("MmReadFromSwapPage failed, status = %x\n", Status);
return Status;
}
Status = MmRequestPageMemoryConsumer(Resources->Consumer,
TRUE,
&Resources->Page[Resources->Offset]);
if (!NT_SUCCESS(Status))
{
DPRINT1("MmRequestPageMemoryConsumer failed, status = %x\n", Status);
return Status;
}
MmSetSavedSwapEntryPage(Resources->Page[Resources->Offset], Resources->SwapEntry);
Status = MmReadFromSwapPage(Resources->SwapEntry,
Resources->Page[Resources->Offset]);
if (!NT_SUCCESS(Status))
{
DPRINT1("MmReadFromSwapPage failed, status = %x\n", Status);
return Status;
}
DPRINT1("MiSwapInPage(%x,%x)\n", Resources->Page[Resources->Offset], Resources->SwapEntry);
MmSetSavedSwapEntryPage(Resources->Page[Resources->Offset],
Resources->SwapEntry);
return Status;
DPRINT1("MiSwapInPage(%x,%x)\n",
Resources->Page[Resources->Offset],
Resources->SwapEntry);
return Status;
}
NTSTATUS
NTAPI
MiWriteFilePage
(PMMSUPPORT AddressSpace,
PMEMORY_AREA MemoryArea,
PMM_REQUIRED_RESOURCES Required)
MiWriteFilePage(PMMSUPPORT AddressSpace,
PMEMORY_AREA MemoryArea,
PMM_REQUIRED_RESOURCES Required)
{
DPRINT1("MiWriteFilePage(%x,%x)\n", Required->Page[Required->Offset], Required->FileOffset.LowPart);
DPRINT1("MiWriteFilePage(%x,%x)\n",
Required->Page[Required->Offset],
Required->FileOffset.LowPart);
return MiWriteBackPage
(Required->Context,
&Required->FileOffset,
PAGE_SIZE,
Required->Page[Required->Offset]);
return MiWriteBackPage(Required->Context,
&Required->FileOffset,
PAGE_SIZE,
Required->Page[Required->Offset]);
}

View file

@ -59,10 +59,12 @@ MiSectionPageTableFree(PRTL_GENERIC_TABLE Table, PVOID Data)
static
RTL_GENERIC_COMPARE_RESULTS
NTAPI
MiSectionPageTableCompare(PRTL_GENERIC_TABLE Table, PVOID PtrA, PVOID PtrB)
MiSectionPageTableCompare(PRTL_GENERIC_TABLE Table,
PVOID PtrA,
PVOID PtrB)
{
PLARGE_INTEGER A = PtrA, B = PtrB;
BOOLEAN Result = (A->QuadPart < B->QuadPart) ? GenericLessThan :
BOOLEAN Result = (A->QuadPart < B->QuadPart) ? GenericLessThan :
(A->QuadPart == B->QuadPart) ? GenericEqual : GenericGreaterThan;
#if 0
@ -71,7 +73,7 @@ MiSectionPageTableCompare(PRTL_GENERIC_TABLE Table, PVOID PtrA, PVOID PtrB)
A->u.HighPart, A->u.LowPart,
B->u.HighPart, B->u.LowPart,
Result == GenericLessThan ? "GenericLessThan" :
Result == GenericGreaterThan ? "GenericGreaterThan" :
Result == GenericGreaterThan ? "GenericGreaterThan" :
"GenericEqual");
#endif
@ -81,48 +83,50 @@ MiSectionPageTableCompare(PRTL_GENERIC_TABLE Table, PVOID PtrA, PVOID PtrB)
static
PCACHE_SECTION_PAGE_TABLE
NTAPI
MiSectionPageTableGet
(PRTL_GENERIC_TABLE Table,
PLARGE_INTEGER FileOffset)
MiSectionPageTableGet(PRTL_GENERIC_TABLE Table,
PLARGE_INTEGER FileOffset)
{
LARGE_INTEGER SearchFileOffset;
PCACHE_SECTION_PAGE_TABLE PageTable;
SearchFileOffset.QuadPart = ROUND_DOWN(FileOffset->QuadPart, ENTRIES_PER_ELEMENT * PAGE_SIZE);
PCACHE_SECTION_PAGE_TABLE PageTable;
SearchFileOffset.QuadPart = ROUND_DOWN(FileOffset->QuadPart,
ENTRIES_PER_ELEMENT * PAGE_SIZE);
PageTable = RtlLookupElementGenericTable(Table, &SearchFileOffset);
DPRINT
("MiSectionPageTableGet(%08x,%08x%08x)\n",
Table,
FileOffset->HighPart,
FileOffset->LowPart);
return PageTable;
DPRINT("MiSectionPageTableGet(%08x,%08x%08x)\n",
Table,
FileOffset->HighPart,
FileOffset->LowPart);
return PageTable;
}
static
PCACHE_SECTION_PAGE_TABLE
NTAPI
MiSectionPageTableGetOrAllocate
(PRTL_GENERIC_TABLE Table,
PLARGE_INTEGER FileOffset)
MiSectionPageTableGetOrAllocate(PRTL_GENERIC_TABLE Table,
PLARGE_INTEGER FileOffset)
{
LARGE_INTEGER SearchFileOffset;
CACHE_SECTION_PAGE_TABLE SectionZeroPageTable;
PCACHE_SECTION_PAGE_TABLE PageTableSlice =
MiSectionPageTableGet(Table, FileOffset);
// Please zero memory when taking away zero initialization.
PCACHE_SECTION_PAGE_TABLE PageTableSlice = MiSectionPageTableGet(Table,
FileOffset);
/* Please zero memory when taking away zero initialization. */
RtlZeroMemory(&SectionZeroPageTable, sizeof(CACHE_SECTION_PAGE_TABLE));
if (!PageTableSlice)
{
SearchFileOffset.QuadPart = ROUND_DOWN(FileOffset->QuadPart, ENTRIES_PER_ELEMENT * PAGE_SIZE);
SearchFileOffset.QuadPart = ROUND_DOWN(FileOffset->QuadPart,
ENTRIES_PER_ELEMENT * PAGE_SIZE);
SectionZeroPageTable.FileOffset = SearchFileOffset;
SectionZeroPageTable.Refcount = 1;
PageTableSlice = RtlInsertElementGenericTable
(Table, &SectionZeroPageTable, sizeof(SectionZeroPageTable), NULL);
PageTableSlice = RtlInsertElementGenericTable(Table,
&SectionZeroPageTable,
sizeof(SectionZeroPageTable),
NULL);
if (!PageTableSlice) return NULL;
DPRINT
("Allocate page table %x (%08x%08x)\n",
PageTableSlice,
PageTableSlice->FileOffset.u.HighPart,
PageTableSlice->FileOffset.u.LowPart);
DPRINT("Allocate page table %x (%08x%08x)\n",
PageTableSlice,
PageTableSlice->FileOffset.u.HighPart,
PageTableSlice->FileOffset.u.LowPart);
}
return PageTableSlice;
}
@ -131,159 +135,179 @@ VOID
NTAPI
MiInitializeSectionPageTable(PMM_SECTION_SEGMENT Segment)
{
RtlInitializeGenericTable
(&Segment->PageTable,
MiSectionPageTableCompare,
MiSectionPageTableAllocate,
MiSectionPageTableFree,
NULL);
RtlInitializeGenericTable(&Segment->PageTable,
MiSectionPageTableCompare,
MiSectionPageTableAllocate,
MiSectionPageTableFree,
NULL);
DPRINT("MiInitializeSectionPageTable(%p)\n", &Segment->PageTable);
}
NTSTATUS
NTAPI
_MmSetPageEntrySectionSegment
(PMM_SECTION_SEGMENT Segment,
PLARGE_INTEGER Offset,
ULONG Entry,
const char *file,
int line)
_MmSetPageEntrySectionSegment(PMM_SECTION_SEGMENT Segment,
PLARGE_INTEGER Offset,
ULONG Entry,
const char *file,
int line)
{
ULONG PageIndex, OldEntry;
PCACHE_SECTION_PAGE_TABLE PageTable;
ASSERT(Segment->Locked);
ASSERT(Segment->Locked);
ASSERT(!IS_SWAP_FROM_SSE(Entry) || !IS_DIRTY_SSE(Entry));
if (Entry && !IS_SWAP_FROM_SSE(Entry))
MmGetRmapListHeadPage(PFN_FROM_SSE(Entry));
PageTable =
MiSectionPageTableGetOrAllocate(&Segment->PageTable, Offset);
if (Entry && !IS_SWAP_FROM_SSE(Entry))
MmGetRmapListHeadPage(PFN_FROM_SSE(Entry));
PageTable = MiSectionPageTableGetOrAllocate(&Segment->PageTable, Offset);
if (!PageTable) return STATUS_NO_MEMORY;
ASSERT(MiSectionPageTableGet(&Segment->PageTable, Offset));
PageTable->Segment = Segment;
PageIndex =
(Offset->QuadPart - PageTable->FileOffset.QuadPart) / PAGE_SIZE;
OldEntry = PageTable->PageEntries[PageIndex];
DPRINT("MiSetPageEntrySectionSegment(%p,%08x%08x,%x=>%x)\n",
Segment, Offset->u.HighPart, Offset->u.LowPart, OldEntry, Entry);
if (PFN_FROM_SSE(Entry) == PFN_FROM_SSE(OldEntry)) {
// Nothing
} else if (Entry && !IS_SWAP_FROM_SSE(Entry)) {
ASSERT(!OldEntry || IS_SWAP_FROM_SSE(OldEntry));
MmSetSectionAssociation(PFN_FROM_SSE(Entry), Segment, Offset);
} else if (OldEntry && !IS_SWAP_FROM_SSE(OldEntry)) {
ASSERT(!Entry || IS_SWAP_FROM_SSE(Entry));
MmDeleteSectionAssociation(PFN_FROM_SSE(OldEntry));
} else if (IS_SWAP_FROM_SSE(Entry)) {
ASSERT(!IS_SWAP_FROM_SSE(OldEntry));
if (OldEntry)
MmDeleteSectionAssociation(PFN_FROM_SSE(OldEntry));
} else if (IS_SWAP_FROM_SSE(OldEntry)) {
ASSERT(!IS_SWAP_FROM_SSE(Entry));
if (Entry)
MmSetSectionAssociation(PFN_FROM_SSE(OldEntry), Segment, Offset);
} else {
// We should not be replacing a page like this
ASSERT(FALSE);
}
ASSERT(MiSectionPageTableGet(&Segment->PageTable, Offset));
PageTable->Segment = Segment;
PageIndex = (Offset->QuadPart - PageTable->FileOffset.QuadPart) / PAGE_SIZE;
OldEntry = PageTable->PageEntries[PageIndex];
DPRINT("MiSetPageEntrySectionSegment(%p,%08x%08x,%x=>%x)\n",
Segment,
Offset->u.HighPart,
Offset->u.LowPart,
OldEntry,
Entry);
if (PFN_FROM_SSE(Entry) == PFN_FROM_SSE(OldEntry)) {
/* Nothing */
} else if (Entry && !IS_SWAP_FROM_SSE(Entry)) {
ASSERT(!OldEntry || IS_SWAP_FROM_SSE(OldEntry));
MmSetSectionAssociation(PFN_FROM_SSE(Entry), Segment, Offset);
} else if (OldEntry && !IS_SWAP_FROM_SSE(OldEntry)) {
ASSERT(!Entry || IS_SWAP_FROM_SSE(Entry));
MmDeleteSectionAssociation(PFN_FROM_SSE(OldEntry));
} else if (IS_SWAP_FROM_SSE(Entry)) {
ASSERT(!IS_SWAP_FROM_SSE(OldEntry));
if (OldEntry)
MmDeleteSectionAssociation(PFN_FROM_SSE(OldEntry));
} else if (IS_SWAP_FROM_SSE(OldEntry)) {
ASSERT(!IS_SWAP_FROM_SSE(Entry));
if (Entry)
MmSetSectionAssociation(PFN_FROM_SSE(OldEntry), Segment, Offset);
} else {
/* We should not be replacing a page like this */
ASSERT(FALSE);
}
PageTable->PageEntries[PageIndex] = Entry;
return STATUS_SUCCESS;
}
ULONG
NTAPI
_MmGetPageEntrySectionSegment
(PMM_SECTION_SEGMENT Segment,
PLARGE_INTEGER Offset,
const char *file,
int line)
_MmGetPageEntrySectionSegment(PMM_SECTION_SEGMENT Segment,
PLARGE_INTEGER Offset,
const char *file,
int line)
{
LARGE_INTEGER FileOffset;
ULONG PageIndex, Result;
PCACHE_SECTION_PAGE_TABLE PageTable;
ASSERT(Segment->Locked);
FileOffset.QuadPart =
ROUND_DOWN(Offset->QuadPart, ENTRIES_PER_ELEMENT * PAGE_SIZE);
FileOffset.QuadPart = ROUND_DOWN(Offset->QuadPart,
ENTRIES_PER_ELEMENT * PAGE_SIZE);
PageTable = MiSectionPageTableGet(&Segment->PageTable, &FileOffset);
if (!PageTable) return 0;
PageIndex =
(Offset->QuadPart - PageTable->FileOffset.QuadPart) / PAGE_SIZE;
PageIndex = (Offset->QuadPart - PageTable->FileOffset.QuadPart) / PAGE_SIZE;
Result = PageTable->PageEntries[PageIndex];
#if 0
DPRINTC
("MiGetPageEntrySectionSegment(%p,%08x%08x) => %x %s:%d\n",
Segment,
FileOffset.u.HighPart,
FileOffset.u.HighPart,
FileOffset.u.LowPart + PageIndex * PAGE_SIZE,
Result,
file, line);
file, line);
#endif
return Result;
}
VOID
NTAPI
MmFreePageTablesSectionSegment
(PMM_SECTION_SEGMENT Segment, FREE_SECTION_PAGE_FUN FreePage)
MmFreePageTablesSectionSegment(PMM_SECTION_SEGMENT Segment,
FREE_SECTION_PAGE_FUN FreePage)
{
PCACHE_SECTION_PAGE_TABLE Element;
DPRINT("MiFreePageTablesSectionSegment(%p)\n", &Segment->PageTable);
while ((Element = RtlGetElementGenericTable(&Segment->PageTable, 0))) {
DPRINT
("Delete table for <%wZ> %x -> %08x%08x\n",
Segment->FileObject ? &Segment->FileObject->FileName : NULL,
Segment,
Element->FileOffset.u.HighPart,
Element->FileOffset.u.LowPart);
if (FreePage)
{
int i;
for (i = 0; i < ENTRIES_PER_ELEMENT; i++)
{
ULONG Entry;
LARGE_INTEGER Offset;
Offset.QuadPart = Element->FileOffset.QuadPart + i * PAGE_SIZE;
Entry = Element->PageEntries[i];
if (Entry && !IS_SWAP_FROM_SSE(Entry))
{
DPRINT("Freeing page %x:%x @ %x\n", Segment, Entry, Offset.LowPart);
FreePage(Segment, &Offset);
}
}
}
DPRINT("Remove memory\n");
DPRINT("Delete table for <%wZ> %x -> %08x%08x\n",
Segment->FileObject ? &Segment->FileObject->FileName : NULL,
Segment,
Element->FileOffset.u.HighPart,
Element->FileOffset.u.LowPart);
if (FreePage)
{
int i;
for (i = 0; i < ENTRIES_PER_ELEMENT; i++)
{
ULONG Entry;
LARGE_INTEGER Offset;
Offset.QuadPart = Element->FileOffset.QuadPart + i * PAGE_SIZE;
Entry = Element->PageEntries[i];
if (Entry && !IS_SWAP_FROM_SSE(Entry))
{
DPRINT("Freeing page %x:%x @ %x\n",
Segment,
Entry,
Offset.LowPart);
FreePage(Segment, &Offset);
}
}
}
DPRINT("Remove memory\n");
RtlDeleteElementGenericTable(&Segment->PageTable, Element);
}
DPRINT("Done\n");
DPRINT("Done\n");
}
PMM_SECTION_SEGMENT
NTAPI
MmGetSectionAssociation(PFN_NUMBER Page, PLARGE_INTEGER Offset)
MmGetSectionAssociation(PFN_NUMBER Page,
PLARGE_INTEGER Offset)
{
ULONG RawOffset;
ULONG RawOffset;
PMM_SECTION_SEGMENT Segment = NULL;
PCACHE_SECTION_PAGE_TABLE PageTable;
PageTable = (PCACHE_SECTION_PAGE_TABLE)MmGetSegmentRmap(Page, &RawOffset);
if (PageTable)
{
Segment = PageTable->Segment;
Offset->QuadPart = PageTable->FileOffset.QuadPart + (RawOffset << PAGE_SHIFT);
}
return(Segment);
PageTable = (PCACHE_SECTION_PAGE_TABLE)MmGetSegmentRmap(Page,
&RawOffset);
if (PageTable)
{
Segment = PageTable->Segment;
Offset->QuadPart = PageTable->FileOffset.QuadPart +
(RawOffset << PAGE_SHIFT);
}
return Segment;
}
NTSTATUS
NTAPI
MmSetSectionAssociation(PFN_NUMBER Page, PMM_SECTION_SEGMENT Segment, PLARGE_INTEGER Offset)
MmSetSectionAssociation(PFN_NUMBER Page,
PMM_SECTION_SEGMENT Segment,
PLARGE_INTEGER Offset)
{
PCACHE_SECTION_PAGE_TABLE PageTable;
ULONG ActualOffset;
PageTable = MiSectionPageTableGet(&Segment->PageTable, Offset);
ASSERT(PageTable);
ActualOffset = (ULONG)(Offset->QuadPart - PageTable->FileOffset.QuadPart);
MmInsertRmap(Page, (PEPROCESS)PageTable, (PVOID)(RMAP_SEGMENT_MASK | (ActualOffset >> PAGE_SHIFT)));
return STATUS_SUCCESS;
ULONG ActualOffset;
PageTable = MiSectionPageTableGet(&Segment->PageTable, Offset);
ASSERT(PageTable);
ActualOffset = (ULONG)(Offset->QuadPart - PageTable->FileOffset.QuadPart);
MmInsertRmap(Page,
(PEPROCESS)PageTable,
(PVOID)(RMAP_SEGMENT_MASK | (ActualOffset >> PAGE_SHIFT)));
return STATUS_SUCCESS;
}

View file

@ -60,424 +60,498 @@ FAST_MUTEX MiGlobalPageOperation;
PFN_NUMBER
NTAPI
MmWithdrawSectionPage
(PMM_SECTION_SEGMENT Segment, PLARGE_INTEGER FileOffset, BOOLEAN *Dirty)
MmWithdrawSectionPage(PMM_SECTION_SEGMENT Segment,
PLARGE_INTEGER FileOffset,
BOOLEAN *Dirty)
{
ULONG Entry;
ULONG Entry;
DPRINT("MmWithdrawSectionPage(%x,%08x%08x,%x)\n", Segment, FileOffset->HighPart, FileOffset->LowPart, Dirty);
DPRINT("MmWithdrawSectionPage(%x,%08x%08x,%x)\n",
Segment,
FileOffset->HighPart,
FileOffset->LowPart,
Dirty);
MmLockSectionSegment(Segment);
Entry = MmGetPageEntrySectionSegment(Segment, FileOffset);
MmLockSectionSegment(Segment);
Entry = MmGetPageEntrySectionSegment(Segment, FileOffset);
*Dirty = !!IS_DIRTY_SSE(Entry);
*Dirty = !!IS_DIRTY_SSE(Entry);
DPRINT("Withdraw %x (%x) of %wZ\n", FileOffset->LowPart, Entry, Segment->FileObject ? &Segment->FileObject->FileName : NULL);
DPRINT("Withdraw %x (%x) of %wZ\n",
FileOffset->LowPart,
Entry,
Segment->FileObject ? &Segment->FileObject->FileName : NULL);
if (!Entry)
{
DPRINT("Stoeled!\n");
MmUnlockSectionSegment(Segment);
return 0;
}
else if (MM_IS_WAIT_PTE(Entry))
{
DPRINT("WAIT\n");
MmUnlockSectionSegment(Segment);
return MM_WAIT_ENTRY;
}
else if (Entry && !IS_SWAP_FROM_SSE(Entry))
{
DPRINT("Page %x\n", PFN_FROM_SSE(Entry));
*Dirty |= (Entry & 2);
MmSetPageEntrySectionSegment(Segment, FileOffset, MAKE_SWAP_SSE(MM_WAIT_ENTRY));
MmUnlockSectionSegment(Segment);
return PFN_FROM_SSE(Entry);
}
else
{
DPRINT1("SWAP ENTRY?! (%x:%08x%08x)\n", Segment, FileOffset->HighPart, FileOffset->LowPart);
ASSERT(FALSE);
MmUnlockSectionSegment(Segment);
return 0;
}
if (!Entry)
{
DPRINT("Stoeled!\n");
MmUnlockSectionSegment(Segment);
return 0;
}
else if (MM_IS_WAIT_PTE(Entry))
{
DPRINT("WAIT\n");
MmUnlockSectionSegment(Segment);
return MM_WAIT_ENTRY;
}
else if (Entry && !IS_SWAP_FROM_SSE(Entry))
{
DPRINT("Page %x\n", PFN_FROM_SSE(Entry));
*Dirty |= (Entry & 2);
MmSetPageEntrySectionSegment(Segment,
FileOffset,
MAKE_SWAP_SSE(MM_WAIT_ENTRY));
MmUnlockSectionSegment(Segment);
return PFN_FROM_SSE(Entry);
}
else
{
DPRINT1("SWAP ENTRY?! (%x:%08x%08x)\n",
Segment,
FileOffset->HighPart,
FileOffset->LowPart);
ASSERT(FALSE);
MmUnlockSectionSegment(Segment);
return 0;
}
}
NTSTATUS
NTAPI
MmFinalizeSectionPageOut
(PMM_SECTION_SEGMENT Segment, PLARGE_INTEGER FileOffset, PFN_NUMBER Page,
BOOLEAN Dirty)
MmFinalizeSectionPageOut(PMM_SECTION_SEGMENT Segment,
PLARGE_INTEGER FileOffset,
PFN_NUMBER Page,
BOOLEAN Dirty)
{
NTSTATUS Status = STATUS_SUCCESS;
BOOLEAN WriteZero = FALSE, WritePage = FALSE;
SWAPENTRY Swap = MmGetSavedSwapEntryPage(Page);
NTSTATUS Status = STATUS_SUCCESS;
BOOLEAN WriteZero = FALSE, WritePage = FALSE;
SWAPENTRY Swap = MmGetSavedSwapEntryPage(Page);
/* Bail early if the reference count isn't where we need it */
if (MmGetReferenceCountPage(Page) != 1)
{
DPRINT1("Cannot page out locked page %x with ref count %d\n", Page, MmGetReferenceCountPage(Page));
DPRINT1("Cannot page out locked page %x with ref count %d\n",
Page,
MmGetReferenceCountPage(Page));
return STATUS_UNSUCCESSFUL;
}
MmLockSectionSegment(Segment);
(void)InterlockedIncrementUL(&Segment->ReferenceCount);
MmLockSectionSegment(Segment);
(void)InterlockedIncrementUL(&Segment->ReferenceCount);
if (Dirty)
{
DPRINT("Finalize (dirty) Segment %x Page %x\n", Segment, Page);
DPRINT("Segment->FileObject %x\n", Segment->FileObject);
DPRINT("Segment->Flags %x\n", Segment->Flags);
if (Dirty)
{
DPRINT("Finalize (dirty) Segment %x Page %x\n", Segment, Page);
DPRINT("Segment->FileObject %x\n", Segment->FileObject);
DPRINT("Segment->Flags %x\n", Segment->Flags);
WriteZero = TRUE;
WritePage = TRUE;
}
else
{
WriteZero = TRUE;
}
WriteZero = TRUE;
WritePage = TRUE;
}
else
{
WriteZero = TRUE;
}
DPRINT("Status %x\n", Status);
DPRINT("Status %x\n", Status);
MmUnlockSectionSegment(Segment);
MmUnlockSectionSegment(Segment);
if (WritePage)
{
DPRINT("MiWriteBackPage(Segment %x FileObject %x Offset %x)\n", Segment, Segment->FileObject, FileOffset->LowPart);
Status = MiWriteBackPage(Segment->FileObject, FileOffset, PAGE_SIZE, Page);
}
if (WritePage)
{
DPRINT("MiWriteBackPage(Segment %x FileObject %x Offset %x)\n",
Segment,
Segment->FileObject,
FileOffset->LowPart);
MmLockSectionSegment(Segment);
Status = MiWriteBackPage(Segment->FileObject,
FileOffset,
PAGE_SIZE,
Page);
}
if (WriteZero && NT_SUCCESS(Status))
{
DPRINT("Setting page entry in segment %x:%x to swap %x\n", Segment, FileOffset->LowPart, Swap);
MmSetPageEntrySectionSegment(Segment, FileOffset, Swap ? MAKE_SWAP_SSE(Swap) : 0);
}
else
{
DPRINT("Setting page entry in segment %x:%x to page %x\n", Segment, FileOffset->LowPart, Page);
MmSetPageEntrySectionSegment
(Segment, FileOffset, Page ? (Dirty ? DIRTY_SSE(MAKE_PFN_SSE(Page)) : MAKE_PFN_SSE(Page)) : 0);
}
MmLockSectionSegment(Segment);
if (NT_SUCCESS(Status))
{
DPRINT("Removing page %x for real\n", Page);
MmSetSavedSwapEntryPage(Page, 0);
MmReleasePageMemoryConsumer(MC_CACHE, Page);
}
if (WriteZero && NT_SUCCESS(Status))
{
DPRINT("Setting page entry in segment %x:%x to swap %x\n",
Segment,
FileOffset->LowPart,
Swap);
MmUnlockSectionSegment(Segment);
MmSetPageEntrySectionSegment(Segment,
FileOffset,
Swap ? MAKE_SWAP_SSE(Swap) : 0);
}
else
{
DPRINT("Setting page entry in segment %x:%x to page %x\n",
Segment,
FileOffset->LowPart,
Page);
if (InterlockedDecrementUL(&Segment->ReferenceCount) == 0)
{
MmFinalizeSegment(Segment);
}
MmSetPageEntrySectionSegment(Segment,
FileOffset,
Page ? (Dirty ? DIRTY_SSE(MAKE_PFN_SSE(Page)) : MAKE_PFN_SSE(Page)) : 0);
}
/* Note: Writing may evict the segment... Nothing is guaranteed from here down */
MiSetPageEvent(Segment, FileOffset->LowPart);
if (NT_SUCCESS(Status))
{
DPRINT("Removing page %x for real\n", Page);
MmSetSavedSwapEntryPage(Page, 0);
MmReleasePageMemoryConsumer(MC_CACHE, Page);
}
DPRINT("Status %x\n", Status);
return Status;
MmUnlockSectionSegment(Segment);
if (InterlockedDecrementUL(&Segment->ReferenceCount) == 0)
{
MmFinalizeSegment(Segment);
}
/* Note: Writing may evict the segment... Nothing is guaranteed from here down */
MiSetPageEvent(Segment, FileOffset->LowPart);
DPRINT("Status %x\n", Status);
return Status;
}
NTSTATUS
NTAPI
MmPageOutCacheSection
(PMMSUPPORT AddressSpace,
MEMORY_AREA* MemoryArea,
PVOID Address,
PBOOLEAN Dirty,
PMM_REQUIRED_RESOURCES Required)
MmPageOutCacheSection(PMMSUPPORT AddressSpace,
MEMORY_AREA* MemoryArea,
PVOID Address,
PBOOLEAN Dirty,
PMM_REQUIRED_RESOURCES Required)
{
ULONG Entry;
ULONG Entry;
PFN_NUMBER OurPage;
PEPROCESS Process = MmGetAddressSpaceOwner(AddressSpace);
LARGE_INTEGER TotalOffset;
PMM_SECTION_SEGMENT Segment;
PVOID PAddress = MM_ROUND_DOWN(Address, PAGE_SIZE);
PEPROCESS Process = MmGetAddressSpaceOwner(AddressSpace);
LARGE_INTEGER TotalOffset;
PMM_SECTION_SEGMENT Segment;
PVOID PAddress = MM_ROUND_DOWN(Address, PAGE_SIZE);
TotalOffset.QuadPart = (ULONG_PTR)PAddress - (ULONG_PTR)MemoryArea->StartingAddress +
MemoryArea->Data.SectionData.ViewOffset.QuadPart;
TotalOffset.QuadPart = (ULONG_PTR)PAddress - (ULONG_PTR)MemoryArea->StartingAddress +
MemoryArea->Data.SectionData.ViewOffset.QuadPart;
Segment = MemoryArea->Data.SectionData.Segment;
Segment = MemoryArea->Data.SectionData.Segment;
MmLockSectionSegment(Segment);
ASSERT(KeGetCurrentIrql() <= APC_LEVEL);
MmLockSectionSegment(Segment);
ASSERT(KeGetCurrentIrql() <= APC_LEVEL);
Entry = MmGetPageEntrySectionSegment(Segment, &TotalOffset);
Entry = MmGetPageEntrySectionSegment(Segment, &TotalOffset);
if (MmIsPageSwapEntry(Process, PAddress))
{
if (MmIsPageSwapEntry(Process, PAddress))
{
SWAPENTRY SwapEntry;
MmGetPageFileMapping(Process, PAddress, &SwapEntry);
MmUnlockSectionSegment(Segment);
return SwapEntry == MM_WAIT_ENTRY ? STATUS_SUCCESS + 1 : STATUS_UNSUCCESSFUL;
}
MmUnlockSectionSegment(Segment);
return SwapEntry == MM_WAIT_ENTRY ? STATUS_SUCCESS + 1 : STATUS_UNSUCCESSFUL;
}
MmDeleteRmap(Required->Page[0], Process, Address);
MmDeleteVirtualMapping(Process, Address, FALSE, Dirty, &OurPage);
ASSERT(OurPage == Required->Page[0]);
MmReleasePageMemoryConsumer(MC_CACHE, Required->Page[0]);
MmReleasePageMemoryConsumer(MC_CACHE, Required->Page[0]);
MmUnlockSectionSegment(Segment);
MiSetPageEvent(Process, Address);
return STATUS_SUCCESS;
MmUnlockSectionSegment(Segment);
MiSetPageEvent(Process, Address);
return STATUS_SUCCESS;
}
NTSTATUS
NTAPI
MmpPageOutPhysicalAddress(PFN_NUMBER Page)
{
BOOLEAN ProcRef = FALSE, PageDirty;
PFN_NUMBER SectionPage = 0;
PMM_RMAP_ENTRY entry;
PMM_SECTION_SEGMENT Segment = NULL;
LARGE_INTEGER FileOffset;
PMEMORY_AREA MemoryArea;
PMMSUPPORT AddressSpace = MmGetKernelAddressSpace();
BOOLEAN Dirty = FALSE;
PVOID Address = NULL;
PEPROCESS Process = NULL;
NTSTATUS Status = STATUS_SUCCESS;
MM_REQUIRED_RESOURCES Resources = { 0 };
BOOLEAN ProcRef = FALSE, PageDirty;
PFN_NUMBER SectionPage = 0;
PMM_RMAP_ENTRY entry;
PMM_SECTION_SEGMENT Segment = NULL;
LARGE_INTEGER FileOffset;
PMEMORY_AREA MemoryArea;
PMMSUPPORT AddressSpace = MmGetKernelAddressSpace();
BOOLEAN Dirty = FALSE;
PVOID Address = NULL;
PEPROCESS Process = NULL;
NTSTATUS Status = STATUS_SUCCESS;
MM_REQUIRED_RESOURCES Resources = { 0 };
DPRINTC("Page out %x (ref ct %x)\n", Page, MmGetReferenceCountPage(Page));
DPRINTC("Page out %x (ref ct %x)\n", Page, MmGetReferenceCountPage(Page));
ExAcquireFastMutex(&MiGlobalPageOperation);
if ((Segment = MmGetSectionAssociation(Page, &FileOffset)))
{
DPRINTC("Withdrawing page (%x) %x:%x\n", Page, Segment, FileOffset.LowPart);
SectionPage = MmWithdrawSectionPage(Segment, &FileOffset, &Dirty);
DPRINTC("SectionPage %x\n", SectionPage);
ExAcquireFastMutex(&MiGlobalPageOperation);
if ((Segment = MmGetSectionAssociation(Page, &FileOffset)))
{
DPRINTC("Withdrawing page (%x) %x:%x\n",
Page,
Segment,
FileOffset.LowPart);
if (SectionPage == MM_WAIT_ENTRY || SectionPage == 0)
{
DPRINT1("In progress page out %x\n", SectionPage);
ExReleaseFastMutex(&MiGlobalPageOperation);
return STATUS_UNSUCCESSFUL;
}
else
{
ASSERT(SectionPage == Page);
}
Resources.State = Dirty ? 1 : 0;
}
else
{
DPRINT("No segment association for %x\n", Page);
}
SectionPage = MmWithdrawSectionPage(Segment, &FileOffset, &Dirty);
DPRINTC("SectionPage %x\n", SectionPage);
if (SectionPage == MM_WAIT_ENTRY || SectionPage == 0)
{
DPRINT1("In progress page out %x\n", SectionPage);
ExReleaseFastMutex(&MiGlobalPageOperation);
return STATUS_UNSUCCESSFUL;
}
else
{
ASSERT(SectionPage == Page);
}
Resources.State = Dirty ? 1 : 0;
}
else
{
DPRINT("No segment association for %x\n", Page);
}
Dirty = MmIsDirtyPageRmap(Page);
Dirty = MmIsDirtyPageRmap(Page);
DPRINTC("Trying to unmap all instances of %x\n", Page);
ExAcquireFastMutex(&RmapListLock);
entry = MmGetRmapListHeadPage(Page);
DPRINTC("Trying to unmap all instances of %x\n", Page);
ExAcquireFastMutex(&RmapListLock);
entry = MmGetRmapListHeadPage(Page);
// Entry and Segment might be null here in the case that the page
// is new and is in the process of being swapped in
if (!entry && !Segment)
{
Status = STATUS_UNSUCCESSFUL;
DPRINT1("Page %x is in transit\n", Page);
ExReleaseFastMutex(&RmapListLock);
goto bail;
}
// Entry and Segment might be null here in the case that the page
// is new and is in the process of being swapped in
if (!entry && !Segment)
{
Status = STATUS_UNSUCCESSFUL;
DPRINT1("Page %x is in transit\n", Page);
ExReleaseFastMutex(&RmapListLock);
goto bail;
}
while (entry != NULL && NT_SUCCESS(Status))
{
Process = entry->Process;
Address = entry->Address;
while (entry != NULL && NT_SUCCESS(Status))
{
Process = entry->Process;
Address = entry->Address;
DPRINTC("Process %x Address %x Page %x\n", Process, Address, Page);
DPRINTC("Process %x Address %x Page %x\n", Process, Address, Page);
if (RMAP_IS_SEGMENT(Address)) {
entry = entry->Next;
continue;
}
if (RMAP_IS_SEGMENT(Address)) {
entry = entry->Next;
continue;
}
if (Process && Address < MmSystemRangeStart)
{
// Make sure we don't try to page out part of an exiting process
if (PspIsProcessExiting(Process))
{
DPRINT("bail\n");
ExReleaseFastMutex(&RmapListLock);
goto bail;
}
Status = ObReferenceObject(Process);
if (!NT_SUCCESS(Status))
{
DPRINT("bail\n");
ExReleaseFastMutex(&RmapListLock);
goto bail;
}
ProcRef = TRUE;
AddressSpace = &Process->Vm;
}
else
{
AddressSpace = MmGetKernelAddressSpace();
}
ExReleaseFastMutex(&RmapListLock);
if (Process && Address < MmSystemRangeStart)
{
/* Make sure we don't try to page out part of an exiting process */
if (PspIsProcessExiting(Process))
{
DPRINT("bail\n");
ExReleaseFastMutex(&RmapListLock);
goto bail;
}
Status = ObReferenceObject(Process);
if (!NT_SUCCESS(Status))
{
DPRINT("bail\n");
ExReleaseFastMutex(&RmapListLock);
goto bail;
}
ProcRef = TRUE;
AddressSpace = &Process->Vm;
}
else
{
AddressSpace = MmGetKernelAddressSpace();
}
ExReleaseFastMutex(&RmapListLock);
RtlZeroMemory(&Resources, sizeof(Resources));
RtlZeroMemory(&Resources, sizeof(Resources));
if ((((ULONG_PTR)Address) & 0xFFF) != 0)
{
KeBugCheck(MEMORY_MANAGEMENT);
}
if ((((ULONG_PTR)Address) & 0xFFF) != 0)
{
KeBugCheck(MEMORY_MANAGEMENT);
}
MmLockAddressSpace(AddressSpace);
MmLockAddressSpace(AddressSpace);
do
{
MemoryArea = MmLocateMemoryAreaByAddress(AddressSpace, Address);
if (MemoryArea == NULL ||
MemoryArea->DeleteInProgress)
{
Status = STATUS_UNSUCCESSFUL;
MmUnlockAddressSpace(AddressSpace);
DPRINTC("bail\n");
goto bail;
}
DPRINTC
("Type %x (%x -> %x)\n",
MemoryArea->Type,
MemoryArea->StartingAddress,
MemoryArea->EndingAddress);
Resources.DoAcquisition = NULL;
Resources.Page[0] = Page;
ASSERT(KeGetCurrentIrql() <= APC_LEVEL);
do
{
MemoryArea = MmLocateMemoryAreaByAddress(AddressSpace, Address);
if (MemoryArea == NULL || MemoryArea->DeleteInProgress)
{
Status = STATUS_UNSUCCESSFUL;
MmUnlockAddressSpace(AddressSpace);
DPRINTC("bail\n");
goto bail;
}
DPRINT("%x:%x, page %x %x\n", Process, Address, Page, Resources.Page[0]);
PageDirty = FALSE;
Status = MmPageOutCacheSection
(AddressSpace, MemoryArea, Address, &PageDirty, &Resources);
Dirty |= PageDirty;
DPRINT("%x\n", Status);
ASSERT(KeGetCurrentIrql() <= APC_LEVEL);
MmUnlockAddressSpace(AddressSpace);
if (Status == STATUS_SUCCESS + 1)
{
// Wait page ... the other guy has it, so we'll just fail for now
DPRINT1("Wait entry ... can't continue\n");
Status = STATUS_UNSUCCESSFUL;
goto bail;
}
else if (Status == STATUS_MORE_PROCESSING_REQUIRED)
{
DPRINTC("DoAcquisition %x\n", Resources.DoAcquisition);
Status = Resources.DoAcquisition(AddressSpace, MemoryArea, &Resources);
DPRINTC("Status %x\n", Status);
if (!NT_SUCCESS(Status))
{
DPRINT1("bail\n");
goto bail;
}
else Status = STATUS_MM_RESTART_OPERATION;
}
MmLockAddressSpace(AddressSpace);
}
while (Status == STATUS_MM_RESTART_OPERATION);
DPRINTC("Type %x (%x -> %x)\n",
MemoryArea->Type,
MemoryArea->StartingAddress,
MemoryArea->EndingAddress);
MmUnlockAddressSpace(AddressSpace);
Resources.DoAcquisition = NULL;
Resources.Page[0] = Page;
if (ProcRef)
{
ObDereferenceObject(Process);
ProcRef = FALSE;
}
ExAcquireFastMutex(&RmapListLock);
ASSERT(!MM_IS_WAIT_PTE(MmGetPfnForProcess(Process, Address)));
entry = MmGetRmapListHeadPage(Page);
ASSERT(KeGetCurrentIrql() <= APC_LEVEL);
DPRINTC("Entry %x\n", entry);
}
DPRINT("%x:%x, page %x %x\n",
Process,
Address,
Page,
Resources.Page[0]);
ExReleaseFastMutex(&RmapListLock);
PageDirty = FALSE;
Status = MmPageOutCacheSection(AddressSpace,
MemoryArea,
Address,
&PageDirty,
&Resources);
Dirty |= PageDirty;
DPRINT("%x\n", Status);
ASSERT(KeGetCurrentIrql() <= APC_LEVEL);
MmUnlockAddressSpace(AddressSpace);
if (Status == STATUS_SUCCESS + 1)
{
// Wait page ... the other guy has it, so we'll just fail for now
DPRINT1("Wait entry ... can't continue\n");
Status = STATUS_UNSUCCESSFUL;
goto bail;
}
else if (Status == STATUS_MORE_PROCESSING_REQUIRED)
{
DPRINTC("DoAcquisition %x\n", Resources.DoAcquisition);
Status = Resources.DoAcquisition(AddressSpace,
MemoryArea,
&Resources);
DPRINTC("Status %x\n", Status);
if (!NT_SUCCESS(Status))
{
DPRINT1("bail\n");
goto bail;
}
else Status = STATUS_MM_RESTART_OPERATION;
}
MmLockAddressSpace(AddressSpace);
}
while (Status == STATUS_MM_RESTART_OPERATION);
MmUnlockAddressSpace(AddressSpace);
if (ProcRef)
{
ObDereferenceObject(Process);
ProcRef = FALSE;
}
ExAcquireFastMutex(&RmapListLock);
ASSERT(!MM_IS_WAIT_PTE(MmGetPfnForProcess(Process, Address)));
entry = MmGetRmapListHeadPage(Page);
DPRINTC("Entry %x\n", entry);
}
ExReleaseFastMutex(&RmapListLock);
bail:
DPRINTC("BAIL %x\n", Status);
DPRINTC("BAIL %x\n", Status);
if (Segment)
{
ULONG RefCount;
if (Segment)
{
ULONG RefCount;
DPRINTC("About to finalize section page %x (%x:%x) Status %x %s\n", Page, Segment, FileOffset.LowPart, Status, Dirty ? "dirty" : "clean");
DPRINTC("About to finalize section page %x (%x:%x) Status %x %s\n",
Page,
Segment,
FileOffset.LowPart,
Status,
Dirty ? "dirty" : "clean");
if (!NT_SUCCESS(Status) ||
!NT_SUCCESS
(Status = MmFinalizeSectionPageOut
(Segment, &FileOffset, Page, Dirty)))
{
DPRINTC
("Failed to page out %x, replacing %x at %x in segment %x\n",
SectionPage, FileOffset.LowPart, Segment);
MmLockSectionSegment(Segment);
MmSetPageEntrySectionSegment(Segment, &FileOffset, Dirty ? MAKE_PFN_SSE(Page) : DIRTY_SSE(MAKE_PFN_SSE(Page)));
MmUnlockSectionSegment(Segment);
}
if (!NT_SUCCESS(Status) ||
!NT_SUCCESS(Status = MmFinalizeSectionPageOut(Segment,
&FileOffset,
Page,
Dirty)))
{
DPRINTC("Failed to page out %x, replacing %x at %x in segment %x\n",
SectionPage,
FileOffset.LowPart,
Segment);
// Alas, we had the last reference
if ((RefCount = InterlockedDecrementUL(&Segment->ReferenceCount)) == 0)
MmFinalizeSegment(Segment);
}
MmLockSectionSegment(Segment);
if (ProcRef)
{
DPRINTC("Dereferencing process...\n");
ObDereferenceObject(Process);
}
MmSetPageEntrySectionSegment(Segment,
&FileOffset,
Dirty ? MAKE_PFN_SSE(Page) : DIRTY_SSE(MAKE_PFN_SSE(Page)));
ExReleaseFastMutex(&MiGlobalPageOperation);
DPRINTC("%s %x %x\n", NT_SUCCESS(Status) ? "Evicted" : "Spared", Page, Status);
return NT_SUCCESS(Status) ? STATUS_SUCCESS : STATUS_UNSUCCESSFUL;
MmUnlockSectionSegment(Segment);
}
/* Alas, we had the last reference */
if ((RefCount = InterlockedDecrementUL(&Segment->ReferenceCount)) == 0)
MmFinalizeSegment(Segment);
}
if (ProcRef)
{
DPRINTC("Dereferencing process...\n");
ObDereferenceObject(Process);
}
ExReleaseFastMutex(&MiGlobalPageOperation);
DPRINTC("%s %x %x\n",
NT_SUCCESS(Status) ? "Evicted" : "Spared",
Page,
Status);
return NT_SUCCESS(Status) ? STATUS_SUCCESS : STATUS_UNSUCCESSFUL;
}
ULONG
NTAPI
MiCacheEvictPages(PMM_SECTION_SEGMENT Segment, ULONG Target)
MiCacheEvictPages(PMM_SECTION_SEGMENT Segment,
ULONG Target)
{
ULONG Entry, Result = 0, i, j;
NTSTATUS Status;
PFN_NUMBER Page;
LARGE_INTEGER Offset;
ULONG Entry, Result = 0, i, j;
NTSTATUS Status;
PFN_NUMBER Page;
LARGE_INTEGER Offset;
MmLockSectionSegment(Segment);
MmLockSectionSegment(Segment);
for (i = 0; i < RtlNumberGenericTableElements(&Segment->PageTable); i++) {
PCACHE_SECTION_PAGE_TABLE Element = RtlGetElementGenericTable(&Segment->PageTable, i);
ASSERT(Element);
Offset = Element->FileOffset;
for (j = 0; j < ENTRIES_PER_ELEMENT; j++, Offset.QuadPart += PAGE_SIZE) {
Entry = MmGetPageEntrySectionSegment(Segment, &Offset);
if (Entry && !IS_SWAP_FROM_SSE(Entry)) {
Page = PFN_FROM_SSE(Entry);
MmUnlockSectionSegment(Segment);
Status = MmpPageOutPhysicalAddress(Page);
if (NT_SUCCESS(Status))
Result++;
MmLockSectionSegment(Segment);
}
}
}
for (i = 0; i < RtlNumberGenericTableElements(&Segment->PageTable); i++) {
MmUnlockSectionSegment(Segment);
PCACHE_SECTION_PAGE_TABLE Element = RtlGetElementGenericTable(&Segment->PageTable,
i);
return Result;
ASSERT(Element);
Offset = Element->FileOffset;
for (j = 0; j < ENTRIES_PER_ELEMENT; j++, Offset.QuadPart += PAGE_SIZE) {
Entry = MmGetPageEntrySectionSegment(Segment, &Offset);
if (Entry && !IS_SWAP_FROM_SSE(Entry)) {
Page = PFN_FROM_SSE(Entry);
MmUnlockSectionSegment(Segment);
Status = MmpPageOutPhysicalAddress(Page);
if (NT_SUCCESS(Status))
Result++;
MmLockSectionSegment(Segment);
}
}
}
MmUnlockSectionSegment(Segment);
return Result;
}
extern LIST_ENTRY MiSegmentList;
@ -486,7 +560,9 @@ extern LIST_ENTRY MiSegmentList;
// This can fall away when our section implementation supports
// demand paging properly
NTSTATUS
MiRosTrimCache(ULONG Target, ULONG Priority, PULONG NrFreed)
MiRosTrimCache(ULONG Target,
ULONG Priority,
PULONG NrFreed)
{
ULONG Freed;
PLIST_ENTRY Entry;
@ -494,9 +570,11 @@ MiRosTrimCache(ULONG Target, ULONG Priority, PULONG NrFreed)
*NrFreed = 0;
DPRINT1("Need to trim %d cache pages\n", Target);
for (Entry = MiSegmentList.Flink; *NrFreed < Target && Entry != &MiSegmentList; Entry = Entry->Flink) {
for (Entry = MiSegmentList.Flink;
*NrFreed < Target && Entry != &MiSegmentList;
Entry = Entry->Flink) {
Segment = CONTAINING_RECORD(Entry, MM_SECTION_SEGMENT, ListOfSegments);
// Defer to MM to try recovering pages from it
/* Defer to MM to try recovering pages from it */
Freed = MiCacheEvictPages(Segment, Target);
*NrFreed += Freed;
}