aboutsummaryrefslogtreecommitdiff
path: root/arch
diff options
context:
space:
mode:
authorFabian Imhof <fabian.imhof@ost.ch>2024-10-29 07:32:24 +0000
committerFabian Imhof <fabian.imhof@ost.ch>2024-10-29 07:32:24 +0000
commit4c4479a4b728fd7eaf007649e946f9435ee1e402 (patch)
treeb30c7da674a9671d75fff13575928480418feb8f /arch
parent0d16592c8dce876d8e621c73dea41c33339f3173 (diff)
downloadteachos-4c4479a4b728fd7eaf007649e946f9435ee1e402.tar.xz
teachos-4c4479a4b728fd7eaf007649e946f9435ee1e402.zip
implement page_table unmapping
Diffstat (limited to 'arch')
-rw-r--r--arch/x86_64/include/arch/memory/paging/page_mapper.hpp41
-rw-r--r--arch/x86_64/include/arch/memory/paging/page_table.hpp7
-rw-r--r--arch/x86_64/src/memory/paging/page_table.cpp5
3 files changed, 44 insertions, 9 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 0ef552a..801ccfb 100644
--- a/arch/x86_64/include/arch/memory/paging/page_mapper.hpp
+++ b/arch/x86_64/include/arch/memory/paging/page_mapper.hpp
@@ -5,6 +5,8 @@
#include "arch/memory/allocator/area_frame_allocator.hpp"
#include "arch/memory/paging/virtual_page.hpp"
+#include <algorithm>
+#include <array>
#include <optional>
namespace teachos::arch::memory::paging
@@ -22,6 +24,28 @@ namespace teachos::arch::memory::paging
{
asm volatile("invlpg (%0)" ::"r"(address) : "memory");
}
+
+ /**
+ * @brief Unmaps specific page at the current internal handle level.
+ *
+ * @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.
+ * @param handle Page Table handle we want to access the entry that should be cleared on.
+ */
+ template<allocator::FrameAllocator T>
+ auto unmap_page_table_entry(T & allocator, virtual_page page, page_table_handle & handle) -> void
+ {
+ auto level_index = page.get_level_index(handle.get_level());
+ auto & entry = handle[level_index];
+ auto const frame = entry.calculate_pointed_to_frame();
+ exception_handling::assert(frame.has_value(),
+ "[Page Mapper] Attempted to unmap page, which has not been mapped previously");
+ entry.set_unused();
+ allocator.deallocate_frame(frame.value());
+ }
} // namespace
/**
@@ -135,8 +159,12 @@ namespace teachos::arch::memory::paging
auto current_handle = create_or_get();
+ std::array<page_table_handle *, 4> handles{};
+
for (auto level = page_table_handle::LEVEL4; level != page_table_handle::LEVEL1; --level)
{
+ handles[level] = *current_handle;
+
auto const level_index = page.get_level_index(level);
auto const 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.
@@ -145,14 +173,11 @@ namespace teachos::arch::memory::paging
current_handle = next_handle.value();
}
- auto & level1_entry = current_handle[page.get_level_index(page_table_handle::LEVEL1)];
- auto const 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.
- // TODO: Fix deallocate because it is not yet implemented.
- allocator.deallocate_frame(level1_frame.value());
+ std::ranges::for_each(handles, [&allocator, page](page_table_handle * handle) {
+ exception_handling::assert(handle != nullptr, "[Page Mapper] Attempted to unmap page behind nullpointer");
+ unmap_page_table_entry(allocator, page, *handle);
+ });
+
invalidate_page_cache(page.start_address());
}
} // namespace teachos::arch::memory::paging
diff --git a/arch/x86_64/include/arch/memory/paging/page_table.hpp b/arch/x86_64/include/arch/memory/paging/page_table.hpp
index 07e7e22..02ed099 100644
--- a/arch/x86_64/include/arch/memory/paging/page_table.hpp
+++ b/arch/x86_64/include/arch/memory/paging/page_table.hpp
@@ -62,6 +62,13 @@ namespace teachos::arch::memory::paging
auto is_empty() const -> bool;
/**
+ * @brief Get the current handle level.
+ *
+ * @return Current handle level.
+ */
+ auto get_level() const -> level;
+
+ /**
* @brief Returns the next page table level from the given page table index. Meaning we
* use an index into a Level 4 page table to get the according Level 3 page table.
*
diff --git a/arch/x86_64/src/memory/paging/page_table.cpp b/arch/x86_64/src/memory/paging/page_table.cpp
index 64a4fd9..0121e95 100644
--- a/arch/x86_64/src/memory/paging/page_table.cpp
+++ b/arch/x86_64/src/memory/paging/page_table.cpp
@@ -92,7 +92,8 @@ namespace teachos::arch::memory::paging
: handle(handle)
, handle_level(handle_level)
{
- exception_handling::assert(handle, "[Page Table] Attempted to pass nullptr as handle to page table handle method");
+ exception_handling::assert(handle != nullptr,
+ "[Page Table] Attempted to pass nullptr as handle to page table handle method");
}
auto page_table_handle::initialize_page_tables() -> void
@@ -133,6 +134,8 @@ namespace teachos::arch::memory::paging
return std::nullopt;
}
+ auto page_table_handle::get_level() const -> page_table_handle::level { return handle_level; }
+
auto page_table_handle::operator[](std::size_t index) -> entry & { return handle->operator[](index); }
auto operator--(page_table_handle::level & value) -> page_table_handle::level &