From 04bd6a059b9eb105024044d74122b0cb76cebf14 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matteo=20Gm=C3=BCr?= Date: Sun, 20 Oct 2024 09:34:03 +0000 Subject: Add translate huge page method --- arch/x86_64/src/memory/paging/page_mapper.cpp | 44 ++++++++++++++++++++++++--- 1 file changed, 40 insertions(+), 4 deletions(-) (limited to 'arch/x86_64/src') diff --git a/arch/x86_64/src/memory/paging/page_mapper.cpp b/arch/x86_64/src/memory/paging/page_mapper.cpp index 5372561..e68bc68 100644 --- a/arch/x86_64/src/memory/paging/page_mapper.cpp +++ b/arch/x86_64/src/memory/paging/page_mapper.cpp @@ -8,7 +8,8 @@ namespace teachos::arch::memory::paging { page_table page_table{}; bool is_valid = false; - auto huge_page = []() -> std::optional { return std::nullopt; }; + + auto huge_page = [&]() -> std::optional {}; for (auto level = page_table::LEVEL4; level != page_table::LEVEL1; level--) { @@ -22,11 +23,46 @@ namespace teachos::arch::memory::paging if (is_valid) { auto level1_index = page.get_level_index(page_table::LEVEL1); - auto frame = page_table[level1_index].calculate_pointed_to_frame(); - return frame; + auto level1_frame = page_table[level1_index].calculate_pointed_to_frame(); + return level1_frame; } - return huge_page(); + return translate_huge_page(page); + } + + auto translate_huge_page(virtual_page page) -> std::optional + { + page_table page_table{}; + bool is_valid = page_table.next_table(page.get_level_index(page_table::LEVEL3)); + + if (is_valid) + { + auto level3_entry = page_table[page.get_level_index(page_table::LEVEL3)]; + auto level3_optional_frame = level3_entry.calculate_pointed_to_frame(); + if (level3_optional_frame.has_value() && level3_entry.contains_flags(entry::HUGE_PAGE)) + { + auto level3_frame = level3_optional_frame.value(); + exception_handling::assert(level3_frame.frame_number % (PAGE_TABLE_ENTRY_COUNT * PAGE_TABLE_ENTRY_COUNT) == 0U, + "[Page Mapper] Physical address must be 1 GiB aligned"); + return allocator::physical_frame{level3_frame.frame_number + + page.get_level_index(page_table::LEVEL2) * PAGE_TABLE_ENTRY_COUNT + + page.get_level_index(page_table::LEVEL1)}; + } + } + is_valid = page_table.next_table(page.get_level_index(page_table::LEVEL3)); + if (is_valid) + { + auto level2_entry = page_table[page.get_level_index(page_table::LEVEL2)]; + auto level2_optional_frame = level2_entry.calculate_pointed_to_frame(); + if (level2_optional_frame.has_value() && level2_entry.contains_flags(entry::HUGE_PAGE)) + { + auto level2_frame = level2_optional_frame.value(); + exception_handling::assert(level2_frame.frame_number % PAGE_TABLE_ENTRY_COUNT == 0U, + "[Page Mapper] Physical address must be 2 MiB aligned"); + return allocator::physical_frame{level2_frame.frame_number + page.get_level_index(page_table::LEVEL1)}; + } + } + return std::nullopt; } auto translate_address(std::size_t virtual_address) -> std::optional -- cgit v1.2.3