aboutsummaryrefslogtreecommitdiff
path: root/arch/x86_64/kapi
diff options
context:
space:
mode:
authorFelix Morgner <felix.morgner@ost.ch>2026-03-13 22:28:50 +0100
committerFelix Morgner <felix.morgner@ost.ch>2026-03-13 23:51:38 +0100
commite284d574ed9237a215d994861cc502452fec11ce (patch)
tree716c9929ef4c0df2b89ab0166c615271aec2374c /arch/x86_64/kapi
parent7ba274d0838e5cd4e48e85f81557bbb837ed4349 (diff)
downloadteachos-e284d574ed9237a215d994861cc502452fec11ce.tar.xz
teachos-e284d574ed9237a215d994861cc502452fec11ce.zip
kernel/memory: implement basic bitmap allocator
Diffstat (limited to 'arch/x86_64/kapi')
-rw-r--r--arch/x86_64/kapi/memory.cpp54
1 files changed, 51 insertions, 3 deletions
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