summaryrefslogtreecommitdiffstats
path: root/src/core/hle/kernel/vm_manager.cpp
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/core/hle/kernel/vm_manager.cpp76
1 files changed, 49 insertions, 27 deletions
diff --git a/src/core/hle/kernel/vm_manager.cpp b/src/core/hle/kernel/vm_manager.cpp
index c929c2a52..501544090 100644
--- a/src/core/hle/kernel/vm_manager.cpp
+++ b/src/core/hle/kernel/vm_manager.cpp
@@ -152,22 +152,33 @@ ResultVal<VMManager::VMAHandle> VMManager::MapBackingMemory(VAddr target, u8* me
}
ResultVal<VAddr> 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<VAddr> 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<VAddr>(target);
}
@@ -614,9 +625,11 @@ void VMManager::UpdatePageTableForVMA(const VirtualMemoryArea& vma) {
void VMManager::InitializeMemoryRegionRanges(FileSys::ProgramAddressSpaceType type) {
u64 map_region_size = 0;
u64 heap_region_size = 0;
- u64 new_map_region_size = 0;
+ u64 stack_region_size = 0;
u64 tls_io_region_size = 0;
+ u64 stack_and_tls_io_end = 0;
+
switch (type) {
case FileSys::ProgramAddressSpaceType::Is32Bit:
case FileSys::ProgramAddressSpaceType::Is32BitNoMap:
@@ -632,6 +645,7 @@ void VMManager::InitializeMemoryRegionRanges(FileSys::ProgramAddressSpaceType ty
map_region_size = 0;
heap_region_size = 0x80000000;
}
+ stack_and_tls_io_end = 0x40000000;
break;
case FileSys::ProgramAddressSpaceType::Is36Bit:
address_space_width = 36;
@@ -641,6 +655,7 @@ void VMManager::InitializeMemoryRegionRanges(FileSys::ProgramAddressSpaceType ty
aslr_region_end = aslr_region_base + 0xFF8000000;
map_region_size = 0x180000000;
heap_region_size = 0x180000000;
+ stack_and_tls_io_end = 0x80000000;
break;
case FileSys::ProgramAddressSpaceType::Is39Bit:
address_space_width = 39;
@@ -650,7 +665,7 @@ void VMManager::InitializeMemoryRegionRanges(FileSys::ProgramAddressSpaceType ty
aslr_region_end = aslr_region_base + 0x7FF8000000;
map_region_size = 0x1000000000;
heap_region_size = 0x180000000;
- new_map_region_size = 0x80000000;
+ stack_region_size = 0x80000000;
tls_io_region_size = 0x1000000000;
break;
default:
@@ -658,6 +673,8 @@ void VMManager::InitializeMemoryRegionRanges(FileSys::ProgramAddressSpaceType ty
return;
}
+ const u64 stack_and_tls_io_begin = aslr_region_base;
+
address_space_base = 0;
address_space_end = 1ULL << address_space_width;
@@ -668,15 +685,20 @@ void VMManager::InitializeMemoryRegionRanges(FileSys::ProgramAddressSpaceType ty
heap_region_end = heap_region_base + heap_region_size;
heap_end = heap_region_base;
- new_map_region_base = heap_region_end;
- new_map_region_end = new_map_region_base + new_map_region_size;
+ stack_region_base = heap_region_end;
+ stack_region_end = stack_region_base + stack_region_size;
- tls_io_region_base = new_map_region_end;
+ tls_io_region_base = stack_region_end;
tls_io_region_end = tls_io_region_base + tls_io_region_size;
- if (new_map_region_size == 0) {
- new_map_region_base = address_space_base;
- new_map_region_end = address_space_end;
+ if (stack_region_size == 0) {
+ stack_region_base = stack_and_tls_io_begin;
+ stack_region_end = stack_and_tls_io_end;
+ }
+
+ if (tls_io_region_size == 0) {
+ tls_io_region_base = stack_and_tls_io_begin;
+ tls_io_region_end = stack_and_tls_io_end;
}
}
@@ -868,21 +890,21 @@ bool VMManager::IsWithinMapRegion(VAddr address, u64 size) const {
return IsInsideAddressRange(address, size, GetMapRegionBaseAddress(), GetMapRegionEndAddress());
}
-VAddr VMManager::GetNewMapRegionBaseAddress() const {
- return new_map_region_base;
+VAddr VMManager::GetStackRegionBaseAddress() const {
+ return stack_region_base;
}
-VAddr VMManager::GetNewMapRegionEndAddress() const {
- return new_map_region_end;
+VAddr VMManager::GetStackRegionEndAddress() const {
+ return stack_region_end;
}
-u64 VMManager::GetNewMapRegionSize() const {
- return new_map_region_end - new_map_region_base;
+u64 VMManager::GetStackRegionSize() const {
+ return stack_region_end - stack_region_base;
}
-bool VMManager::IsWithinNewMapRegion(VAddr address, u64 size) const {
- return IsInsideAddressRange(address, size, GetNewMapRegionBaseAddress(),
- GetNewMapRegionEndAddress());
+bool VMManager::IsWithinStackRegion(VAddr address, u64 size) const {
+ return IsInsideAddressRange(address, size, GetStackRegionBaseAddress(),
+ GetStackRegionEndAddress());
}
VAddr VMManager::GetTLSIORegionBaseAddress() const {