aboutsummaryrefslogtreecommitdiff
path: root/arch/x86_64/src
diff options
context:
space:
mode:
authorMatteo Gmür <matteo.gmuer1@ost.ch>2024-10-21 12:53:23 +0000
committerMatteo Gmür <matteo.gmuer1@ost.ch>2024-10-21 12:53:23 +0000
commit552477a12a1163f0f80801b4055dcb5ab3f79e3e (patch)
tree9cd8f8b02bf8a9208be3a836f4b077c407e35e9c /arch/x86_64/src
parent4b6e66f686a0341613a303b45e16e5bc744c32dd (diff)
downloadteachos-552477a12a1163f0f80801b4055dcb5ab3f79e3e.tar.xz
teachos-552477a12a1163f0f80801b4055dcb5ab3f79e3e.zip
Use forward declaration to hide actual page_table
Diffstat (limited to 'arch/x86_64/src')
-rw-r--r--arch/x86_64/src/memory/paging/page_mapper.cpp21
-rw-r--r--arch/x86_64/src/memory/paging/page_table.cpp63
-rw-r--r--arch/x86_64/src/memory/paging/virtual_page.cpp2
3 files changed, 65 insertions, 21 deletions
diff --git a/arch/x86_64/src/memory/paging/page_mapper.cpp b/arch/x86_64/src/memory/paging/page_mapper.cpp
index 28e248b..b8f6b89 100644
--- a/arch/x86_64/src/memory/paging/page_mapper.cpp
+++ b/arch/x86_64/src/memory/paging/page_mapper.cpp
@@ -11,14 +11,14 @@ namespace teachos::arch::memory::paging
{
static page_table * const active_page{reinterpret_cast<page_table *>(PAGE_TABLE_LEVEL_4_ADDRESS)};
// We can not save page_table_handle as a static variable directly, if we do the program will fail to link.
- return page_table_handle{active_page, page_table::LEVEL4};
+ return page_table_handle{active_page, page_table_handle::LEVEL4};
}
auto translate_page(virtual_page page) -> std::optional<allocator::physical_frame>
{
auto current_handle = create_or_get();
- for (auto level = page_table::LEVEL4; level != page_table::LEVEL1; level--)
+ for (auto level = page_table_handle::LEVEL4; level != page_table_handle::LEVEL1; level--)
{
auto next_handle = current_handle.next_table(page.get_level_index(level));
// If the next table method failed then it is highly likely that it was a huge page and we therefore have to parse
@@ -30,7 +30,7 @@ namespace teachos::arch::memory::paging
current_handle = next_handle.value();
}
- auto level1_index = page.get_level_index(page_table::LEVEL1);
+ auto level1_index = page.get_level_index(page_table_handle::LEVEL1);
auto level1_frame = current_handle[level1_index].calculate_pointed_to_frame();
return level1_frame;
}
@@ -38,14 +38,14 @@ namespace teachos::arch::memory::paging
auto translate_huge_page(virtual_page page) -> std::optional<allocator::physical_frame>
{
auto current_handle = create_or_get();
- auto level3_handle = current_handle.next_table(page.get_level_index(page_table::LEVEL4));
+ auto level3_handle = current_handle.next_table(page.get_level_index(page_table_handle::LEVEL4));
if (!level3_handle)
{
return std::nullopt;
}
- auto level3_entry = level3_handle.value()[page.get_level_index(page_table::LEVEL3)];
+ auto level3_entry = level3_handle.value()[page.get_level_index(page_table_handle::LEVEL3)];
auto level3_frame = level3_entry.calculate_pointed_to_frame();
if (level3_frame && level3_entry.contains_flags(entry::HUGE_PAGE))
{
@@ -53,20 +53,21 @@ namespace teachos::arch::memory::paging
level3_frame.value().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.value().frame_number +
- page.get_level_index(page_table::LEVEL2) * PAGE_TABLE_ENTRY_COUNT +
- page.get_level_index(page_table::LEVEL1)};
+ page.get_level_index(page_table_handle::LEVEL2) * PAGE_TABLE_ENTRY_COUNT +
+ page.get_level_index(page_table_handle::LEVEL1)};
}
- auto level2_handle = level3_handle.value().next_table(page.get_level_index(page_table::LEVEL3));
+ auto level2_handle = level3_handle.value().next_table(page.get_level_index(page_table_handle::LEVEL3));
if (level2_handle)
{
- auto level2_entry = level2_handle.value()[page.get_level_index(page_table::LEVEL2)];
+ auto level2_entry = level2_handle.value()[page.get_level_index(page_table_handle::LEVEL2)];
auto level2_frame = level2_entry.calculate_pointed_to_frame();
if (level2_frame && level2_entry.contains_flags(entry::HUGE_PAGE))
{
exception_handling::assert(level2_frame.value().frame_number % PAGE_TABLE_ENTRY_COUNT == 0U,
"[Page Mapper] Physical address must be 2 MiB aligned");
- return allocator::physical_frame{level2_frame.value().frame_number + page.get_level_index(page_table::LEVEL1)};
+ return allocator::physical_frame{level2_frame.value().frame_number +
+ page.get_level_index(page_table_handle::LEVEL1)};
}
}
return std::nullopt;
diff --git a/arch/x86_64/src/memory/paging/page_table.cpp b/arch/x86_64/src/memory/paging/page_table.cpp
index 907b64f..852bbd5 100644
--- a/arch/x86_64/src/memory/paging/page_table.cpp
+++ b/arch/x86_64/src/memory/paging/page_table.cpp
@@ -4,6 +4,57 @@
namespace teachos::arch::memory::paging
{
+ /**
+ * @brief A Page table containing 512 entries.
+ */
+ struct page_table
+ {
+ /**
+ * @brief Set every entry of the page to unused.
+ */
+ auto zero_entries() -> void;
+
+ /**
+ * @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. This method should not be called
+ * on a Level 1 page table, because there is no furthere page table and mangeling up and returning the physical
+ * address would cause hard to debug issues.
+ *
+ * @param table_index Index of this page table in the page table one level lower.
+ */
+ auto next_table(std::size_t table_index) const -> std::optional<page_table *>;
+
+ /**
+ * @brief Index operator overload to access specific entries directy.
+ *
+ * @param index Index of the entry we want to access and read or write too.
+ * @return Entry at the given table index.
+ */
+ auto operator[](std::size_t index) const -> entry;
+
+ private:
+ /**
+ * @brief Calculates the address of the next page table level for the given table index. The next page table address
+ * is only valid if the corresponding entry is present and not a huge page. Meaning we use an index into a
+ * Level 4 page table to get the according Level 3 page table address.
+ *
+ * @param table_index Index of this page table in the page table one level higher.
+ * @return An optional of the address of the next page table or null.
+ */
+ auto next_table_address(std::size_t table_index) const -> std::optional<std::size_t>;
+
+ entry entries[PAGE_TABLE_ENTRY_COUNT]; ///< Entries containing addresses to page tables of a level below or actual
+ ///< virtual addresses for the level 1 page table.
+ };
+
+ auto operator--(page_table_handle::level level, int) -> page_table_handle::level
+ {
+ exception_handling::assert(level != page_table_handle::LEVEL1,
+ "[Page table] Attemptd to decrement enum to value outside of range");
+ auto value = static_cast<std::underlying_type<page_table_handle::level>::type>(level);
+ return static_cast<page_table_handle::level>(--value);
+ }
+
auto page_table::zero_entries() -> void
{
constexpr size_t entry_amount = sizeof(entries) / sizeof(entries[0]);
@@ -44,15 +95,7 @@ namespace teachos::arch::memory::paging
return std::nullopt;
}
- auto operator--(page_table::level level, int) -> page_table::level
- {
- exception_handling::assert(level != page_table::LEVEL1,
- "[Page table] Attemptd to decrement enum to value outside of range");
- auto value = static_cast<std::underlying_type<page_table::level>::type>(level);
- return static_cast<page_table::level>(--value);
- }
-
- page_table_handle::page_table_handle(page_table * handle, page_table::level handle_level)
+ page_table_handle::page_table_handle(page_table * handle, page_table_handle::level handle_level)
: handle(handle)
, handle_level(handle_level)
{
@@ -63,7 +106,7 @@ namespace teachos::arch::memory::paging
auto page_table_handle::next_table(std::size_t table_index) const -> std::optional<page_table_handle>
{
- exception_handling::assert(handle_level != page_table::LEVEL1,
+ exception_handling::assert(handle_level != page_table_handle::LEVEL1,
"[Page Table] Attempted to call next_table on level 1 page table");
auto next_table = handle->next_table(table_index);
if (next_table)
diff --git a/arch/x86_64/src/memory/paging/virtual_page.cpp b/arch/x86_64/src/memory/paging/virtual_page.cpp
index 9b803d2..fd2085b 100644
--- a/arch/x86_64/src/memory/paging/virtual_page.cpp
+++ b/arch/x86_64/src/memory/paging/virtual_page.cpp
@@ -19,7 +19,7 @@ namespace teachos::arch::memory::paging
auto virtual_page::start_address() const -> uint64_t { return page_number * allocator::PAGE_FRAME_SIZE; }
- auto virtual_page::get_level_index(page_table::level level) const -> uint64_t
+ auto virtual_page::get_level_index(page_table_handle::level level) const -> uint64_t
{
return (start_address() >> (level * 9U)) & 0x1FF;
}