diff --git a/libraries/libmesosphere/source/arch/arm64/kern_cpu.cpp b/libraries/libmesosphere/source/arch/arm64/kern_cpu.cpp index e46c6285d..3da383f02 100644 --- a/libraries/libmesosphere/source/arch/arm64/kern_cpu.cpp +++ b/libraries/libmesosphere/source/arch/arm64/kern_cpu.cpp @@ -283,6 +283,16 @@ namespace ams::kern::arch::arm64::cpu { } } + void StoreDataCacheBySetWay(int level) { + PerformCacheOperationBySetWayImpl(level, StoreDataCacheLineBySetWayImpl); + cpu::DataSynchronizationBarrier(); + } + + void FlushDataCacheBySetWay(int level) { + PerformCacheOperationBySetWayImpl(level, FlushDataCacheLineBySetWayImpl); + cpu::DataSynchronizationBarrier(); + } + void KCacheHelperInterruptHandler::ProcessOperation() { switch (m_operation) { case Operation::Idle: @@ -291,12 +301,10 @@ namespace ams::kern::arch::arm64::cpu { InstructionMemoryBarrier(); break; case Operation::StoreDataCache: - PerformCacheOperationBySetWayLocal(StoreDataCacheLineBySetWayImpl); - DataSynchronizationBarrier(); + StoreDataCacheBySetWay(0); break; case Operation::FlushDataCache: - PerformCacheOperationBySetWayLocal(FlushDataCacheLineBySetWayImpl); - DataSynchronizationBarrier(); + FlushDataCacheBySetWay(0); break; } @@ -374,7 +382,20 @@ namespace ams::kern::arch::arm64::cpu { } void FlushEntireDataCache() { - return PerformCacheOperationBySetWayShared(FlushDataCacheLineBySetWayImpl); + KScopedCoreMigrationDisable dm; + + CacheLineIdRegisterAccessor clidr_el1; + const int levels_of_coherency = clidr_el1.GetLevelsOfCoherency(); + + /* Store cache from L2 up to the level of coherence (if there's an L3 cache or greater). */ + for (int level = 2; level < levels_of_coherency; ++level) { + StoreDataCacheBySetWay(level - 1); + } + + /* Flush cache from the level of coherence down to L2. */ + for (int level = levels_of_coherency; level > 1; --level) { + FlushDataCacheBySetWay(level - 1); + } } Result InvalidateDataCache(void *addr, size_t size) {