SPURS: Implement some portions of spurs initialization

Conflicts:
	rpcs3/Emu/SysCalls/Modules/cellSpurs.cpp
	rpcs3/Emu/SysCalls/Modules/cellSpurs.h
	rpcs3/Emu/SysCalls/Modules/cellSpursSpu.cpp
	rpcs3/Emu/SysCalls/lv2/sys_event.cpp
	rpcs3/Emu/SysCalls/lv2/sys_event.h
	rpcs3/Emu/SysCalls/lv2/sys_lwmutex.cpp
	rpcs3/Emu/SysCalls/lv2/sys_lwmutex.h
	rpcs3/Emu/SysCalls/lv2/sys_semaphore.cpp
	rpcs3/Emu/SysCalls/lv2/sys_semaphore.h
	rpcs3/Emu/SysCalls/lv2/sys_spu.cpp
	rpcs3/Emu/SysCalls/lv2/sys_spu.h
This commit is contained in:
S Gopal Rajagopal 2015-02-22 02:24:53 +05:30 committed by Nekotekina
parent 5b7f701878
commit 46e4f2d48c
13 changed files with 1408 additions and 738 deletions

File diff suppressed because it is too large Load diff

View file

@ -102,9 +102,6 @@ enum SPURSKernelInterfaces
CELL_SPURS_NAME_MAX_LENGTH = 15, CELL_SPURS_NAME_MAX_LENGTH = 15,
CELL_SPURS_SIZE = 4096, CELL_SPURS_SIZE = 4096,
CELL_SPURS_SIZE2 = 8192, CELL_SPURS_SIZE2 = 8192,
CELL_SPURS_ALIGN = 128,
CELL_SPURS_ATTRIBUTE_SIZE = 512,
CELL_SPURS_ATTRIBUTE_ALIGN = 8,
CELL_SPURS_INTERRUPT_VECTOR = 0x0, CELL_SPURS_INTERRUPT_VECTOR = 0x0,
CELL_SPURS_LOCK_LINE = 0x80, CELL_SPURS_LOCK_LINE = 0x80,
CELL_SPURS_KERNEL_DMA_TAG_ID = 31, CELL_SPURS_KERNEL_DMA_TAG_ID = 31,
@ -125,12 +122,10 @@ enum RangeofEventQueuePortNumbers
enum SpursAttrFlags : u32 enum SpursAttrFlags : u32
{ {
SAF_NONE = 0x0, SAF_NONE = 0x00000000,
SAF_EXIT_IF_NO_WORK = 0x00000001,
SAF_EXIT_IF_NO_WORK = 0x1, SAF_UNKNOWN_FLAG_30 = 0x00000002,
SAF_UNKNOWN_FLAG_30 = 0x2, SAF_SECOND_VERSION = 0x00000004,
SAF_SECOND_VERSION = 0x4,
SAF_UNKNOWN_FLAG_9 = 0x00400000, SAF_UNKNOWN_FLAG_9 = 0x00400000,
SAF_UNKNOWN_FLAG_8 = 0x00800000, SAF_UNKNOWN_FLAG_8 = 0x00800000,
SAF_UNKNOWN_FLAG_7 = 0x01000000, SAF_UNKNOWN_FLAG_7 = 0x01000000,
@ -143,8 +138,7 @@ enum SpursAttrFlags : u32
enum SpursFlags1 : u8 enum SpursFlags1 : u8
{ {
SF1_NONE = 0x0, SF1_NONE = 0x00,
SF1_32_WORKLOADS = 0x40, SF1_32_WORKLOADS = 0x40,
SF1_EXIT_IF_NO_WORK = 0x80, SF1_EXIT_IF_NO_WORK = 0x80,
}; };
@ -416,9 +410,10 @@ struct set_alignment(128) CellSpurs
{ {
struct _sub_str1 struct _sub_str1
{ {
u8 unk0[0x20]; // 0x00 - SPU exceptionh handler 0x08 - SPU exception handler args u8 unk0[0x20]; // 0x00 - SPU exception handler 0x08 - SPU exception handler args
be_t<u64> sem; // 0x20 be_t<u64> sem; // 0x20
u8 unk1[0x8]; be_t<u32> x28; // 0x28
be_t<u32> x2C; // 0x2C
vm::bptr<CellSpursShutdownCompletionEventHook, u64> hook; // 0x30 vm::bptr<CellSpursShutdownCompletionEventHook, u64> hook; // 0x30
vm::bptr<void, u64> hookArg; // 0x38 vm::bptr<void, u64> hookArg; // 0x38
u8 unk2[0x40]; u8 unk2[0x40];
@ -426,26 +421,38 @@ struct set_alignment(128) CellSpurs
CHECK_SIZE(_sub_str1, 128); CHECK_SIZE(_sub_str1, 128);
struct _sub_str2 // Event port multiplexer struct EventPortMux;
using EventHandlerCallback = func_def<void(vm::ptr<EventPortMux>, u64 data)>;
struct EventHandlerListNode
{ {
be_t<u32> unk0; // 0x00 Outstanding requests vm::bptr<EventHandlerListNode, u64> next;
be_t<u32> unk1; // 0x04 be_t<u64> data;
be_t<u32> unk2; // 0x08 vm::bptr<EventHandlerCallback, u64> handler;
be_t<u32> unk3; // 0x0C
be_t<u64> port; // 0x10
u8 unk_[0x68]; // 0x18 - The first u64 seems to be the start of a linked list. The linked list struct seems to be {u64 next; u64 data; u64 handler}
}; };
CHECK_SIZE(_sub_str2, 128); struct EventPortMux
{
atomic_be_t<u32> reqPending; // 0x00
be_t<u32> spuPort; // 0x04
be_t<u32> x08; // 0x08
be_t<u32> x0C; // 0x0C
be_t<u64> eventPort; // 0x10
atomic_be_t<vm::ptr<EventHandlerListNode, u64>> handlerList; // 0x18
u8 x20[0x80 - 0x20]; // 0x20
};
CHECK_SIZE(EventPortMux, 128);
struct WorkloadInfo struct WorkloadInfo
{ {
vm::bcptr<void, u64> addr; // Address of the executable vm::bcptr<void, u64> addr; // 0x00 Address of the executable
be_t<u64> arg; // spu argument be_t<u64> arg; // 0x08 Argument
be_t<u32> size; be_t<u32> size; // 0x10 Size of the executable
atomic_be_t<u8> uniqueId; // The unique id is the same for all workloads with the same addr atomic_be_t<u8> uniqueId; // 0x14 Unique id of the workload. It is the same for all workloads with the same addr.
u8 pad[3]; u8 pad[3];
u8 priority[8]; u8 priority[8]; // 0x18 Priority of the workload on each SPU
}; };
CHECK_SIZE(WorkloadInfo, 32); CHECK_SIZE(WorkloadInfo, 32);
@ -463,26 +470,26 @@ struct set_alignment(128) CellSpurs
u8 wklMinContention[0x10]; // 0x40 Min SPUs required for each workload. SPURS1: index = wid. SPURS2: Unused. u8 wklMinContention[0x10]; // 0x40 Min SPUs required for each workload. SPURS1: index = wid. SPURS2: Unused.
atomic_be_t<u8> wklMaxContention[0x10]; // 0x50 Max SPUs that may be allocated to each workload. SPURS1: index = wid. SPURS2: packed 4-bit data, index = wid % 16, internal index = wid / 16. atomic_be_t<u8> wklMaxContention[0x10]; // 0x50 Max SPUs that may be allocated to each workload. SPURS1: index = wid. SPURS2: packed 4-bit data, index = wid % 16, internal index = wid / 16.
CellSpursWorkloadFlag wklFlag; // 0x60 CellSpursWorkloadFlag wklFlag; // 0x60
atomic_be_t<u16> wklSignal1; // 0x70 (bitset for 0..15 wids) atomic_be_t<u16> wklSignal1; // 0x70 Bitset for 0..15 wids
atomic_be_t<u8> sysSrvMessage; // 0x72 atomic_be_t<u8> sysSrvMessage; // 0x72
u8 spuIdling; // 0x73 u8 spuIdling; // 0x73
u8 flags1; // 0x74 Type is SpursFlags1 u8 flags1; // 0x74 Type is SpursFlags1
u8 sysSrvTraceControl; // 0x75 u8 sysSrvTraceControl; // 0x75
u8 nSpus; // 0x76 u8 nSpus; // 0x76
atomic_be_t<u8> wklFlagReceiver; // 0x77 atomic_be_t<u8> wklFlagReceiver; // 0x77
atomic_be_t<u16> wklSignal2; // 0x78 (bitset for 16..32 wids) atomic_be_t<u16> wklSignal2; // 0x78 Bitset for 16..32 wids
u8 x7A[6]; // 0x7A u8 x7A[6]; // 0x7A
atomic_be_t<u8> wklState1[0x10]; // 0x80 SPURS_WKL_STATE_* atomic_be_t<u8> wklState1[0x10]; // 0x80 SPURS_WKL_STATE_*
u8 wklStatus1[0x10]; // 0x90 u8 wklStatus1[0x10]; // 0x90
u8 wklEvent1[0x10]; // 0xA0 atomic_be_t<u8> wklEvent1[0x10]; // 0xA0
atomic_be_t<u32> wklMskA; // 0xB0 - System service - Available workloads (32*u1) atomic_be_t<u32> wklEnabled; // 0xB0
atomic_be_t<u32> wklMskB; // 0xB4 - System service - Available module id atomic_be_t<u32> wklMskB; // 0xB4 - System service - Available module id
u32 xB8; // 0xB8 u32 xB8; // 0xB8
u8 sysSrvExitBarrier; // 0xBC u8 sysSrvExitBarrier; // 0xBC
atomic_be_t<u8> sysSrvMsgUpdateWorkload; // 0xBD atomic_be_t<u8> sysSrvMsgUpdateWorkload; // 0xBD
u8 xBE; // 0xBE u8 xBE; // 0xBE
u8 sysSrvMsgTerminate; // 0xBF u8 sysSrvMsgTerminate; // 0xBF
u8 sysSrvWorkload[8]; // 0xC0 u8 sysSrvPreemptWklId[8]; // 0xC0 Id of the workload that was preempted by the system workload on each SPU
u8 sysSrvOnSpu; // 0xC8 u8 sysSrvOnSpu; // 0xC8
u8 spuPort; // 0xC9 u8 spuPort; // 0xC9
u8 xCA; // 0xCA u8 xCA; // 0xCA
@ -493,7 +500,7 @@ struct set_alignment(128) CellSpurs
u8 xCF; // 0xCF u8 xCF; // 0xCF
atomic_be_t<u8> wklState2[0x10]; // 0xD0 SPURS_WKL_STATE_* atomic_be_t<u8> wklState2[0x10]; // 0xD0 SPURS_WKL_STATE_*
u8 wklStatus2[0x10]; // 0xE0 u8 wklStatus2[0x10]; // 0xE0
u8 wklEvent2[0x10]; // 0xF0 atomic_be_t<u8> wklEvent2[0x10]; // 0xF0
_sub_str1 wklF1[0x10]; // 0x100 _sub_str1 wklF1[0x10]; // 0x100
vm::bptr<CellSpursTraceInfo, u64> traceBuffer; // 0x900 vm::bptr<CellSpursTraceInfo, u64> traceBuffer; // 0x900
be_t<u32> traceStartIndex[6]; // 0x908 be_t<u32> traceStartIndex[6]; // 0x908
@ -508,16 +515,16 @@ struct set_alignment(128) CellSpurs
u8 unknown4[0xB00 - 0x998]; u8 unknown4[0xB00 - 0x998];
WorkloadInfo wklInfo1[0x10]; // 0xB00 WorkloadInfo wklInfo1[0x10]; // 0xB00
WorkloadInfo wklInfoSysSrv; // 0xD00 WorkloadInfo wklInfoSysSrv; // 0xD00
be_t<u64> ppu0; // 0xD20 be_t<u64> ppu0; // 0xD20 Handler thread
be_t<u64> ppu1; // 0xD28 be_t<u64> ppu1; // 0xD28
be_t<u32> spuTG; // 0xD30 - SPU thread group be_t<u32> spuTG; // 0xD30 SPU thread group
be_t<u32> spus[8]; // 0xD34 be_t<u32> spus[8]; // 0xD34
u8 unknown3[0xD5C - 0xD54]; u8 unknown3[0xD5C - 0xD54];
be_t<u32> queue; // 0xD5C - Event queue be_t<u32> eventQueue; // 0xD5C
be_t<u32> port; // 0xD60 - Event port be_t<u32> eventPort; // 0xD60
atomic_be_t<u8> xD64; // 0xD64 - SPURS handler dirty atomic_be_t<u8> handlerDirty; // 0xD64
atomic_be_t<u8> xD65; // 0xD65 - SPURS handler waiting atomic_be_t<u8> handlerWaiting; // 0xD65
atomic_be_t<u8> xD66; // 0xD66 - SPURS handler exiting atomic_be_t<u8> handlerExiting; // 0xD66
atomic_be_t<u32> enableEH; // 0xD68 atomic_be_t<u32> enableEH; // 0xD68
be_t<u32> exception; // 0xD6C be_t<u32> exception; // 0xD6C
sys_spu_image spuImg; // 0xD70 sys_spu_image spuImg; // 0xD70
@ -529,12 +536,12 @@ struct set_alignment(128) CellSpurs
be_t<u32> unk5; // 0xD9C be_t<u32> unk5; // 0xD9C
be_t<u32> revision; // 0xDA0 be_t<u32> revision; // 0xDA0
be_t<u32> sdkVersion; // 0xDA4 be_t<u32> sdkVersion; // 0xDA4
atomic_be_t<u64> spups; // 0xDA8 - SPU port bits atomic_be_t<u64> spuPortBits; // 0xDA8
sys_lwmutex_t mutex; // 0xDB0 sys_lwmutex_t mutex; // 0xDB0
sys_lwcond_t cond; // 0xDC8 sys_lwcond_t cond; // 0xDC8
u8 unknown9[0xE00 - 0xDD0]; u8 unknown9[0xE00 - 0xDD0];
_sub_str4 wklH1[0x10]; // 0xE00 _sub_str4 wklH1[0x10]; // 0xE00
_sub_str2 sub3; // 0xF00 EventPortMux eventPortMux; // 0xF00
u8 unknown6[0x1000 - 0xF80]; // 0xF80 - Gloabl SPU exception handler 0xF88 - Gloabl SPU exception handlers args u8 unknown6[0x1000 - 0xF80]; // 0xF80 - Gloabl SPU exception handler 0xF88 - Gloabl SPU exception handlers args
WorkloadInfo wklInfo2[0x10]; // 0x1000 WorkloadInfo wklInfo2[0x10]; // 0x1000
_sub_str1 wklF2[0x10]; // 0x1200 _sub_str1 wklF2[0x10]; // 0x1200
@ -552,16 +559,6 @@ struct set_alignment(128) CellSpurs
return wklState1[wid & 0xf]; return wklState1[wid & 0xf];
} }
} }
force_inline vm::ptr<sys_lwmutex_t> get_lwmutex()
{
return vm::ptr<sys_lwmutex_t>::make(vm::get_addr(&mutex));
}
force_inline vm::ptr<sys_lwcond_t> get_lwcond()
{
return vm::ptr<sys_lwcond_t>::make(vm::get_addr(&cond));
}
}; };
CHECK_SIZE_ALIGN(CellSpurs, 0x2000, 128); CHECK_SIZE_ALIGN(CellSpurs, 0x2000, 128);
@ -888,5 +885,6 @@ struct SpursTasksetContext
CHECK_SIZE(SpursTasksetContext, 0x900); CHECK_SIZE(SpursTasksetContext, 0x900);
s32 spursAttachLv2EventQueue(vm::ptr<CellSpurs> spurs, u32 queue, vm::ptr<u8> port, s32 isDynamic, bool wasCreated); class SpursModuleExit
s32 spursWakeUp(PPUThread& CPU, vm::ptr<CellSpurs> spurs); {
};

