kern: update KPageTable::Unmap block closing logic

This commit is contained in:
Michael Scire 2021-09-17 16:54:49 -07:00 committed by SciresM
parent 8b49cea4a9
commit 4c73c461f1
3 changed files with 20 additions and 3 deletions

View file

@ -86,6 +86,7 @@ namespace ams::kern {
explicit KPageGroup(KBlockInfoManager *m) : m_block_list(), m_manager(m) { /* ... */ } explicit KPageGroup(KBlockInfoManager *m) : m_block_list(), m_manager(m) { /* ... */ }
~KPageGroup() { this->Finalize(); } ~KPageGroup() { this->Finalize(); }
void CloseAndReset();
void Finalize(); void Finalize();
iterator begin() const { return m_block_list.begin(); } iterator begin() const { return m_block_list.begin(); }

View file

@ -579,7 +579,7 @@ namespace ams::kern::arch::arm64 {
/* Ensure that any pages we track close on exit. */ /* Ensure that any pages we track close on exit. */
KPageGroup pages_to_close(this->GetBlockInfoManager()); KPageGroup pages_to_close(this->GetBlockInfoManager());
ON_SCOPE_EXIT { pages_to_close.Close(); }; ON_SCOPE_EXIT { pages_to_close.CloseAndReset(); };
/* Begin traversal. */ /* Begin traversal. */
TraversalContext context; TraversalContext context;
@ -601,8 +601,9 @@ namespace ams::kern::arch::arm64 {
if (next_entry.block_size > remaining_pages * PageSize) { if (next_entry.block_size > remaining_pages * PageSize) {
MESOSPHERE_ABORT_UNLESS(force); MESOSPHERE_ABORT_UNLESS(force);
MESOSPHERE_R_ABORT_UNLESS(this->SeparatePages(virt_addr, remaining_pages * PageSize, page_list, reuse_ll)); MESOSPHERE_R_ABORT_UNLESS(this->SeparatePages(virt_addr, remaining_pages * PageSize, page_list, reuse_ll));
next_valid = impl.BeginTraversal(std::addressof(next_entry), std::addressof(context), virt_addr); const bool new_valid = impl.BeginTraversal(std::addressof(next_entry), std::addressof(context), virt_addr);
MESOSPHERE_ASSERT(next_valid); MESOSPHERE_ASSERT(new_valid);
MESOSPHERE_UNUSED(new_valid);
} }
/* Check that our state is coherent. */ /* Check that our state is coherent. */
@ -641,6 +642,7 @@ namespace ams::kern::arch::arm64 {
*l1_entry = InvalidL1PageTableEntry; *l1_entry = InvalidL1PageTableEntry;
this->NoteUpdated(); this->NoteUpdated();
this->FreePageTable(page_list, l2_virt); this->FreePageTable(page_list, l2_virt);
pages_to_close.CloseAndReset();
} }
} }
} }
@ -684,6 +686,7 @@ namespace ams::kern::arch::arm64 {
} }
this->FreePageTable(page_list, l3_virt); this->FreePageTable(page_list, l3_virt);
pages_to_close.CloseAndReset();
} }
} }
} }
@ -698,6 +701,7 @@ namespace ams::kern::arch::arm64 {
if (R_FAILED(pages_to_close.AddBlock(block_virt_addr, block_num_pages))) { if (R_FAILED(pages_to_close.AddBlock(block_virt_addr, block_num_pages))) {
this->NoteUpdated(); this->NoteUpdated();
Kernel::GetMemoryManager().Close(block_virt_addr, block_num_pages); Kernel::GetMemoryManager().Close(block_virt_addr, block_num_pages);
pages_to_close.CloseAndReset();
} }
} }

View file

@ -26,6 +26,18 @@ namespace ams::kern {
} }
} }
void KPageGroup::CloseAndReset() {
auto &mm = Kernel::GetMemoryManager();
auto it = m_block_list.begin();
while (it != m_block_list.end()) {
KBlockInfo *info = std::addressof(*it);
it = m_block_list.erase(it);
mm.Close(info->GetAddress(), info->GetNumPages());
m_manager->Free(info);
}
}
size_t KPageGroup::GetNumPages() const { size_t KPageGroup::GetNumPages() const {
size_t num_pages = 0; size_t num_pages = 0;