HLE/IPC: move command buffer translation into kernel as TODO says
This commit is contained in:
parent
de1128c60d
commit
36c8e1d7a9
|
@ -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
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
|
@ -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.
|
||||||
|
|
Reference in New Issue