View file

@ -11,82 +11,75 @@
#include "Loader/ELF32.h" #include "Loader/ELF32.h"
#include "Emu/FS/vfsStreamMemory.h" #include "Emu/FS/vfsStreamMemory.h"
////////////////////////////////////////////////////////////////////////////// //----------------------------------------------------------------------------
// Types
//////////////////////////////////////////////////////////////////////////////
class SpursModuleExit {
};
//////////////////////////////////////////////////////////////////////////////
// Function prototypes
//////////////////////////////////////////////////////////////////////////////
//
// SPURS utility functions
//
void cellSpursModulePutTrace(CellSpursTracePacket * packet, u32 dmaTagId);
u32 cellSpursModulePollStatus(SPUThread & spu, u32 * status);
void cellSpursModuleExit(SPUThread & spu);
bool spursDma(SPUThread & spu, u32 cmd, u64 ea, u32 lsa, u32 size, u32 tag);
u32 spursDmaGetCompletionStatus(SPUThread & spu, u32 tagMask);
u32 spursDmaWaitForCompletion(SPUThread & spu, u32 tagMask, bool waitForAll = true);
void spursHalt(SPUThread & spu);
//
// SPURS Kernel functions
//
bool spursKernel1SelectWorkload(SPUThread & spu);
bool spursKernel2SelectWorkload(SPUThread & spu);
void spursKernelDispatchWorkload(SPUThread & spu, u64 widAndPollStatus);
bool spursKernelWorkloadExit(SPUThread & spu);
bool spursKernelEntry(SPUThread & spu);
//
// SPURS System Service functions
//
bool spursSysServiceEntry(SPUThread & spu);
// TODO: Exit
void spursSysServiceIdleHandler(SPUThread & spu, SpursKernelContext * ctxt);
void spursSysServiceMain(SPUThread & spu, u32 pollStatus);
void spursSysServiceProcessRequests(SPUThread & spu, SpursKernelContext * ctxt);
void spursSysServiceActivateWorkload(SPUThread & spu, SpursKernelContext * ctxt);
// TODO: Deactivate workload
void spursSysServiceUpdateShutdownCompletionEvents(SPUThread & spu, SpursKernelContext * ctxt, u32 wklShutdownBitSet);
void spursSysServiceTraceSaveCount(SPUThread & spu, SpursKernelContext * ctxt);
void spursSysServiceTraceUpdate(SPUThread & spu, SpursKernelContext * ctxt, u32 arg2, u32 arg3, u32 arg4);
// TODO: Deactivate trace
// TODO: System workload entry
void spursSysServiceCleanupAfterSystemWorkload(SPUThread & spu, SpursKernelContext * ctxt);
//
// SPURS Taskset Policy Module functions
//
bool spursTasksetEntry(SPUThread & spu);
bool spursTasksetSyscallEntry(SPUThread & spu);
void spursTasksetResumeTask(SPUThread & spu);
void spursTasksetStartTask(SPUThread & spu, CellSpursTaskArgument & taskArgs);
s32 spursTasksetProcessRequest(SPUThread & spu, s32 request, u32 * taskId, u32 * isWaiting);
void spursTasksetProcessPollStatus(SPUThread & spu, u32 pollStatus);
bool spursTasksetPollStatus(SPUThread & spu);
void spursTasksetExit(SPUThread & spu);
void spursTasksetOnTaskExit(SPUThread & spu, u64 addr, u32 taskId, s32 exitCode, u64 args);
s32 spursTasketSaveTaskContext(SPUThread & spu);
void spursTasksetDispatch(SPUThread & spu);
s32 spursTasksetProcessSyscall(SPUThread & spu, u32 syscallNum, u32 args);
void spursTasksetInit(SPUThread & spu, u32 pollStatus);
s32 spursTasksetLoadElf(SPUThread & spu, u32 * entryPoint, u32 * lowestLoadAddr, u64 elfAddr, bool skipWriteableSegments);
//////////////////////////////////////////////////////////////////////////////
// Externs // Externs
////////////////////////////////////////////////////////////////////////////// //----------------------------------------------------------------------------
extern Module cellSpurs; extern Module cellSpurs;
////////////////////////////////////////////////////////////////////////////// //----------------------------------------------------------------------------
// Function prototypes
//----------------------------------------------------------------------------
//
// SPURS utility functions // SPURS utility functions
////////////////////////////////////////////////////////////////////////////// //
static void cellSpursModulePutTrace(CellSpursTracePacket * packet, u32 dmaTagId);
static u32 cellSpursModulePollStatus(SPUThread & spu, u32 * status);
static void cellSpursModuleExit(SPUThread & spu);
static bool spursDma(SPUThread & spu, u32 cmd, u64 ea, u32 lsa, u32 size, u32 tag);
static u32 spursDmaGetCompletionStatus(SPUThread & spu, u32 tagMask);
static u32 spursDmaWaitForCompletion(SPUThread & spu, u32 tagMask, bool waitForAll = true);
static void spursHalt(SPUThread & spu);
//
// SPURS kernel functions
//
static bool spursKernel1SelectWorkload(SPUThread & spu);
static bool spursKernel2SelectWorkload(SPUThread & spu);
static void spursKernelDispatchWorkload(SPUThread & spu, u64 widAndPollStatus);
static bool spursKernelWorkloadExit(SPUThread & spu);
bool spursKernelEntry(SPUThread & spu);
//
// SPURS system workload functions
//
static bool spursSysServiceEntry(SPUThread & spu);
// TODO: Exit
static void spursSysServiceIdleHandler(SPUThread & spu, SpursKernelContext * ctxt);
static void spursSysServiceMain(SPUThread & spu, u32 pollStatus);
static void spursSysServiceProcessRequests(SPUThread & spu, SpursKernelContext * ctxt);
static void spursSysServiceActivateWorkload(SPUThread & spu, SpursKernelContext * ctxt);
// TODO: Deactivate workload
static void spursSysServiceUpdateShutdownCompletionEvents(SPUThread & spu, SpursKernelContext * ctxt, u32 wklShutdownBitSet);
static void spursSysServiceTraceSaveCount(SPUThread & spu, SpursKernelContext * ctxt);
static void spursSysServiceTraceUpdate(SPUThread & spu, SpursKernelContext * ctxt, u32 arg2, u32 arg3, u32 arg4);
// TODO: Deactivate trace
// TODO: System workload entry
static void spursSysServiceCleanupAfterSystemWorkload(SPUThread & spu, SpursKernelContext * ctxt);
//
// SPURS taskset policy module functions
//
static bool spursTasksetEntry(SPUThread & spu);
static bool spursTasksetSyscallEntry(SPUThread & spu);
static void spursTasksetResumeTask(SPUThread & spu);
static void spursTasksetStartTask(SPUThread & spu, CellSpursTaskArgument & taskArgs);
static s32 spursTasksetProcessRequest(SPUThread & spu, s32 request, u32 * taskId, u32 * isWaiting);
static void spursTasksetProcessPollStatus(SPUThread & spu, u32 pollStatus);
static bool spursTasksetPollStatus(SPUThread & spu);
static void spursTasksetExit(SPUThread & spu);
static void spursTasksetOnTaskExit(SPUThread & spu, u64 addr, u32 taskId, s32 exitCode, u64 args);
static s32 spursTasketSaveTaskContext(SPUThread & spu);
static void spursTasksetDispatch(SPUThread & spu);
static s32 spursTasksetProcessSyscall(SPUThread & spu, u32 syscallNum, u32 args);
static void spursTasksetInit(SPUThread & spu, u32 pollStatus);
static s32 spursTasksetLoadElf(SPUThread & spu, u32 * entryPoint, u32 * lowestLoadAddr, u64 elfAddr, bool skipWriteableSegments);
//----------------------------------------------------------------------------
// SPURS utility functions
//----------------------------------------------------------------------------
/// Output trace information /// Output trace information
void cellSpursModulePutTrace(CellSpursTracePacket * packet, u32 dmaTagId) { void cellSpursModulePutTrace(CellSpursTracePacket * packet, u32 dmaTagId) {
@ -160,9 +153,9 @@ void spursHalt(SPUThread & spu) {
spu.halt(); spu.halt();
} }
////////////////////////////////////////////////////////////////////////////// //----------------------------------------------------------------------------
// SPURS kernel functions // SPURS kernel functions
////////////////////////////////////////////////////////////////////////////// //----------------------------------------------------------------------------
/// Select a workload to run /// Select a workload to run
bool spursKernel1SelectWorkload(SPUThread & spu) { bool spursKernel1SelectWorkload(SPUThread & spu) {
@ -582,9 +575,9 @@ bool spursKernelEntry(SPUThread & spu) {
return false; return false;
} }
////////////////////////////////////////////////////////////////////////////// //----------------------------------------------------------------------------
// SPURS system workload functions // SPURS system workload functions
////////////////////////////////////////////////////////////////////////////// //----------------------------------------------------------------------------
/// Entry point of the system service /// Entry point of the system service
bool spursSysServiceEntry(SPUThread & spu) { bool spursSysServiceEntry(SPUThread & spu) {
@ -931,14 +924,14 @@ void spursSysServiceUpdateShutdownCompletionEvents(SPUThread & spu, SpursKernelC
for (u32 i = 0; i < CELL_SPURS_MAX_WORKLOAD; i++) { for (u32 i = 0; i < CELL_SPURS_MAX_WORKLOAD; i++) {
if (wklShutdownBitSet & (0x80000000u >> i)) { if (wklShutdownBitSet & (0x80000000u >> i)) {
spurs->wklEvent1[i] |= 0x01; spurs->wklEvent1[i] |= 0x01;
if (spurs->wklEvent1[i] & 0x02 || spurs->wklEvent1[i] & 0x10) { if (spurs->wklEvent1[i].read_relaxed() & 0x02 || spurs->wklEvent1[i].read_relaxed() & 0x10) {
wklNotifyBitSet |= 0x80000000u >> i; wklNotifyBitSet |= 0x80000000u >> i;
} }
} }
if (wklShutdownBitSet & (0x8000 >> i)) { if (wklShutdownBitSet & (0x8000 >> i)) {
spurs->wklEvent2[i] |= 0x01; spurs->wklEvent2[i] |= 0x01;
if (spurs->wklEvent2[i] & 0x02 || spurs->wklEvent2[i] & 0x10) { if (spurs->wklEvent2[i].read_relaxed() & 0x02 || spurs->wklEvent2[i].read_relaxed() & 0x10) {
wklNotifyBitSet |= 0x8000 >> i; wklNotifyBitSet |= 0x8000 >> i;
} }
} }
@ -1022,13 +1015,13 @@ void spursSysServiceCleanupAfterSystemWorkload(SPUThread & spu, SpursKernelConte
vm::reservation_op(vm::cast(ctxt->spurs.addr() + offsetof(CellSpurs, wklState1)), 128, [&]() { vm::reservation_op(vm::cast(ctxt->spurs.addr() + offsetof(CellSpurs, wklState1)), 128, [&]() {
auto spurs = ctxt->spurs.priv_ptr(); auto spurs = ctxt->spurs.priv_ptr();
if (spurs->sysSrvWorkload[ctxt->spuNum] == 0xFF) { if (spurs->sysSrvPreemptWklId[ctxt->spuNum] == 0xFF) {
do_return = true; do_return = true;
return; return;
} }
wklId = spurs->sysSrvWorkload[ctxt->spuNum]; wklId = spurs->sysSrvPreemptWklId[ctxt->spuNum];
spurs->sysSrvWorkload[ctxt->spuNum] = 0xFF; spurs->sysSrvPreemptWklId[ctxt->spuNum] = 0xFF;
memcpy(vm::get_ptr(spu.offset + 0x2D80), spurs->wklState1, 128); memcpy(vm::get_ptr(spu.offset + 0x2D80), spurs->wklState1, 128);
}); });
@ -1066,9 +1059,9 @@ void spursSysServiceCleanupAfterSystemWorkload(SPUThread & spu, SpursKernelConte
ctxt->wklCurrentId = wklIdSaved; ctxt->wklCurrentId = wklIdSaved;
} }
////////////////////////////////////////////////////////////////////////////// //----------------------------------------------------------------------------
// SPURS taskset policy module functions // SPURS taskset policy module functions
////////////////////////////////////////////////////////////////////////////// //----------------------------------------------------------------------------
enum SpursTasksetRequest { enum SpursTasksetRequest {
SPURS_TASKSET_REQUEST_POLL_SIGNAL = -1, SPURS_TASKSET_REQUEST_POLL_SIGNAL = -1,

View file

@ -41,3 +41,5 @@ s32 sys_lwcond_signal(PPUThread& CPU, vm::ptr<sys_lwcond_t> lwcond);
s32 sys_lwcond_signal_all(PPUThread& CPU, vm::ptr<sys_lwcond_t> lwcond); s32 sys_lwcond_signal_all(PPUThread& CPU, vm::ptr<sys_lwcond_t> lwcond);
s32 sys_lwcond_signal_to(PPUThread& CPU, vm::ptr<sys_lwcond_t> lwcond, u32 ppu_thread_id); s32 sys_lwcond_signal_to(PPUThread& CPU, vm::ptr<sys_lwcond_t> lwcond, u32 ppu_thread_id);
s32 sys_lwcond_wait(PPUThread& CPU, vm::ptr<sys_lwcond_t> lwcond, u64 timeout); s32 sys_lwcond_wait(PPUThread& CPU, vm::ptr<sys_lwcond_t> lwcond, u64 timeout);
void sys_ppu_thread_exit(PPUThread& CPU, u64 val);

View file

@ -28,6 +28,12 @@ enum
SYS_SYNC_ATTR_RECURSIVE_MASK = 0xF0, //??? SYS_SYNC_ATTR_RECURSIVE_MASK = 0xF0, //???
}; };
// attr_pshared
enum
{
SYS_SYNC_NOT_PROCESS_SHARED = 0x200
};
class sleep_queue_t class sleep_queue_t
{ {
std::vector<u32> m_waiting; std::vector<u32> m_waiting;

View file

@ -13,6 +13,13 @@
SysCallBase sys_event("sys_event"); SysCallBase sys_event("sys_event");
void sys_event_queue_attribute_initialize(vm::ptr<sys_event_queue_attr> attr)
{
attr->protocol = SYS_SYNC_PRIORITY;
attr->type = SYS_PPU_QUEUE;
attr->name[0] = '\0';
}
s32 sys_event_queue_create(vm::ptr<u32> equeue_id, vm::ptr<sys_event_queue_attr> attr, u64 event_queue_key, s32 size) s32 sys_event_queue_create(vm::ptr<u32> equeue_id, vm::ptr<sys_event_queue_attr> attr, u64 event_queue_key, s32 size)
{ {
sys_event.Warning("sys_event_queue_create(equeue_id=*0x%x, attr=*0x%x, event_queue_key=0x%llx, size=%d)", equeue_id, attr, event_queue_key, size); sys_event.Warning("sys_event_queue_create(equeue_id=*0x%x, attr=*0x%x, event_queue_key=0x%llx, size=%d)", equeue_id, attr, event_queue_key, size);

View file

@ -15,12 +15,24 @@ enum : s32
SYS_EVENT_QUEUE_DESTROY_FORCE = 1, SYS_EVENT_QUEUE_DESTROY_FORCE = 1,
}; };
// Event Queue Ipc Key
enum : u64
{
SYS_EVENT_QUEUE_LOCAL = 0x00,
};
// Event Port Type // Event Port Type
enum : s32 enum : s32
{ {
SYS_EVENT_PORT_LOCAL = 1, SYS_EVENT_PORT_LOCAL = 1,
}; };
// Event Port Name
enum : u64
{
SYS_EVENT_PORT_NO_NAME = 0,
};
// Event Source Type // Event Source Type
enum : u32 enum : u32
{ {
@ -31,8 +43,9 @@ enum : u32
// Event Source Key // Event Source Key
enum : u64 enum : u64
{ {
SYS_SPU_THREAD_EVENT_USER_KEY = 0xFFFFFFFF53505501, SYS_SPU_THREAD_EVENT_USER_KEY = 0xFFFFFFFF53505501ull,
SYS_SPU_THREAD_EVENT_DMA_KEY = 0xFFFFFFFF53505502, // ??? SYS_SPU_THREAD_EVENT_DMA_KEY = 0xFFFFFFFF53505502ull,
SYS_SPU_THREAD_EVENT_EXCEPTION_KEY = 0xFFFFFFFF53505503ull,
}; };
struct sys_event_queue_attr struct sys_event_queue_attr
@ -129,6 +142,8 @@ REG_ID_TYPE(lv2_event_port_t, 0x0E); // SYS_EVENT_PORT_OBJECT
class PPUThread; class PPUThread;
void sys_event_queue_attribute_initialize(vm::ptr<sys_event_queue_attr> attr);
// SysCalls // SysCalls
s32 sys_event_queue_create(vm::ptr<u32> equeue_id, vm::ptr<sys_event_queue_attr> attr, u64 event_queue_key, s32 size); s32 sys_event_queue_create(vm::ptr<u32> equeue_id, vm::ptr<sys_event_queue_attr> attr, u64 event_queue_key, s32 size);
s32 sys_event_queue_destroy(u32 equeue_id, s32 mode); s32 sys_event_queue_destroy(u32 equeue_id, s32 mode);

View file

@ -12,6 +12,13 @@
SysCallBase sys_lwmutex("sys_lwmutex"); SysCallBase sys_lwmutex("sys_lwmutex");
void sys_lwmutex_attribute_initialize(vm::ptr<sys_lwmutex_attribute_t> attr)
{
attr->protocol = SYS_SYNC_PRIORITY;
attr->recursive = SYS_SYNC_NOT_RECURSIVE;
attr->name[0] = '\0';
}
void lwmutex_create(sys_lwmutex_t& lwmutex, bool recursive, u32 protocol, u64 name) void lwmutex_create(sys_lwmutex_t& lwmutex, bool recursive, u32 protocol, u64 name)
{ {
lwmutex.lock_var = { { lwmutex::free, lwmutex::zero } }; lwmutex.lock_var = { { lwmutex::free, lwmutex::zero } };

View file

@ -90,9 +90,7 @@ struct lv2_lwmutex_t
REG_ID_TYPE(lv2_lwmutex_t, 0x95); // SYS_LWMUTEX_OBJECT REG_ID_TYPE(lv2_lwmutex_t, 0x95); // SYS_LWMUTEX_OBJECT
// Aux // Aux
void lwmutex_create(sys_lwmutex_t& lwmutex, bool recursive, u32 protocol, u64 name); void sys_lwmutex_attribute_initialize(vm::ptr<sys_lwmutex_attribute_t> attr);
class PPUThread;
// SysCalls // SysCalls
s32 _sys_lwmutex_create(vm::ptr<u32> lwmutex_id, u32 protocol, vm::ptr<sys_lwmutex_t> control, u32 arg4, u64 name, u32 arg6); s32 _sys_lwmutex_create(vm::ptr<u32> lwmutex_id, u32 protocol, vm::ptr<sys_lwmutex_t> control, u32 arg4, u64 name, u32 arg6);

View file

@ -12,6 +12,15 @@
SysCallBase sys_semaphore("sys_semaphore"); SysCallBase sys_semaphore("sys_semaphore");
void sys_semaphore_attribute_initialize(vm::ptr<sys_semaphore_attribute_t> attr)
{
attr->protocol = SYS_SYNC_PRIORITY;
attr->pshared = SYS_SYNC_NOT_PROCESS_SHARED;
attr->ipc_key = 0;
attr->flags = 0;
attr->name[0] = '\0';
}
s32 sys_semaphore_create(vm::ptr<u32> sem, vm::ptr<sys_semaphore_attribute_t> attr, s32 initial_val, s32 max_val) s32 sys_semaphore_create(vm::ptr<u32> sem, vm::ptr<sys_semaphore_attribute_t> attr, s32 initial_val, s32 max_val)
{ {
sys_semaphore.Warning("sys_semaphore_create(sem=*0x%x, attr=*0x%x, initial_val=%d, max_val=%d)", sem, attr, initial_val, max_val); sys_semaphore.Warning("sys_semaphore_create(sem=*0x%x, attr=*0x%x, initial_val=%d, max_val=%d)", sem, attr, initial_val, max_val);

View file

@ -41,6 +41,9 @@ struct lv2_sema_t
REG_ID_TYPE(lv2_sema_t, 0x96); // SYS_SEMAPHORE_OBJECT REG_ID_TYPE(lv2_sema_t, 0x96); // SYS_SEMAPHORE_OBJECT
// Aux
void sys_semaphore_attribute_initialize(vm::ptr<sys_semaphore_attribute_t> attr);
// SysCalls // SysCalls
s32 sys_semaphore_create(vm::ptr<u32> sem, vm::ptr<sys_semaphore_attribute_t> attr, s32 initial_val, s32 max_val); s32 sys_semaphore_create(vm::ptr<u32> sem, vm::ptr<sys_semaphore_attribute_t> attr, s32 initial_val, s32 max_val);
s32 sys_semaphore_destroy(u32 sem); s32 sys_semaphore_destroy(u32 sem);

View file

@ -465,6 +465,13 @@ s32 sys_spu_thread_group_yield(u32 id)
return CELL_OK; return CELL_OK;
} }
void sys_spu_thread_group_attribute_initialize(vm::ptr<sys_spu_thread_group_attribute> attr)
{
attr->name = vm::null;
attr->nsize = 0;
attr->type = SYS_SPU_THREAD_GROUP_TYPE_NORMAL;
}
s32 sys_spu_thread_group_terminate(u32 id, s32 value) s32 sys_spu_thread_group_terminate(u32 id, s32 value)
{ {
sys_spu.Warning("sys_spu_thread_group_terminate(id=0x%x, value=0x%x)", id, value); sys_spu.Warning("sys_spu_thread_group_terminate(id=0x%x, value=0x%x)", id, value);

View file

@ -216,10 +216,12 @@ u32 LoadSpuImage(vfsStream& stream, u32& spu_ep);
s32 spu_image_import(sys_spu_image& img, u32 src, u32 type); s32 spu_image_import(sys_spu_image& img, u32 src, u32 type);
u32 spu_thread_group_create(const std::string& name, u32 num, s32 prio, s32 type, u32 container); u32 spu_thread_group_create(const std::string& name, u32 num, s32 prio, s32 type, u32 container);
u32 spu_thread_initialize(u32 group, u32 spu_num, vm::ptr<sys_spu_image> img, const std::string& name, u32 option, u64 a1, u64 a2, u64 a3, u64 a4, std::function<void(SPUThread&)> task = nullptr); u32 spu_thread_initialize(u32 group, u32 spu_num, vm::ptr<sys_spu_image> img, const std::string& name, u32 option, u64 a1, u64 a2, u64 a3, u64 a4, std::function<void(SPUThread&)> task = nullptr);
void sys_spu_thread_group_attribute_initialize(vm::ptr<sys_spu_thread_group_attribute> attr);
// SysCalls // SysCalls
s32 sys_spu_initialize(u32 max_usable_spu, u32 max_raw_spu); s32 sys_spu_initialize(u32 max_usable_spu, u32 max_raw_spu);
s32 sys_spu_image_open(vm::ptr<sys_spu_image> img, vm::cptr<char> path); s32 sys_spu_image_open(vm::ptr<sys_spu_image> img, vm::cptr<char> path);
s32 sys_spu_image_close(vm::ptr<sys_spu_image> img);
s32 sys_spu_thread_initialize(vm::ptr<u32> thread, u32 group, u32 spu_num, vm::ptr<sys_spu_image> img, vm::ptr<sys_spu_thread_attribute> attr, vm::ptr<sys_spu_thread_argument> arg); s32 sys_spu_thread_initialize(vm::ptr<u32> thread, u32 group, u32 spu_num, vm::ptr<sys_spu_image> img, vm::ptr<sys_spu_thread_attribute> attr, vm::ptr<sys_spu_thread_argument> arg);
s32 sys_spu_thread_set_argument(u32 id, vm::ptr<sys_spu_thread_argument> arg); s32 sys_spu_thread_set_argument(u32 id, vm::ptr<sys_spu_thread_argument> arg);
s32 sys_spu_thread_group_create(vm::ptr<u32> id, u32 num, s32 prio, vm::ptr<sys_spu_thread_group_attribute> attr); s32 sys_spu_thread_group_create(vm::ptr<u32> id, u32 num, s32 prio, vm::ptr<sys_spu_thread_group_attribute> attr);