Lock tracking logic behind a flag, check if faulted address is in emulated memory, check for page dirtiness before fastmem fault, pass whole page size to set page dirty bit
This commit is contained in:
parent
e252c4a729
commit
619cd0aa38
|
@ -82,9 +82,9 @@ void Shutdown(Core::System& system)
|
|||
system.GetCoreTiming().Shutdown();
|
||||
}
|
||||
|
||||
void DoState(Core::System& system, PointerWrap& p)
|
||||
void DoState(Core::System& system, PointerWrap& p, bool delta)
|
||||
{
|
||||
system.GetMemory().DoState(p);
|
||||
system.GetMemory().DoState(p, delta);
|
||||
p.DoMarker("Memory");
|
||||
system.GetMemoryInterface().DoState(p);
|
||||
p.DoMarker("MemoryInterface");
|
||||
|
|
|
@ -14,5 +14,5 @@ namespace HW
|
|||
{
|
||||
void Init(Core::System& system, const Sram* override_sram);
|
||||
void Shutdown(Core::System& system);
|
||||
void DoState(Core::System& system, PointerWrap& p);
|
||||
void DoState(Core::System& system, PointerWrap& p, bool delta);
|
||||
} // namespace HW
|
||||
|
|
|
@ -205,6 +205,27 @@ bool MemoryManager::IsAddressInFastmemArea(const u8* address) const
|
|||
return address >= m_fastmem_arena && address < m_fastmem_arena + m_fastmem_arena_size;
|
||||
}
|
||||
|
||||
bool MemoryManager::IsAddressInEmulatedMemory(const u8* address) const
|
||||
{
|
||||
if (m_ram && address > m_ram && address <= m_ram + GetRamSize())
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else if (m_exram && address > m_exram && address <= m_exram + GetExRamSize())
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else if (m_l1_cache && address > m_l1_cache && address <= m_l1_cache + GetL1CacheSize())
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else if (m_fake_vmem && address > m_fake_vmem && address <= m_fake_vmem + GetFakeVMemSize())
|
||||
{
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool MemoryManager::InitFastmemArena()
|
||||
{
|
||||
// Here we set up memory mappings for fastmem. The basic idea of fastmem is that we reserve 4 GiB
|
||||
|
@ -331,7 +352,7 @@ void MemoryManager::UpdateLogicalMemory(const PowerPC::BatTable& dbat_table)
|
|||
}
|
||||
}
|
||||
|
||||
void MemoryManager::DoState(PointerWrap& p)
|
||||
void MemoryManager::DoState(PointerWrap& p, bool delta)
|
||||
{
|
||||
const u32 current_ram_size = GetRamSize();
|
||||
const u32 current_l1_cache_size = GetL1CacheSize();
|
||||
|
@ -368,53 +389,68 @@ void MemoryManager::DoState(PointerWrap& p)
|
|||
p.SetVerifyMode();
|
||||
return;
|
||||
}
|
||||
u32 page_count = static_cast<u32>(Common::PageSize());
|
||||
p.Do(m_dirty_pages);
|
||||
for (size_t i = 0; i < current_ram_size; i++)
|
||||
if (delta)
|
||||
{
|
||||
if (IsPageDirty(reinterpret_cast<uintptr_t>(&m_ram[i])))
|
||||
u32 page_size = static_cast<u32>(Common::PageSize());
|
||||
p.Do(m_dirty_pages);
|
||||
for (size_t i = 0; i < current_ram_size; i++)
|
||||
{
|
||||
p.DoArray(m_ram + i, page_count);
|
||||
i += page_count;
|
||||
}
|
||||
}
|
||||
for (size_t i = 0; i < current_l1_cache_size; i++)
|
||||
{
|
||||
if (IsPageDirty(reinterpret_cast<uintptr_t>(&m_l1_cache[i])))
|
||||
{
|
||||
p.DoArray(m_l1_cache + i, page_count);
|
||||
i += page_count;
|
||||
}
|
||||
}
|
||||
p.DoMarker("Memory RAM");
|
||||
if (current_have_fake_vmem)
|
||||
{
|
||||
for (size_t i = 0; i < current_fake_vmem_size; i++)
|
||||
{
|
||||
if (IsPageDirty(reinterpret_cast<uintptr_t>(&m_fake_vmem[i])))
|
||||
if (IsPageDirty(reinterpret_cast<uintptr_t>(&m_ram[i])))
|
||||
{
|
||||
p.DoArray(m_fake_vmem + i, page_count);
|
||||
i += page_count;
|
||||
p.DoArray(m_ram + i, page_size);
|
||||
i += page_size;
|
||||
}
|
||||
}
|
||||
}
|
||||
p.DoMarker("Memory FakeVMEM");
|
||||
if (current_have_exram)
|
||||
{
|
||||
for (size_t i = 0; i < current_exram_size; i++)
|
||||
for (size_t i = 0; i < current_l1_cache_size; i++)
|
||||
{
|
||||
if (IsPageDirty(reinterpret_cast<uintptr_t>(&m_exram[i])))
|
||||
if (IsPageDirty(reinterpret_cast<uintptr_t>(&m_l1_cache[i])))
|
||||
{
|
||||
p.DoArray(m_exram + i, page_count);
|
||||
i += page_count;
|
||||
p.DoArray(m_l1_cache + i, page_size);
|
||||
i += page_size;
|
||||
}
|
||||
}
|
||||
}
|
||||
p.DoMarker("Memory EXRAM");
|
||||
p.DoMarker("Memory RAM");
|
||||
if (current_have_fake_vmem)
|
||||
{
|
||||
for (size_t i = 0; i < current_fake_vmem_size; i++)
|
||||
{
|
||||
if (IsPageDirty(reinterpret_cast<uintptr_t>(&m_fake_vmem[i])))
|
||||
{
|
||||
p.DoArray(m_fake_vmem + i, page_size);
|
||||
i += page_size;
|
||||
}
|
||||
}
|
||||
}
|
||||
p.DoMarker("Memory FakeVMEM");
|
||||
if (current_have_exram)
|
||||
{
|
||||
for (size_t i = 0; i < current_exram_size; i++)
|
||||
{
|
||||
if (IsPageDirty(reinterpret_cast<uintptr_t>(&m_exram[i])))
|
||||
{
|
||||
p.DoArray(m_exram + i, page_size);
|
||||
i += page_size;
|
||||
}
|
||||
}
|
||||
}
|
||||
p.DoMarker("Memory EXRAM");
|
||||
|
||||
if (p.IsWriteMode())
|
||||
if (p.IsWriteMode())
|
||||
{
|
||||
ResetDirtyPages();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ResetDirtyPages();
|
||||
p.DoArray(m_ram, current_ram_size);
|
||||
p.DoArray(m_l1_cache, current_l1_cache_size);
|
||||
p.DoMarker("Memory RAM");
|
||||
if (current_have_fake_vmem)
|
||||
p.DoArray(m_fake_vmem, current_fake_vmem_size);
|
||||
p.DoMarker("Memory FakeVMEM");
|
||||
if (current_have_exram)
|
||||
p.DoArray(m_exram, current_exram_size);
|
||||
p.DoMarker("Memory EXRAM");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -79,6 +79,7 @@ public:
|
|||
u32 GetExRamMask() const { return m_exram_mask; }
|
||||
|
||||
bool IsAddressInFastmemArea(const u8* address) const;
|
||||
bool IsAddressInEmulatedMemory(const u8* address) const;
|
||||
u8* GetPhysicalBase() const { return m_physical_base; }
|
||||
u8* GetLogicalBase() const { return m_logical_base; }
|
||||
u8* GetPhysicalPageMappingsBase() const { return m_physical_page_mappings_base; }
|
||||
|
@ -99,7 +100,7 @@ public:
|
|||
void Shutdown();
|
||||
bool InitFastmemArena();
|
||||
void ShutdownFastmemArena();
|
||||
void DoState(PointerWrap& p);
|
||||
void DoState(PointerWrap& p, bool delta);
|
||||
|
||||
void UpdateLogicalMemory(const PowerPC::BatTable& dbat_table);
|
||||
|
||||
|
|
|
@ -64,19 +64,17 @@ static LONG NTAPI Handler(PEXCEPTION_POINTERS pPtrs)
|
|||
SContext* ctx = pPtrs->ContextRecord;
|
||||
Core::System& system = Core::System::GetInstance();
|
||||
Memory::MemoryManager& memory = system.GetMemory();
|
||||
if (system.GetJitInterface().HandleFault(fault_address, ctx))
|
||||
if (!memory.IsPageDirty(fault_address))
|
||||
{
|
||||
return EXCEPTION_CONTINUE_EXECUTION;
|
||||
}
|
||||
else if (!memory.IsPageDirty(fault_address))
|
||||
{
|
||||
memory.SetPageDirtyBit(fault_address, 1, true);
|
||||
|
||||
size_t page_size = Common::PageSize();
|
||||
|
||||
memory.SetPageDirtyBit(fault_address, page_size, true);
|
||||
|
||||
size_t page_mask = page_size - 1;
|
||||
u64 page_index = fault_address & page_mask;
|
||||
|
||||
bool change_protection = memory.VirtualProtectMemory(reinterpret_cast<u8*>(fault_address),
|
||||
page_size - page_index, PAGE_READWRITE);
|
||||
page_size - page_index, PAGE_READWRITE);
|
||||
if (!change_protection)
|
||||
{
|
||||
return EXCEPTION_CONTINUE_SEARCH;
|
||||
|
@ -84,6 +82,10 @@ static LONG NTAPI Handler(PEXCEPTION_POINTERS pPtrs)
|
|||
|
||||
return EXCEPTION_CONTINUE_EXECUTION;
|
||||
}
|
||||
else if (system.GetJitInterface().HandleFault(fault_address, ctx))
|
||||
{
|
||||
return EXCEPTION_CONTINUE_EXECUTION;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Let's not prevent debugging.
|
||||
|
|
|
@ -138,7 +138,7 @@ void EnableCompression(bool compression)
|
|||
s_use_compression = compression;
|
||||
}
|
||||
|
||||
static void DoState(Core::System& system, PointerWrap& p)
|
||||
static void DoState(Core::System& system, PointerWrap& p, bool delta)
|
||||
{
|
||||
bool is_wii = system.IsWii() || system.IsMIOS();
|
||||
const bool is_wii_currently = is_wii;
|
||||
|
@ -187,7 +187,7 @@ static void DoState(Core::System& system, PointerWrap& p)
|
|||
p.DoMarker("CoreTiming");
|
||||
|
||||
// HW needs to be restored before PowerPC because the data cache might need to be flushed.
|
||||
HW::DoState(system, p);
|
||||
HW::DoState(system, p, delta);
|
||||
p.DoMarker("HW");
|
||||
|
||||
system.GetPowerPC().DoState(p);
|
||||
|
@ -223,7 +223,7 @@ void LoadFromBuffer(Core::System& system, std::vector<u8>& buffer)
|
|||
[&] {
|
||||
u8* ptr = buffer.data();
|
||||
PointerWrap p(&ptr, buffer.size(), PointerWrap::Mode::Read);
|
||||
DoState(system, p);
|
||||
DoState(system, p, false);
|
||||
},
|
||||
true);
|
||||
}
|
||||
|
@ -236,13 +236,13 @@ void SaveToBuffer(Core::System& system, std::vector<u8>& buffer)
|
|||
u8* ptr = nullptr;
|
||||
PointerWrap p_measure(&ptr, 0, PointerWrap::Mode::Measure);
|
||||
|
||||
DoState(system, p_measure);
|
||||
DoState(system, p_measure, false);
|
||||
const size_t buffer_size = reinterpret_cast<size_t>(ptr);
|
||||
buffer.resize(buffer_size);
|
||||
|
||||
ptr = buffer.data();
|
||||
PointerWrap p(&ptr, buffer_size, PointerWrap::Mode::Write);
|
||||
DoState(system, p);
|
||||
DoState(system, p, false);
|
||||
},
|
||||
true);
|
||||
}
|
||||
|
@ -487,7 +487,7 @@ void SaveAs(Core::System& system, const std::string& filename, bool wait)
|
|||
// Measure the size of the buffer.
|
||||
u8* ptr = nullptr;
|
||||
PointerWrap p_measure(&ptr, 0, PointerWrap::Mode::Measure);
|
||||
DoState(system, p_measure);
|
||||
DoState(system, p_measure, false);
|
||||
const size_t buffer_size = reinterpret_cast<size_t>(ptr);
|
||||
|
||||
// Then actually do the write.
|
||||
|
@ -495,7 +495,7 @@ void SaveAs(Core::System& system, const std::string& filename, bool wait)
|
|||
current_buffer.resize(buffer_size);
|
||||
ptr = current_buffer.data();
|
||||
PointerWrap p(&ptr, buffer_size, PointerWrap::Mode::Write);
|
||||
DoState(system, p);
|
||||
DoState(system, p, false);
|
||||
|
||||
if (p.IsWriteMode())
|
||||
{
|
||||
|
@ -901,7 +901,7 @@ void LoadAs(Core::System& system, const std::string& filename)
|
|||
{
|
||||
u8* ptr = buffer.data();
|
||||
PointerWrap p(&ptr, buffer.size(), PointerWrap::Mode::Read);
|
||||
DoState(system, p);
|
||||
DoState(system, p, false);
|
||||
loaded = true;
|
||||
loadedSuccessfully = p.IsReadMode();
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue