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 <[email protected]> Reviewed-by: waddlesplash <[email protected]>
This commit is contained in:
committed by
waddlesplash
parent
556aca31e9
commit
1fa60a5cda
@@ -9,4 +9,6 @@
|
|||||||
#define PAGE_SHIFT 12
|
#define PAGE_SHIFT 12
|
||||||
|
|
||||||
|
|
||||||
|
bool flush_va_if_accessed(uint64_t pte, addr_t va, int asid);
|
||||||
|
|
||||||
#endif /* _KERNEL_ARCH_ARM64_ARCH_VM_H_ */
|
#endif /* _KERNEL_ARCH_ARM64_ARCH_VM_H_ */
|
||||||
|
|||||||
@@ -372,21 +372,20 @@ VMSAv8TranslationMap::GetOrMakeTable(phys_addr_t ptPa, int level, int index,
|
|||||||
|
|
||||||
|
|
||||||
bool
|
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))
|
if (!is_pte_accessed(pte))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
InterruptsSpinLocker locker(sAsidLock);
|
|
||||||
if ((pte & kAttrNG) == 0) {
|
if ((pte & kAttrNG) == 0) {
|
||||||
// Flush from all address spaces
|
// Flush from all address spaces
|
||||||
asm("dsb ishst"); // Ensure PTE write completed
|
asm("dsb ishst"); // Ensure PTE write completed
|
||||||
asm("tlbi vaae1is, %0" ::"r"(((va >> 12) & kTLBIMask)));
|
asm("tlbi vaae1is, %0" ::"r"(((va >> 12) & kTLBIMask)));
|
||||||
asm("dsb ish");
|
asm("dsb ish");
|
||||||
asm("isb");
|
asm("isb");
|
||||||
} else if (fASID != -1) {
|
} else if (asid != -1) {
|
||||||
asm("dsb ishst"); // Ensure PTE write completed
|
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("dsb ish"); // Wait for TLB flush to complete
|
||||||
asm("isb");
|
asm("isb");
|
||||||
return true;
|
return true;
|
||||||
@@ -395,6 +394,12 @@ VMSAv8TranslationMap::FlushVAIfAccessed(uint64_t pte, addr_t va)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
VMSAv8TranslationMap::FlushVAIfAccessed(uint64_t pte, addr_t va) {
|
||||||
|
InterruptsSpinLocker locker(sAsidLock);
|
||||||
|
return flush_va_if_accessed(pte, va, fASID);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
bool
|
bool
|
||||||
VMSAv8TranslationMap::AttemptPteBreakBeforeMake(uint64_t* ptePtr, uint64_t oldPte, addr_t va)
|
VMSAv8TranslationMap::AttemptPteBreakBeforeMake(uint64_t* ptePtr, uint64_t oldPte, addr_t va)
|
||||||
|
|||||||
@@ -165,11 +165,10 @@ fixup_entry(phys_addr_t ptPa, int level, addr_t va, bool wr)
|
|||||||
uint64_t newPte = oldPte & ~kAttrAPReadOnly;
|
uint64_t newPte = oldPte & ~kAttrAPReadOnly;
|
||||||
if ((uint64_t)atomic_test_and_set64((int64*)pte, newPte, oldPte) != oldPte)
|
if ((uint64_t)atomic_test_and_set64((int64*)pte, newPte, oldPte) != oldPte)
|
||||||
return true;
|
return true;
|
||||||
asm("dsb ishst");
|
|
||||||
uint64_t ttbr0 = READ_SPECIALREG(TTBR0_EL1);
|
uint64_t asid = READ_SPECIALREG(TTBR0_EL1) >> 48;
|
||||||
asm("tlbi vae1is, %0" ::"r"(((va >> 12) & kTLBIMask) | (ttbr0 & kASIDMask)));
|
flush_va_if_accessed(oldPte, va, asid);
|
||||||
asm("dsb ish");
|
|
||||||
asm("isb");
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
} else if (level < 3 && type == kPteTypeL012Table) {
|
} else if (level < 3 && type == kPteTypeL012Table) {
|
||||||
|
|||||||
Reference in New Issue
Block a user