arm64: Implement ClearFlags in terms of ProcessRange.
Change-Id: I36ac90a3dc9d0a7dbb8c3b448fd79f2121bac9f2 Reviewed-on: https://review.haiku-os.org/c/haiku/+/8159 Reviewed-by: Fredrik Holmqvist <[email protected]>
This commit is contained in:
committed by
waddlesplash
parent
bb67bf75fb
commit
744bdd7337
@@ -829,9 +829,34 @@ VMSAv8TranslationMap::ClearFlags(addr_t va, uint32 flags)
|
||||
ASSERT((va & pageMask) == 0);
|
||||
ASSERT(ValidateVa(va));
|
||||
|
||||
MapRange(
|
||||
fPageTable, fInitialLevel, va & vaMask, 0, B_PAGE_SIZE, VMAction::CLEAR_FLAGS, flags, NULL);
|
||||
bool clearAF = flags & kAttrAF;
|
||||
bool setRO = flags & kAttrAPReadOnly;
|
||||
|
||||
if (!clearAF && !setRO)
|
||||
return B_OK;
|
||||
|
||||
ProcessRange(fPageTable, 0, va & vaMask, B_PAGE_SIZE, nullptr,
|
||||
[=](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) {
|
||||
uint64_t oldPte = atomic_get64((int64_t*)ptePtr);
|
||||
uint64_t newPte = oldPte & ~kAttrAF;
|
||||
newPte |= kAttrAPReadOnly;
|
||||
|
||||
if ((uint64_t)atomic_test_and_set64((int64_t*)ptePtr, newPte, oldPte) == oldPte)
|
||||
break;
|
||||
}
|
||||
} else if (clearAF) {
|
||||
atomic_and64((int64_t*)ptePtr, ~kAttrAPReadOnly);
|
||||
} else {
|
||||
atomic_or64((int64_t*)ptePtr, kAttrAPReadOnly);
|
||||
}
|
||||
asm("dsb ishst"); // Ensure PTE write completed
|
||||
});
|
||||
|
||||
FlushVAFromTLBByASID(va);
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user