summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGravatar Lioncash2019-03-24 15:24:52 -0400
committerGravatar Lioncash2019-03-24 16:17:31 -0400
commit586cab617270346c39ecfb340127e0b8edb863d3 (patch)
tree47daaae2ad06629fc4c636746cc39b6818441425
parentMerge pull request #2221 from DarkLordZach/firmware-version (diff)
downloadyuzu-586cab617270346c39ecfb340127e0b8edb863d3.tar.gz
yuzu-586cab617270346c39ecfb340127e0b8edb863d3.tar.xz
yuzu-586cab617270346c39ecfb340127e0b8edb863d3.zip
kernel/vm_manager: Tidy up heap allocation code
Another holdover from citra that can be tossed out is the notion of the heap needing to be allocated in different addresses. On the switch, the base address of the heap will always be managed by the memory allocator in the kernel, so this doesn't need to be specified in the function's interface itself. The heap on the switch is always allocated with read/write permissions, so we don't need to add specifying the memory permissions as part of the heap allocation itself either. This also corrects the error code returned from within the function. If the size of the heap is larger than the entire heap region, then the kernel will report an out of memory condition.
Diffstat (limited to '')
-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