Kernel: Implement FileBackedRegion::clone

This commit is contained in:
Bananymous 2024-09-05 13:59:09 +03:00
parent 6affef76b1
commit 2f241e1b61
1 changed files with 32 additions and 2 deletions

View File

@ -189,9 +189,39 @@ namespace Kernel
return true; return true;
} }
BAN::ErrorOr<BAN::UniqPtr<MemoryRegion>> FileBackedRegion::clone(PageTable&) BAN::ErrorOr<BAN::UniqPtr<MemoryRegion>> FileBackedRegion::clone(PageTable& page_table)
{ {
ASSERT_NOT_REACHED(); const size_t aligned_size = (m_size + PAGE_SIZE - 1) & PAGE_ADDR_MASK;
auto result = TRY(FileBackedRegion::create(m_inode, page_table, m_offset, m_size, { .start = m_vaddr, .end = m_vaddr + aligned_size }, m_type, m_flags));
// shared regions can just go through demand paging
if (m_type == Type::SHARED)
return BAN::UniqPtr<MemoryRegion>(BAN::move(result));
ASSERT(m_type == Type::PRIVATE);
for (size_t offset = 0; offset < m_size; offset += PAGE_SIZE)
{
const vaddr_t vaddr = m_vaddr + offset;
if (m_page_table.physical_address_of(vaddr) == 0)
continue;
ASSERT(&PageTable::current() == &m_page_table);
const paddr_t paddr = Heap::get().take_free_page();
if (paddr == 0)
return BAN::Error::from_errno(ENOMEM);
page_table.map_page_at(paddr, vaddr, m_flags);
const size_t to_copy = BAN::Math::min<size_t>(PAGE_SIZE, m_size - offset);
PageTable::with_fast_page(paddr, [&] {
memcpy(PageTable::fast_page_as_ptr(), reinterpret_cast<void*>(vaddr), to_copy);
memset(PageTable::fast_page_as_ptr(to_copy), 0, PAGE_SIZE - to_copy);
});
}
return BAN::UniqPtr<MemoryRegion>(BAN::move(result));
} }
} }