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 <no-reply+buildbot@haiku-os.org>
Reviewed-by: waddlesplash <waddlesplash@gmail.com>
This commit is contained in:
Owen Anderson 2024-09-25 07:34:45 +00:00 committed by waddlesplash
parent 556aca31e9
commit 1fa60a5cda
3 changed files with 15 additions and 9 deletions

View File

@ -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_ */

View File

@ -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)

View File

@ -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) {