mirror of
https://github.com/RPCS3/rpcs3.git
synced 2025-07-16 11:48:36 +12:00
SPURS: System service workload - initial commit
This commit is contained in:
parent
52b342464b
commit
6664116042
5 changed files with 561 additions and 103 deletions
|
@ -101,7 +101,7 @@ s64 spursInit(
|
|||
}
|
||||
spurs->m.xCC = 0;
|
||||
spurs->m.xCD = 0;
|
||||
spurs->m.xCE = 0;
|
||||
spurs->m.sysSrvMsgUpdateTrace = 0;
|
||||
for (u32 i = 0; i < 8; i++)
|
||||
{
|
||||
spurs->m.xC0[i] = -1;
|
||||
|
@ -225,8 +225,7 @@ s64 spursInit(
|
|||
// the system service message bit for this SPU is set.
|
||||
if (mgmt->spurs->m.sysSrvMessage.read_relaxed() & (1 << mgmt->spuNum))
|
||||
{
|
||||
// Not sure what this does. Possibly Mark the SPU as in use.
|
||||
mgmt->x1EB = 0;
|
||||
mgmt->spuIdling = 0;
|
||||
if (!isPoll || mgmt->wklCurrentId == CELL_SPURS_SYS_SERVICE_WORKLOAD_ID)
|
||||
{
|
||||
// Clear the message bit
|
||||
|
@ -239,7 +238,7 @@ s64 spursInit(
|
|||
u16 maxWeight = 0;
|
||||
for (auto i = 0; i < CELL_SPURS_MAX_WORKLOAD; i++)
|
||||
{
|
||||
u8 x1EC = mgmt->x1EC & (0x8000 >> i);
|
||||
u8 runnable = mgmt->wklRunnable1 & (0x8000 >> i);
|
||||
u8 wklSignal = mgmt->spurs->m.wklSignal1.read_relaxed() & (0x8000 >> i);
|
||||
u8 wklFlag = mgmt->spurs->m.wklFlag.flag.read_relaxed() == 0 ? mgmt->spurs->m.wklFlagReceiver.read_relaxed() == i ? 1 : 0 : 0;
|
||||
u8 readyCount = mgmt->spurs->m.wklReadyCount1[i].read_relaxed() > CELL_SPURS_MAX_SPU ? CELL_SPURS_MAX_SPU : mgmt->spurs->m.wklReadyCount1[i].read_relaxed();
|
||||
|
@ -249,11 +248,11 @@ s64 spursInit(
|
|||
// For a workload to be considered for scheduling:
|
||||
// 1. Its priority must not be 0
|
||||
// 2. The number of SPUs used by it must be less than the max contention for that workload
|
||||
// 3. The bit in 0x1EC for the wokload must be set
|
||||
// 3. The workload should be in runnable state
|
||||
// 4. The number of SPUs allocated to it must be less than the number of SPUs requested (i.e. readyCount)
|
||||
// OR the workload must be signalled
|
||||
// OR the workload flag is 0 and the workload is configured as the wokload flag receiver
|
||||
if (x1EC && mgmt->priority[i] != 0 && mgmt->spurs->m.wklMaxContention[i].read_relaxed() > contention[i])
|
||||
if (runnable && mgmt->priority[i] != 0 && mgmt->spurs->m.wklMaxContention[i].read_relaxed() > contention[i])
|
||||
{
|
||||
if (wklFlag || wklSignal || (readyCount != 0 && requestCount > contention[i]))
|
||||
{
|
||||
|
@ -287,7 +286,7 @@ s64 spursInit(
|
|||
}
|
||||
|
||||
// Not sure what this does. Possibly mark the SPU as idle/in use.
|
||||
mgmt->x1EB = wklSelectedId == CELL_SPURS_SYS_SERVICE_WORKLOAD_ID ? 1 : 0;
|
||||
mgmt->spuIdling = wklSelectedId == CELL_SPURS_SYS_SERVICE_WORKLOAD_ID ? 1 : 0;
|
||||
|
||||
if (!isPoll || wklSelectedId == mgmt->wklCurrentId)
|
||||
{
|
||||
|
@ -391,7 +390,7 @@ s64 spursInit(
|
|||
if (mgmt->spurs->m.sysSrvMessage.read_relaxed() & (1 << mgmt->spuNum))
|
||||
{
|
||||
// Not sure what this does. Possibly Mark the SPU as in use.
|
||||
mgmt->x1EB = 0;
|
||||
mgmt->spuIdling = 0;
|
||||
if (!isPoll || mgmt->wklCurrentId == CELL_SPURS_SYS_SERVICE_WORKLOAD_ID)
|
||||
{
|
||||
// Clear the message bit
|
||||
|
@ -405,7 +404,7 @@ s64 spursInit(
|
|||
for (auto i = 0; i < CELL_SPURS_MAX_WORKLOAD2; i++)
|
||||
{
|
||||
auto j = i & 0x0F;
|
||||
u8 x1ECx1EE = i < CELL_SPURS_MAX_WORKLOAD ? mgmt->x1EC & (0x8000 >> j) : mgmt->x1EE & (0x8000 >> j);
|
||||
u8 runnable = i < CELL_SPURS_MAX_WORKLOAD ? mgmt->wklRunnable1 & (0x8000 >> j) : mgmt->wklRunnable2 & (0x8000 >> j);
|
||||
u8 priority = i < CELL_SPURS_MAX_WORKLOAD ? mgmt->priority[j] & 0x0F : mgmt->priority[j] >> 4;
|
||||
u8 maxContention = i < CELL_SPURS_MAX_WORKLOAD ? mgmt->spurs->m.wklMaxContention[j].read_relaxed() & 0x0F : mgmt->spurs->m.wklMaxContention[j].read_relaxed() >> 4;
|
||||
u8 wklSignal = i < CELL_SPURS_MAX_WORKLOAD ? mgmt->spurs->m.wklSignal1.read_relaxed() & (0x8000 >> j) : mgmt->spurs->m.wklSignal2.read_relaxed() & (0x8000 >> j);
|
||||
|
@ -415,11 +414,11 @@ s64 spursInit(
|
|||
// For a workload to be considered for scheduling:
|
||||
// 1. Its priority must be greater than 0
|
||||
// 2. The number of SPUs used by it must be less than the max contention for that workload
|
||||
// 3. The bit in 0x1EC/0x1EE for the wokload must be set
|
||||
// 3. The workload should be in runnable state
|
||||
// 4. The number of SPUs allocated to it must be less than the number of SPUs requested (i.e. readyCount)
|
||||
// OR the workload must be signalled
|
||||
// OR the workload flag is 0 and the workload is configured as the wokload receiver
|
||||
if (x1ECx1EE && priority > 0 && maxContention > contention[i])
|
||||
if (runnable && priority > 0 && maxContention > contention[i])
|
||||
{
|
||||
if (wklFlag || wklSignal || readyCount > contention[i])
|
||||
{
|
||||
|
@ -445,7 +444,7 @@ s64 spursInit(
|
|||
}
|
||||
|
||||
// Not sure what this does. Possibly mark the SPU as idle/in use.
|
||||
mgmt->x1EB = wklSelectedId == CELL_SPURS_SYS_SERVICE_WORKLOAD_ID ? 1 : 0;
|
||||
mgmt->spuIdling = wklSelectedId == CELL_SPURS_SYS_SERVICE_WORKLOAD_ID ? 1 : 0;
|
||||
|
||||
if (!isPoll || wklSelectedId == mgmt->wklCurrentId)
|
||||
{
|
||||
|
@ -653,7 +652,7 @@ s64 spursInit(
|
|||
bool do_break = false;
|
||||
for (u32 i = 0; i < 16; i++)
|
||||
{
|
||||
if (spurs->m.wklStat1[i].read_relaxed() == 2 &&
|
||||
if (spurs->m.wklState1[i].read_relaxed() == 2 &&
|
||||
spurs->m.wklInfo1[i].priority.ToBE() != 0 &&
|
||||
spurs->m.wklMaxContention[i].read_relaxed() & 0xf
|
||||
)
|
||||
|
@ -671,7 +670,7 @@ s64 spursInit(
|
|||
}
|
||||
if (spurs->m.flags1 & SF1_32_WORKLOADS) for (u32 i = 0; i < 16; i++)
|
||||
{
|
||||
if (spurs->m.wklStat2[i].read_relaxed() == 2 &&
|
||||
if (spurs->m.wklState2[i].read_relaxed() == 2 &&
|
||||
spurs->m.wklInfo2[i].priority.ToBE() != 0 &&
|
||||
spurs->m.wklMaxContention[i].read_relaxed() & 0xf0
|
||||
)
|
||||
|
@ -756,7 +755,7 @@ s64 spursInit(
|
|||
}
|
||||
}
|
||||
|
||||
spurs->m.unk22 = 0;
|
||||
spurs->m.traceBuffer = 0;
|
||||
// can also use cellLibprof if available (omitted)
|
||||
|
||||
// some unknown subroutine
|
||||
|
@ -1439,13 +1438,16 @@ s32 spursAddWorkload(
|
|||
{
|
||||
assert((spurs->m.wklCurrentContention[wnum] & 0xf) == 0);
|
||||
assert((spurs->m.wklPendingContention[wnum] & 0xf) == 0);
|
||||
spurs->m.wklStat1[wnum].write_relaxed(1);
|
||||
spurs->m.wklD1[wnum] = 0;
|
||||
spurs->m.wklE1[wnum] = 0;
|
||||
spurs->m.wklState1[wnum].write_relaxed(1);
|
||||
spurs->m.wklStatus1[wnum] = 0;
|
||||
spurs->m.wklEvent1[wnum] = 0;
|
||||
spurs->m.wklInfo1[wnum].addr = pm;
|
||||
spurs->m.wklInfo1[wnum].arg = data;
|
||||
spurs->m.wklInfo1[wnum].size = size;
|
||||
spurs->m.wklInfo1[wnum].priority = *(be_t<u64>*)priorityTable;
|
||||
for (u32 i = 0; i < 8; i++)
|
||||
{
|
||||
spurs->m.wklInfo1[wnum].priority[i] = priorityTable[i];
|
||||
}
|
||||
spurs->m.wklH1[wnum].nameClass = nameClass;
|
||||
spurs->m.wklH1[wnum].nameInstance = nameInstance;
|
||||
memset(spurs->m.wklF1[wnum].unk0, 0, 0x20); // clear struct preserving semaphore id
|
||||
|
@ -1454,7 +1456,7 @@ s32 spursAddWorkload(
|
|||
{
|
||||
spurs->m.wklF1[wnum].hook = hook;
|
||||
spurs->m.wklF1[wnum].hookArg = hookArg;
|
||||
spurs->m.wklE1[wnum] |= 2;
|
||||
spurs->m.wklEvent1[wnum] |= 2;
|
||||
}
|
||||
if ((spurs->m.flags1 & SF1_32_WORKLOADS) == 0)
|
||||
{
|
||||
|
@ -1467,13 +1469,16 @@ s32 spursAddWorkload(
|
|||
{
|
||||
assert((spurs->m.wklCurrentContention[index] & 0xf0) == 0);
|
||||
assert((spurs->m.wklPendingContention[index] & 0xf0) == 0);
|
||||
spurs->m.wklStat2[index].write_relaxed(1);
|
||||
spurs->m.wklD2[index] = 0;
|
||||
spurs->m.wklE2[index] = 0;
|
||||
spurs->m.wklState2[index].write_relaxed(1);
|
||||
spurs->m.wklStatus2[index] = 0;
|
||||
spurs->m.wklEvent2[index] = 0;
|
||||
spurs->m.wklInfo2[index].addr = pm;
|
||||
spurs->m.wklInfo2[index].arg = data;
|
||||
spurs->m.wklInfo2[index].size = size;
|
||||
spurs->m.wklInfo2[index].priority = *(be_t<u64>*)priorityTable;
|
||||
for (u32 i = 0; i < 8; i++)
|
||||
{
|
||||
spurs->m.wklInfo2[index].priority[i] = priorityTable[i];
|
||||
}
|
||||
spurs->m.wklH2[index].nameClass = nameClass;
|
||||
spurs->m.wklH2[index].nameInstance = nameInstance;
|
||||
memset(spurs->m.wklF2[index].unk0, 0, 0x20); // clear struct preserving semaphore id
|
||||
|
@ -1482,7 +1487,7 @@ s32 spursAddWorkload(
|
|||
{
|
||||
spurs->m.wklF2[index].hook = hook;
|
||||
spurs->m.wklF2[index].hookArg = hookArg;
|
||||
spurs->m.wklE2[index] |= 2;
|
||||
spurs->m.wklEvent2[index] |= 2;
|
||||
}
|
||||
spurs->m.wklIdleSpuCountOrReadyCount2[wnum].write_relaxed(0);
|
||||
}
|
||||
|
@ -1539,8 +1544,8 @@ s32 spursAddWorkload(
|
|||
});
|
||||
assert(res_wkl <= 31);
|
||||
|
||||
spurs->wklStat(wnum).exchange(2);
|
||||
spurs->m.xBD.exchange(0xff);
|
||||
spurs->wklState(wnum).exchange(2);
|
||||
spurs->m.sysSrvMsgUpdateWorkload.exchange(0xff);
|
||||
spurs->m.sysSrvMessage.exchange(0xff);
|
||||
return CELL_OK;
|
||||
}
|
||||
|
@ -1871,7 +1876,7 @@ s64 cellSpursReadyCountStore(vm::ptr<CellSpurs> spurs, u32 wid, u32 value)
|
|||
{
|
||||
return CELL_SPURS_POLICY_MODULE_ERROR_SRCH;
|
||||
}
|
||||
if (spurs->m.exception.ToBE() || spurs->wklStat(wid).read_relaxed() != 2)
|
||||
if (spurs->m.exception.ToBE() || spurs->wklState(wid).read_relaxed() != 2)
|
||||
{
|
||||
return CELL_SPURS_POLICY_MODULE_ERROR_STAT;
|
||||
}
|
||||
|
@ -3364,6 +3369,190 @@ s64 cellSpursSemaphoreGetTasksetAddress()
|
|||
#endif
|
||||
}
|
||||
|
||||
bool spursIsLibProfLoaded()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
void spursTraceStatusUpdate(vm::ptr<CellSpurs> spurs)
|
||||
{
|
||||
LV2_LOCK(0);
|
||||
|
||||
if (spurs->m.xCC != 0)
|
||||
{
|
||||
spurs->m.xCD = 1;
|
||||
spurs->m.sysSrvMsgUpdateTrace = (1 << spurs->m.nSpus) - 1;
|
||||
spurs->m.sysSrvMessage.write_relaxed(0xFF);
|
||||
sys_semaphore_wait(spurs->m.semPrv, 0);
|
||||
}
|
||||
}
|
||||
|
||||
s64 spursTraceInitialize(vm::ptr<CellSpurs> spurs, vm::ptr<CellSpursTraceInfo> buffer, u32 size, u32 mode, u32 updateStatus)
|
||||
{
|
||||
if (!spurs || !buffer)
|
||||
{
|
||||
return CELL_SPURS_CORE_ERROR_NULL_POINTER;
|
||||
}
|
||||
|
||||
if (spurs.addr() % CellSpurs::align || buffer.addr() % CellSpursTraceInfo::align)
|
||||
{
|
||||
return CELL_SPURS_CORE_ERROR_ALIGN;
|
||||
}
|
||||
|
||||
if (size < CellSpursTraceInfo::size || mode & ~(CELL_SPURS_TRACE_MODE_FLAG_MASK))
|
||||
{
|
||||
return CELL_SPURS_CORE_ERROR_INVAL;
|
||||
}
|
||||
|
||||
if (spurs->m.traceBuffer != 0)
|
||||
{
|
||||
return CELL_SPURS_CORE_ERROR_STAT;
|
||||
}
|
||||
|
||||
spurs->m.traceDataSize = size - CellSpursTraceInfo::size;
|
||||
for (u32 i = 0; i < 8; i++)
|
||||
{
|
||||
buffer->spu_thread[i] = spurs->m.spus[i];
|
||||
buffer->count[i] = 0;
|
||||
}
|
||||
|
||||
buffer->spu_thread_grp = spurs->m.spuTG;
|
||||
buffer->nspu = spurs->m.nSpus;
|
||||
spurs->m.traceBuffer = buffer.addr() | (mode & CELL_SPURS_TRACE_MODE_FLAG_WRAP_BUFFER ? 1 : 0);
|
||||
spurs->m.traceMode = mode;
|
||||
|
||||
u32 spuTraceDataCount = (spurs->m.traceDataSize / CellSpursTracePacket::size) / spurs->m.nSpus;
|
||||
for (u32 i = 0, j = 8; i < 6; i++)
|
||||
{
|
||||
spurs->m.x908[i] = j;
|
||||
j += spuTraceDataCount;
|
||||
}
|
||||
|
||||
spurs->m.sysSrvTraceControl = 0;
|
||||
if (updateStatus)
|
||||
{
|
||||
spursTraceStatusUpdate(spurs);
|
||||
}
|
||||
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
s64 cellSpursTraceInitialize(vm::ptr<CellSpurs> spurs, vm::ptr<CellSpursTraceInfo> buffer, u32 size, u32 mode)
|
||||
{
|
||||
if (spursIsLibProfLoaded())
|
||||
{
|
||||
return CELL_SPURS_CORE_ERROR_STAT;
|
||||
}
|
||||
|
||||
return spursTraceInitialize(spurs, buffer, size, mode, 1);
|
||||
}
|
||||
|
||||
s64 spursTraceStart(vm::ptr<CellSpurs> spurs, u32 updateStatus)
|
||||
{
|
||||
if (!spurs)
|
||||
{
|
||||
return CELL_SPURS_CORE_ERROR_NULL_POINTER;
|
||||
}
|
||||
|
||||
if (spurs.addr() % CellSpurs::align)
|
||||
{
|
||||
return CELL_SPURS_CORE_ERROR_ALIGN;
|
||||
}
|
||||
|
||||
if (!spurs->m.traceBuffer)
|
||||
{
|
||||
return CELL_SPURS_CORE_ERROR_STAT;
|
||||
}
|
||||
|
||||
spurs->m.sysSrvTraceControl = 1;
|
||||
if (updateStatus)
|
||||
{
|
||||
spursTraceStatusUpdate(spurs);
|
||||
}
|
||||
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
s64 cellSpursTraceStart(vm::ptr<CellSpurs> spurs)
|
||||
{
|
||||
if (!spurs)
|
||||
{
|
||||
return CELL_SPURS_CORE_ERROR_NULL_POINTER;
|
||||
}
|
||||
|
||||
if (spurs.addr() % CellSpurs::align)
|
||||
{
|
||||
return CELL_SPURS_CORE_ERROR_ALIGN;
|
||||
}
|
||||
|
||||
return spursTraceStart(spurs, spurs->m.traceMode & CELL_SPURS_TRACE_MODE_FLAG_SYNCHRONOUS_START_STOP);
|
||||
}
|
||||
|
||||
s64 spursTraceStop(vm::ptr<CellSpurs> spurs, u32 updateStatus)
|
||||
{
|
||||
if (!spurs)
|
||||
{
|
||||
return CELL_SPURS_CORE_ERROR_NULL_POINTER;
|
||||
}
|
||||
|
||||
if (spurs.addr() % CellSpurs::align)
|
||||
{
|
||||
return CELL_SPURS_CORE_ERROR_ALIGN;
|
||||
}
|
||||
|
||||
if (!spurs->m.traceBuffer)
|
||||
{
|
||||
return CELL_SPURS_CORE_ERROR_STAT;
|
||||
}
|
||||
|
||||
spurs->m.sysSrvTraceControl = 2;
|
||||
if (updateStatus)
|
||||
{
|
||||
spursTraceStatusUpdate(spurs);
|
||||
}
|
||||
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
s64 cellSpursTraceStop(vm::ptr<CellSpurs> spurs)
|
||||
{
|
||||
if (!spurs)
|
||||
{
|
||||
return CELL_SPURS_CORE_ERROR_NULL_POINTER;
|
||||
}
|
||||
|
||||
if (spurs.addr() % CellSpurs::align)
|
||||
{
|
||||
return CELL_SPURS_CORE_ERROR_ALIGN;
|
||||
}
|
||||
|
||||
return spursTraceStop(spurs, spurs->m.traceMode & CELL_SPURS_TRACE_MODE_FLAG_SYNCHRONOUS_START_STOP);
|
||||
}
|
||||
|
||||
s64 cellSpursTraceFinalize(vm::ptr<CellSpurs> spurs)
|
||||
{
|
||||
if (!spurs)
|
||||
{
|
||||
return CELL_SPURS_CORE_ERROR_NULL_POINTER;
|
||||
}
|
||||
|
||||
if (spurs.addr() % CellSpurs::align)
|
||||
{
|
||||
return CELL_SPURS_CORE_ERROR_ALIGN;
|
||||
}
|
||||
|
||||
if (!spurs->m.traceBuffer)
|
||||
{
|
||||
return CELL_SPURS_CORE_ERROR_STAT;
|
||||
}
|
||||
|
||||
spurs->m.sysSrvTraceControl = 0;
|
||||
spurs->m.traceMode = 0;
|
||||
spurs->m.traceBuffer = 0;
|
||||
spursTraceStatusUpdate(spurs);
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
void cellSpurs_init(Module *pxThis)
|
||||
{
|
||||
cellSpurs = pxThis;
|
||||
|
@ -3521,5 +3710,11 @@ void cellSpurs_init(Module *pxThis)
|
|||
REG_FUNC(cellSpurs, _cellSpursSemaphoreInitialize);
|
||||
REG_FUNC(cellSpurs, cellSpursSemaphoreGetTasksetAddress);
|
||||
|
||||
// Trace
|
||||
REG_FUNC(cellSpurs, cellSpursTraceInitialize);
|
||||
REG_FUNC(cellSpurs, cellSpursTraceStart);
|
||||
REG_FUNC(cellSpurs, cellSpursTraceStop);
|
||||
REG_FUNC(cellSpurs, cellSpursTraceFinalize);
|
||||
|
||||
// TODO: some trace funcs
|
||||
}
|
|
@ -114,34 +114,6 @@ enum RangeofEventQueuePortNumbers
|
|||
CELL_SPURS_DYNAMIC_PORT_RANGE_BOTTOM = 63,
|
||||
};
|
||||
|
||||
enum SPURSTraceTypes
|
||||
{
|
||||
CELL_SPURS_TRACE_TAG_LOAD = 0x2a,
|
||||
CELL_SPURS_TRACE_TAG_MAP = 0x2b,
|
||||
CELL_SPURS_TRACE_TAG_START = 0x2c,
|
||||
CELL_SPURS_TRACE_TAG_STOP = 0x2d,
|
||||
CELL_SPURS_TRACE_TAG_USER = 0x2e,
|
||||
CELL_SPURS_TRACE_TAG_GUID = 0x2f,
|
||||
};
|
||||
|
||||
// SPURS task defines.
|
||||
enum TaskConstants
|
||||
{
|
||||
CELL_SPURS_MAX_TASK = 128,
|
||||
CELL_SPURS_TASK_TOP = 0x3000,
|
||||
CELL_SPURS_TASK_BOTTOM = 0x40000,
|
||||
CELL_SPURS_MAX_TASK_NAME_LENGTH = 32,
|
||||
CELL_SPURS_TASK_ATTRIBUTE_REVISION = 1,
|
||||
CELL_SPURS_TASKSET_ATTRIBUTE_REVISION = 1,
|
||||
CELL_SPURS_TASK_EXECUTION_CONTEXT_SIZE = 1024,
|
||||
};
|
||||
|
||||
class SPURSManager;
|
||||
class SPURSManagerEventFlag;
|
||||
class SPURSManagerTaskset;
|
||||
|
||||
struct CellSpurs;
|
||||
|
||||
enum SpursAttrFlags : u32
|
||||
{
|
||||
SAF_NONE = 0x0,
|
||||
|
@ -168,6 +140,68 @@ enum SpursFlags1 : u8
|
|||
SF1_EXIT_IF_NO_WORK = 0x80,
|
||||
};
|
||||
|
||||
enum SpursWorkloadConstants
|
||||
{
|
||||
// Workload states
|
||||
SPURS_WKL_STATE_NON_EXISTENT = 0,
|
||||
SPURS_WKL_STATE_PREPARING = 1,
|
||||
SPURS_WKL_STATE_RUNNABLE = 2,
|
||||
SPURS_WKL_STATE_SHUTTING_DOWN = 3,
|
||||
SPURS_WKL_STATE_REMOVABLE = 4,
|
||||
SPURS_WKL_STATE_INVALID = 5,
|
||||
};
|
||||
|
||||
enum CellSpursModulePollStatus
|
||||
{
|
||||
CELL_SPURS_MODULE_POLL_STATUS_READYCOUNT = 1,
|
||||
CELL_SPURS_MODULE_POLL_STATUS_SIGNAL = 2,
|
||||
CELL_SPURS_MODULE_POLL_STATUS_FLAG = 4
|
||||
};
|
||||
|
||||
enum SpursTraceConstants
|
||||
{
|
||||
// Trace tag types
|
||||
CELL_SPURS_TRACE_TAG_KERNEL = 0x20,
|
||||
CELL_SPURS_TRACE_TAG_SERVICE = 0x21,
|
||||
CELL_SPURS_TRACE_TAG_TASK = 0x22,
|
||||
CELL_SPURS_TRACE_TAG_JOB = 0x23,
|
||||
CELL_SPURS_TRACE_TAG_OVIS = 0x24,
|
||||
CELL_SPURS_TRACE_TAG_LOAD = 0x2a,
|
||||
CELL_SPURS_TRACE_TAG_MAP = 0x2b,
|
||||
CELL_SPURS_TRACE_TAG_START = 0x2c,
|
||||
CELL_SPURS_TRACE_TAG_STOP = 0x2d,
|
||||
CELL_SPURS_TRACE_TAG_USER = 0x2e,
|
||||
CELL_SPURS_TRACE_TAG_GUID = 0x2f,
|
||||
|
||||
// Service incident
|
||||
CELL_SPURS_TRACE_SERVICE_INIT = 0x01,
|
||||
CELL_SPURS_TRACE_SERVICE_WAIT = 0x02,
|
||||
CELL_SPURS_TRACE_SERVICE_EXIT = 0x03,
|
||||
|
||||
// Trace mode flags
|
||||
CELL_SPURS_TRACE_MODE_FLAG_WRAP_BUFFER = 0x1,
|
||||
CELL_SPURS_TRACE_MODE_FLAG_SYNCHRONOUS_START_STOP = 0x2,
|
||||
CELL_SPURS_TRACE_MODE_FLAG_MASK = 0x3,
|
||||
};
|
||||
|
||||
// SPURS task constants
|
||||
enum SpursTaskConstants
|
||||
{
|
||||
CELL_SPURS_MAX_TASK = 128,
|
||||
CELL_SPURS_TASK_TOP = 0x3000,
|
||||
CELL_SPURS_TASK_BOTTOM = 0x40000,
|
||||
CELL_SPURS_MAX_TASK_NAME_LENGTH = 32,
|
||||
CELL_SPURS_TASK_ATTRIBUTE_REVISION = 1,
|
||||
CELL_SPURS_TASKSET_ATTRIBUTE_REVISION = 1,
|
||||
CELL_SPURS_TASK_EXECUTION_CONTEXT_SIZE = 1024,
|
||||
};
|
||||
|
||||
class SPURSManager;
|
||||
class SPURSManagerEventFlag;
|
||||
class SPURSManagerTaskset;
|
||||
|
||||
struct CellSpurs;
|
||||
|
||||
struct CellSpursAttribute
|
||||
{
|
||||
static const uint align = 8;
|
||||
|
@ -215,12 +249,6 @@ struct CellSpursWorkloadFlag
|
|||
|
||||
typedef void(*CellSpursShutdownCompletionEventHook)(vm::ptr<CellSpurs>, u32 wid, vm::ptr<void> arg);
|
||||
|
||||
enum CellSpursModulePollStatus {
|
||||
CELL_SPURS_MODULE_POLL_STATUS_READYCOUNT = 1,
|
||||
CELL_SPURS_MODULE_POLL_STATUS_SIGNAL = 2,
|
||||
CELL_SPURS_MODULE_POLL_STATUS_FLAG = 4
|
||||
};
|
||||
|
||||
// Core CellSpurs structures
|
||||
struct CellSpurs
|
||||
{
|
||||
|
@ -259,7 +287,7 @@ struct CellSpurs
|
|||
be_t<u64> arg; // spu argument
|
||||
be_t<u32> size;
|
||||
atomic_t<u8> uniqueId; // The unique id is the same for all workloads with the same addr
|
||||
be_t<u64> priority;
|
||||
be_t<u8> priority[8];
|
||||
};
|
||||
|
||||
static_assert(sizeof(WorkloadInfo) == 0x20, "Wrong WorkloadInfo size");
|
||||
|
@ -294,36 +322,41 @@ struct CellSpurs
|
|||
CellSpursWorkloadFlag wklFlag; // 0x60
|
||||
atomic_t<u16> wklSignal1; // 0x70 (bitset for 0..15 wids)
|
||||
atomic_t<u8> sysSrvMessage; // 0x72
|
||||
u8 sysSrvIdling; // 0x73
|
||||
u8 spuIdling; // 0x73
|
||||
u8 flags1; // 0x74 Type is SpursFlags1
|
||||
u8 sysSrvTraceControl; // 0x75
|
||||
u8 nSpus; // 0x76
|
||||
atomic_t<u8> wklFlagReceiver; // 0x77
|
||||
atomic_t<u16> wklSignal2; // 0x78 (bitset for 16..32 wids)
|
||||
u8 x7A[6]; // 0x7A
|
||||
atomic_t<u8> wklStat1[0x10]; // 0x80 - Workload state (16*u8) - State enum {non_exitent, preparing, runnable, shutting_down, removable, invalid}
|
||||
u8 wklD1[0x10]; // 0x90 - Workload status (16*u8)
|
||||
u8 wklE1[0x10]; // 0xA0 - Workload event (16*u8)
|
||||
atomic_t<u8> wklState1[0x10]; // 0x80 SPURS_WKL_STATE_*
|
||||
u8 wklStatus1[0x10]; // 0x90
|
||||
u8 wklEvent1[0x10]; // 0xA0
|
||||
atomic_t<u32> wklMskA; // 0xB0 - System service - Available workloads (32*u1)
|
||||
atomic_t<u32> wklMskB; // 0xB4 - System service - Available module id
|
||||
u8 xB8[5]; // 0xB8 - 0xBC - Syetem service exit barrier
|
||||
atomic_t<u8> xBD; // 0xBD - System service message - update workload
|
||||
u8 xBE[2]; // 0xBE - 0xBF - System service message - terminate
|
||||
atomic_t<u8> sysSrvMsgUpdateWorkload; // 0xBD
|
||||
u8 xBE[2]; // 0xBE
|
||||
u8 sysSrvMsgTerminate; // 0xBF
|
||||
u8 xC0[8]; // 0xC0 - System workload
|
||||
u8 xC8; // 0xC8 - System service - on spu
|
||||
u8 sysSrvOnSpu; // 0xC8
|
||||
u8 spuPort; // 0xC9 - SPU port for system service
|
||||
u8 xCA; // 0xCA
|
||||
u8 xCB; // 0xCB
|
||||
u8 xCC; // 0xCC
|
||||
u8 xCD; // 0xCD
|
||||
u8 xCE; // 0xCE - System service message - update trace
|
||||
u8 sysSrvMsgUpdateTrace; // 0xCE
|
||||
u8 xCF; // 0xCF
|
||||
atomic_t<u8> wklStat2[0x10]; // 0xD0 - Workload state (16*u8)
|
||||
u8 wklD2[0x10]; // 0xE0 - Workload status (16*u8)
|
||||
u8 wklE2[0x10]; // 0xF0 - Workload event (16*u8)
|
||||
atomic_t<u8> wklState2[0x10]; // 0xD0 SPURS_WKL_STATE_*
|
||||
u8 wklStatus2[0x10]; // 0xE0
|
||||
u8 wklEvent2[0x10]; // 0xF0
|
||||
_sub_str1 wklF1[0x10]; // 0x100
|
||||
be_t<u64> unk22; // 0x900 - SPURS trace buffer
|
||||
u8 unknown7[0x980 - 0x908]; // 0x908 - Per SPU trace info ??? (8*u32) 0x950 - SPURS trace mode (u32)
|
||||
be_t<u64> traceBuffer; // 0x900
|
||||
be_t<u32> x908[6]; // 0x908 - Indices to traceData (a guess)
|
||||
u8 unknown7[0x948 - 0x920]; // 0x920
|
||||
be_t<u64> traceDataSize; // 0x948
|
||||
be_t<u32> traceMode; // 0x950
|
||||
u8 unknown8[0x980 - 0x954]; // 0x954
|
||||
be_t<u64> semPrv; // 0x980
|
||||
be_t<u32> unk11; // 0x988
|
||||
be_t<u32> unk12; // 0x98C
|
||||
|
@ -371,15 +404,15 @@ struct CellSpurs
|
|||
} c;
|
||||
};
|
||||
|
||||
__forceinline atomic_t<u8>& wklStat(const u32 wid)
|
||||
__forceinline atomic_t<u8>& wklState(const u32 wid)
|
||||
{
|
||||
if (wid & 0x10)
|
||||
{
|
||||
return m.wklStat2[wid & 0xf];
|
||||
return m.wklState2[wid & 0xf];
|
||||
}
|
||||
else
|
||||
{
|
||||
return m.wklStat1[wid & 0xf];
|
||||
return m.wklState1[wid & 0xf];
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -526,25 +559,21 @@ struct CellSpursExceptionInfo
|
|||
|
||||
struct CellSpursTraceInfo
|
||||
{
|
||||
be_t<u32> spu_thread[8];
|
||||
be_t<u32> count[8];
|
||||
be_t<u32> spu_thread_grp;
|
||||
be_t<u32> nspu;
|
||||
//u8 padding[];
|
||||
};
|
||||
static const u32 size = 0x80;
|
||||
static const u32 align = 16;
|
||||
|
||||
struct CellTraceHeader
|
||||
{
|
||||
u8 tag;
|
||||
u8 length;
|
||||
u8 cpu;
|
||||
u8 thread;
|
||||
be_t<u32> time;
|
||||
be_t<u32> spu_thread[8]; // 0x00
|
||||
be_t<u32> count[8]; // 0x20
|
||||
be_t<u32> spu_thread_grp; // 0x40
|
||||
be_t<u32> nspu; // 0x44
|
||||
//u8 padding[];
|
||||
};
|
||||
|
||||
struct CellSpursTracePacket
|
||||
{
|
||||
struct header_struct
|
||||
static const u32 size = 16;
|
||||
|
||||
struct
|
||||
{
|
||||
u8 tag;
|
||||
u8 length;
|
||||
|
@ -553,23 +582,29 @@ struct CellSpursTracePacket
|
|||
be_t<u32> time;
|
||||
} header;
|
||||
|
||||
struct data_struct
|
||||
union
|
||||
{
|
||||
struct load_struct
|
||||
struct
|
||||
{
|
||||
be_t<u32> incident;
|
||||
be_t<u32> reserved;
|
||||
} service;
|
||||
|
||||
struct
|
||||
{
|
||||
be_t<u32> ea;
|
||||
be_t<u16> ls;
|
||||
be_t<u16> size;
|
||||
} load;
|
||||
|
||||
struct map_struct
|
||||
struct
|
||||
{
|
||||
be_t<u32> offset;
|
||||
be_t<u16> ls;
|
||||
be_t<u16> size;
|
||||
} map;
|
||||
|
||||
struct start_struct
|
||||
struct
|
||||
{
|
||||
s8 module[4];
|
||||
be_t<u16> level;
|
||||
|
@ -578,6 +613,7 @@ struct CellSpursTracePacket
|
|||
|
||||
be_t<u64> user;
|
||||
be_t<u64> guid;
|
||||
be_t<u64> stop;
|
||||
} data;
|
||||
};
|
||||
|
||||
|
@ -771,12 +807,15 @@ struct SpursKernelMgmtData {
|
|||
be_t<u32> selectWorkloadAddr; // 0x1E4
|
||||
u8 x1E8; // 0x1E8
|
||||
u8 x1E9; // 0x1E9
|
||||
u8 x1EA; // 0x1EA
|
||||
u8 x1EB; // 0x1EB - This might be spuIdling
|
||||
be_t<u16> x1EC; // 0x1EC - This might be wklEnable1
|
||||
be_t<u16> x1EE; // 0x1EE - This might be wklEnable2
|
||||
u8 x1F0[0x220 - 0x1F0]; // 0x1F0
|
||||
u8 wklUniqueId[0x10]; // 0x220
|
||||
u8 sysSrvInitialised; // 0x1EA
|
||||
u8 spuIdling; // 0x1EB
|
||||
be_t<u16> wklRunnable1; // 0x1EC
|
||||
be_t<u16> wklRunnable2; // 0x1EE
|
||||
u8 x1F0[0x210 - 0x1F0]; // 0x1F0
|
||||
be_t<u64> traceBuffer; // 0x210
|
||||
be_t<u32> traceMsgCount; // 0x218
|
||||
be_t<u32> traceMaxCount; // 0x21C
|
||||
u8 wklUniqueId[0x10]; // 0x220
|
||||
};
|
||||
|
||||
s64 spursAttachLv2EventQueue(vm::ptr<CellSpurs> spurs, u32 queue, vm::ptr<u8> port, s32 isDynamic, bool wasCreated);
|
||||
|
|
220
rpcs3/cellSpursSpu.cpp
Normal file
220
rpcs3/cellSpursSpu.cpp
Normal file
|
@ -0,0 +1,220 @@
|
|||
#include "stdafx.h"
|
||||
#include "Emu/Memory/Memory.h"
|
||||
#include "Emu/System.h"
|
||||
#include "Emu/Cell/SPUThread.h"
|
||||
#include "Emu/SysCalls/Modules/cellSpurs.h"
|
||||
|
||||
/// Output trace information
|
||||
void cellSpursModulePutTrace(CellSpursTracePacket * packet, unsigned tag) {
|
||||
// TODO: Implement this
|
||||
}
|
||||
|
||||
/// Check for execution right requests
|
||||
unsigned cellSpursModulePollStatus(CellSpursModulePollStatus * status) {
|
||||
// TODO: Implement this
|
||||
return 0;
|
||||
}
|
||||
|
||||
void spursSysServiceCleanup(SPUThread & spu, SpursKernelMgmtData * mgmt) {
|
||||
// TODO: Implement this
|
||||
}
|
||||
|
||||
void spursSysServiceUpdateTrace(SPUThread & spu, SpursKernelMgmtData * mgmt, u32 arg2, u32 arg3, u32 arg4) {
|
||||
// TODO: Implement this
|
||||
}
|
||||
|
||||
void spursSysServiceUpdateEvent(SPUThread & spu, SpursKernelMgmtData * mgmt, u32 wklShutdownMask) {
|
||||
u32 wklNotifyMask = 0;
|
||||
for (u32 i = 0; i < CELL_SPURS_MAX_WORKLOAD; i++) {
|
||||
if (wklShutdownMask & (0x80000000 >> i)) {
|
||||
mgmt->spurs->m.wklEvent1[i] |= 0x01;
|
||||
if (mgmt->spurs->m.wklEvent1[i] & 0x02 || mgmt->spurs->m.wklEvent1[i] & 0x10) {
|
||||
wklNotifyMask |= 0x80000000 >> i;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (u32 i = 0; i < CELL_SPURS_MAX_WORKLOAD; i++) {
|
||||
if (wklShutdownMask & (0x8000 >> i)) {
|
||||
mgmt->spurs->m.wklEvent2[i] |= 0x01;
|
||||
if (mgmt->spurs->m.wklEvent2[i] & 0x02 || mgmt->spurs->m.wklEvent2[i] & 0x10) {
|
||||
wklNotifyMask |= 0x8000 >> i;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (wklNotifyMask) {
|
||||
// TODO: sys_spu_thread_send_event(mgmt->spurs->m.spuPort, 0, wklNotifyMask);
|
||||
}
|
||||
}
|
||||
|
||||
/// Update workload information in the LS from main memory
|
||||
void spursSysServiceUpdateWorkload(SPUThread & spu, SpursKernelMgmtData * mgmt) {
|
||||
u32 wklShutdownMask = 0;
|
||||
mgmt->wklRunnable1 = 0;
|
||||
for (u32 i = 0; i < CELL_SPURS_MAX_WORKLOAD; i++) {
|
||||
mgmt->priority[i] = mgmt->spurs->m.wklInfo1[i].priority[mgmt->spuNum] == 0 ? 0 : 0x10 - mgmt->spurs->m.wklInfo1[i].priority[mgmt->spuNum];
|
||||
mgmt->wklUniqueId[i] = mgmt->spurs->m.wklInfo1[i].uniqueId.read_relaxed();
|
||||
|
||||
auto wklStatus = mgmt->spurs->m.wklStatus1[i];
|
||||
if (mgmt->spurs->m.wklState1[i].read_relaxed() == SPURS_WKL_STATE_RUNNABLE) {
|
||||
mgmt->spurs->m.wklStatus1[i] |= 1 << mgmt->spuNum;
|
||||
mgmt->wklRunnable1 |= 0x8000 >> i;
|
||||
} else {
|
||||
mgmt->spurs->m.wklStatus1[i] &= ~(1 << mgmt->spuNum);
|
||||
}
|
||||
|
||||
if (mgmt->spurs->m.wklState1[i].read_relaxed() == SPURS_WKL_STATE_SHUTTING_DOWN) {
|
||||
if (((wklStatus & (1 << mgmt->spuNum)) != 0) && ((mgmt->spurs->m.wklStatus1[i] & (1 << mgmt->spuNum)) == 0)) {
|
||||
mgmt->spurs->m.wklState1[i].write_relaxed(SPURS_WKL_STATE_REMOVABLE);
|
||||
wklShutdownMask |= 0x80000000 >> i;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (mgmt->spurs->m.flags1 & SF1_32_WORKLOADS) {
|
||||
mgmt->wklRunnable2 = 0;
|
||||
for (u32 i = 0; i < CELL_SPURS_MAX_WORKLOAD; i++) {
|
||||
if (mgmt->spurs->m.wklInfo2[i].priority[mgmt->spuNum]) {
|
||||
mgmt->priority[i] |= (0x10 - mgmt->spurs->m.wklInfo2[i].priority[mgmt->spuNum]) << 4;
|
||||
}
|
||||
|
||||
auto wklStatus = mgmt->spurs->m.wklStatus2[i];
|
||||
if (mgmt->spurs->m.wklState2[i].read_relaxed() == SPURS_WKL_STATE_RUNNABLE) {
|
||||
mgmt->spurs->m.wklStatus2[i] |= 1 << mgmt->spuNum;
|
||||
mgmt->wklRunnable2 |= 0x8000 >> i;
|
||||
} else {
|
||||
mgmt->spurs->m.wklStatus2[i] &= ~(1 << mgmt->spuNum);
|
||||
}
|
||||
|
||||
if (mgmt->spurs->m.wklState2[i].read_relaxed() == SPURS_WKL_STATE_SHUTTING_DOWN) {
|
||||
if (((wklStatus & (1 << mgmt->spuNum)) != 0) && ((mgmt->spurs->m.wklStatus2[i] & (1 << mgmt->spuNum)) == 0)) {
|
||||
mgmt->spurs->m.wklState2[i].write_relaxed(SPURS_WKL_STATE_REMOVABLE);
|
||||
wklShutdownMask |= 0x8000 >> i;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (wklShutdownMask) {
|
||||
spursSysServiceUpdateEvent(spu, mgmt, wklShutdownMask);
|
||||
}
|
||||
}
|
||||
|
||||
/// Process any messages
|
||||
void spursSysServiceProcessMessages(SPUThread & spu, SpursKernelMgmtData * mgmt) {
|
||||
if (mgmt->spurs->m.sysSrvMsgUpdateWorkload.read_relaxed() & (1 << mgmt->spuNum)) {
|
||||
mgmt->spurs->m.sysSrvMsgUpdateWorkload &= ~(1 << mgmt->spuNum);
|
||||
spursSysServiceUpdateWorkload(spu, mgmt);
|
||||
}
|
||||
|
||||
if (mgmt->spurs->m.sysSrvMsgUpdateTrace & (1 << mgmt->spuNum)) {
|
||||
spursSysServiceUpdateTrace(spu, mgmt, 1, 0, 0);
|
||||
}
|
||||
|
||||
if (mgmt->spurs->m.sysSrvMsgTerminate & (1 << mgmt->spuNum)) {
|
||||
mgmt->spurs->m.sysSrvOnSpu &= ~(1 << mgmt->spuNum);
|
||||
// TODO: Rest of the terminate processing
|
||||
}
|
||||
}
|
||||
|
||||
void spursSysServiceExitIfRequired() {
|
||||
// TODO: Implement this
|
||||
}
|
||||
|
||||
/// Main function for the system service workload
|
||||
void spursSysServiceWorkloadMain(SPUThread & spu, u32 pollStatus) {
|
||||
auto mgmt = vm::get_ptr<SpursKernelMgmtData>(spu.ls_offset);
|
||||
|
||||
if (mgmt->spurs.addr() % CellSpurs::align) {
|
||||
// TODO: Halt
|
||||
}
|
||||
|
||||
// Initialise the system service if this is the first time its being started on this SPU
|
||||
if (mgmt->sysSrvInitialised != 0) {
|
||||
mgmt->sysSrvInitialised = 1;
|
||||
|
||||
if (mgmt->spurs->m.sysSrvOnSpu & (1 << mgmt->spuNum)) {
|
||||
// TODO: Halt
|
||||
}
|
||||
|
||||
mgmt->spurs->m.sysSrvOnSpu |= 1 << mgmt->spuNum;
|
||||
mgmt->traceBuffer = 0;
|
||||
mgmt->traceMsgCount = -1;
|
||||
|
||||
spursSysServiceUpdateTrace(spu, mgmt, 1, 1, 0);
|
||||
spursSysServiceCleanup(spu, mgmt);
|
||||
|
||||
// Trace - SERVICE: INIT
|
||||
CellSpursTracePacket pkt;
|
||||
memset(&pkt, 0, sizeof(pkt));
|
||||
pkt.header.tag = CELL_SPURS_TRACE_TAG_SERVICE;
|
||||
pkt.data.service.incident = CELL_SPURS_TRACE_SERVICE_INIT;
|
||||
cellSpursModulePutTrace(&pkt, mgmt->dmaTagId);
|
||||
}
|
||||
|
||||
// Trace - START: Module='SYS '
|
||||
CellSpursTracePacket pkt;
|
||||
memset(&pkt, 0, sizeof(pkt));
|
||||
pkt.header.tag = CELL_SPURS_TRACE_TAG_START;
|
||||
memcpy(pkt.data.start.module, "SYS ", 4);
|
||||
pkt.data.start.level = 1; // Policy module
|
||||
pkt.data.start.ls = 0xA00 >> 2;
|
||||
cellSpursModulePutTrace(&pkt, mgmt->dmaTagId);
|
||||
|
||||
while (true) {
|
||||
spursSysServiceProcessMessages(spu, mgmt);
|
||||
|
||||
if (cellSpursModulePollStatus(nullptr)) {
|
||||
// Trace - SERVICE: EXIT
|
||||
CellSpursTracePacket pkt;
|
||||
memset(&pkt, 0, sizeof(pkt));
|
||||
pkt.header.tag = CELL_SPURS_TRACE_TAG_SERVICE;
|
||||
pkt.data.service.incident = CELL_SPURS_TRACE_SERVICE_EXIT;
|
||||
cellSpursModulePutTrace(&pkt, mgmt->dmaTagId);
|
||||
|
||||
// Trace - STOP: GUID
|
||||
memset(&pkt, 0, sizeof(pkt));
|
||||
pkt.header.tag = CELL_SPURS_TRACE_TAG_STOP;
|
||||
pkt.data.stop = 0; // TODO: Put GUID of the sys service workload here
|
||||
cellSpursModulePutTrace(&pkt, mgmt->dmaTagId);
|
||||
break;
|
||||
}
|
||||
|
||||
if (mgmt->spuIdling == 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Trace - SERVICE: WAIT
|
||||
CellSpursTracePacket pkt;
|
||||
memset(&pkt, 0, sizeof(pkt));
|
||||
pkt.header.tag = CELL_SPURS_TRACE_TAG_SERVICE;
|
||||
pkt.data.service.incident = CELL_SPURS_TRACE_SERVICE_WAIT;
|
||||
cellSpursModulePutTrace(&pkt, mgmt->dmaTagId);
|
||||
|
||||
spursSysServiceExitIfRequired();
|
||||
}
|
||||
}
|
||||
|
||||
/// Entry point of the system service workload
|
||||
void spursSysServiceWorkloadEntry(SPUThread & spu) {
|
||||
auto mgmt = 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];
|
||||
|
||||
spu.GPR[1]._u32[3] = 0x3FFD0;
|
||||
*(vm::ptr<u32>::make(spu.GPR[1]._u32[3])) = 0x3FFF0;
|
||||
memset(vm::get_ptr<void>(spu.ls_offset + 0x3FFE0), 0, 32);
|
||||
|
||||
LV2_LOCK(0);
|
||||
|
||||
if (mgmt->wklCurrentId == CELL_SPURS_SYS_SERVICE_WORKLOAD_ID) {
|
||||
spursSysServiceWorkloadMain(spu, pollStatus);
|
||||
} else {
|
||||
// TODO: If we reach here it means the current workload was preempted to start the
|
||||
// system service workload. Need to implement this.
|
||||
}
|
||||
|
||||
// TODO: Ensure that this function always returns to the SPURS kernel
|
||||
return;
|
||||
}
|
|
@ -54,6 +54,7 @@
|
|||
<ClCompile Include="..\Utilities\SSemaphore.cpp" />
|
||||
<ClCompile Include="..\Utilities\StrFmt.cpp" />
|
||||
<ClCompile Include="..\Utilities\Thread.cpp" />
|
||||
<ClCompile Include="cellSpursSpu.cpp" />
|
||||
<ClCompile Include="Crypto\aes.cpp" />
|
||||
<ClCompile Include="Crypto\ec.cpp" />
|
||||
<ClCompile Include="Crypto\key_vault.cpp" />
|
||||
|
|
|
@ -653,6 +653,9 @@
|
|||
<ClCompile Include="Emu\ARMv7\Modules\sceLibm.cpp">
|
||||
<Filter>Emu\CPU\ARMv7\Modules</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="cellSpursSpu.cpp">
|
||||
<Filter>Emu\SysCalls\Modules</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="Crypto\aes.h">
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue