From a96b1b4b43a1ed962b412c3d28db0fe00661d96f Mon Sep 17 00:00:00 2001 From: Felix Morgner Date: Tue, 2 Dec 2025 18:40:10 +0100 Subject: x86_64/memory: extract PML4 injection --- arch/x86_64/src/memory/scoped_mapping.cpp | 77 +++++++++++++++++++++++++------ 1 file changed, 64 insertions(+), 13 deletions(-) (limited to 'arch/x86_64/src/memory/scoped_mapping.cpp') diff --git a/arch/x86_64/src/memory/scoped_mapping.cpp b/arch/x86_64/src/memory/scoped_mapping.cpp index 27c4785..602198e 100644 --- a/arch/x86_64/src/memory/scoped_mapping.cpp +++ b/arch/x86_64/src/memory/scoped_mapping.cpp @@ -4,25 +4,28 @@ #include "kapi/system.hpp" #include "x86_64/memory/mmu.hpp" +#include "x86_64/memory/page_table.hpp" +#include "x86_64/memory/page_utilities.hpp" #include "x86_64/memory/paging_root.hpp" +#include #include namespace teachos::memory::x86_64 { scoped_mapping::scoped_mapping(scoped_mapping && other) - : m_address{std::exchange(other.m_address, linear_address{})} + : m_page{std::exchange(other.m_page, page{})} , m_allocator{std::exchange(other.m_allocator, nullptr)} , m_mapped{std::exchange(other.m_mapped, false)} {} - scoped_mapping::scoped_mapping(linear_address address, frame_allocator & allocator) - : m_address{address} + scoped_mapping::scoped_mapping(page page, frame_allocator & allocator) + : m_page{page} , m_allocator{&allocator} , m_mapped{false} { - if (paging_root::get().translate(address)) + if (paging_root::get().translate(page)) { system::panic("[MEM] Tried to map a page that is already mapped!"); } @@ -33,7 +36,7 @@ namespace teachos::memory::x86_64 if (m_mapped) { unmap(); - x86_64::tlb_flush(m_address); + x86_64::tlb_flush(m_page.start_address()); } } @@ -46,7 +49,7 @@ namespace teachos::memory::x86_64 using std::swap; - swap(m_address, other.m_address); + swap(m_page, other.m_page); swap(m_allocator, other.m_allocator); swap(m_mapped, other.m_mapped); @@ -55,12 +58,38 @@ namespace teachos::memory::x86_64 auto scoped_mapping::map(frame frame, page_table::entry::flags flags) -> std::byte * { - static_cast(frame); - static_cast(flags); + auto & pml4 = paging_root::get(); + auto pml4_index = pml_index<4>(m_page); + if (!pml4[pml4_index].present()) + { + auto new_frame = m_allocator->allocate(); + pml4[pml4_index].frame(*new_frame, page_table::entry::flags::present | flags); + std::construct_at(pml4.next(pml4_index).value()); + } - m_mapped = true; + auto pml3 = pml4.next(pml4_index).value(); + auto pml3_index = pml_index<3>(m_page); + if (!(*pml3)[pml3_index].present()) + { + auto new_frame = m_allocator->allocate(); + (*pml3)[pml3_index].frame(*new_frame, page_table::entry::flags::present | flags); + std::construct_at((*pml3).next(pml3_index).value()); + } - return nullptr; + auto pml2 = (*pml3).next(pml3_index).value(); + auto pml2_index = pml_index<2>(m_page); + if (!(*pml2)[pml2_index].present()) + { + auto new_frame = m_allocator->allocate(); + (*pml2)[pml2_index].frame(*new_frame, page_table::entry::flags::present | flags); + std::construct_at((*pml2).next(pml2_index).value()); + } + + auto pml1 = (*pml2).next(pml2_index).value(); + auto pml1_index = pml_index<1>(m_page); + (*pml1)[pml1_index].frame(frame, page_table::entry::flags::present | flags); + + return static_cast(frame.start_address()); } auto scoped_mapping::unmap() -> void @@ -70,9 +99,31 @@ namespace teachos::memory::x86_64 system::panic("[MEM] Tried to release an unmapped temporary mapping!"); } - // TODO: scan pages - // TODO: remove mapping - // TODO: release temporary table frames + auto pml3 = paging_root::get().next(pml_index<4>(m_page)).value(); + auto pml2 = pml3->next(pml_index<3>(m_page)).value(); + auto pml1 = pml2->next(pml_index<2>(m_page)).value(); + + auto pml1_entry = (*pml1)[pml_index<1>(m_page)]; + (*pml1)[pml_index<1>(m_page)].clear(); + if (pml1->empty()) + { + m_allocator->release(pml1_entry.frame().value()); + } + + auto pml2_entry = (*pml2)[pml_index<2>(m_page)]; + (*pml2)[pml_index<2>(m_page)].clear(); + if (pml2->empty()) + { + m_allocator->release(pml2_entry.frame().value()); + } + + auto pml3_entry = (*pml3)[pml_index<3>(m_page)]; + (*pml3)[pml_index<3>(m_page)].clear(); + if (pml3->empty()) + { + m_allocator->release(pml3_entry.frame().value()); + } + m_mapped = false; } -- cgit v1.2.3