diff --git a/rpcs3/Emu/Cell/Modules/cellSpurs.cpp b/rpcs3/Emu/Cell/Modules/cellSpurs.cpp index c09c808e92..c5defbd048 100644 --- a/rpcs3/Emu/Cell/Modules/cellSpurs.cpp +++ b/rpcs3/Emu/Cell/Modules/cellSpurs.cpp @@ -1230,7 +1230,7 @@ s32 _spurs::initialize(ppu_thread& ppu, vm::ptr spurs, u32 revision, if (flags & SAF_UNKNOWN_FLAG_9) spuTgAttr->type |= 0x0800; if (flags & SAF_SYSTEM_WORKLOAD_ENABLED) spuTgAttr->type |= SYS_SPU_THREAD_GROUP_TYPE_COOPERATE_WITH_SYSTEM; - if (s32 rc = sys_spu_thread_group_create(ppu, spurs.ptr(&CellSpurs::spuTG), nSpus, spuPriority, spuTgAttr)) + if (s32 rc = sys_spu_thread_group_create(ppu, spurs.ptr(&CellSpurs::spuTG), nSpus, spuPriority, vm::unsafe_ptr_cast(spuTgAttr))) { ppu_execute<&sys_spu_image_close>(ppu, spurs.ptr(&CellSpurs::spuImg)); return rollback(), rc; diff --git a/rpcs3/Emu/Cell/lv2/sys_spu.cpp b/rpcs3/Emu/Cell/lv2/sys_spu.cpp index c3328eb604..3665efcd0a 100644 --- a/rpcs3/Emu/Cell/lv2/sys_spu.cpp +++ b/rpcs3/Emu/Cell/lv2/sys_spu.cpp @@ -767,7 +767,12 @@ error_code sys_spu_thread_initialize(ppu_thread& ppu, vm::ptr thread, u32 g } // Read thread name - const std::string thread_name(attr_data.name.get_ptr(), std::max(attr_data.name_len, 1) - 1); + std::string thread_name; + + if (attr_data.name_len && !vm::read_string(attr_data.name.addr(), attr_data.name_len - 1, thread_name, true)) + { + return { CELL_EFAULT, attr_data.name.addr() }; + } const auto group = idm::get_unlocked(group_id); @@ -906,7 +911,7 @@ error_code sys_spu_thread_get_exit_status(ppu_thread& ppu, u32 id, vm::ptr return CELL_ESTAT; } -error_code sys_spu_thread_group_create(ppu_thread& ppu, vm::ptr id, u32 num, s32 prio, vm::ptr attr) +error_code sys_spu_thread_group_create(ppu_thread& ppu, vm::ptr id, u32 num, s32 prio, vm::ptr attr) { ppu.state += cpu_flag::wait; @@ -914,13 +919,32 @@ error_code sys_spu_thread_group_create(ppu_thread& ppu, vm::ptr id, u32 num const s32 min_prio = g_ps3_process_info.has_root_perm() ? 0 : 16; - const sys_spu_thread_group_attribute attr_data = *attr; + sys_spu_thread_group_attribute attr_data{}; + { + const reduced_sys_spu_thread_group_attribute attr_reduced = *attr; + attr_data.name = attr_reduced.name; + attr_data.nsize = attr_reduced.nsize; + attr_data.type = attr_reduced.type; + + // Read container-id member at offset 12 bytes conditionally (that's what LV2 does) + if (attr_data.type & SYS_SPU_THREAD_GROUP_TYPE_MEMORY_FROM_CONTAINER) + { + attr_data.ct = vm::unsafe_ptr_cast(attr)->ct; + } + } if (attr_data.nsize > 0x80 || !num) { return CELL_EINVAL; } + std::string group_name; + + if (attr_data.nsize && !vm::read_string(attr_data.name.addr(), attr_data.nsize - 1, group_name, true)) + { + return { CELL_EFAULT, attr_data.name.addr() }; + } + const s32 type = attr_data.type; bool use_scheduler = true; @@ -1075,7 +1099,7 @@ error_code sys_spu_thread_group_create(ppu_thread& ppu, vm::ptr id, u32 num return CELL_EBUSY; } - const auto group = idm::make_ptr(std::string(attr_data.name.get_ptr(), std::max(attr_data.nsize, 1) - 1), num, prio, type, ct, use_scheduler, mem_size); + const auto group = idm::make_ptr(std::move(group_name), num, prio, type, ct, use_scheduler, mem_size); if (!group) { diff --git a/rpcs3/Emu/Cell/lv2/sys_spu.h b/rpcs3/Emu/Cell/lv2/sys_spu.h index 06e21e067b..3a0012b760 100644 --- a/rpcs3/Emu/Cell/lv2/sys_spu.h +++ b/rpcs3/Emu/Cell/lv2/sys_spu.h @@ -82,11 +82,18 @@ enum spu_stop_syscall : u32 SYS_SPU_THREAD_STOP_SWITCH_SYSTEM_MODULE = 0x0120, }; -struct sys_spu_thread_group_attribute +struct reduced_sys_spu_thread_group_attribute { be_t nsize; // name length including NULL terminator vm::bcptr name; be_t type; +}; + +struct sys_spu_thread_group_attribute +{ + be_t nsize; + vm::bcptr name; + be_t type; be_t ct; // memory container id }; @@ -360,7 +367,7 @@ error_code _sys_spu_image_close(ppu_thread&, vm::ptr img); error_code _sys_spu_image_get_segments(ppu_thread&, vm::ptr img, vm::ptr segments, s32 nseg); error_code sys_spu_thread_initialize(ppu_thread&, vm::ptr thread, u32 group, u32 spu_num, vm::ptr, vm::ptr, vm::ptr); error_code sys_spu_thread_set_argument(ppu_thread&, u32 id, vm::ptr arg); -error_code sys_spu_thread_group_create(ppu_thread&, vm::ptr id, u32 num, s32 prio, vm::ptr attr); +error_code sys_spu_thread_group_create(ppu_thread&, vm::ptr id, u32 num, s32 prio, vm::ptr attr); error_code sys_spu_thread_group_destroy(ppu_thread&, u32 id); error_code sys_spu_thread_group_start(ppu_thread&, u32 id); error_code sys_spu_thread_group_suspend(ppu_thread&, u32 id);