diff options
| author | 2023-12-06 19:54:52 -0500 | |
|---|---|---|
| committer | 2023-12-07 09:13:43 -0500 | |
| commit | 9268f265a1207f0cddb97a908a1cc349f9b6410b (patch) | |
| tree | 5da6aea714523b3504b78362c5d8abd53689d72f /src/core/hle/kernel/svc | |
| parent | Merge pull request #12236 from liamwhite/cpu-refactor (diff) | |
| download | yuzu-9268f265a1207f0cddb97a908a1cc349f9b6410b.tar.gz yuzu-9268f265a1207f0cddb97a908a1cc349f9b6410b.tar.xz yuzu-9268f265a1207f0cddb97a908a1cc349f9b6410b.zip | |
kernel: implement light IPC
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 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project | 1 | // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project |
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | 2 | // SPDX-License-Identifier: GPL-2.0-or-later |
| 3 | 3 | ||
| 4 | #include "core/arm/arm_interface.h" | ||
| 5 | #include "core/core.h" | 4 | #include "core/core.h" |
| 5 | #include "core/hle/kernel/k_light_client_session.h" | ||
| 6 | #include "core/hle/kernel/k_light_server_session.h" | ||
| 7 | #include "core/hle/kernel/k_process.h" | ||
| 8 | #include "core/hle/kernel/k_thread.h" | ||
| 6 | #include "core/hle/kernel/svc.h" | 9 | #include "core/hle/kernel/svc.h" |
| 7 | #include "core/hle/kernel/svc_results.h" | 10 | #include "core/hle/kernel/svc_results.h" |
| 8 | 11 | ||
| 9 | namespace Kernel::Svc { | 12 | namespace Kernel::Svc { |
| 10 | 13 | ||
| 11 | Result SendSyncRequestLight(Core::System& system, Handle session_handle, u32* args) { | 14 | Result SendSyncRequestLight(Core::System& system, Handle session_handle, u32* args) { |
| 12 | UNIMPLEMENTED(); | 15 | // Get the light client session from its handle. |
| 13 | R_THROW(ResultNotImplemented); | 16 | KScopedAutoObject session = GetCurrentProcess(system.Kernel()) |
| 17 | .GetHandleTable() | ||
| 18 | .GetObject<KLightClientSession>(session_handle); | ||
| 19 | R_UNLESS(session.IsNotNull(), ResultInvalidHandle); | ||
| 20 | |||
| 21 | // Send the request. | ||
| 22 | R_TRY(session->SendSyncRequest(args)); | ||
| 23 | |||
| 24 | R_SUCCEED(); | ||
| 14 | } | 25 | } |
| 15 | 26 | ||
| 16 | Result ReplyAndReceiveLight(Core::System& system, Handle session_handle, u32* args) { | 27 | Result ReplyAndReceiveLight(Core::System& system, Handle session_handle, u32* args) { |
| 17 | UNIMPLEMENTED(); | 28 | // Get the light server session from its handle. |
| 18 | R_THROW(ResultNotImplemented); | 29 | KScopedAutoObject session = GetCurrentProcess(system.Kernel()) |
| 30 | .GetHandleTable() | ||
| 31 | .GetObject<KLightServerSession>(session_handle); | ||
| 32 | R_UNLESS(session.IsNotNull(), ResultInvalidHandle); | ||
| 33 | |||
| 34 | // Handle the request. | ||
| 35 | R_TRY(session->ReplyAndReceive(args)); | ||
| 36 | |||
| 37 | R_SUCCEED(); | ||
| 19 | } | 38 | } |
| 20 | 39 | ||
| 21 | Result SendSyncRequestLight64(Core::System& system, Handle session_handle, u32* args) { | 40 | 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 @@ | |||
| 5 | #include "core/core.h" | 5 | #include "core/core.h" |
| 6 | #include "core/hle/kernel/k_client_port.h" | 6 | #include "core/hle/kernel/k_client_port.h" |
| 7 | #include "core/hle/kernel/k_client_session.h" | 7 | #include "core/hle/kernel/k_client_session.h" |
| 8 | #include "core/hle/kernel/k_light_client_session.h" | ||
| 8 | #include "core/hle/kernel/k_object_name.h" | 9 | #include "core/hle/kernel/k_object_name.h" |
| 9 | #include "core/hle/kernel/k_port.h" | 10 | #include "core/hle/kernel/k_port.h" |
| 10 | #include "core/hle/kernel/k_process.h" | 11 | #include "core/hle/kernel/k_process.h" |
| @@ -51,13 +52,73 @@ Result ConnectToNamedPort(Core::System& system, Handle* out, u64 user_name) { | |||
| 51 | 52 | ||
| 52 | Result CreatePort(Core::System& system, Handle* out_server, Handle* out_client, | 53 | Result CreatePort(Core::System& system, Handle* out_server, Handle* out_client, |
| 53 | int32_t max_sessions, bool is_light, uint64_t name) { | 54 | int32_t max_sessions, bool is_light, uint64_t name) { |
| 54 | UNIMPLEMENTED(); | 55 | auto& kernel = system.Kernel(); |
| 55 | R_THROW(ResultNotImplemented); | 56 | |
| 57 | // Ensure max sessions is valid. | ||
| 58 | R_UNLESS(max_sessions > 0, ResultOutOfRange); | ||
| 59 | |||
| 60 | // Get the current handle table. | ||
| 61 | auto& handle_table = GetCurrentProcess(kernel).GetHandleTable(); | ||
| 62 | |||
| 63 | // Create a new port. | ||
| 64 | KPort* port = KPort::Create(kernel); | ||
| 65 | R_UNLESS(port != nullptr, ResultOutOfResource); | ||
| 66 | |||
| 67 | // Initialize the port. | ||
| 68 | port->Initialize(max_sessions, is_light, name); | ||
| 69 | |||
| 70 | // Ensure that we clean up the port (and its only references are handle table) on function end. | ||
| 71 | SCOPE_EXIT({ | ||
| 72 | port->GetServerPort().Close(); | ||
| 73 | port->GetClientPort().Close(); | ||
| 74 | }); | ||
| 75 | |||
| 76 | // Register the port. | ||
| 77 | KPort::Register(kernel, port); | ||
| 78 | |||
| 79 | // Add the client to the handle table. | ||
| 80 | R_TRY(handle_table.Add(out_client, std::addressof(port->GetClientPort()))); | ||
| 81 | |||
| 82 | // Ensure that we maintain a clean handle state on exit. | ||
| 83 | ON_RESULT_FAILURE { | ||
| 84 | handle_table.Remove(*out_client); | ||
| 85 | }; | ||
| 86 | |||
| 87 | // Add the server to the handle table. | ||
| 88 | R_RETURN(handle_table.Add(out_server, std::addressof(port->GetServerPort()))); | ||
| 56 | } | 89 | } |
| 57 | 90 | ||
| 58 | Result ConnectToPort(Core::System& system, Handle* out_handle, Handle port) { | 91 | Result ConnectToPort(Core::System& system, Handle* out, Handle port) { |
| 59 | UNIMPLEMENTED(); | 92 | // Get the current handle table. |
| 60 | R_THROW(ResultNotImplemented); | 93 | auto& handle_table = GetCurrentProcess(system.Kernel()).GetHandleTable(); |
| 94 | |||
| 95 | // Get the client port. | ||
| 96 | KScopedAutoObject client_port = handle_table.GetObject<KClientPort>(port); | ||
| 97 | R_UNLESS(client_port.IsNotNull(), ResultInvalidHandle); | ||
| 98 | |||
| 99 | // Reserve a handle for the port. | ||
| 100 | // NOTE: Nintendo really does write directly to the output handle here. | ||
| 101 | R_TRY(handle_table.Reserve(out)); | ||
| 102 | ON_RESULT_FAILURE { | ||
| 103 | handle_table.Unreserve(*out); | ||
| 104 | }; | ||
| 105 | |||
| 106 | // Create the session. | ||
| 107 | KAutoObject* session; | ||
| 108 | if (client_port->IsLight()) { | ||
| 109 | R_TRY(client_port->CreateLightSession( | ||
| 110 | reinterpret_cast<KLightClientSession**>(std::addressof(session)))); | ||
| 111 | } else { | ||
| 112 | R_TRY(client_port->CreateSession( | ||
| 113 | reinterpret_cast<KClientSession**>(std::addressof(session)))); | ||
| 114 | } | ||
| 115 | |||
| 116 | // Register the session. | ||
| 117 | handle_table.Register(*out, session); | ||
| 118 | session->Close(); | ||
| 119 | |||
| 120 | // We succeeded. | ||
| 121 | R_SUCCEED(); | ||
| 61 | } | 122 | } |
| 62 | 123 | ||
| 63 | Result ManageNamedPort(Core::System& system, Handle* out_server_handle, uint64_t user_name, | 124 | 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 @@ | |||
| 3 | 3 | ||
| 4 | #include "common/scope_exit.h" | 4 | #include "common/scope_exit.h" |
| 5 | #include "core/core.h" | 5 | #include "core/core.h" |
| 6 | #include "core/hle/kernel/k_light_session.h" | ||
| 6 | #include "core/hle/kernel/k_process.h" | 7 | #include "core/hle/kernel/k_process.h" |
| 7 | #include "core/hle/kernel/k_scoped_resource_reservation.h" | 8 | #include "core/hle/kernel/k_scoped_resource_reservation.h" |
| 9 | #include "core/hle/kernel/k_server_port.h" | ||
| 8 | #include "core/hle/kernel/k_session.h" | 10 | #include "core/hle/kernel/k_session.h" |
| 9 | #include "core/hle/kernel/svc.h" | 11 | #include "core/hle/kernel/svc.h" |
| 10 | 12 | ||
| @@ -20,7 +22,7 @@ Result CreateSession(Core::System& system, Handle* out_server, Handle* out_clien | |||
| 20 | T* session; | 22 | T* session; |
| 21 | 23 | ||
| 22 | // Reserve a new session from the process resource limit. | 24 | // Reserve a new session from the process resource limit. |
| 23 | // FIXME: LimitableResource_SessionCountMax | 25 | // TODO: Dynamic resource limits |
| 24 | KScopedResourceReservation session_reservation(std::addressof(process), | 26 | KScopedResourceReservation session_reservation(std::addressof(process), |
| 25 | LimitableResource::SessionCountMax); | 27 | LimitableResource::SessionCountMax); |
| 26 | if (session_reservation.Succeeded()) { | 28 | if (session_reservation.Succeeded()) { |
| @@ -92,16 +94,42 @@ Result CreateSession(Core::System& system, Handle* out_server, Handle* out_clien | |||
| 92 | Result CreateSession(Core::System& system, Handle* out_server, Handle* out_client, bool is_light, | 94 | Result CreateSession(Core::System& system, Handle* out_server, Handle* out_client, bool is_light, |
| 93 | u64 name) { | 95 | u64 name) { |
| 94 | if (is_light) { | 96 | if (is_light) { |
| 95 | // return CreateSession<KLightSession>(system, out_server, out_client, name); | 97 | R_RETURN(CreateSession<KLightSession>(system, out_server, out_client, name)); |
| 96 | R_THROW(ResultNotImplemented); | ||
| 97 | } else { | 98 | } else { |
| 98 | R_RETURN(CreateSession<KSession>(system, out_server, out_client, name)); | 99 | R_RETURN(CreateSession<KSession>(system, out_server, out_client, name)); |
| 99 | } | 100 | } |
| 100 | } | 101 | } |
| 101 | 102 | ||
| 102 | Result AcceptSession(Core::System& system, Handle* out_handle, Handle port_handle) { | 103 | Result AcceptSession(Core::System& system, Handle* out, Handle port_handle) { |
| 103 | UNIMPLEMENTED(); | 104 | // Get the current handle table. |
| 104 | R_THROW(ResultNotImplemented); | 105 | auto& handle_table = GetCurrentProcess(system.Kernel()).GetHandleTable(); |
| 106 | |||
| 107 | // Get the server port. | ||
| 108 | KScopedAutoObject port = handle_table.GetObject<KServerPort>(port_handle); | ||
| 109 | R_UNLESS(port.IsNotNull(), ResultInvalidHandle); | ||
| 110 | |||
| 111 | // Reserve an entry for the new session. | ||
| 112 | R_TRY(handle_table.Reserve(out)); | ||
| 113 | ON_RESULT_FAILURE { | ||
| 114 | handle_table.Unreserve(*out); | ||
| 115 | }; | ||
| 116 | |||
| 117 | // Accept the session. | ||
| 118 | KAutoObject* session; | ||
| 119 | if (port->IsLight()) { | ||
| 120 | session = port->AcceptLightSession(); | ||
| 121 | } else { | ||
| 122 | session = port->AcceptSession(); | ||
| 123 | } | ||
| 124 | |||
| 125 | // Ensure we accepted successfully. | ||
| 126 | R_UNLESS(session != nullptr, ResultNotFound); | ||
| 127 | |||
| 128 | // Register the session. | ||
| 129 | handle_table.Register(*out, session); | ||
| 130 | session->Close(); | ||
| 131 | |||
| 132 | R_SUCCEED(); | ||
| 105 | } | 133 | } |
| 106 | 134 | ||
| 107 | Result CreateSession64(Core::System& system, Handle* out_server_session_handle, | 135 | Result CreateSession64(Core::System& system, Handle* out_server_session_handle, |