diff options
| author | Matteo Gmür <matteo.gmuer1@ost.ch> | 2024-10-21 13:35:10 +0000 |
|---|---|---|
| committer | Matteo Gmür <matteo.gmuer1@ost.ch> | 2024-10-21 13:35:10 +0000 |
| commit | 039f12eb2f5785357ab1745201c8d420ab644165 (patch) | |
| tree | f12202df532c3466c75c1069ab11c8fa36c08dc3 /arch/x86_64/include | |
| parent | 552477a12a1163f0f80801b4055dcb5ab3f79e3e (diff) | |
| download | teachos-039f12eb2f5785357ab1745201c8d420ab644165.tar.xz teachos-039f12eb2f5785357ab1745201c8d420ab644165.zip | |
Adding more mapping methods
Diffstat (limited to 'arch/x86_64/include')
| -rw-r--r-- | arch/x86_64/include/arch/memory/paging/page_mapper.hpp | 60 |
1 files changed, 60 insertions, 0 deletions
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 0806f58..0f226e2 100644 --- a/arch/x86_64/include/arch/memory/paging/page_mapper.hpp +++ b/arch/x86_64/include/arch/memory/paging/page_mapper.hpp @@ -48,6 +48,8 @@ namespace teachos::arch::memory::paging * 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. * + * @tparam T Type constraint of the allocator, being that is follows the given concept and contains an allocate and + * deallocate method. * @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. @@ -88,6 +90,64 @@ namespace teachos::arch::memory::paging 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}); } + + /** + * @brief Allocates the next free frame and then uses that frame to call map_page_to_frame. + */ + template<allocator::FrameAllocator T> + auto map_next_free_page_to_frame(T & allocator, virtual_page page, std::bitset<64U> flags) -> void + { + auto frame = allocator.allocate_frame(); + exception_handling::assert(!frame.has_value(), "[Page mapper] Out of memory exception"); + map_page_to_frame(allocator, page, frame.value(), flags); + } + + /** + * @brief Gets the corresponding page the given frame has to be contained in and uses that to call map_page_to_frame. + */ + template<allocator::FrameAllocator T> + auto identity_map(T & allocator, allocator::physical_frame frame, std::bitset<64U> flags) -> void + { + auto page = virtual_page::containing_address(frame.start_address()); + map_page_to_frame(allocator, page, frame, flags); + } + + /** + * @brief Unmaps the virtual page from the previously mapped to physical frame and resets the flags. Deallocates and + * unmaps the entry in every page level if this page was the last one up to level 4. + * + * @tparam T Type constraint of the allocator, being that is follows the given concept and contains an allocate and + * deallocate method. + * @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 unmapped. + */ + template<allocator::FrameAllocator T> + auto unmap_page(T & allocator, virtual_page page) -> void + { + exception_handling::assert(translate_page(page).has_value(), + "[Page Mapper] Attempted to unmap page, which has not been mapped previously"); + + auto current_handle = create_or_get(); + + for (auto level = page_table_handle::LEVEL4; level != page_table_handle::LEVEL1; level--) + { + auto level_index = page.get_level_index(level); + auto next_handle = current_handle.next_table(level_index); + // The next table method failed even tough the page has to be mapped already, because translate_page did not fail. + // This can only mean that we attempted to unmap a huge page, which is not supported in the first place. + exception_handling::assert(next_handle.has_value(), "[Page Mapper] Unable to unmap huge pages"); + current_handle = next_handle.value(); + } + + auto level1_entry = current_handle[page.get_level_index(page_table_handle::LEVEL1)]; + auto level1_frame = level1_entry.calculate_pointed_to_frame(); + exception_handling::assert(level1_frame.has_value(), + "[Page Mapper] Attempted to unmap page, which has not been mapped previously"); + level1_entry.set_unused(); + // TODO: Deallocate and unmap level 1, 2, 3 page table entry if this was the last page in them. + allocator.deallocate_frame(level1_frame.value()); + } } // namespace teachos::arch::memory::paging #endif // TEACHOS_ARCH_X86_64_MEMORY_PAGING_PAGE_MAPPER_HPP |
