diff --git a/rpcs3/Emu/Cell/SPUThread.cpp b/rpcs3/Emu/Cell/SPUThread.cpp index 31bf027e06..d968431631 100644 --- a/rpcs3/Emu/Cell/SPUThread.cpp +++ b/rpcs3/Emu/Cell/SPUThread.cpp @@ -1733,21 +1733,48 @@ void spu_thread::cleanup() static_cast&>(*this) = thread_state::finished; } +enum : s64 +{ + SIGNED_LS_SIZE = SPU_LS_SIZE +}; + spu_thread::~spu_thread() { // Unmap LS and its mirrors - shm->unmap(ls + SPU_LS_SIZE); - shm->unmap(ls); - shm->unmap(ls - SPU_LS_SIZE); - utils::memory_release(ls - SPU_LS_SIZE * 2, SPU_LS_SIZE * 5); + for (s64 ls_offs = 0 - SIGNED_LS_SIZE * 2; ls_offs <= SIGNED_LS_SIZE * 2; ls_offs += SIGNED_LS_SIZE) + { + shm->unmap(ls + ls_offs); + } + + utils::memory_release(ls - SIGNED_LS_SIZE * 3, SIGNED_LS_SIZE * 7); } u8* spu_thread::map_ls(utils::shm& shm, void* ptr) { + const auto ls = ptr ? static_cast(ptr) : static_cast(ensure(utils::memory_reserve(SIGNED_LS_SIZE * 7, nullptr, true))) + SIGNED_LS_SIZE * 3; + vm::writer_lock mlock; - const auto ls = ptr ? static_cast(ptr) : static_cast(ensure(utils::memory_reserve(SPU_LS_SIZE * 5, nullptr, true))) + SPU_LS_SIZE * 2; - ensure(shm.map_critical(ls - SPU_LS_SIZE).first && shm.map_critical(ls).first && shm.map_critical(ls + SPU_LS_SIZE).first); + for (s64 ls_offs = 0 - SIGNED_LS_SIZE * 2; ls_offs <= SIGNED_LS_SIZE * 2; ls_offs += SIGNED_LS_SIZE) + { + const auto [ptr_ret, str] = shm.map_critical(ls + ls_offs); + + if (!ptr_ret) + { + fmt::throw_exception("spu_thread::map_ls() failed: map_critical returned error (error=%s) [ls_offs=0x%x]", str, ls_offs); + } + + if (ptr_ret != ls + ls_offs) + { + fmt::throw_exception("spu_thread::map_ls() failed: map_critical returned a different address: 0x%llx vs 0x%llx (error=%s) [ls_offs=0x%x]", ptr_ret, ls + ls_offs, str, ls_offs); + } + + if (!str.empty()) + { + fmt::throw_exception("spu_thread::map_ls() failed: map_critical returned unexpected error (error=%s) [ls_offs=0x%x]", str, ls_offs); + } + } + return ls; } @@ -1792,7 +1819,7 @@ spu_thread::spu_thread(lv2_spu_group* group, u32 index, std::string_view name, u , index(index) , thread_type(group ? spu_type::threaded : is_isolated ? spu_type::isolated : spu_type::raw) , shm(std::make_shared(SPU_LS_SIZE)) - , ls(static_cast(utils::memory_reserve(SPU_LS_SIZE * 5, nullptr, true)) + SPU_LS_SIZE * 2) + , ls(static_cast(utils::memory_reserve(SPU_LS_SIZE * 7, nullptr, true)) + SPU_LS_SIZE * 3) , option(option) , lv2_id(lv2_id) , spu_tname(make_single(name)) diff --git a/rpcs3/util/vm_native.cpp b/rpcs3/util/vm_native.cpp index c66c016a52..5b5c7746f1 100644 --- a/rpcs3/util/vm_native.cpp +++ b/rpcs3/util/vm_native.cpp @@ -909,9 +909,14 @@ namespace utils #ifdef _WIN32 ::MEMORY_BASIC_INFORMATION mem{}; - if (!::VirtualQuery(target, &mem, sizeof(mem)) || mem.State != MEM_RESERVE) + if (!::VirtualQuery(target, &mem, sizeof(mem))) { - return {nullptr, fmt::format("VirtualQuery() Unexpceted memory info: state=0x%x, %s", mem.State, std::as_bytes(std::span(&mem, 1)))}; + return {nullptr, fmt::format("VirtualQuery() Failed with %s", fmt::win_error{GetLastError(), nullptr})}; + } + + if (mem.State != MEM_RESERVE) + { + return {nullptr, fmt::format("VirtualQuery() reported unexpected memory info: state=0x%x, %s", mem.State, std::as_bytes(std::span(&mem, 1)))}; } const auto base = static_cast(mem.AllocationBase); @@ -977,8 +982,14 @@ namespace utils return {nullptr, "VirtualAlloc() failed to reserve allocation end"}; } #endif + const auto mapped_addr = this->map(target, prot, cow); - return {this->map(target, prot, cow), "Failed to map"}; + if (!mapped_addr) + { + return {nullptr, "Failed to map"}; + } + + return {mapped_addr, {}}; } u8* shm::map_self(protection prot)