aboutsummaryrefslogtreecommitdiff
path: root/arch/x86_64/src/memory/paging
diff options
context:
space:
mode:
Diffstat (limited to 'arch/x86_64/src/memory/paging')
-rw-r--r--arch/x86_64/src/memory/paging/page_entry.cpp42
-rw-r--r--arch/x86_64/src/memory/paging/page_table.cpp65
2 files changed, 107 insertions, 0 deletions
diff --git a/arch/x86_64/src/memory/paging/page_entry.cpp b/arch/x86_64/src/memory/paging/page_entry.cpp
new file mode 100644
index 0000000..43c0b71
--- /dev/null
+++ b/arch/x86_64/src/memory/paging/page_entry.cpp
@@ -0,0 +1,42 @@
+#include "arch/memory/paging/page_entry.hpp"
+
+#include "arch/exception_handling/assert.hpp"
+
+namespace teachos::arch::memory::paging
+{
+ auto entry::is_unused() const -> bool { return flags == 0U; }
+
+ auto entry::set_unused() -> void { flags = 0U; }
+
+ auto entry::calculate_pointed_to_frame() const -> std::optional<allocator::physical_frame>
+ {
+ if (contains_flags(PRESENT))
+ {
+ auto physical_address = calculate_physical_address();
+ return allocator::physical_frame::containing_address(physical_address);
+ }
+ return std::nullopt;
+ }
+
+ auto entry::calculate_physical_address() const -> std::size_t
+ {
+ constexpr std::size_t start_bit = 12U;
+ constexpr std::size_t end_bit = 52U;
+ size_t value = 0U;
+
+ for (auto i = start_bit; i < end_bit; i++)
+ {
+ value |= (flags[i] ? (1 << (i - start_bit)) : 0);
+ }
+ return value;
+ }
+
+ auto entry::contains_flags(std::bitset<64U> other) const -> bool { return (flags & other) == other; }
+
+ auto entry::set_address(allocator::physical_frame frame) -> void
+ {
+ arch::exception_handling::assert((frame.start_address() & ~0x000fffff'fffff000) == 0,
+ "Start address is not aligned with Page");
+ flags = std::bitset<64U>(frame.start_address()) | flags;
+ }
+} // namespace teachos::arch::memory::paging
diff --git a/arch/x86_64/src/memory/paging/page_table.cpp b/arch/x86_64/src/memory/paging/page_table.cpp
new file mode 100644
index 0000000..a1cbc72
--- /dev/null
+++ b/arch/x86_64/src/memory/paging/page_table.cpp
@@ -0,0 +1,65 @@
+#include "arch/memory/paging/page_table.hpp"
+
+#include "arch/exception_handling/assert.hpp"
+
+namespace teachos::arch::memory::paging
+{
+ page_table::page_table()
+ : current_level(LEVEL4)
+ , current_table(reinterpret_cast<table_content *>(0xfffffffffffff000))
+ {
+ // Nothing to do
+ }
+
+ auto page_table::zero_entries() -> void
+ {
+ constexpr size_t entry_amount = sizeof(current_table->entries) / sizeof(current_table->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 table_index) -> void
+ {
+ arch::exception_handling::assert(current_level != LEVEL1,
+ "[Page Table] Attempted to call next_table on level 1 page table");
+ auto address = next_table_address(table_index);
+
+ if (address.has_value())
+ {
+ current_table = reinterpret_cast<table_content *>(*address);
+ current_level = static_cast<level>(current_level - 1U);
+ }
+ }
+
+ 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 current_table->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 current_table->entries[index];
+ }
+
+ auto page_table::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;
+ }
+} // namespace teachos::arch::memory::paging