Merge pull request #4908 from hamish-milne/feature/savestates-2
Save states
This commit is contained in:
commit
c605bb42db
354 changed files with 6100 additions and 604 deletions
|
@ -3,8 +3,10 @@
|
|||
// Refer to the license.txt file included.
|
||||
|
||||
#include <algorithm>
|
||||
#include "common/archives.h"
|
||||
#include "common/common_types.h"
|
||||
#include "common/logging/log.h"
|
||||
#include "core/global.h"
|
||||
#include "core/hle/kernel/address_arbiter.h"
|
||||
#include "core/hle/kernel/errors.h"
|
||||
#include "core/hle/kernel/kernel.h"
|
||||
|
@ -14,6 +16,8 @@
|
|||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Kernel namespace
|
||||
|
||||
SERIALIZE_EXPORT_IMPL(Kernel::AddressArbiter)
|
||||
|
||||
namespace Kernel {
|
||||
|
||||
void AddressArbiter::WaitThread(std::shared_ptr<Thread> thread, VAddr wait_address) {
|
||||
|
@ -76,16 +80,18 @@ std::shared_ptr<AddressArbiter> KernelSystem::CreateAddressArbiter(std::string n
|
|||
return address_arbiter;
|
||||
}
|
||||
|
||||
void AddressArbiter::WakeUp(ThreadWakeupReason reason, std::shared_ptr<Thread> thread,
|
||||
std::shared_ptr<WaitObject> object) {
|
||||
ASSERT(reason == ThreadWakeupReason::Timeout);
|
||||
// Remove the newly-awakened thread from the Arbiter's waiting list.
|
||||
waiting_threads.erase(std::remove(waiting_threads.begin(), waiting_threads.end(), thread),
|
||||
waiting_threads.end());
|
||||
};
|
||||
|
||||
ResultCode AddressArbiter::ArbitrateAddress(std::shared_ptr<Thread> thread, ArbitrationType type,
|
||||
VAddr address, s32 value, u64 nanoseconds) {
|
||||
|
||||
auto timeout_callback = [this](ThreadWakeupReason reason, std::shared_ptr<Thread> thread,
|
||||
std::shared_ptr<WaitObject> object) {
|
||||
ASSERT(reason == ThreadWakeupReason::Timeout);
|
||||
// Remove the newly-awakened thread from the Arbiter's waiting list.
|
||||
waiting_threads.erase(std::remove(waiting_threads.begin(), waiting_threads.end(), thread),
|
||||
waiting_threads.end());
|
||||
};
|
||||
auto timeout_callback = std::dynamic_pointer_cast<WakeupCallback>(shared_from_this());
|
||||
|
||||
switch (type) {
|
||||
|
||||
|
|
|
@ -6,8 +6,15 @@
|
|||
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
#include <boost/serialization/base_object.hpp>
|
||||
#include <boost/serialization/export.hpp>
|
||||
#include <boost/serialization/shared_ptr.hpp>
|
||||
#include <boost/serialization/string.hpp>
|
||||
#include <boost/serialization/vector.hpp>
|
||||
#include <boost/serialization/version.hpp>
|
||||
#include "common/common_types.h"
|
||||
#include "core/hle/kernel/object.h"
|
||||
#include "core/hle/kernel/thread.h"
|
||||
#include "core/hle/result.h"
|
||||
|
||||
// Address arbiters are an underlying kernel synchronization object that can be created/used via
|
||||
|
@ -30,7 +37,7 @@ enum class ArbitrationType : u32 {
|
|||
DecrementAndWaitIfLessThanWithTimeout,
|
||||
};
|
||||
|
||||
class AddressArbiter final : public Object {
|
||||
class AddressArbiter final : public Object, public WakeupCallback {
|
||||
public:
|
||||
explicit AddressArbiter(KernelSystem& kernel);
|
||||
~AddressArbiter() override;
|
||||
|
@ -52,6 +59,9 @@ public:
|
|||
ResultCode ArbitrateAddress(std::shared_ptr<Thread> thread, ArbitrationType type, VAddr address,
|
||||
s32 value, u64 nanoseconds);
|
||||
|
||||
void WakeUp(ThreadWakeupReason reason, std::shared_ptr<Thread> thread,
|
||||
std::shared_ptr<WaitObject> object);
|
||||
|
||||
private:
|
||||
KernelSystem& kernel;
|
||||
|
||||
|
@ -67,6 +77,21 @@ private:
|
|||
|
||||
/// Threads waiting for the address arbiter to be signaled.
|
||||
std::vector<std::shared_ptr<Thread>> waiting_threads;
|
||||
|
||||
friend class boost::serialization::access;
|
||||
template <class Archive>
|
||||
void serialize(Archive& ar, const unsigned int file_version) {
|
||||
ar& boost::serialization::base_object<Object>(*this);
|
||||
if (file_version > 0) {
|
||||
ar& boost::serialization::base_object<WakeupCallback>(*this);
|
||||
}
|
||||
ar& name;
|
||||
ar& waiting_threads;
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace Kernel
|
||||
|
||||
BOOST_CLASS_EXPORT_KEY(Kernel::AddressArbiter)
|
||||
BOOST_CLASS_VERSION(Kernel::AddressArbiter, 1)
|
||||
CONSTRUCT_KERNEL_OBJECT(Kernel::AddressArbiter)
|
||||
|
|
|
@ -2,7 +2,9 @@
|
|||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#include "common/archives.h"
|
||||
#include "common/assert.h"
|
||||
#include "core/global.h"
|
||||
#include "core/hle/kernel/client_port.h"
|
||||
#include "core/hle/kernel/client_session.h"
|
||||
#include "core/hle/kernel/errors.h"
|
||||
|
@ -11,6 +13,8 @@
|
|||
#include "core/hle/kernel/server_port.h"
|
||||
#include "core/hle/kernel/server_session.h"
|
||||
|
||||
SERIALIZE_EXPORT_IMPL(Kernel::ClientPort)
|
||||
|
||||
namespace Kernel {
|
||||
|
||||
ClientPort::ClientPort(KernelSystem& kernel) : Object(kernel), kernel(kernel) {}
|
||||
|
|
|
@ -6,6 +6,9 @@
|
|||
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <boost/serialization/export.hpp>
|
||||
#include <boost/serialization/shared_ptr.hpp>
|
||||
#include <boost/serialization/string.hpp>
|
||||
#include "common/common_types.h"
|
||||
#include "core/hle/kernel/object.h"
|
||||
#include "core/hle/kernel/server_port.h"
|
||||
|
@ -59,6 +62,20 @@ private:
|
|||
std::string name; ///< Name of client port (optional)
|
||||
|
||||
friend class KernelSystem;
|
||||
|
||||
private:
|
||||
friend class boost::serialization::access;
|
||||
template <class Archive>
|
||||
void serialize(Archive& ar, const unsigned int file_version) {
|
||||
ar& boost::serialization::base_object<Object>(*this);
|
||||
ar& server_port;
|
||||
ar& max_sessions;
|
||||
ar& active_sessions;
|
||||
ar& name;
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace Kernel
|
||||
|
||||
BOOST_CLASS_EXPORT_KEY(Kernel::ClientPort)
|
||||
CONSTRUCT_KERNEL_OBJECT(Kernel::ClientPort)
|
||||
|
|
|
@ -2,8 +2,8 @@
|
|||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#include "common/archives.h"
|
||||
#include "common/assert.h"
|
||||
|
||||
#include "core/hle/kernel/client_session.h"
|
||||
#include "core/hle/kernel/errors.h"
|
||||
#include "core/hle/kernel/hle_ipc.h"
|
||||
|
@ -11,6 +11,8 @@
|
|||
#include "core/hle/kernel/session.h"
|
||||
#include "core/hle/kernel/thread.h"
|
||||
|
||||
SERIALIZE_EXPORT_IMPL(Kernel::ClientSession)
|
||||
|
||||
namespace Kernel {
|
||||
|
||||
ClientSession::ClientSession(KernelSystem& kernel) : Object(kernel) {}
|
||||
|
|
|
@ -6,6 +6,10 @@
|
|||
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <boost/serialization/base_object.hpp>
|
||||
#include <boost/serialization/export.hpp>
|
||||
#include <boost/serialization/shared_ptr.hpp>
|
||||
#include <boost/serialization/string.hpp>
|
||||
#include "common/common_types.h"
|
||||
#include "core/hle/kernel/object.h"
|
||||
#include "core/hle/result.h"
|
||||
|
@ -46,6 +50,18 @@ public:
|
|||
|
||||
/// The parent session, which links to the server endpoint.
|
||||
std::shared_ptr<Session> parent;
|
||||
|
||||
private:
|
||||
friend class boost::serialization::access;
|
||||
template <class Archive>
|
||||
void serialize(Archive& ar, const unsigned int file_version) {
|
||||
ar& boost::serialization::base_object<Object>(*this);
|
||||
ar& name;
|
||||
ar& parent;
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace Kernel
|
||||
|
||||
BOOST_CLASS_EXPORT_KEY(Kernel::ClientSession)
|
||||
CONSTRUCT_KERNEL_OBJECT(Kernel::ClientSession)
|
||||
|
|
|
@ -3,10 +3,13 @@
|
|||
// Refer to the license.txt file included.
|
||||
|
||||
#include <cstring>
|
||||
#include "common/archives.h"
|
||||
#include "core/hle/kernel/config_mem.h"
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
SERIALIZE_EXPORT_IMPL(ConfigMem::Handler)
|
||||
|
||||
namespace ConfigMem {
|
||||
|
||||
Handler::Handler() {
|
||||
|
|
|
@ -9,8 +9,11 @@
|
|||
// bootrom. Because we're not emulating this, and essentially just "stubbing" the functionality, I'm
|
||||
// putting this as a subset of HLE for now.
|
||||
|
||||
#include <boost/serialization/binary_object.hpp>
|
||||
#include <boost/serialization/export.hpp>
|
||||
#include "common/common_funcs.h"
|
||||
#include "common/common_types.h"
|
||||
#include "common/memory_ref.h"
|
||||
#include "common/swap.h"
|
||||
#include "core/memory.h"
|
||||
|
||||
|
@ -49,13 +52,34 @@ struct ConfigMemDef {
|
|||
static_assert(sizeof(ConfigMemDef) == Memory::CONFIG_MEMORY_SIZE,
|
||||
"Config Memory structure size is wrong");
|
||||
|
||||
class Handler {
|
||||
class Handler : public BackingMem {
|
||||
public:
|
||||
Handler();
|
||||
ConfigMemDef& GetConfigMem();
|
||||
|
||||
u8* GetPtr() override {
|
||||
return reinterpret_cast<u8*>(&config_mem);
|
||||
}
|
||||
|
||||
const u8* GetPtr() const override {
|
||||
return reinterpret_cast<const u8*>(&config_mem);
|
||||
}
|
||||
|
||||
std::size_t GetSize() const override {
|
||||
return sizeof(config_mem);
|
||||
}
|
||||
|
||||
private:
|
||||
ConfigMemDef config_mem;
|
||||
|
||||
friend class boost::serialization::access;
|
||||
template <class Archive>
|
||||
void serialize(Archive& ar, const unsigned int file_version) {
|
||||
ar& boost::serialization::base_object<BackingMem>(*this);
|
||||
ar& boost::serialization::make_binary_object(&config_mem, sizeof(config_mem));
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace ConfigMem
|
||||
|
||||
BOOST_CLASS_EXPORT_KEY(ConfigMem::Handler)
|
||||
|
|
|
@ -5,11 +5,14 @@
|
|||
#include <algorithm>
|
||||
#include <map>
|
||||
#include <vector>
|
||||
#include "common/archives.h"
|
||||
#include "common/assert.h"
|
||||
#include "core/hle/kernel/event.h"
|
||||
#include "core/hle/kernel/kernel.h"
|
||||
#include "core/hle/kernel/thread.h"
|
||||
|
||||
SERIALIZE_EXPORT_IMPL(Kernel::Event)
|
||||
|
||||
namespace Kernel {
|
||||
|
||||
Event::Event(KernelSystem& kernel) : WaitObject(kernel) {}
|
||||
|
|
|
@ -4,6 +4,9 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include <boost/serialization/base_object.hpp>
|
||||
#include <boost/serialization/export.hpp>
|
||||
#include <boost/serialization/string.hpp>
|
||||
#include "common/common_types.h"
|
||||
#include "core/hle/kernel/object.h"
|
||||
#include "core/hle/kernel/wait_object.h"
|
||||
|
@ -49,6 +52,18 @@ private:
|
|||
std::string name; ///< Name of event (optional)
|
||||
|
||||
friend class KernelSystem;
|
||||
|
||||
friend class boost::serialization::access;
|
||||
template <class Archive>
|
||||
void serialize(Archive& ar, const unsigned int file_version) {
|
||||
ar& boost::serialization::base_object<WaitObject>(*this);
|
||||
ar& reset_type;
|
||||
ar& signaled;
|
||||
ar& name;
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace Kernel
|
||||
|
||||
BOOST_CLASS_EXPORT_KEY(Kernel::Event)
|
||||
CONSTRUCT_KERNEL_OBJECT(Kernel::Event)
|
||||
|
|
|
@ -7,6 +7,8 @@
|
|||
#include <array>
|
||||
#include <cstddef>
|
||||
#include <memory>
|
||||
#include <boost/serialization/array.hpp>
|
||||
#include <boost/serialization/shared_ptr.hpp>
|
||||
#include "common/common_types.h"
|
||||
#include "core/hle/kernel/object.h"
|
||||
#include "core/hle/result.h"
|
||||
|
@ -116,6 +118,15 @@ private:
|
|||
u16 next_free_slot;
|
||||
|
||||
KernelSystem& kernel;
|
||||
|
||||
friend class boost::serialization::access;
|
||||
template <class Archive>
|
||||
void serialize(Archive& ar, const unsigned int file_version) {
|
||||
ar& objects;
|
||||
ar& generations;
|
||||
ar& next_generation;
|
||||
ar& next_free_slot;
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace Kernel
|
||||
|
|
|
@ -16,6 +16,47 @@
|
|||
|
||||
namespace Kernel {
|
||||
|
||||
class HLERequestContext::ThreadCallback : public Kernel::WakeupCallback {
|
||||
|
||||
public:
|
||||
ThreadCallback(std::shared_ptr<HLERequestContext> context_,
|
||||
std::shared_ptr<HLERequestContext::WakeupCallback> callback_)
|
||||
: context(std::move(context_)), callback(std::move(callback_)) {}
|
||||
void WakeUp(ThreadWakeupReason reason, std::shared_ptr<Thread> thread,
|
||||
std::shared_ptr<WaitObject> object) {
|
||||
ASSERT(thread->status == ThreadStatus::WaitHleEvent);
|
||||
if (callback) {
|
||||
callback->WakeUp(thread, *context, reason);
|
||||
}
|
||||
|
||||
auto& process = thread->owner_process;
|
||||
// We must copy the entire command buffer *plus* the entire static buffers area, since
|
||||
// the translation might need to read from it in order to retrieve the StaticBuffer
|
||||
// target addresses.
|
||||
std::array<u32_le, IPC::COMMAND_BUFFER_LENGTH + 2 * IPC::MAX_STATIC_BUFFERS> cmd_buff;
|
||||
Memory::MemorySystem& memory = context->kernel.memory;
|
||||
memory.ReadBlock(*process, thread->GetCommandBufferAddress(), cmd_buff.data(),
|
||||
cmd_buff.size() * sizeof(u32));
|
||||
context->WriteToOutgoingCommandBuffer(cmd_buff.data(), *process);
|
||||
// Copy the translated command buffer back into the thread's command buffer area.
|
||||
memory.WriteBlock(*process, thread->GetCommandBufferAddress(), cmd_buff.data(),
|
||||
cmd_buff.size() * sizeof(u32));
|
||||
}
|
||||
|
||||
private:
|
||||
ThreadCallback() = default;
|
||||
std::shared_ptr<HLERequestContext::WakeupCallback> callback{};
|
||||
std::shared_ptr<HLERequestContext> context{};
|
||||
|
||||
template <class Archive>
|
||||
void serialize(Archive& ar, const unsigned int) {
|
||||
ar& boost::serialization::base_object<Kernel::WakeupCallback>(*this);
|
||||
ar& callback;
|
||||
ar& context;
|
||||
}
|
||||
friend class boost::serialization::access;
|
||||
};
|
||||
|
||||
SessionRequestHandler::SessionInfo::SessionInfo(std::shared_ptr<ServerSession> session,
|
||||
std::unique_ptr<SessionDataBase> data)
|
||||
: session(std::move(session)), data(std::move(data)) {}
|
||||
|
@ -33,34 +74,16 @@ void SessionRequestHandler::ClientDisconnected(std::shared_ptr<ServerSession> se
|
|||
connected_sessions.end());
|
||||
}
|
||||
|
||||
std::shared_ptr<Event> HLERequestContext::SleepClientThread(const std::string& reason,
|
||||
std::chrono::nanoseconds timeout,
|
||||
WakeupCallback&& callback) {
|
||||
std::shared_ptr<Event> HLERequestContext::SleepClientThread(
|
||||
const std::string& reason, std::chrono::nanoseconds timeout,
|
||||
std::shared_ptr<WakeupCallback> callback) {
|
||||
// Put the client thread to sleep until the wait event is signaled or the timeout expires.
|
||||
thread->wakeup_callback = [context = *this,
|
||||
callback](ThreadWakeupReason reason, std::shared_ptr<Thread> thread,
|
||||
std::shared_ptr<WaitObject> object) mutable {
|
||||
ASSERT(thread->status == ThreadStatus::WaitHleEvent);
|
||||
callback(thread, context, reason);
|
||||
|
||||
auto& process = thread->owner_process;
|
||||
// We must copy the entire command buffer *plus* the entire static buffers area, since
|
||||
// the translation might need to read from it in order to retrieve the StaticBuffer
|
||||
// target addresses.
|
||||
std::array<u32_le, IPC::COMMAND_BUFFER_LENGTH + 2 * IPC::MAX_STATIC_BUFFERS> cmd_buff;
|
||||
Memory::MemorySystem& memory = context.kernel.memory;
|
||||
memory.ReadBlock(*process, thread->GetCommandBufferAddress(), cmd_buff.data(),
|
||||
cmd_buff.size() * sizeof(u32));
|
||||
context.WriteToOutgoingCommandBuffer(cmd_buff.data(), *process);
|
||||
// Copy the translated command buffer back into the thread's command buffer area.
|
||||
memory.WriteBlock(*process, thread->GetCommandBufferAddress(), cmd_buff.data(),
|
||||
cmd_buff.size() * sizeof(u32));
|
||||
};
|
||||
thread->wakeup_callback = std::make_shared<ThreadCallback>(shared_from_this(), callback);
|
||||
|
||||
auto event = kernel.CreateEvent(Kernel::ResetType::OneShot, "HLE Pause Event: " + reason);
|
||||
thread->status = ThreadStatus::WaitHleEvent;
|
||||
thread->wait_objects = {event};
|
||||
event->AddWaitingThread(SharedFrom(thread));
|
||||
event->AddWaitingThread(thread);
|
||||
|
||||
if (timeout.count() > 0)
|
||||
thread->WakeAfterDelay(timeout.count());
|
||||
|
@ -68,8 +91,10 @@ std::shared_ptr<Event> HLERequestContext::SleepClientThread(const std::string& r
|
|||
return event;
|
||||
}
|
||||
|
||||
HLERequestContext::HLERequestContext() : kernel(Core::Global<KernelSystem>()) {}
|
||||
|
||||
HLERequestContext::HLERequestContext(KernelSystem& kernel, std::shared_ptr<ServerSession> session,
|
||||
Thread* thread)
|
||||
std::shared_ptr<Thread> thread)
|
||||
: kernel(kernel), session(std::move(session)), thread(thread) {
|
||||
cmd_buf[0] = 0;
|
||||
}
|
||||
|
@ -98,8 +123,9 @@ void HLERequestContext::AddStaticBuffer(u8 buffer_id, std::vector<u8> data) {
|
|||
static_buffers[buffer_id] = std::move(data);
|
||||
}
|
||||
|
||||
ResultCode HLERequestContext::PopulateFromIncomingCommandBuffer(const u32_le* src_cmdbuf,
|
||||
Process& src_process) {
|
||||
ResultCode HLERequestContext::PopulateFromIncomingCommandBuffer(
|
||||
const u32_le* src_cmdbuf, std::shared_ptr<Process> src_process_) {
|
||||
auto& src_process = *src_process_;
|
||||
IPC::Header header{src_cmdbuf[0]};
|
||||
|
||||
std::size_t untranslated_size = 1u + header.normal_params_size;
|
||||
|
@ -158,7 +184,7 @@ ResultCode HLERequestContext::PopulateFromIncomingCommandBuffer(const u32_le* sr
|
|||
}
|
||||
case IPC::DescriptorType::MappedBuffer: {
|
||||
u32 next_id = static_cast<u32>(request_mapped_buffers.size());
|
||||
request_mapped_buffers.emplace_back(kernel.memory, src_process, descriptor,
|
||||
request_mapped_buffers.emplace_back(kernel.memory, src_process_, descriptor,
|
||||
src_cmdbuf[i], next_id);
|
||||
cmd_buf[i++] = next_id;
|
||||
break;
|
||||
|
@ -170,7 +196,7 @@ ResultCode HLERequestContext::PopulateFromIncomingCommandBuffer(const u32_le* sr
|
|||
|
||||
if (should_record) {
|
||||
std::vector<u32> translated_cmdbuf{cmd_buf.begin(), cmd_buf.begin() + command_size};
|
||||
kernel.GetIPCRecorder().SetRequestInfo(SharedFrom(thread), std::move(untranslated_cmdbuf),
|
||||
kernel.GetIPCRecorder().SetRequestInfo(thread, std::move(untranslated_cmdbuf),
|
||||
std::move(translated_cmdbuf));
|
||||
}
|
||||
|
||||
|
@ -248,7 +274,7 @@ ResultCode HLERequestContext::WriteToOutgoingCommandBuffer(u32_le* dst_cmdbuf,
|
|||
|
||||
if (should_record) {
|
||||
std::vector<u32> translated_cmdbuf{dst_cmdbuf, dst_cmdbuf + command_size};
|
||||
kernel.GetIPCRecorder().SetReplyInfo(SharedFrom(thread), std::move(untranslated_cmdbuf),
|
||||
kernel.GetIPCRecorder().SetReplyInfo(thread, std::move(untranslated_cmdbuf),
|
||||
std::move(translated_cmdbuf));
|
||||
}
|
||||
|
||||
|
@ -262,13 +288,15 @@ MappedBuffer& HLERequestContext::GetMappedBuffer(u32 id_from_cmdbuf) {
|
|||
|
||||
void HLERequestContext::ReportUnimplemented() const {
|
||||
if (kernel.GetIPCRecorder().IsEnabled()) {
|
||||
kernel.GetIPCRecorder().SetHLEUnimplemented(SharedFrom(thread));
|
||||
kernel.GetIPCRecorder().SetHLEUnimplemented(thread);
|
||||
}
|
||||
}
|
||||
|
||||
MappedBuffer::MappedBuffer(Memory::MemorySystem& memory, const Process& process, u32 descriptor,
|
||||
VAddr address, u32 id)
|
||||
: memory(&memory), id(id), address(address), process(&process) {
|
||||
MappedBuffer::MappedBuffer() : memory(&Core::Global<Core::System>().Memory()) {}
|
||||
|
||||
MappedBuffer::MappedBuffer(Memory::MemorySystem& memory, std::shared_ptr<Process> process,
|
||||
u32 descriptor, VAddr address, u32 id)
|
||||
: memory(&memory), id(id), address(address), process(std::move(process)) {
|
||||
IPC::MappedBufferDescInfo desc{descriptor};
|
||||
size = desc.size;
|
||||
perms = desc.perms;
|
||||
|
@ -287,3 +315,5 @@ void MappedBuffer::Write(const void* src_buffer, std::size_t offset, std::size_t
|
|||
}
|
||||
|
||||
} // namespace Kernel
|
||||
|
||||
SERIALIZE_EXPORT_IMPL(Kernel::HLERequestContext::ThreadCallback)
|
||||
|
|
|
@ -11,7 +11,12 @@
|
|||
#include <string>
|
||||
#include <vector>
|
||||
#include <boost/container/small_vector.hpp>
|
||||
#include <boost/serialization/assume_abstract.hpp>
|
||||
#include <boost/serialization/shared_ptr.hpp>
|
||||
#include <boost/serialization/unique_ptr.hpp>
|
||||
#include <boost/serialization/vector.hpp>
|
||||
#include "common/common_types.h"
|
||||
#include "common/serialization/boost_small_vector.hpp"
|
||||
#include "common/swap.h"
|
||||
#include "core/hle/ipc.h"
|
||||
#include "core/hle/kernel/object.h"
|
||||
|
@ -68,6 +73,11 @@ public:
|
|||
/// in each service must inherit from this.
|
||||
struct SessionDataBase {
|
||||
virtual ~SessionDataBase() = default;
|
||||
|
||||
private:
|
||||
template <class Archive>
|
||||
void serialize(Archive& ar, const unsigned int file_version) {}
|
||||
friend class boost::serialization::access;
|
||||
};
|
||||
|
||||
protected:
|
||||
|
@ -90,15 +100,33 @@ protected:
|
|||
|
||||
std::shared_ptr<ServerSession> session;
|
||||
std::unique_ptr<SessionDataBase> data;
|
||||
|
||||
private:
|
||||
SessionInfo() = default;
|
||||
template <class Archive>
|
||||
void serialize(Archive& ar, const unsigned int file_version) {
|
||||
ar& session;
|
||||
ar& data;
|
||||
}
|
||||
friend class boost::serialization::access;
|
||||
};
|
||||
/// List of sessions that are connected to this handler. A ServerSession whose server endpoint
|
||||
/// is an HLE implementation is kept alive by this list for the duration of the connection.
|
||||
std::vector<SessionInfo> connected_sessions;
|
||||
|
||||
private:
|
||||
template <class Archive>
|
||||
void serialize(Archive& ar, const unsigned int file_version) {
|
||||
ar& connected_sessions;
|
||||
}
|
||||
friend class boost::serialization::access;
|
||||
};
|
||||
|
||||
// NOTE: The below classes are ephemeral and don't need serialization
|
||||
|
||||
class MappedBuffer {
|
||||
public:
|
||||
MappedBuffer(Memory::MemorySystem& memory, const Process& process, u32 descriptor,
|
||||
MappedBuffer(Memory::MemorySystem& memory, std::shared_ptr<Process> process, u32 descriptor,
|
||||
VAddr address, u32 id);
|
||||
|
||||
// interface for service
|
||||
|
@ -122,9 +150,21 @@ private:
|
|||
Memory::MemorySystem* memory;
|
||||
u32 id;
|
||||
VAddr address;
|
||||
const Process* process;
|
||||
std::size_t size;
|
||||
std::shared_ptr<Process> process;
|
||||
u32 size;
|
||||
IPC::MappedBufferPermissions perms;
|
||||
|
||||
MappedBuffer();
|
||||
|
||||
template <class Archive>
|
||||
void serialize(Archive& ar, const unsigned int) {
|
||||
ar& id;
|
||||
ar& address;
|
||||
ar& process;
|
||||
ar& size;
|
||||
ar& perms;
|
||||
}
|
||||
friend class boost::serialization::access;
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -156,9 +196,10 @@ private:
|
|||
* id of the memory interface and let kernel convert it back to client vaddr. No real unmapping is
|
||||
* needed in this case, though.
|
||||
*/
|
||||
class HLERequestContext {
|
||||
class HLERequestContext : public std::enable_shared_from_this<HLERequestContext> {
|
||||
public:
|
||||
HLERequestContext(KernelSystem& kernel, std::shared_ptr<ServerSession> session, Thread* thread);
|
||||
HLERequestContext(KernelSystem& kernel, std::shared_ptr<ServerSession> session,
|
||||
std::shared_ptr<Thread> thread);
|
||||
~HLERequestContext();
|
||||
|
||||
/// Returns a pointer to the IPC command buffer for this request.
|
||||
|
@ -174,8 +215,17 @@ public:
|
|||
return session;
|
||||
}
|
||||
|
||||
using WakeupCallback = std::function<void(
|
||||
std::shared_ptr<Thread> thread, HLERequestContext& context, ThreadWakeupReason reason)>;
|
||||
class WakeupCallback {
|
||||
public:
|
||||
virtual ~WakeupCallback() = default;
|
||||
virtual void WakeUp(std::shared_ptr<Thread> thread, HLERequestContext& context,
|
||||
ThreadWakeupReason reason) = 0;
|
||||
|
||||
private:
|
||||
template <class Archive>
|
||||
void serialize(Archive& ar, const unsigned int) {}
|
||||
friend class boost::serialization::access;
|
||||
};
|
||||
|
||||
/**
|
||||
* Puts the specified guest thread to sleep until the returned event is signaled or until the
|
||||
|
@ -190,7 +240,7 @@ public:
|
|||
*/
|
||||
std::shared_ptr<Event> SleepClientThread(const std::string& reason,
|
||||
std::chrono::nanoseconds timeout,
|
||||
WakeupCallback&& callback);
|
||||
std::shared_ptr<WakeupCallback> callback);
|
||||
|
||||
/**
|
||||
* Resolves a object id from the request command buffer into a pointer to an object. See the
|
||||
|
@ -230,24 +280,42 @@ public:
|
|||
MappedBuffer& GetMappedBuffer(u32 id_from_cmdbuf);
|
||||
|
||||
/// Populates this context with data from the requesting process/thread.
|
||||
ResultCode PopulateFromIncomingCommandBuffer(const u32_le* src_cmdbuf, Process& src_process);
|
||||
ResultCode PopulateFromIncomingCommandBuffer(const u32_le* src_cmdbuf,
|
||||
std::shared_ptr<Process> src_process);
|
||||
/// Writes data from this context back to the requesting process/thread.
|
||||
ResultCode WriteToOutgoingCommandBuffer(u32_le* dst_cmdbuf, Process& dst_process) const;
|
||||
|
||||
/// Reports an unimplemented function.
|
||||
void ReportUnimplemented() const;
|
||||
|
||||
class ThreadCallback;
|
||||
friend class ThreadCallback;
|
||||
|
||||
private:
|
||||
KernelSystem& kernel;
|
||||
std::array<u32, IPC::COMMAND_BUFFER_LENGTH> cmd_buf;
|
||||
std::shared_ptr<ServerSession> session;
|
||||
Thread* thread;
|
||||
std::shared_ptr<Thread> thread;
|
||||
// TODO(yuriks): Check common usage of this and optimize size accordingly
|
||||
boost::container::small_vector<std::shared_ptr<Object>, 8> request_handles;
|
||||
// The static buffers will be created when the IPC request is translated.
|
||||
std::array<std::vector<u8>, IPC::MAX_STATIC_BUFFERS> static_buffers;
|
||||
// The mapped buffers will be created when the IPC request is translated
|
||||
boost::container::small_vector<MappedBuffer, 8> request_mapped_buffers;
|
||||
|
||||
HLERequestContext();
|
||||
template <class Archive>
|
||||
void serialize(Archive& ar, const unsigned int) {
|
||||
ar& cmd_buf;
|
||||
ar& session;
|
||||
ar& thread;
|
||||
ar& request_handles;
|
||||
ar& static_buffers;
|
||||
ar& request_mapped_buffers;
|
||||
}
|
||||
friend class boost::serialization::access;
|
||||
};
|
||||
|
||||
} // namespace Kernel
|
||||
|
||||
BOOST_CLASS_EXPORT_KEY(Kernel::HLERequestContext::ThreadCallback)
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
|
||||
#include <algorithm>
|
||||
#include "common/alignment.h"
|
||||
#include "common/memory_ref.h"
|
||||
#include "core/core.h"
|
||||
#include "core/hle/ipc.h"
|
||||
#include "core/hle/kernel/handle_table.h"
|
||||
|
@ -71,7 +72,7 @@ ResultCode TranslateCommandBuffer(Kernel::KernelSystem& kernel, Memory::MemorySy
|
|||
if (handle == CurrentThread) {
|
||||
object = src_thread;
|
||||
} else if (handle == CurrentProcess) {
|
||||
object = SharedFrom(src_process);
|
||||
object = src_process;
|
||||
} else if (handle != 0) {
|
||||
object = src_process->handle_table.GetGeneric(handle);
|
||||
if (descriptor == IPC::DescriptorType::MoveHandle) {
|
||||
|
@ -193,28 +194,29 @@ ResultCode TranslateCommandBuffer(Kernel::KernelSystem& kernel, Memory::MemorySy
|
|||
// TODO(Subv): Perform permission checks.
|
||||
|
||||
// Reserve a page of memory before the mapped buffer
|
||||
auto reserve_buffer = std::make_unique<u8[]>(Memory::PAGE_SIZE);
|
||||
std::shared_ptr<BackingMem> reserve_buffer =
|
||||
std::make_shared<BufferMem>(Memory::PAGE_SIZE);
|
||||
dst_process->vm_manager.MapBackingMemoryToBase(
|
||||
Memory::IPC_MAPPING_VADDR, Memory::IPC_MAPPING_SIZE, reserve_buffer.get(),
|
||||
Memory::IPC_MAPPING_VADDR, Memory::IPC_MAPPING_SIZE, reserve_buffer,
|
||||
Memory::PAGE_SIZE, Kernel::MemoryState::Reserved);
|
||||
|
||||
auto buffer = std::make_unique<u8[]>(num_pages * Memory::PAGE_SIZE);
|
||||
memory.ReadBlock(*src_process, source_address, buffer.get() + page_offset, size);
|
||||
std::shared_ptr<BackingMem> buffer =
|
||||
std::make_shared<BufferMem>(num_pages * Memory::PAGE_SIZE);
|
||||
memory.ReadBlock(*src_process, source_address, buffer->GetPtr() + page_offset, size);
|
||||
|
||||
// Map the page(s) into the target process' address space.
|
||||
target_address =
|
||||
dst_process->vm_manager
|
||||
.MapBackingMemoryToBase(Memory::IPC_MAPPING_VADDR, Memory::IPC_MAPPING_SIZE,
|
||||
buffer.get(), num_pages * Memory::PAGE_SIZE,
|
||||
Kernel::MemoryState::Shared)
|
||||
buffer, buffer->GetSize(), Kernel::MemoryState::Shared)
|
||||
.Unwrap();
|
||||
|
||||
cmd_buf[i++] = target_address + page_offset;
|
||||
|
||||
// Reserve a page of memory after the mapped buffer
|
||||
dst_process->vm_manager.MapBackingMemoryToBase(
|
||||
Memory::IPC_MAPPING_VADDR, Memory::IPC_MAPPING_SIZE, reserve_buffer.get(),
|
||||
Memory::PAGE_SIZE, Kernel::MemoryState::Reserved);
|
||||
Memory::IPC_MAPPING_VADDR, Memory::IPC_MAPPING_SIZE, reserve_buffer,
|
||||
reserve_buffer->GetSize(), Kernel::MemoryState::Reserved);
|
||||
|
||||
mapped_buffer_context.push_back({permissions, size, source_address,
|
||||
target_address + page_offset, std::move(buffer),
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
#include <boost/serialization/shared_ptr.hpp>
|
||||
#include "common/common_types.h"
|
||||
#include "core/hle/ipc.h"
|
||||
#include "core/hle/kernel/thread.h"
|
||||
|
@ -24,8 +25,20 @@ struct MappedBufferContext {
|
|||
VAddr source_address;
|
||||
VAddr target_address;
|
||||
|
||||
std::unique_ptr<u8[]> buffer;
|
||||
std::unique_ptr<u8[]> reserve_buffer;
|
||||
std::shared_ptr<BackingMem> buffer;
|
||||
std::shared_ptr<BackingMem> reserve_buffer;
|
||||
|
||||
private:
|
||||
template <class Archive>
|
||||
void serialize(Archive& ar, const unsigned int file_version) {
|
||||
ar& permissions;
|
||||
ar& size;
|
||||
ar& source_address;
|
||||
ar& target_address;
|
||||
ar& buffer;
|
||||
ar& reserve_buffer;
|
||||
}
|
||||
friend class boost::serialization::access;
|
||||
};
|
||||
|
||||
/// Performs IPC command buffer translation from one process to another.
|
||||
|
|
|
@ -52,7 +52,7 @@ void Recorder::RegisterRequest(const std::shared_ptr<Kernel::ClientSession>& cli
|
|||
|
||||
RequestRecord record = {/* id */ ++record_count,
|
||||
/* status */ RequestStatus::Sent,
|
||||
/* client_process */ GetObjectInfo(client_thread->owner_process),
|
||||
/* client_process */ GetObjectInfo(client_thread->owner_process.get()),
|
||||
/* client_thread */ GetObjectInfo(client_thread.get()),
|
||||
/* client_session */ GetObjectInfo(client_session.get()),
|
||||
/* client_port */ GetObjectInfo(client_session->parent->port.get()),
|
||||
|
@ -82,7 +82,7 @@ void Recorder::SetRequestInfo(const std::shared_ptr<Kernel::Thread>& client_thre
|
|||
record.translated_request_cmdbuf = std::move(translated_cmdbuf);
|
||||
|
||||
if (server_thread) {
|
||||
record.server_process = GetObjectInfo(server_thread->owner_process);
|
||||
record.server_process = GetObjectInfo(server_thread->owner_process.get());
|
||||
record.server_thread = GetObjectInfo(server_thread.get());
|
||||
} else {
|
||||
record.is_hle = true;
|
||||
|
|
|
@ -2,6 +2,11 @@
|
|||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#include <boost/serialization/shared_ptr.hpp>
|
||||
#include <boost/serialization/unordered_map.hpp>
|
||||
#include <boost/serialization/vector.hpp>
|
||||
#include "common/archives.h"
|
||||
#include "common/serialization/atomic.h"
|
||||
#include "core/hle/kernel/client_port.h"
|
||||
#include "core/hle/kernel/config_mem.h"
|
||||
#include "core/hle/kernel/handle_table.h"
|
||||
|
@ -22,6 +27,8 @@ KernelSystem::KernelSystem(Memory::MemorySystem& memory, Core::Timing& timing,
|
|||
u32 num_cores, u8 n3ds_mode)
|
||||
: memory(memory), timing(timing),
|
||||
prepare_reschedule_callback(std::move(prepare_reschedule_callback)) {
|
||||
std::generate(memory_regions.begin(), memory_regions.end(),
|
||||
[] { return std::make_shared<MemoryRegionInfo>(); });
|
||||
MemoryInit(system_mode, n3ds_mode);
|
||||
|
||||
resource_limits = std::make_unique<ResourceLimitList>(*this);
|
||||
|
@ -58,24 +65,23 @@ std::shared_ptr<Process> KernelSystem::GetCurrentProcess() const {
|
|||
|
||||
void KernelSystem::SetCurrentProcess(std::shared_ptr<Process> process) {
|
||||
current_process = process;
|
||||
SetCurrentMemoryPageTable(&process->vm_manager.page_table);
|
||||
SetCurrentMemoryPageTable(process->vm_manager.page_table);
|
||||
}
|
||||
|
||||
void KernelSystem::SetCurrentProcessForCPU(std::shared_ptr<Process> process, u32 core_id) {
|
||||
if (current_cpu->GetID() == core_id) {
|
||||
current_process = process;
|
||||
SetCurrentMemoryPageTable(&process->vm_manager.page_table);
|
||||
SetCurrentMemoryPageTable(process->vm_manager.page_table);
|
||||
} else {
|
||||
stored_processes[core_id] = process;
|
||||
thread_managers[core_id]->cpu->PageTableChanged(&process->vm_manager.page_table);
|
||||
thread_managers[core_id]->cpu->SetPageTable(process->vm_manager.page_table);
|
||||
}
|
||||
}
|
||||
|
||||
void KernelSystem::SetCurrentMemoryPageTable(Memory::PageTable* page_table) {
|
||||
void KernelSystem::SetCurrentMemoryPageTable(std::shared_ptr<Memory::PageTable> page_table) {
|
||||
memory.SetCurrentPageTable(page_table);
|
||||
if (current_cpu != nullptr) {
|
||||
// Notify the CPU the page table in memory has changed
|
||||
current_cpu->PageTableChanged(page_table);
|
||||
current_cpu->SetPageTable(page_table);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -150,4 +156,29 @@ void KernelSystem::ResetThreadIDs() {
|
|||
next_thread_id = 0;
|
||||
}
|
||||
|
||||
template <class Archive>
|
||||
void KernelSystem::serialize(Archive& ar, const unsigned int file_version) {
|
||||
ar& memory_regions;
|
||||
ar& named_ports;
|
||||
// current_cpu set externally
|
||||
// NB: subsystem references and prepare_reschedule_callback are constant
|
||||
ar&* resource_limits.get();
|
||||
ar& next_object_id;
|
||||
ar&* timer_manager.get();
|
||||
ar& next_process_id;
|
||||
ar& process_list;
|
||||
ar& current_process;
|
||||
// NB: core count checked in 'core'
|
||||
for (auto& thread_manager : thread_managers) {
|
||||
ar&* thread_manager.get();
|
||||
}
|
||||
ar& config_mem_handler;
|
||||
ar& shared_page_handler;
|
||||
ar& stored_processes;
|
||||
ar& next_thread_id;
|
||||
// Deliberately don't include debugger info to allow debugging through loads
|
||||
}
|
||||
|
||||
SERIALIZE_IMPL(KernelSystem)
|
||||
|
||||
} // namespace Kernel
|
||||
|
|
|
@ -132,7 +132,8 @@ public:
|
|||
*/
|
||||
ResultVal<std::shared_ptr<Thread>> CreateThread(std::string name, VAddr entry_point,
|
||||
u32 priority, u32 arg, s32 processor_id,
|
||||
VAddr stack_top, Process& owner_process);
|
||||
VAddr stack_top,
|
||||
std::shared_ptr<Process> owner_process);
|
||||
|
||||
/**
|
||||
* Creates a semaphore.
|
||||
|
@ -213,7 +214,7 @@ public:
|
|||
void SetCurrentProcess(std::shared_ptr<Process> process);
|
||||
void SetCurrentProcessForCPU(std::shared_ptr<Process> process, u32 core_id);
|
||||
|
||||
void SetCurrentMemoryPageTable(Memory::PageTable* page_table);
|
||||
void SetCurrentMemoryPageTable(std::shared_ptr<Memory::PageTable> page_table);
|
||||
|
||||
void SetCPUs(std::vector<std::shared_ptr<ARM_Interface>> cpu);
|
||||
|
||||
|
@ -236,11 +237,11 @@ public:
|
|||
IPCDebugger::Recorder& GetIPCRecorder();
|
||||
const IPCDebugger::Recorder& GetIPCRecorder() const;
|
||||
|
||||
MemoryRegionInfo* GetMemoryRegion(MemoryRegion region);
|
||||
std::shared_ptr<MemoryRegionInfo> GetMemoryRegion(MemoryRegion region);
|
||||
|
||||
void HandleSpecialMapping(VMManager& address_space, const AddressMapping& mapping);
|
||||
|
||||
std::array<MemoryRegionInfo, 3> memory_regions;
|
||||
std::array<std::shared_ptr<MemoryRegionInfo>, 3> memory_regions{};
|
||||
|
||||
/// Adds a port to the named port table
|
||||
void AddNamedPort(std::string name, std::shared_ptr<ClientPort> port);
|
||||
|
@ -291,12 +292,16 @@ private:
|
|||
|
||||
std::vector<std::unique_ptr<ThreadManager>> thread_managers;
|
||||
|
||||
std::unique_ptr<ConfigMem::Handler> config_mem_handler;
|
||||
std::unique_ptr<SharedPage::Handler> shared_page_handler;
|
||||
std::shared_ptr<ConfigMem::Handler> config_mem_handler;
|
||||
std::shared_ptr<SharedPage::Handler> shared_page_handler;
|
||||
|
||||
std::unique_ptr<IPCDebugger::Recorder> ipc_recorder;
|
||||
|
||||
u32 next_thread_id;
|
||||
|
||||
friend class boost::serialization::access;
|
||||
template <class Archive>
|
||||
void serialize(Archive& ar, const unsigned int file_version);
|
||||
};
|
||||
|
||||
} // namespace Kernel
|
||||
|
|
|
@ -71,32 +71,32 @@ void KernelSystem::MemoryInit(u32 mem_type, u8 n3ds_mode) {
|
|||
// the sizes specified in the memory_region_sizes table.
|
||||
VAddr base = 0;
|
||||
for (int i = 0; i < 3; ++i) {
|
||||
memory_regions[i].Reset(base, memory_region_sizes[mem_type][i]);
|
||||
memory_regions[i]->Reset(base, memory_region_sizes[mem_type][i]);
|
||||
|
||||
base += memory_regions[i].size;
|
||||
base += memory_regions[i]->size;
|
||||
}
|
||||
|
||||
// We must've allocated the entire FCRAM by the end
|
||||
ASSERT(base == (is_new_3ds ? Memory::FCRAM_N3DS_SIZE : Memory::FCRAM_SIZE));
|
||||
|
||||
config_mem_handler = std::make_unique<ConfigMem::Handler>();
|
||||
config_mem_handler = std::make_shared<ConfigMem::Handler>();
|
||||
auto& config_mem = config_mem_handler->GetConfigMem();
|
||||
config_mem.app_mem_type = reported_mem_type;
|
||||
config_mem.app_mem_alloc = memory_region_sizes[reported_mem_type][0];
|
||||
config_mem.sys_mem_alloc = memory_regions[1].size;
|
||||
config_mem.base_mem_alloc = memory_regions[2].size;
|
||||
config_mem.sys_mem_alloc = memory_regions[1]->size;
|
||||
config_mem.base_mem_alloc = memory_regions[2]->size;
|
||||
|
||||
shared_page_handler = std::make_unique<SharedPage::Handler>(timing);
|
||||
shared_page_handler = std::make_shared<SharedPage::Handler>(timing);
|
||||
}
|
||||
|
||||
MemoryRegionInfo* KernelSystem::GetMemoryRegion(MemoryRegion region) {
|
||||
std::shared_ptr<MemoryRegionInfo> KernelSystem::GetMemoryRegion(MemoryRegion region) {
|
||||
switch (region) {
|
||||
case MemoryRegion::APPLICATION:
|
||||
return &memory_regions[0];
|
||||
return memory_regions[0];
|
||||
case MemoryRegion::SYSTEM:
|
||||
return &memory_regions[1];
|
||||
return memory_regions[1];
|
||||
case MemoryRegion::BASE:
|
||||
return &memory_regions[2];
|
||||
return memory_regions[2];
|
||||
default:
|
||||
UNREACHABLE();
|
||||
}
|
||||
|
@ -147,7 +147,7 @@ void KernelSystem::HandleSpecialMapping(VMManager& address_space, const AddressM
|
|||
return;
|
||||
}
|
||||
|
||||
u8* target_pointer = memory.GetPhysicalPointer(area->paddr_base + offset_into_region);
|
||||
auto target_pointer = memory.GetPhysicalRef(area->paddr_base + offset_into_region);
|
||||
|
||||
// TODO(yuriks): This flag seems to have some other effect, but it's unknown what
|
||||
MemoryState memory_state = mapping.unk_flag ? MemoryState::Static : MemoryState::IO;
|
||||
|
@ -160,20 +160,16 @@ void KernelSystem::HandleSpecialMapping(VMManager& address_space, const AddressM
|
|||
}
|
||||
|
||||
void KernelSystem::MapSharedPages(VMManager& address_space) {
|
||||
auto cfg_mem_vma =
|
||||
address_space
|
||||
.MapBackingMemory(Memory::CONFIG_MEMORY_VADDR,
|
||||
reinterpret_cast<u8*>(&config_mem_handler->GetConfigMem()),
|
||||
Memory::CONFIG_MEMORY_SIZE, MemoryState::Shared)
|
||||
.Unwrap();
|
||||
auto cfg_mem_vma = address_space
|
||||
.MapBackingMemory(Memory::CONFIG_MEMORY_VADDR, {config_mem_handler},
|
||||
Memory::CONFIG_MEMORY_SIZE, MemoryState::Shared)
|
||||
.Unwrap();
|
||||
address_space.Reprotect(cfg_mem_vma, VMAPermission::Read);
|
||||
|
||||
auto shared_page_vma =
|
||||
address_space
|
||||
.MapBackingMemory(Memory::SHARED_PAGE_VADDR,
|
||||
reinterpret_cast<u8*>(&shared_page_handler->GetSharedPage()),
|
||||
Memory::SHARED_PAGE_SIZE, MemoryState::Shared)
|
||||
.Unwrap();
|
||||
auto shared_page_vma = address_space
|
||||
.MapBackingMemory(Memory::SHARED_PAGE_VADDR, {shared_page_handler},
|
||||
Memory::SHARED_PAGE_SIZE, MemoryState::Shared)
|
||||
.Unwrap();
|
||||
address_space.Reprotect(shared_page_vma, VMAPermission::Read);
|
||||
}
|
||||
|
||||
|
|
|
@ -6,7 +6,9 @@
|
|||
|
||||
#include <optional>
|
||||
#include <boost/icl/interval_set.hpp>
|
||||
#include <boost/serialization/set.hpp>
|
||||
#include "common/common_types.h"
|
||||
#include "common/serialization/boost_interval_set.hpp"
|
||||
|
||||
namespace Kernel {
|
||||
|
||||
|
@ -60,6 +62,16 @@ struct MemoryRegionInfo {
|
|||
* @param size the size of the region to free.
|
||||
*/
|
||||
void Free(u32 offset, u32 size);
|
||||
|
||||
private:
|
||||
friend class boost::serialization::access;
|
||||
template <class Archive>
|
||||
void serialize(Archive& ar, const unsigned int file_version) {
|
||||
ar& base;
|
||||
ar& size;
|
||||
ar& used;
|
||||
ar& free_blocks;
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace Kernel
|
||||
|
|
|
@ -4,14 +4,18 @@
|
|||
|
||||
#include <map>
|
||||
#include <vector>
|
||||
#include "common/archives.h"
|
||||
#include "common/assert.h"
|
||||
#include "core/core.h"
|
||||
#include "core/global.h"
|
||||
#include "core/hle/kernel/errors.h"
|
||||
#include "core/hle/kernel/kernel.h"
|
||||
#include "core/hle/kernel/mutex.h"
|
||||
#include "core/hle/kernel/object.h"
|
||||
#include "core/hle/kernel/thread.h"
|
||||
|
||||
SERIALIZE_EXPORT_IMPL(Kernel::Mutex)
|
||||
|
||||
namespace Kernel {
|
||||
|
||||
void ReleaseThreadMutexes(Thread* thread) {
|
||||
|
|
|
@ -6,6 +6,10 @@
|
|||
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <boost/serialization/base_object.hpp>
|
||||
#include <boost/serialization/export.hpp>
|
||||
#include <boost/serialization/shared_ptr.hpp>
|
||||
#include <boost/serialization/string.hpp>
|
||||
#include "common/common_types.h"
|
||||
#include "core/hle/kernel/kernel.h"
|
||||
#include "core/hle/kernel/wait_object.h"
|
||||
|
@ -58,6 +62,16 @@ public:
|
|||
|
||||
private:
|
||||
KernelSystem& kernel;
|
||||
|
||||
friend class boost::serialization::access;
|
||||
template <class Archive>
|
||||
void serialize(Archive& ar, const unsigned int file_version) {
|
||||
ar& boost::serialization::base_object<WaitObject>(*this);
|
||||
ar& lock_count;
|
||||
ar& priority;
|
||||
ar& name;
|
||||
ar& holding_thread;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -67,3 +81,6 @@ private:
|
|||
void ReleaseThreadMutexes(Thread* thread);
|
||||
|
||||
} // namespace Kernel
|
||||
|
||||
BOOST_CLASS_EXPORT_KEY(Kernel::Mutex)
|
||||
CONSTRUCT_KERNEL_OBJECT(Kernel::Mutex)
|
||||
|
|
|
@ -7,7 +7,12 @@
|
|||
#include <atomic>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <boost/serialization/access.hpp>
|
||||
#include <boost/serialization/assume_abstract.hpp>
|
||||
#include <boost/serialization/export.hpp>
|
||||
#include "common/common_types.h"
|
||||
#include "common/serialization/atomic.h"
|
||||
#include "core/global.h"
|
||||
#include "core/hle/kernel/kernel.h"
|
||||
|
||||
namespace Kernel {
|
||||
|
@ -64,6 +69,12 @@ public:
|
|||
|
||||
private:
|
||||
std::atomic<u32> object_id;
|
||||
|
||||
friend class boost::serialization::access;
|
||||
template <class Archive>
|
||||
void serialize(Archive& ar, const unsigned int file_version) {
|
||||
ar& object_id;
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
|
@ -87,3 +98,13 @@ inline std::shared_ptr<T> DynamicObjectCast(std::shared_ptr<Object> object) {
|
|||
}
|
||||
|
||||
} // namespace Kernel
|
||||
|
||||
BOOST_SERIALIZATION_ASSUME_ABSTRACT(Kernel::Object)
|
||||
|
||||
#define CONSTRUCT_KERNEL_OBJECT(T) \
|
||||
namespace boost::serialization { \
|
||||
template <class Archive> \
|
||||
void load_construct_data(Archive& ar, T* t, const unsigned int file_version) { \
|
||||
::new (t) T(Core::Global<Kernel::KernelSystem>()); \
|
||||
} \
|
||||
}
|
||||
|
|
|
@ -4,9 +4,14 @@
|
|||
|
||||
#include <algorithm>
|
||||
#include <memory>
|
||||
#include <boost/serialization/array.hpp>
|
||||
#include <boost/serialization/bitset.hpp>
|
||||
#include <boost/serialization/shared_ptr.hpp>
|
||||
#include "common/archives.h"
|
||||
#include "common/assert.h"
|
||||
#include "common/common_funcs.h"
|
||||
#include "common/logging/log.h"
|
||||
#include "common/serialization/boost_vector.hpp"
|
||||
#include "core/hle/kernel/errors.h"
|
||||
#include "core/hle/kernel/memory.h"
|
||||
#include "core/hle/kernel/process.h"
|
||||
|
@ -15,8 +20,34 @@
|
|||
#include "core/hle/kernel/vm_manager.h"
|
||||
#include "core/memory.h"
|
||||
|
||||
SERIALIZE_EXPORT_IMPL(Kernel::Process)
|
||||
SERIALIZE_EXPORT_IMPL(Kernel::CodeSet)
|
||||
|
||||
namespace Kernel {
|
||||
|
||||
template <class Archive>
|
||||
void Process::serialize(Archive& ar, const unsigned int file_version) {
|
||||
ar& boost::serialization::base_object<Object>(*this);
|
||||
ar& handle_table;
|
||||
ar& codeset; // TODO: Replace with apploader reference
|
||||
ar& resource_limit;
|
||||
ar& svc_access_mask;
|
||||
ar& handle_table_size;
|
||||
ar&(boost::container::vector<AddressMapping, boost::container::dtl::static_storage_allocator<
|
||||
AddressMapping, 8, 0, true>>&)address_mappings;
|
||||
ar& flags.raw;
|
||||
ar& kernel_version;
|
||||
ar& ideal_processor;
|
||||
ar& status;
|
||||
ar& process_id;
|
||||
ar& vm_manager;
|
||||
ar& memory_used;
|
||||
ar& memory_region;
|
||||
ar& tls_slots;
|
||||
}
|
||||
|
||||
SERIALIZE_IMPL(Process)
|
||||
|
||||
std::shared_ptr<CodeSet> KernelSystem::CreateCodeSet(std::string name, u64 program_id) {
|
||||
auto codeset{std::make_shared<CodeSet>(*this)};
|
||||
|
||||
|
@ -191,7 +222,7 @@ ResultVal<VAddr> Process::HeapAllocate(VAddr target, u32 size, VMAPermission per
|
|||
std::fill(kernel.memory.GetFCRAMPointer(interval.lower()),
|
||||
kernel.memory.GetFCRAMPointer(interval.upper()), 0);
|
||||
auto vma = vm_manager.MapBackingMemory(interval_target,
|
||||
kernel.memory.GetFCRAMPointer(interval.lower()),
|
||||
kernel.memory.GetFCRAMRef(interval.lower()),
|
||||
interval_size, memory_state);
|
||||
ASSERT(vma.Succeeded());
|
||||
vm_manager.Reprotect(vma.Unwrap(), perms);
|
||||
|
@ -219,7 +250,7 @@ ResultCode Process::HeapFree(VAddr target, u32 size) {
|
|||
// Free heaps block by block
|
||||
CASCADE_RESULT(auto backing_blocks, vm_manager.GetBackingBlocksForRange(target, size));
|
||||
for (const auto [backing_memory, block_size] : backing_blocks) {
|
||||
memory_region->Free(kernel.memory.GetFCRAMOffset(backing_memory), block_size);
|
||||
memory_region->Free(kernel.memory.GetFCRAMOffset(backing_memory.GetPtr()), block_size);
|
||||
}
|
||||
|
||||
ResultCode result = vm_manager.UnmapRange(target, size);
|
||||
|
@ -263,9 +294,9 @@ ResultVal<VAddr> Process::LinearAllocate(VAddr target, u32 size, VMAPermission p
|
|||
}
|
||||
}
|
||||
|
||||
u8* backing_memory = kernel.memory.GetFCRAMPointer(physical_offset);
|
||||
auto backing_memory = kernel.memory.GetFCRAMRef(physical_offset);
|
||||
|
||||
std::fill(backing_memory, backing_memory + size, 0);
|
||||
std::fill(backing_memory.GetPtr(), backing_memory.GetPtr() + size, 0);
|
||||
auto vma = vm_manager.MapBackingMemory(target, backing_memory, size, MemoryState::Continuous);
|
||||
ASSERT(vma.Succeeded());
|
||||
vm_manager.Reprotect(vma.Unwrap(), perms);
|
||||
|
@ -403,8 +434,7 @@ ResultCode Process::Unmap(VAddr target, VAddr source, u32 size, VMAPermission pe
|
|||
|
||||
Kernel::Process::Process(KernelSystem& kernel)
|
||||
: Object(kernel), handle_table(kernel), vm_manager(kernel.memory), kernel(kernel) {
|
||||
|
||||
kernel.memory.RegisterPageTable(&vm_manager.page_table);
|
||||
kernel.memory.RegisterPageTable(vm_manager.page_table);
|
||||
}
|
||||
Kernel::Process::~Process() {
|
||||
// Release all objects this process owns first so that their potential destructor can do clean
|
||||
|
@ -413,7 +443,7 @@ Kernel::Process::~Process() {
|
|||
// memory etc.) even if they are still referenced by other processes.
|
||||
handle_table.Clear();
|
||||
|
||||
kernel.memory.UnregisterPageTable(&vm_manager.page_table);
|
||||
kernel.memory.UnregisterPageTable(vm_manager.page_table);
|
||||
}
|
||||
|
||||
std::shared_ptr<Process> KernelSystem::GetProcessById(u32 process_id) const {
|
||||
|
|
|
@ -11,6 +11,10 @@
|
|||
#include <string>
|
||||
#include <vector>
|
||||
#include <boost/container/static_vector.hpp>
|
||||
#include <boost/serialization/array.hpp>
|
||||
#include <boost/serialization/base_object.hpp>
|
||||
#include <boost/serialization/string.hpp>
|
||||
#include <boost/serialization/vector.hpp>
|
||||
#include "common/bit_field.h"
|
||||
#include "common/common_types.h"
|
||||
#include "core/hle/kernel/handle_table.h"
|
||||
|
@ -25,6 +29,16 @@ struct AddressMapping {
|
|||
u32 size;
|
||||
bool read_only;
|
||||
bool unk_flag;
|
||||
|
||||
private:
|
||||
friend class boost::serialization::access;
|
||||
template <class Archive>
|
||||
void serialize(Archive& ar, const unsigned int file_version) {
|
||||
ar& address;
|
||||
ar& size;
|
||||
ar& read_only;
|
||||
ar& unk_flag;
|
||||
}
|
||||
};
|
||||
|
||||
union ProcessFlags {
|
||||
|
@ -59,6 +73,15 @@ public:
|
|||
std::size_t offset = 0;
|
||||
VAddr addr = 0;
|
||||
u32 size = 0;
|
||||
|
||||
private:
|
||||
friend class boost::serialization::access;
|
||||
template <class Archive>
|
||||
void serialize(Archive& ar, const unsigned int file_version) {
|
||||
ar& offset;
|
||||
ar& addr;
|
||||
ar& size;
|
||||
}
|
||||
};
|
||||
|
||||
std::string GetTypeName() const override {
|
||||
|
@ -106,6 +129,18 @@ public:
|
|||
std::string name;
|
||||
/// Title ID corresponding to the process
|
||||
u64 program_id;
|
||||
|
||||
private:
|
||||
friend class boost::serialization::access;
|
||||
template <class Archive>
|
||||
void serialize(Archive& ar, const unsigned int file_version) {
|
||||
ar& boost::serialization::base_object<Object>(*this);
|
||||
ar& memory;
|
||||
ar& segments;
|
||||
ar& entrypoint;
|
||||
ar& name;
|
||||
ar& program_id;
|
||||
}
|
||||
};
|
||||
|
||||
class Process final : public Object {
|
||||
|
@ -167,7 +202,7 @@ public:
|
|||
|
||||
u32 memory_used = 0;
|
||||
|
||||
MemoryRegionInfo* memory_region = nullptr;
|
||||
std::shared_ptr<MemoryRegionInfo> memory_region = nullptr;
|
||||
|
||||
/// The Thread Local Storage area is allocated as processes create threads,
|
||||
/// each TLS area is 0x200 bytes, so one page (0x1000) is split up in 8 parts, and each part
|
||||
|
@ -195,5 +230,14 @@ public:
|
|||
|
||||
private:
|
||||
KernelSystem& kernel;
|
||||
|
||||
friend class boost::serialization::access;
|
||||
template <class Archive>
|
||||
void serialize(Archive& ar, const unsigned int file_version);
|
||||
};
|
||||
} // namespace Kernel
|
||||
|
||||
BOOST_CLASS_EXPORT_KEY(Kernel::CodeSet)
|
||||
BOOST_CLASS_EXPORT_KEY(Kernel::Process)
|
||||
CONSTRUCT_KERNEL_OBJECT(Kernel::CodeSet)
|
||||
CONSTRUCT_KERNEL_OBJECT(Kernel::Process)
|
||||
|
|
|
@ -3,10 +3,13 @@
|
|||
// Refer to the license.txt file included.
|
||||
|
||||
#include <cstring>
|
||||
#include "common/archives.h"
|
||||
#include "common/assert.h"
|
||||
#include "common/logging/log.h"
|
||||
#include "core/hle/kernel/resource_limit.h"
|
||||
|
||||
SERIALIZE_EXPORT_IMPL(Kernel::ResourceLimit)
|
||||
|
||||
namespace Kernel {
|
||||
|
||||
ResourceLimit::ResourceLimit(KernelSystem& kernel) : Object(kernel) {}
|
||||
|
|
|
@ -6,6 +6,10 @@
|
|||
|
||||
#include <array>
|
||||
#include <memory>
|
||||
#include <boost/serialization/array.hpp>
|
||||
#include <boost/serialization/base_object.hpp>
|
||||
#include <boost/serialization/shared_ptr.hpp>
|
||||
#include <boost/serialization/string.hpp>
|
||||
#include "common/common_types.h"
|
||||
#include "core/hle/kernel/object.h"
|
||||
|
||||
|
@ -110,6 +114,35 @@ public:
|
|||
|
||||
/// Current CPU time that the processes in this category are utilizing
|
||||
s32 current_cpu_time = 0;
|
||||
|
||||
private:
|
||||
friend class boost::serialization::access;
|
||||
template <class Archive>
|
||||
void serialize(Archive& ar, const unsigned int file_version) {
|
||||
ar& boost::serialization::base_object<Object>(*this);
|
||||
// NB most of these aren't used at all currently, but we're adding them here for forwards
|
||||
// compatibility
|
||||
ar& name;
|
||||
ar& max_priority;
|
||||
ar& max_commit;
|
||||
ar& max_threads;
|
||||
ar& max_events;
|
||||
ar& max_mutexes;
|
||||
ar& max_semaphores;
|
||||
ar& max_timers;
|
||||
ar& max_shared_mems;
|
||||
ar& max_address_arbiters;
|
||||
ar& max_cpu_time;
|
||||
ar& current_commit;
|
||||
ar& current_threads;
|
||||
ar& current_events;
|
||||
ar& current_mutexes;
|
||||
ar& current_semaphores;
|
||||
ar& current_timers;
|
||||
ar& current_shared_mems;
|
||||
ar& current_address_arbiters;
|
||||
ar& current_cpu_time;
|
||||
}
|
||||
};
|
||||
|
||||
class ResourceLimitList {
|
||||
|
@ -126,6 +159,15 @@ public:
|
|||
|
||||
private:
|
||||
std::array<std::shared_ptr<ResourceLimit>, 4> resource_limits;
|
||||
|
||||
friend class boost::serialization::access;
|
||||
template <class Archive>
|
||||
void serialize(Archive& ar, const unsigned int file_version) {
|
||||
ar& resource_limits;
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace Kernel
|
||||
|
||||
BOOST_CLASS_EXPORT_KEY(Kernel::ResourceLimit)
|
||||
CONSTRUCT_KERNEL_OBJECT(Kernel::ResourceLimit)
|
||||
|
|
|
@ -2,12 +2,15 @@
|
|||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#include "common/archives.h"
|
||||
#include "common/assert.h"
|
||||
#include "core/hle/kernel/errors.h"
|
||||
#include "core/hle/kernel/kernel.h"
|
||||
#include "core/hle/kernel/semaphore.h"
|
||||
#include "core/hle/kernel/thread.h"
|
||||
|
||||
SERIALIZE_EXPORT_IMPL(Kernel::Semaphore)
|
||||
|
||||
namespace Kernel {
|
||||
|
||||
Semaphore::Semaphore(KernelSystem& kernel) : WaitObject(kernel) {}
|
||||
|
|
|
@ -5,6 +5,9 @@
|
|||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include <boost/serialization/base_object.hpp>
|
||||
#include <boost/serialization/export.hpp>
|
||||
#include <boost/serialization/string.hpp>
|
||||
#include <queue>
|
||||
#include "common/common_types.h"
|
||||
#include "core/hle/kernel/object.h"
|
||||
|
@ -43,6 +46,19 @@ public:
|
|||
* @return The number of free slots the semaphore had before this call
|
||||
*/
|
||||
ResultVal<s32> Release(s32 release_count);
|
||||
|
||||
private:
|
||||
friend class boost::serialization::access;
|
||||
template <class Archive>
|
||||
void serialize(Archive& ar, const unsigned int file_version) {
|
||||
ar& boost::serialization::base_object<WaitObject>(*this);
|
||||
ar& max_count;
|
||||
ar& available_count;
|
||||
ar& name;
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace Kernel
|
||||
|
||||
BOOST_CLASS_EXPORT_KEY(Kernel::Semaphore)
|
||||
CONSTRUCT_KERNEL_OBJECT(Kernel::Semaphore)
|
||||
|
|
|
@ -3,14 +3,22 @@
|
|||
// Refer to the license.txt file included.
|
||||
|
||||
#include <tuple>
|
||||
#include <boost/serialization/base_object.hpp>
|
||||
#include <boost/serialization/shared_ptr.hpp>
|
||||
#include <boost/serialization/string.hpp>
|
||||
#include <boost/serialization/vector.hpp>
|
||||
#include "common/archives.h"
|
||||
#include "common/assert.h"
|
||||
#include "core/hle/kernel/client_port.h"
|
||||
#include "core/hle/kernel/errors.h"
|
||||
#include "core/hle/kernel/hle_ipc.h"
|
||||
#include "core/hle/kernel/object.h"
|
||||
#include "core/hle/kernel/server_port.h"
|
||||
#include "core/hle/kernel/server_session.h"
|
||||
#include "core/hle/kernel/thread.h"
|
||||
|
||||
SERIALIZE_EXPORT_IMPL(Kernel::ServerPort)
|
||||
|
||||
namespace Kernel {
|
||||
|
||||
ServerPort::ServerPort(KernelSystem& kernel) : WaitObject(kernel) {}
|
||||
|
@ -48,4 +56,13 @@ KernelSystem::PortPair KernelSystem::CreatePortPair(u32 max_sessions, std::strin
|
|||
return std::make_pair(std::move(server_port), std::move(client_port));
|
||||
}
|
||||
|
||||
template <class Archive>
|
||||
void ServerPort::serialize(Archive& ar, const unsigned int file_version) {
|
||||
ar& boost::serialization::base_object<WaitObject>(*this);
|
||||
ar& name;
|
||||
ar& pending_sessions;
|
||||
ar& hle_handler;
|
||||
}
|
||||
SERIALIZE_IMPL(ServerPort)
|
||||
|
||||
} // namespace Kernel
|
||||
|
|
|
@ -7,8 +7,10 @@
|
|||
#include <memory>
|
||||
#include <string>
|
||||
#include <tuple>
|
||||
#include <boost/serialization/export.hpp>
|
||||
#include "common/common_types.h"
|
||||
#include "core/hle/kernel/object.h"
|
||||
#include "core/hle/kernel/server_session.h"
|
||||
#include "core/hle/kernel/wait_object.h"
|
||||
#include "core/hle/result.h"
|
||||
|
||||
|
@ -60,6 +62,14 @@ public:
|
|||
|
||||
bool ShouldWait(const Thread* thread) const override;
|
||||
void Acquire(Thread* thread) override;
|
||||
|
||||
private:
|
||||
friend class boost::serialization::access;
|
||||
template <class Archive>
|
||||
void serialize(Archive& ar, const unsigned int file_version);
|
||||
};
|
||||
|
||||
} // namespace Kernel
|
||||
|
||||
BOOST_CLASS_EXPORT_KEY(Kernel::ServerPort)
|
||||
CONSTRUCT_KERNEL_OBJECT(Kernel::ServerPort)
|
||||
|
|
|
@ -3,7 +3,10 @@
|
|||
// Refer to the license.txt file included.
|
||||
|
||||
#include <tuple>
|
||||
|
||||
#include <boost/serialization/shared_ptr.hpp>
|
||||
#include <boost/serialization/string.hpp>
|
||||
#include <boost/serialization/vector.hpp>
|
||||
#include "common/archives.h"
|
||||
#include "core/hle/kernel/client_port.h"
|
||||
#include "core/hle/kernel/client_session.h"
|
||||
#include "core/hle/kernel/hle_ipc.h"
|
||||
|
@ -11,8 +14,22 @@
|
|||
#include "core/hle/kernel/session.h"
|
||||
#include "core/hle/kernel/thread.h"
|
||||
|
||||
SERIALIZE_EXPORT_IMPL(Kernel::ServerSession)
|
||||
|
||||
namespace Kernel {
|
||||
|
||||
template <class Archive>
|
||||
void ServerSession::serialize(Archive& ar, const unsigned int file_version) {
|
||||
ar& boost::serialization::base_object<WaitObject>(*this);
|
||||
ar& name;
|
||||
ar& parent;
|
||||
ar& hle_handler;
|
||||
ar& pending_requesting_threads;
|
||||
ar& currently_handling;
|
||||
ar& mapped_buffer_context;
|
||||
}
|
||||
SERIALIZE_IMPL(ServerSession)
|
||||
|
||||
ServerSession::ServerSession(KernelSystem& kernel) : WaitObject(kernel), kernel(kernel) {}
|
||||
ServerSession::~ServerSession() {
|
||||
// This destructor will be called automatically when the last ServerSession handle is closed by
|
||||
|
@ -68,14 +85,15 @@ ResultCode ServerSession::HandleSyncRequest(std::shared_ptr<Thread> thread) {
|
|||
// If this ServerSession has an associated HLE handler, forward the request to it.
|
||||
if (hle_handler != nullptr) {
|
||||
std::array<u32_le, IPC::COMMAND_BUFFER_LENGTH + 2 * IPC::MAX_STATIC_BUFFERS> cmd_buf;
|
||||
Kernel::Process* current_process = thread->owner_process;
|
||||
auto current_process = thread->owner_process;
|
||||
kernel.memory.ReadBlock(*current_process, thread->GetCommandBufferAddress(), cmd_buf.data(),
|
||||
cmd_buf.size() * sizeof(u32));
|
||||
|
||||
Kernel::HLERequestContext context(kernel, SharedFrom(this), thread.get());
|
||||
context.PopulateFromIncomingCommandBuffer(cmd_buf.data(), *current_process);
|
||||
auto context =
|
||||
std::make_shared<Kernel::HLERequestContext>(kernel, SharedFrom(this), thread);
|
||||
context->PopulateFromIncomingCommandBuffer(cmd_buf.data(), current_process);
|
||||
|
||||
hle_handler->HandleSyncRequest(context);
|
||||
hle_handler->HandleSyncRequest(*context);
|
||||
|
||||
ASSERT(thread->status == Kernel::ThreadStatus::Running ||
|
||||
thread->status == Kernel::ThreadStatus::WaitHleEvent);
|
||||
|
@ -83,7 +101,7 @@ ResultCode ServerSession::HandleSyncRequest(std::shared_ptr<Thread> thread) {
|
|||
// put the thread to sleep then the writing of the command buffer will be deferred to the
|
||||
// wakeup callback.
|
||||
if (thread->status == Kernel::ThreadStatus::Running) {
|
||||
context.WriteToOutgoingCommandBuffer(cmd_buf.data(), *current_process);
|
||||
context->WriteToOutgoingCommandBuffer(cmd_buf.data(), *current_process);
|
||||
kernel.memory.WriteBlock(*current_process, thread->GetCommandBufferAddress(),
|
||||
cmd_buf.data(), cmd_buf.size() * sizeof(u32));
|
||||
}
|
||||
|
|
|
@ -6,10 +6,12 @@
|
|||
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <boost/serialization/export.hpp>
|
||||
#include "common/assert.h"
|
||||
#include "common/common_types.h"
|
||||
#include "core/hle/kernel/ipc.h"
|
||||
#include "core/hle/kernel/object.h"
|
||||
#include "core/hle/kernel/session.h"
|
||||
#include "core/hle/kernel/wait_object.h"
|
||||
#include "core/hle/result.h"
|
||||
#include "core/memory.h"
|
||||
|
@ -103,6 +105,13 @@ private:
|
|||
|
||||
friend class KernelSystem;
|
||||
KernelSystem& kernel;
|
||||
|
||||
friend class boost::serialization::access;
|
||||
template <class Archive>
|
||||
void serialize(Archive& ar, const unsigned int file_version);
|
||||
};
|
||||
|
||||
} // namespace Kernel
|
||||
|
||||
BOOST_CLASS_EXPORT_KEY(Kernel::ServerSession)
|
||||
CONSTRUCT_KERNEL_OBJECT(Kernel::ServerSession)
|
||||
|
|
|
@ -2,11 +2,22 @@
|
|||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#include <boost/serialization/shared_ptr.hpp>
|
||||
#include "common/archives.h"
|
||||
#include "core/hle/kernel/client_port.h"
|
||||
#include "core/hle/kernel/client_session.h"
|
||||
#include "core/hle/kernel/server_session.h"
|
||||
#include "core/hle/kernel/session.h"
|
||||
#include "core/hle/kernel/thread.h"
|
||||
|
||||
SERIALIZE_IMPL(Kernel::Session)
|
||||
|
||||
namespace Kernel {
|
||||
|
||||
Session::Session() {}
|
||||
Session::~Session() {}
|
||||
template <class Archive>
|
||||
void Session::serialize(Archive& ar, const unsigned int file_version) {
|
||||
ar& client;
|
||||
ar& server;
|
||||
ar& port;
|
||||
}
|
||||
|
||||
} // namespace Kernel
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
#pragma once
|
||||
|
||||
#include <memory>
|
||||
#include <boost/serialization/access.hpp>
|
||||
#include "core/hle/kernel/object.h"
|
||||
|
||||
namespace Kernel {
|
||||
|
@ -24,5 +25,10 @@ public:
|
|||
ClientSession* client = nullptr; ///< The client endpoint of the session.
|
||||
ServerSession* server = nullptr; ///< The server endpoint of the session.
|
||||
std::shared_ptr<ClientPort> port; ///< The port that this session is associated with (optional).
|
||||
|
||||
private:
|
||||
friend class boost::serialization::access;
|
||||
template <class Archive>
|
||||
void serialize(Archive& ar, const unsigned int file_version);
|
||||
};
|
||||
} // namespace Kernel
|
||||
|
|
|
@ -3,12 +3,15 @@
|
|||
// Refer to the license.txt file included.
|
||||
|
||||
#include <cstring>
|
||||
#include "common/archives.h"
|
||||
#include "common/logging/log.h"
|
||||
#include "core/hle/kernel/errors.h"
|
||||
#include "core/hle/kernel/memory.h"
|
||||
#include "core/hle/kernel/shared_memory.h"
|
||||
#include "core/memory.h"
|
||||
|
||||
SERIALIZE_EXPORT_IMPL(Kernel::SharedMemory)
|
||||
|
||||
namespace Kernel {
|
||||
|
||||
SharedMemory::SharedMemory(KernelSystem& kernel) : Object(kernel), kernel(kernel) {}
|
||||
|
@ -38,13 +41,13 @@ ResultVal<std::shared_ptr<SharedMemory>> KernelSystem::CreateSharedMemory(
|
|||
if (address == 0) {
|
||||
// We need to allocate a block from the Linear Heap ourselves.
|
||||
// We'll manually allocate some memory from the linear heap in the specified region.
|
||||
MemoryRegionInfo* memory_region = GetMemoryRegion(region);
|
||||
auto memory_region = GetMemoryRegion(region);
|
||||
auto offset = memory_region->LinearAllocate(size);
|
||||
|
||||
ASSERT_MSG(offset, "Not enough space in region to allocate shared memory!");
|
||||
|
||||
std::fill(memory.GetFCRAMPointer(*offset), memory.GetFCRAMPointer(*offset + size), 0);
|
||||
shared_memory->backing_blocks = {{memory.GetFCRAMPointer(*offset), size}};
|
||||
shared_memory->backing_blocks = {{memory.GetFCRAMRef(*offset), size}};
|
||||
shared_memory->holding_memory += MemoryRegionInfo::Interval(*offset, *offset + size);
|
||||
shared_memory->linear_heap_phys_offset = *offset;
|
||||
|
||||
|
@ -75,7 +78,7 @@ std::shared_ptr<SharedMemory> KernelSystem::CreateSharedMemoryForApplet(
|
|||
auto shared_memory{std::make_shared<SharedMemory>(*this)};
|
||||
|
||||
// Allocate memory in heap
|
||||
MemoryRegionInfo* memory_region = GetMemoryRegion(MemoryRegion::SYSTEM);
|
||||
auto memory_region = GetMemoryRegion(MemoryRegion::SYSTEM);
|
||||
auto backing_blocks = memory_region->HeapAllocate(size);
|
||||
ASSERT_MSG(!backing_blocks.empty(), "Not enough space in region to allocate shared memory!");
|
||||
shared_memory->holding_memory = backing_blocks;
|
||||
|
@ -86,7 +89,7 @@ std::shared_ptr<SharedMemory> KernelSystem::CreateSharedMemoryForApplet(
|
|||
shared_memory->other_permissions = other_permissions;
|
||||
for (const auto& interval : backing_blocks) {
|
||||
shared_memory->backing_blocks.push_back(
|
||||
{memory.GetFCRAMPointer(interval.lower()), interval.upper() - interval.lower()});
|
||||
{memory.GetFCRAMRef(interval.lower()), interval.upper() - interval.lower()});
|
||||
std::fill(memory.GetFCRAMPointer(interval.lower()),
|
||||
memory.GetFCRAMPointer(interval.upper()), 0);
|
||||
}
|
||||
|
|
|
@ -6,7 +6,11 @@
|
|||
|
||||
#include <string>
|
||||
#include <utility>
|
||||
#include <boost/serialization/base_object.hpp>
|
||||
#include <boost/serialization/export.hpp>
|
||||
#include <boost/serialization/string.hpp>
|
||||
#include "common/common_types.h"
|
||||
#include "common/memory_ref.h"
|
||||
#include "core/hle/kernel/object.h"
|
||||
#include "core/hle/kernel/process.h"
|
||||
#include "core/hle/result.h"
|
||||
|
@ -86,7 +90,7 @@ private:
|
|||
/// during creation.
|
||||
PAddr linear_heap_phys_offset = 0;
|
||||
/// Backing memory for this shared memory block.
|
||||
std::vector<std::pair<u8*, u32>> backing_blocks;
|
||||
std::vector<std::pair<MemoryRef, u32>> backing_blocks;
|
||||
/// Size of the memory block. Page-aligned.
|
||||
u32 size = 0;
|
||||
/// Permission restrictions applied to the process which created the block.
|
||||
|
@ -104,6 +108,24 @@ private:
|
|||
|
||||
friend class KernelSystem;
|
||||
KernelSystem& kernel;
|
||||
|
||||
template <class Archive>
|
||||
void serialize(Archive& ar, const unsigned int file_version) {
|
||||
ar& boost::serialization::base_object<Object>(*this);
|
||||
ar& linear_heap_phys_offset;
|
||||
ar& backing_blocks;
|
||||
ar& size;
|
||||
ar& permissions;
|
||||
ar& other_permissions;
|
||||
ar& owner_process;
|
||||
ar& base_address;
|
||||
ar& name;
|
||||
ar& holding_memory;
|
||||
}
|
||||
friend class boost::serialization::access;
|
||||
};
|
||||
|
||||
} // namespace Kernel
|
||||
|
||||
BOOST_CLASS_EXPORT_KEY(Kernel::SharedMemory)
|
||||
CONSTRUCT_KERNEL_OBJECT(Kernel::SharedMemory)
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
|
||||
#include <chrono>
|
||||
#include <cstring>
|
||||
#include "common/archives.h"
|
||||
#include "core/core.h"
|
||||
#include "core/core_timing.h"
|
||||
#include "core/hle/kernel/shared_page.h"
|
||||
|
@ -13,6 +14,19 @@
|
|||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
SERIALIZE_EXPORT_IMPL(SharedPage::Handler)
|
||||
|
||||
namespace boost::serialization {
|
||||
|
||||
template <class Archive>
|
||||
void load_construct_data(Archive& ar, SharedPage::Handler* t, const unsigned int) {
|
||||
::new (t) SharedPage::Handler(Core::System::GetInstance().CoreTiming());
|
||||
}
|
||||
template void load_construct_data<iarchive>(iarchive& ar, SharedPage::Handler* t,
|
||||
const unsigned int);
|
||||
|
||||
} // namespace boost::serialization
|
||||
|
||||
namespace SharedPage {
|
||||
|
||||
static std::chrono::seconds GetInitTime() {
|
||||
|
|
|
@ -13,9 +13,13 @@
|
|||
#include <chrono>
|
||||
#include <ctime>
|
||||
#include <memory>
|
||||
#include <boost/serialization/base_object.hpp>
|
||||
#include <boost/serialization/binary_object.hpp>
|
||||
#include <boost/serialization/export.hpp>
|
||||
#include "common/bit_field.h"
|
||||
#include "common/common_funcs.h"
|
||||
#include "common/common_types.h"
|
||||
#include "common/memory_ref.h"
|
||||
#include "common/swap.h"
|
||||
#include "core/memory.h"
|
||||
|
||||
|
@ -82,7 +86,7 @@ struct SharedPageDef {
|
|||
static_assert(sizeof(SharedPageDef) == Memory::SHARED_PAGE_SIZE,
|
||||
"Shared page structure size is wrong");
|
||||
|
||||
class Handler {
|
||||
class Handler : public BackingMem {
|
||||
public:
|
||||
Handler(Core::Timing& timing);
|
||||
|
||||
|
@ -96,6 +100,18 @@ public:
|
|||
|
||||
SharedPageDef& GetSharedPage();
|
||||
|
||||
u8* GetPtr() override {
|
||||
return reinterpret_cast<u8*>(&shared_page);
|
||||
}
|
||||
|
||||
const u8* GetPtr() const override {
|
||||
return reinterpret_cast<const u8*>(&shared_page);
|
||||
}
|
||||
|
||||
std::size_t GetSize() const override {
|
||||
return sizeof(shared_page);
|
||||
}
|
||||
|
||||
private:
|
||||
u64 GetSystemTime() const;
|
||||
void UpdateTimeCallback(u64 userdata, int cycles_late);
|
||||
|
@ -104,6 +120,22 @@ private:
|
|||
std::chrono::seconds init_time;
|
||||
|
||||
SharedPageDef shared_page;
|
||||
|
||||
template <class Archive>
|
||||
void serialize(Archive& ar, const unsigned int) {
|
||||
ar& boost::serialization::base_object<BackingMem>(*this);
|
||||
ar& boost::serialization::make_binary_object(&shared_page, sizeof(shared_page));
|
||||
}
|
||||
friend class boost::serialization::access;
|
||||
};
|
||||
|
||||
} // namespace SharedPage
|
||||
|
||||
namespace boost::serialization {
|
||||
|
||||
template <class Archive>
|
||||
void load_construct_data(Archive& ar, SharedPage::Handler* t, const unsigned int);
|
||||
|
||||
} // namespace boost::serialization
|
||||
|
||||
BOOST_CLASS_EXPORT_KEY(SharedPage::Handler)
|
||||
|
|
|
@ -282,7 +282,7 @@ void SVC::ExitProcess() {
|
|||
// Stop all the process threads that are currently waiting for objects.
|
||||
auto& thread_list = kernel.GetCurrentThreadManager().GetThreadList();
|
||||
for (auto& thread : thread_list) {
|
||||
if (thread->owner_process != current_process.get())
|
||||
if (thread->owner_process != current_process)
|
||||
continue;
|
||||
|
||||
if (thread.get() == kernel.GetCurrentThreadManager().GetCurrentThread())
|
||||
|
@ -403,6 +403,76 @@ ResultCode SVC::CloseHandle(Handle handle) {
|
|||
return kernel.GetCurrentProcess()->handle_table.Close(handle);
|
||||
}
|
||||
|
||||
static ResultCode ReceiveIPCRequest(Kernel::KernelSystem& kernel, Memory::MemorySystem& memory,
|
||||
std::shared_ptr<ServerSession> server_session,
|
||||
std::shared_ptr<Thread> thread);
|
||||
|
||||
class SVC_SyncCallback : public Kernel::WakeupCallback {
|
||||
public:
|
||||
explicit SVC_SyncCallback(bool do_output_) : do_output(do_output_) {}
|
||||
void WakeUp(ThreadWakeupReason reason, std::shared_ptr<Thread> thread,
|
||||
std::shared_ptr<WaitObject> object) {
|
||||
|
||||
if (reason == ThreadWakeupReason::Timeout) {
|
||||
thread->SetWaitSynchronizationResult(RESULT_TIMEOUT);
|
||||
return;
|
||||
}
|
||||
|
||||
ASSERT(reason == ThreadWakeupReason::Signal);
|
||||
|
||||
thread->SetWaitSynchronizationResult(RESULT_SUCCESS);
|
||||
|
||||
// The wait_all case does not update the output index.
|
||||
if (do_output) {
|
||||
thread->SetWaitSynchronizationOutput(thread->GetWaitObjectIndex(object.get()));
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
bool do_output;
|
||||
|
||||
SVC_SyncCallback() = default;
|
||||
template <class Archive>
|
||||
void serialize(Archive& ar, const unsigned int) {
|
||||
ar& boost::serialization::base_object<Kernel::WakeupCallback>(*this);
|
||||
ar& do_output;
|
||||
}
|
||||
friend class boost::serialization::access;
|
||||
};
|
||||
|
||||
class SVC_IPCCallback : public Kernel::WakeupCallback {
|
||||
public:
|
||||
explicit SVC_IPCCallback(Core::System& system_) : system(system_) {}
|
||||
|
||||
void WakeUp(ThreadWakeupReason reason, std::shared_ptr<Thread> thread,
|
||||
std::shared_ptr<WaitObject> object) {
|
||||
|
||||
ASSERT(thread->status == ThreadStatus::WaitSynchAny);
|
||||
ASSERT(reason == ThreadWakeupReason::Signal);
|
||||
|
||||
ResultCode result = RESULT_SUCCESS;
|
||||
|
||||
if (object->GetHandleType() == HandleType::ServerSession) {
|
||||
auto server_session = DynamicObjectCast<ServerSession>(object);
|
||||
result = ReceiveIPCRequest(system.Kernel(), system.Memory(), server_session, thread);
|
||||
}
|
||||
|
||||
thread->SetWaitSynchronizationResult(result);
|
||||
thread->SetWaitSynchronizationOutput(thread->GetWaitObjectIndex(object.get()));
|
||||
}
|
||||
|
||||
private:
|
||||
Core::System& system;
|
||||
|
||||
SVC_IPCCallback() : system(Core::Global<Core::System>()) {}
|
||||
|
||||
template <class Archive>
|
||||
void serialize(Archive& ar, const unsigned int) {
|
||||
ar& boost::serialization::base_object<Kernel::WakeupCallback>(*this);
|
||||
}
|
||||
friend class boost::serialization::access;
|
||||
};
|
||||
|
||||
/// Wait for a handle to synchronize, timeout after the specified nanoseconds
|
||||
ResultCode SVC::WaitSynchronization1(Handle handle, s64 nano_seconds) {
|
||||
auto object = kernel.GetCurrentProcess()->handle_table.Get<WaitObject>(handle);
|
||||
|
@ -426,21 +496,7 @@ ResultCode SVC::WaitSynchronization1(Handle handle, s64 nano_seconds) {
|
|||
// Create an event to wake the thread up after the specified nanosecond delay has passed
|
||||
thread->WakeAfterDelay(nano_seconds);
|
||||
|
||||
thread->wakeup_callback = [](ThreadWakeupReason reason, std::shared_ptr<Thread> thread,
|
||||
std::shared_ptr<WaitObject> object) {
|
||||
ASSERT(thread->status == ThreadStatus::WaitSynchAny);
|
||||
|
||||
if (reason == ThreadWakeupReason::Timeout) {
|
||||
thread->SetWaitSynchronizationResult(RESULT_TIMEOUT);
|
||||
return;
|
||||
}
|
||||
|
||||
ASSERT(reason == ThreadWakeupReason::Signal);
|
||||
thread->SetWaitSynchronizationResult(RESULT_SUCCESS);
|
||||
|
||||
// WaitSynchronization1 doesn't have an output index like WaitSynchronizationN, so we
|
||||
// don't have to do anything else here.
|
||||
};
|
||||
thread->wakeup_callback = std::make_shared<SVC_SyncCallback>(false);
|
||||
|
||||
system.PrepareReschedule();
|
||||
|
||||
|
@ -515,20 +571,7 @@ ResultCode SVC::WaitSynchronizationN(s32* out, VAddr handles_address, s32 handle
|
|||
// Create an event to wake the thread up after the specified nanosecond delay has passed
|
||||
thread->WakeAfterDelay(nano_seconds);
|
||||
|
||||
thread->wakeup_callback = [](ThreadWakeupReason reason, std::shared_ptr<Thread> thread,
|
||||
std::shared_ptr<WaitObject> object) {
|
||||
ASSERT(thread->status == ThreadStatus::WaitSynchAll);
|
||||
|
||||
if (reason == ThreadWakeupReason::Timeout) {
|
||||
thread->SetWaitSynchronizationResult(RESULT_TIMEOUT);
|
||||
return;
|
||||
}
|
||||
|
||||
ASSERT(reason == ThreadWakeupReason::Signal);
|
||||
|
||||
thread->SetWaitSynchronizationResult(RESULT_SUCCESS);
|
||||
// The wait_all case does not update the output index.
|
||||
};
|
||||
thread->wakeup_callback = std::make_shared<SVC_SyncCallback>(false);
|
||||
|
||||
system.PrepareReschedule();
|
||||
|
||||
|
@ -575,20 +618,7 @@ ResultCode SVC::WaitSynchronizationN(s32* out, VAddr handles_address, s32 handle
|
|||
// Create an event to wake the thread up after the specified nanosecond delay has passed
|
||||
thread->WakeAfterDelay(nano_seconds);
|
||||
|
||||
thread->wakeup_callback = [](ThreadWakeupReason reason, std::shared_ptr<Thread> thread,
|
||||
std::shared_ptr<WaitObject> object) {
|
||||
ASSERT(thread->status == ThreadStatus::WaitSynchAny);
|
||||
|
||||
if (reason == ThreadWakeupReason::Timeout) {
|
||||
thread->SetWaitSynchronizationResult(RESULT_TIMEOUT);
|
||||
return;
|
||||
}
|
||||
|
||||
ASSERT(reason == ThreadWakeupReason::Signal);
|
||||
|
||||
thread->SetWaitSynchronizationResult(RESULT_SUCCESS);
|
||||
thread->SetWaitSynchronizationOutput(thread->GetWaitObjectIndex(object.get()));
|
||||
};
|
||||
thread->wakeup_callback = std::make_shared<SVC_SyncCallback>(true);
|
||||
|
||||
system.PrepareReschedule();
|
||||
|
||||
|
@ -730,22 +760,7 @@ ResultCode SVC::ReplyAndReceive(s32* index, VAddr handles_address, s32 handle_co
|
|||
|
||||
thread->wait_objects = std::move(objects);
|
||||
|
||||
thread->wakeup_callback = [& kernel = this->kernel, &memory = this->memory](
|
||||
ThreadWakeupReason reason, std::shared_ptr<Thread> thread,
|
||||
std::shared_ptr<WaitObject> object) {
|
||||
ASSERT(thread->status == ThreadStatus::WaitSynchAny);
|
||||
ASSERT(reason == ThreadWakeupReason::Signal);
|
||||
|
||||
ResultCode result = RESULT_SUCCESS;
|
||||
|
||||
if (object->GetHandleType() == HandleType::ServerSession) {
|
||||
auto server_session = DynamicObjectCast<ServerSession>(object);
|
||||
result = ReceiveIPCRequest(kernel, memory, server_session, thread);
|
||||
}
|
||||
|
||||
thread->SetWaitSynchronizationResult(result);
|
||||
thread->SetWaitSynchronizationOutput(thread->GetWaitObjectIndex(object.get()));
|
||||
};
|
||||
thread->wakeup_callback = std::make_shared<SVC_IPCCallback>(system);
|
||||
|
||||
system.PrepareReschedule();
|
||||
|
||||
|
@ -916,7 +931,7 @@ ResultCode SVC::CreateThread(Handle* out_handle, u32 entry_point, u32 arg, VAddr
|
|||
|
||||
CASCADE_RESULT(std::shared_ptr<Thread> thread,
|
||||
kernel.CreateThread(name, entry_point, priority, arg, processor_id, stack_top,
|
||||
*current_process));
|
||||
current_process));
|
||||
|
||||
thread->context->SetFpscr(FPSCR_DEFAULT_NAN | FPSCR_FLUSH_TO_ZERO |
|
||||
FPSCR_ROUND_TOZERO); // 0x03C00000
|
||||
|
@ -1025,7 +1040,7 @@ ResultCode SVC::GetProcessIdOfThread(u32* process_id, Handle thread_handle) {
|
|||
if (thread == nullptr)
|
||||
return ERR_INVALID_HANDLE;
|
||||
|
||||
const std::shared_ptr<Process> process = SharedFrom(thread->owner_process);
|
||||
const std::shared_ptr<Process> process = thread->owner_process;
|
||||
|
||||
ASSERT_MSG(process != nullptr, "Invalid parent process for thread={:#010X}", thread_handle);
|
||||
|
||||
|
@ -1592,6 +1607,7 @@ void SVC::CallSVC(u32 immediate) {
|
|||
"Running threads from exiting processes is unimplemented");
|
||||
|
||||
const FunctionDef* info = GetSVCInfo(immediate);
|
||||
LOG_TRACE(Kernel_SVC, "calling {}", info->name);
|
||||
if (info) {
|
||||
if (info->func) {
|
||||
(this->*(info->func))();
|
||||
|
@ -1619,3 +1635,6 @@ void SVCContext::CallSVC(u32 immediate) {
|
|||
}
|
||||
|
||||
} // namespace Kernel
|
||||
|
||||
SERIALIZE_EXPORT_IMPL(Kernel::SVC_SyncCallback)
|
||||
SERIALIZE_EXPORT_IMPL(Kernel::SVC_IPCCallback)
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
#pragma once
|
||||
|
||||
#include <memory>
|
||||
#include <boost/serialization/export.hpp>
|
||||
#include "common/common_types.h"
|
||||
|
||||
namespace Core {
|
||||
|
@ -25,4 +26,10 @@ private:
|
|||
std::unique_ptr<SVC> impl;
|
||||
};
|
||||
|
||||
class SVC_SyncCallback;
|
||||
class SVC_IPCCallback;
|
||||
|
||||
} // namespace Kernel
|
||||
|
||||
BOOST_CLASS_EXPORT_KEY(Kernel::SVC_SyncCallback)
|
||||
BOOST_CLASS_EXPORT_KEY(Kernel::SVC_IPCCallback)
|
||||
|
|
|
@ -280,6 +280,26 @@ private:
|
|||
}
|
||||
};
|
||||
|
||||
template <typename SVCT>
|
||||
struct WrapPass<SVCT, ResultCode /*empty for T, Ts...*/> {
|
||||
// Call function R(Context::svc)(Us...) and transfer the return value to registers
|
||||
template <typename... Us>
|
||||
static void Call(Context& context, SVCT svc, Us... u) {
|
||||
static_assert(std::is_same_v<SVCT, ResultCode (Context::*)(Us...)>);
|
||||
if constexpr (std::is_void_v<ResultCode>) {
|
||||
(context.*svc)(u...);
|
||||
} else {
|
||||
ResultCode r = (context.*svc)(u...);
|
||||
if (r.IsError()) {
|
||||
LOG_ERROR(Kernel_SVC, "level={} summary={} module={} description={}",
|
||||
r.level.ExtractValue(r.raw), r.summary.ExtractValue(r.raw),
|
||||
r.module.ExtractValue(r.raw), r.description.ExtractValue(r.raw));
|
||||
}
|
||||
SetParam<INDEX_RETURN, ResultCode, ResultCode, Us...>(context, r);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct WrapHelper;
|
||||
|
||||
|
|
|
@ -6,10 +6,13 @@
|
|||
#include <list>
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
#include <boost/serialization/string.hpp>
|
||||
#include "common/archives.h"
|
||||
#include "common/assert.h"
|
||||
#include "common/common_types.h"
|
||||
#include "common/logging/log.h"
|
||||
#include "common/math_util.h"
|
||||
#include "common/serialization/boost_flat_set.h"
|
||||
#include "core/arm/arm_interface.h"
|
||||
#include "core/arm/skyeye_common/armstate.h"
|
||||
#include "core/core.h"
|
||||
|
@ -23,8 +26,34 @@
|
|||
#include "core/hle/result.h"
|
||||
#include "core/memory.h"
|
||||
|
||||
SERIALIZE_EXPORT_IMPL(Kernel::Thread)
|
||||
|
||||
namespace Kernel {
|
||||
|
||||
template <class Archive>
|
||||
void Thread::serialize(Archive& ar, const unsigned int file_version) {
|
||||
ar& boost::serialization::base_object<WaitObject>(*this);
|
||||
ar&* context.get();
|
||||
ar& thread_id;
|
||||
ar& status;
|
||||
ar& entry_point;
|
||||
ar& stack_top;
|
||||
ar& nominal_priority;
|
||||
ar& current_priority;
|
||||
ar& last_running_ticks;
|
||||
ar& processor_id;
|
||||
ar& tls_address;
|
||||
ar& held_mutexes;
|
||||
ar& pending_mutexes;
|
||||
ar& owner_process;
|
||||
ar& wait_objects;
|
||||
ar& wait_address;
|
||||
ar& name;
|
||||
ar& wakeup_callback;
|
||||
}
|
||||
|
||||
SERIALIZE_IMPL(Thread)
|
||||
|
||||
bool Thread::ShouldWait(const Thread* thread) const {
|
||||
return status != ThreadStatus::Dead;
|
||||
}
|
||||
|
@ -34,7 +63,7 @@ void Thread::Acquire(Thread* thread) {
|
|||
}
|
||||
|
||||
Thread::Thread(KernelSystem& kernel, u32 core_id)
|
||||
: WaitObject(kernel), context(kernel.GetThreadManager(core_id).NewContext()),
|
||||
: WaitObject(kernel), context(kernel.GetThreadManager(core_id).NewContext()), core_id(core_id),
|
||||
thread_manager(kernel.GetThreadManager(core_id)) {}
|
||||
Thread::~Thread() {}
|
||||
|
||||
|
@ -75,7 +104,7 @@ void Thread::Stop() {
|
|||
|
||||
void ThreadManager::SwitchContext(Thread* new_thread) {
|
||||
Thread* previous_thread = GetCurrentThread();
|
||||
Process* previous_process = nullptr;
|
||||
std::shared_ptr<Process> previous_process = nullptr;
|
||||
|
||||
Core::Timing& timing = kernel.timing;
|
||||
|
||||
|
@ -107,7 +136,7 @@ void ThreadManager::SwitchContext(Thread* new_thread) {
|
|||
new_thread->status = ThreadStatus::Running;
|
||||
|
||||
if (previous_process != current_thread->owner_process) {
|
||||
kernel.SetCurrentProcessForCPU(SharedFrom(current_thread->owner_process), cpu->GetID());
|
||||
kernel.SetCurrentProcessForCPU(current_thread->owner_process, cpu->GetID());
|
||||
}
|
||||
|
||||
cpu->LoadContext(new_thread->context);
|
||||
|
@ -164,7 +193,7 @@ void ThreadManager::ThreadWakeupCallback(u64 thread_id, s64 cycles_late) {
|
|||
|
||||
// Invoke the wakeup callback before clearing the wait objects
|
||||
if (thread->wakeup_callback)
|
||||
thread->wakeup_callback(ThreadWakeupReason::Timeout, thread, nullptr);
|
||||
thread->wakeup_callback->WakeUp(ThreadWakeupReason::Timeout, thread, nullptr);
|
||||
|
||||
// Remove the thread from each of its waiting objects' waitlists
|
||||
for (auto& object : thread->wait_objects)
|
||||
|
@ -282,10 +311,9 @@ static void ResetThreadContext(const std::unique_ptr<ARM_Interface::ThreadContex
|
|||
context->SetCpsr(USER32MODE | ((entry_point & 1) << 5)); // Usermode and THUMB mode
|
||||
}
|
||||
|
||||
ResultVal<std::shared_ptr<Thread>> KernelSystem::CreateThread(std::string name, VAddr entry_point,
|
||||
u32 priority, u32 arg,
|
||||
s32 processor_id, VAddr stack_top,
|
||||
Process& owner_process) {
|
||||
ResultVal<std::shared_ptr<Thread>> KernelSystem::CreateThread(
|
||||
std::string name, VAddr entry_point, u32 priority, u32 arg, s32 processor_id, VAddr stack_top,
|
||||
std::shared_ptr<Process> owner_process) {
|
||||
// Check if priority is in ranged. Lowest priority -> highest priority id.
|
||||
if (priority > ThreadPrioLowest) {
|
||||
LOG_ERROR(Kernel_SVC, "Invalid thread priority: {}", priority);
|
||||
|
@ -299,7 +327,7 @@ ResultVal<std::shared_ptr<Thread>> KernelSystem::CreateThread(std::string name,
|
|||
|
||||
// TODO(yuriks): Other checks, returning 0xD9001BEA
|
||||
|
||||
if (!Memory::IsValidVirtualAddress(owner_process, entry_point)) {
|
||||
if (!Memory::IsValidVirtualAddress(*owner_process, entry_point)) {
|
||||
LOG_ERROR(Kernel_SVC, "(name={}): invalid entry {:08x}", name, entry_point);
|
||||
// TODO: Verify error
|
||||
return ResultCode(ErrorDescription::InvalidAddress, ErrorModule::Kernel,
|
||||
|
@ -322,17 +350,17 @@ ResultVal<std::shared_ptr<Thread>> KernelSystem::CreateThread(std::string name,
|
|||
thread->wait_address = 0;
|
||||
thread->name = std::move(name);
|
||||
thread_managers[processor_id]->wakeup_callback_table[thread->thread_id] = thread.get();
|
||||
thread->owner_process = &owner_process;
|
||||
thread->owner_process = owner_process;
|
||||
|
||||
// Find the next available TLS index, and mark it as used
|
||||
auto& tls_slots = owner_process.tls_slots;
|
||||
auto& tls_slots = owner_process->tls_slots;
|
||||
|
||||
auto [available_page, available_slot, needs_allocation] = GetFreeThreadLocalSlot(tls_slots);
|
||||
|
||||
if (needs_allocation) {
|
||||
// There are no already-allocated pages with free slots, lets allocate a new one.
|
||||
// TLS pages are allocated from the BASE region in the linear heap.
|
||||
MemoryRegionInfo* memory_region = GetMemoryRegion(MemoryRegion::BASE);
|
||||
auto memory_region = GetMemoryRegion(MemoryRegion::BASE);
|
||||
|
||||
// Allocate some memory from the end of the linear heap for this region.
|
||||
auto offset = memory_region->LinearAllocate(Memory::PAGE_SIZE);
|
||||
|
@ -341,17 +369,17 @@ ResultVal<std::shared_ptr<Thread>> KernelSystem::CreateThread(std::string name,
|
|||
"Not enough space in region to allocate a new TLS page for thread");
|
||||
return ERR_OUT_OF_MEMORY;
|
||||
}
|
||||
owner_process.memory_used += Memory::PAGE_SIZE;
|
||||
owner_process->memory_used += Memory::PAGE_SIZE;
|
||||
|
||||
tls_slots.emplace_back(0); // The page is completely available at the start
|
||||
available_page = tls_slots.size() - 1;
|
||||
available_slot = 0; // Use the first slot in the new page
|
||||
|
||||
auto& vm_manager = owner_process.vm_manager;
|
||||
auto& vm_manager = owner_process->vm_manager;
|
||||
|
||||
// Map the page to the current process' address space.
|
||||
vm_manager.MapBackingMemory(Memory::TLS_AREA_VADDR + available_page * Memory::PAGE_SIZE,
|
||||
memory.GetFCRAMPointer(*offset), Memory::PAGE_SIZE,
|
||||
memory.GetFCRAMRef(*offset), Memory::PAGE_SIZE,
|
||||
MemoryState::Locked);
|
||||
}
|
||||
|
||||
|
@ -360,7 +388,7 @@ ResultVal<std::shared_ptr<Thread>> KernelSystem::CreateThread(std::string name,
|
|||
thread->tls_address = Memory::TLS_AREA_VADDR + available_page * Memory::PAGE_SIZE +
|
||||
available_slot * Memory::TLS_ENTRY_SIZE;
|
||||
|
||||
memory.ZeroBlock(owner_process, thread->tls_address, Memory::TLS_ENTRY_SIZE);
|
||||
memory.ZeroBlock(*owner_process, thread->tls_address, Memory::TLS_ENTRY_SIZE);
|
||||
|
||||
// TODO(peachum): move to ScheduleThread() when scheduler is added so selected core is used
|
||||
// to initialize the context
|
||||
|
@ -407,7 +435,7 @@ std::shared_ptr<Thread> SetupMainThread(KernelSystem& kernel, u32 entry_point, u
|
|||
// Initialize new "main" thread
|
||||
auto thread_res =
|
||||
kernel.CreateThread("main", entry_point, priority, 0, owner_process->ideal_processor,
|
||||
Memory::HEAP_VADDR_END, *owner_process);
|
||||
Memory::HEAP_VADDR_END, owner_process);
|
||||
|
||||
std::shared_ptr<Thread> thread = std::move(thread_res).Unwrap();
|
||||
|
||||
|
|
|
@ -9,6 +9,10 @@
|
|||
#include <unordered_map>
|
||||
#include <vector>
|
||||
#include <boost/container/flat_set.hpp>
|
||||
#include <boost/serialization/export.hpp>
|
||||
#include <boost/serialization/shared_ptr.hpp>
|
||||
#include <boost/serialization/unordered_map.hpp>
|
||||
#include <boost/serialization/vector.hpp>
|
||||
#include "common/common_types.h"
|
||||
#include "common/thread_queue_list.h"
|
||||
#include "core/arm/arm_interface.h"
|
||||
|
@ -57,6 +61,20 @@ enum class ThreadWakeupReason {
|
|||
Timeout // The thread was woken up due to a wait timeout.
|
||||
};
|
||||
|
||||
class Thread;
|
||||
|
||||
class WakeupCallback {
|
||||
public:
|
||||
virtual ~WakeupCallback() = default;
|
||||
virtual void WakeUp(ThreadWakeupReason reason, std::shared_ptr<Thread> thread,
|
||||
std::shared_ptr<WaitObject> object) = 0;
|
||||
|
||||
private:
|
||||
template <class Archive>
|
||||
void serialize(Archive& ar, const unsigned int) {}
|
||||
friend class boost::serialization::access;
|
||||
};
|
||||
|
||||
class ThreadManager {
|
||||
public:
|
||||
explicit ThreadManager(Kernel::KernelSystem& kernel, u32 core_id);
|
||||
|
@ -140,6 +158,15 @@ private:
|
|||
|
||||
friend class Thread;
|
||||
friend class KernelSystem;
|
||||
|
||||
friend class boost::serialization::access;
|
||||
template <class Archive>
|
||||
void serialize(Archive& ar, const unsigned int file_version) {
|
||||
ar& current_thread;
|
||||
ar& ready_queue;
|
||||
ar& wakeup_callback_table;
|
||||
ar& thread_list;
|
||||
}
|
||||
};
|
||||
|
||||
class Thread final : public WaitObject {
|
||||
|
@ -276,30 +303,34 @@ public:
|
|||
VAddr tls_address; ///< Virtual address of the Thread Local Storage of the thread
|
||||
|
||||
/// Mutexes currently held by this thread, which will be released when it exits.
|
||||
boost::container::flat_set<std::shared_ptr<Mutex>> held_mutexes;
|
||||
boost::container::flat_set<std::shared_ptr<Mutex>> held_mutexes{};
|
||||
|
||||
/// Mutexes that this thread is currently waiting for.
|
||||
boost::container::flat_set<std::shared_ptr<Mutex>> pending_mutexes;
|
||||
boost::container::flat_set<std::shared_ptr<Mutex>> pending_mutexes{};
|
||||
|
||||
Process* owner_process; ///< Process that owns this thread
|
||||
std::shared_ptr<Process> owner_process{}; ///< Process that owns this thread
|
||||
|
||||
/// Objects that the thread is waiting on, in the same order as they were
|
||||
// passed to WaitSynchronization1/N.
|
||||
std::vector<std::shared_ptr<WaitObject>> wait_objects;
|
||||
std::vector<std::shared_ptr<WaitObject>> wait_objects{};
|
||||
|
||||
VAddr wait_address; ///< If waiting on an AddressArbiter, this is the arbitration address
|
||||
|
||||
std::string name;
|
||||
std::string name{};
|
||||
|
||||
using WakeupCallback = void(ThreadWakeupReason reason, std::shared_ptr<Thread> thread,
|
||||
std::shared_ptr<WaitObject> object);
|
||||
// Callback that will be invoked when the thread is resumed from a waiting state. If the thread
|
||||
// was waiting via WaitSynchronizationN then the object will be the last object that became
|
||||
// available. In case of a timeout, the object will be nullptr.
|
||||
std::function<WakeupCallback> wakeup_callback;
|
||||
std::shared_ptr<WakeupCallback> wakeup_callback{};
|
||||
|
||||
const u32 core_id;
|
||||
|
||||
private:
|
||||
ThreadManager& thread_manager;
|
||||
|
||||
friend class boost::serialization::access;
|
||||
template <class Archive>
|
||||
void serialize(Archive& ar, const unsigned int file_version);
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -314,3 +345,22 @@ std::shared_ptr<Thread> SetupMainThread(KernelSystem& kernel, u32 entry_point, u
|
|||
std::shared_ptr<Process> owner_process);
|
||||
|
||||
} // namespace Kernel
|
||||
|
||||
BOOST_CLASS_EXPORT_KEY(Kernel::Thread)
|
||||
|
||||
namespace boost::serialization {
|
||||
|
||||
template <class Archive>
|
||||
inline void save_construct_data(Archive& ar, const Kernel::Thread* t,
|
||||
const unsigned int file_version) {
|
||||
ar << t->core_id;
|
||||
}
|
||||
|
||||
template <class Archive>
|
||||
inline void load_construct_data(Archive& ar, Kernel::Thread* t, const unsigned int file_version) {
|
||||
u32 core_id;
|
||||
ar >> core_id;
|
||||
::new (t) Kernel::Thread(Core::Global<Kernel::KernelSystem>(), core_id);
|
||||
}
|
||||
|
||||
} // namespace boost::serialization
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
|
||||
#include <cinttypes>
|
||||
#include <unordered_map>
|
||||
#include "common/archives.h"
|
||||
#include "common/assert.h"
|
||||
#include "common/logging/log.h"
|
||||
#include "core/core.h"
|
||||
|
@ -12,6 +13,8 @@
|
|||
#include "core/hle/kernel/thread.h"
|
||||
#include "core/hle/kernel/timer.h"
|
||||
|
||||
SERIALIZE_EXPORT_IMPL(Kernel::Timer)
|
||||
|
||||
namespace Kernel {
|
||||
|
||||
Timer::Timer(KernelSystem& kernel)
|
||||
|
|
|
@ -4,6 +4,8 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include <boost/serialization/string.hpp>
|
||||
#include <boost/serialization/unordered_map.hpp>
|
||||
#include "common/common_types.h"
|
||||
#include "core/core_timing.h"
|
||||
#include "core/hle/kernel/object.h"
|
||||
|
@ -33,6 +35,13 @@ private:
|
|||
|
||||
friend class Timer;
|
||||
friend class KernelSystem;
|
||||
|
||||
friend class boost::serialization::access;
|
||||
template <class Archive>
|
||||
void serialize(Archive& ar, const unsigned int file_version) {
|
||||
ar& next_timer_callback_id;
|
||||
ar& timer_callback_table;
|
||||
}
|
||||
};
|
||||
|
||||
class Timer final : public WaitObject {
|
||||
|
@ -103,6 +112,21 @@ private:
|
|||
TimerManager& timer_manager;
|
||||
|
||||
friend class KernelSystem;
|
||||
|
||||
friend class boost::serialization::access;
|
||||
template <class Archive>
|
||||
void serialize(Archive& ar, const unsigned int file_version) {
|
||||
ar& boost::serialization::base_object<WaitObject>(*this);
|
||||
ar& reset_type;
|
||||
ar& initial_delay;
|
||||
ar& interval_delay;
|
||||
ar& signaled;
|
||||
ar& name;
|
||||
ar& callback_id;
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace Kernel
|
||||
|
||||
BOOST_CLASS_EXPORT_KEY(Kernel::Timer)
|
||||
CONSTRUCT_KERNEL_OBJECT(Kernel::Timer)
|
||||
|
|
|
@ -27,7 +27,8 @@ bool VirtualMemoryArea::CanBeMergedWith(const VirtualMemoryArea& next) const {
|
|||
type != next.type) {
|
||||
return false;
|
||||
}
|
||||
if (type == VMAType::BackingMemory && backing_memory + size != next.backing_memory) {
|
||||
if (type == VMAType::BackingMemory &&
|
||||
backing_memory.GetPtr() + size != next.backing_memory.GetPtr()) {
|
||||
return false;
|
||||
}
|
||||
if (type == VMAType::MMIO && paddr + size != next.paddr) {
|
||||
|
@ -36,7 +37,8 @@ bool VirtualMemoryArea::CanBeMergedWith(const VirtualMemoryArea& next) const {
|
|||
return true;
|
||||
}
|
||||
|
||||
VMManager::VMManager(Memory::MemorySystem& memory) : memory(memory) {
|
||||
VMManager::VMManager(Memory::MemorySystem& memory)
|
||||
: memory(memory), page_table(std::make_shared<Memory::PageTable>()) {
|
||||
Reset();
|
||||
}
|
||||
|
||||
|
@ -50,8 +52,7 @@ void VMManager::Reset() {
|
|||
initial_vma.size = MAX_ADDRESS;
|
||||
vma_map.emplace(initial_vma.base, initial_vma);
|
||||
|
||||
page_table.pointers.fill(nullptr);
|
||||
page_table.attributes.fill(Memory::PageType::Unmapped);
|
||||
page_table->Clear();
|
||||
|
||||
UpdatePageTableForVMA(initial_vma);
|
||||
}
|
||||
|
@ -64,7 +65,7 @@ VMManager::VMAHandle VMManager::FindVMA(VAddr target) const {
|
|||
}
|
||||
}
|
||||
|
||||
ResultVal<VAddr> VMManager::MapBackingMemoryToBase(VAddr base, u32 region_size, u8* memory,
|
||||
ResultVal<VAddr> VMManager::MapBackingMemoryToBase(VAddr base, u32 region_size, MemoryRef memory,
|
||||
u32 size, MemoryState state) {
|
||||
|
||||
// Find the first Free VMA.
|
||||
|
@ -93,9 +94,9 @@ ResultVal<VAddr> VMManager::MapBackingMemoryToBase(VAddr base, u32 region_size,
|
|||
return MakeResult<VAddr>(target);
|
||||
}
|
||||
|
||||
ResultVal<VMManager::VMAHandle> VMManager::MapBackingMemory(VAddr target, u8* memory, u32 size,
|
||||
MemoryState state) {
|
||||
ASSERT(memory != nullptr);
|
||||
ResultVal<VMManager::VMAHandle> VMManager::MapBackingMemory(VAddr target, MemoryRef memory,
|
||||
u32 size, MemoryState state) {
|
||||
ASSERT(memory.GetPtr() != nullptr);
|
||||
|
||||
// This is the appropriately sized VMA that will turn into our allocation.
|
||||
CASCADE_RESULT(VMAIter vma_handle, CarveVMA(target, size));
|
||||
|
@ -351,20 +352,20 @@ VMManager::VMAIter VMManager::MergeAdjacent(VMAIter iter) {
|
|||
void VMManager::UpdatePageTableForVMA(const VirtualMemoryArea& vma) {
|
||||
switch (vma.type) {
|
||||
case VMAType::Free:
|
||||
memory.UnmapRegion(page_table, vma.base, vma.size);
|
||||
memory.UnmapRegion(*page_table, vma.base, vma.size);
|
||||
break;
|
||||
case VMAType::BackingMemory:
|
||||
memory.MapMemoryRegion(page_table, vma.base, vma.size, vma.backing_memory);
|
||||
memory.MapMemoryRegion(*page_table, vma.base, vma.size, vma.backing_memory);
|
||||
break;
|
||||
case VMAType::MMIO:
|
||||
memory.MapIoRegion(page_table, vma.base, vma.size, vma.mmio_handler);
|
||||
memory.MapIoRegion(*page_table, vma.base, vma.size, vma.mmio_handler);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
ResultVal<std::vector<std::pair<u8*, u32>>> VMManager::GetBackingBlocksForRange(VAddr address,
|
||||
u32 size) {
|
||||
std::vector<std::pair<u8*, u32>> backing_blocks;
|
||||
ResultVal<std::vector<std::pair<MemoryRef, u32>>> VMManager::GetBackingBlocksForRange(VAddr address,
|
||||
u32 size) {
|
||||
std::vector<std::pair<MemoryRef, u32>> backing_blocks;
|
||||
VAddr interval_target = address;
|
||||
while (interval_target != address + size) {
|
||||
auto vma = FindVMA(interval_target);
|
||||
|
@ -375,7 +376,7 @@ ResultVal<std::vector<std::pair<u8*, u32>>> VMManager::GetBackingBlocksForRange(
|
|||
|
||||
VAddr interval_end = std::min(address + size, vma->second.base + vma->second.size);
|
||||
u32 interval_size = interval_end - interval_target;
|
||||
u8* backing_memory = vma->second.backing_memory + (interval_target - vma->second.base);
|
||||
auto backing_memory = vma->second.backing_memory + (interval_target - vma->second.base);
|
||||
backing_blocks.push_back({backing_memory, interval_size});
|
||||
|
||||
interval_target += interval_size;
|
||||
|
|
|
@ -8,7 +8,11 @@
|
|||
#include <memory>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
#include <boost/serialization/map.hpp>
|
||||
#include <boost/serialization/shared_ptr.hpp>
|
||||
#include <boost/serialization/split_member.hpp>
|
||||
#include "common/common_types.h"
|
||||
#include "common/memory_ref.h"
|
||||
#include "core/hle/result.h"
|
||||
#include "core/memory.h"
|
||||
#include "core/mmio.h"
|
||||
|
@ -71,7 +75,7 @@ struct VirtualMemoryArea {
|
|||
|
||||
// Settings for type = BackingMemory
|
||||
/// Pointer backing this VMA. It will not be destroyed or freed when the VMA is removed.
|
||||
u8* backing_memory = nullptr;
|
||||
MemoryRef backing_memory{};
|
||||
|
||||
// Settings for type = MMIO
|
||||
/// Physical address of the register area this VMA maps to.
|
||||
|
@ -80,6 +84,20 @@ struct VirtualMemoryArea {
|
|||
|
||||
/// Tests if this area can be merged to the right with `next`.
|
||||
bool CanBeMergedWith(const VirtualMemoryArea& next) const;
|
||||
|
||||
private:
|
||||
friend class boost::serialization::access;
|
||||
template <class Archive>
|
||||
void serialize(Archive& ar, const unsigned int file_version) {
|
||||
ar& base;
|
||||
ar& size;
|
||||
ar& type;
|
||||
ar& permissions;
|
||||
ar& meminfo_state;
|
||||
ar& backing_memory;
|
||||
ar& paddr;
|
||||
ar& mmio_handler;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -134,7 +152,7 @@ public:
|
|||
* @param state MemoryState tag to attach to the VMA.
|
||||
* @returns The address at which the memory was mapped.
|
||||
*/
|
||||
ResultVal<VAddr> MapBackingMemoryToBase(VAddr base, u32 region_size, u8* memory, u32 size,
|
||||
ResultVal<VAddr> MapBackingMemoryToBase(VAddr base, u32 region_size, MemoryRef memory, u32 size,
|
||||
MemoryState state);
|
||||
/**
|
||||
* Maps an unmanaged host memory pointer at a given address.
|
||||
|
@ -144,7 +162,8 @@ public:
|
|||
* @param size Size of the mapping.
|
||||
* @param state MemoryState tag to attach to the VMA.
|
||||
*/
|
||||
ResultVal<VMAHandle> MapBackingMemory(VAddr target, u8* memory, u32 size, MemoryState state);
|
||||
ResultVal<VMAHandle> MapBackingMemory(VAddr target, MemoryRef memory, u32 size,
|
||||
MemoryState state);
|
||||
|
||||
/**
|
||||
* Maps a memory-mapped IO region at a given address.
|
||||
|
@ -186,11 +205,12 @@ public:
|
|||
void LogLayout(Log::Level log_level) const;
|
||||
|
||||
/// Gets a list of backing memory blocks for the specified range
|
||||
ResultVal<std::vector<std::pair<u8*, u32>>> GetBackingBlocksForRange(VAddr address, u32 size);
|
||||
ResultVal<std::vector<std::pair<MemoryRef, u32>>> GetBackingBlocksForRange(VAddr address,
|
||||
u32 size);
|
||||
|
||||
/// Each VMManager has its own page table, which is set as the main one when the owning process
|
||||
/// is scheduled.
|
||||
Memory::PageTable page_table;
|
||||
std::shared_ptr<Memory::PageTable> page_table;
|
||||
|
||||
private:
|
||||
using VMAIter = decltype(vma_map)::iterator;
|
||||
|
@ -229,5 +249,12 @@ private:
|
|||
void UpdatePageTableForVMA(const VirtualMemoryArea& vma);
|
||||
|
||||
Memory::MemorySystem& memory;
|
||||
|
||||
template <class Archive>
|
||||
void serialize(Archive& ar, const unsigned int) {
|
||||
ar& vma_map;
|
||||
ar& page_table;
|
||||
}
|
||||
friend class boost::serialization::access;
|
||||
};
|
||||
} // namespace Kernel
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
|
||||
#include <algorithm>
|
||||
#include <utility>
|
||||
#include "common/archives.h"
|
||||
#include "common/assert.h"
|
||||
#include "common/logging/log.h"
|
||||
#include "core/hle/kernel/errors.h"
|
||||
|
@ -16,6 +17,15 @@
|
|||
|
||||
namespace Kernel {
|
||||
|
||||
template <class Archive>
|
||||
void WaitObject::serialize(Archive& ar, const unsigned int file_version) {
|
||||
ar& boost::serialization::base_object<Object>(*this);
|
||||
ar& waiting_threads;
|
||||
// NB: hle_notifier *not* serialized since it's a callback!
|
||||
// Fortunately it's only used in one place (DSP) so we can reconstruct it there
|
||||
}
|
||||
SERIALIZE_IMPL(WaitObject)
|
||||
|
||||
void WaitObject::AddWaitingThread(std::shared_ptr<Thread> thread) {
|
||||
auto itr = std::find(waiting_threads.begin(), waiting_threads.end(), thread);
|
||||
if (itr == waiting_threads.end())
|
||||
|
@ -80,7 +90,7 @@ void WaitObject::WakeupAllWaitingThreads() {
|
|||
|
||||
// Invoke the wakeup callback before clearing the wait objects
|
||||
if (thread->wakeup_callback)
|
||||
thread->wakeup_callback(ThreadWakeupReason::Signal, thread, SharedFrom(this));
|
||||
thread->wakeup_callback->WakeUp(ThreadWakeupReason::Signal, thread, SharedFrom(this));
|
||||
|
||||
for (auto& object : thread->wait_objects)
|
||||
object->RemoveWaitingThread(thread.get());
|
||||
|
|
|
@ -7,6 +7,9 @@
|
|||
#include <functional>
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
#include <boost/serialization/base_object.hpp>
|
||||
#include <boost/serialization/shared_ptr.hpp>
|
||||
#include <boost/serialization/vector.hpp>
|
||||
#include "common/common_types.h"
|
||||
#include "core/hle/kernel/object.h"
|
||||
|
||||
|
@ -62,6 +65,11 @@ private:
|
|||
|
||||
/// Function to call when this object becomes available
|
||||
std::function<void()> hle_notifier;
|
||||
|
||||
private:
|
||||
friend class boost::serialization::access;
|
||||
template <class Archive>
|
||||
void serialize(Archive& ar, const unsigned int file_version);
|
||||
};
|
||||
|
||||
// Specialization of DynamicObjectCast for WaitObjects
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
|
||||
#include <new>
|
||||
#include <utility>
|
||||
#include <boost/serialization/access.hpp>
|
||||
#include "common/assert.h"
|
||||
#include "common/bit_field.h"
|
||||
#include "common/common_funcs.h"
|
||||
|
@ -225,6 +226,13 @@ union ResultCode {
|
|||
constexpr bool IsError() const {
|
||||
return is_error.ExtractValue(raw) == 1;
|
||||
}
|
||||
|
||||
private:
|
||||
template <class Archive>
|
||||
void serialize(Archive& ar, const unsigned int) {
|
||||
ar& raw;
|
||||
}
|
||||
friend class boost::serialization::access;
|
||||
};
|
||||
|
||||
constexpr bool operator==(const ResultCode& a, const ResultCode& b) {
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
// Refer to the license.txt file included.
|
||||
|
||||
#include <vector>
|
||||
#include "common/archives.h"
|
||||
#include "common/common_types.h"
|
||||
#include "common/logging/log.h"
|
||||
#include "core/core.h"
|
||||
|
@ -179,4 +180,15 @@ void InstallInterfaces(Core::System& system) {
|
|||
std::make_shared<AC_U>(ac)->InstallAsService(service_manager);
|
||||
}
|
||||
|
||||
template <class Archive>
|
||||
void Module::serialize(Archive& ar, const unsigned int) {
|
||||
ar& ac_connected;
|
||||
ar& close_event;
|
||||
ar& connect_event;
|
||||
ar& disconnect_event;
|
||||
// default_config is never written to
|
||||
}
|
||||
|
||||
} // namespace Service::AC
|
||||
|
||||
SERIALIZE_IMPL(Service::AC::Module)
|
||||
|
|
|
@ -153,6 +153,11 @@ protected:
|
|||
std::shared_ptr<Kernel::Event> close_event;
|
||||
std::shared_ptr<Kernel::Event> connect_event;
|
||||
std::shared_ptr<Kernel::Event> disconnect_event;
|
||||
|
||||
private:
|
||||
template <class Archive>
|
||||
void serialize(Archive& ar, const unsigned int file_version);
|
||||
friend class boost::serialization::access;
|
||||
};
|
||||
|
||||
void InstallInterfaces(Core::System& system);
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#include "common/archives.h"
|
||||
#include "core/hle/service/ac/ac_i.h"
|
||||
|
||||
namespace Service::AC {
|
||||
|
@ -33,3 +34,5 @@ AC_I::AC_I(std::shared_ptr<Module> ac) : Module::Interface(std::move(ac), "ac:i"
|
|||
}
|
||||
|
||||
} // namespace Service::AC
|
||||
|
||||
SERIALIZE_EXPORT_IMPL(Service::AC::AC_I)
|
||||
|
|
|
@ -12,6 +12,12 @@ namespace Service::AC {
|
|||
class AC_I final : public Module::Interface {
|
||||
public:
|
||||
explicit AC_I(std::shared_ptr<Module> ac);
|
||||
|
||||
private:
|
||||
SERVICE_SERIALIZATION(AC_I, ac, Module)
|
||||
};
|
||||
|
||||
} // namespace Service::AC
|
||||
|
||||
BOOST_CLASS_EXPORT_KEY(Service::AC::AC_I)
|
||||
BOOST_SERIALIZATION_CONSTRUCT(Service::AC::AC_I)
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#include "common/archives.h"
|
||||
#include "core/hle/service/ac/ac_u.h"
|
||||
|
||||
namespace Service::AC {
|
||||
|
@ -33,3 +34,5 @@ AC_U::AC_U(std::shared_ptr<Module> ac) : Module::Interface(std::move(ac), "ac:u"
|
|||
}
|
||||
|
||||
} // namespace Service::AC
|
||||
|
||||
SERIALIZE_EXPORT_IMPL(Service::AC::AC_U)
|
||||
|
|
|
@ -12,6 +12,12 @@ namespace Service::AC {
|
|||
class AC_U final : public Module::Interface {
|
||||
public:
|
||||
explicit AC_U(std::shared_ptr<Module> ac);
|
||||
|
||||
private:
|
||||
SERVICE_SERIALIZATION(AC_U, ac, Module)
|
||||
};
|
||||
|
||||
} // namespace Service::AC
|
||||
|
||||
BOOST_CLASS_EXPORT_KEY(Service::AC::AC_U)
|
||||
BOOST_SERIALIZATION_CONSTRUCT(Service::AC::AC_U)
|
||||
|
|
|
@ -20,9 +20,14 @@ public:
|
|||
Interface(std::shared_ptr<Module> act, const char* name);
|
||||
~Interface();
|
||||
|
||||
private:
|
||||
protected:
|
||||
std::shared_ptr<Module> act;
|
||||
};
|
||||
|
||||
private:
|
||||
template <class Archive>
|
||||
void serialize(Archive& ar, const unsigned int file_version) {}
|
||||
friend class boost::serialization::access;
|
||||
};
|
||||
|
||||
void InstallInterfaces(Core::System& system);
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#include "common/archives.h"
|
||||
#include "core/hle/service/act/act_a.h"
|
||||
|
||||
namespace Service::ACT {
|
||||
|
@ -24,3 +25,5 @@ ACT_A::ACT_A(std::shared_ptr<Module> act) : Module::Interface(std::move(act), "a
|
|||
}
|
||||
|
||||
} // namespace Service::ACT
|
||||
|
||||
SERIALIZE_EXPORT_IMPL(Service::ACT::ACT_A)
|
||||
|
|
|
@ -11,6 +11,12 @@ namespace Service::ACT {
|
|||
class ACT_A final : public Module::Interface {
|
||||
public:
|
||||
explicit ACT_A(std::shared_ptr<Module> act);
|
||||
|
||||
private:
|
||||
SERVICE_SERIALIZATION(ACT_A, act, Module)
|
||||
};
|
||||
|
||||
} // namespace Service::ACT
|
||||
|
||||
BOOST_CLASS_EXPORT_KEY(Service::ACT::ACT_A)
|
||||
BOOST_SERIALIZATION_CONSTRUCT(Service::ACT::ACT_A)
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#include "common/archives.h"
|
||||
#include "core/hle/service/act/act_u.h"
|
||||
|
||||
namespace Service::ACT {
|
||||
|
@ -20,3 +21,5 @@ ACT_U::ACT_U(std::shared_ptr<Module> act) : Module::Interface(std::move(act), "a
|
|||
}
|
||||
|
||||
} // namespace Service::ACT
|
||||
|
||||
SERIALIZE_EXPORT_IMPL(Service::ACT::ACT_U)
|
||||
|
|
|
@ -11,6 +11,12 @@ namespace Service::ACT {
|
|||
class ACT_U final : public Module::Interface {
|
||||
public:
|
||||
explicit ACT_U(std::shared_ptr<Module> act);
|
||||
|
||||
private:
|
||||
SERVICE_SERIALIZATION(ACT_U, act, Module)
|
||||
};
|
||||
|
||||
} // namespace Service::ACT
|
||||
|
||||
BOOST_CLASS_EXPORT_KEY(Service::ACT::ACT_U)
|
||||
BOOST_SERIALIZATION_CONSTRUCT(Service::ACT::ACT_U)
|
||||
|
|
|
@ -1053,7 +1053,7 @@ void Module::Interface::BeginImportProgram(Kernel::HLERequestContext& ctx) {
|
|||
// Citra will store contents out to sdmc/nand
|
||||
const FileSys::Path cia_path = {};
|
||||
auto file = std::make_shared<Service::FS::File>(
|
||||
am->system, std::make_unique<CIAFile>(media_type), cia_path);
|
||||
am->kernel, std::make_unique<CIAFile>(media_type), cia_path);
|
||||
|
||||
am->cia_installing = true;
|
||||
|
||||
|
@ -1080,7 +1080,7 @@ void Module::Interface::BeginImportProgramTemporarily(Kernel::HLERequestContext&
|
|||
// contents out to sdmc/nand
|
||||
const FileSys::Path cia_path = {};
|
||||
auto file = std::make_shared<Service::FS::File>(
|
||||
am->system, std::make_unique<CIAFile>(FS::MediaType::NAND), cia_path);
|
||||
am->kernel, std::make_unique<CIAFile>(FS::MediaType::NAND), cia_path);
|
||||
|
||||
am->cia_installing = true;
|
||||
|
||||
|
@ -1482,11 +1482,13 @@ void Module::Interface::GetMetaDataFromCia(Kernel::HLERequestContext& ctx) {
|
|||
rb.PushMappedBuffer(output_buffer);
|
||||
}
|
||||
|
||||
Module::Module(Core::System& system) : system(system) {
|
||||
Module::Module(Core::System& system) : kernel(system.Kernel()) {
|
||||
ScanForAllTitles();
|
||||
system_updater_mutex = system.Kernel().CreateMutex(false, "AM::SystemUpdaterMutex");
|
||||
}
|
||||
|
||||
Module::Module(Kernel::KernelSystem& kernel) : kernel(kernel) {}
|
||||
|
||||
Module::~Module() = default;
|
||||
|
||||
void InstallInterfaces(Core::System& system) {
|
||||
|
|
|
@ -9,9 +9,14 @@
|
|||
#include <memory>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <boost/serialization/array.hpp>
|
||||
#include <boost/serialization/shared_ptr.hpp>
|
||||
#include <boost/serialization/vector.hpp>
|
||||
#include "common/common_types.h"
|
||||
#include "common/construct.h"
|
||||
#include "core/file_sys/cia_container.h"
|
||||
#include "core/file_sys/file_backend.h"
|
||||
#include "core/global.h"
|
||||
#include "core/hle/kernel/mutex.h"
|
||||
#include "core/hle/result.h"
|
||||
#include "core/hle/service/service.h"
|
||||
|
@ -557,11 +562,13 @@ public:
|
|||
*/
|
||||
void GetMetaDataFromCia(Kernel::HLERequestContext& ctx);
|
||||
|
||||
private:
|
||||
protected:
|
||||
std::shared_ptr<Module> am;
|
||||
};
|
||||
|
||||
private:
|
||||
explicit Module(Kernel::KernelSystem& kernel);
|
||||
|
||||
/**
|
||||
* Scans the for titles in a storage medium for listing.
|
||||
* @param media_type the storage medium to scan
|
||||
|
@ -573,12 +580,32 @@ private:
|
|||
*/
|
||||
void ScanForAllTitles();
|
||||
|
||||
Core::System& system;
|
||||
Kernel::KernelSystem& kernel;
|
||||
bool cia_installing = false;
|
||||
std::array<std::vector<u64_le>, 3> am_title_list;
|
||||
std::shared_ptr<Kernel::Mutex> system_updater_mutex;
|
||||
|
||||
template <class Archive>
|
||||
void serialize(Archive& ar, const unsigned int) {
|
||||
ar& cia_installing;
|
||||
ar& am_title_list;
|
||||
ar& system_updater_mutex;
|
||||
}
|
||||
|
||||
template <class Archive>
|
||||
static void load_construct(Archive& ar, Module* t, const unsigned int file_version) {
|
||||
::new (t) Module(Core::Global<Kernel::KernelSystem>());
|
||||
}
|
||||
|
||||
template <class Archive>
|
||||
void save_construct(Archive& ar, const unsigned int file_version) const {}
|
||||
|
||||
friend class ::construct_access;
|
||||
friend class boost::serialization::access;
|
||||
};
|
||||
|
||||
void InstallInterfaces(Core::System& system);
|
||||
|
||||
} // namespace Service::AM
|
||||
|
||||
BOOST_SERIALIZATION_CONSTRUCT(Service::AM::Module);
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#include "common/archives.h"
|
||||
#include "core/hle/service/am/am_app.h"
|
||||
|
||||
namespace Service::AM {
|
||||
|
@ -26,3 +27,5 @@ AM_APP::AM_APP(std::shared_ptr<Module> am) : Module::Interface(std::move(am), "a
|
|||
}
|
||||
|
||||
} // namespace Service::AM
|
||||
|
||||
SERIALIZE_EXPORT_IMPL(Service::AM::AM_APP)
|
||||
|
|
|
@ -11,6 +11,12 @@ namespace Service::AM {
|
|||
class AM_APP final : public Module::Interface {
|
||||
public:
|
||||
explicit AM_APP(std::shared_ptr<Module> am);
|
||||
|
||||
private:
|
||||
SERVICE_SERIALIZATION(AM_APP, am, Module)
|
||||
};
|
||||
|
||||
} // namespace Service::AM
|
||||
|
||||
BOOST_CLASS_EXPORT_KEY(Service::AM::AM_APP)
|
||||
BOOST_SERIALIZATION_CONSTRUCT(Service::AM::AM_APP)
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#include "common/archives.h"
|
||||
#include "core/hle/service/am/am_net.h"
|
||||
|
||||
namespace Service::AM {
|
||||
|
@ -123,3 +124,5 @@ AM_NET::AM_NET(std::shared_ptr<Module> am) : Module::Interface(std::move(am), "a
|
|||
}
|
||||
|
||||
} // namespace Service::AM
|
||||
|
||||
SERIALIZE_EXPORT_IMPL(Service::AM::AM_NET)
|
||||
|
|
|
@ -11,6 +11,12 @@ namespace Service::AM {
|
|||
class AM_NET final : public Module::Interface {
|
||||
public:
|
||||
explicit AM_NET(std::shared_ptr<Module> am);
|
||||
|
||||
private:
|
||||
SERVICE_SERIALIZATION(AM_NET, am, Module)
|
||||
};
|
||||
|
||||
} // namespace Service::AM
|
||||
|
||||
BOOST_CLASS_EXPORT_KEY(Service::AM::AM_NET)
|
||||
BOOST_SERIALIZATION_CONSTRUCT(Service::AM::AM_NET)
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#include "common/archives.h"
|
||||
#include "core/hle/service/am/am_sys.h"
|
||||
|
||||
namespace Service::AM {
|
||||
|
@ -71,3 +72,5 @@ AM_SYS::AM_SYS(std::shared_ptr<Module> am) : Module::Interface(std::move(am), "a
|
|||
}
|
||||
|
||||
} // namespace Service::AM
|
||||
|
||||
SERIALIZE_EXPORT_IMPL(Service::AM::AM_SYS)
|
||||
|
|
|
@ -11,6 +11,12 @@ namespace Service::AM {
|
|||
class AM_SYS final : public Module::Interface {
|
||||
public:
|
||||
explicit AM_SYS(std::shared_ptr<Module> am);
|
||||
|
||||
private:
|
||||
SERVICE_SERIALIZATION(AM_SYS, am, Module)
|
||||
};
|
||||
|
||||
} // namespace Service::AM
|
||||
|
||||
BOOST_CLASS_EXPORT_KEY(Service::AM::AM_SYS)
|
||||
BOOST_SERIALIZATION_CONSTRUCT(Service::AM::AM_SYS)
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#include "common/archives.h"
|
||||
#include "core/hle/service/am/am_u.h"
|
||||
|
||||
namespace Service::AM {
|
||||
|
@ -83,3 +84,5 @@ AM_U::AM_U(std::shared_ptr<Module> am) : Module::Interface(std::move(am), "am:u"
|
|||
}
|
||||
|
||||
} // namespace Service::AM
|
||||
|
||||
SERIALIZE_EXPORT_IMPL(Service::AM::AM_U)
|
||||
|
|
|
@ -11,6 +11,12 @@ namespace Service::AM {
|
|||
class AM_U final : public Module::Interface {
|
||||
public:
|
||||
explicit AM_U(std::shared_ptr<Module> am);
|
||||
|
||||
private:
|
||||
SERVICE_SERIALIZATION(AM_U, am, Module)
|
||||
};
|
||||
|
||||
} // namespace Service::AM
|
||||
|
||||
BOOST_CLASS_EXPORT_KEY(Service::AM::AM_U)
|
||||
BOOST_SERIALIZATION_CONSTRUCT(Service::AM::AM_U)
|
||||
|
|
|
@ -10,6 +10,8 @@
|
|||
#include "core/hle/service/apt/ns.h"
|
||||
#include "core/hle/service/cfg/cfg.h"
|
||||
|
||||
SERVICE_CONSTRUCT_IMPL(Service::APT::AppletManager)
|
||||
|
||||
namespace Service::APT {
|
||||
|
||||
enum class AppletPos { Application = 0, Library = 1, System = 2, SysLibrary = 3, Resident = 4 };
|
||||
|
|
|
@ -6,8 +6,12 @@
|
|||
|
||||
#include <array>
|
||||
#include <memory>
|
||||
#include <optional>
|
||||
#include <vector>
|
||||
#include <boost/serialization/array.hpp>
|
||||
#include <boost/serialization/optional.hpp>
|
||||
#include <boost/serialization/shared_ptr.hpp>
|
||||
#include <boost/serialization/vector.hpp>
|
||||
#include "core/global.h"
|
||||
#include "core/hle/kernel/event.h"
|
||||
#include "core/hle/result.h"
|
||||
#include "core/hle/service/fs/archive.h"
|
||||
|
@ -84,6 +88,17 @@ struct MessageParameter {
|
|||
SignalType signal = SignalType::None;
|
||||
std::shared_ptr<Kernel::Object> object = nullptr;
|
||||
std::vector<u8> buffer;
|
||||
|
||||
private:
|
||||
template <class Archive>
|
||||
void serialize(Archive& ar, const unsigned int) {
|
||||
ar& sender_id;
|
||||
ar& destination_id;
|
||||
ar& signal;
|
||||
ar& object;
|
||||
ar& buffer;
|
||||
}
|
||||
friend class boost::serialization::access;
|
||||
};
|
||||
|
||||
/// Holds information about the parameters used in StartLibraryApplet
|
||||
|
@ -161,6 +176,16 @@ public:
|
|||
|
||||
u64 current_title_id;
|
||||
FS::MediaType current_media_type;
|
||||
|
||||
private:
|
||||
template <class Archive>
|
||||
void serialize(Archive& ar, const unsigned int) {
|
||||
ar& next_title_id;
|
||||
ar& next_media_type;
|
||||
ar& current_title_id;
|
||||
ar& current_media_type;
|
||||
}
|
||||
friend class boost::serialization::access;
|
||||
};
|
||||
|
||||
ApplicationJumpParameters GetApplicationJumpParameters() const {
|
||||
|
@ -169,7 +194,8 @@ public:
|
|||
|
||||
private:
|
||||
/// Parameter data to be returned in the next call to Glance/ReceiveParameter.
|
||||
std::optional<MessageParameter> next_parameter;
|
||||
// NOTE: A bug in gcc prevents serializing std::optional
|
||||
boost::optional<MessageParameter> next_parameter;
|
||||
|
||||
static constexpr std::size_t NumAppletSlot = 4;
|
||||
|
||||
|
@ -199,6 +225,20 @@ private:
|
|||
title_id = 0;
|
||||
attributes.raw = 0;
|
||||
}
|
||||
|
||||
private:
|
||||
template <class Archive>
|
||||
void serialize(Archive& ar, const unsigned int) {
|
||||
ar& applet_id;
|
||||
ar& slot;
|
||||
ar& title_id;
|
||||
ar& registered;
|
||||
ar& loaded;
|
||||
ar& attributes.raw;
|
||||
ar& notification_event;
|
||||
ar& parameter_event;
|
||||
}
|
||||
friend class boost::serialization::access;
|
||||
};
|
||||
|
||||
ApplicationJumpParameters app_jump_parameters{};
|
||||
|
@ -216,6 +256,18 @@ private:
|
|||
SignalType library_applet_closing_command;
|
||||
|
||||
Core::System& system;
|
||||
|
||||
private:
|
||||
template <class Archive>
|
||||
void serialize(Archive& ar, const unsigned int) {
|
||||
ar& next_parameter;
|
||||
ar& app_jump_parameters;
|
||||
ar& applet_slots;
|
||||
ar& library_applet_closing_command;
|
||||
}
|
||||
friend class boost::serialization::access;
|
||||
};
|
||||
|
||||
} // namespace Service::APT
|
||||
|
||||
SERVICE_CONSTRUCT(Service::APT::AppletManager)
|
||||
|
|
|
@ -2,6 +2,9 @@
|
|||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#include <boost/serialization/shared_ptr.hpp>
|
||||
#include <boost/serialization/vector.hpp>
|
||||
#include "common/archives.h"
|
||||
#include "common/common_paths.h"
|
||||
#include "common/file_util.h"
|
||||
#include "common/logging/log.h"
|
||||
|
@ -26,8 +29,25 @@
|
|||
#include "core/hw/aes/ccm.h"
|
||||
#include "core/hw/aes/key.h"
|
||||
|
||||
SERVICE_CONSTRUCT_IMPL(Service::APT::Module)
|
||||
|
||||
namespace Service::APT {
|
||||
|
||||
template <class Archive>
|
||||
void Module::serialize(Archive& ar, const unsigned int) {
|
||||
ar& shared_font_mem;
|
||||
ar& shared_font_loaded;
|
||||
ar& shared_font_relocated;
|
||||
ar& lock;
|
||||
ar& cpu_percent;
|
||||
ar& unknown_ns_state_field;
|
||||
ar& screen_capture_buffer;
|
||||
ar& screen_capture_post_permission;
|
||||
ar& applet_manager;
|
||||
}
|
||||
|
||||
SERIALIZE_IMPL(Module)
|
||||
|
||||
Module::NSInterface::NSInterface(std::shared_ptr<Module> apt, const char* name, u32 max_session)
|
||||
: ServiceFramework(name, max_session), apt(std::move(apt)) {}
|
||||
|
||||
|
|
|
@ -6,9 +6,11 @@
|
|||
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
#include "common/archives.h"
|
||||
#include "common/common_funcs.h"
|
||||
#include "common/common_types.h"
|
||||
#include "common/swap.h"
|
||||
#include "core/global.h"
|
||||
#include "core/hle/kernel/kernel.h"
|
||||
#include "core/hle/service/service.h"
|
||||
|
||||
|
@ -65,7 +67,7 @@ public:
|
|||
NSInterface(std::shared_ptr<Module> apt, const char* name, u32 max_session);
|
||||
~NSInterface();
|
||||
|
||||
private:
|
||||
protected:
|
||||
std::shared_ptr<Module> apt;
|
||||
};
|
||||
|
||||
|
@ -601,9 +603,16 @@ public:
|
|||
*/
|
||||
void CheckNew3DS(Kernel::HLERequestContext& ctx);
|
||||
|
||||
private:
|
||||
protected:
|
||||
bool application_reset_prepared{};
|
||||
std::shared_ptr<Module> apt;
|
||||
|
||||
private:
|
||||
template <class Archive>
|
||||
void serialize(Archive& ar, const unsigned int) {
|
||||
ar& application_reset_prepared;
|
||||
}
|
||||
friend class boost::serialization::access;
|
||||
};
|
||||
|
||||
private:
|
||||
|
@ -630,8 +639,14 @@ private:
|
|||
ScreencapPostPermission::CleanThePermission; // TODO(JamePeng): verify the initial value
|
||||
|
||||
std::shared_ptr<AppletManager> applet_manager;
|
||||
|
||||
template <class Archive>
|
||||
void serialize(Archive& ar, const unsigned int);
|
||||
friend class boost::serialization::access;
|
||||
};
|
||||
|
||||
void InstallInterfaces(Core::System& system);
|
||||
|
||||
} // namespace Service::APT
|
||||
|
||||
SERVICE_CONSTRUCT(Service::APT::Module)
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#include "common/archives.h"
|
||||
#include "core/hle/service/apt/apt_a.h"
|
||||
|
||||
namespace Service::APT {
|
||||
|
@ -105,3 +106,5 @@ APT_A::APT_A(std::shared_ptr<Module> apt)
|
|||
}
|
||||
|
||||
} // namespace Service::APT
|
||||
|
||||
SERIALIZE_EXPORT_IMPL(Service::APT::APT_A)
|
||||
|
|
|
@ -11,6 +11,12 @@ namespace Service::APT {
|
|||
class APT_A final : public Module::APTInterface {
|
||||
public:
|
||||
explicit APT_A(std::shared_ptr<Module> apt);
|
||||
|
||||
private:
|
||||
SERVICE_SERIALIZATION(APT_A, apt, Module)
|
||||
};
|
||||
|
||||
} // namespace Service::APT
|
||||
|
||||
BOOST_CLASS_EXPORT_KEY(Service::APT::APT_A)
|
||||
BOOST_SERIALIZATION_CONSTRUCT(Service::APT::APT_A)
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#include "common/archives.h"
|
||||
#include "core/hle/service/apt/apt_s.h"
|
||||
|
||||
namespace Service::APT {
|
||||
|
@ -105,3 +106,5 @@ APT_S::APT_S(std::shared_ptr<Module> apt)
|
|||
}
|
||||
|
||||
} // namespace Service::APT
|
||||
|
||||
SERIALIZE_EXPORT_IMPL(Service::APT::APT_S)
|
||||
|
|
|
@ -18,6 +18,12 @@ namespace Service::APT {
|
|||
class APT_S final : public Module::APTInterface {
|
||||
public:
|
||||
explicit APT_S(std::shared_ptr<Module> apt);
|
||||
|
||||
private:
|
||||
SERVICE_SERIALIZATION(APT_S, apt, Module)
|
||||
};
|
||||
|
||||
} // namespace Service::APT
|
||||
|
||||
BOOST_CLASS_EXPORT_KEY(Service::APT::APT_S)
|
||||
BOOST_SERIALIZATION_CONSTRUCT(Service::APT::APT_S)
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#include "common/archives.h"
|
||||
#include "core/hle/service/apt/apt_u.h"
|
||||
|
||||
namespace Service::APT {
|
||||
|
@ -102,3 +103,5 @@ APT_U::APT_U(std::shared_ptr<Module> apt)
|
|||
}
|
||||
|
||||
} // namespace Service::APT
|
||||
|
||||
SERIALIZE_EXPORT_IMPL(Service::APT::APT_U)
|
||||
|
|
|
@ -18,6 +18,12 @@ namespace Service::APT {
|
|||
class APT_U final : public Module::APTInterface {
|
||||
public:
|
||||
explicit APT_U(std::shared_ptr<Module> apt);
|
||||
|
||||
private:
|
||||
SERVICE_SERIALIZATION(APT_U, apt, Module)
|
||||
};
|
||||
|
||||
} // namespace Service::APT
|
||||
|
||||
BOOST_CLASS_EXPORT_KEY(Service::APT::APT_U)
|
||||
BOOST_SERIALIZATION_CONSTRUCT(Service::APT::APT_U)
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#include "common/archives.h"
|
||||
#include "core/hle/service/apt/ns_s.h"
|
||||
|
||||
namespace Service::NS {
|
||||
|
@ -29,3 +30,5 @@ NS_S::NS_S(std::shared_ptr<Service::APT::Module> apt)
|
|||
}
|
||||
|
||||
} // namespace Service::NS
|
||||
|
||||
SERIALIZE_EXPORT_IMPL(Service::NS::NS_S)
|
||||
|
|
|
@ -14,6 +14,12 @@ namespace Service::NS {
|
|||
class NS_S final : public Service::APT::Module::NSInterface {
|
||||
public:
|
||||
explicit NS_S(std::shared_ptr<Service::APT::Module> apt);
|
||||
|
||||
private:
|
||||
SERVICE_SERIALIZATION(NS_S, apt, Service::APT::Module)
|
||||
};
|
||||
|
||||
} // namespace Service::NS
|
||||
|
||||
BOOST_CLASS_EXPORT_KEY(Service::NS::NS_S)
|
||||
BOOST_SERIALIZATION_CONSTRUCT(Service::NS::NS_S)
|
||||
|
|
|
@ -5,6 +5,8 @@
|
|||
#pragma once
|
||||
|
||||
#include <memory>
|
||||
#include <boost/serialization/shared_ptr.hpp>
|
||||
#include "core/global.h"
|
||||
#include "core/hle/kernel/event.h"
|
||||
#include "core/hle/service/service.h"
|
||||
|
||||
|
@ -952,19 +954,42 @@ public:
|
|||
*/
|
||||
void GetNsDataNewFlagPrivileged(Kernel::HLERequestContext& ctx);
|
||||
|
||||
private:
|
||||
protected:
|
||||
std::shared_ptr<Module> boss;
|
||||
|
||||
private:
|
||||
u8 new_arrival_flag;
|
||||
u8 ns_data_new_flag;
|
||||
u8 ns_data_new_flag_privileged;
|
||||
u8 output_flag;
|
||||
|
||||
template <class Archive>
|
||||
void serialize(Archive& ar, const unsigned int) {
|
||||
ar& new_arrival_flag;
|
||||
ar& ns_data_new_flag;
|
||||
ar& ns_data_new_flag_privileged;
|
||||
ar& output_flag;
|
||||
}
|
||||
friend class boost::serialization::access;
|
||||
};
|
||||
|
||||
private:
|
||||
std::shared_ptr<Kernel::Event> task_finish_event;
|
||||
|
||||
template <class Archive>
|
||||
void serialize(Archive& ar, const unsigned int) {
|
||||
ar& task_finish_event;
|
||||
}
|
||||
friend class boost::serialization::access;
|
||||
};
|
||||
|
||||
void InstallInterfaces(Core::System& system);
|
||||
|
||||
} // namespace Service::BOSS
|
||||
|
||||
namespace boost::serialization {
|
||||
template <class Archive>
|
||||
void load_construct_data(Archive& ar, Service::BOSS::Module* t, const unsigned int) {
|
||||
::new (t) Service::BOSS::Module(Core::Global<Core::System>());
|
||||
}
|
||||
} // namespace boost::serialization
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#include "common/archives.h"
|
||||
#include "core/hle/service/boss/boss_p.h"
|
||||
|
||||
namespace Service::BOSS {
|
||||
|
@ -84,3 +85,5 @@ BOSS_P::BOSS_P(std::shared_ptr<Module> boss)
|
|||
}
|
||||
|
||||
} // namespace Service::BOSS
|
||||
|
||||
SERIALIZE_EXPORT_IMPL(Service::BOSS::BOSS_P)
|
||||
|
|
|
@ -11,6 +11,12 @@ namespace Service::BOSS {
|
|||
class BOSS_P final : public Module::Interface {
|
||||
public:
|
||||
explicit BOSS_P(std::shared_ptr<Module> boss);
|
||||
|
||||
private:
|
||||
SERVICE_SERIALIZATION(BOSS_P, boss, Module)
|
||||
};
|
||||
|
||||
} // namespace Service::BOSS
|
||||
|
||||
BOOST_CLASS_EXPORT_KEY(Service::BOSS::BOSS_P)
|
||||
BOOST_SERIALIZATION_CONSTRUCT(Service::BOSS::BOSS_P)
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#include "common/archives.h"
|
||||
#include "core/hle/service/boss/boss_u.h"
|
||||
|
||||
namespace Service::BOSS {
|
||||
|
@ -72,3 +73,5 @@ BOSS_U::BOSS_U(std::shared_ptr<Module> boss)
|
|||
}
|
||||
|
||||
} // namespace Service::BOSS
|
||||
|
||||
SERIALIZE_EXPORT_IMPL(Service::BOSS::BOSS_U)
|
||||
|
|
|
@ -11,6 +11,12 @@ namespace Service::BOSS {
|
|||
class BOSS_U final : public Module::Interface {
|
||||
public:
|
||||
explicit BOSS_U(std::shared_ptr<Module> boss);
|
||||
|
||||
private:
|
||||
SERVICE_SERIALIZATION(BOSS_U, boss, Module)
|
||||
};
|
||||
|
||||
} // namespace Service::BOSS
|
||||
|
||||
BOOST_CLASS_EXPORT_KEY(Service::BOSS::BOSS_U)
|
||||
BOOST_SERIALIZATION_CONSTRUCT(Service::BOSS::BOSS_U)
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
// Refer to the license.txt file included.
|
||||
|
||||
#include <algorithm>
|
||||
#include "common/archives.h"
|
||||
#include "common/bit_set.h"
|
||||
#include "common/logging/log.h"
|
||||
#include "core/core.h"
|
||||
|
@ -20,8 +21,32 @@
|
|||
#include "core/memory.h"
|
||||
#include "core/settings.h"
|
||||
|
||||
SERVICE_CONSTRUCT_IMPL(Service::CAM::Module)
|
||||
|
||||
namespace Service::CAM {
|
||||
|
||||
template <class Archive>
|
||||
void Module::serialize(Archive& ar, const unsigned int) {
|
||||
ar& cameras;
|
||||
ar& ports;
|
||||
ar& is_camera_reload_pending;
|
||||
if (Archive::is_loading::value) {
|
||||
for (int i = 0; i < NumCameras; i++) {
|
||||
LoadCameraImplementation(cameras[i], i);
|
||||
}
|
||||
for (std::size_t i = 0; i < ports.size(); i++) {
|
||||
if (ports[i].is_busy) {
|
||||
cameras[ports[i].camera_id].impl->StartCapture();
|
||||
}
|
||||
if (ports[i].is_receiving) {
|
||||
StartReceiving(static_cast<int>(i));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SERIALIZE_IMPL(Module)
|
||||
|
||||
// built-in resolution parameters
|
||||
constexpr std::array<Resolution, 8> PRESET_RESOLUTION{{
|
||||
{640, 480, 0, 0, 639, 479}, // VGA
|
||||
|
|
|
@ -9,8 +9,14 @@
|
|||
#include <future>
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
#include <boost/serialization/array.hpp>
|
||||
#include <boost/serialization/deque.hpp>
|
||||
#include <boost/serialization/shared_ptr.hpp>
|
||||
#include <boost/serialization/unique_ptr.hpp>
|
||||
#include <boost/serialization/version.hpp>
|
||||
#include "common/common_types.h"
|
||||
#include "common/swap.h"
|
||||
#include "core/global.h"
|
||||
#include "core/hle/result.h"
|
||||
#include "core/hle/service/service.h"
|
||||
|
||||
|
@ -180,6 +186,18 @@ struct Resolution {
|
|||
u16 crop_y0;
|
||||
u16 crop_x1;
|
||||
u16 crop_y1;
|
||||
|
||||
private:
|
||||
template <class Archive>
|
||||
void serialize(Archive& ar, const unsigned int) {
|
||||
ar& width;
|
||||
ar& height;
|
||||
ar& crop_x0;
|
||||
ar& crop_y0;
|
||||
ar& crop_x1;
|
||||
ar& crop_y1;
|
||||
}
|
||||
friend class boost::serialization::access;
|
||||
};
|
||||
|
||||
struct PackageParameterWithoutContext {
|
||||
|
@ -726,7 +744,7 @@ public:
|
|||
*/
|
||||
void DriverFinalize(Kernel::HLERequestContext& ctx);
|
||||
|
||||
private:
|
||||
protected:
|
||||
std::shared_ptr<Module> cam;
|
||||
};
|
||||
|
||||
|
@ -755,6 +773,16 @@ private:
|
|||
Effect effect{Effect::None};
|
||||
OutputFormat format{OutputFormat::YUV422};
|
||||
Resolution resolution = {0, 0, 0, 0, 0, 0};
|
||||
|
||||
private:
|
||||
template <class Archive>
|
||||
void serialize(Archive& ar, const unsigned int) {
|
||||
ar& flip;
|
||||
ar& effect;
|
||||
ar& format;
|
||||
ar& resolution;
|
||||
}
|
||||
friend class boost::serialization::access;
|
||||
};
|
||||
|
||||
struct CameraConfig {
|
||||
|
@ -762,6 +790,20 @@ private:
|
|||
std::array<ContextConfig, 2> contexts;
|
||||
int current_context{0};
|
||||
FrameRate frame_rate{FrameRate::Rate_15};
|
||||
|
||||
private:
|
||||
template <class Archive>
|
||||
void serialize(Archive& ar, const unsigned int file_version) {
|
||||
// For compatibility: put a nullptr here
|
||||
if (file_version == 0) {
|
||||
std::unique_ptr<Camera::CameraInterface> x;
|
||||
ar& x;
|
||||
}
|
||||
ar& contexts;
|
||||
ar& current_context;
|
||||
ar& frame_rate;
|
||||
}
|
||||
friend class boost::serialization::access;
|
||||
};
|
||||
|
||||
struct PortConfig {
|
||||
|
@ -798,6 +840,31 @@ private:
|
|||
u32 dest_size{0}; // the destination size of the receiving process
|
||||
|
||||
void Clear();
|
||||
|
||||
private:
|
||||
template <class Archive>
|
||||
void serialize(Archive& ar, const unsigned int) {
|
||||
ar& camera_id;
|
||||
ar& is_active;
|
||||
ar& is_pending_receiving;
|
||||
ar& is_busy;
|
||||
ar& is_receiving;
|
||||
ar& is_trimming;
|
||||
ar& x0;
|
||||
ar& y0;
|
||||
ar& x1;
|
||||
ar& y1;
|
||||
ar& transfer_bytes;
|
||||
ar& completion_event;
|
||||
ar& buffer_error_interrupt_event;
|
||||
ar& vsync_interrupt_event;
|
||||
ar& vsync_timings;
|
||||
// Ignore capture_result. In-progress captures might be affected but this is OK.
|
||||
ar& dest_process;
|
||||
ar& dest;
|
||||
ar& dest_size;
|
||||
}
|
||||
friend class boost::serialization::access;
|
||||
};
|
||||
|
||||
void LoadCameraImplementation(CameraConfig& camera, int camera_id);
|
||||
|
@ -808,6 +875,10 @@ private:
|
|||
Core::TimingEventType* completion_event_callback;
|
||||
Core::TimingEventType* vsync_interrupt_event_callback;
|
||||
std::atomic<bool> is_camera_reload_pending{false};
|
||||
|
||||
template <class Archive>
|
||||
void serialize(Archive& ar, const unsigned int);
|
||||
friend class boost::serialization::access;
|
||||
};
|
||||
|
||||
std::shared_ptr<Module> GetModule(Core::System& system);
|
||||
|
@ -815,3 +886,6 @@ std::shared_ptr<Module> GetModule(Core::System& system);
|
|||
void InstallInterfaces(Core::System& system);
|
||||
|
||||
} // namespace Service::CAM
|
||||
|
||||
SERVICE_CONSTRUCT(Service::CAM::Module)
|
||||
BOOST_CLASS_VERSION(Service::CAM::Module::CameraConfig, 1)
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#include "common/archives.h"
|
||||
#include "core/hle/service/cam/cam.h"
|
||||
#include "core/hle/service/cam/cam_c.h"
|
||||
|
||||
|
@ -79,3 +80,5 @@ CAM_C::CAM_C(std::shared_ptr<Module> cam) : Module::Interface(std::move(cam), "c
|
|||
}
|
||||
|
||||
} // namespace Service::CAM
|
||||
|
||||
SERIALIZE_EXPORT_IMPL(Service::CAM::CAM_C)
|
||||
|
|
|
@ -11,6 +11,12 @@ namespace Service::CAM {
|
|||
class CAM_C final : public Module::Interface {
|
||||
public:
|
||||
explicit CAM_C(std::shared_ptr<Module> cam);
|
||||
|
||||
private:
|
||||
SERVICE_SERIALIZATION(CAM_C, cam, Module)
|
||||
};
|
||||
|
||||
} // namespace Service::CAM
|
||||
|
||||
BOOST_CLASS_EXPORT_KEY(Service::CAM::CAM_C)
|
||||
BOOST_SERIALIZATION_CONSTRUCT(Service::CAM::CAM_C)
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#include "common/archives.h"
|
||||
#include "core/hle/service/cam/cam_q.h"
|
||||
|
||||
namespace Service::CAM {
|
||||
|
@ -13,3 +14,5 @@ CAM_Q::CAM_Q() : ServiceFramework("cam:q", 1 /*TODO: find the true value*/) {
|
|||
}
|
||||
|
||||
} // namespace Service::CAM
|
||||
|
||||
SERIALIZE_EXPORT_IMPL(Service::CAM::CAM_Q)
|
||||
|
|
|
@ -11,6 +11,11 @@ namespace Service::CAM {
|
|||
class CAM_Q : public ServiceFramework<CAM_Q> {
|
||||
public:
|
||||
CAM_Q();
|
||||
|
||||
private:
|
||||
SERVICE_SERIALIZATION_SIMPLE
|
||||
};
|
||||
|
||||
} // namespace Service::CAM
|
||||
|
||||
BOOST_CLASS_EXPORT_KEY(Service::CAM::CAM_Q)
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#include "common/archives.h"
|
||||
#include "core/hle/service/cam/cam.h"
|
||||
#include "core/hle/service/cam/cam_s.h"
|
||||
|
||||
|
@ -79,3 +80,5 @@ CAM_S::CAM_S(std::shared_ptr<Module> cam) : Module::Interface(std::move(cam), "c
|
|||
}
|
||||
|
||||
} // namespace Service::CAM
|
||||
|
||||
SERIALIZE_EXPORT_IMPL(Service::CAM::CAM_S)
|
||||
|
|
|
@ -11,6 +11,12 @@ namespace Service::CAM {
|
|||
class CAM_S final : public Module::Interface {
|
||||
public:
|
||||
explicit CAM_S(std::shared_ptr<Module> cam);
|
||||
|
||||
private:
|
||||
SERVICE_SERIALIZATION(CAM_S, cam, Module)
|
||||
};
|
||||
|
||||
} // namespace Service::CAM
|
||||
|
||||
BOOST_CLASS_EXPORT_KEY(Service::CAM::CAM_S)
|
||||
BOOST_SERIALIZATION_CONSTRUCT(Service::CAM::CAM_S)
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#include "common/archives.h"
|
||||
#include "core/hle/service/cam/cam.h"
|
||||
#include "core/hle/service/cam/cam_u.h"
|
||||
|
||||
|
@ -79,3 +80,5 @@ CAM_U::CAM_U(std::shared_ptr<Module> cam) : Module::Interface(std::move(cam), "c
|
|||
}
|
||||
|
||||
} // namespace Service::CAM
|
||||
|
||||
SERIALIZE_EXPORT_IMPL(Service::CAM::CAM_U)
|
||||
|
|
|
@ -11,6 +11,12 @@ namespace Service::CAM {
|
|||
class CAM_U final : public Module::Interface {
|
||||
public:
|
||||
explicit CAM_U(std::shared_ptr<Module> cam);
|
||||
|
||||
private:
|
||||
SERVICE_SERIALIZATION(CAM_U, cam, Module)
|
||||
};
|
||||
|
||||
} // namespace Service::CAM
|
||||
|
||||
BOOST_CLASS_EXPORT_KEY(Service::CAM::CAM_U)
|
||||
BOOST_SERIALIZATION_CONSTRUCT(Service::CAM::CAM_U)
|
||||
|
|
|
@ -2,9 +2,12 @@
|
|||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#include <boost/serialization/shared_ptr.hpp>
|
||||
#include <boost/serialization/unique_ptr.hpp>
|
||||
#include <cryptopp/base64.h>
|
||||
#include <cryptopp/hmac.h>
|
||||
#include <cryptopp/sha.h>
|
||||
#include "common/archives.h"
|
||||
#include "common/common_paths.h"
|
||||
#include "common/file_util.h"
|
||||
#include "common/logging/log.h"
|
||||
|
@ -24,8 +27,20 @@
|
|||
#include "core/hle/service/cfg/cfg.h"
|
||||
#include "fmt/format.h"
|
||||
|
||||
SERVICE_CONSTRUCT_IMPL(Service::CECD::Module)
|
||||
SERIALIZE_EXPORT_IMPL(Service::CECD::Module)
|
||||
SERIALIZE_EXPORT_IMPL(Service::CECD::Module::SessionData)
|
||||
|
||||
namespace Service::CECD {
|
||||
|
||||
template <class Archive>
|
||||
void Module::serialize(Archive& ar, const unsigned int) {
|
||||
ar& cecd_system_save_data_archive;
|
||||
ar& cecinfo_event;
|
||||
ar& change_state_event;
|
||||
}
|
||||
SERIALIZE_IMPL(Module)
|
||||
|
||||
using CecDataPathType = Module::CecDataPathType;
|
||||
using CecOpenMode = Module::CecOpenMode;
|
||||
using CecSystemInfoType = Module::CecSystemInfoType;
|
||||
|
@ -93,7 +108,7 @@ void Module::Interface::Open(Kernel::HLERequestContext& ctx) {
|
|||
} else {
|
||||
session_data->file = std::move(file_result).Unwrap();
|
||||
rb.Push(RESULT_SUCCESS);
|
||||
rb.Push<u32>(session_data->file->GetSize()); // Return file size
|
||||
rb.Push<u32>(static_cast<u32>(session_data->file->GetSize())); // Return file size
|
||||
}
|
||||
|
||||
if (path_type == CecDataPathType::MboxProgramId) {
|
||||
|
@ -141,8 +156,8 @@ void Module::Interface::Read(Kernel::HLERequestContext& ctx) {
|
|||
break;
|
||||
default: // If not directory, then it is a file
|
||||
std::vector<u8> buffer(write_buffer_size);
|
||||
const u32 bytes_read =
|
||||
session_data->file->Read(0, write_buffer_size, buffer.data()).Unwrap();
|
||||
const u32 bytes_read = static_cast<u32>(
|
||||
session_data->file->Read(0, write_buffer_size, buffer.data()).Unwrap());
|
||||
|
||||
write_buffer.Write(buffer.data(), 0, write_buffer_size);
|
||||
session_data->file->Close();
|
||||
|
@ -184,7 +199,8 @@ void Module::Interface::ReadMessage(Kernel::HLERequestContext& ctx) {
|
|||
auto message = std::move(message_result).Unwrap();
|
||||
std::vector<u8> buffer(buffer_size);
|
||||
|
||||
const u32 bytes_read = message->Read(0, buffer_size, buffer.data()).Unwrap();
|
||||
const u32 bytes_read =
|
||||
static_cast<u32>(message->Read(0, buffer_size, buffer.data()).Unwrap());
|
||||
write_buffer.Write(buffer.data(), 0, buffer_size);
|
||||
message->Close();
|
||||
|
||||
|
@ -253,7 +269,8 @@ void Module::Interface::ReadMessageWithHMAC(Kernel::HLERequestContext& ctx) {
|
|||
auto message = std::move(message_result).Unwrap();
|
||||
std::vector<u8> buffer(buffer_size);
|
||||
|
||||
const u32 bytes_read = message->Read(0, buffer_size, buffer.data()).Unwrap();
|
||||
const u32 bytes_read =
|
||||
static_cast<u32>(message->Read(0, buffer_size, buffer.data()).Unwrap());
|
||||
write_buffer.Write(buffer.data(), 0, buffer_size);
|
||||
message->Close();
|
||||
|
||||
|
@ -354,8 +371,8 @@ void Module::Interface::Write(Kernel::HLERequestContext& ctx) {
|
|||
buffer);
|
||||
}
|
||||
|
||||
const u32 bytes_written =
|
||||
session_data->file->Write(0, buffer.size(), true, buffer.data()).Unwrap();
|
||||
const u32 bytes_written = static_cast<u32>(
|
||||
session_data->file->Write(0, buffer.size(), true, buffer.data()).Unwrap());
|
||||
session_data->file->Close();
|
||||
|
||||
rb.Push(RESULT_SUCCESS);
|
||||
|
@ -416,7 +433,8 @@ void Module::Interface::WriteMessage(Kernel::HLERequestContext& ctx) {
|
|||
msg_header.sender_id, msg_header.sender_id2, msg_header.send_count,
|
||||
msg_header.forward_count, msg_header.user_data);
|
||||
|
||||
const u32 bytes_written = message->Write(0, buffer_size, true, buffer.data()).Unwrap();
|
||||
const u32 bytes_written =
|
||||
static_cast<u32>(message->Write(0, buffer_size, true, buffer.data()).Unwrap());
|
||||
message->Close();
|
||||
|
||||
rb.Push(RESULT_SUCCESS);
|
||||
|
@ -502,7 +520,8 @@ void Module::Interface::WriteMessageWithHMAC(Kernel::HLERequestContext& ctx) {
|
|||
hmac.CalculateDigest(hmac_digest.data(), message_body.data(), msg_header.body_size);
|
||||
std::memcpy(buffer.data() + hmac_offset, hmac_digest.data(), hmac_size);
|
||||
|
||||
const u32 bytes_written = message->Write(0, buffer_size, true, buffer.data()).Unwrap();
|
||||
const u32 bytes_written =
|
||||
static_cast<u32>(message->Write(0, buffer_size, true, buffer.data()).Unwrap());
|
||||
message->Close();
|
||||
|
||||
rb.Push(RESULT_SUCCESS);
|
||||
|
@ -744,7 +763,8 @@ void Module::Interface::OpenAndWrite(Kernel::HLERequestContext& ctx) {
|
|||
cecd->CheckAndUpdateFile(path_type, ncch_program_id, buffer);
|
||||
}
|
||||
|
||||
const u32 bytes_written = file->Write(0, buffer.size(), true, buffer.data()).Unwrap();
|
||||
const u32 bytes_written =
|
||||
static_cast<u32>(file->Write(0, buffer.size(), true, buffer.data()).Unwrap());
|
||||
file->Close();
|
||||
|
||||
rb.Push(RESULT_SUCCESS);
|
||||
|
@ -793,7 +813,8 @@ void Module::Interface::OpenAndRead(Kernel::HLERequestContext& ctx) {
|
|||
auto file = std::move(file_result).Unwrap();
|
||||
std::vector<u8> buffer(buffer_size);
|
||||
|
||||
const u32 bytes_read = file->Read(0, buffer_size, buffer.data()).Unwrap();
|
||||
const u32 bytes_read =
|
||||
static_cast<u32>(file->Read(0, buffer_size, buffer.data()).Unwrap());
|
||||
write_buffer.Write(buffer.data(), 0, buffer_size);
|
||||
file->Close();
|
||||
|
||||
|
@ -924,7 +945,7 @@ void Module::CheckAndUpdateFile(const CecDataPathType path_type, const u32 ncch_
|
|||
constexpr u32 max_num_boxes = 24;
|
||||
constexpr u32 name_size = 16; // fixed size 16 characters long
|
||||
constexpr u32 valid_name_size = 8; // 8 characters are valid, the rest are null
|
||||
const u32 file_size = file_buffer.size();
|
||||
const u32 file_size = static_cast<u32>(file_buffer.size());
|
||||
|
||||
switch (path_type) {
|
||||
case CecDataPathType::MboxList: {
|
||||
|
@ -1008,7 +1029,7 @@ void Module::CheckAndUpdateFile(const CecDataPathType path_type, const u32 ncch_
|
|||
std::u16string u16_filename;
|
||||
|
||||
// Loop through entries but don't add mboxlist____ to itself.
|
||||
for (auto i = 0; i < entry_count; i++) {
|
||||
for (u32 i = 0; i < entry_count; i++) {
|
||||
u16_filename = std::u16string(entries[i].filename);
|
||||
file_name = Common::UTF16ToUTF8(u16_filename);
|
||||
|
||||
|
@ -1199,7 +1220,7 @@ void Module::CheckAndUpdateFile(const CecDataPathType path_type, const u32 ncch_
|
|||
std::string file_name;
|
||||
std::u16string u16_filename;
|
||||
|
||||
for (auto i = 0; i < entry_count; i++) {
|
||||
for (u32 i = 0; i < entry_count; i++) {
|
||||
u16_filename = std::u16string(entries[i].filename);
|
||||
file_name = Common::UTF16ToUTF8(u16_filename);
|
||||
|
||||
|
@ -1217,7 +1238,7 @@ void Module::CheckAndUpdateFile(const CecDataPathType path_type, const u32 ncch_
|
|||
auto message_result = cecd_system_save_data_archive->OpenFile(message_path, mode);
|
||||
|
||||
auto message = std::move(message_result).Unwrap();
|
||||
const u32 message_size = message->GetSize();
|
||||
const u32 message_size = static_cast<u32>(message->GetSize());
|
||||
std::vector<u8> buffer(message_size);
|
||||
|
||||
message->Read(0, message_size, buffer.data()).Unwrap();
|
||||
|
@ -1291,7 +1312,7 @@ void Module::CheckAndUpdateFile(const CecDataPathType path_type, const u32 ncch_
|
|||
std::string file_name;
|
||||
std::u16string u16_filename;
|
||||
|
||||
for (auto i = 0; i < entry_count; i++) {
|
||||
for (u32 i = 0; i < entry_count; i++) {
|
||||
u16_filename = std::u16string(entries[i].filename);
|
||||
file_name = Common::UTF16ToUTF8(u16_filename);
|
||||
|
||||
|
@ -1307,7 +1328,7 @@ void Module::CheckAndUpdateFile(const CecDataPathType path_type, const u32 ncch_
|
|||
auto message_result = cecd_system_save_data_archive->OpenFile(message_path, mode);
|
||||
|
||||
auto message = std::move(message_result).Unwrap();
|
||||
const u32 message_size = message->GetSize();
|
||||
const u32 message_size = static_cast<u32>(message->GetSize());
|
||||
std::vector<u8> buffer(message_size);
|
||||
|
||||
message->Read(0, message_size, buffer.data()).Unwrap();
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue