diff options
| author | Matteo Gmür <matteo.gmuer1@ost.ch> | 2024-10-16 14:30:04 +0000 |
|---|---|---|
| committer | Matteo Gmür <matteo.gmuer1@ost.ch> | 2024-10-16 14:30:04 +0000 |
| commit | d539ed1f4f26a42959bcae6ea3050b7f99f5f872 (patch) | |
| tree | 203e2b060e4b058f142590bb2d1842c82aef9a43 | |
| parent | 35e25757b6cffbcb2ff1eea8daf4c5f1ca421cb0 (diff) | |
| download | teachos-d539ed1f4f26a42959bcae6ea3050b7f99f5f872.tar.xz teachos-d539ed1f4f26a42959bcae6ea3050b7f99f5f872.zip | |
Attempt to implement page table checks using templates
| -rw-r--r-- | arch/x86_64/include/arch/memory/paging.hpp | 83 | ||||
| -rw-r--r-- | arch/x86_64/src/memory/paging.cpp | 58 |
2 files changed, 67 insertions, 74 deletions
diff --git a/arch/x86_64/include/arch/memory/paging.hpp b/arch/x86_64/include/arch/memory/paging.hpp index d55835e..4bbb0e0 100644 --- a/arch/x86_64/include/arch/memory/paging.hpp +++ b/arch/x86_64/include/arch/memory/paging.hpp @@ -105,28 +105,63 @@ namespace teachos::arch::memory ///< used for additional flags by the operating system. }; + enum level : uint8_t; + /** - * @brief A Page table containing 512 entries + * @brief A Page table containing 512 entries. */ + template<level page_table_level> struct page_table { + enum level : uint8_t + { + LEVEL1, + LEVEL2, + LEVEL3, + LEVEL4 + }; + /** * @brief Constructor. */ - page_table(); + page_table() + : entries() + , p4(reinterpret_cast<page_table *>(0xfffffffffffff000)) + { + // Nothing to do + } /** * @brief Set every entry of the page to unused */ - auto zero_entries() -> void; + auto zero_entries() -> void + { + constexpr size_t entry_amount = sizeof(entries) / sizeof(entries[0]); + for (size_t i = 0; i < entry_amount; ++i) + { + auto entry = entry.set_unused(); + } + } /** - * @brief Convert the address of a page_table into a page_table + * @brief Gets the complete 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. * - * @param index Index of the entry we want to access - * @return An optional of the next page table or null + * @param table_index Index of this page table in the page table one level higher. + * @return Entire page table of the next level. */ - auto next_table(std::size_t index) const -> std::optional<const page_table *>; + auto next_table(std::size_t table_index) const -> std::optional<const page_table *> + requires(page_table_level > 0) + { + auto address = next_table_address(table_index); + + if (address.has_value()) + { + return reinterpret_cast<page_table const *>(*address); + } + + return std::nullopt; + } /** * @brief Index operator overload to access specific mutable entry directy @@ -134,7 +169,13 @@ namespace teachos::arch::memory * @param index Index of the entry we want to access and change * @return Entry at the given table index */ - auto operator[](std::size_t index) -> entry &; + auto operator[](std::size_t index) -> entry & + { + // C array is not bounds checked, therefore we have to check ourselves, to ensure no out of bounds reads, which + // could be incredibly hard to debug later. + arch::exception_handling::assert(index < PAGE_TABLE_ENTRY_COUNT, "[Page Table] index out of bounds"); + return entries[index]; + } /** * @brief Index operator overload to access specific immutable entry directy @@ -142,22 +183,32 @@ namespace teachos::arch::memory * @param index Index of the entry we want to access and only read * @return Entry at the given table index */ - auto operator[](std::size_t index) const -> entry const &; + auto operator[](std::size_t index) const -> entry const & { return this->operator[](index); } private: /** - * @brief Find and return the next table address + * @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. * - * The next table address is only valid if the corresponding entry is present - * and does not create a huge page - * - * @param index + * @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 index) const -> std::optional<std::size_t>; + auto next_table_address(std::size_t table_index) const -> std::optional<std::size_t> + { + auto entry = this->operator[](table_index); + + if (entry.contains_flags(entry::PRESENT) && !entry.contains_flags(entry::HUGE_PAGE)) + { + std::size_t const table_address = reinterpret_cast<std::size_t>(this); + return (table_address << 9) | (table_index << 12); + } + // TODO: Implement behaviour for huge pages currently not done + return std::nullopt; + } entry entries[PAGE_TABLE_ENTRY_COUNT]; - page_table const * p4; + page_table<page_table::LEVEL4> const * p4; }; } // namespace teachos::arch::memory diff --git a/arch/x86_64/src/memory/paging.cpp b/arch/x86_64/src/memory/paging.cpp index a8f2c40..9774132 100644 --- a/arch/x86_64/src/memory/paging.cpp +++ b/arch/x86_64/src/memory/paging.cpp @@ -39,62 +39,4 @@ namespace teachos::arch::memory "Start address is not aligned with Page"); flags = std::bitset<64U>(frame.start_address()) | flags; } - - page_table::page_table() - : entries() - , p4(reinterpret_cast<page_table *>(0xfffffffffffff000)) - { - // Nothing to do - } - - auto page_table::zero_entries() -> void - { - constexpr size_t entry_amount = sizeof(entries) / sizeof(entries[0]); - for (size_t i = 0; i < entry_amount; ++i) - { - auto entry = this->operator[](i); - entry.set_unused(); - } - } - - auto page_table::next_table(std::size_t index) const -> std::optional<page_table const *> - { - auto address = next_table_address(index); - - if (address.has_value()) - { - return reinterpret_cast<page_table const *>(*address); - } - - return std::nullopt; - } - - auto page_table::operator[](std::size_t index) -> entry & - { - // C array is not bounds checked, therefore we have to check ourselves, to ensure no out of bounds reads, which - // could be incredibly hard to debug later. - arch::exception_handling::assert(index < PAGE_TABLE_ENTRY_COUNT, "[Page Table] index out of bounds"); - return entries[index]; - } - - auto page_table::operator[](std::size_t index) const -> entry const & - { - // C array is not bounds checked, therefore we have to check ourselves, to ensure no out of bounds reads, which - // could be incredibly hard to debug later. - arch::exception_handling::assert(index < PAGE_TABLE_ENTRY_COUNT, "[Page Table] index out of bounds"); - return entries[index]; - } - - auto page_table::next_table_address(std::size_t index) const -> std::optional<std::size_t> - { - auto entry = this->operator[](index); - - if (entry.contains_flags(entry::PRESENT) && !entry.contains_flags(entry::HUGE_PAGE)) - { - std::size_t const table_address = reinterpret_cast<std::size_t>(this); - return (table_address << 9) | (index << 12); - } - // TODO: Implement behaviour for huge pages currently not done - return std::nullopt; - } } // namespace teachos::arch::memory |
