From 89e12b04c86196ebfcb4d4f9137d9714162d251d Mon Sep 17 00:00:00 2001 From: nikosszzz <19nikospap@gmail.com> Date: Fri, 31 Jul 2026 11:50:53 +0300 Subject: [PATCH] kernel/memory: reserve only available guest address ranges on Linux Reserve only free guest address ranges --- src/kernel/memoryAddressSpace.inc | 67 ++++++++++++++++++++++++++----- 1 file changed, 58 insertions(+), 9 deletions(-) diff --git a/src/kernel/memoryAddressSpace.inc b/src/kernel/memoryAddressSpace.inc index 9fde561..06d9319 100644 --- a/src/kernel/memoryAddressSpace.inc +++ b/src/kernel/memoryAddressSpace.inc @@ -1058,24 +1058,73 @@ private: {HOST_SYSTEM_RESERVED_MIN, HOST_SYSTEM_RESERVED_MAX + 1u}, {HOST_USER_MIN, HOST_USER_MAX + 1u}, }}; - for (const auto& [start, end]: regions) { - int flags = MAP_PRIVATE | MAP_ANON | MAP_NORESERVE; + + std::vector> occupied; + FILE* maps = fopen("/proc/self/maps", "r"); + EXIT_IF(maps == nullptr); + + char line[512]; + while (fgets(line, sizeof(line), maps) != nullptr) { + unsigned long long mapping_start = 0; + unsigned long long mapping_end = 0; + if (sscanf(line, "%llx-%llx", &mapping_start, &mapping_end) == 2) { + occupied.emplace_back(static_cast(mapping_start), + static_cast(mapping_end)); + } + } + fclose(maps); + + auto reserve_range = [this](uint64_t start, uint64_t end) { + start = AlignUp(start, PageSize()); + end = AlignDown(end, PageSize()); + if (start == 0 || end <= start) { + return; + } + + const auto size = end - start; + int flags = MAP_PRIVATE | MAP_ANON | MAP_NORESERVE; #if defined(KYTY_LINKED_GUEST_ADDRESS_SPACE) flags |= MAP_FIXED; #elif defined(MAP_FIXED_NOREPLACE) flags |= MAP_FIXED_NOREPLACE; #endif - void* ptr = mmap(reinterpret_cast(start), end - start, PROT_NONE, flags, -1, 0); + + void* ptr = mmap(reinterpret_cast(start), size, PROT_NONE, flags, -1, 0); if (ptr == MAP_FAILED || reinterpret_cast(ptr) != start) { if (ptr != MAP_FAILED) { - munmap(ptr, end - start); + munmap(ptr, size); } - EXIT("failed to reserve guest address space at 0x%016" PRIx64 ", size 0x%016" PRIx64 - "\n", - start, end - start); + return; + } + + AddFreeUnlocked(start, size); + m_owned.emplace_back(start, size); + }; + + for (const auto& [region_start, region_end]: regions) { + auto current = region_start; + + for (const auto& [mapping_start, mapping_end]: occupied) { + if (mapping_end <= current) { + continue; + } + if (mapping_start >= region_end) { + break; + } + + if (mapping_start > current) { + reserve_range(current, std::min(mapping_start, region_end)); + } + + current = std::max(current, mapping_end); + if (current >= region_end) { + break; + } + } + + if (current < region_end) { + reserve_range(current, region_end); } - AddFreeUnlocked(start, end - start); - m_owned.emplace_back(start, end - start); } #endif }