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()); ThreadCPUPinner pinner(thread_get_current_thread());
uint64_t oldPte = 0;
ProcessRange(fPageTable, fInitialLevel, va, B_PAGE_SIZE, nullptr, ProcessRange(fPageTable, fInitialLevel, va, B_PAGE_SIZE, nullptr,
[=, &oldPte](uint64_t* ptePtr, uint64_t effectiveVa) { [=](uint64_t* ptePtr, uint64_t effectiveVa) {
if (clearAF && setRO) { if (clearAF && setRO) {
// We need to use an atomic compare-swap loop because we must // We need to use an atomic compare-swap loop because we must
// need to clear one bit while setting the other. // need to clear one bit while setting the other.
while (true) { while (true) {
oldPte = atomic_get64((int64_t*)ptePtr); uint64_t oldPte = atomic_get64((int64_t*)ptePtr);
uint64_t newPte = oldPte & ~kAttrAF; uint64_t newPte = oldPte & ~kAttrAF;
newPte = set_pte_clean(newPte); 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; break;
}
} }
} else if (clearAF) { } else if (clearAF) {
oldPte = atomic_and64((int64_t*)ptePtr, ~kAttrAF); atomic_and64((int64_t*)ptePtr, ~kAttrAF);
} else { } else {
while (true) { while (true) {
oldPte = atomic_get64((int64_t*)ptePtr); uint64_t oldPte = atomic_get64((int64_t*)ptePtr);
if (!is_pte_dirty(oldPte)) { if (!is_pte_dirty(oldPte))
// Avoid a TLB flush
oldPte = 0;
return; return;
}
uint64_t newPte = set_pte_clean(oldPte); 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; break;
}
} }
} }
}); });
FlushVAIfAccessed(oldPte, va);
return B_OK; return B_OK;
} }