summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/core/CMakeLists.txt2
-rw-r--r--src/core/hle/kernel/init/init_slab_setup.cpp2
-rw-r--r--src/core/hle/kernel/k_client_session.cpp15
-rw-r--r--src/core/hle/kernel/k_linked_list.h1
-rw-r--r--src/core/hle/kernel/k_page_buffer.h1
-rw-r--r--src/core/hle/kernel/k_server_session.cpp143
-rw-r--r--src/core/hle/kernel/k_server_session.h8
-rw-r--r--src/core/hle/kernel/k_session_request.cpp61
-rw-r--r--src/core/hle/kernel/k_session_request.h307
-rw-r--r--src/core/hle/kernel/k_shared_memory_info.h3
-rw-r--r--src/core/hle/kernel/k_thread_local_page.h2
-rw-r--r--src/core/hle/kernel/kernel.h4
-rw-r--r--src/core/hle/kernel/slab_helpers.h2
13 files changed, 489 insertions, 62 deletions
diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt
index e7fe675cb..055bea641 100644
--- a/src/core/CMakeLists.txt
+++ b/src/core/CMakeLists.txt
@@ -243,6 +243,8 @@ add_library(core STATIC
243 hle/kernel/k_server_session.h 243 hle/kernel/k_server_session.h
244 hle/kernel/k_session.cpp 244 hle/kernel/k_session.cpp
245 hle/kernel/k_session.h 245 hle/kernel/k_session.h
246 hle/kernel/k_session_request.cpp
247 hle/kernel/k_session_request.h
246 hle/kernel/k_shared_memory.cpp 248 hle/kernel/k_shared_memory.cpp
247 hle/kernel/k_shared_memory.h 249 hle/kernel/k_shared_memory.h
248 hle/kernel/k_shared_memory_info.h 250 hle/kernel/k_shared_memory_info.h
diff --git a/src/core/hle/kernel/init/init_slab_setup.cpp b/src/core/hle/kernel/init/init_slab_setup.cpp
index c84d36c8c..477e4e407 100644
--- a/src/core/hle/kernel/init/init_slab_setup.cpp
+++ b/src/core/hle/kernel/init/init_slab_setup.cpp
@@ -18,6 +18,7 @@
18#include "core/hle/kernel/k_process.h" 18#include "core/hle/kernel/k_process.h"
19#include "core/hle/kernel/k_resource_limit.h" 19#include "core/hle/kernel/k_resource_limit.h"
20#include "core/hle/kernel/k_session.h" 20#include "core/hle/kernel/k_session.h"
21#include "core/hle/kernel/k_session_request.h"
21#include "core/hle/kernel/k_shared_memory.h" 22#include "core/hle/kernel/k_shared_memory.h"
22#include "core/hle/kernel/k_shared_memory_info.h" 23#include "core/hle/kernel/k_shared_memory_info.h"
23#include "core/hle/kernel/k_system_control.h" 24#include "core/hle/kernel/k_system_control.h"
@@ -34,6 +35,7 @@ namespace Kernel::Init {
34 HANDLER(KThread, (SLAB_COUNT(KThread)), ##__VA_ARGS__) \ 35 HANDLER(KThread, (SLAB_COUNT(KThread)), ##__VA_ARGS__) \
35 HANDLER(KEvent, (SLAB_COUNT(KEvent)), ##__VA_ARGS__) \ 36 HANDLER(KEvent, (SLAB_COUNT(KEvent)), ##__VA_ARGS__) \
36 HANDLER(KPort, (SLAB_COUNT(KPort)), ##__VA_ARGS__) \ 37 HANDLER(KPort, (SLAB_COUNT(KPort)), ##__VA_ARGS__) \
38 HANDLER(KSessionRequest, (SLAB_COUNT(KSession) * 2), ##__VA_ARGS__) \
37 HANDLER(KSharedMemory, (SLAB_COUNT(KSharedMemory)), ##__VA_ARGS__) \ 39 HANDLER(KSharedMemory, (SLAB_COUNT(KSharedMemory)), ##__VA_ARGS__) \
38 HANDLER(KSharedMemoryInfo, (SLAB_COUNT(KSharedMemory) * 8), ##__VA_ARGS__) \ 40 HANDLER(KSharedMemoryInfo, (SLAB_COUNT(KSharedMemory) * 8), ##__VA_ARGS__) \
39 HANDLER(KTransferMemory, (SLAB_COUNT(KTransferMemory)), ##__VA_ARGS__) \ 41 HANDLER(KTransferMemory, (SLAB_COUNT(KTransferMemory)), ##__VA_ARGS__) \
diff --git a/src/core/hle/kernel/k_client_session.cpp b/src/core/hle/kernel/k_client_session.cpp
index 8892c5b7c..b4197a8d5 100644
--- a/src/core/hle/kernel/k_client_session.cpp
+++ b/src/core/hle/kernel/k_client_session.cpp
@@ -1,6 +1,7 @@
1// SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project 1// SPDX-FileCopyrightText: Copyright 2021 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 "common/scope_exit.h"
4#include "core/hle/kernel/hle_ipc.h" 5#include "core/hle/kernel/hle_ipc.h"
5#include "core/hle/kernel/k_client_session.h" 6#include "core/hle/kernel/k_client_session.h"
6#include "core/hle/kernel/k_server_session.h" 7#include "core/hle/kernel/k_server_session.h"
@@ -10,6 +11,8 @@
10 11
11namespace Kernel { 12namespace Kernel {
12 13
14static constexpr u32 MessageBufferSize = 0x100;
15
13KClientSession::KClientSession(KernelCore& kernel_) 16KClientSession::KClientSession(KernelCore& kernel_)
14 : KAutoObjectWithSlabHeapAndContainer{kernel_} {} 17 : KAutoObjectWithSlabHeapAndContainer{kernel_} {}
15KClientSession::~KClientSession() = default; 18KClientSession::~KClientSession() = default;
@@ -22,8 +25,16 @@ void KClientSession::Destroy() {
22void KClientSession::OnServerClosed() {} 25void KClientSession::OnServerClosed() {}
23 26
24Result KClientSession::SendSyncRequest() { 27Result KClientSession::SendSyncRequest() {
25 // Signal the server session that new data is available 28 // Create a session request.
26 return parent->GetServerSession().OnRequest(); 29 KSessionRequest* request = KSessionRequest::Create(kernel);
30 R_UNLESS(request != nullptr, ResultOutOfResource);
31 SCOPE_EXIT({ request->Close(); });
32
33 // Initialize the request.
34 request->Initialize(nullptr, GetCurrentThread(kernel).GetTLSAddress(), MessageBufferSize);
35
36 // Send the request.
37 return parent->GetServerSession().OnRequest(request);
27} 38}
28 39
29} // namespace Kernel 40} // namespace Kernel
diff --git a/src/core/hle/kernel/k_linked_list.h b/src/core/hle/kernel/k_linked_list.h
index 78859ced3..29ebd16b7 100644
--- a/src/core/hle/kernel/k_linked_list.h
+++ b/src/core/hle/kernel/k_linked_list.h
@@ -16,6 +16,7 @@ class KLinkedListNode : public boost::intrusive::list_base_hook<>,
16 public KSlabAllocated<KLinkedListNode> { 16 public KSlabAllocated<KLinkedListNode> {
17 17
18public: 18public:
19 explicit KLinkedListNode(KernelCore&) {}
19 KLinkedListNode() = default; 20 KLinkedListNode() = default;
20 21
21 void Initialize(void* it) { 22 void Initialize(void* it) {
diff --git a/src/core/hle/kernel/k_page_buffer.h b/src/core/hle/kernel/k_page_buffer.h
index 7e50dc1d1..aef06e213 100644
--- a/src/core/hle/kernel/k_page_buffer.h
+++ b/src/core/hle/kernel/k_page_buffer.h
@@ -13,6 +13,7 @@ namespace Kernel {
13 13
14class KPageBuffer final : public KSlabAllocated<KPageBuffer> { 14class KPageBuffer final : public KSlabAllocated<KPageBuffer> {
15public: 15public:
16 explicit KPageBuffer(KernelCore&) {}
16 KPageBuffer() = default; 17 KPageBuffer() = default;
17 18
18 static KPageBuffer* FromPhysicalAddress(Core::System& system, PAddr phys_addr); 19 static KPageBuffer* FromPhysicalAddress(Core::System& system, PAddr phys_addr);
diff --git a/src/core/hle/kernel/k_server_session.cpp b/src/core/hle/kernel/k_server_session.cpp
index 4252c9adb..685a2a6e6 100644
--- a/src/core/hle/kernel/k_server_session.cpp
+++ b/src/core/hle/kernel/k_server_session.cpp
@@ -29,8 +29,6 @@ namespace Kernel {
29 29
30using ThreadQueueImplForKServerSessionRequest = KThreadQueue; 30using ThreadQueueImplForKServerSessionRequest = KThreadQueue;
31 31
32static constexpr u32 MessageBufferSize = 0x100;
33
34KServerSession::KServerSession(KernelCore& kernel_) 32KServerSession::KServerSession(KernelCore& kernel_)
35 : KSynchronizationObject{kernel_}, m_lock{kernel_} {} 33 : KSynchronizationObject{kernel_}, m_lock{kernel_} {}
36 34
@@ -73,7 +71,7 @@ bool KServerSession::IsSignaled() const {
73 } 71 }
74 72
75 // Otherwise, we're signaled if we have a request and aren't handling one. 73 // Otherwise, we're signaled if we have a request and aren't handling one.
76 return !m_thread_request_list.empty() && m_current_thread_request == nullptr; 74 return !m_request_list.empty() && m_current_request == nullptr;
77} 75}
78 76
79void KServerSession::AppendDomainHandler(SessionRequestHandlerPtr handler) { 77void KServerSession::AppendDomainHandler(SessionRequestHandlerPtr handler) {
@@ -178,7 +176,7 @@ Result KServerSession::CompleteSyncRequest(HLERequestContext& context) {
178 return result; 176 return result;
179} 177}
180 178
181Result KServerSession::OnRequest() { 179Result KServerSession::OnRequest(KSessionRequest* request) {
182 // Create the wait queue. 180 // Create the wait queue.
183 ThreadQueueImplForKServerSessionRequest wait_queue{kernel}; 181 ThreadQueueImplForKServerSessionRequest wait_queue{kernel};
184 182
@@ -198,14 +196,13 @@ Result KServerSession::OnRequest() {
198 this->QueueSyncRequest(GetCurrentThreadPointer(kernel), memory); 196 this->QueueSyncRequest(GetCurrentThreadPointer(kernel), memory);
199 } else { 197 } else {
200 // Non-HLE request. 198 // Non-HLE request.
201 auto* thread{GetCurrentThreadPointer(kernel)};
202 199
203 // Get whether we're empty. 200 // Get whether we're empty.
204 const bool was_empty = m_thread_request_list.empty(); 201 const bool was_empty = m_request_list.empty();
205 202
206 // Add the thread to the list. 203 // Add the request to the list.
207 thread->Open(); 204 request->Open();
208 m_thread_request_list.push_back(thread); 205 m_request_list.push_back(*request);
209 206
210 // If we were empty, signal. 207 // If we were empty, signal.
211 if (was_empty) { 208 if (was_empty) {
@@ -213,6 +210,9 @@ Result KServerSession::OnRequest() {
213 } 210 }
214 } 211 }
215 212
213 // If we have a request event, this is asynchronous, and we don't need to wait.
214 R_SUCCEED_IF(request->GetEvent() != nullptr);
215
216 // This is a synchronous request, so we should wait for our request to complete. 216 // This is a synchronous request, so we should wait for our request to complete.
217 GetCurrentThread(kernel).SetWaitReasonForDebugging(ThreadWaitReasonForDebugging::IPC); 217 GetCurrentThread(kernel).SetWaitReasonForDebugging(ThreadWaitReasonForDebugging::IPC);
218 GetCurrentThread(kernel).BeginWait(&wait_queue); 218 GetCurrentThread(kernel).BeginWait(&wait_queue);
@@ -223,32 +223,32 @@ Result KServerSession::OnRequest() {
223 223
224Result KServerSession::SendReply() { 224Result KServerSession::SendReply() {
225 // Lock the session. 225 // Lock the session.
226 KScopedLightLock lk(m_lock); 226 KScopedLightLock lk{m_lock};
227 227
228 // Get the request. 228 // Get the request.
229 KThread* client_thread; 229 KSessionRequest* request;
230 { 230 {
231 KScopedSchedulerLock sl{kernel}; 231 KScopedSchedulerLock sl{kernel};
232 232
233 // Get the current request. 233 // Get the current request.
234 client_thread = m_current_thread_request; 234 request = m_current_request;
235 R_UNLESS(client_thread != nullptr, ResultInvalidState); 235 R_UNLESS(request != nullptr, ResultInvalidState);
236 236
237 // Clear the current request, since we're processing it. 237 // Clear the current request, since we're processing it.
238 m_current_thread_request = nullptr; 238 m_current_request = nullptr;
239 if (!m_thread_request_list.empty()) { 239 if (!m_request_list.empty()) {
240 this->NotifyAvailable(); 240 this->NotifyAvailable();
241 } 241 }
242 } 242 }
243 243
244 // Close reference to the request once we're done processing it. 244 // Close reference to the request once we're done processing it.
245 SCOPE_EXIT({ client_thread->Close(); }); 245 SCOPE_EXIT({ request->Close(); });
246 246
247 // Extract relevant information from the request. 247 // Extract relevant information from the request.
248 // const uintptr_t client_message = request->GetAddress(); 248 const uintptr_t client_message = request->GetAddress();
249 // const size_t client_buffer_size = request->GetSize(); 249 const size_t client_buffer_size = request->GetSize();
250 // KThread *client_thread = request->GetThread(); 250 KThread* client_thread = request->GetThread();
251 // KEvent *event = request->GetEvent(); 251 KEvent* event = request->GetEvent();
252 252
253 // Check whether we're closed. 253 // Check whether we're closed.
254 const bool closed = (client_thread == nullptr || parent->IsClientClosed()); 254 const bool closed = (client_thread == nullptr || parent->IsClientClosed());
@@ -261,8 +261,8 @@ Result KServerSession::SendReply() {
261 UNIMPLEMENTED_IF(server_thread->GetOwnerProcess() != client_thread->GetOwnerProcess()); 261 UNIMPLEMENTED_IF(server_thread->GetOwnerProcess() != client_thread->GetOwnerProcess());
262 262
263 auto* src_msg_buffer = memory.GetPointer(server_thread->GetTLSAddress()); 263 auto* src_msg_buffer = memory.GetPointer(server_thread->GetTLSAddress());
264 auto* dst_msg_buffer = memory.GetPointer(client_thread->GetTLSAddress()); 264 auto* dst_msg_buffer = memory.GetPointer(client_message);
265 std::memcpy(dst_msg_buffer, src_msg_buffer, MessageBufferSize); 265 std::memcpy(dst_msg_buffer, src_msg_buffer, client_buffer_size);
266 } else { 266 } else {
267 result = ResultSessionClosed; 267 result = ResultSessionClosed;
268 } 268 }
@@ -278,11 +278,30 @@ Result KServerSession::SendReply() {
278 278
279 // If there's a client thread, update it. 279 // If there's a client thread, update it.
280 if (client_thread != nullptr) { 280 if (client_thread != nullptr) {
281 // End the client thread's wait. 281 if (event != nullptr) {
282 KScopedSchedulerLock sl{kernel}; 282 // // Get the client process/page table.
283 // KProcess *client_process = client_thread->GetOwnerProcess();
284 // KPageTable *client_page_table = &client_process->PageTable();
285
286 // // If we need to, reply with an async error.
287 // if (R_FAILED(client_result)) {
288 // ReplyAsyncError(client_process, client_message, client_buffer_size,
289 // client_result);
290 // }
291
292 // // Unlock the client buffer.
293 // // NOTE: Nintendo does not check the result of this.
294 // client_page_table->UnlockForIpcUserBuffer(client_message, client_buffer_size);
295
296 // Signal the event.
297 event->Signal();
298 } else {
299 // End the client thread's wait.
300 KScopedSchedulerLock sl{kernel};
283 301
284 if (!client_thread->IsTerminationRequested()) { 302 if (!client_thread->IsTerminationRequested()) {
285 client_thread->EndWait(client_result); 303 client_thread->EndWait(client_result);
304 }
286 } 305 }
287 } 306 }
288 307
@@ -291,10 +310,10 @@ Result KServerSession::SendReply() {
291 310
292Result KServerSession::ReceiveRequest() { 311Result KServerSession::ReceiveRequest() {
293 // Lock the session. 312 // Lock the session.
294 KScopedLightLock lk(m_lock); 313 KScopedLightLock lk{m_lock};
295 314
296 // Get the request and client thread. 315 // Get the request and client thread.
297 // KSessionRequest *request; 316 KSessionRequest* request;
298 KThread* client_thread; 317 KThread* client_thread;
299 318
300 { 319 {
@@ -304,35 +323,41 @@ Result KServerSession::ReceiveRequest() {
304 R_UNLESS(!parent->IsClientClosed(), ResultSessionClosed); 323 R_UNLESS(!parent->IsClientClosed(), ResultSessionClosed);
305 324
306 // Ensure we aren't already servicing a request. 325 // Ensure we aren't already servicing a request.
307 R_UNLESS(m_current_thread_request == nullptr, ResultNotFound); 326 R_UNLESS(m_current_request == nullptr, ResultNotFound);
308 327
309 // Ensure we have a request to service. 328 // Ensure we have a request to service.
310 R_UNLESS(!m_thread_request_list.empty(), ResultNotFound); 329 R_UNLESS(!m_request_list.empty(), ResultNotFound);
311 330
312 // Pop the first request from the list. 331 // Pop the first request from the list.
313 client_thread = m_thread_request_list.front(); 332 request = &m_request_list.front();
314 m_thread_request_list.pop_front(); 333 m_request_list.pop_front();
315 334
316 // Get the thread for the request. 335 // Get the thread for the request.
336 client_thread = request->GetThread();
317 R_UNLESS(client_thread != nullptr, ResultSessionClosed); 337 R_UNLESS(client_thread != nullptr, ResultSessionClosed);
318 338
319 // Open the client thread. 339 // Open the client thread.
320 client_thread->Open(); 340 client_thread->Open();
321 } 341 }
322 342
323 // SCOPE_EXIT({ client_thread->Close(); }); 343 SCOPE_EXIT({ client_thread->Close(); });
324 344
325 // Set the request as our current. 345 // Set the request as our current.
326 m_current_thread_request = client_thread; 346 m_current_request = request;
347
348 // Get the client address.
349 uintptr_t client_message = request->GetAddress();
350 size_t client_buffer_size = request->GetSize();
351 // bool recv_list_broken = false;
327 352
328 // Receive the message. 353 // Receive the message.
329 Core::Memory::Memory& memory{kernel.System().Memory()}; 354 Core::Memory::Memory& memory{kernel.System().Memory()};
330 KThread* server_thread{GetCurrentThreadPointer(kernel)}; 355 KThread* server_thread{GetCurrentThreadPointer(kernel)};
331 UNIMPLEMENTED_IF(server_thread->GetOwnerProcess() != client_thread->GetOwnerProcess()); 356 UNIMPLEMENTED_IF(server_thread->GetOwnerProcess() != client_thread->GetOwnerProcess());
332 357
333 auto* src_msg_buffer = memory.GetPointer(client_thread->GetTLSAddress()); 358 auto* src_msg_buffer = memory.GetPointer(client_message);
334 auto* dst_msg_buffer = memory.GetPointer(server_thread->GetTLSAddress()); 359 auto* dst_msg_buffer = memory.GetPointer(server_thread->GetTLSAddress());
335 std::memcpy(dst_msg_buffer, src_msg_buffer, MessageBufferSize); 360 std::memcpy(dst_msg_buffer, src_msg_buffer, client_buffer_size);
336 361
337 // We succeeded. 362 // We succeeded.
338 return ResultSuccess; 363 return ResultSuccess;
@@ -344,35 +369,34 @@ void KServerSession::CleanupRequests() {
344 // Clean up any pending requests. 369 // Clean up any pending requests.
345 while (true) { 370 while (true) {
346 // Get the next request. 371 // Get the next request.
347 // KSessionRequest *request = nullptr; 372 KSessionRequest* request = nullptr;
348 KThread* client_thread = nullptr;
349 { 373 {
350 KScopedSchedulerLock sl{kernel}; 374 KScopedSchedulerLock sl{kernel};
351 375
352 if (m_current_thread_request) { 376 if (m_current_request) {
353 // Choose the current request if we have one. 377 // Choose the current request if we have one.
354 client_thread = m_current_thread_request; 378 request = m_current_request;
355 m_current_thread_request = nullptr; 379 m_current_request = nullptr;
356 } else if (!m_thread_request_list.empty()) { 380 } else if (!m_request_list.empty()) {
357 // Pop the request from the front of the list. 381 // Pop the request from the front of the list.
358 client_thread = m_thread_request_list.front(); 382 request = &m_request_list.front();
359 m_thread_request_list.pop_front(); 383 m_request_list.pop_front();
360 } 384 }
361 } 385 }
362 386
363 // If there's no request, we're done. 387 // If there's no request, we're done.
364 if (client_thread == nullptr) { 388 if (request == nullptr) {
365 break; 389 break;
366 } 390 }
367 391
368 // Close a reference to the request once it's cleaned up. 392 // Close a reference to the request once it's cleaned up.
369 SCOPE_EXIT({ client_thread->Close(); }); 393 SCOPE_EXIT({ request->Close(); });
370 394
371 // Extract relevant information from the request. 395 // Extract relevant information from the request.
372 // const uintptr_t client_message = request->GetAddress(); 396 // const uintptr_t client_message = request->GetAddress();
373 // const size_t client_buffer_size = request->GetSize(); 397 // const size_t client_buffer_size = request->GetSize();
374 // KThread *client_thread = request->GetThread(); 398 KThread* client_thread = request->GetThread();
375 // KEvent *event = request->GetEvent(); 399 KEvent* event = request->GetEvent();
376 400
377 // KProcess *server_process = request->GetServerProcess(); 401 // KProcess *server_process = request->GetServerProcess();
378 // KProcess *client_process = (client_thread != nullptr) ? 402 // KProcess *client_process = (client_thread != nullptr) ?
@@ -385,11 +409,24 @@ void KServerSession::CleanupRequests() {
385 409
386 // If there's a client thread, update it. 410 // If there's a client thread, update it.
387 if (client_thread != nullptr) { 411 if (client_thread != nullptr) {
388 // End the client thread's wait. 412 if (event != nullptr) {
389 KScopedSchedulerLock sl{kernel}; 413 // // We need to reply async.
390 414 // ReplyAsyncError(client_process, client_message, client_buffer_size,
391 if (!client_thread->IsTerminationRequested()) { 415 // (R_SUCCEEDED(result) ? ResultSessionClosed : result));
392 client_thread->EndWait(ResultSessionClosed); 416
417 // // Unlock the client buffer.
418 // NOTE: Nintendo does not check the result of this.
419 // client_page_table->UnlockForIpcUserBuffer(client_message, client_buffer_size);
420
421 // Signal the event.
422 event->Signal();
423 } else {
424 // End the client thread's wait.
425 KScopedSchedulerLock sl{kernel};
426
427 if (!client_thread->IsTerminationRequested()) {
428 client_thread->EndWait(ResultSessionClosed);
429 }
393 } 430 }
394 } 431 }
395 } 432 }
diff --git a/src/core/hle/kernel/k_server_session.h b/src/core/hle/kernel/k_server_session.h
index 748d52826..c40ff4aaf 100644
--- a/src/core/hle/kernel/k_server_session.h
+++ b/src/core/hle/kernel/k_server_session.h
@@ -12,6 +12,7 @@
12 12
13#include "core/hle/kernel/hle_ipc.h" 13#include "core/hle/kernel/hle_ipc.h"
14#include "core/hle/kernel/k_light_lock.h" 14#include "core/hle/kernel/k_light_lock.h"
15#include "core/hle/kernel/k_session_request.h"
15#include "core/hle/kernel/k_synchronization_object.h" 16#include "core/hle/kernel/k_synchronization_object.h"
16#include "core/hle/result.h" 17#include "core/hle/result.h"
17 18
@@ -94,7 +95,7 @@ public:
94 } 95 }
95 96
96 /// TODO: flesh these out to match the real kernel 97 /// TODO: flesh these out to match the real kernel
97 Result OnRequest(); 98 Result OnRequest(KSessionRequest* request);
98 Result SendReply(); 99 Result SendReply();
99 Result ReceiveRequest(); 100 Result ReceiveRequest();
100 101
@@ -122,9 +123,8 @@ private:
122 KSession* parent{}; 123 KSession* parent{};
123 124
124 /// List of threads which are pending a reply. 125 /// List of threads which are pending a reply.
125 /// FIXME: KSessionRequest 126 boost::intrusive::list<KSessionRequest> m_request_list;
126 std::list<KThread*> m_thread_request_list; 127 KSessionRequest* m_current_request;
127 KThread* m_current_thread_request{};
128 128
129 KLightLock m_lock; 129 KLightLock m_lock;
130}; 130};
diff --git a/src/core/hle/kernel/k_session_request.cpp b/src/core/hle/kernel/k_session_request.cpp
new file mode 100644
index 000000000..520da6aa7
--- /dev/null
+++ b/src/core/hle/kernel/k_session_request.cpp
@@ -0,0 +1,61 @@
1// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-2.0-or-later
3
4#include "core/hle/kernel/k_page_buffer.h"
5#include "core/hle/kernel/k_session_request.h"
6
7namespace Kernel {
8
9Result KSessionRequest::SessionMappings::PushMap(VAddr client, VAddr server, size_t size,
10 KMemoryState state, size_t index) {
11 // At most 15 buffers of each type (4-bit descriptor counts).
12 ASSERT(index < ((1ul << 4) - 1) * 3);
13
14 // Get the mapping.
15 Mapping* mapping;
16 if (index < NumStaticMappings) {
17 mapping = &m_static_mappings[index];
18 } else {
19 // Allocate a page for the extra mappings.
20 if (m_mappings == nullptr) {
21 KPageBuffer* page_buffer = KPageBuffer::Allocate(kernel);
22 R_UNLESS(page_buffer != nullptr, ResultOutOfMemory);
23
24 m_mappings = reinterpret_cast<Mapping*>(page_buffer);
25 }
26
27 mapping = &m_mappings[index - NumStaticMappings];
28 }
29
30 // Set the mapping.
31 mapping->Set(client, server, size, state);
32
33 return ResultSuccess;
34}
35
36Result KSessionRequest::SessionMappings::PushSend(VAddr client, VAddr server, size_t size,
37 KMemoryState state) {
38 ASSERT(m_num_recv == 0);
39 ASSERT(m_num_exch == 0);
40 return this->PushMap(client, server, size, state, m_num_send++);
41}
42
43Result KSessionRequest::SessionMappings::PushReceive(VAddr client, VAddr server, size_t size,
44 KMemoryState state) {
45 ASSERT(m_num_exch == 0);
46 return this->PushMap(client, server, size, state, m_num_send + m_num_recv++);
47}
48
49Result KSessionRequest::SessionMappings::PushExchange(VAddr client, VAddr server, size_t size,
50 KMemoryState state) {
51 return this->PushMap(client, server, size, state, m_num_send + m_num_recv + m_num_exch++);
52}
53
54void KSessionRequest::SessionMappings::Finalize() {
55 if (m_mappings) {
56 KPageBuffer::Free(kernel, reinterpret_cast<KPageBuffer*>(m_mappings));
57 m_mappings = nullptr;
58 }
59}
60
61} // namespace Kernel
diff --git a/src/core/hle/kernel/k_session_request.h b/src/core/hle/kernel/k_session_request.h
new file mode 100644
index 000000000..fcf521597
--- /dev/null
+++ b/src/core/hle/kernel/k_session_request.h
@@ -0,0 +1,307 @@
1// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-2.0-or-later
3
4#pragma once
5
6#include "core/hle/kernel/k_auto_object.h"
7#include "core/hle/kernel/k_event.h"
8#include "core/hle/kernel/k_memory_block.h"
9#include "core/hle/kernel/k_process.h"
10#include "core/hle/kernel/k_thread.h"
11#include "core/hle/kernel/slab_helpers.h"
12
13namespace Kernel {
14
15class KSessionRequest final : public KSlabAllocated<KSessionRequest>,
16 public KAutoObject,
17 public boost::intrusive::list_base_hook<> {
18 KERNEL_AUTOOBJECT_TRAITS(KSessionRequest, KAutoObject);
19
20public:
21 class SessionMappings {
22 private:
23 static constexpr size_t NumStaticMappings = 8;
24
25 class Mapping {
26 public:
27 constexpr void Set(VAddr c, VAddr s, size_t sz, KMemoryState st) {
28 m_client_address = c;
29 m_server_address = s;
30 m_size = sz;
31 m_state = st;
32 }
33
34 constexpr VAddr GetClientAddress() const {
35 return m_client_address;
36 }
37 constexpr VAddr GetServerAddress() const {
38 return m_server_address;
39 }
40 constexpr size_t GetSize() const {
41 return m_size;
42 }
43 constexpr KMemoryState GetMemoryState() const {
44 return m_state;
45 }
46
47 private:
48 VAddr m_client_address;
49 VAddr m_server_address;
50 size_t m_size;
51 KMemoryState m_state;
52 };
53
54 public:
55 explicit SessionMappings(KernelCore& kernel_)
56 : kernel(kernel_), m_mappings(nullptr), m_num_send(), m_num_recv(), m_num_exch() {}
57
58 void Initialize() {}
59 void Finalize();
60
61 size_t GetSendCount() const {
62 return m_num_send;
63 }
64 size_t GetReceiveCount() const {
65 return m_num_recv;
66 }
67 size_t GetExchangeCount() const {
68 return m_num_exch;
69 }
70
71 Result PushSend(VAddr client, VAddr server, size_t size, KMemoryState state);
72 Result PushReceive(VAddr client, VAddr server, size_t size, KMemoryState state);
73 Result PushExchange(VAddr client, VAddr server, size_t size, KMemoryState state);
74
75 VAddr GetSendClientAddress(size_t i) const {
76 return GetSendMapping(i).GetClientAddress();
77 }
78 VAddr GetSendServerAddress(size_t i) const {
79 return GetSendMapping(i).GetServerAddress();
80 }
81 size_t GetSendSize(size_t i) const {
82 return GetSendMapping(i).GetSize();
83 }
84 KMemoryState GetSendMemoryState(size_t i) const {
85 return GetSendMapping(i).GetMemoryState();
86 }
87
88 VAddr GetReceiveClientAddress(size_t i) const {
89 return GetReceiveMapping(i).GetClientAddress();
90 }
91 VAddr GetReceiveServerAddress(size_t i) const {
92 return GetReceiveMapping(i).GetServerAddress();
93 }
94 size_t GetReceiveSize(size_t i) const {
95 return GetReceiveMapping(i).GetSize();
96 }
97 KMemoryState GetReceiveMemoryState(size_t i) const {
98 return GetReceiveMapping(i).GetMemoryState();
99 }
100
101 VAddr GetExchangeClientAddress(size_t i) const {
102 return GetExchangeMapping(i).GetClientAddress();
103 }
104 VAddr GetExchangeServerAddress(size_t i) const {
105 return GetExchangeMapping(i).GetServerAddress();
106 }
107 size_t GetExchangeSize(size_t i) const {
108 return GetExchangeMapping(i).GetSize();
109 }
110 KMemoryState GetExchangeMemoryState(size_t i) const {
111 return GetExchangeMapping(i).GetMemoryState();
112 }
113
114 private:
115 Result PushMap(VAddr client, VAddr server, size_t size, KMemoryState state, size_t index);
116
117 const Mapping& GetSendMapping(size_t i) const {
118 ASSERT(i < m_num_send);
119
120 const size_t index = i;
121 if (index < NumStaticMappings) {
122 return m_static_mappings[index];
123 } else {
124 return m_mappings[index - NumStaticMappings];
125 }
126 }
127
128 const Mapping& GetReceiveMapping(size_t i) const {
129 ASSERT(i < m_num_recv);
130
131 const size_t index = m_num_send + i;
132 if (index < NumStaticMappings) {
133 return m_static_mappings[index];
134 } else {
135 return m_mappings[index - NumStaticMappings];
136 }
137 }
138
139 const Mapping& GetExchangeMapping(size_t i) const {
140 ASSERT(i < m_num_exch);
141
142 const size_t index = m_num_send + m_num_recv + i;
143 if (index < NumStaticMappings) {
144 return m_static_mappings[index];
145 } else {
146 return m_mappings[index - NumStaticMappings];
147 }
148 }
149
150 private:
151 KernelCore& kernel;
152 Mapping m_static_mappings[NumStaticMappings];
153 Mapping* m_mappings;
154 u8 m_num_send;
155 u8 m_num_recv;
156 u8 m_num_exch;
157 };
158
159public:
160 explicit KSessionRequest(KernelCore& kernel_)
161 : KAutoObject(kernel_), m_mappings(kernel_), m_thread(nullptr), m_server(nullptr),
162 m_event(nullptr) {}
163
164 static KSessionRequest* Create(KernelCore& kernel) {
165 KSessionRequest* req = KSessionRequest::Allocate(kernel);
166 if (req != nullptr) [[likely]] {
167 KAutoObject::Create(req);
168 }
169 return req;
170 }
171
172 void Destroy() override {
173 this->Finalize();
174 KSessionRequest::Free(kernel, this);
175 }
176
177 void Initialize(KEvent* event, uintptr_t address, size_t size) {
178 m_mappings.Initialize();
179
180 m_thread = GetCurrentThreadPointer(kernel);
181 m_event = event;
182 m_address = address;
183 m_size = size;
184
185 m_thread->Open();
186 if (m_event != nullptr) {
187 m_event->Open();
188 }
189 }
190
191 static void PostDestroy(uintptr_t arg) {}
192
193 KThread* GetThread() const {
194 return m_thread;
195 }
196 KEvent* GetEvent() const {
197 return m_event;
198 }
199 uintptr_t GetAddress() const {
200 return m_address;
201 }
202 size_t GetSize() const {
203 return m_size;
204 }
205 KProcess* GetServerProcess() const {
206 return m_server;
207 }
208
209 void SetServerProcess(KProcess* process) {
210 m_server = process;
211 m_server->Open();
212 }
213
214 void ClearThread() {
215 m_thread = nullptr;
216 }
217 void ClearEvent() {
218 m_event = nullptr;
219 }
220
221 size_t GetSendCount() const {
222 return m_mappings.GetSendCount();
223 }
224 size_t GetReceiveCount() const {
225 return m_mappings.GetReceiveCount();
226 }
227 size_t GetExchangeCount() const {
228 return m_mappings.GetExchangeCount();
229 }
230
231 Result PushSend(VAddr client, VAddr server, size_t size, KMemoryState state) {
232 return m_mappings.PushSend(client, server, size, state);
233 }
234
235 Result PushReceive(VAddr client, VAddr server, size_t size, KMemoryState state) {
236 return m_mappings.PushReceive(client, server, size, state);
237 }
238
239 Result PushExchange(VAddr client, VAddr server, size_t size, KMemoryState state) {
240 return m_mappings.PushExchange(client, server, size, state);
241 }
242
243 VAddr GetSendClientAddress(size_t i) const {
244 return m_mappings.GetSendClientAddress(i);
245 }
246 VAddr GetSendServerAddress(size_t i) const {
247 return m_mappings.GetSendServerAddress(i);
248 }
249 size_t GetSendSize(size_t i) const {
250 return m_mappings.GetSendSize(i);
251 }
252 KMemoryState GetSendMemoryState(size_t i) const {
253 return m_mappings.GetSendMemoryState(i);
254 }
255
256 VAddr GetReceiveClientAddress(size_t i) const {
257 return m_mappings.GetReceiveClientAddress(i);
258 }
259 VAddr GetReceiveServerAddress(size_t i) const {
260 return m_mappings.GetReceiveServerAddress(i);
261 }
262 size_t GetReceiveSize(size_t i) const {
263 return m_mappings.GetReceiveSize(i);
264 }
265 KMemoryState GetReceiveMemoryState(size_t i) const {
266 return m_mappings.GetReceiveMemoryState(i);
267 }
268
269 VAddr GetExchangeClientAddress(size_t i) const {
270 return m_mappings.GetExchangeClientAddress(i);
271 }
272 VAddr GetExchangeServerAddress(size_t i) const {
273 return m_mappings.GetExchangeServerAddress(i);
274 }
275 size_t GetExchangeSize(size_t i) const {
276 return m_mappings.GetExchangeSize(i);
277 }
278 KMemoryState GetExchangeMemoryState(size_t i) const {
279 return m_mappings.GetExchangeMemoryState(i);
280 }
281
282private:
283 // NOTE: This is public and virtual in Nintendo's kernel.
284 void Finalize() {
285 m_mappings.Finalize();
286
287 if (m_thread) {
288 m_thread->Close();
289 }
290 if (m_event) {
291 m_event->Close();
292 }
293 if (m_server) {
294 m_server->Close();
295 }
296 }
297
298private:
299 SessionMappings m_mappings;
300 KThread* m_thread;
301 KProcess* m_server;
302 KEvent* m_event;
303 uintptr_t m_address;
304 size_t m_size;
305};
306
307} // namespace Kernel
diff --git a/src/core/hle/kernel/k_shared_memory_info.h b/src/core/hle/kernel/k_shared_memory_info.h
index e43db8515..2bb6b6d08 100644
--- a/src/core/hle/kernel/k_shared_memory_info.h
+++ b/src/core/hle/kernel/k_shared_memory_info.h
@@ -15,7 +15,8 @@ class KSharedMemoryInfo final : public KSlabAllocated<KSharedMemoryInfo>,
15 public boost::intrusive::list_base_hook<> { 15 public boost::intrusive::list_base_hook<> {
16 16
17public: 17public:
18 explicit KSharedMemoryInfo() = default; 18 explicit KSharedMemoryInfo(KernelCore&) {}
19 KSharedMemoryInfo() = default;
19 20
20 constexpr void Initialize(KSharedMemory* shmem) { 21 constexpr void Initialize(KSharedMemory* shmem) {
21 shared_memory = shmem; 22 shared_memory = shmem;
diff --git a/src/core/hle/kernel/k_thread_local_page.h b/src/core/hle/kernel/k_thread_local_page.h
index 0a7f22680..5d466ace7 100644
--- a/src/core/hle/kernel/k_thread_local_page.h
+++ b/src/core/hle/kernel/k_thread_local_page.h
@@ -26,7 +26,7 @@ public:
26 static_assert(RegionsPerPage > 0); 26 static_assert(RegionsPerPage > 0);
27 27
28public: 28public:
29 constexpr explicit KThreadLocalPage(VAddr addr = {}) : m_virt_addr(addr) { 29 constexpr explicit KThreadLocalPage(KernelCore&, VAddr addr = {}) : m_virt_addr(addr) {
30 m_is_region_free.fill(true); 30 m_is_region_free.fill(true);
31 } 31 }
32 32
diff --git a/src/core/hle/kernel/kernel.h b/src/core/hle/kernel/kernel.h
index 6eded9539..266be2bc4 100644
--- a/src/core/hle/kernel/kernel.h
+++ b/src/core/hle/kernel/kernel.h
@@ -47,6 +47,7 @@ class KResourceLimit;
47class KScheduler; 47class KScheduler;
48class KServerSession; 48class KServerSession;
49class KSession; 49class KSession;
50class KSessionRequest;
50class KSharedMemory; 51class KSharedMemory;
51class KSharedMemoryInfo; 52class KSharedMemoryInfo;
52class KThread; 53class KThread;
@@ -360,6 +361,8 @@ public:
360 return slab_heap_container->page_buffer; 361 return slab_heap_container->page_buffer;
361 } else if constexpr (std::is_same_v<T, KThreadLocalPage>) { 362 } else if constexpr (std::is_same_v<T, KThreadLocalPage>) {
362 return slab_heap_container->thread_local_page; 363 return slab_heap_container->thread_local_page;
364 } else if constexpr (std::is_same_v<T, KSessionRequest>) {
365 return slab_heap_container->session_request;
363 } 366 }
364 } 367 }
365 368
@@ -422,6 +425,7 @@ private:
422 KSlabHeap<KCodeMemory> code_memory; 425 KSlabHeap<KCodeMemory> code_memory;
423 KSlabHeap<KPageBuffer> page_buffer; 426 KSlabHeap<KPageBuffer> page_buffer;
424 KSlabHeap<KThreadLocalPage> thread_local_page; 427 KSlabHeap<KThreadLocalPage> thread_local_page;
428 KSlabHeap<KSessionRequest> session_request;
425 }; 429 };
426 430
427 std::unique_ptr<SlabHeapContainer> slab_heap_container; 431 std::unique_ptr<SlabHeapContainer> slab_heap_container;
diff --git a/src/core/hle/kernel/slab_helpers.h b/src/core/hle/kernel/slab_helpers.h
index 299a981a8..06b51e919 100644
--- a/src/core/hle/kernel/slab_helpers.h
+++ b/src/core/hle/kernel/slab_helpers.h
@@ -24,7 +24,7 @@ public:
24 } 24 }
25 25
26 static Derived* Allocate(KernelCore& kernel) { 26 static Derived* Allocate(KernelCore& kernel) {
27 return kernel.SlabHeap<Derived>().Allocate(); 27 return kernel.SlabHeap<Derived>().Allocate(kernel);
28 } 28 }
29 29
30 static void Free(KernelCore& kernel, Derived* obj) { 30 static void Free(KernelCore& kernel, Derived* obj) {