aboutsummaryrefslogtreecommitdiff
path: root/arch
diff options
context:
space:
mode:
authorMatteo Gmür <matteo.gmuer1@ost.ch>2024-10-21 13:35:10 +0000
committerMatteo Gmür <matteo.gmuer1@ost.ch>2024-10-21 13:35:10 +0000
commit039f12eb2f5785357ab1745201c8d420ab644165 (patch)
treef12202df532c3466c75c1069ab11c8fa36c08dc3 /arch
parent552477a12a1163f0f80801b4055dcb5ab3f79e3e (diff)
downloadteachos-039f12eb2f5785357ab1745201c8d420ab644165.tar.xz
teachos-039f12eb2f5785357ab1745201c8d420ab644165.zip
Adding more mapping methods
Diffstat (limited to 'arch')
-rw-r--r--arch/x86_64/include/arch/memory/paging/page_mapper.hpp60
-rw-r--r--arch/x86_64/src/kernel/main.cpp5
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