aboutsummaryrefslogtreecommitdiff
path: root/arch/x86_64
diff options
context:
space:
mode:
authorMatteo Gmür <matteo.gmuer1@ost.ch>2024-10-16 14:30:04 +0000
committerMatteo Gmür <matteo.gmuer1@ost.ch>2024-10-16 14:30:04 +0000
commitd539ed1f4f26a42959bcae6ea3050b7f99f5f872 (patch)
tree203e2b060e4b058f142590bb2d1842c82aef9a43 /arch/x86_64
parent35e25757b6cffbcb2ff1eea8daf4c5f1ca421cb0 (diff)
downloadteachos-d539ed1f4f26a42959bcae6ea3050b7f99f5f872.tar.xz
teachos-d539ed1f4f26a42959bcae6ea3050b7f99f5f872.zip
Attempt to implement page table checks using templates
Diffstat (limited to 'arch/x86_64')
-rw-r--r--arch/x86_64/include/arch/memory/paging.hpp83
-rw-r--r--arch/x86_64/src/memory/paging.cpp58
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