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);
}
#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)
{

View File

@ -105,7 +105,7 @@ bool DynamicMemoryBlockBase<PT>::AllocFixed(u64 addr, u32 size)
template<typename PT>
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;
const u32 first = MemoryBlock::FixAddr(addr) >> 12;

View File

@ -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();
}

View File

@ -24,6 +24,7 @@ class MemoryBase
{
void* m_base_addr;
std::vector<MemoryBlock*> 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<std::mutex> 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<std::mutex> 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<std::mutex> 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);

View File

@ -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: