From eaf0bbc108c10f79a16b17240986d7afd6338fd1 Mon Sep 17 00:00:00 2001 From: Nekotekina Date: Sun, 15 Nov 2020 07:37:56 +0300 Subject: [PATCH] SPU: don't allocate SPU LS in vm::main Create its own shared memory object. Use vm::spu to allocate all SPU types. Use vm::writer_lock for shm::map_critical. --- rpcs3/Emu/Cell/RawSPUThread.cpp | 8 ++++---- rpcs3/Emu/Cell/SPUThread.cpp | 29 ++++++++++++++++++++++------- rpcs3/Emu/Cell/SPUThread.h | 13 ++++++++++--- rpcs3/Emu/Cell/lv2/sys_spu.cpp | 15 +++++++-------- rpcs3/Emu/Memory/vm.cpp | 4 ++-- 5 files changed, 45 insertions(+), 24 deletions(-) diff --git a/rpcs3/Emu/Cell/RawSPUThread.cpp b/rpcs3/Emu/Cell/RawSPUThread.cpp index cb0075d637..b574f582a1 100644 --- a/rpcs3/Emu/Cell/RawSPUThread.cpp +++ b/rpcs3/Emu/Cell/RawSPUThread.cpp @@ -28,7 +28,7 @@ inline void try_start(spu_thread& spu) bool spu_thread::read_reg(const u32 addr, u32& value) { - const u32 offset = addr - this->offset - RAW_SPU_PROB_OFFSET; + const u32 offset = addr - (RAW_SPU_BASE_ADDR + RAW_SPU_OFFSET * index) - RAW_SPU_PROB_OFFSET; spu_log.trace("RawSPU[%u]: Read32(0x%x, offset=0x%x)", index, addr, offset); @@ -165,7 +165,7 @@ bool spu_thread::read_reg(const u32 addr, u32& value) bool spu_thread::write_reg(const u32 addr, const u32 value) { - const u32 offset = addr - this->offset - RAW_SPU_PROB_OFFSET; + const u32 offset = addr - (RAW_SPU_BASE_ADDR + RAW_SPU_OFFSET * index) - RAW_SPU_PROB_OFFSET; spu_log.trace("RawSPU[%u]: Write32(0x%x, offset=0x%x, value=0x%x)", index, addr, offset, value); @@ -321,7 +321,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, SPU_LS_SIZE, vm::spu)); + auto ls0 = vm::addr_t{RAW_SPU_BASE_ADDR}; spu_thread::g_raw_spu_ctr++; @@ -333,7 +333,7 @@ void spu_load_exec(const spu_exec_object& elf) } } - auto spu = idm::make_ptr>("TEST_SPU", ls0, nullptr, 0, "", 0); + auto spu = idm::make_ptr>("TEST_SPU", nullptr, 0, "", 0); spu_thread::g_raw_spu_id[0] = spu->id; diff --git a/rpcs3/Emu/Cell/SPUThread.cpp b/rpcs3/Emu/Cell/SPUThread.cpp index beda025ba8..bd6803decf 100644 --- a/rpcs3/Emu/Cell/SPUThread.cpp +++ b/rpcs3/Emu/Cell/SPUThread.cpp @@ -1384,6 +1384,8 @@ std::string spu_thread::dump_misc() const fmt::append(ret, "...chunk-0x%05x", (name & 0xffff) * 4); } + const u32 offset = group ? SPU_FAKE_BASE_ADDR + (id & 0xffffff) * SPU_LS_SIZE : RAW_SPU_BASE_ADDR + index * RAW_SPU_OFFSET; + fmt::append(ret, "\n[%s]", ch_mfc_cmd); fmt::append(ret, "\nLocal Storage: 0x%08x..0x%08x", offset, offset + 0x3ffff); @@ -1624,16 +1626,19 @@ void spu_thread::cpu_task() spu_thread::~spu_thread() { { - const auto [_, shm] = vm::get(vm::any, offset)->get(offset); + vm::writer_lock(0); for (s32 i = -1; i < 2; i++) { // Unmap LS mirrors shm->unmap_critical(ls + (i * SPU_LS_SIZE)); } + } - // Deallocate Local Storage - vm::dealloc_verbose_nothrow(offset); + if (!group) + { + // Deallocate local storage (thread groups are handled in sys_spu.cpp) + vm::dealloc_verbose_nothrow(RAW_SPU_BASE_ADDR + RAW_SPU_OFFSET * index, vm::spu); } // Release LS mirrors area @@ -1653,14 +1658,25 @@ spu_thread::~spu_thread() perf_log.notice("Perf stats for PUTLLC reload: successs %u, failure %u", last_succ, last_fail); } -spu_thread::spu_thread(vm::addr_t _ls, lv2_spu_group* group, u32 index, std::string_view name, u32 lv2_id, bool is_isolated, u32 option) +spu_thread::spu_thread(lv2_spu_group* group, u32 index, std::string_view name, u32 lv2_id, bool is_isolated, u32 option) : cpu_thread(idm::last_id()) , index(index) + , shm(std::make_shared(SPU_LS_SIZE)) , ls([&]() { - const auto [_, shm] = vm::get(vm::any, _ls)->get(_ls); const auto addr = static_cast(utils::memory_reserve(SPU_LS_SIZE * 5)); + if (!group) + { + vm::get(vm::spu)->falloc(RAW_SPU_BASE_ADDR + RAW_SPU_OFFSET * index, SPU_LS_SIZE, &shm); + } + else + { + vm::get(vm::spu)->falloc(SPU_FAKE_BASE_ADDR + SPU_LS_SIZE * (cpu_thread::id & 0xffffff), SPU_LS_SIZE, &shm); + } + + vm::writer_lock(0); + for (u32 i = 1; i < 4; i++) { // Map LS mirrors @@ -1672,7 +1688,6 @@ spu_thread::spu_thread(vm::addr_t _ls, lv2_spu_group* group, u32 index, std::str return addr + (SPU_LS_SIZE * 2); }()) , thread_type(group ? spu_type::threaded : is_isolated ? spu_type::isolated : spu_type::raw) - , offset(_ls) , group(group) , option(option) , lv2_id(lv2_id) @@ -1837,7 +1852,7 @@ void spu_thread::do_dma_transfer(spu_thread* _this, const spu_mfc_cmd& args, u8* if (offset + args.size - 1 < SPU_LS_SIZE) // LS access { - eal = spu.offset + offset; // redirect access + eal = SPU_FAKE_BASE_ADDR * (spu.id & 0xffffff) + offset; // redirect access } else if (!is_get && args.size == 4 && (offset == SYS_SPU_THREAD_SNR1 || offset == SYS_SPU_THREAD_SNR2)) { diff --git a/rpcs3/Emu/Cell/SPUThread.h b/rpcs3/Emu/Cell/SPUThread.h index 6f00fe998b..0ab76b025c 100644 --- a/rpcs3/Emu/Cell/SPUThread.h +++ b/rpcs3/Emu/Cell/SPUThread.h @@ -14,6 +14,11 @@ struct lv2_event_queue; struct lv2_spu_group; struct lv2_int_tag; +namespace utils +{ + class shm; +} + // JIT Block using spu_function_t = void(*)(spu_thread&, void*, u8*); @@ -157,6 +162,8 @@ enum : u32 RAW_SPU_OFFSET = 0x00100000, RAW_SPU_LS_OFFSET = 0x00000000, RAW_SPU_PROB_OFFSET = 0x00040000, + + SPU_FAKE_BASE_ADDR = 0xE8000000, }; struct spu_channel @@ -629,9 +636,9 @@ public: static const u32 id_base = 0x02000000; // TODO (used to determine thread type) static const u32 id_step = 1; - static const u32 id_count = 2048; + static const u32 id_count = (0xF0000000 - SPU_FAKE_BASE_ADDR) / SPU_LS_SIZE; - spu_thread(vm::addr_t ls, lv2_spu_group* group, u32 index, std::string_view name, u32 lv2_id, bool is_isolated = false, u32 option = 0); + spu_thread(lv2_spu_group* group, u32 index, std::string_view name, u32 lv2_id, bool is_isolated = false, u32 option = 0); u32 pc = 0; @@ -730,10 +737,10 @@ public: atomic_t last_exit_status; // Value to be written in exit_status after checking group termination const u32 index; // SPU index + std::shared_ptr shm; // SPU memory const std::add_pointer_t ls; // SPU LS pointer const spu_type thread_type; private: - const u32 offset; // SPU LS offset lv2_spu_group* const group; // SPU Thread Group (only safe to access in the spu thread itself) public: const u32 option; // sys_spu_thread_initialize option diff --git a/rpcs3/Emu/Cell/lv2/sys_spu.cpp b/rpcs3/Emu/Cell/lv2/sys_spu.cpp index dea049def1..afe3151fd0 100644 --- a/rpcs3/Emu/Cell/lv2/sys_spu.cpp +++ b/rpcs3/Emu/Cell/lv2/sys_spu.cpp @@ -399,8 +399,6 @@ error_code sys_spu_thread_initialize(ppu_thread& ppu, vm::ptr thread, u32 g sys_spu.warning("Unimplemented SPU Thread options (0x%x)", option); } - const vm::addr_t ls_addr{verify("SPU LS" HERE, vm::alloc(SPU_LS_SIZE, vm::main))}; - const u32 inited = group->init; const u32 tid = (inited << 24) | (group_id & 0xffffff); @@ -414,7 +412,7 @@ error_code sys_spu_thread_initialize(ppu_thread& ppu, vm::ptr thread, u32 g fmt::append(full_name, "%s ", thread_name); } - const auto spu = std::make_shared>(full_name, ls_addr, group.get(), spu_num, thread_name, tid, false, option); + const auto spu = std::make_shared>(full_name, group.get(), spu_num, thread_name, tid, false, option); group->threads[inited] = spu; group->threads_map[spu_num] = static_cast(inited); return spu; @@ -683,6 +681,9 @@ error_code sys_spu_thread_group_destroy(ppu_thread& ppu, u32 id) { if (auto thread = t.get()) { + // Deallocate LS + vm::get(vm::spu)->dealloc(SPU_FAKE_BASE_ADDR + SPU_LS_SIZE * (thread->id & 0xffffff), &thread->shm); + // Remove ID from IDM (destruction will occur in group destructor) idm::remove>(thread->id); } @@ -1845,9 +1846,7 @@ error_code sys_raw_spu_create(ppu_thread& ppu, vm::ptr id, vm::ptr at index = 0; } - const vm::addr_t ls_addr{verify(HERE, vm::falloc(RAW_SPU_BASE_ADDR + RAW_SPU_OFFSET * index, SPU_LS_SIZE, vm::spu))}; - - const u32 tid = idm::make>(fmt::format("RawSPU[0x%x] ", index), ls_addr, nullptr, index, "", index); + const u32 tid = idm::make>(fmt::format("RawSPU[0x%x] ", index), nullptr, index, "", index); spu_thread::g_raw_spu_id[index] = verify("RawSPU ID" HERE, tid); @@ -1893,9 +1892,9 @@ error_code sys_isolated_spu_create(ppu_thread& ppu, vm::ptr id, vm::ptr>(fmt::format("IsoSPU[0x%x] ", index), ls_addr, nullptr, index, "", index, true); + const auto thread = idm::make_ptr>(fmt::format("IsoSPU[0x%x] ", index), nullptr, index, "", index, true); thread->gpr[3] = v128::from64(0, arg1); thread->gpr[4] = v128::from64(0, arg2); diff --git a/rpcs3/Emu/Memory/vm.cpp b/rpcs3/Emu/Memory/vm.cpp index c483e3581f..b41ca5d49d 100644 --- a/rpcs3/Emu/Memory/vm.cpp +++ b/rpcs3/Emu/Memory/vm.cpp @@ -1313,10 +1313,10 @@ namespace vm return {addr, nullptr}; } - // Special path + // Special case if (m_common) { - return {this->addr, m_common}; + return {addr, nullptr}; } // Range check