ifdefs and linux (posix) version (not tested)

This commit is contained in:
Nekotekina 2014-07-08 18:26:49 +04:00
parent d1fff053c2
commit 50b42f8593
5 changed files with 131 additions and 70 deletions

View File

@ -280,6 +280,7 @@ void CPUThread::ExecOnce()
SendDbgCommand(DID_PAUSED_THREAD, this); SendDbgCommand(DID_PAUSED_THREAD, this);
} }
#ifdef _WIN32
void _se_translator(unsigned int u, EXCEPTION_POINTERS* pExp) void _se_translator(unsigned int u, EXCEPTION_POINTERS* pExp)
{ {
const u64 addr = (u64)Memory.GetBaseAddr() - (u64)pExp->ExceptionRecord->ExceptionAddress; const u64 addr = (u64)Memory.GetBaseAddr() - (u64)pExp->ExceptionRecord->ExceptionAddress;
@ -296,6 +297,9 @@ void _se_translator(unsigned int u, EXCEPTION_POINTERS* pExp)
return; return;
} }
} }
#else
// TODO: linux version
#endif
void CPUThread::Task() void CPUThread::Task()
{ {
@ -312,7 +316,11 @@ void CPUThread::Task()
} }
} }
#ifdef _WIN32
_set_se_translator(_se_translator); _set_se_translator(_se_translator);
#else
// TODO: linux version
#endif
while (true) while (true)
{ {

View File

@ -105,7 +105,7 @@ bool DynamicMemoryBlockBase<PT>::AllocFixed(u64 addr, u32 size)
template<typename PT> template<typename PT>
void DynamicMemoryBlockBase<PT>::AppendMem(u64 addr, u32 size) /* private */ void DynamicMemoryBlockBase<PT>::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; u8* pointer = (u8*) m_allocated.back().mem;
const u32 first = MemoryBlock::FixAddr(addr) >> 12; const u32 first = MemoryBlock::FixAddr(addr) >> 12;

View File

@ -8,8 +8,53 @@
MemoryBase Memory; 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::MemoryBlock() : mem_inf(nullptr)
{ {
Init(); Init();
} }
@ -29,16 +74,26 @@ void MemoryBlock::Init()
void MemoryBlock::InitMemory() void MemoryBlock::InitMemory()
{ {
if(!range_size) return; if (!range_size) return;
if (mem) VirtualFree(mem, range_size, MEM_DECOMMIT); Free();
mem = (u8*)VirtualAlloc((void*)((u64)Memory.GetBaseAddr() + range_start), range_size, MEM_COMMIT, PAGE_READWRITE); mem_inf = new MemBlockInfo(range_start, range_size);
memset(mem, 0, range_size); mem = (u8*)mem_inf->mem;
}
void MemoryBlock::Free()
{
if (mem_inf)
{
delete mem_inf;
mem_inf = nullptr;
}
mem = nullptr;
} }
void MemoryBlock::Delete() void MemoryBlock::Delete()
{ {
if (mem) VirtualFree(mem, range_size, MEM_DECOMMIT); Free();
Init(); Init();
} }

View File

@ -24,6 +24,7 @@ class MemoryBase
{ {
void* m_base_addr; void* m_base_addr;
std::vector<MemoryBlock*> MemoryBlocks; std::vector<MemoryBlock*> MemoryBlocks;
u32 m_pages[0x100000000 / 4096]; // information about every page
std::mutex m_mutex; std::mutex m_mutex;
public: public:
@ -35,7 +36,7 @@ public:
DynamicMemoryBlock MmaperMem; DynamicMemoryBlock MmaperMem;
DynamicMemoryBlock RSXFBMem; DynamicMemoryBlock RSXFBMem;
DynamicMemoryBlock StackMem; DynamicMemoryBlock StackMem;
MemoryBlock* RawSPUMem[32]; MemoryBlock* RawSPUMem[(0x100000000 - RAW_SPU_BASE_ADDR) / RAW_SPU_OFFSET];
VirtualMemoryBlock RSXIOMem; VirtualMemoryBlock RSXIOMem;
struct struct
@ -70,6 +71,24 @@ public:
return m_base_addr; 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) static __forceinline u16 Reverse16(const u16 val)
{ {
return _byteswap_ushort(val); return _byteswap_ushort(val);
@ -129,7 +148,7 @@ public:
std::lock_guard<std::mutex> lock(m_mutex); std::lock_guard<std::mutex> lock(m_mutex);
MemoryBlocks.push_back(raw_spu); 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) void CloseRawSPU(MemoryBlock* raw_spu, const u32 num)
@ -144,7 +163,7 @@ public:
break; break;
} }
} }
if (num < 32) RawSPUMem[num] = nullptr; if (num < sizeof(RawSPUMem) / sizeof(RawSPUMem[0])) RawSPUMem[num] = nullptr;
} }
void Init(MemoryType type) void Init(MemoryType type)
@ -154,21 +173,26 @@ public:
if(m_inited) return; if(m_inited) return;
m_inited = true; 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); m_base_addr = VirtualAlloc(nullptr, 0x100000000, MEM_RESERVE, PAGE_NOACCESS);
if (!m_base_addr) 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 else
{ {
LOG_NOTICE(MEMORY, "Initing memory: m_base_addr = 0x%llx", (u64)m_base_addr); 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) switch(type)
{ {
case Memory_PS3: case Memory_PS3:
@ -199,52 +223,30 @@ public:
bool IsGoodAddr(const u64 addr) bool IsGoodAddr(const u64 addr)
{ {
//std::lock_guard<std::mutex> lock(m_mutex); if (addr >= 0x100000000 || !m_pages[addr / 4096]) // TODO: define page parameters
__try
{
volatile const u8 test = *GetMemFromAddr(addr);
}
__except (EXCEPTION_EXECUTE_HANDLER)
{ {
return false; return false;
} }
else
return true; {
return true;
//for (auto block : MemoryBlocks) }
//{
// if (block->IsMyAddress(addr))
// return true;
//}
//return false;
} }
bool IsGoodAddr(const u64 addr, const u32 size) bool IsGoodAddr(const u64 addr, const u32 size)
{ {
//std::lock_guard<std::mutex> lock(m_mutex); if (addr + size > 0x100000000)
__try
{
volatile const u8 test1 = *GetMemFromAddr(addr);
volatile const u8 test2 = *GetMemFromAddr(addr + size - 1);
}
__except (EXCEPTION_EXECUTE_HANDLER)
{ {
return false; return false;
} }
else
return true; {
for (u32 i = addr / 4096; i <= (addr + size - 1) / 4096; i++)
//const u64 end = addr + size - 1; {
//for (auto block : MemoryBlocks) if (!m_pages[i]) return false; // TODO: define page parameters
//{ }
// if (block->IsMyAddress(addr) && block->IsMyAddress(end)) return true;
// return true; }
//}
//return false;
} }
void Close() void Close()
@ -256,11 +258,6 @@ public:
LOG_NOTICE(MEMORY, "Closing memory..."); LOG_NOTICE(MEMORY, "Closing memory...");
for (u32 i = 0; i < 32; i++)
{
RawSPUMem[i] = nullptr;
}
for (auto block : MemoryBlocks) for (auto block : MemoryBlocks)
{ {
block->Delete(); block->Delete();
@ -268,10 +265,17 @@ public:
MemoryBlocks.clear(); MemoryBlocks.clear();
#ifdef _WIN32
if (!VirtualFree(m_base_addr, 0, MEM_RELEASE)) if (!VirtualFree(m_base_addr, 0, MEM_RELEASE))
{ {
LOG_ERROR(MEMORY, "VirtualFree(0x%llx) failed", (u64)m_base_addr); 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); void Write8(const u64 addr, const u8 data);

View File

@ -22,17 +22,9 @@ struct MemBlockInfo : public MemInfo
{ {
void *mem; void *mem;
MemBlockInfo(u64 _addr, u32 _size, void* base_addr) MemBlockInfo(u64 _addr, u32 _size);
: MemInfo(_addr, PAGE_4K(_size))
, mem(VirtualAlloc((void*)((u64)base_addr + _addr), PAGE_4K(_size), MEM_COMMIT, PAGE_READWRITE)) void Free();
{
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(MemBlockInfo &other) = delete; MemBlockInfo(MemBlockInfo &other) = delete;
MemBlockInfo(MemBlockInfo &&other) : MemInfo(other.addr,other.size) ,mem(other.mem) MemBlockInfo(MemBlockInfo &&other) : MemInfo(other.addr,other.size) ,mem(other.mem)
@ -43,7 +35,7 @@ struct MemBlockInfo : public MemInfo
MemBlockInfo& operator =(MemBlockInfo &&other){ MemBlockInfo& operator =(MemBlockInfo &&other){
this->addr = other.addr; this->addr = other.addr;
this->size = other.size; this->size = other.size;
if (this->mem) VirtualFree(this->mem, this->size, MEM_DECOMMIT); this->Free();
this->mem = other.mem; this->mem = other.mem;
other.mem = nullptr; other.mem = nullptr;
return *this; return *this;
@ -51,7 +43,7 @@ struct MemBlockInfo : public MemInfo
~MemBlockInfo() ~MemBlockInfo()
{ {
if (mem) VirtualFree(mem, size, MEM_DECOMMIT); Free();
mem = nullptr; mem = nullptr;
} }
}; };
@ -85,7 +77,9 @@ public:
virtual ~MemoryBlock(); virtual ~MemoryBlock();
private: private:
MemBlockInfo* mem_inf;
void Init(); void Init();
void Free();
void InitMemory(); void InitMemory();
public: public: