kernel: Add LLE request/reply recording
The 'translate' function is a great place to put this in IMO as it is possible to get both untranslated and translated cmdbufs. However a kernel reference has to be passed here, but it is not too hard fortunately.
This commit is contained in:
parent
cb0bd6530c
commit
a27dfc269a
3 changed files with 38 additions and 14 deletions
|
@ -8,6 +8,7 @@
|
||||||
#include "core/hle/ipc.h"
|
#include "core/hle/ipc.h"
|
||||||
#include "core/hle/kernel/handle_table.h"
|
#include "core/hle/kernel/handle_table.h"
|
||||||
#include "core/hle/kernel/ipc.h"
|
#include "core/hle/kernel/ipc.h"
|
||||||
|
#include "core/hle/kernel/ipc_debugger/recorder.h"
|
||||||
#include "core/hle/kernel/kernel.h"
|
#include "core/hle/kernel/kernel.h"
|
||||||
#include "core/hle/kernel/memory.h"
|
#include "core/hle/kernel/memory.h"
|
||||||
#include "core/hle/kernel/process.h"
|
#include "core/hle/kernel/process.h"
|
||||||
|
@ -16,7 +17,8 @@
|
||||||
|
|
||||||
namespace Kernel {
|
namespace Kernel {
|
||||||
|
|
||||||
ResultCode TranslateCommandBuffer(Memory::MemorySystem& memory, std::shared_ptr<Thread> src_thread,
|
ResultCode TranslateCommandBuffer(Kernel::KernelSystem& kernel, Memory::MemorySystem& memory,
|
||||||
|
std::shared_ptr<Thread> src_thread,
|
||||||
std::shared_ptr<Thread> dst_thread, VAddr src_address,
|
std::shared_ptr<Thread> dst_thread, VAddr src_address,
|
||||||
VAddr dst_address,
|
VAddr dst_address,
|
||||||
std::vector<MappedBufferContext>& mapped_buffer_context,
|
std::vector<MappedBufferContext>& mapped_buffer_context,
|
||||||
|
@ -37,6 +39,13 @@ ResultCode TranslateCommandBuffer(Memory::MemorySystem& memory, std::shared_ptr<
|
||||||
std::array<u32, IPC::COMMAND_BUFFER_LENGTH> cmd_buf;
|
std::array<u32, IPC::COMMAND_BUFFER_LENGTH> cmd_buf;
|
||||||
memory.ReadBlock(*src_process, src_address, cmd_buf.data(), command_size * sizeof(u32));
|
memory.ReadBlock(*src_process, src_address, cmd_buf.data(), command_size * sizeof(u32));
|
||||||
|
|
||||||
|
const bool should_record = kernel.GetIPCRecorder().IsEnabled();
|
||||||
|
|
||||||
|
std::vector<u32> untranslated_cmdbuf;
|
||||||
|
if (should_record) {
|
||||||
|
untranslated_cmdbuf = std::vector<u32>{cmd_buf.begin(), cmd_buf.begin() + command_size};
|
||||||
|
}
|
||||||
|
|
||||||
std::size_t i = untranslated_size;
|
std::size_t i = untranslated_size;
|
||||||
while (i < command_size) {
|
while (i < command_size) {
|
||||||
u32 descriptor = cmd_buf[i];
|
u32 descriptor = cmd_buf[i];
|
||||||
|
@ -218,6 +227,17 @@ ResultCode TranslateCommandBuffer(Memory::MemorySystem& memory, std::shared_ptr<
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (should_record) {
|
||||||
|
std::vector<u32> translated_cmdbuf{cmd_buf.begin(), cmd_buf.begin() + command_size};
|
||||||
|
if (reply) {
|
||||||
|
kernel.GetIPCRecorder().SetReplyInfo(dst_thread, std::move(untranslated_cmdbuf),
|
||||||
|
std::move(translated_cmdbuf));
|
||||||
|
} else {
|
||||||
|
kernel.GetIPCRecorder().SetRequestInfo(src_thread, std::move(untranslated_cmdbuf),
|
||||||
|
std::move(translated_cmdbuf), dst_thread);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
memory.WriteBlock(*dst_process, dst_address, cmd_buf.data(), command_size * sizeof(u32));
|
memory.WriteBlock(*dst_process, dst_address, cmd_buf.data(), command_size * sizeof(u32));
|
||||||
|
|
||||||
return RESULT_SUCCESS;
|
return RESULT_SUCCESS;
|
||||||
|
|
|
@ -16,6 +16,8 @@ class MemorySystem;
|
||||||
|
|
||||||
namespace Kernel {
|
namespace Kernel {
|
||||||
|
|
||||||
|
class KernelSystem;
|
||||||
|
|
||||||
struct MappedBufferContext {
|
struct MappedBufferContext {
|
||||||
IPC::MappedBufferPermissions permissions;
|
IPC::MappedBufferPermissions permissions;
|
||||||
u32 size;
|
u32 size;
|
||||||
|
@ -27,7 +29,8 @@ struct MappedBufferContext {
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Performs IPC command buffer translation from one process to another.
|
/// Performs IPC command buffer translation from one process to another.
|
||||||
ResultCode TranslateCommandBuffer(Memory::MemorySystem& memory, std::shared_ptr<Thread> src_thread,
|
ResultCode TranslateCommandBuffer(KernelSystem& system, Memory::MemorySystem& memory,
|
||||||
|
std::shared_ptr<Thread> src_thread,
|
||||||
std::shared_ptr<Thread> dst_thread, VAddr src_address,
|
std::shared_ptr<Thread> dst_thread, VAddr src_address,
|
||||||
VAddr dst_address,
|
VAddr dst_address,
|
||||||
std::vector<MappedBufferContext>& mapped_buffer_context,
|
std::vector<MappedBufferContext>& mapped_buffer_context,
|
||||||
|
|
|
@ -19,6 +19,7 @@
|
||||||
#include "core/hle/kernel/event.h"
|
#include "core/hle/kernel/event.h"
|
||||||
#include "core/hle/kernel/handle_table.h"
|
#include "core/hle/kernel/handle_table.h"
|
||||||
#include "core/hle/kernel/ipc.h"
|
#include "core/hle/kernel/ipc.h"
|
||||||
|
#include "core/hle/kernel/ipc_debugger/recorder.h"
|
||||||
#include "core/hle/kernel/memory.h"
|
#include "core/hle/kernel/memory.h"
|
||||||
#include "core/hle/kernel/mutex.h"
|
#include "core/hle/kernel/mutex.h"
|
||||||
#include "core/hle/kernel/process.h"
|
#include "core/hle/kernel/process.h"
|
||||||
|
@ -599,7 +600,7 @@ ResultCode SVC::WaitSynchronizationN(s32* out, VAddr handles_address, s32 handle
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static ResultCode ReceiveIPCRequest(Memory::MemorySystem& memory,
|
static ResultCode ReceiveIPCRequest(Kernel::KernelSystem& kernel, Memory::MemorySystem& memory,
|
||||||
std::shared_ptr<ServerSession> server_session,
|
std::shared_ptr<ServerSession> server_session,
|
||||||
std::shared_ptr<Thread> thread) {
|
std::shared_ptr<Thread> thread) {
|
||||||
if (server_session->parent->client == nullptr) {
|
if (server_session->parent->client == nullptr) {
|
||||||
|
@ -609,9 +610,9 @@ static ResultCode ReceiveIPCRequest(Memory::MemorySystem& memory,
|
||||||
VAddr target_address = thread->GetCommandBufferAddress();
|
VAddr target_address = thread->GetCommandBufferAddress();
|
||||||
VAddr source_address = server_session->currently_handling->GetCommandBufferAddress();
|
VAddr source_address = server_session->currently_handling->GetCommandBufferAddress();
|
||||||
|
|
||||||
ResultCode translation_result =
|
ResultCode translation_result = TranslateCommandBuffer(
|
||||||
TranslateCommandBuffer(memory, server_session->currently_handling, thread, source_address,
|
kernel, memory, server_session->currently_handling, thread, source_address, target_address,
|
||||||
target_address, server_session->mapped_buffer_context, false);
|
server_session->mapped_buffer_context, false);
|
||||||
|
|
||||||
// If a translation error occurred, immediately resume the client thread.
|
// If a translation error occurred, immediately resume the client thread.
|
||||||
if (translation_result.IsError()) {
|
if (translation_result.IsError()) {
|
||||||
|
@ -676,9 +677,9 @@ ResultCode SVC::ReplyAndReceive(s32* index, VAddr handles_address, s32 handle_co
|
||||||
VAddr source_address = thread->GetCommandBufferAddress();
|
VAddr source_address = thread->GetCommandBufferAddress();
|
||||||
VAddr target_address = request_thread->GetCommandBufferAddress();
|
VAddr target_address = request_thread->GetCommandBufferAddress();
|
||||||
|
|
||||||
ResultCode translation_result =
|
ResultCode translation_result = TranslateCommandBuffer(
|
||||||
TranslateCommandBuffer(memory, SharedFrom(thread), request_thread, source_address,
|
kernel, memory, SharedFrom(thread), request_thread, source_address, target_address,
|
||||||
target_address, session->mapped_buffer_context, true);
|
session->mapped_buffer_context, true);
|
||||||
|
|
||||||
// Note: The real kernel seems to always panic if the Server->Client buffer translation
|
// Note: The real kernel seems to always panic if the Server->Client buffer translation
|
||||||
// fails for whatever reason.
|
// fails for whatever reason.
|
||||||
|
@ -713,7 +714,7 @@ ResultCode SVC::ReplyAndReceive(s32* index, VAddr handles_address, s32 handle_co
|
||||||
return RESULT_SUCCESS;
|
return RESULT_SUCCESS;
|
||||||
|
|
||||||
auto server_session = static_cast<ServerSession*>(object);
|
auto server_session = static_cast<ServerSession*>(object);
|
||||||
return ReceiveIPCRequest(memory, SharedFrom(server_session), SharedFrom(thread));
|
return ReceiveIPCRequest(kernel, memory, SharedFrom(server_session), SharedFrom(thread));
|
||||||
}
|
}
|
||||||
|
|
||||||
// No objects were ready to be acquired, prepare to suspend the thread.
|
// No objects were ready to be acquired, prepare to suspend the thread.
|
||||||
|
@ -729,8 +730,8 @@ ResultCode SVC::ReplyAndReceive(s32* index, VAddr handles_address, s32 handle_co
|
||||||
|
|
||||||
thread->wait_objects = std::move(objects);
|
thread->wait_objects = std::move(objects);
|
||||||
|
|
||||||
thread->wakeup_callback = [& memory = this->memory](ThreadWakeupReason reason,
|
thread->wakeup_callback = [& kernel = this->kernel, &memory = this->memory](
|
||||||
std::shared_ptr<Thread> thread,
|
ThreadWakeupReason reason, std::shared_ptr<Thread> thread,
|
||||||
std::shared_ptr<WaitObject> object) {
|
std::shared_ptr<WaitObject> object) {
|
||||||
ASSERT(thread->status == ThreadStatus::WaitSynchAny);
|
ASSERT(thread->status == ThreadStatus::WaitSynchAny);
|
||||||
ASSERT(reason == ThreadWakeupReason::Signal);
|
ASSERT(reason == ThreadWakeupReason::Signal);
|
||||||
|
@ -739,7 +740,7 @@ ResultCode SVC::ReplyAndReceive(s32* index, VAddr handles_address, s32 handle_co
|
||||||
|
|
||||||
if (object->GetHandleType() == HandleType::ServerSession) {
|
if (object->GetHandleType() == HandleType::ServerSession) {
|
||||||
auto server_session = DynamicObjectCast<ServerSession>(object);
|
auto server_session = DynamicObjectCast<ServerSession>(object);
|
||||||
result = ReceiveIPCRequest(memory, server_session, thread);
|
result = ReceiveIPCRequest(kernel, memory, server_session, thread);
|
||||||
}
|
}
|
||||||
|
|
||||||
thread->SetWaitSynchronizationResult(result);
|
thread->SetWaitSynchronizationResult(result);
|
||||||
|
|
Loading…
Reference in a new issue