Fix memory manager crashing upon second reboot

This commit is contained in:
ergo720 2019-10-10 16:49:39 +02:00 committed by RadWolfie
parent f1255cb89b
commit 446b7efc29
2 changed files with 32 additions and 25 deletions

View File

@ -397,6 +397,8 @@ void VMManager::RestorePersistentMemory()
void VMManager::SavePersistentMemory() void VMManager::SavePersistentMemory()
{ {
PersistedMemory* persisted_mem; PersistedMemory* persisted_mem;
size_t num_persisted_ptes;
std::vector<PMMPTE> cached_persisted_ptes;
HANDLE handle; HANDLE handle;
LPVOID addr; LPVOID addr;
PMMPTE PointerPte; PMMPTE PointerPte;
@ -404,8 +406,27 @@ void VMManager::SavePersistentMemory()
int i; int i;
Lock(); Lock();
num_persisted_ptes = 0;
PointerPte = GetPteAddress(CONTIGUOUS_MEMORY_BASE);
if (m_MmLayoutRetail) {
EndingPte = GetPteAddress(CONTIGUOUS_MEMORY_BASE + XBOX_CONTIGUOUS_MEMORY_SIZE - 1);
}
else {
EndingPte = GetPteAddress(CONTIGUOUS_MEMORY_BASE + CHIHIRO_CONTIGUOUS_MEMORY_SIZE - 1);
}
while (PointerPte <= EndingPte)
{
if (PointerPte->Hardware.Valid != 0 && PointerPte->Hardware.Persist != 0) {
cached_persisted_ptes.push_back(PointerPte);
num_persisted_ptes++;
}
PointerPte++;
}
handle = CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, m_NumPersistentPtes * PAGE_SIZE + m_NumPersistentPtes * 4 * 2 + sizeof(PersistedMemory), "PersistentMemory"); handle = CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, num_persisted_ptes * PAGE_SIZE + num_persisted_ptes * 4 * 2 + sizeof(PersistedMemory), "PersistentMemory");
if (handle == NULL) { if (handle == NULL) {
CxbxKrnlCleanup("Couldn't persist memory! CreateFileMapping failed with error 0x%08X", GetLastError()); CxbxKrnlCleanup("Couldn't persist memory! CreateFileMapping failed with error 0x%08X", GetLastError());
return; return;
@ -417,7 +438,7 @@ void VMManager::SavePersistentMemory()
} }
persisted_mem = (PersistedMemory*)addr; persisted_mem = (PersistedMemory*)addr;
persisted_mem->NumOfPtes = m_NumPersistentPtes; persisted_mem->NumOfPtes = num_persisted_ptes;
if (xboxkrnl::LaunchDataPage != xbnullptr) { if (xboxkrnl::LaunchDataPage != xbnullptr) {
persisted_mem->LaunchFrameAddresses[0] = (VAddr)xboxkrnl::LaunchDataPage; persisted_mem->LaunchFrameAddresses[0] = (VAddr)xboxkrnl::LaunchDataPage;
@ -430,27 +451,15 @@ void VMManager::SavePersistentMemory()
} }
i = 0; i = 0;
PointerPte = GetPteAddress(CONTIGUOUS_MEMORY_BASE);
if (m_MmLayoutRetail) { for (const auto &pte : cached_persisted_ptes) {
EndingPte = GetPteAddress(CONTIGUOUS_MEMORY_BASE + XBOX_CONTIGUOUS_MEMORY_SIZE - 1); persisted_mem->Data[i] = GetVAddrMappedByPte(pte);
} persisted_mem->Data[num_persisted_ptes + i] = pte->Default;
else { memcpy(&persisted_mem->Data[num_persisted_ptes * 2 + i * ONE_KB], (void *)(persisted_mem->Data[i]), PAGE_SIZE);
EndingPte = GetPteAddress(CONTIGUOUS_MEMORY_BASE + CHIHIRO_CONTIGUOUS_MEMORY_SIZE - 1); i++;
}
while (PointerPte <= EndingPte)
{
if (PointerPte->Hardware.Valid != 0 && PointerPte->Hardware.Persist != 0) {
persisted_mem->Data[i] = GetVAddrMappedByPte(PointerPte);
persisted_mem->Data[m_NumPersistentPtes + i] = PointerPte->Default;
memcpy(&persisted_mem->Data[m_NumPersistentPtes * 2 + i * ONE_KB], (void*)(persisted_mem->Data[i]), PAGE_SIZE);
i++;
}
PointerPte++;
} }
assert(i == m_NumPersistentPtes); assert(i == num_persisted_ptes);
ipc_send_gui_update(IPC_UPDATE_GUI::VM_PERSIST_MEM, 1); ipc_send_gui_update(IPC_UPDATE_GUI::VM_PERSIST_MEM, 1);
@ -617,7 +626,6 @@ void VMManager::PersistMemory(VAddr addr, size_t Size, bool bPersist)
while (PointerPte <= EndingPte) while (PointerPte <= EndingPte)
{ {
PointerPte->Hardware.Persist = 1; PointerPte->Hardware.Persist = 1;
m_NumPersistentPtes++;
PointerPte++; PointerPte++;
} }
} }
@ -625,7 +633,6 @@ void VMManager::PersistMemory(VAddr addr, size_t Size, bool bPersist)
while (PointerPte <= EndingPte) while (PointerPte <= EndingPte)
{ {
PointerPte->Hardware.Persist = 0; PointerPte->Hardware.Persist = 0;
m_NumPersistentPtes--;
PointerPte++; PointerPte++;
} }
} }

View File

@ -84,7 +84,8 @@ typedef enum _MemoryRegionType
COUNTRegion, COUNTRegion,
}MemoryRegionType; }MemoryRegionType;
#pragma warning(push)
#pragma warning(disable: 4200)
/* struct used to save the persistent memory between reboots */ /* struct used to save the persistent memory between reboots */
typedef struct _PersistedMemory typedef struct _PersistedMemory
{ {
@ -92,6 +93,7 @@ typedef struct _PersistedMemory
VAddr LaunchFrameAddresses[2]; VAddr LaunchFrameAddresses[2];
uint32_t Data[]; uint32_t Data[];
}PersistedMemory; }PersistedMemory;
#pragma warning(pop)
/* VMManager class */ /* VMManager class */
@ -171,8 +173,6 @@ class VMManager : public PhysicalMemory
DWORD m_AllocationGranularity = 0; DWORD m_AllocationGranularity = 0;
// number of bytes reserved with XBOX_MEM_RESERVE by XbAllocateVirtualMemory // number of bytes reserved with XBOX_MEM_RESERVE by XbAllocateVirtualMemory
size_t m_VirtualMemoryBytesReserved = 0; size_t m_VirtualMemoryBytesReserved = 0;
// number of persisted ptes between quick reboots
size_t m_NumPersistentPtes = 0;
// same as AllocateContiguousMemory, but it allows to allocate beyond m_MaxContiguousPfn // same as AllocateContiguousMemory, but it allows to allocate beyond m_MaxContiguousPfn
VAddr AllocateContiguousMemoryInternal(PFN_COUNT NumberOfPages, PFN LowestPfn, PFN HighestPfn, PFN PfnAlignment, DWORD Perms); VAddr AllocateContiguousMemoryInternal(PFN_COUNT NumberOfPages, PFN LowestPfn, PFN HighestPfn, PFN PfnAlignment, DWORD Perms);