diff options
| -rw-r--r-- | src/core/hle/kernel/svc.cpp | 6 | ||||
| -rw-r--r-- | src/core/hle/kernel/vm_manager.cpp | 42 | ||||
| -rw-r--r-- | src/core/hle/kernel/vm_manager.h | 16 |
3 files changed, 37 insertions, 27 deletions
diff --git a/src/core/hle/kernel/svc.cpp b/src/core/hle/kernel/svc.cpp index a6a17efe7..59bc8d9f8 100644 --- a/src/core/hle/kernel/svc.cpp +++ b/src/core/hle/kernel/svc.cpp | |||
| @@ -174,10 +174,8 @@ static ResultCode SetHeapSize(VAddr* heap_addr, u64 heap_size) { | |||
| 174 | return ERR_INVALID_SIZE; | 174 | return ERR_INVALID_SIZE; |
| 175 | } | 175 | } |
| 176 | 176 | ||
| 177 | auto& vm_manager = Core::CurrentProcess()->VMManager(); | 177 | auto& vm_manager = Core::System::GetInstance().Kernel().CurrentProcess()->VMManager(); |
| 178 | const VAddr heap_base = vm_manager.GetHeapRegionBaseAddress(); | 178 | const auto alloc_result = vm_manager.HeapAllocate(heap_size); |
| 179 | const auto alloc_result = | ||
| 180 | vm_manager.HeapAllocate(heap_base, heap_size, VMAPermission::ReadWrite); | ||
| 181 | 179 | ||
| 182 | if (alloc_result.Failed()) { | 180 | if (alloc_result.Failed()) { |
| 183 | return alloc_result.Code(); | 181 | return alloc_result.Code(); |
diff --git a/src/core/hle/kernel/vm_manager.cpp b/src/core/hle/kernel/vm_manager.cpp index 22bf55ce7..9848a8ac6 100644 --- a/src/core/hle/kernel/vm_manager.cpp +++ b/src/core/hle/kernel/vm_manager.cpp | |||
| @@ -256,39 +256,37 @@ ResultCode VMManager::ReprotectRange(VAddr target, u64 size, VMAPermission new_p | |||
| 256 | return RESULT_SUCCESS; | 256 | return RESULT_SUCCESS; |
| 257 | } | 257 | } |
| 258 | 258 | ||
| 259 | ResultVal<VAddr> VMManager::HeapAllocate(VAddr target, u64 size, VMAPermission perms) { | 259 | ResultVal<VAddr> VMManager::HeapAllocate(u64 size) { |
| 260 | if (!IsWithinHeapRegion(target, size)) { | 260 | if (size > GetHeapRegionSize()) { |
| 261 | return ERR_INVALID_ADDRESS; | 261 | return ERR_OUT_OF_MEMORY; |
| 262 | } | 262 | } |
| 263 | 263 | ||
| 264 | if (heap_memory == nullptr) { | 264 | if (heap_memory == nullptr) { |
| 265 | // Initialize heap | 265 | // Initialize heap |
| 266 | heap_memory = std::make_shared<std::vector<u8>>(); | 266 | heap_memory = std::make_shared<std::vector<u8>>(size); |
| 267 | heap_start = heap_end = target; | 267 | heap_end = heap_region_base + size; |
| 268 | } else { | 268 | } else { |
| 269 | UnmapRange(heap_start, heap_end - heap_start); | 269 | UnmapRange(heap_region_base, GetCurrentHeapSize()); |
| 270 | } | 270 | } |
| 271 | 271 | ||
| 272 | // If necessary, expand backing vector to cover new heap extents. | 272 | // If necessary, expand backing vector to cover new heap extents. |
| 273 | if (target < heap_start) { | 273 | if (size > GetCurrentHeapSize()) { |
| 274 | heap_memory->insert(begin(*heap_memory), heap_start - target, 0); | 274 | const u64 alloc_size = size - GetCurrentHeapSize(); |
| 275 | heap_start = target; | 275 | |
| 276 | RefreshMemoryBlockMappings(heap_memory.get()); | 276 | heap_memory->insert(heap_memory->end(), alloc_size, 0); |
| 277 | } | 277 | heap_end = heap_region_base + size; |
| 278 | if (target + size > heap_end) { | ||
| 279 | heap_memory->insert(end(*heap_memory), (target + size) - heap_end, 0); | ||
| 280 | heap_end = target + size; | ||
| 281 | RefreshMemoryBlockMappings(heap_memory.get()); | 278 | RefreshMemoryBlockMappings(heap_memory.get()); |
| 282 | } | 279 | } |
| 283 | ASSERT(heap_end - heap_start == heap_memory->size()); | 280 | ASSERT(GetCurrentHeapSize() == heap_memory->size()); |
| 284 | 281 | ||
| 285 | CASCADE_RESULT(auto vma, MapMemoryBlock(target, heap_memory, target - heap_start, size, | 282 | const auto mapping_result = |
| 286 | MemoryState::Heap)); | 283 | MapMemoryBlock(heap_region_base, heap_memory, 0, size, MemoryState::Heap); |
| 287 | Reprotect(vma, perms); | 284 | if (mapping_result.Failed()) { |
| 285 | return mapping_result.Code(); | ||
| 286 | } | ||
| 288 | 287 | ||
| 289 | heap_used = size; | 288 | heap_used = size; |
| 290 | 289 | return MakeResult<VAddr>(heap_region_base); | |
| 291 | return MakeResult<VAddr>(heap_end - size); | ||
| 292 | } | 290 | } |
| 293 | 291 | ||
| 294 | ResultCode VMManager::HeapFree(VAddr target, u64 size) { | 292 | ResultCode VMManager::HeapFree(VAddr target, u64 size) { |
| @@ -778,6 +776,10 @@ u64 VMManager::GetHeapRegionSize() const { | |||
| 778 | return heap_region_end - heap_region_base; | 776 | return heap_region_end - heap_region_base; |
| 779 | } | 777 | } |
| 780 | 778 | ||
| 779 | u64 VMManager::GetCurrentHeapSize() const { | ||
| 780 | return heap_end - heap_region_base; | ||
| 781 | } | ||
| 782 | |||
| 781 | bool VMManager::IsWithinHeapRegion(VAddr address, u64 size) const { | 783 | bool VMManager::IsWithinHeapRegion(VAddr address, u64 size) const { |
| 782 | return IsInsideAddressRange(address, size, GetHeapRegionBaseAddress(), | 784 | return IsInsideAddressRange(address, size, GetHeapRegionBaseAddress(), |
| 783 | GetHeapRegionEndAddress()); | 785 | GetHeapRegionEndAddress()); |
diff --git a/src/core/hle/kernel/vm_manager.h b/src/core/hle/kernel/vm_manager.h index 7cdff6094..23edd6582 100644 --- a/src/core/hle/kernel/vm_manager.h +++ b/src/core/hle/kernel/vm_manager.h | |||
| @@ -380,7 +380,7 @@ public: | |||
| 380 | /// Changes the permissions of a range of addresses, splitting VMAs as necessary. | 380 | /// Changes the permissions of a range of addresses, splitting VMAs as necessary. |
| 381 | ResultCode ReprotectRange(VAddr target, u64 size, VMAPermission new_perms); | 381 | ResultCode ReprotectRange(VAddr target, u64 size, VMAPermission new_perms); |
| 382 | 382 | ||
| 383 | ResultVal<VAddr> HeapAllocate(VAddr target, u64 size, VMAPermission perms); | 383 | ResultVal<VAddr> HeapAllocate(u64 size); |
| 384 | ResultCode HeapFree(VAddr target, u64 size); | 384 | ResultCode HeapFree(VAddr target, u64 size); |
| 385 | 385 | ||
| 386 | ResultCode MirrorMemory(VAddr dst_addr, VAddr src_addr, u64 size, MemoryState state); | 386 | ResultCode MirrorMemory(VAddr dst_addr, VAddr src_addr, u64 size, MemoryState state); |
| @@ -469,6 +469,13 @@ public: | |||
| 469 | /// Gets the total size of the heap region in bytes. | 469 | /// Gets the total size of the heap region in bytes. |
| 470 | u64 GetHeapRegionSize() const; | 470 | u64 GetHeapRegionSize() const; |
| 471 | 471 | ||
| 472 | /// Gets the total size of the current heap in bytes. | ||
| 473 | /// | ||
| 474 | /// @note This is the current allocated heap size, not the size | ||
| 475 | /// of the region it's allowed to exist within. | ||
| 476 | /// | ||
| 477 | u64 GetCurrentHeapSize() const; | ||
| 478 | |||
| 472 | /// Determines whether or not the specified range is within the heap region. | 479 | /// Determines whether or not the specified range is within the heap region. |
| 473 | bool IsWithinHeapRegion(VAddr address, u64 size) const; | 480 | bool IsWithinHeapRegion(VAddr address, u64 size) const; |
| 474 | 481 | ||
| @@ -628,9 +635,12 @@ private: | |||
| 628 | // This makes deallocation and reallocation of holes fast and keeps process memory contiguous | 635 | // This makes deallocation and reallocation of holes fast and keeps process memory contiguous |
| 629 | // in the emulator address space, allowing Memory::GetPointer to be reasonably safe. | 636 | // in the emulator address space, allowing Memory::GetPointer to be reasonably safe. |
| 630 | std::shared_ptr<std::vector<u8>> heap_memory; | 637 | std::shared_ptr<std::vector<u8>> heap_memory; |
| 631 | // The left/right bounds of the address space covered by heap_memory. | 638 | |
| 632 | VAddr heap_start = 0; | 639 | // The end of the currently allocated heap. This is not an inclusive |
| 640 | // end of the range. This is essentially 'base_address + current_size'. | ||
| 633 | VAddr heap_end = 0; | 641 | VAddr heap_end = 0; |
| 642 | |||
| 643 | // Indicates how many bytes from the current heap are currently used. | ||
| 634 | u64 heap_used = 0; | 644 | u64 heap_used = 0; |
| 635 | }; | 645 | }; |
| 636 | } // namespace Kernel | 646 | } // namespace Kernel |