1c2c66affSColin Finck /* 2c2c66affSColin Finck * COPYRIGHT: See COPYING in the top directory 3c2c66affSColin Finck * PROJECT: ReactOS kernel 4c2c66affSColin Finck * FILE: ntoskrnl/mm/rmap.c 5c2c66affSColin Finck * PURPOSE: Kernel memory managment functions 6c2c66affSColin Finck * 7c2c66affSColin Finck * PROGRAMMERS: David Welch (welch@cwcom.net) 8c2c66affSColin Finck */ 9c2c66affSColin Finck 10c2c66affSColin Finck /* INCLUDES *****************************************************************/ 11c2c66affSColin Finck 12c2c66affSColin Finck #include <ntoskrnl.h> 13c2c66affSColin Finck #include <cache/section/newmm.h> 14c2c66affSColin Finck #define NDEBUG 15c2c66affSColin Finck #include <debug.h> 16c2c66affSColin Finck 17c2c66affSColin Finck /* TYPES ********************************************************************/ 18c2c66affSColin Finck 19c2c66affSColin Finck /* GLOBALS ******************************************************************/ 20c2c66affSColin Finck 21c2c66affSColin Finck static NPAGED_LOOKASIDE_LIST RmapLookasideList; 22c2c66affSColin Finck 23c2c66affSColin Finck /* FUNCTIONS ****************************************************************/ 24c2c66affSColin Finck 25c2c66affSColin Finck _IRQL_requires_max_(DISPATCH_LEVEL) 26c2c66affSColin Finck static 27c2c66affSColin Finck VOID 28c2c66affSColin Finck NTAPI 29c2c66affSColin Finck RmapListFree( 30c2c66affSColin Finck _In_ __drv_freesMem(Mem) PVOID P) 31c2c66affSColin Finck { 32c2c66affSColin Finck ExFreePoolWithTag(P, TAG_RMAP); 33c2c66affSColin Finck } 34c2c66affSColin Finck 355c7ce447SVictor Perevertkin CODE_SEG("INIT") 36b20f8151SSerge Gautherie VOID 37c2c66affSColin Finck NTAPI 38c2c66affSColin Finck MmInitializeRmapList(VOID) 39c2c66affSColin Finck { 40c2c66affSColin Finck ExInitializeNPagedLookasideList (&RmapLookasideList, 41c2c66affSColin Finck NULL, 42c2c66affSColin Finck RmapListFree, 43c2c66affSColin Finck 0, 44c2c66affSColin Finck sizeof(MM_RMAP_ENTRY), 45c2c66affSColin Finck TAG_RMAP, 46c2c66affSColin Finck 50); 47c2c66affSColin Finck } 48c2c66affSColin Finck 49c2c66affSColin Finck NTSTATUS 50c2c66affSColin Finck NTAPI 51c2c66affSColin Finck MmPageOutPhysicalAddress(PFN_NUMBER Page) 52c2c66affSColin Finck { 53c2c66affSColin Finck PMM_RMAP_ENTRY entry; 54c2c66affSColin Finck PMEMORY_AREA MemoryArea; 55c2c66affSColin Finck PMMSUPPORT AddressSpace; 56c2c66affSColin Finck PVOID Address; 57c2c66affSColin Finck PEPROCESS Process; 58c2c66affSColin Finck NTSTATUS Status = STATUS_SUCCESS; 59d8cdb89fSJérôme Gardou PMM_SECTION_SEGMENT Segment; 60d8cdb89fSJérôme Gardou LARGE_INTEGER SegmentOffset; 61d8cdb89fSJérôme Gardou KIRQL OldIrql; 62c2c66affSColin Finck 63d8cdb89fSJérôme Gardou OldIrql = MiAcquirePfnLock(); 64d8cdb89fSJérôme Gardou 65c2c66affSColin Finck entry = MmGetRmapListHeadPage(Page); 66c2c66affSColin Finck 67c2c66affSColin Finck while (entry && RMAP_IS_SEGMENT(entry->Address)) 68c2c66affSColin Finck entry = entry->Next; 69c2c66affSColin Finck 70c2c66affSColin Finck if (entry == NULL) 71c2c66affSColin Finck { 72d8cdb89fSJérôme Gardou MiReleasePfnLock(OldIrql); 73d932bdb9SJérôme Gardou goto WriteSegment; 74c2c66affSColin Finck } 75c2c66affSColin Finck 76c2c66affSColin Finck Process = entry->Process; 77c2c66affSColin Finck Address = entry->Address; 78c2c66affSColin Finck 79c2c66affSColin Finck if ((((ULONG_PTR)Address) & 0xFFF) != 0) 80c2c66affSColin Finck { 81c2c66affSColin Finck KeBugCheck(MEMORY_MANAGEMENT); 82c2c66affSColin Finck } 83c2c66affSColin Finck 84c2c66affSColin Finck if (Address < MmSystemRangeStart) 85c2c66affSColin Finck { 86c2c66affSColin Finck if (!ExAcquireRundownProtection(&Process->RundownProtect)) 87c2c66affSColin Finck { 88d8cdb89fSJérôme Gardou MiReleasePfnLock(OldIrql); 89c2c66affSColin Finck return STATUS_PROCESS_IS_TERMINATING; 90c2c66affSColin Finck } 91c2c66affSColin Finck 92c2c66affSColin Finck Status = ObReferenceObjectByPointer(Process, PROCESS_ALL_ACCESS, NULL, KernelMode); 93d8cdb89fSJérôme Gardou MiReleasePfnLock(OldIrql); 94c2c66affSColin Finck if (!NT_SUCCESS(Status)) 95c2c66affSColin Finck { 96c2c66affSColin Finck ExReleaseRundownProtection(&Process->RundownProtect); 97c2c66affSColin Finck return Status; 98c2c66affSColin Finck } 99c2c66affSColin Finck AddressSpace = &Process->Vm; 100c2c66affSColin Finck } 101c2c66affSColin Finck else 102c2c66affSColin Finck { 103d8cdb89fSJérôme Gardou MiReleasePfnLock(OldIrql); 104c2c66affSColin Finck AddressSpace = MmGetKernelAddressSpace(); 105c2c66affSColin Finck } 106c2c66affSColin Finck 107c2c66affSColin Finck MmLockAddressSpace(AddressSpace); 108d8cdb89fSJérôme Gardou 109c2c66affSColin Finck MemoryArea = MmLocateMemoryAreaByAddress(AddressSpace, Address); 110c2c66affSColin Finck if (MemoryArea == NULL || MemoryArea->DeleteInProgress) 111c2c66affSColin Finck { 112c2c66affSColin Finck MmUnlockAddressSpace(AddressSpace); 113c2c66affSColin Finck if (Address < MmSystemRangeStart) 114c2c66affSColin Finck { 115c2c66affSColin Finck ExReleaseRundownProtection(&Process->RundownProtect); 116c2c66affSColin Finck ObDereferenceObject(Process); 117c2c66affSColin Finck } 118c2c66affSColin Finck return(STATUS_UNSUCCESSFUL); 119c2c66affSColin Finck } 120d8cdb89fSJérôme Gardou 121d8cdb89fSJérôme Gardou if (MemoryArea->Type == MEMORY_AREA_SECTION_VIEW) 122c2c66affSColin Finck { 123c2c66affSColin Finck ULONG_PTR Entry; 124d8cdb89fSJérôme Gardou BOOLEAN Dirty; 125d8cdb89fSJérôme Gardou PFN_NUMBER MapPage; 126d8cdb89fSJérôme Gardou LARGE_INTEGER Offset; 127d8cdb89fSJérôme Gardou BOOLEAN Released; 128d8cdb89fSJérôme Gardou 129d8cdb89fSJérôme Gardou Offset.QuadPart = MemoryArea->SectionData.ViewOffset.QuadPart + 130c2c66affSColin Finck ((ULONG_PTR)Address - MA_GetStartingAddress(MemoryArea)); 131c2c66affSColin Finck 132d8cdb89fSJérôme Gardou Segment = MemoryArea->SectionData.Segment; 133c2c66affSColin Finck 134d8cdb89fSJérôme Gardou MmLockSectionSegment(Segment); 135d8cdb89fSJérôme Gardou 136d8cdb89fSJérôme Gardou Entry = MmGetPageEntrySectionSegment(Segment, &Offset); 137c2c66affSColin Finck if (Entry && MM_IS_WAIT_PTE(Entry)) 138c2c66affSColin Finck { 139d8cdb89fSJérôme Gardou /* The segment is being read or something. Give up */ 140d8cdb89fSJérôme Gardou MmUnlockSectionSegment(Segment); 141c2c66affSColin Finck MmUnlockAddressSpace(AddressSpace); 142c2c66affSColin Finck if (Address < MmSystemRangeStart) 143c2c66affSColin Finck { 144c2c66affSColin Finck ExReleaseRundownProtection(&Process->RundownProtect); 145c2c66affSColin Finck ObDereferenceObject(Process); 146c2c66affSColin Finck } 147c2c66affSColin Finck return(STATUS_UNSUCCESSFUL); 148c2c66affSColin Finck } 149c2c66affSColin Finck 150d8cdb89fSJérôme Gardou /* Delete this virtual mapping in the process */ 151d8cdb89fSJérôme Gardou MmDeleteVirtualMapping(Process, Address, &Dirty, &MapPage); 152d8cdb89fSJérôme Gardou ASSERT(MapPage == Page); 153c2c66affSColin Finck 154d8cdb89fSJérôme Gardou if (Page != PFN_FROM_SSE(Entry)) 155d8cdb89fSJérôme Gardou { 156d8cdb89fSJérôme Gardou SWAPENTRY SwapEntry; 157d8cdb89fSJérôme Gardou 158d8cdb89fSJérôme Gardou /* This page is private to the process */ 159d8cdb89fSJérôme Gardou MmUnlockSectionSegment(Segment); 160d8cdb89fSJérôme Gardou 161d8cdb89fSJérôme Gardou /* Check if we should write it back to the page file */ 162d8cdb89fSJérôme Gardou SwapEntry = MmGetSavedSwapEntryPage(Page); 163d8cdb89fSJérôme Gardou 164d8cdb89fSJérôme Gardou if ((SwapEntry == 0) && Dirty) 165d8cdb89fSJérôme Gardou { 166d8cdb89fSJérôme Gardou /* We don't have a Swap entry, yet the page is dirty. Get one */ 167d8cdb89fSJérôme Gardou SwapEntry = MmAllocSwapPage(); 168d8cdb89fSJérôme Gardou if (!SwapEntry) 169d8cdb89fSJérôme Gardou { 170d8cdb89fSJérôme Gardou PMM_REGION Region = MmFindRegion((PVOID)MA_GetStartingAddress(MemoryArea), 171d8cdb89fSJérôme Gardou &MemoryArea->SectionData.RegionListHead, 172d8cdb89fSJérôme Gardou Address, NULL); 173d8cdb89fSJérôme Gardou 174d8cdb89fSJérôme Gardou /* We can't, so let this page in the Process VM */ 175d8cdb89fSJérôme Gardou MmCreateVirtualMapping(Process, Address, Region->Protect, &Page, 1); 176d8cdb89fSJérôme Gardou MmSetDirtyPage(Process, Address); 177d8cdb89fSJérôme Gardou 178d8cdb89fSJérôme Gardou MmUnlockAddressSpace(AddressSpace); 179d932bdb9SJérôme Gardou if (Address < MmSystemRangeStart) 180d932bdb9SJérôme Gardou { 181d932bdb9SJérôme Gardou ExReleaseRundownProtection(&Process->RundownProtect); 182d932bdb9SJérôme Gardou ObDereferenceObject(Process); 183d932bdb9SJérôme Gardou } 184d932bdb9SJérôme Gardou 185d8cdb89fSJérôme Gardou return STATUS_UNSUCCESSFUL; 186d8cdb89fSJérôme Gardou } 187d8cdb89fSJérôme Gardou } 188d8cdb89fSJérôme Gardou 189d8cdb89fSJérôme Gardou if (Dirty) 190d8cdb89fSJérôme Gardou { 191d8cdb89fSJérôme Gardou Status = MmWriteToSwapPage(SwapEntry, Page); 192d8cdb89fSJérôme Gardou if (!NT_SUCCESS(Status)) 193d8cdb89fSJérôme Gardou { 194d8cdb89fSJérôme Gardou /* We failed at saving the content of this page. Keep it in */ 195d8cdb89fSJérôme Gardou PMM_REGION Region = MmFindRegion((PVOID)MA_GetStartingAddress(MemoryArea), 196d8cdb89fSJérôme Gardou &MemoryArea->SectionData.RegionListHead, 197d8cdb89fSJérôme Gardou Address, NULL); 198d8cdb89fSJérôme Gardou 199d8cdb89fSJérôme Gardou /* This Swap Entry is useless to us */ 200d8cdb89fSJérôme Gardou MmSetSavedSwapEntryPage(Page, 0); 201d8cdb89fSJérôme Gardou MmFreeSwapPage(SwapEntry); 202d8cdb89fSJérôme Gardou 203d8cdb89fSJérôme Gardou /* We can't, so let this page in the Process VM */ 204d8cdb89fSJérôme Gardou MmCreateVirtualMapping(Process, Address, Region->Protect, &Page, 1); 205d8cdb89fSJérôme Gardou MmSetDirtyPage(Process, Address); 206d8cdb89fSJérôme Gardou 207d8cdb89fSJérôme Gardou MmUnlockAddressSpace(AddressSpace); 208d932bdb9SJérôme Gardou if (Address < MmSystemRangeStart) 209d932bdb9SJérôme Gardou { 210d932bdb9SJérôme Gardou ExReleaseRundownProtection(&Process->RundownProtect); 211d932bdb9SJérôme Gardou ObDereferenceObject(Process); 212d932bdb9SJérôme Gardou } 213d8cdb89fSJérôme Gardou return STATUS_UNSUCCESSFUL; 214d8cdb89fSJérôme Gardou } 215d8cdb89fSJérôme Gardou } 216d8cdb89fSJérôme Gardou 217d8cdb89fSJérôme Gardou if (SwapEntry) 218d8cdb89fSJérôme Gardou { 219d8cdb89fSJérôme Gardou /* Keep this in the process VM */ 220d8cdb89fSJérôme Gardou MmCreatePageFileMapping(Process, Address, SwapEntry); 221d8cdb89fSJérôme Gardou MmSetSavedSwapEntryPage(Page, 0); 222d8cdb89fSJérôme Gardou } 223d8cdb89fSJérôme Gardou 224c2c66affSColin Finck MmUnlockAddressSpace(AddressSpace); 225c2c66affSColin Finck 226d8cdb89fSJérôme Gardou /* We can finally let this page go */ 227d8cdb89fSJérôme Gardou MmDeleteRmap(Page, Process, Address); 228d8cdb89fSJérôme Gardou ASSERT(MmGetRmapListHeadPage(Page) == NULL); 229ba49c390SJérôme Gardou MmReleasePageMemoryConsumer(MC_USER, Page); 230d8cdb89fSJérôme Gardou 231d8cdb89fSJérôme Gardou if (Address < MmSystemRangeStart) 232d8cdb89fSJérôme Gardou { 233d8cdb89fSJérôme Gardou ExReleaseRundownProtection(&Process->RundownProtect); 234d8cdb89fSJérôme Gardou ObDereferenceObject(Process); 235d8cdb89fSJérôme Gardou } 236d8cdb89fSJérôme Gardou return STATUS_SUCCESS; 237d8cdb89fSJérôme Gardou } 238d8cdb89fSJérôme Gardou 239d8cdb89fSJérôme Gardou /* Delete this RMAP */ 240d8cdb89fSJérôme Gardou MmDeleteRmap(Page, Process, Address); 241d8cdb89fSJérôme Gardou 242d8cdb89fSJérôme Gardou /* One less mapping referencing this segment */ 243d8cdb89fSJérôme Gardou Released = MmUnsharePageEntrySectionSegment(MemoryArea, Segment, &Offset, Dirty, FALSE, NULL); 244d8cdb89fSJérôme Gardou 245d8cdb89fSJérôme Gardou MmUnlockSectionSegment(Segment); 246d8cdb89fSJérôme Gardou MmUnlockAddressSpace(AddressSpace); 247d8cdb89fSJérôme Gardou 248d8cdb89fSJérôme Gardou if (Address < MmSystemRangeStart) 249d8cdb89fSJérôme Gardou { 250d8cdb89fSJérôme Gardou ExReleaseRundownProtection(&Process->RundownProtect); 251d8cdb89fSJérôme Gardou ObDereferenceObject(Process); 252d8cdb89fSJérôme Gardou } 253d8cdb89fSJérôme Gardou 254d8cdb89fSJérôme Gardou if (Released) return STATUS_SUCCESS; 255c2c66affSColin Finck } 256462d9a09SJérôme Gardou #ifdef NEWCC 257c2c66affSColin Finck else if (Type == MEMORY_AREA_CACHE) 258c2c66affSColin Finck { 259c2c66affSColin Finck /* NEWCC does locking itself */ 260c2c66affSColin Finck MmUnlockAddressSpace(AddressSpace); 261c2c66affSColin Finck Status = MmpPageOutPhysicalAddress(Page); 262c2c66affSColin Finck } 263462d9a09SJérôme Gardou #endif 264c2c66affSColin Finck else 265c2c66affSColin Finck { 266c2c66affSColin Finck KeBugCheck(MEMORY_MANAGEMENT); 267c2c66affSColin Finck } 268c2c66affSColin Finck 269d932bdb9SJérôme Gardou WriteSegment: 270d8cdb89fSJérôme Gardou /* Now write this page to file, if needed */ 271d8cdb89fSJérôme Gardou Segment = MmGetSectionAssociation(Page, &SegmentOffset); 272d8cdb89fSJérôme Gardou if (Segment) 273d8cdb89fSJérôme Gardou { 274d8cdb89fSJérôme Gardou BOOLEAN Released; 275d8cdb89fSJérôme Gardou 276d8cdb89fSJérôme Gardou MmLockSectionSegment(Segment); 277d8cdb89fSJérôme Gardou 278d8cdb89fSJérôme Gardou Released = MmCheckDirtySegment(Segment, &SegmentOffset, FALSE, TRUE); 279d8cdb89fSJérôme Gardou 280d8cdb89fSJérôme Gardou MmUnlockSectionSegment(Segment); 281d8cdb89fSJérôme Gardou 282d8cdb89fSJérôme Gardou MmDereferenceSegment(Segment); 283d8cdb89fSJérôme Gardou 284d8cdb89fSJérôme Gardou if (Released) 285d8cdb89fSJérôme Gardou { 286d8cdb89fSJérôme Gardou return STATUS_SUCCESS; 287d8cdb89fSJérôme Gardou } 288d8cdb89fSJérôme Gardou } 289d8cdb89fSJérôme Gardou 290d8cdb89fSJérôme Gardou /* If we are here, then we didn't release the page */ 291d8cdb89fSJérôme Gardou return STATUS_UNSUCCESSFUL; 292c2c66affSColin Finck } 293c2c66affSColin Finck 294c2c66affSColin Finck VOID 295c2c66affSColin Finck NTAPI 296c2c66affSColin Finck MmSetCleanAllRmaps(PFN_NUMBER Page) 297c2c66affSColin Finck { 298c2c66affSColin Finck PMM_RMAP_ENTRY current_entry; 299d8cdb89fSJérôme Gardou KIRQL OldIrql; 300c2c66affSColin Finck 301d8cdb89fSJérôme Gardou OldIrql = MiAcquirePfnLock(); 302c2c66affSColin Finck current_entry = MmGetRmapListHeadPage(Page); 303c2c66affSColin Finck if (current_entry == NULL) 304c2c66affSColin Finck { 305d8cdb89fSJérôme Gardou DPRINT1("MmSetCleanAllRmaps: No rmaps.\n"); 306c2c66affSColin Finck KeBugCheck(MEMORY_MANAGEMENT); 307c2c66affSColin Finck } 308c2c66affSColin Finck while (current_entry != NULL) 309c2c66affSColin Finck { 310c2c66affSColin Finck if (!RMAP_IS_SEGMENT(current_entry->Address)) 311c2c66affSColin Finck MmSetCleanPage(current_entry->Process, current_entry->Address); 312c2c66affSColin Finck current_entry = current_entry->Next; 313c2c66affSColin Finck } 314d8cdb89fSJérôme Gardou MiReleasePfnLock(OldIrql); 315c2c66affSColin Finck } 316c2c66affSColin Finck 317c2c66affSColin Finck BOOLEAN 318c2c66affSColin Finck NTAPI 319c2c66affSColin Finck MmIsDirtyPageRmap(PFN_NUMBER Page) 320c2c66affSColin Finck { 321c2c66affSColin Finck PMM_RMAP_ENTRY current_entry; 322d8cdb89fSJérôme Gardou KIRQL OldIrql; 323d8cdb89fSJérôme Gardou BOOLEAN Dirty = FALSE; 324c2c66affSColin Finck 325d8cdb89fSJérôme Gardou OldIrql = MiAcquirePfnLock(); 326c2c66affSColin Finck current_entry = MmGetRmapListHeadPage(Page); 327c2c66affSColin Finck if (current_entry == NULL) 328c2c66affSColin Finck { 329d8cdb89fSJérôme Gardou DPRINT1("MmIsDirtyPageRmap: No rmaps.\n"); 330d8cdb89fSJérôme Gardou KeBugCheck(MEMORY_MANAGEMENT); 331c2c66affSColin Finck } 332c2c66affSColin Finck while (current_entry != NULL) 333c2c66affSColin Finck { 334d8cdb89fSJérôme Gardou if (!RMAP_IS_SEGMENT(current_entry->Address)) 335c2c66affSColin Finck { 336d8cdb89fSJérôme Gardou if (MmIsDirtyPage(current_entry->Process, current_entry->Address)) 337d8cdb89fSJérôme Gardou { 338d8cdb89fSJérôme Gardou Dirty = TRUE; 339d8cdb89fSJérôme Gardou break; 340d8cdb89fSJérôme Gardou } 341c2c66affSColin Finck } 342c2c66affSColin Finck current_entry = current_entry->Next; 343c2c66affSColin Finck } 344d8cdb89fSJérôme Gardou MiReleasePfnLock(OldIrql); 345d8cdb89fSJérôme Gardou 346d8cdb89fSJérôme Gardou return Dirty; 347c2c66affSColin Finck } 348c2c66affSColin Finck 349c2c66affSColin Finck VOID 350c2c66affSColin Finck NTAPI 351c2c66affSColin Finck MmInsertRmap(PFN_NUMBER Page, PEPROCESS Process, 352c2c66affSColin Finck PVOID Address) 353c2c66affSColin Finck { 354c2c66affSColin Finck PMM_RMAP_ENTRY current_entry; 355c2c66affSColin Finck PMM_RMAP_ENTRY new_entry; 356c2c66affSColin Finck ULONG PrevSize; 357d8cdb89fSJérôme Gardou KIRQL OldIrql; 358d8cdb89fSJérôme Gardou 359c2c66affSColin Finck if (!RMAP_IS_SEGMENT(Address)) 360c2c66affSColin Finck Address = (PVOID)PAGE_ROUND_DOWN(Address); 361c2c66affSColin Finck 362c2c66affSColin Finck new_entry = ExAllocateFromNPagedLookasideList(&RmapLookasideList); 363c2c66affSColin Finck if (new_entry == NULL) 364c2c66affSColin Finck { 365c2c66affSColin Finck KeBugCheck(MEMORY_MANAGEMENT); 366c2c66affSColin Finck } 367c2c66affSColin Finck new_entry->Address = Address; 368c2c66affSColin Finck new_entry->Process = (PEPROCESS)Process; 369c2c66affSColin Finck #if DBG 370c2c66affSColin Finck #ifdef __GNUC__ 371c2c66affSColin Finck new_entry->Caller = __builtin_return_address(0); 372c2c66affSColin Finck #else 373c2c66affSColin Finck new_entry->Caller = _ReturnAddress(); 374c2c66affSColin Finck #endif 375c2c66affSColin Finck #endif 376c2c66affSColin Finck 377c2c66affSColin Finck if ( 378c2c66affSColin Finck !RMAP_IS_SEGMENT(Address) && 379c2c66affSColin Finck MmGetPfnForProcess(Process, Address) != Page) 380c2c66affSColin Finck { 381c2c66affSColin Finck DPRINT1("Insert rmap (%d, 0x%.8X) 0x%.8X which doesn't match physical " 382c2c66affSColin Finck "address 0x%.8X\n", Process ? Process->UniqueProcessId : 0, 383c2c66affSColin Finck Address, 384c2c66affSColin Finck MmGetPfnForProcess(Process, Address) << PAGE_SHIFT, 385c2c66affSColin Finck Page << PAGE_SHIFT); 386c2c66affSColin Finck KeBugCheck(MEMORY_MANAGEMENT); 387c2c66affSColin Finck } 388c2c66affSColin Finck 389d8cdb89fSJérôme Gardou OldIrql = MiAcquirePfnLock(); 390c2c66affSColin Finck current_entry = MmGetRmapListHeadPage(Page); 391c2c66affSColin Finck new_entry->Next = current_entry; 392c2c66affSColin Finck #if DBG 393c2c66affSColin Finck while (current_entry) 394c2c66affSColin Finck { 395c2c66affSColin Finck if (current_entry->Address == new_entry->Address && current_entry->Process == new_entry->Process) 396c2c66affSColin Finck { 397c2c66affSColin Finck DbgPrint("MmInsertRmap tries to add a second rmap entry for address %p\n current caller ", 398c2c66affSColin Finck current_entry->Address); 399c2c66affSColin Finck DbgPrint("%p", new_entry->Caller); 400c2c66affSColin Finck DbgPrint("\n previous caller "); 401c2c66affSColin Finck DbgPrint("%p", current_entry->Caller); 402c2c66affSColin Finck DbgPrint("\n"); 403c2c66affSColin Finck KeBugCheck(MEMORY_MANAGEMENT); 404c2c66affSColin Finck } 405c2c66affSColin Finck current_entry = current_entry->Next; 406c2c66affSColin Finck } 407c2c66affSColin Finck #endif 408c2c66affSColin Finck MmSetRmapListHeadPage(Page, new_entry); 409d8cdb89fSJérôme Gardou MiReleasePfnLock(OldIrql); 410d8cdb89fSJérôme Gardou 411c2c66affSColin Finck if (!RMAP_IS_SEGMENT(Address)) 412c2c66affSColin Finck { 413*11eee4eeSJérôme Gardou ASSERT(Process != NULL); 414c2c66affSColin Finck PrevSize = InterlockedExchangeAddUL(&Process->Vm.WorkingSetSize, PAGE_SIZE); 415c2c66affSColin Finck if (PrevSize >= Process->Vm.PeakWorkingSetSize) 416c2c66affSColin Finck { 417c2c66affSColin Finck Process->Vm.PeakWorkingSetSize = PrevSize + PAGE_SIZE; 418c2c66affSColin Finck } 419c2c66affSColin Finck } 420c2c66affSColin Finck } 421c2c66affSColin Finck 422c2c66affSColin Finck VOID 423c2c66affSColin Finck NTAPI 424c2c66affSColin Finck MmDeleteRmap(PFN_NUMBER Page, PEPROCESS Process, 425c2c66affSColin Finck PVOID Address) 426c2c66affSColin Finck { 427c2c66affSColin Finck PMM_RMAP_ENTRY current_entry, previous_entry; 428d8cdb89fSJérôme Gardou KIRQL OldIrql; 429c2c66affSColin Finck 430d8cdb89fSJérôme Gardou OldIrql = MiAcquirePfnLock(); 431c2c66affSColin Finck previous_entry = NULL; 432c2c66affSColin Finck current_entry = MmGetRmapListHeadPage(Page); 433c2c66affSColin Finck 434c2c66affSColin Finck while (current_entry != NULL) 435c2c66affSColin Finck { 436c2c66affSColin Finck if (current_entry->Process == (PEPROCESS)Process && 437c2c66affSColin Finck current_entry->Address == Address) 438c2c66affSColin Finck { 439c2c66affSColin Finck if (previous_entry == NULL) 440c2c66affSColin Finck { 441c2c66affSColin Finck MmSetRmapListHeadPage(Page, current_entry->Next); 442c2c66affSColin Finck } 443c2c66affSColin Finck else 444c2c66affSColin Finck { 445c2c66affSColin Finck previous_entry->Next = current_entry->Next; 446c2c66affSColin Finck } 447d8cdb89fSJérôme Gardou MiReleasePfnLock(OldIrql); 448d8cdb89fSJérôme Gardou 449c2c66affSColin Finck ExFreeToNPagedLookasideList(&RmapLookasideList, current_entry); 450c2c66affSColin Finck if (!RMAP_IS_SEGMENT(Address)) 451c2c66affSColin Finck { 452*11eee4eeSJérôme Gardou ASSERT(Process != NULL); 453c2c66affSColin Finck (void)InterlockedExchangeAddUL(&Process->Vm.WorkingSetSize, -PAGE_SIZE); 454c2c66affSColin Finck } 455c2c66affSColin Finck return; 456c2c66affSColin Finck } 457c2c66affSColin Finck previous_entry = current_entry; 458c2c66affSColin Finck current_entry = current_entry->Next; 459c2c66affSColin Finck } 460c2c66affSColin Finck KeBugCheck(MEMORY_MANAGEMENT); 461c2c66affSColin Finck } 462c2c66affSColin Finck 463c2c66affSColin Finck /* 464c2c66affSColin Finck 465c2c66affSColin Finck Return the process pointer given when a previous call to MmInsertRmap was 466c2c66affSColin Finck called with a process and address pointer that conform to the segment rmap 467c2c66affSColin Finck schema. In short, this requires the address part to be 0xffffff00 + n 468c2c66affSColin Finck where n is between 0 and 255. When such an rmap exists, it specifies a 469c2c66affSColin Finck segment rmap in which the process part is a pointer to a slice of a section 470c2c66affSColin Finck page table, and the low 8 bits of the address represent a page index in the 471c2c66affSColin Finck page table slice. Together, this information is used by 472c2c66affSColin Finck MmGetSectionAssociation to determine which page entry points to this page in 473c2c66affSColin Finck the segment page table. 474c2c66affSColin Finck 475c2c66affSColin Finck */ 476c2c66affSColin Finck 477c2c66affSColin Finck PVOID 478c2c66affSColin Finck NTAPI 479c2c66affSColin Finck MmGetSegmentRmap(PFN_NUMBER Page, PULONG RawOffset) 480c2c66affSColin Finck { 481c2c66affSColin Finck PCACHE_SECTION_PAGE_TABLE Result = NULL; 482c2c66affSColin Finck PMM_RMAP_ENTRY current_entry;//, previous_entry; 483d8cdb89fSJérôme Gardou KIRQL OldIrql = MiAcquirePfnLock(); 484c2c66affSColin Finck 485c2c66affSColin Finck //previous_entry = NULL; 486c2c66affSColin Finck current_entry = MmGetRmapListHeadPage(Page); 487c2c66affSColin Finck while (current_entry != NULL) 488c2c66affSColin Finck { 489c2c66affSColin Finck if (RMAP_IS_SEGMENT(current_entry->Address)) 490c2c66affSColin Finck { 491c2c66affSColin Finck Result = (PCACHE_SECTION_PAGE_TABLE)current_entry->Process; 492c2c66affSColin Finck *RawOffset = (ULONG_PTR)current_entry->Address & ~RMAP_SEGMENT_MASK; 493d8cdb89fSJérôme Gardou if (*Result->Segment->Flags & MM_SEGMENT_INDELETE) 494d8cdb89fSJérôme Gardou { 495d8cdb89fSJérôme Gardou MiReleasePfnLock(OldIrql); 496d8cdb89fSJérôme Gardou return NULL; 497d8cdb89fSJérôme Gardou } 498d8cdb89fSJérôme Gardou 499d8cdb89fSJérôme Gardou InterlockedIncrementUL(Result->Segment->ReferenceCount); 500d8cdb89fSJérôme Gardou MiReleasePfnLock(OldIrql); 501c2c66affSColin Finck return Result; 502c2c66affSColin Finck } 503c2c66affSColin Finck //previous_entry = current_entry; 504c2c66affSColin Finck current_entry = current_entry->Next; 505c2c66affSColin Finck } 506d8cdb89fSJérôme Gardou MiReleasePfnLock(OldIrql); 507c2c66affSColin Finck return NULL; 508c2c66affSColin Finck } 509c2c66affSColin Finck 510c2c66affSColin Finck /* 511c2c66affSColin Finck 512c2c66affSColin Finck Remove the section rmap associated with the indicated page, if it exists. 513c2c66affSColin Finck 514c2c66affSColin Finck */ 515c2c66affSColin Finck 516c2c66affSColin Finck VOID 517c2c66affSColin Finck NTAPI 518c2c66affSColin Finck MmDeleteSectionAssociation(PFN_NUMBER Page) 519c2c66affSColin Finck { 520c2c66affSColin Finck PMM_RMAP_ENTRY current_entry, previous_entry; 521d8cdb89fSJérôme Gardou KIRQL OldIrql = MiAcquirePfnLock(); 522c2c66affSColin Finck 523c2c66affSColin Finck previous_entry = NULL; 524c2c66affSColin Finck current_entry = MmGetRmapListHeadPage(Page); 525c2c66affSColin Finck while (current_entry != NULL) 526c2c66affSColin Finck { 527c2c66affSColin Finck if (RMAP_IS_SEGMENT(current_entry->Address)) 528c2c66affSColin Finck { 529c2c66affSColin Finck if (previous_entry == NULL) 530c2c66affSColin Finck { 531c2c66affSColin Finck MmSetRmapListHeadPage(Page, current_entry->Next); 532c2c66affSColin Finck } 533c2c66affSColin Finck else 534c2c66affSColin Finck { 535c2c66affSColin Finck previous_entry->Next = current_entry->Next; 536c2c66affSColin Finck } 537d8cdb89fSJérôme Gardou MiReleasePfnLock(OldIrql); 538c2c66affSColin Finck ExFreeToNPagedLookasideList(&RmapLookasideList, current_entry); 539c2c66affSColin Finck return; 540c2c66affSColin Finck } 541c2c66affSColin Finck previous_entry = current_entry; 542c2c66affSColin Finck current_entry = current_entry->Next; 543c2c66affSColin Finck } 544d8cdb89fSJérôme Gardou MiReleasePfnLock(OldIrql); 545c2c66affSColin Finck } 546