vm_native.cpp: Use Windows 10 memory mapping API (the correct API)

This commit is contained in:
Elad Ashkenazi 2022-06-10 14:27:02 +03:00 committed by GitHub
parent 7235647e67
commit 1738b38536
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 233 additions and 20 deletions

View file

@ -23,11 +23,11 @@ void ppu_remove_hle_instructions(u32 addr, u32 size);
namespace vm
{
static u8* memory_reserve_4GiB(void* _addr, u64 size = 0x100000000)
static u8* memory_reserve_4GiB(void* _addr, u64 size = 0x100000000, bool is_memory_mapping = false)
{
for (u64 addr = reinterpret_cast<u64>(_addr) + 0x100000000; addr < 0x8000'0000'0000; addr += 0x100000000)
{
if (auto ptr = utils::memory_reserve(size, reinterpret_cast<void*>(addr)))
if (auto ptr = utils::memory_reserve(size, reinterpret_cast<void*>(addr), is_memory_mapping))
{
return static_cast<u8*>(ptr);
}
@ -37,7 +37,7 @@ namespace vm
}
// Emulated virtual memory
u8* const g_base_addr = memory_reserve_4GiB(reinterpret_cast<void*>(0x2'0000'0000), 0x2'0000'0000);
u8* const g_base_addr = memory_reserve_4GiB(reinterpret_cast<void*>(0x2'0000'0000), 0x2'0000'0000, true);
// Unprotected virtual memory mirror
u8* const g_sudo_addr = g_base_addr + 0x1'0000'0000;
@ -697,6 +697,21 @@ namespace vm
if (~flags & page_readable)
prot = utils::protection::no;
std::string map_error;
auto map_critical = [&](u8* ptr, utils::protection prot)
{
auto [res, error] = shm->map_critical(ptr, prot);
if (res != ptr)
{
map_error = std::move(error);
return false;
}
return true;
};
if (is_noop)
{
}
@ -704,9 +719,9 @@ namespace vm
{
utils::memory_protect(g_base_addr + addr, size, prot);
}
else if (shm->map_critical(g_base_addr + addr, prot) != g_base_addr + addr || shm->map_critical(g_sudo_addr + addr) != g_sudo_addr + addr || !shm->map_self())
else if (!map_critical(g_base_addr + addr, prot) || !map_critical(g_sudo_addr + addr, utils::protection::rw) || (map_error = "map_self()", !shm->map_self()))
{
fmt::throw_exception("Memory mapping failed - blame Windows (addr=0x%x, size=0x%x, flags=0x%x)", addr, size, flags);
fmt::throw_exception("Memory mapping failed (addr=0x%x, size=0x%x, flags=0x%x): %s", addr, size, flags, map_error);
}
if (flags & page_executable && !is_noop)
@ -1138,10 +1153,28 @@ namespace vm
{
if (this->flags & preallocated)
{
std::string map_error;
auto map_critical = [&](u8* ptr, utils::protection prot)
{
auto [res, error] = m_common->map_critical(ptr, prot);
if (res != ptr)
{
map_error = std::move(error);
return false;
}
return true;
};
// Special path for whole-allocated areas allowing 4k granularity
m_common = std::make_shared<utils::shm>(size);
m_common->map_critical(vm::base(addr), this->flags & page_size_4k && utils::c_page_size > 4096 ? utils::protection::rw : utils::protection::no);
m_common->map_critical(vm::get_super_ptr(addr));
if (!map_critical(vm::_ptr<u8>(addr), this->flags & page_size_4k && utils::c_page_size > 4096 ? utils::protection::rw : utils::protection::no) || !map_critical(vm::get_super_ptr(addr), utils::protection::rw))
{
fmt::throw_exception("Memory mapping failed (addr=0x%x, size=0x%x, flags=0x%x): %s", addr, size, flags, map_error);
}
}
}
@ -1737,7 +1770,6 @@ namespace vm
g_locations.clear();
}
utils::memory_decommit(g_base_addr, 0x200000000);
utils::memory_decommit(g_exec_addr, 0x200000000);
utils::memory_decommit(g_stat_addr, 0x100000000);