aboutsummaryrefslogtreecommitdiff
path: root/arch/x86_64/src/memory
diff options
context:
space:
mode:
Diffstat (limited to 'arch/x86_64/src/memory')
-rw-r--r--arch/x86_64/src/memory/page_table.cpp6
-rw-r--r--arch/x86_64/src/memory/paging_root.cpp18
-rw-r--r--arch/x86_64/src/memory/scoped_mapping.cpp77
3 files changed, 86 insertions, 15 deletions
diff --git a/arch/x86_64/src/memory/page_table.cpp b/arch/x86_64/src/memory/page_table.cpp
index 1273676..60bf94d 100644
--- a/arch/x86_64/src/memory/page_table.cpp
+++ b/arch/x86_64/src/memory/page_table.cpp
@@ -54,4 +54,10 @@ namespace teachos::memory::x86_64
std::ranges::for_each(m_entries, &page_table::entry::clear);
}
+ auto page_table::empty() const noexcept -> bool
+ {
+ return std::ranges::all_of(m_entries,
+ [](auto const & entry) -> auto { return entry.all_flags() == entry::flags::empty; });
+ }
+
} // namespace teachos::memory::x86_64
diff --git a/arch/x86_64/src/memory/paging_root.cpp b/arch/x86_64/src/memory/paging_root.cpp
index 6b65f60..a29304e 100644
--- a/arch/x86_64/src/memory/paging_root.cpp
+++ b/arch/x86_64/src/memory/paging_root.cpp
@@ -40,13 +40,27 @@ namespace teachos::memory::x86_64
auto handle_huge_page = [&] -> std::optional<frame> {
auto pml3_entry = pml3.transform([&](auto pml3) -> auto { return (*pml3)[pml_index<3>(page)]; });
- if (pml3_entry && pml3_entry->huge())
+ if (!pml3_entry)
+ {
+ return std::nullopt;
+ }
+ else if (pml3_entry->huge())
{
auto pml3_entry_frame = *pml3_entry->frame();
return frame{pml3_entry_frame.number() + pml_index<2>(page) * entry_count + pml_index<1>(page)};
}
- // auto pml3_entry = (**pml3)[page.start_address().raw() >> 39 & 0x1ff];
+ auto pml2 = (*pml3)->next(pml_index<3>(page));
+ auto pml2_entry = pml2.transform([&](auto pml2) -> auto { return (*pml2)[pml_index<2>(page)]; });
+ if (!pml2_entry)
+ {
+ return std::nullopt;
+ }
+ else if (pml2_entry->huge())
+ {
+ auto pml2_entry_frame = *pml2_entry->frame();
+ return frame{pml2_entry_frame.number() + pml_index<1>(page)};
+ }
return std::nullopt;
};
diff --git a/arch/x86_64/src/memory/scoped_mapping.cpp b/arch/x86_64/src/memory/scoped_mapping.cpp
index 27c4785..602198e 100644
--- a/arch/x86_64/src/memory/scoped_mapping.cpp
+++ b/arch/x86_64/src/memory/scoped_mapping.cpp
@@ -4,25 +4,28 @@
#include "kapi/system.hpp"
#include "x86_64/memory/mmu.hpp"
+#include "x86_64/memory/page_table.hpp"
+#include "x86_64/memory/page_utilities.hpp"
#include "x86_64/memory/paging_root.hpp"
+#include <memory>
#include <utility>
namespace teachos::memory::x86_64
{
scoped_mapping::scoped_mapping(scoped_mapping && other)
- : m_address{std::exchange(other.m_address, linear_address{})}
+ : m_page{std::exchange(other.m_page, page{})}
, m_allocator{std::exchange(other.m_allocator, nullptr)}
, m_mapped{std::exchange(other.m_mapped, false)}
{}
- scoped_mapping::scoped_mapping(linear_address address, frame_allocator & allocator)
- : m_address{address}
+ scoped_mapping::scoped_mapping(page page, frame_allocator & allocator)
+ : m_page{page}
, m_allocator{&allocator}
, m_mapped{false}
{
- if (paging_root::get().translate(address))
+ if (paging_root::get().translate(page))
{
system::panic("[MEM] Tried to map a page that is already mapped!");
}
@@ -33,7 +36,7 @@ namespace teachos::memory::x86_64
if (m_mapped)
{
unmap();
- x86_64::tlb_flush(m_address);
+ x86_64::tlb_flush(m_page.start_address());
}
}
@@ -46,7 +49,7 @@ namespace teachos::memory::x86_64
using std::swap;
- swap(m_address, other.m_address);
+ swap(m_page, other.m_page);
swap(m_allocator, other.m_allocator);
swap(m_mapped, other.m_mapped);
@@ -55,12 +58,38 @@ namespace teachos::memory::x86_64
auto scoped_mapping::map(frame frame, page_table::entry::flags flags) -> std::byte *
{
- static_cast<void>(frame);
- static_cast<void>(flags);
+ auto & pml4 = paging_root::get();
+ auto pml4_index = pml_index<4>(m_page);
+ if (!pml4[pml4_index].present())
+ {
+ auto new_frame = m_allocator->allocate();
+ pml4[pml4_index].frame(*new_frame, page_table::entry::flags::present | flags);
+ std::construct_at(pml4.next(pml4_index).value());
+ }
- m_mapped = true;
+ auto pml3 = pml4.next(pml4_index).value();
+ auto pml3_index = pml_index<3>(m_page);
+ if (!(*pml3)[pml3_index].present())
+ {
+ auto new_frame = m_allocator->allocate();
+ (*pml3)[pml3_index].frame(*new_frame, page_table::entry::flags::present | flags);
+ std::construct_at((*pml3).next(pml3_index).value());
+ }
- return nullptr;
+ auto pml2 = (*pml3).next(pml3_index).value();
+ auto pml2_index = pml_index<2>(m_page);
+ if (!(*pml2)[pml2_index].present())
+ {
+ auto new_frame = m_allocator->allocate();
+ (*pml2)[pml2_index].frame(*new_frame, page_table::entry::flags::present | flags);
+ std::construct_at((*pml2).next(pml2_index).value());
+ }
+
+ auto pml1 = (*pml2).next(pml2_index).value();
+ auto pml1_index = pml_index<1>(m_page);
+ (*pml1)[pml1_index].frame(frame, page_table::entry::flags::present | flags);
+
+ return static_cast<std::byte *>(frame.start_address());
}
auto scoped_mapping::unmap() -> void
@@ -70,9 +99,31 @@ namespace teachos::memory::x86_64
system::panic("[MEM] Tried to release an unmapped temporary mapping!");
}
- // TODO: scan pages
- // TODO: remove mapping
- // TODO: release temporary table frames
+ auto pml3 = paging_root::get().next(pml_index<4>(m_page)).value();
+ auto pml2 = pml3->next(pml_index<3>(m_page)).value();
+ auto pml1 = pml2->next(pml_index<2>(m_page)).value();
+
+ auto pml1_entry = (*pml1)[pml_index<1>(m_page)];
+ (*pml1)[pml_index<1>(m_page)].clear();
+ if (pml1->empty())
+ {
+ m_allocator->release(pml1_entry.frame().value());
+ }
+
+ auto pml2_entry = (*pml2)[pml_index<2>(m_page)];
+ (*pml2)[pml_index<2>(m_page)].clear();
+ if (pml2->empty())
+ {
+ m_allocator->release(pml2_entry.frame().value());
+ }
+
+ auto pml3_entry = (*pml3)[pml_index<3>(m_page)];
+ (*pml3)[pml_index<3>(m_page)].clear();
+ if (pml3->empty())
+ {
+ m_allocator->release(pml3_entry.frame().value());
+ }
+
m_mapped = false;
}