diff --git a/Utilities/Thread.cpp b/Utilities/Thread.cpp index fc650320c6..05864168df 100644 --- a/Utilities/Thread.cpp +++ b/Utilities/Thread.cpp @@ -1594,21 +1594,27 @@ static LONG exception_handler(PEXCEPTION_POINTERS pExp) noexcept return EXCEPTION_CONTINUE_SEARCH; } - const u64 addr64 = pExp->ExceptionRecord->ExceptionInformation[1] - reinterpret_cast(vm::g_base_addr); - const u64 exec64 = (pExp->ExceptionRecord->ExceptionInformation[1] - reinterpret_cast(vm::g_exec_addr)) / 2; + const auto ptr = reinterpret_cast(pExp->ExceptionRecord->ExceptionInformation[1]); const bool is_writing = pExp->ExceptionRecord->ExceptionInformation[0] != 0; - if (pExp->ExceptionRecord->ExceptionCode == EXCEPTION_ACCESS_VIOLATION && addr64 < 0x100000000ull) + if (pExp->ExceptionRecord->ExceptionCode == EXCEPTION_ACCESS_VIOLATION) { - if (thread_ctrl::get_current() && handle_access_violation(static_cast(addr64), is_writing, pExp->ContextRecord)) - { - return EXCEPTION_CONTINUE_EXECUTION; - } - } + u32 addr = 0; - if (pExp->ExceptionRecord->ExceptionCode == EXCEPTION_ACCESS_VIOLATION && exec64 < 0x100000000ull) - { - if (thread_ctrl::get_current() && handle_access_violation(static_cast(exec64), is_writing, pExp->ContextRecord)) + if (auto [addr0, ok] = vm::try_get_addr(ptr); ok) + { + addr = addr0; + } + else if (const usz exec64 = (ptr - vm::g_exec_addr) / 2; exec64 <= UINT32_MAX) + { + addr = static_cast(exec64); + } + else + { + return EXCEPTION_CONTINUE_SEARCH; + } + + if (thread_ctrl::get_current() && handle_access_violation(addr, is_writing, pExp->ContextRecord)) { return EXCEPTION_CONTINUE_EXECUTION; } @@ -1749,14 +1755,13 @@ static void signal_handler(int sig, siginfo_t* info, void* uct) noexcept const bool is_writing = context->uc_mcontext.gregs[REG_ERR] & 0x2; #endif - const u64 addr64 = reinterpret_cast(info->si_addr) - reinterpret_cast(vm::g_base_addr); const u64 exec64 = (reinterpret_cast(info->si_addr) - reinterpret_cast(vm::g_exec_addr)) / 2; const auto cause = is_writing ? "writing" : "reading"; - if (addr64 < 0x100000000ull) + if (auto [addr, ok] = vm::try_get_addr(info->si_addr); ok) { // Try to process access violation - if (thread_ctrl::get_current() && handle_access_violation(static_cast(addr64), is_writing, context)) + if (thread_ctrl::get_current() && handle_access_violation(addr, is_writing, context)) { return; } diff --git a/rpcs3/Emu/Memory/vm.cpp b/rpcs3/Emu/Memory/vm.cpp index f77048c734..31926844d5 100644 --- a/rpcs3/Emu/Memory/vm.cpp +++ b/rpcs3/Emu/Memory/vm.cpp @@ -39,10 +39,10 @@ namespace vm } // Emulated virtual memory - u8* const g_base_addr = memory_reserve_4GiB(reinterpret_cast(0x2'0000'0000)); + u8* const g_base_addr = memory_reserve_4GiB(reinterpret_cast(0x2'0000'0000), 0x2'0000'0000); // Unprotected virtual memory mirror - u8* const g_sudo_addr = memory_reserve_4GiB(g_base_addr); + u8* const g_sudo_addr = g_base_addr + 0x1'0000'0000; // Auxiliary virtual memory for executable areas u8* const g_exec_addr = memory_reserve_4GiB(g_sudo_addr, 0x200000000); @@ -1671,7 +1671,7 @@ namespace vm { g_locations.clear(); - utils::memory_decommit(g_base_addr, 0x100000000); + utils::memory_decommit(g_base_addr, 0x200000000); utils::memory_decommit(g_exec_addr, 0x100000000); utils::memory_decommit(g_stat_addr, 0x100000000); } diff --git a/rpcs3/Emu/Memory/vm.h b/rpcs3/Emu/Memory/vm.h index b8b91a7e2e..9bde46a236 100644 --- a/rpcs3/Emu/Memory/vm.h +++ b/rpcs3/Emu/Memory/vm.h @@ -146,23 +146,30 @@ namespace vm // Allocate segment at specified location, does nothing if exists already std::shared_ptr reserve_map(memory_location_t location, u32 addr, u32 area_size, u64 flags = 0x200); - // Get PS3/PSV virtual memory address from the provided pointer (nullptr always converted to 0) - inline vm::addr_t get_addr(const void* real_ptr) + // Get PS3 virtual memory address from the provided pointer (nullptr or pointer from outside is always converted to 0) + // Super memory is allowed as well + inline std::pair try_get_addr(const void* real_ptr) { - if (!real_ptr) + const std::make_unsigned_t diff = static_cast(real_ptr) - g_base_addr; + + if (diff <= u64{UINT32_MAX} * 2 + 1) { - return vm::addr_t{}; + return {vm::addr_t{static_cast(diff)}, true}; } - const std::ptrdiff_t diff = static_cast(real_ptr) - g_base_addr; - const u32 res = static_cast(diff); + return {}; + } - if (res == diff) + inline vm::addr_t get_addr(const void* ptr) + { + const auto [addr, ok] = try_get_addr(ptr); + + if (!ok) { - return static_cast(res); + fmt::throw_exception("Not a virtual memory pointer (%p)", ptr); } - fmt::throw_exception("Not a virtual memory pointer (%p)", real_ptr); + return addr; } template diff --git a/rpcs3/Emu/RSX/RSXOffload.cpp b/rpcs3/Emu/RSX/RSXOffload.cpp index ed6c710c46..d80f842e5f 100644 --- a/rpcs3/Emu/RSX/RSXOffload.cpp +++ b/rpcs3/Emu/RSX/RSXOffload.cpp @@ -228,10 +228,6 @@ namespace rsx fmt::throw_exception("Unreachable"); } - const uptr addr = uptr(address); - const uptr base = uptr(vm::g_base_addr); - - ensure(addr > base); - return utils::address_range::start_length(u32(addr - base), range); + return utils::address_range::start_length(vm::get_addr(address), range); } }