From 1fa60a5cda7dbcbcf1c9f3eaaa4b8a6ce8bc91e7 Mon Sep 17 00:00:00 2001 From: Owen Anderson Date: Wed, 25 Sep 2024 07:34:45 +0000 Subject: [PATCH] arm64: Fix TLB flushing in interrupts to handle kernel vs user space Change-Id: Id19236345cf05284c8c5f02360a4a2b3f22fd16d Reviewed-on: https://review.haiku-os.org/c/haiku/+/8365 Tested-by: Commit checker robot Reviewed-by: waddlesplash --- headers/private/kernel/arch/arm64/arch_vm.h | 2 ++ .../kernel/arch/arm64/VMSAv8TranslationMap.cpp | 13 +++++++++---- src/system/kernel/arch/arm64/arch_int.cpp | 9 ++++----- 3 files changed, 15 insertions(+), 9 deletions(-) diff --git a/headers/private/kernel/arch/arm64/arch_vm.h b/headers/private/kernel/arch/arm64/arch_vm.h index aa0ff1735a..d143716f1f 100644 --- a/headers/private/kernel/arch/arm64/arch_vm.h +++ b/headers/private/kernel/arch/arm64/arch_vm.h @@ -9,4 +9,6 @@ #define PAGE_SHIFT 12 +bool flush_va_if_accessed(uint64_t pte, addr_t va, int asid); + #endif /* _KERNEL_ARCH_ARM64_ARCH_VM_H_ */ diff --git a/src/system/kernel/arch/arm64/VMSAv8TranslationMap.cpp b/src/system/kernel/arch/arm64/VMSAv8TranslationMap.cpp index 68e7ff5159..61f89e7d09 100644 --- a/src/system/kernel/arch/arm64/VMSAv8TranslationMap.cpp +++ b/src/system/kernel/arch/arm64/VMSAv8TranslationMap.cpp @@ -372,21 +372,20 @@ VMSAv8TranslationMap::GetOrMakeTable(phys_addr_t ptPa, int level, int index, bool -VMSAv8TranslationMap::FlushVAIfAccessed(uint64_t pte, addr_t va) +flush_va_if_accessed(uint64_t pte, addr_t va, int asid) { if (!is_pte_accessed(pte)) return false; - InterruptsSpinLocker locker(sAsidLock); if ((pte & kAttrNG) == 0) { // Flush from all address spaces asm("dsb ishst"); // Ensure PTE write completed asm("tlbi vaae1is, %0" ::"r"(((va >> 12) & kTLBIMask))); asm("dsb ish"); asm("isb"); - } else if (fASID != -1) { + } else if (asid != -1) { asm("dsb ishst"); // Ensure PTE write completed - asm("tlbi vae1is, %0" ::"r"(((va >> 12) & kTLBIMask) | (uint64_t(fASID) << 48))); + asm("tlbi vae1is, %0" ::"r"(((va >> 12) & kTLBIMask) | (uint64_t(asid) << 48))); asm("dsb ish"); // Wait for TLB flush to complete asm("isb"); return true; @@ -395,6 +394,12 @@ VMSAv8TranslationMap::FlushVAIfAccessed(uint64_t pte, addr_t va) return false; } +bool +VMSAv8TranslationMap::FlushVAIfAccessed(uint64_t pte, addr_t va) { + InterruptsSpinLocker locker(sAsidLock); + return flush_va_if_accessed(pte, va, fASID); +} + bool VMSAv8TranslationMap::AttemptPteBreakBeforeMake(uint64_t* ptePtr, uint64_t oldPte, addr_t va) diff --git a/src/system/kernel/arch/arm64/arch_int.cpp b/src/system/kernel/arch/arm64/arch_int.cpp index 170790f81b..319ff9caaf 100644 --- a/src/system/kernel/arch/arm64/arch_int.cpp +++ b/src/system/kernel/arch/arm64/arch_int.cpp @@ -165,11 +165,10 @@ fixup_entry(phys_addr_t ptPa, int level, addr_t va, bool wr) uint64_t newPte = oldPte & ~kAttrAPReadOnly; if ((uint64_t)atomic_test_and_set64((int64*)pte, newPte, oldPte) != oldPte) return true; - asm("dsb ishst"); - uint64_t ttbr0 = READ_SPECIALREG(TTBR0_EL1); - asm("tlbi vae1is, %0" ::"r"(((va >> 12) & kTLBIMask) | (ttbr0 & kASIDMask))); - asm("dsb ish"); - asm("isb"); + + uint64_t asid = READ_SPECIALREG(TTBR0_EL1) >> 48; + flush_va_if_accessed(oldPte, va, asid); + return true; } } else if (level < 3 && type == kPteTypeL012Table) {