diff options
| author | Felix Morgner <felix.morgner@ost.ch> | 2026-03-17 14:19:02 +0100 |
|---|---|---|
| committer | Felix Morgner <felix.morgner@ost.ch> | 2026-03-17 14:19:02 +0100 |
| commit | 541670e49812b5b07079cc86367247402ace331a (patch) | |
| tree | 1276c3664c73f8d44c5c028b5c88ac2decaa9b66 /arch/x86_64/kapi | |
| parent | 796ce76185b00feb86f6b4f738ac6f953c247116 (diff) | |
| download | teachos-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.cpp | 109 |
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 |
