diff options
author | Liam <byteslice@airmail.cc> | 2023-12-07 01:54:52 +0100 |
---|---|---|
committer | Liam <byteslice@airmail.cc> | 2023-12-07 15:13:43 +0100 |
commit | 9268f265a1207f0cddb97a908a1cc349f9b6410b (patch) | |
tree | 5da6aea714523b3504b78362c5d8abd53689d72f /src/core/hle/kernel/svc | |
parent | Merge pull request #12236 from liamwhite/cpu-refactor (diff) | |
download | yuzu-9268f265a1207f0cddb97a908a1cc349f9b6410b.tar yuzu-9268f265a1207f0cddb97a908a1cc349f9b6410b.tar.gz yuzu-9268f265a1207f0cddb97a908a1cc349f9b6410b.tar.bz2 yuzu-9268f265a1207f0cddb97a908a1cc349f9b6410b.tar.lz yuzu-9268f265a1207f0cddb97a908a1cc349f9b6410b.tar.xz yuzu-9268f265a1207f0cddb97a908a1cc349f9b6410b.tar.zst yuzu-9268f265a1207f0cddb97a908a1cc349f9b6410b.zip |
Diffstat (limited to 'src/core/hle/kernel/svc')
-rw-r--r-- | src/core/hle/kernel/svc/svc_light_ipc.cpp | 29 | ||||
-rw-r--r-- | src/core/hle/kernel/svc/svc_port.cpp | 71 | ||||
-rw-r--r-- | src/core/hle/kernel/svc/svc_session.cpp | 40 |
3 files changed, 124 insertions, 16 deletions
diff --git a/src/core/hle/kernel/svc/svc_light_ipc.cpp b/src/core/hle/kernel/svc/svc_light_ipc.cpp index d757d5af2..4772cbda1 100644 --- a/src/core/hle/kernel/svc/svc_light_ipc.cpp +++ b/src/core/hle/kernel/svc/svc_light_ipc.cpp @@ -1,21 +1,40 @@ // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later -#include "core/arm/arm_interface.h" #include "core/core.h" +#include "core/hle/kernel/k_light_client_session.h" +#include "core/hle/kernel/k_light_server_session.h" +#include "core/hle/kernel/k_process.h" +#include "core/hle/kernel/k_thread.h" #include "core/hle/kernel/svc.h" #include "core/hle/kernel/svc_results.h" namespace Kernel::Svc { Result SendSyncRequestLight(Core::System& system, Handle session_handle, u32* args) { - UNIMPLEMENTED(); - R_THROW(ResultNotImplemented); + // Get the light client session from its handle. + KScopedAutoObject session = GetCurrentProcess(system.Kernel()) + .GetHandleTable() + .GetObject<KLightClientSession>(session_handle); + R_UNLESS(session.IsNotNull(), ResultInvalidHandle); + + // Send the request. + R_TRY(session->SendSyncRequest(args)); + + R_SUCCEED(); } Result ReplyAndReceiveLight(Core::System& system, Handle session_handle, u32* args) { - UNIMPLEMENTED(); - R_THROW(ResultNotImplemented); + // Get the light server session from its handle. + KScopedAutoObject session = GetCurrentProcess(system.Kernel()) + .GetHandleTable() + .GetObject<KLightServerSession>(session_handle); + R_UNLESS(session.IsNotNull(), ResultInvalidHandle); + + // Handle the request. + R_TRY(session->ReplyAndReceive(args)); + + R_SUCCEED(); } Result SendSyncRequestLight64(Core::System& system, Handle session_handle, u32* args) { diff --git a/src/core/hle/kernel/svc/svc_port.cpp b/src/core/hle/kernel/svc/svc_port.cpp index abba757c7..737749f7d 100644 --- a/src/core/hle/kernel/svc/svc_port.cpp +++ b/src/core/hle/kernel/svc/svc_port.cpp @@ -5,6 +5,7 @@ #include "core/core.h" #include "core/hle/kernel/k_client_port.h" #include "core/hle/kernel/k_client_session.h" +#include "core/hle/kernel/k_light_client_session.h" #include "core/hle/kernel/k_object_name.h" #include "core/hle/kernel/k_port.h" #include "core/hle/kernel/k_process.h" @@ -51,13 +52,73 @@ Result ConnectToNamedPort(Core::System& system, Handle* out, u64 user_name) { Result CreatePort(Core::System& system, Handle* out_server, Handle* out_client, int32_t max_sessions, bool is_light, uint64_t name) { - UNIMPLEMENTED(); - R_THROW(ResultNotImplemented); + auto& kernel = system.Kernel(); + + // Ensure max sessions is valid. + R_UNLESS(max_sessions > 0, ResultOutOfRange); + + // Get the current handle table. + auto& handle_table = GetCurrentProcess(kernel).GetHandleTable(); + + // Create a new port. + KPort* port = KPort::Create(kernel); + R_UNLESS(port != nullptr, ResultOutOfResource); + + // Initialize the port. + port->Initialize(max_sessions, is_light, name); + + // Ensure that we clean up the port (and its only references are handle table) on function end. + SCOPE_EXIT({ + port->GetServerPort().Close(); + port->GetClientPort().Close(); + }); + + // Register the port. + KPort::Register(kernel, port); + + // Add the client to the handle table. + R_TRY(handle_table.Add(out_client, std::addressof(port->GetClientPort()))); + + // Ensure that we maintain a clean handle state on exit. + ON_RESULT_FAILURE { + handle_table.Remove(*out_client); + }; + + // Add the server to the handle table. + R_RETURN(handle_table.Add(out_server, std::addressof(port->GetServerPort()))); } -Result ConnectToPort(Core::System& system, Handle* out_handle, Handle port) { - UNIMPLEMENTED(); - R_THROW(ResultNotImplemented); +Result ConnectToPort(Core::System& system, Handle* out, Handle port) { + // Get the current handle table. + auto& handle_table = GetCurrentProcess(system.Kernel()).GetHandleTable(); + + // Get the client port. + KScopedAutoObject client_port = handle_table.GetObject<KClientPort>(port); + R_UNLESS(client_port.IsNotNull(), ResultInvalidHandle); + + // Reserve a handle for the port. + // NOTE: Nintendo really does write directly to the output handle here. + R_TRY(handle_table.Reserve(out)); + ON_RESULT_FAILURE { + handle_table.Unreserve(*out); + }; + + // Create the session. + KAutoObject* session; + if (client_port->IsLight()) { + R_TRY(client_port->CreateLightSession( + reinterpret_cast<KLightClientSession**>(std::addressof(session)))); + } else { + R_TRY(client_port->CreateSession( + reinterpret_cast<KClientSession**>(std::addressof(session)))); + } + + // Register the session. + handle_table.Register(*out, session); + session->Close(); + + // We succeeded. + R_SUCCEED(); } Result ManageNamedPort(Core::System& system, Handle* out_server_handle, uint64_t user_name, diff --git a/src/core/hle/kernel/svc/svc_session.cpp b/src/core/hle/kernel/svc/svc_session.cpp index 01b8a52ad..2f5905f32 100644 --- a/src/core/hle/kernel/svc/svc_session.cpp +++ b/src/core/hle/kernel/svc/svc_session.cpp @@ -3,8 +3,10 @@ #include "common/scope_exit.h" #include "core/core.h" +#include "core/hle/kernel/k_light_session.h" #include "core/hle/kernel/k_process.h" #include "core/hle/kernel/k_scoped_resource_reservation.h" +#include "core/hle/kernel/k_server_port.h" #include "core/hle/kernel/k_session.h" #include "core/hle/kernel/svc.h" @@ -20,7 +22,7 @@ Result CreateSession(Core::System& system, Handle* out_server, Handle* out_clien T* session; // Reserve a new session from the process resource limit. - // FIXME: LimitableResource_SessionCountMax + // TODO: Dynamic resource limits KScopedResourceReservation session_reservation(std::addressof(process), LimitableResource::SessionCountMax); if (session_reservation.Succeeded()) { @@ -92,16 +94,42 @@ Result CreateSession(Core::System& system, Handle* out_server, Handle* out_clien Result CreateSession(Core::System& system, Handle* out_server, Handle* out_client, bool is_light, u64 name) { if (is_light) { - // return CreateSession<KLightSession>(system, out_server, out_client, name); - R_THROW(ResultNotImplemented); + R_RETURN(CreateSession<KLightSession>(system, out_server, out_client, name)); } else { R_RETURN(CreateSession<KSession>(system, out_server, out_client, name)); } } -Result AcceptSession(Core::System& system, Handle* out_handle, Handle port_handle) { - UNIMPLEMENTED(); - R_THROW(ResultNotImplemented); +Result AcceptSession(Core::System& system, Handle* out, Handle port_handle) { + // Get the current handle table. + auto& handle_table = GetCurrentProcess(system.Kernel()).GetHandleTable(); + + // Get the server port. + KScopedAutoObject port = handle_table.GetObject<KServerPort>(port_handle); + R_UNLESS(port.IsNotNull(), ResultInvalidHandle); + + // Reserve an entry for the new session. + R_TRY(handle_table.Reserve(out)); + ON_RESULT_FAILURE { + handle_table.Unreserve(*out); + }; + + // Accept the session. + KAutoObject* session; + if (port->IsLight()) { + session = port->AcceptLightSession(); + } else { + session = port->AcceptSession(); + } + + // Ensure we accepted successfully. + R_UNLESS(session != nullptr, ResultNotFound); + + // Register the session. + handle_table.Register(*out, session); + session->Close(); + + R_SUCCEED(); } Result CreateSession64(Core::System& system, Handle* out_server_session_handle, |