diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/core/hle/kernel/k_memory_block.h | 13 | ||||
| -rw-r--r-- | src/core/hle/kernel/k_memory_block_manager.cpp | 70 | ||||
| -rw-r--r-- | src/core/hle/kernel/k_memory_block_manager.h | 6 | ||||
| -rw-r--r-- | src/core/hle/kernel/k_page_table.cpp | 54 | ||||
| -rw-r--r-- | src/core/hle/kernel/k_page_table.h | 3 | ||||
| -rw-r--r-- | src/core/hle/kernel/svc/svc_memory.cpp | 8 |
6 files changed, 128 insertions, 26 deletions
diff --git a/src/core/hle/kernel/k_memory_block.h b/src/core/hle/kernel/k_memory_block.h index 8437cb659..ef3f61321 100644 --- a/src/core/hle/kernel/k_memory_block.h +++ b/src/core/hle/kernel/k_memory_block.h | |||
| @@ -192,7 +192,7 @@ enum class KMemoryAttribute : u8 { | |||
| 192 | Uncached = static_cast<u8>(Svc::MemoryAttribute::Uncached), | 192 | Uncached = static_cast<u8>(Svc::MemoryAttribute::Uncached), |
| 193 | PermissionLocked = static_cast<u8>(Svc::MemoryAttribute::PermissionLocked), | 193 | PermissionLocked = static_cast<u8>(Svc::MemoryAttribute::PermissionLocked), |
| 194 | 194 | ||
| 195 | SetMask = Uncached, | 195 | SetMask = Uncached | PermissionLocked, |
| 196 | }; | 196 | }; |
| 197 | DECLARE_ENUM_FLAG_OPERATORS(KMemoryAttribute); | 197 | DECLARE_ENUM_FLAG_OPERATORS(KMemoryAttribute); |
| 198 | 198 | ||
| @@ -339,6 +339,10 @@ public: | |||
| 339 | return this->GetEndAddress() - 1; | 339 | return this->GetEndAddress() - 1; |
| 340 | } | 340 | } |
| 341 | 341 | ||
| 342 | constexpr KMemoryState GetState() const { | ||
| 343 | return m_memory_state; | ||
| 344 | } | ||
| 345 | |||
| 342 | constexpr u16 GetIpcLockCount() const { | 346 | constexpr u16 GetIpcLockCount() const { |
| 343 | return m_ipc_lock_count; | 347 | return m_ipc_lock_count; |
| 344 | } | 348 | } |
| @@ -456,6 +460,13 @@ public: | |||
| 456 | } | 460 | } |
| 457 | } | 461 | } |
| 458 | 462 | ||
| 463 | constexpr void UpdateAttribute(KMemoryAttribute mask, KMemoryAttribute attr) { | ||
| 464 | ASSERT(False(mask & KMemoryAttribute::IpcLocked)); | ||
| 465 | ASSERT(False(mask & KMemoryAttribute::DeviceShared)); | ||
| 466 | |||
| 467 | m_attribute = (m_attribute & ~mask) | attr; | ||
| 468 | } | ||
| 469 | |||
| 459 | constexpr void Split(KMemoryBlock* block, KProcessAddress addr) { | 470 | constexpr void Split(KMemoryBlock* block, KProcessAddress addr) { |
| 460 | ASSERT(this->GetAddress() < addr); | 471 | ASSERT(this->GetAddress() < addr); |
| 461 | ASSERT(this->Contains(addr)); | 472 | ASSERT(this->Contains(addr)); |
diff --git a/src/core/hle/kernel/k_memory_block_manager.cpp b/src/core/hle/kernel/k_memory_block_manager.cpp index ab75f550e..58a1e7216 100644 --- a/src/core/hle/kernel/k_memory_block_manager.cpp +++ b/src/core/hle/kernel/k_memory_block_manager.cpp | |||
| @@ -160,8 +160,8 @@ void KMemoryBlockManager::Update(KMemoryBlockManagerUpdateAllocator* allocator, | |||
| 160 | } | 160 | } |
| 161 | 161 | ||
| 162 | // Update block state. | 162 | // Update block state. |
| 163 | it->Update(state, perm, attr, cur_address == address, static_cast<u8>(set_disable_attr), | 163 | it->Update(state, perm, attr, it->GetAddress() == address, |
| 164 | static_cast<u8>(clear_disable_attr)); | 164 | static_cast<u8>(set_disable_attr), static_cast<u8>(clear_disable_attr)); |
| 165 | cur_address += cur_info.GetSize(); | 165 | cur_address += cur_info.GetSize(); |
| 166 | remaining_pages -= cur_info.GetNumPages(); | 166 | remaining_pages -= cur_info.GetNumPages(); |
| 167 | } | 167 | } |
| @@ -175,7 +175,9 @@ void KMemoryBlockManager::UpdateIfMatch(KMemoryBlockManagerUpdateAllocator* allo | |||
| 175 | KProcessAddress address, size_t num_pages, | 175 | KProcessAddress address, size_t num_pages, |
| 176 | KMemoryState test_state, KMemoryPermission test_perm, | 176 | KMemoryState test_state, KMemoryPermission test_perm, |
| 177 | KMemoryAttribute test_attr, KMemoryState state, | 177 | KMemoryAttribute test_attr, KMemoryState state, |
| 178 | KMemoryPermission perm, KMemoryAttribute attr) { | 178 | KMemoryPermission perm, KMemoryAttribute attr, |
| 179 | KMemoryBlockDisableMergeAttribute set_disable_attr, | ||
| 180 | KMemoryBlockDisableMergeAttribute clear_disable_attr) { | ||
| 179 | // Ensure for auditing that we never end up with an invalid tree. | 181 | // Ensure for auditing that we never end up with an invalid tree. |
| 180 | KScopedMemoryBlockManagerAuditor auditor(this); | 182 | KScopedMemoryBlockManagerAuditor auditor(this); |
| 181 | ASSERT(Common::IsAligned(GetInteger(address), PageSize)); | 183 | ASSERT(Common::IsAligned(GetInteger(address), PageSize)); |
| @@ -214,7 +216,8 @@ void KMemoryBlockManager::UpdateIfMatch(KMemoryBlockManagerUpdateAllocator* allo | |||
| 214 | } | 216 | } |
| 215 | 217 | ||
| 216 | // Update block state. | 218 | // Update block state. |
| 217 | it->Update(state, perm, attr, false, 0, 0); | 219 | it->Update(state, perm, attr, false, static_cast<u8>(set_disable_attr), |
| 220 | static_cast<u8>(clear_disable_attr)); | ||
| 218 | cur_address += cur_info.GetSize(); | 221 | cur_address += cur_info.GetSize(); |
| 219 | remaining_pages -= cur_info.GetNumPages(); | 222 | remaining_pages -= cur_info.GetNumPages(); |
| 220 | } else { | 223 | } else { |
| @@ -284,6 +287,65 @@ void KMemoryBlockManager::UpdateLock(KMemoryBlockManagerUpdateAllocator* allocat | |||
| 284 | this->CoalesceForUpdate(allocator, address, num_pages); | 287 | this->CoalesceForUpdate(allocator, address, num_pages); |
| 285 | } | 288 | } |
| 286 | 289 | ||
| 290 | void KMemoryBlockManager::UpdateAttribute(KMemoryBlockManagerUpdateAllocator* allocator, | ||
| 291 | KProcessAddress address, size_t num_pages, | ||
| 292 | KMemoryAttribute mask, KMemoryAttribute attr) { | ||
| 293 | // Ensure for auditing that we never end up with an invalid tree. | ||
| 294 | KScopedMemoryBlockManagerAuditor auditor(this); | ||
| 295 | ASSERT(Common::IsAligned(GetInteger(address), PageSize)); | ||
| 296 | |||
| 297 | KProcessAddress cur_address = address; | ||
| 298 | size_t remaining_pages = num_pages; | ||
| 299 | iterator it = this->FindIterator(address); | ||
| 300 | |||
| 301 | while (remaining_pages > 0) { | ||
| 302 | const size_t remaining_size = remaining_pages * PageSize; | ||
| 303 | KMemoryInfo cur_info = it->GetMemoryInfo(); | ||
| 304 | |||
| 305 | if ((it->GetAttribute() & mask) != attr) { | ||
| 306 | // If we need to, create a new block before and insert it. | ||
| 307 | if (cur_info.GetAddress() != GetInteger(cur_address)) { | ||
| 308 | KMemoryBlock* new_block = allocator->Allocate(); | ||
| 309 | |||
| 310 | it->Split(new_block, cur_address); | ||
| 311 | it = m_memory_block_tree.insert(*new_block); | ||
| 312 | it++; | ||
| 313 | |||
| 314 | cur_info = it->GetMemoryInfo(); | ||
| 315 | cur_address = cur_info.GetAddress(); | ||
| 316 | } | ||
| 317 | |||
| 318 | // If we need to, create a new block after and insert it. | ||
| 319 | if (cur_info.GetSize() > remaining_size) { | ||
| 320 | KMemoryBlock* new_block = allocator->Allocate(); | ||
| 321 | |||
| 322 | it->Split(new_block, cur_address + remaining_size); | ||
| 323 | it = m_memory_block_tree.insert(*new_block); | ||
| 324 | |||
| 325 | cur_info = it->GetMemoryInfo(); | ||
| 326 | } | ||
| 327 | |||
| 328 | // Update block state. | ||
| 329 | it->UpdateAttribute(mask, attr); | ||
| 330 | cur_address += cur_info.GetSize(); | ||
| 331 | remaining_pages -= cur_info.GetNumPages(); | ||
| 332 | } else { | ||
| 333 | // If we already have the right attributes, just advance. | ||
| 334 | if (cur_address + remaining_size < cur_info.GetEndAddress()) { | ||
| 335 | remaining_pages = 0; | ||
| 336 | cur_address += remaining_size; | ||
| 337 | } else { | ||
| 338 | remaining_pages = | ||
| 339 | (cur_address + remaining_size - cur_info.GetEndAddress()) / PageSize; | ||
| 340 | cur_address = cur_info.GetEndAddress(); | ||
| 341 | } | ||
| 342 | } | ||
| 343 | it++; | ||
| 344 | } | ||
| 345 | |||
| 346 | this->CoalesceForUpdate(allocator, address, num_pages); | ||
| 347 | } | ||
| 348 | |||
| 287 | // Debug. | 349 | // Debug. |
| 288 | bool KMemoryBlockManager::CheckState() const { | 350 | bool KMemoryBlockManager::CheckState() const { |
| 289 | // Loop over every block, ensuring that we are sorted and coalesced. | 351 | // Loop over every block, ensuring that we are sorted and coalesced. |
diff --git a/src/core/hle/kernel/k_memory_block_manager.h b/src/core/hle/kernel/k_memory_block_manager.h index 96496e990..cb7b6f430 100644 --- a/src/core/hle/kernel/k_memory_block_manager.h +++ b/src/core/hle/kernel/k_memory_block_manager.h | |||
| @@ -115,7 +115,11 @@ public: | |||
| 115 | void UpdateIfMatch(KMemoryBlockManagerUpdateAllocator* allocator, KProcessAddress address, | 115 | void UpdateIfMatch(KMemoryBlockManagerUpdateAllocator* allocator, KProcessAddress address, |
| 116 | size_t num_pages, KMemoryState test_state, KMemoryPermission test_perm, | 116 | size_t num_pages, KMemoryState test_state, KMemoryPermission test_perm, |
| 117 | KMemoryAttribute test_attr, KMemoryState state, KMemoryPermission perm, | 117 | KMemoryAttribute test_attr, KMemoryState state, KMemoryPermission perm, |
| 118 | KMemoryAttribute attr); | 118 | KMemoryAttribute attr, KMemoryBlockDisableMergeAttribute set_disable_attr, |
| 119 | KMemoryBlockDisableMergeAttribute clear_disable_attr); | ||
| 120 | |||
| 121 | void UpdateAttribute(KMemoryBlockManagerUpdateAllocator* allocator, KProcessAddress address, | ||
| 122 | size_t num_pages, KMemoryAttribute mask, KMemoryAttribute attr); | ||
| 119 | 123 | ||
| 120 | iterator FindIterator(KProcessAddress address) const { | 124 | iterator FindIterator(KProcessAddress address) const { |
| 121 | return m_memory_block_tree.find(KMemoryBlock( | 125 | return m_memory_block_tree.find(KMemoryBlock( |
diff --git a/src/core/hle/kernel/k_page_table.cpp b/src/core/hle/kernel/k_page_table.cpp index ebc540316..387f2c962 100644 --- a/src/core/hle/kernel/k_page_table.cpp +++ b/src/core/hle/kernel/k_page_table.cpp | |||
| @@ -505,7 +505,7 @@ Result KPageTable::UnmapCodeMemory(KProcessAddress dst_address, KProcessAddress | |||
| 505 | R_TRY(this->CheckMemoryStateContiguous( | 505 | R_TRY(this->CheckMemoryStateContiguous( |
| 506 | std::addressof(num_dst_allocator_blocks), dst_address, size, KMemoryState::FlagCanCodeAlias, | 506 | std::addressof(num_dst_allocator_blocks), dst_address, size, KMemoryState::FlagCanCodeAlias, |
| 507 | KMemoryState::FlagCanCodeAlias, KMemoryPermission::None, KMemoryPermission::None, | 507 | KMemoryState::FlagCanCodeAlias, KMemoryPermission::None, KMemoryPermission::None, |
| 508 | KMemoryAttribute::All, KMemoryAttribute::None)); | 508 | KMemoryAttribute::All & ~KMemoryAttribute::PermissionLocked, KMemoryAttribute::None)); |
| 509 | 509 | ||
| 510 | // Determine whether any pages being unmapped are code. | 510 | // Determine whether any pages being unmapped are code. |
| 511 | bool any_code_pages = false; | 511 | bool any_code_pages = false; |
| @@ -1770,7 +1770,11 @@ Result KPageTable::MapPhysicalMemory(KProcessAddress address, size_t size) { | |||
| 1770 | m_memory_block_manager.UpdateIfMatch( | 1770 | m_memory_block_manager.UpdateIfMatch( |
| 1771 | std::addressof(allocator), address, size / PageSize, KMemoryState::Free, | 1771 | std::addressof(allocator), address, size / PageSize, KMemoryState::Free, |
| 1772 | KMemoryPermission::None, KMemoryAttribute::None, KMemoryState::Normal, | 1772 | KMemoryPermission::None, KMemoryAttribute::None, KMemoryState::Normal, |
| 1773 | KMemoryPermission::UserReadWrite, KMemoryAttribute::None); | 1773 | KMemoryPermission::UserReadWrite, KMemoryAttribute::None, |
| 1774 | address == this->GetAliasRegionStart() | ||
| 1775 | ? KMemoryBlockDisableMergeAttribute::Normal | ||
| 1776 | : KMemoryBlockDisableMergeAttribute::None, | ||
| 1777 | KMemoryBlockDisableMergeAttribute::None); | ||
| 1774 | 1778 | ||
| 1775 | R_SUCCEED(); | 1779 | R_SUCCEED(); |
| 1776 | } | 1780 | } |
| @@ -1868,6 +1872,13 @@ Result KPageTable::UnmapPhysicalMemory(KProcessAddress address, size_t size) { | |||
| 1868 | 1872 | ||
| 1869 | // Iterate over the memory, unmapping as we go. | 1873 | // Iterate over the memory, unmapping as we go. |
| 1870 | auto it = m_memory_block_manager.FindIterator(cur_address); | 1874 | auto it = m_memory_block_manager.FindIterator(cur_address); |
| 1875 | |||
| 1876 | const auto clear_merge_attr = | ||
| 1877 | (it->GetState() == KMemoryState::Normal && | ||
| 1878 | it->GetAddress() == this->GetAliasRegionStart() && it->GetAddress() == address) | ||
| 1879 | ? KMemoryBlockDisableMergeAttribute::Normal | ||
| 1880 | : KMemoryBlockDisableMergeAttribute::None; | ||
| 1881 | |||
| 1871 | while (true) { | 1882 | while (true) { |
| 1872 | // Check that the iterator is valid. | 1883 | // Check that the iterator is valid. |
| 1873 | ASSERT(it != m_memory_block_manager.end()); | 1884 | ASSERT(it != m_memory_block_manager.end()); |
| @@ -1905,7 +1916,7 @@ Result KPageTable::UnmapPhysicalMemory(KProcessAddress address, size_t size) { | |||
| 1905 | m_memory_block_manager.Update(std::addressof(allocator), address, size / PageSize, | 1916 | m_memory_block_manager.Update(std::addressof(allocator), address, size / PageSize, |
| 1906 | KMemoryState::Free, KMemoryPermission::None, | 1917 | KMemoryState::Free, KMemoryPermission::None, |
| 1907 | KMemoryAttribute::None, KMemoryBlockDisableMergeAttribute::None, | 1918 | KMemoryAttribute::None, KMemoryBlockDisableMergeAttribute::None, |
| 1908 | KMemoryBlockDisableMergeAttribute::None); | 1919 | clear_merge_attr); |
| 1909 | 1920 | ||
| 1910 | // We succeeded. | 1921 | // We succeeded. |
| 1911 | R_SUCCEED(); | 1922 | R_SUCCEED(); |
| @@ -2650,11 +2661,18 @@ Result KPageTable::SetMemoryAttribute(KProcessAddress addr, size_t size, u32 mas | |||
| 2650 | size_t num_allocator_blocks; | 2661 | size_t num_allocator_blocks; |
| 2651 | constexpr auto AttributeTestMask = | 2662 | constexpr auto AttributeTestMask = |
| 2652 | ~(KMemoryAttribute::SetMask | KMemoryAttribute::DeviceShared); | 2663 | ~(KMemoryAttribute::SetMask | KMemoryAttribute::DeviceShared); |
| 2653 | R_TRY(this->CheckMemoryState( | 2664 | const KMemoryState state_test_mask = |
| 2654 | std::addressof(old_state), std::addressof(old_perm), std::addressof(old_attr), | 2665 | static_cast<KMemoryState>(((mask & static_cast<u32>(KMemoryAttribute::Uncached)) |
| 2655 | std::addressof(num_allocator_blocks), addr, size, KMemoryState::FlagCanChangeAttribute, | 2666 | ? static_cast<u32>(KMemoryState::FlagCanChangeAttribute) |
| 2656 | KMemoryState::FlagCanChangeAttribute, KMemoryPermission::None, KMemoryPermission::None, | 2667 | : 0) | |
| 2657 | AttributeTestMask, KMemoryAttribute::None, ~AttributeTestMask)); | 2668 | ((mask & static_cast<u32>(KMemoryAttribute::PermissionLocked)) |
| 2669 | ? static_cast<u32>(KMemoryState::FlagCanPermissionLock) | ||
| 2670 | : 0)); | ||
| 2671 | R_TRY(this->CheckMemoryState(std::addressof(old_state), std::addressof(old_perm), | ||
| 2672 | std::addressof(old_attr), std::addressof(num_allocator_blocks), | ||
| 2673 | addr, size, state_test_mask, state_test_mask, | ||
| 2674 | KMemoryPermission::None, KMemoryPermission::None, | ||
| 2675 | AttributeTestMask, KMemoryAttribute::None, ~AttributeTestMask)); | ||
| 2658 | 2676 | ||
| 2659 | // Create an update allocator. | 2677 | // Create an update allocator. |
| 2660 | Result allocator_result{ResultSuccess}; | 2678 | Result allocator_result{ResultSuccess}; |
| @@ -2662,18 +2680,17 @@ Result KPageTable::SetMemoryAttribute(KProcessAddress addr, size_t size, u32 mas | |||
| 2662 | m_memory_block_slab_manager, num_allocator_blocks); | 2680 | m_memory_block_slab_manager, num_allocator_blocks); |
| 2663 | R_TRY(allocator_result); | 2681 | R_TRY(allocator_result); |
| 2664 | 2682 | ||
| 2665 | // Determine the new attribute. | 2683 | // If we need to, perform a change attribute operation. |
| 2666 | const KMemoryAttribute new_attr = | 2684 | if (True(KMemoryAttribute::Uncached & static_cast<KMemoryAttribute>(mask))) { |
| 2667 | static_cast<KMemoryAttribute>(((old_attr & static_cast<KMemoryAttribute>(~mask)) | | 2685 | // Perform operation. |
| 2668 | static_cast<KMemoryAttribute>(attr & mask))); | 2686 | R_TRY(this->Operate(addr, num_pages, old_perm, |
| 2669 | 2687 | OperationType::ChangePermissionsAndRefreshAndFlush, 0)); | |
| 2670 | // Perform operation. | 2688 | } |
| 2671 | this->Operate(addr, num_pages, old_perm, OperationType::ChangePermissionsAndRefresh); | ||
| 2672 | 2689 | ||
| 2673 | // Update the blocks. | 2690 | // Update the blocks. |
| 2674 | m_memory_block_manager.Update(std::addressof(allocator), addr, num_pages, old_state, old_perm, | 2691 | m_memory_block_manager.UpdateAttribute(std::addressof(allocator), addr, num_pages, |
| 2675 | new_attr, KMemoryBlockDisableMergeAttribute::None, | 2692 | static_cast<KMemoryAttribute>(mask), |
| 2676 | KMemoryBlockDisableMergeAttribute::None); | 2693 | static_cast<KMemoryAttribute>(attr)); |
| 2677 | 2694 | ||
| 2678 | R_SUCCEED(); | 2695 | R_SUCCEED(); |
| 2679 | } | 2696 | } |
| @@ -3086,6 +3103,7 @@ Result KPageTable::Operate(KProcessAddress addr, size_t num_pages, KMemoryPermis | |||
| 3086 | } | 3103 | } |
| 3087 | case OperationType::ChangePermissions: | 3104 | case OperationType::ChangePermissions: |
| 3088 | case OperationType::ChangePermissionsAndRefresh: | 3105 | case OperationType::ChangePermissionsAndRefresh: |
| 3106 | case OperationType::ChangePermissionsAndRefreshAndFlush: | ||
| 3089 | break; | 3107 | break; |
| 3090 | default: | 3108 | default: |
| 3091 | ASSERT(false); | 3109 | ASSERT(false); |
diff --git a/src/core/hle/kernel/k_page_table.h b/src/core/hle/kernel/k_page_table.h index e69498f02..cbcbb6f62 100644 --- a/src/core/hle/kernel/k_page_table.h +++ b/src/core/hle/kernel/k_page_table.h | |||
| @@ -222,7 +222,8 @@ private: | |||
| 222 | Unmap = 3, | 222 | Unmap = 3, |
| 223 | ChangePermissions = 4, | 223 | ChangePermissions = 4, |
| 224 | ChangePermissionsAndRefresh = 5, | 224 | ChangePermissionsAndRefresh = 5, |
| 225 | Separate = 6, | 225 | ChangePermissionsAndRefreshAndFlush = 6, |
| 226 | Separate = 7, | ||
| 226 | }; | 227 | }; |
| 227 | 228 | ||
| 228 | static constexpr KMemoryAttribute DefaultMemoryIgnoreAttr = | 229 | static constexpr KMemoryAttribute DefaultMemoryIgnoreAttr = |
diff --git a/src/core/hle/kernel/svc/svc_memory.cpp b/src/core/hle/kernel/svc/svc_memory.cpp index 2cab74127..372684094 100644 --- a/src/core/hle/kernel/svc/svc_memory.cpp +++ b/src/core/hle/kernel/svc/svc_memory.cpp | |||
| @@ -108,10 +108,16 @@ Result SetMemoryAttribute(Core::System& system, u64 address, u64 size, u32 mask, | |||
| 108 | R_UNLESS((address < address + size), ResultInvalidCurrentMemory); | 108 | R_UNLESS((address < address + size), ResultInvalidCurrentMemory); |
| 109 | 109 | ||
| 110 | // Validate the attribute and mask. | 110 | // Validate the attribute and mask. |
| 111 | constexpr u32 SupportedMask = static_cast<u32>(MemoryAttribute::Uncached); | 111 | constexpr u32 SupportedMask = |
| 112 | static_cast<u32>(MemoryAttribute::Uncached | MemoryAttribute::PermissionLocked); | ||
| 112 | R_UNLESS((mask | attr) == mask, ResultInvalidCombination); | 113 | R_UNLESS((mask | attr) == mask, ResultInvalidCombination); |
| 113 | R_UNLESS((mask | attr | SupportedMask) == SupportedMask, ResultInvalidCombination); | 114 | R_UNLESS((mask | attr | SupportedMask) == SupportedMask, ResultInvalidCombination); |
| 114 | 115 | ||
| 116 | // Check that permission locked is either being set or not masked. | ||
| 117 | R_UNLESS((static_cast<Svc::MemoryAttribute>(mask) & Svc::MemoryAttribute::PermissionLocked) == | ||
| 118 | (static_cast<Svc::MemoryAttribute>(attr) & Svc::MemoryAttribute::PermissionLocked), | ||
| 119 | ResultInvalidCombination); | ||
| 120 | |||
| 115 | // Validate that the region is in range for the current process. | 121 | // Validate that the region is in range for the current process. |
| 116 | auto& page_table{GetCurrentProcess(system.Kernel()).GetPageTable()}; | 122 | auto& page_table{GetCurrentProcess(system.Kernel()).GetPageTable()}; |
| 117 | R_UNLESS(page_table.Contains(address, size), ResultInvalidCurrentMemory); | 123 | R_UNLESS(page_table.Contains(address, size), ResultInvalidCurrentMemory); |