mirror of
https://github.com/RPCS3/rpcs3.git
synced 2025-07-05 14:31:24 +12:00
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:
parent
5b7f701878
commit
46e4f2d48c
13 changed files with 1408 additions and 738 deletions
File diff suppressed because it is too large
Load diff
|
@ -94,43 +94,38 @@ enum
|
|||
// SPURS defines.
|
||||
enum SPURSKernelInterfaces
|
||||
{
|
||||
CELL_SPURS_MAX_SPU = 8,
|
||||
CELL_SPURS_MAX_WORKLOAD = 16,
|
||||
CELL_SPURS_MAX_WORKLOAD2 = 32,
|
||||
CELL_SPURS_SYS_SERVICE_WORKLOAD_ID = 32,
|
||||
CELL_SPURS_MAX_PRIORITY = 16,
|
||||
CELL_SPURS_NAME_MAX_LENGTH = 15,
|
||||
CELL_SPURS_SIZE = 4096,
|
||||
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_LOCK_LINE = 0x80,
|
||||
CELL_SPURS_KERNEL_DMA_TAG_ID = 31,
|
||||
CELL_SPURS_KERNEL1_ENTRY_ADDR = 0x818,
|
||||
CELL_SPURS_KERNEL2_ENTRY_ADDR = 0x848,
|
||||
CELL_SPURS_KERNEL1_EXIT_ADDR = 0x808,
|
||||
CELL_SPURS_KERNEL2_EXIT_ADDR = 0x838,
|
||||
CELL_SPURS_MAX_SPU = 8,
|
||||
CELL_SPURS_MAX_WORKLOAD = 16,
|
||||
CELL_SPURS_MAX_WORKLOAD2 = 32,
|
||||
CELL_SPURS_SYS_SERVICE_WORKLOAD_ID = 32,
|
||||
CELL_SPURS_MAX_PRIORITY = 16,
|
||||
CELL_SPURS_NAME_MAX_LENGTH = 15,
|
||||
CELL_SPURS_SIZE = 4096,
|
||||
CELL_SPURS_SIZE2 = 8192,
|
||||
CELL_SPURS_INTERRUPT_VECTOR = 0x0,
|
||||
CELL_SPURS_LOCK_LINE = 0x80,
|
||||
CELL_SPURS_KERNEL_DMA_TAG_ID = 31,
|
||||
CELL_SPURS_KERNEL1_ENTRY_ADDR = 0x818,
|
||||
CELL_SPURS_KERNEL2_ENTRY_ADDR = 0x848,
|
||||
CELL_SPURS_KERNEL1_EXIT_ADDR = 0x808,
|
||||
CELL_SPURS_KERNEL2_EXIT_ADDR = 0x838,
|
||||
CELL_SPURS_KERNEL1_SELECT_WORKLOAD_ADDR = 0x290,
|
||||
CELL_SPURS_KERNEL2_SELECT_WORKLOAD_ADDR = 0x290,
|
||||
};
|
||||
|
||||
enum RangeofEventQueuePortNumbers
|
||||
{
|
||||
CELL_SPURS_STATIC_PORT_RANGE_BOTTOM = 15,
|
||||
CELL_SPURS_DYNAMIC_PORT_RANGE_TOP = 16,
|
||||
CELL_SPURS_STATIC_PORT_RANGE_BOTTOM = 15,
|
||||
CELL_SPURS_DYNAMIC_PORT_RANGE_TOP = 16,
|
||||
CELL_SPURS_DYNAMIC_PORT_RANGE_BOTTOM = 63,
|
||||
};
|
||||
|
||||
enum SpursAttrFlags : u32
|
||||
{
|
||||
SAF_NONE = 0x0,
|
||||
|
||||
SAF_EXIT_IF_NO_WORK = 0x1,
|
||||
SAF_UNKNOWN_FLAG_30 = 0x2,
|
||||
SAF_SECOND_VERSION = 0x4,
|
||||
|
||||
SAF_NONE = 0x00000000,
|
||||
SAF_EXIT_IF_NO_WORK = 0x00000001,
|
||||
SAF_UNKNOWN_FLAG_30 = 0x00000002,
|
||||
SAF_SECOND_VERSION = 0x00000004,
|
||||
SAF_UNKNOWN_FLAG_9 = 0x00400000,
|
||||
SAF_UNKNOWN_FLAG_8 = 0x00800000,
|
||||
SAF_UNKNOWN_FLAG_7 = 0x01000000,
|
||||
|
@ -143,8 +138,7 @@ enum SpursAttrFlags : u32
|
|||
|
||||
enum SpursFlags1 : u8
|
||||
{
|
||||
SF1_NONE = 0x0,
|
||||
|
||||
SF1_NONE = 0x00,
|
||||
SF1_32_WORKLOADS = 0x40,
|
||||
SF1_EXIT_IF_NO_WORK = 0x80,
|
||||
};
|
||||
|
@ -416,9 +410,10 @@ struct set_alignment(128) CellSpurs
|
|||
{
|
||||
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
|
||||
u8 unk1[0x8];
|
||||
be_t<u32> x28; // 0x28
|
||||
be_t<u32> x2C; // 0x2C
|
||||
vm::bptr<CellSpursShutdownCompletionEventHook, u64> hook; // 0x30
|
||||
vm::bptr<void, u64> hookArg; // 0x38
|
||||
u8 unk2[0x40];
|
||||
|
@ -426,26 +421,38 @@ struct set_alignment(128) CellSpurs
|
|||
|
||||
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
|
||||
be_t<u32> unk1; // 0x04
|
||||
be_t<u32> unk2; // 0x08
|
||||
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}
|
||||
vm::bptr<EventHandlerListNode, u64> next;
|
||||
be_t<u64> data;
|
||||
vm::bptr<EventHandlerCallback, 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
|
||||
{
|
||||
vm::bcptr<void, u64> addr; // Address of the executable
|
||||
be_t<u64> arg; // spu argument
|
||||
be_t<u32> size;
|
||||
atomic_be_t<u8> uniqueId; // The unique id is the same for all workloads with the same addr
|
||||
vm::bcptr<void, u64> addr; // 0x00 Address of the executable
|
||||
be_t<u64> arg; // 0x08 Argument
|
||||
be_t<u32> size; // 0x10 Size of the executable
|
||||
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 priority[8];
|
||||
u8 priority[8]; // 0x18 Priority of the workload on each SPU
|
||||
};
|
||||
|
||||
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.
|
||||
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
|
||||
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
|
||||
u8 spuIdling; // 0x73
|
||||
u8 flags1; // 0x74 Type is SpursFlags1
|
||||
u8 sysSrvTraceControl; // 0x75
|
||||
u8 nSpus; // 0x76
|
||||
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
|
||||
atomic_be_t<u8> wklState1[0x10]; // 0x80 SPURS_WKL_STATE_*
|
||||
u8 wklStatus1[0x10]; // 0x90
|
||||
u8 wklEvent1[0x10]; // 0xA0
|
||||
atomic_be_t<u32> wklMskA; // 0xB0 - System service - Available workloads (32*u1)
|
||||
atomic_be_t<u8> wklEvent1[0x10]; // 0xA0
|
||||
atomic_be_t<u32> wklEnabled; // 0xB0
|
||||
atomic_be_t<u32> wklMskB; // 0xB4 - System service - Available module id
|
||||
u32 xB8; // 0xB8
|
||||
u8 sysSrvExitBarrier; // 0xBC
|
||||
atomic_be_t<u8> sysSrvMsgUpdateWorkload; // 0xBD
|
||||
u8 xBE; // 0xBE
|
||||
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 spuPort; // 0xC9
|
||||
u8 xCA; // 0xCA
|
||||
|
@ -493,7 +500,7 @@ struct set_alignment(128) CellSpurs
|
|||
u8 xCF; // 0xCF
|
||||
atomic_be_t<u8> wklState2[0x10]; // 0xD0 SPURS_WKL_STATE_*
|
||||
u8 wklStatus2[0x10]; // 0xE0
|
||||
u8 wklEvent2[0x10]; // 0xF0
|
||||
atomic_be_t<u8> wklEvent2[0x10]; // 0xF0
|
||||
_sub_str1 wklF1[0x10]; // 0x100
|
||||
vm::bptr<CellSpursTraceInfo, u64> traceBuffer; // 0x900
|
||||
be_t<u32> traceStartIndex[6]; // 0x908
|
||||
|
@ -508,16 +515,16 @@ struct set_alignment(128) CellSpurs
|
|||
u8 unknown4[0xB00 - 0x998];
|
||||
WorkloadInfo wklInfo1[0x10]; // 0xB00
|
||||
WorkloadInfo wklInfoSysSrv; // 0xD00
|
||||
be_t<u64> ppu0; // 0xD20
|
||||
be_t<u64> ppu0; // 0xD20 Handler thread
|
||||
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
|
||||
u8 unknown3[0xD5C - 0xD54];
|
||||
be_t<u32> queue; // 0xD5C - Event queue
|
||||
be_t<u32> port; // 0xD60 - Event port
|
||||
atomic_be_t<u8> xD64; // 0xD64 - SPURS handler dirty
|
||||
atomic_be_t<u8> xD65; // 0xD65 - SPURS handler waiting
|
||||
atomic_be_t<u8> xD66; // 0xD66 - SPURS handler exiting
|
||||
be_t<u32> eventQueue; // 0xD5C
|
||||
be_t<u32> eventPort; // 0xD60
|
||||
atomic_be_t<u8> handlerDirty; // 0xD64
|
||||
atomic_be_t<u8> handlerWaiting; // 0xD65
|
||||
atomic_be_t<u8> handlerExiting; // 0xD66
|
||||
atomic_be_t<u32> enableEH; // 0xD68
|
||||
be_t<u32> exception; // 0xD6C
|
||||
sys_spu_image spuImg; // 0xD70
|
||||
|
@ -529,12 +536,12 @@ struct set_alignment(128) CellSpurs
|
|||
be_t<u32> unk5; // 0xD9C
|
||||
be_t<u32> revision; // 0xDA0
|
||||
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_lwcond_t cond; // 0xDC8
|
||||
u8 unknown9[0xE00 - 0xDD0];
|
||||
_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
|
||||
WorkloadInfo wklInfo2[0x10]; // 0x1000
|
||||
_sub_str1 wklF2[0x10]; // 0x1200
|
||||
|
@ -552,16 +559,6 @@ struct set_alignment(128) CellSpurs
|
|||
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);
|
||||
|
@ -888,5 +885,6 @@ struct SpursTasksetContext
|
|||
|
||||
CHECK_SIZE(SpursTasksetContext, 0x900);
|
||||
|
||||
s32 spursAttachLv2EventQueue(vm::ptr<CellSpurs> spurs, u32 queue, vm::ptr<u8> port, s32 isDynamic, bool wasCreated);
|
||||
s32 spursWakeUp(PPUThread& CPU, vm::ptr<CellSpurs> spurs);
|
||||
class SpursModuleExit
|
||||
{
|
||||
};
|
||||
|
|
|
@ -11,82 +11,75 @@
|
|||
#include "Loader/ELF32.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
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
extern Module cellSpurs;
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//----------------------------------------------------------------------------
|
||||
// Function prototypes
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
//
|
||||
// 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
|
||||
void cellSpursModulePutTrace(CellSpursTracePacket * packet, u32 dmaTagId) {
|
||||
|
@ -160,9 +153,9 @@ void spursHalt(SPUThread & spu) {
|
|||
spu.halt();
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//----------------------------------------------------------------------------
|
||||
// SPURS kernel functions
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
/// Select a workload to run
|
||||
bool spursKernel1SelectWorkload(SPUThread & spu) {
|
||||
|
@ -582,9 +575,9 @@ bool spursKernelEntry(SPUThread & spu) {
|
|||
return false;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//----------------------------------------------------------------------------
|
||||
// SPURS system workload functions
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
/// Entry point of the system service
|
||||
bool spursSysServiceEntry(SPUThread & spu) {
|
||||
|
@ -931,14 +924,14 @@ void spursSysServiceUpdateShutdownCompletionEvents(SPUThread & spu, SpursKernelC
|
|||
for (u32 i = 0; i < CELL_SPURS_MAX_WORKLOAD; i++) {
|
||||
if (wklShutdownBitSet & (0x80000000u >> i)) {
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
if (wklShutdownBitSet & (0x8000 >> i)) {
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
@ -1022,13 +1015,13 @@ void spursSysServiceCleanupAfterSystemWorkload(SPUThread & spu, SpursKernelConte
|
|||
vm::reservation_op(vm::cast(ctxt->spurs.addr() + offsetof(CellSpurs, wklState1)), 128, [&]() {
|
||||
auto spurs = ctxt->spurs.priv_ptr();
|
||||
|
||||
if (spurs->sysSrvWorkload[ctxt->spuNum] == 0xFF) {
|
||||
if (spurs->sysSrvPreemptWklId[ctxt->spuNum] == 0xFF) {
|
||||
do_return = true;
|
||||
return;
|
||||
}
|
||||
|
||||
wklId = spurs->sysSrvWorkload[ctxt->spuNum];
|
||||
spurs->sysSrvWorkload[ctxt->spuNum] = 0xFF;
|
||||
wklId = spurs->sysSrvPreemptWklId[ctxt->spuNum];
|
||||
spurs->sysSrvPreemptWklId[ctxt->spuNum] = 0xFF;
|
||||
|
||||
memcpy(vm::get_ptr(spu.offset + 0x2D80), spurs->wklState1, 128);
|
||||
});
|
||||
|
@ -1066,9 +1059,9 @@ void spursSysServiceCleanupAfterSystemWorkload(SPUThread & spu, SpursKernelConte
|
|||
ctxt->wklCurrentId = wklIdSaved;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//----------------------------------------------------------------------------
|
||||
// SPURS taskset policy module functions
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
enum SpursTasksetRequest {
|
||||
SPURS_TASKSET_REQUEST_POLL_SIGNAL = -1,
|
||||
|
|
|
@ -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_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);
|
||||
|
||||
void sys_ppu_thread_exit(PPUThread& CPU, u64 val);
|
||||
|
|
|
@ -28,6 +28,12 @@ enum
|
|||
SYS_SYNC_ATTR_RECURSIVE_MASK = 0xF0, //???
|
||||
};
|
||||
|
||||
// attr_pshared
|
||||
enum
|
||||
{
|
||||
SYS_SYNC_NOT_PROCESS_SHARED = 0x200
|
||||
};
|
||||
|
||||
class sleep_queue_t
|
||||
{
|
||||
std::vector<u32> m_waiting;
|
||||
|
|
|
@ -13,6 +13,13 @@
|
|||
|
||||
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)
|
||||
{
|
||||
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);
|
||||
|
|
|
@ -15,12 +15,24 @@ enum : s32
|
|||
SYS_EVENT_QUEUE_DESTROY_FORCE = 1,
|
||||
};
|
||||
|
||||
// Event Queue Ipc Key
|
||||
enum : u64
|
||||
{
|
||||
SYS_EVENT_QUEUE_LOCAL = 0x00,
|
||||
};
|
||||
|
||||
// Event Port Type
|
||||
enum : s32
|
||||
{
|
||||
SYS_EVENT_PORT_LOCAL = 1,
|
||||
};
|
||||
|
||||
// Event Port Name
|
||||
enum : u64
|
||||
{
|
||||
SYS_EVENT_PORT_NO_NAME = 0,
|
||||
};
|
||||
|
||||
// Event Source Type
|
||||
enum : u32
|
||||
{
|
||||
|
@ -31,8 +43,9 @@ enum : u32
|
|||
// Event Source Key
|
||||
enum : u64
|
||||
{
|
||||
SYS_SPU_THREAD_EVENT_USER_KEY = 0xFFFFFFFF53505501,
|
||||
SYS_SPU_THREAD_EVENT_DMA_KEY = 0xFFFFFFFF53505502, // ???
|
||||
SYS_SPU_THREAD_EVENT_USER_KEY = 0xFFFFFFFF53505501ull,
|
||||
SYS_SPU_THREAD_EVENT_DMA_KEY = 0xFFFFFFFF53505502ull,
|
||||
SYS_SPU_THREAD_EVENT_EXCEPTION_KEY = 0xFFFFFFFF53505503ull,
|
||||
};
|
||||
|
||||
struct sys_event_queue_attr
|
||||
|
@ -129,6 +142,8 @@ REG_ID_TYPE(lv2_event_port_t, 0x0E); // SYS_EVENT_PORT_OBJECT
|
|||
|
||||
class PPUThread;
|
||||
|
||||
void sys_event_queue_attribute_initialize(vm::ptr<sys_event_queue_attr> attr);
|
||||
|
||||
// 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_destroy(u32 equeue_id, s32 mode);
|
||||
|
|
|
@ -12,6 +12,13 @@
|
|||
|
||||
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)
|
||||
{
|
||||
lwmutex.lock_var = { { lwmutex::free, lwmutex::zero } };
|
||||
|
|
|
@ -90,9 +90,7 @@ struct lv2_lwmutex_t
|
|||
REG_ID_TYPE(lv2_lwmutex_t, 0x95); // SYS_LWMUTEX_OBJECT
|
||||
|
||||
// Aux
|
||||
void lwmutex_create(sys_lwmutex_t& lwmutex, bool recursive, u32 protocol, u64 name);
|
||||
|
||||
class PPUThread;
|
||||
void sys_lwmutex_attribute_initialize(vm::ptr<sys_lwmutex_attribute_t> attr);
|
||||
|
||||
// SysCalls
|
||||
s32 _sys_lwmutex_create(vm::ptr<u32> lwmutex_id, u32 protocol, vm::ptr<sys_lwmutex_t> control, u32 arg4, u64 name, u32 arg6);
|
||||
|
|
|
@ -12,6 +12,15 @@
|
|||
|
||||
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)
|
||||
{
|
||||
sys_semaphore.Warning("sys_semaphore_create(sem=*0x%x, attr=*0x%x, initial_val=%d, max_val=%d)", sem, attr, initial_val, max_val);
|
||||
|
|
|
@ -41,6 +41,9 @@ struct lv2_sema_t
|
|||
|
||||
REG_ID_TYPE(lv2_sema_t, 0x96); // SYS_SEMAPHORE_OBJECT
|
||||
|
||||
// Aux
|
||||
void sys_semaphore_attribute_initialize(vm::ptr<sys_semaphore_attribute_t> attr);
|
||||
|
||||
// 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_destroy(u32 sem);
|
||||
|
|
|
@ -465,6 +465,13 @@ s32 sys_spu_thread_group_yield(u32 id)
|
|||
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)
|
||||
{
|
||||
sys_spu.Warning("sys_spu_thread_group_terminate(id=0x%x, value=0x%x)", id, value);
|
||||
|
|
|
@ -216,10 +216,12 @@ u32 LoadSpuImage(vfsStream& stream, u32& spu_ep);
|
|||
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_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
|
||||
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_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_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);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue