mirror of
https://github.com/citra-mirror/citra.git
synced 2024-08-18 17:43:22 +02:00
Merge pull request #4617 from wwylele/hle-service-clean
HLE/IPC: clean up System::GetInstance
This commit is contained in:
commit
42c777b0e5
@ -48,7 +48,7 @@ SharedPtr<Event> HLERequestContext::SleepClientThread(SharedPtr<Thread> thread,
|
|||||||
// the translation might need to read from it in order to retrieve the StaticBuffer
|
// the translation might need to read from it in order to retrieve the StaticBuffer
|
||||||
// target addresses.
|
// target addresses.
|
||||||
std::array<u32_le, IPC::COMMAND_BUFFER_LENGTH + 2 * IPC::MAX_STATIC_BUFFERS> cmd_buff;
|
std::array<u32_le, IPC::COMMAND_BUFFER_LENGTH + 2 * IPC::MAX_STATIC_BUFFERS> cmd_buff;
|
||||||
Memory::MemorySystem& memory = Core::System::GetInstance().Memory();
|
Memory::MemorySystem& memory = context.kernel.memory;
|
||||||
memory.ReadBlock(*process, thread->GetCommandBufferAddress(), cmd_buff.data(),
|
memory.ReadBlock(*process, thread->GetCommandBufferAddress(), cmd_buff.data(),
|
||||||
cmd_buff.size() * sizeof(u32));
|
cmd_buff.size() * sizeof(u32));
|
||||||
context.WriteToOutgoingCommandBuffer(cmd_buff.data(), *process);
|
context.WriteToOutgoingCommandBuffer(cmd_buff.data(), *process);
|
||||||
@ -57,8 +57,7 @@ SharedPtr<Event> HLERequestContext::SleepClientThread(SharedPtr<Thread> thread,
|
|||||||
cmd_buff.size() * sizeof(u32));
|
cmd_buff.size() * sizeof(u32));
|
||||||
};
|
};
|
||||||
|
|
||||||
auto event = Core::System::GetInstance().Kernel().CreateEvent(Kernel::ResetType::OneShot,
|
auto event = kernel.CreateEvent(Kernel::ResetType::OneShot, "HLE Pause Event: " + reason);
|
||||||
"HLE Pause Event: " + reason);
|
|
||||||
thread->status = ThreadStatus::WaitHleEvent;
|
thread->status = ThreadStatus::WaitHleEvent;
|
||||||
thread->wait_objects = {event};
|
thread->wait_objects = {event};
|
||||||
event->AddWaitingThread(thread);
|
event->AddWaitingThread(thread);
|
||||||
@ -69,8 +68,8 @@ SharedPtr<Event> HLERequestContext::SleepClientThread(SharedPtr<Thread> thread,
|
|||||||
return event;
|
return event;
|
||||||
}
|
}
|
||||||
|
|
||||||
HLERequestContext::HLERequestContext(SharedPtr<ServerSession> session)
|
HLERequestContext::HLERequestContext(KernelSystem& kernel, SharedPtr<ServerSession> session)
|
||||||
: session(std::move(session)) {
|
: kernel(kernel), session(std::move(session)) {
|
||||||
cmd_buf[0] = 0;
|
cmd_buf[0] = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -143,8 +142,7 @@ ResultCode HLERequestContext::PopulateFromIncomingCommandBuffer(const u32_le* sr
|
|||||||
|
|
||||||
// Copy the input buffer into our own vector and store it.
|
// Copy the input buffer into our own vector and store it.
|
||||||
std::vector<u8> data(buffer_info.size);
|
std::vector<u8> data(buffer_info.size);
|
||||||
Core::System::GetInstance().Memory().ReadBlock(src_process, source_address, data.data(),
|
kernel.memory.ReadBlock(src_process, source_address, data.data(), data.size());
|
||||||
data.size());
|
|
||||||
|
|
||||||
AddStaticBuffer(buffer_info.buffer_id, std::move(data));
|
AddStaticBuffer(buffer_info.buffer_id, std::move(data));
|
||||||
cmd_buf[i++] = source_address;
|
cmd_buf[i++] = source_address;
|
||||||
@ -152,7 +150,8 @@ ResultCode HLERequestContext::PopulateFromIncomingCommandBuffer(const u32_le* sr
|
|||||||
}
|
}
|
||||||
case IPC::DescriptorType::MappedBuffer: {
|
case IPC::DescriptorType::MappedBuffer: {
|
||||||
u32 next_id = static_cast<u32>(request_mapped_buffers.size());
|
u32 next_id = static_cast<u32>(request_mapped_buffers.size());
|
||||||
request_mapped_buffers.emplace_back(src_process, descriptor, src_cmdbuf[i], next_id);
|
request_mapped_buffers.emplace_back(kernel.memory, src_process, descriptor,
|
||||||
|
src_cmdbuf[i], next_id);
|
||||||
cmd_buf[i++] = next_id;
|
cmd_buf[i++] = next_id;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -211,8 +210,7 @@ ResultCode HLERequestContext::WriteToOutgoingCommandBuffer(u32_le* dst_cmdbuf,
|
|||||||
|
|
||||||
ASSERT_MSG(target_descriptor.size >= data.size(), "Static buffer data is too big");
|
ASSERT_MSG(target_descriptor.size >= data.size(), "Static buffer data is too big");
|
||||||
|
|
||||||
Core::System::GetInstance().Memory().WriteBlock(dst_process, target_address,
|
kernel.memory.WriteBlock(dst_process, target_address, data.data(), data.size());
|
||||||
data.data(), data.size());
|
|
||||||
|
|
||||||
dst_cmdbuf[i++] = target_address;
|
dst_cmdbuf[i++] = target_address;
|
||||||
break;
|
break;
|
||||||
@ -235,8 +233,9 @@ MappedBuffer& HLERequestContext::GetMappedBuffer(u32 id_from_cmdbuf) {
|
|||||||
return request_mapped_buffers[id_from_cmdbuf];
|
return request_mapped_buffers[id_from_cmdbuf];
|
||||||
}
|
}
|
||||||
|
|
||||||
MappedBuffer::MappedBuffer(const Process& process, u32 descriptor, VAddr address, u32 id)
|
MappedBuffer::MappedBuffer(Memory::MemorySystem& memory, const Process& process, u32 descriptor,
|
||||||
: id(id), address(address), process(&process) {
|
VAddr address, u32 id)
|
||||||
|
: memory(&memory), id(id), address(address), process(&process) {
|
||||||
IPC::MappedBufferDescInfo desc{descriptor};
|
IPC::MappedBufferDescInfo desc{descriptor};
|
||||||
size = desc.size;
|
size = desc.size;
|
||||||
perms = desc.perms;
|
perms = desc.perms;
|
||||||
@ -245,15 +244,13 @@ MappedBuffer::MappedBuffer(const Process& process, u32 descriptor, VAddr address
|
|||||||
void MappedBuffer::Read(void* dest_buffer, std::size_t offset, std::size_t size) {
|
void MappedBuffer::Read(void* dest_buffer, std::size_t offset, std::size_t size) {
|
||||||
ASSERT(perms & IPC::R);
|
ASSERT(perms & IPC::R);
|
||||||
ASSERT(offset + size <= this->size);
|
ASSERT(offset + size <= this->size);
|
||||||
Core::System::GetInstance().Memory().ReadBlock(*process, address + static_cast<VAddr>(offset),
|
memory->ReadBlock(*process, address + static_cast<VAddr>(offset), dest_buffer, size);
|
||||||
dest_buffer, size);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void MappedBuffer::Write(const void* src_buffer, std::size_t offset, std::size_t size) {
|
void MappedBuffer::Write(const void* src_buffer, std::size_t offset, std::size_t size) {
|
||||||
ASSERT(perms & IPC::W);
|
ASSERT(perms & IPC::W);
|
||||||
ASSERT(offset + size <= this->size);
|
ASSERT(offset + size <= this->size);
|
||||||
Core::System::GetInstance().Memory().WriteBlock(*process, address + static_cast<VAddr>(offset),
|
memory->WriteBlock(*process, address + static_cast<VAddr>(offset), src_buffer, size);
|
||||||
src_buffer, size);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace Kernel
|
} // namespace Kernel
|
||||||
|
@ -21,12 +21,18 @@ namespace Service {
|
|||||||
class ServiceFrameworkBase;
|
class ServiceFrameworkBase;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
namespace Memory {
|
||||||
|
class MemorySystem;
|
||||||
|
}
|
||||||
|
|
||||||
namespace Kernel {
|
namespace Kernel {
|
||||||
|
|
||||||
class HandleTable;
|
class HandleTable;
|
||||||
class Process;
|
class Process;
|
||||||
class Thread;
|
class Thread;
|
||||||
class Event;
|
class Event;
|
||||||
|
class HLERequestContext;
|
||||||
|
class KernelSystem;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Interface implemented by HLE Session handlers.
|
* Interface implemented by HLE Session handlers.
|
||||||
@ -39,13 +45,10 @@ public:
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Handles a sync request from the emulated application.
|
* Handles a sync request from the emulated application.
|
||||||
* @param server_session The ServerSession that was triggered for this sync request,
|
* @param context holds all the information relevant to his request (ServerSession, Translated
|
||||||
* it should be used to differentiate which client (As in ClientSession) we're answering to.
|
* command buffer, etc).
|
||||||
* TODO(Subv): Use a wrapper structure to hold all the information relevant to
|
|
||||||
* this request (ServerSession, Originator thread, Translated command buffer, etc).
|
|
||||||
* @returns ResultCode the result code of the translate operation.
|
|
||||||
*/
|
*/
|
||||||
virtual void HandleSyncRequest(SharedPtr<ServerSession> server_session) = 0;
|
virtual void HandleSyncRequest(Kernel::HLERequestContext& context) = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Signals that a client has just connected to this HLE handler and keeps the
|
* Signals that a client has just connected to this HLE handler and keeps the
|
||||||
@ -95,7 +98,8 @@ protected:
|
|||||||
|
|
||||||
class MappedBuffer {
|
class MappedBuffer {
|
||||||
public:
|
public:
|
||||||
MappedBuffer(const Process& process, u32 descriptor, VAddr address, u32 id);
|
MappedBuffer(Memory::MemorySystem& memory, const Process& process, u32 descriptor,
|
||||||
|
VAddr address, u32 id);
|
||||||
|
|
||||||
// interface for service
|
// interface for service
|
||||||
void Read(void* dest_buffer, std::size_t offset, std::size_t size);
|
void Read(void* dest_buffer, std::size_t offset, std::size_t size);
|
||||||
@ -115,6 +119,7 @@ public:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
friend class HLERequestContext;
|
friend class HLERequestContext;
|
||||||
|
Memory::MemorySystem* memory;
|
||||||
u32 id;
|
u32 id;
|
||||||
VAddr address;
|
VAddr address;
|
||||||
const Process* process;
|
const Process* process;
|
||||||
@ -153,7 +158,7 @@ private:
|
|||||||
*/
|
*/
|
||||||
class HLERequestContext {
|
class HLERequestContext {
|
||||||
public:
|
public:
|
||||||
HLERequestContext(SharedPtr<ServerSession> session);
|
HLERequestContext(KernelSystem& kernel, SharedPtr<ServerSession> session);
|
||||||
~HLERequestContext();
|
~HLERequestContext();
|
||||||
|
|
||||||
/// Returns a pointer to the IPC command buffer for this request.
|
/// Returns a pointer to the IPC command buffer for this request.
|
||||||
@ -230,6 +235,7 @@ public:
|
|||||||
ResultCode WriteToOutgoingCommandBuffer(u32_le* dst_cmdbuf, Process& dst_process) const;
|
ResultCode WriteToOutgoingCommandBuffer(u32_le* dst_cmdbuf, Process& dst_process) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
KernelSystem& kernel;
|
||||||
std::array<u32, IPC::COMMAND_BUFFER_LENGTH> cmd_buf;
|
std::array<u32, IPC::COMMAND_BUFFER_LENGTH> cmd_buf;
|
||||||
SharedPtr<ServerSession> session;
|
SharedPtr<ServerSession> session;
|
||||||
// TODO(yuriks): Check common usage of this and optimize size accordingly
|
// TODO(yuriks): Check common usage of this and optimize size accordingly
|
||||||
|
@ -13,7 +13,7 @@
|
|||||||
|
|
||||||
namespace Kernel {
|
namespace Kernel {
|
||||||
|
|
||||||
ServerSession::ServerSession(KernelSystem& kernel) : WaitObject(kernel) {}
|
ServerSession::ServerSession(KernelSystem& kernel) : WaitObject(kernel), kernel(kernel) {}
|
||||||
ServerSession::~ServerSession() {
|
ServerSession::~ServerSession() {
|
||||||
// This destructor will be called automatically when the last ServerSession handle is closed by
|
// This destructor will be called automatically when the last ServerSession handle is closed by
|
||||||
// the emulated application.
|
// the emulated application.
|
||||||
@ -66,7 +66,26 @@ ResultCode ServerSession::HandleSyncRequest(SharedPtr<Thread> thread) {
|
|||||||
|
|
||||||
// If this ServerSession has an associated HLE handler, forward the request to it.
|
// If this ServerSession has an associated HLE handler, forward the request to it.
|
||||||
if (hle_handler != nullptr) {
|
if (hle_handler != nullptr) {
|
||||||
hle_handler->HandleSyncRequest(SharedPtr<ServerSession>(this));
|
std::array<u32_le, IPC::COMMAND_BUFFER_LENGTH + 2 * IPC::MAX_STATIC_BUFFERS> cmd_buf;
|
||||||
|
Kernel::Process* current_process = thread->owner_process;
|
||||||
|
kernel.memory.ReadBlock(*current_process, thread->GetCommandBufferAddress(), cmd_buf.data(),
|
||||||
|
cmd_buf.size() * sizeof(u32));
|
||||||
|
|
||||||
|
Kernel::HLERequestContext context(kernel, this);
|
||||||
|
context.PopulateFromIncomingCommandBuffer(cmd_buf.data(), *current_process);
|
||||||
|
|
||||||
|
hle_handler->HandleSyncRequest(context);
|
||||||
|
|
||||||
|
ASSERT(thread->status == Kernel::ThreadStatus::Running ||
|
||||||
|
thread->status == Kernel::ThreadStatus::WaitHleEvent);
|
||||||
|
// Only write the response immediately if the thread is still running. If the HLE handler
|
||||||
|
// 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);
|
||||||
|
kernel.memory.WriteBlock(*current_process, thread->GetCommandBufferAddress(),
|
||||||
|
cmd_buf.data(), cmd_buf.size() * sizeof(u32));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (thread->status == ThreadStatus::Running) {
|
if (thread->status == ThreadStatus::Running) {
|
||||||
|
@ -102,6 +102,7 @@ private:
|
|||||||
std::string name = "Unknown");
|
std::string name = "Unknown");
|
||||||
|
|
||||||
friend class KernelSystem;
|
friend class KernelSystem;
|
||||||
|
KernelSystem& kernel;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace Kernel
|
} // namespace Kernel
|
||||||
|
@ -166,42 +166,23 @@ void ServiceFrameworkBase::ReportUnimplementedFunction(u32* cmd_buf, const Funct
|
|||||||
|
|
||||||
LOG_ERROR(Service, "unknown / unimplemented {}", fmt::to_string(buf));
|
LOG_ERROR(Service, "unknown / unimplemented {}", fmt::to_string(buf));
|
||||||
// TODO(bunnei): Hack - ignore error
|
// TODO(bunnei): Hack - ignore error
|
||||||
|
header.normal_params_size.Assign(1);
|
||||||
|
header.translate_params_size.Assign(0);
|
||||||
|
cmd_buf[0] = header.raw;
|
||||||
cmd_buf[1] = 0;
|
cmd_buf[1] = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ServiceFrameworkBase::HandleSyncRequest(
|
void ServiceFrameworkBase::HandleSyncRequest(Kernel::HLERequestContext& context) {
|
||||||
Kernel::SharedPtr<Kernel::ServerSession> server_session) {
|
u32 header_code = context.CommandBuffer()[0];
|
||||||
Kernel::KernelSystem& kernel = Core::System::GetInstance().Kernel();
|
|
||||||
auto thread = kernel.GetThreadManager().GetCurrentThread();
|
|
||||||
// TODO(wwylele): avoid GetPointer
|
|
||||||
u32* cmd_buf = reinterpret_cast<u32*>(
|
|
||||||
Core::System::GetInstance().Memory().GetPointer(thread->GetCommandBufferAddress()));
|
|
||||||
|
|
||||||
u32 header_code = cmd_buf[0];
|
|
||||||
auto itr = handlers.find(header_code);
|
auto itr = handlers.find(header_code);
|
||||||
const FunctionInfoBase* info = itr == handlers.end() ? nullptr : &itr->second;
|
const FunctionInfoBase* info = itr == handlers.end() ? nullptr : &itr->second;
|
||||||
if (info == nullptr || info->handler_callback == nullptr) {
|
if (info == nullptr || info->handler_callback == nullptr) {
|
||||||
return ReportUnimplementedFunction(cmd_buf, info);
|
return ReportUnimplementedFunction(context.CommandBuffer(), info);
|
||||||
}
|
}
|
||||||
|
|
||||||
Kernel::SharedPtr<Kernel::Process> current_process = kernel.GetCurrentProcess();
|
LOG_TRACE(Service, "{}",
|
||||||
|
MakeFunctionString(info->name, GetServiceName().c_str(), context.CommandBuffer()));
|
||||||
// TODO(yuriks): The kernel should be the one handling this as part of translation after
|
|
||||||
// everything else is migrated
|
|
||||||
Kernel::HLERequestContext context(std::move(server_session));
|
|
||||||
context.PopulateFromIncomingCommandBuffer(cmd_buf, *current_process);
|
|
||||||
|
|
||||||
LOG_TRACE(Service, "{}", MakeFunctionString(info->name, GetServiceName().c_str(), cmd_buf));
|
|
||||||
handler_invoker(this, info->handler_callback, context);
|
handler_invoker(this, info->handler_callback, context);
|
||||||
|
|
||||||
ASSERT(thread->status == Kernel::ThreadStatus::Running ||
|
|
||||||
thread->status == Kernel::ThreadStatus::WaitHleEvent);
|
|
||||||
// Only write the response immediately if the thread is still running. If the HLE handler 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, *current_process);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
@ -61,7 +61,7 @@ public:
|
|||||||
/// Creates a port pair and registers it on the kernel's global port registry.
|
/// Creates a port pair and registers it on the kernel's global port registry.
|
||||||
void InstallAsNamedPort(Kernel::KernelSystem& kernel);
|
void InstallAsNamedPort(Kernel::KernelSystem& kernel);
|
||||||
|
|
||||||
void HandleSyncRequest(Kernel::SharedPtr<Kernel::ServerSession> server_session) override;
|
void HandleSyncRequest(Kernel::HLERequestContext& context) override;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
/// Member-function pointer type of SyncRequest handlers.
|
/// Member-function pointer type of SyncRequest handlers.
|
||||||
|
@ -25,7 +25,7 @@ TEST_CASE("HLERequestContext::PopulateFromIncomingCommandBuffer", "[core][kernel
|
|||||||
Memory::MemorySystem memory;
|
Memory::MemorySystem memory;
|
||||||
Kernel::KernelSystem kernel(memory, timing, [] {}, 0);
|
Kernel::KernelSystem kernel(memory, timing, [] {}, 0);
|
||||||
auto session = std::get<SharedPtr<ServerSession>>(kernel.CreateSessionPair());
|
auto session = std::get<SharedPtr<ServerSession>>(kernel.CreateSessionPair());
|
||||||
HLERequestContext context(std::move(session));
|
HLERequestContext context(kernel, std::move(session));
|
||||||
|
|
||||||
auto process = kernel.CreateProcess(kernel.CreateCodeSet("", 0));
|
auto process = kernel.CreateProcess(kernel.CreateCodeSet("", 0));
|
||||||
|
|
||||||
@ -237,7 +237,7 @@ TEST_CASE("HLERequestContext::WriteToOutgoingCommandBuffer", "[core][kernel]") {
|
|||||||
Memory::MemorySystem memory;
|
Memory::MemorySystem memory;
|
||||||
Kernel::KernelSystem kernel(memory, timing, [] {}, 0);
|
Kernel::KernelSystem kernel(memory, timing, [] {}, 0);
|
||||||
auto session = std::get<SharedPtr<ServerSession>>(kernel.CreateSessionPair());
|
auto session = std::get<SharedPtr<ServerSession>>(kernel.CreateSessionPair());
|
||||||
HLERequestContext context(std::move(session));
|
HLERequestContext context(kernel, std::move(session));
|
||||||
|
|
||||||
auto process = kernel.CreateProcess(kernel.CreateCodeSet("", 0));
|
auto process = kernel.CreateProcess(kernel.CreateCodeSet("", 0));
|
||||||
auto* input = context.CommandBuffer();
|
auto* input = context.CommandBuffer();
|
||||||
|
Loading…
Reference in New Issue
Block a user