aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--arch/x86_64/include/arch/memory/paging/page_mapper.hpp21
-rw-r--r--arch/x86_64/src/memory/paging/page_mapper.cpp44
2 files changed, 55 insertions, 10 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 b151a7f..ad9db52 100644
--- a/arch/x86_64/include/arch/memory/paging/page_mapper.hpp
+++ b/arch/x86_64/include/arch/memory/paging/page_mapper.hpp
@@ -8,18 +8,27 @@
namespace teachos::arch::memory::paging
{
/**
- * @brief Translate page into physical_frame
+ * @brief Translates page into physical frame, will first attempt to parse normally using default page size and if it
+ * failed attempt to parse using huge pages.
*
- * @param page Page to translate into physical_frame
- * @return Physical frame corresponding to the provided page_table
+ * @param page Page to translate into physical frame.
+ * @return Physical frame corresponding to the provided virtual page.
*/
auto translate_page(virtual_page page) -> std::optional<allocator::physical_frame>;
/**
- * @brief Translate virtual into phyical address
+ * @brief Translates huge page into actual physical frame.
*
- * @param virtual_address Address to translate into physical
- * @return Physical address
+ * @param page Page to translate into physical frame.
+ * @return Physical frame corresponding to the provided virtual page.
+ */
+ auto translate_huge_page(virtual_page page) -> std::optional<allocator::physical_frame>;
+
+ /**
+ * @brief Translate virtual into phyical address.
+ *
+ * @param virtual_address Address to translate into physical.
+ * @return Physical address.
*/
auto translate_address(std::size_t virtual_address) -> std::optional<std::size_t>;
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<allocator::physical_frame> { return std::nullopt; };
+
+ auto huge_page = [&]() -> std::optional<allocator::physical_frame> {};
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<allocator::physical_frame>
+ {
+ 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<std::size_t>