diff --git a/src/core/hle/kernel/vm_manager.cpp b/src/core/hle/kernel/vm_manager.cpp index c929c2a52..3df5ccb7f 100644 --- a/src/core/hle/kernel/vm_manager.cpp +++ b/src/core/hle/kernel/vm_manager.cpp @@ -152,22 +152,33 @@ ResultVal VMManager::MapBackingMemory(VAddr target, u8* me } ResultVal VMManager::FindFreeRegion(u64 size) const { - // Find the first Free VMA. - const VAddr base = GetASLRRegionBaseAddress(); - const VMAHandle vma_handle = std::find_if(vma_map.begin(), vma_map.end(), [&](const auto& vma) { - if (vma.second.type != VMAType::Free) - return false; + return FindFreeRegion(GetASLRRegionBaseAddress(), GetASLRRegionEndAddress(), size); +} - const VAddr vma_end = vma.second.base + vma.second.size; - return vma_end > base && vma_end >= base + size; - }); +ResultVal VMManager::FindFreeRegion(VAddr begin, VAddr end, u64 size) const { + ASSERT(begin < end); + ASSERT(size <= end - begin); - if (vma_handle == vma_map.end()) { + const VMAHandle vma_handle = + std::find_if(vma_map.begin(), vma_map.end(), [begin, end, size](const auto& vma) { + if (vma.second.type != VMAType::Free) { + return false; + } + const VAddr vma_base = vma.second.base; + const VAddr vma_end = vma_base + vma.second.size; + const VAddr assumed_base = (begin < vma_base) ? vma_base : begin; + const VAddr used_range = assumed_base + size; + + return vma_base <= assumed_base && assumed_base < used_range && used_range < end && + used_range <= vma_end; + }); + + if (vma_handle == vma_map.cend()) { // TODO(Subv): Find the correct error code here. return ResultCode(-1); } - const VAddr target = std::max(base, vma_handle->second.base); + const VAddr target = std::max(begin, vma_handle->second.base); return MakeResult(target); } diff --git a/src/core/hle/kernel/vm_manager.h b/src/core/hle/kernel/vm_manager.h index dfbf7a894..752ae62f9 100644 --- a/src/core/hle/kernel/vm_manager.h +++ b/src/core/hle/kernel/vm_manager.h @@ -362,13 +362,38 @@ public: ResultVal MapBackingMemory(VAddr target, u8* memory, u64 size, MemoryState state); /** - * Finds the first free address that can hold a region of the desired size. + * Finds the first free memory region of the given size within + * the user-addressable ASLR memory region. * - * @param size Size of the desired region. - * @return The found free address. + * @param size The size of the desired region in bytes. + * + * @returns If successful, the base address of the free region with + * the given size. */ ResultVal FindFreeRegion(u64 size) const; + /** + * Finds the first free address range that can hold a region of the desired size + * + * @param begin The starting address of the range. + * This is treated as an inclusive beginning address. + * + * @param end The ending address of the range. + * This is treated as an exclusive ending address. + * + * @param size The size of the free region to attempt to locate, + * in bytes. + * + * @returns If successful, the base address of the free region with + * the given size. + * + * @returns If unsuccessful, a result containing an error code. + * + * @pre The starting address must be less than the ending address. + * @pre The size must not exceed the address range itself. + */ + ResultVal FindFreeRegion(VAddr begin, VAddr end, u64 size) const; + /** * Maps a memory-mapped IO region at a given address. *