kernel/vm_manager: Add overload of FindFreeRegion() that operates on a boundary

This will be necessary for making our TLS slot management slightly more
straightforward. This can also be utilized for other purposes in the
future.

We can implement the existing simpler overload in terms of this one
anyways, we just pass the beginning and end of the ASLR region as the
boundaries.
This commit is contained in:
Lioncash 2019-06-05 14:20:13 -04:00
parent beb3d77a79
commit 55481df50f
2 changed files with 49 additions and 13 deletions

View file

@ -152,22 +152,33 @@ ResultVal<VMManager::VMAHandle> VMManager::MapBackingMemory(VAddr target, u8* me
} }
ResultVal<VAddr> VMManager::FindFreeRegion(u64 size) const { ResultVal<VAddr> VMManager::FindFreeRegion(u64 size) const {
// Find the first Free VMA. return FindFreeRegion(GetASLRRegionBaseAddress(), GetASLRRegionEndAddress(), size);
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;
const VAddr vma_end = vma.second.base + vma.second.size; ResultVal<VAddr> VMManager::FindFreeRegion(VAddr begin, VAddr end, u64 size) const {
return vma_end > base && vma_end >= base + size; 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. // TODO(Subv): Find the correct error code here.
return ResultCode(-1); 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<VAddr>(target); return MakeResult<VAddr>(target);
} }

View file

@ -362,13 +362,38 @@ public:
ResultVal<VMAHandle> MapBackingMemory(VAddr target, u8* memory, u64 size, MemoryState state); ResultVal<VMAHandle> 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. * @param size The size of the desired region in bytes.
* @return The found free address. *
* @returns If successful, the base address of the free region with
* the given size.
*/ */
ResultVal<VAddr> FindFreeRegion(u64 size) const; ResultVal<VAddr> 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<VAddr> FindFreeRegion(VAddr begin, VAddr end, u64 size) const;
/** /**
* Maps a memory-mapped IO region at a given address. * Maps a memory-mapped IO region at a given address.
* *