diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/core/hle/kernel/k_client_session.cpp | 24 | ||||
| -rw-r--r-- | src/core/hle/kernel/k_client_session.h | 18 | ||||
| -rw-r--r-- | src/core/hle/kernel/k_server_session.cpp | 5 | ||||
| -rw-r--r-- | src/core/hle/kernel/k_session.h | 4 | ||||
| -rw-r--r-- | src/core/hle/kernel/svc/svc_ipc.cpp | 296 | ||||
| -rw-r--r-- | src/core/hle/service/sm/sm.cpp | 2 |
6 files changed, 244 insertions, 105 deletions
diff --git a/src/core/hle/kernel/k_client_session.cpp b/src/core/hle/kernel/k_client_session.cpp index 72b66270d..472e8571c 100644 --- a/src/core/hle/kernel/k_client_session.cpp +++ b/src/core/hle/kernel/k_client_session.cpp | |||
| @@ -10,9 +10,7 @@ | |||
| 10 | 10 | ||
| 11 | namespace Kernel { | 11 | namespace Kernel { |
| 12 | 12 | ||
| 13 | static constexpr u32 MessageBufferSize = 0x100; | 13 | KClientSession::KClientSession(KernelCore& kernel) : KAutoObject{kernel} {} |
| 14 | |||
| 15 | KClientSession::KClientSession(KernelCore& kernel) : KAutoObjectWithSlabHeapAndContainer{kernel} {} | ||
| 16 | KClientSession::~KClientSession() = default; | 14 | KClientSession::~KClientSession() = default; |
| 17 | 15 | ||
| 18 | void KClientSession::Destroy() { | 16 | void KClientSession::Destroy() { |
| @@ -22,18 +20,30 @@ void KClientSession::Destroy() { | |||
| 22 | 20 | ||
| 23 | void KClientSession::OnServerClosed() {} | 21 | void KClientSession::OnServerClosed() {} |
| 24 | 22 | ||
| 25 | Result KClientSession::SendSyncRequest() { | 23 | Result KClientSession::SendSyncRequest(uintptr_t address, size_t size) { |
| 24 | // Create a session request. | ||
| 25 | KSessionRequest* request = KSessionRequest::Create(m_kernel); | ||
| 26 | R_UNLESS(request != nullptr, ResultOutOfResource); | ||
| 27 | SCOPE_EXIT({ request->Close(); }); | ||
| 28 | |||
| 29 | // Initialize the request. | ||
| 30 | request->Initialize(nullptr, address, size); | ||
| 31 | |||
| 32 | // Send the request. | ||
| 33 | R_RETURN(m_parent->OnRequest(request)); | ||
| 34 | } | ||
| 35 | |||
| 36 | Result KClientSession::SendAsyncRequest(KEvent* event, uintptr_t address, size_t size) { | ||
| 26 | // Create a session request. | 37 | // Create a session request. |
| 27 | KSessionRequest* request = KSessionRequest::Create(m_kernel); | 38 | KSessionRequest* request = KSessionRequest::Create(m_kernel); |
| 28 | R_UNLESS(request != nullptr, ResultOutOfResource); | 39 | R_UNLESS(request != nullptr, ResultOutOfResource); |
| 29 | SCOPE_EXIT({ request->Close(); }); | 40 | SCOPE_EXIT({ request->Close(); }); |
| 30 | 41 | ||
| 31 | // Initialize the request. | 42 | // Initialize the request. |
| 32 | request->Initialize(nullptr, GetInteger(GetCurrentThread(m_kernel).GetTlsAddress()), | 43 | request->Initialize(event, address, size); |
| 33 | MessageBufferSize); | ||
| 34 | 44 | ||
| 35 | // Send the request. | 45 | // Send the request. |
| 36 | R_RETURN(m_parent->GetServerSession().OnRequest(request)); | 46 | R_RETURN(m_parent->OnRequest(request)); |
| 37 | } | 47 | } |
| 38 | 48 | ||
| 39 | } // namespace Kernel | 49 | } // namespace Kernel |
diff --git a/src/core/hle/kernel/k_client_session.h b/src/core/hle/kernel/k_client_session.h index 9b62e55e4..a39213e17 100644 --- a/src/core/hle/kernel/k_client_session.h +++ b/src/core/hle/kernel/k_client_session.h | |||
| @@ -9,24 +9,12 @@ | |||
| 9 | #include "core/hle/kernel/slab_helpers.h" | 9 | #include "core/hle/kernel/slab_helpers.h" |
| 10 | #include "core/hle/result.h" | 10 | #include "core/hle/result.h" |
| 11 | 11 | ||
| 12 | union Result; | ||
| 13 | |||
| 14 | namespace Core::Memory { | ||
| 15 | class Memory; | ||
| 16 | } | ||
| 17 | |||
| 18 | namespace Core::Timing { | ||
| 19 | class CoreTiming; | ||
| 20 | } | ||
| 21 | |||
| 22 | namespace Kernel { | 12 | namespace Kernel { |
| 23 | 13 | ||
| 24 | class KernelCore; | 14 | class KernelCore; |
| 25 | class KSession; | 15 | class KSession; |
| 26 | class KThread; | ||
| 27 | 16 | ||
| 28 | class KClientSession final | 17 | class KClientSession final : public KAutoObject { |
| 29 | : public KAutoObjectWithSlabHeapAndContainer<KClientSession, KAutoObjectWithList> { | ||
| 30 | KERNEL_AUTOOBJECT_TRAITS(KClientSession, KAutoObject); | 18 | KERNEL_AUTOOBJECT_TRAITS(KClientSession, KAutoObject); |
| 31 | 19 | ||
| 32 | public: | 20 | public: |
| @@ -39,13 +27,13 @@ public: | |||
| 39 | } | 27 | } |
| 40 | 28 | ||
| 41 | void Destroy() override; | 29 | void Destroy() override; |
| 42 | static void PostDestroy(uintptr_t arg) {} | ||
| 43 | 30 | ||
| 44 | KSession* GetParent() const { | 31 | KSession* GetParent() const { |
| 45 | return m_parent; | 32 | return m_parent; |
| 46 | } | 33 | } |
| 47 | 34 | ||
| 48 | Result SendSyncRequest(); | 35 | Result SendSyncRequest(uintptr_t address, size_t size); |
| 36 | Result SendAsyncRequest(KEvent* event, uintptr_t address, size_t size); | ||
| 49 | 37 | ||
| 50 | void OnServerClosed(); | 38 | void OnServerClosed(); |
| 51 | 39 | ||
diff --git a/src/core/hle/kernel/k_server_session.cpp b/src/core/hle/kernel/k_server_session.cpp index 3ea653163..ec6812d5a 100644 --- a/src/core/hle/kernel/k_server_session.cpp +++ b/src/core/hle/kernel/k_server_session.cpp | |||
| @@ -453,6 +453,11 @@ Result KServerSession::ReceiveRequest(std::shared_ptr<Service::HLERequestContext | |||
| 453 | size_t client_buffer_size = request->GetSize(); | 453 | size_t client_buffer_size = request->GetSize(); |
| 454 | // bool recv_list_broken = false; | 454 | // bool recv_list_broken = false; |
| 455 | 455 | ||
| 456 | if (!client_message) { | ||
| 457 | client_message = GetInteger(client_thread->GetTlsAddress()); | ||
| 458 | client_buffer_size = MessageBufferSize; | ||
| 459 | } | ||
| 460 | |||
| 456 | // Receive the message. | 461 | // Receive the message. |
| 457 | Core::Memory::Memory& memory{client_thread->GetOwnerProcess()->GetMemory()}; | 462 | Core::Memory::Memory& memory{client_thread->GetOwnerProcess()->GetMemory()}; |
| 458 | if (out_context != nullptr) { | 463 | if (out_context != nullptr) { |
diff --git a/src/core/hle/kernel/k_session.h b/src/core/hle/kernel/k_session.h index f69bab088..3f4dd5989 100644 --- a/src/core/hle/kernel/k_session.h +++ b/src/core/hle/kernel/k_session.h | |||
| @@ -46,6 +46,10 @@ public: | |||
| 46 | return this->GetState() != State::Normal; | 46 | return this->GetState() != State::Normal; |
| 47 | } | 47 | } |
| 48 | 48 | ||
| 49 | Result OnRequest(KSessionRequest* request) { | ||
| 50 | R_RETURN(m_server.OnRequest(request)); | ||
| 51 | } | ||
| 52 | |||
| 49 | KClientSession& GetClientSession() { | 53 | KClientSession& GetClientSession() { |
| 50 | return m_client; | 54 | return m_client; |
| 51 | } | 55 | } |
diff --git a/src/core/hle/kernel/svc/svc_ipc.cpp b/src/core/hle/kernel/svc/svc_ipc.cpp index 6b5e1cb8d..47a3e7bb0 100644 --- a/src/core/hle/kernel/svc/svc_ipc.cpp +++ b/src/core/hle/kernel/svc/svc_ipc.cpp | |||
| @@ -7,59 +7,127 @@ | |||
| 7 | #include "core/hle/kernel/k_client_session.h" | 7 | #include "core/hle/kernel/k_client_session.h" |
| 8 | #include "core/hle/kernel/k_hardware_timer.h" | 8 | #include "core/hle/kernel/k_hardware_timer.h" |
| 9 | #include "core/hle/kernel/k_process.h" | 9 | #include "core/hle/kernel/k_process.h" |
| 10 | #include "core/hle/kernel/k_scoped_resource_reservation.h" | ||
| 10 | #include "core/hle/kernel/k_server_session.h" | 11 | #include "core/hle/kernel/k_server_session.h" |
| 12 | #include "core/hle/kernel/k_session.h" | ||
| 11 | #include "core/hle/kernel/svc.h" | 13 | #include "core/hle/kernel/svc.h" |
| 12 | #include "core/hle/kernel/svc_results.h" | 14 | #include "core/hle/kernel/svc_results.h" |
| 13 | 15 | ||
| 14 | namespace Kernel::Svc { | 16 | namespace Kernel::Svc { |
| 15 | 17 | ||
| 16 | /// Makes a blocking IPC call to a service. | 18 | namespace { |
| 17 | Result SendSyncRequest(Core::System& system, Handle handle) { | 19 | |
| 18 | // Get the client session from its handle. | 20 | Result SendSyncRequestImpl(KernelCore& kernel, uintptr_t message, size_t buffer_size, |
| 21 | Handle session_handle) { | ||
| 22 | // Get the client session. | ||
| 19 | KScopedAutoObject session = | 23 | KScopedAutoObject session = |
| 20 | GetCurrentProcess(system.Kernel()).GetHandleTable().GetObject<KClientSession>(handle); | 24 | GetCurrentProcess(kernel).GetHandleTable().GetObject<KClientSession>(session_handle); |
| 21 | R_UNLESS(session.IsNotNull(), ResultInvalidHandle); | 25 | R_UNLESS(session.IsNotNull(), ResultInvalidHandle); |
| 22 | 26 | ||
| 23 | LOG_TRACE(Kernel_SVC, "called handle=0x{:08X}", handle); | 27 | // Get the parent, and persist a reference to it until we're done. |
| 28 | KScopedAutoObject parent = session->GetParent(); | ||
| 29 | ASSERT(parent.IsNotNull()); | ||
| 24 | 30 | ||
| 25 | R_RETURN(session->SendSyncRequest()); | 31 | // Send the request. |
| 32 | R_RETURN(session->SendSyncRequest(message, buffer_size)); | ||
| 26 | } | 33 | } |
| 27 | 34 | ||
| 28 | Result SendSyncRequestWithUserBuffer(Core::System& system, uint64_t message_buffer, | 35 | Result ReplyAndReceiveImpl(KernelCore& kernel, int32_t* out_index, uintptr_t message, |
| 29 | uint64_t message_buffer_size, Handle session_handle) { | 36 | size_t buffer_size, KPhysicalAddress message_paddr, |
| 30 | UNIMPLEMENTED(); | 37 | KSynchronizationObject** objs, int32_t num_objects, Handle reply_target, |
| 31 | R_THROW(ResultNotImplemented); | 38 | int64_t timeout_ns) { |
| 32 | } | 39 | // Reply to the target, if one is specified. |
| 40 | if (reply_target != InvalidHandle) { | ||
| 41 | KScopedAutoObject session = | ||
| 42 | GetCurrentProcess(kernel).GetHandleTable().GetObject<KServerSession>(reply_target); | ||
| 43 | R_UNLESS(session.IsNotNull(), ResultInvalidHandle); | ||
| 33 | 44 | ||
| 34 | Result SendAsyncRequestWithUserBuffer(Core::System& system, Handle* out_event_handle, | 45 | // If we fail to reply, we want to set the output index to -1. |
| 35 | uint64_t message_buffer, uint64_t message_buffer_size, | 46 | ON_RESULT_FAILURE { |
| 36 | Handle session_handle) { | 47 | *out_index = -1; |
| 37 | UNIMPLEMENTED(); | 48 | }; |
| 38 | R_THROW(ResultNotImplemented); | 49 | |
| 50 | // Send the reply. | ||
| 51 | R_TRY(session->SendReply()); | ||
| 52 | // R_TRY(session->SendReply(message, buffer_size, message_paddr)); | ||
| 53 | } | ||
| 54 | |||
| 55 | // Receive a message. | ||
| 56 | { | ||
| 57 | // Convert the timeout from nanoseconds to ticks. | ||
| 58 | // NOTE: Nintendo does not use this conversion logic in WaitSynchronization... | ||
| 59 | s64 timeout; | ||
| 60 | if (timeout_ns > 0) { | ||
| 61 | const s64 offset_tick(timeout_ns); | ||
| 62 | if (offset_tick > 0) { | ||
| 63 | timeout = kernel.HardwareTimer().GetTick() + offset_tick + 2; | ||
| 64 | if (timeout <= 0) { | ||
| 65 | timeout = std::numeric_limits<s64>::max(); | ||
| 66 | } | ||
| 67 | } else { | ||
| 68 | timeout = std::numeric_limits<s64>::max(); | ||
| 69 | } | ||
| 70 | } else { | ||
| 71 | timeout = timeout_ns; | ||
| 72 | } | ||
| 73 | |||
| 74 | // Wait for a message. | ||
| 75 | while (true) { | ||
| 76 | // Wait for an object. | ||
| 77 | s32 index; | ||
| 78 | Result result = KSynchronizationObject::Wait(kernel, std::addressof(index), objs, | ||
| 79 | num_objects, timeout); | ||
| 80 | if (ResultTimedOut == result) { | ||
| 81 | R_THROW(result); | ||
| 82 | } | ||
| 83 | |||
| 84 | // Receive the request. | ||
| 85 | if (R_SUCCEEDED(result)) { | ||
| 86 | KServerSession* session = objs[index]->DynamicCast<KServerSession*>(); | ||
| 87 | if (session != nullptr) { | ||
| 88 | // result = session->ReceiveRequest(message, buffer_size, message_paddr); | ||
| 89 | result = session->ReceiveRequest(); | ||
| 90 | if (ResultNotFound == result) { | ||
| 91 | continue; | ||
| 92 | } | ||
| 93 | } | ||
| 94 | } | ||
| 95 | |||
| 96 | *out_index = index; | ||
| 97 | R_RETURN(result); | ||
| 98 | } | ||
| 99 | } | ||
| 39 | } | 100 | } |
| 40 | 101 | ||
| 41 | Result ReplyAndReceive(Core::System& system, s32* out_index, uint64_t handles_addr, s32 num_handles, | 102 | Result ReplyAndReceiveImpl(KernelCore& kernel, int32_t* out_index, uintptr_t message, |
| 42 | Handle reply_target, s64 timeout_ns) { | 103 | size_t buffer_size, KPhysicalAddress message_paddr, |
| 104 | KProcessAddress user_handles, int32_t num_handles, Handle reply_target, | ||
| 105 | int64_t timeout_ns) { | ||
| 43 | // Ensure number of handles is valid. | 106 | // Ensure number of handles is valid. |
| 44 | R_UNLESS(0 <= num_handles && num_handles <= ArgumentHandleCountMax, ResultOutOfRange); | 107 | R_UNLESS(0 <= num_handles && num_handles <= Svc::ArgumentHandleCountMax, ResultOutOfRange); |
| 45 | 108 | ||
| 46 | // Get the synchronization context. | 109 | // Get the synchronization context. |
| 47 | auto& kernel = system.Kernel(); | 110 | auto& process = GetCurrentProcess(kernel); |
| 48 | auto& handle_table = GetCurrentProcess(kernel).GetHandleTable(); | 111 | auto& thread = GetCurrentThread(kernel); |
| 49 | auto objs = GetCurrentThread(kernel).GetSynchronizationObjectBuffer(); | 112 | auto& handle_table = process.GetHandleTable(); |
| 50 | auto handles = GetCurrentThread(kernel).GetHandleBuffer(); | 113 | KSynchronizationObject** objs = thread.GetSynchronizationObjectBuffer().data(); |
| 114 | Handle* handles = thread.GetHandleBuffer().data(); | ||
| 51 | 115 | ||
| 52 | // Copy user handles. | 116 | // Copy user handles. |
| 53 | if (num_handles > 0) { | 117 | if (num_handles > 0) { |
| 54 | // Get the handles. | 118 | // Ensure that we can try to get the handles. |
| 55 | R_UNLESS(GetCurrentMemory(kernel).ReadBlock(handles_addr, handles.data(), | 119 | R_UNLESS(process.GetPageTable().Contains(user_handles, num_handles * sizeof(Handle)), |
| 56 | sizeof(Handle) * num_handles), | ||
| 57 | ResultInvalidPointer); | 120 | ResultInvalidPointer); |
| 58 | 121 | ||
| 122 | // Get the handles | ||
| 123 | R_UNLESS( | ||
| 124 | GetCurrentMemory(kernel).ReadBlock(user_handles, handles, sizeof(Handle) * num_handles), | ||
| 125 | ResultInvalidPointer); | ||
| 126 | |||
| 59 | // Convert the handles to objects. | 127 | // Convert the handles to objects. |
| 60 | R_UNLESS(handle_table.GetMultipleObjects<KSynchronizationObject>( | 128 | R_UNLESS( |
| 61 | objs.data(), handles.data(), num_handles), | 129 | handle_table.GetMultipleObjects<KSynchronizationObject>(objs, handles, num_handles), |
| 62 | ResultInvalidHandle); | 130 | ResultInvalidHandle); |
| 63 | } | 131 | } |
| 64 | 132 | ||
| 65 | // Ensure handles are closed when we're done. | 133 | // Ensure handles are closed when we're done. |
| @@ -69,69 +137,135 @@ Result ReplyAndReceive(Core::System& system, s32* out_index, uint64_t handles_ad | |||
| 69 | } | 137 | } |
| 70 | }); | 138 | }); |
| 71 | 139 | ||
| 72 | // Reply to the target, if one is specified. | 140 | R_RETURN(ReplyAndReceiveImpl(kernel, out_index, message, buffer_size, message_paddr, objs, |
| 73 | if (reply_target != InvalidHandle) { | 141 | num_handles, reply_target, timeout_ns)); |
| 74 | KScopedAutoObject session = handle_table.GetObject<KServerSession>(reply_target); | 142 | } |
| 75 | R_UNLESS(session.IsNotNull(), ResultInvalidHandle); | ||
| 76 | 143 | ||
| 77 | // If we fail to reply, we want to set the output index to -1. | 144 | } // namespace |
| 145 | |||
| 146 | /// Makes a blocking IPC call to a service. | ||
| 147 | Result SendSyncRequest(Core::System& system, Handle session_handle) { | ||
| 148 | R_RETURN(SendSyncRequestImpl(system.Kernel(), 0, 0, session_handle)); | ||
| 149 | } | ||
| 150 | |||
| 151 | Result SendSyncRequestWithUserBuffer(Core::System& system, uint64_t message, uint64_t buffer_size, | ||
| 152 | Handle session_handle) { | ||
| 153 | auto& kernel = system.Kernel(); | ||
| 154 | |||
| 155 | // Validate that the message buffer is page aligned and does not overflow. | ||
| 156 | R_UNLESS(Common::IsAligned(message, PageSize), ResultInvalidAddress); | ||
| 157 | R_UNLESS(buffer_size > 0, ResultInvalidSize); | ||
| 158 | R_UNLESS(Common::IsAligned(buffer_size, PageSize), ResultInvalidSize); | ||
| 159 | R_UNLESS(message < message + buffer_size, ResultInvalidCurrentMemory); | ||
| 160 | |||
| 161 | // Get the process page table. | ||
| 162 | auto& page_table = GetCurrentProcess(kernel).GetPageTable(); | ||
| 163 | |||
| 164 | // Lock the message buffer. | ||
| 165 | R_TRY(page_table.LockForIpcUserBuffer(nullptr, message, buffer_size)); | ||
| 166 | |||
| 167 | { | ||
| 168 | // If we fail to send the message, unlock the message buffer. | ||
| 78 | ON_RESULT_FAILURE { | 169 | ON_RESULT_FAILURE { |
| 79 | *out_index = -1; | 170 | page_table.UnlockForIpcUserBuffer(message, buffer_size); |
| 80 | }; | 171 | }; |
| 81 | 172 | ||
| 82 | // Send the reply. | 173 | // Send the request. |
| 83 | R_TRY(session->SendReply()); | 174 | ASSERT(message != 0); |
| 175 | R_TRY(SendSyncRequestImpl(kernel, message, buffer_size, session_handle)); | ||
| 84 | } | 176 | } |
| 85 | 177 | ||
| 86 | // Convert the timeout from nanoseconds to ticks. | 178 | // We successfully processed, so try to unlock the message buffer. |
| 87 | // NOTE: Nintendo does not use this conversion logic in WaitSynchronization... | 179 | R_RETURN(page_table.UnlockForIpcUserBuffer(message, buffer_size)); |
| 88 | s64 timeout; | 180 | } |
| 89 | if (timeout_ns > 0) { | ||
| 90 | const s64 offset_tick(timeout_ns); | ||
| 91 | if (offset_tick > 0) { | ||
| 92 | timeout = kernel.HardwareTimer().GetTick() + offset_tick + 2; | ||
| 93 | if (timeout <= 0) { | ||
| 94 | timeout = std::numeric_limits<s64>::max(); | ||
| 95 | } | ||
| 96 | } else { | ||
| 97 | timeout = std::numeric_limits<s64>::max(); | ||
| 98 | } | ||
| 99 | } else { | ||
| 100 | timeout = timeout_ns; | ||
| 101 | } | ||
| 102 | 181 | ||
| 103 | // Wait for a message. | 182 | Result SendAsyncRequestWithUserBuffer(Core::System& system, Handle* out_event_handle, |
| 104 | while (true) { | 183 | uint64_t message, uint64_t buffer_size, |
| 105 | // Wait for an object. | 184 | Handle session_handle) { |
| 106 | s32 index; | 185 | // Get the process and handle table. |
| 107 | Result result = KSynchronizationObject::Wait(kernel, std::addressof(index), objs.data(), | 186 | auto& process = GetCurrentProcess(system.Kernel()); |
| 108 | num_handles, timeout); | 187 | auto& handle_table = process.GetHandleTable(); |
| 109 | if (result == ResultTimedOut) { | ||
| 110 | R_RETURN(result); | ||
| 111 | } | ||
| 112 | 188 | ||
| 113 | // Receive the request. | 189 | // Reserve a new event from the process resource limit. |
| 114 | if (R_SUCCEEDED(result)) { | 190 | KScopedResourceReservation event_reservation(std::addressof(process), |
| 115 | KServerSession* session = objs[index]->DynamicCast<KServerSession*>(); | 191 | Svc::LimitableResource::EventCountMax); |
| 116 | if (session != nullptr) { | 192 | R_UNLESS(event_reservation.Succeeded(), ResultLimitReached); |
| 117 | result = session->ReceiveRequest(); | ||
| 118 | if (result == ResultNotFound) { | ||
| 119 | continue; | ||
| 120 | } | ||
| 121 | } | ||
| 122 | } | ||
| 123 | 193 | ||
| 124 | *out_index = index; | 194 | // Get the client session. |
| 125 | R_RETURN(result); | 195 | KScopedAutoObject session = process.GetHandleTable().GetObject<KClientSession>(session_handle); |
| 126 | } | 196 | R_UNLESS(session.IsNotNull(), ResultInvalidHandle); |
| 197 | |||
| 198 | // Get the parent, and persist a reference to it until we're done. | ||
| 199 | KScopedAutoObject parent = session->GetParent(); | ||
| 200 | ASSERT(parent.IsNotNull()); | ||
| 201 | |||
| 202 | // Create a new event. | ||
| 203 | KEvent* event = KEvent::Create(system.Kernel()); | ||
| 204 | R_UNLESS(event != nullptr, ResultOutOfResource); | ||
| 205 | |||
| 206 | // Initialize the event. | ||
| 207 | event->Initialize(std::addressof(process)); | ||
| 208 | |||
| 209 | // Commit our reservation. | ||
| 210 | event_reservation.Commit(); | ||
| 211 | |||
| 212 | // At end of scope, kill the standing references to the sub events. | ||
| 213 | SCOPE_EXIT({ | ||
| 214 | event->GetReadableEvent().Close(); | ||
| 215 | event->Close(); | ||
| 216 | }); | ||
| 217 | |||
| 218 | // Register the event. | ||
| 219 | KEvent::Register(system.Kernel(), event); | ||
| 220 | |||
| 221 | // Add the readable event to the handle table. | ||
| 222 | R_TRY(handle_table.Add(out_event_handle, std::addressof(event->GetReadableEvent()))); | ||
| 223 | |||
| 224 | // Ensure that if we fail to send the request, we close the readable handle. | ||
| 225 | ON_RESULT_FAILURE { | ||
| 226 | handle_table.Remove(*out_event_handle); | ||
| 227 | }; | ||
| 228 | |||
| 229 | // Send the async request. | ||
| 230 | R_RETURN(session->SendAsyncRequest(event, message, buffer_size)); | ||
| 127 | } | 231 | } |
| 128 | 232 | ||
| 129 | Result ReplyAndReceiveWithUserBuffer(Core::System& system, int32_t* out_index, | 233 | Result ReplyAndReceive(Core::System& system, s32* out_index, uint64_t handles, s32 num_handles, |
| 130 | uint64_t message_buffer, uint64_t message_buffer_size, | 234 | Handle reply_target, s64 timeout_ns) { |
| 131 | uint64_t handles, int32_t num_handles, Handle reply_target, | 235 | R_RETURN(ReplyAndReceiveImpl(system.Kernel(), out_index, 0, 0, 0, handles, num_handles, |
| 132 | int64_t timeout_ns) { | 236 | reply_target, timeout_ns)); |
| 133 | UNIMPLEMENTED(); | 237 | } |
| 134 | R_THROW(ResultNotImplemented); | 238 | |
| 239 | Result ReplyAndReceiveWithUserBuffer(Core::System& system, int32_t* out_index, uint64_t message, | ||
| 240 | uint64_t buffer_size, uint64_t handles, int32_t num_handles, | ||
| 241 | Handle reply_target, int64_t timeout_ns) { | ||
| 242 | // Validate that the message buffer is page aligned and does not overflow. | ||
| 243 | R_UNLESS(Common::IsAligned(message, PageSize), ResultInvalidAddress); | ||
| 244 | R_UNLESS(buffer_size > 0, ResultInvalidSize); | ||
| 245 | R_UNLESS(Common::IsAligned(buffer_size, PageSize), ResultInvalidSize); | ||
| 246 | R_UNLESS(message < message + buffer_size, ResultInvalidCurrentMemory); | ||
| 247 | |||
| 248 | // Get the process page table. | ||
| 249 | auto& page_table = GetCurrentProcess(system.Kernel()).GetPageTable(); | ||
| 250 | |||
| 251 | // Lock the message buffer, getting its physical address. | ||
| 252 | KPhysicalAddress message_paddr; | ||
| 253 | R_TRY(page_table.LockForIpcUserBuffer(std::addressof(message_paddr), message, buffer_size)); | ||
| 254 | |||
| 255 | { | ||
| 256 | // If we fail to send the message, unlock the message buffer. | ||
| 257 | ON_RESULT_FAILURE { | ||
| 258 | page_table.UnlockForIpcUserBuffer(message, buffer_size); | ||
| 259 | }; | ||
| 260 | |||
| 261 | // Reply/Receive the request. | ||
| 262 | ASSERT(message != 0); | ||
| 263 | R_TRY(ReplyAndReceiveImpl(system.Kernel(), out_index, message, buffer_size, message_paddr, | ||
| 264 | handles, num_handles, reply_target, timeout_ns)); | ||
| 265 | } | ||
| 266 | |||
| 267 | // We successfully processed, so try to unlock the message buffer. | ||
| 268 | R_RETURN(page_table.UnlockForIpcUserBuffer(message, buffer_size)); | ||
| 135 | } | 269 | } |
| 136 | 270 | ||
| 137 | Result SendSyncRequest64(Core::System& system, Handle session_handle) { | 271 | Result SendSyncRequest64(Core::System& system, Handle session_handle) { |
diff --git a/src/core/hle/service/sm/sm.cpp b/src/core/hle/service/sm/sm.cpp index 9ab718e0a..e0cde9a05 100644 --- a/src/core/hle/service/sm/sm.cpp +++ b/src/core/hle/service/sm/sm.cpp | |||
| @@ -192,8 +192,6 @@ Result SM::GetServiceImpl(Kernel::KClientSession** out_client_session, HLEReques | |||
| 192 | return result; | 192 | return result; |
| 193 | } | 193 | } |
| 194 | 194 | ||
| 195 | LOG_DEBUG(Service_SM, "called service={} -> session={}", name, session->GetId()); | ||
| 196 | |||
| 197 | *out_client_session = session; | 195 | *out_client_session = session; |
| 198 | return ResultSuccess; | 196 | return ResultSuccess; |
| 199 | } | 197 | } |