From e284d574ed9237a215d994861cc502452fec11ce Mon Sep 17 00:00:00 2001 From: Felix Morgner Date: Fri, 13 Mar 2026 22:28:50 +0100 Subject: kernel/memory: implement basic bitmap allocator --- arch/x86_64/kapi/memory.cpp | 54 ++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 51 insertions(+), 3 deletions(-) (limited to 'arch/x86_64/kapi/memory.cpp') diff --git a/arch/x86_64/kapi/memory.cpp b/arch/x86_64/kapi/memory.cpp index b71fa17..48aab9f 100644 --- a/arch/x86_64/kapi/memory.cpp +++ b/arch/x86_64/kapi/memory.cpp @@ -18,14 +18,17 @@ #include +#include #include +#include #include #include #include #include #include #include +#include #include #include @@ -37,6 +40,10 @@ namespace kapi::memory constexpr auto static unused_page_address = linear_address{0x0000'7fff'cafe'faceuz}; constexpr auto static recursive_page_map_index = arch::memory::page_table::entry_count - 2; + auto constinit region_based_allocator = std::optional{}; + auto constinit allocation_buffer = std::optional>{}; + auto constinit recursive_page_mapper = std::optional{}; + //! Instantiate a basic, memory region based, early frame allocator for remapping. auto collect_memory_information() { @@ -150,9 +157,42 @@ namespace kapi::memory } } - auto constinit region_based_allocator = std::optional{}; - auto constinit allocation_buffer = std::optional>{}; - auto constinit recursive_page_mapper = std::optional{}; + auto handoff_to_kernel_pmm(frame_allocator & new_allocator) -> void + { + auto memory_map = boot::bootstrap_information.mbi->memory_map(); + + for (auto const & region : memory_map.regions() | std::views::filter([](auto const & region) { + return region.type == multiboot2::memory_type::available; + })) + { + auto start = frame::containing(physical_address{region.base}); + auto count = region.size_in_B / page::size; + new_allocator.release_many({start, count}); + } + + auto next_free_frame = region_based_allocator->next_free_frame(); + if (!next_free_frame) + { + system::panic("[x86_64:MEM] No more free memory!"); + } + + std::ranges::for_each(std::views::iota(kapi::memory::frame{}, *next_free_frame), + [&](auto frame) { new_allocator.mark_used(frame); }); + + auto image_start = frame::containing(physical_address{&arch::boot::_start_physical}); + auto image_end = frame::containing(physical_address{&arch::boot::_end_physical}) + 1; + + std::ranges::for_each(std::views::iota(image_start, image_end), + [&](auto frame) { new_allocator.mark_used(frame); }); + + auto mbi_base = std::bit_cast(boot::bootstrap_information.mbi); + auto mbi_size = boot::bootstrap_information.mbi->size_bytes(); + auto mbi_address = physical_address{mbi_base & ~std::bit_cast(&arch::boot::TEACHOS_VMA)}; + auto mbi_start = frame::containing(mbi_address); + auto mbi_end = frame::containing(physical_address{mbi_address.raw() + mbi_size}) + 1; + + std::ranges::for_each(std::views::iota(mbi_start, mbi_end), [&](auto frame) { new_allocator.mark_used(frame); }); + } } // namespace @@ -189,6 +229,14 @@ namespace kapi::memory set_frame_allocator(*allocation_buffer); set_page_mapper(*recursive_page_mapper); + + 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); } } // namespace kapi::memory -- cgit v1.2.3