13 changed files with 489 additions and 62 deletions
-
2src/core/CMakeLists.txt
-
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
-
143src/core/hle/kernel/k_server_session.cpp
-
8src/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
@ -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