From 50b42f85932a454e8a0b0f2b5459472378a2df95 Mon Sep 17 00:00:00 2001 From: Nekotekina Date: Tue, 8 Jul 2014 18:26:49 +0400 Subject: [PATCH] ifdefs and linux (posix) version (not tested) --- rpcs3/Emu/CPU/CPUThread.cpp | 8 ++ rpcs3/Emu/Memory/DynamicMemoryBlockBase.h | 2 +- rpcs3/Emu/Memory/Memory.cpp | 67 ++++++++++++-- rpcs3/Emu/Memory/Memory.h | 104 +++++++++++----------- rpcs3/Emu/Memory/MemoryBlock.h | 20 ++--- 5 files changed, 131 insertions(+), 70 deletions(-) diff --git a/rpcs3/Emu/CPU/CPUThread.cpp b/rpcs3/Emu/CPU/CPUThread.cpp index cc21ba3c11..c19d8f48e2 100644 --- a/rpcs3/Emu/CPU/CPUThread.cpp +++ b/rpcs3/Emu/CPU/CPUThread.cpp @@ -280,6 +280,7 @@ void CPUThread::ExecOnce() SendDbgCommand(DID_PAUSED_THREAD, this); } +#ifdef _WIN32 void _se_translator(unsigned int u, EXCEPTION_POINTERS* pExp) { const u64 addr = (u64)Memory.GetBaseAddr() - (u64)pExp->ExceptionRecord->ExceptionAddress; @@ -296,6 +297,9 @@ void _se_translator(unsigned int u, EXCEPTION_POINTERS* pExp) return; } } +#else +// TODO: linux version +#endif void CPUThread::Task() { @@ -312,7 +316,11 @@ void CPUThread::Task() } } +#ifdef _WIN32 _set_se_translator(_se_translator); +#else + // TODO: linux version +#endif while (true) { diff --git a/rpcs3/Emu/Memory/DynamicMemoryBlockBase.h b/rpcs3/Emu/Memory/DynamicMemoryBlockBase.h index 0d86262059..77e50c8869 100644 --- a/rpcs3/Emu/Memory/DynamicMemoryBlockBase.h +++ b/rpcs3/Emu/Memory/DynamicMemoryBlockBase.h @@ -105,7 +105,7 @@ bool DynamicMemoryBlockBase::AllocFixed(u64 addr, u32 size) template void DynamicMemoryBlockBase::AppendMem(u64 addr, u32 size) /* private */ { - m_allocated.emplace_back(addr, size, Memory.GetBaseAddr()); + m_allocated.emplace_back(addr, size); u8* pointer = (u8*) m_allocated.back().mem; const u32 first = MemoryBlock::FixAddr(addr) >> 12; diff --git a/rpcs3/Emu/Memory/Memory.cpp b/rpcs3/Emu/Memory/Memory.cpp index 5395bd1089..cd78fee7ad 100644 --- a/rpcs3/Emu/Memory/Memory.cpp +++ b/rpcs3/Emu/Memory/Memory.cpp @@ -8,8 +8,53 @@ MemoryBase Memory; +MemBlockInfo::MemBlockInfo(u64 _addr, u32 _size) + : MemInfo(_addr, PAGE_4K(_size)) +{ + void* real_addr = (void*)((u64)Memory.GetBaseAddr() + _addr); +#ifdef _WIN32 + mem = VirtualAlloc(real_addr, size, MEM_COMMIT, PAGE_READWRITE); +#else + if (::mprotect(real_addr, size, PROT_READ | PROT_WRITE)) + { + mem = nullptr; + } + else + { + mem = real_addr; + } +#endif + if (mem != real_addr) + { + LOG_ERROR(MEMORY, "Memory allocation failed (addr=0x%llx, size=0x%llx)", addr, size); + Emu.Pause(); + } + else + { + Memory.RegisterPages(_addr, PAGE_4K(_size)); + memset(mem, 0, size); + } +} + +void MemBlockInfo::Free() +{ + if (mem) + { + Memory.UnregisterPages(addr, size); +#ifdef _WIN32 + if (!VirtualFree(mem, size, MEM_DECOMMIT)) +#else + if (::mprotect(mem, size, PROT_NONE)) +#endif + { + LOG_ERROR(MEMORY, "Memory deallocation failed (addr=0x%llx, size=0x%llx)", addr, size); + Emu.Pause(); + } + } +} + //MemoryBlock -MemoryBlock::MemoryBlock() +MemoryBlock::MemoryBlock() : mem_inf(nullptr) { Init(); } @@ -29,16 +74,26 @@ void MemoryBlock::Init() void MemoryBlock::InitMemory() { - if(!range_size) return; + if (!range_size) return; - if (mem) VirtualFree(mem, range_size, MEM_DECOMMIT); - mem = (u8*)VirtualAlloc((void*)((u64)Memory.GetBaseAddr() + range_start), range_size, MEM_COMMIT, PAGE_READWRITE); - memset(mem, 0, range_size); + Free(); + mem_inf = new MemBlockInfo(range_start, range_size); + mem = (u8*)mem_inf->mem; +} + +void MemoryBlock::Free() +{ + if (mem_inf) + { + delete mem_inf; + mem_inf = nullptr; + } + mem = nullptr; } void MemoryBlock::Delete() { - if (mem) VirtualFree(mem, range_size, MEM_DECOMMIT); + Free(); Init(); } diff --git a/rpcs3/Emu/Memory/Memory.h b/rpcs3/Emu/Memory/Memory.h index fb4db9349d..9f682a0c5f 100644 --- a/rpcs3/Emu/Memory/Memory.h +++ b/rpcs3/Emu/Memory/Memory.h @@ -24,6 +24,7 @@ class MemoryBase { void* m_base_addr; std::vector MemoryBlocks; + u32 m_pages[0x100000000 / 4096]; // information about every page std::mutex m_mutex; public: @@ -35,7 +36,7 @@ public: DynamicMemoryBlock MmaperMem; DynamicMemoryBlock RSXFBMem; DynamicMemoryBlock StackMem; - MemoryBlock* RawSPUMem[32]; + MemoryBlock* RawSPUMem[(0x100000000 - RAW_SPU_BASE_ADDR) / RAW_SPU_OFFSET]; VirtualMemoryBlock RSXIOMem; struct @@ -70,6 +71,24 @@ public: return m_base_addr; } + void RegisterPages(u64 addr, u32 size) + { + for (u32 i = addr / 4096; i < (addr + size) / 4096; i++) + { + if (i >= sizeof(m_pages) / sizeof(m_pages[0])) break; + m_pages[i] = 1; // TODO: define page parameters + } + } + + void UnregisterPages(u64 addr, u32 size) + { + for (u32 i = addr / 4096; i < (addr + size) / 4096; i++) + { + if (i >= sizeof(m_pages) / sizeof(m_pages[0])) break; + m_pages[i] = 0; // TODO: define page parameters + } + } + static __forceinline u16 Reverse16(const u16 val) { return _byteswap_ushort(val); @@ -129,7 +148,7 @@ public: std::lock_guard lock(m_mutex); MemoryBlocks.push_back(raw_spu); - if (num < 32) RawSPUMem[num] = raw_spu; + if (num < sizeof(RawSPUMem) / sizeof(RawSPUMem[0])) RawSPUMem[num] = raw_spu; } void CloseRawSPU(MemoryBlock* raw_spu, const u32 num) @@ -144,7 +163,7 @@ public: break; } } - if (num < 32) RawSPUMem[num] = nullptr; + if (num < sizeof(RawSPUMem) / sizeof(RawSPUMem[0])) RawSPUMem[num] = nullptr; } void Init(MemoryType type) @@ -154,21 +173,26 @@ public: if(m_inited) return; m_inited = true; + memset(m_pages, 0, sizeof(m_pages)); + memset(RawSPUMem, 0, sizeof(RawSPUMem)); + +#ifdef _WIN32 m_base_addr = VirtualAlloc(nullptr, 0x100000000, MEM_RESERVE, PAGE_NOACCESS); if (!m_base_addr) +#else + m_base_addr = ::mmap(nullptr, 0x100000000, PROT_NONE, MAP_PRIVATE | MAP_ANONYMOUS, 0, 0); + if (m_base_addr == (void*)-1) +#endif { - LOG_ERROR(MEMORY, "Initing memory: VirtualAlloc() failed"); + m_base_addr = nullptr; + LOG_ERROR(MEMORY, "Initing memory failed"); + assert(0); } else { LOG_NOTICE(MEMORY, "Initing memory: m_base_addr = 0x%llx", (u64)m_base_addr); } - for (u32 i = 0; i < 32; i++) - { - RawSPUMem[i] = nullptr; - } - switch(type) { case Memory_PS3: @@ -199,52 +223,30 @@ public: bool IsGoodAddr(const u64 addr) { - //std::lock_guard lock(m_mutex); - - __try - { - volatile const u8 test = *GetMemFromAddr(addr); - } - __except (EXCEPTION_EXECUTE_HANDLER) + if (addr >= 0x100000000 || !m_pages[addr / 4096]) // TODO: define page parameters { return false; } - - return true; - - //for (auto block : MemoryBlocks) - //{ - // if (block->IsMyAddress(addr)) - // return true; - //} - - //return false; + else + { + return true; + } } bool IsGoodAddr(const u64 addr, const u32 size) { - //std::lock_guard lock(m_mutex); - - __try - { - volatile const u8 test1 = *GetMemFromAddr(addr); - volatile const u8 test2 = *GetMemFromAddr(addr + size - 1); - } - __except (EXCEPTION_EXECUTE_HANDLER) + if (addr + size > 0x100000000) { return false; } - - return true; - - //const u64 end = addr + size - 1; - //for (auto block : MemoryBlocks) - //{ - // if (block->IsMyAddress(addr) && block->IsMyAddress(end)) - // return true; - //} - - //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() @@ -256,11 +258,6 @@ public: LOG_NOTICE(MEMORY, "Closing memory..."); - for (u32 i = 0; i < 32; i++) - { - RawSPUMem[i] = nullptr; - } - for (auto block : MemoryBlocks) { block->Delete(); @@ -268,10 +265,17 @@ public: MemoryBlocks.clear(); +#ifdef _WIN32 if (!VirtualFree(m_base_addr, 0, MEM_RELEASE)) { LOG_ERROR(MEMORY, "VirtualFree(0x%llx) failed", (u64)m_base_addr); } +#else + if (::munmap(m_base_addr, 0x100000000)) + { + LOG_ERROR(MEMORY, "::munmap(0x%llx) failed", (u64)m_base_addr); + } +#endif } void Write8(const u64 addr, const u8 data); diff --git a/rpcs3/Emu/Memory/MemoryBlock.h b/rpcs3/Emu/Memory/MemoryBlock.h index 4917846e0c..d58f5d7f17 100644 --- a/rpcs3/Emu/Memory/MemoryBlock.h +++ b/rpcs3/Emu/Memory/MemoryBlock.h @@ -22,17 +22,9 @@ struct MemBlockInfo : public MemInfo { void *mem; - MemBlockInfo(u64 _addr, u32 _size, void* base_addr) - : MemInfo(_addr, PAGE_4K(_size)) - , mem(VirtualAlloc((void*)((u64)base_addr + _addr), PAGE_4K(_size), MEM_COMMIT, PAGE_READWRITE)) - { - if(!mem) - { - LOG_ERROR(MEMORY, "Out of memory or VirtualAlloc() failed (_addr=0x%llx, _size=0x%llx)", _addr, _size); - assert(0); - } - memset(mem, 0, size); - } + MemBlockInfo(u64 _addr, u32 _size); + + void Free(); MemBlockInfo(MemBlockInfo &other) = delete; MemBlockInfo(MemBlockInfo &&other) : MemInfo(other.addr,other.size) ,mem(other.mem) @@ -43,7 +35,7 @@ struct MemBlockInfo : public MemInfo MemBlockInfo& operator =(MemBlockInfo &&other){ this->addr = other.addr; this->size = other.size; - if (this->mem) VirtualFree(this->mem, this->size, MEM_DECOMMIT); + this->Free(); this->mem = other.mem; other.mem = nullptr; return *this; @@ -51,7 +43,7 @@ struct MemBlockInfo : public MemInfo ~MemBlockInfo() { - if (mem) VirtualFree(mem, size, MEM_DECOMMIT); + Free(); mem = nullptr; } }; @@ -85,7 +77,9 @@ public: virtual ~MemoryBlock(); private: + MemBlockInfo* mem_inf; void Init(); + void Free(); void InitMemory(); public: