mirror of
https://github.com/KytyPS5/KytyPS5.git
synced 2026-10-22 11:56:58 +02:00
memory: separate extended allocations from ordinary guest mappings
This commit is contained in:
@@ -78,8 +78,7 @@ static Graphics::RenderContext& GetGpuResources() {
|
||||
}
|
||||
|
||||
static bool IsGpuAddressRange(uint64_t vaddr, uint64_t size) {
|
||||
constexpr uint64_t GPU_ADDRESS_LIMIT = 1ull << 40u;
|
||||
return vaddr != 0 && size != 0 && vaddr < GPU_ADDRESS_LIMIT && size < GPU_ADDRESS_LIMIT - vaddr;
|
||||
return Graphics::GuestRange {vaddr, size}.Valid();
|
||||
}
|
||||
|
||||
static void MapGpuRange(uint64_t vaddr, uint64_t size) {
|
||||
|
||||
@@ -24,6 +24,8 @@ struct Lifecycle {
|
||||
using callback_func_t = void (*)(uintptr_t addr, size_t size);
|
||||
|
||||
constexpr uint32_t KERNEL_MAXIMUM_NAME_LENGTH = 32;
|
||||
constexpr uint64_t kExtendedMemoryBase = 0x080000000000ull;
|
||||
constexpr uint64_t kExtendedMemorySize = 512ull * 1024 * 1024 * 1024;
|
||||
|
||||
struct VirtualQueryInfo {
|
||||
uintptr_t start;
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
|
||||
static constexpr uint64_t HOST_SYSTEM_MANAGED_MIN = 0x0000040000ull;
|
||||
static constexpr uint64_t HOST_SYSTEM_MANAGED_MAX = 0x07ffffbfffull;
|
||||
static constexpr uint64_t HOST_SYSTEM_RESERVED_MIN = HOST_SYSTEM_MANAGED_MAX + 1u;
|
||||
#if defined(__APPLE__) && (defined(__x86_64__) || defined(_M_X64))
|
||||
static constexpr uint64_t HOST_SYSTEM_RESERVED_MAX = 0x0fbfffffffull;
|
||||
static constexpr uint64_t HOST_USER_MIN = 0x7000000000ull;
|
||||
@@ -1077,51 +1076,51 @@ private:
|
||||
#endif
|
||||
|
||||
void ReserveGuestRegions() {
|
||||
const std::array<std::pair<uint64_t, uint64_t>, 3> regions {{
|
||||
{HOST_SYSTEM_MANAGED_MIN, HOST_SYSTEM_RESERVED_MAX + 1u},
|
||||
{HOST_USER_MIN, HOST_USER_MAX + 1u},
|
||||
{kExtendedMemoryBase, kExtendedMemoryBase + kExtendedMemorySize},
|
||||
}};
|
||||
|
||||
#if KYTY_PLATFORM == KYTY_PLATFORM_WINDOWS
|
||||
constexpr uint64_t MinimumRegionSize = 0x1000000;
|
||||
const auto process = GetCurrentProcess();
|
||||
const auto guest_end = HOST_USER_MAX + 1u;
|
||||
auto next_addr = HOST_SYSTEM_MANAGED_MIN;
|
||||
|
||||
while (next_addr < guest_end) {
|
||||
MEMORY_BASIC_INFORMATION info {};
|
||||
if (VirtualQuery(reinterpret_cast<const void*>(next_addr), &info, sizeof(info)) == 0) {
|
||||
EXIT("failed to inspect guest address space at 0x%016" PRIx64 "\n", next_addr);
|
||||
}
|
||||
|
||||
const auto region_base = reinterpret_cast<uint64_t>(info.BaseAddress);
|
||||
const auto region_end =
|
||||
std::min<uint64_t>(guest_end, region_base + static_cast<uint64_t>(info.RegionSize));
|
||||
const auto reserve_start =
|
||||
AlignUp(std::max<uint64_t>(region_base, HOST_SYSTEM_MANAGED_MIN), m_granularity);
|
||||
const auto reserve_end = AlignDown(region_end, m_granularity);
|
||||
|
||||
if (info.State == MEM_FREE && reserve_end > reserve_start &&
|
||||
reserve_end - reserve_start > MinimumRegionSize) {
|
||||
auto* ptr = VirtualAlloc2(
|
||||
process, reinterpret_cast<void*>(reserve_start), reserve_end - reserve_start,
|
||||
MEM_RESERVE | MEM_RESERVE_PLACEHOLDER, PAGE_NOACCESS, nullptr, 0);
|
||||
if (reinterpret_cast<uint64_t>(ptr) != reserve_start) {
|
||||
EXIT("failed to reserve guest address space at 0x%016" PRIx64
|
||||
", size 0x%016" PRIx64 "\n",
|
||||
reserve_start, reserve_end - reserve_start);
|
||||
for (const auto& [guest_start, guest_end]: regions) {
|
||||
auto next_addr = guest_start;
|
||||
while (next_addr < guest_end) {
|
||||
MEMORY_BASIC_INFORMATION info {};
|
||||
if (VirtualQuery(reinterpret_cast<const void*>(next_addr), &info, sizeof(info)) == 0) {
|
||||
EXIT("failed to inspect guest address space at 0x%016" PRIx64 "\n", next_addr);
|
||||
}
|
||||
AddFreeUnlocked(reserve_start, reserve_end - reserve_start);
|
||||
m_owned.emplace_back(reserve_start, reserve_end - reserve_start);
|
||||
}
|
||||
|
||||
if (region_end <= next_addr) {
|
||||
EXIT("guest address-space scan did not advance at 0x%016" PRIx64 "\n", next_addr);
|
||||
const auto region_base = reinterpret_cast<uint64_t>(info.BaseAddress);
|
||||
const auto region_end = std::min<uint64_t>(
|
||||
guest_end, region_base + static_cast<uint64_t>(info.RegionSize));
|
||||
const auto reserve_start =
|
||||
AlignUp(std::max(region_base, guest_start), m_granularity);
|
||||
const auto reserve_end = AlignDown(region_end, m_granularity);
|
||||
|
||||
if (info.State == MEM_FREE && reserve_end > reserve_start &&
|
||||
reserve_end - reserve_start > MinimumRegionSize) {
|
||||
auto* ptr = VirtualAlloc2(
|
||||
process, reinterpret_cast<void*>(reserve_start), reserve_end - reserve_start,
|
||||
MEM_RESERVE | MEM_RESERVE_PLACEHOLDER, PAGE_NOACCESS, nullptr, 0);
|
||||
if (reinterpret_cast<uint64_t>(ptr) != reserve_start) {
|
||||
EXIT("failed to reserve guest address space at 0x%016" PRIx64
|
||||
", size 0x%016" PRIx64 "\n",
|
||||
reserve_start, reserve_end - reserve_start);
|
||||
}
|
||||
AddFreeUnlocked(reserve_start, reserve_end - reserve_start);
|
||||
m_owned.emplace_back(reserve_start, reserve_end - reserve_start);
|
||||
}
|
||||
|
||||
if (region_end <= next_addr) {
|
||||
EXIT("guest address-space scan did not advance at 0x%016" PRIx64 "\n", next_addr);
|
||||
}
|
||||
next_addr = region_end;
|
||||
}
|
||||
next_addr = region_end;
|
||||
}
|
||||
#else
|
||||
const std::array<std::pair<uint64_t, uint64_t>, 3> regions {{
|
||||
{HOST_SYSTEM_MANAGED_MIN, HOST_SYSTEM_MANAGED_MAX + 1u},
|
||||
{HOST_SYSTEM_RESERVED_MIN, HOST_SYSTEM_RESERVED_MAX + 1u},
|
||||
{HOST_USER_MIN, HOST_USER_MAX + 1u},
|
||||
}};
|
||||
|
||||
#if KYTY_PLATFORM == KYTY_PLATFORM_LINUX && !defined(__APPLE__)
|
||||
std::vector<std::pair<uint64_t, uint64_t>> occupied;
|
||||
FILE* maps = fopen("/proc/self/maps", "r");
|
||||
|
||||
Reference in New Issue
Block a user