arm64: Clean up VMSAv8TranslationMap::ClearFlags

* Save a TLB flush on the case where we only clear the accessed flag.

Change-Id: Icd9210d616a2eca13a9be9497f2a787ab0eaf266
Reviewed-on: https://review.haiku-os.org/c/haiku/+/8422
Reviewed-by: waddlesplash <[email protected]>
This commit is contained in:
Owen Anderson
2024-09-30 15:48:51 +00:00
committed by waddlesplash
parent 1c408b7298
commit f2e8f48cc3
@@ -964,39 +964,37 @@ VMSAv8TranslationMap::ClearFlags(addr_t va, uint32 flags)
ThreadCPUPinner pinner(thread_get_current_thread());
uint64_t oldPte = 0;
ProcessRange(fPageTable, fInitialLevel, va, B_PAGE_SIZE, nullptr,
[=, &oldPte](uint64_t* ptePtr, uint64_t effectiveVa) {
[=](uint64_t* ptePtr, uint64_t effectiveVa) {
if (clearAF && setRO) {
// We need to use an atomic compare-swap loop because we must
// need to clear one bit while setting the other.
while (true) {
oldPte = atomic_get64((int64_t*)ptePtr);
uint64_t oldPte = atomic_get64((int64_t*)ptePtr);
uint64_t newPte = oldPte & ~kAttrAF;
newPte = set_pte_clean(newPte);
if ((uint64_t)atomic_test_and_set64((int64_t*)ptePtr, newPte, oldPte) == oldPte)
if ((uint64_t)atomic_test_and_set64((int64_t*)ptePtr, newPte, oldPte) == oldPte) {
FlushVAIfAccessed(oldPte, va);
break;
}
}
} else if (clearAF) {
oldPte = atomic_and64((int64_t*)ptePtr, ~kAttrAF);
atomic_and64((int64_t*)ptePtr, ~kAttrAF);
} else {
while (true) {
oldPte = atomic_get64((int64_t*)ptePtr);
if (!is_pte_dirty(oldPte)) {
// Avoid a TLB flush
oldPte = 0;
uint64_t oldPte = atomic_get64((int64_t*)ptePtr);
if (!is_pte_dirty(oldPte))
return;
}
uint64_t newPte = set_pte_clean(oldPte);
if ((uint64_t)atomic_test_and_set64((int64_t*)ptePtr, newPte, oldPte) == oldPte)
if ((uint64_t)atomic_test_and_set64((int64_t*)ptePtr, newPte, oldPte) == oldPte) {
FlushVAIfAccessed(oldPte, va);
break;
}
}
}
});
FlushVAIfAccessed(oldPte, va);
return B_OK;
}