diff options
Diffstat (limited to 'kernel/kapi/memory.cpp')
| -rw-r--r-- | kernel/kapi/memory.cpp | 56 |
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 |
