diff options
| author | Felix Morgner <felix.morgner@ost.ch> | 2026-03-13 22:28:50 +0100 |
|---|---|---|
| committer | Felix Morgner <felix.morgner@ost.ch> | 2026-03-13 23:51:38 +0100 |
| commit | e284d574ed9237a215d994861cc502452fec11ce (patch) | |
| tree | 716c9929ef4c0df2b89ab0166c615271aec2374c /arch | |
| parent | 7ba274d0838e5cd4e48e85f81557bbb837ed4349 (diff) | |
| download | teachos-e284d574ed9237a215d994861cc502452fec11ce.tar.xz teachos-e284d574ed9237a215d994861cc502452fec11ce.zip | |
kernel/memory: implement basic bitmap allocator
Diffstat (limited to 'arch')
| -rw-r--r-- | arch/x86_64/include/arch/memory/region_allocator.hpp | 3 | ||||
| -rw-r--r-- | arch/x86_64/kapi/memory.cpp | 54 | ||||
| -rw-r--r-- | arch/x86_64/src/memory/region_allocator.cpp | 9 |
3 files changed, 63 insertions, 3 deletions
diff --git a/arch/x86_64/include/arch/memory/region_allocator.hpp b/arch/x86_64/include/arch/memory/region_allocator.hpp index f391293..1c5885e 100644 --- a/arch/x86_64/include/arch/memory/region_allocator.hpp +++ b/arch/x86_64/include/arch/memory/region_allocator.hpp @@ -58,6 +58,9 @@ namespace arch::memory auto allocate_many(std::size_t count = 1) noexcept -> std::optional<std::pair<kapi::memory::frame, std::size_t>> override; + //! @copydoc kapi::memory::frame_allocator::mark_used + auto mark_used(kapi::memory::frame frame) -> void override; + //! @copydoc kapi::memory::frame_allocator::release_many //! //! @note This implementation will never actually release any frames. 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 <kstd/print> +#include <multiboot2/constants.hpp> #include <multiboot2/information.hpp> +#include <algorithm> #include <atomic> #include <bit> #include <cstddef> #include <cstdint> #include <memory> #include <optional> +#include <ranges> #include <span> #include <utility> @@ -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<arch::memory::region_allocator>{}; + auto constinit allocation_buffer = std::optional<buffered_allocator<4>>{}; + auto constinit recursive_page_mapper = std::optional<arch::memory::recursive_page_mapper>{}; + //! 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<arch::memory::region_allocator>{}; - auto constinit allocation_buffer = std::optional<buffered_allocator<4>>{}; - auto constinit recursive_page_mapper = std::optional<arch::memory::recursive_page_mapper>{}; + 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<std::uintptr_t>(boot::bootstrap_information.mbi); + auto mbi_size = boot::bootstrap_information.mbi->size_bytes(); + auto mbi_address = physical_address{mbi_base & ~std::bit_cast<std::uintptr_t>(&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 diff --git a/arch/x86_64/src/memory/region_allocator.cpp b/arch/x86_64/src/memory/region_allocator.cpp index a2dfd48..36902ad 100644 --- a/arch/x86_64/src/memory/region_allocator.cpp +++ b/arch/x86_64/src/memory/region_allocator.cpp @@ -124,6 +124,15 @@ namespace arch::memory return std::nullopt; } + auto region_allocator::mark_used(kapi::memory::frame frame) -> void + { + if (frame < m_next_frame) + { + m_next_frame = frame; + find_next_frame(); + } + } + auto region_allocator::release_many(std::pair<kapi::memory::frame, std::size_t>) -> void {} auto region_allocator::next_free_frame() noexcept -> std::optional<kapi::memory::frame> |
