From 36c8e1d7a9eddfef7f06cd6e234b9d63e3286643 Mon Sep 17 00:00:00 2001 From: Weiyi Wang Date: Sat, 2 Feb 2019 15:18:01 -0500 Subject: [PATCH] HLE/IPC: move command buffer translation into kernel as TODO says --- src/core/hle/kernel/hle_ipc.h | 10 ++++---- src/core/hle/kernel/server_session.cpp | 22 ++++++++++++++++-- src/core/hle/kernel/server_session.h | 1 + src/core/hle/service/service.cpp | 32 ++++---------------------- src/core/hle/service/service.h | 2 +- 5 files changed, 31 insertions(+), 36 deletions(-) diff --git a/src/core/hle/kernel/hle_ipc.h b/src/core/hle/kernel/hle_ipc.h index 4e0c31d98..55753dce2 100644 --- a/src/core/hle/kernel/hle_ipc.h +++ b/src/core/hle/kernel/hle_ipc.h @@ -27,6 +27,7 @@ class HandleTable; class Process; class Thread; class Event; +class HLERequestContext; /** * Interface implemented by HLE Session handlers. @@ -39,13 +40,10 @@ public: /** * Handles a sync request from the emulated application. - * @param server_session The ServerSession that was triggered for this sync request, - * it should be used to differentiate which client (As in ClientSession) we're answering to. - * 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. + * @param context holds all the information relevant to his request (ServerSession, Translated + * command buffer, etc). */ - virtual void HandleSyncRequest(SharedPtr server_session) = 0; + virtual void HandleSyncRequest(Kernel::HLERequestContext& context) = 0; /** * Signals that a client has just connected to this HLE handler and keeps the diff --git a/src/core/hle/kernel/server_session.cpp b/src/core/hle/kernel/server_session.cpp index 83e2ec4fa..c07bc9840 100644 --- a/src/core/hle/kernel/server_session.cpp +++ b/src/core/hle/kernel/server_session.cpp @@ -13,7 +13,7 @@ namespace Kernel { -ServerSession::ServerSession(KernelSystem& kernel) : WaitObject(kernel) {} +ServerSession::ServerSession(KernelSystem& kernel) : WaitObject(kernel), kernel(kernel) {} ServerSession::~ServerSession() { // This destructor will be called automatically when the last ServerSession handle is closed by // the emulated application. @@ -66,7 +66,25 @@ ResultCode ServerSession::HandleSyncRequest(SharedPtr thread) { // If this ServerSession has an associated HLE handler, forward the request to it. if (hle_handler != nullptr) { - hle_handler->HandleSyncRequest(SharedPtr(this)); + // TODO(wwylele): avoid GetPointer + u32* cmd_buf = + reinterpret_cast(kernel.memory.GetPointer(thread->GetCommandBufferAddress())); + + Kernel::Process* current_process = thread->owner_process; + + Kernel::HLERequestContext context(this); + context.PopulateFromIncomingCommandBuffer(cmd_buf, *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, *current_process); + } } if (thread->status == ThreadStatus::Running) { diff --git a/src/core/hle/kernel/server_session.h b/src/core/hle/kernel/server_session.h index 956deba3f..8fe9a6552 100644 --- a/src/core/hle/kernel/server_session.h +++ b/src/core/hle/kernel/server_session.h @@ -102,6 +102,7 @@ private: std::string name = "Unknown"); friend class KernelSystem; + KernelSystem& kernel; }; } // namespace Kernel diff --git a/src/core/hle/service/service.cpp b/src/core/hle/service/service.cpp index d88ce203f..97ff14338 100644 --- a/src/core/hle/service/service.cpp +++ b/src/core/hle/service/service.cpp @@ -169,39 +169,17 @@ void ServiceFrameworkBase::ReportUnimplementedFunction(u32* cmd_buf, const Funct cmd_buf[1] = 0; } -void ServiceFrameworkBase::HandleSyncRequest( - Kernel::SharedPtr server_session) { - Kernel::KernelSystem& kernel = Core::System::GetInstance().Kernel(); - auto thread = kernel.GetThreadManager().GetCurrentThread(); - // TODO(wwylele): avoid GetPointer - u32* cmd_buf = reinterpret_cast( - Core::System::GetInstance().Memory().GetPointer(thread->GetCommandBufferAddress())); - - u32 header_code = cmd_buf[0]; +void ServiceFrameworkBase::HandleSyncRequest(Kernel::HLERequestContext& context) { + u32 header_code = context.CommandBuffer()[0]; auto itr = handlers.find(header_code); const FunctionInfoBase* info = itr == handlers.end() ? nullptr : &itr->second; if (info == nullptr || info->handler_callback == nullptr) { - return ReportUnimplementedFunction(cmd_buf, info); + return ReportUnimplementedFunction(context.CommandBuffer(), info); } - Kernel::SharedPtr current_process = kernel.GetCurrentProcess(); - - // 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)); + LOG_TRACE(Service, "{}", + MakeFunctionString(info->name, GetServiceName().c_str(), context.CommandBuffer())); 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); - } } //////////////////////////////////////////////////////////////////////////////////////////////////// diff --git a/src/core/hle/service/service.h b/src/core/hle/service/service.h index 5f36f98de..4aa1cb600 100644 --- a/src/core/hle/service/service.h +++ b/src/core/hle/service/service.h @@ -61,7 +61,7 @@ public: /// Creates a port pair and registers it on the kernel's global port registry. void InstallAsNamedPort(Kernel::KernelSystem& kernel); - void HandleSyncRequest(Kernel::SharedPtr server_session) override; + void HandleSyncRequest(Kernel::HLERequestContext& context) override; protected: /// Member-function pointer type of SyncRequest handlers.