From 5631382623004c749d9deb43c43a640382d0ef0e Mon Sep 17 00:00:00 2001 From: Eladash Date: Sun, 3 Nov 2019 01:44:02 +0200 Subject: [PATCH] sys_spu: Fix SPU Thread Id * Removed wrong code in sys_spu_thread_group_terminate. * SPU Thread ID is accurate, including 5th thread id "rule". * Fixed possible use-after-free access of spu_thread::group member. * RawSPU ID management simplified. --- Utilities/Thread.cpp | 13 +- rpcs3/Emu/Cell/RawSPUThread.cpp | 2 +- rpcs3/Emu/Cell/SPUThread.cpp | 13 +- rpcs3/Emu/Cell/SPUThread.h | 7 +- rpcs3/Emu/Cell/lv2/sys_spu.cpp | 193 ++++++++++++++---------------- rpcs3/Emu/Cell/lv2/sys_spu.h | 12 +- rpcs3/rpcs3qt/kernel_explorer.cpp | 2 +- 7 files changed, 122 insertions(+), 120 deletions(-) diff --git a/Utilities/Thread.cpp b/Utilities/Thread.cpp index f9c495178f..da5f79e36e 100644 --- a/Utilities/Thread.cpp +++ b/Utilities/Thread.cpp @@ -1319,14 +1319,15 @@ bool handle_access_violation(u32 addr, bool is_writing, x64_context* context) { data2 = (SYS_MEMORY_PAGE_FAULT_TYPE_PPU_THREAD << 32) | cpu->id; } - else if (static_cast(cpu)->group) - { - data2 = (SYS_MEMORY_PAGE_FAULT_TYPE_SPU_THREAD << 32) | cpu->id; - } else { - // Index is the correct ID in RawSPU - data2 = (SYS_MEMORY_PAGE_FAULT_TYPE_RAW_SPU << 32) | static_cast(cpu)->index; + const auto& spu = static_cast(*cpu); + + const u64 type = spu.offset < RAW_SPU_BASE_ADDR ? + SYS_MEMORY_PAGE_FAULT_TYPE_SPU_THREAD : + SYS_MEMORY_PAGE_FAULT_TYPE_RAW_SPU; + + data2 = (type << 32) | spu.lv2_id; } u64 data3; diff --git a/rpcs3/Emu/Cell/RawSPUThread.cpp b/rpcs3/Emu/Cell/RawSPUThread.cpp index 7c9e03dee5..73fcd4f2d9 100644 --- a/rpcs3/Emu/Cell/RawSPUThread.cpp +++ b/rpcs3/Emu/Cell/RawSPUThread.cpp @@ -266,7 +266,7 @@ bool spu_thread::write_reg(const u32 addr, const u32 value) void spu_load_exec(const spu_exec_object& elf) { auto ls0 = vm::cast(vm::falloc(RAW_SPU_BASE_ADDR, 0x80000, vm::spu)); - auto spu = idm::make_ptr>("TEST_SPU", ls0, nullptr, 0, ""); + auto spu = idm::make_ptr>("TEST_SPU", ls0, nullptr, 0, "", 0); spu_thread::g_raw_spu_ctr++; spu_thread::g_raw_spu_id[0] = spu->id; diff --git a/rpcs3/Emu/Cell/SPUThread.cpp b/rpcs3/Emu/Cell/SPUThread.cpp index 26d5aabd53..ed9b4931b6 100644 --- a/rpcs3/Emu/Cell/SPUThread.cpp +++ b/rpcs3/Emu/Cell/SPUThread.cpp @@ -991,7 +991,7 @@ spu_imm_table_t::spu_imm_table_t() std::string spu_thread::get_name() const { - return fmt::format("%sSPU[0x%x] Thread (%s)", offset >= RAW_SPU_BASE_ADDR ? "Raw" : "", id, spu_name.get()); + return fmt::format("%sSPU[0x%07x] Thread (%s)", offset >= RAW_SPU_BASE_ADDR ? "Raw" : "", lv2_id, spu_name.get()); } std::string spu_thread::dump() const @@ -1202,12 +1202,13 @@ spu_thread::~spu_thread() } } -spu_thread::spu_thread(vm::addr_t ls, lv2_spu_group* group, u32 index, std::string_view name) +spu_thread::spu_thread(vm::addr_t ls, lv2_spu_group* group, u32 index, std::string_view name, u32 lv2_id) : cpu_thread(idm::last_id()) , spu_name(name) , index(index) , offset(ls) , group(group) + , lv2_id(lv2_id) { if (g_cfg.core.spu_decoder == spu_decoder_type::asmjit) { @@ -1295,9 +1296,9 @@ void spu_thread::do_dma_transfer(const spu_mfc_cmd& args) { fmt::throw_exception("SPU MMIO used for RawSPU (cmd=0x%x, lsa=0x%x, ea=0x%llx, tag=0x%x, size=0x%x)" HERE, args.cmd, args.lsa, args.eal, args.tag, args.size); } - else if (group && group->threads[index]) + else if (group && group->threads_map[index] != -1) { - auto& spu = static_cast(*group->threads[index]); + auto& spu = static_cast(*group->threads[group->threads_map[index]]); if (offset + args.size - 1 < 0x40000) // LS access { @@ -2506,7 +2507,7 @@ bool spu_thread::set_ch_value(u32 ch, u32 value) ch_in_mbox.set_values(1, CELL_OK); - if (!queue->send(SYS_SPU_THREAD_EVENT_USER_KEY, id, (u64{spup} << 32) | (value & 0x00ffffff), data)) + if (!queue->send(SYS_SPU_THREAD_EVENT_USER_KEY, lv2_id, (u64{spup} << 32) | (value & 0x00ffffff), data)) { ch_in_mbox.set_values(1, CELL_EBUSY); } @@ -2536,7 +2537,7 @@ bool spu_thread::set_ch_value(u32 ch, u32 value) } // TODO: check passing spup value - if (!queue->send(SYS_SPU_THREAD_EVENT_USER_KEY, id, (u64{spup} << 32) | (value & 0x00ffffff), data)) + if (!queue->send(SYS_SPU_THREAD_EVENT_USER_KEY, lv2_id, (u64{spup} << 32) | (value & 0x00ffffff), data)) { LOG_WARNING(SPU, "sys_spu_thread_throw_event(spup=%d, data0=0x%x, data1=0x%x) failed (queue is full)", spup, (value & 0x00ffffff), data); } diff --git a/rpcs3/Emu/Cell/SPUThread.h b/rpcs3/Emu/Cell/SPUThread.h index f419be2789..dbe3db80ad 100644 --- a/rpcs3/Emu/Cell/SPUThread.h +++ b/rpcs3/Emu/Cell/SPUThread.h @@ -510,7 +510,7 @@ public: static const u32 id_step = 1; static const u32 id_count = 2048; - spu_thread(vm::addr_t ls, lv2_spu_group* group, u32 index, std::string_view name); + spu_thread(vm::addr_t ls, lv2_spu_group* group, u32 index, std::string_view name, u32 lv2_id); u32 pc = 0; @@ -575,7 +575,10 @@ public: const u32 index; // SPU index const u32 offset; // SPU LS offset - lv2_spu_group* const group; // SPU Thread Group +private: + lv2_spu_group* const group; // SPU Thread Group (only safe to access in the spu thread itself) +public: + const u32 lv2_id; // The actual id that is used by syscalls lf_value spu_name; // Thread name diff --git a/rpcs3/Emu/Cell/lv2/sys_spu.cpp b/rpcs3/Emu/Cell/lv2/sys_spu.cpp index b6835ec2a3..b957af2889 100644 --- a/rpcs3/Emu/Cell/lv2/sys_spu.cpp +++ b/rpcs3/Emu/Cell/lv2/sys_spu.cpp @@ -141,6 +141,29 @@ void sys_spu_image::deploy(u32 loc, sys_spu_segment* segs, u32 nsegs) LOG_NOTICE(LOADER, "Loaded SPU image: %s (<- %u)%s", hash, applied, dump); } +// Get spu thread ptr, returns group ptr as well for refcounting +std::pair*, std::shared_ptr> lv2_spu_group::get_thread(u32 id) +{ + if (id >= 0x06000000) + { + // thread index is out of range (5 max) + return {}; + } + + // Bits 0-23 contain group id (without id base) + decltype(get_thread(0)) res{nullptr, idm::get((id & 0xFFFFFF) | (lv2_spu_group::id_base & ~0xFFFFFF))}; + + // Bits 24-31 contain thread index within the group + const u32 index = id >> 24; + + if (auto group = res.second.get(); group && group->init > index) + { + res.first = group->threads[index].get(); + } + + return res; +} + error_code sys_spu_initialize(ppu_thread& ppu, u32 max_usable_spu, u32 max_raw_spu) { vm::temporary_unlock(ppu); @@ -253,9 +276,7 @@ error_code sys_spu_thread_initialize(ppu_thread& ppu, vm::ptr thread, u32 g return CELL_ESRCH; } - std::lock_guard lock(group->mutex); - - if (spu_num >= group->threads.size()) + if (spu_num >= group->threads_map.size()) { return CELL_EINVAL; } @@ -265,7 +286,9 @@ error_code sys_spu_thread_initialize(ppu_thread& ppu, vm::ptr thread, u32 g return CELL_EINVAL; } - if (group->threads[spu_num] || group->run_state != SPU_THREAD_GROUP_STATUS_NOT_INITIALIZED) + std::lock_guard lock(group->mutex); + + if (group->threads_map[spu_num] != -1 || group->run_state != SPU_THREAD_GROUP_STATUS_NOT_INITIALIZED) { return CELL_EBUSY; } @@ -292,26 +315,30 @@ error_code sys_spu_thread_initialize(ppu_thread& ppu, vm::ptr thread, u32 g const vm::addr_t ls_addr{verify("SPU LS" HERE, vm::alloc(0x80000, vm::main))}; - const u32 tid = idm::import>([&]() - { - const u32 tid = idm::last_id(); + const u32 inited = group->init; - std::string full_name = fmt::format("SPU[0x%x] Thread", tid); + const u32 tid = (inited << 24) | (group_id & 0xffffff); + + verify(HERE), idm::import>([&]() + { + std::string full_name = fmt::format("SPU[0x%07x] Thread", tid); if (!thread_name.empty()) { fmt::append(full_name, " (%s)", thread_name); } - group->threads[spu_num] = std::make_shared>(full_name, ls_addr, group.get(), spu_num, thread_name); - return group->threads[spu_num]; + const auto spu = std::make_shared>(full_name, ls_addr, group.get(), spu_num, thread_name, tid); + group->threads[inited] = spu; + group->threads_map[spu_num] = static_cast(inited); + return spu; }); *thread = tid; - group->args[spu_num] = {arg->arg1, arg->arg2, arg->arg3, arg->arg4}; - group->imgs[spu_num] = std::make_pair(image, std::vector()); - group->imgs[spu_num].second.assign(img->segs.get_ptr(), img->segs.get_ptr() + img->nsegs); + group->args[inited] = {arg->arg1, arg->arg2, arg->arg3, arg->arg4}; + group->imgs[inited].first = image; + group->imgs[inited].second.assign(img->segs.get_ptr(), img->segs.get_ptr() + img->nsegs); if (++group->init == group->max_num) { @@ -320,7 +347,7 @@ error_code sys_spu_thread_initialize(ppu_thread& ppu, vm::ptr thread, u32 g if (group->name.size() >= 20 && group->name.compare(group->name.size() - 20, 20, "CellSpursKernelGroup", 20) == 0) { // Hack: don't run more SPURS threads than specified. - group->init = g_cfg.core.max_spurs_threads; + group->max_run = g_cfg.core.max_spurs_threads; LOG_SUCCESS(SPU, "HACK: '%s' (0x%x) limited to %u threads.", group->name, group_id, +g_cfg.core.max_spurs_threads); } @@ -338,18 +365,16 @@ error_code sys_spu_thread_set_argument(ppu_thread& ppu, u32 id, vm::ptr>(id); + const auto [thread, group] = lv2_spu_group::get_thread(id); - if (UNLIKELY(!thread || !thread->group)) + if (UNLIKELY(!thread)) { return CELL_ESRCH; } - const auto group = thread->group; - std::lock_guard lock(group->mutex); - group->args[thread->index] = {arg->arg1, arg->arg2, arg->arg3, arg->arg4}; + group->args[id >> 24] = {arg->arg1, arg->arg2, arg->arg3, arg->arg4}; return CELL_OK; } @@ -360,9 +385,9 @@ error_code sys_spu_thread_get_exit_status(ppu_thread& ppu, u32 id, vm::ptr sys_spu.warning("sys_spu_thread_get_exit_status(id=0x%x, status=*0x%x)", id, status); - const auto thread = idm::get>(id); + const auto [thread, group] = lv2_spu_group::get_thread(id); - if (UNLIKELY(!thread || !thread->group)) + if (UNLIKELY(!thread)) { return CELL_ESRCH; } @@ -427,11 +452,11 @@ error_code sys_spu_thread_group_destroy(ppu_thread& ppu, u32 id) return group.ret; } - // Cleanup - for (auto& ptr : group->threads) + for (const auto& t : group->threads) { - if (auto thread = std::move(ptr)) + if (auto thread = t.get()) { + // Remove ID from IDM (destruction will occur in group destructor) idm::remove>(thread->id); } } @@ -463,23 +488,17 @@ error_code sys_spu_thread_group_start(ppu_thread& ppu, u32 id) std::lock_guard lock(group->mutex); - u32 max_threads = +group->init; + const u32 max_threads = group->max_run; group->join_state = 0; group->running = max_threads; - u32 run_threads = max_threads; for (auto& thread : group->threads) { - if (!run_threads) + if (thread) { - break; - } - - if (thread && run_threads--) - { - auto& args = group->args[thread->index]; - auto& img = group->imgs[thread->index]; + auto& args = group->args[thread->lv2_id >> 24]; + auto& img = group->imgs[thread->lv2_id >> 24]; sys_spu_image::deploy(thread->offset, img.second.data(), img.first.nsegs); @@ -653,35 +672,13 @@ error_code sys_spu_thread_group_terminate(ppu_thread& ppu, u32 id, s32 value) sys_spu.trace("sys_spu_thread_group_terminate(id=0x%x, value=0x%x)", id, value); - // The id can be either SPU Thread Group or SPU Thread - const auto thread = idm::get>(id); - const auto _group = idm::get(id); - const auto group = thread ? thread->group : _group.get(); + const auto group = idm::get(id); - if (!group && (!thread || !thread->group)) + if (!group) { return CELL_ESRCH; } - if (thread) - { - for (auto& t : group->threads) - { - // find primary (?) thread and compare it with the one specified - if (t) - { - if (t == thread) - { - break; - } - else - { - return CELL_EPERM; - } - } - } - } - std::unique_lock lock(group->mutex); if (group->run_state <= SPU_THREAD_GROUP_STATUS_INITIALIZED || @@ -863,15 +860,13 @@ error_code sys_spu_thread_write_ls(ppu_thread& ppu, u32 id, u32 lsa, u64 value, return CELL_EINVAL; } - const auto thread = idm::get>(id); + const auto [thread, group] = lv2_spu_group::get_thread(id); - if (UNLIKELY(!thread || !thread->group)) + if (UNLIKELY(!thread)) { return CELL_ESRCH; } - const auto group = thread->group; - std::lock_guard lock(group->mutex); if (group->run_state < SPU_THREAD_GROUP_STATUS_WAITING || group->run_state > SPU_THREAD_GROUP_STATUS_RUNNING) @@ -902,15 +897,13 @@ error_code sys_spu_thread_read_ls(ppu_thread& ppu, u32 id, u32 lsa, vm::ptr return CELL_EINVAL; } - const auto thread = idm::get>(id); + const auto [thread, group] = lv2_spu_group::get_thread(id); - if (UNLIKELY(!thread || !thread->group)) + if (UNLIKELY(!thread)) { return CELL_ESRCH; } - const auto group = thread->group; - std::lock_guard lock(group->mutex); if (group->run_state < SPU_THREAD_GROUP_STATUS_WAITING || group->run_state > SPU_THREAD_GROUP_STATUS_RUNNING) @@ -936,15 +929,13 @@ error_code sys_spu_thread_write_spu_mb(ppu_thread& ppu, u32 id, u32 value) sys_spu.warning("sys_spu_thread_write_spu_mb(id=0x%x, value=0x%x)", id, value); - const auto thread = idm::get>(id); + const auto [thread, group] = lv2_spu_group::get_thread(id); - if (UNLIKELY(!thread || !thread->group)) + if (UNLIKELY(!thread)) { return CELL_ESRCH; } - const auto group = thread->group; - std::lock_guard lock(group->mutex); thread->ch_in_mbox.push(*thread, value); @@ -963,9 +954,9 @@ error_code sys_spu_thread_set_spu_cfg(ppu_thread& ppu, u32 id, u64 value) return CELL_EINVAL; } - const auto thread = idm::get>(id); + const auto [thread, group] = lv2_spu_group::get_thread(id); - if (UNLIKELY(!thread || !thread->group)) + if (UNLIKELY(!thread)) { return CELL_ESRCH; } @@ -981,9 +972,9 @@ error_code sys_spu_thread_get_spu_cfg(ppu_thread& ppu, u32 id, vm::ptr valu sys_spu.warning("sys_spu_thread_get_spu_cfg(id=0x%x, value=*0x%x)", id, value); - const auto thread = idm::get>(id); + const auto [thread, group] = lv2_spu_group::get_thread(id); - if (UNLIKELY(!thread || !thread->group)) + if (UNLIKELY(!thread)) { return CELL_ESRCH; } @@ -999,9 +990,9 @@ error_code sys_spu_thread_write_snr(ppu_thread& ppu, u32 id, u32 number, u32 val sys_spu.trace("sys_spu_thread_write_snr(id=0x%x, number=%d, value=0x%x)", id, number, value); - const auto thread = idm::get>(id); + const auto [thread, group] = lv2_spu_group::get_thread(id); - if (UNLIKELY(!thread || !thread->group)) + if (UNLIKELY(!thread)) { return CELL_ESRCH; } @@ -1102,10 +1093,10 @@ error_code sys_spu_thread_connect_event(ppu_thread& ppu, u32 id, u32 eq, u32 et, sys_spu.warning("sys_spu_thread_connect_event(id=0x%x, eq=0x%x, et=%d, spup=%d)", id, eq, et, spup); - const auto thread = idm::get>(id); + const auto [thread, group] = lv2_spu_group::get_thread(id); const auto queue = idm::get(eq); - if (UNLIKELY(!queue || !thread || !thread->group)) + if (UNLIKELY(!queue || !thread)) { return CELL_ESRCH; } @@ -1116,7 +1107,7 @@ error_code sys_spu_thread_connect_event(ppu_thread& ppu, u32 id, u32 eq, u32 et, return CELL_EINVAL; } - std::lock_guard lock(thread->group->mutex); + std::lock_guard lock(group->mutex); auto& port = thread->spup[spup]; @@ -1136,9 +1127,9 @@ error_code sys_spu_thread_disconnect_event(ppu_thread& ppu, u32 id, u32 et, u8 s sys_spu.warning("sys_spu_thread_disconnect_event(id=0x%x, et=%d, spup=%d)", id, et, spup); - const auto thread = idm::get>(id); + const auto [thread, group] = lv2_spu_group::get_thread(id); - if (UNLIKELY(!thread || !thread->group)) + if (UNLIKELY(!thread)) { return CELL_ESRCH; } @@ -1149,7 +1140,7 @@ error_code sys_spu_thread_disconnect_event(ppu_thread& ppu, u32 id, u32 et, u8 s return CELL_EINVAL; } - std::lock_guard lock(thread->group->mutex); + std::lock_guard lock(group->mutex); auto& port = thread->spup[spup]; @@ -1169,10 +1160,10 @@ error_code sys_spu_thread_bind_queue(ppu_thread& ppu, u32 id, u32 spuq, u32 spuq sys_spu.warning("sys_spu_thread_bind_queue(id=0x%x, spuq=0x%x, spuq_num=0x%x)", id, spuq, spuq_num); - const auto thread = idm::get>(id); + const auto [thread, group] = lv2_spu_group::get_thread(id); const auto queue = idm::get(spuq); - if (UNLIKELY(!queue || !thread || !thread->group)) + if (UNLIKELY(!queue || !thread)) { return CELL_ESRCH; } @@ -1182,7 +1173,7 @@ error_code sys_spu_thread_bind_queue(ppu_thread& ppu, u32 id, u32 spuq, u32 spuq return CELL_EINVAL; } - std::lock_guard lock(thread->group->mutex); + std::lock_guard lock(group->mutex); decltype(std::data(thread->spuq)) q{}; @@ -1223,14 +1214,14 @@ error_code sys_spu_thread_unbind_queue(ppu_thread& ppu, u32 id, u32 spuq_num) sys_spu.warning("sys_spu_thread_unbind_queue(id=0x%x, spuq_num=0x%x)", id, spuq_num); - const auto thread = idm::get>(id); + const auto [thread, group] = lv2_spu_group::get_thread(id); - if (UNLIKELY(!thread || !thread->group)) + if (UNLIKELY(!thread)) { return CELL_ESRCH; } - std::lock_guard lock(thread->group->mutex); + std::lock_guard lock(group->mutex); for (auto& v : thread->spuq) { @@ -1399,9 +1390,9 @@ error_code sys_spu_thread_recover_page_fault(ppu_thread& ppu, u32 id) sys_spu.warning("sys_spu_thread_recover_page_fault(id=0x%x)", id); - const auto thread = idm::get>(id); + const auto [thread, group] = lv2_spu_group::get_thread(id); - if (UNLIKELY(!thread || !thread->group)) + if (UNLIKELY(!thread)) { return CELL_ESRCH; } @@ -1417,7 +1408,7 @@ error_code sys_raw_spu_recover_page_fault(ppu_thread& ppu, u32 id) const auto thread = idm::get>(spu_thread::find_raw_spu(id)); - if (UNLIKELY(!thread || thread->group)) + if (UNLIKELY(!thread)) { return CELL_ESRCH; } @@ -1449,7 +1440,7 @@ error_code sys_raw_spu_create(ppu_thread& ppu, vm::ptr id, vm::ptr at const vm::addr_t ls_addr{verify(HERE, vm::falloc(RAW_SPU_BASE_ADDR + RAW_SPU_OFFSET * index, 0x40000, vm::spu))}; - const u32 tid = idm::make>(fmt::format("RawSPU[0x%x] Thread", index), ls_addr, nullptr, index, ""); + const u32 tid = idm::make>(fmt::format("RawSPU[0x%x] Thread", index), ls_addr, nullptr, index, "", index); spu_thread::g_raw_spu_id[index] = verify("RawSPU ID" HERE, tid); @@ -1466,7 +1457,7 @@ error_code sys_raw_spu_destroy(ppu_thread& ppu, u32 id) const auto thread = idm::get>(spu_thread::find_raw_spu(id)); - if (UNLIKELY(!thread || thread->group)) + if (UNLIKELY(!thread)) { return CELL_ESRCH; } @@ -1538,7 +1529,7 @@ error_code sys_raw_spu_create_interrupt_tag(ppu_thread& ppu, u32 id, u32 class_i auto thread = idm::check_unlocked>(spu_thread::find_raw_spu(id)); - if (!thread || thread->group) + if (!thread) { error = CELL_ESRCH; return result; @@ -1579,7 +1570,7 @@ error_code sys_raw_spu_set_int_mask(ppu_thread& ppu, u32 id, u32 class_id, u64 m const auto thread = idm::get>(spu_thread::find_raw_spu(id)); - if (UNLIKELY(!thread || thread->group)) + if (UNLIKELY(!thread)) { return CELL_ESRCH; } @@ -1602,7 +1593,7 @@ error_code sys_raw_spu_get_int_mask(ppu_thread& ppu, u32 id, u32 class_id, vm::p const auto thread = idm::get>(spu_thread::find_raw_spu(id)); - if (UNLIKELY(!thread || thread->group)) + if (UNLIKELY(!thread)) { return CELL_ESRCH; } @@ -1625,7 +1616,7 @@ error_code sys_raw_spu_set_int_stat(ppu_thread& ppu, u32 id, u32 class_id, u64 s const auto thread = idm::get>(spu_thread::find_raw_spu(id)); - if (UNLIKELY(!thread || thread->group)) + if (UNLIKELY(!thread)) { return CELL_ESRCH; } @@ -1648,7 +1639,7 @@ error_code sys_raw_spu_get_int_stat(ppu_thread& ppu, u32 id, u32 class_id, vm::p const auto thread = idm::get>(spu_thread::find_raw_spu(id)); - if (UNLIKELY(!thread || thread->group)) + if (UNLIKELY(!thread)) { return CELL_ESRCH; } @@ -1666,7 +1657,7 @@ error_code sys_raw_spu_read_puint_mb(ppu_thread& ppu, u32 id, vm::ptr value const auto thread = idm::get>(spu_thread::find_raw_spu(id)); - if (UNLIKELY(!thread || thread->group)) + if (UNLIKELY(!thread)) { return CELL_ESRCH; } @@ -1689,7 +1680,7 @@ error_code sys_raw_spu_set_spu_cfg(ppu_thread& ppu, u32 id, u32 value) const auto thread = idm::get>(spu_thread::find_raw_spu(id)); - if (UNLIKELY(!thread || thread->group)) + if (UNLIKELY(!thread)) { return CELL_ESRCH; } @@ -1707,7 +1698,7 @@ error_code sys_raw_spu_get_spu_cfg(ppu_thread& ppu, u32 id, vm::ptr value) const auto thread = idm::get>(spu_thread::find_raw_spu(id)); - if (UNLIKELY(!thread || thread->group)) + if (UNLIKELY(!thread)) { return CELL_ESRCH; } diff --git a/rpcs3/Emu/Cell/lv2/sys_spu.h b/rpcs3/Emu/Cell/lv2/sys_spu.h index 1edb65c856..0ea8506533 100644 --- a/rpcs3/Emu/Cell/lv2/sys_spu.h +++ b/rpcs3/Emu/Cell/lv2/sys_spu.h @@ -241,6 +241,7 @@ struct lv2_spu_group const u32 max_num; const s32 type; // SPU Thread Group Type const u32 ct; // Memory Container Id + u32 max_run; shared_mutex mutex; @@ -254,9 +255,10 @@ struct lv2_spu_group atomic_t stop_count; class ppu_thread* waiter = nullptr; - std::array>, 256> threads; // SPU Threads - std::array>, 256> imgs; // SPU Images - std::array, 256> args; // SPU Thread Arguments + std::array>, 8> threads; // SPU Threads + std::array threads_map; // SPU Threads map based number + std::array>, 8> imgs; // SPU Images + std::array, 8> args; // SPU Thread Arguments std::weak_ptr ep_run; // port for SYS_SPU_THREAD_GROUP_EVENT_RUN events std::weak_ptr ep_exception; // TODO: SYS_SPU_THREAD_GROUP_EVENT_EXCEPTION @@ -266,6 +268,7 @@ struct lv2_spu_group : id(idm::last_id()) , name(name) , max_num(num) + , max_run(num) , init(0) , prio(prio) , type(type) @@ -276,6 +279,7 @@ struct lv2_spu_group , running(0) , stop_count(0) { + threads_map.fill(-1); } void send_run_event(u64 data1, u64 data2, u64 data3) @@ -301,6 +305,8 @@ struct lv2_spu_group queue->send(SYS_SPU_THREAD_GROUP_EVENT_SYSTEM_MODULE_KEY, data1, data2, data3); } } + + static std::pair*, std::shared_ptr> get_thread(u32 id); }; class ppu_thread; diff --git a/rpcs3/rpcs3qt/kernel_explorer.cpp b/rpcs3/rpcs3qt/kernel_explorer.cpp index e725094f26..235faeb358 100644 --- a/rpcs3/rpcs3qt/kernel_explorer.cpp +++ b/rpcs3/rpcs3qt/kernel_explorer.cpp @@ -281,7 +281,7 @@ void kernel_explorer::Update() idm::select>([&](u32 id, spu_thread& spu) { lv2_types.back().count++; - l_addTreeChild(lv2_types.back().node, qstr(fmt::format("SPU Thread: ID = 0x%08x '%s'", id, spu.spu_name.get()))); + l_addTreeChild(lv2_types.back().node, qstr(fmt::format("SPU Thread: ID = 0x%08x '%s'", spu.lv2_id, spu.spu_name.get()))); }); lv2_types.emplace_back(l_addTreeChild(root, "SPU Thread Groups"));