diff --git a/Utilities/Thread.cpp b/Utilities/Thread.cpp index b85b96691a..568d262351 100644 --- a/Utilities/Thread.cpp +++ b/Utilities/Thread.cpp @@ -292,47 +292,39 @@ bool handle_access_violation(const u32 addr, x64_context* context) void _se_translator(unsigned int u, EXCEPTION_POINTERS* pExp) { - const u64 addr64 = (u64)pExp->ExceptionRecord->ExceptionInformation[1] - (u64)Memory.GetBaseAddr(); + const u64 addr64 = (u64)pExp->ExceptionRecord->ExceptionInformation[1] - (u64)vm::g_base_addr; const bool is_writing = pExp->ExceptionRecord->ExceptionInformation[0] != 0; + if (u == EXCEPTION_ACCESS_VIOLATION && (u32)addr64 == addr64) { - if (handle_access_violation((u32)addr64, pExp->ContextRecord)) - { - // restore context (further code shouldn't be reached) - RtlRestoreContext(pExp->ContextRecord, nullptr); - - // it's dangerous because destructors won't be executed - } - throw fmt::format("Access violation %s location 0x%llx", is_writing ? "writing" : "reading", addr64); } - - // else some fatal error (should crash) } -extern LPTOP_LEVEL_EXCEPTION_FILTER filter_set; - -LONG __stdcall exception_filter(_EXCEPTION_POINTERS* pExp) +const PVOID exception_handler = (atexit([]{ RemoveVectoredExceptionHandler(exception_handler); }), AddVectoredExceptionHandler(1, [](PEXCEPTION_POINTERS pExp) -> LONG { - _se_translator(pExp->ExceptionRecord->ExceptionCode, pExp); + const u64 addr64 = (u64)pExp->ExceptionRecord->ExceptionInformation[1] - (u64)vm::g_base_addr; - if (filter_set) + if (pExp->ExceptionRecord->ExceptionCode == EXCEPTION_ACCESS_VIOLATION && + (u32)addr64 == addr64 && + GetCurrentNamedThread() && + handle_access_violation((u32)addr64, pExp->ContextRecord)) { - return filter_set(pExp); + return EXCEPTION_CONTINUE_EXECUTION; } else { return EXCEPTION_CONTINUE_SEARCH; } -} - -LPTOP_LEVEL_EXCEPTION_FILTER filter_set = SetUnhandledExceptionFilter(exception_filter); +})); #else void signal_handler(int sig, siginfo_t* info, void* uct) { - const u64 addr64 = (u64)info->si_addr - (u64)Memory.GetBaseAddr(); + const u64 addr64 = (u64)info->si_addr - (u64)vm::g_base_addr; + const bool is_writing = ((ucontext_t*)uct)->uc_mcontext.gregs[REG_ERR] & 0x2; + if ((u32)addr64 == addr64 && GetCurrentNamedThread()) { if (handle_access_violation((u32)addr64, (ucontext_t*)uct)) @@ -341,7 +333,7 @@ void signal_handler(int sig, siginfo_t* info, void* uct) } // TODO: this may be wrong - throw fmt::format("Access violation at location 0x%llx", addr64); + throw fmt::format("Access violation %s location 0x%llx", is_writing ? "writing" : "reading", addr64); } // else some fatal error @@ -451,8 +443,17 @@ void ThreadBase::Start() #ifdef _WIN32 auto old_se_translator = _set_se_translator(_se_translator); + if (!exception_handler) + { + LOG_ERROR(GENERAL, "exception_handler not set"); + return; + } #else - if (sigaction_result == -1) assert(!"sigaction() failed"); + if (sigaction_result == -1) + { + printf("sigaction() failed"); + exit(EXIT_FAILURE); + } #endif SetCurrentNamedThread(this); @@ -590,8 +591,6 @@ void thread_t::start(std::function func) #ifdef _WIN32 auto old_se_translator = _set_se_translator(_se_translator); -#else - if (sigaction_result == -1) assert(!"sigaction() failed"); #endif NamedThreadBase info(name); diff --git a/rpcs3/Emu/Cell/PPUInterpreter.h b/rpcs3/Emu/Cell/PPUInterpreter.h index be1611bf78..83a0101e6d 100644 --- a/rpcs3/Emu/Cell/PPUInterpreter.h +++ b/rpcs3/Emu/Cell/PPUInterpreter.h @@ -2911,9 +2911,7 @@ private: } void ECIWX(u32 rd, u32 ra, u32 rb) { - //HACK! - const u64 addr = ra ? CPU.GPR[ra] + CPU.GPR[rb] : CPU.GPR[rb]; - CPU.GPR[rd] = vm::read32(vm::cast(addr)); + throw __FUNCTION__; } void LHZUX(u32 rd, u32 ra, u32 rb) { @@ -2986,9 +2984,7 @@ private: } void ECOWX(u32 rs, u32 ra, u32 rb) { - //HACK! - const u64 addr = ra ? CPU.GPR[ra] + CPU.GPR[rb] : CPU.GPR[rb]; - vm::write32(vm::cast(addr), (u32)CPU.GPR[rs]); + throw __FUNCTION__; } void STHUX(u32 rs, u32 ra, u32 rb) { diff --git a/rpcs3/Emu/Cell/PPULLVMRecompiler.cpp b/rpcs3/Emu/Cell/PPULLVMRecompiler.cpp index 99203e1864..dedaf358bf 100644 --- a/rpcs3/Emu/Cell/PPULLVMRecompiler.cpp +++ b/rpcs3/Emu/Cell/PPULLVMRecompiler.cpp @@ -3271,15 +3271,16 @@ void Compiler::EQV(u32 ra, u32 rs, u32 rb, bool rc) { } void Compiler::ECIWX(u32 rd, u32 ra, u32 rb) { - auto addr_i64 = GetGpr(rb); - if (ra) { - auto ra_i64 = GetGpr(ra); - addr_i64 = m_ir_builder->CreateAdd(ra_i64, addr_i64); - } + throw __FUNCTION__; + //auto addr_i64 = GetGpr(rb); + //if (ra) { + // auto ra_i64 = GetGpr(ra); + // addr_i64 = m_ir_builder->CreateAdd(ra_i64, addr_i64); + //} - auto mem_i32 = ReadMemory(addr_i64, 32); - auto mem_i64 = m_ir_builder->CreateZExt(mem_i32, m_ir_builder->getInt64Ty()); - SetGpr(rd, mem_i64); + //auto mem_i32 = ReadMemory(addr_i64, 32); + //auto mem_i64 = m_ir_builder->CreateZExt(mem_i32, m_ir_builder->getInt64Ty()); + //SetGpr(rd, mem_i64); } void Compiler::LHZUX(u32 rd, u32 ra, u32 rb) { @@ -3430,13 +3431,14 @@ void Compiler::ORC(u32 ra, u32 rs, u32 rb, bool rc) { } void Compiler::ECOWX(u32 rs, u32 ra, u32 rb) { - auto addr_i64 = GetGpr(rb); - if (ra) { - auto ra_i64 = GetGpr(ra); - addr_i64 = m_ir_builder->CreateAdd(ra_i64, addr_i64); - } + throw __FUNCTION__; + //auto addr_i64 = GetGpr(rb); + //if (ra) { + // auto ra_i64 = GetGpr(ra); + // addr_i64 = m_ir_builder->CreateAdd(ra_i64, addr_i64); + //} - WriteMemory(addr_i64, GetGpr(rs, 32)); + //WriteMemory(addr_i64, GetGpr(rs, 32)); } void Compiler::STHUX(u32 rs, u32 ra, u32 rb) { diff --git a/rpcs3/Emu/Cell/PPULLVMRecompilerTests.cpp b/rpcs3/Emu/Cell/PPULLVMRecompilerTests.cpp index e1054ecc89..511125e233 100644 --- a/rpcs3/Emu/Cell/PPULLVMRecompilerTests.cpp +++ b/rpcs3/Emu/Cell/PPULLVMRecompilerTests.cpp @@ -724,8 +724,8 @@ void Compiler::RunAllTests() { VERIFY_INSTRUCTION_AGAINST_INTERPRETER(LHZU, 0, input, 5, 14, 0x10000); VERIFY_INSTRUCTION_AGAINST_INTERPRETER(LHZX, 0, input, 5, 0, 23); VERIFY_INSTRUCTION_AGAINST_INTERPRETER(LHZX, 1, input, 5, 14, 23); - VERIFY_INSTRUCTION_AGAINST_INTERPRETER(ECIWX, 0, input, 5, 0, 23); - VERIFY_INSTRUCTION_AGAINST_INTERPRETER(ECIWX, 1, input, 5, 14, 23); + //VERIFY_INSTRUCTION_AGAINST_INTERPRETER(ECIWX, 0, input, 5, 0, 23); + //VERIFY_INSTRUCTION_AGAINST_INTERPRETER(ECIWX, 1, input, 5, 14, 23); VERIFY_INSTRUCTION_AGAINST_INTERPRETER(LHZUX, 0, input, 5, 14, 23); VERIFY_INSTRUCTION_AGAINST_INTERPRETER(LHA, 0, input, 5, 0, 0x100F0); VERIFY_INSTRUCTION_AGAINST_INTERPRETER(LHA, 1, input, 5, 14, 0x100F0); @@ -765,10 +765,10 @@ void Compiler::RunAllTests() { VERIFY_INSTRUCTION_AGAINST_INTERPRETER(LFDX, 0, input, 5, 0, 23); VERIFY_INSTRUCTION_AGAINST_INTERPRETER(LFDX, 1, input, 5, 14, 23); VERIFY_INSTRUCTION_AGAINST_INTERPRETER(LFDUX, 0, input, 5, 14, 23); - VERIFY_INSTRUCTION_AGAINST_INTERPRETER(LWARX, 0, input, 5, 0, 23); - VERIFY_INSTRUCTION_AGAINST_INTERPRETER(LWARX, 1, input, 5, 14, 23); - VERIFY_INSTRUCTION_AGAINST_INTERPRETER(LDARX, 0, input, 5, 0, 23); - VERIFY_INSTRUCTION_AGAINST_INTERPRETER(LDARX, 1, input, 5, 14, 23); + //VERIFY_INSTRUCTION_AGAINST_INTERPRETER(LWARX, 0, input, 5, 0, 23); + //VERIFY_INSTRUCTION_AGAINST_INTERPRETER(LWARX, 1, input, 5, 14, 23); + //VERIFY_INSTRUCTION_AGAINST_INTERPRETER(LDARX, 0, input, 5, 0, 23); + //VERIFY_INSTRUCTION_AGAINST_INTERPRETER(LDARX, 1, input, 5, 14, 23); VERIFY_INSTRUCTION_AGAINST_INTERPRETER(LSWI, 0, input, 5, 23, 0); VERIFY_INSTRUCTION_AGAINST_INTERPRETER(LSWI, 1, input, 5, 23, 2); VERIFY_INSTRUCTION_AGAINST_INTERPRETER(LSWI, 2, input, 5, 23, 7); @@ -804,8 +804,8 @@ void Compiler::RunAllTests() { VERIFY_INSTRUCTION_AGAINST_INTERPRETER(STB, 0, input, 3, 0, 0x10000); VERIFY_INSTRUCTION_AGAINST_INTERPRETER(STB, 1, input, 3, 14, 0x10000); VERIFY_INSTRUCTION_AGAINST_INTERPRETER(STBU, 0, input, 3, 14, 0x10000); - VERIFY_INSTRUCTION_AGAINST_INTERPRETER(STDCX_, 0, input, 3, 0, 23); - VERIFY_INSTRUCTION_AGAINST_INTERPRETER(STDCX_, 1, input, 3, 14, 23); + //VERIFY_INSTRUCTION_AGAINST_INTERPRETER(STDCX_, 0, input, 3, 0, 23); + //VERIFY_INSTRUCTION_AGAINST_INTERPRETER(STDCX_, 1, input, 3, 14, 23); VERIFY_INSTRUCTION_AGAINST_INTERPRETER(STBX, 0, input, 3, 0, 23); VERIFY_INSTRUCTION_AGAINST_INTERPRETER(STBX, 1, input, 3, 14, 23); VERIFY_INSTRUCTION_AGAINST_INTERPRETER(STBUX, 0, input, 3, 14, 23); @@ -814,8 +814,8 @@ void Compiler::RunAllTests() { VERIFY_INSTRUCTION_AGAINST_INTERPRETER(STHU, 0, input, 3, 14, 0x10000); VERIFY_INSTRUCTION_AGAINST_INTERPRETER(STHX, 0, input, 3, 0, 23); VERIFY_INSTRUCTION_AGAINST_INTERPRETER(STHX, 1, input, 3, 14, 23); - VERIFY_INSTRUCTION_AGAINST_INTERPRETER(ECOWX, 0, input, 3, 0, 23); - VERIFY_INSTRUCTION_AGAINST_INTERPRETER(ECOWX, 1, input, 3, 14, 23); + //VERIFY_INSTRUCTION_AGAINST_INTERPRETER(ECOWX, 0, input, 3, 0, 23); + //VERIFY_INSTRUCTION_AGAINST_INTERPRETER(ECOWX, 1, input, 3, 14, 23); VERIFY_INSTRUCTION_AGAINST_INTERPRETER(STHUX, 0, input, 3, 14, 23); VERIFY_INSTRUCTION_AGAINST_INTERPRETER(STHBRX, 0, input, 3, 14, 23); VERIFY_INSTRUCTION_AGAINST_INTERPRETER(STW, 0, input, 3, 0, 0x10000); @@ -833,8 +833,8 @@ void Compiler::RunAllTests() { VERIFY_INSTRUCTION_AGAINST_INTERPRETER(STDU, 0, input, 3, 14, 0x10000); VERIFY_INSTRUCTION_AGAINST_INTERPRETER(STDX, 0, input, 3, 0, 23); VERIFY_INSTRUCTION_AGAINST_INTERPRETER(STDX, 1, input, 3, 14, 23); - VERIFY_INSTRUCTION_AGAINST_INTERPRETER(STWCX_, 0, input, 3, 0, 23); - VERIFY_INSTRUCTION_AGAINST_INTERPRETER(STWCX_, 1, input, 3, 14, 23); + //VERIFY_INSTRUCTION_AGAINST_INTERPRETER(STWCX_, 0, input, 3, 0, 23); + //VERIFY_INSTRUCTION_AGAINST_INTERPRETER(STWCX_, 1, input, 3, 14, 23); VERIFY_INSTRUCTION_AGAINST_INTERPRETER(STDUX, 0, input, 3, 14, 23); VERIFY_INSTRUCTION_AGAINST_INTERPRETER(STFS, 0, input, 3, 0, 0x10000); VERIFY_INSTRUCTION_AGAINST_INTERPRETER(STFS, 1, input, 3, 14, 0x10000); diff --git a/rpcs3/Emu/Memory/Memory.h b/rpcs3/Emu/Memory/Memory.h index 3f9a981041..a6aabf35ee 100644 --- a/rpcs3/Emu/Memory/Memory.h +++ b/rpcs3/Emu/Memory/Memory.h @@ -72,11 +72,6 @@ public: Close(); } - static void* const GetBaseAddr() - { - return vm::g_base_addr; - } - void RegisterPages(u64 addr, u32 size); void UnregisterPages(u64 addr, u32 size); diff --git a/rpcs3/Emu/Memory/vm.cpp b/rpcs3/Emu/Memory/vm.cpp index 5cf8962be4..563cceddcf 100644 --- a/rpcs3/Emu/Memory/vm.cpp +++ b/rpcs3/Emu/Memory/vm.cpp @@ -137,6 +137,7 @@ namespace vm NamedThreadBase* g_reservation_owner = nullptr; u32 g_reservation_addr = 0; + u32 g_reservation_size = 0; reservation_mutex_t g_reservation_mutex; @@ -183,6 +184,7 @@ namespace vm g_reservation_owner = nullptr; g_reservation_addr = 0; + g_reservation_size = 0; return true; } @@ -204,7 +206,7 @@ namespace vm bool broken = false; assert(size == 1 || size == 2 || size == 4 || size == 8 || size == 128); - assert((addr + size & ~0xfff) == (addr & ~0xfff)); + assert((addr + size - 1 & ~0xfff) == (addr & ~0xfff)); { std::lock_guard lock(g_reservation_mutex); @@ -213,7 +215,7 @@ namespace vm //g_reservation_mutex.do_notify = false; // break previous reservation - if (g_reservation_addr) + if (g_reservation_owner) { broken = _reservation_break(g_reservation_addr); } @@ -226,6 +228,7 @@ namespace vm // set additional information g_reservation_addr = addr; + g_reservation_size = size; g_reservation_owner = GetCurrentNamedThread(); g_reservation_cb = callback; @@ -239,11 +242,11 @@ namespace vm bool reservation_update(u32 addr, const void* data, u32 size) { assert(size == 1 || size == 2 || size == 4 || size == 8 || size == 128); - assert((addr + size & ~0xfff) == (addr & ~0xfff)); + assert((addr + size - 1 & ~0xfff) == (addr & ~0xfff)); std::lock_guard lock(g_reservation_mutex); - if (g_reservation_addr != addr || g_reservation_owner != GetCurrentNamedThread()) + if (g_reservation_owner != GetCurrentNamedThread() || g_reservation_addr != addr || g_reservation_size != size) { // atomic update failed return false; @@ -291,12 +294,12 @@ namespace vm void reservation_op(u32 addr, u32 size, std::function proc) { assert(size == 1 || size == 2 || size == 4 || size == 8 || size == 128); - assert((addr + size & ~0xfff) == (addr & ~0xfff)); + assert((addr + size - 1 & ~0xfff) == (addr & ~0xfff)); std::lock_guard lock(g_reservation_mutex); // break previous reservation - if (g_reservation_addr) + if (g_reservation_owner) { _reservation_break(g_reservation_addr); } @@ -306,6 +309,7 @@ namespace vm // set additional information g_reservation_addr = addr; + g_reservation_size = size; g_reservation_owner = GetCurrentNamedThread(); g_reservation_cb = nullptr;