From e40776ba79a465b8202cb09beb4bb41012823f7f Mon Sep 17 00:00:00 2001 From: Nekotekina Date: Fri, 26 Sep 2014 01:41:35 +0400 Subject: [PATCH] cellSpursWakeUp, CellSpursWorkloadAttribute +vm_atomic update (8bit type) --- Utilities/GNU.h | 20 + rpcs3/Emu/Memory/vm_atomic.h | 14 +- rpcs3/Emu/SysCalls/Modules/cellMsgDialog.cpp | 11 +- rpcs3/Emu/SysCalls/Modules/cellSpurs.cpp | 863 +++++++++++-------- rpcs3/Emu/SysCalls/Modules/cellSpurs.h | 57 +- rpcs3/Emu/SysCalls/Modules/cellSync.cpp | 15 +- 6 files changed, 599 insertions(+), 381 deletions(-) diff --git a/Utilities/GNU.h b/Utilities/GNU.h index 3581907afc..fc693a24b3 100644 --- a/Utilities/GNU.h +++ b/Utilities/GNU.h @@ -95,6 +95,10 @@ int clock_gettime(int foo, struct timespec *ts); #endif #ifndef InterlockedCompareExchange +static __forceinline uint8_t InterlockedCompareExchange(volatile uint8_t* dest, uint8_t exch, uint8_t comp) +{ + return _InterlockedCompareExchange8((volatile char*)dest, exch, comp); +} static __forceinline uint16_t InterlockedCompareExchange(volatile uint16_t* dest, uint16_t exch, uint16_t comp) { return _InterlockedCompareExchange16((volatile short*)dest, exch, comp); @@ -110,6 +114,10 @@ static __forceinline uint64_t InterlockedCompareExchange(volatile uint64_t* dest #endif #ifndef InterlockedExchange +static __forceinline uint8_t InterlockedExchange(volatile uint8_t* dest, uint8_t value) +{ + return _InterlockedExchange8((volatile char*)dest, value); +} static __forceinline uint16_t InterlockedExchange(volatile uint16_t* dest, uint16_t value) { return _InterlockedExchange16((volatile short*)dest, value); @@ -125,6 +133,10 @@ static __forceinline uint64_t InterlockedExchange(volatile uint64_t* dest, uint6 #endif #ifndef InterlockedOr +static __forceinline uint8_t InterlockedOr(volatile uint8_t* dest, uint8_t value) +{ + return _InterlockedOr8((volatile char*)dest, value); +} static __forceinline uint16_t InterlockedOr(volatile uint16_t* dest, uint16_t value) { return _InterlockedOr16((volatile short*)dest, value); @@ -140,6 +152,10 @@ static __forceinline uint64_t InterlockedOr(volatile uint64_t* dest, uint64_t va #endif #ifndef InterlockedAnd +static __forceinline uint8_t InterlockedAnd(volatile uint8_t* dest, uint8_t value) +{ + return _InterlockedAnd8((volatile char*)dest, value); +} static __forceinline uint16_t InterlockedAnd(volatile uint16_t* dest, uint16_t value) { return _InterlockedAnd16((volatile short*)dest, value); @@ -155,6 +171,10 @@ static __forceinline uint64_t InterlockedAnd(volatile uint64_t* dest, uint64_t v #endif #ifndef InterlockedXor +static __forceinline uint8_t InterlockedXor(volatile uint8_t* dest, uint8_t value) +{ + return _InterlockedXor8((volatile char*)dest, value); +} static __forceinline uint16_t InterlockedXor(volatile uint16_t* dest, uint16_t value) { return _InterlockedXor16((volatile short*)dest, value); diff --git a/rpcs3/Emu/Memory/vm_atomic.h b/rpcs3/Emu/Memory/vm_atomic.h index 8f737940fe..7c117ac066 100644 --- a/rpcs3/Emu/Memory/vm_atomic.h +++ b/rpcs3/Emu/Memory/vm_atomic.h @@ -5,11 +5,17 @@ namespace vm template struct _to_atomic { - static_assert(size == 2 || size == 4 || size == 8, "Invalid atomic type"); + static_assert(size == 1 || size == 2 || size == 4 || size == 8, "Invalid atomic type"); typedef T type; }; + template + struct _to_atomic + { + typedef uint8_t type; + }; + template struct _to_atomic { @@ -99,21 +105,21 @@ namespace vm } } - // atomic bitwise logical OR, returns previous data + // atomic bitwise OR, returns previous data __forceinline const T _or(const T& right) volatile { const atomic_type res = InterlockedOr(&data, (atomic_type&)(right)); return (T&)res; } - // atomic bitwise logical AND, returns previous data + // atomic bitwise AND, returns previous data __forceinline const T _and(const T& right) volatile { const atomic_type res = InterlockedAnd(&data, (atomic_type&)(right)); return (T&)res; } - // atomic bitwise logical XOR, returns previous data + // atomic bitwise XOR, returns previous data __forceinline const T _xor(const T& right) volatile { const atomic_type res = InterlockedXor(&data, (atomic_type&)(right)); diff --git a/rpcs3/Emu/SysCalls/Modules/cellMsgDialog.cpp b/rpcs3/Emu/SysCalls/Modules/cellMsgDialog.cpp index 8df2d3f476..53cf172f63 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellMsgDialog.cpp +++ b/rpcs3/Emu/SysCalls/Modules/cellMsgDialog.cpp @@ -21,6 +21,7 @@ enum MsgDialogState }; std::atomic g_msg_dialog_state(msgDialogNone); +u64 g_msg_dialog_status; u64 g_msg_dialog_wait_until; u32 g_msg_dialog_progress_bar_count; @@ -100,14 +101,14 @@ int cellMsgDialogOpen2(u32 type, vm::ptr msgString, vm::ptr msgString, vm::ptr s32 + Emu.GetCallbackManager().Register([callback, userData]() -> s32 { - callback((s32)status, userData); + callback((s32)g_msg_dialog_status, userData); return CELL_OK; }); } diff --git a/rpcs3/Emu/SysCalls/Modules/cellSpurs.cpp b/rpcs3/Emu/SysCalls/Modules/cellSpurs.cpp index 6c4ef20f46..5edb2e5731 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellSpurs.cpp +++ b/rpcs3/Emu/SysCalls/Modules/cellSpurs.cpp @@ -20,68 +20,6 @@ extern u32 libsre; extern u32 libsre_rtoc; #endif -s64 spursAttachLv2EventQueue(vm::ptr spurs, u32 queue, vm::ptr port, s32 isDynamic, bool wasCreated) -{ -#ifdef PRX_DEBUG_XXX - return cb_call, u32, vm::ptr, s32, bool>(GetCurrentPPUThread(), libsre + 0xAE34, libsre_rtoc, - spurs, queue, port, isDynamic, wasCreated); -#else - if (!spurs || !port) - { - return CELL_SPURS_CORE_ERROR_NULL_POINTER; - } - if (spurs.addr() % 128) - { - return CELL_SPURS_CORE_ERROR_ALIGN; - } - if (spurs->m.unk21.ToBE()) - { - return CELL_SPURS_CORE_ERROR_STAT; - } - - s32 sdk_ver; - assert(process_get_sdk_version(process_getpid(), sdk_ver) == CELL_OK); - if (sdk_ver == -1) sdk_ver = 0x460000; - - u8 _port = 0x3f; - u64 port_mask = 0; - - if (isDynamic == 0) - { - _port = *port; - if (_port > 0x3f) - { - return CELL_SPURS_CORE_ERROR_INVAL; - } - if (sdk_ver > 0x17ffff && _port > 0xf) - { - return CELL_SPURS_CORE_ERROR_PERM; - } - } - - for (u32 i = isDynamic ? 0x10 : _port; i <= _port; i++) - { - port_mask |= 1ull << (i); - } - - assert(port_mask); // zero mask will return CELL_EINVAL - if (s32 res = sys_spu_thread_group_connect_event_all_threads(spurs->m.spuTG, queue, port_mask, port)) - { - if (res == CELL_EISCONN) - { - return CELL_SPURS_CORE_ERROR_BUSY; - } - return res; - } - - if (!wasCreated) - { - spurs->m.spups |= be_t::make(1ull << *port); // atomic bitwise or - } - return CELL_OK; -#endif -} - s64 spursCreateLv2EventQueue(vm::ptr spurs, u32& queue_id, vm::ptr port, s32 size, u64 name_u64) { #ifdef PRX_DEBUG_XXX @@ -90,7 +28,8 @@ s64 spursCreateLv2EventQueue(vm::ptr spurs, u32& queue_id, vm::ptrToLE(); return res; -#else +#endif + queue_id = event_queue_create(SYS_SYNC_FIFO, SYS_PPU_QUEUE, name_u64, 0, size); if (!queue_id) { @@ -99,7 +38,6 @@ s64 spursCreateLv2EventQueue(vm::ptr spurs, u32& queue_id, vm::ptr, u32, u32, s32, s32, s32, u32, u32, u32, u32, u32, u32, u32>(GetCurrentPPUThread(), libsre + 0x74E4, libsre_rtoc, spurs, revision, sdkVersion, nSpus, spuPriority, ppuPriority, flags, Memory.RealToVirtualAddr(prefix), prefixSize, container, Memory.RealToVirtualAddr(swlPriority), swlMaxSpu, swlIsPreem); -#else +#endif // SPURS initialization (asserts should actually rollback and return the error instead) if (!spurs) @@ -307,12 +245,10 @@ s64 spursInit( } else if (flags & SAF_EXIT_IF_NO_WORK) // wakeup { -#ifdef PRX_DEBUG - return cb_call>(GetCurrentPPUThread(), libsre + 0x84D8, libsre_rtoc, spurs); -#endif + return spursWakeUp(spurs); } + return CELL_OK; -#endif } s64 cellSpursInitialize(vm::ptr spurs, s32 nSpus, s32 spuPriority, s32 ppuPriority, bool exitIfNoWork) @@ -322,7 +258,7 @@ s64 cellSpursInitialize(vm::ptr spurs, s32 nSpus, s32 spuPriority, s3 #ifdef PRX_DEBUG_XXX return GetCurrentPPUThread().FastCall2(libsre + 0x8480, libsre_rtoc); -#else +#endif return spursInit( spurs, 0, @@ -337,7 +273,6 @@ s64 cellSpursInitialize(vm::ptr spurs, s32 nSpus, s32 spuPriority, s3 nullptr, 0, 0); -#endif } s64 cellSpursInitializeWithAttribute(vm::ptr spurs, vm::ptr attr) @@ -346,7 +281,7 @@ s64 cellSpursInitializeWithAttribute(vm::ptr spurs, vm::ptr spurs, vm::ptrm.swlPriority, attr->m.swlMaxSpu, attr->m.swlIsPreem); -#endif } s64 cellSpursInitializeWithAttribute2(vm::ptr spurs, vm::ptr attr) @@ -383,7 +317,7 @@ s64 cellSpursInitializeWithAttribute2(vm::ptr spurs, vm::ptr spurs, vm::ptrm.swlPriority, attr->m.swlMaxSpu, attr->m.swlIsPreem); -#endif } s64 _cellSpursAttributeInitialize(vm::ptr attr, u32 revision, u32 sdkVersion, u32 nSpus, s32 spuPriority, s32 ppuPriority, bool exitIfNoWork) @@ -421,7 +354,7 @@ s64 _cellSpursAttributeInitialize(vm::ptr attr, u32 revision #ifdef PRX_DEBUG_XXX return GetCurrentPPUThread().FastCall2(libsre + 0x72CC, libsre_rtoc); -#else +#endif if (!attr) { return CELL_SPURS_CORE_ERROR_NULL_POINTER; @@ -439,7 +372,6 @@ s64 _cellSpursAttributeInitialize(vm::ptr attr, u32 revision attr->m.ppuPriority = ppuPriority; attr->m.exitIfNoWork = exitIfNoWork; return CELL_OK; -#endif } s64 cellSpursAttributeSetMemoryContainerForSpuThread(vm::ptr attr, u32 container) @@ -448,7 +380,7 @@ s64 cellSpursAttributeSetMemoryContainerForSpuThread(vm::ptr #ifdef PRX_DEBUG_XXX return GetCurrentPPUThread().FastCall2(libsre + 0x6FF8, libsre_rtoc); -#else +#endif if (!attr) { return CELL_SPURS_CORE_ERROR_NULL_POINTER; @@ -466,7 +398,6 @@ s64 cellSpursAttributeSetMemoryContainerForSpuThread(vm::ptr attr->m.container = container; attr->m.flags |= SAF_SPU_MEMORY_CONTAINER_SET; return CELL_OK; -#endif } s64 cellSpursAttributeSetNamePrefix(vm::ptr attr, vm::ptr prefix, u32 size) @@ -475,7 +406,7 @@ s64 cellSpursAttributeSetNamePrefix(vm::ptr attr, vm::ptr attr, vm::ptrm.prefix, prefix.get_ptr(), size); attr->m.prefixSize = size; return CELL_OK; -#endif } s64 cellSpursAttributeEnableSpuPrintfIfAvailable(vm::ptr attr) @@ -502,7 +432,7 @@ s64 cellSpursAttributeEnableSpuPrintfIfAvailable(vm::ptr att #ifdef PRX_DEBUG_XXX return GetCurrentPPUThread().FastCall2(libsre + 0x7150, libsre_rtoc); -#else +#endif if (!attr) { return CELL_SPURS_CORE_ERROR_NULL_POINTER; @@ -514,7 +444,6 @@ s64 cellSpursAttributeEnableSpuPrintfIfAvailable(vm::ptr att attr->m.flags |= SAF_SPU_PRINTF_ENABLED; return CELL_OK; -#endif } s64 cellSpursAttributeSetSpuThreadGroupType(vm::ptr attr, s32 type) @@ -523,7 +452,7 @@ s64 cellSpursAttributeSetSpuThreadGroupType(vm::ptr attr, s3 #ifdef PRX_DEBUG_XXX return GetCurrentPPUThread().FastCall2(libsre + 0x70C8, libsre_rtoc); -#else +#endif if (!attr) { return CELL_SPURS_CORE_ERROR_NULL_POINTER; @@ -550,7 +479,6 @@ s64 cellSpursAttributeSetSpuThreadGroupType(vm::ptr attr, s3 return CELL_SPURS_CORE_ERROR_INVAL; } return CELL_OK; -#endif } s64 cellSpursAttributeEnableSystemWorkload(vm::ptr attr, vm::ptr priority, u32 maxSpu, vm::ptr isPreemptible) @@ -560,7 +488,7 @@ s64 cellSpursAttributeEnableSystemWorkload(vm::ptr attr, vm: #ifdef PRX_DEBUG_XXX return GetCurrentPPUThread().FastCall2(libsre + 0xF410, libsre_rtoc); -#else +#endif if (!attr) { return CELL_SPURS_CORE_ERROR_NULL_POINTER; @@ -609,7 +537,6 @@ s64 cellSpursAttributeEnableSystemWorkload(vm::ptr attr, vm: } } return CELL_SPURS_CORE_ERROR_INVAL; -#endif } s64 cellSpursFinalize(vm::ptr spurs) @@ -618,7 +545,100 @@ s64 cellSpursFinalize(vm::ptr spurs) #ifdef PRX_DEBUG return GetCurrentPPUThread().FastCall2(libsre + 0x8568, libsre_rtoc); +#endif + return CELL_OK; +} + +s64 spursAttachLv2EventQueue(vm::ptr spurs, u32 queue, vm::ptr port, s32 isDynamic, bool wasCreated) +{ +#ifdef PRX_DEBUG_XXX + return cb_call, u32, vm::ptr, s32, bool>(GetCurrentPPUThread(), libsre + 0xAE34, libsre_rtoc, + spurs, queue, port, isDynamic, wasCreated); +#endif + if (!spurs || !port) + { + return CELL_SPURS_CORE_ERROR_NULL_POINTER; + } + if (spurs.addr() % 128) + { + return CELL_SPURS_CORE_ERROR_ALIGN; + } + if (spurs->m.unk21.ToBE()) + { + return CELL_SPURS_CORE_ERROR_STAT; + } + + s32 sdk_ver; + assert(process_get_sdk_version(process_getpid(), sdk_ver) == CELL_OK); + if (sdk_ver == -1) sdk_ver = 0x460000; + + u8 _port = 0x3f; + u64 port_mask = 0; + + if (isDynamic == 0) + { + _port = *port; + if (_port > 0x3f) + { + return CELL_SPURS_CORE_ERROR_INVAL; + } + if (sdk_ver > 0x17ffff && _port > 0xf) + { + return CELL_SPURS_CORE_ERROR_PERM; + } + } + + for (u32 i = isDynamic ? 0x10 : _port; i <= _port; i++) + { + port_mask |= 1ull << (i); + } + + assert(port_mask); // zero mask will return CELL_EINVAL + if (s32 res = sys_spu_thread_group_connect_event_all_threads(spurs->m.spuTG, queue, port_mask, port)) + { + if (res == CELL_EISCONN) + { + return CELL_SPURS_CORE_ERROR_BUSY; + } + return res; + } + + if (!wasCreated) + { + spurs->m.spups |= be_t::make(1ull << *port); // atomic bitwise or + } + return CELL_OK; +} + +s64 cellSpursAttachLv2EventQueue(vm::ptr spurs, u32 queue, vm::ptr port, s32 isDynamic) +{ + cellSpurs->Warning("cellSpursAttachLv2EventQueue(spurs_addr=0x%x, queue=%d, port_addr=0x%x, isDynamic=%d)", + spurs.addr(), queue, port.addr(), isDynamic); + +#ifdef PRX_DEBUG_XXX + return GetCurrentPPUThread().FastCall2(libsre + 0xAFE0, libsre_rtoc); +#endif + return spursAttachLv2EventQueue(spurs, queue, port, isDynamic, false); +} + +s64 cellSpursDetachLv2EventQueue(vm::ptr spurs, u8 port) +{ +#ifdef PRX_DEBUG + cellSpurs->Warning("cellSpursDetachLv2EventQueue(spurs_addr=0x%x, port=%d)", spurs.addr(), port); + return GetCurrentPPUThread().FastCall2(libsre + 0xB144, libsre_rtoc); #else + UNIMPLEMENTED_FUNC(cellSpurs); + return CELL_OK; +#endif +} + +s64 cellSpursGetSpuGuid() +{ +#ifdef PRX_DEBUG + cellSpurs->Warning("%s()", __FUNCTION__); + return GetCurrentPPUThread().FastCall2(libsre + 0xEFB0, libsre_rtoc); +#else + UNIMPLEMENTED_FUNC(cellSpurs); return CELL_OK; #endif } @@ -689,29 +709,6 @@ s64 cellSpursSetPreemptionVictimHints(vm::ptr spurs, vm::ptr spurs, u32 queue, vm::ptr port, s32 isDynamic) -{ - cellSpurs->Warning("cellSpursAttachLv2EventQueue(spurs_addr=0x%x, queue=%d, port_addr=0x%x, isDynamic=%d)", - spurs.addr(), queue, port.addr(), isDynamic); - -#ifdef PRX_DEBUG_XXX - return GetCurrentPPUThread().FastCall2(libsre + 0xAFE0, libsre_rtoc); -#else - return spursAttachLv2EventQueue(spurs, queue, port, isDynamic, false); -#endif -} - -s64 cellSpursDetachLv2EventQueue(vm::ptr spurs, u8 port) -{ -#ifdef PRX_DEBUG - cellSpurs->Warning("cellSpursDetachLv2EventQueue(spurs_addr=0x%x, port=0x%x)", spurs.addr(), port); - return GetCurrentPPUThread().FastCall2(libsre + 0xB144, libsre_rtoc); -#else - UNIMPLEMENTED_FUNC(cellSpurs); - return CELL_OK; -#endif -} - s64 cellSpursEnableExceptionEventHandler(vm::ptr spurs, bool flag) { #ifdef PRX_DEBUG @@ -757,6 +754,399 @@ s64 cellSpursGetInfo(vm::ptr spurs, vm::ptr info) #endif } +s64 spursWakeUp(vm::ptr spurs) +{ +#ifdef PRX_DEBUG + return cb_call>(GetCurrentPPUThread(), libsre + 0x84D8, libsre_rtoc, spurs); +#endif + if (!spurs) + { + return CELL_SPURS_POLICY_MODULE_ERROR_NULL_POINTER; + } + if (spurs.addr() % 128) + { + return CELL_SPURS_POLICY_MODULE_ERROR_ALIGN; + } + if (spurs->m.unk21.ToBE()) + { + return CELL_SPURS_POLICY_MODULE_ERROR_STAT; + } + + spurs->m.unk19[0].exchange(1); + if (spurs->m.unk19[1].read_sync()) + { + assert(sys_lwmutex_lock(vm::ptr::make(spurs.addr() + 0xdb0), 0) == 0); + assert(sys_lwcond_signal(vm::ptr::make(spurs.addr() + 0xdc8)) == 0); + assert(sys_lwmutex_unlock(vm::ptr::make(spurs.addr() + 0xdb0)) == 0); + } + return CELL_OK; +} + +s64 cellSpursWakeUp(vm::ptr spurs) +{ + cellSpurs->Warning("%s(spurs_addr=0x%x)", __FUNCTION__, spurs.addr()); + + return spursWakeUp(spurs); +} + +s32 spursAddWorkload( + vm::ptr spurs, + vm::ptr wid, + vm::ptr pm, + u32 size, + u64 data, + const u8 priorityTable[], + u32 minContention, + u32 maxContention, + const char* nameClass, + const char* nameInstance, + vm::ptr hook, + vm::ptr hookArg) +{ +#ifdef PRX_DEBUG + return cb_call, vm::ptr, vm::ptr, u32, u64, u32, u32, u32, u32, u32, u32, u32>(GetCurrentPPUThread(), libsre + 0x96EC, libsre_rtoc, + spurs, wid, pm, size, data, Memory.RealToVirtualAddr(priorityTable), minContention, maxContention, + Memory.RealToVirtualAddr(nameClass), Memory.RealToVirtualAddr(nameInstance), hook.addr(), hookArg.addr()); +#endif + + return CELL_OK; +} + +s64 cellSpursAddWorkload( + vm::ptr spurs, + vm::ptr wid, + vm::ptr pm, + u32 size, + u64 data, + vm::ptr priorityTable, + u32 minContention, + u32 maxContention) +{ + cellSpurs->Warning("%s(spurs_addr=0x%x, wid_addr=0x%x, pm_addr=0x%x, size=0x%x, data=0x%llx, priorityTable_addr=0x%x, minContention=0x%x, maxContention=0x%x)", + __FUNCTION__, spurs.addr(), wid.addr(), pm.addr(), size, data, priorityTable.addr(), minContention, maxContention); + +#ifdef PRX_DEBUG_XXX + return GetCurrentPPUThread().FastCall2(libsre + 0x9ED0, libsre_rtoc); +#endif + + return spursAddWorkload( + spurs, + wid, + pm, + size, + data, + *priorityTable, + minContention, + maxContention, + nullptr, + nullptr, + {}, + {}); +} + +s64 _cellSpursWorkloadAttributeInitialize( + vm::ptr attr, + u32 revision, + u32 sdkVersion, + vm::ptr pm, + u32 size, + u64 data, + vm::ptr priorityTable, + u32 minContention, + u32 maxContention) +{ + cellSpurs->Warning("%s(attr_addr=0x%x, revision=%d, sdkVersion=0x%x, pm_addr=0x%x, size=0x%x, data=0x%llx, priorityTable_addr=0x%x, minContention=0x%x, maxContention=0x%x)", + __FUNCTION__, attr.addr(), revision, sdkVersion, pm.addr(), size, data, priorityTable.addr(), minContention, maxContention); + +#ifdef PRX_DEBUG_XXX + return GetCurrentPPUThread().FastCall2(libsre + 0x9F08, libsre_rtoc); +#endif + if (!attr) + { + return CELL_SPURS_POLICY_MODULE_ERROR_NULL_POINTER; + } + if (attr.addr() % 8) + { + return CELL_SPURS_POLICY_MODULE_ERROR_ALIGN; + } + if (!pm) + { + return CELL_SPURS_POLICY_MODULE_ERROR_NULL_POINTER; + } + if (pm.addr() % 16) + { + return CELL_SPURS_POLICY_MODULE_ERROR_ALIGN; + } + if (minContention == 0 || *(u64*)*priorityTable & 0xf0f0f0f0f0f0f0f0ull) // check if some priority > 15 + { + return CELL_SPURS_POLICY_MODULE_ERROR_INVAL; + } + + memset(attr.get_ptr(), 0, CellSpursWorkloadAttribute::size); + attr->m.revision = revision; + attr->m.sdkVersion = sdkVersion; + attr->m.pm = pm; + attr->m.size = size; + attr->m.data = data; + *(u64*)attr->m.priority = *(u64*)*priorityTable; + attr->m.minContention = minContention; + attr->m.maxContention = maxContention; + return CELL_OK; +} + +s64 cellSpursWorkloadAttributeSetName(vm::ptr attr, vm::ptr nameClass, vm::ptr nameInstance) +{ + cellSpurs->Warning("%s(attr_addr=0x%x, nameClass_addr=0x%x, nameInstance_addr=0x%x)", __FUNCTION__, attr.addr(), nameClass.addr(), nameInstance.addr()); + +#ifdef PRX_DEBUG_XXX + return GetCurrentPPUThread().FastCall2(libsre + 0x9664, libsre_rtoc); +#endif + if (!attr) + { + return CELL_SPURS_POLICY_MODULE_ERROR_NULL_POINTER; + } + if (attr.addr() % 8) + { + return CELL_SPURS_POLICY_MODULE_ERROR_ALIGN; + } + + attr->m.nameClass = nameClass; + attr->m.nameInstance = nameInstance; + return CELL_OK; +} + +s64 cellSpursWorkloadAttributeSetShutdownCompletionEventHook(vm::ptr attr, vm::ptr hook, vm::ptr arg) +{ + cellSpurs->Warning("%s(attr_addr=0x%x, hook_addr=0x%x, arg=0x%x)", __FUNCTION__, attr.addr(), hook.addr(), arg.addr()); + +#ifdef PRX_DEBUG_XXX + return GetCurrentPPUThread().FastCall2(libsre + 0x96A4, libsre_rtoc); +#endif + if (!attr || !hook) + { + return CELL_SPURS_POLICY_MODULE_ERROR_NULL_POINTER; + } + if (attr.addr() % 8) + { + return CELL_SPURS_POLICY_MODULE_ERROR_ALIGN; + } + + attr->m.hook = hook; + attr->m.hookArg = arg; + return CELL_OK; +} + +s64 cellSpursAddWorkloadWithAttribute(vm::ptr spurs, vm::ptr wid, vm::ptr attr) +{ + cellSpurs->Warning("%s(spurs_addr=0x%x, wid_addr=0x%x, attr_addr=0x%x)", __FUNCTION__, spurs.addr(), wid.addr(), attr.addr()); + +#ifdef PRX_DEBUG_XXX + return GetCurrentPPUThread().FastCall2(libsre + 0x9E14, libsre_rtoc); +#endif + if (!attr) + { + return CELL_SPURS_POLICY_MODULE_ERROR_NULL_POINTER; + } + if (attr.addr() % 8) + { + return CELL_SPURS_POLICY_MODULE_ERROR_ALIGN; + } + if (attr->m.revision != be_t::make(1)) + { + return CELL_SPURS_POLICY_MODULE_ERROR_INVAL; + } + + return spursAddWorkload( + spurs, + wid, + vm::ptr::make(attr->m.pm.addr()), + attr->m.size, + attr->m.data, + attr->m.priority, + attr->m.minContention, + attr->m.maxContention, + attr->m.nameClass.get_ptr(), + attr->m.nameInstance.get_ptr(), + vm::ptr::make(attr->m.hook.addr()), + vm::ptr::make(attr->m.hookArg.addr())); +} + +s64 cellSpursRemoveWorkload() +{ +#ifdef PRX_DEBUG + cellSpurs->Warning("%s()", __FUNCTION__); + return GetCurrentPPUThread().FastCall2(libsre + 0xA414, libsre_rtoc); +#else + UNIMPLEMENTED_FUNC(cellSpurs); + return CELL_OK; +#endif +} + +s64 cellSpursWaitForWorkloadShutdown() +{ +#ifdef PRX_DEBUG + cellSpurs->Warning("%s()", __FUNCTION__); + return GetCurrentPPUThread().FastCall2(libsre + 0xA20C, libsre_rtoc); +#else + UNIMPLEMENTED_FUNC(cellSpurs); + return CELL_OK; +#endif +} + +s64 cellSpursShutdownWorkload() +{ +#ifdef PRX_DEBUG + cellSpurs->Warning("%s()", __FUNCTION__); + return GetCurrentPPUThread().FastCall2(libsre + 0xA060, libsre_rtoc); +#else + UNIMPLEMENTED_FUNC(cellSpurs); + return CELL_OK; +#endif +} + +s64 _cellSpursWorkloadFlagReceiver() +{ +#ifdef PRX_DEBUG + cellSpurs->Warning("%s()", __FUNCTION__); + return GetCurrentPPUThread().FastCall2(libsre + 0xF158, libsre_rtoc); +#else + UNIMPLEMENTED_FUNC(cellSpurs); + return CELL_OK; +#endif +} + +s64 cellSpursGetWorkloadFlag() +{ +#ifdef PRX_DEBUG + cellSpurs->Warning("%s()", __FUNCTION__); + return GetCurrentPPUThread().FastCall2(libsre + 0xEC00, libsre_rtoc); +#else + UNIMPLEMENTED_FUNC(cellSpurs); + return CELL_OK; +#endif +} + +s64 cellSpursSendWorkloadSignal() +{ +#ifdef PRX_DEBUG + cellSpurs->Warning("%s()", __FUNCTION__); + return GetCurrentPPUThread().FastCall2(libsre + 0xA658, libsre_rtoc); +#else + UNIMPLEMENTED_FUNC(cellSpurs); + return CELL_OK; +#endif +} + +s64 cellSpursGetWorkloadData() +{ +#ifdef PRX_DEBUG + cellSpurs->Warning("%s()", __FUNCTION__); + return GetCurrentPPUThread().FastCall2(libsre + 0xA78C, libsre_rtoc); +#else + UNIMPLEMENTED_FUNC(cellSpurs); + return CELL_OK; +#endif +} + +s64 cellSpursReadyCountStore() +{ +#ifdef PRX_DEBUG + cellSpurs->Warning("%s()", __FUNCTION__); + return GetCurrentPPUThread().FastCall2(libsre + 0xAB2C, libsre_rtoc); +#else + UNIMPLEMENTED_FUNC(cellSpurs); + return CELL_OK; +#endif +} + +s64 cellSpursReadyCountAdd() +{ +#ifdef PRX_DEBUG + cellSpurs->Warning("%s()", __FUNCTION__); + return GetCurrentPPUThread().FastCall2(libsre + 0xA868, libsre_rtoc); +#else + UNIMPLEMENTED_FUNC(cellSpurs); + return CELL_OK; +#endif +} + +s64 cellSpursReadyCountCompareAndSwap() +{ +#ifdef PRX_DEBUG + cellSpurs->Warning("%s()", __FUNCTION__); + return GetCurrentPPUThread().FastCall2(libsre + 0xA9CC, libsre_rtoc); +#else + UNIMPLEMENTED_FUNC(cellSpurs); + return CELL_OK; +#endif +} + +s64 cellSpursReadyCountSwap() +{ +#ifdef PRX_DEBUG + cellSpurs->Warning("%s()", __FUNCTION__); + return GetCurrentPPUThread().FastCall2(libsre + 0xAC34, libsre_rtoc); +#else + UNIMPLEMENTED_FUNC(cellSpurs); + return CELL_OK; +#endif +} + +s64 cellSpursRequestIdleSpu() +{ +#ifdef PRX_DEBUG + cellSpurs->Warning("%s()", __FUNCTION__); + return GetCurrentPPUThread().FastCall2(libsre + 0xAD88, libsre_rtoc); +#else + UNIMPLEMENTED_FUNC(cellSpurs); + return CELL_OK; +#endif +} + +s64 cellSpursGetWorkloadInfo() +{ +#ifdef PRX_DEBUG + cellSpurs->Warning("%s()", __FUNCTION__); + return GetCurrentPPUThread().FastCall2(libsre + 0xE70C, libsre_rtoc); +#else + UNIMPLEMENTED_FUNC(cellSpurs); + return CELL_OK; +#endif +} + +s64 _cellSpursWorkloadFlagReceiver2() +{ +#ifdef PRX_DEBUG + cellSpurs->Warning("%s()", __FUNCTION__); + return GetCurrentPPUThread().FastCall2(libsre + 0xF298, libsre_rtoc); +#else + UNIMPLEMENTED_FUNC(cellSpurs); + return CELL_OK; +#endif +} + +s64 cellSpursSetExceptionEventHandler() +{ +#ifdef PRX_DEBUG + cellSpurs->Warning("%s()", __FUNCTION__); + return GetCurrentPPUThread().FastCall2(libsre + 0xDB54, libsre_rtoc); +#else + UNIMPLEMENTED_FUNC(cellSpurs); + return CELL_OK; +#endif +} + +s64 cellSpursUnsetExceptionEventHandler() +{ +#ifdef PRX_DEBUG + cellSpurs->Warning("%s()", __FUNCTION__); + return GetCurrentPPUThread().FastCall2(libsre + 0xD77C, libsre_rtoc); +#else + UNIMPLEMENTED_FUNC(cellSpurs); + return CELL_OK; +#endif +} + s64 _cellSpursEventFlagInitialize(vm::ptr spurs, vm::ptr taskset, vm::ptr eventFlag, u32 flagClearMode, u32 flagDirection) { #ifdef PRX_DEBUG @@ -1552,28 +1942,6 @@ s64 cellSpursTasksetGetSpursAddress() #endif } -s64 cellSpursSetExceptionEventHandler() -{ -#ifdef PRX_DEBUG - cellSpurs->Warning("%s()", __FUNCTION__); - return GetCurrentPPUThread().FastCall2(libsre + 0xDB54, libsre_rtoc); -#else - UNIMPLEMENTED_FUNC(cellSpurs); - return CELL_OK; -#endif -} - -s64 cellSpursUnsetExceptionEventHandler() -{ -#ifdef PRX_DEBUG - cellSpurs->Warning("%s()", __FUNCTION__); - return GetCurrentPPUThread().FastCall2(libsre + 0xD77C, libsre_rtoc); -#else - UNIMPLEMENTED_FUNC(cellSpurs); - return CELL_OK; -#endif -} - s64 cellSpursGetTasksetInfo() { #ifdef PRX_DEBUG @@ -1695,237 +2063,6 @@ s64 cellSpursJobChainGetError() #endif } -s64 cellSpursWorkloadAttributeSetName() -{ -#ifdef PRX_DEBUG - cellSpurs->Warning("%s()", __FUNCTION__); - return GetCurrentPPUThread().FastCall2(libsre + 0x9664, libsre_rtoc); -#else - UNIMPLEMENTED_FUNC(cellSpurs); - return CELL_OK; -#endif -} - -s64 cellSpursWorkloadAttributeSetShutdownCompletionEventHook() -{ -#ifdef PRX_DEBUG - cellSpurs->Warning("%s()", __FUNCTION__); - return GetCurrentPPUThread().FastCall2(libsre + 0x96A4, libsre_rtoc); -#else - UNIMPLEMENTED_FUNC(cellSpurs); - return CELL_OK; -#endif -} - -s64 cellSpursAddWorkloadWithAttribute() -{ -#ifdef PRX_DEBUG - cellSpurs->Warning("%s()", __FUNCTION__); - return GetCurrentPPUThread().FastCall2(libsre + 0x9E14, libsre_rtoc); -#else - UNIMPLEMENTED_FUNC(cellSpurs); - return CELL_OK; -#endif -} - -s64 cellSpursRemoveWorkload() -{ -#ifdef PRX_DEBUG - cellSpurs->Warning("%s()", __FUNCTION__); - return GetCurrentPPUThread().FastCall2(libsre + 0xA414, libsre_rtoc); -#else - UNIMPLEMENTED_FUNC(cellSpurs); - return CELL_OK; -#endif -} - -s64 cellSpursWaitForWorkloadShutdown() -{ -#ifdef PRX_DEBUG - cellSpurs->Warning("%s()", __FUNCTION__); - return GetCurrentPPUThread().FastCall2(libsre + 0xA20C, libsre_rtoc); -#else - UNIMPLEMENTED_FUNC(cellSpurs); - return CELL_OK; -#endif -} - -s64 cellSpursAddWorkload() -{ -#ifdef PRX_DEBUG - cellSpurs->Warning("%s()", __FUNCTION__); - return GetCurrentPPUThread().FastCall2(libsre + 0x9ED0, libsre_rtoc); -#else - UNIMPLEMENTED_FUNC(cellSpurs); - return CELL_OK; -#endif -} - -s64 cellSpursWakeUp(vm::ptr spurs) -{ -#ifdef PRX_DEBUG - cellSpurs->Warning("%s()", __FUNCTION__); - return GetCurrentPPUThread().FastCall2(libsre + 0x84D8, libsre_rtoc); -#else - UNIMPLEMENTED_FUNC(cellSpurs); - return CELL_OK; -#endif -} - -s64 cellSpursShutdownWorkload() -{ -#ifdef PRX_DEBUG - cellSpurs->Warning("%s()", __FUNCTION__); - return GetCurrentPPUThread().FastCall2(libsre + 0xA060, libsre_rtoc); -#else - UNIMPLEMENTED_FUNC(cellSpurs); - return CELL_OK; -#endif -} - -s64 _cellSpursWorkloadFlagReceiver() -{ -#ifdef PRX_DEBUG - cellSpurs->Warning("%s()", __FUNCTION__); - return GetCurrentPPUThread().FastCall2(libsre + 0xF158, libsre_rtoc); -#else - UNIMPLEMENTED_FUNC(cellSpurs); - return CELL_OK; -#endif -} - -s64 cellSpursGetWorkloadFlag() -{ -#ifdef PRX_DEBUG - cellSpurs->Warning("%s()", __FUNCTION__); - return GetCurrentPPUThread().FastCall2(libsre + 0xEC00, libsre_rtoc); -#else - UNIMPLEMENTED_FUNC(cellSpurs); - return CELL_OK; -#endif -} - -s64 cellSpursReadyCountStore() -{ -#ifdef PRX_DEBUG - cellSpurs->Warning("%s()", __FUNCTION__); - return GetCurrentPPUThread().FastCall2(libsre + 0xAB2C, libsre_rtoc); -#else - UNIMPLEMENTED_FUNC(cellSpurs); - return CELL_OK; -#endif -} - -s64 _cellSpursWorkloadAttributeInitialize() -{ -#ifdef PRX_DEBUG - cellSpurs->Warning("%s()", __FUNCTION__); - return GetCurrentPPUThread().FastCall2(libsre + 0x9F08, libsre_rtoc); -#else - UNIMPLEMENTED_FUNC(cellSpurs); - return CELL_OK; -#endif -} - -s64 cellSpursSendWorkloadSignal() -{ -#ifdef PRX_DEBUG - cellSpurs->Warning("%s()", __FUNCTION__); - return GetCurrentPPUThread().FastCall2(libsre + 0xA658, libsre_rtoc); -#else - UNIMPLEMENTED_FUNC(cellSpurs); - return CELL_OK; -#endif -} - -s64 cellSpursGetWorkloadData() -{ -#ifdef PRX_DEBUG - cellSpurs->Warning("%s()", __FUNCTION__); - return GetCurrentPPUThread().FastCall2(libsre + 0xA78C, libsre_rtoc); -#else - UNIMPLEMENTED_FUNC(cellSpurs); - return CELL_OK; -#endif -} - -s64 cellSpursReadyCountAdd() -{ -#ifdef PRX_DEBUG - cellSpurs->Warning("%s()", __FUNCTION__); - return GetCurrentPPUThread().FastCall2(libsre + 0xA868, libsre_rtoc); -#else - UNIMPLEMENTED_FUNC(cellSpurs); - return CELL_OK; -#endif -} - -s64 cellSpursReadyCountCompareAndSwap() -{ -#ifdef PRX_DEBUG - cellSpurs->Warning("%s()", __FUNCTION__); - return GetCurrentPPUThread().FastCall2(libsre + 0xA9CC, libsre_rtoc); -#else - UNIMPLEMENTED_FUNC(cellSpurs); - return CELL_OK; -#endif -} - -s64 cellSpursReadyCountSwap() -{ -#ifdef PRX_DEBUG - cellSpurs->Warning("%s()", __FUNCTION__); - return GetCurrentPPUThread().FastCall2(libsre + 0xAC34, libsre_rtoc); -#else - UNIMPLEMENTED_FUNC(cellSpurs); - return CELL_OK; -#endif -} - -s64 cellSpursRequestIdleSpu() -{ -#ifdef PRX_DEBUG - cellSpurs->Warning("%s()", __FUNCTION__); - return GetCurrentPPUThread().FastCall2(libsre + 0xAD88, libsre_rtoc); -#else - UNIMPLEMENTED_FUNC(cellSpurs); - return CELL_OK; -#endif -} - -s64 cellSpursGetWorkloadInfo() -{ -#ifdef PRX_DEBUG - cellSpurs->Warning("%s()", __FUNCTION__); - return GetCurrentPPUThread().FastCall2(libsre + 0xE70C, libsre_rtoc); -#else - UNIMPLEMENTED_FUNC(cellSpurs); - return CELL_OK; -#endif -} - -s64 cellSpursGetSpuGuid() -{ -#ifdef PRX_DEBUG - cellSpurs->Warning("%s()", __FUNCTION__); - return GetCurrentPPUThread().FastCall2(libsre + 0xEFB0, libsre_rtoc); -#else - UNIMPLEMENTED_FUNC(cellSpurs); - return CELL_OK; -#endif -} - -s64 _cellSpursWorkloadFlagReceiver2() -{ -#ifdef PRX_DEBUG - cellSpurs->Warning("%s()", __FUNCTION__); - return GetCurrentPPUThread().FastCall2(libsre + 0xF298, libsre_rtoc); -#else - UNIMPLEMENTED_FUNC(cellSpurs); - return CELL_OK; -#endif -} - s64 cellSpursGetJobPipelineInfo() { #ifdef PRX_DEBUG diff --git a/rpcs3/Emu/SysCalls/Modules/cellSpurs.h b/rpcs3/Emu/SysCalls/Modules/cellSpurs.h index d3ab987c2d..404a3ed463 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellSpurs.h +++ b/rpcs3/Emu/SysCalls/Modules/cellSpurs.h @@ -17,6 +17,27 @@ enum CELL_SPURS_CORE_ERROR_NULL_POINTER = 0x80410711, }; +// +enum +{ + CELL_SPURS_POLICY_MODULE_ERROR_AGAIN = 0x80410801, + CELL_SPURS_POLICY_MODULE_ERROR_INVAL = 0x80410802, + CELL_SPURS_POLICY_MODULE_ERROR_NOSYS = 0x80410803, + CELL_SPURS_POLICY_MODULE_ERROR_NOMEM = 0x80410804, + CELL_SPURS_POLICY_MODULE_ERROR_SRCH = 0x80410805, + CELL_SPURS_POLICY_MODULE_ERROR_NOENT = 0x80410806, + CELL_SPURS_POLICY_MODULE_ERROR_NOEXEC = 0x80410807, + CELL_SPURS_POLICY_MODULE_ERROR_DEADLK = 0x80410808, + CELL_SPURS_POLICY_MODULE_ERROR_PERM = 0x80410809, + CELL_SPURS_POLICY_MODULE_ERROR_BUSY = 0x8041080A, + CELL_SPURS_POLICY_MODULE_ERROR_ABORT = 0x8041080C, + CELL_SPURS_POLICY_MODULE_ERROR_FAULT = 0x8041080D, + CELL_SPURS_POLICY_MODULE_ERROR_CHILD = 0x8041080E, + CELL_SPURS_POLICY_MODULE_ERROR_STAT = 0x8041080F, + CELL_SPURS_POLICY_MODULE_ERROR_ALIGN = 0x80410810, + CELL_SPURS_POLICY_MODULE_ERROR_NULL_POINTER = 0x80410811, +}; + // Task return codes. enum { @@ -207,7 +228,7 @@ struct CellSpurs u8 unknown3[0xD5C - 0xD54]; be_t queue; // 0xD5C be_t port; // 0xD60 - be_t unk19; // 0xD64 + vm::atomic unk19[4]; // 0xD64 (used in wakeup) vm::atomic enableEH; // 0xD68 be_t unk21; // 0xD6C sys_spu_image spuImg; // 0xD70 @@ -239,6 +260,37 @@ struct CellSpurs typedef CellSpurs CellSpurs2; +typedef void(*CellSpursShutdownCompletionEventHook)(vm::ptr, u32 wid, vm::ptr arg); + +struct CellSpursWorkloadAttribute +{ + static const uint align = 8; + static const uint size = 512; + + union + { + // raw data + u8 _u8[size]; + + // real data + struct + { + be_t revision; + be_t sdkVersion; + vm::bptr pm; + be_t size; + be_t data; + u8 priority[8]; + be_t minContention; + be_t maxContention; + vm::bptr nameClass; + vm::bptr nameInstance; + vm::bptr hook; + vm::bptr hookArg; + } m; + }; +}; + struct CellSpursEventFlag { SPURSManagerEventFlag *eventFlag; @@ -435,3 +487,6 @@ struct CellSpursTaskBinInfo be_t __reserved__; CellSpursTaskLsPattern lsPattern; }; + +s64 spursAttachLv2EventQueue(vm::ptr spurs, u32 queue, vm::ptr port, s32 isDynamic, bool wasCreated); +s64 spursWakeUp(vm::ptr spurs); diff --git a/rpcs3/Emu/SysCalls/Modules/cellSync.cpp b/rpcs3/Emu/SysCalls/Modules/cellSync.cpp index 8f06a48660..f647f6c871 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellSync.cpp +++ b/rpcs3/Emu/SysCalls/Modules/cellSync.cpp @@ -892,7 +892,7 @@ s32 syncLFQueueInitialize(vm::ptr queue, vm::ptr buffer, u3 #ifdef PRX_DEBUG_XXX return cb_caller, vm::ptr, u32, u32, CellSyncQueueDirection, vm::ptr>::call(GetCurrentPPUThread(), libsre + 0x205C, libsre_rtoc, queue, buffer, size, depth, direction, eaSignal); -#else +#endif if (!queue) { @@ -991,7 +991,6 @@ s32 syncLFQueueInitialize(vm::ptr queue, vm::ptr buffer, u3 // prx: sync queue->init.read_sync(); return CELL_OK; -#endif } s32 cellSyncLFQueueInitialize(vm::ptr queue, vm::ptr buffer, u32 size, u32 depth, CellSyncQueueDirection direction, vm::ptr eaSignal) @@ -1933,10 +1932,10 @@ s32 syncLFQueueAttachLv2EventQueue(vm::ptr spus, u32 num, vm::ptr, u32, vm::ptr>(GetCurrentPPUThread(), libsre + 0x19A8, libsre_rtoc, spus, num, queue); -#else - assert(!syncLFQueueAttachLv2EventQueue); - return CELL_OK; #endif + + assert(!"syncLFQueueAttachLv2EventQueue"); + return CELL_OK; } s32 _cellSyncLFQueueAttachLv2EventQueue(vm::ptr spus, u32 num, vm::ptr queue) @@ -1951,10 +1950,10 @@ s32 syncLFQueueDetachLv2EventQueue(vm::ptr spus, u32 num, vm::ptr, u32, vm::ptr>(GetCurrentPPUThread(), libsre + 0x1DA0, libsre_rtoc, spus, num, queue); -#else - assert(!syncLFQueueDetachLv2EventQueue); - return CELL_OK; #endif + + assert(!"syncLFQueueDetachLv2EventQueue"); + return CELL_OK; } s32 _cellSyncLFQueueDetachLv2EventQueue(vm::ptr spus, u32 num, vm::ptr queue)