diff --git a/rpcs3/Emu/ARMv7/ARMv7Decoder.cpp b/rpcs3/Emu/ARMv7/ARMv7Decoder.cpp index 70ccd9f240..0b62114b2b 100644 --- a/rpcs3/Emu/ARMv7/ARMv7Decoder.cpp +++ b/rpcs3/Emu/ARMv7/ARMv7Decoder.cpp @@ -1281,7 +1281,7 @@ void armv7_decoder_initialize(u32 addr, u32 end_addr, bool dump) const u32 i2 = (code.data >> 11) & 0x1 ^ s ^ 1; const u32 target = (addr + 4 & ~3) + sign<25, u32>(s << 24 | i2 << 23 | i1 << 22 | (code.data & 0x3ff0000) >> 4 | (code.data & 0x7ff) << 1); - const u32 instr = Memory.IsGoodAddr(target, 4) ? vm::psv::read32(target) : 0; + const u32 instr = vm::check_addr(target, 4) ? vm::psv::read32(target) : 0; // possibly a call to imported function: if (target >= end_addr && ((target - end_addr) % 16) == 0 && (instr & 0xfff000f0) == 0xe0700090) diff --git a/rpcs3/Emu/ARMv7/ARMv7Thread.cpp b/rpcs3/Emu/ARMv7/ARMv7Thread.cpp index 0a57e4abcf..2e4d6c4ecb 100644 --- a/rpcs3/Emu/ARMv7/ARMv7Thread.cpp +++ b/rpcs3/Emu/ARMv7/ARMv7Thread.cpp @@ -39,7 +39,7 @@ std::array, TLS_MAX> g_armv7_tls_owners; void armv7_init_tls() { - g_armv7_tls_start = Emu.GetTLSMemsz() ? vm::cast(Memory.PSV.RAM.AllocAlign(Emu.GetTLSMemsz() * TLS_MAX, 4096)) : 0; + g_armv7_tls_start = Emu.GetTLSMemsz() ? Memory.PSV.RAM.AllocAlign(Emu.GetTLSMemsz() * TLS_MAX, 4096) : 0; for (auto& v : g_armv7_tls_owners) { @@ -126,7 +126,7 @@ void ARMv7Thread::InitStack() if (!m_stack_addr) { assert(m_stack_size); - m_stack_addr = vm::cast(Memory.Alloc(m_stack_size, 4096)); + m_stack_addr = Memory.Alloc(m_stack_size, 4096); } } @@ -269,7 +269,7 @@ cpu_thread& armv7_thread::args(std::initializer_list values) argc++; } - argv = vm::cast(Memory.PSV.RAM.AllocAlign(argv_size, 4096)); // allocate arg list + argv = Memory.PSV.RAM.AllocAlign(argv_size, 4096); // allocate arg list memcpy(vm::get_ptr(argv), argv_data.data(), argv_size); // copy arg list return *this; diff --git a/rpcs3/Emu/Cell/PPUThread.cpp b/rpcs3/Emu/Cell/PPUThread.cpp index e6d229583a..63ccda64d6 100644 --- a/rpcs3/Emu/Cell/PPUThread.cpp +++ b/rpcs3/Emu/Cell/PPUThread.cpp @@ -85,7 +85,7 @@ void PPUThread::InitStack() if (!m_stack_addr) { assert(m_stack_size); - m_stack_addr = vm::cast(Memory.StackMem.AllocAlign(m_stack_size, 4096)); + m_stack_addr = Memory.StackMem.AllocAlign(m_stack_size, 4096); } } diff --git a/rpcs3/Emu/Memory/Memory.cpp b/rpcs3/Emu/Memory/Memory.cpp index 00eee9da85..f5904b2c28 100644 --- a/rpcs3/Emu/Memory/Memory.cpp +++ b/rpcs3/Emu/Memory/Memory.cpp @@ -4,55 +4,8 @@ #include "Memory.h" #include "Emu/Cell/RawSPUThread.h" -#ifndef _WIN32 -#include - -/* OS X uses MAP_ANON instead of MAP_ANONYMOUS */ -#ifndef MAP_ANONYMOUS -#define MAP_ANONYMOUS MAP_ANON -#endif -#else -#include -#endif - MemoryBase Memory; -void MemoryBase::RegisterPages(u32 addr, u32 size) -{ - assert(size && (size | addr) % 4096 == 0); - - LV2_LOCK(0); - - //LOG_NOTICE(MEMORY, "RegisterPages(addr=0x%x, size=0x%x)", addr, size); - for (u32 i = addr / 4096; i < addr / 4096 + size / 4096; i++) - { - if (m_pages[i]) - { - LOG_ERROR(MEMORY, "Page already registered (addr=0x%x)", i * 4096); - Emu.Pause(); - } - m_pages[i] = 1; // TODO: define page parameters - } -} - -void MemoryBase::UnregisterPages(u32 addr, u32 size) -{ - assert(size && (size | addr) % 4096 == 0); - - LV2_LOCK(0); - - //LOG_NOTICE(MEMORY, "UnregisterPages(addr=0x%x, size=0x%x)", addr, size); - for (u32 i = addr / 4096; i < addr / 4096 + size / 4096; i++) - { - if (!m_pages[i]) - { - LOG_ERROR(MEMORY, "Page not registered (addr=0x%x)", i * 4096); - Emu.Pause(); - } - m_pages[i] = 0; // TODO: define page parameters - } -} - u32 MemoryBase::InitRawSPU(MemoryBlock* raw_spu) { LV2_LOCK(0); @@ -93,7 +46,6 @@ void MemoryBase::Init(MemoryType type) if (m_inited) return; m_inited = true; - memset(m_pages, 0, sizeof(m_pages)); memset(RawSPUMem, 0, sizeof(RawSPUMem)); LOG_NOTICE(MEMORY, "Initializing memory: base_addr = 0x%llx, priv_addr = 0x%llx", (u64)vm::g_base_addr, (u64)vm::g_priv_addr); @@ -111,11 +63,8 @@ void MemoryBase::Init(MemoryType type) switch (type) { case Memory_PS3: - MemoryBlocks.push_back(MainMem.SetRange(0x00010000, 0x2FFF0000)); - MemoryBlocks.push_back(UserMemory = PRXMem.SetRange(0x30000000, 0x10000000)); - MemoryBlocks.push_back(RSXCMDMem.SetRange(0x40000000, 0x10000000)); - MemoryBlocks.push_back(SPRXMem.SetRange(0x50000000, 0x10000000)); - MemoryBlocks.push_back(MmaperMem.SetRange(0xB0000000, 0x10000000)); + MemoryBlocks.push_back(MainMem.SetRange(0x00010000, 0x1FFF0000)); + MemoryBlocks.push_back(UserMemory = Userspace.SetRange(0x20000000, 0x10000000)); MemoryBlocks.push_back(RSXFBMem.SetRange(0xC0000000, 0x10000000)); MemoryBlocks.push_back(StackMem.SetRange(0xD0000000, 0x10000000)); break; @@ -189,7 +138,7 @@ bool MemoryBase::Map(const u32 addr, const u32 size) for (u32 i = addr / 4096; i < addr / 4096 + size / 4096; i++) { - if (m_pages[i]) + if (vm::check_addr(i * 4096, 4096)) { return false; } @@ -220,45 +169,15 @@ bool MemoryBase::Unmap(const u32 addr) MemBlockInfo::MemBlockInfo(u32 addr, u32 size) : MemInfo(addr, size) { - assert(size && (size | addr) % 4096 == 0); - - void* real_addr = vm::get_ptr(addr); - void* priv_addr = vm::get_priv_ptr(addr); - -#ifdef _WIN32 - if (!VirtualAlloc(priv_addr, size, MEM_COMMIT, PAGE_READWRITE) || !VirtualAlloc(real_addr, size, MEM_COMMIT, PAGE_READWRITE)) -#else - if (mprotect(real_addr, size, PROT_READ | PROT_WRITE) || mprotect(priv_addr, size, PROT_READ | PROT_WRITE)) -#endif - { - LOG_ERROR(MEMORY, "Memory allocation failed (addr=0x%x, size=0x%x)", addr, size); - Emu.Pause(); - } - else - { - Memory.RegisterPages(addr, size); - - mem = real_addr; - memset(mem, 0, size); // ??? - } + vm::page_map(addr, size, vm::page_readable | vm::page_writable | vm::page_executable); } void MemBlockInfo::Free() { - if (mem) + if (addr && size) { - Memory.UnregisterPages(addr, size); -#ifdef _WIN32 - DWORD old; - - if (!VirtualProtect(mem, size, PAGE_NOACCESS, &old) || !VirtualProtect(vm::get_priv_ptr(addr), size, PAGE_NOACCESS, &old)) -#else - if (mprotect(mem, size, PROT_NONE) || mprotect(vm::get_priv_ptr(addr), size, PROT_NONE)) -#endif - { - LOG_ERROR(MEMORY, "Memory deallocation failed (addr=0x%x, size=0x%x)", addr, size); - Emu.Pause(); - } + vm::page_unmap(addr, size); + addr = size = 0; } } @@ -277,21 +196,14 @@ void MemoryBlock::Init() { range_start = 0; range_size = 0; - - mem = vm::get_ptr(0u); } void MemoryBlock::InitMemory() { - if (!range_size) - { - mem = vm::get_ptr(range_start); - } - else + if (range_size) { Free(); mem_inf = new MemBlockInfo(range_start, range_size); - mem = (u8*)mem_inf->mem; } } diff --git a/rpcs3/Emu/Memory/Memory.h b/rpcs3/Emu/Memory/Memory.h index 84b459f9bb..a6e6edbf94 100644 --- a/rpcs3/Emu/Memory/Memory.h +++ b/rpcs3/Emu/Memory/Memory.h @@ -30,16 +30,12 @@ namespace vm class MemoryBase { std::vector MemoryBlocks; - u32 m_pages[0x100000000 / 4096]; // information about every page public: MemoryBlock* UserMemory; DynamicMemoryBlock MainMem; - DynamicMemoryBlock SPRXMem; - DynamicMemoryBlock PRXMem; - DynamicMemoryBlock RSXCMDMem; - DynamicMemoryBlock MmaperMem; + DynamicMemoryBlock Userspace; DynamicMemoryBlock RSXFBMem; DynamicMemoryBlock StackMem; MemoryBlock* RawSPUMem[(0x100000000 - RAW_SPU_BASE_ADDR) / RAW_SPU_OFFSET]; @@ -82,27 +78,6 @@ public: void Init(MemoryType type); - bool IsGoodAddr(const u32 addr) - { - return m_pages[addr / 4096] != 0; // TODO: define page parameters - } - - bool IsGoodAddr(const u32 addr, const u32 size) - { - if (!size || addr + size - 1 < addr) - { - return false; - } - else - { - for (u32 i = addr / 4096; i <= (addr + size - 1) / 4096; i++) - { - if (!m_pages[i]) return false; // TODO: define page parameters - } - return true; - } - } - void Close(); __noinline void WriteMMIO32(u32 addr, const u32 data); diff --git a/rpcs3/Emu/Memory/MemoryBlock.h b/rpcs3/Emu/Memory/MemoryBlock.h index 81dfcd3e1d..4cabf37db0 100644 --- a/rpcs3/Emu/Memory/MemoryBlock.h +++ b/rpcs3/Emu/Memory/MemoryBlock.h @@ -22,8 +22,6 @@ struct MemInfo struct MemBlockInfo : public MemInfo { - void *mem; - MemBlockInfo(u32 addr, u32 size); void Free(); @@ -32,27 +30,26 @@ struct MemBlockInfo : public MemInfo MemBlockInfo(MemBlockInfo &&other) : MemInfo(other.addr,other.size) - , mem(other.mem) { - other.mem = nullptr; + other.addr = 0; + other.size = 0; } MemBlockInfo& operator =(MemBlockInfo &other) = delete; MemBlockInfo& operator =(MemBlockInfo &&other) { - this->Free(); + Free(); this->addr = other.addr; this->size = other.size; - this->mem = other.mem; - other.mem = nullptr; + other.addr = 0; + other.size = 0; return *this; } ~MemBlockInfo() { Free(); - mem = nullptr; } }; @@ -76,7 +73,6 @@ struct VirtualMemInfo : public MemInfo class MemoryBlock { protected: - u8* mem; u32 range_start; u32 range_size; diff --git a/rpcs3/Emu/Memory/vm.cpp b/rpcs3/Emu/Memory/vm.cpp index 1a0b9edd5c..188f0f373e 100644 --- a/rpcs3/Emu/Memory/vm.cpp +++ b/rpcs3/Emu/Memory/vm.cpp @@ -80,6 +80,8 @@ namespace vm void* const g_base_addr = (atexit(finalize), initialize()); + std::array, 0x100000000ull / 4096> g_page_info = {}; // information about every page + class reservation_mutex_t { std::atomic m_owner; @@ -211,6 +213,12 @@ namespace vm { std::lock_guard lock(g_reservation_mutex); + u8 flags = g_page_info[addr >> 12].read_relaxed(); + if (!(flags & page_writable) || !(flags & page_allocated) || (flags & page_no_reservations)) + { + throw fmt::format("vm::reservation_acquire(addr=0x%x, size=0x%x) failed (invalid page flags: 0x%x)", addr, size, flags); + } + // silent unlocking to prevent priority boost for threads going to break reservation //g_reservation_mutex.do_notify = false; @@ -272,13 +280,9 @@ namespace vm { std::lock_guard lock(g_reservation_mutex); + if (!check_addr(addr)) { - LV2_LOCK(0); - - if (!Memory.IsGoodAddr(addr)) - { - return false; - } + return false; } if (is_writing) @@ -335,11 +339,157 @@ namespace vm _reservation_break(addr); } - bool check_addr(u32 addr) + void page_map(u32 addr, u32 size, u8 flags) { - // Checking address before using it is unsafe. - // The only safe way to check it is to protect both actions (checking and using) with mutex that is used for mapping/allocation. - return false; + assert(size && (size | addr) % 4096 == 0 && flags < page_allocated); + + std::lock_guard lock(g_reservation_mutex); + + for (u32 i = addr / 4096; i < addr / 4096 + size / 4096; i++) + { + if (g_page_info[i].read_relaxed()) + { + throw fmt::format("vm::page_map(addr=0x%x, size=0x%x, flags=0x%x) failed (already mapped at 0x%x)", addr, size, flags, i * 4096); + } + } + + void* real_addr = vm::get_ptr(addr); + void* priv_addr = vm::get_priv_ptr(addr); + +#ifdef _WIN32 + auto protection = flags & page_writable ? PAGE_READWRITE : (flags & page_readable ? PAGE_READONLY : PAGE_NOACCESS); + if (!VirtualAlloc(priv_addr, size, MEM_COMMIT, PAGE_READWRITE) || !VirtualAlloc(real_addr, size, MEM_COMMIT, protection)) +#else + auto protection = flags & page_writable ? PROT_WRITE | PROT_READ : (flags & page_readable ? PROT_READ : PROT_NONE); + if (mprotect(priv_addr, size, PROT_READ | PROT_WRITE) || mprotect(real_addr, size, protection)) +#endif + { + throw fmt::format("vm::page_map(addr=0x%x, size=0x%x, flags=0x%x) failed (API)", addr, size, flags); + } + + for (u32 i = addr / 4096; i < addr / 4096 + size / 4096; i++) + { + if (g_page_info[i].exchange(flags | page_allocated)) + { + throw fmt::format("vm::page_map(addr=0x%x, size=0x%x, flags=0x%x) failed (concurrent access at 0x%x)", addr, size, flags, i * 4096); + } + } + + memset(priv_addr, 0, size); // ??? + } + + bool page_protect(u32 addr, u32 size, u8 flags_test, u8 flags_set, u8 flags_clear) + { + u8 flags_inv = flags_set & flags_clear; + + assert(size && (size | addr) % 4096 == 0); + + flags_test |= page_allocated; + + std::lock_guard lock(g_reservation_mutex); + + for (u32 i = addr / 4096; i < addr / 4096 + size / 4096; i++) + { + if ((g_page_info[i].read_relaxed() & flags_test) != (flags_test | page_allocated)) + { + return false; + } + } + + if (!flags_inv && !flags_set && !flags_clear) + { + return true; + } + + for (u32 i = addr / 4096; i < addr / 4096 + size / 4096; i++) + { + _reservation_break(i * 4096); + + const u8 f1 = g_page_info[i]._or(flags_set & ~flags_inv) & (page_writable | page_readable); + g_page_info[i]._and_not(flags_clear & ~flags_inv); + const u8 f2 = (g_page_info[i] ^= flags_inv) & (page_writable | page_readable); + + if (f1 != f2) + { + void* real_addr = vm::get_ptr(i * 4096); + +#ifdef _WIN32 + DWORD old; + + auto protection = f2 & page_writable ? PAGE_READWRITE : (f2 & page_readable ? PAGE_READONLY : PAGE_NOACCESS); + if (!VirtualProtect(real_addr, size, protection, &old)) +#else + auto protection = f2 & page_writable ? PROT_WRITE | PROT_READ : (f2 & page_readable ? PROT_READ : PROT_NONE); + if (mprotect(real_addr, size, protection)) +#endif + { + throw fmt::format("vm::page_protect(addr=0x%x, size=0x%x, flags_test=0x%x, flags_set=0x%x, flags_clear=0x%x) failed (API)", addr, size, flags_test, flags_set, flags_clear); + } + } + } + + return true; + } + + void page_unmap(u32 addr, u32 size) + { + assert(size && (size | addr) % 4096 == 0); + + std::lock_guard lock(g_reservation_mutex); + + for (u32 i = addr / 4096; i < addr / 4096 + size / 4096; i++) + { + if (!(g_page_info[i].read_relaxed() & page_allocated)) + { + throw fmt::format("vm::page_unmap(addr=0x%x, size=0x%x) failed (not mapped at 0x%x)", addr, size, i * 4096); + } + } + + for (u32 i = addr / 4096; i < addr / 4096 + size / 4096; i++) + { + _reservation_break(i * 4096); + + if (!(g_page_info[i].exchange(0) & page_allocated)) + { + throw fmt::format("vm::page_unmap(addr=0x%x, size=0x%x) failed (concurrent access at 0x%x)", addr, size, i * 4096); + } + } + + void* real_addr = vm::get_ptr(addr); + void* priv_addr = vm::get_priv_ptr(addr); + +#ifdef _WIN32 + DWORD old; + + if (!VirtualProtect(real_addr, size, PAGE_NOACCESS, &old) || !VirtualProtect(priv_addr, size, PAGE_NOACCESS, &old)) +#else + if (mprotect(real_addr, size, PROT_NONE) || mprotect(priv_addr, size, PROT_NONE)) +#endif + { + throw fmt::format("vm::page_unmap(addr=0x%x, size=0x%x) failed (API)", addr, size); + } + } + + // Not checked if address is writable/readable. Checking address before using it is unsafe. + // The only safe way to check it is to protect both actions (checking and using) with mutex that is used for mapping/allocation. + bool check_addr(u32 addr, u32 size) + { + assert(size); + + if (addr + (size - 1) < addr) + { + return false; + } + + for (u32 i = addr / 4096; i <= (addr + size - 1) / 4096; i++) + { + if ((g_page_info[i].read_sync() & page_allocated) != page_allocated) + { + return false; + } + } + + return true; } //TODO @@ -406,6 +556,19 @@ namespace vm Memory.MainMem.Free(addr); } + u32 user_space_alloc(u32 size) + { + return Memory.Userspace.AllocAlign(size, 1); + } + u32 user_space_fixed_alloc(u32 addr, u32 size) + { + return Memory.Userspace.AllocFixed(addr, size) ? addr : 0; + } + void user_space_dealloc(u32 addr) + { + Memory.Userspace.Free(addr); + } + u32 g_stack_offset = 0; u32 stack_alloc(u32 size) @@ -421,32 +584,6 @@ namespace vm Memory.StackMem.Free(addr); } - u32 sprx_alloc(u32 size) - { - return Memory.SPRXMem.AllocAlign(size, 1); - } - u32 sprx_fixed_alloc(u32 addr, u32 size) - { - return Memory.SPRXMem.AllocFixed(Memory.SPRXMem.GetStartAddr() + addr, size) ? Memory.SPRXMem.GetStartAddr() + addr : 0; - } - void sprx_dealloc(u32 addr) - { - Memory.SPRXMem.Free(addr); - } - - u32 user_space_alloc(u32 size) - { - return Memory.PRXMem.AllocAlign(size, 1); - } - u32 user_space_fixed_alloc(u32 addr, u32 size) - { - return Memory.PRXMem.AllocFixed(addr, size) ? addr : 0; - } - void user_space_dealloc(u32 addr) - { - Memory.PRXMem.Free(addr); - } - void init() { Memory.Init(Memory_PS3); @@ -471,13 +608,9 @@ namespace vm location_info g_locations[memory_location_count] = { - { 0x00010000, 0x2FFF0000, ps3::main_alloc, ps3::main_fixed_alloc, ps3::main_dealloc }, + { 0x00010000, 0x1FFF0000, ps3::main_alloc, ps3::main_fixed_alloc, ps3::main_dealloc }, + { 0x20000000, 0x10000000, ps3::user_space_alloc, ps3::user_space_fixed_alloc, ps3::user_space_dealloc }, { 0xD0000000, 0x10000000, ps3::stack_alloc, ps3::stack_fixed_alloc, ps3::stack_dealloc }, - - //remove me - { 0x00010000, 0x2FFF0000, ps3::sprx_alloc, ps3::sprx_fixed_alloc, ps3::sprx_dealloc }, - - { 0x30000000, 0x10000000, ps3::user_space_alloc, ps3::user_space_fixed_alloc, ps3::user_space_dealloc }, }; void close() diff --git a/rpcs3/Emu/Memory/vm.h b/rpcs3/Emu/Memory/vm.h index a49c21eaab..5e07706646 100644 --- a/rpcs3/Emu/Memory/vm.h +++ b/rpcs3/Emu/Memory/vm.h @@ -8,16 +8,24 @@ namespace vm enum memory_location : uint { main, + user_space, stack, - //remove me - sprx, - - user_space, - memory_location_count }; + enum page_info_t : u8 + { + page_readable = (1 << 0), + page_writable = (1 << 1), + page_executable = (1 << 2), + + page_fault_notification = (1 << 3), + page_no_reservations = (1 << 4), + + page_allocated = (1 << 7), + }; + static void set_stack_size(u32 size) {} static void initialize_stack() {} @@ -34,11 +42,23 @@ namespace vm bool reservation_acquire(void* data, u32 addr, u32 size, const std::function& callback = nullptr); // attempt to atomically update reserved memory bool reservation_update(u32 addr, const void* data, u32 size); + // for internal use bool reservation_query(u32 addr, bool is_writing); + // for internal use void reservation_free(); // perform complete operation void reservation_op(u32 addr, u32 size, std::function proc); + // for internal use + void page_map(u32 addr, u32 size, u8 flags); + // for internal use + bool page_protect(u32 addr, u32 size, u8 flags_test = 0, u8 flags_set = 0, u8 flags_clear = 0); + // for internal use + void page_unmap(u32 addr, u32 size); + + // unsafe address check + bool check_addr(u32 addr, u32 size = 1); + bool map(u32 addr, u32 size, u32 flags); bool unmap(u32 addr, u32 size = 0, u32 flags = 0); u32 alloc(u32 size, memory_location location = user_space); diff --git a/rpcs3/Emu/Memory/vm_var.h b/rpcs3/Emu/Memory/vm_var.h index 06864950b9..a8c380aac1 100644 --- a/rpcs3/Emu/Memory/vm_var.h +++ b/rpcs3/Emu/Memory/vm_var.h @@ -35,7 +35,7 @@ namespace vm void alloc() { - m_addr = vm::cast(Memory.Alloc(size(), m_align)); + m_addr = Memory.Alloc(size(), m_align); m_ptr = vm::get_ptr(m_addr); } @@ -162,7 +162,7 @@ namespace vm void alloc() { - m_addr = vm::cast(Memory.Alloc(size(), m_align)); + m_addr = Memory.Alloc(size(), m_align); m_ptr = vm::get_ptr(m_addr); } diff --git a/rpcs3/Emu/RSX/GCM.h b/rpcs3/Emu/RSX/GCM.h index 929b968503..c372ddd6b1 100644 --- a/rpcs3/Emu/RSX/GCM.h +++ b/rpcs3/Emu/RSX/GCM.h @@ -235,6 +235,7 @@ struct gcmInfo u32 config_addr; u32 context_addr; u32 control_addr; + u32 label_addr; }; struct CellGcmSurface diff --git a/rpcs3/Emu/RSX/GL/GLGSRender.cpp b/rpcs3/Emu/RSX/GL/GLGSRender.cpp index 1b3df4a0bd..b1f0475d9d 100644 --- a/rpcs3/Emu/RSX/GL/GLGSRender.cpp +++ b/rpcs3/Emu/RSX/GL/GLGSRender.cpp @@ -104,12 +104,7 @@ void GLTexture::Init(RSXTexture& tex) Bind(); - const u64 texaddr = GetAddress(tex.GetOffset(), tex.GetLocation()); - if (!Memory.IsGoodAddr(texaddr)) - { - LOG_ERROR(RSX, "Bad texture address=0x%x", texaddr); - return; - } + const u32 texaddr = GetAddress(tex.GetOffset(), tex.GetLocation()); //LOG_WARNING(RSX, "texture addr = 0x%x, width = %d, height = %d, max_aniso=%d, mipmap=%d, remap=0x%x, zfunc=0x%x, wraps=0x%x, wrapt=0x%x, wrapr=0x%x, minlod=0x%x, maxlod=0x%x", // m_offset, m_width, m_height, m_maxaniso, m_mipmap, m_remap, m_zfunc, m_wraps, m_wrapt, m_wrapr, m_minlod, m_maxlod); @@ -1242,11 +1237,6 @@ void GLGSRender::WriteDepthBuffer() } u32 address = GetAddress(m_surface_offset_z, m_context_dma_z - 0xfeed0000); - if (!Memory.IsGoodAddr(address)) - { - LOG_WARNING(RSX, "Bad depth buffer address: address=0x%x, offset=0x%x, dma=0x%x", address, m_surface_offset_z, m_context_dma_z); - return; - } auto ptr = vm::get_ptr(address); glBindBuffer(GL_PIXEL_PACK_BUFFER, g_pbo[4]); @@ -1279,11 +1269,6 @@ void GLGSRender::WriteColorBufferA() } u32 address = GetAddress(m_surface_offset_a, m_context_dma_color_a - 0xfeed0000); - if (!Memory.IsGoodAddr(address)) - { - LOG_ERROR(RSX, "Bad color buffer A address: address=0x%x, offset=0x%x, dma=0x%x", address, m_surface_offset_a, m_context_dma_color_a); - return; - } glReadBuffer(GL_COLOR_ATTACHMENT0); checkForGlError("WriteColorBufferA(): glReadBuffer"); @@ -1310,11 +1295,6 @@ void GLGSRender::WriteColorBufferB() } u32 address = GetAddress(m_surface_offset_b, m_context_dma_color_b - 0xfeed0000); - if (!Memory.IsGoodAddr(address)) - { - LOG_ERROR(RSX, "Bad color buffer B address: address=0x%x, offset=0x%x, dma=0x%x", address, m_surface_offset_b, m_context_dma_color_b); - return; - } glReadBuffer(GL_COLOR_ATTACHMENT1); checkForGlError("WriteColorBufferB(): glReadBuffer"); @@ -1341,11 +1321,6 @@ void GLGSRender::WriteColorBufferC() } u32 address = GetAddress(m_surface_offset_c, m_context_dma_color_c - 0xfeed0000); - if (!Memory.IsGoodAddr(address)) - { - LOG_ERROR(RSX, "Bad color buffer C address: address=0x%x, offset=0x%x, dma=0x%x", address, m_surface_offset_c, m_context_dma_color_c); - return; - } glReadBuffer(GL_COLOR_ATTACHMENT2); checkForGlError("WriteColorBufferC(): glReadBuffer"); @@ -1372,11 +1347,6 @@ void GLGSRender::WriteColorBufferD() } u32 address = GetAddress(m_surface_offset_d, m_context_dma_color_d - 0xfeed0000); - if (!Memory.IsGoodAddr(address)) - { - LOG_ERROR(RSX, "Bad color buffer D address: address=0x%x, offset=0x%x, dma=0x%x", address, m_surface_offset_d, m_context_dma_color_d); - return; - } glReadBuffer(GL_COLOR_ATTACHMENT3); checkForGlError("WriteColorBufferD(): glReadBuffer"); @@ -1682,14 +1652,9 @@ void GLGSRender::InitDrawBuffers() u32 format = GL_BGRA; CellGcmDisplayInfo* buffers = vm::get_ptr(m_gcm_buffers_addr); u32 addr = GetAddress(buffers[m_gcm_current_buffer].offset, CELL_GCM_LOCATION_LOCAL); - - if (Memory.IsGoodAddr(addr)) - { - u32 width = buffers[m_gcm_current_buffer].width; - u32 height = buffers[m_gcm_current_buffer].height; - - glDrawPixels(width, height, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8, vm::get_ptr(addr)); - } + u32 width = buffers[m_gcm_current_buffer].width; + u32 height = buffers[m_gcm_current_buffer].height; + glDrawPixels(width, height, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8, vm::get_ptr(addr)); } } @@ -2139,17 +2104,9 @@ void GLGSRender::Flip() format = GL_BGRA; CellGcmDisplayInfo* buffers = vm::get_ptr(m_gcm_buffers_addr); u32 addr = GetAddress(buffers[m_gcm_current_buffer].offset, CELL_GCM_LOCATION_LOCAL); - - if (Memory.IsGoodAddr(addr)) - { - width = buffers[m_gcm_current_buffer].width; - height = buffers[m_gcm_current_buffer].height; - src_buffer = vm::get_ptr(addr); - } - else - { - src_buffer = nullptr; - } + width = buffers[m_gcm_current_buffer].width; + height = buffers[m_gcm_current_buffer].height; + src_buffer = vm::get_ptr(addr); } else if (m_fbo.IsCreated()) { diff --git a/rpcs3/Emu/RSX/RSXThread.cpp b/rpcs3/Emu/RSX/RSXThread.cpp index 45ab4e068d..e302ec5de5 100644 --- a/rpcs3/Emu/RSX/RSXThread.cpp +++ b/rpcs3/Emu/RSX/RSXThread.cpp @@ -261,7 +261,7 @@ void RSXThread::DoCmd(const u32 fcmd, const u32 cmd, const u32 args_addr, const if (m_set_semaphore_offset) { m_set_semaphore_offset = false; - vm::write32(Memory.RSXCMDMem.GetStartAddr() + m_semaphore_offset, ARGS(0)); + vm::write32(m_label_addr + m_semaphore_offset, ARGS(0)); } break; } @@ -274,7 +274,7 @@ void RSXThread::DoCmd(const u32 fcmd, const u32 cmd, const u32 args_addr, const u32 value = ARGS(0); value = (value & 0xff00ff00) | ((value & 0xff) << 16) | ((value >> 16) & 0xff); - vm::write32(Memory.RSXCMDMem.GetStartAddr() + m_semaphore_offset, value); + vm::write32(m_label_addr + m_semaphore_offset, value); } break; } diff --git a/rpcs3/Emu/RSX/RSXThread.h b/rpcs3/Emu/RSX/RSXThread.h index 75ea01fe78..79bc63a96f 100644 --- a/rpcs3/Emu/RSX/RSXThread.h +++ b/rpcs3/Emu/RSX/RSXThread.h @@ -134,6 +134,7 @@ public: u32 m_gcm_current_buffer; u32 m_ctxt_addr; u32 m_report_main_addr; + u32 m_label_addr; // DMA u32 dma_report; diff --git a/rpcs3/Emu/SysCalls/Modules/cellAudio.cpp b/rpcs3/Emu/SysCalls/Modules/cellAudio.cpp index 56cd7a7e79..11e7b78220 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellAudio.cpp +++ b/rpcs3/Emu/SysCalls/Modules/cellAudio.cpp @@ -41,8 +41,8 @@ s32 cellAudioInit() g_audio.start_time = get_system_time(); // alloc memory (only once until the emulator is stopped) - g_audio.buffer = g_audio.buffer ? g_audio.buffer : vm::cast(Memory.MainMem.AllocAlign(AUDIO_PORT_OFFSET * AUDIO_PORT_COUNT, 4096)); - g_audio.indexes = g_audio.indexes ? g_audio.indexes : vm::cast(Memory.MainMem.AllocAlign(sizeof(u64) * AUDIO_PORT_COUNT, __alignof(u64))); + g_audio.buffer = g_audio.buffer ? g_audio.buffer : Memory.MainMem.AllocAlign(AUDIO_PORT_OFFSET * AUDIO_PORT_COUNT, 4096); + g_audio.indexes = g_audio.indexes ? g_audio.indexes : Memory.MainMem.AllocAlign(sizeof(u64) * AUDIO_PORT_COUNT, __alignof(u64)); // clear memory memset(vm::get_ptr(g_audio.buffer), 0, AUDIO_PORT_OFFSET * AUDIO_PORT_COUNT); diff --git a/rpcs3/Emu/SysCalls/Modules/cellGcmSys.cpp b/rpcs3/Emu/SysCalls/Modules/cellGcmSys.cpp index 547c1b61ad..2b9ee49ff2 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellGcmSys.cpp +++ b/rpcs3/Emu/SysCalls/Modules/cellGcmSys.cpp @@ -76,7 +76,7 @@ void InitOffsetTable() u32 cellGcmGetLabelAddress(u8 index) { cellGcmSys->Log("cellGcmGetLabelAddress(index=%d)", index); - return (u32)Memory.RSXCMDMem.GetStartAddr() + 0x10 * index; + return gcm_info.label_addr + 0x10 * index; } vm::ptr cellGcmGetReportDataAddressLocation(u32 index, u32 location) @@ -360,8 +360,6 @@ s32 _cellGcmInitBody(vm::ptr context, u32 cmdSize, u32 ioSiz current_config.memoryFrequency = 650000000; current_config.coreFrequency = 500000000; - Memory.RSXCMDMem.AllocAlign(cmdSize); - u32 ctx_begin = ioAddress/* + 0x1000*/; u32 ctx_size = 0x6ffc; current_context.begin = ctx_begin; @@ -369,9 +367,11 @@ s32 _cellGcmInitBody(vm::ptr context, u32 cmdSize, u32 ioSiz current_context.current = current_context.begin; current_context.callback.set(be_t::make(Emu.GetRSXCallback() - 4)); - gcm_info.context_addr = (u32)Memory.MainMem.AllocAlign(0x1000); + gcm_info.context_addr = Memory.MainMem.AllocAlign(0x1000); gcm_info.control_addr = gcm_info.context_addr + 0x40; + gcm_info.label_addr = Memory.MainMem.AllocAlign(0x1000); // ??? + vm::get_ref(gcm_info.context_addr) = current_context; vm::write32(context.addr(), gcm_info.context_addr); @@ -388,6 +388,7 @@ s32 _cellGcmInitBody(vm::ptr context, u32 cmdSize, u32 ioSiz render.m_gcm_buffers_count = 0; render.m_gcm_current_buffer = 0; render.m_main_mem_addr = 0; + render.m_label_addr = gcm_info.label_addr; render.Init(ctx_begin, ctx_size, gcm_info.control_addr, local_addr); return CELL_OK; @@ -1109,7 +1110,7 @@ int cellGcmSetFlipCommandWithWaitLabel(vm::ptr ctx, u32 id, ctx.addr(), id, label_index, label_value); int res = cellGcmSetPrepareFlip(ctx, id); - vm::write32(Memory.RSXCMDMem.GetStartAddr() + 0x10 * label_index, label_value); + vm::write32(gcm_info.label_addr + 0x10 * label_index, label_value); return res < 0 ? CELL_GCM_ERROR_FAILURE : CELL_OK; } diff --git a/rpcs3/Emu/SysCalls/Modules/sysPrxForUser.cpp b/rpcs3/Emu/SysCalls/Modules/sysPrxForUser.cpp index 961e04dde3..37ae8f610c 100644 --- a/rpcs3/Emu/SysCalls/Modules/sysPrxForUser.cpp +++ b/rpcs3/Emu/SysCalls/Modules/sysPrxForUser.cpp @@ -41,7 +41,7 @@ u32 ppu_get_tls(u32 thread) if (!g_tls_start) { g_tls_size = Emu.GetTLSMemsz() + TLS_SYS; - g_tls_start = vm::cast(Memory.MainMem.AllocAlign(g_tls_size * TLS_MAX, 4096)); // memory for up to TLS_MAX threads + g_tls_start = Memory.MainMem.AllocAlign(g_tls_size * TLS_MAX, 4096); // memory for up to TLS_MAX threads sysPrxForUser->Notice("Thread Local Storage initialized (g_tls_start=0x%x, user_size=0x%x)\n*** TLS segment addr: 0x%08x\n*** TLS segment size: 0x%08x", g_tls_start, Emu.GetTLSMemsz(), Emu.GetTLSAddr(), Emu.GetTLSFilesz()); } diff --git a/rpcs3/Emu/SysCalls/lv2/sys_spu.cpp b/rpcs3/Emu/SysCalls/lv2/sys_spu.cpp index 8def286a85..26df83c60d 100644 --- a/rpcs3/Emu/SysCalls/lv2/sys_spu.cpp +++ b/rpcs3/Emu/SysCalls/lv2/sys_spu.cpp @@ -88,7 +88,7 @@ SPUThread* spu_thread_initialize(std::shared_ptr& group, u32 spu_n const u32 spu_ep = img.entry_point; // Copy SPU image: // TODO: use segment info - const u32 spu_offset = vm::cast(Memory.MainMem.AllocAlign(256 * 1024, 4096)); + const u32 spu_offset = Memory.MainMem.AllocAlign(256 * 1024, 4096); memcpy(vm::get_ptr(spu_offset), vm::get_ptr(img.addr), 256 * 1024); SPUThread& new_thread = static_cast(Emu.GetCPU().AddThread(CPU_THREAD_SPU)); diff --git a/rpcs3/Emu/SysCalls/lv2/sys_vm.cpp b/rpcs3/Emu/SysCalls/lv2/sys_vm.cpp index ed0615c13b..ab9c5cdcf6 100644 --- a/rpcs3/Emu/SysCalls/lv2/sys_vm.cpp +++ b/rpcs3/Emu/SysCalls/lv2/sys_vm.cpp @@ -27,7 +27,7 @@ s32 sys_vm_memory_map(u32 vsize, u32 psize, u32 cid, u64 flag, u64 policy, u32 a } // Use fixed address (TODO: search and use some free address instead) - u32 new_addr = Memory.IsGoodAddr(0x60000000) ? 0x70000000 : 0x60000000; + u32 new_addr = vm::check_addr(0x60000000) ? 0x70000000 : 0x60000000; // If container ID is SYS_MEMORY_CONTAINER_ID_INVALID, allocate directly. if(cid == SYS_MEMORY_CONTAINER_ID_INVALID) @@ -45,7 +45,10 @@ s32 sys_vm_memory_map(u32 vsize, u32 psize, u32 cid, u64 flag, u64 policy, u32 a } // Allocate actual memory using virtual size (physical size is ignored) - assert(Memory.Map(new_addr, vsize)); + if (!Memory.Map(new_addr, vsize)) + { + return CELL_ENOMEM; + } // Write a pointer for the allocated memory. vm::write32(addr, new_addr); diff --git a/rpcs3/Gui/InterpreterDisAsm.cpp b/rpcs3/Gui/InterpreterDisAsm.cpp index b16742f078..2fb7e97fe4 100644 --- a/rpcs3/Gui/InterpreterDisAsm.cpp +++ b/rpcs3/Gui/InterpreterDisAsm.cpp @@ -251,7 +251,7 @@ void InterpreterDisAsmFrame::ShowAddr(const u64 addr) disasm->offset = vm::get_ptr(CPU->GetOffset()); for(uint i=0, count = 4; iGetOffset() + PC, 4)) + if(!vm::check_addr(CPU->GetOffset() + PC, 4)) { m_list->SetItem(i, 0, wxString(IsBreakPoint(PC) ? ">>> " : " ") + wxString::Format("[%08llx] illegal address", PC)); count = 4; diff --git a/rpcs3/Gui/MemoryStringSearcher.cpp b/rpcs3/Gui/MemoryStringSearcher.cpp index 8676d57371..aa823d245e 100644 --- a/rpcs3/Gui/MemoryStringSearcher.cpp +++ b/rpcs3/Gui/MemoryStringSearcher.cpp @@ -45,7 +45,7 @@ void MemoryStringSearcher::Search(wxCommandEvent& event) u32 strIndex = 0; u32 numFound = 0; for (u32 addr = Memory.MainMem.GetStartAddr(); addr < Memory.MainMem.GetEndAddr(); addr++) { - if (!Memory.IsGoodAddr(addr)) { + if (!vm::check_addr(addr)) { strIndex = 0; continue; } diff --git a/rpcs3/Gui/MemoryViewer.cpp b/rpcs3/Gui/MemoryViewer.cpp index 59f3917713..f6455c12d7 100644 --- a/rpcs3/Gui/MemoryViewer.cpp +++ b/rpcs3/Gui/MemoryViewer.cpp @@ -200,7 +200,7 @@ void MemoryViewerPanel::ShowMemory() { u32 addr = m_addr + row * m_colcount + col; - if (Memory.IsGoodAddr(addr)) + if (vm::check_addr(addr)) { const u8 rmem = vm::read8(addr); t_mem_hex_str += wxString::Format("%02x ", rmem); diff --git a/rpcs3/Gui/RSXDebugger.cpp b/rpcs3/Gui/RSXDebugger.cpp index 4c408b509e..99ce16e0ae 100644 --- a/rpcs3/Gui/RSXDebugger.cpp +++ b/rpcs3/Gui/RSXDebugger.cpp @@ -259,14 +259,14 @@ void RSXDebugger::OnChangeToolsAddr(wxCommandEvent& event) void RSXDebugger::OnScrollMemory(wxMouseEvent& event) { - if(Memory.IsGoodAddr(m_addr)) + if(vm::check_addr(m_addr)) { int items = event.ControlDown() ? m_item_count : 1; for(int i=0; iGetId()) { u8 location = render.m_textures[m_cur_texture].GetLocation(); - if(location <= 1 && Memory.IsGoodAddr(GetAddress(render.m_textures[m_cur_texture].GetOffset(), location)) + if(location <= 1 && vm::check_addr(GetAddress(render.m_textures[m_cur_texture].GetOffset(), location)) && render.m_textures[m_cur_texture].GetWidth() && render.m_textures[m_cur_texture].GetHeight()) MemoryViewerPanel::ShowImage(this, GetAddress(render.m_textures[m_cur_texture].GetOffset(), location), 1, @@ -380,7 +380,7 @@ void RSXDebugger::GetMemory() { m_list_commands->SetItem(i, 0, wxString::Format("%08x", addr)); - if (isReady && Memory.IsGoodAddr(addr)) + if (isReady && vm::check_addr(addr)) { u32 cmd = vm::read32(addr); u32 count = (cmd >> 18) & 0x7ff; @@ -409,13 +409,13 @@ void RSXDebugger::GetBuffers() // TODO: Currently it only supports color buffers for (u32 bufferId=0; bufferId < render.m_gcm_buffers_count; bufferId++) { - if(!Memory.IsGoodAddr(render.m_gcm_buffers_addr)) + if(!vm::check_addr(render.m_gcm_buffers_addr)) continue; auto buffers = vm::get_ptr(render.m_gcm_buffers_addr); u32 RSXbuffer_addr = render.m_local_mem_addr + buffers[bufferId].offset; - if(!Memory.IsGoodAddr(RSXbuffer_addr)) + if(!vm::check_addr(RSXbuffer_addr)) continue; auto RSXbuffer = vm::get_ptr(RSXbuffer_addr); @@ -467,7 +467,7 @@ void RSXDebugger::GetBuffers() u32 TexBuffer_addr = GetAddress(offset, location); - if(!Memory.IsGoodAddr(TexBuffer_addr)) + if(!vm::check_addr(TexBuffer_addr)) return; unsigned char* TexBuffer = vm::get_ptr(TexBuffer_addr); diff --git a/rpcs3/Loader/ELF64.cpp b/rpcs3/Loader/ELF64.cpp index ac64afc207..a83883484c 100644 --- a/rpcs3/Loader/ELF64.cpp +++ b/rpcs3/Loader/ELF64.cpp @@ -101,7 +101,7 @@ namespace loader segment.size = phdr.p_memsz; segment.size_file = phdr.p_filesz; - segment.begin.set(vm::alloc(segment.size, vm::sprx)); + segment.begin.set(vm::alloc(segment.size, vm::main)); if (!segment.begin) {