HLE/IPC: move command buffer translation into kernel as TODO says

This commit is contained in:
Weiyi Wang 2019-02-02 15:18:01 -05:00
parent de1128c60d
commit 36c8e1d7a9
5 changed files with 31 additions and 36 deletions

View file

@ -27,6 +27,7 @@ class HandleTable;
class Process; class Process;
class Thread; class Thread;
class Event; class Event;
class HLERequestContext;
/** /**
* Interface implemented by HLE Session handlers. * Interface implemented by HLE Session handlers.
@ -39,13 +40,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

View file

@ -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,25 @@ 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)); // TODO(wwylele): avoid GetPointer
u32* cmd_buf =
reinterpret_cast<u32*>(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) { if (thread->status == ThreadStatus::Running) {

View file

@ -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

View file

@ -169,39 +169,17 @@ void ServiceFrameworkBase::ReportUnimplementedFunction(u32* cmd_buf, const Funct
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);
}
} }
//////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////

View file

@ -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.