Browse Source
Merge pull request #9078 from liamwhite/session-request
Merge pull request #9078 from liamwhite/session-request
kernel: Session request cleanupnce_cpp
committed by
GitHub
17 changed files with 608 additions and 200 deletions
-
2src/core/CMakeLists.txt
-
11src/core/hle/ipc_helpers.h
-
110src/core/hle/kernel/hle_ipc.cpp
-
9src/core/hle/kernel/hle_ipc.h
-
2src/core/hle/kernel/init/init_slab_setup.cpp
-
15src/core/hle/kernel/k_client_session.cpp
-
1src/core/hle/kernel/k_linked_list.h
-
1src/core/hle/kernel/k_page_buffer.h
-
214src/core/hle/kernel/k_server_session.cpp
-
41src/core/hle/kernel/k_server_session.h
-
61src/core/hle/kernel/k_session_request.cpp
-
307src/core/hle/kernel/k_session_request.h
-
3src/core/hle/kernel/k_shared_memory_info.h
-
2src/core/hle/kernel/k_thread_local_page.h
-
4src/core/hle/kernel/kernel.h
-
2src/core/hle/kernel/slab_helpers.h
-
5src/core/hle/service/sm/sm_controller.cpp
@ -0,0 +1,61 @@ |
|||||
|
// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project
|
||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
|
||||
|
#include "core/hle/kernel/k_page_buffer.h"
|
||||
|
#include "core/hle/kernel/k_session_request.h"
|
||||
|
|
||||
|
namespace Kernel { |
||||
|
|
||||
|
Result KSessionRequest::SessionMappings::PushMap(VAddr client, VAddr server, size_t size, |
||||
|
KMemoryState state, size_t index) { |
||||
|
// At most 15 buffers of each type (4-bit descriptor counts).
|
||||
|
ASSERT(index < ((1ul << 4) - 1) * 3); |
||||
|
|
||||
|
// Get the mapping.
|
||||
|
Mapping* mapping; |
||||
|
if (index < NumStaticMappings) { |
||||
|
mapping = &m_static_mappings[index]; |
||||
|
} else { |
||||
|
// Allocate a page for the extra mappings.
|
||||
|
if (m_mappings == nullptr) { |
||||
|
KPageBuffer* page_buffer = KPageBuffer::Allocate(kernel); |
||||
|
R_UNLESS(page_buffer != nullptr, ResultOutOfMemory); |
||||
|
|
||||
|
m_mappings = reinterpret_cast<Mapping*>(page_buffer); |
||||
|
} |
||||
|
|
||||
|
mapping = &m_mappings[index - NumStaticMappings]; |
||||
|
} |
||||
|
|
||||
|
// Set the mapping.
|
||||
|
mapping->Set(client, server, size, state); |
||||
|
|
||||
|
return ResultSuccess; |
||||
|
} |
||||
|
|
||||
|
Result KSessionRequest::SessionMappings::PushSend(VAddr client, VAddr server, size_t size, |
||||
|
KMemoryState state) { |
||||
|
ASSERT(m_num_recv == 0); |
||||
|
ASSERT(m_num_exch == 0); |
||||
|
return this->PushMap(client, server, size, state, m_num_send++); |
||||
|
} |
||||
|
|
||||
|
Result KSessionRequest::SessionMappings::PushReceive(VAddr client, VAddr server, size_t size, |
||||
|
KMemoryState state) { |
||||
|
ASSERT(m_num_exch == 0); |
||||
|
return this->PushMap(client, server, size, state, m_num_send + m_num_recv++); |
||||
|
} |
||||
|
|
||||
|
Result KSessionRequest::SessionMappings::PushExchange(VAddr client, VAddr server, size_t size, |
||||
|
KMemoryState state) { |
||||
|
return this->PushMap(client, server, size, state, m_num_send + m_num_recv + m_num_exch++); |
||||
|
} |
||||
|
|
||||
|
void KSessionRequest::SessionMappings::Finalize() { |
||||
|
if (m_mappings) { |
||||
|
KPageBuffer::Free(kernel, reinterpret_cast<KPageBuffer*>(m_mappings)); |
||||
|
m_mappings = nullptr; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
} // namespace Kernel
|
||||
@ -0,0 +1,307 @@ |
|||||
|
// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project |
||||
|
// SPDX-License-Identifier: GPL-2.0-or-later |
||||
|
|
||||
|
#pragma once |
||||
|
|
||||
|
#include "core/hle/kernel/k_auto_object.h" |
||||
|
#include "core/hle/kernel/k_event.h" |
||||
|
#include "core/hle/kernel/k_memory_block.h" |
||||
|
#include "core/hle/kernel/k_process.h" |
||||
|
#include "core/hle/kernel/k_thread.h" |
||||
|
#include "core/hle/kernel/slab_helpers.h" |
||||
|
|
||||
|
namespace Kernel { |
||||
|
|
||||
|
class KSessionRequest final : public KSlabAllocated<KSessionRequest>, |
||||
|
public KAutoObject, |
||||
|
public boost::intrusive::list_base_hook<> { |
||||
|
KERNEL_AUTOOBJECT_TRAITS(KSessionRequest, KAutoObject); |
||||
|
|
||||
|
public: |
||||
|
class SessionMappings { |
||||
|
private: |
||||
|
static constexpr size_t NumStaticMappings = 8; |
||||
|
|
||||
|
class Mapping { |
||||
|
public: |
||||
|
constexpr void Set(VAddr c, VAddr s, size_t sz, KMemoryState st) { |
||||
|
m_client_address = c; |
||||
|
m_server_address = s; |
||||
|
m_size = sz; |
||||
|
m_state = st; |
||||
|
} |
||||
|
|
||||
|
constexpr VAddr GetClientAddress() const { |
||||
|
return m_client_address; |
||||
|
} |
||||
|
constexpr VAddr GetServerAddress() const { |
||||
|
return m_server_address; |
||||
|
} |
||||
|
constexpr size_t GetSize() const { |
||||
|
return m_size; |
||||
|
} |
||||
|
constexpr KMemoryState GetMemoryState() const { |
||||
|
return m_state; |
||||
|
} |
||||
|
|
||||
|
private: |
||||
|
VAddr m_client_address; |
||||
|
VAddr m_server_address; |
||||
|
size_t m_size; |
||||
|
KMemoryState m_state; |
||||
|
}; |
||||
|
|
||||
|
public: |
||||
|
explicit SessionMappings(KernelCore& kernel_) |
||||
|
: kernel(kernel_), m_mappings(nullptr), m_num_send(), m_num_recv(), m_num_exch() {} |
||||
|
|
||||
|
void Initialize() {} |
||||
|
void Finalize(); |
||||
|
|
||||
|
size_t GetSendCount() const { |
||||
|
return m_num_send; |
||||
|
} |
||||
|
size_t GetReceiveCount() const { |
||||
|
return m_num_recv; |
||||
|
} |
||||
|
size_t GetExchangeCount() const { |
||||
|
return m_num_exch; |
||||
|
} |
||||
|
|
||||
|
Result PushSend(VAddr client, VAddr server, size_t size, KMemoryState state); |
||||
|
Result PushReceive(VAddr client, VAddr server, size_t size, KMemoryState state); |
||||
|
Result PushExchange(VAddr client, VAddr server, size_t size, KMemoryState state); |
||||
|
|
||||
|
VAddr GetSendClientAddress(size_t i) const { |
||||
|
return GetSendMapping(i).GetClientAddress(); |
||||
|
} |
||||
|
VAddr GetSendServerAddress(size_t i) const { |
||||
|
return GetSendMapping(i).GetServerAddress(); |
||||
|
} |
||||
|
size_t GetSendSize(size_t i) const { |
||||
|
return GetSendMapping(i).GetSize(); |
||||
|
} |
||||
|
KMemoryState GetSendMemoryState(size_t i) const { |
||||
|
return GetSendMapping(i).GetMemoryState(); |
||||
|
} |
||||
|
|
||||
|
VAddr GetReceiveClientAddress(size_t i) const { |
||||
|
return GetReceiveMapping(i).GetClientAddress(); |
||||
|
} |
||||
|
VAddr GetReceiveServerAddress(size_t i) const { |
||||
|
return GetReceiveMapping(i).GetServerAddress(); |
||||
|
} |
||||
|
size_t GetReceiveSize(size_t i) const { |
||||
|
return GetReceiveMapping(i).GetSize(); |
||||
|
} |
||||
|
KMemoryState GetReceiveMemoryState(size_t i) const { |
||||
|
return GetReceiveMapping(i).GetMemoryState(); |
||||
|
} |
||||
|
|
||||
|
VAddr GetExchangeClientAddress(size_t i) const { |
||||
|
return GetExchangeMapping(i).GetClientAddress(); |
||||
|
} |
||||
|
VAddr GetExchangeServerAddress(size_t i) const { |
||||
|
return GetExchangeMapping(i).GetServerAddress(); |
||||
|
} |
||||
|
size_t GetExchangeSize(size_t i) const { |
||||
|
return GetExchangeMapping(i).GetSize(); |
||||
|
} |
||||
|
KMemoryState GetExchangeMemoryState(size_t i) const { |
||||
|
return GetExchangeMapping(i).GetMemoryState(); |
||||
|
} |
||||
|
|
||||
|
private: |
||||
|
Result PushMap(VAddr client, VAddr server, size_t size, KMemoryState state, size_t index); |
||||
|
|
||||
|
const Mapping& GetSendMapping(size_t i) const { |
||||
|
ASSERT(i < m_num_send); |
||||
|
|
||||
|
const size_t index = i; |
||||
|
if (index < NumStaticMappings) { |
||||
|
return m_static_mappings[index]; |
||||
|
} else { |
||||
|
return m_mappings[index - NumStaticMappings]; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
const Mapping& GetReceiveMapping(size_t i) const { |
||||
|
ASSERT(i < m_num_recv); |
||||
|
|
||||
|
const size_t index = m_num_send + i; |
||||
|
if (index < NumStaticMappings) { |
||||
|
return m_static_mappings[index]; |
||||
|
} else { |
||||
|
return m_mappings[index - NumStaticMappings]; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
const Mapping& GetExchangeMapping(size_t i) const { |
||||
|
ASSERT(i < m_num_exch); |
||||
|
|
||||
|
const size_t index = m_num_send + m_num_recv + i; |
||||
|
if (index < NumStaticMappings) { |
||||
|
return m_static_mappings[index]; |
||||
|
} else { |
||||
|
return m_mappings[index - NumStaticMappings]; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
private: |
||||
|
KernelCore& kernel; |
||||
|
Mapping m_static_mappings[NumStaticMappings]; |
||||
|
Mapping* m_mappings; |
||||
|
u8 m_num_send; |
||||
|
u8 m_num_recv; |
||||
|
u8 m_num_exch; |
||||
|
}; |
||||
|
|
||||
|
public: |
||||
|
explicit KSessionRequest(KernelCore& kernel_) |
||||
|
: KAutoObject(kernel_), m_mappings(kernel_), m_thread(nullptr), m_server(nullptr), |
||||
|
m_event(nullptr) {} |
||||
|
|
||||
|
static KSessionRequest* Create(KernelCore& kernel) { |
||||
|
KSessionRequest* req = KSessionRequest::Allocate(kernel); |
||||
|
if (req != nullptr) [[likely]] { |
||||
|
KAutoObject::Create(req); |
||||
|
} |
||||
|
return req; |
||||
|
} |
||||
|
|
||||
|
void Destroy() override { |
||||
|
this->Finalize(); |
||||
|
KSessionRequest::Free(kernel, this); |
||||
|
} |
||||
|
|
||||
|
void Initialize(KEvent* event, uintptr_t address, size_t size) { |
||||
|
m_mappings.Initialize(); |
||||
|
|
||||
|
m_thread = GetCurrentThreadPointer(kernel); |
||||
|
m_event = event; |
||||
|
m_address = address; |
||||
|
m_size = size; |
||||
|
|
||||
|
m_thread->Open(); |
||||
|
if (m_event != nullptr) { |
||||
|
m_event->Open(); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
static void PostDestroy(uintptr_t arg) {} |
||||
|
|
||||
|
KThread* GetThread() const { |
||||
|
return m_thread; |
||||
|
} |
||||
|
KEvent* GetEvent() const { |
||||
|
return m_event; |
||||
|
} |
||||
|
uintptr_t GetAddress() const { |
||||
|
return m_address; |
||||
|
} |
||||
|
size_t GetSize() const { |
||||
|
return m_size; |
||||
|
} |
||||
|
KProcess* GetServerProcess() const { |
||||
|
return m_server; |
||||
|
} |
||||
|
|
||||
|
void SetServerProcess(KProcess* process) { |
||||
|
m_server = process; |
||||
|
m_server->Open(); |
||||
|
} |
||||
|
|
||||
|
void ClearThread() { |
||||
|
m_thread = nullptr; |
||||
|
} |
||||
|
void ClearEvent() { |
||||
|
m_event = nullptr; |
||||
|
} |
||||
|
|
||||
|
size_t GetSendCount() const { |
||||
|
return m_mappings.GetSendCount(); |
||||
|
} |
||||
|
size_t GetReceiveCount() const { |
||||
|
return m_mappings.GetReceiveCount(); |
||||
|
} |
||||
|
size_t GetExchangeCount() const { |
||||
|
return m_mappings.GetExchangeCount(); |
||||
|
} |
||||
|
|
||||
|
Result PushSend(VAddr client, VAddr server, size_t size, KMemoryState state) { |
||||
|
return m_mappings.PushSend(client, server, size, state); |
||||
|
} |
||||
|
|
||||
|
Result PushReceive(VAddr client, VAddr server, size_t size, KMemoryState state) { |
||||
|
return m_mappings.PushReceive(client, server, size, state); |
||||
|
} |
||||
|
|
||||
|
Result PushExchange(VAddr client, VAddr server, size_t size, KMemoryState state) { |
||||
|
return m_mappings.PushExchange(client, server, size, state); |
||||
|
} |
||||
|
|
||||
|
VAddr GetSendClientAddress(size_t i) const { |
||||
|
return m_mappings.GetSendClientAddress(i); |
||||
|
} |
||||
|
VAddr GetSendServerAddress(size_t i) const { |
||||
|
return m_mappings.GetSendServerAddress(i); |
||||
|
} |
||||
|
size_t GetSendSize(size_t i) const { |
||||
|
return m_mappings.GetSendSize(i); |
||||
|
} |
||||
|
KMemoryState GetSendMemoryState(size_t i) const { |
||||
|
return m_mappings.GetSendMemoryState(i); |
||||
|
} |
||||
|
|
||||
|
VAddr GetReceiveClientAddress(size_t i) const { |
||||
|
return m_mappings.GetReceiveClientAddress(i); |
||||
|
} |
||||
|
VAddr GetReceiveServerAddress(size_t i) const { |
||||
|
return m_mappings.GetReceiveServerAddress(i); |
||||
|
} |
||||
|
size_t GetReceiveSize(size_t i) const { |
||||
|
return m_mappings.GetReceiveSize(i); |
||||
|
} |
||||
|
KMemoryState GetReceiveMemoryState(size_t i) const { |
||||
|
return m_mappings.GetReceiveMemoryState(i); |
||||
|
} |
||||
|
|
||||
|
VAddr GetExchangeClientAddress(size_t i) const { |
||||
|
return m_mappings.GetExchangeClientAddress(i); |
||||
|
} |
||||
|
VAddr GetExchangeServerAddress(size_t i) const { |
||||
|
return m_mappings.GetExchangeServerAddress(i); |
||||
|
} |
||||
|
size_t GetExchangeSize(size_t i) const { |
||||
|
return m_mappings.GetExchangeSize(i); |
||||
|
} |
||||
|
KMemoryState GetExchangeMemoryState(size_t i) const { |
||||
|
return m_mappings.GetExchangeMemoryState(i); |
||||
|
} |
||||
|
|
||||
|
private: |
||||
|
// NOTE: This is public and virtual in Nintendo's kernel. |
||||
|
void Finalize() { |
||||
|
m_mappings.Finalize(); |
||||
|
|
||||
|
if (m_thread) { |
||||
|
m_thread->Close(); |
||||
|
} |
||||
|
if (m_event) { |
||||
|
m_event->Close(); |
||||
|
} |
||||
|
if (m_server) { |
||||
|
m_server->Close(); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
private: |
||||
|
SessionMappings m_mappings; |
||||
|
KThread* m_thread; |
||||
|
KProcess* m_server; |
||||
|
KEvent* m_event; |
||||
|
uintptr_t m_address; |
||||
|
size_t m_size; |
||||
|
}; |
||||
|
|
||||
|
} // namespace Kernel |
||||
Write
Preview
Loading…
Cancel
Save
Reference in new issue