diff --git a/libraries/libmesosphere/include/mesosphere/kern_k_page_table_base.hpp b/libraries/libmesosphere/include/mesosphere/kern_k_page_table_base.hpp index 3bdfe1776..06d735504 100644 --- a/libraries/libmesosphere/include/mesosphere/kern_k_page_table_base.hpp +++ b/libraries/libmesosphere/include/mesosphere/kern_k_page_table_base.hpp @@ -57,11 +57,26 @@ namespace ams::kern { using TraversalEntry = KPageTableImpl::TraversalEntry; using TraversalContext = KPageTableImpl::TraversalContext; - struct MemoryRange { - KPhysicalAddress address; - size_t size; + class MemoryRange { + private: + KPhysicalAddress m_address; + size_t m_size; + bool m_heap; + public: + constexpr MemoryRange() : m_address(Null), m_size(0), m_heap(false) { /* ... */ } - void Close(); + void Set(KPhysicalAddress address, size_t size, bool heap) { + m_address = address; + m_size = size; + m_heap = heap; + } + + constexpr KPhysicalAddress GetAddress() const { return m_address; } + constexpr size_t GetSize() const { return m_size; } + constexpr bool IsHeap() const { return m_heap; } + + void Open(); + void Close(); }; protected: enum MemoryFillValue { diff --git a/libraries/libmesosphere/source/board/nintendo/nx/kern_k_device_page_table.cpp b/libraries/libmesosphere/source/board/nintendo/nx/kern_k_device_page_table.cpp index 0f09886dc..f70bcbb97 100644 --- a/libraries/libmesosphere/source/board/nintendo/nx/kern_k_device_page_table.cpp +++ b/libraries/libmesosphere/source/board/nintendo/nx/kern_k_device_page_table.cpp @@ -1133,17 +1133,17 @@ namespace ams::kern::board::nintendo::nx { size_t cur_size; { /* Get the current contiguous range. */ - KPageTableBase::MemoryRange contig_range = { .address = Null, .size = 0 }; + KPageTableBase::MemoryRange contig_range; R_TRY(page_table->OpenMemoryRangeForMapDeviceAddressSpace(std::addressof(contig_range), process_address + mapped_size, size - mapped_size, ConvertToKMemoryPermission(device_perm), is_aligned)); /* Ensure we close the range when we're done. */ ON_SCOPE_EXIT { contig_range.Close(); }; /* Get the current size. */ - cur_size = contig_range.size; + cur_size = contig_range.GetSize(); /* Map the device page. */ - R_TRY(this->MapDevicePage(contig_range.address, contig_range.size, cur_addr, device_perm)); + R_TRY(this->MapDevicePage(contig_range.GetAddress(), cur_size, cur_addr, device_perm)); } /* Advance. */ @@ -1288,7 +1288,7 @@ namespace ams::kern::board::nintendo::nx { MESOSPHERE_ASSERT(((device_address + size - 1) & ~DeviceVirtualAddressMask) == 0); /* We need to traverse the ranges that make up our mapping, to make sure they're all good. Start by getting a contiguous range. */ - KPageTableBase::MemoryRange contig_range = { .address = Null, .size = 0 }; + KPageTableBase::MemoryRange contig_range; if (R_FAILED(page_table->OpenMemoryRangeForUnmapDeviceAddressSpace(std::addressof(contig_range), process_address, size))) { return false; } @@ -1300,8 +1300,8 @@ namespace ams::kern::board::nintendo::nx { /* Walk the directory. */ KProcessAddress cur_process_address = process_address; size_t remaining_size = size; - KPhysicalAddress cur_phys_address = contig_range.address; - size_t remaining_in_range = contig_range.size; + KPhysicalAddress cur_phys_address = contig_range.GetAddress(); + size_t remaining_in_range = contig_range.GetSize(); bool first = true; u32 first_attr = 0; while (remaining_size > 0) { @@ -1347,8 +1347,8 @@ namespace ams::kern::board::nintendo::nx { } range_open = true; - cur_phys_address = contig_range.address; - remaining_in_range = contig_range.size; + cur_phys_address = contig_range.GetAddress(); + remaining_in_range = contig_range.GetSize(); } /* Check that the physical address is expected. */ @@ -1390,8 +1390,8 @@ namespace ams::kern::board::nintendo::nx { } range_open = true; - cur_phys_address = contig_range.address; - remaining_in_range = contig_range.size; + cur_phys_address = contig_range.GetAddress(); + remaining_in_range = contig_range.GetSize(); } /* Check that the physical address is expected, and there's enough in the range. */ diff --git a/libraries/libmesosphere/source/kern_k_page_table_base.cpp b/libraries/libmesosphere/source/kern_k_page_table_base.cpp index 46e23435c..06aa158c6 100644 --- a/libraries/libmesosphere/source/kern_k_page_table_base.cpp +++ b/libraries/libmesosphere/source/kern_k_page_table_base.cpp @@ -74,8 +74,18 @@ namespace ams::kern { } + void KPageTableBase::MemoryRange::Open() { + /* If the range contains heap pages, open them. */ + if (this->IsHeap()) { + Kernel::GetMemoryManager().Open(this->GetAddress(), this->GetSize() / PageSize); + } + } + void KPageTableBase::MemoryRange::Close() { - Kernel::GetMemoryManager().Close(address, size / PageSize); + /* If the range contains heap pages, close them. */ + if (this->IsHeap()) { + Kernel::GetMemoryManager().Close(this->GetAddress(), this->GetSize() / PageSize); + } } Result KPageTableBase::InitializeForKernel(bool is_64_bit, void *table, KVirtualAddress start, KVirtualAddress end) { @@ -1504,16 +1514,13 @@ namespace ams::kern { /* Check that the memory is contiguous (modulo the reference count bit). */ const u32 test_state_mask = state_mask | KMemoryState_FlagReferenceCounted; - if (R_FAILED(this->CheckMemoryStateContiguous(address, size, test_state_mask, state | KMemoryState_FlagReferenceCounted, perm_mask, perm, attr_mask, attr))) { + const bool is_heap = R_SUCCEEDED(this->CheckMemoryStateContiguous(address, size, test_state_mask, state | KMemoryState_FlagReferenceCounted, perm_mask, perm, attr_mask, attr)); + if (!is_heap) { R_TRY(this->CheckMemoryStateContiguous(address, size, test_state_mask, state, perm_mask, perm, attr_mask, attr)); } /* The memory is contiguous, so set the output range. */ - *out = { - .address = phys_address, - .size = size, - }; - + out->Set(phys_address, size, is_heap); R_SUCCEED(); } @@ -2932,7 +2939,7 @@ namespace ams::kern { KMemoryAttribute_IpcLocked | KMemoryAttribute_Locked, KMemoryAttribute_None)); /* We got the range, so open it. */ - Kernel::GetMemoryManager().Open(out->address, out->size / PageSize); + out->Open(); R_SUCCEED(); } @@ -2949,7 +2956,7 @@ namespace ams::kern { KMemoryAttribute_DeviceShared | KMemoryAttribute_Locked, KMemoryAttribute_DeviceShared)); /* We got the range, so open it. */ - Kernel::GetMemoryManager().Open(out->address, out->size / PageSize); + out->Open(); R_SUCCEED(); } @@ -3020,7 +3027,7 @@ namespace ams::kern { KMemoryAttribute_Uncached, KMemoryAttribute_None)); /* We got the range, so open it. */ - Kernel::GetMemoryManager().Open(out->address, out->size / PageSize); + out->Open(); R_SUCCEED(); } diff --git a/libraries/libmesosphere/source/svc/kern_svc_cache.cpp b/libraries/libmesosphere/source/svc/kern_svc_cache.cpp index 6b5e0ea99..62997b50b 100644 --- a/libraries/libmesosphere/source/svc/kern_svc_cache.cpp +++ b/libraries/libmesosphere/source/svc/kern_svc_cache.cpp @@ -36,15 +36,15 @@ namespace ams::kern::svc { size_t remaining = size; while (remaining > 0) { /* Get a contiguous range to operate on. */ - KPageTableBase::MemoryRange contig_range = { .address = Null, .size = 0 }; + KPageTableBase::MemoryRange contig_range; R_TRY(page_table.OpenMemoryRangeForProcessCacheOperation(std::addressof(contig_range), cur_address, aligned_end - cur_address)); /* Close the range when we're done operating on it. */ ON_SCOPE_EXIT { contig_range.Close(); }; /* Adjust to remain within range. */ - KVirtualAddress operate_address = KMemoryLayout::GetLinearVirtualAddress(contig_range.address); - size_t operate_size = contig_range.size; + KVirtualAddress operate_address = KMemoryLayout::GetLinearVirtualAddress(contig_range.GetAddress()); + size_t operate_size = contig_range.GetSize(); if (cur_address < address) { operate_address += (address - cur_address); operate_size -= (address - cur_address); @@ -57,7 +57,7 @@ namespace ams::kern::svc { operation.Operate(GetVoidPointer(operate_address), operate_size); /* Advance. */ - cur_address += contig_range.size; + cur_address += contig_range.GetSize(); remaining -= operate_size; } MESOSPHERE_ASSERT(remaining == 0);