From de4746ff69d595645bb0511d857829ca6bcc25d5 Mon Sep 17 00:00:00 2001 From: bunnei Date: Fri, 2 Apr 2021 23:50:39 -0700 Subject: hle: kernel: svc: Migrate CreateThread. --- src/core/hle/kernel/svc.cpp | 35 +++++++++++++++++++++-------------- 1 file changed, 21 insertions(+), 14 deletions(-) (limited to 'src/core/hle/kernel/svc.cpp') diff --git a/src/core/hle/kernel/svc.cpp b/src/core/hle/kernel/svc.cpp index bebb86154..036603315 100644 --- a/src/core/hle/kernel/svc.cpp +++ b/src/core/hle/kernel/svc.cpp @@ -1521,6 +1521,7 @@ static ResultCode CreateThread(Core::System& system, Handle* out_handle, VAddr e return ResultInvalidPriority; } + // Reserve a new thread from the process resource limit (waiting up to 100ms). KScopedResourceReservation thread_reservation( kernel.CurrentProcess(), LimitableResource::Threads, 1, system.CoreTiming().GetGlobalTimeNs().count() + 100000000); @@ -1529,27 +1530,33 @@ static ResultCode CreateThread(Core::System& system, Handle* out_handle, VAddr e return ResultResourceLimitedExceeded; } - std::shared_ptr thread; - { - KScopedLightLock lk{process.GetStateLock()}; - CASCADE_RESULT(thread, - KThread::CreateUserThread(system, ThreadType::User, "", entry_point, - priority, arg, core_id, stack_bottom, &process)); + // Create the thread. + KThread* thread = KThread::CreateWithKernel(kernel); + if (!thread) { + LOG_ERROR(Kernel_SVC, "Unable to create new threads. Thread creation limit reached."); + return ResultOutOfResource; } + SCOPE_EXIT({ thread->Close(); }); - const auto new_thread_handle = process.GetHandleTable().Create(thread); - if (new_thread_handle.Failed()) { - LOG_ERROR(Kernel_SVC, "Failed to create handle with error=0x{:X}", - new_thread_handle.Code().raw); - return new_thread_handle.Code(); + // Initialize the thread. + { + KScopedLightLock lk{process.GetStateLock()}; + R_TRY(KThread::InitializeUserThread(system, thread, entry_point, arg, stack_bottom, + priority, core_id, &process)); } - *out_handle = *new_thread_handle; // Set the thread name for debugging purposes. - thread->SetName( - fmt::format("thread[entry_point={:X}, handle={:X}]", entry_point, *new_thread_handle)); + thread->SetName(fmt::format("thread[entry_point={:X}, handle={:X}]", entry_point, *out_handle)); + + // Commit the thread reservation. thread_reservation.Commit(); + // Register the new thread. + KThread::Register(thread); + + // Add the thread to the handle table. + R_TRY(process.GetHandleTable().Add(out_handle, thread)); + return RESULT_SUCCESS; } -- cgit v1.2.3 From 6fca1c82fd98b284cef2fb45fbaeae0cbc6241ac Mon Sep 17 00:00:00 2001 From: bunnei Date: Fri, 2 Apr 2021 23:53:31 -0700 Subject: hle: kernel: svc: Migrate GetThreadPriority, StartThread, and ExitThread. --- src/core/hle/kernel/svc.cpp | 33 ++++++++++++--------------------- 1 file changed, 12 insertions(+), 21 deletions(-) (limited to 'src/core/hle/kernel/svc.cpp') diff --git a/src/core/hle/kernel/svc.cpp b/src/core/hle/kernel/svc.cpp index 036603315..395962885 100644 --- a/src/core/hle/kernel/svc.cpp +++ b/src/core/hle/kernel/svc.cpp @@ -1150,12 +1150,9 @@ static ResultCode GetThreadPriority(Core::System& system, u32* out_priority, Han LOG_TRACE(Kernel_SVC, "called"); // Get the thread from its handle. - const auto& handle_table = system.Kernel().CurrentProcess()->GetHandleTable(); - const std::shared_ptr thread = handle_table.Get(handle); - if (!thread) { - LOG_ERROR(Kernel_SVC, "Invalid thread handle provided (handle={:08X})", handle); - return ResultInvalidHandle; - } + KScopedAutoObject thread = + system.Kernel().CurrentProcess()->GetHandleTable().GetObject(handle); + R_UNLESS(thread.IsNotNull(), ResultInvalidHandle); // Get the thread's priority. *out_priority = thread->GetPriority(); @@ -1552,7 +1549,7 @@ static ResultCode CreateThread(Core::System& system, Handle* out_handle, VAddr e thread_reservation.Commit(); // Register the new thread. - KThread::Register(thread); + KThread::Register(kernel, thread); // Add the thread to the handle table. R_TRY(process.GetHandleTable().Add(out_handle, thread)); @@ -1570,21 +1567,15 @@ static ResultCode StartThread(Core::System& system, Handle thread_handle) { LOG_DEBUG(Kernel_SVC, "called thread=0x{:08X}", thread_handle); // Get the thread from its handle. - const auto& handle_table = system.Kernel().CurrentProcess()->GetHandleTable(); - const std::shared_ptr thread = handle_table.Get(thread_handle); - if (!thread) { - LOG_ERROR(Kernel_SVC, "Invalid thread handle provided (handle={:08X})", thread_handle); - return ResultInvalidHandle; - } + KScopedAutoObject thread = + system.Kernel().CurrentProcess()->GetHandleTable().GetObject(thread_handle); + R_UNLESS(thread.IsNotNull(), ResultInvalidHandle); // Try to start the thread. - const auto run_result = thread->Run(); - if (run_result.IsError()) { - LOG_ERROR(Kernel_SVC, - "Unable to successfuly start thread (thread handle={:08X}, result={})", - thread_handle, run_result.raw); - return run_result; - } + R_TRY(thread->Run()); + + // If we succeeded, persist a reference to the thread. + thread->Open(); return RESULT_SUCCESS; } @@ -1598,7 +1589,7 @@ static void ExitThread(Core::System& system) { LOG_DEBUG(Kernel_SVC, "called, pc=0x{:08X}", system.CurrentArmInterface().GetPC()); auto* const current_thread = system.Kernel().CurrentScheduler()->GetCurrentThread(); - system.GlobalSchedulerContext().RemoveThread(SharedFrom(current_thread)); + system.GlobalSchedulerContext().RemoveThread(current_thread); current_thread->Exit(); } -- cgit v1.2.3 From da7e9553dea4b1eaefb71aca8642ccce7c7f50fb Mon Sep 17 00:00:00 2001 From: bunnei Date: Sat, 3 Apr 2021 19:11:46 -0700 Subject: hle: kernel: Migrate more of KThread to KAutoObject. --- src/core/hle/kernel/svc.cpp | 268 +++++++++++--------------------------------- 1 file changed, 68 insertions(+), 200 deletions(-) (limited to 'src/core/hle/kernel/svc.cpp') diff --git a/src/core/hle/kernel/svc.cpp b/src/core/hle/kernel/svc.cpp index 395962885..813450115 100644 --- a/src/core/hle/kernel/svc.cpp +++ b/src/core/hle/kernel/svc.cpp @@ -355,7 +355,7 @@ static ResultCode SendSyncRequest(Core::System& system, Handle handle) { KScopedSchedulerLock lock(kernel); thread->SetState(ThreadState::Waiting); thread->SetWaitReasonForDebugging(ThreadWaitReasonForDebugging::IPC); - session->SendSyncRequest(SharedFrom(thread), system.Memory(), system.CoreTiming()); + session->SendSyncRequest(thread, system.Memory(), system.CoreTiming()); } KSynchronizationObject* dummy{}; @@ -368,18 +368,13 @@ static ResultCode SendSyncRequest32(Core::System& system, Handle handle) { /// Get the ID for the specified thread. static ResultCode GetThreadId(Core::System& system, u64* out_thread_id, Handle thread_handle) { - LOG_TRACE(Kernel_SVC, "called thread=0x{:08X}", thread_handle); - // Get the thread from its handle. - const auto& handle_table = system.Kernel().CurrentProcess()->GetHandleTable(); - const std::shared_ptr thread = handle_table.Get(thread_handle); - if (!thread) { - LOG_ERROR(Kernel_SVC, "Invalid thread handle provided (handle={:08X})", thread_handle); - return ResultInvalidHandle; - } + KScopedAutoObject thread = + system.Kernel().CurrentProcess()->GetHandleTable().GetObject(thread_handle); + R_UNLESS(thread.IsNotNull(), ResultInvalidHandle); // Get the thread's id. - *out_thread_id = thread->GetThreadID(); + *out_thread_id = thread->GetId(); return RESULT_SUCCESS; } @@ -396,30 +391,7 @@ static ResultCode GetThreadId32(Core::System& system, u32* out_thread_id_low, /// Gets the ID of the specified process or a specified thread's owning process. static ResultCode GetProcessId(Core::System& system, u64* process_id, Handle handle) { - LOG_DEBUG(Kernel_SVC, "called handle=0x{:08X}", handle); - - const auto& handle_table = system.Kernel().CurrentProcess()->GetHandleTable(); - const std::shared_ptr process = handle_table.Get(handle); - if (process) { - *process_id = process->GetProcessID(); - return RESULT_SUCCESS; - } - - const std::shared_ptr thread = handle_table.Get(handle); - if (thread) { - const Process* const owner_process = thread->GetOwnerProcess(); - if (!owner_process) { - LOG_ERROR(Kernel_SVC, "Non-existent owning process encountered."); - return ResultInvalidHandle; - } - - *process_id = owner_process->GetProcessID(); - return RESULT_SUCCESS; - } - - // NOTE: This should also handle debug objects before returning. - - LOG_ERROR(Kernel_SVC, "Handle does not exist, handle=0x{:08X}", handle); + __debugbreak(); return ResultInvalidHandle; } @@ -460,14 +432,30 @@ static ResultCode WaitSynchronization(Core::System& system, s32* index, VAddr ha for (u64 i = 0; i < handle_count; ++i) { const Handle handle = memory.Read32(handles_address + i * sizeof(Handle)); - const auto object = handle_table.Get(handle); - if (object == nullptr) { - LOG_ERROR(Kernel_SVC, "Object is a nullptr"); - return ResultInvalidHandle; + bool succeeded{}; + { + auto object = handle_table.Get(handle); + if (object) { + objects[i] = object.get(); + succeeded = true; + } } - objects[i] = object.get(); + // TODO(bunnei): WORKAROUND WHILE WE HAVE TWO HANDLE TABLES + if (!succeeded) { + { + auto object = handle_table.GetObject(handle); + + if (object.IsNull()) { + LOG_ERROR(Kernel_SVC, "Object is a nullptr"); + return ResultInvalidHandle; + } + + objects[i] = object.GetPointerUnsafe(); + succeeded = true; + } + } } return KSynchronizationObject::Wait(kernel, index, objects.data(), static_cast(objects.size()), nano_seconds); @@ -481,19 +469,7 @@ static ResultCode WaitSynchronization32(Core::System& system, u32 timeout_low, u /// Resumes a thread waiting on WaitSynchronization static ResultCode CancelSynchronization(Core::System& system, Handle thread_handle) { - LOG_TRACE(Kernel_SVC, "called thread=0x{:X}", thread_handle); - - // Get the thread from its handle. - const auto& handle_table = system.Kernel().CurrentProcess()->GetHandleTable(); - std::shared_ptr thread = handle_table.Get(thread_handle); - - if (!thread) { - LOG_ERROR(Kernel_SVC, "Invalid thread handle provided (handle={:08X})", thread_handle); - return ResultInvalidHandle; - } - - // Cancel the thread's wait. - thread->WaitCancel(); + __debugbreak(); return RESULT_SUCCESS; } @@ -899,9 +875,10 @@ static ResultCode GetInfo(Core::System& system, u64* result, u64 info_id, u64 ha return ResultInvalidCombination; } - const auto thread = system.Kernel().CurrentProcess()->GetHandleTable().Get( - static_cast(handle)); - if (!thread) { + KScopedAutoObject thread = + system.Kernel().CurrentProcess()->GetHandleTable().GetObject( + static_cast(handle)); + if (thread.IsNull()) { LOG_ERROR(Kernel_SVC, "Thread handle does not exist, handle=0x{:08X}", static_cast(handle)); return ResultInvalidHandle; @@ -910,7 +887,7 @@ static ResultCode GetInfo(Core::System& system, u64* result, u64 info_id, u64 ha const auto& core_timing = system.CoreTiming(); const auto& scheduler = *system.Kernel().CurrentScheduler(); const auto* const current_thread = scheduler.GetCurrentThread(); - const bool same_thread = current_thread == thread.get(); + const bool same_thread = current_thread == thread.GetPointerUnsafe(); const u64 prev_ctx_ticks = scheduler.GetLastContextSwitchTicks(); u64 out_ticks = 0; @@ -1055,45 +1032,7 @@ static ResultCode UnmapPhysicalMemory32(Core::System& system, u32 addr, u32 size /// Sets the thread activity static ResultCode SetThreadActivity(Core::System& system, Handle thread_handle, ThreadActivity thread_activity) { - LOG_DEBUG(Kernel_SVC, "called, handle=0x{:08X}, activity=0x{:08X}", thread_handle, - thread_activity); - - // Validate the activity. - constexpr auto IsValidThreadActivity = [](ThreadActivity activity) { - return activity == ThreadActivity::Runnable || activity == ThreadActivity::Paused; - }; - if (!IsValidThreadActivity(thread_activity)) { - LOG_ERROR(Kernel_SVC, "Invalid thread activity value provided (activity={})", - thread_activity); - return ResultInvalidEnumValue; - } - - // Get the thread from its handle. - auto& kernel = system.Kernel(); - const auto& handle_table = kernel.CurrentProcess()->GetHandleTable(); - const std::shared_ptr thread = handle_table.Get(thread_handle); - if (!thread) { - LOG_ERROR(Kernel_SVC, "Invalid thread handle provided (handle={:08X})", thread_handle); - return ResultInvalidHandle; - } - - // Check that the activity is being set on a non-current thread for the current process. - if (thread->GetOwnerProcess() != kernel.CurrentProcess()) { - LOG_ERROR(Kernel_SVC, "Invalid owning process for the created thread."); - return ResultInvalidHandle; - } - if (thread.get() == GetCurrentThreadPointer(kernel)) { - LOG_ERROR(Kernel_SVC, "Thread is busy"); - return ResultBusy; - } - - // Set the activity. - const auto set_result = thread->SetActivity(thread_activity); - if (set_result.IsError()) { - LOG_ERROR(Kernel_SVC, "Failed to set thread activity."); - return set_result; - } - + __debugbreak(); return RESULT_SUCCESS; } @@ -1107,36 +1046,7 @@ static ResultCode GetThreadContext(Core::System& system, VAddr out_context, Hand LOG_DEBUG(Kernel_SVC, "called, out_context=0x{:08X}, thread_handle=0x{:X}", out_context, thread_handle); - // Get the thread from its handle. - const auto* current_process = system.Kernel().CurrentProcess(); - const std::shared_ptr thread = - current_process->GetHandleTable().Get(thread_handle); - if (!thread) { - LOG_ERROR(Kernel_SVC, "Invalid thread handle provided (handle={})", thread_handle); - return ResultInvalidHandle; - } - - // Require the handle be to a non-current thread in the current process. - if (thread->GetOwnerProcess() != current_process) { - LOG_ERROR(Kernel_SVC, "Thread owning process is not the current process."); - return ResultInvalidHandle; - } - if (thread.get() == system.Kernel().CurrentScheduler()->GetCurrentThread()) { - LOG_ERROR(Kernel_SVC, "Current thread is busy."); - return ResultBusy; - } - - // Get the thread context. - std::vector context; - const auto context_result = thread->GetThreadContext3(context); - if (context_result.IsError()) { - LOG_ERROR(Kernel_SVC, "Unable to successfully retrieve thread context (result: {})", - context_result.raw); - return context_result; - } - - // Copy the thread context to user space. - system.Memory().WriteBlock(out_context, context.data(), context.size()); + __debugbreak(); return RESULT_SUCCESS; } @@ -1164,30 +1074,26 @@ static ResultCode GetThreadPriority32(Core::System& system, u32* out_priority, H } /// Sets the priority for the specified thread -static ResultCode SetThreadPriority(Core::System& system, Handle handle, u32 priority) { - LOG_TRACE(Kernel_SVC, "called"); +static ResultCode SetThreadPriority(Core::System& system, Handle thread_handle, u32 priority) { + // Get the current process. + Process& process = *system.Kernel().CurrentProcess(); // Validate the priority. - if (HighestThreadPriority > priority || priority > LowestThreadPriority) { - LOG_ERROR(Kernel_SVC, "Invalid thread priority specified (priority={})", priority); - return ResultInvalidPriority; - } + R_UNLESS(HighestThreadPriority <= priority && priority <= LowestThreadPriority, + ResultInvalidPriority); + R_UNLESS(process.CheckThreadPriority(priority), ResultInvalidPriority); // Get the thread from its handle. - const auto& handle_table = system.Kernel().CurrentProcess()->GetHandleTable(); - const std::shared_ptr thread = handle_table.Get(handle); - if (!thread) { - LOG_ERROR(Kernel_SVC, "Invalid handle provided (handle={:08X})", handle); - return ResultInvalidHandle; - } + KScopedAutoObject thread = process.GetHandleTable().GetObject(thread_handle); + R_UNLESS(thread.IsNotNull(), ResultInvalidHandle); // Set the thread priority. thread->SetBasePriority(priority); return RESULT_SUCCESS; } -static ResultCode SetThreadPriority32(Core::System& system, Handle handle, u32 priority) { - return SetThreadPriority(system, handle, priority); +static ResultCode SetThreadPriority32(Core::System& system, Handle thread_handle, u32 priority) { + return SetThreadPriority(system, thread_handle, priority); } /// Get which CPU core is executing the current thread @@ -1480,7 +1386,7 @@ static void ExitProcess32(Core::System& system) { ExitProcess(system); } -static constexpr bool IsValidCoreId(int32_t core_id) { +static constexpr bool IsValidVirtualCoreId(int32_t core_id) { return (0 <= core_id && core_id < static_cast(Core::Hardware::NUM_CPU_CORES)); } @@ -1500,7 +1406,7 @@ static ResultCode CreateThread(Core::System& system, Handle* out_handle, VAddr e } // Validate arguments. - if (!IsValidCoreId(core_id)) { + if (!IsValidVirtualCoreId(core_id)) { LOG_ERROR(Kernel_SVC, "Invalid Core ID specified (id={})", core_id); return ResultInvalidCoreId; } @@ -1822,8 +1728,11 @@ static void GetSystemTick32(Core::System& system, u32* time_low, u32* time_high) static ResultCode CloseHandle(Core::System& system, Handle handle) { LOG_TRACE(Kernel_SVC, "Closing handle 0x{:08X}", handle); - auto& handle_table = system.Kernel().CurrentProcess()->GetHandleTable(); - return handle_table.Close(handle); + // Remove the handle. + R_UNLESS(system.Kernel().CurrentProcess()->GetHandleTable().Remove(handle), + ResultInvalidHandle); + + return RESULT_SUCCESS; } static ResultCode CloseHandle32(Core::System& system, Handle handle) { @@ -1925,23 +1834,7 @@ static ResultCode CreateTransferMemory32(Core::System& system, Handle* handle, u static ResultCode GetThreadCoreMask(Core::System& system, Handle thread_handle, s32* out_core_id, u64* out_affinity_mask) { - LOG_TRACE(Kernel_SVC, "called, handle=0x{:08X}", thread_handle); - - // Get the thread from its handle. - const auto& handle_table = system.Kernel().CurrentProcess()->GetHandleTable(); - const std::shared_ptr thread = handle_table.Get(thread_handle); - if (!thread) { - LOG_ERROR(Kernel_SVC, "Invalid thread handle specified (handle={:08X})", thread_handle); - return ResultInvalidHandle; - } - - // Get the core mask. - const auto result = thread->GetCoreMask(out_core_id, out_affinity_mask); - if (result.IsError()) { - LOG_ERROR(Kernel_SVC, "Unable to successfully retrieve core mask (result={})", result.raw); - return result; - } - + __debugbreak(); return RESULT_SUCCESS; } @@ -1956,58 +1849,33 @@ static ResultCode GetThreadCoreMask32(Core::System& system, Handle thread_handle static ResultCode SetThreadCoreMask(Core::System& system, Handle thread_handle, s32 core_id, u64 affinity_mask) { - LOG_DEBUG(Kernel_SVC, "called, handle=0x{:08X}, core_id=0x{:X}, affinity_mask=0x{:016X}", - thread_handle, core_id, affinity_mask); - - const auto& current_process = *system.Kernel().CurrentProcess(); - // Determine the core id/affinity mask. - if (core_id == Svc::IdealCoreUseProcessValue) { - core_id = current_process.GetIdealCoreId(); + if (core_id == IdealCoreUseProcessValue) { + core_id = system.Kernel().CurrentProcess()->GetIdealCoreId(); affinity_mask = (1ULL << core_id); } else { // Validate the affinity mask. - const u64 process_core_mask = current_process.GetCoreMask(); - if ((affinity_mask | process_core_mask) != process_core_mask) { - LOG_ERROR(Kernel_SVC, - "Affinity mask does match the process core mask (affinity mask={:016X}, core " - "mask={:016X})", - affinity_mask, process_core_mask); - return ResultInvalidCoreId; - } - if (affinity_mask == 0) { - LOG_ERROR(Kernel_SVC, "Affinity mask is zero."); - return ResultInvalidCombination; - } + const u64 process_core_mask = system.Kernel().CurrentProcess()->GetCoreMask(); + R_UNLESS((affinity_mask | process_core_mask) == process_core_mask, ResultInvalidCoreId); + R_UNLESS(affinity_mask != 0, ResultInvalidCombination); // Validate the core id. - if (IsValidCoreId(core_id)) { - if (((1ULL << core_id) & affinity_mask) == 0) { - LOG_ERROR(Kernel_SVC, "Invalid core ID (ID={})", core_id); - return ResultInvalidCombination; - } + if (IsValidVirtualCoreId(core_id)) { + R_UNLESS(((1ULL << core_id) & affinity_mask) != 0, ResultInvalidCombination); } else { - if (core_id != IdealCoreNoUpdate && core_id != IdealCoreDontCare) { - LOG_ERROR(Kernel_SVC, "Invalid core ID (ID={})", core_id); - return ResultInvalidCoreId; - } + R_UNLESS(core_id == IdealCoreNoUpdate || core_id == IdealCoreDontCare, + ResultInvalidCoreId); } } // Get the thread from its handle. - const auto& handle_table = system.Kernel().CurrentProcess()->GetHandleTable(); - const std::shared_ptr thread = handle_table.Get(thread_handle); - if (!thread) { - LOG_ERROR(Kernel_SVC, "Invalid thread handle (handle={:08X})", thread_handle); - return ResultInvalidHandle; - } + KScopedAutoObject thread = + system.Kernel().CurrentProcess()->GetHandleTable().GetObject(thread_handle); + R_UNLESS(thread.IsNotNull(), ResultInvalidHandle); // Set the core mask. - const auto set_result = thread->SetCoreMask(core_id, affinity_mask); - if (set_result.IsError()) { - LOG_ERROR(Kernel_SVC, "Unable to successfully set core mask (result={})", set_result.raw); - return set_result; - } + R_TRY(thread->SetCoreMask(core_id, affinity_mask)); + return RESULT_SUCCESS; } @@ -2105,7 +1973,7 @@ static ResultCode CreateEvent(Core::System& system, Handle* out_write, Handle* o *out_write = *write_create_result; // Add the writable event to the handle table. - auto handle_guard = SCOPE_GUARD({ handle_table.Close(*write_create_result); }); + auto handle_guard = SCOPE_GUARD({ handle_table.Remove(*write_create_result); }); // Add the readable event to the handle table. const auto read_create_result = handle_table.Create(event->GetReadableEvent()); -- cgit v1.2.3 From 5e5933256b022f6890fc3f14164ae9e9c3ee9ae3 Mon Sep 17 00:00:00 2001 From: bunnei Date: Sat, 3 Apr 2021 21:21:22 -0700 Subject: hle: kernel: Refactor IPC interfaces to not use std::shared_ptr. --- src/core/hle/kernel/svc.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/core/hle/kernel/svc.cpp') diff --git a/src/core/hle/kernel/svc.cpp b/src/core/hle/kernel/svc.cpp index 813450115..dca1bcc92 100644 --- a/src/core/hle/kernel/svc.cpp +++ b/src/core/hle/kernel/svc.cpp @@ -1976,7 +1976,7 @@ static ResultCode CreateEvent(Core::System& system, Handle* out_write, Handle* o auto handle_guard = SCOPE_GUARD({ handle_table.Remove(*write_create_result); }); // Add the readable event to the handle table. - const auto read_create_result = handle_table.Create(event->GetReadableEvent()); + const auto read_create_result = handle_table.Create(SharedFrom(event->GetReadableEvent())); if (read_create_result.Failed()) { return read_create_result.Code(); } -- cgit v1.2.3 From 7ccbdd4d8d3dea7294d2cac38779cceea9745d52 Mon Sep 17 00:00:00 2001 From: bunnei Date: Sat, 3 Apr 2021 22:22:36 -0700 Subject: hle: kernel: Migrate KProcess to KAutoObject. --- src/core/hle/kernel/svc.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'src/core/hle/kernel/svc.cpp') diff --git a/src/core/hle/kernel/svc.cpp b/src/core/hle/kernel/svc.cpp index dca1bcc92..7d676e5f7 100644 --- a/src/core/hle/kernel/svc.cpp +++ b/src/core/hle/kernel/svc.cpp @@ -342,7 +342,7 @@ static ResultCode ConnectToNamedPort32(Core::System& system, Handle* out_handle, static ResultCode SendSyncRequest(Core::System& system, Handle handle) { auto& kernel = system.Kernel(); const auto& handle_table = kernel.CurrentProcess()->GetHandleTable(); - std::shared_ptr session = handle_table.Get(handle); + auto session = handle_table.Get(handle); if (!session) { LOG_ERROR(Kernel_SVC, "called with invalid handle=0x{:08X}", handle); return ResultInvalidHandle; @@ -437,7 +437,7 @@ static ResultCode WaitSynchronization(Core::System& system, s32* index, VAddr ha { auto object = handle_table.Get(handle); if (object) { - objects[i] = object.get(); + objects[i] = object; succeeded = true; } } @@ -1190,7 +1190,7 @@ static ResultCode QueryProcessMemory(Core::System& system, VAddr memory_info_add std::lock_guard lock{HLE::g_hle_lock}; LOG_TRACE(Kernel_SVC, "called process=0x{:08X} address={:X}", process_handle, address); const auto& handle_table = system.Kernel().CurrentProcess()->GetHandleTable(); - std::shared_ptr process = handle_table.Get(process_handle); + auto process = handle_table.Get(process_handle); if (!process) { LOG_ERROR(Kernel_SVC, "Process handle does not exist, process_handle=0x{:08X}", process_handle); -- cgit v1.2.3 From 086db71e942dc3468bccb741cabf62fdd221e790 Mon Sep 17 00:00:00 2001 From: bunnei Date: Sat, 3 Apr 2021 23:22:07 -0700 Subject: hle: kernel: Migrate KSharedMemory to KAutoObject. --- src/core/hle/kernel/svc.cpp | 21 +++++++++------------ 1 file changed, 9 insertions(+), 12 deletions(-) (limited to 'src/core/hle/kernel/svc.cpp') diff --git a/src/core/hle/kernel/svc.cpp b/src/core/hle/kernel/svc.cpp index 7d676e5f7..17d63658a 100644 --- a/src/core/hle/kernel/svc.cpp +++ b/src/core/hle/kernel/svc.cpp @@ -328,7 +328,7 @@ static ResultCode ConnectToNamedPort(Core::System& system, Handle* out_handle, // Return the client session auto& handle_table = kernel.CurrentProcess()->GetHandleTable(); - CASCADE_RESULT(*out_handle, handle_table.Create(client_session)); + CASCADE_RESULT(*out_handle, handle_table.Create(client_session.get())); return RESULT_SUCCESS; } @@ -836,7 +836,7 @@ static ResultCode GetInfo(Core::System& system, u64* result, u64 info_id, u64 ha return RESULT_SUCCESS; } - const auto table_result = handle_table.Create(resource_limit); + const auto table_result = handle_table.Create(resource_limit.get()); if (table_result.Failed()) { return table_result.Code(); } @@ -1168,12 +1168,9 @@ static ResultCode MapSharedMemory(Core::System& system, Handle shared_memory_han return ResultInvalidMemoryRange; } - auto shared_memory{current_process->GetHandleTable().Get(shared_memory_handle)}; - if (!shared_memory) { - LOG_ERROR(Kernel_SVC, "Shared memory does not exist, shared_memory_handle=0x{:08X}", - shared_memory_handle); - return ResultInvalidHandle; - } + auto shared_memory{ + current_process->GetHandleTable().GetObject(shared_memory_handle)}; + R_UNLESS(shared_memory.IsNotNull(), ResultInvalidHandle); return shared_memory->Map(*current_process, addr, size, static_cast(permission_type)); @@ -1817,7 +1814,7 @@ static ResultCode CreateTransferMemory(Core::System& system, Handle* handle, VAd } auto& handle_table = kernel.CurrentProcess()->GetHandleTable(); - const auto result{handle_table.Create(std::move(transfer_mem_handle))}; + const auto result{handle_table.Create(transfer_mem_handle.get())}; if (result.Failed()) { return result.Code(); } @@ -1966,7 +1963,7 @@ static ResultCode CreateEvent(Core::System& system, Handle* out_write, Handle* o event->Initialize(); // Add the writable event to the handle table. - const auto write_create_result = handle_table.Create(event->GetWritableEvent()); + const auto write_create_result = handle_table.Create(event->GetWritableEvent().get()); if (write_create_result.Failed()) { return write_create_result.Code(); } @@ -1976,7 +1973,7 @@ static ResultCode CreateEvent(Core::System& system, Handle* out_write, Handle* o auto handle_guard = SCOPE_GUARD({ handle_table.Remove(*write_create_result); }); // Add the readable event to the handle table. - const auto read_create_result = handle_table.Create(SharedFrom(event->GetReadableEvent())); + const auto read_create_result = handle_table.Create(event->GetReadableEvent()); if (read_create_result.Failed()) { return read_create_result.Code(); } @@ -2027,7 +2024,7 @@ static ResultCode CreateResourceLimit(Core::System& system, Handle* out_handle) auto* const current_process = kernel.CurrentProcess(); ASSERT(current_process != nullptr); - const auto handle = current_process->GetHandleTable().Create(std::move(resource_limit)); + const auto handle = current_process->GetHandleTable().Create(resource_limit.get()); if (handle.Failed()) { return handle.Code(); } -- cgit v1.2.3 From addc0bf0379e075786048921bede6e089552a6db Mon Sep 17 00:00:00 2001 From: bunnei Date: Sun, 4 Apr 2021 00:56:09 -0700 Subject: hle: kernel: Migrate KEvent to KAutoObject. --- src/core/hle/kernel/svc.cpp | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) (limited to 'src/core/hle/kernel/svc.cpp') diff --git a/src/core/hle/kernel/svc.cpp b/src/core/hle/kernel/svc.cpp index 17d63658a..b143a51c7 100644 --- a/src/core/hle/kernel/svc.cpp +++ b/src/core/hle/kernel/svc.cpp @@ -1953,14 +1953,11 @@ static ResultCode CreateEvent(Core::System& system, Handle* out_write, Handle* o HandleTable& handle_table = kernel.CurrentProcess()->GetHandleTable(); // Create a new event. - const auto event = KEvent::Create(kernel, "CreateEvent"); - if (!event) { - LOG_ERROR(Kernel_SVC, "Unable to create new events. Event creation limit reached."); - return ResultOutOfResource; - } + KEvent* event = KEvent::CreateWithKernel(kernel); + R_UNLESS(event != nullptr, ResultOutOfResource); // Initialize the event. - event->Initialize(); + event->Initialize("CreateEvent"); // Add the writable event to the handle table. const auto write_create_result = handle_table.Create(event->GetWritableEvent().get()); -- cgit v1.2.3 From 89edbe8aa20d278d6f2c5ab735163f0d96ff88d2 Mon Sep 17 00:00:00 2001 From: bunnei Date: Fri, 9 Apr 2021 22:42:23 -0700 Subject: hle: kernel: Refactor several threads/events/sharedmemory to use slab heaps. --- src/core/hle/kernel/svc.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/core/hle/kernel/svc.cpp') diff --git a/src/core/hle/kernel/svc.cpp b/src/core/hle/kernel/svc.cpp index b143a51c7..8050359be 100644 --- a/src/core/hle/kernel/svc.cpp +++ b/src/core/hle/kernel/svc.cpp @@ -1431,7 +1431,7 @@ static ResultCode CreateThread(Core::System& system, Handle* out_handle, VAddr e } // Create the thread. - KThread* thread = KThread::CreateWithKernel(kernel); + KThread* thread = KThread::Create(kernel); if (!thread) { LOG_ERROR(Kernel_SVC, "Unable to create new threads. Thread creation limit reached."); return ResultOutOfResource; @@ -1953,7 +1953,7 @@ static ResultCode CreateEvent(Core::System& system, Handle* out_write, Handle* o HandleTable& handle_table = kernel.CurrentProcess()->GetHandleTable(); // Create a new event. - KEvent* event = KEvent::CreateWithKernel(kernel); + KEvent* event = KEvent::Create(kernel); R_UNLESS(event != nullptr, ResultOutOfResource); // Initialize the event. -- cgit v1.2.3 From 2e8d6fe9a0c07538397682e1cb25992bfd15676d Mon Sep 17 00:00:00 2001 From: bunnei Date: Sat, 10 Apr 2021 02:34:26 -0700 Subject: hle: kernel: Migrate KReadableEvent and KWritableEvent to KAutoObject. --- src/core/hle/kernel/svc.cpp | 70 +++++++++++++++++++++------------------------ 1 file changed, 32 insertions(+), 38 deletions(-) (limited to 'src/core/hle/kernel/svc.cpp') diff --git a/src/core/hle/kernel/svc.cpp b/src/core/hle/kernel/svc.cpp index 8050359be..c6334f91c 100644 --- a/src/core/hle/kernel/svc.cpp +++ b/src/core/hle/kernel/svc.cpp @@ -1745,16 +1745,16 @@ static ResultCode ResetSignal(Core::System& system, Handle handle) { // Try to reset as readable event. { - auto readable_event = handle_table.Get(handle); - if (readable_event) { + KScopedAutoObject readable_event = handle_table.GetObject(handle); + if (readable_event.IsNotNull()) { return readable_event->Reset(); } } // Try to reset as process. { - auto process = handle_table.Get(handle); - if (process) { + KScopedAutoObject process = handle_table.GetObject(handle); + if (process.IsNotNull()) { return process->Reset(); } } @@ -1885,27 +1885,12 @@ static ResultCode SetThreadCoreMask32(Core::System& system, Handle thread_handle static ResultCode SignalEvent(Core::System& system, Handle event_handle) { LOG_DEBUG(Kernel_SVC, "called, event_handle=0x{:08X}", event_handle); - auto& kernel = system.Kernel(); // Get the current handle table. - const HandleTable& handle_table = kernel.CurrentProcess()->GetHandleTable(); - - // Reserve a new event from the process resource limit. - KScopedResourceReservation event_reservation(kernel.CurrentProcess(), - LimitableResource::Events); - if (!event_reservation.Succeeded()) { - LOG_ERROR(Kernel, "Could not reserve a new event"); - return ResultResourceLimitedExceeded; - } + const HandleTable& handle_table = system.Kernel().CurrentProcess()->GetHandleTable(); // Get the writable event. - auto writable_event = handle_table.Get(event_handle); - if (!writable_event) { - LOG_ERROR(Kernel_SVC, "Invalid event handle provided (handle={:08X})", event_handle); - return ResultInvalidHandle; - } - - // Commit the successfuly reservation. - event_reservation.Commit(); + KScopedAutoObject writable_event = handle_table.GetObject(event_handle); + R_UNLESS(writable_event.IsNotNull(), ResultInvalidHandle); return writable_event->Signal(); } @@ -1922,16 +1907,16 @@ static ResultCode ClearEvent(Core::System& system, Handle event_handle) { // Try to clear the writable event. { - auto writable_event = handle_table.Get(event_handle); - if (writable_event) { + KScopedAutoObject writable_event = handle_table.GetObject(event_handle); + if (writable_event.IsNotNull()) { return writable_event->Clear(); } } // Try to clear the readable event. { - auto readable_event = handle_table.Get(event_handle); - if (readable_event) { + KScopedAutoObject readable_event = handle_table.GetObject(event_handle); + if (readable_event.IsNotNull()) { return readable_event->Clear(); } } @@ -1950,7 +1935,12 @@ static ResultCode CreateEvent(Core::System& system, Handle* out_write, Handle* o // Get the kernel reference and handle table. auto& kernel = system.Kernel(); - HandleTable& handle_table = kernel.CurrentProcess()->GetHandleTable(); + auto& handle_table = kernel.CurrentProcess()->GetHandleTable(); + + // Reserve a new event from the process resource limit + KScopedResourceReservation event_reservation(kernel.CurrentProcess(), + LimitableResource::Events); + R_UNLESS(event_reservation.Succeeded(), ResultResourceLimitedExceeded); // Create a new event. KEvent* event = KEvent::Create(kernel); @@ -1959,22 +1949,26 @@ static ResultCode CreateEvent(Core::System& system, Handle* out_write, Handle* o // Initialize the event. event->Initialize("CreateEvent"); + // Commit the thread reservation. + event_reservation.Commit(); + + // Ensure that we clean up the event (and its only references are handle table) on function end. + SCOPE_EXIT({ + event->GetWritableEvent().Close(); + event->GetReadableEvent().Close(); + }); + + // Register the event. + KEvent::Register(kernel, event); + // Add the writable event to the handle table. - const auto write_create_result = handle_table.Create(event->GetWritableEvent().get()); - if (write_create_result.Failed()) { - return write_create_result.Code(); - } - *out_write = *write_create_result; + R_TRY(handle_table.Add(out_write, std::addressof(event->GetWritableEvent()))); // Add the writable event to the handle table. - auto handle_guard = SCOPE_GUARD({ handle_table.Remove(*write_create_result); }); + auto handle_guard = SCOPE_GUARD({ handle_table.Remove(*out_write); }); // Add the readable event to the handle table. - const auto read_create_result = handle_table.Create(event->GetReadableEvent()); - if (read_create_result.Failed()) { - return read_create_result.Code(); - } - *out_read = *read_create_result; + R_TRY(handle_table.Add(out_read, std::addressof(event->GetReadableEvent()))); // We succeeded. handle_guard.Cancel(); -- cgit v1.2.3 From 269d233a9421e43c2383fe29603b3dfbdaa900e9 Mon Sep 17 00:00:00 2001 From: bunnei Date: Sun, 11 Apr 2021 11:41:48 -0700 Subject: hle: kernel: svc_results: Update naming.. --- src/core/hle/kernel/svc.cpp | 38 +++++++++++++++++++------------------- 1 file changed, 19 insertions(+), 19 deletions(-) (limited to 'src/core/hle/kernel/svc.cpp') diff --git a/src/core/hle/kernel/svc.cpp b/src/core/hle/kernel/svc.cpp index c6334f91c..5ead3a270 100644 --- a/src/core/hle/kernel/svc.cpp +++ b/src/core/hle/kernel/svc.cpp @@ -113,7 +113,7 @@ ResultCode MapUnmapMemorySanityChecks(const KPageTable& manager, VAddr dst_addr, LOG_ERROR(Kernel_SVC, "Destination is not within the stack region, addr=0x{:016X}, size=0x{:016X}", dst_addr, size); - return ResultInvalidMemoryRange; + return ResultInvalidMemoryRegion; } if (manager.IsInsideHeapRegion(dst_addr, size)) { @@ -121,7 +121,7 @@ ResultCode MapUnmapMemorySanityChecks(const KPageTable& manager, VAddr dst_addr, "Destination does not fit within the heap region, addr=0x{:016X}, " "size=0x{:016X}", dst_addr, size); - return ResultInvalidMemoryRange; + return ResultInvalidMemoryRegion; } if (manager.IsInsideAliasRegion(dst_addr, size)) { @@ -129,7 +129,7 @@ ResultCode MapUnmapMemorySanityChecks(const KPageTable& manager, VAddr dst_addr, "Destination does not fit within the map region, addr=0x{:016X}, " "size=0x{:016X}", dst_addr, size); - return ResultInvalidMemoryRange; + return ResultInvalidMemoryRegion; } return RESULT_SUCCESS; @@ -943,7 +943,7 @@ static ResultCode MapPhysicalMemory(Core::System& system, VAddr addr, u64 size) if (!(addr < addr + size)) { LOG_ERROR(Kernel_SVC, "Size causes 64-bit overflow of address"); - return ResultInvalidMemoryRange; + return ResultInvalidMemoryRegion; } Process* const current_process{system.Kernel().CurrentProcess()}; @@ -958,14 +958,14 @@ static ResultCode MapPhysicalMemory(Core::System& system, VAddr addr, u64 size) LOG_ERROR(Kernel_SVC, "Address is not within the address space, addr=0x{:016X}, size=0x{:016X}", addr, size); - return ResultInvalidMemoryRange; + return ResultInvalidMemoryRegion; } if (page_table.IsOutsideAliasRegion(addr, size)) { LOG_ERROR(Kernel_SVC, "Address is not within the alias region, addr=0x{:016X}, size=0x{:016X}", addr, size); - return ResultInvalidMemoryRange; + return ResultInvalidMemoryRegion; } return page_table.MapPhysicalMemory(addr, size); @@ -997,7 +997,7 @@ static ResultCode UnmapPhysicalMemory(Core::System& system, VAddr addr, u64 size if (!(addr < addr + size)) { LOG_ERROR(Kernel_SVC, "Size causes 64-bit overflow of address"); - return ResultInvalidMemoryRange; + return ResultInvalidMemoryRegion; } Process* const current_process{system.Kernel().CurrentProcess()}; @@ -1012,14 +1012,14 @@ static ResultCode UnmapPhysicalMemory(Core::System& system, VAddr addr, u64 size LOG_ERROR(Kernel_SVC, "Address is not within the address space, addr=0x{:016X}, size=0x{:016X}", addr, size); - return ResultInvalidMemoryRange; + return ResultInvalidMemoryRegion; } if (page_table.IsOutsideAliasRegion(addr, size)) { LOG_ERROR(Kernel_SVC, "Address is not within the alias region, addr=0x{:016X}, size=0x{:016X}", addr, size); - return ResultInvalidMemoryRange; + return ResultInvalidMemoryRegion; } return page_table.UnmapPhysicalMemory(addr, size); @@ -1138,7 +1138,7 @@ static ResultCode MapSharedMemory(Core::System& system, Handle shared_memory_han if ((permission_type | MemoryPermission::Write) != MemoryPermission::ReadWrite) { LOG_ERROR(Kernel_SVC, "Expected Read or ReadWrite permission but got permissions=0x{:08X}", permissions); - return ResultInvalidMemoryPermissions; + return ResultInvalidNewMemoryPermission; } auto* const current_process{system.Kernel().CurrentProcess()}; @@ -1149,7 +1149,7 @@ static ResultCode MapSharedMemory(Core::System& system, Handle shared_memory_han "Addr does not fit within the valid region, addr=0x{:016X}, " "size=0x{:016X}", addr, size); - return ResultInvalidMemoryRange; + return ResultInvalidMemoryRegion; } if (page_table.IsInsideHeapRegion(addr, size)) { @@ -1157,7 +1157,7 @@ static ResultCode MapSharedMemory(Core::System& system, Handle shared_memory_han "Addr does not fit within the heap region, addr=0x{:016X}, " "size=0x{:016X}", addr, size); - return ResultInvalidMemoryRange; + return ResultInvalidMemoryRegion; } if (page_table.IsInsideAliasRegion(addr, size)) { @@ -1165,7 +1165,7 @@ static ResultCode MapSharedMemory(Core::System& system, Handle shared_memory_han "Address does not fit within the map region, addr=0x{:016X}, " "size=0x{:016X}", addr, size); - return ResultInvalidMemoryRange; + return ResultInvalidMemoryRegion; } auto shared_memory{ @@ -1290,7 +1290,7 @@ static ResultCode MapProcessCodeMemory(Core::System& system, Handle process_hand "Destination address range is not within the ASLR region (dst_address=0x{:016X}, " "size=0x{:016X}).", dst_address, size); - return ResultInvalidMemoryRange; + return ResultInvalidMemoryRegion; } return page_table.MapProcessCodeMemory(dst_address, src_address, size); @@ -1358,7 +1358,7 @@ static ResultCode UnmapProcessCodeMemory(Core::System& system, Handle process_ha "Destination address range is not within the ASLR region (dst_address=0x{:016X}, " "size=0x{:016X}).", dst_address, size); - return ResultInvalidMemoryRange; + return ResultInvalidMemoryRegion; } return page_table.UnmapProcessCodeMemory(dst_address, src_address, size); @@ -1427,7 +1427,7 @@ static ResultCode CreateThread(Core::System& system, Handle* out_handle, VAddr e system.CoreTiming().GetGlobalTimeNs().count() + 100000000); if (!thread_reservation.Succeeded()) { LOG_ERROR(Kernel_SVC, "Could not reserve a new thread"); - return ResultResourceLimitedExceeded; + return ResultLimitReached; } // Create the thread. @@ -1795,7 +1795,7 @@ static ResultCode CreateTransferMemory(Core::System& system, Handle* handle, VAd if (perms > MemoryPermission::ReadWrite || perms == MemoryPermission::Write) { LOG_ERROR(Kernel_SVC, "Invalid memory permissions for transfer memory! (perms={:08X})", permissions); - return ResultInvalidMemoryPermissions; + return ResultInvalidNewMemoryPermission; } auto& kernel = system.Kernel(); @@ -1804,7 +1804,7 @@ static ResultCode CreateTransferMemory(Core::System& system, Handle* handle, VAd LimitableResource::TransferMemory); if (!trmem_reservation.Succeeded()) { LOG_ERROR(Kernel_SVC, "Could not reserve a new transfer memory"); - return ResultResourceLimitedExceeded; + return ResultLimitReached; } auto transfer_mem_handle = TransferMemory::Create(kernel, system.Memory(), addr, size, static_cast(perms)); @@ -1940,7 +1940,7 @@ static ResultCode CreateEvent(Core::System& system, Handle* out_write, Handle* o // Reserve a new event from the process resource limit KScopedResourceReservation event_reservation(kernel.CurrentProcess(), LimitableResource::Events); - R_UNLESS(event_reservation.Succeeded(), ResultResourceLimitedExceeded); + R_UNLESS(event_reservation.Succeeded(), ResultLimitReached); // Create a new event. KEvent* event = KEvent::Create(kernel); -- cgit v1.2.3 From 76a0814142b0f46374f1311515c1c870ac5f18e0 Mon Sep 17 00:00:00 2001 From: bunnei Date: Sun, 11 Apr 2021 12:49:18 -0700 Subject: hle: kernel: svc: Migrate GetProcessId, CancelSynchronization, SetThreadActivity. --- src/core/hle/kernel/svc.cpp | 80 +++++++++++++++++++++++++++++++++++++-------- 1 file changed, 67 insertions(+), 13 deletions(-) (limited to 'src/core/hle/kernel/svc.cpp') diff --git a/src/core/hle/kernel/svc.cpp b/src/core/hle/kernel/svc.cpp index 5ead3a270..fae4c7209 100644 --- a/src/core/hle/kernel/svc.cpp +++ b/src/core/hle/kernel/svc.cpp @@ -390,17 +390,43 @@ static ResultCode GetThreadId32(Core::System& system, u32* out_thread_id_low, } /// Gets the ID of the specified process or a specified thread's owning process. -static ResultCode GetProcessId(Core::System& system, u64* process_id, Handle handle) { - __debugbreak(); +static ResultCode GetProcessId(Core::System& system, u64* out_process_id, Handle handle) { + LOG_DEBUG(Kernel_SVC, "called handle=0x{:08X}", handle); + + // Get the object from the handle table. + KScopedAutoObject obj = + system.Kernel().CurrentProcess()->GetHandleTable().GetObject( + static_cast(handle)); + R_UNLESS(obj.IsNotNull(), ResultInvalidHandle); + + // Get the process from the object. + Process* process = nullptr; + if (Process* p = obj->DynamicCast(); p != nullptr) { + // The object is a process, so we can use it directly. + process = p; + } else if (KThread* t = obj->DynamicCast(); t != nullptr) { + // The object is a thread, so we want to use its parent. + process = reinterpret_cast(obj.GetPointerUnsafe())->GetOwnerProcess(); + } else { + // TODO(bunnei): This should also handle debug objects before returning. + UNIMPLEMENTED_MSG("Debug objects not implemented"); + } + + // Make sure the target process exists. + R_UNLESS(process != nullptr, ResultInvalidHandle); + + // Get the process id. + *out_process_id = process->GetId(); + return ResultInvalidHandle; } -static ResultCode GetProcessId32(Core::System& system, u32* process_id_low, u32* process_id_high, - Handle handle) { - u64 process_id{}; - const auto result = GetProcessId(system, &process_id, handle); - *process_id_low = static_cast(process_id); - *process_id_high = static_cast(process_id >> 32); +static ResultCode GetProcessId32(Core::System& system, u32* out_process_id_low, + u32* out_process_id_high, Handle handle) { + u64 out_process_id{}; + const auto result = GetProcessId(system, &out_process_id, handle); + *out_process_id_low = static_cast(out_process_id); + *out_process_id_high = static_cast(out_process_id >> 32); return result; } @@ -468,13 +494,21 @@ static ResultCode WaitSynchronization32(Core::System& system, u32 timeout_low, u } /// Resumes a thread waiting on WaitSynchronization -static ResultCode CancelSynchronization(Core::System& system, Handle thread_handle) { - __debugbreak(); +static ResultCode CancelSynchronization(Core::System& system, Handle handle) { + LOG_TRACE(Kernel_SVC, "called handle=0x{:X}", handle); + + // Get the thread from its handle. + KScopedAutoObject thread = + system.Kernel().CurrentProcess()->GetHandleTable().GetObject( + static_cast(handle)); + + // Cancel the thread's wait. + thread->WaitCancel(); return RESULT_SUCCESS; } -static ResultCode CancelSynchronization32(Core::System& system, Handle thread_handle) { - return CancelSynchronization(system, thread_handle); +static ResultCode CancelSynchronization32(Core::System& system, Handle handle) { + return CancelSynchronization(system, handle); } /// Attempts to locks a mutex @@ -1032,7 +1066,27 @@ static ResultCode UnmapPhysicalMemory32(Core::System& system, u32 addr, u32 size /// Sets the thread activity static ResultCode SetThreadActivity(Core::System& system, Handle thread_handle, ThreadActivity thread_activity) { - __debugbreak(); + LOG_DEBUG(Kernel_SVC, "called, handle=0x{:08X}, activity=0x{:08X}", thread_handle, + thread_activity); + + // Validate the activity. + constexpr auto IsValidThreadActivity = [](ThreadActivity activity) { + return activity == ThreadActivity::Runnable || activity == ThreadActivity::Paused; + }; + R_UNLESS(IsValidThreadActivity(thread_activity), ResultInvalidEnumValue); + + // Get the thread from its handle. + KScopedAutoObject thread = + system.Kernel().CurrentProcess()->GetHandleTable().GetObject(thread_handle); + R_UNLESS(thread.IsNotNull(), ResultInvalidHandle); + + // Check that the activity is being set on a non-current thread for the current process. + R_UNLESS(thread->GetOwnerProcess() == system.Kernel().CurrentProcess(), ResultInvalidHandle); + R_UNLESS(thread.GetPointerUnsafe() != GetCurrentThreadPointer(system.Kernel()), ResultBusy); + + // Set the activity. + R_TRY(thread->SetActivity(thread_activity)); + return RESULT_SUCCESS; } -- cgit v1.2.3 From 2cb6106523a87ae78d3a6b92c34b3b1d2817415e Mon Sep 17 00:00:00 2001 From: bunnei Date: Sun, 11 Apr 2021 12:49:51 -0700 Subject: hle: kernel: svc: Migrate GetThreadContext, GetThreadCoreMask. --- src/core/hle/kernel/svc.cpp | 61 +++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 59 insertions(+), 2 deletions(-) (limited to 'src/core/hle/kernel/svc.cpp') diff --git a/src/core/hle/kernel/svc.cpp b/src/core/hle/kernel/svc.cpp index fae4c7209..b83ee3e69 100644 --- a/src/core/hle/kernel/svc.cpp +++ b/src/core/hle/kernel/svc.cpp @@ -1100,7 +1100,55 @@ static ResultCode GetThreadContext(Core::System& system, VAddr out_context, Hand LOG_DEBUG(Kernel_SVC, "called, out_context=0x{:08X}, thread_handle=0x{:X}", out_context, thread_handle); - __debugbreak(); + auto& kernel = system.Kernel(); + + // Get the thread from its handle. + KScopedAutoObject thread = + kernel.CurrentProcess()->GetHandleTable().GetObject(thread_handle); + R_UNLESS(thread.IsNotNull(), ResultInvalidHandle); + + // Require the handle be to a non-current thread in the current process. + const auto* current_process = kernel.CurrentProcess(); + R_UNLESS(current_process == thread->GetOwnerProcess(), ResultInvalidId); + + // Verify that the thread isn't terminated. + R_UNLESS(thread->GetState() != ThreadState::Terminated, ResultTerminationRequested); + + /// Check that the thread is not the current one. + /// NOTE: Nintendo does not check this, and thus the following loop will deadlock. + R_UNLESS(thread.GetPointerUnsafe() != GetCurrentThreadPointer(kernel), ResultInvalidId); + + // Try to get the thread context until the thread isn't current on any core. + while (true) { + KScopedSchedulerLock sl{kernel}; + + // TODO(bunnei): Enforce that thread is suspended for debug here. + + // If the thread's raw state isn't runnable, check if it's current on some core. + if (thread->GetRawState() != ThreadState::Runnable) { + bool current = false; + for (auto i = 0; i < static_cast(Core::Hardware::NUM_CPU_CORES); ++i) { + if (thread.GetPointerUnsafe() == kernel.Scheduler(i).GetCurrentThread()) { + current = true; + } + break; + } + + // If the thread is current, retry until it isn't. + if (current) { + continue; + } + } + + // Get the thread context. + std::vector context; + R_TRY(thread->GetThreadContext3(context)); + + // Copy the thread context to user space. + system.Memory().WriteBlock(out_context, context.data(), context.size()); + + return RESULT_SUCCESS; + } return RESULT_SUCCESS; } @@ -1885,7 +1933,16 @@ static ResultCode CreateTransferMemory32(Core::System& system, Handle* handle, u static ResultCode GetThreadCoreMask(Core::System& system, Handle thread_handle, s32* out_core_id, u64* out_affinity_mask) { - __debugbreak(); + LOG_TRACE(Kernel_SVC, "called, handle=0x{:08X}", thread_handle); + + // Get the thread from its handle. + KScopedAutoObject thread = + system.Kernel().CurrentProcess()->GetHandleTable().GetObject(thread_handle); + R_UNLESS(thread.IsNotNull(), ResultInvalidHandle); + + // Get the core mask. + R_TRY(thread->GetCoreMask(out_core_id, out_affinity_mask)); + return RESULT_SUCCESS; } -- cgit v1.2.3 From 7444963bbb300cff269e410948de7fa577f5ff16 Mon Sep 17 00:00:00 2001 From: bunnei Date: Tue, 13 Apr 2021 17:48:37 -0700 Subject: hle: kernel: Migrate KSession, KClientSession, and KServerSession to KAutoObject. --- src/core/hle/kernel/svc.cpp | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) (limited to 'src/core/hle/kernel/svc.cpp') diff --git a/src/core/hle/kernel/svc.cpp b/src/core/hle/kernel/svc.cpp index b83ee3e69..28c45e8a3 100644 --- a/src/core/hle/kernel/svc.cpp +++ b/src/core/hle/kernel/svc.cpp @@ -22,9 +22,9 @@ #include "core/core_timing_util.h" #include "core/cpu_manager.h" #include "core/hle/kernel/client_port.h" -#include "core/hle/kernel/client_session.h" #include "core/hle/kernel/handle_table.h" #include "core/hle/kernel/k_address_arbiter.h" +#include "core/hle/kernel/k_client_session.h" #include "core/hle/kernel/k_condition_variable.h" #include "core/hle/kernel/k_event.h" #include "core/hle/kernel/k_memory_block.h" @@ -323,12 +323,12 @@ static ResultCode ConnectToNamedPort(Core::System& system, Handle* out_handle, auto client_port = it->second; - std::shared_ptr client_session; + KClientSession* client_session{}; CASCADE_RESULT(client_session, client_port->Connect()); // Return the client session auto& handle_table = kernel.CurrentProcess()->GetHandleTable(); - CASCADE_RESULT(*out_handle, handle_table.Create(client_session.get())); + CASCADE_RESULT(*out_handle, handle_table.Create(client_session)); return RESULT_SUCCESS; } @@ -340,15 +340,13 @@ static ResultCode ConnectToNamedPort32(Core::System& system, Handle* out_handle, /// Makes a blocking IPC call to an OS service. static ResultCode SendSyncRequest(Core::System& system, Handle handle) { + LOG_TRACE(Kernel_SVC, "called handle=0x{:08X}({})", handle, session->GetName()); + auto& kernel = system.Kernel(); - const auto& handle_table = kernel.CurrentProcess()->GetHandleTable(); - auto session = handle_table.Get(handle); - if (!session) { - LOG_ERROR(Kernel_SVC, "called with invalid handle=0x{:08X}", handle); - return ResultInvalidHandle; - } - LOG_TRACE(Kernel_SVC, "called handle=0x{:08X}({})", handle, session->GetName()); + KScopedAutoObject session = + kernel.CurrentProcess()->GetHandleTable().GetObject(handle); + R_UNLESS(session.IsNotNull(), ResultInvalidHandle); auto thread = kernel.CurrentScheduler()->GetCurrentThread(); { -- cgit v1.2.3 From c7d8b7421cd6bdb64410bbb0094ce540f0280c27 Mon Sep 17 00:00:00 2001 From: bunnei Date: Sat, 17 Apr 2021 00:52:53 -0700 Subject: hle: kernel: Migrate KTransferMemory to KAutoObject. --- src/core/hle/kernel/svc.cpp | 93 +++++++++++++++++++++++---------------------- 1 file changed, 48 insertions(+), 45 deletions(-) (limited to 'src/core/hle/kernel/svc.cpp') diff --git a/src/core/hle/kernel/svc.cpp b/src/core/hle/kernel/svc.cpp index 28c45e8a3..0b7eb0740 100644 --- a/src/core/hle/kernel/svc.cpp +++ b/src/core/hle/kernel/svc.cpp @@ -38,6 +38,7 @@ #include "core/hle/kernel/k_shared_memory.h" #include "core/hle/kernel/k_synchronization_object.h" #include "core/hle/kernel/k_thread.h" +#include "core/hle/kernel/k_transfer_memory.h" #include "core/hle/kernel/k_writable_event.h" #include "core/hle/kernel/kernel.h" #include "core/hle/kernel/physical_core.h" @@ -47,7 +48,6 @@ #include "core/hle/kernel/svc_types.h" #include "core/hle/kernel/svc_wrap.h" #include "core/hle/kernel/time_manager.h" -#include "core/hle/kernel/transfer_memory.h" #include "core/hle/lock.h" #include "core/hle/result.h" #include "core/hle/service/service.h" @@ -1868,65 +1868,68 @@ static ResultCode ResetSignal32(Core::System& system, Handle handle) { return ResetSignal(system, handle); } -/// Creates a TransferMemory object -static ResultCode CreateTransferMemory(Core::System& system, Handle* handle, VAddr addr, u64 size, - u32 permissions) { - std::lock_guard lock{HLE::g_hle_lock}; - LOG_DEBUG(Kernel_SVC, "called addr=0x{:X}, size=0x{:X}, perms=0x{:08X}", addr, size, - permissions); - - if (!Common::Is4KBAligned(addr)) { - LOG_ERROR(Kernel_SVC, "Address ({:016X}) is not page aligned!", addr); - return ResultInvalidAddress; +static constexpr bool IsValidTransferMemoryPermission(MemoryPermission perm) { + switch (perm) { + case MemoryPermission::None: + case MemoryPermission::Read: + case MemoryPermission::ReadWrite: + return true; + default: + return false; } +} - if (!Common::Is4KBAligned(size) || size == 0) { - LOG_ERROR(Kernel_SVC, "Size ({:016X}) is not page aligned or equal to zero!", size); - return ResultInvalidAddress; - } +/// Creates a TransferMemory object +static ResultCode CreateTransferMemory(Core::System& system, Handle* out, VAddr address, u64 size, + MemoryPermission map_perm) { + auto& kernel = system.Kernel(); - if (!IsValidAddressRange(addr, size)) { - LOG_ERROR(Kernel_SVC, "Address and size cause overflow! (address={:016X}, size={:016X})", - addr, size); - return ResultInvalidCurrentMemory; - } + // Validate the size. + R_UNLESS(Common::IsAligned(address, PageSize), ResultInvalidAddress); + R_UNLESS(Common::IsAligned(size, PageSize), ResultInvalidSize); + R_UNLESS(size > 0, ResultInvalidSize); + R_UNLESS((address < address + size), ResultInvalidCurrentMemory); - const auto perms{static_cast(permissions)}; - if (perms > MemoryPermission::ReadWrite || perms == MemoryPermission::Write) { - LOG_ERROR(Kernel_SVC, "Invalid memory permissions for transfer memory! (perms={:08X})", - permissions); - return ResultInvalidNewMemoryPermission; - } + // Validate the permissions. + R_UNLESS(IsValidTransferMemoryPermission(map_perm), ResultInvalidNewMemoryPermission); + + // Get the current process and handle table. + auto& process = *kernel.CurrentProcess(); + auto& handle_table = process.GetHandleTable(); - auto& kernel = system.Kernel(); // Reserve a new transfer memory from the process resource limit. KScopedResourceReservation trmem_reservation(kernel.CurrentProcess(), LimitableResource::TransferMemory); - if (!trmem_reservation.Succeeded()) { - LOG_ERROR(Kernel_SVC, "Could not reserve a new transfer memory"); - return ResultLimitReached; - } - auto transfer_mem_handle = TransferMemory::Create(kernel, system.Memory(), addr, size, - static_cast(perms)); + R_UNLESS(trmem_reservation.Succeeded(), ResultLimitReached); - if (const auto reserve_result{transfer_mem_handle->Reserve()}; reserve_result.IsError()) { - return reserve_result; - } + // Create the transfer memory. + KTransferMemory* trmem = KTransferMemory::Create(kernel); + R_UNLESS(trmem != nullptr, ResultOutOfResource); - auto& handle_table = kernel.CurrentProcess()->GetHandleTable(); - const auto result{handle_table.Create(transfer_mem_handle.get())}; - if (result.Failed()) { - return result.Code(); - } + // Ensure the only reference is in the handle table when we're done. + SCOPE_EXIT({ trmem->Close(); }); + + // Ensure that the region is in range. + R_UNLESS(process.PageTable().Contains(address, size), ResultInvalidCurrentMemory); + + // Initialize the transfer memory. + R_TRY(trmem->Initialize(address, size, map_perm)); + + // Commit the reservation. trmem_reservation.Commit(); - *handle = *result; + // Register the transfer memory. + KTransferMemory::Register(kernel, trmem); + + // Add the transfer memory to the handle table. + R_TRY(handle_table.Add(out, trmem)); + return RESULT_SUCCESS; } -static ResultCode CreateTransferMemory32(Core::System& system, Handle* handle, u32 addr, u32 size, - u32 permissions) { - return CreateTransferMemory(system, handle, addr, size, permissions); +static ResultCode CreateTransferMemory32(Core::System& system, Handle* out, u32 address, u32 size, + MemoryPermission map_perm) { + return CreateTransferMemory(system, out, address, size, map_perm); } static ResultCode GetThreadCoreMask(Core::System& system, Handle thread_handle, s32* out_core_id, -- cgit v1.2.3 From 126aaeb6d30c4f99c7ee28e38de00d2994bf8853 Mon Sep 17 00:00:00 2001 From: bunnei Date: Sat, 17 Apr 2021 22:21:59 -0700 Subject: hle: kernel: svc: Use new handle table API for Process. --- src/core/hle/kernel/svc.cpp | 25 ++++++++++++------------- 1 file changed, 12 insertions(+), 13 deletions(-) (limited to 'src/core/hle/kernel/svc.cpp') diff --git a/src/core/hle/kernel/svc.cpp b/src/core/hle/kernel/svc.cpp index 0b7eb0740..790839a4b 100644 --- a/src/core/hle/kernel/svc.cpp +++ b/src/core/hle/kernel/svc.cpp @@ -686,7 +686,7 @@ static void OutputDebugString(Core::System& system, VAddr address, u64 len) { } /// Gets system/memory information for the current process -static ResultCode GetInfo(Core::System& system, u64* result, u64 info_id, u64 handle, +static ResultCode GetInfo(Core::System& system, u64* result, u64 info_id, Handle handle, u64 info_sub_id) { std::lock_guard lock{HLE::g_hle_lock}; LOG_TRACE(Kernel_SVC, "called info_id=0x{:X}, info_sub_id=0x{:X}, handle=0x{:08X}", info_id, @@ -752,10 +752,9 @@ static ResultCode GetInfo(Core::System& system, u64* result, u64 info_id, u64 ha return ResultInvalidEnumValue; } - const auto& current_process_handle_table = - system.Kernel().CurrentProcess()->GetHandleTable(); - const auto process = current_process_handle_table.Get(static_cast(handle)); - if (!process) { + const auto& handle_table = system.Kernel().CurrentProcess()->GetHandleTable(); + KScopedAutoObject process = handle_table.GetObject(handle); + if (process.IsNull()) { LOG_ERROR(Kernel_SVC, "Process is not valid! info_id={}, info_sub_id={}, handle={:08X}", info_id, info_sub_id, handle); return ResultInvalidHandle; @@ -1287,8 +1286,8 @@ static ResultCode QueryProcessMemory(Core::System& system, VAddr memory_info_add std::lock_guard lock{HLE::g_hle_lock}; LOG_TRACE(Kernel_SVC, "called process=0x{:08X} address={:X}", process_handle, address); const auto& handle_table = system.Kernel().CurrentProcess()->GetHandleTable(); - auto process = handle_table.Get(process_handle); - if (!process) { + KScopedAutoObject process = handle_table.GetObject(process_handle); + if (process.IsNull()) { LOG_ERROR(Kernel_SVC, "Process handle does not exist, process_handle=0x{:08X}", process_handle); return ResultInvalidHandle; @@ -1369,8 +1368,8 @@ static ResultCode MapProcessCodeMemory(Core::System& system, Handle process_hand } const auto& handle_table = system.Kernel().CurrentProcess()->GetHandleTable(); - auto process = handle_table.Get(process_handle); - if (!process) { + KScopedAutoObject process = handle_table.GetObject(process_handle); + if (process.IsNull()) { LOG_ERROR(Kernel_SVC, "Invalid process handle specified (handle=0x{:08X}).", process_handle); return ResultInvalidHandle; @@ -1437,8 +1436,8 @@ static ResultCode UnmapProcessCodeMemory(Core::System& system, Handle process_ha } const auto& handle_table = system.Kernel().CurrentProcess()->GetHandleTable(); - auto process = handle_table.Get(process_handle); - if (!process) { + KScopedAutoObject process = handle_table.GetObject(process_handle); + if (process.IsNull()) { LOG_ERROR(Kernel_SVC, "Invalid process handle specified (handle=0x{:08X}).", process_handle); return ResultInvalidHandle; @@ -2100,8 +2099,8 @@ static ResultCode GetProcessInfo(Core::System& system, u64* out, Handle process_ }; const auto& handle_table = system.Kernel().CurrentProcess()->GetHandleTable(); - const auto process = handle_table.Get(process_handle); - if (!process) { + KScopedAutoObject process = handle_table.GetObject(process_handle); + if (process.IsNull()) { LOG_ERROR(Kernel_SVC, "Process handle does not exist, process_handle=0x{:08X}", process_handle); return ResultInvalidHandle; -- cgit v1.2.3 From 674122038ad01aae7eb4b6eff604f94fb8864bd4 Mon Sep 17 00:00:00 2001 From: bunnei Date: Sat, 17 Apr 2021 23:38:20 -0700 Subject: hle: kernel: svc: Migrate WaitSynchronization. --- src/core/hle/kernel/svc.cpp | 70 +++++++++++++++------------------------------ 1 file changed, 23 insertions(+), 47 deletions(-) (limited to 'src/core/hle/kernel/svc.cpp') diff --git a/src/core/hle/kernel/svc.cpp b/src/core/hle/kernel/svc.cpp index 790839a4b..9e8184758 100644 --- a/src/core/hle/kernel/svc.cpp +++ b/src/core/hle/kernel/svc.cpp @@ -430,65 +430,41 @@ static ResultCode GetProcessId32(Core::System& system, u32* out_process_id_low, /// Wait for the given handles to synchronize, timeout after the specified nanoseconds static ResultCode WaitSynchronization(Core::System& system, s32* index, VAddr handles_address, - u64 handle_count, s64 nano_seconds) { - LOG_TRACE(Kernel_SVC, "called handles_address=0x{:X}, handle_count={}, nano_seconds={}", - handles_address, handle_count, nano_seconds); + u64 num_handles, s64 nano_seconds) { + LOG_TRACE(Kernel_SVC, "called handles_address=0x{:X}, num_handles={}, nano_seconds={}", + handles_address, num_handles, nano_seconds); - auto& memory = system.Memory(); - if (!memory.IsValidVirtualAddress(handles_address)) { - LOG_ERROR(Kernel_SVC, - "Handle address is not a valid virtual address, handle_address=0x{:016X}", - handles_address); - return ResultInvalidPointer; - } - - static constexpr u64 MaxHandles = 0x40; - - if (handle_count > MaxHandles) { - LOG_ERROR(Kernel_SVC, "Handle count specified is too large, expected {} but got {}", - MaxHandles, handle_count); - return ResultOutOfRange; - } + // Ensure number of handles is valid. + R_UNLESS(0 <= num_handles && num_handles <= ArgumentHandleCountMax, ResultOutOfRange); auto& kernel = system.Kernel(); - std::vector objects(handle_count); + std::vector objs(num_handles); const auto& handle_table = kernel.CurrentProcess()->GetHandleTable(); + Handle* handles = system.Memory().GetPointer(handles_address); - for (u64 i = 0; i < handle_count; ++i) { - const Handle handle = memory.Read32(handles_address + i * sizeof(Handle)); + // Copy user handles. + if (num_handles > 0) { + // Convert the handles to objects. + R_UNLESS(handle_table.GetMultipleObjects(objs.data(), handles, + num_handles), + ResultInvalidHandle); + } - bool succeeded{}; - { - auto object = handle_table.Get(handle); - if (object) { - objects[i] = object; - succeeded = true; - } + // Ensure handles are closed when we're done. + SCOPE_EXIT({ + for (u64 i = 0; i < num_handles; ++i) { + objs[i]->Close(); } + }); - // TODO(bunnei): WORKAROUND WHILE WE HAVE TWO HANDLE TABLES - if (!succeeded) { - { - auto object = handle_table.GetObject(handle); - - if (object.IsNull()) { - LOG_ERROR(Kernel_SVC, "Object is a nullptr"); - return ResultInvalidHandle; - } - - objects[i] = object.GetPointerUnsafe(); - succeeded = true; - } - } - } - return KSynchronizationObject::Wait(kernel, index, objects.data(), - static_cast(objects.size()), nano_seconds); + return KSynchronizationObject::Wait(kernel, index, objs.data(), static_cast(objs.size()), + nano_seconds); } static ResultCode WaitSynchronization32(Core::System& system, u32 timeout_low, u32 handles_address, - s32 handle_count, u32 timeout_high, s32* index) { + s32 num_handles, u32 timeout_high, s32* index) { const s64 nano_seconds{(static_cast(timeout_high) << 32) | static_cast(timeout_low)}; - return WaitSynchronization(system, index, handles_address, handle_count, nano_seconds); + return WaitSynchronization(system, index, handles_address, num_handles, nano_seconds); } /// Resumes a thread waiting on WaitSynchronization -- cgit v1.2.3 From b57c5a9b54b23a348d7e80e51943f27a54fb8c2f Mon Sep 17 00:00:00 2001 From: bunnei Date: Tue, 20 Apr 2021 21:28:11 -0700 Subject: hle: kernel: Migrate KResourceLimit to KAutoObject. --- src/core/hle/kernel/svc.cpp | 127 ++++++++++++++++++++++---------------------- 1 file changed, 64 insertions(+), 63 deletions(-) (limited to 'src/core/hle/kernel/svc.cpp') diff --git a/src/core/hle/kernel/svc.cpp b/src/core/hle/kernel/svc.cpp index 9e8184758..a78bfd1da 100644 --- a/src/core/hle/kernel/svc.cpp +++ b/src/core/hle/kernel/svc.cpp @@ -153,9 +153,9 @@ ResultVal RetrieveResourceLimitValue(Core::System& system, Handle resource_ const auto* const current_process = system.Kernel().CurrentProcess(); ASSERT(current_process != nullptr); - const auto resource_limit_object = - current_process->GetHandleTable().Get(resource_limit); - if (!resource_limit_object) { + auto resource_limit_object = + current_process->GetHandleTable().GetObject(resource_limit); + if (resource_limit_object.IsNull()) { LOG_ERROR(Kernel_SVC, "Handle to non-existent resource limit instance used. Handle={:08X}", resource_limit); return ResultInvalidHandle; @@ -843,12 +843,10 @@ static ResultCode GetInfo(Core::System& system, u64* result, u64 info_id, Handle return RESULT_SUCCESS; } - const auto table_result = handle_table.Create(resource_limit.get()); - if (table_result.Failed()) { - return table_result.Code(); - } + Handle handle{}; + R_TRY(handle_table.Add(&handle, resource_limit)); - *result = *table_result; + *result = handle; return RESULT_SUCCESS; } @@ -2093,83 +2091,86 @@ static ResultCode GetProcessInfo(Core::System& system, u64* out, Handle process_ } static ResultCode CreateResourceLimit(Core::System& system, Handle* out_handle) { - std::lock_guard lock{HLE::g_hle_lock}; LOG_DEBUG(Kernel_SVC, "called"); + // Create a new resource limit. auto& kernel = system.Kernel(); - auto resource_limit = std::make_shared(kernel, system.CoreTiming()); + KResourceLimit* resource_limit = KResourceLimit::Create(kernel); + R_UNLESS(resource_limit != nullptr, ResultOutOfResource); - auto* const current_process = kernel.CurrentProcess(); - ASSERT(current_process != nullptr); + // Ensure we don't leak a reference to the limit. + SCOPE_EXIT({ resource_limit->Close(); }); - const auto handle = current_process->GetHandleTable().Create(resource_limit.get()); - if (handle.Failed()) { - return handle.Code(); - } + // Initialize the resource limit. + resource_limit->Initialize(&system.CoreTiming()); + + // Register the limit. + KResourceLimit::Register(kernel, resource_limit); + + // Add the limit to the handle table. + R_TRY(kernel.CurrentProcess()->GetHandleTable().Add(out_handle, resource_limit)); - *out_handle = *handle; return RESULT_SUCCESS; } -static ResultCode GetResourceLimitLimitValue(Core::System& system, u64* out_value, - Handle resource_limit, u32 resource_type) { - LOG_DEBUG(Kernel_SVC, "called. Handle={:08X}, Resource type={}", resource_limit, resource_type); +static ResultCode GetResourceLimitLimitValue(Core::System& system, u64* out_limit_value, + Handle resource_limit_handle, + LimitableResource which) { + LOG_DEBUG(Kernel_SVC, "called, resource_limit_handle={:08X}, which={}", resource_limit_handle, + which); - const auto limit_value = RetrieveResourceLimitValue(system, resource_limit, resource_type, - ResourceLimitValueType::LimitValue); - if (limit_value.Failed()) { - return limit_value.Code(); - } + // Validate the resource. + R_UNLESS(IsValidResourceType(which), ResultInvalidEnumValue); + + // Get the resource limit. + auto& kernel = system.Kernel(); + KScopedAutoObject resource_limit = + kernel.CurrentProcess()->GetHandleTable().GetObject(resource_limit_handle); + R_UNLESS(resource_limit.IsNotNull(), ResultInvalidHandle); + + // Get the limit value. + *out_limit_value = resource_limit->GetLimitValue(which); - *out_value = static_cast(*limit_value); return RESULT_SUCCESS; } -static ResultCode GetResourceLimitCurrentValue(Core::System& system, u64* out_value, - Handle resource_limit, u32 resource_type) { - LOG_DEBUG(Kernel_SVC, "called. Handle={:08X}, Resource type={}", resource_limit, resource_type); +static ResultCode GetResourceLimitCurrentValue(Core::System& system, u64* out_current_value, + Handle resource_limit_handle, + LimitableResource which) { + LOG_DEBUG(Kernel_SVC, "called, resource_limit_handle={:08X}, which={}", resource_limit_handle, + which); - const auto current_value = RetrieveResourceLimitValue(system, resource_limit, resource_type, - ResourceLimitValueType::CurrentValue); - if (current_value.Failed()) { - return current_value.Code(); - } + // Validate the resource. + R_UNLESS(IsValidResourceType(which), ResultInvalidEnumValue); + + // Get the resource limit. + auto& kernel = system.Kernel(); + KScopedAutoObject resource_limit = + kernel.CurrentProcess()->GetHandleTable().GetObject(resource_limit_handle); + R_UNLESS(resource_limit.IsNotNull(), ResultInvalidHandle); + + // Get the current value. + *out_current_value = resource_limit->GetCurrentValue(which); - *out_value = static_cast(*current_value); return RESULT_SUCCESS; } -static ResultCode SetResourceLimitLimitValue(Core::System& system, Handle resource_limit, - u32 resource_type, u64 value) { - LOG_DEBUG(Kernel_SVC, "called. Handle={:08X}, Resource type={}, Value={}", resource_limit, - resource_type, value); +static ResultCode SetResourceLimitLimitValue(Core::System& system, Handle resource_limit_handle, + LimitableResource which, u64 limit_value) { + LOG_DEBUG(Kernel_SVC, "called, resource_limit_handle={:08X}, which={}, limit_value={}", + resource_limit_handle, which, limit_value); - const auto type = static_cast(resource_type); - if (!IsValidResourceType(type)) { - LOG_ERROR(Kernel_SVC, "Invalid resource limit type: '{}'", resource_type); - return ResultInvalidEnumValue; - } - - auto* const current_process = system.Kernel().CurrentProcess(); - ASSERT(current_process != nullptr); + // Validate the resource. + R_UNLESS(IsValidResourceType(which), ResultInvalidEnumValue); - auto resource_limit_object = - current_process->GetHandleTable().Get(resource_limit); - if (!resource_limit_object) { - LOG_ERROR(Kernel_SVC, "Handle to non-existent resource limit instance used. Handle={:08X}", - resource_limit); - return ResultInvalidHandle; - } + // Get the resource limit. + auto& kernel = system.Kernel(); + KScopedAutoObject resource_limit = + kernel.CurrentProcess()->GetHandleTable().GetObject(resource_limit_handle); + R_UNLESS(resource_limit.IsNotNull(), ResultInvalidHandle); - const auto set_result = resource_limit_object->SetLimitValue(type, static_cast(value)); - if (set_result.IsError()) { - LOG_ERROR(Kernel_SVC, - "Attempted to lower resource limit ({}) for category '{}' below its current " - "value ({})", - resource_limit_object->GetLimitValue(type), resource_type, - resource_limit_object->GetCurrentValue(type)); - return set_result; - } + // Set the limit value. + R_TRY(resource_limit->SetLimitValue(which, limit_value)); return RESULT_SUCCESS; } -- cgit v1.2.3 From aa2844bcf9b2b9bca2ce263270b963ffd13b05e7 Mon Sep 17 00:00:00 2001 From: bunnei Date: Tue, 20 Apr 2021 22:18:56 -0700 Subject: hle: kernel: HandleTable: Remove deprecated APIs. --- src/core/hle/kernel/svc.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/core/hle/kernel/svc.cpp') diff --git a/src/core/hle/kernel/svc.cpp b/src/core/hle/kernel/svc.cpp index a78bfd1da..fa85bd631 100644 --- a/src/core/hle/kernel/svc.cpp +++ b/src/core/hle/kernel/svc.cpp @@ -328,7 +328,7 @@ static ResultCode ConnectToNamedPort(Core::System& system, Handle* out_handle, // Return the client session auto& handle_table = kernel.CurrentProcess()->GetHandleTable(); - CASCADE_RESULT(*out_handle, handle_table.Create(client_session)); + handle_table.Add(out_handle, client_session); return RESULT_SUCCESS; } -- cgit v1.2.3 From 0297448fbc6bf909b0bc061723c38208b9667b66 Mon Sep 17 00:00:00 2001 From: bunnei Date: Wed, 21 Apr 2021 21:43:25 -0700 Subject: hle: kernel: Migrate KClientPort to KAutoObject. --- src/core/hle/kernel/svc.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/core/hle/kernel/svc.cpp') diff --git a/src/core/hle/kernel/svc.cpp b/src/core/hle/kernel/svc.cpp index fa85bd631..8d8d3dd5a 100644 --- a/src/core/hle/kernel/svc.cpp +++ b/src/core/hle/kernel/svc.cpp @@ -21,9 +21,9 @@ #include "core/core_timing.h" #include "core/core_timing_util.h" #include "core/cpu_manager.h" -#include "core/hle/kernel/client_port.h" #include "core/hle/kernel/handle_table.h" #include "core/hle/kernel/k_address_arbiter.h" +#include "core/hle/kernel/k_client_port.h" #include "core/hle/kernel/k_client_session.h" #include "core/hle/kernel/k_condition_variable.h" #include "core/hle/kernel/k_event.h" -- cgit v1.2.3 From 626f746971d1d3216a38b20680959df3a1f5f256 Mon Sep 17 00:00:00 2001 From: bunnei Date: Fri, 23 Apr 2021 17:00:15 -0700 Subject: hle: kernel: Migrate KPort, KClientPort, and KServerPort to KAutoObject. --- src/core/hle/kernel/svc.cpp | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) (limited to 'src/core/hle/kernel/svc.cpp') diff --git a/src/core/hle/kernel/svc.cpp b/src/core/hle/kernel/svc.cpp index 8d8d3dd5a..ef8fa98a9 100644 --- a/src/core/hle/kernel/svc.cpp +++ b/src/core/hle/kernel/svc.cpp @@ -293,9 +293,7 @@ static ResultCode UnmapMemory32(Core::System& system, u32 dst_addr, u32 src_addr /// Connect to an OS service given the port name, returns the handle to the port to out static ResultCode ConnectToNamedPort(Core::System& system, Handle* out_handle, VAddr port_name_address) { - std::lock_guard lock{HLE::g_hle_lock}; auto& memory = system.Memory(); - if (!memory.IsValidVirtualAddress(port_name_address)) { LOG_ERROR(Kernel_SVC, "Port Name Address is not a valid virtual address, port_name_address=0x{:016X}", @@ -314,21 +312,27 @@ static ResultCode ConnectToNamedPort(Core::System& system, Handle* out_handle, LOG_TRACE(Kernel_SVC, "called port_name={}", port_name); + // Get the current handle table. auto& kernel = system.Kernel(); + auto& handle_table = kernel.CurrentProcess()->GetHandleTable(); + + // Find the client port. const auto it = kernel.FindNamedPort(port_name); if (!kernel.IsValidNamedPort(it)) { LOG_WARNING(Kernel_SVC, "tried to connect to unknown port: {}", port_name); return ResultNotFound; } + auto port = it->second; - auto client_port = it->second; + // Create a session. + KClientSession* session{}; + R_TRY(port->CreateSession(std::addressof(session))); - KClientSession* client_session{}; - CASCADE_RESULT(client_session, client_port->Connect()); + // Register the session in the table, close the extra reference. + handle_table.Add(out_handle, session); + session->Close(); - // Return the client session - auto& handle_table = kernel.CurrentProcess()->GetHandleTable(); - handle_table.Add(out_handle, client_session); + // We succeeded. return RESULT_SUCCESS; } @@ -340,13 +344,13 @@ static ResultCode ConnectToNamedPort32(Core::System& system, Handle* out_handle, /// Makes a blocking IPC call to an OS service. static ResultCode SendSyncRequest(Core::System& system, Handle handle) { - LOG_TRACE(Kernel_SVC, "called handle=0x{:08X}({})", handle, session->GetName()); auto& kernel = system.Kernel(); KScopedAutoObject session = kernel.CurrentProcess()->GetHandleTable().GetObject(handle); R_UNLESS(session.IsNotNull(), ResultInvalidHandle); + LOG_TRACE(Kernel_SVC, "called handle=0x{:08X}({})", handle, session->GetName()); auto thread = kernel.CurrentScheduler()->GetCurrentThread(); { -- cgit v1.2.3 From 2a7eff57a8048933a89c1a8f8d6dced7b5d604f2 Mon Sep 17 00:00:00 2001 From: bunnei Date: Fri, 23 Apr 2021 22:04:28 -0700 Subject: hle: kernel: Rename Process to KProcess. --- src/core/hle/kernel/svc.cpp | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) (limited to 'src/core/hle/kernel/svc.cpp') diff --git a/src/core/hle/kernel/svc.cpp b/src/core/hle/kernel/svc.cpp index ef8fa98a9..725f16ea4 100644 --- a/src/core/hle/kernel/svc.cpp +++ b/src/core/hle/kernel/svc.cpp @@ -30,6 +30,7 @@ #include "core/hle/kernel/k_memory_block.h" #include "core/hle/kernel/k_memory_layout.h" #include "core/hle/kernel/k_page_table.h" +#include "core/hle/kernel/k_process.h" #include "core/hle/kernel/k_readable_event.h" #include "core/hle/kernel/k_resource_limit.h" #include "core/hle/kernel/k_scheduler.h" @@ -42,7 +43,6 @@ #include "core/hle/kernel/k_writable_event.h" #include "core/hle/kernel/kernel.h" #include "core/hle/kernel/physical_core.h" -#include "core/hle/kernel/process.h" #include "core/hle/kernel/svc.h" #include "core/hle/kernel/svc_results.h" #include "core/hle/kernel/svc_types.h" @@ -402,8 +402,8 @@ static ResultCode GetProcessId(Core::System& system, u64* out_process_id, Handle R_UNLESS(obj.IsNotNull(), ResultInvalidHandle); // Get the process from the object. - Process* process = nullptr; - if (Process* p = obj->DynamicCast(); p != nullptr) { + KProcess* process = nullptr; + if (KProcess* p = obj->DynamicCast(); p != nullptr) { // The object is a process, so we can use it directly. process = p; } else if (KThread* t = obj->DynamicCast(); t != nullptr) { @@ -733,7 +733,7 @@ static ResultCode GetInfo(Core::System& system, u64* result, u64 info_id, Handle } const auto& handle_table = system.Kernel().CurrentProcess()->GetHandleTable(); - KScopedAutoObject process = handle_table.GetObject(handle); + KScopedAutoObject process = handle_table.GetObject(handle); if (process.IsNull()) { LOG_ERROR(Kernel_SVC, "Process is not valid! info_id={}, info_sub_id={}, handle={:08X}", info_id, info_sub_id, handle); @@ -838,7 +838,7 @@ static ResultCode GetInfo(Core::System& system, u64* result, u64 info_id, Handle return ResultInvalidCombination; } - Process* const current_process = system.Kernel().CurrentProcess(); + KProcess* const current_process = system.Kernel().CurrentProcess(); HandleTable& handle_table = current_process->GetHandleTable(); const auto resource_limit = current_process->GetResourceLimit(); if (!resource_limit) { @@ -861,9 +861,9 @@ static ResultCode GetInfo(Core::System& system, u64* result, u64 info_id, Handle return ResultInvalidHandle; } - if (info_sub_id >= Process::RANDOM_ENTROPY_SIZE) { + if (info_sub_id >= KProcess::RANDOM_ENTROPY_SIZE) { LOG_ERROR(Kernel_SVC, "Entropy size is out of range, expected {} but got {}", - Process::RANDOM_ENTROPY_SIZE, info_sub_id); + KProcess::RANDOM_ENTROPY_SIZE, info_sub_id); return ResultInvalidCombination; } @@ -955,7 +955,7 @@ static ResultCode MapPhysicalMemory(Core::System& system, VAddr addr, u64 size) return ResultInvalidMemoryRegion; } - Process* const current_process{system.Kernel().CurrentProcess()}; + KProcess* const current_process{system.Kernel().CurrentProcess()}; auto& page_table{current_process->PageTable()}; if (current_process->GetSystemResourceSize() == 0) { @@ -1009,7 +1009,7 @@ static ResultCode UnmapPhysicalMemory(Core::System& system, VAddr addr, u64 size return ResultInvalidMemoryRegion; } - Process* const current_process{system.Kernel().CurrentProcess()}; + KProcess* const current_process{system.Kernel().CurrentProcess()}; auto& page_table{current_process->PageTable()}; if (current_process->GetSystemResourceSize() == 0) { @@ -1153,7 +1153,7 @@ static ResultCode GetThreadPriority32(Core::System& system, u32* out_priority, H /// Sets the priority for the specified thread static ResultCode SetThreadPriority(Core::System& system, Handle thread_handle, u32 priority) { // Get the current process. - Process& process = *system.Kernel().CurrentProcess(); + KProcess& process = *system.Kernel().CurrentProcess(); // Validate the priority. R_UNLESS(HighestThreadPriority <= priority && priority <= LowestThreadPriority, @@ -1264,7 +1264,7 @@ static ResultCode QueryProcessMemory(Core::System& system, VAddr memory_info_add std::lock_guard lock{HLE::g_hle_lock}; LOG_TRACE(Kernel_SVC, "called process=0x{:08X} address={:X}", process_handle, address); const auto& handle_table = system.Kernel().CurrentProcess()->GetHandleTable(); - KScopedAutoObject process = handle_table.GetObject(process_handle); + KScopedAutoObject process = handle_table.GetObject(process_handle); if (process.IsNull()) { LOG_ERROR(Kernel_SVC, "Process handle does not exist, process_handle=0x{:08X}", process_handle); @@ -1346,7 +1346,7 @@ static ResultCode MapProcessCodeMemory(Core::System& system, Handle process_hand } const auto& handle_table = system.Kernel().CurrentProcess()->GetHandleTable(); - KScopedAutoObject process = handle_table.GetObject(process_handle); + KScopedAutoObject process = handle_table.GetObject(process_handle); if (process.IsNull()) { LOG_ERROR(Kernel_SVC, "Invalid process handle specified (handle=0x{:08X}).", process_handle); @@ -1414,7 +1414,7 @@ static ResultCode UnmapProcessCodeMemory(Core::System& system, Handle process_ha } const auto& handle_table = system.Kernel().CurrentProcess()->GetHandleTable(); - KScopedAutoObject process = handle_table.GetObject(process_handle); + KScopedAutoObject process = handle_table.GetObject(process_handle); if (process.IsNull()) { LOG_ERROR(Kernel_SVC, "Invalid process handle specified (handle=0x{:08X}).", process_handle); @@ -1830,7 +1830,7 @@ static ResultCode ResetSignal(Core::System& system, Handle handle) { // Try to reset as process. { - KScopedAutoObject process = handle_table.GetObject(handle); + KScopedAutoObject process = handle_table.GetObject(handle); if (process.IsNotNull()) { return process->Reset(); } @@ -2077,7 +2077,7 @@ static ResultCode GetProcessInfo(Core::System& system, u64* out, Handle process_ }; const auto& handle_table = system.Kernel().CurrentProcess()->GetHandleTable(); - KScopedAutoObject process = handle_table.GetObject(process_handle); + KScopedAutoObject process = handle_table.GetObject(process_handle); if (process.IsNull()) { LOG_ERROR(Kernel_SVC, "Process handle does not exist, process_handle=0x{:08X}", process_handle); -- cgit v1.2.3 From 0b27c721c994e10200893c3306cdab2184e5143c Mon Sep 17 00:00:00 2001 From: bunnei Date: Fri, 30 Apr 2021 14:53:22 -0700 Subject: hle: kernel: Improve MapSharedMemory and implement UnmapSharedMemory. --- src/core/hle/kernel/svc.cpp | 138 +++++++++++++++++++++++++------------------- 1 file changed, 78 insertions(+), 60 deletions(-) (limited to 'src/core/hle/kernel/svc.cpp') diff --git a/src/core/hle/kernel/svc.cpp b/src/core/hle/kernel/svc.cpp index 725f16ea4..156c565b0 100644 --- a/src/core/hle/kernel/svc.cpp +++ b/src/core/hle/kernel/svc.cpp @@ -1183,79 +1183,97 @@ static u32 GetCurrentProcessorNumber32(Core::System& system) { return GetCurrentProcessorNumber(system); } -static ResultCode MapSharedMemory(Core::System& system, Handle shared_memory_handle, VAddr addr, - u64 size, u32 permissions) { - std::lock_guard lock{HLE::g_hle_lock}; +constexpr bool IsValidSharedMemoryPermission(Svc::MemoryPermission perm) { + switch (perm) { + case Svc::MemoryPermission::Read: + case Svc::MemoryPermission::ReadWrite: + return true; + default: + return false; + } +} + +constexpr bool IsValidRemoteSharedMemoryPermission(Svc::MemoryPermission perm) { + return IsValidSharedMemoryPermission(perm) || perm == Svc::MemoryPermission::DontCare; +} + +static ResultCode MapSharedMemory(Core::System& system, Handle shmem_handle, VAddr address, + u64 size, Svc::MemoryPermission map_perm) { LOG_TRACE(Kernel_SVC, "called, shared_memory_handle=0x{:X}, addr=0x{:X}, size=0x{:X}, permissions=0x{:08X}", - shared_memory_handle, addr, size, permissions); + shmem_handle, address, size, map_perm); - if (!Common::Is4KBAligned(addr)) { - LOG_ERROR(Kernel_SVC, "Address is not aligned to 4KB, addr=0x{:016X}", addr); - return ResultInvalidAddress; - } + // Validate the address/size. + R_UNLESS(Common::IsAligned(address, PageSize), ResultInvalidAddress); + R_UNLESS(Common::IsAligned(size, PageSize), ResultInvalidSize); + R_UNLESS(size > 0, ResultInvalidSize); + R_UNLESS((address < address + size), ResultInvalidCurrentMemory); - if (size == 0) { - LOG_ERROR(Kernel_SVC, "Size is 0"); - return ResultInvalidSize; - } + // Validate the permission. + R_UNLESS(IsValidSharedMemoryPermission(map_perm), ResultInvalidNewMemoryPermission); - if (!Common::Is4KBAligned(size)) { - LOG_ERROR(Kernel_SVC, "Size is not aligned to 4KB, size=0x{:016X}", size); - return ResultInvalidSize; - } + // Get the current process. + auto& process = *system.Kernel().CurrentProcess(); + auto& page_table = process.PageTable(); - if (!IsValidAddressRange(addr, size)) { - LOG_ERROR(Kernel_SVC, "Region is not a valid address range, addr=0x{:016X}, size=0x{:016X}", - addr, size); - return ResultInvalidCurrentMemory; - } + // Get the shared memory. + KScopedAutoObject shmem = process.GetHandleTable().GetObject(shmem_handle); + R_UNLESS(shmem.IsNotNull(), ResultInvalidHandle); - const auto permission_type = static_cast(permissions); - if ((permission_type | MemoryPermission::Write) != MemoryPermission::ReadWrite) { - LOG_ERROR(Kernel_SVC, "Expected Read or ReadWrite permission but got permissions=0x{:08X}", - permissions); - return ResultInvalidNewMemoryPermission; - } + // Verify that the mapping is in range. + R_UNLESS(page_table.CanContain(address, size, KMemoryState::Shared), ResultInvalidMemoryRegion); - auto* const current_process{system.Kernel().CurrentProcess()}; - auto& page_table{current_process->PageTable()}; + // Add the shared memory to the process. + R_TRY(process.AddSharedMemory(shmem.GetPointerUnsafe(), address, size)); - if (page_table.IsInvalidRegion(addr, size)) { - LOG_ERROR(Kernel_SVC, - "Addr does not fit within the valid region, addr=0x{:016X}, " - "size=0x{:016X}", - addr, size); - return ResultInvalidMemoryRegion; - } + // Ensure that we clean up the shared memory if we fail to map it. + auto guard = + SCOPE_GUARD({ process.RemoveSharedMemory(shmem.GetPointerUnsafe(), address, size); }); - if (page_table.IsInsideHeapRegion(addr, size)) { - LOG_ERROR(Kernel_SVC, - "Addr does not fit within the heap region, addr=0x{:016X}, " - "size=0x{:016X}", - addr, size); - return ResultInvalidMemoryRegion; - } + // Map the shared memory. + R_TRY(shmem->Map(process, address, size, map_perm)); - if (page_table.IsInsideAliasRegion(addr, size)) { - LOG_ERROR(Kernel_SVC, - "Address does not fit within the map region, addr=0x{:016X}, " - "size=0x{:016X}", - addr, size); - return ResultInvalidMemoryRegion; - } + // We succeeded. + guard.Cancel(); + return RESULT_SUCCESS; +} + +static ResultCode MapSharedMemory32(Core::System& system, Handle shmem_handle, u32 address, + u32 size, Svc::MemoryPermission map_perm) { + return MapSharedMemory(system, shmem_handle, address, size, map_perm); +} + +static ResultCode UnmapSharedMemory(Core::System& system, Handle shmem_handle, VAddr address, + u64 size) { + // Validate the address/size. + R_UNLESS(Common::IsAligned(address, PageSize), ResultInvalidAddress); + R_UNLESS(Common::IsAligned(size, PageSize), ResultInvalidSize); + R_UNLESS(size > 0, ResultInvalidSize); + R_UNLESS((address < address + size), ResultInvalidCurrentMemory); + + // Get the current process. + auto& process = *system.Kernel().CurrentProcess(); + auto& page_table = process.PageTable(); + + // Get the shared memory. + KScopedAutoObject shmem = process.GetHandleTable().GetObject(shmem_handle); + R_UNLESS(shmem.IsNotNull(), ResultInvalidHandle); - auto shared_memory{ - current_process->GetHandleTable().GetObject(shared_memory_handle)}; - R_UNLESS(shared_memory.IsNotNull(), ResultInvalidHandle); + // Verify that the mapping is in range. + R_UNLESS(page_table.CanContain(address, size, KMemoryState::Shared), ResultInvalidMemoryRegion); - return shared_memory->Map(*current_process, addr, size, - static_cast(permission_type)); + // Unmap the shared memory. + R_TRY(shmem->Unmap(process, address, size)); + + // Remove the shared memory from the process. + process.RemoveSharedMemory(shmem.GetPointerUnsafe(), address, size); + + return RESULT_SUCCESS; } -static ResultCode MapSharedMemory32(Core::System& system, Handle shared_memory_handle, u32 addr, - u32 size, u32 permissions) { - return MapSharedMemory(system, shared_memory_handle, addr, size, permissions); +static ResultCode UnmapSharedMemory32(Core::System& system, Handle shmem_handle, u32 address, + u32 size) { + return UnmapSharedMemory(system, shmem_handle, address, size); } static ResultCode QueryProcessMemory(Core::System& system, VAddr memory_info_address, @@ -2297,7 +2315,7 @@ static const FunctionDef SVC_Table_32[] = { {0x11, SvcWrap32, "SignalEvent32"}, {0x12, SvcWrap32, "ClearEvent32"}, {0x13, SvcWrap32, "MapSharedMemory32"}, - {0x14, nullptr, "UnmapSharedMemory32"}, + {0x14, SvcWrap32, "UnmapSharedMemory32"}, {0x15, SvcWrap32, "CreateTransferMemory32"}, {0x16, SvcWrap32, "CloseHandle32"}, {0x17, SvcWrap32, "ResetSignal32"}, @@ -2492,7 +2510,7 @@ static const FunctionDef SVC_Table_64[] = { {0x11, SvcWrap64, "SignalEvent"}, {0x12, SvcWrap64, "ClearEvent"}, {0x13, SvcWrap64, "MapSharedMemory"}, - {0x14, nullptr, "UnmapSharedMemory"}, + {0x14, SvcWrap64, "UnmapSharedMemory"}, {0x15, SvcWrap64, "CreateTransferMemory"}, {0x16, SvcWrap64, "CloseHandle"}, {0x17, SvcWrap64, "ResetSignal"}, -- cgit v1.2.3 From 4b03e6e776e6421c2b2c290b0822b9e5a8556a4c Mon Sep 17 00:00:00 2001 From: bunnei Date: Sat, 24 Apr 2021 02:40:31 -0700 Subject: hle: kernel: Migrate to KHandleTable. --- src/core/hle/kernel/svc.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'src/core/hle/kernel/svc.cpp') diff --git a/src/core/hle/kernel/svc.cpp b/src/core/hle/kernel/svc.cpp index 156c565b0..d3293a1fe 100644 --- a/src/core/hle/kernel/svc.cpp +++ b/src/core/hle/kernel/svc.cpp @@ -21,12 +21,12 @@ #include "core/core_timing.h" #include "core/core_timing_util.h" #include "core/cpu_manager.h" -#include "core/hle/kernel/handle_table.h" #include "core/hle/kernel/k_address_arbiter.h" #include "core/hle/kernel/k_client_port.h" #include "core/hle/kernel/k_client_session.h" #include "core/hle/kernel/k_condition_variable.h" #include "core/hle/kernel/k_event.h" +#include "core/hle/kernel/k_handle_table.h" #include "core/hle/kernel/k_memory_block.h" #include "core/hle/kernel/k_memory_layout.h" #include "core/hle/kernel/k_page_table.h" @@ -839,10 +839,10 @@ static ResultCode GetInfo(Core::System& system, u64* result, u64 info_id, Handle } KProcess* const current_process = system.Kernel().CurrentProcess(); - HandleTable& handle_table = current_process->GetHandleTable(); + KHandleTable& handle_table = current_process->GetHandleTable(); const auto resource_limit = current_process->GetResourceLimit(); if (!resource_limit) { - *result = KernelHandle::InvalidHandle; + *result = Svc::InvalidHandle; // Yes, the kernel considers this a successful operation. return RESULT_SUCCESS; } @@ -1993,7 +1993,7 @@ static ResultCode SignalEvent(Core::System& system, Handle event_handle) { LOG_DEBUG(Kernel_SVC, "called, event_handle=0x{:08X}", event_handle); // Get the current handle table. - const HandleTable& handle_table = system.Kernel().CurrentProcess()->GetHandleTable(); + const KHandleTable& handle_table = system.Kernel().CurrentProcess()->GetHandleTable(); // Get the writable event. KScopedAutoObject writable_event = handle_table.GetObject(event_handle); -- cgit v1.2.3 From 7866eb03bb2e84917ba3930efed6c6b52035f368 Mon Sep 17 00:00:00 2001 From: bunnei Date: Sat, 24 Apr 2021 02:54:16 -0700 Subject: hle: kernel: svc: ConnectToNamedPort: Use KHandleTable::Reserve. --- src/core/hle/kernel/svc.cpp | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) (limited to 'src/core/hle/kernel/svc.cpp') diff --git a/src/core/hle/kernel/svc.cpp b/src/core/hle/kernel/svc.cpp index d3293a1fe..80d70a816 100644 --- a/src/core/hle/kernel/svc.cpp +++ b/src/core/hle/kernel/svc.cpp @@ -291,8 +291,7 @@ static ResultCode UnmapMemory32(Core::System& system, u32 dst_addr, u32 src_addr } /// Connect to an OS service given the port name, returns the handle to the port to out -static ResultCode ConnectToNamedPort(Core::System& system, Handle* out_handle, - VAddr port_name_address) { +static ResultCode ConnectToNamedPort(Core::System& system, Handle* out, VAddr port_name_address) { auto& memory = system.Memory(); if (!memory.IsValidVirtualAddress(port_name_address)) { LOG_ERROR(Kernel_SVC, @@ -324,15 +323,21 @@ static ResultCode ConnectToNamedPort(Core::System& system, Handle* out_handle, } auto port = it->second; + // Reserve a handle for the port. + // NOTE: Nintendo really does write directly to the output handle here. + R_TRY(handle_table.Reserve(out)); + auto handle_guard = SCOPE_GUARD({ handle_table.Unreserve(*out); }); + // Create a session. KClientSession* session{}; R_TRY(port->CreateSession(std::addressof(session))); // Register the session in the table, close the extra reference. - handle_table.Add(out_handle, session); + handle_table.Register(*out, session); session->Close(); // We succeeded. + handle_guard.Cancel(); return RESULT_SUCCESS; } -- cgit v1.2.3 From eae107d0e9764ac2773a20e744c17201cfe2f814 Mon Sep 17 00:00:00 2001 From: bunnei Date: Sun, 2 May 2021 00:44:28 -0700 Subject: kernel: svc: Remove unused RetrieveResourceLimitValue function. --- src/core/hle/kernel/svc.cpp | 32 -------------------------------- 1 file changed, 32 deletions(-) (limited to 'src/core/hle/kernel/svc.cpp') diff --git a/src/core/hle/kernel/svc.cpp b/src/core/hle/kernel/svc.cpp index 80d70a816..52011be9c 100644 --- a/src/core/hle/kernel/svc.cpp +++ b/src/core/hle/kernel/svc.cpp @@ -141,38 +141,6 @@ enum class ResourceLimitValueType { PeakValue, }; -ResultVal RetrieveResourceLimitValue(Core::System& system, Handle resource_limit, - u32 resource_type, ResourceLimitValueType value_type) { - std::lock_guard lock{HLE::g_hle_lock}; - const auto type = static_cast(resource_type); - if (!IsValidResourceType(type)) { - LOG_ERROR(Kernel_SVC, "Invalid resource limit type: '{}'", resource_type); - return ResultInvalidEnumValue; - } - - const auto* const current_process = system.Kernel().CurrentProcess(); - ASSERT(current_process != nullptr); - - auto resource_limit_object = - current_process->GetHandleTable().GetObject(resource_limit); - if (resource_limit_object.IsNull()) { - LOG_ERROR(Kernel_SVC, "Handle to non-existent resource limit instance used. Handle={:08X}", - resource_limit); - return ResultInvalidHandle; - } - - switch (value_type) { - case ResourceLimitValueType::CurrentValue: - return MakeResult(resource_limit_object->GetCurrentValue(type)); - case ResourceLimitValueType::LimitValue: - return MakeResult(resource_limit_object->GetLimitValue(type)); - case ResourceLimitValueType::PeakValue: - return MakeResult(resource_limit_object->GetPeakValue(type)); - default: - LOG_ERROR(Kernel_SVC, "Invalid resource value_type: '{}'", value_type); - return ResultInvalidEnumValue; - } -} } // Anonymous namespace /// Set the process heap to a given Size. It can both extend and shrink the heap. -- cgit v1.2.3