mirror of
https://github.com/RPCS3/rpcs3.git
synced 2025-04-20 11:36:13 +00:00
kernel-explorer: Initial SPURS debugger
This commit is contained in:
parent
983547af7e
commit
a5cff8b186
3 changed files with 139 additions and 19 deletions
|
@ -136,6 +136,25 @@ void fmt_class_string<CellSpursJobError>::format(std::string& out, u64 arg)
|
|||
});
|
||||
}
|
||||
|
||||
template <>
|
||||
void fmt_class_string<SpursWorkloadState>::format(std::string& out, u64 arg)
|
||||
{
|
||||
format_enum(out, arg, [](auto error)
|
||||
{
|
||||
switch (error)
|
||||
{
|
||||
case SPURS_WKL_STATE_NON_EXISTENT: return "Non-existent";
|
||||
case SPURS_WKL_STATE_PREPARING: return "Preparing";
|
||||
case SPURS_WKL_STATE_RUNNABLE: return "Runnable";
|
||||
case SPURS_WKL_STATE_SHUTTING_DOWN: return "In-shutdown";
|
||||
case SPURS_WKL_STATE_REMOVABLE: return "Removable";
|
||||
case SPURS_WKL_STATE_INVALID: break;
|
||||
}
|
||||
|
||||
return unknown;
|
||||
});
|
||||
}
|
||||
|
||||
extern u64 ppu_ldarx(ppu_thread&, u32);
|
||||
extern u32 ppu_lwarx(ppu_thread&, u32);
|
||||
extern bool ppu_stwcx(ppu_thread&, u32, u32);
|
||||
|
@ -761,15 +780,13 @@ s32 _spurs::wakeup_shutdown_completion_waiter(ppu_thread& ppu, vm::ptr<CellSpurs
|
|||
return CELL_SPURS_POLICY_MODULE_ERROR_SRCH;
|
||||
}
|
||||
|
||||
const u8 wklState = wid < CELL_SPURS_MAX_WORKLOAD ? spurs->wklState1[wid] : spurs->wklState2[wid & 0x0F];
|
||||
|
||||
if (wklState != SPURS_WKL_STATE_REMOVABLE)
|
||||
if (spurs->wklState(wid) != SPURS_WKL_STATE_REMOVABLE)
|
||||
{
|
||||
return CELL_SPURS_POLICY_MODULE_ERROR_STAT;
|
||||
}
|
||||
|
||||
const auto wklF = wid < CELL_SPURS_MAX_WORKLOAD ? &spurs->wklF1[wid] : &spurs->wklF2[wid & 0x0F];
|
||||
const auto wklEvent = wid < CELL_SPURS_MAX_WORKLOAD ? &spurs->wklEvent1[wid] : &spurs->wklEvent2[wid & 0x0F];
|
||||
const auto wklEvent = &spurs->wklEvent(wid);
|
||||
|
||||
if (wklF->hook)
|
||||
{
|
||||
|
@ -2255,7 +2272,7 @@ s32 _spurs::add_workload(vm::ptr<CellSpurs> spurs, vm::ptr<u32> wid, vm::cptr<vo
|
|||
{
|
||||
verify(HERE), (spurs->wklCurrentContention[wnum] & 0xf) == 0;
|
||||
verify(HERE), (spurs->wklPendingContention[wnum] & 0xf) == 0;
|
||||
spurs->wklState1[wnum] = 1;
|
||||
spurs->wklState1[wnum] = SPURS_WKL_STATE_PREPARING;
|
||||
spurs->wklStatus1[wnum] = 0;
|
||||
spurs->wklEvent1[wnum] = 0;
|
||||
spurs->wklInfo1[wnum].addr = pm;
|
||||
|
@ -2291,7 +2308,7 @@ s32 _spurs::add_workload(vm::ptr<CellSpurs> spurs, vm::ptr<u32> wid, vm::cptr<vo
|
|||
{
|
||||
verify(HERE), (spurs->wklCurrentContention[index] & 0xf0) == 0;
|
||||
verify(HERE), (spurs->wklPendingContention[index] & 0xf0) == 0;
|
||||
spurs->wklState2[index] = 1;
|
||||
spurs->wklState2[index] = SPURS_WKL_STATE_PREPARING;
|
||||
spurs->wklStatus2[index] = 0;
|
||||
spurs->wklEvent2[index] = 0;
|
||||
spurs->wklInfo2[index].addr = pm;
|
||||
|
@ -2370,7 +2387,7 @@ s32 _spurs::add_workload(vm::ptr<CellSpurs> spurs, vm::ptr<u32> wid, vm::cptr<vo
|
|||
});
|
||||
|
||||
verify(HERE), (res_wkl <= 31);
|
||||
spurs->wklState(wnum).exchange(2);
|
||||
spurs->wklState(wnum).exchange(SPURS_WKL_STATE_RUNNABLE);
|
||||
spurs->sysSrvMsgUpdateWorkload.exchange(0xff);
|
||||
spurs->sysSrvMessage.exchange(0xff);
|
||||
return CELL_OK;
|
||||
|
@ -2555,7 +2572,7 @@ s32 cellSpursReadyCountStore(ppu_thread& ppu, vm::ptr<CellSpurs> spurs, u32 wid,
|
|||
return CELL_SPURS_POLICY_MODULE_ERROR_SRCH;
|
||||
}
|
||||
|
||||
if (spurs->exception || spurs->wklState(wid) != 2)
|
||||
if (spurs->exception || spurs->wklState(wid) != SPURS_WKL_STATE_RUNNABLE)
|
||||
{
|
||||
return CELL_SPURS_POLICY_MODULE_ERROR_STAT;
|
||||
}
|
||||
|
@ -2591,7 +2608,7 @@ s32 cellSpursReadyCountSwap(ppu_thread& ppu, vm::ptr<CellSpurs> spurs, u32 wid,
|
|||
return CELL_SPURS_POLICY_MODULE_ERROR_SRCH;
|
||||
}
|
||||
|
||||
if (spurs->exception || spurs->wklState(wid) != 2)
|
||||
if (spurs->exception || spurs->wklState(wid) != SPURS_WKL_STATE_RUNNABLE)
|
||||
{
|
||||
return CELL_SPURS_POLICY_MODULE_ERROR_STAT;
|
||||
}
|
||||
|
@ -2629,7 +2646,7 @@ s32 cellSpursReadyCountCompareAndSwap(ppu_thread& ppu, vm::ptr<CellSpurs> spurs,
|
|||
return CELL_SPURS_POLICY_MODULE_ERROR_SRCH;
|
||||
}
|
||||
|
||||
if (spurs->exception || spurs->wklState(wid) != 2)
|
||||
if (spurs->exception || spurs->wklState(wid) != SPURS_WKL_STATE_RUNNABLE)
|
||||
{
|
||||
return CELL_SPURS_POLICY_MODULE_ERROR_STAT;
|
||||
}
|
||||
|
@ -2669,7 +2686,7 @@ s32 cellSpursReadyCountAdd(ppu_thread& ppu, vm::ptr<CellSpurs> spurs, u32 wid, v
|
|||
return CELL_SPURS_POLICY_MODULE_ERROR_SRCH;
|
||||
}
|
||||
|
||||
if (spurs->exception || spurs->wklState(wid) != 2)
|
||||
if (spurs->exception || spurs->wklState(wid) != SPURS_WKL_STATE_RUNNABLE)
|
||||
{
|
||||
return CELL_SPURS_POLICY_MODULE_ERROR_STAT;
|
||||
}
|
||||
|
|
|
@ -145,7 +145,7 @@ enum SpursFlags1 : u8
|
|||
SF1_EXIT_IF_NO_WORK = 0x80,
|
||||
};
|
||||
|
||||
enum SpursWorkloadConstants : u32
|
||||
enum SpursWorkloadState : u8
|
||||
{
|
||||
// Workload states
|
||||
SPURS_WKL_STATE_NON_EXISTENT = 0,
|
||||
|
@ -154,7 +154,10 @@ enum SpursWorkloadConstants : u32
|
|||
SPURS_WKL_STATE_SHUTTING_DOWN = 3,
|
||||
SPURS_WKL_STATE_REMOVABLE = 4,
|
||||
SPURS_WKL_STATE_INVALID = 5,
|
||||
};
|
||||
|
||||
enum SpursImgAddrConstants : u32
|
||||
{
|
||||
// Image addresses
|
||||
SPURS_IMG_ADDR_SYS_SRV_WORKLOAD = 0x100,
|
||||
SPURS_IMG_ADDR_TASKSET_PM = 0x200,
|
||||
|
@ -537,7 +540,7 @@ struct alignas(128) CellSpurs
|
|||
atomic_t<u8> wklFlagReceiver; // 0x77
|
||||
atomic_be_t<u16> wklSignal2; // 0x78 Bitset for 16..32 wids
|
||||
u8 x7A[6]; // 0x7A
|
||||
atomic_t<u8> wklState1[0x10]; // 0x80 SPURS_WKL_STATE_*
|
||||
atomic_t<SpursWorkloadState> wklState1[0x10]; // 0x80
|
||||
u8 wklStatus1[0x10]; // 0x90
|
||||
atomic_t<u8> wklEvent1[0x10]; // 0xA0
|
||||
atomic_be_t<u32> wklEnabled; // 0xB0
|
||||
|
@ -563,7 +566,7 @@ struct alignas(128) CellSpurs
|
|||
|
||||
atomic_t<SrvTraceSyncVar> sysSrvTrace; // 0xCC
|
||||
|
||||
atomic_t<u8> wklState2[0x10]; // 0xD0 SPURS_WKL_STATE_*
|
||||
atomic_t<SpursWorkloadState> wklState2[0x10]; // 0xD0
|
||||
u8 wklStatus2[0x10]; // 0xE0
|
||||
atomic_t<u8> wklEvent2[0x10]; // 0xF0
|
||||
_sub_str1 wklF1[0x10]; // 0x100
|
||||
|
@ -615,7 +618,7 @@ struct alignas(128) CellSpurs
|
|||
_sub_str4 wklH2[0x10]; // 0x1A00
|
||||
u8 unknown_[0x2000 - 0x1B00];
|
||||
|
||||
atomic_t<u8>& wklState(const u32 wid)
|
||||
atomic_t<SpursWorkloadState>& wklState(u32 wid)
|
||||
{
|
||||
if (wid & 0x10)
|
||||
{
|
||||
|
@ -627,6 +630,18 @@ struct alignas(128) CellSpurs
|
|||
}
|
||||
}
|
||||
|
||||
atomic_t<u8>& wklEvent(u32 wid)
|
||||
{
|
||||
if (wid & 0x10)
|
||||
{
|
||||
return wklEvent2[wid & 0xf];
|
||||
}
|
||||
else
|
||||
{
|
||||
return wklEvent1[wid & 0xf];
|
||||
}
|
||||
}
|
||||
|
||||
atomic_t<u8>& readyCount(u32 wid)
|
||||
{
|
||||
if (wid & 0x10)
|
||||
|
@ -638,6 +653,18 @@ struct alignas(128) CellSpurs
|
|||
return wklIdleSpuCountOrReadyCount2[wid & 0xf];
|
||||
}
|
||||
}
|
||||
|
||||
_sub_str4& wklName(u32 wid)
|
||||
{
|
||||
if (wid & 0x10)
|
||||
{
|
||||
return wklH2[wid & 0xf];
|
||||
}
|
||||
else
|
||||
{
|
||||
return wklH1[wid & 0xf];
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
CHECK_SIZE_ALIGN(CellSpurs, 0x2000, 128);
|
||||
|
|
|
@ -29,6 +29,7 @@
|
|||
#include "Emu/Cell/lv2/sys_vm.h"
|
||||
#include "Emu/Cell/lv2/sys_net.h"
|
||||
#include "Emu/Cell/lv2/sys_fs.h"
|
||||
#include "Emu/Cell/Modules/cellSpurs.h"
|
||||
|
||||
#include "Emu/RSX/RSXThread.h"
|
||||
|
||||
|
@ -50,6 +51,7 @@ enum kernel_item_type : int
|
|||
root,
|
||||
node,
|
||||
volatile_node,
|
||||
solid_node,
|
||||
leaf
|
||||
};
|
||||
|
||||
|
@ -134,6 +136,20 @@ static QTreeWidgetItem* add_volatile_node(QTreeWidget* tree, QTreeWidgetItem *pa
|
|||
return node;
|
||||
}
|
||||
|
||||
static QTreeWidgetItem* add_solid_node(QTreeWidget* tree, QTreeWidgetItem *parent, const QString& base_text, const QString& text = "", int column = 0)
|
||||
{
|
||||
QTreeWidgetItem* node = find_first_node(tree, parent, base_text + ".*");
|
||||
if (!node)
|
||||
{
|
||||
node = add_child(parent, base_text, column, kernel_item_type::solid_node);
|
||||
}
|
||||
if (node)
|
||||
{
|
||||
node->setText(0, text.isEmpty() ? base_text : text);
|
||||
}
|
||||
return node;
|
||||
}
|
||||
|
||||
kernel_explorer::kernel_explorer(QWidget* parent) : QDialog(parent)
|
||||
{
|
||||
setWindowTitle(tr("Kernel Explorer"));
|
||||
|
@ -251,6 +267,7 @@ void kernel_explorer::Update()
|
|||
}
|
||||
[[fallthrough]];
|
||||
}
|
||||
case kernel_item_type::solid_node:
|
||||
case kernel_item_type::node:
|
||||
case kernel_item_type::root:
|
||||
default:
|
||||
|
@ -480,7 +497,65 @@ void kernel_explorer::Update()
|
|||
|
||||
idm::select<lv2_spu_group>([&](u32 id, lv2_spu_group& tg)
|
||||
{
|
||||
add_leaf(find_node(m_tree, additional_nodes::spu_thread_groups), qstr(fmt::format(u8"SPU Group 0x%07x: “%s”, Status = %s, Priority = %d, Type = 0x%x", id, tg.name, tg.run_state.load(), +tg.prio, tg.type)));
|
||||
QTreeWidgetItem* spu_tree = add_solid_node(m_tree, find_node(m_tree, additional_nodes::spu_thread_groups), qstr(fmt::format(u8"SPU Group 0x%07x: “%s”, Status = %s, Priority = %d, Type = 0x%x", id, tg.name, tg.run_state.load(), +tg.prio, tg.type)));
|
||||
|
||||
if (tg.name.ends_with("CellSpursKernelGroup"sv))
|
||||
{
|
||||
vm::ptr<CellSpurs> pspurs{};
|
||||
|
||||
for (const auto& thread : tg.threads)
|
||||
{
|
||||
if (thread)
|
||||
{
|
||||
// Find SPURS structure address
|
||||
const u64 arg = tg.args[thread->index][1];
|
||||
|
||||
if (!pspurs)
|
||||
{
|
||||
if (arg < UINT32_MAX && arg % 0x80 == 0 && vm::check_addr(arg, pspurs.size()))
|
||||
{
|
||||
pspurs.set(static_cast<u32>(arg));
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (pspurs.addr() != arg)
|
||||
{
|
||||
pspurs = {};
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
CellSpurs spurs{};
|
||||
|
||||
if (pspurs && pspurs.try_read(spurs))
|
||||
{
|
||||
const QString branch_name = "SPURS";
|
||||
const u32 wklEnabled = spurs.wklEnabled;
|
||||
QTreeWidgetItem* spurs_tree = add_solid_node(m_tree, spu_tree, branch_name, branch_name + qstr(fmt::format(", Instance: *0x%x, LWMutex: 0x%x, LWCond: 0x%x"
|
||||
, pspurs, spurs.mutex.sleep_queue, spurs.cond.lwcond_queue)));
|
||||
|
||||
for (u32 i = 1; i; i <<= 1)
|
||||
{
|
||||
if (!(wklEnabled & i))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
const u32 wid = std::countr_zero(i);
|
||||
const u32 ready_count = spurs.readyCount(wid);
|
||||
const auto state = spurs.wklState(wid).load();
|
||||
add_leaf(spurs_tree, qstr(fmt::format("Workload %u, Name: %s, State: %s, ReadyCnt: %u", wid, +spurs.wklName(wid).nameInstance, state, ready_count)));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// TODO: Might be old CellSpurs structure which is smaller
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
QTreeWidgetItem* rsx_context_node = find_node(m_tree, additional_nodes::rsx_contexts);
|
||||
|
@ -504,7 +579,7 @@ void kernel_explorer::Update()
|
|||
}
|
||||
|
||||
const QString branch_name = "RSX Context 0x55555555";
|
||||
QTreeWidgetItem* rsx_tree = add_volatile_node(m_tree, rsx_context_node, branch_name,
|
||||
QTreeWidgetItem* rsx_tree = add_solid_node(m_tree, rsx_context_node, branch_name,
|
||||
branch_name + qstr(fmt::format(u8", Local Size: %u MB, Base Addr: 0x%x, Device Addr: 0x%x, Handlers: 0x%x", context_info->memory_size >> 20, base, context_info->device_addr, +vm::_ref<RsxDriverInfo>(context_info->driver_info).handlers)));
|
||||
|
||||
QTreeWidgetItem* io_tree = add_volatile_node(m_tree, rsx_tree, tr("IO-EA Table"));
|
||||
|
@ -611,7 +686,7 @@ void kernel_explorer::Update()
|
|||
continue;
|
||||
}
|
||||
|
||||
switch (node->data(0, kernel_item_role::type_role).toInt())
|
||||
switch (int type = node->data(0, kernel_item_role::type_role).toInt())
|
||||
{
|
||||
case kernel_item_type::leaf:
|
||||
{
|
||||
|
@ -619,6 +694,7 @@ void kernel_explorer::Update()
|
|||
break;
|
||||
}
|
||||
case kernel_item_type::node:
|
||||
case kernel_item_type::solid_node:
|
||||
case kernel_item_type::volatile_node:
|
||||
{
|
||||
const int count = final_touches(node);
|
||||
|
@ -633,7 +709,7 @@ void kernel_explorer::Update()
|
|||
}
|
||||
|
||||
// Hide node if it has no children
|
||||
node->setHidden(count <= 0);
|
||||
node->setHidden(type != kernel_item_type::solid_node && count <= 0);
|
||||
break;
|
||||
}
|
||||
case kernel_item_type::root:
|
||||
|
|
Loading…
Add table
Reference in a new issue