From 64399d45c1ac15203084dc41947a38d7a7a29d65 Mon Sep 17 00:00:00 2001 From: Eladash Date: Sat, 16 Oct 2021 12:13:29 +0300 Subject: [PATCH] vm: Make falloc return value bool Allow to check properly for the success of 0 address allocation. --- Utilities/Thread.cpp | 10 +++++++--- Utilities/bin_patch.cpp | 15 ++++++++++++++- rpcs3/Emu/Cell/lv2/sys_rsx.cpp | 4 ++-- rpcs3/Emu/Memory/vm.cpp | 16 ++++++++-------- rpcs3/Emu/Memory/vm.h | 4 ++-- 5 files changed, 33 insertions(+), 16 deletions(-) diff --git a/Utilities/Thread.cpp b/Utilities/Thread.cpp index 82e4966881..430681a8b8 100644 --- a/Utilities/Thread.cpp +++ b/Utilities/Thread.cpp @@ -1423,6 +1423,11 @@ bool handle_access_violation(u32 addr, bool is_writing, ucontext_t* context) noe { g_tls_access_violation_recovered = true; + if (vm::check_addr(addr, is_writing ? vm::page_writable : vm::page_readable)) + { + return true; + } + const auto area = vm::reserve_map(vm::any, addr & -0x10000, 0x10000); if (!area) @@ -1430,15 +1435,14 @@ bool handle_access_violation(u32 addr, bool is_writing, ucontext_t* context) noe return false; } - if (vm::writer_lock mlock; vm::check_addr(addr, 0)) + if (vm::writer_lock mlock; area->flags & vm::preallocated || vm::check_addr(addr, 0)) { // For allocated memory with protection lower than required (such as protection::no or read-only while writing to it) utils::memory_protect(vm::base(addr & -0x1000), 0x1000, utils::protection::rw); return true; } - area->falloc(addr & -0x10000, 0x10000); - return vm::check_addr(addr, is_writing ? vm::page_writable : vm::page_readable); + return area->falloc(addr & -0x10000, 0x10000) || vm::check_addr(addr, is_writing ? vm::page_writable : vm::page_readable); }; if (cpu && (cpu->id_type() == 1 || cpu->id_type() == 2)) diff --git a/Utilities/bin_patch.cpp b/Utilities/bin_patch.cpp index 75b19d7446..f9dbfe5a92 100644 --- a/Utilities/bin_patch.cpp +++ b/Utilities/bin_patch.cpp @@ -610,8 +610,21 @@ static usz apply_modification(std::basic_string& applied, const patch_engin if (alloc_map) { - if ((p.alloc_addr = alloc_map->falloc(alloc_at, alloc_size, nullptr, flags))) + if (alloc_map->falloc(alloc_at, alloc_size, nullptr, flags)) { + if (vm::check_addr(alloc_at, vm::page_1m_size)) + { + p.alloc_addr = alloc_at & -0x100000; + } + else if (vm::check_addr(alloc_at, vm::page_64k_size)) + { + p.alloc_addr = alloc_at & -0x10000; + } + else + { + p.alloc_addr = alloc_at & -0x1000; + } + if (flags & vm::alloc_executable) { ppu_register_range(alloc_at, alloc_size); diff --git a/rpcs3/Emu/Cell/lv2/sys_rsx.cpp b/rpcs3/Emu/Cell/lv2/sys_rsx.cpp index dcda9280b5..86adbba504 100644 --- a/rpcs3/Emu/Cell/lv2/sys_rsx.cpp +++ b/rpcs3/Emu/Cell/lv2/sys_rsx.cpp @@ -116,10 +116,10 @@ error_code sys_rsx_memory_allocate(cpu_thread& cpu, vm::ptr mem_handle, vm: sys_rsx.warning("sys_rsx_memory_allocate(mem_handle=*0x%x, mem_addr=*0x%x, size=0x%x, flags=0x%llx, a5=0x%llx, a6=0x%llx, a7=0x%llx)", mem_handle, mem_addr, size, flags, a5, a6, a7); - if (u32 addr = vm::falloc(rsx::constants::local_mem_base, size, vm::video)) + if (vm::falloc(rsx::constants::local_mem_base, size, vm::video)) { rsx::get_current_renderer()->local_mem_size = size; - *mem_addr = addr; + *mem_addr = rsx::constants::local_mem_base; *mem_handle = 0x5a5a5a5b; return CELL_OK; } diff --git a/rpcs3/Emu/Memory/vm.cpp b/rpcs3/Emu/Memory/vm.cpp index 62aaa4afaa..e59bc3fda0 100644 --- a/rpcs3/Emu/Memory/vm.cpp +++ b/rpcs3/Emu/Memory/vm.cpp @@ -979,7 +979,7 @@ namespace vm return block->alloc(size, nullptr, align); } - u32 falloc(u32 addr, u32 size, memory_location_t location, const std::shared_ptr* src) + bool falloc(u32 addr, u32 size, memory_location_t location, const std::shared_ptr* src) { const auto block = get(location, addr); @@ -987,7 +987,7 @@ namespace vm { vm_log.error("vm::falloc(): Invalid memory location (%u, addr=0x%x)", +location, addr); ensure(location == any || location < memory_location_max); // The only allowed locations to fail - return 0; + return false; } return block->falloc(addr, size, src); @@ -1254,7 +1254,7 @@ namespace vm u32 addr = utils::align(this->addr, align); - if (this->addr > std::min(max, addr)) + if (this->addr > max || addr > max) { return 0; } @@ -1284,7 +1284,7 @@ namespace vm return 0; } - u32 block_t::falloc(u32 addr, const u32 orig_size, const std::shared_ptr* src, u64 flags) + bool block_t::falloc(u32 addr, const u32 orig_size, const std::shared_ptr* src, u64 flags) { if (!src) { @@ -1311,7 +1311,7 @@ namespace vm (src && (orig_size | addr) % min_page_size) || flags & stack_guarded) { - return 0; + return false; } // Force aligned address @@ -1334,15 +1334,15 @@ namespace vm if (!is_valid()) { // Expired block - return 0; + return false; } if (!try_alloc(addr, flags, size, std::move(shm))) { - return 0; + return false; } - return addr; + return true; } u32 block_t::dealloc(u32 addr, const std::shared_ptr* src) const diff --git a/rpcs3/Emu/Memory/vm.h b/rpcs3/Emu/Memory/vm.h index e819c7006d..a40a9eb075 100644 --- a/rpcs3/Emu/Memory/vm.h +++ b/rpcs3/Emu/Memory/vm.h @@ -82,7 +82,7 @@ namespace vm u32 alloc(u32 size, memory_location_t location, u32 align = 0x10000); // Map memory at specified address (in optionally specified memory location) - u32 falloc(u32 addr, u32 size, memory_location_t location = any, const std::shared_ptr* src = nullptr); + bool falloc(u32 addr, u32 size, memory_location_t location = any, const std::shared_ptr* src = nullptr); // Unmap memory at specified address (in optionally specified memory location), return size u32 dealloc(u32 addr, memory_location_t location = any, const std::shared_ptr* src = nullptr); @@ -147,7 +147,7 @@ namespace vm u32 alloc(u32 size, const std::shared_ptr* = nullptr, u32 align = 0x10000, u64 flags = 0); // Try to map memory at fixed location - u32 falloc(u32 addr, u32 size, const std::shared_ptr* = nullptr, u64 flags = 0); + bool falloc(u32 addr, u32 size, const std::shared_ptr* = nullptr, u64 flags = 0); // Unmap memory at specified location previously returned by alloc(), return size u32 dealloc(u32 addr, const std::shared_ptr* = nullptr) const;