[Kernel] Experimental debug monitor/PIX code.
This commit is contained in:
parent
09585eb103
commit
2ef3ea996f
|
@ -0,0 +1,42 @@
|
|||
/**
|
||||
******************************************************************************
|
||||
* Xenia : Xbox 360 Emulator Research Project *
|
||||
******************************************************************************
|
||||
* Copyright 2013 Ben Vanik. All rights reserved. *
|
||||
* Released under the BSD license - see LICENSE in the root for more details. *
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
#include "xenia/kernel/xboxkrnl/xboxkrnl_module.h"
|
||||
|
||||
#include <gflags/gflags.h>
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include "xenia/base/clock.h"
|
||||
#include "xenia/base/debugging.h"
|
||||
#include "xenia/base/logging.h"
|
||||
#include "xenia/base/math.h"
|
||||
#include "xenia/cpu/ppc/ppc_context.h"
|
||||
#include "xenia/cpu/processor.h"
|
||||
#include "xenia/emulator.h"
|
||||
#include "xenia/kernel/kernel_state.h"
|
||||
#include "xenia/kernel/user_module.h"
|
||||
#include "xenia/kernel/xboxkrnl/xboxkrnl_private.h"
|
||||
#include "xenia/kernel/xthread.h"
|
||||
|
||||
namespace xe {
|
||||
namespace kernel {
|
||||
namespace xboxkrnl {
|
||||
|
||||
void KeCertMonitorCallback(cpu::ppc::PPCContext* ppc_context,
|
||||
kernel::KernelState* kernel_state) {
|
||||
auto id = ppc_context->r[3];
|
||||
auto arg = ppc_context->r[4];
|
||||
XELOGI("KeCertMonitorCallback(%u, %08x)", id, arg);
|
||||
auto xboxkrnl = kernel_state->GetKernelModule<XboxkrnlModule>("xboxkrnl.exe");
|
||||
}
|
||||
|
||||
} // namespace xboxkrnl
|
||||
} // namespace kernel
|
||||
} // namespace xe
|
|
@ -0,0 +1,35 @@
|
|||
/**
|
||||
******************************************************************************
|
||||
* Xenia : Xbox 360 Emulator Research Project *
|
||||
******************************************************************************
|
||||
* Copyright 2013 Ben Vanik. All rights reserved. *
|
||||
* Released under the BSD license - see LICENSE in the root for more details. *
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
#ifndef XENIA_KERNEL_KERNEL_XBOXKRNL_CERT_MONITOR_H_
|
||||
#define XENIA_KERNEL_KERNEL_XBOXKRNL_CERT_MONITOR_H_
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include "xenia/base/threading.h"
|
||||
#include "xenia/cpu/export_resolver.h"
|
||||
#include "xenia/kernel/kernel_module.h"
|
||||
#include "xenia/kernel/kernel_state.h"
|
||||
|
||||
namespace xe {
|
||||
namespace kernel {
|
||||
namespace xboxkrnl {
|
||||
|
||||
struct X_KECERTMONITORDATA {
|
||||
xe::be<uint32_t> callback_fn;
|
||||
};
|
||||
|
||||
void KeCertMonitorCallback(cpu::ppc::PPCContext* ppc_context,
|
||||
kernel::KernelState* kernel_state);
|
||||
|
||||
} // namespace xboxkrnl
|
||||
} // namespace kernel
|
||||
} // namespace xe
|
||||
|
||||
#endif // XENIA_KERNEL_KERNEL_XBOXKRNL_CERT_MONITOR_H_
|
|
@ -0,0 +1,99 @@
|
|||
/**
|
||||
******************************************************************************
|
||||
* Xenia : Xbox 360 Emulator Research Project *
|
||||
******************************************************************************
|
||||
* Copyright 2013 Ben Vanik. All rights reserved. *
|
||||
* Released under the BSD license - see LICENSE in the root for more details. *
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
#include "xenia/kernel/xboxkrnl/xboxkrnl_module.h"
|
||||
|
||||
#include <gflags/gflags.h>
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include "xenia/base/clock.h"
|
||||
#include "xenia/base/debugging.h"
|
||||
#include "xenia/base/logging.h"
|
||||
#include "xenia/base/math.h"
|
||||
#include "xenia/cpu/ppc/ppc_context.h"
|
||||
#include "xenia/cpu/processor.h"
|
||||
#include "xenia/emulator.h"
|
||||
#include "xenia/kernel/kernel_state.h"
|
||||
#include "xenia/kernel/user_module.h"
|
||||
#include "xenia/kernel/util/shim_utils.h"
|
||||
#include "xenia/kernel/xboxkrnl/xboxkrnl_private.h"
|
||||
#include "xenia/kernel/xthread.h"
|
||||
|
||||
DECLARE_bool(kernel_pix);
|
||||
|
||||
namespace xe {
|
||||
namespace kernel {
|
||||
namespace xboxkrnl {
|
||||
|
||||
enum class DebugMonitorCommand {
|
||||
PIXCommandResult = 27,
|
||||
SetPIXCallback = 28,
|
||||
Unknown66 = 66,
|
||||
Unknown89 = 89,
|
||||
Unknown94 = 94,
|
||||
};
|
||||
|
||||
void KeDebugMonitorCallback(cpu::ppc::PPCContext* ppc_context,
|
||||
kernel::KernelState* kernel_state) {
|
||||
auto id = static_cast<DebugMonitorCommand>(ppc_context->r[3] & 0xFFFFFFFFu);
|
||||
auto arg = static_cast<uint32_t>(ppc_context->r[4] & 0xFFFFFFFFu);
|
||||
|
||||
XELOGI("KeDebugMonitorCallback(%u, %08x)", static_cast<uint32_t>(id), arg);
|
||||
|
||||
if (!FLAGS_kernel_pix) {
|
||||
SHIM_SET_RETURN_32(-1);
|
||||
return;
|
||||
}
|
||||
|
||||
auto xboxkrnl = kernel_state->GetKernelModule<XboxkrnlModule>("xboxkrnl.exe");
|
||||
|
||||
switch (id) {
|
||||
case DebugMonitorCommand::PIXCommandResult: {
|
||||
auto s = kernel_state->memory()->TranslateVirtual<const char*>(arg);
|
||||
debugging::DebugPrint("%s\n", s);
|
||||
XELOGD("PIX command result: %s\n", s);
|
||||
if (strcmp(s, "PIX!{CaptureFileCreationEnded} 0x00000000") == 0) {
|
||||
xboxkrnl->SendPIXCommand("{BeginCapture}");
|
||||
}
|
||||
SHIM_SET_RETURN_32(0);
|
||||
break;
|
||||
}
|
||||
case DebugMonitorCommand::SetPIXCallback:
|
||||
xboxkrnl->set_pix_function(arg);
|
||||
xboxkrnl->SendPIXCommand("{LimitCaptureSize} 100"); // in MB
|
||||
xboxkrnl->SendPIXCommand("{BeginCaptureFileCreation} scratch:\\test.cap");
|
||||
SHIM_SET_RETURN_32(0);
|
||||
break;
|
||||
case DebugMonitorCommand::Unknown66: {
|
||||
struct callback_info {
|
||||
xe::be<uint32_t> callback_fn;
|
||||
xe::be<uint32_t> callback_arg; // D3D device object?
|
||||
};
|
||||
auto cbi = kernel_state->memory()->TranslateVirtual<callback_info*>(arg);
|
||||
SHIM_SET_RETURN_32(0);
|
||||
break;
|
||||
}
|
||||
case DebugMonitorCommand::Unknown89:
|
||||
// arg = function pointer?
|
||||
SHIM_SET_RETURN_32(0);
|
||||
break;
|
||||
case DebugMonitorCommand::Unknown94:
|
||||
// xboxkrnl->SendPIXCommand("{EndCapture}");
|
||||
SHIM_SET_RETURN_32(0);
|
||||
break;
|
||||
default:
|
||||
SHIM_SET_RETURN_32(-1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace xboxkrnl
|
||||
} // namespace kernel
|
||||
} // namespace xe
|
|
@ -0,0 +1,43 @@
|
|||
/**
|
||||
******************************************************************************
|
||||
* Xenia : Xbox 360 Emulator Research Project *
|
||||
******************************************************************************
|
||||
* Copyright 2013 Ben Vanik. All rights reserved. *
|
||||
* Released under the BSD license - see LICENSE in the root for more details. *
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
#ifndef XENIA_KERNEL_KERNEL_XBOXKRNL_DEBUG_MONITOR_H_
|
||||
#define XENIA_KERNEL_KERNEL_XBOXKRNL_DEBUG_MONITOR_H_
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include "xenia/base/threading.h"
|
||||
#include "xenia/cpu/export_resolver.h"
|
||||
#include "xenia/kernel/kernel_module.h"
|
||||
#include "xenia/kernel/kernel_state.h"
|
||||
|
||||
namespace xe {
|
||||
namespace kernel {
|
||||
namespace xboxkrnl {
|
||||
|
||||
struct X_KEDEBUGMONITORDATA {
|
||||
xe::be<uint32_t> unk_00; // 0x00
|
||||
xe::be<uint32_t> unk_04; // 0x04
|
||||
xe::be<uint32_t> unk_08; // 0x08
|
||||
xe::be<uint32_t> unk_0C; // 0x0C
|
||||
xe::be<uint32_t> unk_10; // 0x10
|
||||
xe::be<uint32_t> unk_14; // 0x14
|
||||
xe::be<uint32_t> callback_fn; // 0x18 function
|
||||
xe::be<uint32_t> unk_1C; // 0x1C
|
||||
xe::be<uint32_t> unk_20; // 0x20 Vd graphics data?
|
||||
};
|
||||
|
||||
void KeDebugMonitorCallback(cpu::ppc::PPCContext* ppc_context,
|
||||
kernel::KernelState* kernel_state);
|
||||
|
||||
} // namespace xboxkrnl
|
||||
} // namespace kernel
|
||||
} // namespace xe
|
||||
|
||||
#endif // XENIA_KERNEL_KERNEL_DEBUG_MONITOR_H_
|
|
@ -14,17 +14,64 @@
|
|||
#include <vector>
|
||||
|
||||
#include "xenia/base/clock.h"
|
||||
#include "xenia/base/debugging.h"
|
||||
#include "xenia/base/logging.h"
|
||||
#include "xenia/base/math.h"
|
||||
#include "xenia/cpu/ppc/ppc_context.h"
|
||||
#include "xenia/cpu/processor.h"
|
||||
#include "xenia/emulator.h"
|
||||
#include "xenia/kernel/kernel_state.h"
|
||||
#include "xenia/kernel/user_module.h"
|
||||
#include "xenia/kernel/xboxkrnl/cert_monitor.h"
|
||||
#include "xenia/kernel/xboxkrnl/debug_monitor.h"
|
||||
#include "xenia/kernel/xboxkrnl/xboxkrnl_private.h"
|
||||
#include "xenia/kernel/xthread.h"
|
||||
|
||||
DEFINE_bool(kernel_debug_monitor, false, "Enable debug monitor.");
|
||||
DEFINE_bool(kernel_cert_monitor, false, "Enable cert monitor.");
|
||||
DEFINE_bool(kernel_pix, false, "Enable PIX.");
|
||||
|
||||
namespace xe {
|
||||
namespace kernel {
|
||||
namespace xboxkrnl {
|
||||
|
||||
bool XboxkrnlModule::SendPIXCommand(const char* cmd) {
|
||||
if (!FLAGS_kernel_pix) {
|
||||
return false;
|
||||
}
|
||||
|
||||
auto global_lock = global_critical_region_.Acquire();
|
||||
if (!XThread::IsInThread()) {
|
||||
assert_always();
|
||||
return false;
|
||||
}
|
||||
|
||||
auto scratch = memory_->SystemHeapAlloc(260 + 260);
|
||||
|
||||
auto response = memory_->TranslateVirtual<const char*>(scratch + 0);
|
||||
auto command = memory_->TranslateVirtual<char*>(scratch + 260);
|
||||
|
||||
std::snprintf(command, 260, "PIX!m!%s", cmd);
|
||||
|
||||
global_lock.unlock();
|
||||
uint64_t args[] = {scratch + 260, scratch, 260};
|
||||
auto result = kernel_state_->processor()->Execute(
|
||||
XThread::GetCurrentThread()->thread_state(), pix_function_, args,
|
||||
xe::countof(args));
|
||||
global_lock.lock();
|
||||
|
||||
XELOGD("PIX(command): %s", cmd);
|
||||
XELOGD("PIX(response): %s", response);
|
||||
|
||||
memory_->SystemHeapFree(scratch);
|
||||
|
||||
if (XSUCCEEDED(result)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
XboxkrnlModule::XboxkrnlModule(Emulator* emulator, KernelState* kernel_state)
|
||||
: KernelModule(kernel_state, "xe:\\xboxkrnl.exe"),
|
||||
timestamp_timer_(nullptr) {
|
||||
|
@ -52,19 +99,46 @@ XboxkrnlModule::XboxkrnlModule(Emulator* emulator, KernelState* kernel_state)
|
|||
// Set to a valid value when a remote debugger is attached.
|
||||
// Offset 0x18 is a 4b pointer to a handler function that seems to take two
|
||||
// arguments. If we wanted to see what would happen we could fake that.
|
||||
uint32_t pKeDebugMonitorData = memory_->SystemHeapAlloc(256);
|
||||
auto lpKeDebugMonitorData = memory_->TranslateVirtual(pKeDebugMonitorData);
|
||||
uint32_t pKeDebugMonitorData;
|
||||
if (!FLAGS_kernel_debug_monitor) {
|
||||
pKeDebugMonitorData = memory_->SystemHeapAlloc(4);
|
||||
auto lpKeDebugMonitorData = memory_->TranslateVirtual(pKeDebugMonitorData);
|
||||
xe::store_and_swap<uint32_t>(lpKeDebugMonitorData, 0);
|
||||
} else {
|
||||
pKeDebugMonitorData =
|
||||
memory_->SystemHeapAlloc(4 + sizeof(X_KEDEBUGMONITORDATA));
|
||||
xe::store_and_swap<uint32_t>(memory_->TranslateVirtual(pKeDebugMonitorData),
|
||||
pKeDebugMonitorData + 4);
|
||||
auto lpKeDebugMonitorData =
|
||||
memory_->TranslateVirtual<X_KEDEBUGMONITORDATA*>(pKeDebugMonitorData +
|
||||
4);
|
||||
std::memset(lpKeDebugMonitorData, 0, sizeof(X_KEDEBUGMONITORDATA));
|
||||
lpKeDebugMonitorData->callback_fn =
|
||||
GenerateTrampoline("KeDebugMonitorCallback", KeDebugMonitorCallback);
|
||||
}
|
||||
export_resolver_->SetVariableMapping(
|
||||
"xboxkrnl.exe", ordinals::KeDebugMonitorData, pKeDebugMonitorData);
|
||||
xe::store_and_swap<uint32_t>(lpKeDebugMonitorData, 0);
|
||||
|
||||
// KeCertMonitorData (?*)
|
||||
// Always set to zero, ignored.
|
||||
uint32_t pKeCertMonitorData = memory_->SystemHeapAlloc(4);
|
||||
auto lpKeCertMonitorData = memory_->TranslateVirtual(pKeCertMonitorData);
|
||||
uint32_t pKeCertMonitorData;
|
||||
if (!FLAGS_kernel_cert_monitor) {
|
||||
pKeCertMonitorData = memory_->SystemHeapAlloc(4);
|
||||
auto lpKeCertMonitorData = memory_->TranslateVirtual(pKeCertMonitorData);
|
||||
xe::store_and_swap<uint32_t>(lpKeCertMonitorData, 0);
|
||||
} else {
|
||||
pKeCertMonitorData =
|
||||
memory_->SystemHeapAlloc(4 + sizeof(X_KECERTMONITORDATA));
|
||||
xe::store_and_swap<uint32_t>(memory_->TranslateVirtual(pKeCertMonitorData),
|
||||
pKeCertMonitorData + 4);
|
||||
auto lpKeCertMonitorData =
|
||||
memory_->TranslateVirtual<X_KECERTMONITORDATA*>(pKeCertMonitorData + 4);
|
||||
std::memset(lpKeCertMonitorData, 0, sizeof(X_KECERTMONITORDATA));
|
||||
lpKeCertMonitorData->callback_fn =
|
||||
GenerateTrampoline("KeCertMonitorCallback", KeCertMonitorCallback);
|
||||
}
|
||||
export_resolver_->SetVariableMapping(
|
||||
"xboxkrnl.exe", ordinals::KeCertMonitorData, pKeCertMonitorData);
|
||||
xe::store_and_swap<uint32_t>(lpKeCertMonitorData, 0);
|
||||
|
||||
// XboxHardwareInfo (XboxHardwareInfo_t, 16b)
|
||||
// flags cpu# ? ? ? ? ? ?
|
||||
|
|
|
@ -32,6 +32,13 @@ class XboxkrnlModule : public KernelModule {
|
|||
|
||||
static void RegisterExportTable(xe::cpu::ExportResolver* export_resolver);
|
||||
|
||||
bool SendPIXCommand(const char* cmd);
|
||||
|
||||
void set_pix_function(uint32_t addr) { pix_function_ = addr; }
|
||||
|
||||
protected:
|
||||
uint32_t pix_function_ = 0;
|
||||
|
||||
private:
|
||||
std::unique_ptr<xe::threading::HighResolutionTimer> timestamp_timer_;
|
||||
};
|
||||
|
|
Loading…
Reference in New Issue