aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--arch/x86_64/include/arch/memory/paging/page_mapper.hpp4
-rw-r--r--arch/x86_64/include/arch/memory/paging/page_table.hpp77
-rw-r--r--arch/x86_64/include/arch/memory/paging/virtual_page.hpp2
-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
6 files changed, 87 insertions, 82 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 a874f75..0806f58 100644
--- a/arch/x86_64/include/arch/memory/paging/page_mapper.hpp
+++ b/arch/x86_64/include/arch/memory/paging/page_mapper.hpp
@@ -60,7 +60,7 @@ namespace teachos::arch::memory::paging
{
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 level_index = page.get_level_index(level);
auto next_handle = current_handle.next_table(level_index);
@@ -82,7 +82,7 @@ namespace teachos::arch::memory::paging
current_handle = next_handle.value();
}
- auto level1_entry = current_handle[page.get_level_index(page_table::LEVEL1)];
+ auto level1_entry = current_handle[page.get_level_index(page_table_handle::LEVEL1)];
arch::exception_handling::assert(!level1_entry.contains_flags(entry::HUGE_PAGE),
"[Page Mapper] Unable to map huge pages");
arch::exception_handling::assert(!level1_entry.is_unused(), "[Page Mapper] Page table entry is already used");
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 a1c8abe..91ce81c 100644
--- a/arch/x86_64/include/arch/memory/paging/page_table.hpp
+++ b/arch/x86_64/include/arch/memory/paging/page_table.hpp
@@ -11,12 +11,20 @@ namespace teachos::arch::memory::paging
}
/**
- * @brief A Page table containing 512 entries.
+ * @brief Forward delcaration of the page_table, because it should only be accessible over the handle, the actual
+ * methods or constructor are not defined meaning they are not callable from outside. Instead the struct is only fully
+ * defined in the implementation (.cpp) file of the page table, and therefore also only accesible in that file.
*/
- struct page_table
+ struct page_table;
+
+ /**
+ * @brief Handle that ensures accessing the page table is safe because it adds additional checks to the next_table
+ * method and ensures it can only be called if the table level is not LEVEL1.
+ */
+ struct page_table_handle
{
/**
- * @brief Level of the page table, level 1 should not be able to call next_table anymore, because it would result in
+ * @brief Level of the page table, level 1 will not be able to call next_table anymore, because it would result in
* attempting to access memory that it should not.
*/
enum level : uint8_t
@@ -28,61 +36,12 @@ namespace teachos::arch::memory::paging
};
/**
- * @brief Deleted constructor. Object can only be created by casting from the fixed Level 4
- * page table address `reinterpret_cast<page_table *>(0xfffffffffffff000)`.
- */
- page_table() = delete;
-
- /**
- * @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::level & level, int) -> page_table::level;
-
- /**
- * @brief Handle that ensures accessing the page table is safe because it adds additional checks to the next_table
- * method and ensures it can only be called if the table level is not LEVEL1.
- */
- struct page_table_handle
- {
- /**
* @brief Constructor.
+ *
+ * @param handle Underlying page table the handle should point to.
+ * @param handle_level Level the underlying page table is on, used to ensure safety.
*/
- page_table_handle(page_table * handle, page_table::level handle_level);
+ page_table_handle(page_table * handle, level handle_level);
/**
* @brief Set every entry of the page to unused.
@@ -109,9 +68,11 @@ namespace teachos::arch::memory::paging
private:
page_table * handle; ///< Handle to underlying page table, can never be null (invariant ensured by constructor)
- page_table::level handle_level; ///< Level page table is currently on, depends on how often next_level was
- ///< called successfully.
+ level handle_level; ///< Level page table is currently on, depends on how often next_level was
+ ///< called successfully.
};
+
+ auto operator--(page_table_handle::level & level, int) -> page_table_handle::level;
} // namespace teachos::arch::memory::paging
#endif // TEACHOS_ARCH_X86_64_MEMORY_PAGING_PAGE_TABLE_HPP
diff --git a/arch/x86_64/include/arch/memory/paging/virtual_page.hpp b/arch/x86_64/include/arch/memory/paging/virtual_page.hpp
index f8dfbf0..ca11b3c 100644
--- a/arch/x86_64/include/arch/memory/paging/virtual_page.hpp
+++ b/arch/x86_64/include/arch/memory/paging/virtual_page.hpp
@@ -43,7 +43,7 @@ namespace teachos::arch::memory::paging
* @param level Level of the page table we want to calculate the index for.
* @return Index into the page table with the given level.
*/
- auto get_level_index(page_table::level level) const -> uint64_t;
+ auto get_level_index(page_table_handle::level level) const -> uint64_t;
/**
* @brief Defaulted equals operator.
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;
}