summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/core/hle/kernel/svc.cpp6
-rw-r--r--src/core/hle/kernel/vm_manager.cpp42
-rw-r--r--src/core/hle/kernel/vm_manager.h16
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
259ResultVal<VAddr> VMManager::HeapAllocate(VAddr target, u64 size, VMAPermission perms) { 259ResultVal<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
294ResultCode VMManager::HeapFree(VAddr target, u64 size) { 292ResultCode 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
779u64 VMManager::GetCurrentHeapSize() const {
780 return heap_end - heap_region_base;
781}
782
781bool VMManager::IsWithinHeapRegion(VAddr address, u64 size) const { 783bool 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