diff options
| author | Matteo Gmür <matteo.gmuer1@ost.ch> | 2024-10-20 12:48:51 +0000 |
|---|---|---|
| committer | Matteo Gmür <matteo.gmuer1@ost.ch> | 2024-10-20 12:48:51 +0000 |
| commit | bb8b3f9c0734220702e3e930e7acb4906aa13db6 (patch) | |
| tree | 27abc97180567298256bd211c8e1e1a6576c394b /arch | |
| parent | dd5dab7fd34c6745a16ac572ecd099e4bc26c1fb (diff) | |
| download | teachos-bb8b3f9c0734220702e3e930e7acb4906aa13db6.tar.xz teachos-bb8b3f9c0734220702e3e930e7acb4906aa13db6.zip | |
Make map_page_to_frame use concept
Diffstat (limited to 'arch')
3 files changed, 42 insertions, 36 deletions
diff --git a/arch/x86_64/include/arch/memory/allocator/area_frame_allocator.hpp b/arch/x86_64/include/arch/memory/allocator/area_frame_allocator.hpp index c9d4e7f..f99b7c8 100644 --- a/arch/x86_64/include/arch/memory/allocator/area_frame_allocator.hpp +++ b/arch/x86_64/include/arch/memory/allocator/area_frame_allocator.hpp @@ -8,6 +8,12 @@ namespace teachos::arch::memory::allocator { + template<typename T> + concept FrameAllocator = requires(T t) { + { t.allocate_frame() } -> std::same_as<std::optional<physical_frame>>; + { t.deallocate_frame() } -> std::same_as<void>; + }; + /** * @brief Allocates memory using memory areas read from the multiboot2 information pointer. */ diff --git a/arch/x86_64/include/arch/memory/paging/page_mapper.hpp b/arch/x86_64/include/arch/memory/paging/page_mapper.hpp index 635a848..5bdd82a 100644 --- a/arch/x86_64/include/arch/memory/paging/page_mapper.hpp +++ b/arch/x86_64/include/arch/memory/paging/page_mapper.hpp @@ -1,6 +1,7 @@ #ifndef TEACHOS_ARCH_X86_64_MEMORY_PAGING_PAGE_MAPPER_HPP #define TEACHOS_ARCH_X86_64_MEMORY_PAGING_PAGE_MAPPER_HPP +#include "arch/exception_handling/assert.hpp" #include "arch/memory/allocator/area_frame_allocator.hpp" #include "arch/memory/paging/virtual_page.hpp" @@ -34,16 +35,44 @@ namespace teachos::arch::memory::paging auto translate_address(std::size_t virtual_address) -> std::optional<std::size_t>; /** - * @brief Maps a virtual page to a physical frame in the page table with the specified flags. + * @brief Maps a virtual page to a physical frame in the page table with the specified flags. Allocates and maps an + * entry in every page level if it does not exists yet down to level 1. If the level 1 page table already exists it + * halts execution instead. * - * @param allocator Reference to the area frame allocator, which is used to allocate frames when a new page table is - * required. - * @param page Reference to the virtual page that is being mapped. - * @param frame The physical frame that the virtual page will be mapped to. + * @param allocator Reference to an allocator following the FrameAllocator concept, which is used to allocate entries + * when a new page table is required. + * @param page Virtual page that is being mapped. + * @param frame Physical frame that the virtual page will be mapped to. * @param flags A bitset of flags that configure the page table entry for this mapping. */ - auto map_page_to_frame(allocator::area_frame_allocator & allocator, virtual_page page, - allocator::physical_frame frame, std::bitset<64U> flags) -> void; + template<allocator::FrameAllocator T> + auto map_page_to_frame(T & allocator, virtual_page page, allocator::physical_frame frame, + std::bitset<64U> flags) -> void + + { + page_table page_table{}; + bool table_exists = false; + + for (auto level = page_table::LEVEL4; level != page_table::LEVEL1; level--) + { + std::size_t level_index = page.get_level_index(level); + table_exists = page_table.next_table(level_index); + + if (!table_exists) + { + auto allocated_frame = allocator.allocate_frame(); + exception_handling::assert(!allocated_frame.has_value(), "[Page mapper]: Unable to allocate frame"); + page_table[level_index].set_entry(allocated_frame.value(), entry::PRESENT | entry::WRITABLE); + page_table.zero_entries(); + } + } + + auto level1_entry = page_table[page.get_level_index(page_table::LEVEL1)]; + arch::exception_handling::assert(!level1_entry.contains_flags(entry::HUGE_PAGE), + "[Page Mapper]: Unable to map huge pages"); + arch::exception_handling::assert(!level1_entry.is_unused(), "[Page Mapper]: Page table entry is already used"); + level1_entry.set_entry(frame, flags | std::bitset<64U>{entry::PRESENT}); + } } // namespace teachos::arch::memory::paging #endif // TEACHOS_ARCH_X86_64_MEMORY_PAGING_PAGE_MAPPER_HPP diff --git a/arch/x86_64/src/memory/paging/page_mapper.cpp b/arch/x86_64/src/memory/paging/page_mapper.cpp index 0874230..5b72a63 100644 --- a/arch/x86_64/src/memory/paging/page_mapper.cpp +++ b/arch/x86_64/src/memory/paging/page_mapper.cpp @@ -1,7 +1,5 @@ #include "arch/memory/paging/page_mapper.hpp" -#include "arch/exception_handling/assert.hpp" - namespace teachos::arch::memory::paging { auto translate_page(virtual_page page) -> std::optional<allocator::physical_frame> @@ -76,31 +74,4 @@ namespace teachos::arch::memory::paging return std::nullopt; } - - auto map_page_to_frame(allocator::area_frame_allocator & allocator, virtual_page page, - allocator::physical_frame frame, std::bitset<64U> flags) -> void - { - page_table page_table{}; - bool table_exists = false; - - for (auto level = page_table::LEVEL4; level != page_table::LEVEL1; level--) - { - std::size_t level_index = page.get_level_index(level); - table_exists = page_table.next_table(level_index); - - if (!table_exists) - { - auto allocated_frame = allocator.allocate_frame(); - exception_handling::assert(!allocated_frame.has_value(), "[Page mapper]: Unable to allocate frame"); - page_table[level_index].set_entry(allocated_frame.value(), entry::PRESENT | entry::WRITABLE); - page_table.zero_entries(); - } - } - - auto level1_entry = page_table[page.get_level_index(page_table::LEVEL1)]; - arch::exception_handling::assert(!level1_entry.contains_flags(entry::HUGE_PAGE), - "[Page Mapper]: Unable to map huge pages"); - arch::exception_handling::assert(!level1_entry.is_unused(), "[Page Mapper]: Page table entry is already used"); - level1_entry.set_entry(frame, flags | std::bitset<64U>{entry::PRESENT}); - } } // namespace teachos::arch::memory::paging |
