From 2f241e1b61318a8e58e619a774df6ec08285fd4a Mon Sep 17 00:00:00 2001 From: Bananymous Date: Thu, 5 Sep 2024 13:59:09 +0300 Subject: [PATCH] Kernel: Implement FileBackedRegion::clone --- kernel/kernel/Memory/FileBackedRegion.cpp | 34 +++++++++++++++++++++-- 1 file changed, 32 insertions(+), 2 deletions(-) diff --git a/kernel/kernel/Memory/FileBackedRegion.cpp b/kernel/kernel/Memory/FileBackedRegion.cpp index c6718d5c..d4abd8d4 100644 --- a/kernel/kernel/Memory/FileBackedRegion.cpp +++ b/kernel/kernel/Memory/FileBackedRegion.cpp @@ -189,9 +189,39 @@ namespace Kernel return true; } - BAN::ErrorOr> FileBackedRegion::clone(PageTable&) + BAN::ErrorOr> 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(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(PAGE_SIZE, m_size - offset); + PageTable::with_fast_page(paddr, [&] { + memcpy(PageTable::fast_page_as_ptr(), reinterpret_cast(vaddr), to_copy); + memset(PageTable::fast_page_as_ptr(to_copy), 0, PAGE_SIZE - to_copy); + }); + } + + return BAN::UniqPtr(BAN::move(result)); } }