kernel: add KSessionRequest
parent
5ffb8b8039
commit
3efb8eb2dc
@ -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
|
Loading…
Reference in New Issue