From 20e5abb30807d4e0e34c79c049252f0872e47ca7 Mon Sep 17 00:00:00 2001 From: Yuri Kunde Schlesner Date: Thu, 8 Jun 2017 23:52:30 -0700 Subject: [PATCH] ServiceFramework: Use separate copy of command buffer Copy the IPC command buffer to/from the request context before/after the handler is invoked. This is part of a move away from using global data for handling IPC requests. --- src/core/hle/ipc.h | 3 +++ src/core/hle/kernel/hle_ipc.h | 9 ++++++--- src/core/hle/service/service.cpp | 26 ++++++++++++++++++++------ 3 files changed, 29 insertions(+), 9 deletions(-) diff --git a/src/core/hle/ipc.h b/src/core/hle/ipc.h index 303ca090db..f7f96125ab 100644 --- a/src/core/hle/ipc.h +++ b/src/core/hle/ipc.h @@ -44,6 +44,9 @@ inline u32* GetStaticBuffers(const int offset = 0) { namespace IPC { +/// Size of the command buffer area, in 32-bit words. +constexpr size_t COMMAND_BUFFER_LENGTH = 0x100 / sizeof(u32); + // These errors are commonly returned by invalid IPC translations, so alias them here for // convenience. // TODO(yuriks): These will probably go away once translation is implemented inside the kernel. diff --git a/src/core/hle/kernel/hle_ipc.h b/src/core/hle/kernel/hle_ipc.h index c30184eab9..aa00460011 100644 --- a/src/core/hle/kernel/hle_ipc.h +++ b/src/core/hle/kernel/hle_ipc.h @@ -4,8 +4,11 @@ #pragma once +#include #include #include +#include "common/common_types.h" +#include "core/hle/ipc.h" #include "core/hle/kernel/kernel.h" #include "core/hle/kernel/server_session.h" @@ -65,8 +68,8 @@ public: ~HLERequestContext(); /// Returns a pointer to the IPC command buffer for this request. - u32* CommandBuffer() const { - return cmd_buf; + u32* CommandBuffer() { + return cmd_buf.data(); } /** @@ -80,7 +83,7 @@ public: private: friend class Service::ServiceFrameworkBase; - u32* cmd_buf = nullptr; + std::array cmd_buf; SharedPtr session; }; diff --git a/src/core/hle/service/service.cpp b/src/core/hle/service/service.cpp index d349684282..35582b0ff5 100644 --- a/src/core/hle/service/service.cpp +++ b/src/core/hle/service/service.cpp @@ -2,9 +2,12 @@ // Licensed under GPLv2 or any later version // Refer to the license.txt file included. +#include #include +#include "common/assert.h" #include "common/logging/log.h" #include "common/string_util.h" +#include "core/hle/ipc.h" #include "core/hle/kernel/client_port.h" #include "core/hle/kernel/server_port.h" #include "core/hle/kernel/server_session.h" @@ -160,12 +163,6 @@ void ServiceFrameworkBase::ReportUnimplementedFunction(u32* cmd_buf, const Funct void ServiceFrameworkBase::HandleSyncRequest(SharedPtr server_session) { u32* cmd_buf = Kernel::GetCommandBuffer(); - // TODO(yuriks): The kernel should be the one handling this as part of translation after - // everything else is migrated - Kernel::HLERequestContext context; - context.cmd_buf = cmd_buf; - context.session = std::move(server_session); - u32 header_code = cmd_buf[0]; auto itr = handlers.find(header_code); const FunctionInfoBase* info = itr == handlers.end() ? nullptr : &itr->second; @@ -173,9 +170,26 @@ void ServiceFrameworkBase::HandleSyncRequest(SharedPtr server_ses return ReportUnimplementedFunction(cmd_buf, info); } + // TODO(yuriks): The kernel should be the one handling this as part of translation after + // everything else is migrated + IPC::Header request_header{cmd_buf[0]}; + size_t request_size = + 1 + request_header.normal_params_size + request_header.translate_params_size; + ASSERT(request_size <= IPC::COMMAND_BUFFER_LENGTH); // TODO(yuriks): Return error + + Kernel::HLERequestContext context; + std::copy_n(cmd_buf, request_size, context.cmd_buf.begin()); + context.session = std::move(server_session); + LOG_TRACE(Service, "%s", MakeFunctionString(info->name, GetServiceName().c_str(), cmd_buf).c_str()); handler_invoker(this, info->handler_callback, context); + + IPC::Header response_header{context.cmd_buf[0]}; + size_t response_size = + 1 + response_header.normal_params_size + response_header.translate_params_size; + ASSERT(response_size <= IPC::COMMAND_BUFFER_LENGTH); + std::copy_n(context.cmd_buf.begin(), response_size, cmd_buf); } ////////////////////////////////////////////////////////////////////////////////////////////////////