aboutsummaryrefslogtreecommitdiff
path: root/arch/x86_64/src
diff options
context:
space:
mode:
authorMatteo Gmür <matteo.gmuer1@ost.ch>2024-10-20 09:34:03 +0000
committerMatteo Gmür <matteo.gmuer1@ost.ch>2024-10-20 09:34:03 +0000
commit04bd6a059b9eb105024044d74122b0cb76cebf14 (patch)
tree69f9c12d0da0cbb1d3f4fcabeb0872d30cff1cf4 /arch/x86_64/src
parent1d157101eb550f99dac9ec943053f85bbf6c7644 (diff)
downloadteachos-04bd6a059b9eb105024044d74122b0cb76cebf14.tar.xz
teachos-04bd6a059b9eb105024044d74122b0cb76cebf14.zip
Add translate huge page method
Diffstat (limited to 'arch/x86_64/src')
-rw-r--r--arch/x86_64/src/memory/paging/page_mapper.cpp44
1 files changed, 40 insertions, 4 deletions
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>