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((va & pageMask) == 0);
|
||||||
ASSERT(ValidateVa(va));
|
ASSERT(ValidateVa(va));
|
||||||
|
|
||||||
MapRange(
|
bool clearAF = flags & kAttrAF;
|
||||||
fPageTable, fInitialLevel, va & vaMask, 0, B_PAGE_SIZE, VMAction::CLEAR_FLAGS, flags, NULL);
|
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;
|
return B_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user