From 2ce164be0993f155b099c38ba162500aa84c015d Mon Sep 17 00:00:00 2001 From: Eladash Date: Fri, 13 Aug 2021 19:24:50 +0300 Subject: [PATCH] rsx: Implement crash-proofing for 308A_COLOR dst address --- rpcs3/Emu/RSX/RSXThread.cpp | 19 ++++++++++++++----- rpcs3/Emu/RSX/RSXThread.h | 2 +- rpcs3/Emu/RSX/rsx_methods.cpp | 33 ++++++++++++++++++++++----------- 3 files changed, 37 insertions(+), 17 deletions(-) diff --git a/rpcs3/Emu/RSX/RSXThread.cpp b/rpcs3/Emu/RSX/RSXThread.cpp index 89353ea42e..65d2844ed5 100644 --- a/rpcs3/Emu/RSX/RSXThread.cpp +++ b/rpcs3/Emu/RSX/RSXThread.cpp @@ -74,7 +74,7 @@ namespace rsx { std::function g_access_violation_handler; - u32 get_address(u32 offset, u32 location, bool allow_failure, u32 line, u32 col, const char* file, const char* func) + u32 get_address(u32 offset, u32 location, u32 size_to_check, u32 line, u32 col, const char* file, const char* func) { const auto render = get_current_renderer(); std::string_view msg; @@ -84,7 +84,7 @@ namespace rsx case CELL_GCM_CONTEXT_DMA_MEMORY_FRAME_BUFFER: case CELL_GCM_LOCATION_LOCAL: { - if (offset < render->local_mem_size) + if (offset < render->local_mem_size && render->local_mem_size - offset >= size_to_check) { return rsx::constants::local_mem_base + offset; } @@ -98,7 +98,10 @@ namespace rsx { if (const u32 ea = render->iomap_table.get_addr(offset); ea + 1) { - return ea; + if (!size_to_check || vm::check_addr(ea, 0, size_to_check)) + { + return ea; + } } msg = "RSXIO memory not mapped!"sv; @@ -120,7 +123,10 @@ namespace rsx { if (const u32 ea = offset < 0x1000000 ? render->iomap_table.get_addr(0x0e000000 + offset) : -1; ea + 1) { - return ea; + if (!size_to_check || vm::check_addr(ea, 0, size_to_check)) + { + return ea; + } } msg = "RSXIO REPORT memory not mapped!"sv; @@ -181,8 +187,11 @@ namespace rsx } } - if (allow_failure) + if (size_to_check) { + // Allow failure if specified size + // This is to allow accurate recovery for failures + rsx_log.warning("rsx::get_address(offset=0x%x, location=0x%x, size=0x%x): %s%s", offset, location, size_to_check, msg, src_loc{line, col, file, func}); return 0; } diff --git a/rpcs3/Emu/RSX/RSXThread.h b/rpcs3/Emu/RSX/RSXThread.h index c02d4781b4..ec4bcf0b54 100644 --- a/rpcs3/Emu/RSX/RSXThread.h +++ b/rpcs3/Emu/RSX/RSXThread.h @@ -169,7 +169,7 @@ namespace rsx u32 get_vertex_type_size_on_host(vertex_base_type type, u32 size); - u32 get_address(u32 offset, u32 location, bool allow_failure = false, + u32 get_address(u32 offset, u32 location, u32 size_to_check = 0, u32 line = __builtin_LINE(), u32 col = __builtin_COLUMN(), const char* file = __builtin_FILE(), diff --git a/rpcs3/Emu/RSX/rsx_methods.cpp b/rpcs3/Emu/RSX/rsx_methods.cpp index c7d71ccab4..6f14a35f83 100644 --- a/rpcs3/Emu/RSX/rsx_methods.cpp +++ b/rpcs3/Emu/RSX/rsx_methods.cpp @@ -925,8 +925,8 @@ namespace rsx const u32 x = method_registers.nv308a_x() + index; const u32 y = method_registers.nv308a_y(); - // TODO - //auto res = vm::passive_lock(address, address + write_len); + // Skip "handled methods" + rsx->fifo_ctrl->skip_methods(count - 1); switch (method_registers.blit_engine_nv3062_color_format()) { @@ -935,12 +935,21 @@ namespace rsx { // Bit cast - optimize to mem copy - const auto dst_address = get_address(dst_offset + (x * 4) + (out_pitch * y), dst_dma); + const u32 data_length = count * 4; + + const auto dst_address = get_address(dst_offset + (x * 4) + (out_pitch * y), dst_dma, data_length); + + if (!dst_address) + { + rsx->recover_fifo(); + return; + } + const auto src_address = get_address(src_offset, CELL_GCM_LOCATION_MAIN); + const auto dst = vm::_ptr(dst_address); const auto src = vm::_ptr(src_address); - const u32 data_length = count * 4; auto res = rsx::reservation_lock(dst_address, data_length, src_address, data_length); if (rsx->fifo_ctrl->last_cmd() & RSX_METHOD_NON_INCREMENT_CMD_MASK) [[unlikely]] @@ -969,12 +978,19 @@ namespace rsx } case blit_engine::transfer_destination_format::r5g6b5: { - const auto dst_address = get_address(dst_offset + (x * 2) + (y * out_pitch), dst_dma); + const auto data_length = count * 2; + + const auto dst_address = get_address(dst_offset + (x * 2) + (y * out_pitch), dst_dma, data_length); const auto src_address = get_address(src_offset, CELL_GCM_LOCATION_MAIN); const auto dst = vm::_ptr(dst_address); const auto src = vm::_ptr(src_address); - const auto data_length = count * 2; + if (!dst_address) + { + rsx->recover_fifo(); + return; + } + auto res = rsx::reservation_lock(dst_address, data_length, src_address, data_length); auto convert = [](u32 input) -> u16 @@ -1011,11 +1027,6 @@ namespace rsx fmt::throw_exception("Unreachable"); } } - - //res->release(0); - - // Skip "handled methods" - rsx->fifo_ctrl->skip_methods(count - 1); } }; }