diff --git a/src/common/IPCHybrid.hpp b/src/common/IPCHybrid.hpp index ff605733f..5a249f228 100644 --- a/src/common/IPCHybrid.hpp +++ b/src/common/IPCHybrid.hpp @@ -38,7 +38,6 @@ typedef enum class _IPC_UPDATE_GUI { , XBOX_LED_COLOUR , LOG_ENABLED , KRNL_IS_READY - , VM_PERSIST_MEM } IPC_UPDATE_GUI; void ipc_send_gui_update(IPC_UPDATE_GUI command, const unsigned int value); diff --git a/src/common/win32/IPCWindows.cpp b/src/common/win32/IPCWindows.cpp index 0c8388630..19eb2b681 100644 --- a/src/common/win32/IPCWindows.cpp +++ b/src/common/win32/IPCWindows.cpp @@ -65,10 +65,6 @@ void ipc_send_gui_update(IPC_UPDATE_GUI command, const unsigned int value) cmdParam = ID_GUI_STATUS_KRNL_IS_READY; break; - case IPC_UPDATE_GUI::VM_PERSIST_MEM: - cmdParam = ID_GUI_VM_PERSIST_MEM; - break; - default: cmdParam = 0; break; diff --git a/src/core/kernel/init/CxbxKrnl.cpp b/src/core/kernel/init/CxbxKrnl.cpp index 8cb74336b..eea384916 100644 --- a/src/core/kernel/init/CxbxKrnl.cpp +++ b/src/core/kernel/init/CxbxKrnl.cpp @@ -786,6 +786,11 @@ void CxbxKrnlEmulate(uint32_t blocks_reserved[384]) // Set up the logging variables for the kernel process during initialization. log_sync_config(); + // When a reboot occur, we need to keep persistent memory buffer open before emulation process shutdown. + if ((BootFlags & BOOT_QUICK_REBOOT) != 0) { + g_VMManager.GetPersistentMemory(); + } + if (CxbxKrnl_hEmuParent != NULL) { ipc_send_gui_update(IPC_UPDATE_GUI::KRNL_IS_READY, static_cast(GetCurrentProcessId())); @@ -1771,6 +1776,9 @@ void CxbxKrnlShutDown() // Shutdown the input device manager g_InputDeviceManager.Shutdown(); + // Shutdown the memory manager + g_VMManager.Shutdown(); + CxbxUnlockFilePath(); if (CxbxKrnl_hEmuParent != NULL) { diff --git a/src/core/kernel/memory-manager/VMManager.cpp b/src/core/kernel/memory-manager/VMManager.cpp index 10bba22fa..6a3b7a179 100644 --- a/src/core/kernel/memory-manager/VMManager.cpp +++ b/src/core/kernel/memory-manager/VMManager.cpp @@ -39,6 +39,7 @@ #include "Logging.h" #include "EmuShared.h" #include "core\kernel\exports\EmuKrnl.h" // For InitializeListHead(), etc. +#include "common/util/cliConfig.hpp" // For GetSessionID #include // Temporary usage for need ReserveAddressRanges func with cxbx.exe's emulation. #ifndef CXBXR_EMU @@ -46,9 +47,23 @@ #endif +constexpr char str_persistent_memory_s[] = "PersistentMemory-s"; VMManager g_VMManager; +void VMManager::Shutdown() +{ + // Can't enable this yet. After the memory is deleted, other parts of cxbxr still run before process termination, and attempt to + // access the now deleted memory, causing a crash at shutdown + //DestroyMemoryRegions(); + DeleteCriticalSection(&m_CriticalSection); + + if (m_PersistentMemoryHandle != nullptr) { + CloseHandle(m_PersistentMemoryHandle); + m_PersistentMemoryHandle = nullptr; + } +} + bool VirtualMemoryArea::CanBeMergedWith(const VirtualMemoryArea& next) const { assert(base + size == next.base); @@ -286,15 +301,29 @@ void VMManager::InitializeSystemAllocations() } } -void VMManager::RestorePersistentMemory() -{ - HANDLE handle = OpenFileMapping(FILE_MAP_READ, FALSE, "PersistentMemory"); - if (handle == NULL) { - CxbxKrnlCleanup("Couldn't restore persistent memory! OpenFileMapping failed with error 0x%08X", GetLastError()); +void VMManager::GetPersistentMemory() +{ + if (m_PersistentMemoryHandle != nullptr) { + CxbxKrnlCleanup("Persistent memory is already opened!"); return; } - PersistedMemory* persisted_mem = (PersistedMemory*)MapViewOfFile(handle, FILE_MAP_READ, 0, 0, 0); + std::string persisted_mem_sid = str_persistent_memory_s + std::to_string(cli_config::GetSessionID()); + m_PersistentMemoryHandle = OpenFileMapping(FILE_MAP_READ, FALSE, persisted_mem_sid.c_str()); + if (m_PersistentMemoryHandle == nullptr) { + CxbxKrnlCleanup("Couldn't open persistent memory! OpenFileMapping failed with error 0x%08X", GetLastError()); + return; + } +} + +void VMManager::RestorePersistentMemory() +{ + if (m_PersistentMemoryHandle == nullptr) { + CxbxKrnlCleanup("Persistent memory is not open!"); + return; + } + + PersistedMemory* persisted_mem = (PersistedMemory*)MapViewOfFile(m_PersistentMemoryHandle, FILE_MAP_READ, 0, 0, 0); if (persisted_mem == nullptr) { CxbxKrnlCleanup("Couldn't restore persistent memory! MapViewOfFile failed with error 0x%08X", GetLastError()); return; @@ -389,9 +418,8 @@ void VMManager::RestorePersistentMemory() } UnmapViewOfFile(persisted_mem); - CloseHandle(handle); - - ipc_send_gui_update(IPC_UPDATE_GUI::VM_PERSIST_MEM, 0); + CloseHandle(m_PersistentMemoryHandle); + m_PersistentMemoryHandle = nullptr; } void VMManager::SavePersistentMemory() @@ -399,7 +427,6 @@ void VMManager::SavePersistentMemory() PersistedMemory* persisted_mem; size_t num_persisted_ptes; std::vector cached_persisted_ptes; - HANDLE handle; LPVOID addr; PMMPTE PointerPte; PMMPTE EndingPte; @@ -426,12 +453,13 @@ void VMManager::SavePersistentMemory() PointerPte++; } - 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) { + std::string persistent_mem_sid = str_persistent_memory_s + std::to_string(cli_config::GetSessionID()); + m_PersistentMemoryHandle = CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, num_persisted_ptes * PAGE_SIZE + num_persisted_ptes * 4 * 2 + sizeof(PersistedMemory), persistent_mem_sid.c_str()); + if (m_PersistentMemoryHandle == NULL) { CxbxKrnlCleanup("Couldn't persist memory! CreateFileMapping failed with error 0x%08X", GetLastError()); return; } - addr = MapViewOfFile(handle, FILE_MAP_READ | FILE_MAP_WRITE, 0, 0, 0); + addr = MapViewOfFile(m_PersistentMemoryHandle, FILE_MAP_READ | FILE_MAP_WRITE, 0, 0, 0); if (addr == nullptr) { CxbxKrnlCleanup("Couldn't persist memory! MapViewOfFile failed with error 0x%08X", GetLastError()); return; @@ -461,8 +489,6 @@ void VMManager::SavePersistentMemory() assert(i == num_persisted_ptes); - ipc_send_gui_update(IPC_UPDATE_GUI::VM_PERSIST_MEM, 1); - Unlock(); } diff --git a/src/core/kernel/memory-manager/VMManager.h b/src/core/kernel/memory-manager/VMManager.h index 4b90eb0fe..d50190745 100644 --- a/src/core/kernel/memory-manager/VMManager.h +++ b/src/core/kernel/memory-manager/VMManager.h @@ -100,14 +100,8 @@ class VMManager : public PhysicalMemory public: // constructor VMManager() {}; - // destructor - ~VMManager() - { - // DestroyMemoryRegions is not called when emulation ends, but only when the GUI process ends. This is probably because the emu - // process is killed with TerminateProcess and so it doesn't have a chance to perform a cleanup... - //DestroyMemoryRegions(); - DeleteCriticalSection(&m_CriticalSection); - } + // shutdown routine + void Shutdown(); // initializes the memory manager to the default configuration void Initialize(int SystemType, int BootFlags, uint32_t blocks_reserved[384]); // retrieves memory statistics @@ -158,6 +152,8 @@ class VMManager : public PhysicalMemory xboxkrnl::NTSTATUS XbVirtualProtect(VAddr* addr, size_t* Size, DWORD* Protect); // xbox implementation of NtQueryVirtualMemory xboxkrnl::NTSTATUS XbVirtualMemoryStatistics(VAddr addr, xboxkrnl::PMEMORY_BASIC_INFORMATION memory_statistics); + // get persistent memory from previous process until RestorePersistentMemory is called + void GetPersistentMemory(); // saves all persisted memory just before a quick reboot void SavePersistentMemory(); @@ -171,6 +167,8 @@ class VMManager : public PhysicalMemory DWORD m_AllocationGranularity = 0; // number of bytes reserved with XBOX_MEM_RESERVE by XbAllocateVirtualMemory size_t m_VirtualMemoryBytesReserved = 0; + // handle "shared" persistent memory open for reboot process + void* m_PersistentMemoryHandle = nullptr; // same as AllocateContiguousMemory, but it allows to allocate beyond m_MaxContiguousPfn VAddr AllocateContiguousMemoryInternal(PFN_COUNT NumberOfPages, PFN LowestPfn, PFN HighestPfn, PFN PfnAlignment, DWORD Perms); diff --git a/src/gui/WndMain.cpp b/src/gui/WndMain.cpp index ffcc32fed..3a58cc81a 100644 --- a/src/gui/WndMain.cpp +++ b/src/gui/WndMain.cpp @@ -67,33 +67,6 @@ static int gameLogoWidth, gameLogoHeight; static int splashLogoWidth, splashLogoHeight; -static HANDLE hPersistedMemory = NULL; -static LPVOID PersistedMemoryAddr = nullptr; - -void MapPersistedMemory() -{ - assert(((hPersistedMemory == NULL) == (PersistedMemoryAddr == nullptr)) && "Persistent memory handle and address must both be unset (or already set)!"); - - if (hPersistedMemory == NULL) { - hPersistedMemory = OpenFileMapping(FILE_MAP_READ, FALSE, "PersistentMemory"); - assert(hPersistedMemory != NULL); - - PersistedMemoryAddr = MapViewOfFile(hPersistedMemory, FILE_MAP_READ, 0, 0, 0); - assert(PersistedMemoryAddr != nullptr); - } -} - -void UnmapPersistedMemory() -{ - if (hPersistedMemory != NULL) { - UnmapViewOfFile(PersistedMemoryAddr); - PersistedMemoryAddr = nullptr; - - CloseHandle(hPersistedMemory); - hPersistedMemory = NULL; - } -} - bool g_SaveOnExit = true; void ClearSymbolCache(const char sStorageLocation[MAX_PATH]) @@ -377,15 +350,6 @@ LRESULT CALLBACK WndMain::WndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lP g_EmuShared->SetIsReady(true); } break; - - case ID_GUI_VM_PERSIST_MEM: { - if (lParam) { - MapPersistedMemory(); - } else { - UnmapPersistedMemory(); - } - } - break; } } break; @@ -2293,8 +2257,6 @@ void WndMain::StartEmulation(HWND hwndParent, DebuggerState LocalDebuggerState / } /* Main process to generate emulation command line end. */ - UnmapPersistedMemory(); - if (AttachLocalDebugger) { // Check then close existing debugger monitor. diff --git a/src/gui/resource/ResCxbx.h b/src/gui/resource/ResCxbx.h index 91cc68481..5616f36d7 100644 --- a/src/gui/resource/ResCxbx.h +++ b/src/gui/resource/ResCxbx.h @@ -194,7 +194,6 @@ #define ID_GUI_STATUS_LLE_FLAGS 1097 #define ID_GUI_STATUS_XBOX_LED_COLOUR 1098 #define ID_GUI_STATUS_LOG_ENABLED 1099 -#define ID_GUI_VM_PERSIST_MEM 1100 #define IDC_AC_MUTE_ON_UNFOCUS_DISABLE 1101 #define IDC_XBOX_PORT_0 1158 #define IDC_XBOX_PORT_1 1166