bool ARMVMTranslationMap32Bit::ClearAccessedAndModified(VMArea* area, addr_t address, bool unmapIfUnaccessed, bool& _modified) { ASSERT(address % B_PAGE_SIZE == 0); page_directory_entry* pd = fPagingStructures->pgdir_virt; TRACE("ARMVMTranslationMap32Bit::ClearAccessedAndModified(%#" B_PRIxADDR ")\n", address); RecursiveLocker locker(fLock); int index = VADDR_TO_PDENT(address); if ((pd[index] & ARM_PDE_TYPE_MASK) == 0) return false; ThreadCPUPinner pinner(thread_get_current_thread()); page_table_entry* pt = (page_table_entry*)fPageMapper->GetPageTableAt( pd[index] & ARM_PDE_ADDRESS_MASK); index = VADDR_TO_PTENT(address); // perform the deed page_table_entry oldEntry; if (unmapIfUnaccessed) { while (true) { oldEntry = pt[index]; if ((oldEntry & ARM_PTE_TYPE_MASK) == 0) { // page mapping not valid return false; } #if 0 //IRA if (oldEntry & ARM_PTE_ACCESSED) { // page was accessed -- just clear the flags oldEntry = ARMPagingMethod32Bit::ClearPageTableEntryFlags( &pt[index], ARM_PTE_ACCESSED | ARM_PTE_DIRTY); break; } #endif // page hasn't been accessed -- unmap it if (ARMPagingMethod32Bit::TestAndSetPageTableEntry(&pt[index], 0, oldEntry) == oldEntry) { break; } // something changed -- check again } } else { #if 0 //IRA oldEntry = ARMPagingMethod32Bit::ClearPageTableEntryFlags(&pt[index], ARM_PTE_ACCESSED | ARM_PTE_DIRTY); #else oldEntry = pt[index]; #endif } pinner.Unlock(); _modified = true /* (oldEntry & ARM_PTE_DIRTY) != 0 */; // XXX IRA if (true /*(oldEntry & ARM_PTE_ACCESSED) != 0*/) { // Note, that we only need to invalidate the address, if the // accessed flags was set, since only then the entry could have been // in any TLB. InvalidatePage(address); Flush(); return true; } if (!unmapIfUnaccessed) return false; // We have unmapped the address. Do the "high level" stuff. fMapCount--; locker.Detach(); // UnaccessedPageUnmapped() will unlock for us UnaccessedPageUnmapped(area, (oldEntry & ARM_PTE_ADDRESS_MASK) / B_PAGE_SIZE); return false; }
bool X86VMTranslationMap64Bit::ClearAccessedAndModified(VMArea* area, addr_t address, bool unmapIfUnaccessed, bool& _modified) { ASSERT(address % B_PAGE_SIZE == 0); TRACE("X86VMTranslationMap64Bit::ClearAccessedAndModified(%#" B_PRIxADDR ")\n", address); RecursiveLocker locker(fLock); ThreadCPUPinner pinner(thread_get_current_thread()); uint64* entry = X86PagingMethod64Bit::PageTableEntryForAddress( fPagingStructures->VirtualPML4(), address, fIsKernelMap, false, NULL, fPageMapper, fMapCount); if (entry == NULL) return false; uint64 oldEntry; if (unmapIfUnaccessed) { while (true) { oldEntry = *entry; if ((oldEntry & X86_64_PTE_PRESENT) == 0) { // page mapping not valid return false; } if (oldEntry & X86_64_PTE_ACCESSED) { // page was accessed -- just clear the flags oldEntry = X86PagingMethod64Bit::ClearTableEntryFlags(entry, X86_64_PTE_ACCESSED | X86_64_PTE_DIRTY); break; } // page hasn't been accessed -- unmap it if (X86PagingMethod64Bit::TestAndSetTableEntry(entry, 0, oldEntry) == oldEntry) { break; } // something changed -- check again } } else { oldEntry = X86PagingMethod64Bit::ClearTableEntryFlags(entry, X86_64_PTE_ACCESSED | X86_64_PTE_DIRTY); } pinner.Unlock(); _modified = (oldEntry & X86_64_PTE_DIRTY) != 0; if ((oldEntry & X86_64_PTE_ACCESSED) != 0) { // Note, that we only need to invalidate the address, if the // accessed flags was set, since only then the entry could have been // in any TLB. InvalidatePage(address); Flush(); return true; } if (!unmapIfUnaccessed) return false; // We have unmapped the address. Do the "high level" stuff. fMapCount--; locker.Detach(); // UnaccessedPageUnmapped() will unlock for us UnaccessedPageUnmapped(area, (oldEntry & X86_64_PTE_ADDRESS_MASK) / B_PAGE_SIZE); return false; }