diff --git a/headers/private/kernel/vm/VMTranslationMap.h b/headers/private/kernel/vm/VMTranslationMap.h index e4396afb21..2a29e0685f 100644 --- a/headers/private/kernel/vm/VMTranslationMap.h +++ b/headers/private/kernel/vm/VMTranslationMap.h @@ -84,7 +84,8 @@ public: protected: void PageUnmapped(VMArea* area, page_num_t pageNumber, bool accessed, - bool modified, bool updatePageQueue); + bool modified, bool updatePageQueue, + VMAreaMappings* mappingsQueue = NULL); void UnaccessedPageUnmapped(VMArea* area, page_num_t pageNumber); diff --git a/src/system/kernel/arch/arm/paging/32bit/ARMVMTranslationMap32Bit.cpp b/src/system/kernel/arch/arm/paging/32bit/ARMVMTranslationMap32Bit.cpp index 54946f9be2..ca52197ddd 100644 --- a/src/system/kernel/arch/arm/paging/32bit/ARMVMTranslationMap32Bit.cpp +++ b/src/system/kernel/arch/arm/paging/32bit/ARMVMTranslationMap32Bit.cpp @@ -452,52 +452,11 @@ ARMVMTranslationMap32Bit::UnmapPages(VMArea* area, addr_t base, size_t size, } if (area->cache_type != CACHE_TYPE_DEVICE) { - // get the page - vm_page* page = vm_lookup_page( - (oldEntry & ARM_PTE_ADDRESS_MASK) / B_PAGE_SIZE); - ASSERT(page != NULL); - - DEBUG_PAGE_ACCESS_START(page); - - // transfer the accessed/dirty flags to the page - if ((oldEntry & ARM_MMU_L2_FLAG_AP0) != 0) - page->accessed = true; - if ((oldEntry & ARM_MMU_L2_FLAG_AP2) == 0) - page->modified = true; - - // remove the mapping object/decrement the wired_count of the - // page - if (area->wiring == B_NO_LOCK) { - vm_page_mapping* mapping = NULL; - vm_page_mappings::Iterator iterator - = page->mappings.GetIterator(); - while ((mapping = iterator.Next()) != NULL) { - if (mapping->area == area) - break; - } - - ASSERT(mapping != NULL); - - area->mappings.Remove(mapping); - page->mappings.Remove(mapping); - queue.Add(mapping); - } else - page->DecrementWiredCount(); - - if (!page->IsMapped()) { - atomic_add(&gMappedPagesCount, -1); - - if (updatePageQueue) { - if (page->Cache()->temporary) - vm_page_set_state(page, PAGE_STATE_INACTIVE); - else if (page->modified) - vm_page_set_state(page, PAGE_STATE_MODIFIED); - else - vm_page_set_state(page, PAGE_STATE_CACHED); - } - } - - DEBUG_PAGE_ACCESS_END(page); + page_num_t page = (oldEntry & ARM_PTE_ADDRESS_MASK) / B_PAGE_SIZE; + PageUnmapped(area, page, + (oldEntry & ARM_MMU_L2_FLAG_AP0) != 0, + (oldEntry & ARM_MMU_L2_FLAG_AP2) != 0, + updatePageQueue, &queue); } } diff --git a/src/system/kernel/arch/arm64/VMSAv8TranslationMap.cpp b/src/system/kernel/arch/arm64/VMSAv8TranslationMap.cpp index 47339f867e..9f5fa63b7b 100644 --- a/src/system/kernel/arch/arm64/VMSAv8TranslationMap.cpp +++ b/src/system/kernel/arch/arm64/VMSAv8TranslationMap.cpp @@ -681,49 +681,10 @@ VMSAv8TranslationMap::UnmapPages(VMArea* area, addr_t address, size_t size, bool if (area->cache_type == CACHE_TYPE_DEVICE) return; - // get the page - vm_page* page = vm_lookup_page((oldPte & kPteAddrMask) >> fPageBits); - ASSERT(page != NULL); - - DEBUG_PAGE_ACCESS_START(page); - - // transfer the accessed/dirty flags to the page - page->accessed = is_pte_accessed(oldPte); - page->modified = is_pte_dirty(oldPte); - - // remove the mapping object/decrement the wired_count of the - // page - if (area->wiring == B_NO_LOCK) { - vm_page_mapping* mapping = NULL; - vm_page_mappings::Iterator iterator - = page->mappings.GetIterator(); - while ((mapping = iterator.Next()) != NULL) { - if (mapping->area == area) - break; - } - - ASSERT(mapping != NULL); - - area->mappings.Remove(mapping); - page->mappings.Remove(mapping); - queue.Add(mapping); - } else - page->DecrementWiredCount(); - - if (!page->IsMapped()) { - atomic_add(&gMappedPagesCount, -1); - - if (updatePageQueue) { - if (page->Cache()->temporary) - vm_page_set_state(page, PAGE_STATE_INACTIVE); - else if (page->modified) - vm_page_set_state(page, PAGE_STATE_MODIFIED); - else - vm_page_set_state(page, PAGE_STATE_CACHED); - } - } - - DEBUG_PAGE_ACCESS_END(page); + page_num_t page = (oldPte & kPteAddrMask) >> fPageBits; + PageUnmapped(area, page, + is_pte_accessed(oldPte), is_pte_dirty(oldPte), + updatePageQueue, &queue); }); // TODO: As in UnmapPage() we can lose page dirty flags here. ATM it's not diff --git a/src/system/kernel/arch/m68k/paging/040/M68KVMTranslationMap040.cpp b/src/system/kernel/arch/m68k/paging/040/M68KVMTranslationMap040.cpp index 90b871649e..7d7239285a 100644 --- a/src/system/kernel/arch/m68k/paging/040/M68KVMTranslationMap040.cpp +++ b/src/system/kernel/arch/m68k/paging/040/M68KVMTranslationMap040.cpp @@ -573,52 +573,11 @@ M68KVMTranslationMap040::UnmapPages(VMArea* area, addr_t base, size_t size, } if (area->cache_type != CACHE_TYPE_DEVICE) { - // get the page - vm_page* page = vm_lookup_page( - (oldEntry & M68K_PTE_ADDRESS_MASK) / B_PAGE_SIZE); - ASSERT(page != NULL); - - DEBUG_PAGE_ACCESS_START(page); - - // transfer the accessed/dirty flags to the page - if ((oldEntry & M68K_PTE_ACCESSED) != 0) - page->accessed = true; - if ((oldEntry & M68K_PTE_DIRTY) != 0) - page->modified = true; - - // remove the mapping object/decrement the wired_count of the - // page - if (area->wiring == B_NO_LOCK) { - vm_page_mapping* mapping = NULL; - vm_page_mappings::Iterator iterator - = page->mappings.GetIterator(); - while ((mapping = iterator.Next()) != NULL) { - if (mapping->area == area) - break; - } - - ASSERT(mapping != NULL); - - area->mappings.Remove(mapping); - page->mappings.Remove(mapping); - queue.Add(mapping); - } else - page->DecrementWiredCount(); - - if (!page->IsMapped()) { - atomic_add(&gMappedPagesCount, -1); - - if (updatePageQueue) { - if (page->Cache()->temporary) - vm_page_set_state(page, PAGE_STATE_INACTIVE); - else if (page->modified) - vm_page_set_state(page, PAGE_STATE_MODIFIED); - else - vm_page_set_state(page, PAGE_STATE_CACHED); - } - } - - DEBUG_PAGE_ACCESS_END(page); + page_num_t page = (oldEntry & M68K_PTE_ADDRESS_MASK) / B_PAGE_SIZE; + PageUnmapped(area, page, + (oldEntry & M68K_PTE_ACCESSED) != 0, + (oldEntry & M68K_PTE_DIRTY) != 0, + updatePageQueue, &queue); } } diff --git a/src/system/kernel/arch/ppc/paging/460/PPCVMTranslationMap460.cpp b/src/system/kernel/arch/ppc/paging/460/PPCVMTranslationMap460.cpp index bf6549c2a8..d379e94642 100644 --- a/src/system/kernel/arch/ppc/paging/460/PPCVMTranslationMap460.cpp +++ b/src/system/kernel/arch/ppc/paging/460/PPCVMTranslationMap460.cpp @@ -798,52 +798,11 @@ PPCVMTranslationMap460::UnmapPages(VMArea* area, addr_t base, size_t size, } if (area->cache_type != CACHE_TYPE_DEVICE) { - // get the page - vm_page* page = vm_lookup_page( - (oldEntry & PPC_PTE_ADDRESS_MASK) / B_PAGE_SIZE); - ASSERT(page != NULL); - - DEBUG_PAGE_ACCESS_START(page); - - // transfer the accessed/dirty flags to the page - if ((oldEntry & PPC_PTE_ACCESSED) != 0) - page->accessed = true; - if ((oldEntry & PPC_PTE_DIRTY) != 0) - page->modified = true; - - // remove the mapping object/decrement the wired_count of the - // page - if (area->wiring == B_NO_LOCK) { - vm_page_mapping* mapping = NULL; - vm_page_mappings::Iterator iterator - = page->mappings.GetIterator(); - while ((mapping = iterator.Next()) != NULL) { - if (mapping->area == area) - break; - } - - ASSERT(mapping != NULL); - - area->mappings.Remove(mapping); - page->mappings.Remove(mapping); - queue.Add(mapping); - } else - page->DecrementWiredCount(); - - if (!page->IsMapped()) { - atomic_add(&gMappedPagesCount, -1); - - if (updatePageQueue) { - if (page->Cache()->temporary) - vm_page_set_state(page, PAGE_STATE_INACTIVE); - else if (page->modified) - vm_page_set_state(page, PAGE_STATE_MODIFIED); - else - vm_page_set_state(page, PAGE_STATE_CACHED); - } - } - - DEBUG_PAGE_ACCESS_END(page); + page_num_t page = (oldEntry & PPC_PTE_ADDRESS_MASK) / B_PAGE_SIZE; + PageUnmapped(area, page, + (oldEntry & PPC_PTE_ACCESSED) != 0, + (oldEntry & PPC_PTE_DIRTY) != 0, + updatePageQueue, &queue); } } diff --git a/src/system/kernel/arch/ppc/paging/classic/PPCVMTranslationMapClassic.cpp b/src/system/kernel/arch/ppc/paging/classic/PPCVMTranslationMapClassic.cpp index 6cb83f7790..e9918c3296 100644 --- a/src/system/kernel/arch/ppc/paging/classic/PPCVMTranslationMapClassic.cpp +++ b/src/system/kernel/arch/ppc/paging/classic/PPCVMTranslationMapClassic.cpp @@ -798,52 +798,11 @@ PPCVMTranslationMapClassic::UnmapPages(VMArea* area, addr_t base, size_t size, } if (area->cache_type != CACHE_TYPE_DEVICE) { - // get the page - vm_page* page = vm_lookup_page( - (oldEntry & PPC_PTE_ADDRESS_MASK) / B_PAGE_SIZE); - ASSERT(page != NULL); - - DEBUG_PAGE_ACCESS_START(page); - - // transfer the accessed/dirty flags to the page - if ((oldEntry & PPC_PTE_ACCESSED) != 0) - page->accessed = true; - if ((oldEntry & PPC_PTE_DIRTY) != 0) - page->modified = true; - - // remove the mapping object/decrement the wired_count of the - // page - if (area->wiring == B_NO_LOCK) { - vm_page_mapping* mapping = NULL; - vm_page_mappings::Iterator iterator - = page->mappings.GetIterator(); - while ((mapping = iterator.Next()) != NULL) { - if (mapping->area == area) - break; - } - - ASSERT(mapping != NULL); - - area->mappings.Remove(mapping); - page->mappings.Remove(mapping); - queue.Add(mapping); - } else - page->DecrementWiredCount(); - - if (!page->IsMapped()) { - atomic_add(&gMappedPagesCount, -1); - - if (updatePageQueue) { - if (page->Cache()->temporary) - vm_page_set_state(page, PAGE_STATE_INACTIVE); - else if (page->modified) - vm_page_set_state(page, PAGE_STATE_MODIFIED); - else - vm_page_set_state(page, PAGE_STATE_CACHED); - } - } - - DEBUG_PAGE_ACCESS_END(page); + page_num_t page = (oldEntry & PPC_PTE_ADDRESS_MASK) / B_PAGE_SIZE; + PageUnmapped(area, page, + (oldEntry & PPC_PTE_ACCESSED) != 0, + (oldEntry & PPC_PTE_DIRTY) != 0, + updatePageQueue, &queue); } } diff --git a/src/system/kernel/arch/riscv64/RISCV64VMTranslationMap.cpp b/src/system/kernel/arch/riscv64/RISCV64VMTranslationMap.cpp index 6effcad4d7..17d9dfb0da 100644 --- a/src/system/kernel/arch/riscv64/RISCV64VMTranslationMap.cpp +++ b/src/system/kernel/arch/riscv64/RISCV64VMTranslationMap.cpp @@ -393,49 +393,8 @@ RISCV64VMTranslationMap::UnmapPages(VMArea* area, addr_t base, size_t size, InvalidatePage(start); if (area->cache_type != CACHE_TYPE_DEVICE) { - // get the page - vm_page* page = vm_lookup_page(oldPte.ppn); - ASSERT(page != NULL); - - DEBUG_PAGE_ACCESS_START(page); - - // transfer the accessed/dirty flags to the page - page->accessed = oldPte.isAccessed; - page->modified = oldPte.isDirty; - - // remove the mapping object/decrement the wired_count of the - // page - if (area->wiring == B_NO_LOCK) { - vm_page_mapping* mapping = NULL; - vm_page_mappings::Iterator iterator - = page->mappings.GetIterator(); - while ((mapping = iterator.Next()) != NULL) { - if (mapping->area == area) - break; - } - - ASSERT(mapping != NULL); - - area->mappings.Remove(mapping); - page->mappings.Remove(mapping); - queue.Add(mapping); - } else - page->DecrementWiredCount(); - - if (!page->IsMapped()) { - atomic_add(&gMappedPagesCount, -1); - - if (updatePageQueue) { - if (page->Cache()->temporary) - vm_page_set_state(page, PAGE_STATE_INACTIVE); - else if (page->modified) - vm_page_set_state(page, PAGE_STATE_MODIFIED); - else - vm_page_set_state(page, PAGE_STATE_CACHED); - } - } - - DEBUG_PAGE_ACCESS_END(page); + PageUnmapped(area, oldPte.ppn, oldPte.isAccessed, oldPte.isDirty, + updatePageQueue, &queue); } // flush explicitly, since we directly use the lock diff --git a/src/system/kernel/arch/x86/paging/32bit/X86VMTranslationMap32Bit.cpp b/src/system/kernel/arch/x86/paging/32bit/X86VMTranslationMap32Bit.cpp index ec8f6a105a..b429954b41 100644 --- a/src/system/kernel/arch/x86/paging/32bit/X86VMTranslationMap32Bit.cpp +++ b/src/system/kernel/arch/x86/paging/32bit/X86VMTranslationMap32Bit.cpp @@ -435,52 +435,11 @@ X86VMTranslationMap32Bit::UnmapPages(VMArea* area, addr_t base, size_t size, } if (area->cache_type != CACHE_TYPE_DEVICE) { - // get the page - vm_page* page = vm_lookup_page( - (oldEntry & X86_PTE_ADDRESS_MASK) / B_PAGE_SIZE); - ASSERT(page != NULL); - - DEBUG_PAGE_ACCESS_START(page); - - // transfer the accessed/dirty flags to the page - if ((oldEntry & X86_PTE_ACCESSED) != 0) - page->accessed = true; - if ((oldEntry & X86_PTE_DIRTY) != 0) - page->modified = true; - - // remove the mapping object/decrement the wired_count of the - // page - if (area->wiring == B_NO_LOCK) { - vm_page_mapping* mapping = NULL; - vm_page_mappings::Iterator iterator - = page->mappings.GetIterator(); - while ((mapping = iterator.Next()) != NULL) { - if (mapping->area == area) - break; - } - - ASSERT(mapping != NULL); - - area->mappings.Remove(mapping); - page->mappings.Remove(mapping); - queue.Add(mapping); - } else - page->DecrementWiredCount(); - - if (!page->IsMapped()) { - atomic_add(&gMappedPagesCount, -1); - - if (updatePageQueue) { - if (page->Cache()->temporary) - vm_page_set_state(page, PAGE_STATE_INACTIVE); - else if (page->modified) - vm_page_set_state(page, PAGE_STATE_MODIFIED); - else - vm_page_set_state(page, PAGE_STATE_CACHED); - } - } - - DEBUG_PAGE_ACCESS_END(page); + page_num_t page = (oldEntry & X86_PTE_ADDRESS_MASK) / B_PAGE_SIZE; + PageUnmapped(area, page, + (oldEntry & X86_PTE_ACCESSED) != 0, + (oldEntry & X86_PTE_DIRTY) != 0, + updatePageQueue, &queue); } } diff --git a/src/system/kernel/arch/x86/paging/64bit/X86VMTranslationMap64Bit.cpp b/src/system/kernel/arch/x86/paging/64bit/X86VMTranslationMap64Bit.cpp index 83cef2786a..406e5fd4c3 100644 --- a/src/system/kernel/arch/x86/paging/64bit/X86VMTranslationMap64Bit.cpp +++ b/src/system/kernel/arch/x86/paging/64bit/X86VMTranslationMap64Bit.cpp @@ -437,52 +437,11 @@ X86VMTranslationMap64Bit::UnmapPages(VMArea* area, addr_t base, size_t size, } if (area->cache_type != CACHE_TYPE_DEVICE) { - // get the page - vm_page* page = vm_lookup_page( - (oldEntry & X86_64_PTE_ADDRESS_MASK) / B_PAGE_SIZE); - ASSERT(page != NULL); - - DEBUG_PAGE_ACCESS_START(page); - - // transfer the accessed/dirty flags to the page - if ((oldEntry & X86_64_PTE_ACCESSED) != 0) - page->accessed = true; - if ((oldEntry & X86_64_PTE_DIRTY) != 0) - page->modified = true; - - // remove the mapping object/decrement the wired_count of the - // page - if (area->wiring == B_NO_LOCK) { - vm_page_mapping* mapping = NULL; - vm_page_mappings::Iterator iterator - = page->mappings.GetIterator(); - while ((mapping = iterator.Next()) != NULL) { - if (mapping->area == area) - break; - } - - ASSERT(mapping != NULL); - - area->mappings.Remove(mapping); - page->mappings.Remove(mapping); - queue.Add(mapping); - } else - page->DecrementWiredCount(); - - if (!page->IsMapped()) { - atomic_add(&gMappedPagesCount, -1); - - if (updatePageQueue) { - if (page->Cache()->temporary) - vm_page_set_state(page, PAGE_STATE_INACTIVE); - else if (page->modified) - vm_page_set_state(page, PAGE_STATE_MODIFIED); - else - vm_page_set_state(page, PAGE_STATE_CACHED); - } - } - - DEBUG_PAGE_ACCESS_END(page); + page_num_t page = (oldEntry & X86_64_PTE_ADDRESS_MASK) / B_PAGE_SIZE; + PageUnmapped(area, page, + (oldEntry & X86_64_PTE_ACCESSED) != 0, + (oldEntry & X86_64_PTE_DIRTY) != 0, + updatePageQueue, &queue); } } diff --git a/src/system/kernel/arch/x86/paging/pae/X86VMTranslationMapPAE.cpp b/src/system/kernel/arch/x86/paging/pae/X86VMTranslationMapPAE.cpp index 33bd8193b9..42b28daacf 100644 --- a/src/system/kernel/arch/x86/paging/pae/X86VMTranslationMapPAE.cpp +++ b/src/system/kernel/arch/x86/paging/pae/X86VMTranslationMapPAE.cpp @@ -682,52 +682,11 @@ X86VMTranslationMapPAE::UnmapPages(VMArea* area, addr_t base, size_t size, } if (area->cache_type != CACHE_TYPE_DEVICE) { - // get the page - vm_page* page = vm_lookup_page( - (oldEntry & X86_PAE_PTE_ADDRESS_MASK) / B_PAGE_SIZE); - ASSERT(page != NULL); - - DEBUG_PAGE_ACCESS_START(page); - - // transfer the accessed/dirty flags to the page - if ((oldEntry & X86_PAE_PTE_ACCESSED) != 0) - page->accessed = true; - if ((oldEntry & X86_PAE_PTE_DIRTY) != 0) - page->modified = true; - - // remove the mapping object/decrement the wired_count of the - // page - if (area->wiring == B_NO_LOCK) { - vm_page_mapping* mapping = NULL; - vm_page_mappings::Iterator iterator - = page->mappings.GetIterator(); - while ((mapping = iterator.Next()) != NULL) { - if (mapping->area == area) - break; - } - - ASSERT(mapping != NULL); - - area->mappings.Remove(mapping); - page->mappings.Remove(mapping); - queue.Add(mapping); - } else - page->DecrementWiredCount(); - - if (!page->IsMapped()) { - atomic_add(&gMappedPagesCount, -1); - - if (updatePageQueue) { - if (page->Cache()->temporary) - vm_page_set_state(page, PAGE_STATE_INACTIVE); - else if (page->modified) - vm_page_set_state(page, PAGE_STATE_MODIFIED); - else - vm_page_set_state(page, PAGE_STATE_CACHED); - } - } - - DEBUG_PAGE_ACCESS_END(page); + page_num_t page = (oldEntry & X86_PAE_PTE_ADDRESS_MASK) / B_PAGE_SIZE; + PageUnmapped(area, page, + (oldEntry & X86_PAE_PTE_ACCESSED) != 0, + (oldEntry & X86_PAE_PTE_DIRTY) != 0, + updatePageQueue, &queue); } } diff --git a/src/system/kernel/vm/VMTranslationMap.cpp b/src/system/kernel/vm/VMTranslationMap.cpp index d91afecae6..1cd4663a88 100644 --- a/src/system/kernel/vm/VMTranslationMap.cpp +++ b/src/system/kernel/vm/VMTranslationMap.cpp @@ -158,13 +158,18 @@ VMTranslationMap::DebugGetReverseMappingInfo(phys_addr_t physicalAddress, /*! Called by UnmapPage() after performing the architecture specific part. Looks up the page, updates its flags, removes the page-area mapping, and requeues the page, if necessary. + + If \c mappingsQueue is unspecified, then it unlocks the map and frees the + page-area mapping. If \c mappingsQueue is specified, then it adds the removed + mapping to the queue and does NOT unlock the map. */ void VMTranslationMap::PageUnmapped(VMArea* area, page_num_t pageNumber, - bool accessed, bool modified, bool updatePageQueue) + bool accessed, bool modified, bool updatePageQueue, VMAreaMappings* mappingsQueue) { if (area->cache_type == CACHE_TYPE_DEVICE) { - recursive_lock_unlock(&fLock); + if (mappingsQueue == NULL) + recursive_lock_unlock(&fLock); return; } @@ -173,6 +178,12 @@ VMTranslationMap::PageUnmapped(VMArea* area, page_num_t pageNumber, ASSERT_PRINT(page != NULL, "page number: %#" B_PRIxPHYSADDR ", accessed: %d, modified: %d", pageNumber, accessed, modified); + if (mappingsQueue != NULL) { + DEBUG_PAGE_ACCESS_START(page); + } else { + DEBUG_PAGE_ACCESS_CHECK(page); + } + // transfer the accessed/dirty flags to the page page->accessed |= accessed; page->modified |= modified; @@ -195,7 +206,8 @@ VMTranslationMap::PageUnmapped(VMArea* area, page_num_t pageNumber, } else page->DecrementWiredCount(); - recursive_lock_unlock(&fLock); + if (mappingsQueue == NULL) + recursive_lock_unlock(&fLock); if (!page->IsMapped()) { atomic_add(&gMappedPagesCount, -1); @@ -210,11 +222,19 @@ VMTranslationMap::PageUnmapped(VMArea* area, page_num_t pageNumber, } } + if (mappingsQueue != NULL) { + DEBUG_PAGE_ACCESS_END(page); + } + if (mapping != NULL) { - bool isKernelSpace = area->address_space == VMAddressSpace::Kernel(); - vm_free_page_mapping(pageNumber, mapping, - CACHE_DONT_WAIT_FOR_MEMORY - | (isKernelSpace ? CACHE_DONT_LOCK_KERNEL_SPACE : 0)); + if (mappingsQueue == NULL) { + bool isKernelSpace = area->address_space == VMAddressSpace::Kernel(); + vm_free_page_mapping(pageNumber, mapping, + CACHE_DONT_WAIT_FOR_MEMORY + | (isKernelSpace ? CACHE_DONT_LOCK_KERNEL_SPACE : 0)); + } else { + mappingsQueue->Add(mapping); + } } }