From 432e32f7c254a75359970359bc7b51aa1f1fc34e Mon Sep 17 00:00:00 2001 From: "Dr. Chat" Date: Tue, 1 Dec 2015 17:26:55 -0600 Subject: [PATCH] memory Save/Restore --- src/xenia/memory.cc | 106 ++++++++++++++++++++++++++++++++++++++++++++ src/xenia/memory.h | 14 ++++++ 2 files changed, 120 insertions(+) diff --git a/src/xenia/memory.cc b/src/xenia/memory.cc index fc9722f01..d01f8fb46 100644 --- a/src/xenia/memory.cc +++ b/src/xenia/memory.cc @@ -14,6 +14,7 @@ #include #include +#include "xenia/base/byte_stream.h" #include "xenia/base/clock.h" #include "xenia/base/logging.h" #include "xenia/base/math.h" @@ -436,6 +437,35 @@ void Memory::DumpMap() { 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) { if ((protect & kMemoryProtectRead) && !(protect & kMemoryProtectWrite)) { 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(); + 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, uint32_t allocation_type, uint32_t protect, bool top_down, uint32_t* out_address) { diff --git a/src/xenia/memory.h b/src/xenia/memory.h index 3b5c59f5c..f65edb85c 100644 --- a/src/xenia/memory.h +++ b/src/xenia/memory.h @@ -19,6 +19,10 @@ #include "xenia/base/mutex.h" #include "xenia/cpu/mmio_handler.h" +namespace xe { +class ByteStream; +} // namespace xe + namespace xe { enum SystemHeapFlag : uint32_t { @@ -144,6 +148,11 @@ class BaseHeap { // This is only valid if the page is backed by a physical allocation. uint32_t GetPhysicalAddress(uint32_t address); + bool Save(ByteStream* stream); + bool Restore(ByteStream* stream); + + void Reset(); + protected: BaseHeap(); @@ -320,6 +329,11 @@ class Memory { // Dumps a map of all allocated memory to the log. void DumpMap(); + bool Save(ByteStream* stream); + bool Restore(ByteStream* stream); + + void Reset(); + private: int MapViews(uint8_t* mapping_base); void UnmapViews();