diff options
Diffstat (limited to 'arch/x86_64')
| -rw-r--r-- | arch/x86_64/include/arch/memory/paging/page_mapper.hpp | 60 | ||||
| -rw-r--r-- | arch/x86_64/src/kernel/main.cpp | 5 |
2 files changed, 65 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 diff --git a/arch/x86_64/src/kernel/main.cpp b/arch/x86_64/src/kernel/main.cpp index 88f6329..8e5aa05 100644 --- a/arch/x86_64/src/kernel/main.cpp +++ b/arch/x86_64/src/kernel/main.cpp @@ -3,6 +3,7 @@ #include "arch/exception_handling/assert.hpp" #include "arch/memory/allocator/area_frame_allocator.hpp" #include "arch/memory/multiboot/reader.hpp" +#include "arch/memory/paging/page_mapper.hpp" #include "arch/video/vga/text.hpp" #include <algorithm> @@ -28,5 +29,9 @@ namespace teachos::arch::kernel video::vga::text::write("Allocated Frames", video::vga::text::common_attributes::green_on_black); video::vga::text::write_number(last_allocated.value().frame_number, video::vga::text::common_attributes::green_on_black); + memory::paging::map_page_to_frame(allocator, memory::paging::virtual_page{0U}, last_allocated.value(), 0U); + memory::paging::map_next_free_page_to_frame(allocator, memory::paging::virtual_page{0U}, 0U); + memory::paging::identity_map(allocator, last_allocated.value(), 0U); + memory::paging::unmap_page(allocator, memory::paging::virtual_page{0U}); } } // namespace teachos::arch::kernel |
