Browse Source

track unaligned mappings and only map when needed

remotes/1785372757367212240/tmp_refs/heads/variable-page-size
Exverge 1 month ago
parent
commit
8ea600f0a7
No known key found for this signature in database GPG Key ID: DAD399BCC5FB77E4
  1. 49
      src/common/host_memory.cpp
  2. 8
      src/common/host_memory.h

49
src/common/host_memory.cpp

@ -4,6 +4,7 @@
// SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#include "core/memory.h"
#ifdef _WIN32
#include <iterator>
@ -766,22 +767,46 @@ HostMemory::HostMemory(HostMemory&&) noexcept = default;
HostMemory& HostMemory::operator=(HostMemory&&) noexcept = default;
bool HostMemory::IsIrregularlyMappedAddress(size_t addr) noexcept {
auto index = addr / Core::Memory::YUZU_PAGESIZE;
auto i = irregular_mappings.upper_bound(index);
if (i == irregular_mappings.begin())
return false;
--i;
return index < i->first + i->second;
}
void HostMemory::Map(size_t virtual_offset, size_t host_offset, size_t length, MemoryPermission perms, bool separate_heap) {
#if !(defined(__OPENORBIS__) || defined(__managarm__))
size_t aligned_length = length;
ASSERT(virtual_offset % HostPageSize == host_offset % HostPageSize);
// todo: placeholder for now, our best bet is probably using the whole pa page for it
if (virtual_offset % HostPageSize != 0) {
// todo: use most permissive protections? or leave to Protect
LOG_WARNING(HW_Memory, "Memory address is unaligned to virtual base, surrounding pages will inherit the same permissions", HostPageSize);
auto aligned = AlignDown(virtual_offset, HostPageSize);
auto diff = virtual_offset - aligned;
assert(virtual_offset > aligned);
virtual_offset = aligned;
aligned_length = AlignUp(length + diff, HostPageSize);
ASSERT(aligned_length >= length);
if (IsIrregularlyMappedAddress(virtual_offset)) {
auto aligned = AlignUp(virtual_offset, HostPageSize);
LOG_WARNING(HW_Memory, "Irregularly mapped virtual addresses {:#x}-{:#x} will not have a valid physical address",
virtual_offset, aligned);
length -= aligned - virtual_offset;
virtual_offset = aligned;
} else {
auto aligned = AlignDown(virtual_offset, HostPageSize);
irregular_mappings.emplace(aligned / Core::Memory::YUZU_PAGESIZE, virtual_offset - aligned);
length += virtual_offset - aligned;
virtual_offset = aligned;
}
}
if (length % HostPageSize != 0) {
if (IsIrregularlyMappedAddress(virtual_offset + length)) {
auto aligned = AlignDown(length, HostPageSize);
LOG_WARNING(HW_Memory, "Irregularly mapped virtual addresses {:#x}-{:#x} will not have a valid physical address",
virtual_offset + aligned, virtual_offset + length);
length = aligned;
} else {
auto aligned = AlignUp(length, HostPageSize);
irregular_mappings.emplace((virtual_offset + aligned) / Core::Memory::YUZU_PAGESIZE, aligned - length);
length = aligned;
}
}
length = aligned_length;
ASSERT(virtual_offset % HostPageSize == 0);
ASSERT(host_offset % HostPageSize == 0);

8
src/common/host_memory.h

@ -13,6 +13,8 @@
#include <unistd.h>
#endif
#include <map>
#include "common/common_funcs.h"
#include "common/common_types.h"
#include "common/virtual_buffer.h"
@ -24,7 +26,7 @@ const size_t HostPageSize = sysconf(_SC_PAGESIZE);
#else
constexpr size_t HostPageSize = 0x1000;
#endif
const size_t GuestHostAlignment = HostPageSize / 4096;
const size_t GuestHostAlignment = HostPageSize / 0x1000;
constexpr size_t HugePageSize = 0x200000;
enum class MemoryPermission : u32 {
@ -98,8 +100,12 @@ private:
u8* backing_base{};
u8* virtual_base{};
size_t virtual_base_offset{};
// todo: include actual paddr for host ops?
std::map<size_t, size_t> irregular_mappings{};
// Windows requires it for kernels whom lack proper support for some functions!
std::optional<Common::VirtualBuffer<u8>> fallback_buffer;
bool IsIrregularlyMappedAddress(size_t addr) noexcept;
};
} // namespace Common
Loading…
Cancel
Save