diff options
Diffstat (limited to '')
| -rw-r--r-- | src/core/hle/kernel/k_memory_block.h | 2 | ||||
| -rw-r--r-- | src/core/hle/kernel/k_page_table.cpp | 167 | ||||
| -rw-r--r-- | src/core/hle/kernel/k_page_table.h | 19 | ||||
| -rw-r--r-- | src/core/hle/kernel/k_process.cpp | 8 | ||||
| -rw-r--r-- | src/core/hle/kernel/svc.cpp | 23 | ||||
| -rw-r--r-- | src/core/hle/kernel/svc_common.h | 5 |
6 files changed, 141 insertions, 83 deletions
diff --git a/src/core/hle/kernel/k_memory_block.h b/src/core/hle/kernel/k_memory_block.h index fd491146f..9e51c33ce 100644 --- a/src/core/hle/kernel/k_memory_block.h +++ b/src/core/hle/kernel/k_memory_block.h | |||
| @@ -120,7 +120,7 @@ static_assert(static_cast<u32>(KMemoryState::CodeOut) == 0x00402015); | |||
| 120 | 120 | ||
| 121 | enum class KMemoryPermission : u8 { | 121 | enum class KMemoryPermission : u8 { |
| 122 | None = 0, | 122 | None = 0, |
| 123 | Mask = static_cast<u8>(~None), | 123 | All = static_cast<u8>(~None), |
| 124 | 124 | ||
| 125 | Read = 1 << 0, | 125 | Read = 1 << 0, |
| 126 | Write = 1 << 1, | 126 | Write = 1 << 1, |
diff --git a/src/core/hle/kernel/k_page_table.cpp b/src/core/hle/kernel/k_page_table.cpp index f2f88c147..4da509224 100644 --- a/src/core/hle/kernel/k_page_table.cpp +++ b/src/core/hle/kernel/k_page_table.cpp | |||
| @@ -264,9 +264,9 @@ ResultCode KPageTable::InitializeForProcess(FileSys::ProgramAddressSpaceType as_ | |||
| 264 | ASSERT(heap_last < stack_start || stack_last < heap_start); | 264 | ASSERT(heap_last < stack_start || stack_last < heap_start); |
| 265 | ASSERT(heap_last < kmap_start || kmap_last < heap_start); | 265 | ASSERT(heap_last < kmap_start || kmap_last < heap_start); |
| 266 | 266 | ||
| 267 | current_heap_addr = heap_region_start; | 267 | current_heap_end = heap_region_start; |
| 268 | heap_capacity = 0; | 268 | max_heap_size = 0; |
| 269 | physical_memory_usage = 0; | 269 | mapped_physical_memory_size = 0; |
| 270 | memory_pool = pool; | 270 | memory_pool = pool; |
| 271 | 271 | ||
| 272 | page_table_impl.Resize(address_space_width, PageBits); | 272 | page_table_impl.Resize(address_space_width, PageBits); |
| @@ -306,7 +306,7 @@ ResultCode KPageTable::MapProcessCodeMemory(VAddr dst_addr, VAddr src_addr, std: | |||
| 306 | KMemoryState state{}; | 306 | KMemoryState state{}; |
| 307 | KMemoryPermission perm{}; | 307 | KMemoryPermission perm{}; |
| 308 | CASCADE_CODE(CheckMemoryState(&state, &perm, nullptr, src_addr, size, KMemoryState::All, | 308 | CASCADE_CODE(CheckMemoryState(&state, &perm, nullptr, src_addr, size, KMemoryState::All, |
| 309 | KMemoryState::Normal, KMemoryPermission::Mask, | 309 | KMemoryState::Normal, KMemoryPermission::All, |
| 310 | KMemoryPermission::ReadAndWrite, KMemoryAttribute::Mask, | 310 | KMemoryPermission::ReadAndWrite, KMemoryAttribute::Mask, |
| 311 | KMemoryAttribute::None, KMemoryAttribute::IpcAndDeviceMapped)); | 311 | KMemoryAttribute::None, KMemoryAttribute::IpcAndDeviceMapped)); |
| 312 | 312 | ||
| @@ -465,7 +465,7 @@ ResultCode KPageTable::MapPhysicalMemory(VAddr addr, std::size_t size) { | |||
| 465 | 465 | ||
| 466 | MapPhysicalMemory(page_linked_list, addr, end_addr); | 466 | MapPhysicalMemory(page_linked_list, addr, end_addr); |
| 467 | 467 | ||
| 468 | physical_memory_usage += remaining_size; | 468 | mapped_physical_memory_size += remaining_size; |
| 469 | 469 | ||
| 470 | const std::size_t num_pages{size / PageSize}; | 470 | const std::size_t num_pages{size / PageSize}; |
| 471 | block_manager->Update(addr, num_pages, KMemoryState::Free, KMemoryPermission::None, | 471 | block_manager->Update(addr, num_pages, KMemoryState::Free, KMemoryPermission::None, |
| @@ -507,7 +507,7 @@ ResultCode KPageTable::UnmapPhysicalMemory(VAddr addr, std::size_t size) { | |||
| 507 | 507 | ||
| 508 | auto process{system.Kernel().CurrentProcess()}; | 508 | auto process{system.Kernel().CurrentProcess()}; |
| 509 | process->GetResourceLimit()->Release(LimitableResource::PhysicalMemory, mapped_size); | 509 | process->GetResourceLimit()->Release(LimitableResource::PhysicalMemory, mapped_size); |
| 510 | physical_memory_usage -= mapped_size; | 510 | mapped_physical_memory_size -= mapped_size; |
| 511 | 511 | ||
| 512 | return ResultSuccess; | 512 | return ResultSuccess; |
| 513 | } | 513 | } |
| @@ -554,7 +554,7 @@ ResultCode KPageTable::Map(VAddr dst_addr, VAddr src_addr, std::size_t size) { | |||
| 554 | KMemoryState src_state{}; | 554 | KMemoryState src_state{}; |
| 555 | CASCADE_CODE(CheckMemoryState( | 555 | CASCADE_CODE(CheckMemoryState( |
| 556 | &src_state, nullptr, nullptr, src_addr, size, KMemoryState::FlagCanAlias, | 556 | &src_state, nullptr, nullptr, src_addr, size, KMemoryState::FlagCanAlias, |
| 557 | KMemoryState::FlagCanAlias, KMemoryPermission::Mask, KMemoryPermission::ReadAndWrite, | 557 | KMemoryState::FlagCanAlias, KMemoryPermission::All, KMemoryPermission::ReadAndWrite, |
| 558 | KMemoryAttribute::Mask, KMemoryAttribute::None, KMemoryAttribute::IpcAndDeviceMapped)); | 558 | KMemoryAttribute::Mask, KMemoryAttribute::None, KMemoryAttribute::IpcAndDeviceMapped)); |
| 559 | 559 | ||
| 560 | if (IsRegionMapped(dst_addr, size)) { | 560 | if (IsRegionMapped(dst_addr, size)) { |
| @@ -593,7 +593,7 @@ ResultCode KPageTable::Unmap(VAddr dst_addr, VAddr src_addr, std::size_t size) { | |||
| 593 | KMemoryState src_state{}; | 593 | KMemoryState src_state{}; |
| 594 | CASCADE_CODE(CheckMemoryState( | 594 | CASCADE_CODE(CheckMemoryState( |
| 595 | &src_state, nullptr, nullptr, src_addr, size, KMemoryState::FlagCanAlias, | 595 | &src_state, nullptr, nullptr, src_addr, size, KMemoryState::FlagCanAlias, |
| 596 | KMemoryState::FlagCanAlias, KMemoryPermission::Mask, KMemoryPermission::None, | 596 | KMemoryState::FlagCanAlias, KMemoryPermission::All, KMemoryPermission::None, |
| 597 | KMemoryAttribute::Mask, KMemoryAttribute::Locked, KMemoryAttribute::IpcAndDeviceMapped)); | 597 | KMemoryAttribute::Mask, KMemoryAttribute::Locked, KMemoryAttribute::IpcAndDeviceMapped)); |
| 598 | 598 | ||
| 599 | KMemoryPermission dst_perm{}; | 599 | KMemoryPermission dst_perm{}; |
| @@ -784,7 +784,7 @@ ResultCode KPageTable::ReserveTransferMemory(VAddr addr, std::size_t size, KMemo | |||
| 784 | CASCADE_CODE(CheckMemoryState( | 784 | CASCADE_CODE(CheckMemoryState( |
| 785 | &state, nullptr, &attribute, addr, size, | 785 | &state, nullptr, &attribute, addr, size, |
| 786 | KMemoryState::FlagCanTransfer | KMemoryState::FlagReferenceCounted, | 786 | KMemoryState::FlagCanTransfer | KMemoryState::FlagReferenceCounted, |
| 787 | KMemoryState::FlagCanTransfer | KMemoryState::FlagReferenceCounted, KMemoryPermission::Mask, | 787 | KMemoryState::FlagCanTransfer | KMemoryState::FlagReferenceCounted, KMemoryPermission::All, |
| 788 | KMemoryPermission::ReadAndWrite, KMemoryAttribute::Mask, KMemoryAttribute::None, | 788 | KMemoryPermission::ReadAndWrite, KMemoryAttribute::Mask, KMemoryAttribute::None, |
| 789 | KMemoryAttribute::IpcAndDeviceMapped)); | 789 | KMemoryAttribute::IpcAndDeviceMapped)); |
| 790 | 790 | ||
| @@ -859,61 +859,125 @@ ResultCode KPageTable::SetMemoryAttribute(VAddr addr, std::size_t size, KMemoryA | |||
| 859 | return ResultSuccess; | 859 | return ResultSuccess; |
| 860 | } | 860 | } |
| 861 | 861 | ||
| 862 | ResultCode KPageTable::SetHeapCapacity(std::size_t new_heap_capacity) { | 862 | ResultCode KPageTable::SetMaxHeapSize(std::size_t size) { |
| 863 | // Lock the table. | ||
| 863 | std::lock_guard lock{page_table_lock}; | 864 | std::lock_guard lock{page_table_lock}; |
| 864 | heap_capacity = new_heap_capacity; | ||
| 865 | return ResultSuccess; | ||
| 866 | } | ||
| 867 | 865 | ||
| 868 | ResultVal<VAddr> KPageTable::SetHeapSize(std::size_t size) { | 866 | // Only process page tables are allowed to set heap size. |
| 867 | ASSERT(!this->IsKernel()); | ||
| 869 | 868 | ||
| 870 | if (size > heap_region_end - heap_region_start) { | 869 | max_heap_size = size; |
| 871 | return ResultOutOfMemory; | ||
| 872 | } | ||
| 873 | 870 | ||
| 874 | const u64 previous_heap_size{GetHeapSize()}; | 871 | return ResultSuccess; |
| 875 | 872 | } | |
| 876 | UNIMPLEMENTED_IF_MSG(previous_heap_size > size, "Heap shrink is unimplemented"); | ||
| 877 | 873 | ||
| 878 | // Increase the heap size | 874 | ResultCode KPageTable::SetHeapSize(VAddr* out, std::size_t size) { |
| 875 | // Try to perform a reduction in heap, instead of an extension. | ||
| 876 | VAddr cur_address{}; | ||
| 877 | std::size_t allocation_size{}; | ||
| 879 | { | 878 | { |
| 880 | std::lock_guard lock{page_table_lock}; | 879 | // Lock the table. |
| 881 | 880 | std::lock_guard lk(page_table_lock); | |
| 882 | const u64 delta{size - previous_heap_size}; | 881 | |
| 883 | 882 | // Validate that setting heap size is possible at all. | |
| 884 | // Reserve memory for the heap extension. | 883 | R_UNLESS(!is_kernel, ResultOutOfMemory); |
| 885 | KScopedResourceReservation memory_reservation( | 884 | R_UNLESS(size <= static_cast<std::size_t>(heap_region_end - heap_region_start), |
| 886 | system.Kernel().CurrentProcess()->GetResourceLimit(), LimitableResource::PhysicalMemory, | 885 | ResultOutOfMemory); |
| 887 | delta); | 886 | R_UNLESS(size <= max_heap_size, ResultOutOfMemory); |
| 888 | 887 | ||
| 889 | if (!memory_reservation.Succeeded()) { | 888 | if (size < GetHeapSize()) { |
| 890 | LOG_ERROR(Kernel, "Could not reserve heap extension of size {:X} bytes", delta); | 889 | // The size being requested is less than the current size, so we need to free the end of |
| 891 | return ResultLimitReached; | 890 | // the heap. |
| 891 | |||
| 892 | // Validate memory state. | ||
| 893 | std::size_t num_allocator_blocks; | ||
| 894 | R_TRY(this->CheckMemoryState(std::addressof(num_allocator_blocks), | ||
| 895 | heap_region_start + size, GetHeapSize() - size, | ||
| 896 | KMemoryState::All, KMemoryState::Normal, | ||
| 897 | KMemoryPermission::All, KMemoryPermission::ReadAndWrite, | ||
| 898 | KMemoryAttribute::All, KMemoryAttribute::None)); | ||
| 899 | |||
| 900 | // Unmap the end of the heap. | ||
| 901 | const auto num_pages = (GetHeapSize() - size) / PageSize; | ||
| 902 | R_TRY(Operate(heap_region_start + size, num_pages, KMemoryPermission::None, | ||
| 903 | OperationType::Unmap)); | ||
| 904 | |||
| 905 | // Release the memory from the resource limit. | ||
| 906 | system.Kernel().CurrentProcess()->GetResourceLimit()->Release( | ||
| 907 | LimitableResource::PhysicalMemory, num_pages * PageSize); | ||
| 908 | |||
| 909 | // Apply the memory block update. | ||
| 910 | block_manager->Update(heap_region_start + size, num_pages, KMemoryState::Free, | ||
| 911 | KMemoryPermission::None, KMemoryAttribute::None); | ||
| 912 | |||
| 913 | // Update the current heap end. | ||
| 914 | current_heap_end = heap_region_start + size; | ||
| 915 | |||
| 916 | // Set the output. | ||
| 917 | *out = heap_region_start; | ||
| 918 | return ResultSuccess; | ||
| 919 | } else if (size == GetHeapSize()) { | ||
| 920 | // The size requested is exactly the current size. | ||
| 921 | *out = heap_region_start; | ||
| 922 | return ResultSuccess; | ||
| 923 | } else { | ||
| 924 | // We have to allocate memory. Determine how much to allocate and where while the table | ||
| 925 | // is locked. | ||
| 926 | cur_address = current_heap_end; | ||
| 927 | allocation_size = size - GetHeapSize(); | ||
| 892 | } | 928 | } |
| 929 | } | ||
| 893 | 930 | ||
| 894 | KPageLinkedList page_linked_list; | 931 | // Reserve memory for the heap extension. |
| 895 | const std::size_t num_pages{delta / PageSize}; | 932 | KScopedResourceReservation memory_reservation( |
| 933 | system.Kernel().CurrentProcess()->GetResourceLimit(), LimitableResource::PhysicalMemory, | ||
| 934 | allocation_size); | ||
| 935 | R_UNLESS(memory_reservation.Succeeded(), ResultLimitReached); | ||
| 896 | 936 | ||
| 897 | CASCADE_CODE( | 937 | // Allocate pages for the heap extension. |
| 898 | system.Kernel().MemoryManager().Allocate(page_linked_list, num_pages, memory_pool)); | 938 | KPageLinkedList page_linked_list; |
| 939 | R_TRY(system.Kernel().MemoryManager().Allocate(page_linked_list, allocation_size / PageSize, | ||
| 940 | memory_pool)); | ||
| 899 | 941 | ||
| 900 | if (IsRegionMapped(current_heap_addr, delta)) { | 942 | // Map the pages. |
| 901 | return ResultInvalidCurrentMemory; | 943 | { |
| 944 | // Lock the table. | ||
| 945 | std::lock_guard lk(page_table_lock); | ||
| 946 | |||
| 947 | // Ensure that the heap hasn't changed since we began executing. | ||
| 948 | ASSERT(cur_address == current_heap_end); | ||
| 949 | |||
| 950 | // Check the memory state. | ||
| 951 | std::size_t num_allocator_blocks{}; | ||
| 952 | R_TRY(this->CheckMemoryState(std::addressof(num_allocator_blocks), current_heap_end, | ||
| 953 | allocation_size, KMemoryState::All, KMemoryState::Free, | ||
| 954 | KMemoryPermission::None, KMemoryPermission::None, | ||
| 955 | KMemoryAttribute::None, KMemoryAttribute::None)); | ||
| 956 | |||
| 957 | // Map the pages. | ||
| 958 | const auto num_pages = allocation_size / PageSize; | ||
| 959 | R_TRY(Operate(current_heap_end, num_pages, page_linked_list, OperationType::MapGroup)); | ||
| 960 | |||
| 961 | // Clear all the newly allocated pages. | ||
| 962 | for (std::size_t cur_page = 0; cur_page < num_pages; ++cur_page) { | ||
| 963 | std::memset(system.Memory().GetPointer(current_heap_end + (cur_page * PageSize)), 0, | ||
| 964 | PageSize); | ||
| 902 | } | 965 | } |
| 903 | 966 | ||
| 904 | CASCADE_CODE( | 967 | // We succeeded, so commit our memory reservation. |
| 905 | Operate(current_heap_addr, num_pages, page_linked_list, OperationType::MapGroup)); | ||
| 906 | |||
| 907 | // Succeeded in allocation, commit the resource reservation | ||
| 908 | memory_reservation.Commit(); | 968 | memory_reservation.Commit(); |
| 909 | 969 | ||
| 910 | block_manager->Update(current_heap_addr, num_pages, KMemoryState::Normal, | 970 | // Apply the memory block update. |
| 911 | KMemoryPermission::ReadAndWrite); | 971 | block_manager->Update(current_heap_end, num_pages, KMemoryState::Normal, |
| 972 | KMemoryPermission::ReadAndWrite, KMemoryAttribute::None); | ||
| 912 | 973 | ||
| 913 | current_heap_addr = heap_region_start + size; | 974 | // Update the current heap end. |
| 914 | } | 975 | current_heap_end = heap_region_start + size; |
| 915 | 976 | ||
| 916 | return heap_region_start; | 977 | // Set the output. |
| 978 | *out = heap_region_start; | ||
| 979 | return ResultSuccess; | ||
| 980 | } | ||
| 917 | } | 981 | } |
| 918 | 982 | ||
| 919 | ResultVal<VAddr> KPageTable::AllocateAndMapMemory(std::size_t needed_num_pages, std::size_t align, | 983 | ResultVal<VAddr> KPageTable::AllocateAndMapMemory(std::size_t needed_num_pages, std::size_t align, |
| @@ -1005,7 +1069,7 @@ ResultCode KPageTable::LockForCodeMemory(VAddr addr, std::size_t size) { | |||
| 1005 | 1069 | ||
| 1006 | if (const ResultCode result{CheckMemoryState( | 1070 | if (const ResultCode result{CheckMemoryState( |
| 1007 | nullptr, &old_perm, nullptr, addr, size, KMemoryState::FlagCanCodeMemory, | 1071 | nullptr, &old_perm, nullptr, addr, size, KMemoryState::FlagCanCodeMemory, |
| 1008 | KMemoryState::FlagCanCodeMemory, KMemoryPermission::Mask, | 1072 | KMemoryState::FlagCanCodeMemory, KMemoryPermission::All, |
| 1009 | KMemoryPermission::UserReadWrite, KMemoryAttribute::All, KMemoryAttribute::None)}; | 1073 | KMemoryPermission::UserReadWrite, KMemoryAttribute::All, KMemoryAttribute::None)}; |
| 1010 | result.IsError()) { | 1074 | result.IsError()) { |
| 1011 | return result; | 1075 | return result; |
| @@ -1058,9 +1122,8 @@ ResultCode KPageTable::InitializeMemoryLayout(VAddr start, VAddr end) { | |||
| 1058 | 1122 | ||
| 1059 | bool KPageTable::IsRegionMapped(VAddr address, u64 size) { | 1123 | bool KPageTable::IsRegionMapped(VAddr address, u64 size) { |
| 1060 | return CheckMemoryState(address, size, KMemoryState::All, KMemoryState::Free, | 1124 | return CheckMemoryState(address, size, KMemoryState::All, KMemoryState::Free, |
| 1061 | KMemoryPermission::Mask, KMemoryPermission::None, | 1125 | KMemoryPermission::All, KMemoryPermission::None, KMemoryAttribute::Mask, |
| 1062 | KMemoryAttribute::Mask, KMemoryAttribute::None, | 1126 | KMemoryAttribute::None, KMemoryAttribute::IpcAndDeviceMapped) |
| 1063 | KMemoryAttribute::IpcAndDeviceMapped) | ||
| 1064 | .IsError(); | 1127 | .IsError(); |
| 1065 | } | 1128 | } |
| 1066 | 1129 | ||
diff --git a/src/core/hle/kernel/k_page_table.h b/src/core/hle/kernel/k_page_table.h index db08ea8ce..564410dca 100644 --- a/src/core/hle/kernel/k_page_table.h +++ b/src/core/hle/kernel/k_page_table.h | |||
| @@ -50,8 +50,8 @@ public: | |||
| 50 | ResultCode SetMemoryPermission(VAddr addr, std::size_t size, Svc::MemoryPermission perm); | 50 | ResultCode SetMemoryPermission(VAddr addr, std::size_t size, Svc::MemoryPermission perm); |
| 51 | ResultCode SetMemoryAttribute(VAddr addr, std::size_t size, KMemoryAttribute mask, | 51 | ResultCode SetMemoryAttribute(VAddr addr, std::size_t size, KMemoryAttribute mask, |
| 52 | KMemoryAttribute value); | 52 | KMemoryAttribute value); |
| 53 | ResultCode SetHeapCapacity(std::size_t new_heap_capacity); | 53 | ResultCode SetMaxHeapSize(std::size_t size); |
| 54 | ResultVal<VAddr> SetHeapSize(std::size_t size); | 54 | ResultCode SetHeapSize(VAddr* out, std::size_t size); |
| 55 | ResultVal<VAddr> AllocateAndMapMemory(std::size_t needed_num_pages, std::size_t align, | 55 | ResultVal<VAddr> AllocateAndMapMemory(std::size_t needed_num_pages, std::size_t align, |
| 56 | bool is_map_only, VAddr region_start, | 56 | bool is_map_only, VAddr region_start, |
| 57 | std::size_t region_num_pages, KMemoryState state, | 57 | std::size_t region_num_pages, KMemoryState state, |
| @@ -183,14 +183,15 @@ public: | |||
| 183 | constexpr VAddr GetAliasCodeRegionSize() const { | 183 | constexpr VAddr GetAliasCodeRegionSize() const { |
| 184 | return alias_code_region_end - alias_code_region_start; | 184 | return alias_code_region_end - alias_code_region_start; |
| 185 | } | 185 | } |
| 186 | size_t GetNormalMemorySize() { | ||
| 187 | std::lock_guard lk(page_table_lock); | ||
| 188 | return GetHeapSize() + mapped_physical_memory_size; | ||
| 189 | } | ||
| 186 | constexpr std::size_t GetAddressSpaceWidth() const { | 190 | constexpr std::size_t GetAddressSpaceWidth() const { |
| 187 | return address_space_width; | 191 | return address_space_width; |
| 188 | } | 192 | } |
| 189 | constexpr std::size_t GetHeapSize() { | 193 | constexpr std::size_t GetHeapSize() const { |
| 190 | return current_heap_addr - heap_region_start; | 194 | return current_heap_end - heap_region_start; |
| 191 | } | ||
| 192 | constexpr std::size_t GetTotalHeapSize() { | ||
| 193 | return GetHeapSize() + physical_memory_usage; | ||
| 194 | } | 195 | } |
| 195 | constexpr bool IsInsideAddressSpace(VAddr address, std::size_t size) const { | 196 | constexpr bool IsInsideAddressSpace(VAddr address, std::size_t size) const { |
| 196 | return address_space_start <= address && address + size - 1 <= address_space_end - 1; | 197 | return address_space_start <= address && address + size - 1 <= address_space_end - 1; |
| @@ -270,10 +271,8 @@ private: | |||
| 270 | VAddr code_region_end{}; | 271 | VAddr code_region_end{}; |
| 271 | VAddr alias_code_region_start{}; | 272 | VAddr alias_code_region_start{}; |
| 272 | VAddr alias_code_region_end{}; | 273 | VAddr alias_code_region_end{}; |
| 273 | VAddr current_heap_addr{}; | ||
| 274 | 274 | ||
| 275 | std::size_t heap_capacity{}; | 275 | std::size_t mapped_physical_memory_size{}; |
| 276 | std::size_t physical_memory_usage{}; | ||
| 277 | std::size_t max_heap_size{}; | 276 | std::size_t max_heap_size{}; |
| 278 | std::size_t max_physical_memory_size{}; | 277 | std::size_t max_physical_memory_size{}; |
| 279 | std::size_t address_space_width{}; | 278 | std::size_t address_space_width{}; |
diff --git a/src/core/hle/kernel/k_process.cpp b/src/core/hle/kernel/k_process.cpp index aee313995..73f8bc4fe 100644 --- a/src/core/hle/kernel/k_process.cpp +++ b/src/core/hle/kernel/k_process.cpp | |||
| @@ -172,7 +172,7 @@ void KProcess::DecrementThreadCount() { | |||
| 172 | 172 | ||
| 173 | u64 KProcess::GetTotalPhysicalMemoryAvailable() const { | 173 | u64 KProcess::GetTotalPhysicalMemoryAvailable() const { |
| 174 | const u64 capacity{resource_limit->GetFreeValue(LimitableResource::PhysicalMemory) + | 174 | const u64 capacity{resource_limit->GetFreeValue(LimitableResource::PhysicalMemory) + |
| 175 | page_table->GetTotalHeapSize() + GetSystemResourceSize() + image_size + | 175 | page_table->GetNormalMemorySize() + GetSystemResourceSize() + image_size + |
| 176 | main_thread_stack_size}; | 176 | main_thread_stack_size}; |
| 177 | if (const auto pool_size = kernel.MemoryManager().GetSize(KMemoryManager::Pool::Application); | 177 | if (const auto pool_size = kernel.MemoryManager().GetSize(KMemoryManager::Pool::Application); |
| 178 | capacity != pool_size) { | 178 | capacity != pool_size) { |
| @@ -189,7 +189,7 @@ u64 KProcess::GetTotalPhysicalMemoryAvailableWithoutSystemResource() const { | |||
| 189 | } | 189 | } |
| 190 | 190 | ||
| 191 | u64 KProcess::GetTotalPhysicalMemoryUsed() const { | 191 | u64 KProcess::GetTotalPhysicalMemoryUsed() const { |
| 192 | return image_size + main_thread_stack_size + page_table->GetTotalHeapSize() + | 192 | return image_size + main_thread_stack_size + page_table->GetNormalMemorySize() + |
| 193 | GetSystemResourceSize(); | 193 | GetSystemResourceSize(); |
| 194 | } | 194 | } |
| 195 | 195 | ||
| @@ -410,8 +410,8 @@ void KProcess::Run(s32 main_thread_priority, u64 stack_size) { | |||
| 410 | resource_limit->Reserve(LimitableResource::Threads, 1); | 410 | resource_limit->Reserve(LimitableResource::Threads, 1); |
| 411 | resource_limit->Reserve(LimitableResource::PhysicalMemory, main_thread_stack_size); | 411 | resource_limit->Reserve(LimitableResource::PhysicalMemory, main_thread_stack_size); |
| 412 | 412 | ||
| 413 | const std::size_t heap_capacity{memory_usage_capacity - main_thread_stack_size - image_size}; | 413 | const std::size_t heap_capacity{memory_usage_capacity - (main_thread_stack_size + image_size)}; |
| 414 | ASSERT(!page_table->SetHeapCapacity(heap_capacity).IsError()); | 414 | ASSERT(!page_table->SetMaxHeapSize(heap_capacity).IsError()); |
| 415 | 415 | ||
| 416 | ChangeStatus(ProcessStatus::Running); | 416 | ChangeStatus(ProcessStatus::Running); |
| 417 | 417 | ||
diff --git a/src/core/hle/kernel/svc.cpp b/src/core/hle/kernel/svc.cpp index 68cb47211..63e2dff19 100644 --- a/src/core/hle/kernel/svc.cpp +++ b/src/core/hle/kernel/svc.cpp | |||
| @@ -135,24 +135,15 @@ enum class ResourceLimitValueType { | |||
| 135 | } // Anonymous namespace | 135 | } // Anonymous namespace |
| 136 | 136 | ||
| 137 | /// Set the process heap to a given Size. It can both extend and shrink the heap. | 137 | /// Set the process heap to a given Size. It can both extend and shrink the heap. |
| 138 | static ResultCode SetHeapSize(Core::System& system, VAddr* heap_addr, u64 heap_size) { | 138 | static ResultCode SetHeapSize(Core::System& system, VAddr* out_address, u64 size) { |
| 139 | LOG_TRACE(Kernel_SVC, "called, heap_size=0x{:X}", heap_size); | 139 | LOG_TRACE(Kernel_SVC, "called, heap_size=0x{:X}", size); |
| 140 | 140 | ||
| 141 | // Size must be a multiple of 0x200000 (2MB) and be equal to or less than 8GB. | 141 | // Validate size. |
| 142 | if ((heap_size % 0x200000) != 0) { | 142 | R_UNLESS(Common::IsAligned(size, HeapSizeAlignment), ResultInvalidSize); |
| 143 | LOG_ERROR(Kernel_SVC, "The heap size is not a multiple of 2MB, heap_size=0x{:016X}", | 143 | R_UNLESS(size < MainMemorySizeMax, ResultInvalidSize); |
| 144 | heap_size); | ||
| 145 | return ResultInvalidSize; | ||
| 146 | } | ||
| 147 | |||
| 148 | if (heap_size >= 0x200000000) { | ||
| 149 | LOG_ERROR(Kernel_SVC, "The heap size is not less than 8GB, heap_size=0x{:016X}", heap_size); | ||
| 150 | return ResultInvalidSize; | ||
| 151 | } | ||
| 152 | |||
| 153 | auto& page_table{system.Kernel().CurrentProcess()->PageTable()}; | ||
| 154 | 144 | ||
| 155 | CASCADE_RESULT(*heap_addr, page_table.SetHeapSize(heap_size)); | 145 | // Set the heap size. |
| 146 | R_TRY(system.Kernel().CurrentProcess()->PageTable().SetHeapSize(out_address, size)); | ||
| 156 | 147 | ||
| 157 | return ResultSuccess; | 148 | return ResultSuccess; |
| 158 | } | 149 | } |
diff --git a/src/core/hle/kernel/svc_common.h b/src/core/hle/kernel/svc_common.h index 60ea2c405..25de6e437 100644 --- a/src/core/hle/kernel/svc_common.h +++ b/src/core/hle/kernel/svc_common.h | |||
| @@ -5,6 +5,7 @@ | |||
| 5 | #pragma once | 5 | #pragma once |
| 6 | 6 | ||
| 7 | #include "common/common_types.h" | 7 | #include "common/common_types.h" |
| 8 | #include "common/literals.h" | ||
| 8 | 9 | ||
| 9 | namespace Kernel { | 10 | namespace Kernel { |
| 10 | using Handle = u32; | 11 | using Handle = u32; |
| @@ -12,9 +13,13 @@ using Handle = u32; | |||
| 12 | 13 | ||
| 13 | namespace Kernel::Svc { | 14 | namespace Kernel::Svc { |
| 14 | 15 | ||
| 16 | using namespace Common::Literals; | ||
| 17 | |||
| 15 | constexpr s32 ArgumentHandleCountMax = 0x40; | 18 | constexpr s32 ArgumentHandleCountMax = 0x40; |
| 16 | constexpr u32 HandleWaitMask{1u << 30}; | 19 | constexpr u32 HandleWaitMask{1u << 30}; |
| 17 | 20 | ||
| 21 | constexpr inline std::size_t HeapSizeAlignment = 2_MiB; | ||
| 22 | |||
| 18 | constexpr inline Handle InvalidHandle = Handle(0); | 23 | constexpr inline Handle InvalidHandle = Handle(0); |
| 19 | 24 | ||
| 20 | enum PseudoHandle : Handle { | 25 | enum PseudoHandle : Handle { |