diff --git a/reactos/ntoskrnl/cache/section/data.c b/reactos/ntoskrnl/cache/section/data.c index 486bb0e1e34..3a9b84973e1 100644 --- a/reactos/ntoskrnl/cache/section/data.c +++ b/reactos/ntoskrnl/cache/section/data.c @@ -65,8 +65,8 @@ ULONG_PTR MmSubsectionBase; static const INFORMATION_CLASS_INFO ExSectionInfoClass[] = { - ICI_SQ_SAME( sizeof(SECTION_BASIC_INFORMATION), sizeof(ULONG), ICIF_QUERY ), /* SectionBasicInformation */ - ICI_SQ_SAME( sizeof(SECTION_IMAGE_INFORMATION), sizeof(ULONG), ICIF_QUERY ), /* SectionImageInformation */ + ICI_SQ_SAME( sizeof(SECTION_BASIC_INFORMATION), sizeof(ULONG), ICIF_QUERY ), /* SectionBasicInformation */ + ICI_SQ_SAME( sizeof(SECTION_IMAGE_INFORMATION), sizeof(ULONG), ICIF_QUERY ), /* SectionImageInformation */ }; /* FUNCTIONS *****************************************************************/ @@ -77,714 +77,776 @@ VOID NTAPI _MmLockSectionSegment(PMM_SECTION_SEGMENT Segment, const char *file, int line) { - //DPRINT("MmLockSectionSegment(%p,%s:%d)\n", Segment, file, line); - ExAcquireFastMutex(&Segment->Lock); - Segment->Locked = TRUE; + //DPRINT("MmLockSectionSegment(%p,%s:%d)\n", Segment, file, line); + ExAcquireFastMutex(&Segment->Lock); + Segment->Locked = TRUE; } VOID NTAPI _MmUnlockSectionSegment(PMM_SECTION_SEGMENT Segment, const char *file, int line) { - ASSERT(Segment->Locked); - Segment->Locked = FALSE; - ExReleaseFastMutex(&Segment->Lock); - //DPRINT("MmUnlockSectionSegment(%p,%s:%d)\n", Segment, file, line); + ASSERT(Segment->Locked); + Segment->Locked = FALSE; + ExReleaseFastMutex(&Segment->Lock); + //DPRINT("MmUnlockSectionSegment(%p,%s:%d)\n", Segment, file, line); } NTSTATUS NTAPI -MiZeroFillSection -(PVOID Address, - PLARGE_INTEGER FileOffsetPtr, - ULONG Length) +MiZeroFillSection(PVOID Address, PLARGE_INTEGER FileOffsetPtr, ULONG Length) { - PFN_NUMBER Page; - PMMSUPPORT AddressSpace; - PMEMORY_AREA MemoryArea; - PMM_SECTION_SEGMENT Segment; - LARGE_INTEGER FileOffset = *FileOffsetPtr, End, FirstMapped; - KIRQL OldIrql; + PFN_NUMBER Page; + PMMSUPPORT AddressSpace; + PMEMORY_AREA MemoryArea; + PMM_SECTION_SEGMENT Segment; + LARGE_INTEGER FileOffset = *FileOffsetPtr, End, FirstMapped; + KIRQL OldIrql; - DPRINT("MiZeroFillSection(Address %x,Offset %x,Length %x)\n", Address, FileOffset.LowPart, Length); + DPRINT("MiZeroFillSection(Address %x,Offset %x,Length %x)\n", + Address, + FileOffset.LowPart, + Length); - AddressSpace = MmGetKernelAddressSpace(); + AddressSpace = MmGetKernelAddressSpace(); - MmLockAddressSpace(AddressSpace); - MemoryArea = MmLocateMemoryAreaByAddress(AddressSpace, Address); - MmUnlockAddressSpace(AddressSpace); - if (!MemoryArea || MemoryArea->Type != MEMORY_AREA_SECTION_VIEW || MemoryArea->DeleteInProgress) - { - return STATUS_NOT_MAPPED_DATA; - } + MmLockAddressSpace(AddressSpace); + MemoryArea = MmLocateMemoryAreaByAddress(AddressSpace, Address); + MmUnlockAddressSpace(AddressSpace); + if (!MemoryArea || MemoryArea->Type != MEMORY_AREA_SECTION_VIEW || MemoryArea->DeleteInProgress) + { + return STATUS_NOT_MAPPED_DATA; + } - Segment = MemoryArea->Data.SectionData.Segment; - End.QuadPart = FileOffset.QuadPart + Length; - End.LowPart = PAGE_ROUND_DOWN(End.LowPart); - FileOffset.LowPart = PAGE_ROUND_UP(FileOffset.LowPart); - FirstMapped.QuadPart = MemoryArea->Data.SectionData.ViewOffset.QuadPart; - DPRINT - ("Pulling zero pages for %08x%08x-%08x%08x\n", - FileOffset.u.HighPart, FileOffset.u.LowPart, - End.u.HighPart, End.u.LowPart); - while (FileOffset.QuadPart < End.QuadPart) - { - PVOID Address; - ULONG Entry; + Segment = MemoryArea->Data.SectionData.Segment; + End.QuadPart = FileOffset.QuadPart + Length; + End.LowPart = PAGE_ROUND_DOWN(End.LowPart); + FileOffset.LowPart = PAGE_ROUND_UP(FileOffset.LowPart); + FirstMapped.QuadPart = MemoryArea->Data.SectionData.ViewOffset.QuadPart; + DPRINT("Pulling zero pages for %08x%08x-%08x%08x\n", + FileOffset.u.HighPart, FileOffset.u.LowPart, + End.u.HighPart, End.u.LowPart); + while (FileOffset.QuadPart < End.QuadPart) + { + PVOID Address; + ULONG Entry; - if (!NT_SUCCESS(MmRequestPageMemoryConsumer(MC_CACHE, TRUE, &Page))) - break; + if (!NT_SUCCESS(MmRequestPageMemoryConsumer(MC_CACHE, TRUE, &Page))) + break; - MmLockAddressSpace(AddressSpace); - MmLockSectionSegment(Segment); + MmLockAddressSpace(AddressSpace); + MmLockSectionSegment(Segment); - Entry = MmGetPageEntrySectionSegment(Segment, &FileOffset); - if (Entry == 0) - { - MmSetPageEntrySectionSegment(Segment, &FileOffset, MAKE_PFN_SSE(Page)); - Address = ((PCHAR)MemoryArea->StartingAddress) + FileOffset.QuadPart - FirstMapped.QuadPart; + Entry = MmGetPageEntrySectionSegment(Segment, &FileOffset); + if (Entry == 0) + { + MmSetPageEntrySectionSegment(Segment, &FileOffset, MAKE_PFN_SSE(Page)); + Address = ((PCHAR)MemoryArea->StartingAddress) + FileOffset.QuadPart - FirstMapped.QuadPart; - OldIrql = KeAcquireQueuedSpinLock(LockQueuePfnLock); - MmReferencePage(Page); - KeReleaseQueuedSpinLock(LockQueuePfnLock, OldIrql); + OldIrql = KeAcquireQueuedSpinLock(LockQueuePfnLock); + MmReferencePage(Page); + KeReleaseQueuedSpinLock(LockQueuePfnLock, OldIrql); - MmCreateVirtualMapping(NULL, Address, PAGE_READWRITE, &Page, 1); - MmInsertRmap(Page, NULL, Address); - } - else - MmReleasePageMemoryConsumer(MC_CACHE, Page); + MmCreateVirtualMapping(NULL, Address, PAGE_READWRITE, &Page, 1); + MmInsertRmap(Page, NULL, Address); + } + else + { + MmReleasePageMemoryConsumer(MC_CACHE, Page); + } - MmUnlockSectionSegment(Segment); - MmUnlockAddressSpace(AddressSpace); + MmUnlockSectionSegment(Segment); + MmUnlockAddressSpace(AddressSpace); - FileOffset.QuadPart += PAGE_SIZE; - } - return STATUS_SUCCESS; + FileOffset.QuadPart += PAGE_SIZE; + } + return STATUS_SUCCESS; } NTSTATUS NTAPI -_MiFlushMappedSection -(PVOID BaseAddress, - PLARGE_INTEGER BaseOffset, - PLARGE_INTEGER FileSize, - BOOLEAN WriteData, - const char *File, - int Line) +_MiFlushMappedSection(PVOID BaseAddress, + PLARGE_INTEGER BaseOffset, + PLARGE_INTEGER FileSize, + BOOLEAN WriteData, + const char *File, + int Line) { - NTSTATUS Status = STATUS_SUCCESS; - ULONG_PTR PageAddress; - PMMSUPPORT AddressSpace = MmGetKernelAddressSpace(); - PMEMORY_AREA MemoryArea; - PMM_SECTION_SEGMENT Segment; - ULONG_PTR BeginningAddress, EndingAddress; - LARGE_INTEGER ViewOffset; - LARGE_INTEGER FileOffset; - PFN_NUMBER Page; - PPFN_NUMBER Pages; - KIRQL OldIrql; + NTSTATUS Status = STATUS_SUCCESS; + ULONG_PTR PageAddress; + PMMSUPPORT AddressSpace = MmGetKernelAddressSpace(); + PMEMORY_AREA MemoryArea; + PMM_SECTION_SEGMENT Segment; + ULONG_PTR BeginningAddress, EndingAddress; + LARGE_INTEGER ViewOffset; + LARGE_INTEGER FileOffset; + PFN_NUMBER Page; + PPFN_NUMBER Pages; + KIRQL OldIrql; - DPRINT("MiFlushMappedSection(%x,%08x,%x,%d,%s:%d)\n", BaseAddress, BaseOffset->LowPart, FileSize, WriteData, File, Line); + DPRINT("MiFlushMappedSection(%x,%08x,%x,%d,%s:%d)\n", + BaseAddress, + BaseOffset->LowPart, + FileSize, + WriteData, + File, + Line); - MmLockAddressSpace(AddressSpace); - MemoryArea = MmLocateMemoryAreaByAddress(AddressSpace, BaseAddress); - if (!MemoryArea || MemoryArea->Type != MEMORY_AREA_CACHE || MemoryArea->DeleteInProgress) - { - MmUnlockAddressSpace(AddressSpace); - DPRINT("STATUS_NOT_MAPPED_DATA\n"); - return STATUS_NOT_MAPPED_DATA; - } - BeginningAddress = PAGE_ROUND_DOWN((ULONG_PTR)MemoryArea->StartingAddress); - EndingAddress = PAGE_ROUND_UP((ULONG_PTR)MemoryArea->EndingAddress); - Segment = MemoryArea->Data.SectionData.Segment; - ViewOffset.QuadPart = MemoryArea->Data.SectionData.ViewOffset.QuadPart; + MmLockAddressSpace(AddressSpace); + MemoryArea = MmLocateMemoryAreaByAddress(AddressSpace, BaseAddress); + if (!MemoryArea || MemoryArea->Type != MEMORY_AREA_CACHE || MemoryArea->DeleteInProgress) + { + MmUnlockAddressSpace(AddressSpace); + DPRINT("STATUS_NOT_MAPPED_DATA\n"); + return STATUS_NOT_MAPPED_DATA; + } + BeginningAddress = PAGE_ROUND_DOWN((ULONG_PTR)MemoryArea->StartingAddress); + EndingAddress = PAGE_ROUND_UP((ULONG_PTR)MemoryArea->EndingAddress); + Segment = MemoryArea->Data.SectionData.Segment; + ViewOffset.QuadPart = MemoryArea->Data.SectionData.ViewOffset.QuadPart; - ASSERT(ViewOffset.QuadPart == BaseOffset->QuadPart); + ASSERT(ViewOffset.QuadPart == BaseOffset->QuadPart); - MmLockSectionSegment(Segment); + MmLockSectionSegment(Segment); - Pages = ExAllocatePool - (NonPagedPool, - sizeof(PFN_NUMBER) * - ((EndingAddress - BeginningAddress) >> PAGE_SHIFT)); + Pages = ExAllocatePool(NonPagedPool, + sizeof(PFN_NUMBER) * ((EndingAddress - BeginningAddress) >> PAGE_SHIFT)); - if (!Pages) - { - ASSERT(FALSE); - } + if (!Pages) + { + ASSERT(FALSE); + } - //DPRINT("Getting pages in range %08x-%08x\n", BeginningAddress, EndingAddress); + //DPRINT("Getting pages in range %08x-%08x\n", BeginningAddress, EndingAddress); - for (PageAddress = BeginningAddress; - PageAddress < EndingAddress; - PageAddress += PAGE_SIZE) - { - ULONG Entry; - FileOffset.QuadPart = ViewOffset.QuadPart + PageAddress - BeginningAddress; - Entry = - MmGetPageEntrySectionSegment - (MemoryArea->Data.SectionData.Segment, - &FileOffset); - Page = PFN_FROM_SSE(Entry); - if (Entry != 0 && !IS_SWAP_FROM_SSE(Entry) && - (MmIsDirtyPageRmap(Page) || IS_DIRTY_SSE(Entry)) && - FileOffset.QuadPart < FileSize->QuadPart) - { - OldIrql = KeAcquireQueuedSpinLock(LockQueuePfnLock); - MmReferencePage(Page); - KeReleaseQueuedSpinLock(LockQueuePfnLock, OldIrql); - Pages[(PageAddress - BeginningAddress) >> PAGE_SHIFT] = Entry; - } - else - Pages[(PageAddress - BeginningAddress) >> PAGE_SHIFT] = 0; - } + for (PageAddress = BeginningAddress; + PageAddress < EndingAddress; + PageAddress += PAGE_SIZE) + { + ULONG Entry; + FileOffset.QuadPart = ViewOffset.QuadPart + PageAddress - BeginningAddress; + Entry = MmGetPageEntrySectionSegment(MemoryArea->Data.SectionData.Segment, + &FileOffset); + Page = PFN_FROM_SSE(Entry); + if (Entry != 0 && !IS_SWAP_FROM_SSE(Entry) && + (MmIsDirtyPageRmap(Page) || IS_DIRTY_SSE(Entry)) && + FileOffset.QuadPart < FileSize->QuadPart) + { + OldIrql = KeAcquireQueuedSpinLock(LockQueuePfnLock); + MmReferencePage(Page); + KeReleaseQueuedSpinLock(LockQueuePfnLock, OldIrql); + Pages[(PageAddress - BeginningAddress) >> PAGE_SHIFT] = Entry; + } + else + { + Pages[(PageAddress - BeginningAddress) >> PAGE_SHIFT] = 0; + } + } - MmUnlockSectionSegment(Segment); - MmUnlockAddressSpace(AddressSpace); + MmUnlockSectionSegment(Segment); + MmUnlockAddressSpace(AddressSpace); - for (PageAddress = BeginningAddress; - PageAddress < EndingAddress; - PageAddress += PAGE_SIZE) - { - ULONG Entry; - FileOffset.QuadPart = ViewOffset.QuadPart + PageAddress - BeginningAddress; - Entry = Pages[(PageAddress - BeginningAddress) >> PAGE_SHIFT]; - Page = PFN_FROM_SSE(Entry); - if (Page) - { - if (WriteData) { - //DPRINT("MiWriteBackPage(%wZ,addr %x,%08x%08x)\n", &Segment->FileObject->FileName, PageAddress, FileOffset.u.HighPart, FileOffset.u.LowPart); - Status = MiWriteBackPage(Segment->FileObject, &FileOffset, PAGE_SIZE, Page); - } else - Status = STATUS_SUCCESS; + for (PageAddress = BeginningAddress; + PageAddress < EndingAddress; + PageAddress += PAGE_SIZE) + { + ULONG Entry; + FileOffset.QuadPart = ViewOffset.QuadPart + PageAddress - BeginningAddress; + Entry = Pages[(PageAddress - BeginningAddress) >> PAGE_SHIFT]; + Page = PFN_FROM_SSE(Entry); + if (Page) + { + if (WriteData) { + //DPRINT("MiWriteBackPage(%wZ,addr %x,%08x%08x)\n", &Segment->FileObject->FileName, PageAddress, FileOffset.u.HighPart, FileOffset.u.LowPart); + Status = MiWriteBackPage(Segment->FileObject, &FileOffset, PAGE_SIZE, Page); + } else + Status = STATUS_SUCCESS; - if (NT_SUCCESS(Status)) { - MmLockAddressSpace(AddressSpace); - MmSetCleanAllRmaps(Page); - MmSetPageProtect(MmGetAddressSpaceOwner(AddressSpace), (PVOID)PageAddress, PAGE_READONLY); - MmLockSectionSegment(Segment); - Entry = MmGetPageEntrySectionSegment(Segment, &FileOffset); - if (Entry && !IS_SWAP_FROM_SSE(Entry) && PFN_FROM_SSE(Entry) == Page) - MmSetPageEntrySectionSegment(Segment, &FileOffset, CLEAN_SSE(Entry)); - MmUnlockSectionSegment(Segment); - MmUnlockAddressSpace(AddressSpace); - } else { - DPRINT - ("Writeback from section flush %08x%08x (%x) %x@%x (%08x%08x:%wZ) failed %x\n", - FileOffset.u.HighPart, FileOffset.u.LowPart, - (ULONG)(FileSize->QuadPart - FileOffset.QuadPart), - PageAddress, - Page, - FileSize->u.HighPart, - FileSize->u.LowPart, - &Segment->FileObject->FileName, - Status); - } - MmReleasePageMemoryConsumer(MC_CACHE, Page); - } - } + if (NT_SUCCESS(Status)) { + MmLockAddressSpace(AddressSpace); + MmSetCleanAllRmaps(Page); - ExFreePool(Pages); + MmSetPageProtect(MmGetAddressSpaceOwner(AddressSpace), + (PVOID)PageAddress, + PAGE_READONLY); - return Status; + MmLockSectionSegment(Segment); + Entry = MmGetPageEntrySectionSegment(Segment, &FileOffset); + + if (Entry && !IS_SWAP_FROM_SSE(Entry) && PFN_FROM_SSE(Entry) == Page) + MmSetPageEntrySectionSegment(Segment, &FileOffset, CLEAN_SSE(Entry)); + + MmUnlockSectionSegment(Segment); + MmUnlockAddressSpace(AddressSpace); + } else { + DPRINT("Writeback from section flush %08x%08x (%x) %x@%x (%08x%08x:%wZ) failed %x\n", + FileOffset.u.HighPart, + FileOffset.u.LowPart, + (ULONG)(FileSize->QuadPart - FileOffset.QuadPart), + PageAddress, + Page, + FileSize->u.HighPart, + FileSize->u.LowPart, + &Segment->FileObject->FileName, + Status); + } + MmReleasePageMemoryConsumer(MC_CACHE, Page); + } + } + + ExFreePool(Pages); + + return Status; } VOID NTAPI MmFinalizeSegment(PMM_SECTION_SEGMENT Segment) { - KIRQL OldIrql = 0; + KIRQL OldIrql = 0; - DPRINT("Finalize segment %p\n", Segment); + DPRINT("Finalize segment %p\n", Segment); - MmLockSectionSegment(Segment); - RemoveEntryList(&Segment->ListOfSegments); - if (Segment->Flags & MM_DATAFILE_SEGMENT) { - KeAcquireSpinLock(&Segment->FileObject->IrpListLock, &OldIrql); - if (Segment->Flags & MM_SEGMENT_FINALIZE) { - KeReleaseSpinLock(&Segment->FileObject->IrpListLock, OldIrql); - MmUnlockSectionSegment(Segment); - return; - } - Segment->Flags |= MM_SEGMENT_FINALIZE; - DPRINTC("Finalizing data file segment %p\n", Segment); + MmLockSectionSegment(Segment); + RemoveEntryList(&Segment->ListOfSegments); + if (Segment->Flags & MM_DATAFILE_SEGMENT) { + KeAcquireSpinLock(&Segment->FileObject->IrpListLock, &OldIrql); + if (Segment->Flags & MM_SEGMENT_FINALIZE) { + KeReleaseSpinLock(&Segment->FileObject->IrpListLock, OldIrql); + MmUnlockSectionSegment(Segment); + return; + } + Segment->Flags |= MM_SEGMENT_FINALIZE; + DPRINTC("Finalizing data file segment %p\n", Segment); - Segment->FileObject->SectionObjectPointer->DataSectionObject = NULL; - KeReleaseSpinLock(&Segment->FileObject->IrpListLock, OldIrql); - MmFreePageTablesSectionSegment(Segment, MiFreeSegmentPage); - MmUnlockSectionSegment(Segment); - DPRINT("Dereference file object %wZ\n", &Segment->FileObject->FileName); - ObDereferenceObject(Segment->FileObject); - DPRINT("Done with %wZ\n", &Segment->FileObject->FileName); - Segment->FileObject = NULL; - } else { - DPRINTC("Finalizing segment %p\n", Segment); - MmFreePageTablesSectionSegment(Segment, MiFreeSegmentPage); - MmUnlockSectionSegment(Segment); - } - DPRINTC("Segment %p destroy\n", Segment); - ExFreePoolWithTag(Segment, TAG_MM_SECTION_SEGMENT); + Segment->FileObject->SectionObjectPointer->DataSectionObject = NULL; + KeReleaseSpinLock(&Segment->FileObject->IrpListLock, OldIrql); + MmFreePageTablesSectionSegment(Segment, MiFreeSegmentPage); + MmUnlockSectionSegment(Segment); + DPRINT("Dereference file object %wZ\n", &Segment->FileObject->FileName); + ObDereferenceObject(Segment->FileObject); + DPRINT("Done with %wZ\n", &Segment->FileObject->FileName); + Segment->FileObject = NULL; + } else { + DPRINTC("Finalizing segment %p\n", Segment); + MmFreePageTablesSectionSegment(Segment, MiFreeSegmentPage); + MmUnlockSectionSegment(Segment); + } + DPRINTC("Segment %p destroy\n", Segment); + ExFreePoolWithTag(Segment, TAG_MM_SECTION_SEGMENT); } NTSTATUS NTAPI MmCreateCacheSection(PROS_SECTION_OBJECT *SectionObject, - ACCESS_MASK DesiredAccess, - POBJECT_ATTRIBUTES ObjectAttributes, - PLARGE_INTEGER UMaximumSize, - ULONG SectionPageProtection, - ULONG AllocationAttributes, - PFILE_OBJECT FileObject) + ACCESS_MASK DesiredAccess, + POBJECT_ATTRIBUTES ObjectAttributes, + PLARGE_INTEGER UMaximumSize, + ULONG SectionPageProtection, + ULONG AllocationAttributes, + PFILE_OBJECT FileObject) /* * Create a section backed by a data file */ { - PROS_SECTION_OBJECT Section; - NTSTATUS Status; - ULARGE_INTEGER MaximumSize; - PMM_SECTION_SEGMENT Segment; - IO_STATUS_BLOCK Iosb; - CC_FILE_SIZES FileSizes; - FILE_STANDARD_INFORMATION FileInfo; - KIRQL OldIrql; + PROS_SECTION_OBJECT Section; + NTSTATUS Status; + ULARGE_INTEGER MaximumSize; + PMM_SECTION_SEGMENT Segment; + IO_STATUS_BLOCK Iosb; + CC_FILE_SIZES FileSizes; + FILE_STANDARD_INFORMATION FileInfo; + KIRQL OldIrql; - DPRINT("MmCreateDataFileSection\n"); + DPRINT("MmCreateDataFileSection\n"); - /* - * Create the section - */ - Status = ObCreateObject(ExGetPreviousMode(), - MmSectionObjectType, - ObjectAttributes, - ExGetPreviousMode(), - NULL, - sizeof(ROS_SECTION_OBJECT), - 0, - 0, - (PVOID*)(PVOID)&Section); - if (!NT_SUCCESS(Status)) - { - DPRINT("Failed: %x\n", Status); - return(Status); - } - /* - * Initialize it - */ - RtlZeroMemory(Section, sizeof(ROS_SECTION_OBJECT)); - Section->Type = 'SC'; - Section->Size = 'TN'; - Section->SectionPageProtection = SectionPageProtection; - Section->AllocationAttributes = AllocationAttributes; - Section->Segment = NULL; + /* Create the section */ + Status = ObCreateObject(ExGetPreviousMode(), + MmSectionObjectType, + ObjectAttributes, + ExGetPreviousMode(), + NULL, + sizeof(ROS_SECTION_OBJECT), + 0, + 0, + (PVOID*)(PVOID)&Section); + if (!NT_SUCCESS(Status)) + { + DPRINT("Failed: %x\n", Status); + return Status; + } - Section->FileObject = FileObject; + /* Initialize it */ + RtlZeroMemory(Section, sizeof(ROS_SECTION_OBJECT)); + Section->Type = 'SC'; + Section->Size = 'TN'; + Section->SectionPageProtection = SectionPageProtection; + Section->AllocationAttributes = AllocationAttributes; + Section->Segment = NULL; - DPRINT("Getting original file size\n"); - /* A hack: If we're cached, we can overcome deadlocking with the upper + Section->FileObject = FileObject; + + DPRINT("Getting original file size\n"); + /* A hack: If we're cached, we can overcome deadlocking with the upper * layer filesystem call by retriving the object sizes from the cache * which is made to keep track. If I had to guess, they were figuring * out a similar problem. */ - if (!CcGetFileSizes(FileObject, &FileSizes)) - { - /* - * FIXME: This is propably not entirely correct. We can't look into - * the standard FCB header because it might not be initialized yet - * (as in case of the EXT2FS driver by Manoj Paul Joseph where the - * standard file information is filled on first request). - */ - DPRINT("Querying info\n"); - Status = IoQueryFileInformation - (FileObject, - FileStandardInformation, - sizeof(FILE_STANDARD_INFORMATION), - &FileInfo, - &Iosb.Information); - DPRINT("Query => %x\n", Status); + if (!CcGetFileSizes(FileObject, &FileSizes)) + { + /* + * FIXME: This is propably not entirely correct. We can't look into + * the standard FCB header because it might not be initialized yet + * (as in case of the EXT2FS driver by Manoj Paul Joseph where the + * standard file information is filled on first request). + */ + DPRINT("Querying info\n"); + Status = IoQueryFileInformation(FileObject, + FileStandardInformation, + sizeof(FILE_STANDARD_INFORMATION), + &FileInfo, + &Iosb.Information); + DPRINT("Query => %x\n", Status); - if (!NT_SUCCESS(Status)) - { - DPRINT("Status %x\n", Status); - ObDereferenceObject(Section); - return Status; - } - ASSERT(Status != STATUS_PENDING); + if (!NT_SUCCESS(Status)) + { + DPRINT("Status %x\n", Status); + ObDereferenceObject(Section); + return Status; + } + ASSERT(Status != STATUS_PENDING); - FileSizes.ValidDataLength = FileInfo.EndOfFile; - FileSizes.FileSize = FileInfo.EndOfFile; - } - DPRINT("Got %08x\n", FileSizes.ValidDataLength.u.LowPart); + FileSizes.ValidDataLength = FileInfo.EndOfFile; + FileSizes.FileSize = FileInfo.EndOfFile; + } + DPRINT("Got %08x\n", FileSizes.ValidDataLength.u.LowPart); - /* + /* * FIXME: Revise this once a locking order for file size changes is * decided - * - * We're handed down a maximum size in every case. Should we still check at all? + * + * We're handed down a maximum size in every case. Should we still check at all? */ - if (UMaximumSize != NULL && UMaximumSize->QuadPart) - { - DPRINT("Taking maximum %x\n", UMaximumSize->LowPart); - MaximumSize.QuadPart = UMaximumSize->QuadPart; - } - else - { - DPRINT("Got file size %08x%08x\n", FileSizes.FileSize.u.HighPart, FileSizes.FileSize.u.LowPart); - MaximumSize.QuadPart = FileSizes.FileSize.QuadPart; - } + if (UMaximumSize != NULL && UMaximumSize->QuadPart) + { + DPRINT("Taking maximum %x\n", UMaximumSize->LowPart); + MaximumSize.QuadPart = UMaximumSize->QuadPart; + } + else + { + DPRINT("Got file size %08x%08x\n", + FileSizes.FileSize.u.HighPart, + FileSizes.FileSize.u.LowPart); - /* Mapping zero-sized files isn't allowed. */ - if (MaximumSize.QuadPart == 0) - { - DPRINT("Zero size file\n"); - ObDereferenceObject(Section); - return STATUS_FILE_INVALID; - } + MaximumSize.QuadPart = FileSizes.FileSize.QuadPart; + } - Segment = ExAllocatePoolWithTag(NonPagedPool, sizeof(MM_SECTION_SEGMENT), - TAG_MM_SECTION_SEGMENT); - if (Segment == NULL) - { - DPRINT("Failed: STATUS_NO_MEMORY\n"); - ObDereferenceObject(Section); - return(STATUS_NO_MEMORY); - } + /* Mapping zero-sized files isn't allowed. */ + if (MaximumSize.QuadPart == 0) + { + DPRINT("Zero size file\n"); + ObDereferenceObject(Section); + return STATUS_FILE_INVALID; + } - DPRINT("Zeroing %x\n", Segment); - RtlZeroMemory(Segment, sizeof(MM_SECTION_SEGMENT)); - ExInitializeFastMutex(&Segment->Lock); + Segment = ExAllocatePoolWithTag(NonPagedPool, + sizeof(MM_SECTION_SEGMENT), + TAG_MM_SECTION_SEGMENT); + if (Segment == NULL) + { + DPRINT("Failed: STATUS_NO_MEMORY\n"); + ObDereferenceObject(Section); + return STATUS_NO_MEMORY; + } - Segment->ReferenceCount = 1; - Segment->Locked = TRUE; - RtlZeroMemory(&Segment->Image, sizeof(Segment->Image)); - Section->Segment = Segment; - - KeAcquireSpinLock(&FileObject->IrpListLock, &OldIrql); - /* + DPRINT("Zeroing %x\n", Segment); + RtlZeroMemory(Segment, sizeof(MM_SECTION_SEGMENT)); + ExInitializeFastMutex(&Segment->Lock); + + Segment->ReferenceCount = 1; + Segment->Locked = TRUE; + RtlZeroMemory(&Segment->Image, sizeof(Segment->Image)); + Section->Segment = Segment; + + KeAcquireSpinLock(&FileObject->IrpListLock, &OldIrql); + /* * If this file hasn't been mapped as a data file before then allocate a * section segment to describe the data file mapping */ - if (FileObject->SectionObjectPointer->DataSectionObject == NULL) - { - FileObject->SectionObjectPointer->DataSectionObject = (PVOID)Segment; - KeReleaseSpinLock(&FileObject->IrpListLock, OldIrql); + if (FileObject->SectionObjectPointer->DataSectionObject == NULL) + { + FileObject->SectionObjectPointer->DataSectionObject = (PVOID)Segment; + KeReleaseSpinLock(&FileObject->IrpListLock, OldIrql); - /* - * Set the lock before assigning the segment to the file object - */ - ExAcquireFastMutex(&Segment->Lock); + /* + * Set the lock before assigning the segment to the file object + */ + ExAcquireFastMutex(&Segment->Lock); - DPRINT("Filling out Segment info (No previous data section)\n"); - ObReferenceObject(FileObject); - Segment->FileObject = FileObject; - Segment->Protection = SectionPageProtection; - Segment->Flags = MM_DATAFILE_SEGMENT; - memset(&Segment->Image, 0, sizeof(Segment->Image)); - Segment->WriteCopy = FALSE; + DPRINT("Filling out Segment info (No previous data section)\n"); + ObReferenceObject(FileObject); + Segment->FileObject = FileObject; + Segment->Protection = SectionPageProtection; + Segment->Flags = MM_DATAFILE_SEGMENT; + memset(&Segment->Image, 0, sizeof(Segment->Image)); + Segment->WriteCopy = FALSE; - if (AllocationAttributes & SEC_RESERVE) - { - Segment->Length.QuadPart = Segment->RawLength.QuadPart = 0; - } - else - { - Segment->RawLength.QuadPart = MaximumSize.QuadPart; - Segment->Length.QuadPart = PAGE_ROUND_UP(Segment->RawLength.QuadPart); - } - MiInitializeSectionPageTable(Segment); - InsertHeadList(&MiSegmentList, &Segment->ListOfSegments); - } - else - { - KeReleaseSpinLock(&FileObject->IrpListLock, OldIrql); - DPRINTC("Free Segment %x\n", Segment); - ExFreePool(Segment); + if (AllocationAttributes & SEC_RESERVE) + { + Segment->Length.QuadPart = Segment->RawLength.QuadPart = 0; + } + else + { + Segment->RawLength.QuadPart = MaximumSize.QuadPart; + Segment->Length.QuadPart = PAGE_ROUND_UP(Segment->RawLength.QuadPart); + } + MiInitializeSectionPageTable(Segment); + InsertHeadList(&MiSegmentList, &Segment->ListOfSegments); + } + else + { + KeReleaseSpinLock(&FileObject->IrpListLock, OldIrql); + DPRINTC("Free Segment %x\n", Segment); + ExFreePool(Segment); - DPRINT("Filling out Segment info (previous data section)\n"); + DPRINT("Filling out Segment info (previous data section)\n"); - /* - * If the file is already mapped as a data file then we may need - * to extend it - */ - Segment = - (PMM_SECTION_SEGMENT)FileObject->SectionObjectPointer-> - DataSectionObject; - Section->Segment = Segment; - (void)InterlockedIncrementUL(&Segment->ReferenceCount); + /* + * If the file is already mapped as a data file then we may need + * to extend it + */ + Segment = (PMM_SECTION_SEGMENT)FileObject->SectionObjectPointer->DataSectionObject; + Section->Segment = Segment; + (void)InterlockedIncrementUL(&Segment->ReferenceCount); - MmLockSectionSegment(Segment); + MmLockSectionSegment(Segment); - if (MaximumSize.QuadPart > Segment->RawLength.QuadPart && + if (MaximumSize.QuadPart > Segment->RawLength.QuadPart && !(AllocationAttributes & SEC_RESERVE)) - { - Segment->RawLength.QuadPart = MaximumSize.QuadPart; - Segment->Length.QuadPart = PAGE_ROUND_UP(Segment->RawLength.QuadPart); - } - } + { + Segment->RawLength.QuadPart = MaximumSize.QuadPart; + Segment->Length.QuadPart = PAGE_ROUND_UP(Segment->RawLength.QuadPart); + } + } - MmUnlockSectionSegment(Segment); + MmUnlockSectionSegment(Segment); - Section->MaximumSize.QuadPart = MaximumSize.QuadPart; + Section->MaximumSize.QuadPart = MaximumSize.QuadPart; - /* Extend file if section is longer */ - DPRINT("MaximumSize %08x%08x ValidDataLength %08x%08x\n", - MaximumSize.u.HighPart, MaximumSize.u.LowPart, - FileSizes.ValidDataLength.u.HighPart, FileSizes.ValidDataLength.u.LowPart); - if (MaximumSize.QuadPart > FileSizes.ValidDataLength.QuadPart) - { - DPRINT("Changing file size to %08x%08x, segment %x\n", MaximumSize.u.HighPart, MaximumSize.u.LowPart, Segment); - Status = IoSetInformation(FileObject, FileEndOfFileInformation, sizeof(LARGE_INTEGER), &MaximumSize); - DPRINT("Change: Status %x\n", Status); - if (!NT_SUCCESS(Status)) - { - DPRINT("Could not expand section\n"); - ObDereferenceObject(Section); - return Status; - } - } + /* Extend file if section is longer */ + DPRINT("MaximumSize %08x%08x ValidDataLength %08x%08x\n", + MaximumSize.u.HighPart, + MaximumSize.u.LowPart, + FileSizes.ValidDataLength.u.HighPart, + FileSizes.ValidDataLength.u.LowPart); + if (MaximumSize.QuadPart > FileSizes.ValidDataLength.QuadPart) + { + DPRINT("Changing file size to %08x%08x, segment %x\n", + MaximumSize.u.HighPart, + MaximumSize.u.LowPart, + Segment); - DPRINTC("Segment %x created (%x)\n", Segment, Segment->Flags); + Status = IoSetInformation(FileObject, + FileEndOfFileInformation, + sizeof(LARGE_INTEGER), + &MaximumSize); - *SectionObject = Section; - return(STATUS_SUCCESS); + DPRINT("Change: Status %x\n", Status); + if (!NT_SUCCESS(Status)) + { + DPRINT("Could not expand section\n"); + ObDereferenceObject(Section); + return Status; + } + } + + DPRINTC("Segment %x created (%x)\n", Segment, Segment->Flags); + + *SectionObject = Section; + return STATUS_SUCCESS; } 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) { - PMEMORY_AREA MArea; - NTSTATUS Status; - PHYSICAL_ADDRESS BoundaryAddressMultiple; + PMEMORY_AREA MArea; + NTSTATUS Status; + PHYSICAL_ADDRESS BoundaryAddressMultiple; - BoundaryAddressMultiple.QuadPart = 0; + BoundaryAddressMultiple.QuadPart = 0; - Status = MmCreateMemoryArea - (AddressSpace, - MEMORY_AREA_CACHE, - BaseAddress, - ViewSize, - Protect, - &MArea, - FALSE, - AllocationType, - BoundaryAddressMultiple); + Status = MmCreateMemoryArea(AddressSpace, + MEMORY_AREA_CACHE, + BaseAddress, + ViewSize, + Protect, + &MArea, + FALSE, + AllocationType, + BoundaryAddressMultiple); - if (!NT_SUCCESS(Status)) - { - DPRINT("Mapping between 0x%.8X and 0x%.8X failed (%X).\n", - (*BaseAddress), (char*)(*BaseAddress) + ViewSize, Status); - return(Status); - } + if (!NT_SUCCESS(Status)) + { + DPRINT("Mapping between 0x%.8X and 0x%.8X failed (%X).\n", + (*BaseAddress), + (char*)(*BaseAddress) + ViewSize, + Status); - DPRINTC("MiMapViewOfSegment %x %x %x %x %x %wZ %s:%d\n", MmGetAddressSpaceOwner(AddressSpace), *BaseAddress, Segment, ViewOffset ? ViewOffset->LowPart : 0, ViewSize, Segment->FileObject ? &Segment->FileObject->FileName : NULL, file, line); + return Status; + } - MArea->Data.SectionData.Segment = Segment; - if (ViewOffset) - MArea->Data.SectionData.ViewOffset = *ViewOffset; - else - MArea->Data.SectionData.ViewOffset.QuadPart = 0; + DPRINTC("MiMapViewOfSegment %x %x %x %x %x %wZ %s:%d\n", + MmGetAddressSpaceOwner(AddressSpace), + *BaseAddress, + Segment, + ViewOffset ? ViewOffset->LowPart : 0, + ViewSize, + Segment->FileObject ? &Segment->FileObject->FileName : NULL, + file, + line); + + MArea->Data.SectionData.Segment = Segment; + if (ViewOffset) + MArea->Data.SectionData.ViewOffset = *ViewOffset; + else + MArea->Data.SectionData.ViewOffset.QuadPart = 0; #if 0 - MArea->NotPresent = MmNotPresentFaultPageFile; - MArea->AccessFault = MiCowSectionPage; - MArea->PageOut = MmPageOutPageFileView; + MArea->NotPresent = MmNotPresentFaultPageFile; + MArea->AccessFault = MiCowSectionPage; + MArea->PageOut = MmPageOutPageFileView; #endif - MmInitializeRegion(&MArea->Data.SectionData.RegionListHead, - ViewSize, 0, Protect); + MmInitializeRegion(&MArea->Data.SectionData.RegionListHead, + ViewSize, + 0, + Protect); - DPRINTC - ("MiMapViewOfSegment(P %x, A %x, T %x)\n", - MmGetAddressSpaceOwner(AddressSpace), *BaseAddress, MArea->Type); + DPRINTC("MiMapViewOfSegment(P %x, A %x, T %x)\n", + MmGetAddressSpaceOwner(AddressSpace), + *BaseAddress, + MArea->Type); - return(STATUS_SUCCESS); + return STATUS_SUCCESS; } VOID NTAPI -MiFreeSegmentPage -(PMM_SECTION_SEGMENT Segment, - PLARGE_INTEGER FileOffset) +MiFreeSegmentPage(PMM_SECTION_SEGMENT Segment, + PLARGE_INTEGER FileOffset) { - ULONG Entry; - PFILE_OBJECT FileObject = Segment->FileObject; + ULONG Entry; + PFILE_OBJECT FileObject = Segment->FileObject; - Entry = MmGetPageEntrySectionSegment(Segment, FileOffset); - DPRINTC("MiFreeSegmentPage(%x:%08x%08x -> Entry %x\n", - Segment, FileOffset->HighPart, FileOffset->LowPart, Entry); + Entry = MmGetPageEntrySectionSegment(Segment, FileOffset); + DPRINTC("MiFreeSegmentPage(%x:%08x%08x -> Entry %x\n", + Segment, + FileOffset->HighPart, + FileOffset->LowPart, + Entry); - if (Entry && !IS_SWAP_FROM_SSE(Entry)) - { - // The segment is carrying a dirty page. - PFN_NUMBER OldPage = PFN_FROM_SSE(Entry); - if (IS_DIRTY_SSE(Entry) && FileObject) - { - DPRINT("MiWriteBackPage(%x,%wZ,%08x%08x)\n", Segment, &FileObject->FileName, FileOffset->u.HighPart, FileOffset->u.LowPart); - MiWriteBackPage(FileObject, FileOffset, PAGE_SIZE, OldPage); - } - DPRINTC("Free page %x (off %x from %x) (ref ct %d, ent %x, dirty? %s)\n", OldPage, FileOffset->LowPart, Segment, MmGetReferenceCountPage(OldPage), Entry, IS_DIRTY_SSE(Entry) ? "true" : "false"); + if (Entry && !IS_SWAP_FROM_SSE(Entry)) + { + // The segment is carrying a dirty page. + PFN_NUMBER OldPage = PFN_FROM_SSE(Entry); + if (IS_DIRTY_SSE(Entry) && FileObject) + { + DPRINT("MiWriteBackPage(%x,%wZ,%08x%08x)\n", + Segment, + &FileObject->FileName, + FileOffset->u.HighPart, + FileOffset->u.LowPart); - MmSetPageEntrySectionSegment(Segment, FileOffset, 0); - MmReleasePageMemoryConsumer(MC_CACHE, OldPage); - } - else if (IS_SWAP_FROM_SSE(Entry)) - { - DPRINT("Free swap\n"); - MmFreeSwapPage(SWAPENTRY_FROM_SSE(Entry)); - } + MiWriteBackPage(FileObject, FileOffset, PAGE_SIZE, OldPage); + } + DPRINTC("Free page %x (off %x from %x) (ref ct %d, ent %x, dirty? %s)\n", + OldPage, + FileOffset->LowPart, + Segment, + MmGetReferenceCountPage(OldPage), + Entry, + IS_DIRTY_SSE(Entry) ? "true" : "false"); - DPRINT("Done\n"); + MmSetPageEntrySectionSegment(Segment, FileOffset, 0); + MmReleasePageMemoryConsumer(MC_CACHE, OldPage); + } + else if (IS_SWAP_FROM_SSE(Entry)) + { + DPRINT("Free swap\n"); + MmFreeSwapPage(SWAPENTRY_FROM_SSE(Entry)); + } + + DPRINT("Done\n"); } 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) { - ULONG Entry; - PVOID *ContextData = Context; - PMMSUPPORT AddressSpace; - PEPROCESS Process; - PMM_SECTION_SEGMENT Segment; - LARGE_INTEGER Offset; + ULONG Entry; + PVOID *ContextData = Context; + PMMSUPPORT AddressSpace; + PEPROCESS Process; + PMM_SECTION_SEGMENT Segment; + LARGE_INTEGER Offset; - DPRINT("MmFreeSectionPage(%x,%x,%x,%x,%d)\n", MmGetAddressSpaceOwner(ContextData[0]), Address, Page, SwapEntry, Dirty); + DPRINT("MmFreeSectionPage(%x,%x,%x,%x,%d)\n", + MmGetAddressSpaceOwner(ContextData[0]), + Address, + Page, + SwapEntry, + Dirty); - AddressSpace = ContextData[0]; - Process = MmGetAddressSpaceOwner(AddressSpace); - Address = (PVOID)PAGE_ROUND_DOWN(Address); - Segment = ContextData[1]; - Offset.QuadPart = (ULONG_PTR)Address - (ULONG_PTR)MemoryArea->StartingAddress + - MemoryArea->Data.SectionData.ViewOffset.QuadPart; + AddressSpace = ContextData[0]; + Process = MmGetAddressSpaceOwner(AddressSpace); + Address = (PVOID)PAGE_ROUND_DOWN(Address); + Segment = ContextData[1]; + Offset.QuadPart = (ULONG_PTR)Address - (ULONG_PTR)MemoryArea->StartingAddress + + MemoryArea->Data.SectionData.ViewOffset.QuadPart; - Entry = MmGetPageEntrySectionSegment(Segment, &Offset); + Entry = MmGetPageEntrySectionSegment(Segment, &Offset); - if (Page != 0 && PFN_FROM_SSE(Entry) == Page && Dirty) - { - DPRINT("Freeing section page %x:%x -> %x\n", Segment, Offset.LowPart, Entry); - MmSetPageEntrySectionSegment(Segment, &Offset, DIRTY_SSE(Entry)); - } - if (Page) - { - DPRINT("Removing page %x:%x -> %x\n", Segment, Offset.LowPart, Entry); - MmSetSavedSwapEntryPage(Page, 0); - MmDeleteRmap(Page, Process, Address); - MmDeleteVirtualMapping(Process, Address, FALSE, NULL, NULL); - MmReleasePageMemoryConsumer(MC_CACHE, Page); - } - if (SwapEntry != 0) - { - MmFreeSwapPage(SwapEntry); - } + if (Page != 0 && PFN_FROM_SSE(Entry) == Page && Dirty) + { + DPRINT("Freeing section page %x:%x -> %x\n", Segment, Offset.LowPart, Entry); + MmSetPageEntrySectionSegment(Segment, &Offset, DIRTY_SSE(Entry)); + } + if (Page) + { + DPRINT("Removing page %x:%x -> %x\n", Segment, Offset.LowPart, Entry); + MmSetSavedSwapEntryPage(Page, 0); + MmDeleteRmap(Page, Process, Address); + MmDeleteVirtualMapping(Process, Address, FALSE, NULL, NULL); + MmReleasePageMemoryConsumer(MC_CACHE, Page); + } + if (SwapEntry != 0) + { + MmFreeSwapPage(SwapEntry); + } } NTSTATUS NTAPI -MmUnmapViewOfCacheSegment -(PMMSUPPORT AddressSpace, - PVOID BaseAddress) +MmUnmapViewOfCacheSegment(PMMSUPPORT AddressSpace, + PVOID BaseAddress) { - PVOID Context[2]; - PMEMORY_AREA MemoryArea; - PMM_SECTION_SEGMENT Segment; + PVOID Context[2]; + PMEMORY_AREA MemoryArea; + PMM_SECTION_SEGMENT Segment; - MemoryArea = MmLocateMemoryAreaByAddress(AddressSpace, BaseAddress); - if (MemoryArea == NULL || MemoryArea->DeleteInProgress) - { - ASSERT(MemoryArea); - return(STATUS_UNSUCCESSFUL); - } + MemoryArea = MmLocateMemoryAreaByAddress(AddressSpace, BaseAddress); + if (MemoryArea == NULL || MemoryArea->DeleteInProgress) + { + ASSERT(MemoryArea); + return STATUS_UNSUCCESSFUL; + } - MemoryArea->DeleteInProgress = TRUE; - Segment = MemoryArea->Data.SectionData.Segment; - MemoryArea->Data.SectionData.Segment = NULL; - - MmLockSectionSegment(Segment); + MemoryArea->DeleteInProgress = TRUE; + Segment = MemoryArea->Data.SectionData.Segment; + MemoryArea->Data.SectionData.Segment = NULL; - Context[0] = AddressSpace; - Context[1] = Segment; - DPRINT("MmFreeMemoryArea(%x,%x)\n", MmGetAddressSpaceOwner(AddressSpace), MemoryArea->StartingAddress); - MmFreeMemoryArea(AddressSpace, MemoryArea, MmFreeCacheSectionPage, Context); + MmLockSectionSegment(Segment); - MmUnlockSectionSegment(Segment); + Context[0] = AddressSpace; + Context[1] = Segment; - DPRINTC("MiUnmapViewOfSegment %x %x %x\n", MmGetAddressSpaceOwner(AddressSpace), BaseAddress, Segment); + DPRINT("MmFreeMemoryArea(%x,%x)\n", + MmGetAddressSpaceOwner(AddressSpace), + MemoryArea->StartingAddress); - return(STATUS_SUCCESS); + MmFreeMemoryArea(AddressSpace, MemoryArea, MmFreeCacheSectionPage, Context); + + MmUnlockSectionSegment(Segment); + + DPRINTC("MiUnmapViewOfSegment %x %x %x\n", + MmGetAddressSpaceOwner(AddressSpace), + BaseAddress, + Segment); + + return STATUS_SUCCESS; } NTSTATUS NTAPI -MmExtendCacheSection -(PROS_SECTION_OBJECT Section, - PLARGE_INTEGER NewSize, - BOOLEAN ExtendFile) +MmExtendCacheSection(PROS_SECTION_OBJECT Section, + PLARGE_INTEGER NewSize, + BOOLEAN ExtendFile) { - LARGE_INTEGER OldSize; - PMM_SECTION_SEGMENT Segment = Section->Segment; - DPRINT("Extend Segment %x\n", Segment); + LARGE_INTEGER OldSize; + PMM_SECTION_SEGMENT Segment = Section->Segment; + DPRINT("Extend Segment %x\n", Segment); - MmLockSectionSegment(Segment); - OldSize.QuadPart = Segment->RawLength.QuadPart; - MmUnlockSectionSegment(Segment); + MmLockSectionSegment(Segment); + OldSize.QuadPart = Segment->RawLength.QuadPart; + MmUnlockSectionSegment(Segment); - DPRINT("OldSize %08x%08x NewSize %08x%08x\n", - OldSize.u.HighPart, OldSize.u.LowPart, - NewSize->u.HighPart, NewSize->u.LowPart); + DPRINT("OldSize %08x%08x NewSize %08x%08x\n", + OldSize.u.HighPart, OldSize.u.LowPart, + NewSize->u.HighPart, NewSize->u.LowPart); - if (ExtendFile && OldSize.QuadPart < NewSize->QuadPart) - { - NTSTATUS Status; - Status = IoSetInformation(Segment->FileObject, FileEndOfFileInformation, sizeof(LARGE_INTEGER), NewSize); - if (!NT_SUCCESS(Status)) return Status; - } + if (ExtendFile && OldSize.QuadPart < NewSize->QuadPart) + { + NTSTATUS Status; - MmLockSectionSegment(Segment); - Segment->RawLength.QuadPart = NewSize->QuadPart; - Segment->Length.QuadPart = MAX(Segment->Length.QuadPart, PAGE_ROUND_UP(Segment->RawLength.LowPart)); - MmUnlockSectionSegment(Segment); - return STATUS_SUCCESS; + Status = IoSetInformation(Segment->FileObject, + FileEndOfFileInformation, + sizeof(LARGE_INTEGER), + NewSize); + + if (!NT_SUCCESS(Status)) return Status; + } + + MmLockSectionSegment(Segment); + Segment->RawLength.QuadPart = NewSize->QuadPart; + Segment->Length.QuadPart = MAX(Segment->Length.QuadPart, + PAGE_ROUND_UP(Segment->RawLength.LowPart)); + MmUnlockSectionSegment(Segment); + return STATUS_SUCCESS; } -NTSTATUS +NTSTATUS NTAPI -MmMapCacheViewInSystemSpaceAtOffset -(IN PMM_SECTION_SEGMENT Segment, - OUT PVOID *MappedBase, - PLARGE_INTEGER FileOffset, - IN OUT PULONG ViewSize) +MmMapCacheViewInSystemSpaceAtOffset(IN PMM_SECTION_SEGMENT Segment, + OUT PVOID *MappedBase, + PLARGE_INTEGER FileOffset, + IN OUT PULONG ViewSize) { PMMSUPPORT AddressSpace; NTSTATUS Status; - - DPRINT("MmMapViewInSystemSpaceAtOffset() called offset %08x%08x\n", FileOffset->HighPart, FileOffset->LowPart); - + + DPRINT("MmMapViewInSystemSpaceAtOffset() called offset %08x%08x\n", + FileOffset->HighPart, + FileOffset->LowPart); + AddressSpace = MmGetKernelAddressSpace(); - + MmLockAddressSpace(AddressSpace); MmLockSectionSegment(Segment); - - Status = MiMapViewOfSegment - (AddressSpace, - Segment, - MappedBase, - *ViewSize, - PAGE_READWRITE, - FileOffset, - 0); - + + Status = MiMapViewOfSegment(AddressSpace, + Segment, + MappedBase, + *ViewSize, + PAGE_READWRITE, + FileOffset, + 0); + MmUnlockSectionSegment(Segment); MmUnlockAddressSpace(AddressSpace); - + return Status; } @@ -794,16 +856,16 @@ MmMapCacheViewInSystemSpaceAtOffset NTSTATUS NTAPI MmUnmapCacheViewInSystemSpace (IN PVOID MappedBase) { - PMMSUPPORT AddressSpace; - NTSTATUS Status; + PMMSUPPORT AddressSpace; + NTSTATUS Status; - DPRINT("MmUnmapViewInSystemSpace() called\n"); + DPRINT("MmUnmapViewInSystemSpace() called\n"); - AddressSpace = MmGetKernelAddressSpace(); + AddressSpace = MmGetKernelAddressSpace(); - Status = MmUnmapViewOfCacheSegment(AddressSpace, MappedBase); + Status = MmUnmapViewOfCacheSegment(AddressSpace, MappedBase); - return Status; + return Status; } /* EOF */ diff --git a/reactos/ntoskrnl/cache/section/fault.c b/reactos/ntoskrnl/cache/section/fault.c index c12f3d54104..a9881bd183d 100644 --- a/reactos/ntoskrnl/cache/section/fault.c +++ b/reactos/ntoskrnl/cache/section/fault.c @@ -58,159 +58,174 @@ extern PMMWSL MmWorkingSetList; NTSTATUS NTAPI -MmNotPresentFaultCachePage -(PMMSUPPORT AddressSpace, - MEMORY_AREA* MemoryArea, - PVOID Address, - BOOLEAN Locked, - PMM_REQUIRED_RESOURCES Required) +MmNotPresentFaultCachePage(PMMSUPPORT AddressSpace, + MEMORY_AREA* MemoryArea, + PVOID Address, + BOOLEAN Locked, + PMM_REQUIRED_RESOURCES Required) { - NTSTATUS Status; - PVOID PAddress; - ULONG Consumer; - PMM_SECTION_SEGMENT Segment; - LARGE_INTEGER FileOffset, TotalOffset; - ULONG Entry; - ULONG Attributes; - PEPROCESS Process = MmGetAddressSpaceOwner(AddressSpace); - KIRQL OldIrql; + NTSTATUS Status; + PVOID PAddress; + ULONG Consumer; + PMM_SECTION_SEGMENT Segment; + LARGE_INTEGER FileOffset, TotalOffset; + ULONG Entry; + ULONG Attributes; + PEPROCESS Process = MmGetAddressSpaceOwner(AddressSpace); + KIRQL OldIrql; - DPRINT("Not Present: %p %p (%p-%p)\n", AddressSpace, Address, MemoryArea->StartingAddress, MemoryArea->EndingAddress); - - /* - * There is a window between taking the page fault and locking the - * address space when another thread could load the page so we check - * that. - */ - if (MmIsPagePresent(Process, Address)) - { - DPRINT("Done\n"); - return(STATUS_SUCCESS); - } + DPRINT("Not Present: %p %p (%p-%p)\n", + AddressSpace, + Address, + MemoryArea->StartingAddress, + MemoryArea->EndingAddress); - PAddress = MM_ROUND_DOWN(Address, PAGE_SIZE); - TotalOffset.QuadPart = (ULONG_PTR)PAddress - (ULONG_PTR)MemoryArea->StartingAddress; + /* + * There is a window between taking the page fault and locking the + * address space when another thread could load the page so we check + * that. + */ + if (MmIsPagePresent(Process, Address)) + { + DPRINT("Done\n"); + return STATUS_SUCCESS; + } - Segment = MemoryArea->Data.SectionData.Segment; + PAddress = MM_ROUND_DOWN(Address, PAGE_SIZE); + TotalOffset.QuadPart = (ULONG_PTR)PAddress - + (ULONG_PTR)MemoryArea->StartingAddress; - TotalOffset.QuadPart += MemoryArea->Data.SectionData.ViewOffset.QuadPart; - FileOffset = TotalOffset; + Segment = MemoryArea->Data.SectionData.Segment; - //Consumer = (Segment->Flags & MM_DATAFILE_SEGMENT) ? MC_CACHE : MC_USER; - Consumer = MC_CACHE; + TotalOffset.QuadPart += MemoryArea->Data.SectionData.ViewOffset.QuadPart; + FileOffset = TotalOffset; - if (Segment->FileObject) - { - DPRINT("FileName %wZ\n", &Segment->FileObject->FileName); - } + //Consumer = (Segment->Flags & MM_DATAFILE_SEGMENT) ? MC_CACHE : MC_USER; + Consumer = MC_CACHE; - DPRINT("Total Offset %08x%08x\n", TotalOffset.HighPart, TotalOffset.LowPart); + if (Segment->FileObject) + { + DPRINT("FileName %wZ\n", &Segment->FileObject->FileName); + } - /* - * Lock the segment - */ - MmLockSectionSegment(Segment); + DPRINT("Total Offset %08x%08x\n", TotalOffset.HighPart, TotalOffset.LowPart); - /* - * Get the entry corresponding to the offset within the section - */ - Entry = MmGetPageEntrySectionSegment(Segment, &TotalOffset); + /* Lock the segment */ + MmLockSectionSegment(Segment); - Attributes = PAGE_READONLY; + /* Get the entry corresponding to the offset within the section */ + Entry = MmGetPageEntrySectionSegment(Segment, &TotalOffset); - if (Required->State && Required->Page[0]) - { - DPRINT("Have file and page, set page %x in section @ %x #\n", Required->Page[0], TotalOffset.LowPart); + Attributes = PAGE_READONLY; - if (Required->SwapEntry) - MmSetSavedSwapEntryPage(Required->Page[0], Required->SwapEntry); + if (Required->State && Required->Page[0]) + { + DPRINT("Have file and page, set page %x in section @ %x #\n", + Required->Page[0], + TotalOffset.LowPart); - if (Required->State & 2) - { - DPRINT("Set in section @ %x\n", TotalOffset.LowPart); - Status = MmSetPageEntrySectionSegment - (Segment, &TotalOffset, Entry = MAKE_PFN_SSE(Required->Page[0])); - if (!NT_SUCCESS(Status)) - { - MmReleasePageMemoryConsumer(MC_CACHE, Required->Page[0]); - } - MmUnlockSectionSegment(Segment); - MiSetPageEvent(Process, Address); - DPRINT("Status %x\n", Status); - return STATUS_MM_RESTART_OPERATION; - } - else - { - DPRINT("Set %x in address space @ %x\n", Required->Page[0], Address); - Status = MmCreateVirtualMapping(Process, Address, Attributes, Required->Page, 1); - if (NT_SUCCESS(Status)) - { - MmInsertRmap(Required->Page[0], Process, Address); - } - else - { - // Drop the reference for our address space ... - MmReleasePageMemoryConsumer(MC_CACHE, Required->Page[0]); - } - MmUnlockSectionSegment(Segment); - DPRINTC("XXX Set Event %x\n", Status); - MiSetPageEvent(Process, Address); - DPRINT("Status %x\n", Status); - return Status; - } - } - else if (MM_IS_WAIT_PTE(Entry)) - { - MmUnlockSectionSegment(Segment); - return STATUS_SUCCESS + 1; - } - else if (Entry) - { - PFN_NUMBER Page = PFN_FROM_SSE(Entry); - DPRINT("Take reference to page %x #\n", Page); + if (Required->SwapEntry) + MmSetSavedSwapEntryPage(Required->Page[0], Required->SwapEntry); - if (MiGetPfnEntry(Page) == NULL) - { - DPRINT1("Found no PFN entry for page 0x%x in page entry 0x%x (segment: 0x%p, offset: %08x%08x)\n", - Page, Entry, Segment, TotalOffset.HighPart, TotalOffset.LowPart); - KeBugCheck(CACHE_MANAGER); - } + if (Required->State & 2) + { + DPRINT("Set in section @ %x\n", TotalOffset.LowPart); + Status = MmSetPageEntrySectionSegment(Segment, + &TotalOffset, + Entry = MAKE_PFN_SSE(Required->Page[0])); + if (!NT_SUCCESS(Status)) + { + MmReleasePageMemoryConsumer(MC_CACHE, Required->Page[0]); + } + MmUnlockSectionSegment(Segment); + MiSetPageEvent(Process, Address); + DPRINT("Status %x\n", Status); + return STATUS_MM_RESTART_OPERATION; + } + else + { + DPRINT("Set %x in address space @ %x\n", Required->Page[0], Address); + Status = MmCreateVirtualMapping(Process, + Address, + Attributes, + Required->Page, + 1); + if (NT_SUCCESS(Status)) + { + MmInsertRmap(Required->Page[0], Process, Address); + } + else + { + /* Drop the reference for our address space ... */ + MmReleasePageMemoryConsumer(MC_CACHE, Required->Page[0]); + } + MmUnlockSectionSegment(Segment); + DPRINTC("XXX Set Event %x\n", Status); + MiSetPageEvent(Process, Address); + DPRINT("Status %x\n", Status); + return Status; + } + } + else if (MM_IS_WAIT_PTE(Entry)) + { + MmUnlockSectionSegment(Segment); + return STATUS_SUCCESS + 1; + } + else if (Entry) + { + PFN_NUMBER Page = PFN_FROM_SSE(Entry); + DPRINT("Take reference to page %x #\n", Page); - OldIrql = KeAcquireQueuedSpinLock(LockQueuePfnLock); - MmReferencePage(Page); - KeReleaseQueuedSpinLock(LockQueuePfnLock, OldIrql); + if (MiGetPfnEntry(Page) == NULL) + { + DPRINT1("Found no PFN entry for page 0x%x in page entry 0x%x (segment: 0x%p, offset: %08x%08x)\n", + Page, + Entry, + Segment, + TotalOffset.HighPart, + TotalOffset.LowPart); + KeBugCheck(CACHE_MANAGER); + } - Status = MmCreateVirtualMapping(Process, Address, Attributes, &Page, 1); - if (NT_SUCCESS(Status)) - { - MmInsertRmap(Page, Process, Address); - } - DPRINT("XXX Set Event %x\n", Status); - MiSetPageEvent(Process, Address); - MmUnlockSectionSegment(Segment); - DPRINT("Status %x\n", Status); - return Status; - } - else - { - DPRINT("Get page into section\n"); - /* - * If the entry is zero (and it can't change because we have - * locked the segment) then we need to load the page. - */ - //DPRINT1("Read from file %08x %wZ\n", FileOffset.LowPart, &Section->FileObject->FileName); - Required->State = 2; - Required->Context = Segment->FileObject; - Required->Consumer = Consumer; - Required->FileOffset = FileOffset; - Required->Amount = PAGE_SIZE; - Required->DoAcquisition = MiReadFilePage; - MmSetPageEntrySectionSegment(Segment, &TotalOffset, MAKE_SWAP_SSE(MM_WAIT_ENTRY)); - MmUnlockSectionSegment(Segment); - return STATUS_MORE_PROCESSING_REQUIRED; - } - ASSERT(FALSE); - return STATUS_ACCESS_VIOLATION; + OldIrql = KeAcquireQueuedSpinLock(LockQueuePfnLock); + MmReferencePage(Page); + KeReleaseQueuedSpinLock(LockQueuePfnLock, OldIrql); + + Status = MmCreateVirtualMapping(Process, Address, Attributes, &Page, 1); + if (NT_SUCCESS(Status)) + { + MmInsertRmap(Page, Process, Address); + } + DPRINT("XXX Set Event %x\n", Status); + MiSetPageEvent(Process, Address); + MmUnlockSectionSegment(Segment); + DPRINT("Status %x\n", Status); + return Status; + } + else + { + DPRINT("Get page into section\n"); + /* + * If the entry is zero (and it can't change because we have + * locked the segment) then we need to load the page. + */ + //DPRINT1("Read from file %08x %wZ\n", FileOffset.LowPart, &Section->FileObject->FileName); + Required->State = 2; + Required->Context = Segment->FileObject; + Required->Consumer = Consumer; + Required->FileOffset = FileOffset; + Required->Amount = PAGE_SIZE; + Required->DoAcquisition = MiReadFilePage; + + MmSetPageEntrySectionSegment(Segment, + &TotalOffset, + MAKE_SWAP_SSE(MM_WAIT_ENTRY)); + + MmUnlockSectionSegment(Segment); + return STATUS_MORE_PROCESSING_REQUIRED; + } + ASSERT(FALSE); + return STATUS_ACCESS_VIOLATION; } NTSTATUS @@ -220,568 +235,591 @@ MiCopyPageToPage(PFN_NUMBER DestPage, PFN_NUMBER SrcPage) PEPROCESS Process; KIRQL Irql, Irql2; PVOID TempAddress, TempSource; - + Process = PsGetCurrentProcess(); TempAddress = MiMapPageInHyperSpace(Process, DestPage, &Irql); if (TempAddress == NULL) { - return(STATUS_NO_MEMORY); + return STATUS_NO_MEMORY; + } + TempSource = MiMapPageInHyperSpace(Process, SrcPage, &Irql2); + if (!TempSource) { + MiUnmapPageInHyperSpace(Process, TempAddress, Irql); + return STATUS_NO_MEMORY; } - TempSource = MiMapPageInHyperSpace(Process, SrcPage, &Irql2); - if (!TempSource) { - MiUnmapPageInHyperSpace(Process, TempAddress, Irql); - return(STATUS_NO_MEMORY); - } memcpy(TempAddress, TempSource, PAGE_SIZE); - MiUnmapPageInHyperSpace(Process, TempSource, Irql2); + MiUnmapPageInHyperSpace(Process, TempSource, Irql2); MiUnmapPageInHyperSpace(Process, TempAddress, Irql); - return(STATUS_SUCCESS); + return STATUS_SUCCESS; } 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) { - PMM_SECTION_SEGMENT Segment; - PFN_NUMBER NewPage, OldPage; - NTSTATUS Status; - PVOID PAddress; - LARGE_INTEGER Offset; - PEPROCESS Process = MmGetAddressSpaceOwner(AddressSpace); + PMM_SECTION_SEGMENT Segment; + PFN_NUMBER NewPage, OldPage; + NTSTATUS Status; + PVOID PAddress; + LARGE_INTEGER Offset; + PEPROCESS Process = MmGetAddressSpaceOwner(AddressSpace); - DPRINT("MmAccessFaultSectionView(%x, %x, %x, %x)\n", AddressSpace, MemoryArea, Address, Locked); + DPRINT("MmAccessFaultSectionView(%x, %x, %x, %x)\n", + AddressSpace, + MemoryArea, + Address, + Locked); - Segment = MemoryArea->Data.SectionData.Segment; + Segment = MemoryArea->Data.SectionData.Segment; - /* - * Lock the segment - */ - MmLockSectionSegment(Segment); - - /* - * Find the offset of the page - */ - PAddress = MM_ROUND_DOWN(Address, PAGE_SIZE); - Offset.QuadPart = (ULONG_PTR)PAddress - (ULONG_PTR)MemoryArea->StartingAddress + - MemoryArea->Data.SectionData.ViewOffset.QuadPart; + /* Lock the segment */ + MmLockSectionSegment(Segment); - if (!Segment->WriteCopy /*&& - !MemoryArea->Data.SectionData.WriteCopyView*/ || - Segment->Image.Characteristics & IMAGE_SCN_MEM_SHARED) - { + /* Find the offset of the page */ + PAddress = MM_ROUND_DOWN(Address, PAGE_SIZE); + Offset.QuadPart = (ULONG_PTR)PAddress - (ULONG_PTR)MemoryArea->StartingAddress + + MemoryArea->Data.SectionData.ViewOffset.QuadPart; + + if (!Segment->WriteCopy /*&& + !MemoryArea->Data.SectionData.WriteCopyView*/ || + Segment->Image.Characteristics & IMAGE_SCN_MEM_SHARED) + { #if 0 - if (Region->Protect == PAGE_READWRITE || - Region->Protect == PAGE_EXECUTE_READWRITE) + if (Region->Protect == PAGE_READWRITE || + Region->Protect == PAGE_EXECUTE_READWRITE) #endif - { - ULONG Entry; - DPRINTC("setting non-cow page %x %x:%x offset %x (%x) to writable\n", Segment, Process, PAddress, Offset.u.LowPart, MmGetPfnForProcess(Process, Address)); - if (Segment->FileObject) - { - DPRINTC("file %wZ\n", &Segment->FileObject->FileName); - } - Entry = MmGetPageEntrySectionSegment(Segment, &Offset); - DPRINT("Entry %x\n", Entry); - if (Entry && - !IS_SWAP_FROM_SSE(Entry) && - PFN_FROM_SSE(Entry) == MmGetPfnForProcess(Process, Address)) { - MmSetPageEntrySectionSegment(Segment, &Offset, DIRTY_SSE(Entry)); - } - MmSetPageProtect(Process, PAddress, PAGE_READWRITE); - MmSetDirtyPage(Process, PAddress); - MmUnlockSectionSegment(Segment); - DPRINT("Done\n"); - return STATUS_SUCCESS; - } + { + ULONG Entry; + DPRINTC("setting non-cow page %x %x:%x offset %x (%x) to writable\n", + Segment, + Process, + PAddress, + Offset.u.LowPart, + MmGetPfnForProcess(Process, Address)); + if (Segment->FileObject) + { + DPRINTC("file %wZ\n", &Segment->FileObject->FileName); + } + Entry = MmGetPageEntrySectionSegment(Segment, &Offset); + DPRINT("Entry %x\n", Entry); + if (Entry && + !IS_SWAP_FROM_SSE(Entry) && + PFN_FROM_SSE(Entry) == MmGetPfnForProcess(Process, Address)) { + + MmSetPageEntrySectionSegment(Segment, + &Offset, + DIRTY_SSE(Entry)); + } + MmSetPageProtect(Process, PAddress, PAGE_READWRITE); + MmSetDirtyPage(Process, PAddress); + MmUnlockSectionSegment(Segment); + DPRINT("Done\n"); + return STATUS_SUCCESS; + } #if 0 - else - { - DPRINT("Not supposed to be writable\n"); - MmUnlockSectionSegment(Segment); - return STATUS_ACCESS_VIOLATION; - } + else + { + DPRINT("Not supposed to be writable\n"); + MmUnlockSectionSegment(Segment); + return STATUS_ACCESS_VIOLATION; + } #endif - } - - if (!Required->Page[0]) - { - SWAPENTRY SwapEntry; - if (MmIsPageSwapEntry(Process, Address)) - { - MmGetPageFileMapping(Process, Address, &SwapEntry); - MmUnlockSectionSegment(Segment); - if (SwapEntry == MM_WAIT_ENTRY) - return STATUS_SUCCESS + 1; // Wait ... somebody else is getting it right now - else - return STATUS_SUCCESS; // Nonwait swap entry ... handle elsewhere - } - Required->Page[1] = MmGetPfnForProcess(Process, Address); - Required->Consumer = MC_CACHE; - Required->Amount = 1; - Required->File = __FILE__; - Required->Line = __LINE__; - Required->DoAcquisition = MiGetOnePage; - MmCreatePageFileMapping(Process, Address, MM_WAIT_ENTRY); - MmUnlockSectionSegment(Segment); - return STATUS_MORE_PROCESSING_REQUIRED; - } + } - NewPage = Required->Page[0]; - OldPage = Required->Page[1]; + if (!Required->Page[0]) + { + SWAPENTRY SwapEntry; + if (MmIsPageSwapEntry(Process, Address)) + { + MmGetPageFileMapping(Process, Address, &SwapEntry); + MmUnlockSectionSegment(Segment); + if (SwapEntry == MM_WAIT_ENTRY) + return STATUS_SUCCESS + 1; // Wait ... somebody else is getting it right now + else + return STATUS_SUCCESS; // Nonwait swap entry ... handle elsewhere + } + Required->Page[1] = MmGetPfnForProcess(Process, Address); + Required->Consumer = MC_CACHE; + Required->Amount = 1; + Required->File = __FILE__; + Required->Line = __LINE__; + Required->DoAcquisition = MiGetOnePage; + MmCreatePageFileMapping(Process, Address, MM_WAIT_ENTRY); + MmUnlockSectionSegment(Segment); + return STATUS_MORE_PROCESSING_REQUIRED; + } - DPRINT("Allocated page %x\n", NewPage); + NewPage = Required->Page[0]; + OldPage = Required->Page[1]; - /* - * Unshare the old page. - */ + DPRINT("Allocated page %x\n", NewPage); + + /* Unshare the old page */ MmDeleteRmap(OldPage, Process, PAddress); - /* - * Copy the old page - */ - DPRINT("Copying\n"); - MiCopyPageToPage(NewPage, OldPage); + /* Copy the old page */ + DPRINT("Copying\n"); + MiCopyPageToPage(NewPage, OldPage); - /* - * Set the PTE to point to the new page - */ - Status = MmCreateVirtualMapping - (Process, Address, PAGE_READWRITE, &NewPage, 1); + /* Set the PTE to point to the new page */ + Status = MmCreateVirtualMapping(Process, + Address, + PAGE_READWRITE, + &NewPage, + 1); - if (!NT_SUCCESS(Status)) - { - DPRINT1("MmCreateVirtualMapping failed, not out of memory\n"); - ASSERT(FALSE); - MmUnlockSectionSegment(Segment); - return(Status); - } + if (!NT_SUCCESS(Status)) + { + DPRINT1("MmCreateVirtualMapping failed, not out of memory\n"); + ASSERT(FALSE); + MmUnlockSectionSegment(Segment); + return Status; + } - MmInsertRmap(NewPage, Process, PAddress); - MmReleasePageMemoryConsumer(MC_CACHE, OldPage); - MmUnlockSectionSegment(Segment); + MmInsertRmap(NewPage, Process, PAddress); + MmReleasePageMemoryConsumer(MC_CACHE, OldPage); + MmUnlockSectionSegment(Segment); - DPRINT("Address 0x%.8X\n", Address); - return(STATUS_SUCCESS); + DPRINT("Address 0x%.8X\n", Address); + return STATUS_SUCCESS; } KEVENT MmWaitPageEvent; typedef struct _WORK_QUEUE_WITH_CONTEXT { - WORK_QUEUE_ITEM WorkItem; - PMMSUPPORT AddressSpace; - PMEMORY_AREA MemoryArea; - PMM_REQUIRED_RESOURCES Required; - NTSTATUS Status; - KEVENT Wait; - AcquireResource DoAcquisition; + WORK_QUEUE_ITEM WorkItem; + PMMSUPPORT AddressSpace; + PMEMORY_AREA MemoryArea; + PMM_REQUIRED_RESOURCES Required; + NTSTATUS Status; + KEVENT Wait; + AcquireResource DoAcquisition; } WORK_QUEUE_WITH_CONTEXT, *PWORK_QUEUE_WITH_CONTEXT; VOID NTAPI -MmpFaultWorker -(PWORK_QUEUE_WITH_CONTEXT WorkItem) +MmpFaultWorker(PWORK_QUEUE_WITH_CONTEXT WorkItem) { - DPRINT("Calling work\n"); - WorkItem->Status = - WorkItem->Required->DoAcquisition - (WorkItem->AddressSpace, - WorkItem->MemoryArea, - WorkItem->Required); - DPRINT("Status %x\n", WorkItem->Status); - KeSetEvent(&WorkItem->Wait, IO_NO_INCREMENT, FALSE); + DPRINT("Calling work\n"); + WorkItem->Status = WorkItem->Required->DoAcquisition(WorkItem->AddressSpace, + WorkItem->MemoryArea, + WorkItem->Required); + DPRINT("Status %x\n", WorkItem->Status); + KeSetEvent(&WorkItem->Wait, IO_NO_INCREMENT, FALSE); } NTSTATUS NTAPI -MmpSectionAccessFaultInner -(KPROCESSOR_MODE Mode, - PMMSUPPORT AddressSpace, - ULONG_PTR Address, - BOOLEAN FromMdl, - PETHREAD Thread) +MmpSectionAccessFaultInner(KPROCESSOR_MODE Mode, + PMMSUPPORT AddressSpace, + ULONG_PTR Address, + BOOLEAN FromMdl, + PETHREAD Thread) { - MEMORY_AREA* MemoryArea; - NTSTATUS Status; - BOOLEAN Locked = FromMdl; - MM_REQUIRED_RESOURCES Resources = { 0 }; - WORK_QUEUE_WITH_CONTEXT Context; - - RtlZeroMemory(&Context, sizeof(WORK_QUEUE_WITH_CONTEXT)); - - DPRINT("MmAccessFault(Mode %d, Address %x)\n", Mode, Address); - - if (KeGetCurrentIrql() >= DISPATCH_LEVEL) - { - DPRINT1("Page fault at high IRQL was %d\n", KeGetCurrentIrql()); - return(STATUS_UNSUCCESSFUL); - } - - /* - * Find the memory area for the faulting address - */ - if (Address >= (ULONG_PTR)MmSystemRangeStart) - { - /* - * Check permissions - */ - if (Mode != KernelMode) - { - DPRINT("MmAccessFault(Mode %d, Address %x)\n", Mode, Address); - return(STATUS_ACCESS_VIOLATION); - } - AddressSpace = MmGetKernelAddressSpace(); - } - else - { - AddressSpace = &PsGetCurrentProcess()->Vm; - } - - if (!FromMdl) - { - MmLockAddressSpace(AddressSpace); - } - - do - { - MemoryArea = MmLocateMemoryAreaByAddress(AddressSpace, (PVOID)Address); - if (MemoryArea == NULL || - MemoryArea->DeleteInProgress) - { - if (!FromMdl) - { - MmUnlockAddressSpace(AddressSpace); - } - DPRINT("Address: %x\n", Address); - return (STATUS_ACCESS_VIOLATION); - } - - DPRINT - ("Type %x (%x -> %x)\n", - MemoryArea->Type, - MemoryArea->StartingAddress, - MemoryArea->EndingAddress); - - Resources.DoAcquisition = NULL; - - // Note: fault handlers are called with address space locked - // We return STATUS_MORE_PROCESSING_REQUIRED if anything is needed - Status = MiCowCacheSectionPage - (AddressSpace, MemoryArea, (PVOID)Address, Locked, &Resources); - - if (!FromMdl) - { - MmUnlockAddressSpace(AddressSpace); - } - - if (Status == STATUS_SUCCESS + 1) - { - // Wait page ... - DPRINT("Waiting for %x\n", Address); - MiWaitForPageEvent(MmGetAddressSpaceOwner(AddressSpace), Address); - DPRINT("Restarting fault %x\n", Address); - Status = STATUS_MM_RESTART_OPERATION; - } - else if (Status == STATUS_MM_RESTART_OPERATION) - { - // Clean slate - RtlZeroMemory(&Resources, sizeof(Resources)); - } - else if (Status == STATUS_MORE_PROCESSING_REQUIRED) - { - if (Thread->ActiveFaultCount > 0) - { - DPRINT("Already fault handling ... going to work item (%x)\n", Address); - Context.AddressSpace = AddressSpace; - Context.MemoryArea = MemoryArea; - Context.Required = &Resources; - KeInitializeEvent(&Context.Wait, NotificationEvent, FALSE); - ExInitializeWorkItem(&Context.WorkItem, (PWORKER_THREAD_ROUTINE)MmpFaultWorker, &Context); - DPRINT("Queue work item\n"); - ExQueueWorkItem(&Context.WorkItem, DelayedWorkQueue); - DPRINT("Wait\n"); - KeWaitForSingleObject(&Context.Wait, 0, KernelMode, FALSE, NULL); - Status = Context.Status; - DPRINT("Status %x\n", Status); - } - else - { - Status = Resources.DoAcquisition(AddressSpace, MemoryArea, &Resources); - } - - if (NT_SUCCESS(Status)) - { - Status = STATUS_MM_RESTART_OPERATION; - } - } - - if (!FromMdl) - { - MmLockAddressSpace(AddressSpace); - } - } - while (Status == STATUS_MM_RESTART_OPERATION); - - if (!NT_SUCCESS(Status) && MemoryArea->Type == 1) - { - DPRINT1("Completed page fault handling %x %x\n", Address, Status); - DPRINT1 - ("Type %x (%x -> %x)\n", - MemoryArea->Type, - MemoryArea->StartingAddress, - MemoryArea->EndingAddress); - } - - if (!FromMdl) - { - MmUnlockAddressSpace(AddressSpace); - } - - return(Status); -} - -NTSTATUS -NTAPI -MmAccessFaultCacheSection -(KPROCESSOR_MODE Mode, - ULONG_PTR Address, - BOOLEAN FromMdl) -{ - PETHREAD Thread; - PMMSUPPORT AddressSpace; - NTSTATUS Status; - - DPRINT("MmpAccessFault(Mode %d, Address %x)\n", Mode, Address); - - Thread = PsGetCurrentThread(); - - if (KeGetCurrentIrql() >= DISPATCH_LEVEL) - { - DPRINT1("Page fault at high IRQL %d, address %x\n", KeGetCurrentIrql(), Address); - return(STATUS_UNSUCCESSFUL); - } - - /* - * Find the memory area for the faulting address - */ - if (Address >= (ULONG_PTR)MmSystemRangeStart) - { - /* - * Check permissions - */ - if (Mode != KernelMode) - { - DPRINT1("Address: %x:%x\n", PsGetCurrentProcess(), Address); - return(STATUS_ACCESS_VIOLATION); - } - AddressSpace = MmGetKernelAddressSpace(); - } - else - { - AddressSpace = &PsGetCurrentProcess()->Vm; - } - - Thread->ActiveFaultCount++; - Status = MmpSectionAccessFaultInner(Mode, AddressSpace, Address, FromMdl, Thread); - Thread->ActiveFaultCount--; - - return(Status); -} - -NTSTATUS -NTAPI -MmNotPresentFaultCacheSectionInner -(KPROCESSOR_MODE Mode, - PMMSUPPORT AddressSpace, - ULONG_PTR Address, - BOOLEAN FromMdl, - PETHREAD Thread) -{ - BOOLEAN Locked = FromMdl; - PMEMORY_AREA MemoryArea; - MM_REQUIRED_RESOURCES Resources = { 0 }; - WORK_QUEUE_WITH_CONTEXT Context; - NTSTATUS Status = STATUS_SUCCESS; + MEMORY_AREA* MemoryArea; + NTSTATUS Status; + BOOLEAN Locked = FromMdl; + MM_REQUIRED_RESOURCES Resources = { 0 }; + WORK_QUEUE_WITH_CONTEXT Context; RtlZeroMemory(&Context, sizeof(WORK_QUEUE_WITH_CONTEXT)); - if (!FromMdl) - { - MmLockAddressSpace(AddressSpace); - } - - /* - * Call the memory area specific fault handler - */ - do - { - MemoryArea = MmLocateMemoryAreaByAddress(AddressSpace, (PVOID)Address); - if (MemoryArea == NULL || MemoryArea->DeleteInProgress) - { - Status = STATUS_ACCESS_VIOLATION; - if (MemoryArea) - { - DPRINT1("Type %x DIP %x\n", MemoryArea->Type, MemoryArea->DeleteInProgress); - } - else - { - DPRINT1("No memory area\n"); - } - DPRINT1("Process %x, Address %x\n", MmGetAddressSpaceOwner(AddressSpace), Address); - break; - } - - DPRINTC - ("Type %x (%x -> %x -> %x) in %x\n", - MemoryArea->Type, - MemoryArea->StartingAddress, - Address, - MemoryArea->EndingAddress, - PsGetCurrentThread()); - - Resources.DoAcquisition = NULL; - - // Note: fault handlers are called with address space locked - // We return STATUS_MORE_PROCESSING_REQUIRED if anything is needed + DPRINT("MmAccessFault(Mode %d, Address %x)\n", Mode, Address); - Status = MmNotPresentFaultCachePage - (AddressSpace, MemoryArea, (PVOID)Address, Locked, &Resources); - - if (!FromMdl) - { - MmUnlockAddressSpace(AddressSpace); - } - - if (Status == STATUS_SUCCESS) - { - ; // Nothing - } - else if (Status == STATUS_SUCCESS + 1) - { - // Wait page ... - DPRINT("Waiting for %x\n", Address); - MiWaitForPageEvent(MmGetAddressSpaceOwner(AddressSpace), Address); - DPRINT("Done waiting for %x\n", Address); - Status = STATUS_MM_RESTART_OPERATION; - } - else if (Status == STATUS_MM_RESTART_OPERATION) - { - // Clean slate - DPRINT("Clear resource\n"); - RtlZeroMemory(&Resources, sizeof(Resources)); - } - else if (Status == STATUS_MORE_PROCESSING_REQUIRED) - { - if (Thread->ActiveFaultCount > 2) - { - DPRINTC("Already fault handling ... going to work item (%x)\n", Address); - Context.AddressSpace = AddressSpace; - Context.MemoryArea = MemoryArea; - Context.Required = &Resources; - KeInitializeEvent(&Context.Wait, NotificationEvent, FALSE); - ExInitializeWorkItem(&Context.WorkItem, (PWORKER_THREAD_ROUTINE)MmpFaultWorker, &Context); - DPRINT("Queue work item\n"); - ExQueueWorkItem(&Context.WorkItem, DelayedWorkQueue); - DPRINT("Wait\n"); - KeWaitForSingleObject(&Context.Wait, 0, KernelMode, FALSE, NULL); - Status = Context.Status; - DPRINTC("Status %x\n", Status); - } - else - { - DPRINT("DoAcquisition %x\n", Resources.DoAcquisition); - Status = Resources.DoAcquisition - (AddressSpace, MemoryArea, &Resources); - DPRINT("DoAcquisition %x -> %x\n", Resources.DoAcquisition, Status); - } + if (KeGetCurrentIrql() >= DISPATCH_LEVEL) + { + DPRINT1("Page fault at high IRQL was %d\n", KeGetCurrentIrql()); + return STATUS_UNSUCCESSFUL; + } - if (NT_SUCCESS(Status)) - { - Status = STATUS_MM_RESTART_OPERATION; - } - } - else if (NT_SUCCESS(Status)) - { - ASSERT(FALSE); - } + /* Find the memory area for the faulting address */ + if (Address >= (ULONG_PTR)MmSystemRangeStart) + { + /* Check permissions */ + if (Mode != KernelMode) + { + DPRINT("MmAccessFault(Mode %d, Address %x)\n", Mode, Address); + return STATUS_ACCESS_VIOLATION; + } + AddressSpace = MmGetKernelAddressSpace(); + } + else + { + AddressSpace = &PsGetCurrentProcess()->Vm; + } - if (!FromMdl) - { - MmLockAddressSpace(AddressSpace); - } - } - while (Status == STATUS_MM_RESTART_OPERATION); + if (!FromMdl) + { + MmLockAddressSpace(AddressSpace); + } - DPRINTC("Completed page fault handling: %x:%x %x\n", MmGetAddressSpaceOwner(AddressSpace), Address, Status); - if (!FromMdl) - { - MmUnlockAddressSpace(AddressSpace); - } + do + { + MemoryArea = MmLocateMemoryAreaByAddress(AddressSpace, (PVOID)Address); + if (MemoryArea == NULL || + MemoryArea->DeleteInProgress) + { + if (!FromMdl) + { + MmUnlockAddressSpace(AddressSpace); + } + DPRINT("Address: %x\n", Address); + return STATUS_ACCESS_VIOLATION; + } - MiSetPageEvent(MmGetAddressSpaceOwner(AddressSpace), Address); - DPRINT("Done %x\n", Status); + DPRINT("Type %x (%x -> %x)\n", + MemoryArea->Type, + MemoryArea->StartingAddress, + MemoryArea->EndingAddress); - return Status; + Resources.DoAcquisition = NULL; + + // Note: fault handlers are called with address space locked + // We return STATUS_MORE_PROCESSING_REQUIRED if anything is needed + Status = MiCowCacheSectionPage(AddressSpace, + MemoryArea, + (PVOID)Address, + Locked, + &Resources); + + if (!FromMdl) + { + MmUnlockAddressSpace(AddressSpace); + } + + if (Status == STATUS_SUCCESS + 1) + { + /* Wait page ... */ + DPRINT("Waiting for %x\n", Address); + MiWaitForPageEvent(MmGetAddressSpaceOwner(AddressSpace), Address); + DPRINT("Restarting fault %x\n", Address); + Status = STATUS_MM_RESTART_OPERATION; + } + else if (Status == STATUS_MM_RESTART_OPERATION) + { + /* Clean slate */ + RtlZeroMemory(&Resources, sizeof(Resources)); + } + else if (Status == STATUS_MORE_PROCESSING_REQUIRED) + { + if (Thread->ActiveFaultCount > 0) + { + DPRINT("Already fault handling ... going to work item (%x)\n", + Address); + Context.AddressSpace = AddressSpace; + Context.MemoryArea = MemoryArea; + Context.Required = &Resources; + KeInitializeEvent(&Context.Wait, NotificationEvent, FALSE); + + ExInitializeWorkItem(&Context.WorkItem, + (PWORKER_THREAD_ROUTINE)MmpFaultWorker, + &Context); + + DPRINT("Queue work item\n"); + ExQueueWorkItem(&Context.WorkItem, DelayedWorkQueue); + DPRINT("Wait\n"); + KeWaitForSingleObject(&Context.Wait, 0, KernelMode, FALSE, NULL); + Status = Context.Status; + DPRINT("Status %x\n", Status); + } + else + { + Status = Resources.DoAcquisition(AddressSpace, MemoryArea, &Resources); + } + + if (NT_SUCCESS(Status)) + { + Status = STATUS_MM_RESTART_OPERATION; + } + } + + if (!FromMdl) + { + MmLockAddressSpace(AddressSpace); + } + } + while (Status == STATUS_MM_RESTART_OPERATION); + + if (!NT_SUCCESS(Status) && MemoryArea->Type == 1) + { + DPRINT1("Completed page fault handling %x %x\n", Address, Status); + DPRINT1("Type %x (%x -> %x)\n", + MemoryArea->Type, + MemoryArea->StartingAddress, + MemoryArea->EndingAddress); + } + + if (!FromMdl) + { + MmUnlockAddressSpace(AddressSpace); + } + + return Status; } NTSTATUS NTAPI -MmNotPresentFaultCacheSection -(KPROCESSOR_MODE Mode, - ULONG_PTR Address, - BOOLEAN FromMdl) +MmAccessFaultCacheSection(KPROCESSOR_MODE Mode, + ULONG_PTR Address, + BOOLEAN FromMdl) { - PETHREAD Thread; - PMMSUPPORT AddressSpace; - NTSTATUS Status; + PETHREAD Thread; + PMMSUPPORT AddressSpace; + NTSTATUS Status; - Address &= ~(PAGE_SIZE - 1); - DPRINT("MmNotPresentFault(Mode %d, Address %x)\n", Mode, Address); - - Thread = PsGetCurrentThread(); + DPRINT("MmpAccessFault(Mode %d, Address %x)\n", Mode, Address); - if (KeGetCurrentIrql() >= DISPATCH_LEVEL) - { - DPRINT1("Page fault at high IRQL %d, address %x\n", KeGetCurrentIrql(), Address); - ASSERT(FALSE); - return(STATUS_UNSUCCESSFUL); - } - - /* - * Find the memory area for the faulting address - */ - if (Address >= (ULONG_PTR)MmSystemRangeStart) - { - /* - * Check permissions - */ - if (Mode != KernelMode) - { - DPRINTC("Address: %x\n", Address); - return(STATUS_ACCESS_VIOLATION); - } - AddressSpace = MmGetKernelAddressSpace(); - } - else - { - AddressSpace = &PsGetCurrentProcess()->Vm; - } - - Thread->ActiveFaultCount++; - Status = MmNotPresentFaultCacheSectionInner - (Mode, AddressSpace, Address, FromMdl, Thread); - Thread->ActiveFaultCount--; + Thread = PsGetCurrentThread(); - ASSERT(Status != STATUS_UNSUCCESSFUL); - ASSERT(Status != STATUS_INVALID_PARAMETER); - DPRINT("MmAccessFault %x:%x -> %x\n", MmGetAddressSpaceOwner(AddressSpace), Address, Status); + if (KeGetCurrentIrql() >= DISPATCH_LEVEL) + { + DPRINT1("Page fault at high IRQL %d, address %x\n", + KeGetCurrentIrql(), + Address); + return STATUS_UNSUCCESSFUL; + } - return(Status); + /* Find the memory area for the faulting address */ + if (Address >= (ULONG_PTR)MmSystemRangeStart) + { + /* Check permissions */ + if (Mode != KernelMode) + { + DPRINT1("Address: %x:%x\n", PsGetCurrentProcess(), Address); + return STATUS_ACCESS_VIOLATION; + } + AddressSpace = MmGetKernelAddressSpace(); + } + else + { + AddressSpace = &PsGetCurrentProcess()->Vm; + } + + Thread->ActiveFaultCount++; + Status = MmpSectionAccessFaultInner(Mode, + AddressSpace, + Address, + FromMdl, + Thread); + Thread->ActiveFaultCount--; + + return Status; +} + +NTSTATUS +NTAPI +MmNotPresentFaultCacheSectionInner(KPROCESSOR_MODE Mode, + PMMSUPPORT AddressSpace, + ULONG_PTR Address, + BOOLEAN FromMdl, + PETHREAD Thread) +{ + BOOLEAN Locked = FromMdl; + PMEMORY_AREA MemoryArea; + MM_REQUIRED_RESOURCES Resources = { 0 }; + WORK_QUEUE_WITH_CONTEXT Context; + NTSTATUS Status = STATUS_SUCCESS; + + RtlZeroMemory(&Context, sizeof(WORK_QUEUE_WITH_CONTEXT)); + + if (!FromMdl) + { + MmLockAddressSpace(AddressSpace); + } + + /* Call the memory area specific fault handler */ + do + { + MemoryArea = MmLocateMemoryAreaByAddress(AddressSpace, (PVOID)Address); + if (MemoryArea == NULL || MemoryArea->DeleteInProgress) + { + Status = STATUS_ACCESS_VIOLATION; + if (MemoryArea) + { + DPRINT1("Type %x DIP %x\n", + MemoryArea->Type, + MemoryArea->DeleteInProgress); + } + else + { + DPRINT1("No memory area\n"); + } + DPRINT1("Process %x, Address %x\n", + MmGetAddressSpaceOwner(AddressSpace), + Address); + break; + } + + DPRINTC("Type %x (%x -> %x -> %x) in %x\n", + MemoryArea->Type, + MemoryArea->StartingAddress, + Address, + MemoryArea->EndingAddress, + PsGetCurrentThread()); + + Resources.DoAcquisition = NULL; + + // Note: fault handlers are called with address space locked + // We return STATUS_MORE_PROCESSING_REQUIRED if anything is needed + + Status = MmNotPresentFaultCachePage(AddressSpace, + MemoryArea, + (PVOID)Address, + Locked, + &Resources); + + if (!FromMdl) + { + MmUnlockAddressSpace(AddressSpace); + } + + if (Status == STATUS_SUCCESS) + { + ; // Nothing + } + else if (Status == STATUS_SUCCESS + 1) + { + /* Wait page ... */ + DPRINT("Waiting for %x\n", Address); + MiWaitForPageEvent(MmGetAddressSpaceOwner(AddressSpace), Address); + DPRINT("Done waiting for %x\n", Address); + Status = STATUS_MM_RESTART_OPERATION; + } + else if (Status == STATUS_MM_RESTART_OPERATION) + { + /* Clean slate */ + DPRINT("Clear resource\n"); + RtlZeroMemory(&Resources, sizeof(Resources)); + } + else if (Status == STATUS_MORE_PROCESSING_REQUIRED) + { + if (Thread->ActiveFaultCount > 2) + { + DPRINTC("Already fault handling ... going to work item (%x)\n", Address); + Context.AddressSpace = AddressSpace; + Context.MemoryArea = MemoryArea; + Context.Required = &Resources; + KeInitializeEvent(&Context.Wait, NotificationEvent, FALSE); + + ExInitializeWorkItem(&Context.WorkItem, + (PWORKER_THREAD_ROUTINE)MmpFaultWorker, + &Context); + + DPRINT("Queue work item\n"); + ExQueueWorkItem(&Context.WorkItem, DelayedWorkQueue); + DPRINT("Wait\n"); + KeWaitForSingleObject(&Context.Wait, 0, KernelMode, FALSE, NULL); + Status = Context.Status; + DPRINTC("Status %x\n", Status); + } + else + { + DPRINT("DoAcquisition %x\n", Resources.DoAcquisition); + + Status = Resources.DoAcquisition(AddressSpace, + MemoryArea, + &Resources); + + DPRINT("DoAcquisition %x -> %x\n", + Resources.DoAcquisition, + Status); + } + + if (NT_SUCCESS(Status)) + { + Status = STATUS_MM_RESTART_OPERATION; + } + } + else if (NT_SUCCESS(Status)) + { + ASSERT(FALSE); + } + + if (!FromMdl) + { + MmLockAddressSpace(AddressSpace); + } + } + while (Status == STATUS_MM_RESTART_OPERATION); + + DPRINTC("Completed page fault handling: %x:%x %x\n", + MmGetAddressSpaceOwner(AddressSpace), + Address, + Status); + + if (!FromMdl) + { + MmUnlockAddressSpace(AddressSpace); + } + + MiSetPageEvent(MmGetAddressSpaceOwner(AddressSpace), Address); + DPRINT("Done %x\n", Status); + + return Status; +} + +NTSTATUS +NTAPI +MmNotPresentFaultCacheSection(KPROCESSOR_MODE Mode, + ULONG_PTR Address, + BOOLEAN FromMdl) +{ + PETHREAD Thread; + PMMSUPPORT AddressSpace; + NTSTATUS Status; + + Address &= ~(PAGE_SIZE - 1); + DPRINT("MmNotPresentFault(Mode %d, Address %x)\n", Mode, Address); + + Thread = PsGetCurrentThread(); + + if (KeGetCurrentIrql() >= DISPATCH_LEVEL) + { + DPRINT1("Page fault at high IRQL %d, address %x\n", + KeGetCurrentIrql(), + Address); + + ASSERT(FALSE); + return STATUS_UNSUCCESSFUL; + } + + /* Find the memory area for the faulting address */ + if (Address >= (ULONG_PTR)MmSystemRangeStart) + { + /* Check permissions */ + if (Mode != KernelMode) + { + DPRINTC("Address: %x\n", Address); + return STATUS_ACCESS_VIOLATION; + } + AddressSpace = MmGetKernelAddressSpace(); + } + else + { + AddressSpace = &PsGetCurrentProcess()->Vm; + } + + Thread->ActiveFaultCount++; + Status = MmNotPresentFaultCacheSectionInner(Mode, + AddressSpace, + Address, + FromMdl, + Thread); + Thread->ActiveFaultCount--; + + ASSERT(Status != STATUS_UNSUCCESSFUL); + ASSERT(Status != STATUS_INVALID_PARAMETER); + DPRINT("MmAccessFault %x:%x -> %x\n", + MmGetAddressSpaceOwner(AddressSpace), + Address, + Status); + + return Status; } diff --git a/reactos/ntoskrnl/cache/section/io.c b/reactos/ntoskrnl/cache/section/io.c index 09384470af4..19d6269e904 100644 --- a/reactos/ntoskrnl/cache/section/io.c +++ b/reactos/ntoskrnl/cache/section/io.c @@ -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; } diff --git a/reactos/ntoskrnl/cache/section/newmm.h b/reactos/ntoskrnl/cache/section/newmm.h index 3bd1762434f..3443b955caf 100644 --- a/reactos/ntoskrnl/cache/section/newmm.h +++ b/reactos/ntoskrnl/cache/section/newmm.h @@ -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); diff --git a/reactos/ntoskrnl/cache/section/reqtools.c b/reactos/ntoskrnl/cache/section/reqtools.c index 6f77f21e520..3f248498896 100644 --- a/reactos/ntoskrnl/cache/section/reqtools.c +++ b/reactos/ntoskrnl/cache/section/reqtools.c @@ -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]); } diff --git a/reactos/ntoskrnl/cache/section/sptab.c b/reactos/ntoskrnl/cache/section/sptab.c index 2e240f7e83b..9f39a85c0ed 100644 --- a/reactos/ntoskrnl/cache/section/sptab.c +++ b/reactos/ntoskrnl/cache/section/sptab.c @@ -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; } diff --git a/reactos/ntoskrnl/cache/section/swapout.c b/reactos/ntoskrnl/cache/section/swapout.c index dcadefbe2bf..60c1c223e23 100644 --- a/reactos/ntoskrnl/cache/section/swapout.c +++ b/reactos/ntoskrnl/cache/section/swapout.c @@ -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; }