aboutsummaryrefslogtreecommitdiff
path: root/kernel/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 /kernel/kapi
parent7ba274d0838e5cd4e48e85f81557bbb837ed4349 (diff)
downloadteachos-e284d574ed9237a215d994861cc502452fec11ce.tar.xz
teachos-e284d574ed9237a215d994861cc502452fec11ce.zip
kernel/memory: implement basic bitmap allocator
Diffstat (limited to 'kernel/kapi')
-rw-r--r--kernel/kapi/memory.cpp56
1 files changed, 53 insertions, 3 deletions
diff --git a/kernel/kapi/memory.cpp b/kernel/kapi/memory.cpp
index 7c9b1da..1699cd3 100644
--- a/kernel/kapi/memory.cpp
+++ b/kernel/kapi/memory.cpp
@@ -2,8 +2,17 @@
#include "kapi/system.hpp"
+#include "kernel/memory/bitmap_allocator.hpp"
+
+#include <kstd/print>
+
+#include <algorithm>
+#include <bit>
#include <cstddef>
+#include <cstdint>
#include <optional>
+#include <ranges>
+#include <span>
#include <utility>
namespace kapi::memory
@@ -20,6 +29,11 @@ namespace kapi::memory
system::panic("Tried to allocate frames without an active allocator.");
}
+ auto mark_used(frame) -> void override
+ {
+ system::panic("Tried to mark frame as used without an active allocator.");
+ }
+
auto release_many(std::pair<frame, std::size_t>) -> void override
{
system::panic("Tried to release frames without an active allocator.");
@@ -48,11 +62,17 @@ namespace kapi::memory
constinit bad_frame_allocator bad_frame_allocator::instance{};
constinit bad_page_mapper bad_page_mapper::instance{};
+ auto constinit allocator = std::optional<kernel::memory::bitmap_frame_allocator>{};
} // namespace
constinit auto static active_frame_allocator = static_cast<frame_allocator *>(&bad_frame_allocator::instance);
constinit auto static active_page_mapper = static_cast<page_mapper *>(&bad_page_mapper::instance);
+ auto get_frame_allocator() -> frame_allocator &
+ {
+ return *active_frame_allocator;
+ }
+
auto set_frame_allocator(frame_allocator & allocator) -> std::optional<frame_allocator *>
{
if (&allocator == active_frame_allocator)
@@ -73,12 +93,12 @@ namespace kapi::memory
auto allocate_frame() -> std::optional<frame>
{
- return active_frame_allocator->allocate();
+ return get_frame_allocator().allocate();
}
auto allocate_many_frames(std::size_t count) -> std::optional<std::pair<frame, std::size_t>>
{
- return active_frame_allocator->allocate_many(count);
+ return get_frame_allocator().allocate_many(count);
}
auto map(page page, frame frame) -> std::byte *
@@ -91,4 +111,34 @@ namespace kapi::memory
return active_page_mapper->unmap(page);
}
-} // namespace kapi::memory \ No newline at end of file
+ auto init_pmm(std::size_t frame_count, void (&handoff_handler)(frame_allocator &)) -> void
+ {
+ auto const bitmap_bytes = (frame_count + 7uz) / 8uz;
+ auto const bitmap_pages = (bitmap_bytes + page::size - 1uz) / page::size;
+
+ auto const bitmap_frames = allocate_many_frames(bitmap_pages);
+ if (!bitmap_frames)
+ {
+ system::panic("[OS:MEM] Not enough memory for bitmap allocator!");
+ }
+
+ auto const base_address = 0xffff'c000'0000'0000uz;
+ auto const flags = page_mapper::flags::writable | page_mapper::flags::supervisor_only;
+
+ std::ranges::for_each(std::views::iota(0uz, bitmap_pages), [&](auto index) {
+ auto page = page::containing(linear_address{base_address + index * page::size});
+ auto frame = memory::frame(bitmap_frames->first.number() + index);
+ active_page_mapper->map(page, frame, flags);
+ });
+
+ auto bitmap_ptr = std::bit_cast<std::uint64_t *>(base_address);
+ auto bitmap = std::span{bitmap_ptr, (bitmap_bytes + sizeof(std::uint64_t) - 1uz) / sizeof(std::uint64_t)};
+
+ allocator.emplace(bitmap, frame_count);
+
+ handoff_handler(allocator.value());
+ set_frame_allocator(allocator.value());
+ kstd::println("[OS:MEM] Physical memory manager initialized.");
+ }
+
+} // namespace kapi::memory