From 42b6c2dd958518b88363e72026898d6d6c1688a1 Mon Sep 17 00:00:00 2001 From: Michael Scire Date: Tue, 19 Oct 2021 01:19:31 -0700 Subject: [PATCH] kern: fix use of plr vs plr_heap, fix close/unlock order in ArbitrateLock --- .../include/mesosphere/kern_k_process.hpp | 2 ++ .../arch/arm64/kern_exception_handlers.cpp | 24 +++++++++---------- .../source/kern_k_condition_variable.cpp | 8 +++++-- .../libmesosphere/source/kern_k_thread.cpp | 2 +- 4 files changed, 21 insertions(+), 15 deletions(-) diff --git a/libraries/libmesosphere/include/mesosphere/kern_k_process.hpp b/libraries/libmesosphere/include/mesosphere/kern_k_process.hpp index 78d7bb18c..7453fd2e6 100644 --- a/libraries/libmesosphere/include/mesosphere/kern_k_process.hpp +++ b/libraries/libmesosphere/include/mesosphere/kern_k_process.hpp @@ -284,6 +284,8 @@ namespace ams::kern { constexpr KProcessAddress GetProcessLocalRegionAddress() const { return m_plr_address; } + constexpr void *GetProcessLocalRegionHeapAddress() const { return m_plr_heap_address; } + void AddCpuTime(s64 diff) { m_cpu_time += diff; } s64 GetCpuTime() { return m_cpu_time; } diff --git a/libraries/libmesosphere/source/arch/arm64/kern_exception_handlers.cpp b/libraries/libmesosphere/source/arch/arm64/kern_exception_handlers.cpp index 0cb325865..e920a707d 100644 --- a/libraries/libmesosphere/source/arch/arm64/kern_exception_handlers.cpp +++ b/libraries/libmesosphere/source/arch/arm64/kern_exception_handlers.cpp @@ -126,7 +126,7 @@ namespace ams::kern::arch::arm64 { const bool is_aarch64 = (context->psr & 0x10) == 0; if (is_aarch64) { /* 64-bit. */ - ams::svc::aarch64::ExceptionInfo *info = std::addressof(GetPointer(cur_process.GetProcessLocalRegionAddress())->exception_info); + ams::svc::aarch64::ExceptionInfo *info = std::addressof(static_cast(cur_process.GetProcessLocalRegionHeapAddress())->exception_info); for (size_t i = 0; i < util::size(info->r); ++i) { info->r[i] = context->x[i]; @@ -141,7 +141,7 @@ namespace ams::kern::arch::arm64 { info->far = far; } else { /* 32-bit. */ - ams::svc::aarch32::ExceptionInfo *info = std::addressof(GetPointer(cur_process.GetProcessLocalRegionAddress())->exception_info); + ams::svc::aarch32::ExceptionInfo *info = std::addressof(static_cast(cur_process.GetProcessLocalRegionHeapAddress())->exception_info); for (size_t i = 0; i < util::size(info->r); ++i) { info->r[i] = context->x[i]; @@ -201,17 +201,17 @@ namespace ams::kern::arch::arm64 { context->pc = GetInteger(cur_process.GetEntryPoint()); context->x[0] = type; if (is_aarch64) { - context->x[1] = GetInteger(cur_process.GetProcessLocalRegionAddress() + AMS_OFFSETOF(ams::svc::aarch64::ProcessLocalRegion, exception_info)); + context->x[1] = GetInteger(cur_process.GetProcessLocalRegionAddress() + AMS_OFFSETOF(ams::svc::aarch64::ProcessLocalRegion, exception_info)); - auto *plr = GetPointer(cur_process.GetProcessLocalRegionAddress()); - context->sp = util::AlignDown(reinterpret_cast(plr->data) + sizeof(plr->data), 0x10); - context->psr = 0; + const auto *plr = GetPointer(cur_process.GetProcessLocalRegionAddress()); + context->sp = util::AlignDown(reinterpret_cast(plr->data) + sizeof(plr->data), 0x10); + context->psr = 0; } else { - context->x[1] = GetInteger(cur_process.GetProcessLocalRegionAddress() + AMS_OFFSETOF(ams::svc::aarch32::ProcessLocalRegion, exception_info)); + context->x[1] = GetInteger(cur_process.GetProcessLocalRegionAddress() + AMS_OFFSETOF(ams::svc::aarch32::ProcessLocalRegion, exception_info)); - auto *plr = GetPointer(cur_process.GetProcessLocalRegionAddress()); - context->x[13] = util::AlignDown(reinterpret_cast(plr->data) + sizeof(plr->data), 0x10); - context->psr = 0x10; + const auto *plr = GetPointer(cur_process.GetProcessLocalRegionAddress()); + context->x[13] = util::AlignDown(reinterpret_cast(plr->data) + sizeof(plr->data), 0x08); + context->psr = 0x10; } /* Set exception SVC permissions. */ @@ -380,10 +380,10 @@ namespace ams::kern::arch::arm64 { const bool is_aarch64 = (e_ctx->psr & 0x10) == 0; if (is_aarch64) { /* We're 64-bit. */ - info.info64 = GetPointer(cur_process.GetProcessLocalRegionAddress())->exception_info; + info.info64 = static_cast(cur_process.GetProcessLocalRegionHeapAddress())->exception_info; } else { /* We're 32-bit. */ - info.info32 = GetPointer(cur_process.GetProcessLocalRegionAddress())->exception_info; + info.info32 = static_cast(cur_process.GetProcessLocalRegionHeapAddress())->exception_info; } /* Try to leave the user exception. */ diff --git a/libraries/libmesosphere/source/kern_k_condition_variable.cpp b/libraries/libmesosphere/source/kern_k_condition_variable.cpp index 2302660fd..764ca0bcd 100644 --- a/libraries/libmesosphere/source/kern_k_condition_variable.cpp +++ b/libraries/libmesosphere/source/kern_k_condition_variable.cpp @@ -113,6 +113,7 @@ namespace ams::kern { ThreadQueueImplForKConditionVariableWaitForAddress wait_queue; /* Wait for the address. */ + KThread *owner_thread; { KScopedSchedulerLock sl; @@ -127,8 +128,8 @@ namespace ams::kern { R_SUCCEED_IF(test_tag != (handle | ams::svc::HandleWaitMask)); /* Get the lock owner thread. */ - KScopedAutoObject owner_thread = GetCurrentProcess().GetHandleTable().GetObjectWithoutPseudoHandle(handle); - R_UNLESS(owner_thread.IsNotNull(), svc::ResultInvalidHandle()); + owner_thread = GetCurrentProcess().GetHandleTable().GetObjectWithoutPseudoHandle(handle).ReleasePointerUnsafe(); + R_UNLESS(owner_thread != nullptr, svc::ResultInvalidHandle()); /* Update the lock. */ cur_thread->SetAddressKey(addr, value); @@ -138,6 +139,9 @@ namespace ams::kern { cur_thread->BeginWait(std::addressof(wait_queue)); } + /* Close our reference to the owner thread, now that the wait is over. */ + owner_thread->Close(); + /* Get the wait result. */ return cur_thread->GetWaitResult(); } diff --git a/libraries/libmesosphere/source/kern_k_thread.cpp b/libraries/libmesosphere/source/kern_k_thread.cpp index e0e7e5d6a..3f19f8880 100644 --- a/libraries/libmesosphere/source/kern_k_thread.cpp +++ b/libraries/libmesosphere/source/kern_k_thread.cpp @@ -21,7 +21,7 @@ namespace ams::kern { constexpr inline s32 TerminatingThreadPriority = ams::svc::SystemThreadPriorityHighest - 1; - constexpr bool IsKernelAddressKey(KProcessAddress key) { + constexpr ALWAYS_INLINE bool IsKernelAddressKey(KProcessAddress key) { const uintptr_t key_uptr = GetInteger(key); return KernelVirtualAddressSpaceBase <= key_uptr && key_uptr <= KernelVirtualAddressSpaceLast && (key_uptr & 1) == 0; }