From 675f38d6733fb19b4ffc7e9fbddb93acdd1d1e31 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matteo=20Gm=C3=BCr?= Date: Sat, 19 Oct 2024 14:40:25 +0000 Subject: Seperate allocation and paging code into multiple files as well --- arch/x86_64/src/memory/paging/page_entry.cpp | 42 ++++++++++++++++++ arch/x86_64/src/memory/paging/page_table.cpp | 65 ++++++++++++++++++++++++++++ 2 files changed, 107 insertions(+) create mode 100644 arch/x86_64/src/memory/paging/page_entry.cpp create mode 100644 arch/x86_64/src/memory/paging/page_table.cpp (limited to 'arch/x86_64/src/memory/paging') diff --git a/arch/x86_64/src/memory/paging/page_entry.cpp b/arch/x86_64/src/memory/paging/page_entry.cpp new file mode 100644 index 0000000..43c0b71 --- /dev/null +++ b/arch/x86_64/src/memory/paging/page_entry.cpp @@ -0,0 +1,42 @@ +#include "arch/memory/paging/page_entry.hpp" + +#include "arch/exception_handling/assert.hpp" + +namespace teachos::arch::memory::paging +{ + auto entry::is_unused() const -> bool { return flags == 0U; } + + auto entry::set_unused() -> void { flags = 0U; } + + auto entry::calculate_pointed_to_frame() const -> std::optional + { + if (contains_flags(PRESENT)) + { + auto physical_address = calculate_physical_address(); + return allocator::physical_frame::containing_address(physical_address); + } + return std::nullopt; + } + + auto entry::calculate_physical_address() const -> std::size_t + { + constexpr std::size_t start_bit = 12U; + constexpr std::size_t end_bit = 52U; + size_t value = 0U; + + for (auto i = start_bit; i < end_bit; i++) + { + value |= (flags[i] ? (1 << (i - start_bit)) : 0); + } + return value; + } + + auto entry::contains_flags(std::bitset<64U> other) const -> bool { return (flags & other) == other; } + + auto entry::set_address(allocator::physical_frame frame) -> void + { + arch::exception_handling::assert((frame.start_address() & ~0x000fffff'fffff000) == 0, + "Start address is not aligned with Page"); + flags = std::bitset<64U>(frame.start_address()) | flags; + } +} // namespace teachos::arch::memory::paging diff --git a/arch/x86_64/src/memory/paging/page_table.cpp b/arch/x86_64/src/memory/paging/page_table.cpp new file mode 100644 index 0000000..a1cbc72 --- /dev/null +++ b/arch/x86_64/src/memory/paging/page_table.cpp @@ -0,0 +1,65 @@ +#include "arch/memory/paging/page_table.hpp" + +#include "arch/exception_handling/assert.hpp" + +namespace teachos::arch::memory::paging +{ + page_table::page_table() + : current_level(LEVEL4) + , current_table(reinterpret_cast(0xfffffffffffff000)) + { + // Nothing to do + } + + auto page_table::zero_entries() -> void + { + constexpr size_t entry_amount = sizeof(current_table->entries) / sizeof(current_table->entries[0]); + for (size_t i = 0; i < entry_amount; ++i) + { + auto entry = this->operator[](i); + entry.set_unused(); + } + } + + auto page_table::next_table(std::size_t table_index) -> void + { + arch::exception_handling::assert(current_level != LEVEL1, + "[Page Table] Attempted to call next_table on level 1 page table"); + auto address = next_table_address(table_index); + + if (address.has_value()) + { + current_table = reinterpret_cast(*address); + current_level = static_cast(current_level - 1U); + } + } + + auto page_table::operator[](std::size_t index) -> entry & + { + // C array is not bounds checked, therefore we have to check ourselves, to ensure no out of bounds reads, which + // could be incredibly hard to debug later. + arch::exception_handling::assert(index < PAGE_TABLE_ENTRY_COUNT, "[Page Table] index out of bounds"); + return current_table->entries[index]; + } + + auto page_table::operator[](std::size_t index) const -> entry const & + { + // C array is not bounds checked, therefore we have to check ourselves, to ensure no out of bounds reads, which + // could be incredibly hard to debug later. + arch::exception_handling::assert(index < PAGE_TABLE_ENTRY_COUNT, "[Page Table] index out of bounds"); + return current_table->entries[index]; + } + + auto page_table::next_table_address(std::size_t table_index) const -> std::optional + { + auto entry = this->operator[](table_index); + + if (entry.contains_flags(entry::PRESENT) && !entry.contains_flags(entry::HUGE_PAGE)) + { + std::size_t const table_address = reinterpret_cast(this); + return (table_address << 9) | (table_index << 12); + } + // TODO: Implement behaviour for huge pages currently not done + return std::nullopt; + } +} // namespace teachos::arch::memory::paging -- cgit v1.2.3 From 7ebfe9e09efa84044d1470132b7f55ebf53a7f89 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matteo=20Gm=C3=BCr?= Date: Sun, 20 Oct 2024 06:32:02 +0000 Subject: Fix next_table_address --- arch/x86_64/src/memory/paging/page_table.cpp | 14 +++----------- 1 file changed, 3 insertions(+), 11 deletions(-) (limited to 'arch/x86_64/src/memory/paging') diff --git a/arch/x86_64/src/memory/paging/page_table.cpp b/arch/x86_64/src/memory/paging/page_table.cpp index a1cbc72..786ff69 100644 --- a/arch/x86_64/src/memory/paging/page_table.cpp +++ b/arch/x86_64/src/memory/paging/page_table.cpp @@ -29,7 +29,7 @@ namespace teachos::arch::memory::paging if (address.has_value()) { - current_table = reinterpret_cast(*address); + current_table = reinterpret_cast(address.value()); current_level = static_cast(current_level - 1U); } } @@ -42,21 +42,13 @@ namespace teachos::arch::memory::paging return current_table->entries[index]; } - auto page_table::operator[](std::size_t index) const -> entry const & - { - // C array is not bounds checked, therefore we have to check ourselves, to ensure no out of bounds reads, which - // could be incredibly hard to debug later. - arch::exception_handling::assert(index < PAGE_TABLE_ENTRY_COUNT, "[Page Table] index out of bounds"); - return current_table->entries[index]; - } - - auto page_table::next_table_address(std::size_t table_index) const -> std::optional + auto page_table::next_table_address(std::size_t table_index) -> std::optional { auto entry = this->operator[](table_index); if (entry.contains_flags(entry::PRESENT) && !entry.contains_flags(entry::HUGE_PAGE)) { - std::size_t const table_address = reinterpret_cast(this); + std::size_t const table_address = reinterpret_cast(current_table); return (table_address << 9) | (table_index << 12); } // TODO: Implement behaviour for huge pages currently not done -- cgit v1.2.3 From d728052d62470799f73f6d9a2b8baa2b0b357383 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matteo=20Gm=C3=BCr?= Date: Sun, 20 Oct 2024 07:01:53 +0000 Subject: Add helper methods to phyisca frame --- arch/x86_64/src/memory/paging/page_entry.cpp | 4 ++-- arch/x86_64/src/memory/paging/page_table.cpp | 6 +++--- arch/x86_64/src/memory/paging/virtual_page.cpp | 22 ++++++++++++++++++++++ 3 files changed, 27 insertions(+), 5 deletions(-) create mode 100644 arch/x86_64/src/memory/paging/virtual_page.cpp (limited to 'arch/x86_64/src/memory/paging') diff --git a/arch/x86_64/src/memory/paging/page_entry.cpp b/arch/x86_64/src/memory/paging/page_entry.cpp index 43c0b71..692f8ae 100644 --- a/arch/x86_64/src/memory/paging/page_entry.cpp +++ b/arch/x86_64/src/memory/paging/page_entry.cpp @@ -35,8 +35,8 @@ namespace teachos::arch::memory::paging auto entry::set_address(allocator::physical_frame frame) -> void { - arch::exception_handling::assert((frame.start_address() & ~0x000fffff'fffff000) == 0, - "Start address is not aligned with Page"); + exception_handling::assert((frame.start_address() & ~0x000fffff'fffff000) == 0, + "Start address is not aligned with Page"); flags = std::bitset<64U>(frame.start_address()) | flags; } } // namespace teachos::arch::memory::paging diff --git a/arch/x86_64/src/memory/paging/page_table.cpp b/arch/x86_64/src/memory/paging/page_table.cpp index 786ff69..8345161 100644 --- a/arch/x86_64/src/memory/paging/page_table.cpp +++ b/arch/x86_64/src/memory/paging/page_table.cpp @@ -23,8 +23,8 @@ namespace teachos::arch::memory::paging auto page_table::next_table(std::size_t table_index) -> void { - arch::exception_handling::assert(current_level != LEVEL1, - "[Page Table] Attempted to call next_table on level 1 page table"); + exception_handling::assert(current_level != LEVEL1, + "[Page Table] Attempted to call next_table on level 1 page table"); auto address = next_table_address(table_index); if (address.has_value()) @@ -38,7 +38,7 @@ namespace teachos::arch::memory::paging { // C array is not bounds checked, therefore we have to check ourselves, to ensure no out of bounds reads, which // could be incredibly hard to debug later. - arch::exception_handling::assert(index < PAGE_TABLE_ENTRY_COUNT, "[Page Table] index out of bounds"); + exception_handling::assert(index < PAGE_TABLE_ENTRY_COUNT, "[Page Table] index out of bounds"); return current_table->entries[index]; } diff --git a/arch/x86_64/src/memory/paging/virtual_page.cpp b/arch/x86_64/src/memory/paging/virtual_page.cpp new file mode 100644 index 0000000..3fb6caf --- /dev/null +++ b/arch/x86_64/src/memory/paging/virtual_page.cpp @@ -0,0 +1,22 @@ +#include "arch/memory/paging/virtual_page.hpp" + +#include "arch/exception_handling/assert.hpp" +#include "arch/memory/allocator/physical_frame.hpp" + +namespace teachos::arch::memory::paging +{ + virtual_page::virtual_page(std::size_t page_number) + : page_number(page_number) + { + // Nothing to do + } + + auto virtual_page::containing_address(std::size_t virtual_address) -> virtual_page + { + exception_handling::assert(virtual_address < 0x0000800000000000 || virtual_address >= 0xffff800000000000, + "[Virtual Page] Attempted to create virtual page from invalid address"); + return virtual_page{virtual_address / allocator::PAGE_FRAME_SIZE}; + } + + auto virtual_page::start_address() const -> uint64_t { return page_number * allocator::PAGE_FRAME_SIZE; } +} // namespace teachos::arch::memory::paging -- cgit v1.2.3 From e5206b3bf1883fd9601a37f5cce392d8080b8791 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matteo=20Gm=C3=BCr?= Date: Sun, 20 Oct 2024 07:43:00 +0000 Subject: Add get level index method to virtual page --- arch/x86_64/src/memory/paging/page_table.cpp | 8 ++------ arch/x86_64/src/memory/paging/virtual_page.cpp | 5 +++++ 2 files changed, 7 insertions(+), 6 deletions(-) (limited to 'arch/x86_64/src/memory/paging') diff --git a/arch/x86_64/src/memory/paging/page_table.cpp b/arch/x86_64/src/memory/paging/page_table.cpp index 8345161..9857294 100644 --- a/arch/x86_64/src/memory/paging/page_table.cpp +++ b/arch/x86_64/src/memory/paging/page_table.cpp @@ -26,12 +26,8 @@ namespace teachos::arch::memory::paging exception_handling::assert(current_level != LEVEL1, "[Page Table] Attempted to call next_table on level 1 page table"); auto address = next_table_address(table_index); - - if (address.has_value()) - { - current_table = reinterpret_cast(address.value()); - current_level = static_cast(current_level - 1U); - } + current_table = reinterpret_cast(address.value()); + current_level = static_cast(current_level - 1U); } auto page_table::operator[](std::size_t index) -> entry & diff --git a/arch/x86_64/src/memory/paging/virtual_page.cpp b/arch/x86_64/src/memory/paging/virtual_page.cpp index 3fb6caf..dcdec7f 100644 --- a/arch/x86_64/src/memory/paging/virtual_page.cpp +++ b/arch/x86_64/src/memory/paging/virtual_page.cpp @@ -19,4 +19,9 @@ namespace teachos::arch::memory::paging } auto virtual_page::start_address() const -> uint64_t { return page_number * allocator::PAGE_FRAME_SIZE; } + + auto virtual_page::get_level_index(page_table::level level) const -> uint64_t + { + return (start_address() >> (level * 9U)) & 0x1FF; + } } // namespace teachos::arch::memory::paging -- cgit v1.2.3 From f8928c877c48b5beba9bb42876f70213aba68f88 Mon Sep 17 00:00:00 2001 From: Fabian Imhof Date: Sun, 20 Oct 2024 07:46:51 +0000 Subject: translate --- arch/x86_64/src/memory/paging/page_table.cpp | 2 +- arch/x86_64/src/memory/paging/virtual_page.cpp | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) (limited to 'arch/x86_64/src/memory/paging') diff --git a/arch/x86_64/src/memory/paging/page_table.cpp b/arch/x86_64/src/memory/paging/page_table.cpp index 9857294..3fb7a3f 100644 --- a/arch/x86_64/src/memory/paging/page_table.cpp +++ b/arch/x86_64/src/memory/paging/page_table.cpp @@ -45,7 +45,7 @@ namespace teachos::arch::memory::paging if (entry.contains_flags(entry::PRESENT) && !entry.contains_flags(entry::HUGE_PAGE)) { std::size_t const table_address = reinterpret_cast(current_table); - return (table_address << 9) | (table_index << 12); + return ((table_address << 9) | (table_index << 12)); } // TODO: Implement behaviour for huge pages currently not done return std::nullopt; diff --git a/arch/x86_64/src/memory/paging/virtual_page.cpp b/arch/x86_64/src/memory/paging/virtual_page.cpp index dcdec7f..9b803d2 100644 --- a/arch/x86_64/src/memory/paging/virtual_page.cpp +++ b/arch/x86_64/src/memory/paging/virtual_page.cpp @@ -1,7 +1,6 @@ #include "arch/memory/paging/virtual_page.hpp" #include "arch/exception_handling/assert.hpp" -#include "arch/memory/allocator/physical_frame.hpp" namespace teachos::arch::memory::paging { -- cgit v1.2.3 From 882ccdcc0e3c19fbcc595c6a371ef79587f63648 Mon Sep 17 00:00:00 2001 From: Fabian Imhof Date: Sun, 20 Oct 2024 08:11:19 +0000 Subject: implement translate_page --- arch/x86_64/src/memory/paging/page_table.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch/x86_64/src/memory/paging') diff --git a/arch/x86_64/src/memory/paging/page_table.cpp b/arch/x86_64/src/memory/paging/page_table.cpp index 3fb7a3f..3c4f6d8 100644 --- a/arch/x86_64/src/memory/paging/page_table.cpp +++ b/arch/x86_64/src/memory/paging/page_table.cpp @@ -21,7 +21,7 @@ namespace teachos::arch::memory::paging } } - auto page_table::next_table(std::size_t table_index) -> void + auto page_table::next_table(std::size_t table_index) -> bool { exception_handling::assert(current_level != LEVEL1, "[Page Table] Attempted to call next_table on level 1 page table"); -- cgit v1.2.3 From 89ad7a0b60ce74c70fc3865e0967c601a6050674 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matteo=20Gm=C3=BCr?= Date: Sun, 20 Oct 2024 08:13:31 +0000 Subject: Make next table return boolean --- arch/x86_64/src/memory/paging/page_table.cpp | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) (limited to 'arch/x86_64/src/memory/paging') diff --git a/arch/x86_64/src/memory/paging/page_table.cpp b/arch/x86_64/src/memory/paging/page_table.cpp index 3c4f6d8..ab7331a 100644 --- a/arch/x86_64/src/memory/paging/page_table.cpp +++ b/arch/x86_64/src/memory/paging/page_table.cpp @@ -26,8 +26,13 @@ namespace teachos::arch::memory::paging exception_handling::assert(current_level != LEVEL1, "[Page Table] Attempted to call next_table on level 1 page table"); auto address = next_table_address(table_index); - current_table = reinterpret_cast(address.value()); - current_level = static_cast(current_level - 1U); + bool const success = address.has_value(); + if (success) + { + current_table = reinterpret_cast(address.value()); + current_level = static_cast(current_level - 1U); + } + return success; } auto page_table::operator[](std::size_t index) -> entry & @@ -47,7 +52,6 @@ namespace teachos::arch::memory::paging std::size_t const table_address = reinterpret_cast(current_table); return ((table_address << 9) | (table_index << 12)); } - // TODO: Implement behaviour for huge pages currently not done return std::nullopt; } } // namespace teachos::arch::memory::paging -- cgit v1.2.3 From d934ea6875932a7139eba77bb5248fca8be7fd01 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matteo=20Gm=C3=BCr?= Date: Sun, 20 Oct 2024 08:37:49 +0000 Subject: =?UTF-8?q?Implement=20translate=20page=20in=20a=20big=20brain=20w?= =?UTF-8?q?ay=20=F0=9F=A4=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- arch/x86_64/src/memory/paging/page_table.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'arch/x86_64/src/memory/paging') diff --git a/arch/x86_64/src/memory/paging/page_table.cpp b/arch/x86_64/src/memory/paging/page_table.cpp index ab7331a..02ababe 100644 --- a/arch/x86_64/src/memory/paging/page_table.cpp +++ b/arch/x86_64/src/memory/paging/page_table.cpp @@ -54,4 +54,12 @@ namespace teachos::arch::memory::paging } return std::nullopt; } + + auto operator--(page_table::level & level, int) -> page_table::level + { + exception_handling::assert(level != page_table::LEVEL1, + "[Page table] Attemptd to decrement enum to value outside of range"); + auto value = static_cast::type>(level); + return static_cast(--value); + } } // namespace teachos::arch::memory::paging -- cgit v1.2.3 From 1d157101eb550f99dac9ec943053f85bbf6c7644 Mon Sep 17 00:00:00 2001 From: Fabian Imhof Date: Sun, 20 Oct 2024 09:03:30 +0000 Subject: create page_mapper --- arch/x86_64/src/memory/paging/page_mapper.cpp | 57 +++++++++++++++++++++++++++ 1 file changed, 57 insertions(+) create mode 100644 arch/x86_64/src/memory/paging/page_mapper.cpp (limited to 'arch/x86_64/src/memory/paging') diff --git a/arch/x86_64/src/memory/paging/page_mapper.cpp b/arch/x86_64/src/memory/paging/page_mapper.cpp new file mode 100644 index 0000000..5372561 --- /dev/null +++ b/arch/x86_64/src/memory/paging/page_mapper.cpp @@ -0,0 +1,57 @@ +#include "arch/exception_handling/assert.hpp" +#include "arch/memory/allocator/area_frame_allocator.hpp" +#include "arch/memory/paging/virtual_page.hpp" + +namespace teachos::arch::memory::paging +{ + auto translate_page(virtual_page page) -> std::optional + { + page_table page_table{}; + bool is_valid = false; + auto huge_page = []() -> std::optional { return std::nullopt; }; + + for (auto level = page_table::LEVEL4; level != page_table::LEVEL1; level--) + { + is_valid = page_table.next_table(page.get_level_index(level)); + if (!is_valid) + { + break; + } + } + + if (is_valid) + { + auto level1_index = page.get_level_index(page_table::LEVEL1); + auto frame = page_table[level1_index].calculate_pointed_to_frame(); + return frame; + } + + return huge_page(); + } + + auto translate_address(std::size_t virtual_address) -> std::optional + { + std::size_t offset = virtual_address % allocator::PAGE_FRAME_SIZE; + virtual_page page = virtual_page::containing_address(virtual_address); + std::optional frame = translate_page(page); + + if (frame.has_value()) + { + return frame.value().frame_number * allocator::PAGE_FRAME_SIZE + offset; + } + + return std::nullopt; + } + + auto map_page_to_frame(memory::allocator::area_frame_allocator & allocator, const virtual_page & page, + const memory::allocator::physical_frame & frame, entry::bitset flags) -> void + { + auto p4 = reinterpret_cast(P4); // Assuming P4 is defined somewhere + auto p3 = p4->next_table_create(page.p4_index(), allocator); + auto p2 = p3->next_table_create(page.p3_index(), allocator); + auto p1 = p2->next_table_create(page.p2_index(), allocator); + + assert(p1[page.p1_index()].is_unused()); + p1[page.p1_index()].set(frame, flags | PRESENT); + } +} // namespace teachos::arch::memory::paging \ No newline at end of file -- cgit v1.2.3 From 04bd6a059b9eb105024044d74122b0cb76cebf14 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matteo=20Gm=C3=BCr?= Date: Sun, 20 Oct 2024 09:34:03 +0000 Subject: Add translate huge page method --- arch/x86_64/src/memory/paging/page_mapper.cpp | 44 ++++++++++++++++++++++++--- 1 file changed, 40 insertions(+), 4 deletions(-) (limited to 'arch/x86_64/src/memory/paging') diff --git a/arch/x86_64/src/memory/paging/page_mapper.cpp b/arch/x86_64/src/memory/paging/page_mapper.cpp index 5372561..e68bc68 100644 --- a/arch/x86_64/src/memory/paging/page_mapper.cpp +++ b/arch/x86_64/src/memory/paging/page_mapper.cpp @@ -8,7 +8,8 @@ namespace teachos::arch::memory::paging { page_table page_table{}; bool is_valid = false; - auto huge_page = []() -> std::optional { return std::nullopt; }; + + auto huge_page = [&]() -> std::optional {}; for (auto level = page_table::LEVEL4; level != page_table::LEVEL1; level--) { @@ -22,11 +23,46 @@ namespace teachos::arch::memory::paging if (is_valid) { auto level1_index = page.get_level_index(page_table::LEVEL1); - auto frame = page_table[level1_index].calculate_pointed_to_frame(); - return frame; + auto level1_frame = page_table[level1_index].calculate_pointed_to_frame(); + return level1_frame; } - return huge_page(); + return translate_huge_page(page); + } + + auto translate_huge_page(virtual_page page) -> std::optional + { + page_table page_table{}; + bool is_valid = page_table.next_table(page.get_level_index(page_table::LEVEL3)); + + if (is_valid) + { + auto level3_entry = page_table[page.get_level_index(page_table::LEVEL3)]; + auto level3_optional_frame = level3_entry.calculate_pointed_to_frame(); + if (level3_optional_frame.has_value() && level3_entry.contains_flags(entry::HUGE_PAGE)) + { + auto level3_frame = level3_optional_frame.value(); + exception_handling::assert(level3_frame.frame_number % (PAGE_TABLE_ENTRY_COUNT * PAGE_TABLE_ENTRY_COUNT) == 0U, + "[Page Mapper] Physical address must be 1 GiB aligned"); + return allocator::physical_frame{level3_frame.frame_number + + page.get_level_index(page_table::LEVEL2) * PAGE_TABLE_ENTRY_COUNT + + page.get_level_index(page_table::LEVEL1)}; + } + } + is_valid = page_table.next_table(page.get_level_index(page_table::LEVEL3)); + if (is_valid) + { + auto level2_entry = page_table[page.get_level_index(page_table::LEVEL2)]; + auto level2_optional_frame = level2_entry.calculate_pointed_to_frame(); + if (level2_optional_frame.has_value() && level2_entry.contains_flags(entry::HUGE_PAGE)) + { + auto level2_frame = level2_optional_frame.value(); + exception_handling::assert(level2_frame.frame_number % PAGE_TABLE_ENTRY_COUNT == 0U, + "[Page Mapper] Physical address must be 2 MiB aligned"); + return allocator::physical_frame{level2_frame.frame_number + page.get_level_index(page_table::LEVEL1)}; + } + } + return std::nullopt; } auto translate_address(std::size_t virtual_address) -> std::optional -- cgit v1.2.3 From ecf89844100248db3ad08d5c76091de563488b95 Mon Sep 17 00:00:00 2001 From: Fabian Imhof Date: Sun, 20 Oct 2024 09:37:08 +0000 Subject: implement map_page_to_frame --- arch/x86_64/src/memory/paging/page_entry.cpp | 4 ++-- arch/x86_64/src/memory/paging/page_mapper.cpp | 32 ++++++++++++++++++--------- 2 files changed, 24 insertions(+), 12 deletions(-) (limited to 'arch/x86_64/src/memory/paging') diff --git a/arch/x86_64/src/memory/paging/page_entry.cpp b/arch/x86_64/src/memory/paging/page_entry.cpp index 692f8ae..0dbbae1 100644 --- a/arch/x86_64/src/memory/paging/page_entry.cpp +++ b/arch/x86_64/src/memory/paging/page_entry.cpp @@ -33,10 +33,10 @@ namespace teachos::arch::memory::paging auto entry::contains_flags(std::bitset<64U> other) const -> bool { return (flags & other) == other; } - auto entry::set_address(allocator::physical_frame frame) -> void + auto entry::set_entry(allocator::physical_frame frame, std::bitset<64U> additional_flags) -> void { exception_handling::assert((frame.start_address() & ~0x000fffff'fffff000) == 0, "Start address is not aligned with Page"); - flags = std::bitset<64U>(frame.start_address()) | flags; + flags = std::bitset<64U>(frame.start_address()) | additional_flags; } } // namespace teachos::arch::memory::paging diff --git a/arch/x86_64/src/memory/paging/page_mapper.cpp b/arch/x86_64/src/memory/paging/page_mapper.cpp index e68bc68..ec1d5d5 100644 --- a/arch/x86_64/src/memory/paging/page_mapper.cpp +++ b/arch/x86_64/src/memory/paging/page_mapper.cpp @@ -1,6 +1,6 @@ +#include "arch/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" namespace teachos::arch::memory::paging { @@ -9,8 +9,6 @@ namespace teachos::arch::memory::paging page_table page_table{}; bool is_valid = false; - auto huge_page = [&]() -> std::optional {}; - for (auto level = page_table::LEVEL4; level != page_table::LEVEL1; level--) { is_valid = page_table.next_table(page.get_level_index(level)); @@ -82,12 +80,26 @@ namespace teachos::arch::memory::paging auto map_page_to_frame(memory::allocator::area_frame_allocator & allocator, const virtual_page & page, const memory::allocator::physical_frame & frame, entry::bitset flags) -> void { - auto p4 = reinterpret_cast(P4); // Assuming P4 is defined somewhere - auto p3 = p4->next_table_create(page.p4_index(), allocator); - auto p2 = p3->next_table_create(page.p3_index(), allocator); - auto p1 = p2->next_table_create(page.p2_index(), allocator); + page_table page_table{}; + bool is_valid = false; + + for (auto level = page_table::LEVEL4; level != page_table::LEVEL1; level--) + { + std::size_t level_index = page.get_level_index(level); + is_valid = page_table.next_table(level_index); + page_table[level_index].set_entry(frame, entry::PRESENT | entry::WRITABLE); + page_table.zero_entries(); + + if (!is_valid) + { + break; + } + } - assert(p1[page.p1_index()].is_unused()); - p1[page.p1_index()].set(frame, flags | PRESENT); + entry page_table_entry = page_table[page.get_level_index(page_table::LEVEL1)]; + arch::exception_handling::assert(!page_table_entry.contains_flags(entry::HUGE_PAGE), + "[Page Mapper]: Unable to map huge pages"); + arch::exception_handling::assert(!page_table_entry.is_unused(), "[Page Mapper]: Page table entry is already used"); + page_table_entry.set_entry(frame, flags | entry::PRESENT); } } // namespace teachos::arch::memory::paging \ No newline at end of file -- cgit v1.2.3 From f47f1468c8c281ee9603b7669f5e685e5f36fa3f Mon Sep 17 00:00:00 2001 From: Fabian Imhof Date: Sun, 20 Oct 2024 11:23:02 +0000 Subject: finalize map_page_to_frame --- arch/x86_64/src/memory/paging/page_mapper.cpp | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) (limited to 'arch/x86_64/src/memory/paging') diff --git a/arch/x86_64/src/memory/paging/page_mapper.cpp b/arch/x86_64/src/memory/paging/page_mapper.cpp index ec1d5d5..6b01548 100644 --- a/arch/x86_64/src/memory/paging/page_mapper.cpp +++ b/arch/x86_64/src/memory/paging/page_mapper.cpp @@ -77,8 +77,8 @@ namespace teachos::arch::memory::paging return std::nullopt; } - auto map_page_to_frame(memory::allocator::area_frame_allocator & allocator, const virtual_page & page, - const memory::allocator::physical_frame & frame, entry::bitset flags) -> void + auto map_page_to_frame(memory::allocator::area_frame_allocator & allocator, virtual_page const & page, + memory::allocator::physical_frame const & frame, entry::bitset flags) -> void { page_table page_table{}; bool is_valid = false; @@ -87,7 +87,10 @@ namespace teachos::arch::memory::paging { std::size_t level_index = page.get_level_index(level); is_valid = page_table.next_table(level_index); - page_table[level_index].set_entry(frame, entry::PRESENT | entry::WRITABLE); + + std::optional 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(); if (!is_valid) -- cgit v1.2.3 From f4a14572a661b1f2bac283615d5b070408b382f7 Mon Sep 17 00:00:00 2001 From: Fabian Imhof Date: Sun, 20 Oct 2024 11:24:58 +0000 Subject: fix syntax --- arch/x86_64/src/memory/paging/page_mapper.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'arch/x86_64/src/memory/paging') diff --git a/arch/x86_64/src/memory/paging/page_mapper.cpp b/arch/x86_64/src/memory/paging/page_mapper.cpp index 6b01548..eaafafa 100644 --- a/arch/x86_64/src/memory/paging/page_mapper.cpp +++ b/arch/x86_64/src/memory/paging/page_mapper.cpp @@ -77,8 +77,8 @@ namespace teachos::arch::memory::paging return std::nullopt; } - auto map_page_to_frame(memory::allocator::area_frame_allocator & allocator, virtual_page const & page, - memory::allocator::physical_frame const & frame, entry::bitset flags) -> void + auto map_page_to_frame(allocator::area_frame_allocator & allocator, virtual_page const & page, + allocator::physical_frame const & frame, entry::bitset flags) -> void { page_table page_table{}; bool is_valid = false; @@ -88,7 +88,7 @@ namespace teachos::arch::memory::paging std::size_t level_index = page.get_level_index(level); is_valid = page_table.next_table(level_index); - std::optional allocated_frame = allocator.allocate_frame(); + std::optional 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(); -- cgit v1.2.3 From 0d42fed17834a21d29032dd2d8e56e11596056bc Mon Sep 17 00:00:00 2001 From: Fabian Imhof Date: Sun, 20 Oct 2024 11:29:53 +0000 Subject: fix logic --- arch/x86_64/src/memory/paging/page_mapper.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'arch/x86_64/src/memory/paging') diff --git a/arch/x86_64/src/memory/paging/page_mapper.cpp b/arch/x86_64/src/memory/paging/page_mapper.cpp index eaafafa..eb1e18c 100644 --- a/arch/x86_64/src/memory/paging/page_mapper.cpp +++ b/arch/x86_64/src/memory/paging/page_mapper.cpp @@ -88,15 +88,15 @@ namespace teachos::arch::memory::paging std::size_t level_index = page.get_level_index(level); is_valid = page_table.next_table(level_index); - std::optional 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(); - if (!is_valid) { break; } + + 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(); } entry page_table_entry = page_table[page.get_level_index(page_table::LEVEL1)]; -- cgit v1.2.3 From da2341ec12128d3b4983a67d39aeaf76b1781fa8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matteo=20Gm=C3=BCr?= Date: Sun, 20 Oct 2024 12:02:20 +0000 Subject: Add printf like behaviour to assert --- arch/x86_64/src/memory/paging/page_entry.cpp | 2 +- arch/x86_64/src/memory/paging/page_mapper.cpp | 24 +++++++++++------------- arch/x86_64/src/memory/paging/page_table.cpp | 2 +- 3 files changed, 13 insertions(+), 15 deletions(-) (limited to 'arch/x86_64/src/memory/paging') diff --git a/arch/x86_64/src/memory/paging/page_entry.cpp b/arch/x86_64/src/memory/paging/page_entry.cpp index 0dbbae1..30a8961 100644 --- a/arch/x86_64/src/memory/paging/page_entry.cpp +++ b/arch/x86_64/src/memory/paging/page_entry.cpp @@ -36,7 +36,7 @@ namespace teachos::arch::memory::paging auto entry::set_entry(allocator::physical_frame frame, std::bitset<64U> additional_flags) -> void { exception_handling::assert((frame.start_address() & ~0x000fffff'fffff000) == 0, - "Start address is not aligned with Page"); + "[Paging Entry] Start address is not aligned with page"); flags = std::bitset<64U>(frame.start_address()) | additional_flags; } } // namespace teachos::arch::memory::paging diff --git a/arch/x86_64/src/memory/paging/page_mapper.cpp b/arch/x86_64/src/memory/paging/page_mapper.cpp index eb1e18c..8c64f22 100644 --- a/arch/x86_64/src/memory/paging/page_mapper.cpp +++ b/arch/x86_64/src/memory/paging/page_mapper.cpp @@ -81,28 +81,26 @@ namespace teachos::arch::memory::paging allocator::physical_frame const & frame, entry::bitset flags) -> void { page_table page_table{}; - bool is_valid = false; + 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); - is_valid = page_table.next_table(level_index); + table_exists = page_table.next_table(level_index); - if (!is_valid) + if (!table_exists) { - break; + 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 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(); } - entry page_table_entry = page_table[page.get_level_index(page_table::LEVEL1)]; - arch::exception_handling::assert(!page_table_entry.contains_flags(entry::HUGE_PAGE), + 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(!page_table_entry.is_unused(), "[Page Mapper]: Page table entry is already used"); - page_table_entry.set_entry(frame, flags | entry::PRESENT); + arch::exception_handling::assert(!level1_entry.is_unused(), "[Page Mapper]: Page table entry is already used"); + level1_entry.set_entry(frame, flags | entry::PRESENT); } } // namespace teachos::arch::memory::paging \ No newline at end of file diff --git a/arch/x86_64/src/memory/paging/page_table.cpp b/arch/x86_64/src/memory/paging/page_table.cpp index 02ababe..ea2e9c2 100644 --- a/arch/x86_64/src/memory/paging/page_table.cpp +++ b/arch/x86_64/src/memory/paging/page_table.cpp @@ -39,7 +39,7 @@ namespace teachos::arch::memory::paging { // C array is not bounds checked, therefore we have to check ourselves, to ensure no out of bounds reads, which // could be incredibly hard to debug later. - exception_handling::assert(index < PAGE_TABLE_ENTRY_COUNT, "[Page Table] index out of bounds"); + exception_handling::assert(index < PAGE_TABLE_ENTRY_COUNT, "[Page Table] Index out of bounds"); return current_table->entries[index]; } -- cgit v1.2.3 From aa0634589cb7d51f57e3e555bb15ebca99bc162e Mon Sep 17 00:00:00 2001 From: Fabian Imhof Date: Sun, 20 Oct 2024 12:17:58 +0000 Subject: document page mapping and entry --- arch/x86_64/src/memory/paging/page_entry.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'arch/x86_64/src/memory/paging') diff --git a/arch/x86_64/src/memory/paging/page_entry.cpp b/arch/x86_64/src/memory/paging/page_entry.cpp index 30a8961..8a7442e 100644 --- a/arch/x86_64/src/memory/paging/page_entry.cpp +++ b/arch/x86_64/src/memory/paging/page_entry.cpp @@ -33,10 +33,10 @@ namespace teachos::arch::memory::paging auto entry::contains_flags(std::bitset<64U> other) const -> bool { return (flags & other) == other; } - auto entry::set_entry(allocator::physical_frame frame, std::bitset<64U> additional_flags) -> void + auto entry::set_entry(allocator::physical_frame frame, std::bitset<64U> flags) -> void { exception_handling::assert((frame.start_address() & ~0x000fffff'fffff000) == 0, "[Paging Entry] Start address is not aligned with page"); - flags = std::bitset<64U>(frame.start_address()) | additional_flags; + flags = std::bitset<64U>(frame.start_address()) | flags; } } // namespace teachos::arch::memory::paging -- cgit v1.2.3 From 8e9a924f9fba18de9a5e37b1baf1d97e9b008251 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matteo=20Gm=C3=BCr?= Date: Sun, 20 Oct 2024 12:21:57 +0000 Subject: Fix useless copy by reference --- arch/x86_64/src/memory/paging/page_mapper.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'arch/x86_64/src/memory/paging') diff --git a/arch/x86_64/src/memory/paging/page_mapper.cpp b/arch/x86_64/src/memory/paging/page_mapper.cpp index 8c64f22..1912174 100644 --- a/arch/x86_64/src/memory/paging/page_mapper.cpp +++ b/arch/x86_64/src/memory/paging/page_mapper.cpp @@ -77,8 +77,8 @@ namespace teachos::arch::memory::paging return std::nullopt; } - auto map_page_to_frame(allocator::area_frame_allocator & allocator, virtual_page const & page, - allocator::physical_frame const & frame, entry::bitset flags) -> void + auto map_page_to_frame(allocator::area_frame_allocator & allocator, virtual_page page, + allocator::physical_frame frame, entry::bitset flags) -> void { page_table page_table{}; bool table_exists = false; -- cgit v1.2.3 From dd5dab7fd34c6745a16ac572ecd099e4bc26c1fb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matteo=20Gm=C3=BCr?= Date: Sun, 20 Oct 2024 12:35:39 +0000 Subject: Fix set_entry flags usage --- arch/x86_64/src/memory/paging/page_entry.cpp | 2 +- arch/x86_64/src/memory/paging/page_mapper.cpp | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) (limited to 'arch/x86_64/src/memory/paging') diff --git a/arch/x86_64/src/memory/paging/page_entry.cpp b/arch/x86_64/src/memory/paging/page_entry.cpp index 8a7442e..a172ca8 100644 --- a/arch/x86_64/src/memory/paging/page_entry.cpp +++ b/arch/x86_64/src/memory/paging/page_entry.cpp @@ -37,6 +37,6 @@ namespace teachos::arch::memory::paging { exception_handling::assert((frame.start_address() & ~0x000fffff'fffff000) == 0, "[Paging Entry] Start address is not aligned with page"); - flags = std::bitset<64U>(frame.start_address()) | flags; + flags = std::bitset<64U>{frame.start_address()} | flags; } } // namespace teachos::arch::memory::paging diff --git a/arch/x86_64/src/memory/paging/page_mapper.cpp b/arch/x86_64/src/memory/paging/page_mapper.cpp index 1912174..0874230 100644 --- a/arch/x86_64/src/memory/paging/page_mapper.cpp +++ b/arch/x86_64/src/memory/paging/page_mapper.cpp @@ -78,7 +78,7 @@ namespace teachos::arch::memory::paging } auto map_page_to_frame(allocator::area_frame_allocator & allocator, virtual_page page, - allocator::physical_frame frame, entry::bitset flags) -> void + allocator::physical_frame frame, std::bitset<64U> flags) -> void { page_table page_table{}; bool table_exists = false; @@ -101,6 +101,6 @@ namespace teachos::arch::memory::paging 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 | entry::PRESENT); + level1_entry.set_entry(frame, flags | std::bitset<64U>{entry::PRESENT}); } -} // namespace teachos::arch::memory::paging \ No newline at end of file +} // namespace teachos::arch::memory::paging -- cgit v1.2.3 From bb8b3f9c0734220702e3e930e7acb4906aa13db6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matteo=20Gm=C3=BCr?= Date: Sun, 20 Oct 2024 12:48:51 +0000 Subject: Make map_page_to_frame use concept --- arch/x86_64/src/memory/paging/page_mapper.cpp | 29 --------------------------- 1 file changed, 29 deletions(-) (limited to 'arch/x86_64/src/memory/paging') 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 @@ -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 -- cgit v1.2.3 From 1b03bcecac1276b486e17daf0384de7fa203d974 Mon Sep 17 00:00:00 2001 From: Fabian Imhof Date: Sun, 20 Oct 2024 12:57:21 +0000 Subject: create active_page_table --- .../x86_64/src/memory/paging/active_page_table.cpp | 31 ++++++++++++++++++++++ 1 file changed, 31 insertions(+) create mode 100644 arch/x86_64/src/memory/paging/active_page_table.cpp (limited to 'arch/x86_64/src/memory/paging') diff --git a/arch/x86_64/src/memory/paging/active_page_table.cpp b/arch/x86_64/src/memory/paging/active_page_table.cpp new file mode 100644 index 0000000..eb85c34 --- /dev/null +++ b/arch/x86_64/src/memory/paging/active_page_table.cpp @@ -0,0 +1,31 @@ +#include "arch/memory/paging/active_page_table.hpp" + +namespace teachos::arch::memory::paging +{ + struct active_page_table + { + auto create(page_table * level4_page_table) -> active_page_table * + { + if (instantiated) + { + return this; + } + + instantiated = true; + return &active_page_table(level4_page_table); + } + + active_page_table(const active_page_table &) = delete; + active_page_table & operator=(const active_page_table &) = delete; + + private: + active_page_table(page_table * level4_page_table) + : level4_page_table(level4_page_table) + { + // Nothing to do + } + + bool instantiated = false; + page_table * level4_page_table; + }; +} // namespace teachos::arch::memory::paging \ No newline at end of file -- cgit v1.2.3 From 49ae81912f3a440f1958e86296d468ec669f71a2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matteo=20Gm=C3=BCr?= Date: Sun, 20 Oct 2024 13:17:24 +0000 Subject: Fix active page table cpp --- .../x86_64/src/memory/paging/active_page_table.cpp | 34 ++++++++-------------- 1 file changed, 12 insertions(+), 22 deletions(-) (limited to 'arch/x86_64/src/memory/paging') diff --git a/arch/x86_64/src/memory/paging/active_page_table.cpp b/arch/x86_64/src/memory/paging/active_page_table.cpp index eb85c34..ec89e0e 100644 --- a/arch/x86_64/src/memory/paging/active_page_table.cpp +++ b/arch/x86_64/src/memory/paging/active_page_table.cpp @@ -2,30 +2,20 @@ namespace teachos::arch::memory::paging { - struct active_page_table + auto active_page_table::create(page_table * level4_page_table) -> active_page_table * { - auto create(page_table * level4_page_table) -> active_page_table * + if (instantiated) { - if (instantiated) - { - return this; - } - - instantiated = true; - return &active_page_table(level4_page_table); + return this; } - active_page_table(const active_page_table &) = delete; - active_page_table & operator=(const active_page_table &) = delete; + instantiated = true; + return &active_page_table(level4_page_table); + } - private: - active_page_table(page_table * level4_page_table) - : level4_page_table(level4_page_table) - { - // Nothing to do - } - - bool instantiated = false; - page_table * level4_page_table; - }; -} // namespace teachos::arch::memory::paging \ No newline at end of file + active_page_table::active_page_table(page_table * level4_page_table) + : level4_page_table(level4_page_table) + { + // Nothing to do + } +} // namespace teachos::arch::memory::paging -- cgit v1.2.3 From f171efed99684bf03c315405efda34e36d7db82c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matteo=20Gm=C3=BCr?= Date: Mon, 21 Oct 2024 09:31:58 +0000 Subject: Ensure only one instance of global page table can exist --- .../x86_64/src/memory/paging/active_page_table.cpp | 21 ----- arch/x86_64/src/memory/paging/page_mapper.cpp | 91 +++++++++++++--------- arch/x86_64/src/memory/paging/page_table.cpp | 28 +++---- 3 files changed, 65 insertions(+), 75 deletions(-) delete mode 100644 arch/x86_64/src/memory/paging/active_page_table.cpp (limited to 'arch/x86_64/src/memory/paging') diff --git a/arch/x86_64/src/memory/paging/active_page_table.cpp b/arch/x86_64/src/memory/paging/active_page_table.cpp deleted file mode 100644 index ec89e0e..0000000 --- a/arch/x86_64/src/memory/paging/active_page_table.cpp +++ /dev/null @@ -1,21 +0,0 @@ -#include "arch/memory/paging/active_page_table.hpp" - -namespace teachos::arch::memory::paging -{ - auto active_page_table::create(page_table * level4_page_table) -> active_page_table * - { - if (instantiated) - { - return this; - } - - instantiated = true; - return &active_page_table(level4_page_table); - } - - active_page_table::active_page_table(page_table * level4_page_table) - : level4_page_table(level4_page_table) - { - // Nothing to do - } -} // namespace teachos::arch::memory::paging diff --git a/arch/x86_64/src/memory/paging/page_mapper.cpp b/arch/x86_64/src/memory/paging/page_mapper.cpp index 5b72a63..cedda54 100644 --- a/arch/x86_64/src/memory/paging/page_mapper.cpp +++ b/arch/x86_64/src/memory/paging/page_mapper.cpp @@ -2,60 +2,79 @@ namespace teachos::arch::memory::paging { + namespace + { + constexpr size_t PAGE_TABLE_LEVEL_4_ADDRESS = 0xfffffffffffff000; + } + + auto create_or_get() -> page_table * + { + static bool instantiated = false; + static page_table * active_page = nullptr; + + if (instantiated) + { + return active_page; + } + + instantiated = true; + active_page = reinterpret_cast(PAGE_TABLE_LEVEL_4_ADDRESS); + return active_page; + } + auto translate_page(virtual_page page) -> std::optional { - page_table page_table{}; - bool is_valid = false; + page_table * current_page_table = create_or_get(); for (auto level = page_table::LEVEL4; level != page_table::LEVEL1; level--) { - is_valid = page_table.next_table(page.get_level_index(level)); - if (!is_valid) + auto next_page_table = current_page_table->next_table(page.get_level_index(level)); + // If the next table method failed then it is highly likely that it was a huge page and we therefore have to parse + // the table differently. Therefore, we attempt to parse it using the method required by huge pages. + if (!next_page_table) { - break; + return translate_huge_page(page); } + current_page_table = next_page_table.value(); } - if (is_valid) - { - auto level1_index = page.get_level_index(page_table::LEVEL1); - auto level1_frame = page_table[level1_index].calculate_pointed_to_frame(); - return level1_frame; - } - - return translate_huge_page(page); + auto level1_index = page.get_level_index(page_table::LEVEL1); + auto level1_frame = current_page_table->operator[](level1_index).calculate_pointed_to_frame(); + return level1_frame; } auto translate_huge_page(virtual_page page) -> std::optional { - page_table page_table{}; - bool is_valid = page_table.next_table(page.get_level_index(page_table::LEVEL3)); + page_table * current_page_table = create_or_get(); + auto level3_page_table = current_page_table->next_table(page.get_level_index(page_table::LEVEL4)); - if (is_valid) + if (!level3_page_table) { - auto level3_entry = page_table[page.get_level_index(page_table::LEVEL3)]; - auto level3_optional_frame = level3_entry.calculate_pointed_to_frame(); - if (level3_optional_frame.has_value() && level3_entry.contains_flags(entry::HUGE_PAGE)) - { - auto level3_frame = level3_optional_frame.value(); - exception_handling::assert(level3_frame.frame_number % (PAGE_TABLE_ENTRY_COUNT * PAGE_TABLE_ENTRY_COUNT) == 0U, - "[Page Mapper] Physical address must be 1 GiB aligned"); - return allocator::physical_frame{level3_frame.frame_number + - page.get_level_index(page_table::LEVEL2) * PAGE_TABLE_ENTRY_COUNT + - page.get_level_index(page_table::LEVEL1)}; - } + return std::nullopt; } - is_valid = page_table.next_table(page.get_level_index(page_table::LEVEL3)); - if (is_valid) + + auto level3_entry = level3_page_table.value()->operator[](page.get_level_index(page_table::LEVEL3)); + auto level3_frame = level3_entry.calculate_pointed_to_frame(); + if (level3_frame && level3_entry.contains_flags(entry::HUGE_PAGE)) + { + exception_handling::assert( + level3_frame.value().frame_number % (PAGE_TABLE_ENTRY_COUNT * PAGE_TABLE_ENTRY_COUNT) == 0U, + "[Page Mapper] Physical address must be 1 GiB aligned"); + return allocator::physical_frame{level3_frame.value().frame_number + + page.get_level_index(page_table::LEVEL2) * PAGE_TABLE_ENTRY_COUNT + + page.get_level_index(page_table::LEVEL1)}; + } + + auto level2_page_table = level3_page_table.value()->next_table(page.get_level_index(page_table::LEVEL3)); + if (level2_page_table) { - auto level2_entry = page_table[page.get_level_index(page_table::LEVEL2)]; - auto level2_optional_frame = level2_entry.calculate_pointed_to_frame(); - if (level2_optional_frame.has_value() && level2_entry.contains_flags(entry::HUGE_PAGE)) + auto level2_entry = level2_page_table.value()->operator[](page.get_level_index(page_table::LEVEL2)); + auto level2_frame = level2_entry.calculate_pointed_to_frame(); + if (level2_frame && level2_entry.contains_flags(entry::HUGE_PAGE)) { - auto level2_frame = level2_optional_frame.value(); - exception_handling::assert(level2_frame.frame_number % PAGE_TABLE_ENTRY_COUNT == 0U, + exception_handling::assert(level2_frame.value().frame_number % PAGE_TABLE_ENTRY_COUNT == 0U, "[Page Mapper] Physical address must be 2 MiB aligned"); - return allocator::physical_frame{level2_frame.frame_number + page.get_level_index(page_table::LEVEL1)}; + return allocator::physical_frame{level2_frame.value().frame_number + page.get_level_index(page_table::LEVEL1)}; } } return std::nullopt; @@ -67,7 +86,7 @@ namespace teachos::arch::memory::paging virtual_page page = virtual_page::containing_address(virtual_address); std::optional frame = translate_page(page); - if (frame.has_value()) + if (frame) { return frame.value().frame_number * allocator::PAGE_FRAME_SIZE + offset; } diff --git a/arch/x86_64/src/memory/paging/page_table.cpp b/arch/x86_64/src/memory/paging/page_table.cpp index ea2e9c2..5daf8bb 100644 --- a/arch/x86_64/src/memory/paging/page_table.cpp +++ b/arch/x86_64/src/memory/paging/page_table.cpp @@ -4,16 +4,9 @@ namespace teachos::arch::memory::paging { - page_table::page_table() - : current_level(LEVEL4) - , current_table(reinterpret_cast(0xfffffffffffff000)) - { - // Nothing to do - } - auto page_table::zero_entries() -> void { - constexpr size_t entry_amount = sizeof(current_table->entries) / sizeof(current_table->entries[0]); + constexpr size_t entry_amount = sizeof(entries) / sizeof(entries[0]); for (size_t i = 0; i < entry_amount; ++i) { auto entry = this->operator[](i); @@ -21,18 +14,17 @@ namespace teachos::arch::memory::paging } } - auto page_table::next_table(std::size_t table_index) -> bool + auto page_table::next_table(std::size_t table_index) -> std::optional { - exception_handling::assert(current_level != LEVEL1, - "[Page Table] Attempted to call next_table on level 1 page table"); + // TODO: Find another way to ensure the current page table is not LEVEL1 + // exception_handling::assert(current_level != LEVEL1, "[Page Table] Attempted to call next_table on level 1 page + // table"); auto address = next_table_address(table_index); - bool const success = address.has_value(); - if (success) + if (address) { - current_table = reinterpret_cast(address.value()); - current_level = static_cast(current_level - 1U); + return reinterpret_cast(address.value()); } - return success; + return std::nullopt; } auto page_table::operator[](std::size_t index) -> entry & @@ -40,7 +32,7 @@ namespace teachos::arch::memory::paging // C array is not bounds checked, therefore we have to check ourselves, to ensure no out of bounds reads, which // could be incredibly hard to debug later. exception_handling::assert(index < PAGE_TABLE_ENTRY_COUNT, "[Page Table] Index out of bounds"); - return current_table->entries[index]; + return entries[index]; } auto page_table::next_table_address(std::size_t table_index) -> std::optional @@ -49,7 +41,7 @@ namespace teachos::arch::memory::paging if (entry.contains_flags(entry::PRESENT) && !entry.contains_flags(entry::HUGE_PAGE)) { - std::size_t const table_address = reinterpret_cast(current_table); + std::size_t const table_address = reinterpret_cast(this); return ((table_address << 9) | (table_index << 12)); } return std::nullopt; -- cgit v1.2.3 From 72cb015567cb65527e9105e653c001be3c04eab5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matteo=20Gm=C3=BCr?= Date: Mon, 21 Oct 2024 12:03:21 +0000 Subject: Use handle struct to ensure next_table is not called on page table level 1 --- arch/x86_64/src/memory/paging/page_mapper.cpp | 37 +++++++++++---------------- arch/x86_64/src/memory/paging/page_table.cpp | 34 +++++++++++++++++++----- 2 files changed, 42 insertions(+), 29 deletions(-) (limited to 'arch/x86_64/src/memory/paging') diff --git a/arch/x86_64/src/memory/paging/page_mapper.cpp b/arch/x86_64/src/memory/paging/page_mapper.cpp index cedda54..01c39ca 100644 --- a/arch/x86_64/src/memory/paging/page_mapper.cpp +++ b/arch/x86_64/src/memory/paging/page_mapper.cpp @@ -7,53 +7,46 @@ namespace teachos::arch::memory::paging constexpr size_t PAGE_TABLE_LEVEL_4_ADDRESS = 0xfffffffffffff000; } - auto create_or_get() -> page_table * + auto create_or_get() -> page_table_handle { - static bool instantiated = false; - static page_table * active_page = nullptr; + static page_table_handle active_page{reinterpret_cast(PAGE_TABLE_LEVEL_4_ADDRESS), + page_table::LEVEL4}; - if (instantiated) - { - return active_page; - } - - instantiated = true; - active_page = reinterpret_cast(PAGE_TABLE_LEVEL_4_ADDRESS); return active_page; } auto translate_page(virtual_page page) -> std::optional { - page_table * current_page_table = create_or_get(); + auto current_handle = create_or_get(); for (auto level = page_table::LEVEL4; level != page_table::LEVEL1; level--) { - auto next_page_table = current_page_table->next_table(page.get_level_index(level)); + auto next_handle = current_handle.next_table(page.get_level_index(level)); // If the next table method failed then it is highly likely that it was a huge page and we therefore have to parse // the table differently. Therefore, we attempt to parse it using the method required by huge pages. - if (!next_page_table) + if (!next_handle) { return translate_huge_page(page); } - current_page_table = next_page_table.value(); + current_handle = next_handle.value(); } auto level1_index = page.get_level_index(page_table::LEVEL1); - auto level1_frame = current_page_table->operator[](level1_index).calculate_pointed_to_frame(); + auto level1_frame = current_handle[level1_index].calculate_pointed_to_frame(); return level1_frame; } auto translate_huge_page(virtual_page page) -> std::optional { - page_table * current_page_table = create_or_get(); - auto level3_page_table = current_page_table->next_table(page.get_level_index(page_table::LEVEL4)); + auto current_handle = create_or_get(); + auto level3_handle = current_handle.next_table(page.get_level_index(page_table::LEVEL4)); - if (!level3_page_table) + if (!level3_handle) { return std::nullopt; } - auto level3_entry = level3_page_table.value()->operator[](page.get_level_index(page_table::LEVEL3)); + auto level3_entry = level3_handle.value()[page.get_level_index(page_table::LEVEL3)]; auto level3_frame = level3_entry.calculate_pointed_to_frame(); if (level3_frame && level3_entry.contains_flags(entry::HUGE_PAGE)) { @@ -65,10 +58,10 @@ namespace teachos::arch::memory::paging page.get_level_index(page_table::LEVEL1)}; } - auto level2_page_table = level3_page_table.value()->next_table(page.get_level_index(page_table::LEVEL3)); - if (level2_page_table) + auto level2_handle = level3_handle.value().next_table(page.get_level_index(page_table::LEVEL3)); + if (level2_handle) { - auto level2_entry = level2_page_table.value()->operator[](page.get_level_index(page_table::LEVEL2)); + auto level2_entry = level2_handle.value()[page.get_level_index(page_table::LEVEL2)]; auto level2_frame = level2_entry.calculate_pointed_to_frame(); if (level2_frame && level2_entry.contains_flags(entry::HUGE_PAGE)) { diff --git a/arch/x86_64/src/memory/paging/page_table.cpp b/arch/x86_64/src/memory/paging/page_table.cpp index 5daf8bb..907b64f 100644 --- a/arch/x86_64/src/memory/paging/page_table.cpp +++ b/arch/x86_64/src/memory/paging/page_table.cpp @@ -14,11 +14,8 @@ namespace teachos::arch::memory::paging } } - auto page_table::next_table(std::size_t table_index) -> std::optional + auto page_table::next_table(std::size_t table_index) const -> std::optional { - // TODO: Find another way to ensure the current page table is not LEVEL1 - // exception_handling::assert(current_level != LEVEL1, "[Page Table] Attempted to call next_table on level 1 page - // table"); auto address = next_table_address(table_index); if (address) { @@ -27,7 +24,7 @@ namespace teachos::arch::memory::paging return std::nullopt; } - auto page_table::operator[](std::size_t index) -> entry & + auto page_table::operator[](std::size_t index) const -> entry { // C array is not bounds checked, therefore we have to check ourselves, to ensure no out of bounds reads, which // could be incredibly hard to debug later. @@ -35,7 +32,7 @@ namespace teachos::arch::memory::paging return entries[index]; } - auto page_table::next_table_address(std::size_t table_index) -> std::optional + auto page_table::next_table_address(std::size_t table_index) const -> std::optional { auto entry = this->operator[](table_index); @@ -47,11 +44,34 @@ namespace teachos::arch::memory::paging return std::nullopt; } - auto operator--(page_table::level & level, int) -> page_table::level + auto operator--(page_table::level level, int) -> page_table::level { exception_handling::assert(level != page_table::LEVEL1, "[Page table] Attemptd to decrement enum to value outside of range"); auto value = static_cast::type>(level); return static_cast(--value); } + + page_table_handle::page_table_handle(page_table * handle, page_table::level handle_level) + : handle(handle) + , handle_level(handle_level) + { + exception_handling::assert(handle, "[Page table] Attemptd to pass nullptr as handle to page table handle method"); + } + + auto page_table_handle::zero_entries() -> void { handle->zero_entries(); } + + auto page_table_handle::next_table(std::size_t table_index) const -> std::optional + { + exception_handling::assert(handle_level != page_table::LEVEL1, + "[Page Table] Attempted to call next_table on level 1 page table"); + auto next_table = handle->next_table(table_index); + if (next_table) + { + retur