aboutsummaryrefslogtreecommitdiff
path: root/kernel
diff options
context:
space:
mode:
authorFelix Morgner <felix.morgner@ost.ch>2026-04-08 13:54:52 +0200
committerFelix Morgner <felix.morgner@ost.ch>2026-04-08 13:54:52 +0200
commit878852c94c4d56f303366cec177b3edef9b3b9c5 (patch)
treeb7c33b89201f6a8ae55fdc4ba041c4f1b9b97f99 /kernel
parent0bbec5ceba0df5668ab1aedcbf2905bf599f6eba (diff)
downloadteachos-878852c94c4d56f303366cec177b3edef9b3b9c5.tar.xz
teachos-878852c94c4d56f303366cec177b3edef9b3b9c5.zip
kapi: add basic support for MMIO mapping
Diffstat (limited to 'kernel')
-rw-r--r--kernel/CMakeLists.txt41
-rw-r--r--kernel/include/kernel/memory/mmio_allocator.hpp41
-rw-r--r--kernel/kapi/memory.cpp25
-rw-r--r--kernel/src/memory/mmio_allocator.cpp107
4 files changed, 194 insertions, 20 deletions
diff --git a/kernel/CMakeLists.txt b/kernel/CMakeLists.txt
index ef73586..67db0a8 100644
--- a/kernel/CMakeLists.txt
+++ b/kernel/CMakeLists.txt
@@ -20,6 +20,7 @@ add_library("kernel_objs" OBJECT
"src/acpi/manager.cpp"
"src/memory/bitmap_allocator.cpp"
"src/memory/block_list_allocator.cpp"
+ "src/memory/mmio_allocator.cpp"
"src/memory.cpp"
"src/devices/block_device.cpp"
"src/devices/block_device_utils.cpp"
@@ -66,37 +67,37 @@ target_sources("kernel_objs" PUBLIC
add_library("os::kernel" ALIAS "kernel_objs")
if(CMAKE_CROSSCOMPILING)
- add_executable("kernel"
+ add_executable("kernel"
"src/main.cpp"
"src/memory/operators.cpp"
)
- target_link_libraries("kernel" PRIVATE
+ target_link_libraries("kernel" PRIVATE
"os::arch"
"os::kernel"
)
- target_link_options("kernel" PRIVATE
+ target_link_options("kernel" PRIVATE
"-T${KERNEL_LINKER_SCRIPT}"
"-no-pie"
"-nostdlib"
)
- set_property(TARGET "kernel"
+ set_property(TARGET "kernel"
APPEND
PROPERTY LINK_DEPENDS
"${KERNEL_LINKER_SCRIPT}"
)
- target_disassemble("kernel")
- target_extract_debug_symbols("kernel")
- target_strip("kernel")
+ target_disassemble("kernel")
+ target_extract_debug_symbols("kernel")
+ target_strip("kernel")
- target_generate_bootable_iso("kernel")
+ target_generate_bootable_iso("kernel")
else()
- enable_coverage("kernel_objs")
+ enable_coverage("kernel_objs")
- add_library("kernel_test_support" OBJECT
+ add_library("kernel_test_support" OBJECT
"src/test_support/kapi/cpu.cpp"
"src/test_support/kapi/cio.cpp"
"src/test_support/kapi/interrupts.cpp"
@@ -108,21 +109,21 @@ else()
"src/test_support/simulated_memory.cpp"
"src/test_support/state_reset_listener.cpp"
)
- add_library("os::kernel_test_support" ALIAS "kernel_test_support")
+ add_library("os::kernel_test_support" ALIAS "kernel_test_support")
- target_link_libraries("kernel_test_support" PUBLIC
+ target_link_libraries("kernel_test_support" PUBLIC
"os::kernel"
"Catch2::Catch2WithMain"
)
- add_executable("kernel_tests"
+ add_executable("kernel_tests"
# KAPI Shim Tests
"kapi/cpu.tests.cpp"
"kapi/system.tests.cpp"
-
+
# KSTD Shim Tests
"kstd/print.tests.cpp"
-
+
# Memory Subsystem Tests
"src/memory/bitmap_allocator.tests.cpp"
"src/memory/block_list_allocator.tests.cpp"
@@ -130,19 +131,19 @@ else()
# Storage Subsystem Tests
"src/devices/storage/ram_disk/device.tests.cpp"
)
- add_executable("os::kernel_tests" ALIAS "kernel_tests")
+ add_executable("os::kernel_tests" ALIAS "kernel_tests")
- target_link_libraries("kernel_tests" PRIVATE
+ target_link_libraries("kernel_tests" PRIVATE
"os::kernel"
"os::kernel_test_support"
)
- set_target_properties("kernel_tests" PROPERTIES
+ set_target_properties("kernel_tests" PROPERTIES
C_CLANG_TIDY ""
CXX_CLANG_TIDY ""
)
- enable_coverage("kernel_tests")
- catch_discover_tests("os::kernel_tests")
+ enable_coverage("kernel_tests")
+ catch_discover_tests("os::kernel_tests")
endif()
diff --git a/kernel/include/kernel/memory/mmio_allocator.hpp b/kernel/include/kernel/memory/mmio_allocator.hpp
new file mode 100644
index 0000000..4ec6bec
--- /dev/null
+++ b/kernel/include/kernel/memory/mmio_allocator.hpp
@@ -0,0 +1,41 @@
+#ifndef TEACHOS_KERNEL_MEMORY_MMIO_ALLOCATOR_HPP
+#define TEACHOS_KERNEL_MEMORY_MMIO_ALLOCATOR_HPP
+
+#include "kapi/memory.hpp"
+
+#include <kstd/allocator>
+#include <kstd/memory>
+
+#include <cstddef>
+
+namespace kernel::memory
+{
+
+ struct mmio_allocator
+ {
+ mmio_allocator(kapi::memory::linear_address base, std::size_t pages);
+
+ [[nodiscard]] auto allocate(std::size_t page_count) -> kapi::memory::linear_address;
+ auto release(kapi::memory::linear_address base) -> void;
+
+ private:
+ struct node
+ {
+ kapi::memory::linear_address base{};
+ std::size_t page_count{};
+ node * next{};
+ node * previous{};
+ bool is_free{};
+ };
+
+ auto make_node(kapi::memory::linear_address base, std::size_t page_count, node * next, node * previous,
+ bool is_free) -> node *;
+ auto destroy_node(node *) -> void;
+
+ [[no_unique_address]] kstd::allocator<node> m_allocator{};
+ node * m_head{};
+ };
+
+} // namespace kernel::memory
+
+#endif
diff --git a/kernel/kapi/memory.cpp b/kernel/kapi/memory.cpp
index 06a3165..b224c50 100644
--- a/kernel/kapi/memory.cpp
+++ b/kernel/kapi/memory.cpp
@@ -3,6 +3,7 @@
#include "kapi/system.hpp"
#include "kernel/memory/bitmap_allocator.hpp"
+#include "kernel/memory/mmio_allocator.hpp"
#include <kstd/print>
#include <kstd/units>
@@ -63,6 +64,7 @@ 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>{};
+ auto constinit mmio_allocator = std::optional<kernel::memory::mmio_allocator>{};
} // namespace
constinit auto static active_frame_allocator = static_cast<frame_allocator *>(&bad_frame_allocator::instance);
@@ -147,4 +149,27 @@ namespace kapi::memory
kstd::println("[OS:MEM] Physical memory manager initialized.");
}
+ auto init_mmio(linear_address base, std::size_t page_count) -> void
+ {
+ mmio_allocator.emplace(base, page_count);
+ }
+
+ auto allocate_mmio_region(std::size_t page_count) -> linear_address
+ {
+ auto region = mmio_allocator->allocate(page_count);
+ return region;
+ }
+
+ auto map_mmio_region(linear_address base, physical_address hw_base, page_mapper::flags flags) -> std::byte *
+ {
+ auto start_page = page::containing(base);
+ auto start_frame = frame::containing(hw_base);
+ return map(start_page, start_frame, flags | page_mapper::flags::uncached);
+ }
+
+ auto release_mmio_region(linear_address base) -> void
+ {
+ mmio_allocator->release(base);
+ }
+
} // namespace kapi::memory
diff --git a/kernel/src/memory/mmio_allocator.cpp b/kernel/src/memory/mmio_allocator.cpp
new file mode 100644
index 0000000..f77f14f
--- /dev/null
+++ b/kernel/src/memory/mmio_allocator.cpp
@@ -0,0 +1,107 @@
+#include "kernel/memory/mmio_allocator.hpp"
+
+#include "kapi/memory.hpp"
+#include "kapi/system.hpp"
+
+#include <kstd/allocator>
+
+#include <cstddef>
+#include <memory>
+#include <utility>
+
+namespace kernel::memory
+{
+
+ mmio_allocator::mmio_allocator(kapi::memory::linear_address base, std::size_t pages)
+ : m_head{make_node(base, pages, nullptr, nullptr, true)}
+ {}
+
+ auto mmio_allocator::allocate(std::size_t count) -> kapi::memory::linear_address
+ {
+ if (count == 0 || !m_head)
+ {
+ return {};
+ }
+
+ auto current = m_head;
+ while (current)
+ {
+ if (current->page_count > count)
+ {
+ auto new_base = current->base + (count * kapi::memory::page::size);
+ auto split_node = make_node(new_base, current->page_count - count, std::move(current->next), current, true);
+
+ if (current->next)
+ {
+ current->next->previous = split_node;
+ }
+ current->next = split_node;
+ current->page_count = count;
+ }
+
+ current->is_free = false;
+ return current->base;
+ }
+
+ kapi::system::panic("[OS:MEM] MMIO alloctor out of memory!");
+ return {};
+ }
+
+ auto mmio_allocator::release(kapi::memory::linear_address base) -> void
+ {
+ auto current = m_head;
+
+ while (current)
+ {
+ if (current->base == base && !current->is_free)
+ {
+ current->is_free = true;
+
+ if (current->next && current->next->is_free)
+ {
+ auto removed = current->next;
+ current->page_count += removed->page_count;
+ current->next = removed->next;
+ if (current->next)
+ {
+ current->next->previous = current;
+ }
+ destroy_node(removed);
+ }
+
+ if (current->previous && current->previous->is_free)
+ {
+ auto removed = current;
+ removed->previous->page_count += removed->page_count;
+ removed->previous->next = removed->next;
+ if (removed->next)
+ {
+ removed->next->previous = removed->previous;
+ }
+ destroy_node(removed);
+ }
+ return;
+ }
+ current = current->next;
+ }
+ }
+
+ auto mmio_allocator::make_node(kapi::memory::linear_address base, std::size_t page_count, node * next,
+ node * previous, bool is_free) -> node *
+ {
+ using traits = std::allocator_traits<kstd::allocator<node>>;
+
+ auto new_node = traits::allocate(m_allocator, 1);
+ traits::construct(m_allocator, new_node, base, page_count, next, previous, is_free);
+ return new_node;
+ }
+
+ auto mmio_allocator::destroy_node(node * instance) -> void
+ {
+ using traits = std::allocator_traits<kstd::allocator<node>>;
+
+ traits::destroy(m_allocator, instance);
+ traits::deallocate(m_allocator, instance, 1);
+ }
+
+} // namespace kernel::memory