fix standalone persisted memory support

This commit is contained in:
RadWolfie 2019-10-18 11:27:23 -05:00
parent b20a970b1d
commit 8a33562dc8
7 changed files with 55 additions and 67 deletions

View File

@ -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);

View File

@ -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;

View File

@ -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<UINT>(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) {

View File

@ -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 <assert.h>
// 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<PMMPTE> 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();
}

View File

@ -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);

View File

@ -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.

View File

@ -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