mirror of
https://github.com/RPCS3/rpcs3.git
synced 2025-02-06 09:39:55 +00:00
SPURS: Implement some portions of taskset policy module
This commit is contained in:
parent
430aa9af89
commit
2e2f92f4f6
@ -1702,7 +1702,7 @@ s64 _cellSpursEventFlagInitialize(vm::ptr<CellSpurs> spurs, vm::ptr<CellSpursTas
|
||||
#ifdef PRX_DEBUG
|
||||
return GetCurrentPPUThread().FastCall2(libsre + 0x1564C, libsre_rtoc);
|
||||
#else
|
||||
if (taskset.addr() == 0 || spurs.addr() == 0)
|
||||
if (taskset.addr() == 0 && spurs.addr() == 0)
|
||||
{
|
||||
return CELL_SPURS_TASK_ERROR_NULL_POINTER;
|
||||
}
|
||||
@ -3365,7 +3365,7 @@ s64 cellSpursGetTasksetInfo()
|
||||
|
||||
s64 _cellSpursTasksetAttributeInitialize(vm::ptr<CellSpursTasksetAttribute> attribute, u32 revision, u32 sdk_version, u64 args, vm::ptr<const u8> priority, u32 max_contention)
|
||||
{
|
||||
cellSpurs->Warning("%s(attribute=0x%x, revision=%u, skd_version=%u, args=0x%llx, priority=0x%x, max_contention=%u)",
|
||||
cellSpurs->Warning("%s(attribute=0x%x, revision=%d, skd_version=%d, args=0x%llx, priority=0x%x, max_contention=%d)",
|
||||
__FUNCTION__, attribute.addr(), revision, sdk_version, args, priority.addr(), max_contention);
|
||||
|
||||
#ifdef PRX_DEBUG
|
||||
|
@ -564,7 +564,7 @@ struct CellSpursEventFlag
|
||||
be_t<u16> spuTaskPendingRecv; // 0x02 A bit is set to 1 when the condition of the SPU task using the slot are met and back to 0 when the SPU task unblocks
|
||||
be_t<u16> ppuWaitMask; // 0x04 Wait mask for blocked PPU thread
|
||||
u8 ppuWaitSlotAndMode; // 0x06 Top 4 bits: Wait slot number of the blocked PPU threa, Bottom 4 bits: Wait mode of the blocked PPU thread
|
||||
u8 ppuPendingRecv; // 0x07 Set to 1 when the blocked PPU thread's conditions are met and back to 0 when the PPU thread is ublocked
|
||||
u8 ppuPendingRecv; // 0x07 Set to 1 when the blocked PPU thread's conditions are met and back to 0 when the PPU thread is unblocked
|
||||
be_t<u16> spuTaskUsedWaitSlots; // 0x08 A bit is set to 1 if the wait slot corresponding to the bit is used by an SPU task and 0 otherwise
|
||||
be_t<u16> spuTaskWaitMode; // 0x0A A bit is set to 1 if the wait mode for the SPU task corresponding to the bit is AND and 0 otherwise
|
||||
u8 spuPort; // 0x0C
|
||||
@ -852,8 +852,9 @@ struct CellSpursTaskBinInfo
|
||||
CellSpursTaskLsPattern lsPattern;
|
||||
};
|
||||
|
||||
// The SPURS kernel data store. This resides at 0x00 of the LS.
|
||||
struct SpursKernelMgmtData {
|
||||
// The SPURS kernel data store. This resides at 0x100 of the LS.
|
||||
struct SpursKernelMgmtData
|
||||
{
|
||||
u8 tempArea[0x80]; // 0x100
|
||||
u8 wklLocContention[0x10]; // 0x180
|
||||
u8 wklLocPendingContention[0x10]; // 0x190
|
||||
@ -867,8 +868,7 @@ struct SpursKernelMgmtData {
|
||||
be_t<u32> wklCurrentId; // 0x1DC
|
||||
be_t<u32> yieldToKernelAddr; // 0x1E0
|
||||
be_t<u32> selectWorkloadAddr; // 0x1E4
|
||||
u8 x1E8; // 0x1E8
|
||||
u8 x1E9; // 0x1E9
|
||||
u8 moduleId[2]; // 0x1E8
|
||||
u8 sysSrvInitialised; // 0x1EA
|
||||
u8 spuIdling; // 0x1EB
|
||||
be_t<u16> wklRunnable1; // 0x1EC
|
||||
@ -880,5 +880,28 @@ struct SpursKernelMgmtData {
|
||||
u8 wklUniqueId[0x10]; // 0x220
|
||||
};
|
||||
|
||||
static_assert(sizeof(SpursKernelMgmtData) == 0x130, "Incorrect size for SpursKernelMgmtData");
|
||||
|
||||
// The SPURS taskset policy module data store. This resides at 0x2700 of the LS.
|
||||
struct SpursTasksetPmMgmtData
|
||||
{
|
||||
u8 tempArea[0x80]; // 0x2700
|
||||
u8 x2780[0x27B8 - 0x2780]; // 0x2780
|
||||
vm::bptr<CellSpursTaskset, 1, u64> taskset; // 0x27B8
|
||||
be_t<u32> kernelMgmt; // 0x27C0
|
||||
be_t<u32> yieldAddr; // 0x27C4
|
||||
be_t<u32> x27C8; // 0x27C8
|
||||
be_t<u32> spuNum; // 0x27CC
|
||||
be_t<u32> dmaTagId; // 0x27D0
|
||||
be_t<u32> taskId; // 0x27D4
|
||||
u8 x27D8[0x2840 - 0x27D8]; // 0x27D8
|
||||
u8 moduleId[16]; // 0x2840
|
||||
u8 x2850[0x2C80 - 0x2850]; // 0x2850
|
||||
be_t<u128> contextSaveArea[50]; // 0x2C80
|
||||
u8 x2FA0[0x3000 - 0x2FA0]; // 0x2FA0
|
||||
};
|
||||
|
||||
static_assert(sizeof(SpursTasksetPmMgmtData) == 0x900, "Incorrect size for SpursTasksetPmMgmtData");
|
||||
|
||||
s64 spursAttachLv2EventQueue(vm::ptr<CellSpurs> spurs, u32 queue, vm::ptr<u8> port, s32 isDynamic, bool wasCreated);
|
||||
s64 spursWakeUp(PPUThread& CPU, vm::ptr<CellSpurs> spurs);
|
||||
|
@ -33,6 +33,10 @@ void spursSysServiceWaitOrExit(SPUThread & spu, SpursKernelMgmtData * mgmt);
|
||||
void spursSysServiceWorkloadMain(SPUThread & spu, u32 pollStatus);
|
||||
void spursSysServiceWorkloadEntry(SPUThread & spu);
|
||||
|
||||
//
|
||||
// SPURS taskset polict module functions
|
||||
//
|
||||
|
||||
extern Module *cellSpurs;
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
@ -378,8 +382,8 @@ void spursKernelMain(SPUThread & spu) {
|
||||
}
|
||||
|
||||
if (!isSecond) {
|
||||
mgmt->x1E8 = 0;
|
||||
mgmt->x1E9 = 0;
|
||||
mgmt->moduleId[0] = 0;
|
||||
mgmt->moduleId[1] = 0;
|
||||
}
|
||||
|
||||
// Run workload
|
||||
@ -387,6 +391,7 @@ void spursKernelMain(SPUThread & spu) {
|
||||
spu.GPR[3]._u32[3] = 0x100;
|
||||
spu.GPR[4]._u64[1] = wkl.arg;
|
||||
spu.GPR[5]._u32[3] = pollStatus;
|
||||
spu.SetPc(0xA00);
|
||||
switch (mgmt->wklCurrentAddr.addr()) {
|
||||
case SPURS_IMG_ADDR_SYS_SRV_WORKLOAD:
|
||||
spursSysServiceWorkloadEntry(spu);
|
||||
@ -797,3 +802,136 @@ void spursSysServiceWorkloadEntry(SPUThread & spu) {
|
||||
// TODO: Ensure that this function always returns to the SPURS kernel
|
||||
return;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
// SPURS taskset policy module functions
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
bool spursTasksetProcessRequest(SPUThread & spu, s32 request, u32 * taskId, u32 * isWaiting) {
|
||||
auto kernelMgmt = vm::get_ptr<SpursKernelMgmtData>(spu.ls_offset + 0x100);
|
||||
auto mgmt = vm::get_ptr<SpursTasksetPmMgmtData>(spu.ls_offset + 0x2700);
|
||||
|
||||
// Verify taskset state is valid
|
||||
for (auto i = 0; i < 4; i ++) {
|
||||
if ((mgmt->taskset->m.waiting_set[i] & mgmt->taskset->m.running_set[i]) ||
|
||||
(mgmt->taskset->m.ready_set[i] & mgmt->taskset->m.ready2_set[i]) ||
|
||||
((mgmt->taskset->m.running_set[i] | mgmt->taskset->m.ready_set[i] |
|
||||
mgmt->taskset->m.ready2_set[i] | mgmt->taskset->m.signal_received_set[i] |
|
||||
mgmt->taskset->m.waiting_set[i]) & ~mgmt->taskset->m.enabled_set[i])) {
|
||||
assert(0);
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: Implement cases
|
||||
s32 delta = 0;
|
||||
switch (request + 1) {
|
||||
case 0:
|
||||
break;
|
||||
case 1:
|
||||
break;
|
||||
case 2:
|
||||
break;
|
||||
case 3:
|
||||
break;
|
||||
case 4:
|
||||
break;
|
||||
case 5:
|
||||
break;
|
||||
case 6:
|
||||
break;
|
||||
default:
|
||||
assert(0);
|
||||
break;
|
||||
}
|
||||
|
||||
// Set the ready count of the workload to the number of ready tasks
|
||||
do {
|
||||
s32 readyCount = kernelMgmt->wklCurrentId >= CELL_SPURS_MAX_WORKLOAD ?
|
||||
kernelMgmt->spurs->m.wklIdleSpuCountOrReadyCount2[kernelMgmt->wklCurrentId & 0x0F].read_relaxed() :
|
||||
kernelMgmt->spurs->m.wklReadyCount1[kernelMgmt->wklCurrentId].read_relaxed();
|
||||
|
||||
auto newReadyCount = readyCount + delta > 0xFF ? 0xFF : readyCount + delta < 0 ? 0 : readyCount + delta;
|
||||
|
||||
if (kernelMgmt->wklCurrentId >= CELL_SPURS_MAX_WORKLOAD) {
|
||||
kernelMgmt->spurs->m.wklIdleSpuCountOrReadyCount2[kernelMgmt->wklCurrentId & 0x0F].write_relaxed(newReadyCount);
|
||||
} else {
|
||||
kernelMgmt->spurs->m.wklReadyCount1[kernelMgmt->wklCurrentId].write_relaxed(newReadyCount);
|
||||
}
|
||||
|
||||
delta += readyCount;
|
||||
} while (delta > 0);
|
||||
|
||||
// TODO: Implement return
|
||||
return false;
|
||||
}
|
||||
|
||||
void spursTasksetDispatch() {
|
||||
}
|
||||
|
||||
void spursTasksetProcessPollStatus(SPUThread & spu, u32 pollStatus) {
|
||||
if (pollStatus & CELL_SPURS_MODULE_POLL_STATUS_FLAG) {
|
||||
spursTasksetProcessRequest(spu, 6, nullptr, nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
bool spursTasksetShouldYield(SPUThread & spu) {
|
||||
u32 pollStatus;
|
||||
|
||||
if (cellSpursModulePollStatus(spu, &pollStatus)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
spursTasksetProcessPollStatus(spu, pollStatus);
|
||||
return false;
|
||||
}
|
||||
|
||||
void spursTasksetInit(SPUThread & spu, u32 pollStatus) {
|
||||
auto mgmt = vm::get_ptr<SpursTasksetPmMgmtData>(spu.ls_offset + 0x2700);
|
||||
auto kernelMgmt = vm::get_ptr<SpursKernelMgmtData>(spu.ls_offset + 0x100);
|
||||
|
||||
kernelMgmt->moduleId[0] = 'T';
|
||||
kernelMgmt->moduleId[1] = 'K';
|
||||
|
||||
// Trace - START: Module='TKST'
|
||||
CellSpursTracePacket pkt;
|
||||
memset(&pkt, 0, sizeof(pkt));
|
||||
pkt.header.tag = 0x52; // Its not clear what this tag means exactly but it seems similar to CELL_SPURS_TRACE_TAG_START
|
||||
memcpy(pkt.data.start.module, "TKST", 4);
|
||||
pkt.data.start.level = 2;
|
||||
pkt.data.start.ls = 0xA00 >> 2;
|
||||
cellSpursModulePutTrace(&pkt, mgmt->dmaTagId);
|
||||
|
||||
spursTasksetProcessPollStatus(spu, pollStatus);
|
||||
}
|
||||
|
||||
void spursTasksetEntry(SPUThread & spu) {
|
||||
auto mgmt = vm::get_ptr<SpursTasksetPmMgmtData>(spu.ls_offset + 0x2700);
|
||||
|
||||
// Check if the function was invoked by the SPURS kernel or because of a syscall
|
||||
if (spu.PC != 0xA70) {
|
||||
// Called from kernel
|
||||
auto kernelMgmt = vm::get_ptr<SpursKernelMgmtData>(spu.ls_offset + spu.GPR[3]._u32[3]);
|
||||
auto arg = spu.GPR[4]._u64[1];
|
||||
auto pollStatus = spu.GPR[5]._u32[3];
|
||||
|
||||
memset(mgmt, 0, sizeof(*mgmt));
|
||||
mgmt->taskset.set(arg);
|
||||
memcpy(mgmt->moduleId, "SPURSTASK MODULE", 16);
|
||||
mgmt->kernelMgmt = spu.GPR[3]._u32[3];
|
||||
mgmt->yieldAddr = 0xA70;
|
||||
mgmt->spuNum = kernelMgmt->spuNum;
|
||||
mgmt->dmaTagId = kernelMgmt->dmaTagId;
|
||||
mgmt->taskId = 0xFFFFFFFF;
|
||||
|
||||
spursTasksetInit(spu, pollStatus);
|
||||
// TODO: Dispatch
|
||||
}
|
||||
|
||||
mgmt->contextSaveArea[0] = spu.GPR[0];
|
||||
mgmt->contextSaveArea[1] = spu.GPR[1];
|
||||
for (auto i = 0; i < 48; i++) {
|
||||
mgmt->contextSaveArea[i + 2] = spu.GPR[80 + i];
|
||||
}
|
||||
|
||||
// TODO: Process syscall
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user