diff --git a/libraries/libmesosphere/include/mesosphere/arch/arm64/kern_cpu.hpp b/libraries/libmesosphere/include/mesosphere/arch/arm64/kern_cpu.hpp index 41a8d7d0b..e3e519020 100644 --- a/libraries/libmesosphere/include/mesosphere/arch/arm64/kern_cpu.hpp +++ b/libraries/libmesosphere/include/mesosphere/arch/arm64/kern_cpu.hpp @@ -64,6 +64,10 @@ namespace ams::kern::arch::arm64::cpu { EnsureInstructionConsistency(); } + ALWAYS_INLINE void Yield() { + __asm__ __volatile__("yield" ::: "memory"); + } + ALWAYS_INLINE void SwitchProcess(u64 ttbr, u32 proc_id) { SetTtbr0El1(ttbr); ContextIdRegisterAccessor(0).SetProcId(proc_id).Store(); diff --git a/libraries/libmesosphere/source/arch/arm64/kern_cpu.cpp b/libraries/libmesosphere/source/arch/arm64/kern_cpu.cpp index 2a443d539..170ae14e0 100644 --- a/libraries/libmesosphere/source/arch/arm64/kern_cpu.cpp +++ b/libraries/libmesosphere/source/arch/arm64/kern_cpu.cpp @@ -60,7 +60,7 @@ namespace ams::kern::arch::arm64::cpu { void Wait() { while (!this->done) { - __asm__ __volatile__("yield"); + cpu::Yield(); } } @@ -173,7 +173,7 @@ namespace ams::kern::arch::arm64::cpu { Kernel::GetInterruptManager().SendInterProcessorInterrupt(KInterruptName_CacheOperation, target_mask); this->ProcessOperation(); while (this->target_cores != 0) { - __asm__ __volatile__("yield"); + cpu::Yield(); } } else { /* Request all cores. */ diff --git a/libraries/libmesosphere/source/kern_debug_log_impl.board.nintendo_nx.cpp b/libraries/libmesosphere/source/kern_debug_log_impl.board.nintendo_nx.cpp index c3be814f5..dc90e1c9e 100644 --- a/libraries/libmesosphere/source/kern_debug_log_impl.board.nintendo_nx.cpp +++ b/libraries/libmesosphere/source/kern_debug_log_impl.board.nintendo_nx.cpp @@ -86,7 +86,7 @@ namespace ams::kern { void KDebugLogImpl::PutChar(char c) { while (ReadUartRegister(UartRegister_LSR) & 0x100) { /* While the FIFO is full, yield. */ - __asm__ __volatile__("yield" ::: "memory"); + cpu::Yield(); } WriteUartRegister(UartRegister_THR, c); cpu::DataSynchronizationBarrier(); diff --git a/libraries/libmesosphere/source/svc/kern_svc_cache.cpp b/libraries/libmesosphere/source/svc/kern_svc_cache.cpp index 62487b361..8deb3f595 100644 --- a/libraries/libmesosphere/source/svc/kern_svc_cache.cpp +++ b/libraries/libmesosphere/source/svc/kern_svc_cache.cpp @@ -73,6 +73,32 @@ namespace ams::kern::svc { return ResultSuccess(); } + void FlushEntireDataCache() { + /* Flushing cache takes up to 1ms, so determine our minimum end tick. */ + const s64 timeout = KHardwareTimer::GetTick() + ams::svc::Tick(TimeSpan::FromMilliSeconds(1)); + + /* Flush the entire data cache. */ + cpu::FlushEntireDataCache(); + + /* Wait for 1ms to have passed. */ + while (KHardwareTimer::GetTick() < timeout) { + cpu::Yield(); + } + } + + Result FlushDataCache(uintptr_t address, size_t size) { + /* Succeed if there's nothing to do. */ + R_SUCCEED_IF(size == 0); + + /* Validate that the region is within range. */ + R_UNLESS(GetCurrentProcess().GetPageTable().Contains(address, size), svc::ResultInvalidCurrentMemory()); + + /* Flush the cache. */ + R_TRY(cpu::FlushDataCache(reinterpret_cast(address), size)); + + return ResultSuccess(); + } + Result InvalidateProcessDataCache(ams::svc::Handle process_handle, uint64_t address, uint64_t size) { /* Validate address/size. */ R_UNLESS(size > 0, svc::ResultInvalidSize()); @@ -148,11 +174,11 @@ namespace ams::kern::svc { /* ============================= 64 ABI ============================= */ void FlushEntireDataCache64() { - MESOSPHERE_PANIC("Stubbed SvcFlushEntireDataCache64 was called."); + return FlushEntireDataCache(); } Result FlushDataCache64(ams::svc::Address address, ams::svc::Size size) { - MESOSPHERE_PANIC("Stubbed SvcFlushDataCache64 was called."); + return FlushDataCache(address, size); } Result InvalidateProcessDataCache64(ams::svc::Handle process_handle, uint64_t address, uint64_t size) { @@ -170,11 +196,11 @@ namespace ams::kern::svc { /* ============================= 64From32 ABI ============================= */ void FlushEntireDataCache64From32() { - MESOSPHERE_PANIC("Stubbed SvcFlushEntireDataCache64From32 was called."); + return FlushEntireDataCache(); } Result FlushDataCache64From32(ams::svc::Address address, ams::svc::Size size) { - MESOSPHERE_PANIC("Stubbed SvcFlushDataCache64From32 was called."); + return FlushDataCache(address, size); } Result InvalidateProcessDataCache64From32(ams::svc::Handle process_handle, uint64_t address, uint64_t size) {