aboutsummaryrefslogtreecommitdiff
path: root/arch/x86_64/kapi
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/kapi
parent796ce76185b00feb86f6b4f738ac6f953c247116 (diff)
downloadteachos-541670e49812b5b07079cc86367247402ace331a.tar.xz
teachos-541670e49812b5b07079cc86367247402ace331a.zip
x86_64/memory: finish HHDM-based mapper
Diffstat (limited to 'arch/x86_64/kapi')
-rw-r--r--arch/x86_64/kapi/memory.cpp109
1 files changed, 57 insertions, 52 deletions
diff --git a/arch/x86_64/kapi/memory.cpp b/arch/x86_64/kapi/memory.cpp
index f74eea6..a9e1216 100644
--- a/arch/x86_64/kapi/memory.cpp
+++ b/arch/x86_64/kapi/memory.cpp
@@ -6,9 +6,10 @@
#include "arch/boot/boot.hpp"
#include "arch/boot/ld.hpp"
#include "arch/cpu/registers.hpp"
+#include "arch/memory/higher_half_mapper.hpp"
#include "arch/memory/kernel_mapper.hpp"
-#include "arch/memory/mmu.hpp"
#include "arch/memory/page_table.hpp"
+#include "arch/memory/page_utilities.hpp"
#include "arch/memory/region_allocator.hpp"
#include <kstd/print>
@@ -21,6 +22,7 @@
#include <bit>
#include <cstddef>
#include <cstdint>
+#include <memory>
#include <optional>
#include <ranges>
#include <span>
@@ -32,6 +34,7 @@ namespace kapi::memory
namespace
{
auto constinit region_based_allocator = std::optional<arch::memory::region_allocator>{};
+ auto constinit higher_half_mapper = std::optional<arch::memory::higher_half_mapper>{};
//! Instantiate a basic, memory region based, early frame allocator for remapping.
auto collect_memory_information()
@@ -53,6 +56,27 @@ namespace kapi::memory
};
}
+ auto establish_higher_half_direct_mapping() -> void
+ {
+ auto pml3_frame = kapi::memory::allocate_frame();
+ auto pml3 = static_cast<arch::memory::page_table *>(pml3_frame->start_address());
+ pml3->clear();
+
+ std::ranges::for_each(std::views::iota(0uz, 512uz), [&](auto index) {
+ auto frame = kapi::memory::frame{(1024uz * 1024uz * 1024uz * index)};
+ auto & entry = (*pml3)[index];
+ entry.frame(frame, arch::memory::page_table::entry::flags::present |
+ arch::memory::page_table::entry::flags::writable |
+ arch::memory::page_table::entry::flags::huge_page);
+ });
+
+ auto current_cr3 = arch::cpu::cr3::read();
+ auto pml4 = static_cast<arch::memory::page_table *>(current_cr3.address());
+ (*pml4)[256].frame(*pml3_frame, arch::memory::page_table::entry::flags::present |
+ arch::memory::page_table::entry::flags::writable |
+ arch::memory::page_table::entry::flags::global);
+ }
+
//! Enable additional CPU protection features, required during later stages of the kernel.
auto enable_cpu_protections() -> void
{
@@ -62,7 +86,8 @@ namespace kapi::memory
[[maybe_unused]] auto remap_kernel(page_mapper & mapper) -> void
{
- auto kernel_mapper = arch::memory::kernel_mapper{boot::bootstrap_information.mbi};
+ auto mbi_pointer = boot::bootstrap_information.mbi;
+ auto kernel_mapper = arch::memory::kernel_mapper{mbi_pointer};
kernel_mapper.remap_kernel(mapper);
}
@@ -133,39 +158,6 @@ namespace kapi::memory
std::ranges::for_each(std::views::iota(mbi_start, mbi_end), [&](auto frame) { new_allocator.mark_used(frame); });
}
- auto establish_higher_half_direct_mapping() -> void
- {
- auto hhdm_frame = kapi::memory::allocate_frame();
- auto hhdm_pml3 = static_cast<arch::memory::page_table *>(hhdm_frame->start_address());
- hhdm_pml3->clear();
-
- std::ranges::for_each(std::views::iota(0uz, 512uz), [&](auto index) {
- auto frame = kapi::memory::frame{(1024uz * 1024uz * 1024uz * index)};
- auto & entry = (*hhdm_pml3)[index];
- entry.frame(frame, arch::memory::page_table::entry::flags::present |
- arch::memory::page_table::entry::flags::writable |
- arch::memory::page_table::entry::flags::huge_page);
- });
-
- auto current_cr3 = arch::cpu::cr3::read();
- auto pml4_address = linear_address{current_cr3.address().raw()};
- auto pml4 = static_cast<arch::memory::page_table *>(pml4_address);
- (*pml4)[256].frame(*hhdm_frame, arch::memory::page_table::entry::flags::present |
- arch::memory::page_table::entry::flags::writable |
- arch::memory::page_table::entry::flags::global);
- }
-
- auto clear_lower_address_space() -> void
- {
- auto current_cr3 = arch::cpu::cr3::read();
- auto pml4_address = memory::higher_half_direct_map_base + current_cr3.address().raw();
- auto pml4 = static_cast<arch::memory::page_table *>(pml4_address);
-
- std::ranges::for_each(std::views::iota(0uz, 1uz), [&](auto index) { (*pml4)[index].clear(); });
-
- arch::memory::tlb_flush_all();
- }
-
} // namespace
auto init() -> void
@@ -187,31 +179,44 @@ namespace kapi::memory
kstd::println("[x86_64:MEM] Establishing higher-half direct mapping.");
establish_higher_half_direct_mapping();
- clear_lower_address_space();
kstd::println("[x86_64:MEM] Preparing new paging hierarchy.");
- // remap_kernel(*recursive_page_mapper);
- // remap_vga_text_mode_buffer(*recursive_page_mapper);
- // remap_multiboot_information(*recursive_page_mapper);
+ auto new_pml4_frame = kapi::memory::allocate_frame();
+ if (!new_pml4_frame)
+ {
+ system::panic("[x86_64:MEM] Failed to allocate new PML4!");
+ }
+ auto new_pml4 = arch::memory::to_higher_half_pointer<arch::memory::page_table>(new_pml4_frame->start_address());
+ std::construct_at(new_pml4);
+
+ higher_half_mapper.emplace(new_pml4);
+ set_page_mapper(*higher_half_mapper);
+
+ remap_kernel(*higher_half_mapper);
+ remap_vga_text_mode_buffer(*higher_half_mapper);
+ remap_multiboot_information(*higher_half_mapper);
+
+ auto current_cr3 = arch::cpu::cr3::read();
+ auto old_pml4 = static_cast<arch::memory::page_table *>(current_cr3.address());
+ (*new_pml4)[256] = (*old_pml4)[256];
- // kstd::println("[x86_64:MEM] Switching to new paging hierarchy.");
+ kstd::println("[x86_64:MEM] Switching to new paging hierarchy.");
- // auto cr3 = arch::cpu::cr3::read();
- // cr3.frame(new_pml4_frame);
- // arch::cpu::cr3::write(cr3);
+ auto cr3 = arch::cpu::cr3::read();
+ cr3.frame(*new_pml4_frame);
+ arch::cpu::cr3::write(cr3);
- // auto memory_map = boot::bootstrap_information.mbi->memory_map();
- // auto highest_byte = std::ranges::max(std::views::transform(
- // std::views::filter(memory_map.regions(),
- // [](auto const & region) { return region.type == multiboot2::memory_type::available; }),
- // [](auto const & region) { return region.base + region.size_in_B; }));
+ auto memory_map = boot::bootstrap_information.mbi->memory_map();
+ auto highest_byte = std::ranges::max(std::views::transform(
+ std::views::filter(memory_map.regions(),
+ [](auto const & region) { return region.type == multiboot2::memory_type::available; }),
+ [](auto const & region) { return region.base + region.size_in_B; }));
- // init_pmm(frame::containing(physical_address{highest_byte}).number() + 1, handoff_to_kernel_pmm);
+ init_pmm(frame::containing(physical_address{highest_byte}).number() + 1, handoff_to_kernel_pmm);
- // kstd::println("[x86_64:MEM] Releasing bootstrap memory allocators.");
- // allocation_buffer.reset();
- // region_based_allocator.reset();
+ kstd::println("[x86_64:MEM] Releasing bootstrap memory allocators.");
+ region_based_allocator.reset();
}
} // namespace kapi::memory