From 4c4479a4b728fd7eaf007649e946f9435ee1e402 Mon Sep 17 00:00:00 2001 From: Fabian Imhof Date: Tue, 29 Oct 2024 07:32:24 +0000 Subject: implement page_table unmapping --- .../include/arch/memory/paging/page_mapper.hpp | 41 +++++++++++++++++----- .../include/arch/memory/paging/page_table.hpp | 7 ++++ arch/x86_64/src/memory/paging/page_table.cpp | 5 ++- 3 files changed, 44 insertions(+), 9 deletions(-) (limited to 'arch') diff --git a/arch/x86_64/include/arch/memory/paging/page_mapper.hpp b/arch/x86_64/include/arch/memory/paging/page_mapper.hpp index 0ef552a..801ccfb 100644 --- a/arch/x86_64/include/arch/memory/paging/page_mapper.hpp +++ b/arch/x86_64/include/arch/memory/paging/page_mapper.hpp @@ -5,6 +5,8 @@ #include "arch/memory/allocator/area_frame_allocator.hpp" #include "arch/memory/paging/virtual_page.hpp" +#include +#include #include namespace teachos::arch::memory::paging @@ -22,6 +24,28 @@ namespace teachos::arch::memory::paging { asm volatile("invlpg (%0)" ::"r"(address) : "memory"); } + + /** + * @brief Unmaps specific page at the current internal handle level. + * + * @tparam T Type constraint of the allocator, being that is follows the given concept and contains an allocate and + * deallocate method. + * @param allocator Reference to an allocator following the FrameAllocator concept, which is used to allocate + * entries *when a new page table is required. + * @param page Virtual page that is being unmapped. + * @param handle Page Table handle we want to access the entry that should be cleared on. + */ + template + auto unmap_page_table_entry(T & allocator, virtual_page page, page_table_handle & handle) -> void + { + auto level_index = page.get_level_index(handle.get_level()); + auto & entry = handle[level_index]; + auto const frame = entry.calculate_pointed_to_frame(); + exception_handling::assert(frame.has_value(), + "[Page Mapper] Attempted to unmap page, which has not been mapped previously"); + entry.set_unused(); + allocator.deallocate_frame(frame.value()); + } } // namespace /** @@ -135,8 +159,12 @@ namespace teachos::arch::memory::paging auto current_handle = create_or_get(); + std::array handles{}; + for (auto level = page_table_handle::LEVEL4; level != page_table_handle::LEVEL1; --level) { + handles[level] = *current_handle; + auto const level_index = page.get_level_index(level); auto const next_handle = current_handle.next_table(level_index); // The next table method failed even tough the page has to be mapped already, because translate_page did not fail. @@ -145,14 +173,11 @@ namespace teachos::arch::memory::paging current_handle = next_handle.value(); } - auto & level1_entry = current_handle[page.get_level_index(page_table_handle::LEVEL1)]; - auto const level1_frame = level1_entry.calculate_pointed_to_frame(); - exception_handling::assert(level1_frame.has_value(), - "[Page Mapper] Attempted to unmap page, which has not been mapped previously"); - level1_entry.set_unused(); - // TODO: Deallocate and unmap level 1, 2, 3 page table entry if this was the last page in them. - // TODO: Fix deallocate because it is not yet implemented. - allocator.deallocate_frame(level1_frame.value()); + std::ranges::for_each(handles, [&allocator, page](page_table_handle * handle) { + exception_handling::assert(handle != nullptr, "[Page Mapper] Attempted to unmap page behind nullpointer"); + unmap_page_table_entry(allocator, page, *handle); + }); + invalidate_page_cache(page.start_address()); } } // namespace teachos::arch::memory::paging diff --git a/arch/x86_64/include/arch/memory/paging/page_table.hpp b/arch/x86_64/include/arch/memory/paging/page_table.hpp index 07e7e22..02ed099 100644 --- a/arch/x86_64/include/arch/memory/paging/page_table.hpp +++ b/arch/x86_64/include/arch/memory/paging/page_table.hpp @@ -61,6 +61,13 @@ namespace teachos::arch::memory::paging */ auto is_empty() const -> bool; + /** + * @brief Get the current handle level. + * + * @return Current handle level. + */ + auto get_level() const -> level; + /** * @brief Returns the next page table level from the given page table index. Meaning we * use an index into a Level 4 page table to get the according Level 3 page table. diff --git a/arch/x86_64/src/memory/paging/page_table.cpp b/arch/x86_64/src/memory/paging/page_table.cpp index 64a4fd9..0121e95 100644 --- a/arch/x86_64/src/memory/paging/page_table.cpp +++ b/arch/x86_64/src/memory/paging/page_table.cpp @@ -92,7 +92,8 @@ namespace teachos::arch::memory::paging : handle(handle) , handle_level(handle_level) { - exception_handling::assert(handle, "[Page Table] Attempted to pass nullptr as handle to page table handle method"); + exception_handling::assert(handle != nullptr, + "[Page Table] Attempted to pass nullptr as handle to page table handle method"); } auto page_table_handle::initialize_page_tables() -> void @@ -133,6 +134,8 @@ namespace teachos::arch::memory::paging return std::nullopt; } + auto page_table_handle::get_level() const -> page_table_handle::level { return handle_level; } + auto page_table_handle::operator[](std::size_t index) -> entry & { return handle->operator[](index); } auto operator--(page_table_handle::level & value) -> page_table_handle::level & -- cgit v1.2.3