From f73ff202af35c3be68f5172263a60d634736dc2a Mon Sep 17 00:00:00 2001 From: Owen Anderson Date: Sat, 31 Aug 2024 07:16:12 +0000 Subject: [PATCH] arm64: Implement VMSAv8TranslationMap::Protect in terms of ProcessRange. Change-Id: I2825d265fec69c2ae033ee09ff0ead9b098a7ca9 Reviewed-on: https://review.haiku-os.org/c/haiku/+/8160 Tested-by: Commit checker robot Reviewed-by: Fredrik Holmqvist --- .../arch/arm64/VMSAv8TranslationMap.cpp | 21 ++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/src/system/kernel/arch/arm64/VMSAv8TranslationMap.cpp b/src/system/kernel/arch/arm64/VMSAv8TranslationMap.cpp index e864b3f918..e715606171 100644 --- a/src/system/kernel/arch/arm64/VMSAv8TranslationMap.cpp +++ b/src/system/kernel/arch/arm64/VMSAv8TranslationMap.cpp @@ -801,7 +801,7 @@ status_t VMSAv8TranslationMap::Protect(addr_t start, addr_t end, uint32 attributes, uint32 memoryType) { ThreadCPUPinner pinner(thread_get_current_thread()); - + uint64_t attr = GetMemoryAttr(attributes, memoryType, fIsKernel); size_t size = end - start + 1; uint64_t pageMask = (1UL << fPageBits) - 1; @@ -811,8 +811,23 @@ VMSAv8TranslationMap::Protect(addr_t start, addr_t end, uint32 attributes, uint3 ASSERT((size & pageMask) == 0); ASSERT(ValidateVa(start)); - uint64_t attr = GetMemoryAttr(attributes, memoryType, fIsKernel); - MapRange(fPageTable, fInitialLevel, start & vaMask, 0, size, VMAction::SET_ATTR, attr, NULL); + ProcessRange(fPageTable, 0, start & vaMask, size, nullptr, + [=](uint64_t* ptePtr, uint64_t effectiveVa) { + // We need to use an atomic compare-swap loop because we must + // need to clear somes bits while setting others. + while (true) { + uint64_t oldPte = atomic_get64((int64_t*)ptePtr); + uint64_t newPte = oldPte & ~kPteAttrMask; + newPte |= attr; + + if ((uint64_t)atomic_test_and_set64((int64_t*)ptePtr, newPte, oldPte) == oldPte) { + asm("dsb ishst"); // Ensure PTE write completed + if ((oldPte & kAttrAF) != 0) + FlushVAFromTLBByASID(effectiveVa); + break; + } + } + }); return B_OK; }