kern: update KPageTable::Unmap block closing logic

This commit is contained in:
Michael Scire 2021-09-17 16:54:49 -07:00
parent 62fe20693e
commit ecd2392ff4
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) { /* ... */ }
~KPageGroup() { this->Finalize(); }
void CloseAndReset();
void Finalize();
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. */
KPageGroup pages_to_close(this->GetBlockInfoManager());
ON_SCOPE_EXIT { pages_to_close.Close(); };
ON_SCOPE_EXIT { pages_to_close.CloseAndReset(); };
/* Begin traversal. */
TraversalContext context;
@ -601,8 +601,9 @@ namespace ams::kern::arch::arm64 {
if (next_entry.block_size > remaining_pages * PageSize) {
MESOSPHERE_ABORT_UNLESS(force);
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);
MESOSPHERE_ASSERT(next_valid);
const bool new_valid = impl.BeginTraversal(std::addressof(next_entry), std::addressof(context), virt_addr);
MESOSPHERE_ASSERT(new_valid);
MESOSPHERE_UNUSED(new_valid);
}
/* Check that our state is coherent. */
@ -641,6 +642,7 @@ namespace ams::kern::arch::arm64 {
*l1_entry = InvalidL1PageTableEntry;
this->NoteUpdated();
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);
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))) {
this->NoteUpdated();
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 num_pages = 0;