Browse Source

[core] support direct mappings on win32

remotes/1785372757367212240/tmp_refs/heads/variable-page-size
Exverge 4 weeks ago
parent
commit
1adf6aa500
No known key found for this signature in database GPG Key ID: DAD399BCC5FB77E4
  1. 50
      src/common/host_memory.cpp
  2. 17
      src/common/host_memory.h

50
src/common/host_memory.cpp

@ -203,7 +203,7 @@ public:
virtual_base = static_cast<u8*>(pfn_VirtualAlloc2 virtual_base = static_cast<u8*>(pfn_VirtualAlloc2
(process, nullptr, virtual_size, MEM_RESERVE | MEM_RESERVE_PLACEHOLDER, PAGE_NOACCESS, nullptr, 0)); (process, nullptr, virtual_size, MEM_RESERVE | MEM_RESERVE_PLACEHOLDER, PAGE_NOACCESS, nullptr, 0));
} }
virtual_map_base = virtual_base;
if (!virtual_base) { if (!virtual_base) {
Release(); Release();
LOG_CRITICAL(HW_Memory, "Failed to reserve {} GiB of virtual memory", virtual_size >> 30); LOG_CRITICAL(HW_Memory, "Failed to reserve {} GiB of virtual memory", virtual_size >> 30);
@ -217,6 +217,7 @@ public:
} }
void Map(size_t virtual_offset, size_t host_offset, size_t length, MemoryPermission perms) { void Map(size_t virtual_offset, size_t host_offset, size_t length, MemoryPermission perms) {
AdjustMap(virtual_map_base, virtual_size, &virtual_offset, &length);
std::unique_lock lock{placeholder_mutex}; std::unique_lock lock{placeholder_mutex};
if (!IsNiechePlaceholder(virtual_offset, length)) { if (!IsNiechePlaceholder(virtual_offset, length)) {
Split(virtual_offset, length); Split(virtual_offset, length);
@ -228,6 +229,7 @@ public:
} }
void Unmap(size_t virtual_offset, size_t length) { void Unmap(size_t virtual_offset, size_t length) {
AdjustMap(virtual_map_base, virtual_size, &virtual_offset, &length);
std::scoped_lock lock{placeholder_mutex}; std::scoped_lock lock{placeholder_mutex};
// Unmap until there are no more placeholders // Unmap until there are no more placeholders
@ -236,15 +238,21 @@ public:
} }
void Protect(size_t virtual_offset, size_t length, bool read, bool write, bool execute) { void Protect(size_t virtual_offset, size_t length, bool read, bool write, bool execute) {
AdjustMap(virtual_map_base, virtual_size, &virtual_offset, &length);
DWORD new_flags{}; DWORD new_flags{};
if (read && write) {
if (read && write && execute) {
new_flags = PAGE_EXECUTE_READWRITE;
} else if (read && write) {
new_flags = PAGE_READWRITE; new_flags = PAGE_READWRITE;
} else if (read && execute) {
new_flags = PAGE_EXECUTE_READ;
} else if (read && !write) { } else if (read && !write) {
new_flags = PAGE_READONLY; new_flags = PAGE_READONLY;
} else if (!read && !write) {
} else if (!read && !write && !execute) {
new_flags = PAGE_NOACCESS; new_flags = PAGE_NOACCESS;
} else { } else {
UNIMPLEMENTED_MSG("Protection flag combination read={} write={}", read, write);
UNIMPLEMENTED_MSG("Protection flag combination read={} write={} execute={}", read, write, execute);
} }
const size_t virtual_end = virtual_offset + length; const size_t virtual_end = virtual_offset + length;
@ -263,7 +271,7 @@ public:
void EnableDirectMappedAddress() { void EnableDirectMappedAddress() {
// TODO // TODO
UNREACHABLE();
virtual_base = nullptr;
} }
const size_t backing_size; ///< Size of the backing memory in bytes const size_t backing_size; ///< Size of the backing memory in bytes
@ -271,6 +279,7 @@ public:
u8* backing_base{}; u8* backing_base{};
u8* virtual_base{}; u8* virtual_base{};
u8* virtual_map_base{};
private: private:
/// Release all resources in the object /// Release all resources in the object
@ -284,8 +293,8 @@ private:
} }
Coalesce(0, virtual_size); Coalesce(0, virtual_size);
} }
if (virtual_base) {
if (!VirtualFree(virtual_base, 0, MEM_RELEASE)) {
if (virtual_map_base) {
if (!VirtualFree(virtual_map_base, 0, MEM_RELEASE)) {
LOG_CRITICAL(HW_Memory, "Failed to free virtual memory"); LOG_CRITICAL(HW_Memory, "Failed to free virtual memory");
} }
} }
@ -668,7 +677,7 @@ public:
void Map(size_t virtual_offset, size_t host_offset, size_t length, MemoryPermission perms) { void Map(size_t virtual_offset, size_t host_offset, size_t length, MemoryPermission perms) {
// Intersect the range with our address space. // Intersect the range with our address space.
AdjustMap(&virtual_offset, &length);
AdjustMap(virtual_map_base, virtual_size, &virtual_offset, &length);
// We are removing a placeholder. // We are removing a placeholder.
free_manager.AllocateBlock(virtual_base + virtual_offset, length); free_manager.AllocateBlock(virtual_base + virtual_offset, length);
@ -693,7 +702,7 @@ public:
// We don't want to unmap, we want to reserve this memory. // We don't want to unmap, we want to reserve this memory.
// Intersect the range with our address space. // Intersect the range with our address space.
AdjustMap(&virtual_offset, &length);
AdjustMap(virtual_map_base, virtual_size, &virtual_offset, &length);
// Merge with any adjacent placeholder mappings. // Merge with any adjacent placeholder mappings.
auto [merged_pointer, merged_size] = auto [merged_pointer, merged_size] =
@ -705,7 +714,7 @@ public:
void Protect(size_t virtual_offset, size_t length, bool read, bool write, bool execute) { void Protect(size_t virtual_offset, size_t length, bool read, bool write, bool execute) {
// Intersect the range with our address space. // Intersect the range with our address space.
AdjustMap(&virtual_offset, &length);
AdjustMap(virtual_map_base, virtual_size, &virtual_offset, &length);
int flags = PROT_NONE; int flags = PROT_NONE;
if (read) { if (read) {
@ -753,27 +762,6 @@ private:
} }
} }
void AdjustMap(size_t* virtual_offset, size_t* length) {
if (virtual_base != nullptr) {
return;
}
// If we are direct mapped, we want to make sure we are operating on a region
// that is in range of our virtual mapping.
size_t intended_start = *virtual_offset;
size_t intended_end = intended_start + *length;
size_t address_space_start = reinterpret_cast<size_t>(virtual_map_base);
size_t address_space_end = address_space_start + virtual_size;
if (address_space_start > intended_end || intended_start > address_space_end) {
*virtual_offset = 0;
*length = 0;
} else {
*virtual_offset = (std::max)(intended_start, address_space_start);
*length = (std::min)(intended_end, address_space_end) - *virtual_offset;
}
}
int fd{-1}; // memfd file descriptor, -1 is the error value of memfd_create int fd{-1}; // memfd file descriptor, -1 is the error value of memfd_create
FreeRegionManager free_manager{}; FreeRegionManager free_manager{};
}; };

17
src/common/host_memory.h

@ -94,6 +94,23 @@ public:
return address >= virtual_base && address < virtual_base + virtual_size; return address >= virtual_base && address < virtual_base + virtual_size;
} }
static void AdjustMap(u8* virtual_map_base, size_t virtual_size, size_t* virtual_offset, size_t* length) {
// If we are direct mapped, we want to make sure we are operating on a region
// that is in range of our virtual mapping.
size_t intended_start = *virtual_offset;
size_t intended_end = intended_start + *length;
size_t address_space_start = reinterpret_cast<size_t>(virtual_map_base);
size_t address_space_end = address_space_start + virtual_size;
if (address_space_start > intended_end || intended_start > address_space_end) {
*virtual_offset = 0;
*length = 0;
} else {
*virtual_offset = (std::max)(intended_start, address_space_start);
*length = (std::min)(intended_end, address_space_end) - *virtual_offset;
}
}
using by_vaddr = bi::set_base_hook<bi::tag<struct _by_vaddr>>; using by_vaddr = bi::set_base_hook<bi::tag<struct _by_vaddr>>;
struct MisalignedMapping : by_vaddr { struct MisalignedMapping : by_vaddr {

Loading…
Cancel
Save