aboutsummaryrefslogtreecommitdiff
path: root/arch
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
parent7ba274d0838e5cd4e48e85f81557bbb837ed4349 (diff)
downloadteachos-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.hpp3
-rw-r--r--arch/x86_64/kapi/memory.cpp54
-rw-r--r--arch/x86_64/src/memory/region_allocator.cpp9
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>