memory Save/Restore

This commit is contained in:
Dr. Chat 2015-12-01 17:26:55 -06:00 committed by Ben Vanik
parent aa7919bd89
commit 432e32f7c2
2 changed files with 120 additions and 0 deletions

View File

@ -14,6 +14,7 @@
#include <algorithm> #include <algorithm>
#include <cstring> #include <cstring>
#include "xenia/base/byte_stream.h"
#include "xenia/base/clock.h" #include "xenia/base/clock.h"
#include "xenia/base/logging.h" #include "xenia/base/logging.h"
#include "xenia/base/math.h" #include "xenia/base/math.h"
@ -436,6 +437,35 @@ void Memory::DumpMap() {
XELOGE(""); XELOGE("");
} }
bool Memory::Save(ByteStream* stream) {
XELOGD("Serializing memory...");
heaps_.v00000000.Save(stream);
heaps_.v40000000.Save(stream);
heaps_.v80000000.Save(stream);
heaps_.v90000000.Save(stream);
heaps_.physical.Save(stream);
return true;
}
bool Memory::Restore(ByteStream* stream) {
heaps_.v00000000.Restore(stream);
heaps_.v40000000.Restore(stream);
heaps_.v80000000.Restore(stream);
heaps_.v90000000.Restore(stream);
heaps_.physical.Restore(stream);
return true;
}
void Memory::Reset() {
heaps_.v00000000.Reset();
heaps_.v40000000.Reset();
heaps_.v80000000.Reset();
heaps_.v90000000.Reset();
heaps_.physical.Reset();
}
xe::memory::PageAccess ToPageAccess(uint32_t protect) { xe::memory::PageAccess ToPageAccess(uint32_t protect) {
if ((protect & kMemoryProtectRead) && !(protect & kMemoryProtectWrite)) { if ((protect & kMemoryProtectRead) && !(protect & kMemoryProtectWrite)) {
return xe::memory::PageAccess::kReadOnly; return xe::memory::PageAccess::kReadOnly;
@ -522,6 +552,82 @@ void BaseHeap::DumpMap() {
} }
} }
bool BaseHeap::Save(ByteStream* stream) {
XELOGD("Heap %.8X-%.8X", heap_base_, heap_base_ + heap_size_);
for (size_t i = 0; i < page_table_.size(); i++) {
auto& page = page_table_[i];
stream->Write(page.qword);
if (!page.state) {
// Unallocated.
continue;
}
// TODO: Write compressed
if (page.state & kMemoryAllocationCommit &&
page.current_protect & kMemoryProtectRead) {
stream->Write((void*)(membase_ + heap_base_ + i * page_size_),
page_size_);
}
}
return true;
}
bool BaseHeap::Restore(ByteStream* stream) {
for (size_t i = 0; i < page_table_.size(); i++) {
auto& page = page_table_[i];
page.qword = stream->Read<uint64_t>();
if (!page.state) {
// Unallocated.
continue;
}
memory::AllocationType alloc_type;
memory::PageAccess page_access = memory::PageAccess::kNoAccess;
if ((page.state & (kMemoryAllocationReserve | kMemoryAllocationCommit)) ==
3) {
alloc_type = memory::AllocationType::kReserveCommit;
} else if (page.state & kMemoryAllocationCommit) {
alloc_type = memory::AllocationType::kCommit;
} else if (page.state & kMemoryAllocationReserve) {
alloc_type = memory::AllocationType::kReserve;
}
if ((page.current_protect & (kMemoryProtectRead | kMemoryProtectWrite)) ==
3) {
page_access = memory::PageAccess::kReadWrite;
} else if (page.current_protect & kMemoryProtectRead) {
page_access = memory::PageAccess::kReadOnly;
}
// Blah allocate on page granularity for now
if ((uint32_t)alloc_type & (uint32_t)memory::AllocationType::kCommit) {
xe::memory::AllocFixed(membase_ + heap_base_ + i * page_size_, page_size_,
alloc_type, page_access);
}
if (page.state & kMemoryAllocationCommit &&
page.current_protect & kMemoryProtectRead) {
if (!xe::memory::Protect(membase_ + heap_base_ + i * page_size_,
page_size_, page_access, nullptr)) {
assert_always();
}
stream->Read((void*)(membase_ + heap_base_ + i * page_size_), page_size_);
}
}
return true;
}
void BaseHeap::Reset() {
// TODO: Protect pages
for (size_t i = 0; i < page_table_.size(); i++) {
auto& page = page_table_[i];
page.qword = 0;
}
}
bool BaseHeap::Alloc(uint32_t size, uint32_t alignment, bool BaseHeap::Alloc(uint32_t size, uint32_t alignment,
uint32_t allocation_type, uint32_t protect, bool top_down, uint32_t allocation_type, uint32_t protect, bool top_down,
uint32_t* out_address) { uint32_t* out_address) {

View File

@ -19,6 +19,10 @@
#include "xenia/base/mutex.h" #include "xenia/base/mutex.h"
#include "xenia/cpu/mmio_handler.h" #include "xenia/cpu/mmio_handler.h"
namespace xe {
class ByteStream;
} // namespace xe
namespace xe { namespace xe {
enum SystemHeapFlag : uint32_t { enum SystemHeapFlag : uint32_t {
@ -144,6 +148,11 @@ class BaseHeap {
// This is only valid if the page is backed by a physical allocation. // This is only valid if the page is backed by a physical allocation.
uint32_t GetPhysicalAddress(uint32_t address); uint32_t GetPhysicalAddress(uint32_t address);
bool Save(ByteStream* stream);
bool Restore(ByteStream* stream);
void Reset();
protected: protected:
BaseHeap(); BaseHeap();
@ -320,6 +329,11 @@ class Memory {
// Dumps a map of all allocated memory to the log. // Dumps a map of all allocated memory to the log.
void DumpMap(); void DumpMap();
bool Save(ByteStream* stream);
bool Restore(ByteStream* stream);
void Reset();
private: private:
int MapViews(uint8_t* mapping_base); int MapViews(uint8_t* mapping_base);
void UnmapViews(); void UnmapViews();