From 3737151a2f98a8d0eb1a8070950d776626b97b3a Mon Sep 17 00:00:00 2001 From: Michael Scire Date: Wed, 11 Oct 2023 09:37:45 -0700 Subject: [PATCH] kern: Add special-case for InvalidateProcessDataCache on current process --- .../arch/arm64/kern_k_process_page_table.hpp | 4 ++++ .../mesosphere/kern_k_page_table_base.hpp | 1 + .../source/kern_k_page_table_base.cpp | 17 +++++++++++++++++ .../libmesosphere/source/svc/kern_svc_cache.cpp | 6 +++++- 4 files changed, 27 insertions(+), 1 deletion(-) diff --git a/libraries/libmesosphere/include/mesosphere/arch/arm64/kern_k_process_page_table.hpp b/libraries/libmesosphere/include/mesosphere/arch/arm64/kern_k_process_page_table.hpp index c0a266e78..297d30b52 100644 --- a/libraries/libmesosphere/include/mesosphere/arch/arm64/kern_k_process_page_table.hpp +++ b/libraries/libmesosphere/include/mesosphere/arch/arm64/kern_k_process_page_table.hpp @@ -150,6 +150,10 @@ namespace ams::kern::arch::arm64 { R_RETURN(m_page_table.InvalidateProcessDataCache(address, size)); } + Result InvalidateCurrentProcessDataCache(KProcessAddress address, size_t size) { + R_RETURN(m_page_table.InvalidateCurrentProcessDataCache(address, size)); + } + Result ReadDebugMemory(void *buffer, KProcessAddress address, size_t size) { R_RETURN(m_page_table.ReadDebugMemory(buffer, address, size)); } diff --git a/libraries/libmesosphere/include/mesosphere/kern_k_page_table_base.hpp b/libraries/libmesosphere/include/mesosphere/kern_k_page_table_base.hpp index f45f0eba0..fcc06d733 100644 --- a/libraries/libmesosphere/include/mesosphere/kern_k_page_table_base.hpp +++ b/libraries/libmesosphere/include/mesosphere/kern_k_page_table_base.hpp @@ -412,6 +412,7 @@ namespace ams::kern { Result MakeAndOpenPageGroup(KPageGroup *out, KProcessAddress address, size_t num_pages, u32 state_mask, u32 state, u32 perm_mask, u32 perm, u32 attr_mask, u32 attr); Result InvalidateProcessDataCache(KProcessAddress address, size_t size); + Result InvalidateCurrentProcessDataCache(KProcessAddress address, size_t size); Result ReadDebugMemory(void *buffer, KProcessAddress address, size_t size); Result ReadDebugIoMemory(void *buffer, KProcessAddress address, size_t size, KMemoryState state); diff --git a/libraries/libmesosphere/source/kern_k_page_table_base.cpp b/libraries/libmesosphere/source/kern_k_page_table_base.cpp index 3d6bc0c95..79034dcf2 100644 --- a/libraries/libmesosphere/source/kern_k_page_table_base.cpp +++ b/libraries/libmesosphere/source/kern_k_page_table_base.cpp @@ -2508,6 +2508,23 @@ namespace ams::kern { R_SUCCEED(); } + Result KPageTableBase::InvalidateCurrentProcessDataCache(KProcessAddress address, size_t size) { + /* Check pre-condition: this is being called on the current process. */ + MESOSPHERE_ASSERT(this == std::addressof(GetCurrentProcess().GetPageTable().GetBasePageTable())); + + /* Check that the region is in range. */ + R_UNLESS(this->Contains(address, size), svc::ResultInvalidCurrentMemory()); + + /* Lock the table. */ + KScopedLightLock lk(m_general_lock); + + /* Check the memory state. */ + R_TRY(this->CheckMemoryStateContiguous(address, size, KMemoryState_FlagReferenceCounted, KMemoryState_FlagReferenceCounted, KMemoryPermission_UserReadWrite, KMemoryPermission_UserReadWrite, KMemoryAttribute_Uncached, KMemoryAttribute_None)); + + /* Invalidate the data cache. */ + R_RETURN(cpu::InvalidateDataCache(GetVoidPointer(address), size)); + } + Result KPageTableBase::ReadDebugMemory(void *buffer, KProcessAddress address, size_t size) { /* Lightly validate the region is in range. */ R_UNLESS(this->Contains(address, size), svc::ResultInvalidCurrentMemory()); diff --git a/libraries/libmesosphere/source/svc/kern_svc_cache.cpp b/libraries/libmesosphere/source/svc/kern_svc_cache.cpp index 62997b50b..c6ffb5e4c 100644 --- a/libraries/libmesosphere/source/svc/kern_svc_cache.cpp +++ b/libraries/libmesosphere/source/svc/kern_svc_cache.cpp @@ -102,7 +102,11 @@ namespace ams::kern::svc { R_UNLESS(process.IsNotNull(), svc::ResultInvalidHandle()); /* Invalidate the cache. */ - R_TRY(process->GetPageTable().InvalidateProcessDataCache(address, size)); + if (process.GetPointerUnsafe() == GetCurrentProcessPointer()) { + R_TRY(process->GetPageTable().InvalidateCurrentProcessDataCache(address, size)); + } else { + R_TRY(process->GetPageTable().InvalidateProcessDataCache(address, size)); + } R_SUCCEED(); }