diff options
| -rw-r--r-- | arch/x86_64/include/arch/memory/paging/page_mapper.hpp | 41 | ||||
| -rw-r--r-- | arch/x86_64/include/arch/memory/paging/page_table.hpp | 7 | ||||
| -rw-r--r-- | arch/x86_64/src/memory/paging/page_table.cpp | 5 |
3 files changed, 44 insertions, 9 deletions
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 <algorithm> +#include <array> #include <optional> 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<allocator::FrameAllocator T> + 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<page_table_handle *, 4> 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 @@ -62,6 +62,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 & |
