diff options
Diffstat (limited to 'src/core/hle/kernel')
-rw-r--r-- | src/core/hle/kernel/k_address_space_info.cpp | 4 | ||||
-rw-r--r-- | src/core/hle/kernel/k_address_space_info.h | 2 | ||||
-rw-r--r-- | src/core/hle/kernel/k_device_address_space.h | 4 | ||||
-rw-r--r-- | src/core/hle/kernel/k_process.h | 4 | ||||
-rw-r--r-- | src/core/hle/kernel/k_resource_limit.cpp | 3 | ||||
-rw-r--r-- | src/core/hle/kernel/k_thread.cpp | 24 | ||||
-rw-r--r-- | src/core/hle/kernel/k_thread.h | 2 | ||||
-rw-r--r-- | src/core/hle/kernel/svc/svc_synchronization.cpp | 45 | ||||
-rw-r--r-- | src/core/hle/kernel/svc/svc_thread.cpp | 3 |
9 files changed, 66 insertions, 25 deletions
diff --git a/src/core/hle/kernel/k_address_space_info.cpp b/src/core/hle/kernel/k_address_space_info.cpp index 97972ebae..c36eb5dc4 100644 --- a/src/core/hle/kernel/k_address_space_info.cpp +++ b/src/core/hle/kernel/k_address_space_info.cpp @@ -44,11 +44,11 @@ const KAddressSpaceInfo& GetAddressSpaceInfo(size_t width, KAddressSpaceInfo::Ty } // namespace -uintptr_t KAddressSpaceInfo::GetAddressSpaceStart(size_t width, KAddressSpaceInfo::Type type) { +std::size_t KAddressSpaceInfo::GetAddressSpaceStart(size_t width, KAddressSpaceInfo::Type type) { return GetAddressSpaceInfo(width, type).address; } -size_t KAddressSpaceInfo::GetAddressSpaceSize(size_t width, KAddressSpaceInfo::Type type) { +std::size_t KAddressSpaceInfo::GetAddressSpaceSize(size_t width, KAddressSpaceInfo::Type type) { return GetAddressSpaceInfo(width, type).size; } diff --git a/src/core/hle/kernel/k_address_space_info.h b/src/core/hle/kernel/k_address_space_info.h index 69e9d77f2..9a26f6b90 100644 --- a/src/core/hle/kernel/k_address_space_info.h +++ b/src/core/hle/kernel/k_address_space_info.h @@ -18,7 +18,7 @@ struct KAddressSpaceInfo final { Count, }; - static u64 GetAddressSpaceStart(std::size_t width, Type type); + static std::size_t GetAddressSpaceStart(std::size_t width, Type type); static std::size_t GetAddressSpaceSize(std::size_t width, Type type); const std::size_t bit_width{}; diff --git a/src/core/hle/kernel/k_device_address_space.h b/src/core/hle/kernel/k_device_address_space.h index 4709df995..b4a014c38 100644 --- a/src/core/hle/kernel/k_device_address_space.h +++ b/src/core/hle/kernel/k_device_address_space.h @@ -21,9 +21,9 @@ public: ~KDeviceAddressSpace(); Result Initialize(u64 address, u64 size); - void Finalize(); + void Finalize() override; - bool IsInitialized() const { + bool IsInitialized() const override { return m_is_initialized; } static void PostDestroy(uintptr_t arg) {} diff --git a/src/core/hle/kernel/k_process.h b/src/core/hle/kernel/k_process.h index 09bf2f1d0..549809000 100644 --- a/src/core/hle/kernel/k_process.h +++ b/src/core/hle/kernel/k_process.h @@ -310,10 +310,10 @@ public: /// Clears the signaled state of the process if and only if it's signaled. /// /// @pre The process must not be already terminated. If this is called on a - /// terminated process, then ERR_INVALID_STATE will be returned. + /// terminated process, then ResultInvalidState will be returned. /// /// @pre The process must be in a signaled state. If this is called on a - /// process instance that is not signaled, ERR_INVALID_STATE will be + /// process instance that is not signaled, ResultInvalidState will be /// returned. Result Reset(); diff --git a/src/core/hle/kernel/k_resource_limit.cpp b/src/core/hle/kernel/k_resource_limit.cpp index b9d22b414..626517619 100644 --- a/src/core/hle/kernel/k_resource_limit.cpp +++ b/src/core/hle/kernel/k_resource_limit.cpp @@ -2,6 +2,7 @@ // SPDX-License-Identifier: GPL-2.0-or-later #include "common/assert.h" +#include "common/overflow.h" #include "core/core.h" #include "core/core_timing.h" #include "core/hle/kernel/k_resource_limit.h" @@ -104,7 +105,7 @@ bool KResourceLimit::Reserve(LimitableResource which, s64 value, s64 timeout) { ASSERT(current_hints[index] <= current_values[index]); // If we would overflow, don't allow to succeed. - if (current_values[index] + value <= current_values[index]) { + if (Common::WrappingAdd(current_values[index], value) <= current_values[index]) { break; } diff --git a/src/core/hle/kernel/k_thread.cpp b/src/core/hle/kernel/k_thread.cpp index 96b90ffef..26e3700e4 100644 --- a/src/core/hle/kernel/k_thread.cpp +++ b/src/core/hle/kernel/k_thread.cpp @@ -49,6 +49,7 @@ static void ResetThreadContext32(Core::ARM_Interface::ThreadContext32& context, context.cpu_registers[0] = arg; context.cpu_registers[15] = entry_point; context.cpu_registers[13] = stack_top; + context.fpscr = 0; } static void ResetThreadContext64(Core::ARM_Interface::ThreadContext64& context, VAddr stack_top, @@ -58,8 +59,8 @@ static void ResetThreadContext64(Core::ARM_Interface::ThreadContext64& context, context.cpu_registers[18] = Kernel::KSystemControl::GenerateRandomU64() | 1; context.pc = entry_point; context.sp = stack_top; - // TODO(merry): Perform a hardware test to determine the below value. context.fpcr = 0; + context.fpsr = 0; } } // namespace @@ -815,6 +816,27 @@ void KThread::Continue() { KScheduler::OnThreadStateChanged(kernel, this, old_state); } +void KThread::CloneFpuStatus() { + // We shouldn't reach here when starting kernel threads. + ASSERT(this->GetOwnerProcess() != nullptr); + ASSERT(this->GetOwnerProcess() == GetCurrentProcessPointer(kernel)); + + if (this->GetOwnerProcess()->Is64BitProcess()) { + // Clone FPSR and FPCR. + ThreadContext64 cur_ctx{}; + kernel.System().CurrentArmInterface().SaveContext(cur_ctx); + + this->GetContext64().fpcr = cur_ctx.fpcr; + this->GetContext64().fpsr = cur_ctx.fpsr; + } else { + // Clone FPSCR. + ThreadContext32 cur_ctx{}; + kernel.System().CurrentArmInterface().SaveContext(cur_ctx); + + this->GetContext32().fpscr = cur_ctx.fpscr; + } +} + Result KThread::SetActivity(Svc::ThreadActivity activity) { // Lock ourselves. KScopedLightLock lk(activity_pause_lock); diff --git a/src/core/hle/kernel/k_thread.h b/src/core/hle/kernel/k_thread.h index bd125f5f1..9423f08ca 100644 --- a/src/core/hle/kernel/k_thread.h +++ b/src/core/hle/kernel/k_thread.h @@ -254,6 +254,8 @@ public: thread_context_32.tpidr = static_cast<u32>(value); } + void CloneFpuStatus(); + [[nodiscard]] ThreadContext32& GetContext32() { return thread_context_32; } diff --git a/src/core/hle/kernel/svc/svc_synchronization.cpp b/src/core/hle/kernel/svc/svc_synchronization.cpp index 1a8f7e191..9e7bf9530 100644 --- a/src/core/hle/kernel/svc/svc_synchronization.cpp +++ b/src/core/hle/kernel/svc/svc_synchronization.cpp @@ -48,19 +48,15 @@ Result ResetSignal(Core::System& system, Handle handle) { return ResultInvalidHandle; } -/// Wait for the given handles to synchronize, timeout after the specified nanoseconds -Result WaitSynchronization(Core::System& system, s32* index, VAddr handles_address, s32 num_handles, - s64 nano_seconds) { - LOG_TRACE(Kernel_SVC, "called handles_address=0x{:X}, num_handles={}, nano_seconds={}", - handles_address, num_handles, nano_seconds); - +static Result WaitSynchronization(Core::System& system, int32_t* out_index, const Handle* handles, + int32_t num_handles, int64_t timeout_ns) { // Ensure number of handles is valid. - R_UNLESS(0 <= num_handles && num_handles <= ArgumentHandleCountMax, ResultOutOfRange); + R_UNLESS(0 <= num_handles && num_handles <= Svc::ArgumentHandleCountMax, ResultOutOfRange); + // Get the synchronization context. auto& kernel = system.Kernel(); + auto& handle_table = GetCurrentProcess(kernel).GetHandleTable(); std::vector<KSynchronizationObject*> objs(num_handles); - const auto& handle_table = GetCurrentProcess(kernel).GetHandleTable(); - Handle* handles = system.Memory().GetPointer<Handle>(handles_address); // Copy user handles. if (num_handles > 0) { @@ -68,21 +64,38 @@ Result WaitSynchronization(Core::System& system, s32* index, VAddr handles_addre R_UNLESS(handle_table.GetMultipleObjects<KSynchronizationObject>(objs.data(), handles, num_handles), ResultInvalidHandle); - for (const auto& obj : objs) { - kernel.RegisterInUseObject(obj); - } } // Ensure handles are closed when we're done. SCOPE_EXIT({ - for (s32 i = 0; i < num_handles; ++i) { - kernel.UnregisterInUseObject(objs[i]); + for (auto i = 0; i < num_handles; ++i) { objs[i]->Close(); } }); - return KSynchronizationObject::Wait(kernel, index, objs.data(), static_cast<s32>(objs.size()), - nano_seconds); + // Wait on the objects. + Result res = KSynchronizationObject::Wait(kernel, out_index, objs.data(), + static_cast<s32>(objs.size()), timeout_ns); + + R_SUCCEED_IF(res == ResultSessionClosed); + R_RETURN(res); +} + +/// Wait for the given handles to synchronize, timeout after the specified nanoseconds +Result WaitSynchronization(Core::System& system, int32_t* out_index, VAddr user_handles, + int32_t num_handles, int64_t timeout_ns) { + LOG_TRACE(Kernel_SVC, "called user_handles={:#x}, num_handles={}, timeout_ns={}", user_handles, + num_handles, timeout_ns); + + // Ensure number of handles is valid. + R_UNLESS(0 <= num_handles && num_handles <= Svc::ArgumentHandleCountMax, ResultOutOfRange); + + std::vector<Handle> handles(num_handles); + if (num_handles > 0) { + system.Memory().ReadBlock(user_handles, handles.data(), num_handles * sizeof(Handle)); + } + + R_RETURN(WaitSynchronization(system, out_index, handles.data(), num_handles, timeout_ns)); } /// Resumes a thread waiting on WaitSynchronization diff --git a/src/core/hle/kernel/svc/svc_thread.cpp b/src/core/hle/kernel/svc/svc_thread.cpp index b39807841..9bc1ebe74 100644 --- a/src/core/hle/kernel/svc/svc_thread.cpp +++ b/src/core/hle/kernel/svc/svc_thread.cpp @@ -82,6 +82,9 @@ Result CreateThread(Core::System& system, Handle* out_handle, VAddr entry_point, // Commit the thread reservation. thread_reservation.Commit(); + // Clone the current fpu status to the new thread. + thread->CloneFpuStatus(); + // Register the new thread. KThread::Register(kernel, thread); |