diff options
| author | Felix Morgner <felix.morgner@ost.ch> | 2026-04-08 13:54:52 +0200 |
|---|---|---|
| committer | Felix Morgner <felix.morgner@ost.ch> | 2026-04-08 13:54:52 +0200 |
| commit | 878852c94c4d56f303366cec177b3edef9b3b9c5 (patch) | |
| tree | b7c33b89201f6a8ae55fdc4ba041c4f1b9b97f99 /kernel | |
| parent | 0bbec5ceba0df5668ab1aedcbf2905bf599f6eba (diff) | |
| download | teachos-878852c94c4d56f303366cec177b3edef9b3b9c5.tar.xz teachos-878852c94c4d56f303366cec177b3edef9b3b9c5.zip | |
kapi: add basic support for MMIO mapping
Diffstat (limited to 'kernel')
| -rw-r--r-- | kernel/CMakeLists.txt | 41 | ||||
| -rw-r--r-- | kernel/include/kernel/memory/mmio_allocator.hpp | 41 | ||||
| -rw-r--r-- | kernel/kapi/memory.cpp | 25 | ||||
| -rw-r--r-- | kernel/src/memory/mmio_allocator.cpp | 107 |
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 |
