aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--arch/x86_64/include/arch/memory/allocator/area_frame_allocator.hpp6
-rw-r--r--arch/x86_64/include/arch/memory/paging/page_mapper.hpp43
-rw-r--r--arch/x86_64/src/memory/paging/page_mapper.cpp29
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