aboutsummaryrefslogtreecommitdiff
path: root/arch/x86_64/src
diff options
context:
space:
mode:
authorFelix Morgner <felix.morgner@ost.ch>2026-03-17 14:19:02 +0100
committerFelix Morgner <felix.morgner@ost.ch>2026-03-17 14:19:02 +0100
commit541670e49812b5b07079cc86367247402ace331a (patch)
tree1276c3664c73f8d44c5c028b5c88ac2decaa9b66 /arch/x86_64/src
parent796ce76185b00feb86f6b4f738ac6f953c247116 (diff)
downloadteachos-541670e49812b5b07079cc86367247402ace331a.tar.xz
teachos-541670e49812b5b07079cc86367247402ace331a.zip
x86_64/memory: finish HHDM-based mapper
Diffstat (limited to 'arch/x86_64/src')
-rw-r--r--arch/x86_64/src/boot/boot32.S2
-rw-r--r--arch/x86_64/src/memory/higher_half_mapper.cpp104
2 files changed, 98 insertions, 8 deletions
diff --git a/arch/x86_64/src/boot/boot32.S b/arch/x86_64/src/boot/boot32.S
index 694b8b7..1c2fdaf 100644
--- a/arch/x86_64/src/boot/boot32.S
+++ b/arch/x86_64/src/boot/boot32.S
@@ -306,7 +306,7 @@ _assert_cpu_supports_long_mode:
pie_function_end
/**
- * @brief Prepare a recursive page map hierarchy
+ * @brief Prepare a basic page map hierarchy
*
* @param ebp+8 The number of huge pages to map
* @return void
diff --git a/arch/x86_64/src/memory/higher_half_mapper.cpp b/arch/x86_64/src/memory/higher_half_mapper.cpp
index 9fe3c89..abb54a3 100644
--- a/arch/x86_64/src/memory/higher_half_mapper.cpp
+++ b/arch/x86_64/src/memory/higher_half_mapper.cpp
@@ -1,29 +1,119 @@
#include "arch/memory/higher_half_mapper.hpp"
#include "kapi/memory.hpp"
+#include "kapi/system.hpp"
+#include "arch/memory/page_table.hpp"
+#include "arch/memory/page_utilities.hpp"
+
+#include <algorithm>
+#include <array>
#include <cstddef>
+#include <memory>
+#include <ranges>
+#include <utility>
namespace arch::memory
{
+ higher_half_mapper::higher_half_mapper(page_table * root)
+ : m_root{root}
+ {}
+
auto higher_half_mapper::map(kapi::memory::page page, kapi::memory::frame frame, flags flags) -> std::byte *
{
- static_cast<void>(page);
- static_cast<void>(frame);
- static_cast<void>(flags);
- return nullptr;
+ auto table = get_or_create_page_table(page);
+ if (!table)
+ {
+ return nullptr;
+ }
+
+ auto const index = pml_index(1, page);
+ auto & entry = (*table)[index];
+
+ if (entry.present())
+ {
+ kapi::system::panic("[x86_64:MEM] Tried to map a page that is already mapped!");
+ }
+
+ entry.frame(frame, to_table_flags(flags) | page_table::entry::flags::present);
+
+ return static_cast<std::byte *>(page.start_address());
}
auto higher_half_mapper::unmap(kapi::memory::page page) -> void
{
- static_cast<void>(page);
+ if (!try_unmap(page))
+ {
+ kapi::system::panic("[x86_64:MEM] Tried to unmap a page that is not mapped!");
+ }
}
auto higher_half_mapper::try_unmap(kapi::memory::page page) noexcept -> bool
{
- static_cast<void>(page);
- return false;
+ auto table_path = std::array<std::pair<page_table *, std::size_t>, 4>{};
+ table_path[0] = std::pair{m_root, pml_index(4, page)};
+
+ for (auto level = 4uz; level > 1uz; --level)
+ {
+ auto [table, index] = table_path[4 - level];
+ auto & entry = (*table)[index];
+
+ if (!entry.present())
+ {
+ return false;
+ }
+
+ auto next_table = to_higher_half_pointer<page_table>(entry.frame()->start_address());
+ auto next_index = pml_index(4 - level - 1, page);
+ table_path[4 - level - 1] = std::pair{next_table, next_index};
+ }
+
+ std::ranges::for_each(std::views::reverse(table_path), [previous_was_empty = true](auto & step) mutable {
+ auto [table, index] = step;
+ auto & entry = (*table)[index];
+ auto frame = entry.frame();
+
+ if (previous_was_empty)
+ {
+ entry.clear();
+ previous_was_empty = table->empty();
+ kapi::memory::get_frame_allocator().release(*frame);
+ }
+ });
+
+ return true;
+ }
+
+ auto higher_half_mapper::get_or_create_page_table(kapi::memory::page page) noexcept -> page_table *
+ {
+ auto table = m_root;
+
+ for (auto level = 4uz; level > 1uz; --level)
+ {
+ auto index = pml_index(level, page);
+ auto & entry = (*table)[index];
+
+ if (!entry.present())
+ {
+ auto table_frame = kapi::memory::allocate_frame();
+ if (!table_frame)
+ {
+ return nullptr;
+ }
+
+ auto new_table = to_higher_half_pointer<page_table>(table_frame->start_address());
+ std::construct_at(new_table);
+
+ auto const flags = page_table::entry::flags::present | page_table::entry::flags::writable |
+ page_table::entry::flags::user_accessible;
+ entry.frame(*table_frame, flags);
+ }
+
+ table = to_higher_half_pointer<page_table>(entry.frame()->start_address());
+ }
+
+ return table;
}
} // namespace arch::memory \ No newline at end of file