From 32add45849744dc976c7af6ec24f985bbace47d3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matteo=20Gm=C3=BCr?= Date: Wed, 2 Oct 2024 13:02:35 +0000 Subject: Creating base frame allocation code --- arch/x86_64/src/memory/frame_allocator.cpp | 9 +++++++++ 1 file changed, 9 insertions(+) create mode 100644 arch/x86_64/src/memory/frame_allocator.cpp (limited to 'arch/x86_64/src/memory') diff --git a/arch/x86_64/src/memory/frame_allocator.cpp b/arch/x86_64/src/memory/frame_allocator.cpp new file mode 100644 index 0000000..425528a --- /dev/null +++ b/arch/x86_64/src/memory/frame_allocator.cpp @@ -0,0 +1,9 @@ +#include "arch/memory/frame_allocator.hpp" + +namespace teachos::arch::memory +{ + auto AreaFrameAllocator::allocate_frame() -> std::optional {} + + auto AreaFrameAllocator::deallocate_frame(Frame frame) -> void {} + +} // namespace teachos::arch::memory -- cgit v1.2.3 From 1ab9c3c09d32283b39ca1026a9e29ada5ff7fda5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matteo=20Gm=C3=BCr?= Date: Sun, 6 Oct 2024 07:34:30 +0000 Subject: Renaming scheme --- arch/x86_64/src/memory/frame_allocator.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'arch/x86_64/src/memory') diff --git a/arch/x86_64/src/memory/frame_allocator.cpp b/arch/x86_64/src/memory/frame_allocator.cpp index 425528a..b9d26a5 100644 --- a/arch/x86_64/src/memory/frame_allocator.cpp +++ b/arch/x86_64/src/memory/frame_allocator.cpp @@ -2,8 +2,8 @@ namespace teachos::arch::memory { - auto AreaFrameAllocator::allocate_frame() -> std::optional {} + auto area_frame_allocator::allocate_frame() -> std::optional {} - auto AreaFrameAllocator::deallocate_frame(Frame frame) -> void {} + auto area_frame_allocator::deallocate_frame(frame frame) -> void {} } // namespace teachos::arch::memory -- cgit v1.2.3 From 8773024d1b4e756fe5d3494479247c64c7ad8491 Mon Sep 17 00:00:00 2001 From: Fabian Imhof Date: Tue, 8 Oct 2024 09:51:26 +0000 Subject: begin implementing frame allocator --- arch/x86_64/src/memory/frame_allocator.cpp | 70 +++++++++++++++++++++++++++++- 1 file changed, 69 insertions(+), 1 deletion(-) (limited to 'arch/x86_64/src/memory') diff --git a/arch/x86_64/src/memory/frame_allocator.cpp b/arch/x86_64/src/memory/frame_allocator.cpp index b9d26a5..b8f53be 100644 --- a/arch/x86_64/src/memory/frame_allocator.cpp +++ b/arch/x86_64/src/memory/frame_allocator.cpp @@ -2,8 +2,76 @@ namespace teachos::arch::memory { - auto area_frame_allocator::allocate_frame() -> std::optional {} + auto area_frame_allocator::allocate_frame() -> std::optional + { + /* + * Only try to allocate memory if current_area is not null, because + * the current_area is null if there is no more available memory. + */ + if (current_area) + { + frame frame{next_free_frame.frame_number}; + + struct frame current_area_last_frame = { + frame::containing_address(current_area->base_address + current_area->area_length - 1)}; + + if (next_free_frame > current_area_last_frame) + { + // All frames of current area are used, switch to next area + choose_next_area(); + } + else if (frame >= multiboot_start && frame <= kernel_end) + { + // `frame` is used by the kernel or multiboot information structure + next_free_frame = arch::memory::frame{kernel_end.frame_number + 1}; + } + else + { + // Frame is unused, increment `next_free_frame` and return it + next_free_frame.frame_number += 1; + return frame; + } + + // `frame` was not valid, try it again with the updated `next_free_frame` + return allocate_frame(); + } + + // no free frames left + return std::nullopt; + } auto area_frame_allocator::deallocate_frame(frame frame) -> void {} + namespace + { + auto area_frame_allocator::choose_next_area() -> void + { + current_area = std::nullopt; + + // TODO: Fix this loop as soon as you've created an area iterator + for (const auto & area : areas) + { + std::size_t address = area.base_addr + area.length - 1; + if (frame::containing_address(address) >= next_free_frame) + { + // The `next_free_frame` address is smaller than the last address of the current area + if (!current_area || area.base_addr < current_area->base_address) + { + current_area = area; + } + } + } + + if (current_area) + { + // Update the `next_free_frame` according to the new memory area + frame start_frame = frame::containing_address(current_area->base_address); + if (next_free_frame < start_frame) + { + next_free_frame = start_frame; + } + } + } + + } // namespace } // namespace teachos::arch::memory -- cgit v1.2.3 From 7edd03e9a14a3025b4d2b2ff51d838d20b79b2c4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matteo=20Gm=C3=BCr?= Date: Tue, 8 Oct 2024 11:30:01 +0000 Subject: Added doxygen comments to all fields and structs --- arch/x86_64/src/memory/multiboot.cpp | 41 ++++++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) create mode 100644 arch/x86_64/src/memory/multiboot.cpp (limited to 'arch/x86_64/src/memory') diff --git a/arch/x86_64/src/memory/multiboot.cpp b/arch/x86_64/src/memory/multiboot.cpp new file mode 100644 index 0000000..91e7550 --- /dev/null +++ b/arch/x86_64/src/memory/multiboot.cpp @@ -0,0 +1,41 @@ +#include "multiboot.hpp" + +namespace teachos::arch::memory +{ + auto elf_section_flags::writeable() const -> bool { return is_bit_set(0); } + + auto elf_section_flags::occupies_memory() const -> bool { return is_bit_set(1); } + + auto elf_section_flags::is_executable() const -> bool { return is_bit_set(2); } + + auto elf_section_flags::contains_duplicate_data() const -> bool { return is_bit_set(4); } + + auto elf_section_flags::contains_strings() const -> bool { return is_bit_set(5); } + + auto elf_section_flags::section_header_info_is_section_header_table_index() const -> bool { return is_bit_set(6); } + + auto elf_section_flags::preserve_ordering_after_combination() const -> bool { return is_bit_set(7); } + + auto elf_section_flags::requires_special_os_processing() const -> bool { return is_bit_set(8); } + + auto elf_section_flags::is_section_group_member() const -> bool { return is_bit_set(9); } + + auto elf_section_flags::holds_thread_local_data() const -> bool { return is_bit_set(10); } + + auto elf_section_flags::is_compressed() const -> bool { return is_bit_set(11); } + + auto elf_section_flags::has_special_ordering_requirements() const -> bool { return is_bit_set(30); } + + auto elf_section_flags::is_excluded_unless_referenced_or_allocated() const -> bool { return is_bit_set(31); } + + auto elf_section_flags::operator==(elf_section_flags const & other) const -> bool { return flags == other.flags; } + + auto elf_section_flags::is_bit_set(uint8_t index) const -> bool { return flags[index] == 1; } + + auto elf_section_header::is_null() const -> bool + { + return name_table_index == 0U && type == elf_section_type::UNSPECIFIED && + flags == teachos::arch::memory::elf_section_flags{0U} && virtual_address == 0U && file_offset == 0U && + additional_information == 0U && address_alignment == 0U && fixed_table_entry_size == 0U; + } +} // namespace teachos::arch::memory -- cgit v1.2.3 From 553f3a824511bb8107982b2b2737f5b1dff59855 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matteo=20Gm=C3=BCr?= Date: Sun, 13 Oct 2024 08:28:30 +0000 Subject: Add missing cpp files to cmake and fix elf alignment issues --- arch/x86_64/src/memory/frame_allocator.cpp | 66 ++++++++++++++++-------------- arch/x86_64/src/memory/multiboot.cpp | 4 +- 2 files changed, 37 insertions(+), 33 deletions(-) (limited to 'arch/x86_64/src/memory') diff --git a/arch/x86_64/src/memory/frame_allocator.cpp b/arch/x86_64/src/memory/frame_allocator.cpp index b8f53be..3793ac6 100644 --- a/arch/x86_64/src/memory/frame_allocator.cpp +++ b/arch/x86_64/src/memory/frame_allocator.cpp @@ -2,6 +2,37 @@ namespace teachos::arch::memory { + auto area_frame_allocator::choose_next_area() -> void + { + current_area = std::nullopt; + auto begin = areas; + auto end = areas + 5; + + // TODO: Fix this loop as soon as you've created an area iterator + for (auto area = begin; area != end; ++area) + { + std::size_t address = area->base_address + area->area_length - 1; + if (frame::containing_address(address) >= next_free_frame) + { + // The `next_free_frame` address is smaller than the last address of the current area + if (!current_area || area->base_address < current_area->base_address) + { + current_area = *area; + } + } + } + + if (current_area) + { + // Update the `next_free_frame` according to the new memory area + frame start_frame = frame::containing_address(current_area->base_address); + if (next_free_frame < start_frame) + { + next_free_frame = start_frame; + } + } + } + auto area_frame_allocator::allocate_frame() -> std::optional { /* @@ -40,38 +71,11 @@ namespace teachos::arch::memory return std::nullopt; } - auto area_frame_allocator::deallocate_frame(frame frame) -> void {} - - namespace + auto area_frame_allocator::deallocate_frame(frame frame) -> void { - auto area_frame_allocator::choose_next_area() -> void + // TODO: Fix, simply done because compiler will complain if frame is unused and not compile + if (frame.frame_number == 3) { - current_area = std::nullopt; - - // TODO: Fix this loop as soon as you've created an area iterator - for (const auto & area : areas) - { - std::size_t address = area.base_addr + area.length - 1; - if (frame::containing_address(address) >= next_free_frame) - { - // The `next_free_frame` address is smaller than the last address of the current area - if (!current_area || area.base_addr < current_area->base_address) - { - current_area = area; - } - } - } - - if (current_area) - { - // Update the `next_free_frame` according to the new memory area - frame start_frame = frame::containing_address(current_area->base_address); - if (next_free_frame < start_frame) - { - next_free_frame = start_frame; - } - } } - - } // namespace + } } // namespace teachos::arch::memory diff --git a/arch/x86_64/src/memory/multiboot.cpp b/arch/x86_64/src/memory/multiboot.cpp index 91e7550..3f6248d 100644 --- a/arch/x86_64/src/memory/multiboot.cpp +++ b/arch/x86_64/src/memory/multiboot.cpp @@ -1,4 +1,4 @@ -#include "multiboot.hpp" +#include "arch/memory/multiboot.hpp" namespace teachos::arch::memory { @@ -34,7 +34,7 @@ namespace teachos::arch::memory auto elf_section_header::is_null() const -> bool { - return name_table_index == 0U && type == elf_section_type::UNSPECIFIED && + return name_table_index == 0U && type == elf_section_type::INACTIVE && flags == teachos::arch::memory::elf_section_flags{0U} && virtual_address == 0U && file_offset == 0U && additional_information == 0U && address_alignment == 0U && fixed_table_entry_size == 0U; } -- cgit v1.2.3 From b3c8a1819226b7dbaad82623c8294b99c91297ef Mon Sep 17 00:00:00 2001 From: Fabian Imhof Date: Sun, 13 Oct 2024 10:58:34 +0000 Subject: continue implementing frame allocator --- arch/x86_64/src/memory/frame_allocator.cpp | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) (limited to 'arch/x86_64/src/memory') diff --git a/arch/x86_64/src/memory/frame_allocator.cpp b/arch/x86_64/src/memory/frame_allocator.cpp index 3793ac6..829cd6d 100644 --- a/arch/x86_64/src/memory/frame_allocator.cpp +++ b/arch/x86_64/src/memory/frame_allocator.cpp @@ -5,19 +5,18 @@ namespace teachos::arch::memory auto area_frame_allocator::choose_next_area() -> void { current_area = std::nullopt; - auto begin = areas; - auto end = areas + 5; - // TODO: Fix this loop as soon as you've created an area iterator - for (auto area = begin; area != end; ++area) + for (memory_area_iterator it = begin(); it != end(); ++it) { - std::size_t address = area->base_address + area->area_length - 1; + memory_area & area = *it; + + std::size_t address = area.base_address + area.area_length - 1; if (frame::containing_address(address) >= next_free_frame) { // The `next_free_frame` address is smaller than the last address of the current area - if (!current_area || area->base_address < current_area->base_address) + if (!current_area || area.base_address < current_area->base_address) { - current_area = *area; + current_area = area; } } } -- cgit v1.2.3 From 8beb8b758c33cf1ac5357b31296927e7df8cf971 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matteo=20Gm=C3=BCr?= Date: Mon, 14 Oct 2024 08:15:16 +0000 Subject: Fix typos, implementation in header and missing doxygen --- arch/x86_64/src/memory/frame_allocator.cpp | 32 ++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) (limited to 'arch/x86_64/src/memory') diff --git a/arch/x86_64/src/memory/frame_allocator.cpp b/arch/x86_64/src/memory/frame_allocator.cpp index 829cd6d..3ad2d96 100644 --- a/arch/x86_64/src/memory/frame_allocator.cpp +++ b/arch/x86_64/src/memory/frame_allocator.cpp @@ -2,6 +2,34 @@ namespace teachos::arch::memory { + frame::frame(std::size_t frame_number) + : frame_number(frame_number) + { + // Nothing to do + } + + auto frame::containing_address(std::size_t address) -> frame { return frame{address / PAGE_FRAME_SIZE}; } + + memory_area_iterator::memory_area_iterator(memory_area * p) + : ptr(p) + { + // Nothing to do + } + + memory_area & memory_area_iterator::operator*() const { return *ptr; } + + auto memory_area_iterator::operator++(int) -> memory_area_iterator + { + ++(*this); + return *this; + } + + auto memory_area_iterator::operator++() -> memory_area_iterator & + { + ++ptr; + return *this; + } + auto area_frame_allocator::choose_next_area() -> void { current_area = std::nullopt; @@ -77,4 +105,8 @@ namespace teachos::arch::memory { } } + + auto area_frame_allocator::begin() -> memory_area_iterator { return area_begin; } + + auto area_frame_allocator::end() -> memory_area_iterator { return area_end; } } // namespace teachos::arch::memory -- cgit v1.2.3 From 38e0b13ab9a4997fdf9f311fd125825919d2e6c7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matteo=20Gm=C3=BCr?= Date: Mon, 14 Oct 2024 14:03:27 +0000 Subject: Start developing paging --- arch/x86_64/src/memory/frame_allocator.cpp | 35 +++++++++++--------- arch/x86_64/src/memory/multiboot.cpp | 28 ++++++++-------- arch/x86_64/src/memory/paging.cpp | 53 ++++++++++++++++++++++++++++++ 3 files changed, 86 insertions(+), 30 deletions(-) create mode 100644 arch/x86_64/src/memory/paging.cpp (limited to 'arch/x86_64/src/memory') diff --git a/arch/x86_64/src/memory/frame_allocator.cpp b/arch/x86_64/src/memory/frame_allocator.cpp index 3ad2d96..3733cc3 100644 --- a/arch/x86_64/src/memory/frame_allocator.cpp +++ b/arch/x86_64/src/memory/frame_allocator.cpp @@ -2,13 +2,16 @@ namespace teachos::arch::memory { - frame::frame(std::size_t frame_number) + physical_frame::physical_frame(std::size_t frame_number) : frame_number(frame_number) { // Nothing to do } - auto frame::containing_address(std::size_t address) -> frame { return frame{address / PAGE_FRAME_SIZE}; } + auto physical_frame::containing_address(std::size_t address) -> physical_frame + { + return physical_frame{address / PAGE_FRAME_SIZE}; + } memory_area_iterator::memory_area_iterator(memory_area * p) : ptr(p) @@ -39,7 +42,7 @@ namespace teachos::arch::memory memory_area & area = *it; std::size_t address = area.base_address + area.area_length - 1; - if (frame::containing_address(address) >= next_free_frame) + if (physical_frame::containing_address(address) >= next_free_frame) { // The `next_free_frame` address is smaller than the last address of the current area if (!current_area || area.base_address < current_area->base_address) @@ -52,7 +55,7 @@ namespace teachos::arch::memory if (current_area) { // Update the `next_free_frame` according to the new memory area - frame start_frame = frame::containing_address(current_area->base_address); + physical_frame start_frame = physical_frame::containing_address(current_area->base_address); if (next_free_frame < start_frame) { next_free_frame = start_frame; @@ -60,7 +63,7 @@ namespace teachos::arch::memory } } - auto area_frame_allocator::allocate_frame() -> std::optional + auto area_frame_allocator::allocate_frame() -> std::optional { /* * Only try to allocate memory if current_area is not null, because @@ -68,29 +71,29 @@ namespace teachos::arch::memory */ if (current_area) { - frame frame{next_free_frame.frame_number}; + physical_frame physical_frame{next_free_frame.frame_number}; - struct frame current_area_last_frame = { - frame::containing_address(current_area->base_address + current_area->area_length - 1)}; + struct physical_frame current_area_last_frame = { + physical_frame::containing_address(current_area->base_address + current_area->area_length - 1)}; if (next_free_frame > current_area_last_frame) { // All frames of current area are used, switch to next area choose_next_area(); } - else if (frame >= multiboot_start && frame <= kernel_end) + else if (physical_frame >= multiboot_start && physical_frame <= kernel_end) { - // `frame` is used by the kernel or multiboot information structure - next_free_frame = arch::memory::frame{kernel_end.frame_number + 1}; + // `physical_frame` is used by the kernel or multiboot information structure + next_free_frame = arch::memory::physical_frame{kernel_end.frame_number + 1}; } else { // Frame is unused, increment `next_free_frame` and return it next_free_frame.frame_number += 1; - return frame; + return physical_frame; } - // `frame` was not valid, try it again with the updated `next_free_frame` + // `physical_frame` was not valid, try it again with the updated `next_free_frame` return allocate_frame(); } @@ -98,10 +101,10 @@ namespace teachos::arch::memory return std::nullopt; } - auto area_frame_allocator::deallocate_frame(frame frame) -> void + auto area_frame_allocator::deallocate_frame(physical_frame physical_frame) -> void { - // TODO: Fix, simply done because compiler will complain if frame is unused and not compile - if (frame.frame_number == 3) + // TODO: Fix, simply done because compiler will complain if physical_frame is unused and not compile + if (physical_frame.frame_number == 3) { } } diff --git a/arch/x86_64/src/memory/multiboot.cpp b/arch/x86_64/src/memory/multiboot.cpp index 3f6248d..bd3b00b 100644 --- a/arch/x86_64/src/memory/multiboot.cpp +++ b/arch/x86_64/src/memory/multiboot.cpp @@ -2,35 +2,35 @@ namespace teachos::arch::memory { - auto elf_section_flags::writeable() const -> bool { return is_bit_set(0); } + auto elf_section_flags::writable() const -> bool { return is_bit_set(0U); } - auto elf_section_flags::occupies_memory() const -> bool { return is_bit_set(1); } + auto elf_section_flags::occupies_memory() const -> bool { return is_bit_set(1U); } - auto elf_section_flags::is_executable() const -> bool { return is_bit_set(2); } + auto elf_section_flags::is_executable() const -> bool { return is_bit_set(2U); } - auto elf_section_flags::contains_duplicate_data() const -> bool { return is_bit_set(4); } + auto elf_section_flags::contains_duplicate_data() const -> bool { return is_bit_set(4U); } - auto elf_section_flags::contains_strings() const -> bool { return is_bit_set(5); } + auto elf_section_flags::contains_strings() const -> bool { return is_bit_set(5U); } - auto elf_section_flags::section_header_info_is_section_header_table_index() const -> bool { return is_bit_set(6); } + auto elf_section_flags::section_header_info_is_section_header_table_index() const -> bool { return is_bit_set(6U); } - auto elf_section_flags::preserve_ordering_after_combination() const -> bool { return is_bit_set(7); } + auto elf_section_flags::preserve_ordering_after_combination() const -> bool { return is_bit_set(7U); } - auto elf_section_flags::requires_special_os_processing() const -> bool { return is_bit_set(8); } + auto elf_section_flags::requires_special_os_processing() const -> bool { return is_bit_set(8U); } - auto elf_section_flags::is_section_group_member() const -> bool { return is_bit_set(9); } + auto elf_section_flags::is_section_group_member() const -> bool { return is_bit_set(9U); } - auto elf_section_flags::holds_thread_local_data() const -> bool { return is_bit_set(10); } + auto elf_section_flags::holds_thread_local_data() const -> bool { return is_bit_set(10U); } - auto elf_section_flags::is_compressed() const -> bool { return is_bit_set(11); } + auto elf_section_flags::is_compressed() const -> bool { return is_bit_set(11U); } - auto elf_section_flags::has_special_ordering_requirements() const -> bool { return is_bit_set(30); } + auto elf_section_flags::has_special_ordering_requirements() const -> bool { return is_bit_set(30U); } - auto elf_section_flags::is_excluded_unless_referenced_or_allocated() const -> bool { return is_bit_set(31); } + auto elf_section_flags::is_excluded_unless_referenced_or_allocated() const -> bool { return is_bit_set(31U); } auto elf_section_flags::operator==(elf_section_flags const & other) const -> bool { return flags == other.flags; } - auto elf_section_flags::is_bit_set(uint8_t index) const -> bool { return flags[index] == 1; } + auto elf_section_flags::is_bit_set(uint8_t index) const -> bool { return flags[index] == 1U; } auto elf_section_header::is_null() const -> bool { diff --git a/arch/x86_64/src/memory/paging.cpp b/arch/x86_64/src/memory/paging.cpp new file mode 100644 index 0000000..555357c --- /dev/null +++ b/arch/x86_64/src/memory/paging.cpp @@ -0,0 +1,53 @@ +#include "arch/memory/paging.hpp" + +namespace teachos::arch::memory +{ + auto entry::is_unused() const -> bool { return flags == 0U; } + + auto entry::set_unused() -> void { flags = 0U; } + + auto entry::present() const -> bool { return is_bit_set(0U); } + + auto entry::writable() const -> bool { return is_bit_set(1U); } + + auto entry::user_accessible() const -> bool { return is_bit_set(2U); } + + auto entry::write_through_caching() const -> bool { return is_bit_set(3U); } + + auto entry::disabled_caching() const -> bool { return is_bit_set(4U); } + + auto entry::is_accessing() const -> bool { return is_bit_set(5U); } + + auto entry::is_diry() const -> bool { return is_bit_set(6U); } + + auto entry::is_huge_page() const -> bool { return is_bit_set(7U); } + + auto entry::is_global() const -> bool { return is_bit_set(8U); } + + auto entry::executing_code_forbidden() const -> bool { return is_bit_set(63U); } + + auto entry::calculate_pointed_to_frame() const -> std::optional + { + if (present()) + { + auto physical_address = calculate_physical_address(); + return 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 = 51U; + 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::is_bit_set(uint8_t index) const -> bool { return flags[index] == 1U; } +} // namespace teachos::arch::memory -- cgit v1.2.3 From 205934ca45d591924b4be6e7ae5a8849958e0cf6 Mon Sep 17 00:00:00 2001 From: Fabian Imhof Date: Tue, 15 Oct 2024 08:23:39 +0000 Subject: continue implementing paging --- arch/x86_64/src/memory/frame_allocator.cpp | 12 ++++++---- arch/x86_64/src/memory/paging.cpp | 36 +++++++++++------------------- 2 files changed, 21 insertions(+), 27 deletions(-) (limited to 'arch/x86_64/src/memory') diff --git a/arch/x86_64/src/memory/frame_allocator.cpp b/arch/x86_64/src/memory/frame_allocator.cpp index 3733cc3..01dcc88 100644 --- a/arch/x86_64/src/memory/frame_allocator.cpp +++ b/arch/x86_64/src/memory/frame_allocator.cpp @@ -1,7 +1,11 @@ #include "arch/memory/frame_allocator.hpp" +#include "arch/exception_handling/assert.hpp" + namespace teachos::arch::memory { + uint64_t PAGE_SIZE; + physical_frame::physical_frame(std::size_t frame_number) : frame_number(frame_number) { @@ -13,6 +17,8 @@ namespace teachos::arch::memory return physical_frame{address / PAGE_FRAME_SIZE}; } + auto physical_frame::start_address() const -> uint64_t { return frame_number * PAGE_SIZE; } + memory_area_iterator::memory_area_iterator(memory_area * p) : ptr(p) { @@ -103,10 +109,8 @@ namespace teachos::arch::memory auto area_frame_allocator::deallocate_frame(physical_frame physical_frame) -> void { - // TODO: Fix, simply done because compiler will complain if physical_frame is unused and not compile - if (physical_frame.frame_number == 3) - { - } + arch::exception_handling::assert(false && physical_frame.frame_number == 0, + "[deallocate_frame] Not implemented Exception"); } auto area_frame_allocator::begin() -> memory_area_iterator { return area_begin; } diff --git a/arch/x86_64/src/memory/paging.cpp b/arch/x86_64/src/memory/paging.cpp index 555357c..90c4199 100644 --- a/arch/x86_64/src/memory/paging.cpp +++ b/arch/x86_64/src/memory/paging.cpp @@ -1,34 +1,16 @@ #include "arch/memory/paging.hpp" +#include "arch/exception_handling/assert.hpp" + namespace teachos::arch::memory { auto entry::is_unused() const -> bool { return flags == 0U; } auto entry::set_unused() -> void { flags = 0U; } - auto entry::present() const -> bool { return is_bit_set(0U); } - - auto entry::writable() const -> bool { return is_bit_set(1U); } - - auto entry::user_accessible() const -> bool { return is_bit_set(2U); } - - auto entry::write_through_caching() const -> bool { return is_bit_set(3U); } - - auto entry::disabled_caching() const -> bool { return is_bit_set(4U); } - - auto entry::is_accessing() const -> bool { return is_bit_set(5U); } - - auto entry::is_diry() const -> bool { return is_bit_set(6U); } - - auto entry::is_huge_page() const -> bool { return is_bit_set(7U); } - - auto entry::is_global() const -> bool { return is_bit_set(8U); } - - auto entry::executing_code_forbidden() const -> bool { return is_bit_set(63U); } - auto entry::calculate_pointed_to_frame() const -> std::optional { - if (present()) + if (contains_flags(1)) { auto physical_address = calculate_physical_address(); return physical_frame::containing_address(physical_address); @@ -39,7 +21,7 @@ namespace teachos::arch::memory auto entry::calculate_physical_address() const -> std::size_t { constexpr std::size_t start_bit = 12U; - constexpr std::size_t end_bit = 51U; + constexpr std::size_t end_bit = 52U; size_t value = 0U; for (auto i = start_bit; i < end_bit; i++) @@ -49,5 +31,13 @@ namespace teachos::arch::memory return value; } - auto entry::is_bit_set(uint8_t index) const -> bool { return flags[index] == 1U; } + auto entry::set(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; + } + + auto entry::contains_flags(std::bitset<64U> b) const -> bool { return (flags & b) == b; } + } // namespace teachos::arch::memory -- cgit v1.2.3 From 03d3dec4807d6adcfc5e21bd13992014900b4eac Mon Sep 17 00:00:00 2001 From: Fabian Imhof Date: Tue, 15 Oct 2024 08:40:56 +0000 Subject: implement page table members --- arch/x86_64/src/memory/paging.cpp | 11 +++++++++++ 1 file changed, 11 insertions(+) (limited to 'arch/x86_64/src/memory') diff --git a/arch/x86_64/src/memory/paging.cpp b/arch/x86_64/src/memory/paging.cpp index 90c4199..58a2b99 100644 --- a/arch/x86_64/src/memory/paging.cpp +++ b/arch/x86_64/src/memory/paging.cpp @@ -40,4 +40,15 @@ namespace teachos::arch::memory auto entry::contains_flags(std::bitset<64U> b) const -> bool { return (flags & b) == b; } + auto page_table::zero_entries() -> void + { + auto begin = &entries[0]; + auto end = &entries[PAGE_TABLE_ENTRY_COUNT]; + + for (auto entry = begin; entry < end; ++entry) + { + entry->set_unused(); + } + } + } // namespace teachos::arch::memory -- cgit v1.2.3 From 11f9c91e602bd0231e6bc402418dedf445e47402 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matteo=20Gm=C3=BCr?= Date: Tue, 15 Oct 2024 08:45:29 +0000 Subject: Adding enum flags --- arch/x86_64/src/memory/multiboot.cpp | 36 ++++-------------------------------- arch/x86_64/src/memory/paging.cpp | 7 +++---- 2 files changed, 7 insertions(+), 36 deletions(-) (limited to 'arch/x86_64/src/memory') diff --git a/arch/x86_64/src/memory/multiboot.cpp b/arch/x86_64/src/memory/multiboot.cpp index bd3b00b..b0432a9 100644 --- a/arch/x86_64/src/memory/multiboot.cpp +++ b/arch/x86_64/src/memory/multiboot.cpp @@ -2,40 +2,12 @@ namespace teachos::arch::memory { - auto elf_section_flags::writable() const -> bool { return is_bit_set(0U); } - - auto elf_section_flags::occupies_memory() const -> bool { return is_bit_set(1U); } - - auto elf_section_flags::is_executable() const -> bool { return is_bit_set(2U); } - - auto elf_section_flags::contains_duplicate_data() const -> bool { return is_bit_set(4U); } - - auto elf_section_flags::contains_strings() const -> bool { return is_bit_set(5U); } - - auto elf_section_flags::section_header_info_is_section_header_table_index() const -> bool { return is_bit_set(6U); } - - auto elf_section_flags::preserve_ordering_after_combination() const -> bool { return is_bit_set(7U); } - - auto elf_section_flags::requires_special_os_processing() const -> bool { return is_bit_set(8U); } - - auto elf_section_flags::is_section_group_member() const -> bool { return is_bit_set(9U); } - - auto elf_section_flags::holds_thread_local_data() const -> bool { return is_bit_set(10U); } - - auto elf_section_flags::is_compressed() const -> bool { return is_bit_set(11U); } - - auto elf_section_flags::has_special_ordering_requirements() const -> bool { return is_bit_set(30U); } - - auto elf_section_flags::is_excluded_unless_referenced_or_allocated() const -> bool { return is_bit_set(31U); } - - auto elf_section_flags::operator==(elf_section_flags const & other) const -> bool { return flags == other.flags; } - - auto elf_section_flags::is_bit_set(uint8_t index) const -> bool { return flags[index] == 1U; } + auto elf_section_flags::contains_flags(std::bitset<64U> b) const -> bool { return (flags & b) == b; } auto elf_section_header::is_null() const -> bool { - return name_table_index == 0U && type == elf_section_type::INACTIVE && - flags == teachos::arch::memory::elf_section_flags{0U} && virtual_address == 0U && file_offset == 0U && - additional_information == 0U && address_alignment == 0U && fixed_table_entry_size == 0U; + return name_table_index == 0U && type == elf_section_type::INACTIVE && flags == elf_section_flags(0U) && + virtual_address == 0U && file_offset == 0U && additional_information == 0U && address_alignment == 0U && + fixed_table_entry_size == 0U; } } // namespace teachos::arch::memory diff --git a/arch/x86_64/src/memory/paging.cpp b/arch/x86_64/src/memory/paging.cpp index 58a2b99..6fef339 100644 --- a/arch/x86_64/src/memory/paging.cpp +++ b/arch/x86_64/src/memory/paging.cpp @@ -31,15 +31,15 @@ namespace teachos::arch::memory return value; } - auto entry::set(physical_frame frame) -> void + auto entry::contains_flags(std::bitset<64U> b) const -> bool { return (flags & b) == b; } + + auto entry::set_address(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; } - auto entry::contains_flags(std::bitset<64U> b) const -> bool { return (flags & b) == b; } - auto page_table::zero_entries() -> void { auto begin = &entries[0]; @@ -50,5 +50,4 @@ namespace teachos::arch::memory entry->set_unused(); } } - } // namespace teachos::arch::memory -- cgit v1.2.3 From 0fac2d5f7a868b5d65db6fb42ce256485e651206 Mon Sep 17 00:00:00 2001 From: Fabian Imhof Date: Tue, 15 Oct 2024 09:02:52 +0000 Subject: replace standalone value with enum --- arch/x86_64/src/memory/paging.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch/x86_64/src/memory') diff --git a/arch/x86_64/src/memory/paging.cpp b/arch/x86_64/src/memory/paging.cpp index 6fef339..4603e74 100644 --- a/arch/x86_64/src/memory/paging.cpp +++ b/arch/x86_64/src/memory/paging.cpp @@ -10,7 +10,7 @@ namespace teachos::arch::memory auto entry::calculate_pointed_to_frame() const -> std::optional { - if (contains_flags(1)) + if (contains_flags(PRESENT)) { auto physical_address = calculate_physical_address(); return physical_frame::containing_address(physical_address); -- cgit v1.2.3 From 429d99ca40254e9e19da938ff9f2065a543708cd Mon Sep 17 00:00:00 2001 From: Fabian Imhof Date: Tue, 15 Oct 2024 09:05:37 +0000 Subject: rename contains_flags parameter --- arch/x86_64/src/memory/multiboot.cpp | 2 +- arch/x86_64/src/memory/paging.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'arch/x86_64/src/memory') diff --git a/arch/x86_64/src/memory/multiboot.cpp b/arch/x86_64/src/memory/multiboot.cpp index b0432a9..8c6793e 100644 --- a/arch/x86_64/src/memory/multiboot.cpp +++ b/arch/x86_64/src/memory/multiboot.cpp @@ -2,7 +2,7 @@ namespace teachos::arch::memory { - auto elf_section_flags::contains_flags(std::bitset<64U> b) const -> bool { return (flags & b) == b; } + auto elf_section_flags::contains_flags(std::bitset<64U> other) const -> bool { return (flags & other) == other; } auto elf_section_header::is_null() const -> bool { diff --git a/arch/x86_64/src/memory/paging.cpp b/arch/x86_64/src/memory/paging.cpp index 4603e74..445c796 100644 --- a/arch/x86_64/src/memory/paging.cpp +++ b/arch/x86_64/src/memory/paging.cpp @@ -31,7 +31,7 @@ namespace teachos::arch::memory return value; } - auto entry::contains_flags(std::bitset<64U> b) const -> bool { return (flags & b) == b; } + auto entry::contains_flags(std::bitset<64U> other) const -> bool { return (flags & other) == other; } auto entry::set_address(physical_frame frame) -> void { -- cgit v1.2.3 From 0c4fd9eaed4a71975879aa83cd2da4b6266a64b5 Mon Sep 17 00:00:00 2001 From: Fabian Imhof Date: Tue, 15 Oct 2024 15:48:43 +0000 Subject: add 4th level page table --- arch/x86_64/src/memory/paging.cpp | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) (limited to 'arch/x86_64/src/memory') diff --git a/arch/x86_64/src/memory/paging.cpp b/arch/x86_64/src/memory/paging.cpp index 445c796..61d9d0f 100644 --- a/arch/x86_64/src/memory/paging.cpp +++ b/arch/x86_64/src/memory/paging.cpp @@ -50,4 +50,31 @@ namespace teachos::arch::memory entry->set_unused(); } } + + auto page_table::next_table_address(std::size_t index) const -> std::optional + { + auto entry = entries[index]; + + if (entry.contains_flags(entry.PRESENT) && !entry.contains_flags(entry.HUGE_PAGE)) + { + std::size_t table_address = reinterpret_cast(this); + return (table_address << 9) | (index << 12); + } + else + { + return std::nullopt; + } + } + + auto page_table::next_table(size_t index) const -> std::optional + { + auto address = next_table_address(index); + + if (address.has_value()) + { + return reinterpret_cast(*address); + } + + return std::nullopt; + } } // namespace teachos::arch::memory -- cgit v1.2.3 From f56004a77314d4b4d68bfaf496fd7c6013ba7a27 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matteo=20Gm=C3=BCr?= Date: Wed, 16 Oct 2024 11:52:01 +0000 Subject: Adjust types --- arch/x86_64/src/memory/paging.cpp | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) (limited to 'arch/x86_64/src/memory') diff --git a/arch/x86_64/src/memory/paging.cpp b/arch/x86_64/src/memory/paging.cpp index 61d9d0f..2f78da8 100644 --- a/arch/x86_64/src/memory/paging.cpp +++ b/arch/x86_64/src/memory/paging.cpp @@ -60,19 +60,17 @@ namespace teachos::arch::memory std::size_t table_address = reinterpret_cast(this); return (table_address << 9) | (index << 12); } - else - { - return std::nullopt; - } + // TODO: Implement behaviour for huge pages currently not done + return std::nullopt; } - auto page_table::next_table(size_t index) const -> std::optional + auto page_table::next_table(std::size_t index) const -> std::optional { auto address = next_table_address(index); if (address.has_value()) { - return reinterpret_cast(*address); + return reinterpret_cast(*address); } return std::nullopt; -- cgit v1.2.3 From 934822e48a7c5a3e65ed74261ce5ab4315595f64 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matteo=20Gm=C3=BCr?= Date: Wed, 16 Oct 2024 13:33:23 +0000 Subject: Fix compilation issues with assigning values to page_map_variable address --- arch/x86_64/src/memory/frame_allocator.cpp | 19 ++++++++++++++++--- arch/x86_64/src/memory/paging.cpp | 13 ++++++++----- 2 files changed, 24 insertions(+), 8 deletions(-) (limited to 'arch/x86_64/src/memory') diff --git a/arch/x86_64/src/memory/frame_allocator.cpp b/arch/x86_64/src/memory/frame_allocator.cpp index 01dcc88..70276ae 100644 --- a/arch/x86_64/src/memory/frame_allocator.cpp +++ b/arch/x86_64/src/memory/frame_allocator.cpp @@ -4,8 +4,6 @@ namespace teachos::arch::memory { - uint64_t PAGE_SIZE; - physical_frame::physical_frame(std::size_t frame_number) : frame_number(frame_number) { @@ -17,7 +15,7 @@ namespace teachos::arch::memory return physical_frame{address / PAGE_FRAME_SIZE}; } - auto physical_frame::start_address() const -> uint64_t { return frame_number * PAGE_SIZE; } + auto physical_frame::start_address() const -> uint64_t { return frame_number * PAGE_FRAME_SIZE; } memory_area_iterator::memory_area_iterator(memory_area * p) : ptr(p) @@ -39,6 +37,21 @@ namespace teachos::arch::memory return *this; } + area_frame_allocator::area_frame_allocator(std::size_t kernel_start, std::size_t kernel_end, + std::size_t multiboot_start, std::size_t multiboot_end, + memory_area * memory_areas, uint8_t area_count) + : next_free_frame(0) + , current_area(std::nullopt) + , area_begin(memory_areas) + , area_end(memory_areas + area_count) + , kernel_start(physical_frame::containing_address(kernel_start)) + , kernel_end(physical_frame::containing_address(kernel_end)) + , multiboot_start(physical_frame::containing_address(multiboot_start)) + , multiboot_end(physical_frame::containing_address(multiboot_end)) + { + choose_next_area(); + } + auto area_frame_allocator::choose_next_area() -> void { current_area = std::nullopt; diff --git a/arch/x86_64/src/memory/paging.cpp b/arch/x86_64/src/memory/paging.cpp index 2f78da8..a07b2c0 100644 --- a/arch/x86_64/src/memory/paging.cpp +++ b/arch/x86_64/src/memory/paging.cpp @@ -42,12 +42,9 @@ namespace teachos::arch::memory auto page_table::zero_entries() -> void { - auto begin = &entries[0]; - auto end = &entries[PAGE_TABLE_ENTRY_COUNT]; - - for (auto entry = begin; entry < end; ++entry) + for (size_t i = 0; i < sizeof(entries) / sizeof(entries[0]); ++i) { - entry->set_unused(); + entries[i].set_unused(); } } @@ -75,4 +72,10 @@ namespace teachos::arch::memory return std::nullopt; } + + entry & page_table::operator[](std::size_t index) + { + arch::exception_handling::assert(index < PAGE_TABLE_ENTRY_COUNT, "[Page Table] index out of bounds"); + return entries[index]; + } } // namespace teachos::arch::memory -- cgit v1.2.3 From 35e25757b6cffbcb2ff1eea8daf4c5f1ca421cb0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matteo=20Gm=C3=BCr?= Date: Wed, 16 Oct 2024 14:10:32 +0000 Subject: Adjust table accessing code to make it safer (always out of bounds checked) --- arch/x86_64/src/memory/paging.cpp | 47 +++++++++++++++++++++++++++------------ 1 file changed, 33 insertions(+), 14 deletions(-) (limited to 'arch/x86_64/src/memory') diff --git a/arch/x86_64/src/memory/paging.cpp b/arch/x86_64/src/memory/paging.cpp index a07b2c0..a8f2c40 100644 --- a/arch/x86_64/src/memory/paging.cpp +++ b/arch/x86_64/src/memory/paging.cpp @@ -40,25 +40,21 @@ namespace teachos::arch::memory flags = std::bitset<64U>(frame.start_address()) | flags; } - auto page_table::zero_entries() -> void + page_table::page_table() + : entries() + , p4(reinterpret_cast(0xfffffffffffff000)) { - for (size_t i = 0; i < sizeof(entries) / sizeof(entries[0]); ++i) - { - entries[i].set_unused(); - } + // Nothing to do } - auto page_table::next_table_address(std::size_t index) const -> std::optional + auto page_table::zero_entries() -> void { - auto entry = entries[index]; - - if (entry.contains_flags(entry.PRESENT) && !entry.contains_flags(entry.HUGE_PAGE)) + constexpr size_t entry_amount = sizeof(entries) / sizeof(entries[0]); + for (size_t i = 0; i < entry_amount; ++i) { - std::size_t table_address = reinterpret_cast(this); - return (table_address << 9) | (index << 12); + auto entry = this->operator[](i); + entry.set_unused(); } - // TODO: Implement behaviour for huge pages currently not done - return std::nullopt; } auto page_table::next_table(std::size_t index) const -> std::optional @@ -73,9 +69,32 @@ namespace teachos::arch::memory return std::nullopt; } - entry & page_table::operator[](std::size_t index) + 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 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 entries[index]; } + + auto page_table::next_table_address(std::size_t index) const -> std::optional + { + auto entry = this->operator[](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) | (index << 12); + } + // TODO: Implement behaviour for huge pages currently not done + return std::nullopt; + } } // namespace teachos::arch::memory -- cgit v1.2.3 From d539ed1f4f26a42959bcae6ea3050b7f99f5f872 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matteo=20Gm=C3=BCr?= Date: Wed, 16 Oct 2024 14:30:04 +0000 Subject: Attempt to implement page table checks using templates --- arch/x86_64/src/memory/paging.cpp | 58 --------------------------------------- 1 file changed, 58 deletions(-) (limited to 'arch/x86_64/src/memory') diff --git a/arch/x86_64/src/memory/paging.cpp b/arch/x86_64/src/memory/paging.cpp index a8f2c40..9774132 100644 --- a/arch/x86_64/src/memory/paging.cpp +++ b/arch/x86_64/src/memory/paging.cpp @@ -39,62 +39,4 @@ namespace teachos::arch::memory "Start address is not aligned with Page"); flags = std::bitset<64U>(frame.start_address()) | flags; } - - page_table::page_table() - : entries() - , p4(reinterpret_cast(0xfffffffffffff000)) - { - // Nothing to do - } - - auto page_table::zero_entries() -> void - { - constexpr size_t entry_amount = sizeof(entries) / sizeof(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 index) const -> std::optional - { - auto address = next_table_address(index); - - if (address.has_value()) - { - return reinterpret_cast(*address); - } - - return std::nullopt; - } - - 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 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 entries[index]; - } - - auto page_table::next_table_address(std::size_t index) const -> std::optional - { - auto entry = this->operator[](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) | (index << 12); - } - // TODO: Implement behaviour for huge pages currently not done - return std::nullopt; - } } // namespace teachos::arch::memory -- cgit v1.2.3 From a2fdcea0d7615f8933401e45e0c64a2f618bb730 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matteo=20Gm=C3=BCr?= Date: Sat, 19 Oct 2024 13:15:45 +0000 Subject: Move compelte multiboot2 code into seperate files and behaviour into seperate static class --- arch/x86_64/src/memory/frame_allocator.cpp | 44 ++------ arch/x86_64/src/memory/multiboot.cpp | 13 --- .../src/memory/multiboot/elf_symbols_section.cpp | 13 +++ arch/x86_64/src/memory/multiboot/memory_map.cpp | 24 +++++ arch/x86_64/src/memory/multiboot/reader.cpp | 117 +++++++++++++++++++++ 5 files changed, 165 insertions(+), 46 deletions(-) delete mode 100644 arch/x86_64/src/memory/multiboot.cpp create mode 100644 arch/x86_64/src/memory/multiboot/elf_symbols_section.cpp create mode 100644 arch/x86_64/src/memory/multiboot/memory_map.cpp create mode 100644 arch/x86_64/src/memory/multiboot/reader.cpp (limited to 'arch/x86_64/src/memory') diff --git a/arch/x86_64/src/memory/frame_allocator.cpp b/arch/x86_64/src/memory/frame_allocator.cpp index 70276ae..7776082 100644 --- a/arch/x86_64/src/memory/frame_allocator.cpp +++ b/arch/x86_64/src/memory/frame_allocator.cpp @@ -17,37 +17,15 @@ namespace teachos::arch::memory auto physical_frame::start_address() const -> uint64_t { return frame_number * PAGE_FRAME_SIZE; } - memory_area_iterator::memory_area_iterator(memory_area * p) - : ptr(p) - { - // Nothing to do - } - - memory_area & memory_area_iterator::operator*() const { return *ptr; } - - auto memory_area_iterator::operator++(int) -> memory_area_iterator - { - ++(*this); - return *this; - } - - auto memory_area_iterator::operator++() -> memory_area_iterator & - { - ++ptr; - return *this; - } - - area_frame_allocator::area_frame_allocator(std::size_t kernel_start, std::size_t kernel_end, - std::size_t multiboot_start, std::size_t multiboot_end, - memory_area * memory_areas, uint8_t area_count) + area_frame_allocator::area_frame_allocator(multiboot::memory_information mem_info) : next_free_frame(0) , current_area(std::nullopt) - , area_begin(memory_areas) - , area_end(memory_areas + area_count) - , kernel_start(physical_frame::containing_address(kernel_start)) - , kernel_end(physical_frame::containing_address(kernel_end)) - , multiboot_start(physical_frame::containing_address(multiboot_start)) - , multiboot_end(physical_frame::containing_address(multiboot_end)) + , area_begin(mem_info.memory_areas) + , area_end(mem_info.memory_areas + mem_info.area_count) + , kernel_start(physical_frame::containing_address(mem_info.kernel_start)) + , kernel_end(physical_frame::containing_address(mem_info.kernel_end)) + , multiboot_start(physical_frame::containing_address(mem_info.multiboot_start)) + , multiboot_end(physical_frame::containing_address(mem_info.multiboot_end)) { choose_next_area(); } @@ -56,9 +34,9 @@ namespace teachos::arch::memory { current_area = std::nullopt; - for (memory_area_iterator it = begin(); it != end(); ++it) + for (multiboot::memory_area_iterator it = begin(); it != end(); ++it) { - memory_area & area = *it; + multiboot::memory_area & area = *it; std::size_t address = area.base_address + area.area_length - 1; if (physical_frame::containing_address(address) >= next_free_frame) @@ -126,7 +104,7 @@ namespace teachos::arch::memory "[deallocate_frame] Not implemented Exception"); } - auto area_frame_allocator::begin() -> memory_area_iterator { return area_begin; } + auto area_frame_allocator::begin() -> multiboot::memory_area_iterator { return area_begin; } - auto area_frame_allocator::end() -> memory_area_iterator { return area_end; } + auto area_frame_allocator::end() -> multiboot::memory_area_iterator { return area_end; } } // namespace teachos::arch::memory diff --git a/arch/x86_64/src/memory/multiboot.cpp b/arch/x86_64/src/memory/multiboot.cpp deleted file mode 100644 index 8c6793e..0000000 --- a/arch/x86_64/src/memory/multiboot.cpp +++ /dev/null @@ -1,13 +0,0 @@ -#include "arch/memory/multiboot.hpp" - -namespace teachos::arch::memory -{ - auto elf_section_flags::contains_flags(std::bitset<64U> other) const -> bool { return (flags & other) == other; } - - auto elf_section_header::is_null() const -> bool - { - return name_table_index == 0U && type == elf_section_type::INACTIVE && flags == elf_section_flags(0U) && - virtual_address == 0U && file_offset == 0U && additional_information == 0U && address_alignment == 0U && - fixed_table_entry_size == 0U; - } -} // namespace teachos::arch::memory diff --git a/arch/x86_64/src/memory/multiboot/elf_symbols_section.cpp b/arch/x86_64/src/memory/multiboot/elf_symbols_section.cpp new file mode 100644 index 0000000..78ab952 --- /dev/null +++ b/arch/x86_64/src/memory/multiboot/elf_symbols_section.cpp @@ -0,0 +1,13 @@ +#include "arch/memory/multiboot/elf_sybols_section.hpp" + +namespace teachos::arch::memory::multiboot +{ + auto elf_section_flags::contains_flags(std::bitset<64U> other) const -> bool { return (flags & other) == other; } + + auto elf_section_header::is_null() const -> bool + { + return name_table_index == 0U && type == elf_section_type::INACTIVE && flags == elf_section_flags(0U) && + virtual_address == 0U && file_offset == 0U && additional_information == 0U && address_alignment == 0U && + fixed_table_entry_size == 0U; + } +} // namespace teachos::arch::memory::multiboot diff --git a/arch/x86_64/src/memory/multiboot/memory_map.cpp b/arch/x86_64/src/memory/multiboot/memory_map.cpp new file mode 100644 index 0000000..6b1d1d4 --- /dev/null +++ b/arch/x86_64/src/memory/multiboot/memory_map.cpp @@ -0,0 +1,24 @@ +#include "arch/memory/multiboot/memory_map.hpp" + +namespace teachos::arch::memory::multiboot +{ + memory_area_iterator::memory_area_iterator(multiboot::memory_area * p) + : ptr(p) + { + // Nothing to do + } + + multiboot::memory_area & memory_area_iterator::operator*() const { return *ptr; } + + auto memory_area_iterator::operator++(int) -> memory_area_iterator + { + ++(*this); + return *this; + } + + auto memory_area_iterator::operator++() -> memory_area_iterator & + { + ++ptr; + return *this; + } +} // namespace teachos::arch::memory::multiboot diff --git a/arch/x86_64/src/memory/multiboot/reader.cpp b/arch/x86_64/src/memory/multiboot/reader.cpp new file mode 100644 index 0000000..8741b44 --- /dev/null +++ b/arch/x86_64/src/memory/multiboot/reader.cpp @@ -0,0 +1,117 @@ +#include "arch/memory/multiboot/reader.hpp" + +#include "arch/boot/pointers.hpp" +#include "arch/exception_handling/assert.hpp" +#include "arch/memory/multiboot/info.hpp" + +namespace teachos::arch::memory::multiboot +{ + namespace + { + template + requires std::is_pointer::value + auto align_to_8_byte_boundary(T ptr, uint32_t size) -> T + { + return reinterpret_cast(reinterpret_cast(ptr) + ((size + 7) & ~7)); + } + + auto process_memory_map(memory_map_header * mminfo, memory_area *& memory_areas, uint8_t & area_count) -> void + { + auto expected_entry_size = mminfo->entry_size; + constexpr auto actual_entry_size = sizeof(memory_area); + arch::exception_handling::assert(expected_entry_size == actual_entry_size, "Unexpected memory_area entry size"); + + auto total_size = mminfo->info.size; + auto total_entries_size = total_size - sizeof(memory_map_header) + actual_entry_size; + auto number_of_entries = total_entries_size / actual_entry_size; + + memory_areas = &mminfo->entries; + area_count = number_of_entries; + } + + auto process_elf_sections(elf_symbols_section_header * symbol, uint64_t & kernel_start, + uint64_t & kernel_end) -> void + { + auto expected_entry_size = symbol->entry_size; + constexpr auto actual_entry_size = sizeof(elf_section_header); + arch::exception_handling::assert(expected_entry_size == actual_entry_size, + "Unexpected elf_section_header entry size"); + + auto expected_total_size = symbol->info.size; + auto actual_total_entry_size = actual_entry_size * symbol->number_of_sections; + constexpr auto actual_total_section_size = sizeof(elf_symbols_section_header) - sizeof(uint32_t); + auto actual_total_size = actual_total_entry_size + actual_total_section_size; + arch::exception_handling::assert(expected_total_size == actual_total_size, + "Unexpected elf_symbols_section_header total size"); + + auto begin = reinterpret_cast(&symbol->end); + auto end = begin + symbol->number_of_sections; + arch::exception_handling::assert(begin->is_null(), "Missing elf_section_header begin"); + + std::size_t symbol_table_section_count = 0U; + std::size_t dynamic_section_count = 0U; + + for (auto section = begin; section != end; ++section) + { + switch (section->type) + { + case elf_section_type::PROGRAMM: { + if (section->virtual_address < kernel_start) + { + kernel_start = section->virtual_address; + } + auto virtual_address_end = section->virtual_address + section->section_size; + if (virtual_address_end > kernel_end) + { + kernel_end = virtual_address_end; + } + break; + } + case elf_section_type::DYNAMIC_SYMBOL_TABLE: + case elf_section_type::SYMBOL_TABLE: + symbol_table_section_count++; + break; + case elf_section_type::DYNAMIC: + dynamic_section_count++; + break; + default: + // All other cases are not important and can be ignored + break; + } + } + + arch::exception_handling::assert(symbol_table_section_count == 1U, "Unexpected symbol_table_count value"); + arch::exception_handling::assert(dynamic_section_count <= 1U, "Unexpected dynamic_section_count value"); + } + } // namespace + + auto read_multiboot2() -> memory_information + { + memory_information mem_info{UINT64_MAX, 0U, boot::multiboot_information_pointer, 0U, nullptr, 0U}; + + auto * multiboot_information_pointer = reinterpret_cast(boot::multiboot_information_pointer); + auto multiboot_tag = &(multiboot_information_pointer->tags); + mem_info.multiboot_end = mem_info.multiboot_start + multiboot_information_pointer->total_size; + + for (auto tag = multiboot_tag; tag->type != tag_type::END; tag = align_to_8_byte_boundary(tag, tag->size)) + { + switch (tag->type) + { + case tag_type::ELF_SECTIONS: { + auto symbol = reinterpret_cast(tag); + process_elf_sections(symbol, mem_info.kernel_start, mem_info.kernel_end); + break; + } + case tag_type::MEMORY_MAP: { + auto mminfo = reinterpret_cast(tag); + process_memory_map(mminfo, mem_info.memory_areas, mem_info.area_count); + break; + } + default: + // All other cases are not important and can be ignored + break; + } + } + return mem_info; + } +} // namespace teachos::arch::memory::multiboot -- cgit v1.2.3 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 --- .../src/memory/allocator/area_frame_allocator.cpp | 97 ++++++++++++++++++ .../x86_64/src/memory/allocator/physical_frame.cpp | 22 +++++ arch/x86_64/src/memory/frame_allocator.cpp | 110 --------------------- arch/x86_64/src/memory/paging.cpp | 42 -------- arch/x86_64/src/memory/paging/page_entry.cpp | 42 ++++++++ arch/x86_64/src/memory/paging/page_table.cpp | 65 ++++++++++++ 6 files changed, 226 insertions(+), 152 deletions(-) create mode 100644 arch/x86_64/src/memory/allocator/area_frame_allocator.cpp create mode 100644 arch/x86_64/src/memory/allocator/physical_frame.cpp delete mode 100644 arch/x86_64/src/memory/frame_allocator.cpp delete mode 100644 arch/x86_64/src/memory/paging.cpp 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') diff --git a/arch/x86_64/src/memory/allocator/area_frame_allocator.cpp b/arch/x86_64/src/memory/allocator/area_frame_allocator.cpp new file mode 100644 index 0000000..9c344d8 --- /dev/null +++ b/arch/x86_64/src/memory/allocator/area_frame_allocator.cpp @@ -0,0 +1,97 @@ +#include "arch/memory/allocator/area_frame_allocator.hpp" + +#include "arch/exception_handling/assert.hpp" + +namespace teachos::arch::memory::allocator +{ + area_frame_allocator::area_frame_allocator(multiboot::memory_information mem_info) + : next_free_frame(0) + , current_area(std::nullopt) + , area_begin(mem_info.memory_areas) + , area_end(mem_info.memory_areas + mem_info.area_count) + , kernel_start(physical_frame::containing_address(mem_info.kernel_start)) + , kernel_end(physical_frame::containing_address(mem_info.kernel_end)) + , multiboot_start(physical_frame::containing_address(mem_info.multiboot_start)) + , multiboot_end(physical_frame::containing_address(mem_info.multiboot_end)) + { + choose_next_area(); + } + + auto area_frame_allocator::choose_next_area() -> void + { + current_area = std::nullopt; + + for (multiboot::memory_area_iterator it = begin(); it != end(); ++it) + { + multiboot::memory_area & area = *it; + + std::size_t address = area.base_address + area.area_length - 1; + if (physical_frame::containing_address(address) >= next_free_frame) + { + // The `next_free_frame` address is smaller than the last address of the current area + if (!current_area || area.base_address < current_area->base_address) + { + current_area = area; + } + } + } + + if (current_area) + { + // Update the `next_free_frame` according to the new memory area + physical_frame start_frame = physical_frame::containing_address(current_area->base_address); + if (next_free_frame < start_frame) + { + next_free_frame = start_frame; + } + } + } + + auto area_frame_allocator::allocate_frame() -> std::optional + { + /* + * Only try to allocate memory if current_area is not null, because + * the current_area is null if there is no more available memory. + */ + if (current_area) + { + physical_frame physical_frame{next_free_frame.frame_number}; + + struct physical_frame current_area_last_frame = { + physical_frame::containing_address(current_area->base_address + current_area->area_length - 1)}; + + if (next_free_frame > current_area_last_frame) + { + // All frames of current area are used, switch to next area + choose_next_area(); + } + else if (physical_frame >= multiboot_start && physical_frame <= kernel_end) + { + // `physical_frame` is used by the kernel or multiboot information structure + next_free_frame = allocator::physical_frame{kernel_end.frame_number + 1}; + } + else + { + // Frame is unused, increment `next_free_frame` and return it + next_free_frame.frame_number += 1; + return physical_frame; + } + + // `physical_frame` was not valid, try it again with the updated `next_free_frame` + return allocate_frame(); + } + + // no free frames left + return std::nullopt; + } + + auto area_frame_allocator::deallocate_frame(physical_frame physical_frame) -> void + { + arch::exception_handling::assert(false && physical_frame.frame_number == 0, + "[deallocate_frame] Not implemented Exception"); + } + + auto area_frame_allocator::begin() -> multiboot::memory_area_iterator { return area_begin; } + + auto area_frame_allocator::end() -> multiboot::memory_area_iterator { return area_end; } +} // namespace teachos::arch::memory::allocator diff --git a/arch/x86_64/src/memory/allocator/physical_frame.cpp b/arch/x86_64/src/memory/allocator/physical_frame.cpp new file mode 100644 index 0000000..03ec193 --- /dev/null +++ b/arch/x86_64/src/memory/allocator/physical_frame.cpp @@ -0,0 +1,22 @@ +#include "arch/memory/allocator/physical_frame.hpp" + +namespace teachos::arch::memory::allocator +{ + namespace + { + constexpr std::size_t PAGE_FRAME_SIZE = 4096U; ///< Default page size of x86_84 is always 4KiB. + } + + physical_frame::physical_frame(std::size_t frame_number) + : frame_number(frame_number) + { + // Nothing to do + } + + auto physical_frame::containing_address(std::size_t address) -> physical_frame + { + return physical_frame{address / PAGE_FRAME_SIZE}; + } + + auto physical_frame::start_address() const -> uint64_t { return frame_number * PAGE_FRAME_SIZE; } +} // namespace teachos::arch::memory::allocator diff --git a/arch/x86_64/src/memory/frame_allocator.cpp b/arch/x86_64/src/memory/frame_allocator.cpp deleted file mode 100644 index 7776082..0000000 --- a/arch/x86_64/src/memory/frame_allocator.cpp +++ /dev/null @@ -1,110 +0,0 @@ -#include "arch/memory/frame_allocator.hpp" - -#include "arch/exception_handling/assert.hpp" - -namespace teachos::arch::memory -{ - physical_frame::physical_frame(std::size_t frame_number) - : frame_number(frame_number) - { - // Nothing to do - } - - auto physical_frame::containing_address(std::size_t address) -> physical_frame - { - return physical_frame{address / PAGE_FRAME_SIZE}; - } - - auto physical_frame::start_address() const -> uint64_t { return frame_number * PAGE_FRAME_SIZE; } - - area_frame_allocator::area_frame_allocator(multiboot::memory_information mem_info) - : next_free_frame(0) - , current_area(std::nullopt) - , area_begin(mem_info.memory_areas) - , area_end(mem_info.memory_areas + mem_info.area_count) - , kernel_start(physical_frame::containing_address(mem_info.kernel_start)) - , kernel_end(physical_frame::containing_address(mem_info.kernel_end)) - , multiboot_start(physical_frame::containing_address(mem_info.multiboot_start)) - , multiboot_end(physical_frame::containing_address(mem_info.multiboot_end)) - { - choose_next_area(); - } - - auto area_frame_allocator::choose_next_area() -> void - { - current_area = std::nullopt; - - for (multiboot::memory_area_iterator it = begin(); it != end(); ++it) - { - multiboot::memory_area & area = *it; - - std::size_t address = area.base_address + area.area_length - 1; - if (physical_frame::containing_address(address) >= next_free_frame) - { - // The `next_free_frame` address is smaller than the last address of the current area - if (!current_area || area.base_address < current_area->base_address) - { - current_area = area; - } - } - } - - if (current_area) - { - // Update the `next_free_frame` according to the new memory area - physical_frame start_frame = physical_frame::containing_address(current_area->base_address); - if (next_free_frame < start_frame) - { - next_free_frame = start_frame; - } - } - } - - auto area_frame_allocator::allocate_frame() -> std::optional - { - /* - * Only try to allocate memory if current_area is not null, because - * the current_area is null if there is no more available memory. - */ - if (current_area) - { - physical_frame physical_frame{next_free_frame.frame_number}; - - struct physical_frame current_area_last_frame = { - physical_frame::containing_address(current_area->base_address + current_area->area_length - 1)}; - - if (next_free_frame > current_area_last_frame) - { - // All frames of current area are used, switch to next area - choose_next_area(); - } - else if (physical_frame >= multiboot_start && physical_frame <= kernel_end) - { - // `physical_frame` is used by the kernel or multiboot information structure - next_free_frame = arch::memory::physical_frame{kernel_end.frame_number + 1}; - } - else - { - // Frame is unused, increment `next_free_frame` and return it - next_free_frame.frame_number += 1; - return physical_frame; - } - - // `physical_frame` was not valid, try it again with the updated `next_free_frame` - return allocate_frame(); - } - - // no free frames left - return std::nullopt; - } - - auto area_frame_allocator::deallocate_frame(physical_frame physical_frame) -> void - { - arch::exception_handling::assert(false && physical_frame.frame_number == 0, - "[deallocate_frame] Not implemented Exception"); - } - - auto area_frame_allocator::begin() -> multiboot::memory_area_iterator { return area_begin; } - - auto area_frame_allocator::end() -> multiboot::memory_area_iterator { return area_end; } -} // namespace teachos::arch::memory diff --git a/arch/x86_64/src/memory/paging.cpp b/arch/x86_64/src/memory/paging.cpp deleted file mode 100644 index 9774132..0000000 --- a/arch/x86_64/src/memory/paging.cpp +++ /dev/null @@ -1,42 +0,0 @@ -#include "arch/memory/paging.hpp" - -#include "arch/exception_handling/assert.hpp" - -namespace teachos::arch::memory -{ - 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 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(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 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 7ca089125b8c5e55dd584648cd33612883cc004d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matteo=20Gm=C3=BCr?= Date: Sun, 20 Oct 2024 06:26:58 +0000 Subject: Fix typo in file name --- arch/x86_64/src/memory/multiboot/elf_symbols_section.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch/x86_64/src/memory') diff --git a/arch/x86_64/src/memory/multiboot/elf_symbols_section.cpp b/arch/x86_64/src/memory/multiboot/elf_symbols_section.cpp index 78ab952..953a57d 100644 --- a/arch/x86_64/src/memory/multiboot/elf_symbols_section.cpp +++ b/arch/x86_64/src/memory/multiboot/elf_symbols_section.cpp @@ -1,4 +1,4 @@ -#include "arch/memory/multiboot/elf_sybols_section.hpp" +#include "arch/memory/multiboot/elf_symbols_section.hpp" namespace teachos::arch::memory::multiboot { -- 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') 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 --- .../src/memory/allocator/area_frame_allocator.cpp | 4 ++-- .../x86_64/src/memory/allocator/physical_frame.cpp | 5 ----- arch/x86_64/src/memory/multiboot/reader.cpp | 15 +++++++-------- 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 ++++++++++++++++++++++ 6 files changed, 36 insertions(+), 20 deletions(-) create mode 100644 arch/x86_64/src/memory/paging/virtual_page.cpp (limited to 'arch/x86_64/src/memory') diff --git a/arch/x86_64/src/memory/allocator/area_frame_allocator.cpp b/arch/x86_64/src/memory/allocator/area_frame_allocator.cpp index 9c344d8..c2cafce 100644 --- a/arch/x86_64/src/memory/allocator/area_frame_allocator.cpp +++ b/arch/x86_64/src/memory/allocator/area_frame_allocator.cpp @@ -87,8 +87,8 @@ namespace teachos::arch::memory::allocator auto area_frame_allocator::deallocate_frame(physical_frame physical_frame) -> void { - arch::exception_handling::assert(false && physical_frame.frame_number == 0, - "[deallocate_frame] Not implemented Exception"); + exception_handling::assert(false && physical_frame.frame_number == 0, + "[deallocate_frame] Not implemented Exception"); } auto area_frame_allocator::begin() -> multiboot::memory_area_iterator { return area_begin; } diff --git a/arch/x86_64/src/memory/allocator/physical_frame.cpp b/arch/x86_64/src/memory/allocator/physical_frame.cpp index 03ec193..03bd965 100644 --- a/arch/x86_64/src/memory/allocator/physical_frame.cpp +++ b/arch/x86_64/src/memory/allocator/physical_frame.cpp @@ -2,11 +2,6 @@ namespace teachos::arch::memory::allocator { - namespace - { - constexpr std::size_t PAGE_FRAME_SIZE = 4096U; ///< Default page size of x86_84 is always 4KiB. - } - physical_frame::physical_frame(std::size_t frame_number) : frame_number(frame_number) { diff --git a/arch/x86_64/src/memory/multiboot/reader.cpp b/arch/x86_64/src/memory/multiboot/reader.cpp index 8741b44..156b437 100644 --- a/arch/x86_64/src/memory/multiboot/reader.cpp +++ b/arch/x86_64/src/memory/multiboot/reader.cpp @@ -19,7 +19,7 @@ namespace teachos::arch::memory::multiboot { auto expected_entry_size = mminfo->entry_size; constexpr auto actual_entry_size = sizeof(memory_area); - arch::exception_handling::assert(expected_entry_size == actual_entry_size, "Unexpected memory_area entry size"); + exception_handling::assert(expected_entry_size == actual_entry_size, "Unexpected memory_area entry size"); auto total_size = mminfo->info.size; auto total_entries_size = total_size - sizeof(memory_map_header) + actual_entry_size; @@ -34,19 +34,18 @@ namespace teachos::arch::memory::multiboot { auto expected_entry_size = symbol->entry_size; constexpr auto actual_entry_size = sizeof(elf_section_header); - arch::exception_handling::assert(expected_entry_size == actual_entry_size, - "Unexpected elf_section_header entry size"); + exception_handling::assert(expected_entry_size == actual_entry_size, "Unexpected elf_section_header entry size"); auto expected_total_size = symbol->info.size; auto actual_total_entry_size = actual_entry_size * symbol->number_of_sections; constexpr auto actual_total_section_size = sizeof(elf_symbols_section_header) - sizeof(uint32_t); auto actual_total_size = actual_total_entry_size + actual_total_section_size; - arch::exception_handling::assert(expected_total_size == actual_total_size, - "Unexpected elf_symbols_section_header total size"); + exception_handling::assert(expected_total_size == actual_total_size, + "Unexpected elf_symbols_section_header total size"); auto begin = reinterpret_cast(&symbol->end); auto end = begin + symbol->number_of_sections; - arch::exception_handling::assert(begin->is_null(), "Missing elf_section_header begin"); + exception_handling::assert(begin->is_null(), "Missing elf_section_header begin"); std::size_t symbol_table_section_count = 0U; std::size_t dynamic_section_count = 0U; @@ -80,8 +79,8 @@ namespace teachos::arch::memory::multiboot } } - arch::exception_handling::assert(symbol_table_section_count == 1U, "Unexpected symbol_table_count value"); - arch::exception_handling::assert(dynamic_section_count <= 1U, "Unexpected dynamic_section_count value"); + exception_handling::assert(symbol_table_section_count == 1U, "Unexpected symbol_table_count value"); + exception_handling::assert(dynamic_section_count <= 1U, "Unexpected dynamic_section_count value"); } } // namespace 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') 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/multiboot/reader.cpp | 1 + arch/x86_64/src/memory/paging/page_table.cpp | 2 +- arch/x86_64/src/memory/paging/virtual_page.cpp | 1 - 3 files changed, 2 insertions(+), 2 deletions(-) (limited to 'arch/x86_64/src/memory') diff --git a/arch/x86_64/src/memory/multiboot/reader.cpp b/arch/x86_64/src/memory/multiboot/reader.cpp index 156b437..565f604 100644 --- a/arch/x86_64/src/memory/multiboot/reader.cpp +++ b/arch/x86_64/src/memory/multiboot/reader.cpp @@ -111,6 +111,7 @@ namespace teachos::arch::memory::multiboot break; } } + return mem_info; } } // namespace teachos::arch::memory::multiboot 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') 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') 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') 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') 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') 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') 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') 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') 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') 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/multiboot/reader.cpp | 24 ++++++++++++++++++------ 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 +- 4 files changed, 31 insertions(+), 21 deletions(-) (limited to 'arch/x86_64/src/memory') diff --git a/arch/x86_64/src/memory/multiboot/reader.cpp b/arch/x86_64/src/memory/multiboot/reader.cpp index 565f604..4e78a06 100644 --- a/arch/x86_64/src/memory/multiboot/reader.cpp +++ b/arch/x86_64/src/memory/multiboot/reader.cpp @@ -19,7 +19,9 @@ namespace teachos::arch::memory::multiboot { auto expected_entry_size = mminfo->entry_size; constexpr auto actual_entry_size = sizeof(memory_area); - exception_handling::assert(expected_entry_size == actual_entry_size, "Unexpected memory_area entry size"); + exception_handling::assert(expected_entry_size == actual_entry_size, + "[Multiboot Reader] Expected memory area entry size (%u) but got (%u)", + expected_entry_size, actual_entry_size); auto total_size = mminfo->info.size; auto total_entries_size = total_size - sizeof(memory_map_header) + actual_entry_size; @@ -34,18 +36,22 @@ namespace teachos::arch::memory::multiboot { auto expected_entry_size = symbol->entry_size; constexpr auto actual_entry_size = sizeof(elf_section_header); - exception_handling::assert(expected_entry_size == actual_entry_size, "Unexpected elf_section_header entry size"); + exception_handling::assert(expected_entry_size == actual_entry_size, + "[Multiboot Reader] Expected elf section header entry size (%u) but got (%u)", + expected_entry_size, actual_entry_size); auto expected_total_size = symbol->info.size; auto actual_total_entry_size = actual_entry_size * symbol->number_of_sections; constexpr auto actual_total_section_size = sizeof(elf_symbols_section_header) - sizeof(uint32_t); auto actual_total_size = actual_total_entry_size + actual_total_section_size; exception_handling::assert(expected_total_size == actual_total_size, - "Unexpected elf_symbols_section_header total size"); + "[Multiboot Reader] Expected elf symbols section header total size (%u) but got (%u)", + expected_total_size, actual_total_size); auto begin = reinterpret_cast(&symbol->end); auto end = begin + symbol->number_of_sections; - exception_handling::assert(begin->is_null(), "Missing elf_section_header begin"); + exception_handling::assert(begin->is_null(), + "[Multiboot Reader] Elf symbols section not starting with SHT_NULL section"); std::size_t symbol_table_section_count = 0U; std::size_t dynamic_section_count = 0U; @@ -79,8 +85,14 @@ namespace teachos::arch::memory::multiboot } } - exception_handling::assert(symbol_table_section_count == 1U, "Unexpected symbol_table_count value"); - exception_handling::assert(dynamic_section_count <= 1U, "Unexpected dynamic_section_count value"); + exception_handling::assert( + symbol_table_section_count == 1U, + "[Multiboot Reader] ELF Specifications allows only (1) symbol table section, but got (%u)", + symbol_table_section_count); + exception_handling::assert( + dynamic_section_count <= 1U, + "[Multiboot Reader] ELF Specifications allows only (1) or less dynamic sections, but got (%u)", + dynamic_section_count); } } // namespace 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 2129bdb22bab7dc5a9d23a31c23f38e847511a46 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matteo=20Gm=C3=BCr?= Date: Sun, 20 Oct 2024 12:17:44 +0000 Subject: =?UTF-8?q?Revert=20assert=20with=20printf=20functionality,=20requ?= =?UTF-8?q?ires=20malloc=20=F0=9F=98=AD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- arch/x86_64/src/memory/multiboot/reader.cpp | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) (limited to 'arch/x86_64/src/memory') diff --git a/arch/x86_64/src/memory/multiboot/reader.cpp b/arch/x86_64/src/memory/multiboot/reader.cpp index 4e78a06..545e517 100644 --- a/arch/x86_64/src/memory/multiboot/reader.cpp +++ b/arch/x86_64/src/memory/multiboot/reader.cpp @@ -20,8 +20,7 @@ namespace teachos::arch::memory::multiboot auto expected_entry_size = mminfo->entry_size; constexpr auto actual_entry_size = sizeof(memory_area); exception_handling::assert(expected_entry_size == actual_entry_size, - "[Multiboot Reader] Expected memory area entry size (%u) but got (%u)", - expected_entry_size, actual_entry_size); + "[Multiboot Reader] Unexpected memory area entry size"); auto total_size = mminfo->info.size; auto total_entries_size = total_size - sizeof(memory_map_header) + actual_entry_size; @@ -37,16 +36,14 @@ namespace teachos::arch::memory::multiboot auto expected_entry_size = symbol->entry_size; constexpr auto actual_entry_size = sizeof(elf_section_header); exception_handling::assert(expected_entry_size == actual_entry_size, - "[Multiboot Reader] Expected elf section header entry size (%u) but got (%u)", - expected_entry_size, actual_entry_size); + "[Multiboot Reader] Unexpected elf section header entry size"); auto expected_total_size = symbol->info.size; auto actual_total_entry_size = actual_entry_size * symbol->number_of_sections; constexpr auto actual_total_section_size = sizeof(elf_symbols_section_header) - sizeof(uint32_t); auto actual_total_size = actual_total_entry_size + actual_total_section_size; exception_handling::assert(expected_total_size == actual_total_size, - "[Multiboot Reader] Expected elf symbols section header total size (%u) but got (%u)", - expected_total_size, actual_total_size); + "[Multiboot Reader] Unexpected elf symbols section header total size"); auto begin = reinterpret_cast(&symbol->end); auto end = begin + symbol->number_of_sections; @@ -87,12 +84,10 @@ namespace teachos::arch::memory::multiboot exception_handling::assert( symbol_table_section_count == 1U, - "[Multiboot Reader] ELF Specifications allows only (1) symbol table section, but got (%u)", - symbol_table_section_count); + "[Multiboot Reader] ELF Specifications allows only (1) symbol table section, but got more"); exception_handling::assert( dynamic_section_count <= 1U, - "[Multiboot Reader] ELF Specifications allows only (1) or less dynamic sections, but got (%u)", - dynamic_section_count); + "[Multiboot Reader] ELF Specifications allows only (1) or less dynamic sections, but got more"); } } // namespace -- 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') 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') 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') 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') 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') 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') 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') 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') 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) + { + return page_table_handle{next_table.value(), handle_level--}; + } + return std::nullopt; + } + + auto page_table_handle::operator[](std::size_t index) const -> entry { return handle->operator[](index); } } // namespace teachos::arch::memory::paging -- cgit v1.2.3 From 4b6e66f686a0341613a303b45e16e5bc744c32dd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matteo=20Gm=C3=BCr?= Date: Mon, 21 Oct 2024 12:37:36 +0000 Subject: Fix weird linker error --- arch/x86_64/src/memory/paging/page_mapper.cpp | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) (limited to 'arch/x86_64/src/memory') diff --git a/arch/x86_64/src/memory/paging/page_mapper.cpp b/arch/x86_64/src/memory/paging/page_mapper.cpp index 01c39ca..28e248b 100644 --- a/arch/x86_64/src/memory/paging/page_mapper.cpp +++ b/arch/x86_64/src/memory/paging/page_mapper.cpp @@ -9,10 +9,9 @@ namespace teachos::arch::memory::paging auto create_or_get() -> page_table_handle { - static page_table_handle active_page{reinterpret_cast(PAGE_TABLE_LEVEL_4_ADDRESS), - page_table::LEVEL4}; - - return active_page; + static page_table * const active_page{reinterpret_cast(PAGE_TABLE_LEVEL_4_ADDRESS)}; + // We can not save page_table_handle as a static variable directly, if we do the program will fail to link. + return page_table_handle{active_page, page_table::LEVEL4}; } auto translate_page(virtual_page page) -> std::optional -- cgit v1.2.3 From 552477a12a1163f0f80801b4055dcb5ab3f79e3e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matteo=20Gm=C3=BCr?= Date: Mon, 21 Oct 2024 12:53:23 +0000 Subject: Use forward declaration to hide actual page_table --- arch/x86_64/src/memory/paging/page_mapper.cpp | 21 +++++---- arch/x86_64/src/memory/paging/page_table.cpp | 63 ++++++++++++++++++++++---- arch/x86_64/src/memory/paging/virtual_page.cpp | 2 +- 3 files changed, 65 insertions(+), 21 deletions(-) (limited to 'arch/x86_64/src/memory') diff --git a/arch/x86_64/src/memory/paging/page_mapper.cpp b/arch/x86_64/src/memory/paging/page_mapper.cpp index 28e248b..b8f6b89 100644 --- a/arch/x86_64/src/memory/paging/page_mapper.cpp +++ b/arch/x86_64/src/memory/paging/page_mapper.cpp @@ -11,14 +11,14 @@ namespace teachos::arch::memory::paging { static page_table * const active_page{reinterpret_cast(PAGE_TABLE_LEVEL_4_ADDRESS)}; // We can not save page_table_handle as a static variable directly, if we do the program will fail to link. - return page_table_handle{active_page, page_table::LEVEL4}; + return page_table_handle{active_page, page_table_handle::LEVEL4}; } auto translate_page(virtual_page page) -> std::optional { auto current_handle = create_or_get(); - for (auto level = page_table::LEVEL4; level != page_table::LEVEL1; level--) + for (auto level = page_table_handle::LEVEL4; level != page_table_handle::LEVEL1; 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 @@ -30,7 +30,7 @@ namespace teachos::arch::memory::paging current_handle = next_handle.value(); } - auto level1_index = page.get_level_index(page_table::LEVEL1); + auto level1_index = page.get_level_index(page_table_handle::LEVEL1); auto level1_frame = current_handle[level1_index].calculate_pointed_to_frame(); return level1_frame; } @@ -38,14 +38,14 @@ namespace teachos::arch::memory::paging auto translate_huge_page(virtual_page page) -> std::optional { auto current_handle = create_or_get(); - auto level3_handle = current_handle.next_table(page.get_level_index(page_table::LEVEL4)); + auto level3_handle = current_handle.next_table(page.get_level_index(page_table_handle::LEVEL4)); if (!level3_handle) { return std::nullopt; } - auto level3_entry = level3_handle.value()[page.get_level_index(page_table::LEVEL3)]; + auto level3_entry = level3_handle.value()[page.get_level_index(page_table_handle::LEVEL3)]; auto level3_frame = level3_entry.calculate_pointed_to_frame(); if (level3_frame && level3_entry.contains_flags(entry::HUGE_PAGE)) { @@ -53,20 +53,21 @@ namespace teachos::arch::memory::paging 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)}; + page.get_level_index(page_table_handle::LEVEL2) * PAGE_TABLE_ENTRY_COUNT + + page.get_level_index(page_table_handle::LEVEL1)}; } - auto level2_handle = level3_handle.value().next_table(page.get_level_index(page_table::LEVEL3)); + auto level2_handle = level3_handle.value().next_table(page.get_level_index(page_table_handle::LEVEL3)); if (level2_handle) { - auto level2_entry = level2_handle.value()[page.get_level_index(page_table::LEVEL2)]; + auto level2_entry = level2_handle.value()[page.get_level_index(page_table_handle::LEVEL2)]; auto level2_frame = level2_entry.calculate_pointed_to_frame(); if (level2_frame && level2_entry.contains_flags(entry::HUGE_PAGE)) { 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.value().frame_number + page.get_level_index(page_table::LEVEL1)}; + return allocator::physical_frame{level2_frame.value().frame_number + + page.get_level_index(page_table_handle::LEVEL1)}; } } return std::nullopt; diff --git a/arch/x86_64/src/memory/paging/page_table.cpp b/arch/x86_64/src/memory/paging/page_table.cpp index 907b64f..852bbd5 100644 --- a/arch/x86_64/src/memory/paging/page_table.cpp +++ b/arch/x86_64/src/memory/paging/page_table.cpp @@ -4,6 +4,57 @@ namespace teachos::arch::memory::paging { + /** + * @brief A Page table containing 512 entries. + */ + struct page_table + { + /** + * @brief Set every entry of the page to unused. + */ + auto zero_entries() -> void; + + /** + * @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. This method should not be called + * on a Level 1 page table, because there is no furthere page table and mangeling up and returning the physical + * address would cause hard to debug issues. + * + * @param table_index Index of this page table in the page table one level lower. + */ + auto next_table(std::size_t table_index) const -> std::optional; + + /** + * @brief Index operator overload to access specific entries directy. + * + * @param index Index of the entry we want to access and read or write too. + * @return Entry at the given table index. + */ + auto operator[](std::size_t index) const -> entry; + + private: + /** + * @brief Calculates the address of the next page table level for the given table index. The next page table address + * is only valid if the corresponding entry is present and not a huge page. Meaning we use an index into a + * Level 4 page table to get the according Level 3 page table address. + * + * @param table_index Index of this page table in the page table one level higher. + * @return An optional of the address of the next page table or null. + */ + auto next_table_address(std::size_t table_index) const -> std::optional; + + entry entries[PAGE_TABLE_ENTRY_COUNT]; ///< Entries containing addresses to page tables of a level below or actual + ///< virtual addresses for the level 1 page table. + }; + + auto operator--(page_table_handle::level level, int) -> page_table_handle::level + { + exception_handling::assert(level != page_table_handle::LEVEL1, + "[Page table] Attemptd to decrement enum to value outside of range"); + auto value = static_cast::type>(level); + return static_cast(--value); + } + auto page_table::zero_entries() -> void { constexpr size_t entry_amount = sizeof(entries) / sizeof(entries[0]); @@ -44,15 +95,7 @@ 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); - } - - page_table_handle::page_table_handle(page_table * handle, page_table::level handle_level) + page_table_handle::page_table_handle(page_table * handle, page_table_handle::level handle_level) : handle(handle) , handle_level(handle_level) { @@ -63,7 +106,7 @@ namespace teachos::arch::memory::paging auto page_table_handle::next_table(std::size_t table_index) const -> std::optional { - exception_handling::assert(handle_level != page_table::LEVEL1, + exception_handling::assert(handle_level != page_table_handle::LEVEL1, "[Page Table] Attempted to call next_table on level 1 page table"); auto next_table = handle->next_table(table_index); if (next_table) diff --git a/arch/x86_64/src/memory/paging/virtual_page.cpp b/arch/x86_64/src/memory/paging/virtual_page.cpp index 9b803d2..fd2085b 100644 --- a/arch/x86_64/src/memory/paging/virtual_page.cpp +++ b/arch/x86_64/src/memory/paging/virtual_page.cpp @@ -19,7 +19,7 @@ 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 + auto virtual_page::get_level_index(page_table_handle::level level) const -> uint64_t { return (start_address() >> (level * 9U)) & 0x1FF; } -- cgit v1.2.3 From 8502cc9b19a9e934e3a4c0b3190b690ee0407a25 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matteo=20Gm=C3=BCr?= Date: Mon, 21 Oct 2024 14:48:03 +0000 Subject: =?UTF-8?q?Fix=20linker=20error=20using=20friend=20method=20?= =?UTF-8?q?=F0=9F=91=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- arch/x86_64/src/memory/paging/page_mapper.cpp | 14 +++++++++++--- arch/x86_64/src/memory/paging/page_table.cpp | 16 ++++++++-------- 2 files changed, 19 insertions(+), 11 deletions(-) (limited to 'arch/x86_64/src/memory') diff --git a/arch/x86_64/src/memory/paging/page_mapper.cpp b/arch/x86_64/src/memory/paging/page_mapper.cpp index b8f6b89..75b17ff 100644 --- a/arch/x86_64/src/memory/paging/page_mapper.cpp +++ b/arch/x86_64/src/memory/paging/page_mapper.cpp @@ -14,15 +14,23 @@ namespace teachos::arch::memory::paging return page_table_handle{active_page, page_table_handle::LEVEL4}; } + auto subtract_level(page_table_handle::level level) -> page_table_handle::level + { + exception_handling::assert(level != page_table_handle::LEVEL1, + "[Page table] Attemptd to decrement enum to value outside of range"); + auto value = static_cast::type>(level); + return static_cast(--value); + } + auto translate_page(virtual_page page) -> std::optional { auto current_handle = create_or_get(); - for (auto level = page_table_handle::LEVEL4; level != page_table_handle::LEVEL1; level--) + for (auto level = page_table_handle::LEVEL4; level != page_table_handle::LEVEL1; level = subtract_level(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 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_handle) { return translate_huge_page(page); diff --git a/arch/x86_64/src/memory/paging/page_table.cpp b/arch/x86_64/src/memory/paging/page_table.cpp index 852bbd5..9c9ca76 100644 --- a/arch/x86_64/src/memory/paging/page_table.cpp +++ b/arch/x86_64/src/memory/paging/page_table.cpp @@ -47,14 +47,6 @@ namespace teachos::arch::memory::paging ///< virtual addresses for the level 1 page table. }; - auto operator--(page_table_handle::level level, int) -> page_table_handle::level - { - exception_handling::assert(level != page_table_handle::LEVEL1, - "[Page table] Attemptd to decrement enum to value outside of range"); - auto value = static_cast::type>(level); - return static_cast(--value); - } - auto page_table::zero_entries() -> void { constexpr size_t entry_amount = sizeof(entries) / sizeof(entries[0]); @@ -117,4 +109,12 @@ namespace teachos::arch::memory::paging } auto page_table_handle::operator[](std::size_t index) const -> entry { return handle->operator[](index); } + + auto operator--(page_table_handle::level value, int) -> page_table_handle::level + { + exception_handling::assert(value != page_table_handle::LEVEL1, + "[Page table] Attemptd to decrement enum to value outside of range"); + auto new_value = static_cast::type>(value); + return static_cast(--new_value); + } } // namespace teachos::arch::memory::paging -- cgit v1.2.3 From 7d1d7c5f63791506049cc188740cc4956fc8d14c Mon Sep 17 00:00:00 2001 From: Fabian Imhof Date: Tue, 22 Oct 2024 05:37:28 +0000 Subject: update comments --- arch/x86_64/src/memory/paging/page_table.cpp | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) (limited to 'arch/x86_64/src/memory') diff --git a/arch/x86_64/src/memory/paging/page_table.cpp b/arch/x86_64/src/memory/paging/page_table.cpp index 9c9ca76..939f3b1 100644 --- a/arch/x86_64/src/memory/paging/page_table.cpp +++ b/arch/x86_64/src/memory/paging/page_table.cpp @@ -15,10 +15,11 @@ namespace teachos::arch::memory::paging auto zero_entries() -> void; /** - * @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. This method should not be called - * on a Level 1 page table, because there is no furthere page table and mangeling up and returning the physical - * address would cause hard to debug issues. + * @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. This method should not + * be called on a Level 1 page table, because there is no furthere page table and mangeling up and returning the + * physical address would cause hard to debug issues. * * @param table_index Index of this page table in the page table one level lower. */ @@ -34,7 +35,9 @@ namespace teachos::arch::memory::paging private: /** - * @brief Calculates the address of the next page table level for the given table index. The next page table address + * @brief Calculates the address of the next page table level for the given table index. + * + * The next page table address * is only valid if the corresponding entry is present and not a huge page. Meaning we use an index into a * Level 4 page table to get the according Level 3 page table address. * @@ -43,8 +46,8 @@ namespace teachos::arch::memory::paging */ auto next_table_address(std::size_t table_index) const -> std::optional; - entry entries[PAGE_TABLE_ENTRY_COUNT]; ///< Entries containing addresses to page tables of a level below or actual - ///< virtual addresses for the level 1 page table. + entry entries[PAGE_TABLE_ENTRY_COUNT]; ///< Entries containing addresses to page tables of a level below or + ///< actual virtual addresses for the level 1 page table. }; auto page_table::zero_entries() -> void @@ -91,7 +94,7 @@ namespace teachos::arch::memory::paging : handle(handle) , handle_level(handle_level) { - exception_handling::assert(handle, "[Page table] Attemptd to pass nullptr as handle to page table handle method"); + exception_handling::assert(handle, "[Page table] Attempted to pass nullptr as handle to page table handle method"); } auto page_table_handle::zero_entries() -> void { handle->zero_entries(); } @@ -113,7 +116,7 @@ namespace teachos::arch::memory::paging auto operator--(page_table_handle::level value, int) -> page_table_handle::level { exception_handling::assert(value != page_table_handle::LEVEL1, - "[Page table] Attemptd to decrement enum to value outside of range"); + "[Page table] Attempted to decrement enum to value outside of range"); auto new_value = static_cast::type>(value); return static_cast(--new_value); } -- cgit v1.2.3 From ba054441f93a30e2042a71d632a6a5fb04007d15 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matteo=20Gm=C3=BCr?= Date: Tue, 22 Oct 2024 06:16:51 +0000 Subject: Adjust all briefs --- arch/x86_64/src/memory/paging/page_table.cpp | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'arch/x86_64/src/memory') diff --git a/arch/x86_64/src/memory/paging/page_table.cpp b/arch/x86_64/src/memory/paging/page_table.cpp index 939f3b1..555d38a 100644 --- a/arch/x86_64/src/memory/paging/page_table.cpp +++ b/arch/x86_64/src/memory/paging/page_table.cpp @@ -15,11 +15,12 @@ namespace teachos::arch::memory::paging auto zero_entries() -> void; /** - * @brief Returns the next page table level from the given page table index. + * @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. * - * Meaning we use an index into a Level 4 page table to get the according Level 3 page table. This method should not - * be called on a Level 1 page table, because there is no furthere page table and mangeling up and returning the - * physical address would cause hard to debug issues. + * @note This method + * should not be called on a Level 1 page table, because there is no furthere page table and mangeling up and + * returning the physical address would cause hard to debug issues. * * @param table_index Index of this page table in the page table one level lower. */ @@ -37,9 +38,8 @@ namespace teachos::arch::memory::paging /** * @brief Calculates the address of the next page table level for the given table index. * - * The next page table address - * is only valid if the corresponding entry is present and not a huge page. Meaning we use an index into a - * Level 4 page table to get the according Level 3 page table address. + * @note The next page table address is only valid if the corresponding entry is present and not a huge page. + * Meaning we use an index into a Level 4 page table to get the according Level 3 page table address. * * @param table_index Index of this page table in the page table one level higher. * @return An optional of the address of the next page table or null. -- cgit v1.2.3 From 5a2892f65abe13c32bb07de697826f374c1d2b1d Mon Sep 17 00:00:00 2001 From: Fabian Imhof Date: Tue, 22 Oct 2024 07:40:35 +0000 Subject: change table level 4 address --- arch/x86_64/src/memory/paging/page_mapper.cpp | 15 ++++----------- 1 file changed, 4 insertions(+), 11 deletions(-) (limited to 'arch/x86_64/src/memory') diff --git a/arch/x86_64/src/memory/paging/page_mapper.cpp b/arch/x86_64/src/memory/paging/page_mapper.cpp index 75b17ff..1371868 100644 --- a/arch/x86_64/src/memory/paging/page_mapper.cpp +++ b/arch/x86_64/src/memory/paging/page_mapper.cpp @@ -4,8 +4,9 @@ namespace teachos::arch::memory::paging { namespace { - constexpr size_t PAGE_TABLE_LEVEL_4_ADDRESS = 0xfffffffffffff000; - } + // TODO: Set the address to a sensible location, this is merely a placeholder + constexpr size_t PAGE_TABLE_LEVEL_4_ADDRESS = 0x27AC40; + } // namespace auto create_or_get() -> page_table_handle { @@ -14,19 +15,11 @@ namespace teachos::arch::memory::paging return page_table_handle{active_page, page_table_handle::LEVEL4}; } - auto subtract_level(page_table_handle::level level) -> page_table_handle::level - { - exception_handling::assert(level != page_table_handle::LEVEL1, - "[Page table] Attemptd to decrement enum to value outside of range"); - auto value = static_cast::type>(level); - return static_cast(--value); - } - auto translate_page(virtual_page page) -> std::optional { auto current_handle = create_or_get(); - for (auto level = page_table_handle::LEVEL4; level != page_table_handle::LEVEL1; level = subtract_level(level)) + for (auto level = page_table_handle::LEVEL4; level != page_table_handle::LEVEL1; 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 -- cgit v1.2.3 From 7d4139b6fa0214604f467a782951cdc0f90e903f Mon Sep 17 00:00:00 2001 From: Fabian Imhof Date: Tue, 22 Oct 2024 08:00:57 +0000 Subject: fix page level -- operator --- arch/x86_64/src/memory/paging/page_table.cpp | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) (limited to 'arch/x86_64/src/memory') diff --git a/arch/x86_64/src/memory/paging/page_table.cpp b/arch/x86_64/src/memory/paging/page_table.cpp index 555d38a..b229ff7 100644 --- a/arch/x86_64/src/memory/paging/page_table.cpp +++ b/arch/x86_64/src/memory/paging/page_table.cpp @@ -99,25 +99,30 @@ namespace teachos::arch::memory::paging auto page_table_handle::zero_entries() -> void { handle->zero_entries(); } - auto page_table_handle::next_table(std::size_t table_index) const -> std::optional + auto page_table_handle::next_table(std::size_t table_index) -> std::optional { exception_handling::assert(handle_level != page_table_handle::LEVEL1, "[Page Table] Attempted to call next_table on level 1 page table"); auto next_table = handle->next_table(table_index); if (next_table) { - return page_table_handle{next_table.value(), handle_level--}; + handle_level--; + return page_table_handle{next_table.value(), handle_level}; } return std::nullopt; } auto page_table_handle::operator[](std::size_t index) const -> entry { return handle->operator[](index); } - auto operator--(page_table_handle::level value, int) -> page_table_handle::level + auto operator--(page_table_handle::level & value, int) -> page_table_handle::level { exception_handling::assert(value != page_table_handle::LEVEL1, "[Page table] Attempted to decrement enum to value outside of range"); + + page_table_handle::level original_value = value; auto new_value = static_cast::type>(value); - return static_cast(--new_value); + value = static_cast(--new_value); + + return original_value; } } // namespace teachos::arch::memory::paging -- cgit v1.2.3 From 9a1f3e66b6c860fdca689241e78f85bdbb5b4da5 Mon Sep 17 00:00:00 2001 From: Fabian Imhof Date: Tue, 22 Oct 2024 08:01:40 +0000 Subject: add previous state to comment --- arch/x86_64/src/memory/paging/page_mapper.cpp | 1 + 1 file changed, 1 insertion(+) (limited to 'arch/x86_64/src/memory') diff --git a/arch/x86_64/src/memory/paging/page_mapper.cpp b/arch/x86_64/src/memory/paging/page_mapper.cpp index 1371868..03f9f10 100644 --- a/arch/x86_64/src/memory/paging/page_mapper.cpp +++ b/arch/x86_64/src/memory/paging/page_mapper.cpp @@ -5,6 +5,7 @@ namespace teachos::arch::memory::paging namespace { // TODO: Set the address to a sensible location, this is merely a placeholder + // constexpr size_t PAGE_TABLE_LEVEL_4_ADDRESS = 0xfffffffffffff000; constexpr size_t PAGE_TABLE_LEVEL_4_ADDRESS = 0x27AC40; } // namespace -- cgit v1.2.3 From d43f5cb4c13b39b89951434e73078859d121cd4a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matteo=20Gm=C3=BCr?= Date: Tue, 22 Oct 2024 08:13:13 +0000 Subject: Implement precrement instead --- arch/x86_64/src/memory/paging/page_mapper.cpp | 2 +- arch/x86_64/src/memory/paging/page_table.cpp | 10 +++------- 2 files changed, 4 insertions(+), 8 deletions(-) (limited to 'arch/x86_64/src/memory') diff --git a/arch/x86_64/src/memory/paging/page_mapper.cpp b/arch/x86_64/src/memory/paging/page_mapper.cpp index 03f9f10..e9c6766 100644 --- a/arch/x86_64/src/memory/paging/page_mapper.cpp +++ b/arch/x86_64/src/memory/paging/page_mapper.cpp @@ -20,7 +20,7 @@ namespace teachos::arch::memory::paging { auto current_handle = create_or_get(); - for (auto level = page_table_handle::LEVEL4; level != page_table_handle::LEVEL1; level--) + for (auto level = page_table_handle::LEVEL4; level != page_table_handle::LEVEL1; --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 diff --git a/arch/x86_64/src/memory/paging/page_table.cpp b/arch/x86_64/src/memory/paging/page_table.cpp index b229ff7..c735a62 100644 --- a/arch/x86_64/src/memory/paging/page_table.cpp +++ b/arch/x86_64/src/memory/paging/page_table.cpp @@ -106,23 +106,19 @@ namespace teachos::arch::memory::paging auto next_table = handle->next_table(table_index); if (next_table) { - handle_level--; - return page_table_handle{next_table.value(), handle_level}; + return page_table_handle{next_table.value(), --handle_level}; } return std::nullopt; } auto page_table_handle::operator[](std::size_t index) const -> entry { return handle->operator[](index); } - auto operator--(page_table_handle::level & value, int) -> page_table_handle::level + auto operator--(page_table_handle::level & value) -> page_table_handle::level & { exception_handling::assert(value != page_table_handle::LEVEL1, "[Page table] Attempted to decrement enum to value outside of range"); - - page_table_handle::level original_value = value; auto new_value = static_cast::type>(value); value = static_cast(--new_value); - - return original_value; + return value; } } // namespace teachos::arch::memory::paging -- cgit v1.2.3 From c29d8c3b65f63bfd54031412d9c2975ef7571460 Mon Sep 17 00:00:00 2001 From: Fabian Imhof Date: Tue, 22 Oct 2024 08:58:48 +0000 Subject: use actual page_table address --- arch/x86_64/src/memory/paging/page_entry.cpp | 4 ++-- arch/x86_64/src/memory/paging/page_mapper.cpp | 9 ++++----- arch/x86_64/src/memory/paging/page_table.cpp | 14 +++++++------- 3 files changed, 13 insertions(+), 14 deletions(-) (limited to 'arch/x86_64/src/memory') diff --git a/arch/x86_64/src/memory/paging/page_entry.cpp b/arch/x86_64/src/memory/paging/page_entry.cpp index a172ca8..5d597ab 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> flags) -> void + auto entry::set_entry(allocator::physical_frame frame, std::bitset<64U> additional_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()} | 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 03f9f10..1fe72e3 100644 --- a/arch/x86_64/src/memory/paging/page_mapper.cpp +++ b/arch/x86_64/src/memory/paging/page_mapper.cpp @@ -1,19 +1,18 @@ #include "arch/memory/paging/page_mapper.hpp" +#include "arch/boot/pointers.hpp" + namespace teachos::arch::memory::paging { namespace { - // TODO: Set the address to a sensible location, this is merely a placeholder - // constexpr size_t PAGE_TABLE_LEVEL_4_ADDRESS = 0xfffffffffffff000; - constexpr size_t PAGE_TABLE_LEVEL_4_ADDRESS = 0x27AC40; + page_table * PAGE_TABLE_LEVEL_4_ADDRESS = boot::page_map_level_4; } // namespace auto create_or_get() -> page_table_handle { - static page_table * const active_page{reinterpret_cast(PAGE_TABLE_LEVEL_4_ADDRESS)}; // We can not save page_table_handle as a static variable directly, if we do the program will fail to link. - return page_table_handle{active_page, page_table_handle::LEVEL4}; + return page_table_handle{PAGE_TABLE_LEVEL_4_ADDRESS, page_table_handle::LEVEL4}; } auto translate_page(virtual_page page) -> std::optional diff --git a/arch/x86_64/src/memory/paging/page_table.cpp b/arch/x86_64/src/memory/paging/page_table.cpp index b229ff7..8971209 100644 --- a/arch/x86_64/src/memory/paging/page_table.cpp +++ b/arch/x86_64/src/memory/paging/page_table.cpp @@ -24,7 +24,7 @@ namespace teachos::arch::memory::paging * * @param table_index Index of this page table in the page table one level lower. */ - auto next_table(std::size_t table_index) const -> std::optional; + auto next_table(std::size_t table_index) -> std::optional; /** * @brief Index operator overload to access specific entries directy. @@ -32,7 +32,7 @@ namespace teachos::arch::memory::paging * @param index Index of the entry we want to access and read or write too. * @return Entry at the given table index. */ - auto operator[](std::size_t index) const -> entry; + auto operator[](std::size_t index) -> entry &; private: /** @@ -44,7 +44,7 @@ namespace teachos::arch::memory::paging * @param table_index Index of this page table in the page table one level higher. * @return An optional of the address of the next page table or null. */ - auto next_table_address(std::size_t table_index) const -> std::optional; + auto next_table_address(std::size_t table_index) -> std::optional; entry entries[PAGE_TABLE_ENTRY_COUNT]; ///< Entries containing addresses to page tables of a level below or ///< actual virtual addresses for the level 1 page table. @@ -60,7 +60,7 @@ namespace teachos::arch::memory::paging } } - auto page_table::next_table(std::size_t table_index) const -> std::optional + auto page_table::next_table(std::size_t table_index) -> std::optional { auto address = next_table_address(table_index); if (address) @@ -70,7 +70,7 @@ namespace teachos::arch::memory::paging return std::nullopt; } - auto page_table::operator[](std::size_t index) const -> entry + 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. @@ -78,7 +78,7 @@ namespace teachos::arch::memory::paging return 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); @@ -112,7 +112,7 @@ namespace teachos::arch::memory::paging return std::nullopt; } - auto page_table_handle::operator[](std::size_t index) const -> entry { return handle->operator[](index); } + auto page_table_handle::operator[](std::size_t index) -> entry & { return handle->operator[](index); } auto operator--(page_table_handle::level & value, int) -> page_table_handle::level { -- cgit v1.2.3 From d42ef85dbc3786fb45b8b4625b3f07446f51390d Mon Sep 17 00:00:00 2001 From: Fabian Imhof Date: Tue, 22 Oct 2024 09:19:57 +0000 Subject: add todos --- arch/x86_64/src/memory/paging/page_table.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'arch/x86_64/src/memory') diff --git a/arch/x86_64/src/memory/paging/page_table.cpp b/arch/x86_64/src/memory/paging/page_table.cpp index 33d0b75..5faad24 100644 --- a/arch/x86_64/src/memory/paging/page_table.cpp +++ b/arch/x86_64/src/memory/paging/page_table.cpp @@ -46,8 +46,8 @@ namespace teachos::arch::memory::paging */ auto next_table_address(std::size_t table_index) -> std::optional; - entry entries[PAGE_TABLE_ENTRY_COUNT]; ///< Entries containing addresses to page tables of a level below or - ///< actual virtual addresses for the level 1 page table. + entry entries[PAGE_TABLE_ENTRY_COUNT] = {}; ///< Entries containing addresses to page tables of a level below or + ///< actual virtual addresses for the level 1 page table. }; auto page_table::zero_entries() -> void @@ -55,6 +55,7 @@ namespace teachos::arch::memory::paging constexpr size_t entry_amount = sizeof(entries) / sizeof(entries[0]); for (size_t i = 0; i < entry_amount; ++i) { + // TODO: Crashes when trying to access entry! auto entry = this->operator[](i); entry.set_unused(); } -- cgit v1.2.3 From ef22c9394534014dbda3e2a070df3d02a9fd041e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matteo=20Gm=C3=BCr?= Date: Tue, 22 Oct 2024 09:22:04 +0000 Subject: Remove default initalization of member variables --- arch/x86_64/src/memory/paging/page_table.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'arch/x86_64/src/memory') diff --git a/arch/x86_64/src/memory/paging/page_table.cpp b/arch/x86_64/src/memory/paging/page_table.cpp index 5faad24..33d0b75 100644 --- a/arch/x86_64/src/memory/paging/page_table.cpp +++ b/arch/x86_64/src/memory/paging/page_table.cpp @@ -46,8 +46,8 @@ namespace teachos::arch::memory::paging */ auto next_table_address(std::size_t table_index) -> std::optional; - entry entries[PAGE_TABLE_ENTRY_COUNT] = {}; ///< Entries containing addresses to page tables of a level below or - ///< actual virtual addresses for the level 1 page table. + entry entries[PAGE_TABLE_ENTRY_COUNT]; ///< Entries containing addresses to page tables of a level below or + ///< actual virtual addresses for the level 1 page table. }; auto page_table::zero_entries() -> void @@ -55,7 +55,6 @@ namespace teachos::arch::memory::paging constexpr size_t entry_amount = sizeof(entries) / sizeof(entries[0]); for (size_t i = 0; i < entry_amount; ++i) { - // TODO: Crashes when trying to access entry! auto entry = this->operator[](i); entry.set_unused(); } -- cgit v1.2.3 From 61db7fa6097a9e3784f8fb18a8d3de47d7d7c007 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matteo=20Gm=C3=BCr?= Date: Wed, 23 Oct 2024 13:28:07 +0000 Subject: Extract next_table_or_create into page_table --- arch/x86_64/src/memory/paging/page_table.cpp | 2 -- 1 file changed, 2 deletions(-) (limited to 'arch/x86_64/src/memory') diff --git a/arch/x86_64/src/memory/paging/page_table.cpp b/arch/x86_64/src/memory/paging/page_table.cpp index 33d0b75..40662e3 100644 --- a/arch/x86_64/src/memory/paging/page_table.cpp +++ b/arch/x86_64/src/memory/paging/page_table.cpp @@ -1,7 +1,5 @@ #include "arch/memory/paging/page_table.hpp" -#include "arch/exception_handling/assert.hpp" - namespace teachos::arch::memory::paging { /** -- cgit v1.2.3 From c373109b4912e857273c30b3ebd2d25296da85fe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matteo=20Gm=C3=BCr?= Date: Wed, 23 Oct 2024 13:40:02 +0000 Subject: Ensure page table is static --- arch/x86_64/src/memory/paging/page_mapper.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch/x86_64/src/memory') diff --git a/arch/x86_64/src/memory/paging/page_mapper.cpp b/arch/x86_64/src/memory/paging/page_mapper.cpp index b89b637..995f2c3 100644 --- a/arch/x86_64/src/memory/paging/page_mapper.cpp +++ b/arch/x86_64/src/memory/paging/page_mapper.cpp @@ -6,7 +6,7 @@ namespace teachos::arch::memory::paging { namespace { - page_table * PAGE_TABLE_LEVEL_4_ADDRESS = boot::page_map_level_4; + static page_table * PAGE_TABLE_LEVEL_4_ADDRESS = boot::page_map_level_4; } // namespace auto create_or_get() -> page_table_handle -- cgit v1.2.3 From 355993d16fcdb2d020d6f1ff02adfa191f8f4d48 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matteo=20Gm=C3=BCr?= Date: Wed, 23 Oct 2024 13:42:32 +0000 Subject: Initalize page table on first call --- arch/x86_64/src/memory/paging/page_mapper.cpp | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) (limited to 'arch/x86_64/src/memory') diff --git a/arch/x86_64/src/memory/paging/page_mapper.cpp b/arch/x86_64/src/memory/paging/page_mapper.cpp index 995f2c3..39b5e64 100644 --- a/arch/x86_64/src/memory/paging/page_mapper.cpp +++ b/arch/x86_64/src/memory/paging/page_mapper.cpp @@ -4,15 +4,11 @@ namespace teachos::arch::memory::paging { - namespace - { - static page_table * PAGE_TABLE_LEVEL_4_ADDRESS = boot::page_map_level_4; - } // namespace - auto create_or_get() -> page_table_handle { + static page_table * table = boot::page_map_level_4; // We can not save page_table_handle as a static variable directly, if we do the program will fail to link. - return page_table_handle{PAGE_TABLE_LEVEL_4_ADDRESS, page_table_handle::LEVEL4}; + return page_table_handle{table, page_table_handle::LEVEL4}; } auto translate_page(virtual_page page) -> std::optional -- cgit v1.2.3 From cf52909d11fba4e81e77f264abe1f7055399793a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matteo=20Gm=C3=BCr?= Date: Wed, 23 Oct 2024 13:55:23 +0000 Subject: Revert "Initalize page table on first call" This reverts commit 355993d16fcdb2d020d6f1ff02adfa191f8f4d48. --- arch/x86_64/src/memory/paging/page_mapper.cpp | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'arch/x86_64/src/memory') diff --git a/arch/x86_64/src/memory/paging/page_mapper.cpp b/arch/x86_64/src/memory/paging/page_mapper.cpp index 39b5e64..995f2c3 100644 --- a/arch/x86_64/src/memory/paging/page_mapper.cpp +++ b/arch/x86_64/src/memory/paging/page_mapper.cpp @@ -4,11 +4,15 @@ namespace teachos::arch::memory::paging { + namespace + { + static page_table * PAGE_TABLE_LEVEL_4_ADDRESS = boot::page_map_level_4; + } // namespace + auto create_or_get() -> page_table_handle { - static page_table * table = boot::page_map_level_4; // We can not save page_table_handle as a static variable directly, if we do the program will fail to link. - return page_table_handle{table, page_table_handle::LEVEL4}; + return page_table_handle{PAGE_TABLE_LEVEL_4_ADDRESS, page_table_handle::LEVEL4}; } auto translate_page(virtual_page page) -> std::optional -- cgit v1.2.3 From c7bc900ef9293045265f503696277b0405119c40 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matteo=20Gm=C3=BCr?= Date: Wed, 23 Oct 2024 14:29:08 +0000 Subject: Use virtual level 4 address again --- arch/x86_64/src/memory/paging/page_mapper.cpp | 6 ++++-- arch/x86_64/src/memory/paging/page_table.cpp | 4 +++- 2 files changed, 7 insertions(+), 3 deletions(-) (limited to 'arch/x86_64/src/memory') diff --git a/arch/x86_64/src/memory/paging/page_mapper.cpp b/arch/x86_64/src/memory/paging/page_mapper.cpp index 995f2c3..687bffd 100644 --- a/arch/x86_64/src/memory/paging/page_mapper.cpp +++ b/arch/x86_64/src/memory/paging/page_mapper.cpp @@ -6,13 +6,15 @@ namespace teachos::arch::memory::paging { namespace { - static page_table * PAGE_TABLE_LEVEL_4_ADDRESS = boot::page_map_level_4; + constexpr size_t PAGE_TABLE_LEVEL_4_ADDRESS = 0xfffffffffffff000; } // namespace auto create_or_get() -> page_table_handle { + // Perhaps we need to access boot::page_map_level_4; so we do not crash when returning entry? + static page_table * const active_page = reinterpret_cast(PAGE_TABLE_LEVEL_4_ADDRESS); // We can not save page_table_handle as a static variable directly, if we do the program will fail to link. - return page_table_handle{PAGE_TABLE_LEVEL_4_ADDRESS, page_table_handle::LEVEL4}; + return page_table_handle{active_page, page_table_handle::LEVEL4}; } auto translate_page(virtual_page page) -> std::optional diff --git a/arch/x86_64/src/memory/paging/page_table.cpp b/arch/x86_64/src/memory/paging/page_table.cpp index 40662e3..bfd91da 100644 --- a/arch/x86_64/src/memory/paging/page_table.cpp +++ b/arch/x86_64/src/memory/paging/page_table.cpp @@ -51,6 +51,7 @@ namespace teachos::arch::memory::paging auto page_table::zero_entries() -> void { constexpr size_t entry_amount = sizeof(entries) / sizeof(entries[0]); + static_assert(entry_amount == PAGE_TABLE_ENTRY_COUNT); for (size_t i = 0; i < entry_amount; ++i) { auto entry = this->operator[](i); @@ -73,7 +74,8 @@ 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 entries[index]; + auto & entry = entries[index]; + return entry; } auto page_table::next_table_address(std::size_t table_index) -> std::optional -- cgit v1.2.3 From 97fe123c2d5bd0c49e8d360a989fcee8971c61ba Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matteo=20Gm=C3=BCr?= Date: Wed, 23 Oct 2024 14:32:27 +0000 Subject: Add todo comment on why code crashes --- arch/x86_64/src/memory/paging/page_table.cpp | 1 + 1 file changed, 1 insertion(+) (limited to 'arch/x86_64/src/memory') diff --git a/arch/x86_64/src/memory/paging/page_table.cpp b/arch/x86_64/src/memory/paging/page_table.cpp index bfd91da..21611e1 100644 --- a/arch/x86_64/src/memory/paging/page_table.cpp +++ b/arch/x86_64/src/memory/paging/page_table.cpp @@ -74,6 +74,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"); + // TODO: This section seems to return completly invalid entry, debugger doesn't even show a value? Revert once fixed auto & entry = entries[index]; return entry; } -- cgit v1.2.3 From 4c97a4e1e2055ce63a0d16d1e5be880792a5e7eb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matteo=20Gm=C3=BCr?= Date: Wed, 23 Oct 2024 15:08:10 +0000 Subject: Replace uint64_t with size_t --- arch/x86_64/src/memory/paging/virtual_page.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'arch/x86_64/src/memory') diff --git a/arch/x86_64/src/memory/paging/virtual_page.cpp b/arch/x86_64/src/memory/paging/virtual_page.cpp index fd2085b..91f63b4 100644 --- a/arch/x86_64/src/memory/paging/virtual_page.cpp +++ b/arch/x86_64/src/memory/paging/virtual_page.cpp @@ -17,9 +17,9 @@ namespace teachos::arch::memory::paging return virtual_page{virtual_address / allocator::PAGE_FRAME_SIZE}; } - auto virtual_page::start_address() const -> uint64_t { return page_number * allocator::PAGE_FRAME_SIZE; } + auto virtual_page::start_address() const -> size_t { return page_number * allocator::PAGE_FRAME_SIZE; } - auto virtual_page::get_level_index(page_table_handle::level level) const -> uint64_t + auto virtual_page::get_level_index(page_table_handle::level level) const -> size_t { return (start_address() >> (level * 9U)) & 0x1FF; } -- cgit v1.2.3 From c2c7503fec31c07645fdc087dbf1ef487e90912e Mon Sep 17 00:00:00 2001 From: Fabian Imhof Date: Sat, 26 Oct 2024 07:03:01 +0000 Subject: fix mmap type, adjust linker, use std::array --- arch/x86_64/src/memory/paging/page_table.cpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'arch/x86_64/src/memory') diff --git a/arch/x86_64/src/memory/paging/page_table.cpp b/arch/x86_64/src/memory/paging/page_table.cpp index 21611e1..1d7b8a0 100644 --- a/arch/x86_64/src/memory/paging/page_table.cpp +++ b/arch/x86_64/src/memory/paging/page_table.cpp @@ -1,5 +1,7 @@ #include "arch/memory/paging/page_table.hpp" +#include + namespace teachos::arch::memory::paging { /** @@ -44,8 +46,9 @@ namespace teachos::arch::memory::paging */ auto next_table_address(std::size_t table_index) -> std::optional; - entry entries[PAGE_TABLE_ENTRY_COUNT]; ///< Entries containing addresses to page tables of a level below or - ///< actual virtual addresses for the level 1 page table. + std::array + entries{}; ///< Entries containing addresses to page tables of a level below or + ///< actual virtual addresses for the level 1 page table. }; auto page_table::zero_entries() -> void -- cgit v1.2.3 From e44a16e45a309aa96375a2215d0d2405cf467dae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matteo=20Gm=C3=BCr?= Date: Sat, 26 Oct 2024 07:37:50 +0000 Subject: Use construct at to zero memory before using it. --- arch/x86_64/src/memory/paging/page_mapper.cpp | 11 ++--------- arch/x86_64/src/memory/paging/page_table.cpp | 15 +++++++++++---- 2 files changed, 13 insertions(+), 13 deletions(-) (limited to 'arch/x86_64/src/memory') diff --git a/arch/x86_64/src/memory/paging/page_mapper.cpp b/arch/x86_64/src/memory/paging/page_mapper.cpp index 687bffd..cd77366 100644 --- a/arch/x86_64/src/memory/paging/page_mapper.cpp +++ b/arch/x86_64/src/memory/paging/page_mapper.cpp @@ -4,17 +4,10 @@ namespace teachos::arch::memory::paging { - namespace - { - constexpr size_t PAGE_TABLE_LEVEL_4_ADDRESS = 0xfffffffffffff000; - } // namespace - auto create_or_get() -> page_table_handle { - // Perhaps we need to access boot::page_map_level_4; so we do not crash when returning entry? - static page_table * const active_page = reinterpret_cast(PAGE_TABLE_LEVEL_4_ADDRESS); - // We can not save page_table_handle as a static variable directly, if we do the program will fail to link. - return page_table_handle{active_page, page_table_handle::LEVEL4}; + // TODO: As soon as linker error is fixed in toolchain make handle static and return that. + return page_table_handle{arch::boot::page_map_level_4, page_table_handle::LEVEL4}; } auto translate_page(virtual_page page) -> std::optional diff --git a/arch/x86_64/src/memory/paging/page_table.cpp b/arch/x86_64/src/memory/paging/page_table.cpp index 1d7b8a0..2f97a80 100644 --- a/arch/x86_64/src/memory/paging/page_table.cpp +++ b/arch/x86_64/src/memory/paging/page_table.cpp @@ -1,6 +1,7 @@ #include "arch/memory/paging/page_table.hpp" #include +#include namespace teachos::arch::memory::paging { @@ -9,6 +10,11 @@ namespace teachos::arch::memory::paging */ struct page_table { + /** + * @brief Defaulted constructor. + */ + page_table() = default; + /** * @brief Set every entry of the page to unused. */ @@ -46,9 +52,9 @@ namespace teachos::arch::memory::paging */ auto next_table_address(std::size_t table_index) -> std::optional; - std::array - entries{}; ///< Entries containing addresses to page tables of a level below or - ///< actual virtual addresses for the level 1 page table. + std::array entries = + {}; ///< Entries containing addresses to page tables of a level below or + ///< actual virtual addresses for the level 1 page table. }; auto page_table::zero_entries() -> void @@ -67,7 +73,8 @@ namespace teachos::arch::memory::paging auto address = next_table_address(table_index); if (address) { - return reinterpret_cast(address.value()); + // TODO: Probably erases the data even if the page table already existed previously and had values. + return std::construct_at(reinterpret_cast(address.value())); } return std::nullopt; } -- cgit v1.2.3 From bca36b0c10fcae447c90e211e83987fea28eecdc Mon Sep 17 00:00:00 2001 From: Fabian Imhof Date: Sat, 26 Oct 2024 08:47:26 +0000 Subject: wip --- arch/x86_64/src/memory/paging/page_mapper.cpp | 12 +++++++++++- arch/x86_64/src/memory/paging/page_table.cpp | 15 +++++++++------ 2 files changed, 20 insertions(+), 7 deletions(-) (limited to 'arch/x86_64/src/memory') diff --git a/arch/x86_64/src/memory/paging/page_mapper.cpp b/arch/x86_64/src/memory/paging/page_mapper.cpp index cd77366..dff9ae4 100644 --- a/arch/x86_64/src/memory/paging/page_mapper.cpp +++ b/arch/x86_64/src/memory/paging/page_mapper.cpp @@ -4,10 +4,20 @@ namespace teachos::arch::memory::paging { + auto create_or_get() -> page_table_handle { + static auto initialized = false; // TODO: As soon as linker error is fixed in toolchain make handle static and return that. - return page_table_handle{arch::boot::page_map_level_4, page_table_handle::LEVEL4}; + page_table_handle active_handle{boot::page_map_level_4, page_table_handle::LEVEL4}; + + if (!initialized) + { + active_handle.initialize_page_tables(); + initialized = true; + } + + return active_handle; } auto translate_page(virtual_page page) -> std::optional diff --git a/arch/x86_64/src/memory/paging/page_table.cpp b/arch/x86_64/src/memory/paging/page_table.cpp index 2f97a80..b5315a0 100644 --- a/arch/x86_64/src/memory/paging/page_table.cpp +++ b/arch/x86_64/src/memory/paging/page_table.cpp @@ -10,11 +10,6 @@ namespace teachos::arch::memory::paging */ struct page_table { - /** - * @brief Defaulted constructor. - */ - page_table() = default; - /** * @brief Set every entry of the page to unused. */ @@ -105,7 +100,15 @@ 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, "[Page Table] Attempted to pass nullptr as handle to page table handle method"); + } + + auto page_table_handle::initialize_page_table() -> void + { + exception_handling::assert(handle_level == page_table_handle::LEVEL4, + "[Page Table] Attempted to initialize a page table of level 3 or lower"); + + auto level_3_page_table = boot::page_map_level_3; } auto page_table_handle::zero_entries() -> void { handle->zero_entries(); } -- cgit v1.2.3 From e56964da2dd54e598d3a7fca20fc0071f32026a4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matteo=20Gm=C3=BCr?= Date: Sat, 26 Oct 2024 09:20:53 +0000 Subject: Adjust to toolchain updates --- arch/x86_64/src/memory/paging/page_mapper.cpp | 3 +-- arch/x86_64/src/memory/paging/page_table.cpp | 5 ++--- 2 files changed, 3 insertions(+), 5 deletions(-) (limited to 'arch/x86_64/src/memory') diff --git a/arch/x86_64/src/memory/paging/page_mapper.cpp b/arch/x86_64/src/memory/paging/page_mapper.cpp index dff9ae4..75d6759 100644 --- a/arch/x86_64/src/memory/paging/page_mapper.cpp +++ b/arch/x86_64/src/memory/paging/page_mapper.cpp @@ -8,8 +8,7 @@ namespace teachos::arch::memory::paging auto create_or_get() -> page_table_handle { static auto initialized = false; - // TODO: As soon as linker error is fixed in toolchain make handle static and return that. - page_table_handle active_handle{boot::page_map_level_4, page_table_handle::LEVEL4}; + static page_table_handle active_handle{boot::page_map_level_4, page_table_handle::LEVEL4}; if (!initialized) { diff --git a/arch/x86_64/src/memory/paging/page_table.cpp b/arch/x86_64/src/memory/paging/page_table.cpp index b5315a0..808fbbc 100644 --- a/arch/x86_64/src/memory/paging/page_table.cpp +++ b/arch/x86_64/src/memory/paging/page_table.cpp @@ -103,12 +103,11 @@ namespace teachos::arch::memory::paging exception_handling::assert(handle, "[Page Table] Attempted to pass nullptr as handle to page table handle method"); } - auto page_table_handle::initialize_page_table() -> void + auto page_table_handle::initialize_page_tables() -> void { exception_handling::assert(handle_level == page_table_handle::LEVEL4, "[Page Table] Attempted to initialize a page table of level 3 or lower"); - - auto level_3_page_table = boot::page_map_level_3; + // std::construct_at(reinterpret_cast(_end_of_image)); } auto page_table_handle::zero_entries() -> void { handle->zero_entries(); } -- cgit v1.2.3 From 47ec911e3b3624d875da5b9cc0102e3d17a6d54a Mon Sep 17 00:00:00 2001 From: Fabian Imhof Date: Sat, 26 Oct 2024 10:09:46 +0000 Subject: use linker variable --- arch/x86_64/src/memory/paging/page_table.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'arch/x86_64/src/memory') diff --git a/arch/x86_64/src/memory/paging/page_table.cpp b/arch/x86_64/src/memory/paging/page_table.cpp index 808fbbc..059ada2 100644 --- a/arch/x86_64/src/memory/paging/page_table.cpp +++ b/arch/x86_64/src/memory/paging/page_table.cpp @@ -3,6 +3,8 @@ #include #include +extern char _end_of_image; + namespace teachos::arch::memory::paging { /** @@ -107,7 +109,7 @@ namespace teachos::arch::memory::paging { exception_handling::assert(handle_level == page_table_handle::LEVEL4, "[Page Table] Attempted to initialize a page table of level 3 or lower"); - // std::construct_at(reinterpret_cast(_end_of_image)); + auto level3_page_table = std::construct_at(reinterpret_cast(_end_of_image)); } auto page_table_handle::zero_entries() -> void { handle->zero_entries(); } -- cgit v1.2.3 From ffb6507d565585bb2a817ff01317b7643bd6d981 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matteo=20Gm=C3=BCr?= Date: Sat, 26 Oct 2024 11:23:58 +0000 Subject: Create for loops to construct base level 3 page table --- arch/x86_64/src/memory/paging/page_table.cpp | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) (limited to 'arch/x86_64/src/memory') diff --git a/arch/x86_64/src/memory/paging/page_table.cpp b/arch/x86_64/src/memory/paging/page_table.cpp index 059ada2..935dd8c 100644 --- a/arch/x86_64/src/memory/paging/page_table.cpp +++ b/arch/x86_64/src/memory/paging/page_table.cpp @@ -70,8 +70,7 @@ namespace teachos::arch::memory::paging auto address = next_table_address(table_index); if (address) { - // TODO: Probably erases the data even if the page table already existed previously and had values. - return std::construct_at(reinterpret_cast(address.value())); + return reinterpret_cast(address.value()); } return std::nullopt; } @@ -109,7 +108,17 @@ namespace teachos::arch::memory::paging { exception_handling::assert(handle_level == page_table_handle::LEVEL4, "[Page Table] Attempted to initialize a page table of level 3 or lower"); - auto level3_page_table = std::construct_at(reinterpret_cast(_end_of_image)); + auto level3_page_table = std::construct_at(reinterpret_cast(&_end_of_image)); + for (size_t n = 1; n <= PAGE_TABLE_ENTRY_COUNT; ++n) + { + size_t offset = sizeof(page_table) * n; + std::construct_at(reinterpret_cast(&_end_of_image + offset)); + for (size_t m = 0; m < PAGE_TABLE_ENTRY_COUNT; ++m) + { + size_t offset = sizeof(page_table) * (n + m); + std::construct_at(reinterpret_cast(&_end_of_image + offset)); + } + } } auto page_table_handle::zero_entries() -> void { handle->zero_entries(); } -- cgit v1.2.3 From bc993ccf7c5a80a8f4b1cd05437701efb81beec9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matteo=20Gm=C3=BCr?= Date: Sat, 26 Oct 2024 11:24:13 +0000 Subject: Fix typo --- arch/x86_64/src/memory/paging/page_table.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch/x86_64/src/memory') diff --git a/arch/x86_64/src/memory/paging/page_table.cpp b/arch/x86_64/src/memory/paging/page_table.cpp index 935dd8c..38d5025 100644 --- a/arch/x86_64/src/memory/paging/page_table.cpp +++ b/arch/x86_64/src/memory/paging/page_table.cpp @@ -113,7 +113,7 @@ namespace teachos::arch::memory::paging { size_t offset = sizeof(page_table) * n; std::construct_at(reinterpret_cast(&_end_of_image + offset)); - for (size_t m = 0; m < PAGE_TABLE_ENTRY_COUNT; ++m) + for (size_t m = 1; m <= PAGE_TABLE_ENTRY_COUNT; ++m) { size_t offset = sizeof(page_table) * (n + m); std::construct_at(reinterpret_cast(&_end_of_image + offset)); -- cgit v1.2.3 From 454dcb6f2033ee80a43f99d23323b02e8fd0a115 Mon Sep 17 00:00:00 2001 From: Fabian Imhof Date: Sat, 26 Oct 2024 11:30:01 +0000 Subject: add doc --- arch/x86_64/src/memory/paging/page_table.cpp | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'arch/x86_64/src/memory') diff --git a/arch/x86_64/src/memory/paging/page_table.cpp b/arch/x86_64/src/memory/paging/page_table.cpp index 059ada2..14ead9e 100644 --- a/arch/x86_64/src/memory/paging/page_table.cpp +++ b/arch/x86_64/src/memory/paging/page_table.cpp @@ -3,6 +3,10 @@ #include #include +/* + * This is a linker variable reference. This referenc cannot reside inside a namespace, because in + * that case the compiler would try to find arch::memory::paging::_end_of_image inside the ELF file. + */ extern char _end_of_image; namespace teachos::arch::memory::paging -- cgit v1.2.3 From f4ab51df7f9ed783dbcfbecffc0a9d919c501135 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matteo=20Gm=C3=BCr?= Date: Sat, 26 Oct 2024 11:44:12 +0000 Subject: Write P3 table into P4 table at index 0 --- arch/x86_64/src/memory/paging/page_entry.cpp | 6 ++++++ arch/x86_64/src/memory/paging/page_table.cpp | 2 ++ 2 files changed, 8 insertions(+) (limited to 'arch/x86_64/src/memory') diff --git a/arch/x86_64/src/memory/paging/page_entry.cpp b/arch/x86_64/src/memory/paging/page_entry.cpp index 5d597ab..09d048b 100644 --- a/arch/x86_64/src/memory/paging/page_entry.cpp +++ b/arch/x86_64/src/memory/paging/page_entry.cpp @@ -4,6 +4,12 @@ namespace teachos::arch::memory::paging { + entry::entry(uint64_t flags) + : flags(flags) + { + // Nothing to do. + } + auto entry::is_unused() const -> bool { return flags == 0U; } auto entry::set_unused() -> void { flags = 0U; } diff --git a/arch/x86_64/src/memory/paging/page_table.cpp b/arch/x86_64/src/memory/paging/page_table.cpp index c0f199a..4747e0b 100644 --- a/arch/x86_64/src/memory/paging/page_table.cpp +++ b/arch/x86_64/src/memory/paging/page_table.cpp @@ -123,6 +123,8 @@ namespace teachos::arch::memory::paging std::construct_at(reinterpret_cast(&_end_of_image + offset)); } } + size_t const flags = reinterpret_cast(level3_page_table); + this->operator[](0U) = entry{flags}; } auto page_table_handle::zero_entries() -> void { handle->zero_entries(); } -- cgit v1.2.3 From 6eec9c34a83fc5c0d93bc485c2ee0252824c2201 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matteo=20Gm=C3=BCr?= Date: Sat, 26 Oct 2024 11:57:11 +0000 Subject: Fix missing default constructor. --- arch/x86_64/src/memory/paging/page_table.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'arch/x86_64/src/memory') diff --git a/arch/x86_64/src/memory/paging/page_table.cpp b/arch/x86_64/src/memory/paging/page_table.cpp index 4747e0b..c9b4a37 100644 --- a/arch/x86_64/src/memory/paging/page_table.cpp +++ b/arch/x86_64/src/memory/paging/page_table.cpp @@ -85,8 +85,7 @@ namespace teachos::arch::memory::paging // could be incredibly hard to debug later. exception_handling::assert(index < PAGE_TABLE_ENTRY_COUNT, "[Page Table] Index out of bounds"); // TODO: This section seems to return completly invalid entry, debugger doesn't even show a value? Revert once fixed - auto & entry = entries[index]; - return entry; + return entries[index]; } auto page_table::next_table_address(std::size_t table_index) -> std::optional -- cgit v1.2.3 From d86af47f0b62cb3ae302fb292747944620542db1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matteo=20Gm=C3=BCr?= Date: Sat, 26 Oct 2024 12:19:16 +0000 Subject: Attempt to fix initalize_page_tables, crashes on n = 1, m = 507 --- arch/x86_64/src/memory/paging/page_table.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch/x86_64/src/memory') diff --git a/arch/x86_64/src/memory/paging/page_table.cpp b/arch/x86_64/src/memory/paging/page_table.cpp index c9b4a37..93cc0de 100644 --- a/arch/x86_64/src/memory/paging/page_table.cpp +++ b/arch/x86_64/src/memory/paging/page_table.cpp @@ -118,7 +118,7 @@ namespace teachos::arch::memory::paging std::construct_at(reinterpret_cast(&_end_of_image + offset)); for (size_t m = 1; m <= PAGE_TABLE_ENTRY_COUNT; ++m) { - size_t offset = sizeof(page_table) * (n + m); + size_t offset = sizeof(page_table) * ((PAGE_TABLE_ENTRY_COUNT * n) + m); std::construct_at(reinterpret_cast(&_end_of_image + offset)); } } -- cgit v1.2.3 From ca17ed52ea768f1e1c837207f7d27afa6ed99cc2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matteo=20Gm=C3=BCr?= Date: Sat, 26 Oct 2024 13:43:51 +0000 Subject: Update boot.s comments and comment initalize page tables out --- arch/x86_64/src/memory/paging/page_table.cpp | 3 +++ 1 file changed, 3 insertions(+) (limited to 'arch/x86_64/src/memory') diff --git a/arch/x86_64/src/memory/paging/page_table.cpp b/arch/x86_64/src/memory/paging/page_table.cpp index 93cc0de..868cf86 100644 --- a/arch/x86_64/src/memory/paging/page_table.cpp +++ b/arch/x86_64/src/memory/paging/page_table.cpp @@ -109,6 +109,8 @@ namespace teachos::arch::memory::paging auto page_table_handle::initialize_page_tables() -> void { + // TODO: This should be done differently and only once the other methods are working see Rempaing the Kernel + /* exception_handling::assert(handle_level == page_table_handle::LEVEL4, "[Page Table] Attempted to initialize a page table of level 3 or lower"); auto level3_page_table = std::construct_at(reinterpret_cast(&_end_of_image)); @@ -124,6 +126,7 @@ namespace teachos::arch::memory::paging } size_t const flags = reinterpret_cast(level3_page_table); this->operator[](0U) = entry{flags}; + */ } auto page_table_handle::zero_entries() -> void { handle->zero_entries(); } -- cgit v1.2.3 From a29e823c6ead21fa7c8f6445411d52f57c4518fb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matteo=20Gm=C3=BCr?= Date: Sun, 27 Oct 2024 09:21:25 +0000 Subject: Attempt to start using C++20 algorithm calls. --- .../src/memory/allocator/area_frame_allocator.cpp | 24 ++++++++++++++-------- arch/x86_64/src/memory/multiboot/memory_map.cpp | 15 +++++++++++++- 2 files changed, 29 insertions(+), 10 deletions(-) (limited to 'arch/x86_64/src/memory') diff --git a/arch/x86_64/src/memory/allocator/area_frame_allocator.cpp b/arch/x86_64/src/memory/allocator/area_frame_allocator.cpp index c2cafce..c3f77e1 100644 --- a/arch/x86_64/src/memory/allocator/area_frame_allocator.cpp +++ b/arch/x86_64/src/memory/allocator/area_frame_allocator.cpp @@ -2,13 +2,16 @@ #include "arch/exception_handling/assert.hpp" +#include +#include +#include + namespace teachos::arch::memory::allocator { area_frame_allocator::area_frame_allocator(multiboot::memory_information mem_info) : next_free_frame(0) , current_area(std::nullopt) - , area_begin(mem_info.memory_areas) - , area_end(mem_info.memory_areas + mem_info.area_count) + , memory_areas(mem_info.memory_areas, mem_info.area_count) , kernel_start(physical_frame::containing_address(mem_info.kernel_start)) , kernel_end(physical_frame::containing_address(mem_info.kernel_end)) , multiboot_start(physical_frame::containing_address(mem_info.multiboot_start)) @@ -21,10 +24,17 @@ namespace teachos::arch::memory::allocator { current_area = std::nullopt; - for (multiboot::memory_area_iterator it = begin(); it != end(); ++it) - { - multiboot::memory_area & area = *it; + /**auto filtered_areas = memory_areas | std::views::filter([this](multiboot::memory_area area) { + auto address = area.base_address + area.area_length - 1; + return physical_frame::containing_address(address) >= next_free_frame; + });**/ + + std::ranges::min_element(memory_areas, [](multiboot::memory_area a, multiboot::memory_area b) { + return a.base_address < b.base_address; + }); + for (auto area : memory_areas) + { std::size_t address = area.base_address + area.area_length - 1; if (physical_frame::containing_address(address) >= next_free_frame) { @@ -90,8 +100,4 @@ namespace teachos::arch::memory::allocator exception_handling::assert(false && physical_frame.frame_number == 0, "[deallocate_frame] Not implemented Exception"); } - - auto area_frame_allocator::begin() -> multiboot::memory_area_iterator { return area_begin; } - - auto area_frame_allocator::end() -> multiboot::memory_area_iterator { return area_end; } } // namespace teachos::arch::memory::allocator diff --git a/arch/x86_64/src/memory/multiboot/memory_map.cpp b/arch/x86_64/src/memory/multiboot/memory_map.cpp index 6b1d1d4..da7f05d 100644 --- a/arch/x86_64/src/memory/multiboot/memory_map.cpp +++ b/arch/x86_64/src/memory/multiboot/memory_map.cpp @@ -1,11 +1,13 @@ #include "arch/memory/multiboot/memory_map.hpp" +#include "arch/exception_handling/assert.hpp" + namespace teachos::arch::memory::multiboot { memory_area_iterator::memory_area_iterator(multiboot::memory_area * p) : ptr(p) { - // Nothing to do + exception_handling::assert(ptr, "[Memory Area] Attempted to pass nullptr as iterator"); } multiboot::memory_area & memory_area_iterator::operator*() const { return *ptr; } @@ -21,4 +23,15 @@ namespace teachos::arch::memory::multiboot ++ptr; return *this; } + + memory_area_container::memory_area_container(memory_area * begin, std::size_t size) + : area_begin(begin) + , area_end(begin + size) + { + // Nothing to do + } + + auto memory_area_container::begin() const -> multiboot::memory_area_iterator { return area_begin; } + + auto memory_area_container::end() const -> multiboot::memory_area_iterator { return area_end; } } // namespace teachos::arch::memory::multiboot -- cgit v1.2.3 From 3fb2780f665eb3514ef07d2d4a83820653e35b52 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matteo=20Gm=C3=BCr?= Date: Sun, 27 Oct 2024 11:20:46 +0000 Subject: Use container and C++20 range algorithms for allocator. --- .../src/memory/allocator/area_frame_allocator.cpp | 86 ++++++++++------------ arch/x86_64/src/memory/multiboot/memory_map.cpp | 44 ++++++++++- 2 files changed, 78 insertions(+), 52 deletions(-) (limited to 'arch/x86_64/src/memory') diff --git a/arch/x86_64/src/memory/allocator/area_frame_allocator.cpp b/arch/x86_64/src/memory/allocator/area_frame_allocator.cpp index c3f77e1..d91b7f4 100644 --- a/arch/x86_64/src/memory/allocator/area_frame_allocator.cpp +++ b/arch/x86_64/src/memory/allocator/area_frame_allocator.cpp @@ -23,33 +23,21 @@ namespace teachos::arch::memory::allocator auto area_frame_allocator::choose_next_area() -> void { current_area = std::nullopt; + auto next_area_with_free_frames = memory_areas | std::views::filter([this](multiboot::memory_area const & area) { + auto address = area.base_address + area.area_length - 1; + return physical_frame::containing_address(address) >= next_free_frame; + }); - /**auto filtered_areas = memory_areas | std::views::filter([this](multiboot::memory_area area) { - auto address = area.base_address + area.area_length - 1; - return physical_frame::containing_address(address) >= next_free_frame; - });**/ + auto lowest_area_with_free_frames = + std::ranges::min_element(next_area_with_free_frames, [](multiboot::memory_area a, multiboot::memory_area b) { + return a.base_address < b.base_address; + }); - std::ranges::min_element(memory_areas, [](multiboot::memory_area a, multiboot::memory_area b) { - return a.base_address < b.base_address; - }); - - for (auto area : memory_areas) - { - std::size_t address = area.base_address + area.area_length - 1; - if (physical_frame::containing_address(address) >= next_free_frame) - { - // The `next_free_frame` address is smaller than the last address of the current area - if (!current_area || area.base_address < current_area->base_address) - { - current_area = area; - } - } - } - - if (current_area) + if (lowest_area_with_free_frames != next_area_with_free_frames.end()) { + current_area = *lowest_area_with_free_frames; // Update the `next_free_frame` according to the new memory area - physical_frame start_frame = physical_frame::containing_address(current_area->base_address); + auto start_frame = physical_frame::containing_address(current_area.value().base_address); if (next_free_frame < start_frame) { next_free_frame = start_frame; @@ -63,36 +51,38 @@ namespace teachos::arch::memory::allocator * Only try to allocate memory if current_area is not null, because * the current_area is null if there is no more available memory. */ - if (current_area) + if (!current_area) { - physical_frame physical_frame{next_free_frame.frame_number}; + return std::nullopt; + } - struct physical_frame current_area_last_frame = { - physical_frame::containing_address(current_area->base_address + current_area->area_length - 1)}; + auto address = current_area.value().base_address + current_area.value().area_length - 1; + physical_frame current_area_last_frame = physical_frame::containing_address(address); - if (next_free_frame > current_area_last_frame) - { - // All frames of current area are used, switch to next area - choose_next_area(); - } - else if (physical_frame >= multiboot_start && physical_frame <= kernel_end) - { - // `physical_frame` is used by the kernel or multiboot information structure - next_free_frame = allocator::physical_frame{kernel_end.frame_number + 1}; - } - else - { - // Frame is unused, increment `next_free_frame` and return it - next_free_frame.frame_number += 1; - return physical_frame; - } - - // `physical_frame` was not valid, try it again with the updated `next_free_frame` - return allocate_frame(); + if (next_free_frame > current_area_last_frame) + { + // All frames of current area are used, switch to next area. + choose_next_area(); + } + else if (next_free_frame >= kernel_start && next_free_frame <= kernel_end) + { + // `physical_frame` is used by the kernel or multiboot information structure. + next_free_frame = allocator::physical_frame{kernel_end.frame_number + 1}; + } + else if (next_free_frame >= multiboot_start && next_free_frame <= multiboot_end) + { + // `physical_frame` is used by the kernel or multiboot information structure. + next_free_frame = allocator::physical_frame{multiboot_end.frame_number + 1}; + } + else + { + // Frame is unused, increment `next_free_frame` and return it. + next_free_frame.frame_number += 1; + return next_free_frame; } - // no free frames left - return std::nullopt; + // `physical_frame` was not valid, try it again with the updated `next_free_frame`. + return allocate_frame(); } auto area_frame_allocator::deallocate_frame(physical_frame physical_frame) -> void diff --git a/arch/x86_64/src/memory/multiboot/memory_map.cpp b/arch/x86_64/src/memory/multiboot/memory_map.cpp index da7f05d..b5e2759 100644 --- a/arch/x86_64/src/memory/multiboot/memory_map.cpp +++ b/arch/x86_64/src/memory/multiboot/memory_map.cpp @@ -4,18 +4,21 @@ namespace teachos::arch::memory::multiboot { - memory_area_iterator::memory_area_iterator(multiboot::memory_area * p) + memory_area_iterator::memory_area_iterator(value_type * p) : ptr(p) { exception_handling::assert(ptr, "[Memory Area] Attempted to pass nullptr as iterator"); } - multiboot::memory_area & memory_area_iterator::operator*() const { return *ptr; } + auto memory_area_iterator::operator*() const -> value_type & { return *ptr; } + + auto memory_area_iterator::operator->() const -> value_type * { return ptr; } auto memory_area_iterator::operator++(int) -> memory_area_iterator { - ++(*this); - return *this; + memory_area_iterator old_value = *this; + ++ptr; + return old_value; } auto memory_area_iterator::operator++() -> memory_area_iterator & @@ -24,6 +27,35 @@ namespace teachos::arch::memory::multiboot return *this; } + auto memory_area_iterator::operator+=(difference_type value) -> memory_area_iterator & + { + ptr += value; + return *this; + } + + auto memory_area_iterator::operator-=(difference_type value) -> memory_area_iterator & + { + ptr -= value; + return *this; + } + + auto memory_area_iterator::operator+(difference_type value) const -> memory_area_iterator + { + return memory_area_iterator{ptr + value}; + } + + auto memory_area_iterator::operator-(difference_type value) const -> memory_area_iterator + { + return memory_area_iterator{ptr - value}; + } + + auto memory_area_iterator::operator-(const memory_area_iterator & other) const -> difference_type + { + return ptr - other.ptr; + } + + auto memory_area_iterator::operator[](difference_type index) const -> value_type & { return *(ptr + index); } + memory_area_container::memory_area_container(memory_area * begin, std::size_t size) : area_begin(begin) , area_end(begin + size) @@ -34,4 +66,8 @@ namespace teachos::arch::memory::multiboot auto memory_area_container::begin() const -> multiboot::memory_area_iterator { return area_begin; } auto memory_area_container::end() const -> multiboot::memory_area_iterator { return area_end; } + + auto memory_area_container::size() const -> size_type { return std::distance(begin(), end()); } + + auto memory_area_container::empty() const -> bool { return size() == 0; } } // namespace teachos::arch::memory::multiboot -- cgit v1.2.3 From 1518177efac38961a36db0bc40152d00c38e6281 Mon Sep 17 00:00:00 2001 From: Fabian Imhof Date: Sun, 27 Oct 2024 13:27:33 +0000 Subject: add correct optional handling --- .../src/memory/allocator/area_frame_allocator.cpp | 17 +++++++++++------ arch/x86_64/src/memory/paging/page_mapper.cpp | 12 ++++++------ arch/x86_64/src/memory/paging/page_table.cpp | 4 ++-- 3 files changed, 19 insertions(+), 14 deletions(-) (limited to 'arch/x86_64/src/memory') diff --git a/arch/x86_64/src/memory/allocator/area_frame_allocator.cpp b/arch/x86_64/src/memory/allocator/area_frame_allocator.cpp index c2cafce..05b828c 100644 --- a/arch/x86_64/src/memory/allocator/area_frame_allocator.cpp +++ b/arch/x86_64/src/memory/allocator/area_frame_allocator.cpp @@ -29,14 +29,14 @@ namespace teachos::arch::memory::allocator if (physical_frame::containing_address(address) >= next_free_frame) { // The `next_free_frame` address is smaller than the last address of the current area - if (!current_area || area.base_address < current_area->base_address) + if (!current_area.has_value() || area.base_address < current_area.value().base_address) { - current_area = area; + current_area.emplace(area); } } } - if (current_area) + if (current_area.has_value()) { // Update the `next_free_frame` according to the new memory area physical_frame start_frame = physical_frame::containing_address(current_area->base_address); @@ -53,7 +53,7 @@ namespace teachos::arch::memory::allocator * Only try to allocate memory if current_area is not null, because * the current_area is null if there is no more available memory. */ - if (current_area) + if (current_area.has_value()) { physical_frame physical_frame{next_free_frame.frame_number}; @@ -65,11 +65,16 @@ namespace teachos::arch::memory::allocator // All frames of current area are used, switch to next area choose_next_area(); } - else if (physical_frame >= multiboot_start && physical_frame <= kernel_end) + else if (physical_frame >= kernel_start && physical_frame <= kernel_end) { - // `physical_frame` is used by the kernel or multiboot information structure + // `physical_frame` is used by the kernel next_free_frame = allocator::physical_frame{kernel_end.frame_number + 1}; } + else if (physical_frame >= multiboot_start && physical_frame <= multiboot_end) + { + // `physical_frame` is used by the multiboot information structure + next_free_frame = allocator::physical_frame{multiboot_end.frame_number + 1}; + } else { // Frame is unused, increment `next_free_frame` and return it diff --git a/arch/x86_64/src/memory/paging/page_mapper.cpp b/arch/x86_64/src/memory/paging/page_mapper.cpp index 75d6759..bc0c0d9 100644 --- a/arch/x86_64/src/memory/paging/page_mapper.cpp +++ b/arch/x86_64/src/memory/paging/page_mapper.cpp @@ -28,7 +28,7 @@ namespace teachos::arch::memory::paging 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_handle) + if (!next_handle.has_value()) { return translate_huge_page(page); } @@ -45,14 +45,14 @@ namespace teachos::arch::memory::paging auto current_handle = create_or_get(); auto level3_handle = current_handle.next_table(page.get_level_index(page_table_handle::LEVEL4)); - if (!level3_handle) + if (!level3_handle.has_value()) { return std::nullopt; } auto level3_entry = level3_handle.value()[page.get_level_index(page_table_handle::LEVEL3)]; auto level3_frame = level3_entry.calculate_pointed_to_frame(); - if (level3_frame && level3_entry.contains_flags(entry::HUGE_PAGE)) + if (level3_frame.has_value() && level3_entry.contains_flags(entry::HUGE_PAGE)) { exception_handling::assert( level3_frame.value().frame_number % (PAGE_TABLE_ENTRY_COUNT * PAGE_TABLE_ENTRY_COUNT) == 0U, @@ -63,11 +63,11 @@ namespace teachos::arch::memory::paging } auto level2_handle = level3_handle.value().next_table(page.get_level_index(page_table_handle::LEVEL3)); - if (level2_handle) + if (level2_handle.has_value()) { auto level2_entry = level2_handle.value()[page.get_level_index(page_table_handle::LEVEL2)]; auto level2_frame = level2_entry.calculate_pointed_to_frame(); - if (level2_frame && level2_entry.contains_flags(entry::HUGE_PAGE)) + if (level2_frame.has_value() && level2_entry.contains_flags(entry::HUGE_PAGE)) { exception_handling::assert(level2_frame.value().frame_number % PAGE_TABLE_ENTRY_COUNT == 0U, "[Page Mapper] Physical address must be 2 MiB aligned"); @@ -84,7 +84,7 @@ namespace teachos::arch::memory::paging virtual_page page = virtual_page::containing_address(virtual_address); std::optional frame = translate_page(page); - if (frame) + if (frame.has_value()) { 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 868cf86..f1df31d 100644 --- a/arch/x86_64/src/memory/paging/page_table.cpp +++ b/arch/x86_64/src/memory/paging/page_table.cpp @@ -72,7 +72,7 @@ namespace teachos::arch::memory::paging auto page_table::next_table(std::size_t table_index) -> std::optional { auto address = next_table_address(table_index); - if (address) + if (address.has_value()) { return reinterpret_cast(address.value()); } @@ -136,7 +136,7 @@ namespace teachos::arch::memory::paging exception_handling::assert(handle_level != page_table_handle::LEVEL1, "[Page Table] Attempted to call next_table on level 1 page table"); auto next_table = handle->next_table(table_index); - if (next_table) + if (next_table.has_value()) { return page_table_handle{next_table.value(), --handle_level}; } -- cgit v1.2.3 From d0f47ef0cd8cb2f5079808a261dd724b3eb1a3a1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matteo=20Gm=C3=BCr?= Date: Sun, 27 Oct 2024 14:12:35 +0000 Subject: Fix typos --- arch/x86_64/src/memory/multiboot/reader.cpp | 22 ++++++++++------------ arch/x86_64/src/memory/paging/page_entry.cpp | 2 +- arch/x86_64/src/memory/paging/virtual_page.cpp | 2 +- 3 files changed, 12 insertions(+), 14 deletions(-) (limited to 'arch/x86_64/src/memory') diff --git a/arch/x86_64/src/memory/multiboot/reader.cpp b/arch/x86_64/src/memory/multiboot/reader.cpp index 545e517..c750ae1 100644 --- a/arch/x86_64/src/memory/multiboot/reader.cpp +++ b/arch/x86_64/src/memory/multiboot/reader.cpp @@ -55,20 +55,18 @@ namespace teachos::arch::memory::multiboot for (auto section = begin; section != end; ++section) { + if (section->virtual_address < kernel_start) + { + kernel_start = section->virtual_address; + } + auto virtual_address_end = section->virtual_address + section->section_size; + if (virtual_address_end > kernel_end) + { + kernel_end = virtual_address_end; + } + switch (section->type) { - case elf_section_type::PROGRAMM: { - if (section->virtual_address < kernel_start) - { - kernel_start = section->virtual_address; - } - auto virtual_address_end = section->virtual_address + section->section_size; - if (virtual_address_end > kernel_end) - { - kernel_end = virtual_address_end; - } - break; - } case elf_section_type::DYNAMIC_SYMBOL_TABLE: case elf_section_type::SYMBOL_TABLE: symbol_table_section_count++; diff --git a/arch/x86_64/src/memory/paging/page_entry.cpp b/arch/x86_64/src/memory/paging/page_entry.cpp index 09d048b..8b4aa36 100644 --- a/arch/x86_64/src/memory/paging/page_entry.cpp +++ b/arch/x86_64/src/memory/paging/page_entry.cpp @@ -19,7 +19,7 @@ namespace teachos::arch::memory::paging if (contains_flags(PRESENT)) { auto physical_address = calculate_physical_address(); - return allocator::physical_frame::containing_address(physical_address); + return allocator::physical_frame::containing_address(physical_address & 0x000ffffffffff000); } 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 91f63b4..db0d96c 100644 --- a/arch/x86_64/src/memory/paging/virtual_page.cpp +++ b/arch/x86_64/src/memory/paging/virtual_page.cpp @@ -21,6 +21,6 @@ namespace teachos::arch::memory::paging auto virtual_page::get_level_index(page_table_handle::level level) const -> size_t { - return (start_address() >> (level * 9U)) & 0x1FF; + return (page_number >> (level * 9U)) & 0x1FF; } } // namespace teachos::arch::memory::paging -- cgit v1.2.3 From 38e87d52891429d56d20a54ce205d1e421068f36 Mon Sep 17 00:00:00 2001 From: Fabian Imhof Date: Sun, 27 Oct 2024 14:16:35 +0000 Subject: update gas --- arch/x86_64/src/memory/paging/page_entry.cpp | 17 ++--------------- 1 file changed, 2 insertions(+), 15 deletions(-) (limited to 'arch/x86_64/src/memory') diff --git a/arch/x86_64/src/memory/paging/page_entry.cpp b/arch/x86_64/src/memory/paging/page_entry.cpp index 8b4aa36..f3b5be1 100644 --- a/arch/x86_64/src/memory/paging/page_entry.cpp +++ b/arch/x86_64/src/memory/paging/page_entry.cpp @@ -18,25 +18,12 @@ namespace teachos::arch::memory::paging { if (contains_flags(PRESENT)) { - auto physical_address = calculate_physical_address(); - return allocator::physical_frame::containing_address(physical_address & 0x000ffffffffff000); + constexpr std::size_t mask = 0x000fffff'fffff000; + return allocator::physical_frame::containing_address(flags.to_ullong() & mask); } 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_entry(allocator::physical_frame frame, std::bitset<64U> additional_flags) -> void -- cgit v1.2.3 From acbd91c9898808a928af0b1bdd9d5058e8a91f62 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matteo=20Gm=C3=BCr?= Date: Sun, 27 Oct 2024 14:55:52 +0000 Subject: Add typedef for virtual / physical addresses --- .../x86_64/src/memory/allocator/physical_frame.cpp | 2 +- arch/x86_64/src/memory/paging/page_mapper.cpp | 28 +++++++++++----------- arch/x86_64/src/memory/paging/virtual_page.cpp | 6 ++--- 3 files changed, 18 insertions(+), 18 deletions(-) (limited to 'arch/x86_64/src/memory') diff --git a/arch/x86_64/src/memory/allocator/physical_frame.cpp b/arch/x86_64/src/memory/allocator/physical_frame.cpp index 03bd965..b05254b 100644 --- a/arch/x86_64/src/memory/allocator/physical_frame.cpp +++ b/arch/x86_64/src/memory/allocator/physical_frame.cpp @@ -8,7 +8,7 @@ namespace teachos::arch::memory::allocator // Nothing to do } - auto physical_frame::containing_address(std::size_t address) -> physical_frame + auto physical_frame::containing_address(physical_address address) -> physical_frame { return physical_frame{address / PAGE_FRAME_SIZE}; } diff --git a/arch/x86_64/src/memory/paging/page_mapper.cpp b/arch/x86_64/src/memory/paging/page_mapper.cpp index bc0c0d9..00c27b0 100644 --- a/arch/x86_64/src/memory/paging/page_mapper.cpp +++ b/arch/x86_64/src/memory/paging/page_mapper.cpp @@ -19,6 +19,20 @@ namespace teachos::arch::memory::paging return active_handle; } + auto translate_address(virtual_address address) -> std::optional + { + auto offset = address % allocator::PAGE_FRAME_SIZE; + auto page = virtual_page::containing_address(address); + auto frame = translate_page(page); + + if (frame.has_value()) + { + return frame.value().frame_number * allocator::PAGE_FRAME_SIZE + offset; + } + + return std::nullopt; + } + auto translate_page(virtual_page page) -> std::optional { auto current_handle = create_or_get(); @@ -77,18 +91,4 @@ namespace teachos::arch::memory::paging } return std::nullopt; } - - 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; - } } // namespace teachos::arch::memory::paging diff --git a/arch/x86_64/src/memory/paging/virtual_page.cpp b/arch/x86_64/src/memory/paging/virtual_page.cpp index db0d96c..d39bb7f 100644 --- a/arch/x86_64/src/memory/paging/virtual_page.cpp +++ b/arch/x86_64/src/memory/paging/virtual_page.cpp @@ -10,11 +10,11 @@ namespace teachos::arch::memory::paging // Nothing to do } - auto virtual_page::containing_address(std::size_t virtual_address) -> virtual_page + auto virtual_page::containing_address(virtual_address address) -> virtual_page { - exception_handling::assert(virtual_address < 0x0000800000000000 || virtual_address >= 0xffff800000000000, + exception_handling::assert(address < 0x0000800000000000 || address >= 0xffff800000000000, "[Virtual Page] Attempted to create virtual page from invalid address"); - return virtual_page{virtual_address / allocator::PAGE_FRAME_SIZE}; + return virtual_page{address / allocator::PAGE_FRAME_SIZE}; } auto virtual_page::start_address() const -> size_t { return page_number * allocator::PAGE_FRAME_SIZE; } -- cgit v1.2.3 From 58d01f6aae80a66faa5163602c399c28dcf30cb6 Mon Sep 17 00:00:00 2001 From: Fabian Imhof Date: Sun, 27 Oct 2024 15:25:57 +0000 Subject: revert p4 address update --- arch/x86_64/src/memory/paging/page_entry.cpp | 10 +++++++--- arch/x86_64/src/memory/paging/page_mapper.cpp | 3 ++- 2 files changed, 9 insertions(+), 4 deletions(-) (limited to 'arch/x86_64/src/memory') diff --git a/arch/x86_64/src/memory/paging/page_entry.cpp b/arch/x86_64/src/memory/paging/page_entry.cpp index f3b5be1..c3e9614 100644 --- a/arch/x86_64/src/memory/paging/page_entry.cpp +++ b/arch/x86_64/src/memory/paging/page_entry.cpp @@ -4,6 +4,11 @@ namespace teachos::arch::memory::paging { + namespace + { + constexpr std::size_t PHYSICAL_ADDRESS_MASK = 0x000fffff'fffff000; + } + entry::entry(uint64_t flags) : flags(flags) { @@ -18,8 +23,7 @@ namespace teachos::arch::memory::paging { if (contains_flags(PRESENT)) { - constexpr std::size_t mask = 0x000fffff'fffff000; - return allocator::physical_frame::containing_address(flags.to_ullong() & mask); + return allocator::physical_frame::containing_address(flags.to_ullong() & PHYSICAL_ADDRESS_MASK); } return std::nullopt; } @@ -28,7 +32,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, + exception_handling::assert((frame.start_address() & ~PHYSICAL_ADDRESS_MASK) == 0, "[Paging Entry] Start address is not aligned with page"); flags = std::bitset<64U>{frame.start_address()} | additional_flags; } diff --git a/arch/x86_64/src/memory/paging/page_mapper.cpp b/arch/x86_64/src/memory/paging/page_mapper.cpp index 00c27b0..fb9ea39 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 auto create_or_get() -> page_table_handle { static auto initialized = false; - static page_table_handle active_handle{boot::page_map_level_4, page_table_handle::LEVEL4}; + static page_table_handle active_handle{reinterpret_cast(0xffffffff'fffff000), + page_table_handle::LEVEL4}; if (!initialized) { -- cgit v1.2.3 From 04b0285d8329e45cea426aa1a8e69203685a4467 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matteo=20Gm=C3=BCr?= Date: Mon, 28 Oct 2024 10:15:18 +0000 Subject: Move iterator and container into generic template classes. Use algorithms instead of raw pointer for loops --- .../src/memory/allocator/area_frame_allocator.cpp | 4 +- arch/x86_64/src/memory/multiboot/memory_map.cpp | 73 -------------------- arch/x86_64/src/memory/multiboot/reader.cpp | 79 ++++++++++++---------- 3 files changed, 44 insertions(+), 112 deletions(-) delete mode 100644 arch/x86_64/src/memory/multiboot/memory_map.cpp (limited to 'arch/x86_64/src/memory') diff --git a/arch/x86_64/src/memory/allocator/area_frame_allocator.cpp b/arch/x86_64/src/memory/allocator/area_frame_allocator.cpp index 6ed4f28..e03c66a 100644 --- a/arch/x86_64/src/memory/allocator/area_frame_allocator.cpp +++ b/arch/x86_64/src/memory/allocator/area_frame_allocator.cpp @@ -9,9 +9,9 @@ namespace teachos::arch::memory::allocator { area_frame_allocator::area_frame_allocator(multiboot::memory_information mem_info) - : next_free_frame(0) + : next_free_frame(0U) , current_area(std::nullopt) - , memory_areas(mem_info.memory_areas, mem_info.area_count) + , memory_areas(mem_info.begin_area, mem_info.end_area) , kernel_start(physical_frame::containing_address(mem_info.kernel_start)) , kernel_end(physical_frame::containing_address(mem_info.kernel_end)) , multiboot_start(physical_frame::containing_address(mem_info.multiboot_start)) diff --git a/arch/x86_64/src/memory/multiboot/memory_map.cpp b/arch/x86_64/src/memory/multiboot/memory_map.cpp deleted file mode 100644 index b5e2759..0000000 --- a/arch/x86_64/src/memory/multiboot/memory_map.cpp +++ /dev/null @@ -1,73 +0,0 @@ -#include "arch/memory/multiboot/memory_map.hpp" - -#include "arch/exception_handling/assert.hpp" - -namespace teachos::arch::memory::multiboot -{ - memory_area_iterator::memory_area_iterator(value_type * p) - : ptr(p) - { - exception_handling::assert(ptr, "[Memory Area] Attempted to pass nullptr as iterator"); - } - - auto memory_area_iterator::operator*() const -> value_type & { return *ptr; } - - auto memory_area_iterator::operator->() const -> value_type * { return ptr; } - - auto memory_area_iterator::operator++(int) -> memory_area_iterator - { - memory_area_iterator old_value = *this; - ++ptr; - return old_value; - } - - auto memory_area_iterator::operator++() -> memory_area_iterator & - { - ++ptr; - return *this; - } - - auto memory_area_iterator::operator+=(difference_type value) -> memory_area_iterator & - { - ptr += value; - return *this; - } - - auto memory_area_iterator::operator-=(difference_type value) -> memory_area_iterator & - { - ptr -= value; - return *this; - } - - auto memory_area_iterator::operator+(difference_type value) const -> memory_area_iterator - { - return memory_area_iterator{ptr + value}; - } - - auto memory_area_iterator::operator-(difference_type value) const -> memory_area_iterator - { - return memory_area_iterator{ptr - value}; - } - - auto memory_area_iterator::operator-(const memory_area_iterator & other) const -> difference_type - { - return ptr - other.ptr; - } - - auto memory_area_iterator::operator[](difference_type index) const -> value_type & { return *(ptr + index); } - - memory_area_container::memory_area_container(memory_area * begin, std::size_t size) - : area_begin(begin) - , area_end(begin + size) - { - // Nothing to do - } - - auto memory_area_container::begin() const -> multiboot::memory_area_iterator { return area_begin; } - - auto memory_area_container::end() const -> multiboot::memory_area_iterator { return area_end; } - - auto memory_area_container::size() const -> size_type { return std::distance(begin(), end()); } - - auto memory_area_container::empty() const -> bool { return size() == 0; } -} // namespace teachos::arch::memory::multiboot diff --git a/arch/x86_64/src/memory/multiboot/reader.cpp b/arch/x86_64/src/memory/multiboot/reader.cpp index c750ae1..228aa09 100644 --- a/arch/x86_64/src/memory/multiboot/reader.cpp +++ b/arch/x86_64/src/memory/multiboot/reader.cpp @@ -2,8 +2,11 @@ #include "arch/boot/pointers.hpp" #include "arch/exception_handling/assert.hpp" +#include "arch/memory/multiboot/elf_symbols_section.hpp" #include "arch/memory/multiboot/info.hpp" +#include + namespace teachos::arch::memory::multiboot { namespace @@ -15,7 +18,8 @@ namespace teachos::arch::memory::multiboot return reinterpret_cast(reinterpret_cast(ptr) + ((size + 7) & ~7)); } - auto process_memory_map(memory_map_header * mminfo, memory_area *& memory_areas, uint8_t & area_count) -> void + auto process_memory_map(memory_map_header * mminfo, memory_area_container::iterator & begin_area, + memory_area_container::iterator & end_area) -> void { auto expected_entry_size = mminfo->entry_size; constexpr auto actual_entry_size = sizeof(memory_area); @@ -26,8 +30,8 @@ namespace teachos::arch::memory::multiboot auto total_entries_size = total_size - sizeof(memory_map_header) + actual_entry_size; auto number_of_entries = total_entries_size / actual_entry_size; - memory_areas = &mminfo->entries; - area_count = number_of_entries; + begin_area = memory_area_container::iterator{&mminfo->entries}; + end_area = begin_area + number_of_entries; } auto process_elf_sections(elf_symbols_section_header * symbol, uint64_t & kernel_start, @@ -45,40 +49,30 @@ namespace teachos::arch::memory::multiboot exception_handling::assert(expected_total_size == actual_total_size, "[Multiboot Reader] Unexpected elf symbols section header total size"); - auto begin = reinterpret_cast(&symbol->end); + auto begin = elf_section_header_container::iterator{reinterpret_cast(&symbol->end)}; auto end = begin + symbol->number_of_sections; exception_handling::assert(begin->is_null(), "[Multiboot Reader] Elf symbols section not starting with SHT_NULL section"); - std::size_t symbol_table_section_count = 0U; - std::size_t dynamic_section_count = 0U; + elf_section_header_container container{begin, end}; - for (auto section = begin; section != end; ++section) - { - if (section->virtual_address < kernel_start) - { - kernel_start = section->virtual_address; - } - auto virtual_address_end = section->virtual_address + section->section_size; - if (virtual_address_end > kernel_end) - { - kernel_end = virtual_address_end; - } + auto elf_section_with_lowest_virtual_address = + std::ranges::min_element(container, [](elf_section_header const & a, elf_section_header const & b) { + return a.virtual_address < b.virtual_address; + }); - switch (section->type) - { - case elf_section_type::DYNAMIC_SYMBOL_TABLE: - case elf_section_type::SYMBOL_TABLE: - symbol_table_section_count++; - break; - case elf_section_type::DYNAMIC: - dynamic_section_count++; - break; - default: - // All other cases are not important and can be ignored - break; - } - } + auto elf_section_with_highest_virtual_address = + std::ranges::max_element(container, [](elf_section_header const & a, elf_section_header const & b) { + auto a_virtual_address_end = a.virtual_address + a.section_size; + auto b_virtual_address_end = b.virtual_address + b.section_size; + return a_virtual_address_end < b_virtual_address_end; + }); + + auto symbol_table_section_count = std::ranges::count_if(container, [](elf_section_header const & section) { + return section.type == elf_section_type::DYNAMIC_SYMBOL_TABLE || section.type == elf_section_type::SYMBOL_TABLE; + }); + auto dynamic_section_count = std::ranges::count_if( + container, [](elf_section_header const & section) { return section.type == elf_section_type::DYNAMIC; }); exception_handling::assert( symbol_table_section_count == 1U, @@ -86,15 +80,26 @@ namespace teachos::arch::memory::multiboot exception_handling::assert( dynamic_section_count <= 1U, "[Multiboot Reader] ELF Specifications allows only (1) or less dynamic sections, but got more"); + + auto lowest_elf_section = *elf_section_with_lowest_virtual_address; + kernel_start = lowest_elf_section.virtual_address; + + auto highest_elf_section = *elf_section_with_highest_virtual_address; + kernel_end = highest_elf_section.virtual_address + highest_elf_section.section_size; } } // namespace auto read_multiboot2() -> memory_information { - memory_information mem_info{UINT64_MAX, 0U, boot::multiboot_information_pointer, 0U, nullptr, 0U}; - - auto * multiboot_information_pointer = reinterpret_cast(boot::multiboot_information_pointer); - auto multiboot_tag = &(multiboot_information_pointer->tags); + memory_information mem_info{UINT64_MAX, + 0U, + boot::multiboot_information_pointer, + 0U, + memory_area_container::iterator{}, + memory_area_container::iterator{}}; + + auto multiboot_information_pointer = reinterpret_cast(boot::multiboot_information_pointer); + auto multiboot_tag = &multiboot_information_pointer->tags; mem_info.multiboot_end = mem_info.multiboot_start + multiboot_information_pointer->total_size; for (auto tag = multiboot_tag; tag->type != tag_type::END; tag = align_to_8_byte_boundary(tag, tag->size)) @@ -108,11 +113,11 @@ namespace teachos::arch::memory::multiboot } case tag_type::MEMORY_MAP: { auto mminfo = reinterpret_cast(tag); - process_memory_map(mminfo, mem_info.memory_areas, mem_info.area_count); + process_memory_map(mminfo, mem_info.begin_area, mem_info.end_area); break; } default: - // All other cases are not important and can be ignored + // All other cases are not important and can be ignored. break; } } -- cgit v1.2.3 From 58680f7d84ca5771be31c0037e8caf5791d79b3c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matteo=20Gm=C3=BCr?= Date: Mon, 28 Oct 2024 12:29:39 +0000 Subject: Fix invalid assertion --- arch/x86_64/src/memory/paging/page_table.cpp | 1 - 1 file changed, 1 deletion(-) (limited to 'arch/x86_64/src/memory') diff --git a/arch/x86_64/src/memory/paging/page_table.cpp b/arch/x86_64/src/memory/paging/page_table.cpp index f1df31d..e919a1e 100644 --- a/arch/x86_64/src/memory/paging/page_table.cpp +++ b/arch/x86_64/src/memory/paging/page_table.cpp @@ -84,7 +84,6 @@ 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"); - // TODO: This section seems to return completly invalid entry, debugger doesn't even show a value? Revert once fixed return entries[index]; } -- cgit v1.2.3 From efcb913196ccf0386a557e8c1053c430e5896179 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matteo=20Gm=C3=BCr?= Date: Mon, 28 Oct 2024 12:45:46 +0000 Subject: Convert bitset to uint64_t instead of uint64_t to bitset --- arch/x86_64/src/memory/paging/page_entry.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'arch/x86_64/src/memory') diff --git a/arch/x86_64/src/memory/paging/page_entry.cpp b/arch/x86_64/src/memory/paging/page_entry.cpp index c3e9614..dbf23e2 100644 --- a/arch/x86_64/src/memory/paging/page_entry.cpp +++ b/arch/x86_64/src/memory/paging/page_entry.cpp @@ -23,7 +23,7 @@ namespace teachos::arch::memory::paging { if (contains_flags(PRESENT)) { - return allocator::physical_frame::containing_address(flags.to_ullong() & PHYSICAL_ADDRESS_MASK); + return allocator::physical_frame::containing_address(flags.to_ulong() & PHYSICAL_ADDRESS_MASK); } return std::nullopt; } @@ -34,6 +34,6 @@ namespace teachos::arch::memory::paging { exception_handling::assert((frame.start_address() & ~PHYSICAL_ADDRESS_MASK) == 0, "[Paging Entry] Start address is not aligned with page"); - flags = std::bitset<64U>{frame.start_address()} | additional_flags; + flags = frame.start_address() | additional_flags.to_ulong(); } } // namespace teachos::arch::memory::paging -- cgit v1.2.3 From e5925df93411429340d2887594004aaa690d2ef5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matteo=20Gm=C3=BCr?= Date: Mon, 28 Oct 2024 13:32:09 +0000 Subject: Adjust constant and make all possible variables const --- .../src/memory/allocator/area_frame_allocator.cpp | 12 +++--- arch/x86_64/src/memory/multiboot/reader.cpp | 47 +++++++++++----------- arch/x86_64/src/memory/paging/page_entry.cpp | 2 +- arch/x86_64/src/memory/paging/page_mapper.cpp | 26 +++++++----- arch/x86_64/src/memory/paging/page_table.cpp | 22 +++++----- arch/x86_64/src/memory/paging/virtual_page.cpp | 2 +- 6 files changed, 56 insertions(+), 55 deletions(-) (limited to 'arch/x86_64/src/memory') diff --git a/arch/x86_64/src/memory/allocator/area_frame_allocator.cpp b/arch/x86_64/src/memory/allocator/area_frame_allocator.cpp index e03c66a..6ec3e95 100644 --- a/arch/x86_64/src/memory/allocator/area_frame_allocator.cpp +++ b/arch/x86_64/src/memory/allocator/area_frame_allocator.cpp @@ -28,7 +28,7 @@ namespace teachos::arch::memory::allocator return physical_frame::containing_address(address) >= next_free_frame; }); - auto lowest_area_with_free_frames = + auto const lowest_area_with_free_frames = std::ranges::min_element(next_area_with_free_frames, [](multiboot::memory_area a, multiboot::memory_area b) { return a.base_address < b.base_address; }); @@ -37,7 +37,7 @@ namespace teachos::arch::memory::allocator { current_area = *lowest_area_with_free_frames; // Update the `next_free_frame` according to the new memory area - auto start_frame = physical_frame::containing_address(current_area.value().base_address); + auto const start_frame = physical_frame::containing_address(current_area.value().base_address); if (next_free_frame < start_frame) { next_free_frame = start_frame; @@ -47,16 +47,14 @@ namespace teachos::arch::memory::allocator auto area_frame_allocator::allocate_frame() -> std::optional { - /* - * Only try to allocate memory if current_area is not null, because - * the current_area is null if there is no more available memory. - */ + // Only try to allocate memory if current_area is not null, because + // the current_area is null if there is no more available memory. if (!current_area.has_value()) { return std::nullopt; } - auto address = current_area.value().base_address + current_area.value().area_length - 1; + auto const address = current_area.value().base_address + current_area.value().area_length - 1; physical_frame current_area_last_frame = physical_frame::containing_address(address); if (next_free_frame > current_area_last_frame) diff --git a/arch/x86_64/src/memory/multiboot/reader.cpp b/arch/x86_64/src/memory/multiboot/reader.cpp index 228aa09..c3a78df 100644 --- a/arch/x86_64/src/memory/multiboot/reader.cpp +++ b/arch/x86_64/src/memory/multiboot/reader.cpp @@ -21,14 +21,14 @@ namespace teachos::arch::memory::multiboot auto process_memory_map(memory_map_header * mminfo, memory_area_container::iterator & begin_area, memory_area_container::iterator & end_area) -> void { - auto expected_entry_size = mminfo->entry_size; - constexpr auto actual_entry_size = sizeof(memory_area); + auto const expected_entry_size = mminfo->entry_size; + auto constexpr actual_entry_size = sizeof(memory_area); exception_handling::assert(expected_entry_size == actual_entry_size, "[Multiboot Reader] Unexpected memory area entry size"); - auto total_size = mminfo->info.size; - auto total_entries_size = total_size - sizeof(memory_map_header) + actual_entry_size; - auto number_of_entries = total_entries_size / actual_entry_size; + auto const total_size = mminfo->info.size; + auto const total_entries_size = total_size - sizeof(memory_map_header) + actual_entry_size; + auto const number_of_entries = total_entries_size / actual_entry_size; begin_area = memory_area_container::iterator{&mminfo->entries}; end_area = begin_area + number_of_entries; @@ -37,41 +37,41 @@ namespace teachos::arch::memory::multiboot auto process_elf_sections(elf_symbols_section_header * symbol, uint64_t & kernel_start, uint64_t & kernel_end) -> void { - auto expected_entry_size = symbol->entry_size; - constexpr auto actual_entry_size = sizeof(elf_section_header); + auto const expected_entry_size = symbol->entry_size; + auto constexpr actual_entry_size = sizeof(elf_section_header); exception_handling::assert(expected_entry_size == actual_entry_size, "[Multiboot Reader] Unexpected elf section header entry size"); - auto expected_total_size = symbol->info.size; - auto actual_total_entry_size = actual_entry_size * symbol->number_of_sections; - constexpr auto actual_total_section_size = sizeof(elf_symbols_section_header) - sizeof(uint32_t); - auto actual_total_size = actual_total_entry_size + actual_total_section_size; + auto const expected_total_size = symbol->info.size; + auto const actual_total_entry_size = actual_entry_size * symbol->number_of_sections; + auto constexpr actual_total_section_size = sizeof(elf_symbols_section_header) - sizeof(uint32_t); + auto const actual_total_size = actual_total_entry_size + actual_total_section_size; exception_handling::assert(expected_total_size == actual_total_size, "[Multiboot Reader] Unexpected elf symbols section header total size"); - auto begin = elf_section_header_container::iterator{reinterpret_cast(&symbol->end)}; - auto end = begin + symbol->number_of_sections; + auto const begin = elf_section_header_container::iterator{reinterpret_cast(&symbol->end)}; + auto const end = begin + symbol->number_of_sections; exception_handling::assert(begin->is_null(), "[Multiboot Reader] Elf symbols section not starting with SHT_NULL section"); elf_section_header_container container{begin, end}; - auto elf_section_with_lowest_virtual_address = + auto const elf_section_with_lowest_virtual_address = std::ranges::min_element(container, [](elf_section_header const & a, elf_section_header const & b) { return a.virtual_address < b.virtual_address; }); - auto elf_section_with_highest_virtual_address = + auto const elf_section_with_highest_virtual_address = std::ranges::max_element(container, [](elf_section_header const & a, elf_section_header const & b) { auto a_virtual_address_end = a.virtual_address + a.section_size; auto b_virtual_address_end = b.virtual_address + b.section_size; return a_virtual_address_end < b_virtual_address_end; }); - auto symbol_table_section_count = std::ranges::count_if(container, [](elf_section_header const & section) { + auto const symbol_table_section_count = std::ranges::count_if(container, [](elf_section_header const & section) { return section.type == elf_section_type::DYNAMIC_SYMBOL_TABLE || section.type == elf_section_type::SYMBOL_TABLE; }); - auto dynamic_section_count = std::ranges::count_if( + auto const dynamic_section_count = std::ranges::count_if( container, [](elf_section_header const & section) { return section.type == elf_section_type::DYNAMIC; }); exception_handling::assert( @@ -81,10 +81,10 @@ namespace teachos::arch::memory::multiboot dynamic_section_count <= 1U, "[Multiboot Reader] ELF Specifications allows only (1) or less dynamic sections, but got more"); - auto lowest_elf_section = *elf_section_with_lowest_virtual_address; + auto const lowest_elf_section = *elf_section_with_lowest_virtual_address; kernel_start = lowest_elf_section.virtual_address; - auto highest_elf_section = *elf_section_with_highest_virtual_address; + auto const highest_elf_section = *elf_section_with_highest_virtual_address; kernel_end = highest_elf_section.virtual_address + highest_elf_section.section_size; } } // namespace @@ -98,8 +98,8 @@ namespace teachos::arch::memory::multiboot memory_area_container::iterator{}, memory_area_container::iterator{}}; - auto multiboot_information_pointer = reinterpret_cast(boot::multiboot_information_pointer); - auto multiboot_tag = &multiboot_information_pointer->tags; + auto const multiboot_information_pointer = reinterpret_cast(boot::multiboot_information_pointer); + auto const multiboot_tag = &multiboot_information_pointer->tags; mem_info.multiboot_end = mem_info.multiboot_start + multiboot_information_pointer->total_size; for (auto tag = multiboot_tag; tag->type != tag_type::END; tag = align_to_8_byte_boundary(tag, tag->size)) @@ -107,12 +107,12 @@ namespace teachos::arch::memory::multiboot switch (tag->type) { case tag_type::ELF_SECTIONS: { - auto symbol = reinterpret_cast(tag); + auto const symbol = reinterpret_cast(tag); process_elf_sections(symbol, mem_info.kernel_start, mem_info.kernel_end); break; } case tag_type::MEMORY_MAP: { - auto mminfo = reinterpret_cast(tag); + auto const mminfo = reinterpret_cast(tag); process_memory_map(mminfo, mem_info.begin_area, mem_info.end_area); break; } @@ -121,7 +121,6 @@ namespace teachos::arch::memory::multiboot break; } } - return mem_info; } } // namespace teachos::arch::memory::multiboot diff --git a/arch/x86_64/src/memory/paging/page_entry.cpp b/arch/x86_64/src/memory/paging/page_entry.cpp index dbf23e2..8923fea 100644 --- a/arch/x86_64/src/memory/paging/page_entry.cpp +++ b/arch/x86_64/src/memory/paging/page_entry.cpp @@ -6,7 +6,7 @@ namespace teachos::arch::memory::paging { namespace { - constexpr std::size_t PHYSICAL_ADDRESS_MASK = 0x000fffff'fffff000; + std::size_t constexpr PHYSICAL_ADDRESS_MASK = 0x000fffff'fffff000; } entry::entry(uint64_t flags) diff --git a/arch/x86_64/src/memory/paging/page_mapper.cpp b/arch/x86_64/src/memory/paging/page_mapper.cpp index fb9ea39..3baf6ae 100644 --- a/arch/x86_64/src/memory/paging/page_mapper.cpp +++ b/arch/x86_64/src/memory/paging/page_mapper.cpp @@ -4,11 +4,15 @@ namespace teachos::arch::memory::paging { + namespace + { + std::size_t constexpr PAGE_TABLE_LEVEL_4_ADDRESS = 0xffffffff'fffff000; + } // namespace auto create_or_get() -> page_table_handle { static auto initialized = false; - static page_table_handle active_handle{reinterpret_cast(0xffffffff'fffff000), + static page_table_handle active_handle{reinterpret_cast(PAGE_TABLE_LEVEL_4_ADDRESS), page_table_handle::LEVEL4}; if (!initialized) @@ -22,9 +26,9 @@ namespace teachos::arch::memory::paging auto translate_address(virtual_address address) -> std::optional { - auto offset = address % allocator::PAGE_FRAME_SIZE; - auto page = virtual_page::containing_address(address); - auto frame = translate_page(page); + auto const offset = address % allocator::PAGE_FRAME_SIZE; + auto const page = virtual_page::containing_address(address); + auto const frame = translate_page(page); if (frame.has_value()) { @@ -40,7 +44,7 @@ namespace teachos::arch::memory::paging for (auto level = page_table_handle::LEVEL4; level != page_table_handle::LEVEL1; --level) { - auto next_handle = current_handle.next_table(page.get_level_index(level)); + auto const 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_handle.has_value()) @@ -50,8 +54,8 @@ namespace teachos::arch::memory::paging current_handle = next_handle.value(); } - auto level1_index = page.get_level_index(page_table_handle::LEVEL1); - auto level1_frame = current_handle[level1_index].calculate_pointed_to_frame(); + auto const level1_index = page.get_level_index(page_table_handle::LEVEL1); + auto const level1_frame = current_handle[level1_index].calculate_pointed_to_frame(); return level1_frame; } @@ -65,8 +69,8 @@ namespace teachos::arch::memory::paging return std::nullopt; } - auto level3_entry = level3_handle.value()[page.get_level_index(page_table_handle::LEVEL3)]; - auto level3_frame = level3_entry.calculate_pointed_to_frame(); + auto const level3_entry = level3_handle.value()[page.get_level_index(page_table_handle::LEVEL3)]; + auto const level3_frame = level3_entry.calculate_pointed_to_frame(); if (level3_frame.has_value() && level3_entry.contains_flags(entry::HUGE_PAGE)) { exception_handling::assert( @@ -80,8 +84,8 @@ namespace teachos::arch::memory::paging auto level2_handle = level3_handle.value().next_table(page.get_level_index(page_table_handle::LEVEL3)); if (level2_handle.has_value()) { - auto level2_entry = level2_handle.value()[page.get_level_index(page_table_handle::LEVEL2)]; - auto level2_frame = level2_entry.calculate_pointed_to_frame(); + auto const level2_entry = level2_handle.value()[page.get_level_index(page_table_handle::LEVEL2)]; + auto const level2_frame = level2_entry.calculate_pointed_to_frame(); if (level2_frame.has_value() && level2_entry.contains_flags(entry::HUGE_PAGE)) { exception_handling::assert(level2_frame.value().frame_number % PAGE_TABLE_ENTRY_COUNT == 0U, diff --git a/arch/x86_64/src/memory/paging/page_table.cpp b/arch/x86_64/src/memory/paging/page_table.cpp index e919a1e..a01c431 100644 --- a/arch/x86_64/src/memory/paging/page_table.cpp +++ b/arch/x86_64/src/memory/paging/page_table.cpp @@ -60,9 +60,9 @@ namespace teachos::arch::memory::paging auto page_table::zero_entries() -> void { - constexpr size_t entry_amount = sizeof(entries) / sizeof(entries[0]); + std::size_t constexpr entry_amount = sizeof(entries) / sizeof(entries[0]); static_assert(entry_amount == PAGE_TABLE_ENTRY_COUNT); - for (size_t i = 0; i < entry_amount; ++i) + for (std::size_t i = 0; i < entry_amount; ++i) { auto entry = this->operator[](i); entry.set_unused(); @@ -71,7 +71,7 @@ namespace teachos::arch::memory::paging auto page_table::next_table(std::size_t table_index) -> std::optional { - auto address = next_table_address(table_index); + auto const address = next_table_address(table_index); if (address.has_value()) { return reinterpret_cast(address.value()); @@ -89,11 +89,11 @@ namespace teachos::arch::memory::paging auto page_table::next_table_address(std::size_t table_index) -> std::optional { - auto entry = this->operator[](table_index); + auto const 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); + auto const table_address = reinterpret_cast(this); return ((table_address << 9) | (table_index << 12)); } return std::nullopt; @@ -113,17 +113,17 @@ namespace teachos::arch::memory::paging exception_handling::assert(handle_level == page_table_handle::LEVEL4, "[Page Table] Attempted to initialize a page table of level 3 or lower"); auto level3_page_table = std::construct_at(reinterpret_cast(&_end_of_image)); - for (size_t n = 1; n <= PAGE_TABLE_ENTRY_COUNT; ++n) + for (std::size_t n = 1; n <= PAGE_TABLE_ENTRY_COUNT; ++n) { - size_t offset = sizeof(page_table) * n; + std::size_t offset = sizeof(page_table) * n; std::construct_at(reinterpret_cast(&_end_of_image + offset)); - for (size_t m = 1; m <= PAGE_TABLE_ENTRY_COUNT; ++m) + for (std::size_t m = 1; m <= PAGE_TABLE_ENTRY_COUNT; ++m) { - size_t offset = sizeof(page_table) * ((PAGE_TABLE_ENTRY_COUNT * n) + m); + std::size_t offset = sizeof(page_table) * ((PAGE_TABLE_ENTRY_COUNT * n) + m); std::construct_at(reinterpret_cast(&_end_of_image + offset)); } } - size_t const flags = reinterpret_cast(level3_page_table); + std::size_t const flags = reinterpret_cast(level3_page_table); this->operator[](0U) = entry{flags}; */ } @@ -134,7 +134,7 @@ namespace teachos::arch::memory::paging { exception_handling::assert(handle_level != page_table_handle::LEVEL1, "[Page Table] Attempted to call next_table on level 1 page table"); - auto next_table = handle->next_table(table_index); + auto const next_table = handle->next_table(table_index); if (next_table.has_value()) { return page_table_handle{next_table.value(), --handle_level}; diff --git a/arch/x86_64/src/memory/paging/virtual_page.cpp b/arch/x86_64/src/memory/paging/virtual_page.cpp index d39bb7f..4221335 100644 --- a/arch/x86_64/src/memory/paging/virtual_page.cpp +++ b/arch/x86_64/src/memory/paging/virtual_page.cpp @@ -12,7 +12,7 @@ namespace teachos::arch::memory::paging auto virtual_page::containing_address(virtual_address address) -> virtual_page { - exception_handling::assert(address < 0x0000800000000000 || address >= 0xffff800000000000, + exception_handling::assert(address < 0x00008000'00000000 || address >= 0xffff8000'00000000, "[Virtual Page] Attempted to create virtual page from invalid address"); return virtual_page{address / allocator::PAGE_FRAME_SIZE}; } -- cgit v1.2.3 From aa981cad951c4aa2a5e2f7a7f8f1b7b9a0ff4bcd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matteo=20Gm=C3=BCr?= Date: Mon, 28 Oct 2024 14:41:31 +0000 Subject: Fix lost updates, because of writing into copies instead of references --- arch/x86_64/src/memory/allocator/area_frame_allocator.cpp | 8 ++++++-- arch/x86_64/src/memory/paging/page_entry.cpp | 3 ++- arch/x86_64/src/memory/paging/page_mapper.cpp | 4 ++-- 3 files changed, 10 insertions(+), 5 deletions(-) (limited to 'arch/x86_64/src/memory') diff --git a/arch/x86_64/src/memory/allocator/area_frame_allocator.cpp b/arch/x86_64/src/memory/allocator/area_frame_allocator.cpp index 6ec3e95..fecc6cd 100644 --- a/arch/x86_64/src/memory/allocator/area_frame_allocator.cpp +++ b/arch/x86_64/src/memory/allocator/area_frame_allocator.cpp @@ -85,7 +85,11 @@ namespace teachos::arch::memory::allocator auto area_frame_allocator::deallocate_frame(physical_frame physical_frame) -> void { - exception_handling::assert(false && physical_frame.frame_number == 0, - "[deallocate_frame] Not implemented Exception"); + // TODO: Implement deallocation to make unmap actually work. + if (physical_frame.frame_number == 0) + { + } + /*exception_handling::assert(false && physical_frame.frame_number == 0, + "[deallocate_frame] Not implemented Exception");*/ } } // namespace teachos::arch::memory::allocator diff --git a/arch/x86_64/src/memory/paging/page_entry.cpp b/arch/x86_64/src/memory/paging/page_entry.cpp index 8923fea..23c700f 100644 --- a/arch/x86_64/src/memory/paging/page_entry.cpp +++ b/arch/x86_64/src/memory/paging/page_entry.cpp @@ -23,7 +23,8 @@ namespace teachos::arch::memory::paging { if (contains_flags(PRESENT)) { - return allocator::physical_frame::containing_address(flags.to_ulong() & PHYSICAL_ADDRESS_MASK); + auto const address = flags.to_ulong() & PHYSICAL_ADDRESS_MASK; + return allocator::physical_frame::containing_address(address); } return std::nullopt; } diff --git a/arch/x86_64/src/memory/paging/page_mapper.cpp b/arch/x86_64/src/memory/paging/page_mapper.cpp index 3baf6ae..0a1fc65 100644 --- a/arch/x86_64/src/memory/paging/page_mapper.cpp +++ b/arch/x86_64/src/memory/paging/page_mapper.cpp @@ -55,8 +55,8 @@ namespace teachos::arch::memory::paging } auto const level1_index = page.get_level_index(page_table_handle::LEVEL1); - auto const level1_frame = current_handle[level1_index].calculate_pointed_to_frame(); - return level1_frame; + auto const level1_entry = current_handle[level1_index]; + return level1_entry.calculate_pointed_to_frame(); } auto translate_huge_page(virtual_page page) -> std::optional -- cgit v1.2.3 From bd3ae51093b504bd035cb698c637ef6f82994ba2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matteo=20Gm=C3=BCr?= Date: Mon, 28 Oct 2024 14:48:32 +0000 Subject: Remove not required includes --- arch/x86_64/src/memory/paging/page_mapper.cpp | 2 -- 1 file changed, 2 deletions(-) (limited to 'arch/x86_64/src/memory') diff --git a/arch/x86_64/src/memory/paging/page_mapper.cpp b/arch/x86_64/src/memory/paging/page_mapper.cpp index 0a1fc65..be4b259 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/boot/pointers.hpp" - namespace teachos::arch::memory::paging { namespace -- cgit v1.2.3 From f9f047f519d0100c40b914d3ce777ac2f8430b38 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matteo=20Gm=C3=BCr?= Date: Mon, 28 Oct 2024 15:18:31 +0000 Subject: Add is empty check method for page table --- .../src/memory/allocator/area_frame_allocator.cpp | 9 ++-- arch/x86_64/src/memory/paging/page_table.cpp | 55 +++++++++------------- 2 files changed, 26 insertions(+), 38 deletions(-) (limited to 'arch/x86_64/src/memory') diff --git a/arch/x86_64/src/memory/allocator/area_frame_allocator.cpp b/arch/x86_64/src/memory/allocator/area_frame_allocator.cpp index fecc6cd..e79cd8b 100644 --- a/arch/x86_64/src/memory/allocator/area_frame_allocator.cpp +++ b/arch/x86_64/src/memory/allocator/area_frame_allocator.cpp @@ -85,11 +85,8 @@ namespace teachos::arch::memory::allocator auto area_frame_allocator::deallocate_frame(physical_frame physical_frame) -> void { - // TODO: Implement deallocation to make unmap actually work. - if (physical_frame.frame_number == 0) - { - } - /*exception_handling::assert(false && physical_frame.frame_number == 0, - "[deallocate_frame] Not implemented Exception");*/ + // TODO: Fix create acutal deallocation of frames if it is even possible. Can the area frame allocator even + // deallocate in the first place? + next_free_frame = physical_frame; } } // namespace teachos::arch::memory::allocator diff --git a/arch/x86_64/src/memory/paging/page_table.cpp b/arch/x86_64/src/memory/paging/page_table.cpp index a01c431..64a4fd9 100644 --- a/arch/x86_64/src/memory/paging/page_table.cpp +++ b/arch/x86_64/src/memory/paging/page_table.cpp @@ -1,5 +1,6 @@ #include "arch/memory/paging/page_table.hpp" +#include #include #include @@ -16,31 +17,16 @@ namespace teachos::arch::memory::paging */ struct page_table { - /** - * @brief Set every entry of the page to unused. - */ auto zero_entries() -> void; - /** - * @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. - * - * @note This method - * should not be called on a Level 1 page table, because there is no furthere page table and mangeling up and - * returning the physical address would cause hard to debug issues. - * - * @param table_index Index of this page table in the page table one level lower. - */ - auto next_table(std::size_t table_index) -> std::optional; + auto is_empty() const -> bool; + + auto next_table(std::size_t table_index) const -> std::optional; - /** - * @brief Index operator overload to access specific entries directy. - * - * @param index Index of the entry we want to access and read or write too. - * @return Entry at the given table index. - */ auto operator[](std::size_t index) -> entry &; + auto operator[](std::size_t index) const -> entry const &; + private: /** * @brief Calculates the address of the next page table level for the given table index. @@ -51,7 +37,7 @@ namespace teachos::arch::memory::paging * @param table_index Index of this page table in the page table one level higher. * @return An optional of the address of the next page table or null. */ - auto next_table_address(std::size_t table_index) -> std::optional; + auto next_table_address(std::size_t table_index) const -> std::optional; std::array entries = {}; ///< Entries containing addresses to page tables of a level below or @@ -60,16 +46,15 @@ namespace teachos::arch::memory::paging auto page_table::zero_entries() -> void { - std::size_t constexpr entry_amount = sizeof(entries) / sizeof(entries[0]); - static_assert(entry_amount == PAGE_TABLE_ENTRY_COUNT); - for (std::size_t i = 0; i < entry_amount; ++i) - { - auto entry = this->operator[](i); - entry.set_unused(); - } + std::ranges::for_each(entries, [](entry & entry) { entry.set_unused(); }); + } + + auto page_table::is_empty() const -> bool + { + return std::all_of(entries.begin(), entries.end(), [](entry const & entry) { return entry.is_unused(); }); } - 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 { auto const address = next_table_address(table_index); if (address.has_value()) @@ -81,13 +66,17 @@ namespace teachos::arch::memory::paging 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. exception_handling::assert(index < PAGE_TABLE_ENTRY_COUNT, "[Page Table] Index out of bounds"); return entries[index]; } - auto page_table::next_table_address(std::size_t table_index) -> std::optional + auto page_table::operator[](std::size_t index) const -> entry const & + { + exception_handling::assert(index < PAGE_TABLE_ENTRY_COUNT, "[Page Table] Index out of bounds"); + return entries[index]; + } + + auto page_table::next_table_address(std::size_t table_index) const -> std::optional { auto const entry = this->operator[](table_index); @@ -130,6 +119,8 @@ namespace teachos::arch::memory::paging auto page_table_handle::zero_entries() -> void { handle->zero_entries(); } + auto page_table_handle::is_empty() const -> bool { return handle->is_empty(); } + auto page_table_handle::next_table(std::size_t table_index) -> std::optional { exception_handling::assert(handle_level != page_table_handle::LEVEL1, -- cgit v1.2.3 From 0d16592c8dce876d8e621c73dea41c33339f3173 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matteo=20Gm=C3=BCr?= Date: Tue, 29 Oct 2024 06:55:36 +0000 Subject: Use more virtual and physical address typedef where useful --- arch/x86_64/src/memory/allocator/physical_frame.cpp | 2 +- arch/x86_64/src/memory/paging/virtual_page.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'arch/x86_64/src/memory') diff --git a/arch/x86_64/src/memory/allocator/physical_frame.cpp b/arch/x86_64/src/memory/allocator/physical_frame.cpp index b05254b..bef9322 100644 --- a/arch/x86_64/src/memory/allocator/physical_frame.cpp +++ b/arch/x86_64/src/memory/allocator/physical_frame.cpp @@ -13,5 +13,5 @@ namespace teachos::arch::memory::allocator return physical_frame{address / PAGE_FRAME_SIZE}; } - auto physical_frame::start_address() const -> uint64_t { return frame_number * PAGE_FRAME_SIZE; } + auto physical_frame::start_address() const -> physical_address { return frame_number * PAGE_FRAME_SIZE; } } // namespace teachos::arch::memory::allocator diff --git a/arch/x86_64/src/memory/paging/virtual_page.cpp b/arch/x86_64/src/memory/paging/virtual_page.cpp index 4221335..c0ec88d 100644 --- a/arch/x86_64/src/memory/paging/virtual_page.cpp +++ b/arch/x86_64/src/memory/paging/virtual_page.cpp @@ -17,7 +17,7 @@ namespace teachos::arch::memory::paging return virtual_page{address / allocator::PAGE_FRAME_SIZE}; } - auto virtual_page::start_address() const -> size_t { return page_number * allocator::PAGE_FRAME_SIZE; } + auto virtual_page::start_address() const -> virtual_address { return page_number * allocator::PAGE_FRAME_SIZE; } auto virtual_page::get_level_index(page_table_handle::level level) const -> size_t { -- cgit v1.2.3 From 4c4479a4b728fd7eaf007649e946f9435ee1e402 Mon Sep 17 00:00:00 2001 From: Fabian Imhof Date: Tue, 29 Oct 2024 07:32:24 +0000 Subject: implement page_table unmapping --- arch/x86_64/src/memory/paging/page_table.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'arch/x86_64/src/memory') 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 & -- cgit v1.2.3 From 5334a63e7fc3959536f4f443c86f8913f7cb2451 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matteo=20Gm=C3=BCr?= Date: Tue, 29 Oct 2024 08:05:22 +0000 Subject: Unmap all empty page tables in unmap function. --- arch/x86_64/src/memory/allocator/area_frame_allocator.cpp | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) (limited to 'arch/x86_64/src/memory') diff --git a/arch/x86_64/src/memory/allocator/area_frame_allocator.cpp b/arch/x86_64/src/memory/allocator/area_frame_allocator.cpp index e79cd8b..1e87147 100644 --- a/arch/x86_64/src/memory/allocator/area_frame_allocator.cpp +++ b/arch/x86_64/src/memory/allocator/area_frame_allocator.cpp @@ -83,10 +83,5 @@ namespace teachos::arch::memory::allocator return allocate_frame(); } - auto area_frame_allocator::deallocate_frame(physical_frame physical_frame) -> void - { - // TODO: Fix create acutal deallocation of frames if it is even possible. Can the area frame allocator even - // deallocate in the first place? - next_free_frame = physical_frame; - } + auto area_frame_allocator::deallocate_frame(physical_frame physical_frame) -> void { (void)physical_frame; } } // namespace teachos::arch::memory::allocator -- cgit v1.2.3 From 4e9338075cf30702b922e5aecbc33c18bfd3f759 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matteo=20Gm=C3=BCr?= Date: Tue, 29 Oct 2024 08:11:13 +0000 Subject: Remove not required methods --- arch/x86_64/src/memory/paging/page_mapper.cpp | 8 -------- arch/x86_64/src/memory/paging/page_table.cpp | 22 ---------------------- 2 files changed, 30 deletions(-) (limited to 'arch/x86_64/src/memory') diff --git a/arch/x86_64/src/memory/paging/page_mapper.cpp b/arch/x86_64/src/memory/paging/page_mapper.cpp index be4b259..2f2ee6a 100644 --- a/arch/x86_64/src/memory/paging/page_mapper.cpp +++ b/arch/x86_64/src/memory/paging/page_mapper.cpp @@ -9,16 +9,8 @@ namespace teachos::arch::memory::paging auto create_or_get() -> page_table_handle { - static auto initialized = false; static page_table_handle active_handle{reinterpret_cast(PAGE_TABLE_LEVEL_4_ADDRESS), page_table_handle::LEVEL4}; - - if (!initialized) - { - active_handle.initialize_page_tables(); - initialized = true; - } - return active_handle; } diff --git a/arch/x86_64/src/memory/paging/page_table.cpp b/arch/x86_64/src/memory/paging/page_table.cpp index 0121e95..3ad1d54 100644 --- a/arch/x86_64/src/memory/paging/page_table.cpp +++ b/arch/x86_64/src/memory/paging/page_table.cpp @@ -96,28 +96,6 @@ namespace teachos::arch::memory::paging "[Page Table] Attempted to pass nullptr as handle to page table handle method"); } - auto page_table_handle::initialize_page_tables() -> void - { - // TODO: This should be done differently and only once the other methods are working see Rempaing the Kernel - /* - exception_handling::assert(handle_level == page_table_handle::LEVEL4, - "[Page Table] Attempted to initialize a page table of level 3 or lower"); - auto level3_page_table = std::construct_at(reinterpret_cast(&_end_of_image)); - for (std::size_t n = 1; n <= PAGE_TABLE_ENTRY_COUNT; ++n) - { - std::size_t offset = sizeof(page_table) * n; - std::construct_at(reinterpret_cast(&_end_of_image + offset)); - for (std::size_t m = 1; m <= PAGE_TABLE_ENTRY_COUNT; ++m) - { - std::size_t offset = sizeof(page_table) * ((PAGE_TABLE_ENTRY_COUNT * n) + m); - std::construct_at(reinterpret_cast(&_end_of_image + offset)); - } - } - std::size_t const flags = reinterpret_cast(level3_page_table); - this->operator[](0U) = entry{flags}; - */ - } - auto page_table_handle::zero_entries() -> void { handle->zero_entries(); } auto page_table_handle::is_empty() const -> bool { return handle->is_empty(); } -- cgit v1.2.3 From dfb0ea2fd7525dd12addf295aef4d642e93ea22a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matteo=20Gm=C3=BCr?= Date: Tue, 29 Oct 2024 09:31:36 +0000 Subject: Create tiny frame allocator which holds only 3 frames --- .../src/memory/allocator/tiny_frame_allocator.cpp | 34 ++++++++++++++++++++++ 1 file changed, 34 insertions(+) create mode 100644 arch/x86_64/src/memory/allocator/tiny_frame_allocator.cpp (limited to 'arch/x86_64/src/memory') diff --git a/arch/x86_64/src/memory/allocator/tiny_frame_allocator.cpp b/arch/x86_64/src/memory/allocator/tiny_frame_allocator.cpp new file mode 100644 index 0000000..d07398a --- /dev/null +++ b/arch/x86_64/src/memory/allocator/tiny_frame_allocator.cpp @@ -0,0 +1,34 @@ +#include "arch/memory/allocator/tiny_frame_allocator.hpp" + +#include "arch/exception_handling/panic.hpp" + +namespace teachos::arch::memory::allocator +{ + auto tiny_frame_allocator::allocate_frame() -> std::optional + { + for (auto & frame_option : frames) + { + if (frame_option.has_value()) + { + auto value = frame_option; + frame_option = std::nullopt; + return value; + } + } + return std::nullopt; + } + + auto tiny_frame_allocator::deallocate_frame(physical_frame physical_frame) -> void + { + for (auto & frame_option : frames) + { + if (!frame_option.has_value()) + { + frame_option = physical_frame; + return; + } + } + exception_handling::panic( + "[Tiny Frame Allocator] Attempted to deallocate more than the 3 frames, that can be held"); + } +} // namespace teachos::arch::memory::allocator -- cgit v1.2.3 From 29c51a2cc30060bd904b06cbe6913755352c48c7 Mon Sep 17 00:00:00 2001 From: Fabian Imhof Date: Fri, 1 Nov 2024 10:08:50 +0000 Subject: create temporary page implementation --- arch/x86_64/src/memory/paging/page_table.cpp | 24 ++++++++-------- arch/x86_64/src/memory/paging/temporary_page.cpp | 35 ++++++++++++++++++++++++ 2 files changed, 47 insertions(+), 12 deletions(-) create mode 100644 arch/x86_64/src/memory/paging/temporary_page.cpp (limited to 'arch/x86_64/src/memory') diff --git a/arch/x86_64/src/memory/paging/page_table.cpp b/arch/x86_64/src/memory/paging/page_table.cpp index 3ad1d54..3c9942a 100644 --- a/arch/x86_64/src/memory/paging/page_table.cpp +++ b/arch/x86_64/src/memory/paging/page_table.cpp @@ -88,33 +88,33 @@ namespace teachos::arch::memory::paging return std::nullopt; } - page_table_handle::page_table_handle(page_table * handle, page_table_handle::level handle_level) - : handle(handle) - , handle_level(handle_level) + page_table_handle::page_table_handle(page_table * table, page_table_handle::level table_level) + : table(table) + , table_level(table_level) { - exception_handling::assert(handle != nullptr, - "[Page Table] Attempted to pass nullptr as handle to page table handle method"); + exception_handling::assert(table != nullptr, + "[Page Table] Attempted to pass nullptr as table to page table table method"); } - auto page_table_handle::zero_entries() -> void { handle->zero_entries(); } + auto page_table_handle::zero_entries() -> void { table->zero_entries(); } - auto page_table_handle::is_empty() const -> bool { return handle->is_empty(); } + auto page_table_handle::is_empty() const -> bool { return table->is_empty(); } auto page_table_handle::next_table(std::size_t table_index) -> std::optional { - exception_handling::assert(handle_level != page_table_handle::LEVEL1, + exception_handling::assert(table_level != page_table_handle::LEVEL1, "[Page Table] Attempted to call next_table on level 1 page table"); - auto const next_table = handle->next_table(table_index); + auto const next_table = table->next_table(table_index); if (next_table.has_value()) { - return page_table_handle{next_table.value(), --handle_level}; + return page_table_handle{next_table.value(), --table_level}; } return std::nullopt; } - auto page_table_handle::get_level() const -> page_table_handle::level { return handle_level; } + auto page_table_handle::get_level() const -> page_table_handle::level { return table_level; } - auto page_table_handle::operator[](std::size_t index) -> entry & { return handle->operator[](index); } + auto page_table_handle::operator[](std::size_t index) -> entry & { return table->operator[](index); } auto operator--(page_table_handle::level & value) -> page_table_handle::level & { diff --git a/arch/x86_64/src/memory/paging/temporary_page.cpp b/arch/x86_64/src/memory/paging/temporary_page.cpp new file mode 100644 index 0000000..433f0ce --- /dev/null +++ b/arch/x86_64/src/memory/paging/temporary_page.cpp @@ -0,0 +1,35 @@ +#include "arch/memory/paging/temporary_page.hpp" + +#include "arch/memory/paging/page_entry.hpp" +#include "arch/memory/paging/page_mapper.hpp" + +namespace teachos::arch::memory::paging +{ + auto temporary_page::map_to_frame(allocator::physical_frame frame) -> virtual_address + { + exception_handling::assert(!translate_page(page).has_value(), "[Temporary page] Page is already mapped"); + + map_page_to_frame(allocator, page, frame, entry::WRITABLE); + return page.start_address(); + } + + auto temporary_page::unmap() -> void { unmap_page(allocator, page); } + + auto temporary_page::map_table_frame(allocator::physical_frame frame) -> page_table_handle + { + page_table_handle handle{reinterpret_cast(map_to_frame(frame)), page_table_handle::LEVEL1}; + return handle; + } + + auto temporary_page::zero_entries() -> void + { + auto frame = allocator.allocate_frame(); + exception_handling::assert(!frame.has_value(), "[Temporary Page] Tiny allocator could not allocate a frame"); + + page_table_handle handle = map_table_frame(frame.value()); + handle.zero_entries(); + handle[511].set_entry(frame.value(), entry::PRESENT | entry::WRITABLE); + + unmap(); + } +} // namespace teachos::arch::memory::paging \ No newline at end of file -- cgit v1.2.3 From defb727b2d0ac902e10e9736440779495b8b51a9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matteo=20Gm=C3=BCr?= Date: Fri, 1 Nov 2024 12:56:22 +0000 Subject: Move methods into seperate class. --- arch/x86_64/src/memory/paging/page_mapper.cpp | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) (limited to 'arch/x86_64/src/memory') diff --git a/arch/x86_64/src/memory/paging/page_mapper.cpp b/arch/x86_64/src/memory/paging/page_mapper.cpp index 2f2ee6a..30055e8 100644 --- a/arch/x86_64/src/memory/paging/page_mapper.cpp +++ b/arch/x86_64/src/memory/paging/page_mapper.cpp @@ -7,14 +7,15 @@ namespace teachos::arch::memory::paging std::size_t constexpr PAGE_TABLE_LEVEL_4_ADDRESS = 0xffffffff'fffff000; } // namespace - auto create_or_get() -> page_table_handle + auto active_page_table::create_or_get() -> active_page_table & { static page_table_handle active_handle{reinterpret_cast(PAGE_TABLE_LEVEL_4_ADDRESS), page_table_handle::LEVEL4}; - return active_handle; + static active_page_table active_page{active_handle}; + return active_page; } - auto translate_address(virtual_address address) -> std::optional + auto active_page_table::translate_address(virtual_address address) -> std::optional { auto const offset = address % allocator::PAGE_FRAME_SIZE; auto const page = virtual_page::containing_address(address); @@ -28,9 +29,9 @@ namespace teachos::arch::memory::paging return std::nullopt; } - auto translate_page(virtual_page page) -> std::optional + auto active_page_table::translate_page(virtual_page page) -> std::optional { - auto current_handle = create_or_get(); + auto current_handle = active_handle; for (auto level = page_table_handle::LEVEL4; level != page_table_handle::LEVEL1; --level) { @@ -49,9 +50,9 @@ namespace teachos::arch::memory::paging return level1_entry.calculate_pointed_to_frame(); } - auto translate_huge_page(virtual_page page) -> std::optional + auto active_page_table::translate_huge_page(virtual_page page) -> std::optional { - auto current_handle = create_or_get(); + auto current_handle = active_handle; auto level3_handle = current_handle.next_table(page.get_level_index(page_table_handle::LEVEL4)); if (!level3_handle.has_value()) @@ -86,4 +87,10 @@ namespace teachos::arch::memory::paging } return std::nullopt; } + + active_page_table::active_page_table(page_table_handle active_handle) + : active_handle(active_handle) + { + // Nothing to do + } } // namespace teachos::arch::memory::paging -- cgit v1.2.3 From b0d917bc8ad95e282f25949c489dfc1c06b91b83 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matteo=20Gm=C3=BCr?= Date: Fri, 1 Nov 2024 13:02:14 +0000 Subject: Adjust temporary page to changes --- arch/x86_64/src/memory/paging/temporary_page.cpp | 25 +++++++++++++----------- 1 file changed, 14 insertions(+), 11 deletions(-) (limited to 'arch/x86_64/src/memory') diff --git a/arch/x86_64/src/memory/paging/temporary_page.cpp b/arch/x86_64/src/memory/paging/temporary_page.cpp index 433f0ce..4a8f4da 100644 --- a/arch/x86_64/src/memory/paging/temporary_page.cpp +++ b/arch/x86_64/src/memory/paging/temporary_page.cpp @@ -1,35 +1,38 @@ #include "arch/memory/paging/temporary_page.hpp" #include "arch/memory/paging/page_entry.hpp" -#include "arch/memory/paging/page_mapper.hpp" namespace teachos::arch::memory::paging { - auto temporary_page::map_to_frame(allocator::physical_frame frame) -> virtual_address + auto temporary_page::map_to_frame(allocator::physical_frame frame, + active_page_table & active_table) -> virtual_address { - exception_handling::assert(!translate_page(page).has_value(), "[Temporary page] Page is already mapped"); + exception_handling::assert(!active_table.translate_page(page).has_value(), + "[Temporary page] Page is already mapped"); - map_page_to_frame(allocator, page, frame, entry::WRITABLE); + active_table.map_page_to_frame(allocator, page, frame, entry::WRITABLE); return page.start_address(); } - auto temporary_page::unmap() -> void { unmap_page(allocator, page); } + auto temporary_page::unmap(active_page_table & active_table) -> void { active_table.unmap_page(allocator, page); } - auto temporary_page::map_table_frame(allocator::physical_frame frame) -> page_table_handle + auto temporary_page::map_table_frame(allocator::physical_frame frame, + active_page_table & active_table) -> page_table_handle { - page_table_handle handle{reinterpret_cast(map_to_frame(frame)), page_table_handle::LEVEL1}; + page_table_handle handle{reinterpret_cast(map_to_frame(frame, active_table)), + page_table_handle::LEVEL1}; return handle; } - auto temporary_page::zero_entries() -> void + auto temporary_page::zero_entries(active_page_table & active_table) -> void { auto frame = allocator.allocate_frame(); exception_handling::assert(!frame.has_value(), "[Temporary Page] Tiny allocator could not allocate a frame"); - page_table_handle handle = map_table_frame(frame.value()); + page_table_handle handle = map_table_frame(frame.value(), active_table); handle.zero_entries(); handle[511].set_entry(frame.value(), entry::PRESENT | entry::WRITABLE); - unmap(); + unmap(active_table); } -} // namespace teachos::arch::memory::paging \ No newline at end of file +} // namespace teachos::arch::memory::paging -- cgit v1.2.3 From 31e1ac359eb4b84bdd81f768b2de327193976a55 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matteo=20Gm=C3=BCr?= Date: Fri, 1 Nov 2024 13:22:02 +0000 Subject: Remove static page mapper and replace with unique active and inactive page table classes. --- .../x86_64/src/memory/paging/active_page_table.cpp | 96 ++++++++++++++++++++++ .../src/memory/paging/inactive_page_table.cpp | 5 ++ arch/x86_64/src/memory/paging/page_mapper.cpp | 96 ---------------------- arch/x86_64/src/memory/paging/temporary_page.cpp | 2 +- 4 files changed, 102 insertions(+), 97 deletions(-) create mode 100644 arch/x86_64/src/memory/paging/active_page_table.cpp create mode 100644 arch/x86_64/src/memory/paging/inactive_page_table.cpp delete mode 100644 arch/x86_64/src/memory/paging/page_mapper.cpp (limited to 'arch/x86_64/src/memory') 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..38696f8 --- /dev/null +++ b/arch/x86_64/src/memory/paging/active_page_table.cpp @@ -0,0 +1,96 @@ +#include "arch/memory/paging/active_page_table.hpp" + +namespace teachos::arch::memory::paging +{ + namespace + { + std::size_t constexpr PAGE_TABLE_LEVEL_4_ADDRESS = 0xffffffff'fffff000; + } // namespace + + auto active_page_table::create_or_get() -> active_page_table & + { + static page_table_handle active_handle{reinterpret_cast(PAGE_TABLE_LEVEL_4_ADDRESS), + page_table_handle::LEVEL4}; + static active_page_table active_page{active_handle}; + return active_page; + } + + auto active_page_table::translate_address(virtual_address address) -> std::optional + { + auto const offset = address % allocator::PAGE_FRAME_SIZE; + auto const page = virtual_page::containing_address(address); + auto const frame = translate_page(page); + + if (frame.has_value()) + { + return frame.value().frame_number * allocator::PAGE_FRAME_SIZE + offset; + } + + return std::nullopt; + } + + auto active_page_table::translate_page(virtual_page page) -> std::optional + { + auto current_handle = active_handle; + + for (auto level = page_table_handle::LEVEL4; level != page_table_handle::LEVEL1; --level) + { + auto const 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_handle.has_value()) + { + return translate_huge_page(page); + } + current_handle = next_handle.value(); + } + + auto const level1_index = page.get_level_index(page_table_handle::LEVEL1); + auto const level1_entry = current_handle[level1_index]; + return level1_entry.calculate_pointed_to_frame(); + } + + auto active_page_table::translate_huge_page(virtual_page page) -> std::optional + { + auto current_handle = active_handle; + auto level3_handle = current_handle.next_table(page.get_level_index(page_table_handle::LEVEL4)); + + if (!level3_handle.has_value()) + { + return std::nullopt; + } + + auto const level3_entry = level3_handle.value()[page.get_level_index(page_table_handle::LEVEL3)]; + auto const level3_frame = level3_entry.calculate_pointed_to_frame(); + if (level3_frame.has_value() && 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_handle::LEVEL2) * PAGE_TABLE_ENTRY_COUNT + + page.get_level_index(page_table_handle::LEVEL1)}; + } + + auto level2_handle = level3_handle.value().next_table(page.get_level_index(page_table_handle::LEVEL3)); + if (level2_handle.has_value()) + { + auto const level2_entry = level2_handle.value()[page.get_level_index(page_table_handle::LEVEL2)]; + auto const level2_frame = level2_entry.calculate_pointed_to_frame(); + if (level2_frame.has_value() && level2_entry.contains_flags(entry::HUGE_PAGE)) + { + 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.value().frame_number + + page.get_level_index(page_table_handle::LEVEL1)}; + } + } + return std::nullopt; + } + + active_page_table::active_page_table(page_table_handle active_handle) + : active_handle(active_handle) + { + // Nothing to do + } +} // namespace teachos::arch::memory::paging diff --git a/arch/x86_64/src/memory/paging/inactive_page_table.cpp b/arch/x86_64/src/memory/paging/inactive_page_table.cpp new file mode 100644 index 0000000..1f36aa3 --- /dev/null +++ b/arch/x86_64/src/memory/paging/inactive_page_table.cpp @@ -0,0 +1,5 @@ +#include "arch/memory/paging/inactive_page_table.hpp" + +namespace teachos::arch::memory::paging +{ +} // 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 deleted file mode 100644 index 30055e8..0000000 --- a/arch/x86_64/src/memory/paging/page_mapper.cpp +++ /dev/null @@ -1,96 +0,0 @@ -#include "arch/memory/paging/page_mapper.hpp" - -namespace teachos::arch::memory::paging -{ - namespace - { - std::size_t constexpr PAGE_TABLE_LEVEL_4_ADDRESS = 0xffffffff'fffff000; - } // namespace - - auto active_page_table::create_or_get() -> active_page_table & - { - static page_table_handle active_handle{reinterpret_cast(PAGE_TABLE_LEVEL_4_ADDRESS), - page_table_handle::LEVEL4}; - static active_page_table active_page{active_handle}; - return active_page; - } - - auto active_page_table::translate_address(virtual_address address) -> std::optional - { - auto const offset = address % allocator::PAGE_FRAME_SIZE; - auto const page = virtual_page::containing_address(address); - auto const frame = translate_page(page); - - if (frame.has_value()) - { - return frame.value().frame_number * allocator::PAGE_FRAME_SIZE + offset; - } - - return std::nullopt; - } - - auto active_page_table::translate_page(virtual_page page) -> std::optional - { - auto current_handle = active_handle; - - for (auto level = page_table_handle::LEVEL4; level != page_table_handle::LEVEL1; --level) - { - auto const 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_handle.has_value()) - { - return translate_huge_page(page); - } - current_handle = next_handle.value(); - } - - auto const level1_index = page.get_level_index(page_table_handle::LEVEL1); - auto const level1_entry = current_handle[level1_index]; - return level1_entry.calculate_pointed_to_frame(); - } - - auto active_page_table::translate_huge_page(virtual_page page) -> std::optional - { - auto current_handle = active_handle; - auto level3_handle = current_handle.next_table(page.get_level_index(page_table_handle::LEVEL4)); - - if (!level3_handle.has_value()) - { - return std::nullopt; - } - - auto const level3_entry = level3_handle.value()[page.get_level_index(page_table_handle::LEVEL3)]; - auto const level3_frame = level3_entry.calculate_pointed_to_frame(); - if (level3_frame.has_value() && 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_handle::LEVEL2) * PAGE_TABLE_ENTRY_COUNT + - page.get_level_index(page_table_handle::LEVEL1)}; - } - - auto level2_handle = level3_handle.value().next_table(page.get_level_index(page_table_handle::LEVEL3)); - if (level2_handle.has_value()) - { - auto const level2_entry = level2_handle.value()[page.get_level_index(page_table_handle::LEVEL2)]; - auto const level2_frame = level2_entry.calculate_pointed_to_frame(); - if (level2_frame.has_value() && level2_entry.contains_flags(entry::HUGE_PAGE)) - { - 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.value().frame_number + - page.get_level_index(page_table_handle::LEVEL1)}; - } - } - return std::nullopt; - } - - active_page_table::active_page_table(page_table_handle active_handle) - : active_handle(active_handle) - { - // Nothing to do - } -} // namespace teachos::arch::memory::paging diff --git a/arch/x86_64/src/memory/paging/temporary_page.cpp b/arch/x86_64/src/memory/paging/temporary_page.cpp index 4a8f4da..180b4a8 100644 --- a/arch/x86_64/src/memory/paging/temporary_page.cpp +++ b/arch/x86_64/src/memory/paging/temporary_page.cpp @@ -27,7 +27,7 @@ namespace teachos::arch::memory::paging auto temporary_page::zero_entries(active_page_table & active_table) -> void { auto frame = allocator.allocate_frame(); - exception_handling::assert(!frame.has_value(), "[Temporary Page] Tiny allocator could not allocate a frame"); + exception_handling::assert(frame.has_value(), "[Temporary Page] Tiny allocator could not allocate a frame"); page_table_handle handle = map_table_frame(frame.value(), active_table); handle.zero_entries(); -- cgit v1.2.3 From b9fdcc729c1875858297c0f3fb9d8e6feff71374 Mon Sep 17 00:00:00 2001 From: Fabian Imhof Date: Fri, 1 Nov 2024 14:29:58 +0000 Subject: implement temporary_page and update active/inactive page tables --- arch/x86_64/src/memory/paging/active_page_table.cpp | 10 ++++++++++ arch/x86_64/src/memory/paging/inactive_page_table.cpp | 10 ++++++++++ 2 files changed, 20 insertions(+) (limited to 'arch/x86_64/src/memory') 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 38696f8..5f31f75 100644 --- a/arch/x86_64/src/memory/paging/active_page_table.cpp +++ b/arch/x86_64/src/memory/paging/active_page_table.cpp @@ -93,4 +93,14 @@ namespace teachos::arch::memory::paging { // Nothing to do } + + auto active_page_table::with(inactive_page_table inactive_page_table, temporary_page temporary_page, + active_page_table::function f) -> void + { + active_handle[511].set_entry(inactive_page_table.page_table_level_4_frame, entry::PRESENT | entry::WRITABLE); + invalidate_page_cache(PAGE_TABLE_LEVEL_4_ADDRESS); + + f(*mapper); + } + } // namespace teachos::arch::memory::paging diff --git a/arch/x86_64/src/memory/paging/inactive_page_table.cpp b/arch/x86_64/src/memory/paging/inactive_page_table.cpp index 1f36aa3..afba1f0 100644 --- a/arch/x86_64/src/memory/paging/inactive_page_table.cpp +++ b/arch/x86_64/src/memory/paging/inactive_page_table.cpp @@ -2,4 +2,14 @@ namespace teachos::arch::memory::paging { + inactive_page_table::inactive_page_table(allocator::physical_frame frame, active_page_table active_page_table, + temporary_page temporary_page) + : page_table_level_4_frame{frame} + { + auto table = temporary_page.map_table_frame(page_table_level_4_frame, active_page_table); + table.zero_entries(); + table[511].set_entry(page_table_level_4_frame, entry::PRESENT | entry::WRITABLE); + + temporary_page.unmap(active_page_table); + } } // namespace teachos::arch::memory::paging -- cgit v1.2.3 From 08875c9c42c94dd23b16baa70b2be60cf35eb253 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matteo=20Gm=C3=BCr?= Date: Fri, 1 Nov 2024 14:53:31 +0000 Subject: Fix circular dependency issue --- arch/x86_64/src/memory/paging/active_page_table.cpp | 10 ---------- arch/x86_64/src/memory/paging/kernel_mapper.cpp | 13 +++++++++++++ 2 files changed, 13 insertions(+), 10 deletions(-) create mode 100644 arch/x86_64/src/memory/paging/kernel_mapper.cpp (limited to 'arch/x86_64/src/memory') 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 5f31f75..38696f8 100644 --- a/arch/x86_64/src/memory/paging/active_page_table.cpp +++ b/arch/x86_64/src/memory/paging/active_page_table.cpp @@ -93,14 +93,4 @@ namespace teachos::arch::memory::paging { // Nothing to do } - - auto active_page_table::with(inactive_page_table inactive_page_table, temporary_page temporary_page, - active_page_table::function f) -> void - { - active_handle[511].set_entry(inactive_page_table.page_table_level_4_frame, entry::PRESENT | entry::WRITABLE); - invalidate_page_cache(PAGE_TABLE_LEVEL_4_ADDRESS); - - f(*mapper); - } - } // namespace teachos::arch::memory::paging diff --git a/arch/x86_64/src/memory/paging/kernel_mapper.cpp b/arch/x86_64/src/memory/paging/kernel_mapper.cpp new file mode 100644 index 0000000..9dfc5ad --- /dev/null +++ b/arch/x86_64/src/memory/paging/kernel_mapper.cpp @@ -0,0 +1,13 @@ +#include "arch/memory/paging/kernel_mapper.hpp" + +namespace teachos::arch::memory::paging +{ + auto with(inactive_page_table inactive_page_table, temporary_page temporary_page, + active_page_table::function f) -> void + { + /*active_handle[511].set_entry(inactive_page_table.page_table_level_4_frame, entry::PRESENT | entry::WRITABLE); + invalidate_page_cache(PAGE_TABLE_LEVEL_4_ADDRESS); + + f(*this);*/ + } +} // namespace teachos::arch::memory::paging -- cgit v1.2.3 From 86f19267c7ca4e14ac6169f758130b3c27e62cdb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matteo=20Gm=C3=BCr?= Date: Fri, 1 Nov 2024 15:10:30 +0000 Subject: Resolve compilation issues --- arch/x86_64/src/memory/paging/active_page_table.cpp | 5 ----- arch/x86_64/src/memory/paging/kernel_mapper.cpp | 17 ++++++++++++----- 2 files changed, 12 insertions(+), 10 deletions(-) (limited to 'arch/x86_64/src/memory') 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 38696f8..844ae37 100644 --- a/arch/x86_64/src/memory/paging/active_page_table.cpp +++ b/arch/x86_64/src/memory/paging/active_page_table.cpp @@ -2,11 +2,6 @@ namespace teachos::arch::memory::paging { - namespace - { - std::size_t constexpr PAGE_TABLE_LEVEL_4_ADDRESS = 0xffffffff'fffff000; - } // namespace - auto active_page_table::create_or_get() -> active_page_table & { static page_table_handle active_handle{reinterpret_cast(PAGE_TABLE_LEVEL_4_ADDRESS), diff --git a/arch/x86_64/src/memory/paging/kernel_mapper.cpp b/arch/x86_64/src/memory/paging/kernel_mapper.cpp index 9dfc5ad..59930fc 100644 --- a/arch/x86_64/src/memory/paging/kernel_mapper.cpp +++ b/arch/x86_64/src/memory/paging/kernel_mapper.cpp @@ -2,12 +2,19 @@ namespace teachos::arch::memory::paging { - auto with(inactive_page_table inactive_page_table, temporary_page temporary_page, - active_page_table::function f) -> void + kernel_mapper::kernel_mapper(active_page_table & active_table) + : active_table(active_table) { - /*active_handle[511].set_entry(inactive_page_table.page_table_level_4_frame, entry::PRESENT | entry::WRITABLE); - invalidate_page_cache(PAGE_TABLE_LEVEL_4_ADDRESS); + // Nothing to do + } + + auto kernel_mapper::with(inactive_page_table inactive_page_table, temporary_page temporary_page, + active_page_table::function f) -> void + { + active_table.active_handle[511].set_entry(inactive_page_table.page_table_level_4_frame, + entry::PRESENT | entry::WRITABLE); + active_page_table::invalidate_page_cache(PAGE_TABLE_LEVEL_4_ADDRESS); - f(*this);*/ + f(active_table); } } // namespace teachos::arch::memory::paging -- cgit v1.2.3 From 38cda6bf579f7b09d06ad73c9f4ab893939727a2 Mon Sep 17 00:00:00 2001 From: Fabian Imhof Date: Fri, 1 Nov 2024 15:32:24 +0000 Subject: extract tlb methods and finish implementation of with --- arch/x86_64/src/memory/paging/kernel_mapper.cpp | 13 ++++++++++++- arch/x86_64/src/memory/paging/tlb.cpp | 7 +++++++ 2 files changed, 19 insertions(+), 1 deletion(-) create mode 100644 arch/x86_64/src/memory/paging/tlb.cpp (limited to 'arch/x86_64/src/memory') diff --git a/arch/x86_64/src/memory/paging/kernel_mapper.cpp b/arch/x86_64/src/memory/paging/kernel_mapper.cpp index 59930fc..07d55ff 100644 --- a/arch/x86_64/src/memory/paging/kernel_mapper.cpp +++ b/arch/x86_64/src/memory/paging/kernel_mapper.cpp @@ -1,5 +1,8 @@ #include "arch/memory/paging/kernel_mapper.hpp" +#include "arch/memory/allocator/physical_frame.hpp" +#include "arch/memory/paging/tlb.hpp" + namespace teachos::arch::memory::paging { kernel_mapper::kernel_mapper(active_page_table & active_table) @@ -11,10 +14,18 @@ namespace teachos::arch::memory::paging auto kernel_mapper::with(inactive_page_table inactive_page_table, temporary_page temporary_page, active_page_table::function f) -> void { + auto backup = allocator::physical_frame::containing_address(PAGE_TABLE_LEVEL_4_ADDRESS); + auto page_table_level4 = temporary_page.map_table_frame(backup, active_table); + active_table.active_handle[511].set_entry(inactive_page_table.page_table_level_4_frame, entry::PRESENT | entry::WRITABLE); - active_page_table::invalidate_page_cache(PAGE_TABLE_LEVEL_4_ADDRESS); + tlb_flush_all(); f(active_table); + + page_table_level4[511].set_entry(backup, entry::PRESENT | entry::WRITABLE); + tlb_flush_all(); + + temporary_page.unmap(active_table); } } // namespace teachos::arch::memory::paging diff --git a/arch/x86_64/src/memory/paging/tlb.cpp b/arch/x86_64/src/memory/paging/tlb.cpp new file mode 100644 index 0000000..b3255e9 --- /dev/null +++ b/arch/x86_64/src/memory/paging/tlb.cpp @@ -0,0 +1,7 @@ +#include "arch/memory/paging/tlb.hpp" + +namespace teachos::arch::memory::paging +{ + auto tlb_flush(virtual_address address) -> void { asm volatile("invlpg (%0)" ::"r"(address) : "memory"); } + auto tlb_flush_all() -> void { flush(PAGE_TABLE_LEVEL_4_ADDRESS); } +} // namespace teachos::arch::memory::paging -- cgit v1.2.3 From d488a0709c5a2701482130a3d9c972c0b468a1d2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matteo=20Gm=C3=BCr?= Date: Fri, 1 Nov 2024 15:34:03 +0000 Subject: Fix typo --- arch/x86_64/src/memory/paging/tlb.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch/x86_64/src/memory') diff --git a/arch/x86_64/src/memory/paging/tlb.cpp b/arch/x86_64/src/memory/paging/tlb.cpp index b3255e9..c1160dc 100644 --- a/arch/x86_64/src/memory/paging/tlb.cpp +++ b/arch/x86_64/src/memory/paging/tlb.cpp @@ -3,5 +3,5 @@ namespace teachos::arch::memory::paging { auto tlb_flush(virtual_address address) -> void { asm volatile("invlpg (%0)" ::"r"(address) : "memory"); } - auto tlb_flush_all() -> void { flush(PAGE_TABLE_LEVEL_4_ADDRESS); } + auto tlb_flush_all() -> void { tlb_flush(PAGE_TABLE_LEVEL_4_ADDRESS); } } // namespace teachos::arch::memory::paging -- cgit v1.2.3 From 5ffe7d69545bf098efdd70f105a5df83304b211a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matteo=20Gm=C3=BCr?= Date: Sat, 2 Nov 2024 11:49:38 +0000 Subject: Add physical frame iterator and continue implementing kernel mapping. --- .../src/memory/allocator/area_frame_allocator.cpp | 2 +- .../x86_64/src/memory/allocator/physical_frame.cpp | 123 +++++++++++++++++++++ arch/x86_64/src/memory/multiboot/reader.cpp | 18 +-- .../src/memory/paging/inactive_page_table.cpp | 2 +- arch/x86_64/src/memory/paging/kernel_mapper.cpp | 31 ------ 5 files changed, 136 insertions(+), 40 deletions(-) delete mode 100644 arch/x86_64/src/memory/paging/kernel_mapper.cpp (limited to 'arch/x86_64/src/memory') diff --git a/arch/x86_64/src/memory/allocator/area_frame_allocator.cpp b/arch/x86_64/src/memory/allocator/area_frame_allocator.cpp index 1e87147..5d56a2a 100644 --- a/arch/x86_64/src/memory/allocator/area_frame_allocator.cpp +++ b/arch/x86_64/src/memory/allocator/area_frame_allocator.cpp @@ -8,7 +8,7 @@ namespace teachos::arch::memory::allocator { - area_frame_allocator::area_frame_allocator(multiboot::memory_information mem_info) + area_frame_allocator::area_frame_allocator(multiboot::memory_information const & mem_info) : next_free_frame(0U) , current_area(std::nullopt) , memory_areas(mem_info.begin_area, mem_info.end_area) diff --git a/arch/x86_64/src/memory/allocator/physical_frame.cpp b/arch/x86_64/src/memory/allocator/physical_frame.cpp index bef9322..9307602 100644 --- a/arch/x86_64/src/memory/allocator/physical_frame.cpp +++ b/arch/x86_64/src/memory/allocator/physical_frame.cpp @@ -14,4 +14,127 @@ namespace teachos::arch::memory::allocator } auto physical_frame::start_address() const -> physical_address { return frame_number * PAGE_FRAME_SIZE; } + + /** + * @brief Constructor. + * + * @param value Underlying value the iterator should point too + */ + physical_frame_iterator::physical_frame_iterator(physical_frame_iterator::value_type value) + : value(value) + { + // Nothing to do + } + + /** + * @brief Dereferences the initally given pointer to its value. + * + * @return Reference to the value. + */ + auto physical_frame_iterator::operator*() -> physical_frame_iterator::value_type & { return value; } + + /** + * @brief Get underlying value, which is the intially passed pointer. + * + * @return Underlying value passed intially. + */ + auto physical_frame_iterator::operator->() -> physical_frame_iterator::value_type * { return &value; } + + /** + * @brief Post increment operator. Returns a copy of the value. + * + * @return Copy of the incremented underlying address. + */ + auto physical_frame_iterator::operator++(int) -> physical_frame_iterator + { + physical_frame_iterator const old_value = *this; + ++value.frame_number; + return old_value; + } + + /** + * @brief Pre increment operator. Returns a reference to the changed value. + * + * @return Reference to the incremented underlying address. + */ + auto physical_frame_iterator::operator++() -> physical_frame_iterator & + { + ++value.frame_number; + return *this; + } + + /** + * @brief Addition assignment operator. Returns a reference to the changed value. + * + * @param operand Value we want to add to the underlying address. + * @return Reference to the changed underlying address. + */ + auto + physical_frame_iterator::operator+=(physical_frame_iterator::difference_type operand) -> physical_frame_iterator & + { + value.frame_number += operand; + return *this; + } + + /** + * @brief Subtraction assignment operator. Returns a reference to the changed value. + * + * @param operand Value we want to subtract from the underlying address. + * @return Reference to the changed underlying address. + */ + auto + physical_frame_iterator::operator-=(physical_frame_iterator::difference_type operand) -> physical_frame_iterator & + { + value.frame_number -= operand; + return *this; + } + + /** + * @brief Addition operator. Returns the changed value. + * + * @param operand Value we want to add to a copy of the underlying address. + * @return Copy of underlying address incremented by the given value. + */ + auto + physical_frame_iterator::operator+(physical_frame_iterator::difference_type operand) const -> physical_frame_iterator + { + return physical_frame_iterator{physical_frame_iterator::value_type{value.frame_number + operand}}; + } + + /** + * @brief Subtraction operator. Returns the changed value. + * + * @param operand Value we want to subtrcat from a copy of the underlying address. + * @return Copy of underlying address decremented by the given value. + */ + auto + physical_frame_iterator::operator-(physical_frame_iterator::difference_type operand) const -> physical_frame_iterator + { + return physical_frame_iterator{physical_frame_iterator::value_type{value.frame_number - operand}}; + } + + /** + * @brief Subtraction operator. Returns the size difference between two iterators. + * + * @param other Other iterator we want to substract the underlying address with ours. + * @return Size difference between the underlying address of this instance and the given iterator. + */ + auto physical_frame_iterator::operator-(const physical_frame_iterator & other) const + -> physical_frame_iterator::difference_type + { + return value.frame_number - other.value.frame_number; + } + + /** + * @brief Index operator overload. Returns a reference to the value at the given index. Simply returns the + * dereferenced underlying pointer incremented by the given index. + * + * @param index Index we want to access and get the value from. + * @return Reference to the value at the given index. + */ + auto physical_frame_iterator::operator[](physical_frame_iterator::difference_type index) const + -> physical_frame_iterator::value_type + { + return physical_frame_iterator::value_type{value.frame_number + index}; + } } // namespace teachos::arch::memory::allocator diff --git a/arch/x86_64/src/memory/multiboot/reader.cpp b/arch/x86_64/src/memory/multiboot/reader.cpp index c3a78df..e35baf3 100644 --- a/arch/x86_64/src/memory/multiboot/reader.cpp +++ b/arch/x86_64/src/memory/multiboot/reader.cpp @@ -34,8 +34,9 @@ namespace teachos::arch::memory::multiboot end_area = begin_area + number_of_entries; } - auto process_elf_sections(elf_symbols_section_header * symbol, uint64_t & kernel_start, - uint64_t & kernel_end) -> void + auto process_elf_sections(elf_symbols_section_header * symbol, std::size_t & kernel_start, std::size_t & kernel_end, + elf_section_header_container::iterator & begin_kernel, + elf_section_header_container::iterator & end_kernel) -> void { auto const expected_entry_size = symbol->entry_size; auto constexpr actual_entry_size = sizeof(elf_section_header); @@ -49,12 +50,12 @@ namespace teachos::arch::memory::multiboot exception_handling::assert(expected_total_size == actual_total_size, "[Multiboot Reader] Unexpected elf symbols section header total size"); - auto const begin = elf_section_header_container::iterator{reinterpret_cast(&symbol->end)}; - auto const end = begin + symbol->number_of_sections; - exception_handling::assert(begin->is_null(), + begin_kernel = elf_section_header_container::iterator{reinterpret_cast(&symbol->end)}; + end_kernel = begin_kernel + symbol->number_of_sections; + exception_handling::assert(begin_kernel->is_null(), "[Multiboot Reader] Elf symbols section not starting with SHT_NULL section"); - elf_section_header_container container{begin, end}; + elf_section_header_container container{begin_kernel, end_kernel}; auto const elf_section_with_lowest_virtual_address = std::ranges::min_element(container, [](elf_section_header const & a, elf_section_header const & b) { @@ -93,6 +94,8 @@ namespace teachos::arch::memory::multiboot { memory_information mem_info{UINT64_MAX, 0U, + elf_section_header_container::iterator{}, + elf_section_header_container::iterator{}, boot::multiboot_information_pointer, 0U, memory_area_container::iterator{}, @@ -108,7 +111,8 @@ namespace teachos::arch::memory::multiboot { case tag_type::ELF_SECTIONS: { auto const symbol = reinterpret_cast(tag); - process_elf_sections(symbol, mem_info.kernel_start, mem_info.kernel_end); + process_elf_sections(symbol, mem_info.kernel_start, mem_info.kernel_end, mem_info.begin_kernel, + mem_info.end_kernel); break; } case tag_type::MEMORY_MAP: { diff --git a/arch/x86_64/src/memory/paging/inactive_page_table.cpp b/arch/x86_64/src/memory/paging/inactive_page_table.cpp index afba1f0..de0421d 100644 --- a/arch/x86_64/src/memory/paging/inactive_page_table.cpp +++ b/arch/x86_64/src/memory/paging/inactive_page_table.cpp @@ -2,7 +2,7 @@ namespace teachos::arch::memory::paging { - inactive_page_table::inactive_page_table(allocator::physical_frame frame, active_page_table active_page_table, + inactive_page_table::inactive_page_table(allocator::physical_frame frame, active_page_table & active_page_table, temporary_page temporary_page) : page_table_level_4_frame{frame} { diff --git a/arch/x86_64/src/memory/paging/kernel_mapper.cpp b/arch/x86_64/src/memory/paging/kernel_mapper.cpp deleted file mode 100644 index 07d55ff..0000000 --- a/arch/x86_64/src/memory/paging/kernel_mapper.cpp +++ /dev/null @@ -1,31 +0,0 @@ -#include "arch/memory/paging/kernel_mapper.hpp" - -#include "arch/memory/allocator/physical_frame.hpp" -#include "arch/memory/paging/tlb.hpp" - -namespace teachos::arch::memory::paging -{ - kernel_mapper::kernel_mapper(active_page_table & active_table) - : active_table(active_table) - { - // Nothing to do - } - - auto kernel_mapper::with(inactive_page_table inactive_page_table, temporary_page temporary_page, - active_page_table::function f) -> void - { - auto backup = allocator::physical_frame::containing_address(PAGE_TABLE_LEVEL_4_ADDRESS); - auto page_table_level4 = temporary_page.map_table_frame(backup, active_table); - - active_table.active_handle[511].set_entry(inactive_page_table.page_table_level_4_frame, - entry::PRESENT | entry::WRITABLE); - tlb_flush_all(); - - f(active_table); - - page_table_level4[511].set_entry(backup, entry::PRESENT | entry::WRITABLE); - tlb_flush_all(); - - temporary_page.unmap(active_table); - } -} // namespace teachos::arch::memory::paging -- cgit v1.2.3 From 5ade8e0d5f190f2e439f81232b38b90c49c0cd1e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matteo=20Gm=C3=BCr?= Date: Sat, 2 Nov 2024 12:38:22 +0000 Subject: Add comments and improve multiboot information struct usability. --- .../src/memory/allocator/area_frame_allocator.cpp | 2 +- arch/x86_64/src/memory/multiboot/reader.cpp | 42 +++++++++++----------- .../src/memory/paging/inactive_page_table.cpp | 1 - 3 files changed, 21 insertions(+), 24 deletions(-) (limited to 'arch/x86_64/src/memory') diff --git a/arch/x86_64/src/memory/allocator/area_frame_allocator.cpp b/arch/x86_64/src/memory/allocator/area_frame_allocator.cpp index 5d56a2a..da4a919 100644 --- a/arch/x86_64/src/memory/allocator/area_frame_allocator.cpp +++ b/arch/x86_64/src/memory/allocator/area_frame_allocator.cpp @@ -11,7 +11,7 @@ namespace teachos::arch::memory::allocator area_frame_allocator::area_frame_allocator(multiboot::memory_information const & mem_info) : next_free_frame(0U) , current_area(std::nullopt) - , memory_areas(mem_info.begin_area, mem_info.end_area) + , memory_areas(mem_info.areas) , kernel_start(physical_frame::containing_address(mem_info.kernel_start)) , kernel_end(physical_frame::containing_address(mem_info.kernel_end)) , multiboot_start(physical_frame::containing_address(mem_info.multiboot_start)) diff --git a/arch/x86_64/src/memory/multiboot/reader.cpp b/arch/x86_64/src/memory/multiboot/reader.cpp index e35baf3..7bdf48f 100644 --- a/arch/x86_64/src/memory/multiboot/reader.cpp +++ b/arch/x86_64/src/memory/multiboot/reader.cpp @@ -18,8 +18,7 @@ namespace teachos::arch::memory::multiboot return reinterpret_cast(reinterpret_cast(ptr) + ((size + 7) & ~7)); } - auto process_memory_map(memory_map_header * mminfo, memory_area_container::iterator & begin_area, - memory_area_container::iterator & end_area) -> void + auto process_memory_map(memory_map_header * mminfo) -> memory_area_container { auto const expected_entry_size = mminfo->entry_size; auto constexpr actual_entry_size = sizeof(memory_area); @@ -30,13 +29,13 @@ namespace teachos::arch::memory::multiboot auto const total_entries_size = total_size - sizeof(memory_map_header) + actual_entry_size; auto const number_of_entries = total_entries_size / actual_entry_size; - begin_area = memory_area_container::iterator{&mminfo->entries}; - end_area = begin_area + number_of_entries; + auto const begin = memory_area_container::iterator{&mminfo->entries}; + auto const end = begin + number_of_entries; + return memory_area_container{begin, end}; } - auto process_elf_sections(elf_symbols_section_header * symbol, std::size_t & kernel_start, std::size_t & kernel_end, - elf_section_header_container::iterator & begin_kernel, - elf_section_header_container::iterator & end_kernel) -> void + auto process_elf_sections(elf_symbols_section_header * symbol, std::size_t & kernel_start, + std::size_t & kernel_end) -> elf_section_header_container { auto const expected_entry_size = symbol->entry_size; auto constexpr actual_entry_size = sizeof(elf_section_header); @@ -50,30 +49,30 @@ namespace teachos::arch::memory::multiboot exception_handling::assert(expected_total_size == actual_total_size, "[Multiboot Reader] Unexpected elf symbols section header total size"); - begin_kernel = elf_section_header_container::iterator{reinterpret_cast(&symbol->end)}; - end_kernel = begin_kernel + symbol->number_of_sections; - exception_handling::assert(begin_kernel->is_null(), + auto const begin = elf_section_header_container::iterator{reinterpret_cast(&symbol->end)}; + auto const end = begin + symbol->number_of_sections; + exception_handling::assert(begin->is_null(), "[Multiboot Reader] Elf symbols section not starting with SHT_NULL section"); - elf_section_header_container container{begin_kernel, end_kernel}; + elf_section_header_container sections{begin, end}; auto const elf_section_with_lowest_virtual_address = - std::ranges::min_element(container, [](elf_section_header const & a, elf_section_header const & b) { + std::ranges::min_element(sections, [](elf_section_header const & a, elf_section_header const & b) { return a.virtual_address < b.virtual_address; }); auto const elf_section_with_highest_virtual_address = - std::ranges::max_element(container, [](elf_section_header const & a, elf_section_header const & b) { + std::ranges::max_element(sections, [](elf_section_header const & a, elf_section_header const & b) { auto a_virtual_address_end = a.virtual_address + a.section_size; auto b_virtual_address_end = b.virtual_address + b.section_size; return a_virtual_address_end < b_virtual_address_end; }); - auto const symbol_table_section_count = std::ranges::count_if(container, [](elf_section_header const & section) { + auto const symbol_table_section_count = std::ranges::count_if(sections, [](elf_section_header const & section) { return section.type == elf_section_type::DYNAMIC_SYMBOL_TABLE || section.type == elf_section_type::SYMBOL_TABLE; }); auto const dynamic_section_count = std::ranges::count_if( - container, [](elf_section_header const & section) { return section.type == elf_section_type::DYNAMIC; }); + sections, [](elf_section_header const & section) { return section.type == elf_section_type::DYNAMIC; }); exception_handling::assert( symbol_table_section_count == 1U, @@ -87,6 +86,8 @@ namespace teachos::arch::memory::multiboot auto const highest_elf_section = *elf_section_with_highest_virtual_address; kernel_end = highest_elf_section.virtual_address + highest_elf_section.section_size; + + return sections; } } // namespace @@ -94,12 +95,10 @@ namespace teachos::arch::memory::multiboot { memory_information mem_info{UINT64_MAX, 0U, - elf_section_header_container::iterator{}, - elf_section_header_container::iterator{}, + elf_section_header_container{}, boot::multiboot_information_pointer, 0U, - memory_area_container::iterator{}, - memory_area_container::iterator{}}; + memory_area_container{}}; auto const multiboot_information_pointer = reinterpret_cast(boot::multiboot_information_pointer); auto const multiboot_tag = &multiboot_information_pointer->tags; @@ -111,13 +110,12 @@ namespace teachos::arch::memory::multiboot { case tag_type::ELF_SECTIONS: { auto const symbol = reinterpret_cast(tag); - process_elf_sections(symbol, mem_info.kernel_start, mem_info.kernel_end, mem_info.begin_kernel, - mem_info.end_kernel); + mem_info.sections = process_elf_sections(symbol, mem_info.kernel_start, mem_info.kernel_end); break; } case tag_type::MEMORY_MAP: { auto const mminfo = reinterpret_cast(tag); - process_memory_map(mminfo, mem_info.begin_area, mem_info.end_area); + mem_info.areas = process_memory_map(mminfo); break; } default: diff --git a/arch/x86_64/src/memory/paging/inactive_page_table.cpp b/arch/x86_64/src/memory/paging/inactive_page_table.cpp index de0421d..0b141e2 100644 --- a/arch/x86_64/src/memory/paging/inactive_page_table.cpp +++ b/arch/x86_64/src/memory/paging/inactive_page_table.cpp @@ -9,7 +9,6 @@ namespace teachos::arch::memory::paging auto table = temporary_page.map_table_frame(page_table_level_4_frame, active_page_table); table.zero_entries(); table[511].set_entry(page_table_level_4_frame, entry::PRESENT | entry::WRITABLE); - temporary_page.unmap(active_page_table); } } // namespace teachos::arch::memory::paging -- cgit v1.2.3 From 4d76f412b071a05f0aae1d1307f2b58cb2778569 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matteo=20Gm=C3=BCr?= Date: Sat, 2 Nov 2024 14:08:55 +0000 Subject: Attempt to fix crashes --- arch/x86_64/src/memory/allocator/tiny_frame_allocator.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'arch/x86_64/src/memory') diff --git a/arch/x86_64/src/memory/allocator/tiny_frame_allocator.cpp b/arch/x86_64/src/memory/allocator/tiny_frame_allocator.cpp index d07398a..b9fd2c8 100644 --- a/arch/x86_64/src/memory/allocator/tiny_frame_allocator.cpp +++ b/arch/x86_64/src/memory/allocator/tiny_frame_allocator.cpp @@ -11,7 +11,7 @@ namespace teachos::arch::memory::allocator if (frame_option.has_value()) { auto value = frame_option; - frame_option = std::nullopt; + frame_option.reset(); return value; } } @@ -24,7 +24,7 @@ namespace teachos::arch::memory::allocator { if (!frame_option.has_value()) { - frame_option = physical_frame; + frame_option.emplace(physical_frame); return; } } -- cgit v1.2.3 From d4b1b8a85212f07df47217fe13d86956c7eb064f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matteo=20Gm=C3=BCr?= Date: Sun, 3 Nov 2024 10:47:33 +0000 Subject: Use passed allocator in inactive page instead of tiny. --- arch/x86_64/src/memory/paging/inactive_page_table.cpp | 2 +- arch/x86_64/src/memory/paging/temporary_page.cpp | 7 +++++-- 2 files changed, 6 insertions(+), 3 deletions(-) (limited to 'arch/x86_64/src/memory') diff --git a/arch/x86_64/src/memory/paging/inactive_page_table.cpp b/arch/x86_64/src/memory/paging/inactive_page_table.cpp index 0b141e2..f6ecb8b 100644 --- a/arch/x86_64/src/memory/paging/inactive_page_table.cpp +++ b/arch/x86_64/src/memory/paging/inactive_page_table.cpp @@ -9,6 +9,6 @@ namespace teachos::arch::memory::paging auto table = temporary_page.map_table_frame(page_table_level_4_frame, active_page_table); table.zero_entries(); table[511].set_entry(page_table_level_4_frame, entry::PRESENT | entry::WRITABLE); - temporary_page.unmap(active_page_table); + temporary_page.unmap_page(active_page_table); } } // namespace teachos::arch::memory::paging diff --git a/arch/x86_64/src/memory/paging/temporary_page.cpp b/arch/x86_64/src/memory/paging/temporary_page.cpp index 180b4a8..7b065ab 100644 --- a/arch/x86_64/src/memory/paging/temporary_page.cpp +++ b/arch/x86_64/src/memory/paging/temporary_page.cpp @@ -14,7 +14,10 @@ namespace teachos::arch::memory::paging return page.start_address(); } - auto temporary_page::unmap(active_page_table & active_table) -> void { active_table.unmap_page(allocator, page); } + auto temporary_page::unmap_page(active_page_table & active_table) -> void + { + active_table.unmap_page(allocator, page); + } auto temporary_page::map_table_frame(allocator::physical_frame frame, active_page_table & active_table) -> page_table_handle @@ -33,6 +36,6 @@ namespace teachos::arch::memory::paging handle.zero_entries(); handle[511].set_entry(frame.value(), entry::PRESENT | entry::WRITABLE); - unmap(active_table); + unmap_page(active_table); } } // namespace teachos::arch::memory::paging -- cgit v1.2.3 From 9292814545ab5df5aa69d4f75a6d9230f3e03f5b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matteo=20Gm=C3=BCr?= Date: Sun, 3 Nov 2024 11:03:34 +0000 Subject: Move possible implementation into cpp --- .../x86_64/src/memory/allocator/tiny_frame_allocator.cpp | 16 ++++++++++++++++ arch/x86_64/src/memory/paging/temporary_page.cpp | 16 ++++++++-------- 2 files changed, 24 insertions(+), 8 deletions(-) (limited to 'arch/x86_64/src/memory') diff --git a/arch/x86_64/src/memory/allocator/tiny_frame_allocator.cpp b/arch/x86_64/src/memory/allocator/tiny_frame_allocator.cpp index b9fd2c8..d37864e 100644 --- a/arch/x86_64/src/memory/allocator/tiny_frame_allocator.cpp +++ b/arch/x86_64/src/memory/allocator/tiny_frame_allocator.cpp @@ -4,6 +4,22 @@ namespace teachos::arch::memory::allocator { + tiny_frame_allocator::tiny_frame_allocator(area_frame_allocator & allocator) + : frames{} + { + // Has to be done this way, because constructing the constructor with the data from allocator.allocate_frames(), + // does not work because it would set the value correctly but because we pass it as an std::optional it would not + // set the engaged flag. Meaning the has_value() method would still return false. + for (auto & frame : frames) + { + auto allocated = allocator.allocate_frame(); + if (allocated.has_value()) + { + frame.emplace(allocated.value()); + } + } + } + auto tiny_frame_allocator::allocate_frame() -> std::optional { for (auto & frame_option : frames) diff --git a/arch/x86_64/src/memory/paging/temporary_page.cpp b/arch/x86_64/src/memory/paging/temporary_page.cpp index 7b065ab..5f760a5 100644 --- a/arch/x86_64/src/memory/paging/temporary_page.cpp +++ b/arch/x86_64/src/memory/paging/temporary_page.cpp @@ -4,6 +4,14 @@ namespace teachos::arch::memory::paging { + auto temporary_page::map_table_frame(allocator::physical_frame frame, + active_page_table & active_table) -> page_table_handle + { + page_table_handle handle{reinterpret_cast(map_to_frame(frame, active_table)), + page_table_handle::LEVEL1}; + return handle; + } + auto temporary_page::map_to_frame(allocator::physical_frame frame, active_page_table & active_table) -> virtual_address { @@ -19,14 +27,6 @@ namespace teachos::arch::memory::paging active_table.unmap_page(allocator, page); } - auto temporary_page::map_table_frame(allocator::physical_frame frame, - active_page_table & active_table) -> page_table_handle - { - page_table_handle handle{reinterpret_cast(map_to_frame(frame, active_table)), - page_table_handle::LEVEL1}; - return handle; - } - auto temporary_page::zero_entries(active_page_table & active_table) -> void { auto frame = allocator.allocate_frame(); -- cgit v1.2.3 From be546b091795e740e9dd4c35fce6453fafe0319c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matteo=20Gm=C3=BCr?= Date: Sun, 3 Nov 2024 11:56:46 +0000 Subject: Make member variables private again. --- arch/x86_64/src/memory/paging/active_page_table.cpp | 2 ++ 1 file changed, 2 insertions(+) (limited to 'arch/x86_64/src/memory') 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 844ae37..033a363 100644 --- a/arch/x86_64/src/memory/paging/active_page_table.cpp +++ b/arch/x86_64/src/memory/paging/active_page_table.cpp @@ -10,6 +10,8 @@ namespace teachos::arch::memory::paging return active_page; } + auto active_page_table::operator[](std::size_t index) -> entry & { return active_handle[index]; } + auto active_page_table::translate_address(virtual_address address) -> std::optional { auto const offset = address % allocator::PAGE_FRAME_SIZE; -- cgit v1.2.3 From 67be3c58bef94fece14d4e3a79f3559649e9a74c Mon Sep 17 00:00:00 2001 From: Fabian Imhof Date: Sun, 3 Nov 2024 12:12:41 +0000 Subject: rename member and use correct address --- .../src/memory/multiboot/elf_symbols_section.cpp | 2 +- arch/x86_64/src/memory/multiboot/reader.cpp | 20 ++++++++++---------- 2 files changed, 11 insertions(+), 11 deletions(-) (limited to 'arch/x86_64/src/memory') diff --git a/arch/x86_64/src/memory/multiboot/elf_symbols_section.cpp b/arch/x86_64/src/memory/multiboot/elf_symbols_section.cpp index 953a57d..f5d126b 100644 --- a/arch/x86_64/src/memory/multiboot/elf_symbols_section.cpp +++ b/arch/x86_64/src/memory/multiboot/elf_symbols_section.cpp @@ -7,7 +7,7 @@ namespace teachos::arch::memory::multiboot auto elf_section_header::is_null() const -> bool { return name_table_index == 0U && type == elf_section_type::INACTIVE && flags == elf_section_flags(0U) && - virtual_address == 0U && file_offset == 0U && additional_information == 0U && address_alignment == 0U && + physical_address == 0U && file_offset == 0U && additional_information == 0U && address_alignment == 0U && fixed_table_entry_size == 0U; } } // namespace teachos::arch::memory::multiboot diff --git a/arch/x86_64/src/memory/multiboot/reader.cpp b/arch/x86_64/src/memory/multiboot/reader.cpp index 7bdf48f..4576085 100644 --- a/arch/x86_64/src/memory/multiboot/reader.cpp +++ b/arch/x86_64/src/memory/multiboot/reader.cpp @@ -56,16 +56,16 @@ namespace teachos::arch::memory::multiboot elf_section_header_container sections{begin, end}; - auto const elf_section_with_lowest_virtual_address = + auto const elf_section_with_lowest_physical_address = std::ranges::min_element(sections, [](elf_section_header const & a, elf_section_header const & b) { - return a.virtual_address < b.virtual_address; + return a.physical_address < b.physical_address; }); - auto const elf_section_with_highest_virtual_address = + auto const elf_section_with_highest_physical_address = std::ranges::max_element(sections, [](elf_section_header const & a, elf_section_header const & b) { - auto a_virtual_address_end = a.virtual_address + a.section_size; - auto b_virtual_address_end = b.virtual_address + b.section_size; - return a_virtual_address_end < b_virtual_address_end; + auto a_physical_address_end = a.physical_address + a.section_size; + auto b_physical_address_end = b.physical_address + b.section_size; + return a_physical_address_end < b_physical_address_end; }); auto const symbol_table_section_count = std::ranges::count_if(sections, [](elf_section_header const & section) { @@ -81,11 +81,11 @@ namespace teachos::arch::memory::multiboot dynamic_section_count <= 1U, "[Multiboot Reader] ELF Specifications allows only (1) or less dynamic sections, but got more"); - auto const lowest_elf_section = *elf_section_with_lowest_virtual_address; - kernel_start = lowest_elf_section.virtual_address; + auto const lowest_elf_section = *elf_section_with_lowest_physical_address; + kernel_start = lowest_elf_section.physical_address; - auto const highest_elf_section = *elf_section_with_highest_virtual_address; - kernel_end = highest_elf_section.virtual_address + highest_elf_section.section_size; + auto const highest_elf_section = *elf_section_with_highest_physical_address; + kernel_end = highest_elf_section.physical_address + highest_elf_section.section_size; return sections; } -- cgit v1.2.3 From 380bc85d1a4fdbef102132c726ef2ac7ac6355da Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matteo=20Gm=C3=BCr?= Date: Sun, 3 Nov 2024 12:20:21 +0000 Subject: Make constructor constexpr for basic page and frame types --- arch/x86_64/src/memory/allocator/physical_frame.cpp | 6 ------ arch/x86_64/src/memory/paging/virtual_page.cpp | 6 ------ 2 files changed, 12 deletions(-) (limited to 'arch/x86_64/src/memory') diff --git a/arch/x86_64/src/memory/allocator/physical_frame.cpp b/arch/x86_64/src/memory/allocator/physical_frame.cpp index 9307602..227745a 100644 --- a/arch/x86_64/src/memory/allocator/physical_frame.cpp +++ b/arch/x86_64/src/memory/allocator/physical_frame.cpp @@ -2,12 +2,6 @@ namespace teachos::arch::memory::allocator { - physical_frame::physical_frame(std::size_t frame_number) - : frame_number(frame_number) - { - // Nothing to do - } - auto physical_frame::containing_address(physical_address address) -> physical_frame { return physical_frame{address / PAGE_FRAME_SIZE}; diff --git a/arch/x86_64/src/memory/paging/virtual_page.cpp b/arch/x86_64/src/memory/paging/virtual_page.cpp index c0ec88d..f798709 100644 --- a/arch/x86_64/src/memory/paging/virtual_page.cpp +++ b/arch/x86_64/src/memory/paging/virtual_page.cpp @@ -4,12 +4,6 @@ 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(virtual_address address) -> virtual_page { exception_handling::assert(address < 0x00008000'00000000 || address >= 0xffff8000'00000000, -- cgit v1.2.3 From db70018fc76800dd56b4421be797bffd00d7619d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matteo=20Gm=C3=BCr?= Date: Sun, 3 Nov 2024 13:52:22 +0000 Subject: Convert elf section flags to entry flags --- arch/x86_64/src/memory/paging/page_entry.cpp | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) (limited to 'arch/x86_64/src/memory') diff --git a/arch/x86_64/src/memory/paging/page_entry.cpp b/arch/x86_64/src/memory/paging/page_entry.cpp index 23c700f..5c4bc67 100644 --- a/arch/x86_64/src/memory/paging/page_entry.cpp +++ b/arch/x86_64/src/memory/paging/page_entry.cpp @@ -7,7 +7,8 @@ namespace teachos::arch::memory::paging namespace { std::size_t constexpr PHYSICAL_ADDRESS_MASK = 0x000fffff'fffff000; - } + std::size_t constexpr ENTRY_FLAGS_MASK = 0xfff00000'00000fff; + } // namespace entry::entry(uint64_t flags) : flags(flags) @@ -15,6 +16,23 @@ namespace teachos::arch::memory::paging // Nothing to do. } + entry::entry(multiboot::elf_section_flags elf_flags) + { + if (elf_flags.contains_flags(multiboot::elf_section_flags::OCCUPIES_MEMORY)) + { + flags = flags.to_ulong() | entry::PRESENT; + } + if (elf_flags.contains_flags(multiboot::elf_section_flags::WRITABLE)) + { + flags = flags.to_ulong() | entry::WRITABLE; + } + if (!elf_flags.contains_flags(multiboot::elf_section_flags::EXECUTABLE_CODE)) + { + // TODO: Ensure to set the NXE bit, if we don't using this entry flag causes crashes + // flags = flags.to_ulong() | entry::EXECUTING_CODE_FORBIDDEN; + } + } + auto entry::is_unused() const -> bool { return flags == 0U; } auto entry::set_unused() -> void { flags = 0U; } @@ -37,4 +55,6 @@ namespace teachos::arch::memory::paging "[Paging Entry] Start address is not aligned with page"); flags = frame.start_address() | additional_flags.to_ulong(); } + + auto entry::get_flags() -> std::bitset<64U> { return flags.to_ulong() & ENTRY_FLAGS_MASK; } } // namespace teachos::arch::memory::paging -- cgit v1.2.3 From e20b9a2acd77ab6df00ee4a9390aaef8c6941dc6 Mon Sep 17 00:00:00 2001 From: Fabian Imhof Date: Sun, 3 Nov 2024 13:55:59 +0000 Subject: remove elf flags mask --- arch/x86_64/src/memory/paging/page_entry.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'arch/x86_64/src/memory') diff --git a/arch/x86_64/src/memory/paging/page_entry.cpp b/arch/x86_64/src/memory/paging/page_entry.cpp index 5c4bc67..f13e645 100644 --- a/arch/x86_64/src/memory/paging/page_entry.cpp +++ b/arch/x86_64/src/memory/paging/page_entry.cpp @@ -7,7 +7,6 @@ namespace teachos::arch::memory::paging namespace { std::size_t constexpr PHYSICAL_ADDRESS_MASK = 0x000fffff'fffff000; - std::size_t constexpr ENTRY_FLAGS_MASK = 0xfff00000'00000fff; } // namespace entry::entry(uint64_t flags) @@ -56,5 +55,5 @@ namespace teachos::arch::memory::paging flags = frame.start_address() | additional_flags.to_ulong(); } - auto entry::get_flags() -> std::bitset<64U> { return flags.to_ulong() & ENTRY_FLAGS_MASK; } + auto entry::get_flags() -> std::bitset<64U> { return flags.to_ulong() & ~PHYSICAL_ADDRESS_MASK; } } // namespace teachos::arch::memory::paging -- cgit v1.2.3 From 162bea11c7a4f1854cde53920b4c14b4eadf539d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matteo=20Gm=C3=BCr?= Date: Mon, 4 Nov 2024 12:13:44 +0000 Subject: WIP attempt to fix crashes --- .../src/memory/allocator/area_frame_allocator.cpp | 12 +-- .../x86_64/src/memory/allocator/physical_frame.cpp | 113 +++------------------ arch/x86_64/src/memory/multiboot/reader.cpp | 25 +++-- 3 files changed, 32 insertions(+), 118 deletions(-) (limited to 'arch/x86_64/src/memory') diff --git a/arch/x86_64/src/memory/allocator/area_frame_allocator.cpp b/arch/x86_64/src/memory/allocator/area_frame_allocator.cpp index da4a919..42aff68 100644 --- a/arch/x86_64/src/memory/allocator/area_frame_allocator.cpp +++ b/arch/x86_64/src/memory/allocator/area_frame_allocator.cpp @@ -23,19 +23,17 @@ namespace teachos::arch::memory::allocator auto area_frame_allocator::choose_next_area() -> void { current_area = std::nullopt; - auto next_area_with_free_frames = memory_areas | std::views::filter([this](multiboot::memory_area const & area) { - auto address = area.base_address + area.area_length - 1; + auto next_area_with_free_frames = memory_areas | std::views::filter([this](auto const & area) { + auto address = area->base_address + area->area_length - 1; return physical_frame::containing_address(address) >= next_free_frame; }); - auto const lowest_area_with_free_frames = - std::ranges::min_element(next_area_with_free_frames, [](multiboot::memory_area a, multiboot::memory_area b) { - return a.base_address < b.base_address; - }); + auto const lowest_area_with_free_frames = std::ranges::min_element( + next_area_with_free_frames, [](auto const & a, auto const & b) { return a->base_address < b->base_address; }); if (lowest_area_with_free_frames != next_area_with_free_frames.end()) { - current_area = *lowest_area_with_free_frames; + current_area = **lowest_area_with_free_frames; // Update the `next_free_frame` according to the new memory area auto const start_frame = physical_frame::containing_address(current_area.value().base_address); if (next_free_frame < start_frame) diff --git a/arch/x86_64/src/memory/allocator/physical_frame.cpp b/arch/x86_64/src/memory/allocator/physical_frame.cpp index 227745a..63d84ec 100644 --- a/arch/x86_64/src/memory/allocator/physical_frame.cpp +++ b/arch/x86_64/src/memory/allocator/physical_frame.cpp @@ -9,126 +9,43 @@ namespace teachos::arch::memory::allocator auto physical_frame::start_address() const -> physical_address { return frame_number * PAGE_FRAME_SIZE; } - /** - * @brief Constructor. - * - * @param value Underlying value the iterator should point too - */ - physical_frame_iterator::physical_frame_iterator(physical_frame_iterator::value_type value) - : value(value) + auto physical_frame::operator++(int) -> physical_frame { - // Nothing to do - } - - /** - * @brief Dereferences the initally given pointer to its value. - * - * @return Reference to the value. - */ - auto physical_frame_iterator::operator*() -> physical_frame_iterator::value_type & { return value; } - - /** - * @brief Get underlying value, which is the intially passed pointer. - * - * @return Underlying value passed intially. - */ - auto physical_frame_iterator::operator->() -> physical_frame_iterator::value_type * { return &value; } - - /** - * @brief Post increment operator. Returns a copy of the value. - * - * @return Copy of the incremented underlying address. - */ - auto physical_frame_iterator::operator++(int) -> physical_frame_iterator - { - physical_frame_iterator const old_value = *this; - ++value.frame_number; + physical_frame const old_value = *this; + ++frame_number; return old_value; } - /** - * @brief Pre increment operator. Returns a reference to the changed value. - * - * @return Reference to the incremented underlying address. - */ - auto physical_frame_iterator::operator++() -> physical_frame_iterator & + auto physical_frame::operator++() -> physical_frame & { - ++value.frame_number; + ++frame_number; return *this; } - /** - * @brief Addition assignment operator. Returns a reference to the changed value. - * - * @param operand Value we want to add to the underlying address. - * @return Reference to the changed underlying address. - */ - auto - physical_frame_iterator::operator+=(physical_frame_iterator::difference_type operand) -> physical_frame_iterator & + auto physical_frame::operator+=(std::size_t operand) -> physical_frame & { - value.frame_number += operand; + frame_number += operand; return *this; } - /** - * @brief Subtraction assignment operator. Returns a reference to the changed value. - * - * @param operand Value we want to subtract from the underlying address. - * @return Reference to the changed underlying address. - */ - auto - physical_frame_iterator::operator-=(physical_frame_iterator::difference_type operand) -> physical_frame_iterator & + auto physical_frame::operator-=(std::size_t operand) -> physical_frame & { - value.frame_number -= operand; + frame_number -= operand; return *this; } - /** - * @brief Addition operator. Returns the changed value. - * - * @param operand Value we want to add to a copy of the underlying address. - * @return Copy of underlying address incremented by the given value. - */ - auto - physical_frame_iterator::operator+(physical_frame_iterator::difference_type operand) const -> physical_frame_iterator - { - return physical_frame_iterator{physical_frame_iterator::value_type{value.frame_number + operand}}; - } - - /** - * @brief Subtraction operator. Returns the changed value. - * - * @param operand Value we want to subtrcat from a copy of the underlying address. - * @return Copy of underlying address decremented by the given value. - */ - auto - physical_frame_iterator::operator-(physical_frame_iterator::difference_type operand) const -> physical_frame_iterator + auto physical_frame::operator+(std::size_t operand) const -> physical_frame { - return physical_frame_iterator{physical_frame_iterator::value_type{value.frame_number - operand}}; + return physical_frame{frame_number + operand}; } - /** - * @brief Subtraction operator. Returns the size difference between two iterators. - * - * @param other Other iterator we want to substract the underlying address with ours. - * @return Size difference between the underlying address of this instance and the given iterator. - */ - auto physical_frame_iterator::operator-(const physical_frame_iterator & other) const - -> physical_frame_iterator::difference_type + auto physical_frame::operator-(std::size_t operand) const -> physical_frame { - return value.frame_number - other.value.frame_number; + return physical_frame{frame_number - operand}; } - /** - * @brief Index operator overload. Returns a reference to the value at the given index. Simply returns the - * dereferenced underlying pointer incremented by the given index. - * - * @param index Index we want to access and get the value from. - * @return Reference to the value at the given index. - */ - auto physical_frame_iterator::operator[](physical_frame_iterator::difference_type index) const - -> physical_frame_iterator::value_type + auto physical_frame::operator-(const physical_frame & other) const -> std::size_t { - return physical_frame_iterator::value_type{value.frame_number + index}; + return frame_number - other.frame_number; } } // namespace teachos::arch::memory::allocator diff --git a/arch/x86_64/src/memory/multiboot/reader.cpp b/arch/x86_64/src/memory/multiboot/reader.cpp index 4576085..178cc45 100644 --- a/arch/x86_64/src/memory/multiboot/reader.cpp +++ b/arch/x86_64/src/memory/multiboot/reader.cpp @@ -51,28 +51,27 @@ namespace teachos::arch::memory::multiboot auto const begin = elf_section_header_container::iterator{reinterpret_cast(&symbol->end)}; auto const end = begin + symbol->number_of_sections; - exception_handling::assert(begin->is_null(), + exception_handling::assert((*begin)->is_null(), "[Multiboot Reader] Elf symbols section not starting with SHT_NULL section"); elf_section_header_container sections{begin, end}; - auto const elf_section_with_lowest_physical_address = - std::ranges::min_element(sections, [](elf_section_header const & a, elf_section_header const & b) { - return a.physical_address < b.physical_address; - }); + auto const elf_section_with_lowest_physical_address = std::ranges::min_element( + sections, [](auto const & a, auto const & b) { return a->physical_address < b->physical_address; }); auto const elf_section_with_highest_physical_address = - std::ranges::max_element(sections, [](elf_section_header const & a, elf_section_header const & b) { - auto a_physical_address_end = a.physical_address + a.section_size; - auto b_physical_address_end = b.physical_address + b.section_size; + std::ranges::max_element(sections, [](auto const & a, auto const & b) { + auto a_physical_address_end = a->physical_address + a->section_size; + auto b_physical_address_end = b->physical_address + b->section_size; return a_physical_address_end < b_physical_address_end; }); - auto const symbol_table_section_count = std::ranges::count_if(sections, [](elf_section_header const & section) { - return section.type == elf_section_type::DYNAMIC_SYMBOL_TABLE || section.type == elf_section_type::SYMBOL_TABLE; + auto const symbol_table_section_count = std::ranges::count_if(sections, [](auto const & section) { + return section->type == elf_section_type::DYNAMIC_SYMBOL_TABLE || + section->type == elf_section_type::SYMBOL_TABLE; }); auto const dynamic_section_count = std::ranges::count_if( - sections, [](elf_section_header const & section) { return section.type == elf_section_type::DYNAMIC; }); + sections, [](auto const & section) { return section->type == elf_section_type::DYNAMIC; }); exception_handling::assert( symbol_table_section_count == 1U, @@ -82,10 +81,10 @@ namespace teachos::arch::memory::multiboot "[Multiboot Reader] ELF Specifications allows only (1) or less dynamic sections, but got more"); auto const lowest_elf_section = *elf_section_with_lowest_physical_address; - kernel_start = lowest_elf_section.physical_address; + kernel_start = lowest_elf_section->physical_address; auto const highest_elf_section = *elf_section_with_highest_physical_address; - kernel_end = highest_elf_section.physical_address + highest_elf_section.section_size; + kernel_end = highest_elf_section->physical_address + highest_elf_section->section_size; return sections; } -- cgit v1.2.3 From 30466aeb3da181c21bd451f32c1ff97e53a55dbc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matteo=20Gm=C3=BCr?= Date: Mon, 4 Nov 2024 13:29:03 +0000 Subject: Use more concepts and seperate iterator implementations --- .../src/memory/allocator/area_frame_allocator.cpp | 6 ++--- .../x86_64/src/memory/allocator/physical_frame.cpp | 27 ---------------------- arch/x86_64/src/memory/multiboot/reader.cpp | 17 +++++++------- 3 files changed, 11 insertions(+), 39 deletions(-) (limited to 'arch/x86_64/src/memory') diff --git a/arch/x86_64/src/memory/allocator/area_frame_allocator.cpp b/arch/x86_64/src/memory/allocator/area_frame_allocator.cpp index 42aff68..3bc9676 100644 --- a/arch/x86_64/src/memory/allocator/area_frame_allocator.cpp +++ b/arch/x86_64/src/memory/allocator/area_frame_allocator.cpp @@ -24,16 +24,16 @@ namespace teachos::arch::memory::allocator { current_area = std::nullopt; auto next_area_with_free_frames = memory_areas | std::views::filter([this](auto const & area) { - auto address = area->base_address + area->area_length - 1; + auto address = area.base_address + area.area_length - 1; return physical_frame::containing_address(address) >= next_free_frame; }); auto const lowest_area_with_free_frames = std::ranges::min_element( - next_area_with_free_frames, [](auto const & a, auto const & b) { return a->base_address < b->base_address; }); + next_area_with_free_frames, [](auto const & a, auto const & b) { return a.base_address < b.base_address; }); if (lowest_area_with_free_frames != next_area_with_free_frames.end()) { - current_area = **lowest_area_with_free_frames; + current_area = *lowest_area_with_free_frames; // Update the `next_free_frame` according to the new memory area auto const start_frame = physical_frame::containing_address(current_area.value().base_address); if (next_free_frame < start_frame) diff --git a/arch/x86_64/src/memory/allocator/physical_frame.cpp b/arch/x86_64/src/memory/allocator/physical_frame.cpp index 63d84ec..ec387a1 100644 --- a/arch/x86_64/src/memory/allocator/physical_frame.cpp +++ b/arch/x86_64/src/memory/allocator/physical_frame.cpp @@ -21,31 +21,4 @@ namespace teachos::arch::memory::allocator ++frame_number; return *this; } - - auto physical_frame::operator+=(std::size_t operand) -> physical_frame & - { - frame_number += operand; - return *this; - } - - auto physical_frame::operator-=(std::size_t operand) -> physical_frame & - { - frame_number -= operand; - return *this; - } - - auto physical_frame::operator+(std::size_t operand) const -> physical_frame - { - return physical_frame{frame_number + operand}; - } - - auto physical_frame::operator-(std::size_t operand) const -> physical_frame - { - return physical_frame{frame_number - operand}; - } - - auto physical_frame::operator-(const physical_frame & other) const -> std::size_t - { - return frame_number - other.frame_number; - } } // namespace teachos::arch::memory::allocator diff --git a/arch/x86_64/src/memory/multiboot/reader.cpp b/arch/x86_64/src/memory/multiboot/reader.cpp index 178cc45..1dd18ff 100644 --- a/arch/x86_64/src/memory/multiboot/reader.cpp +++ b/arch/x86_64/src/memory/multiboot/reader.cpp @@ -51,27 +51,26 @@ namespace teachos::arch::memory::multiboot auto const begin = elf_section_header_container::iterator{reinterpret_cast(&symbol->end)}; auto const end = begin + symbol->number_of_sections; - exception_handling::assert((*begin)->is_null(), + exception_handling::assert(begin->is_null(), "[Multiboot Reader] Elf symbols section not starting with SHT_NULL section"); elf_section_header_container sections{begin, end}; auto const elf_section_with_lowest_physical_address = std::ranges::min_element( - sections, [](auto const & a, auto const & b) { return a->physical_address < b->physical_address; }); + sections, [](auto const & a, auto const & b) { return a.physical_address < b.physical_address; }); auto const elf_section_with_highest_physical_address = std::ranges::max_element(sections, [](auto const & a, auto const & b) { - auto a_physical_address_end = a->physical_address + a->section_size; - auto b_physical_address_end = b->physical_address + b->section_size; + auto a_physical_address_end = a.physical_address + a.section_size; + auto b_physical_address_end = b.physical_address + b.section_size; return a_physical_address_end < b_physical_address_end; }); auto const symbol_table_section_count = std::ranges::count_if(sections, [](auto const & section) { - return section->type == elf_section_type::DYNAMIC_SYMBOL_TABLE || - section->type == elf_section_type::SYMBOL_TABLE; + return section.type == elf_section_type::DYNAMIC_SYMBOL_TABLE || section.type == elf_section_type::SYMBOL_TABLE; }); auto const dynamic_section_count = std::ranges::count_if( - sections, [](auto const & section) { return section->type == elf_section_type::DYNAMIC; }); + sections, [](auto const & section) { return section.type == elf_section_type::DYNAMIC; }); exception_handling::assert( symbol_table_section_count == 1U, @@ -81,10 +80,10 @@ namespace teachos::arch::memory::multiboot "[Multiboot Reader] ELF Specifications allows only (1) or less dynamic sections, but got more"); auto const lowest_elf_section = *elf_section_with_lowest_physical_address; - kernel_start = lowest_elf_section->physical_address; + kernel_start = lowest_elf_section.physical_address; auto const highest_elf_section = *elf_section_with_highest_physical_address; - kernel_end = highest_elf_section->physical_address + highest_elf_section->section_size; + kernel_end = highest_elf_section.physical_address + highest_elf_section.section_size; return sections; } -- cgit v1.2.3 From c887e22cd7827ae53fd3eab6f5af41969cdd616c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matteo=20Gm=C3=BCr?= Date: Mon, 4 Nov 2024 13:55:22 +0000 Subject: Use auto where possible --- arch/x86_64/src/memory/paging/page_table.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch/x86_64/src/memory') diff --git a/arch/x86_64/src/memory/paging/page_table.cpp b/arch/x86_64/src/memory/paging/page_table.cpp index 3c9942a..a39c235 100644 --- a/arch/x86_64/src/memory/paging/page_table.cpp +++ b/arch/x86_64/src/memory/paging/page_table.cpp @@ -46,7 +46,7 @@ namespace teachos::arch::memory::paging auto page_table::zero_entries() -> void { - std::ranges::for_each(entries, [](entry & entry) { entry.set_unused(); }); + std::ranges::for_each(entries, [](auto & entry) { entry.set_unused(); }); } auto page_table::is_empty() const -> bool -- cgit v1.2.3 From dc80a11864444cae275e9e7be9ae120a92433034 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matteo=20Gm=C3=BCr?= Date: Tue, 5 Nov 2024 09:58:05 +0000 Subject: Move tlb into seperate subfolder and create cr3 header for reading and writing. --- arch/x86_64/src/memory/cpu/cr3.cpp | 23 ++++++++++++++++++++++ arch/x86_64/src/memory/cpu/tlb.cpp | 8 ++++++++ .../x86_64/src/memory/paging/active_page_table.cpp | 2 +- arch/x86_64/src/memory/paging/tlb.cpp | 7 ------- 4 files changed, 32 insertions(+), 8 deletions(-) create mode 100644 arch/x86_64/src/memory/cpu/cr3.cpp create mode 100644 arch/x86_64/src/memory/cpu/tlb.cpp delete mode 100644 arch/x86_64/src/memory/paging/tlb.cpp (limited to 'arch/x86_64/src/memory') diff --git a/arch/x86_64/src/memory/cpu/cr3.cpp b/arch/x86_64/src/memory/cpu/cr3.cpp new file mode 100644 index 0000000..7e48d40 --- /dev/null +++ b/arch/x86_64/src/memory/cpu/cr3.cpp @@ -0,0 +1,23 @@ +#include "arch/memory/cpu/cr3.hpp" + +#include "arch/exception_handling/assert.hpp" + +namespace teachos::arch::memory::cpu +{ + auto read_cr3_register() -> allocator::physical_address + { + allocator::physical_address cr3; + asm volatile("movq %%cr3, %[output]" : [output] "=r"(cr3) : /* no input into call */ : "memory"); + return cr3; + } + + auto write_cr3_register(allocator::physical_address new_p4_table_address) -> void + { + exception_handling::assert(new_p4_table_address % allocator::PAGE_FRAME_SIZE == 0U, + "[CR3] Physical address to be written into register must be page aligned"); + asm volatile("movq %[input], %%cr3" + : /* no output from call */ + : [input] "r"(new_p4_table_address) + : "memory"); + } +} // namespace teachos::arch::memory::cpu diff --git a/arch/x86_64/src/memory/cpu/tlb.cpp b/arch/x86_64/src/memory/cpu/tlb.cpp new file mode 100644 index 0000000..bac46b7 --- /dev/null +++ b/arch/x86_64/src/memory/cpu/tlb.cpp @@ -0,0 +1,8 @@ +#include "arch/memory/cpu/tlb.hpp" + +namespace teachos::arch::memory::cpu +{ + auto tlb_flush(paging::virtual_address address) -> void { asm volatile("invlpg (%0)" ::"r"(address) : "memory"); } + + auto tlb_flush_all() -> void { tlb_flush(PAGE_TABLE_LEVEL_4_ADDRESS); } +} // namespace teachos::arch::memory::cpu 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 033a363..3f62419 100644 --- a/arch/x86_64/src/memory/paging/active_page_table.cpp +++ b/arch/x86_64/src/memory/paging/active_page_table.cpp @@ -4,7 +4,7 @@ namespace teachos::arch::memory::paging { auto active_page_table::create_or_get() -> active_page_table & { - static page_table_handle active_handle{reinterpret_cast(PAGE_TABLE_LEVEL_4_ADDRESS), + static page_table_handle active_handle{reinterpret_cast(cpu::PAGE_TABLE_LEVEL_4_ADDRESS), page_table_handle::LEVEL4}; static active_page_table active_page{active_handle}; return active_page; diff --git a/arch/x86_64/src/memory/paging/tlb.cpp b/arch/x86_64/src/memory/paging/tlb.cpp deleted file mode 100644 index c1160dc..0000000 --- a/arch/x86_64/src/memory/paging/tlb.cpp +++ /dev/null @@ -1,7 +0,0 @@ -#include "arch/memory/paging/tlb.hpp" - -namespace teachos::arch::memory::paging -{ - auto tlb_flush(virtual_address address) -> void { asm volatile("invlpg (%0)" ::"r"(address) : "memory"); } - auto tlb_flush_all() -> void { tlb_flush(PAGE_TABLE_LEVEL_4_ADDRESS); } -} // namespace teachos::arch::memory::paging -- cgit v1.2.3 From d18cf4a3e4abdea80992b8bba3d1ca50ae215253 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matteo=20Gm=C3=BCr?= Date: Sat, 9 Nov 2024 14:51:10 +0000 Subject: Add switch method to kernel --- arch/x86_64/src/memory/paging/inactive_page_table.cpp | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'arch/x86_64/src/memory') diff --git a/arch/x86_64/src/memory/paging/inactive_page_table.cpp b/arch/x86_64/src/memory/paging/inactive_page_table.cpp index f6ecb8b..4e0610e 100644 --- a/arch/x86_64/src/memory/paging/inactive_page_table.cpp +++ b/arch/x86_64/src/memory/paging/inactive_page_table.cpp @@ -2,8 +2,14 @@ namespace teachos::arch::memory::paging { + inactive_page_table::inactive_page_table(allocator::physical_frame frame) + : page_table_level_4_frame{frame} + { + // Nothing to do + } + inactive_page_table::inactive_page_table(allocator::physical_frame frame, active_page_table & active_page_table, - temporary_page temporary_page) + temporary_page & temporary_page) : page_table_level_4_frame{frame} { auto table = temporary_page.map_table_frame(page_table_level_4_frame, active_page_table); -- cgit v1.2.3 From 022e2555c233c13f990026ea86d164f56a9cd7be Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matteo=20Gm=C3=BCr?= Date: Sat, 9 Nov 2024 15:25:33 +0000 Subject: Remove unused method --- arch/x86_64/src/memory/paging/temporary_page.cpp | 12 ------------ 1 file changed, 12 deletions(-) (limited to 'arch/x86_64/src/memory') diff --git a/arch/x86_64/src/memory/paging/temporary_page.cpp b/arch/x86_64/src/memory/paging/temporary_page.cpp index 5f760a5..152241d 100644 --- a/arch/x86_64/src/memory/paging/temporary_page.cpp +++ b/arch/x86_64/src/memory/paging/temporary_page.cpp @@ -26,16 +26,4 @@ namespace teachos::arch::memory::paging { active_table.unmap_page(allocator, page); } - - auto temporary_page::zero_entries(active_page_table & active_table) -> void - { - auto frame = allocator.allocate_frame(); - exception_handling::assert(frame.has_value(), "[Temporary Page] Tiny allocator could not allocate a frame"); - - page_table_handle handle = map_table_frame(frame.value(), active_table); - handle.zero_entries(); - handle[511].set_entry(frame.value(), entry::PRESENT | entry::WRITABLE); - - unmap_page(active_table); - } } // namespace teachos::arch::memory::paging -- cgit v1.2.3 From 4c030cbaee174a9f7f42d4f5ca7ddf6debbbe048 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matteo=20Gm=C3=BCr?= Date: Sat, 9 Nov 2024 16:25:11 +0000 Subject: Fix flush all method and move crash. --- arch/x86_64/src/memory/cpu/tlb.cpp | 9 +++++++-- arch/x86_64/src/memory/paging/active_page_table.cpp | 7 ++++++- 2 files changed, 13 insertions(+), 3 deletions(-) (limited to 'arch/x86_64/src/memory') diff --git a/arch/x86_64/src/memory/cpu/tlb.cpp b/arch/x86_64/src/memory/cpu/tlb.cpp index bac46b7..1663e80 100644 --- a/arch/x86_64/src/memory/cpu/tlb.cpp +++ b/arch/x86_64/src/memory/cpu/tlb.cpp @@ -1,8 +1,13 @@ #include "arch/memory/cpu/tlb.hpp" +#include "arch/memory/cpu/cr3.hpp" + namespace teachos::arch::memory::cpu { - auto tlb_flush(paging::virtual_address address) -> void { asm volatile("invlpg (%0)" ::"r"(address) : "memory"); } + auto tlb_flush(paging::virtual_address address) -> void + { + asm volatile("invlpg (%[input])" : /* no output from call */ : [input] "r"(address) : "memory"); + } - auto tlb_flush_all() -> void { tlb_flush(PAGE_TABLE_LEVEL_4_ADDRESS); } + auto tlb_flush_all() -> void { write_cr3_register(read_cr3_register()); } } // namespace teachos::arch::memory::cpu 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 3f62419..0113869 100644 --- a/arch/x86_64/src/memory/paging/active_page_table.cpp +++ b/arch/x86_64/src/memory/paging/active_page_table.cpp @@ -2,9 +2,14 @@ namespace teachos::arch::memory::paging { + namespace + { + paging::virtual_address constexpr PAGE_TABLE_LEVEL_4_ADDRESS = 0xffffffff'fffff000; + } + auto active_page_table::create_or_get() -> active_page_table & { - static page_table_handle active_handle{reinterpret_cast(cpu::PAGE_TABLE_LEVEL_4_ADDRESS), + static page_table_handle active_handle{reinterpret_cast(PAGE_TABLE_LEVEL_4_ADDRESS), page_table_handle::LEVEL4}; static active_page_table active_page{active_handle}; return active_page; -- cgit v1.2.3 From edc11135d83ef1f8fcbc1575a290b31ccbdb7e07 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matteo=20Gm=C3=BCr?= Date: Sun, 10 Nov 2024 09:34:21 +0000 Subject: Identity map memory map and vga text buffer,w hen setting up kernel --- arch/x86_64/src/memory/paging/page_entry.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch/x86_64/src/memory') diff --git a/arch/x86_64/src/memory/paging/page_entry.cpp b/arch/x86_64/src/memory/paging/page_entry.cpp index f13e645..aae5013 100644 --- a/arch/x86_64/src/memory/paging/page_entry.cpp +++ b/arch/x86_64/src/memory/paging/page_entry.cpp @@ -55,5 +55,5 @@ namespace teachos::arch::memory::paging flags = frame.start_address() | additional_flags.to_ulong(); } - auto entry::get_flags() -> std::bitset<64U> { return flags.to_ulong() & ~PHYSICAL_ADDRESS_MASK; } + auto entry::get_flags() const -> std::bitset<64U> { return flags.to_ulong() & ~PHYSICAL_ADDRESS_MASK; } } // namespace teachos::arch::memory::paging -- cgit v1.2.3 From 1275612382c5c9d31ed7b24a2c6d699c14a10081 Mon Sep 17 00:00:00 2001 From: Fabian Imhof Date: Sun, 10 Nov 2024 10:59:22 +0000 Subject: implement model specific register calls --- arch/x86_64/src/memory/cpu/msr.cpp | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) create mode 100644 arch/x86_64/src/memory/cpu/msr.cpp (limited to 'arch/x86_64/src/memory') diff --git a/arch/x86_64/src/memory/cpu/msr.cpp b/arch/x86_64/src/memory/cpu/msr.cpp new file mode 100644 index 0000000..3a917c9 --- /dev/null +++ b/arch/x86_64/src/memory/cpu/msr.cpp @@ -0,0 +1,29 @@ +#include "arch/memory/cpu/msr.hpp" + +namespace teachos::arch::memory::cpu +{ + uint64_t read_msr(uint32_t msr) + { + uint32_t low, high; + asm volatile("rdmsr" : "=a"(low), "=d"(high) : "c"(msr)); + return (static_cast(high) << 32) | low; + } + + void write_msr(uint32_t msr, uint64_t value) + { + uint32_t low = value & 0xFFFFFFFF; + uint32_t high = value >> 32; + asm volatile("wrmsr" + : /* no output from call */ + : "c"(msr), "a"(low), "d"(high)); + } + + void set_msr_bit(msr_flags flag) + { + uint64_t efer = read_msr(IA32_EFER); + write_msr(IA32_EFER, static_cast(flag) | efer); + } + + void enable_nxe_bit() { set_msr_bit(msr_flags::NXE); } + +} // namespace teachos::arch::memory::cpu -- cgit v1.2.3 From 45e7b24f19b3c4557f98996a44d8857d750ca5b3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matteo=20Gm=C3=BCr?= Date: Sun, 10 Nov 2024 11:45:26 +0000 Subject: Adjust comments and constant --- arch/x86_64/src/memory/cpu/control_register.cpp | 66 +++++++++++++++++++++++++ arch/x86_64/src/memory/cpu/cr3.cpp | 23 --------- arch/x86_64/src/memory/cpu/msr.cpp | 18 ++++--- arch/x86_64/src/memory/cpu/tlb.cpp | 7 ++- 4 files changed, 82 insertions(+), 32 deletions(-) create mode 100644 arch/x86_64/src/memory/cpu/control_register.cpp delete mode 100644 arch/x86_64/src/memory/cpu/cr3.cpp (limited to 'arch/x86_64/src/memory') diff --git a/arch/x86_64/src/memory/cpu/control_register.cpp b/arch/x86_64/src/memory/cpu/control_register.cpp new file mode 100644 index 0000000..38a887c --- /dev/null +++ b/arch/x86_64/src/memory/cpu/control_register.cpp @@ -0,0 +1,66 @@ +#include "arch/memory/cpu/control_register.hpp" + +#include "arch/exception_handling/assert.hpp" + +namespace teachos::arch::memory::cpu +{ + auto read_control_register(control_register cr) -> std::size_t + { + std::size_t current_value; + switch (cr) + { + case control_register::CR0: + asm volatile("movq %%cr0, %[output]" : [output] "=r"(current_value)); + break; + case control_register::CR2: + asm volatile("movq %%cr2, %[output]" : [output] "=r"(current_value)); + break; + case control_register::CR3: + asm volatile("movq %%cr3, %[output]" : [output] "=r"(current_value)); + break; + case control_register::CR4: + asm volatile("movq %%cr4, %[output]" : [output] "=r"(current_value)); + break; + default: + exception_handling::assert(false, + "[Control Register] Attempted to read non-existent or reserved control register"); + break; + } + return current_value; + } + + auto write_control_register(control_register cr, std::size_t new_value) -> void + { + switch (cr) + { + case control_register::CR0: + asm volatile("movq %[input], %%cr0" + : /* no output from call */ + : [input] "r"(new_value) + : "memory"); + break; + case control_register::CR2: + asm volatile("movq %[input], %%cr2" + : /* no output from call */ + : [input] "r"(new_value) + : "memory"); + break; + case control_register::CR3: + asm volatile("movq %[input], %%cr3" + : /* no output from call */ + : [input] "r"(new_value) + : "memory"); + break; + case control_register::CR4: + asm volatile("movq %[input], %%cr4" + : /* no output from call */ + : [input] "r"(new_value) + : "memory"); + break; + default: + exception_handling::assert(false, + "[Control Register] Attempted to write non-existent or reserved control register"); + break; + } + } +} // namespace teachos::arch::memory::cpu diff --git a/arch/x86_64/src/memory/cpu/cr3.cpp b/arch/x86_64/src/memory/cpu/cr3.cpp deleted file mode 100644 index 7e48d40..0000000 --- a/arch/x86_64/src/memory/cpu/cr3.cpp +++ /dev/null @@ -1,23 +0,0 @@ -#include "arch/memory/cpu/cr3.hpp" - -#include "arch/exception_handling/assert.hpp" - -namespace teachos::arch::memory::cpu -{ - auto read_cr3_register() -> allocator::physical_address - { - allocator::physical_address cr3; - asm volatile("movq %%cr3, %[output]" : [output] "=r"(cr3) : /* no input into call */ : "memory"); - return cr3; - } - - auto write_cr3_register(allocator::physical_address new_p4_table_address) -> void - { - exception_handling::assert(new_p4_table_address % allocator::PAGE_FRAME_SIZE == 0U, - "[CR3] Physical address to be written into register must be page aligned"); - asm volatile("movq %[input], %%cr3" - : /* no output from call */ - : [input] "r"(new_p4_table_address) - : "memory"); - } -} // namespace teachos::arch::memory::cpu diff --git a/arch/x86_64/src/memory/cpu/msr.cpp b/arch/x86_64/src/memory/cpu/msr.cpp index 3a917c9..6e3d1d3 100644 --- a/arch/x86_64/src/memory/cpu/msr.cpp +++ b/arch/x86_64/src/memory/cpu/msr.cpp @@ -2,14 +2,19 @@ namespace teachos::arch::memory::cpu { - uint64_t read_msr(uint32_t msr) + namespace + { + constexpr uint32_t IA32_EFER_ADDRESS = 0xC0000080; + } + + auto read_msr(uint32_t msr) -> uint64_t { uint32_t low, high; asm volatile("rdmsr" : "=a"(low), "=d"(high) : "c"(msr)); return (static_cast(high) << 32) | low; } - void write_msr(uint32_t msr, uint64_t value) + auto write_msr(uint32_t msr, uint64_t value) -> void { uint32_t low = value & 0xFFFFFFFF; uint32_t high = value >> 32; @@ -18,12 +23,11 @@ namespace teachos::arch::memory::cpu : "c"(msr), "a"(low), "d"(high)); } - void set_msr_bit(msr_flags flag) + auto set_efer_bit(efer_flags flag) -> void { - uint64_t efer = read_msr(IA32_EFER); - write_msr(IA32_EFER, static_cast(flag) | efer); + uint64_t const efer = read_msr(IA32_EFER_ADDRESS); + write_msr(IA32_EFER_ADDRESS, static_cast(flag) | efer); } - void enable_nxe_bit() { set_msr_bit(msr_flags::NXE); } - + auto enable_nxe_bit() -> void { set_efer_bit(efer_flags::NXE); } } // namespace teachos::arch::memory::cpu diff --git a/arch/x86_64/src/memory/cpu/tlb.cpp b/arch/x86_64/src/memory/cpu/tlb.cpp index 1663e80..591d9fc 100644 --- a/arch/x86_64/src/memory/cpu/tlb.cpp +++ b/arch/x86_64/src/memory/cpu/tlb.cpp @@ -1,6 +1,6 @@ #include "arch/memory/cpu/tlb.hpp" -#include "arch/memory/cpu/cr3.hpp" +#include "arch/memory/cpu/control_register.hpp" namespace teachos::arch::memory::cpu { @@ -9,5 +9,8 @@ namespace teachos::arch::memory::cpu asm volatile("invlpg (%[input])" : /* no output from call */ : [input] "r"(address) : "memory"); } - auto tlb_flush_all() -> void { write_cr3_register(read_cr3_register()); } + auto tlb_flush_all() -> void + { + write_control_register(cpu::control_register::CR3, read_control_register(cpu::control_register::CR3)); + } } // namespace teachos::arch::memory::cpu -- cgit v1.2.3 From 8eb68ccb8837ba867550d16f967d9ef21921abe2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matteo=20Gm=C3=BCr?= Date: Sun, 10 Nov 2024 12:08:02 +0000 Subject: Finish control register and adjust msr --- arch/x86_64/src/memory/cpu/control_register.cpp | 30 ++++++++++++++++--------- arch/x86_64/src/memory/cpu/msr.cpp | 8 +++---- 2 files changed, 22 insertions(+), 16 deletions(-) (limited to 'arch/x86_64/src/memory') diff --git a/arch/x86_64/src/memory/cpu/control_register.cpp b/arch/x86_64/src/memory/cpu/control_register.cpp index 38a887c..7624244 100644 --- a/arch/x86_64/src/memory/cpu/control_register.cpp +++ b/arch/x86_64/src/memory/cpu/control_register.cpp @@ -2,24 +2,26 @@ #include "arch/exception_handling/assert.hpp" +#include + namespace teachos::arch::memory::cpu { - auto read_control_register(control_register cr) -> std::size_t + auto read_control_register(control_register cr) -> uint64_t { - std::size_t current_value; + uint64_t current_value; switch (cr) { case control_register::CR0: - asm volatile("movq %%cr0, %[output]" : [output] "=r"(current_value)); + asm volatile("mov %%cr0, %[output]" : [output] "=r"(current_value)); break; case control_register::CR2: - asm volatile("movq %%cr2, %[output]" : [output] "=r"(current_value)); + asm volatile("mov %%cr2, %[output]" : [output] "=r"(current_value)); break; case control_register::CR3: - asm volatile("movq %%cr3, %[output]" : [output] "=r"(current_value)); + asm volatile("mov %%cr3, %[output]" : [output] "=r"(current_value)); break; case control_register::CR4: - asm volatile("movq %%cr4, %[output]" : [output] "=r"(current_value)); + asm volatile("mov %%cr4, %[output]" : [output] "=r"(current_value)); break; default: exception_handling::assert(false, @@ -29,30 +31,30 @@ namespace teachos::arch::memory::cpu return current_value; } - auto write_control_register(control_register cr, std::size_t new_value) -> void + auto write_control_register(control_register cr, uint64_t new_value) -> void { switch (cr) { case control_register::CR0: - asm volatile("movq %[input], %%cr0" + asm volatile("mov %[input], %%cr0" : /* no output from call */ : [input] "r"(new_value) : "memory"); break; case control_register::CR2: - asm volatile("movq %[input], %%cr2" + asm volatile("mov %[input], %%cr2" : /* no output from call */ : [input] "r"(new_value) : "memory"); break; case control_register::CR3: - asm volatile("movq %[input], %%cr3" + asm volatile("mov %[input], %%cr3" : /* no output from call */ : [input] "r"(new_value) : "memory"); break; case control_register::CR4: - asm volatile("movq %[input], %%cr4" + asm volatile("mov %[input], %%cr4" : /* no output from call */ : [input] "r"(new_value) : "memory"); @@ -63,4 +65,10 @@ namespace teachos::arch::memory::cpu break; } } + + auto set_cr2_bit(cr2_flags flag) -> void + { + auto const cr2 = read_control_register(control_register::CR2); + write_control_register(control_register::CR2, static_cast::type>(flag) | cr2); + } } // namespace teachos::arch::memory::cpu diff --git a/arch/x86_64/src/memory/cpu/msr.cpp b/arch/x86_64/src/memory/cpu/msr.cpp index 6e3d1d3..b83f902 100644 --- a/arch/x86_64/src/memory/cpu/msr.cpp +++ b/arch/x86_64/src/memory/cpu/msr.cpp @@ -4,7 +4,7 @@ namespace teachos::arch::memory::cpu { namespace { - constexpr uint32_t IA32_EFER_ADDRESS = 0xC0000080; + auto constexpr IA32_EFER_ADDRESS = 0xC0000080; } auto read_msr(uint32_t msr) -> uint64_t @@ -25,9 +25,7 @@ namespace teachos::arch::memory::cpu auto set_efer_bit(efer_flags flag) -> void { - uint64_t const efer = read_msr(IA32_EFER_ADDRESS); - write_msr(IA32_EFER_ADDRESS, static_cast(flag) | efer); + auto const efer = read_msr(IA32_EFER_ADDRESS); + write_msr(IA32_EFER_ADDRESS, static_cast::type>(flag) | efer); } - - auto enable_nxe_bit() -> void { set_efer_bit(efer_flags::NXE); } } // namespace teachos::arch::memory::cpu -- cgit v1.2.3 From 50d99ddaff23f43c3b678021d1ebc0455860d998 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matteo=20Gm=C3=BCr?= Date: Sun, 10 Nov 2024 12:09:30 +0000 Subject: Remove fixed todo --- arch/x86_64/src/memory/paging/page_entry.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'arch/x86_64/src/memory') diff --git a/arch/x86_64/src/memory/paging/page_entry.cpp b/arch/x86_64/src/memory/paging/page_entry.cpp index aae5013..08702cf 100644 --- a/arch/x86_64/src/memory/paging/page_entry.cpp +++ b/arch/x86_64/src/memory/paging/page_entry.cpp @@ -27,8 +27,7 @@ namespace teachos::arch::memory::paging } if (!elf_flags.contains_flags(multiboot::elf_section_flags::EXECUTABLE_CODE)) { - // TODO: Ensure to set the NXE bit, if we don't using this entry flag causes crashes - // flags = flags.to_ulong() | entry::EXECUTING_CODE_FORBIDDEN; + flags = flags.to_ulong() | entry::EXECUTING_CODE_FORBIDDEN; } } -- cgit v1.2.3 From 0a299adbb31605cc3018a5f37132113acd19bf4a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matteo=20Gm=C3=BCr?= Date: Sun, 10 Nov 2024 13:57:29 +0000 Subject: Use |= operator where possible --- arch/x86_64/src/memory/paging/page_entry.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'arch/x86_64/src/memory') diff --git a/arch/x86_64/src/memory/paging/page_entry.cpp b/arch/x86_64/src/memory/paging/page_entry.cpp index 08702cf..5aa0982 100644 --- a/arch/x86_64/src/memory/paging/page_entry.cpp +++ b/arch/x86_64/src/memory/paging/page_entry.cpp @@ -19,15 +19,15 @@ namespace teachos::arch::memory::paging { if (elf_flags.contains_flags(multiboot::elf_section_flags::OCCUPIES_MEMORY)) { - flags = flags.to_ulong() | entry::PRESENT; + flags |= entry::PRESENT; } if (elf_flags.contains_flags(multiboot::elf_section_flags::WRITABLE)) { - flags = flags.to_ulong() | entry::WRITABLE; + flags |= entry::WRITABLE; } if (!elf_flags.contains_flags(multiboot::elf_section_flags::EXECUTABLE_CODE)) { - flags = flags.to_ulong() | entry::EXECUTING_CODE_FORBIDDEN; + flags |= entry::EXECUTING_CODE_FORBIDDEN; } } -- cgit v1.2.3 From 325d540236476b50af78e5781e3afead9e910359 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matteo=20Gm=C3=BCr?= Date: Mon, 11 Nov 2024 10:10:08 +0000 Subject: Add todos to section that cause the crash --- arch/x86_64/src/memory/paging/inactive_page_table.cpp | 1 + arch/x86_64/src/memory/paging/page_entry.cpp | 1 + 2 files changed, 2 insertions(+) (limited to 'arch/x86_64/src/memory') diff --git a/arch/x86_64/src/memory/paging/inactive_page_table.cpp b/arch/x86_64/src/memory/paging/inactive_page_table.cpp index 4e0610e..d2eecb8 100644 --- a/arch/x86_64/src/memory/paging/inactive_page_table.cpp +++ b/arch/x86_64/src/memory/paging/inactive_page_table.cpp @@ -12,6 +12,7 @@ namespace teachos::arch::memory::paging temporary_page & temporary_page) : page_table_level_4_frame{frame} { + // TODO: Here the exact same mapping code auto table = temporary_page.map_table_frame(page_table_level_4_frame, active_page_table); table.zero_entries(); table[511].set_entry(page_table_level_4_frame, entry::PRESENT | entry::WRITABLE); diff --git a/arch/x86_64/src/memory/paging/page_entry.cpp b/arch/x86_64/src/memory/paging/page_entry.cpp index 5aa0982..ba3deb3 100644 --- a/arch/x86_64/src/memory/paging/page_entry.cpp +++ b/arch/x86_64/src/memory/paging/page_entry.cpp @@ -51,6 +51,7 @@ namespace teachos::arch::memory::paging { exception_handling::assert((frame.start_address() & ~PHYSICAL_ADDRESS_MASK) == 0, "[Paging Entry] Start address is not aligned with page"); + // TODO: Crash when trying to write invalid value at 0xffffff8657f5d5f0 flags = frame.start_address() | additional_flags.to_ulong(); } -- cgit v1.2.3 From 0f3c5c2bc02d7aa48f8edbe42a67dd91821032b7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matteo=20Gm=C3=BCr?= Date: Mon, 11 Nov 2024 12:02:35 +0000 Subject: Mark the two methods that first work and then fail --- arch/x86_64/src/memory/paging/inactive_page_table.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch/x86_64/src/memory') diff --git a/arch/x86_64/src/memory/paging/inactive_page_table.cpp b/arch/x86_64/src/memory/paging/inactive_page_table.cpp index d2eecb8..8ebc8ce 100644 --- a/arch/x86_64/src/memory/paging/inactive_page_table.cpp +++ b/arch/x86_64/src/memory/paging/inactive_page_table.cpp @@ -12,7 +12,7 @@ namespace teachos::arch::memory::paging temporary_page & temporary_page) : page_table_level_4_frame{frame} { - // TODO: Here the exact same mapping code + // TODO: Here the exact same mapping code but it actually works?, is it the different frame? auto table = temporary_page.map_table_frame(page_table_level_4_frame, active_page_table); table.zero_entries(); table[511].set_entry(page_table_level_4_frame, entry::PRESENT | entry::WRITABLE); -- cgit v1.2.3 From 0ca0c40c197c214288ad2ed1179ae9ae28c50194 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matteo=20Gm=C3=BCr?= Date: Mon, 11 Nov 2024 14:16:18 +0000 Subject: Improve calculation of kernel end and start address. --- arch/x86_64/src/memory/multiboot/reader.cpp | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) (limited to 'arch/x86_64/src/memory') diff --git a/arch/x86_64/src/memory/multiboot/reader.cpp b/arch/x86_64/src/memory/multiboot/reader.cpp index 1dd18ff..2bf5b25 100644 --- a/arch/x86_64/src/memory/multiboot/reader.cpp +++ b/arch/x86_64/src/memory/multiboot/reader.cpp @@ -6,6 +6,7 @@ #include "arch/memory/multiboot/info.hpp" #include +#include namespace teachos::arch::memory::multiboot { @@ -56,11 +57,15 @@ namespace teachos::arch::memory::multiboot elf_section_header_container sections{begin, end}; + auto allocated_sections = sections | std::views::filter([](auto const & section) { + return section.flags.contains_flags(elf_section_flags::OCCUPIES_MEMORY); + }); + auto const elf_section_with_lowest_physical_address = std::ranges::min_element( - sections, [](auto const & a, auto const & b) { return a.physical_address < b.physical_address; }); + allocated_sections, [](auto const & a, auto const & b) { return a.physical_address < b.physical_address; }); auto const elf_section_with_highest_physical_address = - std::ranges::max_element(sections, [](auto const & a, auto const & b) { + std::ranges::max_element(allocated_sections, [](auto const & a, auto const & b) { auto a_physical_address_end = a.physical_address + a.section_size; auto b_physical_address_end = b.physical_address + b.section_size; return a_physical_address_end < b_physical_address_end; -- cgit v1.2.3 From 7db57d7a47671b4023e34413a2276611e1c65f72 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matteo=20Gm=C3=BCr?= Date: Tue, 12 Nov 2024 10:24:12 +0000 Subject: Add comment to flush all and remove now redudant todos. --- arch/x86_64/src/memory/paging/inactive_page_table.cpp | 1 - arch/x86_64/src/memory/paging/page_entry.cpp | 1 - 2 files changed, 2 deletions(-) (limited to 'arch/x86_64/src/memory') diff --git a/arch/x86_64/src/memory/paging/inactive_page_table.cpp b/arch/x86_64/src/memory/paging/inactive_page_table.cpp index 8ebc8ce..4e0610e 100644 --- a/arch/x86_64/src/memory/paging/inactive_page_table.cpp +++ b/arch/x86_64/src/memory/paging/inactive_page_table.cpp @@ -12,7 +12,6 @@ namespace teachos::arch::memory::paging temporary_page & temporary_page) : page_table_level_4_frame{frame} { - // TODO: Here the exact same mapping code but it actually works?, is it the different frame? auto table = temporary_page.map_table_frame(page_table_level_4_frame, active_page_table); table.zero_entries(); table[511].set_entry(page_table_level_4_frame, entry::PRESENT | entry::WRITABLE); diff --git a/arch/x86_64/src/memory/paging/page_entry.cpp b/arch/x86_64/src/memory/paging/page_entry.cpp index ba3deb3..5aa0982 100644 --- a/arch/x86_64/src/memory/paging/page_entry.cpp +++ b/arch/x86_64/src/memory/paging/page_entry.cpp @@ -51,7 +51,6 @@ namespace teachos::arch::memory::paging { exception_handling::assert((frame.start_address() & ~PHYSICAL_ADDRESS_MASK) == 0, "[Paging Entry] Start address is not aligned with page"); - // TODO: Crash when trying to write invalid value at 0xffffff8657f5d5f0 flags = frame.start_address() | additional_flags.to_ulong(); } -- cgit v1.2.3 From d10bc808b29b0b647cbbb6c92d253fbb8c5cf431 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matteo=20Gm=C3=BCr?= Date: Tue, 12 Nov 2024 10:59:50 +0000 Subject: Fix next table overwriting old page handle --- arch/x86_64/src/memory/paging/page_table.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'arch/x86_64/src/memory') diff --git a/arch/x86_64/src/memory/paging/page_table.cpp b/arch/x86_64/src/memory/paging/page_table.cpp index a39c235..eb11810 100644 --- a/arch/x86_64/src/memory/paging/page_table.cpp +++ b/arch/x86_64/src/memory/paging/page_table.cpp @@ -100,14 +100,15 @@ namespace teachos::arch::memory::paging auto page_table_handle::is_empty() const -> bool { return table->is_empty(); } - auto page_table_handle::next_table(std::size_t table_index) -> std::optional + auto page_table_handle::next_table(std::size_t table_index) const -> std::optional { exception_handling::assert(table_level != page_table_handle::LEVEL1, "[Page Table] Attempted to call next_table on level 1 page table"); auto const next_table = table->next_table(table_index); if (next_table.has_value()) { - return page_table_handle{next_table.value(), --table_level}; + auto const new_level = static_cast(table_level - 1); + return page_table_handle{next_table.value(), new_level}; } return std::nullopt; } -- cgit v1.2.3 From 1cd666241b59b800818812220e28b8b8572e4263 Mon Sep 17 00:00:00 2001 From: Felix Morgner Date: Tue, 19 Nov 2024 17:32:02 +0100 Subject: paging: de-templetize implementation --- .../src/memory/allocator/area_frame_allocator.cpp | 2 +- .../src/memory/allocator/tiny_frame_allocator.cpp | 4 +- .../x86_64/src/memory/paging/active_page_table.cpp | 67 +++++++++++++++ arch/x86_64/src/memory/paging/kernel_mapper.cpp | 94 ++++++++++++++++++++++ arch/x86_64/src/memory/paging/page_table.cpp | 21 +++++ arch/x86_64/src/memory/paging/temporary_page.cpp | 9 ++- 6 files changed, 193 insertions(+), 4 deletions(-) create mode 100644 arch/x86_64/src/memory/paging/kernel_mapper.cpp (limited to 'arch/x86_64/src/memory') diff --git a/arch/x86_64/src/memory/allocator/area_frame_allocator.cpp b/arch/x86_64/src/memory/allocator/area_frame_allocator.cpp index 3bc9676..cb4fefa 100644 --- a/arch/x86_64/src/memory/allocator/area_frame_allocator.cpp +++ b/arch/x86_64/src/memory/allocator/area_frame_allocator.cpp @@ -81,5 +81,5 @@ namespace teachos::arch::memory::allocator return allocate_frame(); } - auto area_frame_allocator::deallocate_frame(physical_frame physical_frame) -> void { (void)physical_frame; } + auto area_frame_allocator::deallocate_frame(physical_frame const & physical_frame) -> void { (void)physical_frame; } } // namespace teachos::arch::memory::allocator diff --git a/arch/x86_64/src/memory/allocator/tiny_frame_allocator.cpp b/arch/x86_64/src/memory/allocator/tiny_frame_allocator.cpp index d37864e..ed000a0 100644 --- a/arch/x86_64/src/memory/allocator/tiny_frame_allocator.cpp +++ b/arch/x86_64/src/memory/allocator/tiny_frame_allocator.cpp @@ -4,7 +4,7 @@ namespace teachos::arch::memory::allocator { - tiny_frame_allocator::tiny_frame_allocator(area_frame_allocator & allocator) + tiny_frame_allocator::tiny_frame_allocator(frame_allocator & allocator) : frames{} { // Has to be done this way, because constructing the constructor with the data from allocator.allocate_frames(), @@ -34,7 +34,7 @@ namespace teachos::arch::memory::allocator return std::nullopt; } - auto tiny_frame_allocator::deallocate_frame(physical_frame physical_frame) -> void + auto tiny_frame_allocator::deallocate_frame(physical_frame const & physical_frame) -> void { for (auto & frame_option : frames) { 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 0113869..d2bf683 100644 --- a/arch/x86_64/src/memory/paging/active_page_table.cpp +++ b/arch/x86_64/src/memory/paging/active_page_table.cpp @@ -1,5 +1,7 @@ #include "arch/memory/paging/active_page_table.hpp" +#include "arch/memory/cpu/tlb.hpp" + namespace teachos::arch::memory::paging { namespace @@ -15,6 +17,71 @@ namespace teachos::arch::memory::paging return active_page; } + auto active_page_table::map_page_to_frame(allocator::frame_allocator & allocator, virtual_page page, + allocator::physical_frame frame, std::bitset<64U> flags) -> void + { + auto current_handle = active_handle; + + for (auto level = page_table_handle::LEVEL4; level != page_table_handle::LEVEL1; --level) + { + current_handle = current_handle.next_table_or_create(allocator, page.get_level_index(level)); + } + + auto & level1_entry = current_handle[page.get_level_index(page_table_handle::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.to_ulong() | entry::PRESENT); + } + + auto active_page_table::identity_map(allocator::frame_allocator & allocator, allocator::physical_frame frame, + std::bitset<64U> flags) -> void + { + auto const page = virtual_page::containing_address(frame.start_address()); + map_page_to_frame(allocator, page, frame, flags); + } + + auto active_page_table::map_next_free_page_to_frame(allocator::frame_allocator & allocator, virtual_page page, + std::bitset<64U> flags) -> void + { + auto const 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); + } + + auto active_page_table::unmap_page(allocator::frame_allocator & 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 = active_handle; + + for (auto level = page_table_handle::LEVEL4; level != page_table_handle::LEVEL1; --level) + { + 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. 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(); + } + + unmap_page_table_entry(allocator, page, current_handle); + cpu::tlb_flush(page.start_address()); + } + + auto active_page_table::unmap_page_table_entry(allocator::frame_allocator & 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()); + } + auto active_page_table::operator[](std::size_t index) -> entry & { return active_handle[index]; } auto active_page_table::translate_address(virtual_address address) -> std::optional diff --git a/arch/x86_64/src/memory/paging/kernel_mapper.cpp b/arch/x86_64/src/memory/paging/kernel_mapper.cpp new file mode 100644 index 0000000..f938cb3 --- /dev/null +++ b/arch/x86_64/src/memory/paging/kernel_mapper.cpp @@ -0,0 +1,94 @@ +#include "arch/memory/paging/kernel_mapper.hpp" + +#include "arch/memory/cpu/control_register.hpp" +#include "arch/memory/cpu/tlb.hpp" +#include "arch/memory/paging/temporary_page.hpp" +#include "arch/video/vga/text.hpp" + +namespace teachos::arch::memory::paging +{ + + kernel_mapper::kernel_mapper(allocator::frame_allocator & allocator, multiboot::memory_information const & mem_info) + : allocator(allocator) + , mem_info(mem_info) + { + // Nothing to do + } + + auto kernel_mapper::remap_kernel() -> active_page_table & + { + temporary_page temporary_page{virtual_page{0xCAFEBABE}, allocator}; + auto & active_table = active_page_table::create_or_get(); + auto const frame = allocator.allocate_frame(); + exception_handling::assert(frame.has_value(), + "[Kernel Mapper] Frame could not be allocated and therefore kernel not mapped"); + inactive_page_table new_table{frame.value(), active_table, temporary_page}; + remap_elf_kernel_sections(new_table, temporary_page, active_table); + auto const old_table = switch_active_page_table(new_table); + auto const old_level_4_page = virtual_page::containing_address(old_table.page_table_level_4_frame.start_address()); + active_table.unmap_page(allocator, old_level_4_page); + return active_table; + } + + auto kernel_mapper::remap_elf_kernel_sections(inactive_page_table & inactive_table, temporary_page & temporary_page, + active_page_table & active_table) -> void + { + auto const backup = + allocator::physical_frame::containing_address(cpu::read_control_register(cpu::control_register::CR3)); + auto page_table_level4 = temporary_page.map_table_frame(backup, active_table); + + active_table[511].set_entry(inactive_table.page_table_level_4_frame, entry::PRESENT | entry::WRITABLE); + cpu::tlb_flush_all(); + map_elf_kernel_sections(active_table); + + page_table_level4[511].set_entry(backup, entry::PRESENT | entry::WRITABLE); + cpu::tlb_flush_all(); + temporary_page.unmap_page(active_table); + } + + auto kernel_mapper::switch_active_page_table(inactive_page_table new_table) -> inactive_page_table + { + auto const backup = + allocator::physical_frame::containing_address(cpu::read_control_register(cpu::control_register::CR3)); + auto const old_table = inactive_page_table{backup}; + + auto const new_address = new_table.page_table_level_4_frame.start_address(); + cpu::write_control_register(cpu::control_register::CR3, new_address); + return old_table; + } + + auto kernel_mapper::map_elf_kernel_sections(active_page_table & active_table) -> void + { + exception_handling::assert(!mem_info.sections.empty(), "[Kernel Mapper] Kernel elf sections empty"); + for (auto const & section : mem_info.sections) + { + if (!section.flags.contains_flags(multiboot::elf_section_flags::OCCUPIES_MEMORY)) + { + continue; + } + exception_handling::assert(section.physical_address % allocator::PAGE_FRAME_SIZE == 0U, + "[Kernel Mapper] Section must be page aligned"); + auto const start_frame = allocator::physical_frame::containing_address(section.physical_address); + // End address is exclusive, so that it is not part of the section anymore (one past the last frame of this + // section). But end frame would now point to the actual last frame and not one past the last frame, therefore + // we increment by one to get one past the last frame of this section. + auto const end_frame = + ++(allocator::physical_frame::containing_address(section.physical_address + section.section_size - 1)); + + allocator::frame_container::iterator const begin{start_frame}; + allocator::frame_container::iterator const end{end_frame}; + allocator::frame_container const frames{begin, end}; + entry const entry{section.flags}; + + for (auto const & frame : frames) + { + active_table.identity_map(allocator, frame, entry.get_flags()); + } + } + + auto const vga_buffer_frame = + allocator::physical_frame::containing_address(video::vga::text::DEFAULT_VGA_TEXT_BUFFER_ADDRESS); + active_table.identity_map(allocator, vga_buffer_frame, entry::WRITABLE); + } + +} // 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 eb11810..48e6d4f 100644 --- a/arch/x86_64/src/memory/paging/page_table.cpp +++ b/arch/x86_64/src/memory/paging/page_table.cpp @@ -96,6 +96,27 @@ namespace teachos::arch::memory::paging "[Page Table] Attempted to pass nullptr as table to page table table method"); } + auto page_table_handle::next_table_or_create(allocator::frame_allocator & allocator, + std::size_t table_index) -> page_table_handle + { + auto next_handle = next_table(table_index); + // If the next table method failed then it means that the page level of the frame we want allocate has not yet + // been created itself. So we have to do that before we are able to allocate the wanted frame. This has to be done + // for every level, meaning we potenitally create a level 4, level 3 and level 2 page entry, each pointing to a + // page table one level below. + if (!next_handle.has_value()) + { + auto const allocated_frame = allocator.allocate_frame(); + exception_handling::assert(allocated_frame.has_value(), "[Page mapper] Unable to allocate frame"); + this->operator[](table_index).set_entry(allocated_frame.value(), entry::PRESENT | entry::WRITABLE); + // There should now be an entry at the previously not existent index, therefore we can simply access it again. + next_handle = next_table(table_index); + exception_handling::assert(next_handle.has_value(), "[Page mapper] Unable to create new entry into page table"); + next_handle.value().zero_entries(); + } + return next_handle.value(); + } + auto page_table_handle::zero_entries() -> void { table->zero_entries(); } auto page_table_handle::is_empty() const -> bool { return table->is_empty(); } diff --git a/arch/x86_64/src/memory/paging/temporary_page.cpp b/arch/x86_64/src/memory/paging/temporary_page.cpp index 152241d..8439864 100644 --- a/arch/x86_64/src/memory/paging/temporary_page.cpp +++ b/arch/x86_64/src/memory/paging/temporary_page.cpp @@ -4,6 +4,13 @@ namespace teachos::arch::memory::paging { + temporary_page::temporary_page(virtual_page page, allocator::frame_allocator & allocator) + : page{page} + , allocator{allocator} + { + // Nothing to do + } + auto temporary_page::map_table_frame(allocator::physical_frame frame, active_page_table & active_table) -> page_table_handle { @@ -24,6 +31,6 @@ namespace teachos::arch::memory::paging auto temporary_page::unmap_page(active_page_table & active_table) -> void { - active_table.unmap_page(allocator, page); + active_table.unmap_page(this->allocator, page); } } // namespace teachos::arch::memory::paging -- cgit v1.2.3 From 4c44f822eefa743649693e0a49a978291925ddff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matteo=20Gm=C3=BCr?= Date: Sun, 24 Nov 2024 09:17:53 +0000 Subject: Revert: de-templatize paging implementation --- .../src/memory/allocator/tiny_frame_allocator.cpp | 16 ---- .../x86_64/src/memory/paging/active_page_table.cpp | 67 --------------- arch/x86_64/src/memory/paging/kernel_mapper.cpp | 94 ---------------------- arch/x86_64/src/memory/paging/page_table.cpp | 21 ----- arch/x86_64/src/memory/paging/temporary_page.cpp | 9 +-- 5 files changed, 1 insertion(+), 206 deletions(-) delete mode 100644 arch/x86_64/src/memory/paging/kernel_mapper.cpp (limited to 'arch/x86_64/src/memory') diff --git a/arch/x86_64/src/memory/allocator/tiny_frame_allocator.cpp b/arch/x86_64/src/memory/allocator/tiny_frame_allocator.cpp index ed000a0..3cdf9c7 100644 --- a/arch/x86_64/src/memory/allocator/tiny_frame_allocator.cpp +++ b/arch/x86_64/src/memory/allocator/tiny_frame_allocator.cpp @@ -4,22 +4,6 @@ namespace teachos::arch::memory::allocator { - tiny_frame_allocator::tiny_frame_allocator(frame_allocator & allocator) - : frames{} - { - // Has to be done this way, because constructing the constructor with the data from allocator.allocate_frames(), - // does not work because it would set the value correctly but because we pass it as an std::optional it would not - // set the engaged flag. Meaning the has_value() method would still return false. - for (auto & frame : frames) - { - auto allocated = allocator.allocate_frame(); - if (allocated.has_value()) - { - frame.emplace(allocated.value()); - } - } - } - auto tiny_frame_allocator::allocate_frame() -> std::optional { for (auto & frame_option : frames) 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 d2bf683..0113869 100644 --- a/arch/x86_64/src/memory/paging/active_page_table.cpp +++ b/arch/x86_64/src/memory/paging/active_page_table.cpp @@ -1,7 +1,5 @@ #include "arch/memory/paging/active_page_table.hpp" -#include "arch/memory/cpu/tlb.hpp" - namespace teachos::arch::memory::paging { namespace @@ -17,71 +15,6 @@ namespace teachos::arch::memory::paging return active_page; } - auto active_page_table::map_page_to_frame(allocator::frame_allocator & allocator, virtual_page page, - allocator::physical_frame frame, std::bitset<64U> flags) -> void - { - auto current_handle = active_handle; - - for (auto level = page_table_handle::LEVEL4; level != page_table_handle::LEVEL1; --level) - { - current_handle = current_handle.next_table_or_create(allocator, page.get_level_index(level)); - } - - auto & level1_entry = current_handle[page.get_level_index(page_table_handle::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.to_ulong() | entry::PRESENT); - } - - auto active_page_table::identity_map(allocator::frame_allocator & allocator, allocator::physical_frame frame, - std::bitset<64U> flags) -> void - { - auto const page = virtual_page::containing_address(frame.start_address()); - map_page_to_frame(allocator, page, frame, flags); - } - - auto active_page_table::map_next_free_page_to_frame(allocator::frame_allocator & allocator, virtual_page page, - std::bitset<64U> flags) -> void - { - auto const 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); - } - - auto active_page_table::unmap_page(allocator::frame_allocator & 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 = active_handle; - - for (auto level = page_table_handle::LEVEL4; level != page_table_handle::LEVEL1; --level) - { - 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. 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(); - } - - unmap_page_table_entry(allocator, page, current_handle); - cpu::tlb_flush(page.start_address()); - } - - auto active_page_table::unmap_page_table_entry(allocator::frame_allocator & 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()); - } - auto active_page_table::operator[](std::size_t index) -> entry & { return active_handle[index]; } auto active_page_table::translate_address(virtual_address address) -> std::optional diff --git a/arch/x86_64/src/memory/paging/kernel_mapper.cpp b/arch/x86_64/src/memory/paging/kernel_mapper.cpp deleted file mode 100644 index f938cb3..0000000 --- a/arch/x86_64/src/memory/paging/kernel_mapper.cpp +++ /dev/null @@ -1,94 +0,0 @@ -#include "arch/memory/paging/kernel_mapper.hpp" - -#include "arch/memory/cpu/control_register.hpp" -#include "arch/memory/cpu/tlb.hpp" -#include "arch/memory/paging/temporary_page.hpp" -#include "arch/video/vga/text.hpp" - -namespace teachos::arch::memory::paging -{ - - kernel_mapper::kernel_mapper(allocator::frame_allocator & allocator, multiboot::memory_information const & mem_info) - : allocator(allocator) - , mem_info(mem_info) - { - // Nothing to do - } - - auto kernel_mapper::remap_kernel() -> active_page_table & - { - temporary_page temporary_page{virtual_page{0xCAFEBABE}, allocator}; - auto & active_table = active_page_table::create_or_get(); - auto const frame = allocator.allocate_frame(); - exception_handling::assert(frame.has_value(), - "[Kernel Mapper] Frame could not be allocated and therefore kernel not mapped"); - inactive_page_table new_table{frame.value(), active_table, temporary_page}; - remap_elf_kernel_sections(new_table, temporary_page, active_table); - auto const old_table = switch_active_page_table(new_table); - auto const old_level_4_page = virtual_page::containing_address(old_table.page_table_level_4_frame.start_address()); - active_table.unmap_page(allocator, old_level_4_page); - return active_table; - } - - auto kernel_mapper::remap_elf_kernel_sections(inactive_page_table & inactive_table, temporary_page & temporary_page, - active_page_table & active_table) -> void - { - auto const backup = - allocator::physical_frame::containing_address(cpu::read_control_register(cpu::control_register::CR3)); - auto page_table_level4 = temporary_page.map_table_frame(backup, active_table); - - active_table[511].set_entry(inactive_table.page_table_level_4_frame, entry::PRESENT | entry::WRITABLE); - cpu::tlb_flush_all(); - map_elf_kernel_sections(active_table); - - page_table_level4[511].set_entry(backup, entry::PRESENT | entry::WRITABLE); - cpu::tlb_flush_all(); - temporary_page.unmap_page(active_table); - } - - auto kernel_mapper::switch_active_page_table(inactive_page_table new_table) -> inactive_page_table - { - auto const backup = - allocator::physical_frame::containing_address(cpu::read_control_register(cpu::control_register::CR3)); - auto const old_table = inactive_page_table{backup}; - - auto const new_address = new_table.page_table_level_4_frame.start_address(); - cpu::write_control_register(cpu::control_register::CR3, new_address); - return old_table; - } - - auto kernel_mapper::map_elf_kernel_sections(active_page_table & active_table) -> void - { - exception_handling::assert(!mem_info.sections.empty(), "[Kernel Mapper] Kernel elf sections empty"); - for (auto const & section : mem_info.sections) - { - if (!section.flags.contains_flags(multiboot::elf_section_flags::OCCUPIES_MEMORY)) - { - continue; - } - exception_handling::assert(section.physical_address % allocator::PAGE_FRAME_SIZE == 0U, - "[Kernel Mapper] Section must be page aligned"); - auto const start_frame = allocator::physical_frame::containing_address(section.physical_address); - // End address is exclusive, so that it is not part of the section anymore (one past the last frame of this - // section). But end frame would now point to the actual last frame and not one past the last frame, therefore - // we increment by one to get one past the last frame of this section. - auto const end_frame = - ++(allocator::physical_frame::containing_address(section.physical_address + section.section_size - 1)); - - allocator::frame_container::iterator const begin{start_frame}; - allocator::frame_container::iterator const end{end_frame}; - allocator::frame_container const frames{begin, end}; - entry const entry{section.flags}; - - for (auto const & frame : frames) - { - active_table.identity_map(allocator, frame, entry.get_flags()); - } - } - - auto const vga_buffer_frame = - allocator::physical_frame::containing_address(video::vga::text::DEFAULT_VGA_TEXT_BUFFER_ADDRESS); - active_table.identity_map(allocator, vga_buffer_frame, entry::WRITABLE); - } - -} // 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 48e6d4f..eb11810 100644 --- a/arch/x86_64/src/memory/paging/page_table.cpp +++ b/arch/x86_64/src/memory/paging/page_table.cpp @@ -96,27 +96,6 @@ namespace teachos::arch::memory::paging "[Page Table] Attempted to pass nullptr as table to page table table method"); } - auto page_table_handle::next_table_or_create(allocator::frame_allocator & allocator, - std::size_t table_index) -> page_table_handle - { - auto next_handle = next_table(table_index); - // If the next table method failed then it means that the page level of the frame we want allocate has not yet - // been created itself. So we have to do that before we are able to allocate the wanted frame. This has to be done - // for every level, meaning we potenitally create a level 4, level 3 and level 2 page entry, each pointing to a - // page table one level below. - if (!next_handle.has_value()) - { - auto const allocated_frame = allocator.allocate_frame(); - exception_handling::assert(allocated_frame.has_value(), "[Page mapper] Unable to allocate frame"); - this->operator[](table_index).set_entry(allocated_frame.value(), entry::PRESENT | entry::WRITABLE); - // There should now be an entry at the previously not existent index, therefore we can simply access it again. - next_handle = next_table(table_index); - exception_handling::assert(next_handle.has_value(), "[Page mapper] Unable to create new entry into page table"); - next_handle.value().zero_entries(); - } - return next_handle.value(); - } - auto page_table_handle::zero_entries() -> void { table->zero_entries(); } auto page_table_handle::is_empty() const -> bool { return table->is_empty(); } diff --git a/arch/x86_64/src/memory/paging/temporary_page.cpp b/arch/x86_64/src/memory/paging/temporary_page.cpp index 8439864..152241d 100644 --- a/arch/x86_64/src/memory/paging/temporary_page.cpp +++ b/arch/x86_64/src/memory/paging/temporary_page.cpp @@ -4,13 +4,6 @@ namespace teachos::arch::memory::paging { - temporary_page::temporary_page(virtual_page page, allocator::frame_allocator & allocator) - : page{page} - , allocator{allocator} - { - // Nothing to do - } - auto temporary_page::map_table_frame(allocator::physical_frame frame, active_page_table & active_table) -> page_table_handle { @@ -31,6 +24,6 @@ namespace teachos::arch::memory::paging auto temporary_page::unmap_page(active_page_table & active_table) -> void { - active_table.unmap_page(this->allocator, page); + active_table.unmap_page(allocator, page); } } // namespace teachos::arch::memory::paging -- cgit v1.2.3 From 55f32173e97fdcf4a45006b66cc4b20329a5c7af Mon Sep 17 00:00:00 2001 From: Fabian Imhof Date: Sun, 24 Nov 2024 13:10:21 +0000 Subject: implement basic heap and remap it --- arch/x86_64/src/memory/heap/allocator.cpp | 27 ++++++++++++++++++ arch/x86_64/src/memory/main.cpp | 47 +++++++++++++++++++++++++++++++ 2 files changed, 74 insertions(+) create mode 100644 arch/x86_64/src/memory/heap/allocator.cpp create mode 100644 arch/x86_64/src/memory/main.cpp (limited to 'arch/x86_64/src/memory') diff --git a/arch/x86_64/src/memory/heap/allocator.cpp b/arch/x86_64/src/memory/heap/allocator.cpp new file mode 100644 index 0000000..c9ddd78 --- /dev/null +++ b/arch/x86_64/src/memory/heap/allocator.cpp @@ -0,0 +1,27 @@ +#include "arch/memory/heap/allocator.hpp" + +#include "arch/exception_handling/assert.hpp" + +namespace teachos::arch::memory::heap +{ + auto bump_allocator::allocate(std::size_t size) -> void * + { + // Uses some sort of alignment orignally: + // https://github.com/phil-opp/blog_os/blob/7f6576c9dc34e360b81236c54c25c7827fd6a2df/src/memory/heap_allocator.rs#L24 + auto alloc_start = next; + auto alloc_end = next + size; + + arch::exception_handling::assert(alloc_end <= heap_end, "[Heap Allocator] Out of memory!"); + + next = alloc_end; + return reinterpret_cast(alloc_start); + } + + auto bump_allocator::deallocate(uint8_t * pointer, std::size_t size) -> void + { + // Memory leak + if (pointer || size) + { + } + } +} // namespace teachos::arch::memory::heap \ No newline at end of file diff --git a/arch/x86_64/src/memory/main.cpp b/arch/x86_64/src/memory/main.cpp new file mode 100644 index 0000000..ce07115 --- /dev/null +++ b/arch/x86_64/src/memory/main.cpp @@ -0,0 +1,47 @@ +#include "arch/memory/main.hpp" + +#include "arch/exception_handling/assert.hpp" +#include "arch/memory/allocator/area_frame_allocator.hpp" +#include "arch/memory/cpu/control_register.hpp" +#include "arch/memory/cpu/msr.hpp" +#include "arch/memory/heap/allocator.hpp" +#include "arch/memory/paging/active_page_table.hpp" +#include "arch/memory/paging/kernel_mapper.hpp" + +namespace teachos::arch::memory +{ + namespace + { + auto remap_heap(allocator::area_frame_allocator allocator, paging::active_page_table & active_table) -> void + { + auto heap_start_page = paging::virtual_page::containing_address(memory::heap::HEAP_START); + auto heap_end_page = + paging::virtual_page::containing_address(memory::heap::HEAP_START + memory::heap::HEAP_SIZE - 1); + + for (auto i = heap_start_page.page_number; i <= heap_end_page.page_number; i++) + { + active_table.map_page_to_next_free_frame(allocator, paging::virtual_page{i}, paging::entry::WRITABLE); + } + } + } // namespace + + auto initialize_memory_management() -> void + { + static bool has_been_called = false; + arch::exception_handling::assert(!has_been_called, + "[Initialization] Memory management has already been initialized"); + has_been_called = true; + + auto const memory_information = multiboot::read_multiboot2(); + allocator::area_frame_allocator allocator(memory_information); + + cpu::set_cr2_bit(memory::cpu::cr2_flags::WRITE_PROTECT); + cpu::set_efer_bit(memory::cpu::efer_flags::NXE); + + paging::kernel_mapper kernel(allocator, memory_information); + auto & active_table = kernel.remap_kernel(); + video::vga::text::write("Kernel remapping successfull", video::vga::text::common_attributes::green_on_black); + + remap_heap(allocator, active_table); + } +} // namespace teachos::arch::memory \ No newline at end of file -- cgit v1.2.3 From 24805678884bcfcc3f14e88757955ab574d647cb Mon Sep 17 00:00:00 2001 From: Fabian Imhof Date: Sun, 24 Nov 2024 13:18:31 +0000 Subject: add doxygen comments to remapping --- arch/x86_64/src/memory/heap/allocator.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'arch/x86_64/src/memory') diff --git a/arch/x86_64/src/memory/heap/allocator.cpp b/arch/x86_64/src/memory/heap/allocator.cpp index c9ddd78..bb61be4 100644 --- a/arch/x86_64/src/memory/heap/allocator.cpp +++ b/arch/x86_64/src/memory/heap/allocator.cpp @@ -17,10 +17,10 @@ namespace teachos::arch::memory::heap return reinterpret_cast(alloc_start); } - auto bump_allocator::deallocate(uint8_t * pointer, std::size_t size) -> void + auto bump_allocator::deallocate(uint8_t * pointer) -> void { - // Memory leak - if (pointer || size) + // Not implemented; leaking memory + if (pointer) { } } -- cgit v1.2.3 From 47732f54474a083e9f98e52714c12c0ca1181174 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matteo=20Gm=C3=BCr?= Date: Sun, 24 Nov 2024 13:27:15 +0000 Subject: Use container helper classes for heap remapping --- arch/x86_64/src/memory/main.cpp | 16 ++++++++++------ arch/x86_64/src/memory/paging/virtual_page.cpp | 13 +++++++++++++ 2 files changed, 23 insertions(+), 6 deletions(-) (limited to 'arch/x86_64/src/memory') diff --git a/arch/x86_64/src/memory/main.cpp b/arch/x86_64/src/memory/main.cpp index ce07115..80242cc 100644 --- a/arch/x86_64/src/memory/main.cpp +++ b/arch/x86_64/src/memory/main.cpp @@ -14,13 +14,16 @@ namespace teachos::arch::memory { auto remap_heap(allocator::area_frame_allocator allocator, paging::active_page_table & active_table) -> void { - auto heap_start_page = paging::virtual_page::containing_address(memory::heap::HEAP_START); - auto heap_end_page = - paging::virtual_page::containing_address(memory::heap::HEAP_START + memory::heap::HEAP_SIZE - 1); - - for (auto i = heap_start_page.page_number; i <= heap_end_page.page_number; i++) + auto const start_page = paging::virtual_page::containing_address(memory::heap::HEAP_START); + auto const end_page = + ++(paging::virtual_page::containing_address(memory::heap::HEAP_START + memory::heap::HEAP_SIZE - 1)); + paging::page_container::iterator const begin{start_page}; + paging::page_container::iterator const end{end_page}; + paging::page_container const pages{begin, end}; + + for (auto const & page : pages) { - active_table.map_page_to_next_free_frame(allocator, paging::virtual_page{i}, paging::entry::WRITABLE); + active_table.map_page_to_next_free_frame(allocator, page, paging::entry::WRITABLE); } } } // namespace @@ -43,5 +46,6 @@ namespace teachos::arch::memory video::vga::text::write("Kernel remapping successfull", video::vga::text::common_attributes::green_on_black); remap_heap(allocator, active_table); + video::vga::text::write("Heap remapping successfull", video::vga::text::common_attributes::green_on_black); } } // namespace teachos::arch::memory \ No newline at end of file diff --git a/arch/x86_64/src/memory/paging/virtual_page.cpp b/arch/x86_64/src/memory/paging/virtual_page.cpp index f798709..d374156 100644 --- a/arch/x86_64/src/memory/paging/virtual_page.cpp +++ b/arch/x86_64/src/memory/paging/virtual_page.cpp @@ -17,4 +17,17 @@ namespace teachos::arch::memory::paging { return (page_number >> (level * 9U)) & 0x1FF; } + + auto virtual_page::operator++(int) -> virtual_page + { + virtual_page const old_value = *this; + ++page_number; + return old_value; + } + + auto virtual_page::operator++() -> virtual_page & + { + ++page_number; + return *this; + } } // namespace teachos::arch::memory::paging -- cgit v1.2.3 From c291e1ed629489c418049f6c4116433636717636 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matteo=20Gm=C3=BCr?= Date: Sun, 24 Nov 2024 13:51:12 +0000 Subject: Add comments and rename file --- arch/x86_64/src/memory/heap/allocator.cpp | 27 -------------------------- arch/x86_64/src/memory/heap/bump_allocator.cpp | 26 +++++++++++++++++++++++++ arch/x86_64/src/memory/main.cpp | 2 +- 3 files changed, 27 insertions(+), 28 deletions(-) delete mode 100644 arch/x86_64/src/memory/heap/allocator.cpp create mode 100644 arch/x86_64/src/memory/heap/bump_allocator.cpp (limited to 'arch/x86_64/src/memory') diff --git a/arch/x86_64/src/memory/heap/allocator.cpp b/arch/x86_64/src/memory/heap/allocator.cpp deleted file mode 100644 index bb61be4..0000000 --- a/arch/x86_64/src/memory/heap/allocator.cpp +++ /dev/null @@ -1,27 +0,0 @@ -#include "arch/memory/heap/allocator.hpp" - -#include "arch/exception_handling/assert.hpp" - -namespace teachos::arch::memory::heap -{ - auto bump_allocator::allocate(std::size_t size) -> void * - { - // Uses some sort of alignment orignally: - // https://github.com/phil-opp/blog_os/blob/7f6576c9dc34e360b81236c54c25c7827fd6a2df/src/memory/heap_allocator.rs#L24 - auto alloc_start = next; - auto alloc_end = next + size; - - arch::exception_handling::assert(alloc_end <= heap_end, "[Heap Allocator] Out of memory!"); - - next = alloc_end; - return reinterpret_cast(alloc_start); - } - - auto bump_allocator::deallocate(uint8_t * pointer) -> void - { - // Not implemented; leaking memory - if (pointer) - { - } - } -} // namespace teachos::arch::memory::heap \ No newline at end of file diff --git a/arch/x86_64/src/memory/heap/bump_allocator.cpp b/arch/x86_64/src/memory/heap/bump_allocator.cpp new file mode 100644 index 0000000..486ece8 --- /dev/null +++ b/arch/x86_64/src/memory/heap/bump_allocator.cpp @@ -0,0 +1,26 @@ +#include "arch/memory/heap/bump_allocator.hpp" + +#include "arch/exception_handling/assert.hpp" + +namespace teachos::arch::memory::heap +{ + auto bump_allocator::allocate(std::size_t size) -> void * + { + // Uses some sort of alignment orignally: + // https://github.com/phil-opp/blog_os/blob/7f6576c9dc34e360b81236c54c25c7827fd6a2df/src/memory/heap_allocator.rs#L24 + auto alloc_start = next; + auto alloc_end = next + size; + + arch::exception_handling::assert(alloc_end <= heap_end, "[Heap Allocator] Out of memory!"); + + next = alloc_end; + return reinterpret_cast(alloc_start); + } + + auto bump_allocator::deallocate(uint8_t * pointer, std::size_t size) -> void + { + if (pointer || size) + { + } + } +} // namespace teachos::arch::memory::heap \ No newline at end of file diff --git a/arch/x86_64/src/memory/main.cpp b/arch/x86_64/src/memory/main.cpp index 80242cc..34ce113 100644 --- a/arch/x86_64/src/memory/main.cpp +++ b/arch/x86_64/src/memory/main.cpp @@ -4,7 +4,7 @@ #include "arch/memory/allocator/area_frame_allocator.hpp" #include "arch/memory/cpu/control_register.hpp" #include "arch/memory/cpu/msr.hpp" -#include "arch/memory/heap/allocator.hpp" +#include "arch/memory/heap/concept.hpp" #include "arch/memory/paging/active_page_table.hpp" #include "arch/memory/paging/kernel_mapper.hpp" -- cgit v1.2.3 From eada7bbb150fd81e6fbf71b1df28c8dc19393cfa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matteo=20Gm=C3=BCr?= Date: Sun, 24 Nov 2024 15:19:29 +0000 Subject: Adjust bump allocator comment --- arch/x86_64/src/memory/heap/bump_allocator.cpp | 2 -- 1 file changed, 2 deletions(-) (limited to 'arch/x86_64/src/memory') diff --git a/arch/x86_64/src/memory/heap/bump_allocator.cpp b/arch/x86_64/src/memory/heap/bump_allocator.cpp index 486ece8..1ab8ea9 100644 --- a/arch/x86_64/src/memory/heap/bump_allocator.cpp +++ b/arch/x86_64/src/memory/heap/bump_allocator.cpp @@ -6,8 +6,6 @@ namespace teachos::arch::memory::heap { auto bump_allocator::allocate(std::size_t size) -> void * { - // Uses some sort of alignment orignally: - // https://github.com/phil-opp/blog_os/blob/7f6576c9dc34e360b81236c54c25c7827fd6a2df/src/memory/heap_allocator.rs#L24 auto alloc_start = next; auto alloc_end = next + size; -- cgit v1.2.3 From d2aa4fbf948a56df5328e0f1b8ec3dfd52b16e13 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matteo=20Gm=C3=BCr?= Date: Tue, 26 Nov 2024 09:49:06 +0000 Subject: Make bump allocator atomic and therefore thread safe --- arch/x86_64/src/memory/heap/bump_allocator.cpp | 43 +++++++++++++++++++++----- 1 file changed, 35 insertions(+), 8 deletions(-) (limited to 'arch/x86_64/src/memory') diff --git a/arch/x86_64/src/memory/heap/bump_allocator.cpp b/arch/x86_64/src/memory/heap/bump_allocator.cpp index 1ab8ea9..19ced47 100644 --- a/arch/x86_64/src/memory/heap/bump_allocator.cpp +++ b/arch/x86_64/src/memory/heap/bump_allocator.cpp @@ -2,17 +2,43 @@ #include "arch/exception_handling/assert.hpp" +#include +#include + namespace teachos::arch::memory::heap { - auto bump_allocator::allocate(std::size_t size) -> void * + namespace { - auto alloc_start = next; - auto alloc_end = next + size; - - arch::exception_handling::assert(alloc_end <= heap_end, "[Heap Allocator] Out of memory!"); + template + auto saturating_add(T x, T y) -> T + requires std::is_unsigned_v + { + if (x > std::numeric_limits::max() - y) + { + return std::numeric_limits::max(); + } + T result = x + y; + return result; + } + } // namespace - next = alloc_end; - return reinterpret_cast(alloc_start); + auto bump_allocator::allocate(std::size_t size) -> void * + { + // Repeat allocation until it succeeds, has to be done, because another allocator could overtake it at any time + // causing the value to differ and the calculation to have to be redone. + for (;;) + { + auto alloc_start = next.load(std::memory_order::relaxed); + auto const alloc_end = saturating_add(alloc_start, size); + arch::exception_handling::assert(alloc_end <= heap_end, "[Heap Allocator] Out of memory"); + // Check if the atomic value is still the one initally loaded, if it isn't we have been overtaken by another + // thread and need to redo the calculation. + auto const updated = next.compare_exchange_strong(alloc_start, alloc_end, std::memory_order::relaxed); + if (updated) + { + return reinterpret_cast(alloc_start); + } + } } auto bump_allocator::deallocate(uint8_t * pointer, std::size_t size) -> void @@ -21,4 +47,5 @@ namespace teachos::arch::memory::heap { } } -} // namespace teachos::arch::memory::heap \ No newline at end of file + +} // namespace teachos::arch::memory::heap -- cgit v1.2.3 From a4268440d5c77f39032bb9f003aafd7fef2ca997 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matteo=20Gm=C3=BCr?= Date: Tue, 26 Nov 2024 11:09:59 +0000 Subject: Replace strong with weak compare_exchange --- arch/x86_64/src/memory/heap/bump_allocator.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'arch/x86_64/src/memory') diff --git a/arch/x86_64/src/memory/heap/bump_allocator.cpp b/arch/x86_64/src/memory/heap/bump_allocator.cpp index 19ced47..8807645 100644 --- a/arch/x86_64/src/memory/heap/bump_allocator.cpp +++ b/arch/x86_64/src/memory/heap/bump_allocator.cpp @@ -32,8 +32,9 @@ namespace teachos::arch::memory::heap auto const alloc_end = saturating_add(alloc_start, size); arch::exception_handling::assert(alloc_end <= heap_end, "[Heap Allocator] Out of memory"); // Check if the atomic value is still the one initally loaded, if it isn't we have been overtaken by another - // thread and need to redo the calculation. - auto const updated = next.compare_exchange_strong(alloc_start, alloc_end, std::memory_order::relaxed); + // thread and need to redo the calculation. Spurious failure by weak can be ignored, because the whole allocation + // is wrapped in an infinite for loop so a failure that wasn't actually one will simply be retried until it works. + auto const updated = next.compare_exchange_weak(alloc_start, alloc_end, std::memory_order::relaxed); if (updated) { return reinterpret_cast(alloc_start); -- cgit v1.2.3 From 31796138b1c85e7b3236055b6d93d568e1fe8a81 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matteo=20Gm=C3=BCr?= Date: Thu, 28 Nov 2024 12:40:04 +0000 Subject: Create base of linked list allocator --- arch/x86_64/src/memory/heap/linked_list_allocator.cpp | 16 ++++++++++++++++ arch/x86_64/src/memory/heap/memory_hole.cpp | 11 +++++++++++ 2 files changed, 27 insertions(+) create mode 100644 arch/x86_64/src/memory/heap/linked_list_allocator.cpp create mode 100644 arch/x86_64/src/memory/heap/memory_hole.cpp (limited to 'arch/x86_64/src/memory') diff --git a/arch/x86_64/src/memory/heap/linked_list_allocator.cpp b/arch/x86_64/src/memory/heap/linked_list_allocator.cpp new file mode 100644 index 0000000..b0f011b --- /dev/null +++ b/arch/x86_64/src/memory/heap/linked_list_allocator.cpp @@ -0,0 +1,16 @@ +#include "arch/memory/heap/linked_list_allocator.hpp" + +#include "arch/exception_handling/assert.hpp" + +namespace teachos::arch::memory::heap +{ + linked_list_allocator::linked_list_allocator(std::size_t heap_start, std::size_t heap_end) + : heap_start(heap_start) + , heap_end(heap_end) + , first(heap_end - heap_start, nullptr) + { + exception_handling::assert(heap_end - heap_start < min_allocatable_size(), + "[Memory Hole List] Total heap size can not be smaller than minimum of 16 bytes to hold " + "atleast one memory hole entry"); + } +} // namespace teachos::arch::memory::heap diff --git a/arch/x86_64/src/memory/heap/memory_hole.cpp b/arch/x86_64/src/memory/heap/memory_hole.cpp new file mode 100644 index 0000000..7590610 --- /dev/null +++ b/arch/x86_64/src/memory/heap/memory_hole.cpp @@ -0,0 +1,11 @@ +#include "arch/memory/heap/memory_hole.hpp" + +namespace teachos::arch::memory::heap +{ + memory_hole::memory_hole(std::size_t size, memory_hole * next) + : size(size) + , next(next) + { + // Nothing to do + } +} // namespace teachos::arch::memory::heap -- cgit v1.2.3 From d3e4df4dd4ee117e247f78a86746bf178787bc8f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matteo=20Gm=C3=BCr?= Date: Thu, 28 Nov 2024 13:53:01 +0000 Subject: Start with linked list alloc and dealloc --- .../src/memory/heap/linked_list_allocator.cpp | 27 ++++++++++++++++++++++ 1 file changed, 27 insertions(+) (limited to 'arch/x86_64/src/memory') diff --git a/arch/x86_64/src/memory/heap/linked_list_allocator.cpp b/arch/x86_64/src/memory/heap/linked_list_allocator.cpp index b0f011b..006d9c7 100644 --- a/arch/x86_64/src/memory/heap/linked_list_allocator.cpp +++ b/arch/x86_64/src/memory/heap/linked_list_allocator.cpp @@ -2,6 +2,8 @@ #include "arch/exception_handling/assert.hpp" +#include + namespace teachos::arch::memory::heap { linked_list_allocator::linked_list_allocator(std::size_t heap_start, std::size_t heap_end) @@ -13,4 +15,29 @@ namespace teachos::arch::memory::heap "[Memory Hole List] Total heap size can not be smaller than minimum of 16 bytes to hold " "atleast one memory hole entry"); } + + auto linked_list_allocator::allocate(std::size_t size) -> void * + { + if (first.next == nullptr || size) + { + } + return nullptr; + } + + auto linked_list_allocator::deallocate(uint8_t * pointer, std::size_t size) -> void + { + auto const deallocate_size = std::max(size, min_allocatable_size()); + if (pointer || deallocate_size) + { + } + } + + auto split_hole(memory_hole & current_hole, memory_hole *& new_hole) -> void * + { + if (new_hole) + { + } + return static_cast(¤t_hole); + } + } // namespace teachos::arch::memory::heap -- cgit v1.2.3 From 9af867de0050eef28772f7dee799666ae343950e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matteo=20Gm=C3=BCr?= Date: Thu, 28 Nov 2024 14:33:42 +0000 Subject: Start imlementation on actual algorithm --- .../src/memory/heap/linked_list_allocator.cpp | 44 ++++++++++++++++------ 1 file changed, 33 insertions(+), 11 deletions(-) (limited to 'arch/x86_64/src/memory') diff --git a/arch/x86_64/src/memory/heap/linked_list_allocator.cpp b/arch/x86_64/src/memory/heap/linked_list_allocator.cpp index 006d9c7..f4ba5e2 100644 --- a/arch/x86_64/src/memory/heap/linked_list_allocator.cpp +++ b/arch/x86_64/src/memory/heap/linked_list_allocator.cpp @@ -1,6 +1,7 @@ #include "arch/memory/heap/linked_list_allocator.hpp" #include "arch/exception_handling/assert.hpp" +#include "arch/exception_handling/panic.hpp" #include @@ -9,19 +10,39 @@ namespace teachos::arch::memory::heap linked_list_allocator::linked_list_allocator(std::size_t heap_start, std::size_t heap_end) : heap_start(heap_start) , heap_end(heap_end) - , first(heap_end - heap_start, nullptr) + , first(nullptr) { - exception_handling::assert(heap_end - heap_start < min_allocatable_size(), - "[Memory Hole List] Total heap size can not be smaller than minimum of 16 bytes to hold " - "atleast one memory hole entry"); + auto const heap_size = heap_end - heap_start; + exception_handling::assert( + heap_size < min_allocatable_size(), + "[Linked List Allocator] Total heap size can not be smaller than minimum of 16 bytes to hold " + "atleast one memory hole entry"); + first = new (reinterpret_cast(heap_start)) memory_hole(heap_size, nullptr); } auto linked_list_allocator::allocate(std::size_t size) -> void * { - if (first.next == nullptr || size) + memory_hole * previous = nullptr; + auto current = first; + while (current != nullptr) { + if (current->size > size) + { + return split_hole(current, size); + } + else if (current->size == size) + { + if (previous != nullptr) + { + previous->next = current->next; + } + delete current; + return static_cast(current); + } + previous = current; + current = current->next; } - return nullptr; + exception_handling::panic("[Linked List Allocator] Out of memory"); } auto linked_list_allocator::deallocate(uint8_t * pointer, std::size_t size) -> void @@ -32,12 +53,13 @@ namespace teachos::arch::memory::heap } } - auto split_hole(memory_hole & current_hole, memory_hole *& new_hole) -> void * + auto split_hole(memory_hole *& current_hole, std::size_t size) -> void * { - if (new_hole) - { - } - return static_cast(¤t_hole); + auto const previous_address = reinterpret_cast(current_hole); + auto const new_address = previous_address + size; + current_hole = + new (reinterpret_cast(new_address)) memory_hole(current_hole->size - size, current_hole->next); + return reinterpret_cast(previous_address); } } // namespace teachos::arch::memory::heap -- cgit v1.2.3 From 318fbff1717b291c81db8f9c4d5a84019fe2b4b9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matteo=20Gm=C3=BCr?= Date: Sun, 1 Dec 2024 10:21:17 +0000 Subject: Adjust allocate --- arch/x86_64/src/memory/heap/linked_list_allocator.cpp | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) (limited to 'arch/x86_64/src/memory') diff --git a/arch/x86_64/src/memory/heap/linked_list_allocator.cpp b/arch/x86_64/src/memory/heap/linked_list_allocator.cpp index f4ba5e2..a2a8c79 100644 --- a/arch/x86_64/src/memory/heap/linked_list_allocator.cpp +++ b/arch/x86_64/src/memory/heap/linked_list_allocator.cpp @@ -22,8 +22,8 @@ namespace teachos::arch::memory::heap auto linked_list_allocator::allocate(std::size_t size) -> void * { - memory_hole * previous = nullptr; - auto current = first; + auto & previous = first; + auto & current = first; while (current != nullptr) { if (current->size > size) @@ -32,10 +32,14 @@ namespace teachos::arch::memory::heap } else if (current->size == size) { - if (previous != nullptr) + if (previous != current) { previous->next = current->next; } + else + { + current = current->next; + } delete current; return static_cast(current); } -- cgit v1.2.3 From eba6c94eed15b90ea8a09e4bc16ae1c0f1645dea Mon Sep 17 00:00:00 2001 From: Fabian Imhof Date: Sun, 1 Dec 2024 11:08:00 +0000 Subject: implement first half of linked list dallocation --- arch/x86_64/src/memory/heap/bump_allocator.cpp | 2 +- .../src/memory/heap/linked_list_allocator.cpp | 55 +++++++++++++++++----- arch/x86_64/src/memory/heap/memory_block.cpp | 11 +++++ arch/x86_64/src/memory/heap/memory_hole.cpp | 11 ----- 4 files changed, 56 insertions(+), 23 deletions(-) create mode 100644 arch/x86_64/src/memory/heap/memory_block.cpp delete mode 100644 arch/x86_64/src/memory/heap/memory_hole.cpp (limited to 'arch/x86_64/src/memory') diff --git a/arch/x86_64/src/memory/heap/bump_allocator.cpp b/arch/x86_64/src/memory/heap/bump_allocator.cpp index 8807645..bbf2021 100644 --- a/arch/x86_64/src/memory/heap/bump_allocator.cpp +++ b/arch/x86_64/src/memory/heap/bump_allocator.cpp @@ -42,7 +42,7 @@ namespace teachos::arch::memory::heap } } - auto bump_allocator::deallocate(uint8_t * pointer, std::size_t size) -> void + auto bump_allocator::deallocate(void * pointer, std::size_t size) -> void { if (pointer || size) { diff --git a/arch/x86_64/src/memory/heap/linked_list_allocator.cpp b/arch/x86_64/src/memory/heap/linked_list_allocator.cpp index a2a8c79..9b27f70 100644 --- a/arch/x86_64/src/memory/heap/linked_list_allocator.cpp +++ b/arch/x86_64/src/memory/heap/linked_list_allocator.cpp @@ -17,20 +17,24 @@ namespace teachos::arch::memory::heap heap_size < min_allocatable_size(), "[Linked List Allocator] Total heap size can not be smaller than minimum of 16 bytes to hold " "atleast one memory hole entry"); - first = new (reinterpret_cast(heap_start)) memory_hole(heap_size, nullptr); + first = new (reinterpret_cast(heap_start)) memory_block(heap_size, nullptr); } auto linked_list_allocator::allocate(std::size_t size) -> void * { + exception_handling::assert(size < min_allocatable_size(), + "[Linked List Allocator] Allocated memory cannot be smaller than 16 bytes"); + auto & previous = first; auto & current = first; + while (current != nullptr) { - if (current->size > size) + if (current->size >= size + min_allocatable_size()) { - return split_hole(current, size); + return split_free_memory_block(current, size); } - else if (current->size == size) + else if (current->size >= size) { if (previous != current) { @@ -40,30 +44,59 @@ namespace teachos::arch::memory::heap { current = current->next; } + delete current; return static_cast(current); } + previous = current; current = current->next; } exception_handling::panic("[Linked List Allocator] Out of memory"); } - auto linked_list_allocator::deallocate(uint8_t * pointer, std::size_t size) -> void + auto linked_list_allocator::deallocate(void * pointer, std::size_t size) -> void { - auto const deallocate_size = std::max(size, min_allocatable_size()); - if (pointer || deallocate_size) + exception_handling::assert(size < min_allocatable_size(), + "[Linked List Allocator] Allocated memory cannot be smaller than 16 bytes"); + + auto & previous = first; + auto & current = first; + + while (current != nullptr) { + // if pointer + size < current + // create memory block + auto const previous_address = reinterpret_cast(pointer); + auto const new_address = previous_address + size; + + if (new_address != reinterpret_cast(current) && + previous_address != (reinterpret_cast(previous) + previous->size)) + { + auto new_block = new (pointer) memory_block(size, current); + previous->next = new_block; + return; + } + + // elseif pointer + size == current + // combine memory block with current + // combine(previous, pointer, current) + + previous = current; + current = current->next; } } - auto split_hole(memory_hole *& current_hole, std::size_t size) -> void * + auto linked_list_allocator::split_free_memory_block(memory_block *& current_block, std::size_t size) -> void * { - auto const previous_address = reinterpret_cast(current_hole); + auto const previous_address = reinterpret_cast(current_block); auto const new_address = previous_address + size; - current_hole = - new (reinterpret_cast(new_address)) memory_hole(current_hole->size - size, current_hole->next); + current_block = + new (reinterpret_cast(new_address)) memory_block(current_block->size - size, current_block->next); return reinterpret_cast(previous_address); } + // auto linked_list_allocator::combine_free_memory_block(memory_block *& previous_block, memory_block *& + // current_block, std::size_t size) -> void * + } // namespace teachos::arch::memory::heap diff --git a/arch/x86_64/src/memory/heap/memory_block.cpp b/arch/x86_64/src/memory/heap/memory_block.cpp new file mode 100644 index 0000000..b68dd6d --- /dev/null +++ b/arch/x86_64/src/memory/heap/memory_block.cpp @@ -0,0 +1,11 @@ +#include "arch/memory/heap/memory_block.hpp" + +namespace teachos::arch::memory::heap +{ + memory_block::memory_block(std::size_t size, memory_block * next) + : size(size) + , next(next) + { + // Nothing to do + } +} // namespace teachos::arch::memory::heap diff --git a/arch/x86_64/src/memory/heap/memory_hole.cpp b/arch/x86_64/src/memory/heap/memory_hole.cpp deleted file mode 100644 index 7590610..0000000 --- a/arch/x86_64/src/memory/heap/memory_hole.cpp +++ /dev/null @@ -1,11 +0,0 @@ -#include "arch/memory/heap/memory_hole.hpp" - -namespace teachos::arch::memory::heap -{ - memory_hole::memory_hole(std::size_t size, memory_hole * next) - : size(size) - , next(next) - { - // Nothing to do - } -} // namespace teachos::arch::memory::heap -- cgit v1.2.3 From b8fd52b6b3a7f002cff58ff8da0313a684cb3ab4 Mon Sep 17 00:00:00 2001 From: Fabian Imhof Date: Sun, 1 Dec 2024 11:44:30 +0000 Subject: implement heap linked_list deallocate --- .../src/memory/heap/linked_list_allocator.cpp | 64 +++++++++++++++------- 1 file changed, 43 insertions(+), 21 deletions(-) (limited to 'arch/x86_64/src/memory') diff --git a/arch/x86_64/src/memory/heap/linked_list_allocator.cpp b/arch/x86_64/src/memory/heap/linked_list_allocator.cpp index 9b27f70..3330399 100644 --- a/arch/x86_64/src/memory/heap/linked_list_allocator.cpp +++ b/arch/x86_64/src/memory/heap/linked_list_allocator.cpp @@ -60,43 +60,65 @@ namespace teachos::arch::memory::heap exception_handling::assert(size < min_allocatable_size(), "[Linked List Allocator] Allocated memory cannot be smaller than 16 bytes"); + auto const start_address = reinterpret_cast(pointer); + auto const end_address = start_address + size; + auto & previous = first; auto & current = first; while (current != nullptr) { - // if pointer + size < current - // create memory block - auto const previous_address = reinterpret_cast(pointer); - auto const new_address = previous_address + size; - - if (new_address != reinterpret_cast(current) && - previous_address != (reinterpret_cast(previous) + previous->size)) + if (reinterpret_cast(current) >= end_address) { - auto new_block = new (pointer) memory_block(size, current); - previous->next = new_block; - return; + break; } - // elseif pointer + size == current - // combine memory block with current - // combine(previous, pointer, current) - - previous = current; + previous->next = current; current = current->next; } + + coalesce_free_memory_block(previous, current, pointer, size); } auto linked_list_allocator::split_free_memory_block(memory_block *& current_block, std::size_t size) -> void * { - auto const previous_address = reinterpret_cast(current_block); - auto const new_address = previous_address + size; + auto const start_address = reinterpret_cast(current_block); + auto const end_address = start_address + size; current_block = - new (reinterpret_cast(new_address)) memory_block(current_block->size - size, current_block->next); - return reinterpret_cast(previous_address); + new (reinterpret_cast(end_address)) memory_block(current_block->size - size, current_block->next); + return reinterpret_cast(start_address); } - // auto linked_list_allocator::combine_free_memory_block(memory_block *& previous_block, memory_block *& - // current_block, std::size_t size) -> void * + auto linked_list_allocator::coalesce_free_memory_block(memory_block *& previous_block, memory_block *& current_block, + void * pointer, std::size_t size) -> void * + { + auto const start_address = reinterpret_cast(pointer); + auto const end_address = start_address + size; + + auto block_size = size; + auto new_block_address = pointer; + auto next_block = current_block; + + // If free memory block after block to deallocate is adjacent + if (end_address == reinterpret_cast(current_block)) + { + block_size += current_block->size; + next_block = current_block->next; + + delete current_block; + } + + // If free memory block before block to deallocate is adjacent + if (start_address == (reinterpret_cast(previous_block) + previous_block->size)) + { + block_size += previous_block->size; + + previous_block->size = block_size; + previous_block->next = next_block; + return; + } + + new (reinterpret_cast(new_block_address)) memory_block(block_size, next_block); + } } // namespace teachos::arch::memory::heap -- cgit v1.2.3 From 2671b9522db44418536559524a22c95d3575569e Mon Sep 17 00:00:00 2001 From: Fabian Imhof Date: Sun, 1 Dec 2024 12:07:42 +0000 Subject: enable heap test --- arch/x86_64/src/memory/heap/linked_list_allocator.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'arch/x86_64/src/memory') diff --git a/arch/x86_64/src/memory/heap/linked_list_allocator.cpp b/arch/x86_64/src/memory/heap/linked_list_allocator.cpp index 3330399..98a936c 100644 --- a/arch/x86_64/src/memory/heap/linked_list_allocator.cpp +++ b/arch/x86_64/src/memory/heap/linked_list_allocator.cpp @@ -90,13 +90,12 @@ namespace teachos::arch::memory::heap } auto linked_list_allocator::coalesce_free_memory_block(memory_block *& previous_block, memory_block *& current_block, - void * pointer, std::size_t size) -> void * + void * pointer, std::size_t size) -> void { auto const start_address = reinterpret_cast(pointer); auto const end_address = start_address + size; auto block_size = size; - auto new_block_address = pointer; auto next_block = current_block; // If free memory block after block to deallocate is adjacent @@ -118,7 +117,7 @@ namespace teachos::arch::memory::heap return; } - new (reinterpret_cast(new_block_address)) memory_block(block_size, next_block); + new (reinterpret_cast(pointer)) memory_block(block_size, next_block); } } // namespace teachos::arch::memory::heap -- cgit v1.2.3 From 0cf972394e99dfa69fbaf2ec9f4c718fd36bbc3e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matteo=20Gm=C3=BCr?= Date: Sun, 1 Dec 2024 12:38:38 +0000 Subject: Add comments and fix edge case --- .../src/memory/heap/linked_list_allocator.cpp | 23 +++++++++++++++++++--- 1 file changed, 20 insertions(+), 3 deletions(-) (limited to 'arch/x86_64/src/memory') diff --git a/arch/x86_64/src/memory/heap/linked_list_allocator.cpp b/arch/x86_64/src/memory/heap/linked_list_allocator.cpp index 98a936c..63a762e 100644 --- a/arch/x86_64/src/memory/heap/linked_list_allocator.cpp +++ b/arch/x86_64/src/memory/heap/linked_list_allocator.cpp @@ -68,6 +68,8 @@ namespace teachos::arch::memory::heap while (current != nullptr) { + // Current address of the free memory block now points to an address that is after our block to deallocate in heap + // memory space. if (reinterpret_cast(current) >= end_address) { break; @@ -95,10 +97,22 @@ namespace teachos::arch::memory::heap auto const start_address = reinterpret_cast(pointer); auto const end_address = start_address + size; + // Inital values if there are no adjacent blocks either before or after, meaning we have to simply create a free + // memory block that is placed in between the previous and next block. auto block_size = size; auto next_block = current_block; - // If free memory block after block to deallocate is adjacent + // Heap memory has been completly used up and therefore the inital free pointer is null and this deallocation will + // result in the first inital pointer in our linked list of free memory blocks. + if (previous_block == nullptr) + { + previous_block = new (pointer) memory_block(block_size, next_block); + return; + } + + // If the block we want to deallocate is before another free block and we can therefore combine both into one. + // This is done by deleting the current free block and creating a new block at the start address of the block to + // deallocate with both the size of the block to deallcoate and the free block next to it. if (end_address == reinterpret_cast(current_block)) { block_size += current_block->size; @@ -107,7 +121,9 @@ namespace teachos::arch::memory::heap delete current_block; } - // If free memory block before block to deallocate is adjacent + // If the block we want to deallocate is behind another free block and we can therefore combine both into one. + // This is done by simply changin the size of the previous block to include the size of the block to deallocate. + // This is done, because the previous block might still be referencered by the next field of other memory blocks. if (start_address == (reinterpret_cast(previous_block) + previous_block->size)) { block_size += previous_block->size; @@ -117,7 +133,8 @@ namespace teachos::arch::memory::heap return; } - new (reinterpret_cast(pointer)) memory_block(block_size, next_block); + auto const new_block = new (pointer) memory_block(block_size, next_block); + previous_block->next = new_block; } } // namespace teachos::arch::memory::heap -- cgit v1.2.3 From 9072c2a277c0da298b977cf4fb3dbebb5481abd0 Mon Sep 17 00:00:00 2001 From: Fabian Imhof Date: Sun, 1 Dec 2024 13:34:46 +0000 Subject: implement clear_memory_block_header --- .../src/memory/heap/linked_list_allocator.cpp | 22 +++++++++++++++------- 1 file changed, 15 insertions(+), 7 deletions(-) (limited to 'arch/x86_64/src/memory') diff --git a/arch/x86_64/src/memory/heap/linked_list_allocator.cpp b/arch/x86_64/src/memory/heap/linked_list_allocator.cpp index 63a762e..07d7e5e 100644 --- a/arch/x86_64/src/memory/heap/linked_list_allocator.cpp +++ b/arch/x86_64/src/memory/heap/linked_list_allocator.cpp @@ -3,6 +3,8 @@ #include "arch/exception_handling/assert.hpp" #include "arch/exception_handling/panic.hpp" +#include + #include namespace teachos::arch::memory::heap @@ -14,7 +16,7 @@ namespace teachos::arch::memory::heap { auto const heap_size = heap_end - heap_start; exception_handling::assert( - heap_size < min_allocatable_size(), + heap_size > min_allocatable_size(), "[Linked List Allocator] Total heap size can not be smaller than minimum of 16 bytes to hold " "atleast one memory hole entry"); first = new (reinterpret_cast(heap_start)) memory_block(heap_size, nullptr); @@ -22,7 +24,7 @@ namespace teachos::arch::memory::heap auto linked_list_allocator::allocate(std::size_t size) -> void * { - exception_handling::assert(size < min_allocatable_size(), + exception_handling::assert(size > min_allocatable_size(), "[Linked List Allocator] Allocated memory cannot be smaller than 16 bytes"); auto & previous = first; @@ -34,7 +36,8 @@ namespace teachos::arch::memory::heap { return split_free_memory_block(current, size); } - else if (current->size >= size) + + if (current->size >= size) { if (previous != current) { @@ -42,10 +45,10 @@ namespace teachos::arch::memory::heap } else { - current = current->next; + first = current->next; } - delete current; + clear_memory_block_header(current); return static_cast(current); } @@ -57,7 +60,7 @@ namespace teachos::arch::memory::heap auto linked_list_allocator::deallocate(void * pointer, std::size_t size) -> void { - exception_handling::assert(size < min_allocatable_size(), + exception_handling::assert(size > min_allocatable_size(), "[Linked List Allocator] Allocated memory cannot be smaller than 16 bytes"); auto const start_address = reinterpret_cast(pointer); @@ -118,7 +121,7 @@ namespace teachos::arch::memory::heap block_size += current_block->size; next_block = current_block->next; - delete current_block; + clear_memory_block_header(current_block); } // If the block we want to deallocate is behind another free block and we can therefore combine both into one. @@ -137,4 +140,9 @@ namespace teachos::arch::memory::heap previous_block->next = new_block; } + auto linked_list_allocator::clear_memory_block_header(void * pointer) -> void + { + memset(pointer, 0, min_allocatable_size()); + } + } // namespace teachos::arch::memory::heap -- cgit v1.2.3 From a5e5eabd32872f81a7190589aa648dc0e1963888 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matteo=20Gm=C3=BCr?= Date: Mon, 2 Dec 2024 10:17:36 +0000 Subject: Fix algorithm issues with linked list allocator --- .../src/memory/heap/linked_list_allocator.cpp | 64 +++++++++++----------- 1 file changed, 31 insertions(+), 33 deletions(-) (limited to 'arch/x86_64/src/memory') diff --git a/arch/x86_64/src/memory/heap/linked_list_allocator.cpp b/arch/x86_64/src/memory/heap/linked_list_allocator.cpp index 07d7e5e..706f43e 100644 --- a/arch/x86_64/src/memory/heap/linked_list_allocator.cpp +++ b/arch/x86_64/src/memory/heap/linked_list_allocator.cpp @@ -27,29 +27,14 @@ namespace teachos::arch::memory::heap exception_handling::assert(size > min_allocatable_size(), "[Linked List Allocator] Allocated memory cannot be smaller than 16 bytes"); - auto & previous = first; - auto & current = first; + memory_block * previous = nullptr; + auto current = first; while (current != nullptr) { if (current->size >= size + min_allocatable_size()) { - return split_free_memory_block(current, size); - } - - if (current->size >= size) - { - if (previous != current) - { - previous->next = current->next; - } - else - { - first = current->next; - } - - clear_memory_block_header(current); - return static_cast(current); + return split_free_memory_block(previous, current, size); } previous = current; @@ -66,8 +51,8 @@ namespace teachos::arch::memory::heap auto const start_address = reinterpret_cast(pointer); auto const end_address = start_address + size; - auto & previous = first; - auto & current = first; + memory_block * previous = nullptr; + auto current = first; while (current != nullptr) { @@ -78,23 +63,35 @@ namespace teachos::arch::memory::heap break; } - previous->next = current; + previous = current; current = current->next; } coalesce_free_memory_block(previous, current, pointer, size); } - auto linked_list_allocator::split_free_memory_block(memory_block *& current_block, std::size_t size) -> void * + auto linked_list_allocator::split_free_memory_block(memory_block * previous_block, memory_block * current_block, + std::size_t size) -> void * { auto const start_address = reinterpret_cast(current_block); auto const end_address = start_address + size; - current_block = + auto const new_block = new (reinterpret_cast(end_address)) memory_block(current_block->size - size, current_block->next); + // If we want to allocate into the first block that is before any other free block, then there exists no previous + // free block (nullptr). Therefore we have to overwrite the first block instead of overwriting its next value. + if (previous_block == nullptr) + { + first = new_block; + } + else + { + previous_block->next = new_block; + } + clear_memory_block_header(current_block); return reinterpret_cast(start_address); } - auto linked_list_allocator::coalesce_free_memory_block(memory_block *& previous_block, memory_block *& current_block, + auto linked_list_allocator::coalesce_free_memory_block(memory_block * previous_block, memory_block * current_block, void * pointer, std::size_t size) -> void { auto const start_address = reinterpret_cast(pointer); @@ -105,14 +102,6 @@ namespace teachos::arch::memory::heap auto block_size = size; auto next_block = current_block; - // Heap memory has been completly used up and therefore the inital free pointer is null and this deallocation will - // result in the first inital pointer in our linked list of free memory blocks. - if (previous_block == nullptr) - { - previous_block = new (pointer) memory_block(block_size, next_block); - return; - } - // If the block we want to deallocate is before another free block and we can therefore combine both into one. // This is done by deleting the current free block and creating a new block at the start address of the block to // deallocate with both the size of the block to deallcoate and the free block next to it. @@ -127,7 +116,8 @@ namespace teachos::arch::memory::heap // If the block we want to deallocate is behind another free block and we can therefore combine both into one. // This is done by simply changin the size of the previous block to include the size of the block to deallocate. // This is done, because the previous block might still be referencered by the next field of other memory blocks. - if (start_address == (reinterpret_cast(previous_block) + previous_block->size)) + if (previous_block != nullptr && + start_address == (reinterpret_cast(previous_block) + previous_block->size)) { block_size += previous_block->size; @@ -137,6 +127,14 @@ namespace teachos::arch::memory::heap } auto const new_block = new (pointer) memory_block(block_size, next_block); + // If we want to deallocate the first block that is before any other free block, then there exists no previous free + // block (nullptr). Therefore we have to overwrite the first block instead of overwriting its + // next value. + if (previous_block == nullptr) + { + first = new_block; + return; + } previous_block->next = new_block; } -- cgit v1.2.3 From aa4de534ec7bf0b609aff032c4649484aa49823c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matteo=20Gm=C3=BCr?= Date: Mon, 2 Dec 2024 11:14:43 +0000 Subject: Add check to detect double free in linked list allocator --- arch/x86_64/src/memory/heap/linked_list_allocator.cpp | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'arch/x86_64/src/memory') diff --git a/arch/x86_64/src/memory/heap/linked_list_allocator.cpp b/arch/x86_64/src/memory/heap/linked_list_allocator.cpp index 706f43e..f596f27 100644 --- a/arch/x86_64/src/memory/heap/linked_list_allocator.cpp +++ b/arch/x86_64/src/memory/heap/linked_list_allocator.cpp @@ -126,6 +126,13 @@ namespace teachos::arch::memory::heap return; } + // Check if the block we want to deallocate is contained in the previous block, because if it is it can only mean + // that the block has already been deallocated and we therefore attempted a double free. + exception_handling::assert(previous_block == nullptr || + start_address >= + (reinterpret_cast(previous_block) + previous_block->size), + "[Linked List Allocator] Attempted double free detected"); + auto const new_block = new (pointer) memory_block(block_size, next_block); // If we want to deallocate the first block that is before any other free block, then there exists no previous free // block (nullptr). Therefore we have to overwrite the first block instead of overwriting its -- cgit v1.2.3 From dcd83b71c833e86c7e00e2b8f75ab6208b5d360d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matteo=20Gm=C3=BCr?= Date: Mon, 2 Dec 2024 13:51:58 +0000 Subject: WIP thread safe linked list --- arch/x86_64/src/memory/heap/linked_list_allocator.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'arch/x86_64/src/memory') diff --git a/arch/x86_64/src/memory/heap/linked_list_allocator.cpp b/arch/x86_64/src/memory/heap/linked_list_allocator.cpp index f596f27..22b5757 100644 --- a/arch/x86_64/src/memory/heap/linked_list_allocator.cpp +++ b/arch/x86_64/src/memory/heap/linked_list_allocator.cpp @@ -28,7 +28,7 @@ namespace teachos::arch::memory::heap "[Linked List Allocator] Allocated memory cannot be smaller than 16 bytes"); memory_block * previous = nullptr; - auto current = first; + auto current = first.load(std::memory_order::relaxed); while (current != nullptr) { @@ -52,7 +52,7 @@ namespace teachos::arch::memory::heap auto const end_address = start_address + size; memory_block * previous = nullptr; - auto current = first; + auto current = first.load(std::memory_order::relaxed); while (current != nullptr) { @@ -81,11 +81,11 @@ namespace teachos::arch::memory::heap // free block (nullptr). Therefore we have to overwrite the first block instead of overwriting its next value. if (previous_block == nullptr) { - first = new_block; + first.compare_exchange_weak(previous_block, new_block, std::memory_order::relaxed); } else { - previous_block->next = new_block; + previous_block->next.compare_exchange_weak(current_block, new_block, std::memory_order::relaxed); } clear_memory_block_header(current_block); return reinterpret_cast(start_address); -- cgit v1.2.3 From b4962c8c7b94fce2e67a00671de87fa96fdbb659 Mon Sep 17 00:00:00 2001 From: Fabian Imhof Date: Tue, 3 Dec 2024 08:00:26 +0000 Subject: add mutex to linked_list_allocator --- arch/x86_64/src/memory/heap/linked_list_allocator.cpp | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) (limited to 'arch/x86_64/src/memory') diff --git a/arch/x86_64/src/memory/heap/linked_list_allocator.cpp b/arch/x86_64/src/memory/heap/linked_list_allocator.cpp index 22b5757..01838f9 100644 --- a/arch/x86_64/src/memory/heap/linked_list_allocator.cpp +++ b/arch/x86_64/src/memory/heap/linked_list_allocator.cpp @@ -13,6 +13,7 @@ namespace teachos::arch::memory::heap : heap_start(heap_start) , heap_end(heap_end) , first(nullptr) + , mutex{shared::mutex{}} { auto const heap_size = heap_end - heap_start; exception_handling::assert( @@ -26,9 +27,10 @@ namespace teachos::arch::memory::heap { exception_handling::assert(size > min_allocatable_size(), "[Linked List Allocator] Allocated memory cannot be smaller than 16 bytes"); + mutex.lock(); memory_block * previous = nullptr; - auto current = first.load(std::memory_order::relaxed); + auto current = first; while (current != nullptr) { @@ -40,6 +42,8 @@ namespace teachos::arch::memory::heap previous = current; current = current->next; } + + mutex.unlock(); exception_handling::panic("[Linked List Allocator] Out of memory"); } @@ -47,12 +51,13 @@ namespace teachos::arch::memory::heap { exception_handling::assert(size > min_allocatable_size(), "[Linked List Allocator] Allocated memory cannot be smaller than 16 bytes"); + mutex.lock(); auto const start_address = reinterpret_cast(pointer); auto const end_address = start_address + size; memory_block * previous = nullptr; - auto current = first.load(std::memory_order::relaxed); + auto current = first; while (current != nullptr) { @@ -68,6 +73,7 @@ namespace teachos::arch::memory::heap } coalesce_free_memory_block(previous, current, pointer, size); + mutex.unlock(); } auto linked_list_allocator::split_free_memory_block(memory_block * previous_block, memory_block * current_block, @@ -81,11 +87,11 @@ namespace teachos::arch::memory::heap // free block (nullptr). Therefore we have to overwrite the first block instead of overwriting its next value. if (previous_block == nullptr) { - first.compare_exchange_weak(previous_block, new_block, std::memory_order::relaxed); + first = new_block; } else { - previous_block->next.compare_exchange_weak(current_block, new_block, std::memory_order::relaxed); + previous_block = new_block; } clear_memory_block_header(current_block); return reinterpret_cast(start_address); -- cgit v1.2.3 From 45e36abbd404ba0c4137d0b989f3774af9ac9e3c Mon Sep 17 00:00:00 2001 From: Fabian Imhof Date: Tue, 3 Dec 2024 08:10:33 +0000 Subject: fix linked_list_allocator mutex usage --- arch/x86_64/src/memory/heap/linked_list_allocator.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'arch/x86_64/src/memory') diff --git a/arch/x86_64/src/memory/heap/linked_list_allocator.cpp b/arch/x86_64/src/memory/heap/linked_list_allocator.cpp index 01838f9..1c5c443 100644 --- a/arch/x86_64/src/memory/heap/linked_list_allocator.cpp +++ b/arch/x86_64/src/memory/heap/linked_list_allocator.cpp @@ -36,14 +36,15 @@ namespace teachos::arch::memory::heap { if (current->size >= size + min_allocatable_size()) { - return split_free_memory_block(previous, current, size); + auto memory_address = split_free_memory_block(previous, current, size); + mutex.unlock(); + return memory_address; } previous = current; current = current->next; } - mutex.unlock(); exception_handling::panic("[Linked List Allocator] Out of memory"); } -- cgit v1.2.3 From e6da0a1b12a3e777bd54e4b22b6a873a4c5fe195 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matteo=20Gm=C3=BCr?= Date: Tue, 3 Dec 2024 08:19:24 +0000 Subject: Add allocate case where size fits exactly --- .../src/memory/heap/linked_list_allocator.cpp | 26 ++++++++++++++++++++-- 1 file changed, 24 insertions(+), 2 deletions(-) (limited to 'arch/x86_64/src/memory') diff --git a/arch/x86_64/src/memory/heap/linked_list_allocator.cpp b/arch/x86_64/src/memory/heap/linked_list_allocator.cpp index 1c5c443..d922dc8 100644 --- a/arch/x86_64/src/memory/heap/linked_list_allocator.cpp +++ b/arch/x86_64/src/memory/heap/linked_list_allocator.cpp @@ -34,7 +34,11 @@ namespace teachos::arch::memory::heap while (current != nullptr) { - if (current->size >= size + min_allocatable_size()) + if (current->size == size) + { + return remove_free_memory_block(previous, current, size); + } + else if (current->size >= size + min_allocatable_size()) { auto memory_address = split_free_memory_block(previous, current, size); mutex.unlock(); @@ -77,6 +81,24 @@ namespace teachos::arch::memory::heap mutex.unlock(); } + auto linked_list_allocator::remove_free_memory_block(memory_block * previous_block, memory_block * current_block, + std::size_t size) -> void * + { + auto const start_address = reinterpret_cast(current_block); + // If we want to allocate into the first block that is before any other free block, then there exists no previous + // free block (nullptr). Therefore we have to overwrite the first block instead of overwriting its next value. + if (previous_block == nullptr) + { + first = nullptr; + } + else + { + previous_block->next = current_block->next; + } + clear_memory_block_header(current_block); + return reinterpret_cast(start_address); + } + auto linked_list_allocator::split_free_memory_block(memory_block * previous_block, memory_block * current_block, std::size_t size) -> void * { @@ -92,7 +114,7 @@ namespace teachos::arch::memory::heap } else { - previous_block = new_block; + previous_block->next = new_block; } clear_memory_block_header(current_block); return reinterpret_cast(start_address); -- cgit v1.2.3 From 23526b8d10cf41ad5598928bf2bf3264539d497f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matteo=20Gm=C3=BCr?= Date: Tue, 3 Dec 2024 08:41:59 +0000 Subject: Add missing comments --- .../src/memory/heap/linked_list_allocator.cpp | 30 +++++++++------------- 1 file changed, 12 insertions(+), 18 deletions(-) (limited to 'arch/x86_64/src/memory') diff --git a/arch/x86_64/src/memory/heap/linked_list_allocator.cpp b/arch/x86_64/src/memory/heap/linked_list_allocator.cpp index d922dc8..6600c6e 100644 --- a/arch/x86_64/src/memory/heap/linked_list_allocator.cpp +++ b/arch/x86_64/src/memory/heap/linked_list_allocator.cpp @@ -36,7 +36,7 @@ namespace teachos::arch::memory::heap { if (current->size == size) { - return remove_free_memory_block(previous, current, size); + return remove_free_memory_block(previous, current); } else if (current->size >= size + min_allocatable_size()) { @@ -81,31 +81,25 @@ namespace teachos::arch::memory::heap mutex.unlock(); } - auto linked_list_allocator::remove_free_memory_block(memory_block * previous_block, memory_block * current_block, - std::size_t size) -> void * + auto linked_list_allocator::remove_free_memory_block(memory_block * previous_block, + memory_block * current_block) -> void * { - auto const start_address = reinterpret_cast(current_block); - // If we want to allocate into the first block that is before any other free block, then there exists no previous - // free block (nullptr). Therefore we have to overwrite the first block instead of overwriting its next value. - if (previous_block == nullptr) - { - first = nullptr; - } - else - { - previous_block->next = current_block->next; - } - clear_memory_block_header(current_block); - return reinterpret_cast(start_address); + return replace_free_memory_block(previous_block, current_block, current_block->next); } auto linked_list_allocator::split_free_memory_block(memory_block * previous_block, memory_block * current_block, std::size_t size) -> void * { - auto const start_address = reinterpret_cast(current_block); - auto const end_address = start_address + size; + auto const end_address = reinterpret_cast(current_block) + size; auto const new_block = new (reinterpret_cast(end_address)) memory_block(current_block->size - size, current_block->next); + return replace_free_memory_block(previous_block, current_block, new_block); + } + + auto linked_list_allocator::replace_free_memory_block(memory_block * previous_block, memory_block * current_block, + memory_block * new_block) -> void * + { + auto const start_address = reinterpret_cast(current_block); // If we want to allocate into the first block that is before any other free block, then there exists no previous // free block (nullptr). Therefore we have to overwrite the first block instead of overwriting its next value. if (previous_block == nullptr) -- cgit v1.2.3 From 0a531eaa43cdd6ab15e60da2f4b203505265f5c6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matteo=20Gm=C3=BCr?= Date: Tue, 3 Dec 2024 08:47:13 +0000 Subject: Fix missing mutex unlock --- arch/x86_64/src/memory/heap/linked_list_allocator.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'arch/x86_64/src/memory') diff --git a/arch/x86_64/src/memory/heap/linked_list_allocator.cpp b/arch/x86_64/src/memory/heap/linked_list_allocator.cpp index 6600c6e..d0bf8e6 100644 --- a/arch/x86_64/src/memory/heap/linked_list_allocator.cpp +++ b/arch/x86_64/src/memory/heap/linked_list_allocator.cpp @@ -36,11 +36,13 @@ namespace teachos::arch::memory::heap { if (current->size == size) { - return remove_free_memory_block(previous, current); + auto const memory_address = remove_free_memory_block(previous, current); + mutex.unlock(); + return memory_address; } else if (current->size >= size + min_allocatable_size()) { - auto memory_address = split_free_memory_block(previous, current, size); + auto const memory_address = split_free_memory_block(previous, current, size); mutex.unlock(); return memory_address; } -- cgit v1.2.3 From 05fe50cefb12a7333a320a3d101dccdd13b8034a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matteo=20Gm=C3=BCr?= Date: Tue, 3 Dec 2024 09:13:53 +0000 Subject: Clear old memory in contructor --- arch/x86_64/src/memory/heap/linked_list_allocator.cpp | 14 ++------------ arch/x86_64/src/memory/heap/memory_block.cpp | 10 +++++++--- 2 files changed, 9 insertions(+), 15 deletions(-) (limited to 'arch/x86_64/src/memory') diff --git a/arch/x86_64/src/memory/heap/linked_list_allocator.cpp b/arch/x86_64/src/memory/heap/linked_list_allocator.cpp index d0bf8e6..e5bae21 100644 --- a/arch/x86_64/src/memory/heap/linked_list_allocator.cpp +++ b/arch/x86_64/src/memory/heap/linked_list_allocator.cpp @@ -3,10 +3,6 @@ #include "arch/exception_handling/assert.hpp" #include "arch/exception_handling/panic.hpp" -#include - -#include - namespace teachos::arch::memory::heap { linked_list_allocator::linked_list_allocator(std::size_t heap_start, std::size_t heap_end) @@ -112,7 +108,7 @@ namespace teachos::arch::memory::heap { previous_block->next = new_block; } - clear_memory_block_header(current_block); + current_block->~memory_block(); return reinterpret_cast(start_address); } @@ -134,8 +130,7 @@ namespace teachos::arch::memory::heap { block_size += current_block->size; next_block = current_block->next; - - clear_memory_block_header(current_block); + current_block->~memory_block(); } // If the block we want to deallocate is behind another free block and we can therefore combine both into one. @@ -170,9 +165,4 @@ namespace teachos::arch::memory::heap previous_block->next = new_block; } - auto linked_list_allocator::clear_memory_block_header(void * pointer) -> void - { - memset(pointer, 0, min_allocatable_size()); - } - } // namespace teachos::arch::memory::heap diff --git a/arch/x86_64/src/memory/heap/memory_block.cpp b/arch/x86_64/src/memory/heap/memory_block.cpp index b68dd6d..446cd96 100644 --- a/arch/x86_64/src/memory/heap/memory_block.cpp +++ b/arch/x86_64/src/memory/heap/memory_block.cpp @@ -1,11 +1,15 @@ #include "arch/memory/heap/memory_block.hpp" +#include + namespace teachos::arch::memory::heap { memory_block::memory_block(std::size_t size, memory_block * next) - : size(size) - , next(next) { - // Nothing to do + memset(static_cast(this), 0, size); + this->size = size; + this->next = next; } + + memory_block::~memory_block() { memset(static_cast(this), 0, sizeof(memory_block)); } } // namespace teachos::arch::memory::heap -- cgit v1.2.3 From 4ff0477e844fe13620b02c197a8db4c01809399f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matteo=20Gm=C3=BCr?= Date: Mon, 9 Dec 2024 15:16:50 +0000 Subject: Fix method writing to wrong CR register and improve doxygen comments. --- arch/x86_64/src/memory/cpu/control_register.cpp | 6 +++--- arch/x86_64/src/memory/main.cpp | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) (limited to 'arch/x86_64/src/memory') diff --git a/arch/x86_64/src/memory/cpu/control_register.cpp b/arch/x86_64/src/memory/cpu/control_register.cpp index 7624244..298874f 100644 --- a/arch/x86_64/src/memory/cpu/control_register.cpp +++ b/arch/x86_64/src/memory/cpu/control_register.cpp @@ -66,9 +66,9 @@ namespace teachos::arch::memory::cpu } } - auto set_cr2_bit(cr2_flags flag) -> void + auto set_cr0_bit(cr0_flags flag) -> void { - auto const cr2 = read_control_register(control_register::CR2); - write_control_register(control_register::CR2, static_cast::type>(flag) | cr2); + auto const cr0 = read_control_register(control_register::CR0); + write_control_register(control_register::CR0, static_cast::type>(flag) | cr0); } } // namespace teachos::arch::memory::cpu diff --git a/arch/x86_64/src/memory/main.cpp b/arch/x86_64/src/memory/main.cpp index 34ce113..2f01c5e 100644 --- a/arch/x86_64/src/memory/main.cpp +++ b/arch/x86_64/src/memory/main.cpp @@ -38,7 +38,7 @@ namespace teachos::arch::memory auto const memory_information = multiboot::read_multiboot2(); allocator::area_frame_allocator allocator(memory_information); - cpu::set_cr2_bit(memory::cpu::cr2_flags::WRITE_PROTECT); + cpu::set_cr0_bit(memory::cpu::cr0_flags::WRITE_PROTECT); cpu::set_efer_bit(memory::cpu::efer_flags::NXE); paging::kernel_mapper kernel(allocator, memory_information); -- cgit v1.2.3 From 568d0fd25f4ab12b183e230210d68252031bfa18 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matteo=20Gm=C3=BCr?= Date: Tue, 17 Dec 2024 08:24:15 +0000 Subject: Improve log messages --- arch/x86_64/src/memory/main.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'arch/x86_64/src/memory') diff --git a/arch/x86_64/src/memory/main.cpp b/arch/x86_64/src/memory/main.cpp index 2f01c5e..5290061 100644 --- a/arch/x86_64/src/memory/main.cpp +++ b/arch/x86_64/src/memory/main.cpp @@ -44,8 +44,10 @@ namespace teachos::arch::memory paging::kernel_mapper kernel(allocator, memory_information); auto & active_table = kernel.remap_kernel(); video::vga::text::write("Kernel remapping successfull", video::vga::text::common_attributes::green_on_black); + video::vga::text::newline(); remap_heap(allocator, active_table); video::vga::text::write("Heap remapping successfull", video::vga::text::common_attributes::green_on_black); + video::vga::text::newline(); } -} // namespace teachos::arch::memory \ No newline at end of file +} // namespace teachos::arch::memory -- cgit v1.2.3 From 3d488e53a1d15fcc01a7b1d23b9585ca7a724864 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matteo=20Gm=C3=BCr?= Date: Tue, 17 Dec 2024 09:36:31 +0000 Subject: Fix typo --- arch/x86_64/src/memory/main.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'arch/x86_64/src/memory') diff --git a/arch/x86_64/src/memory/main.cpp b/arch/x86_64/src/memory/main.cpp index 5290061..b978319 100644 --- a/arch/x86_64/src/memory/main.cpp +++ b/arch/x86_64/src/memory/main.cpp @@ -43,11 +43,11 @@ namespace teachos::arch::memory paging::kernel_mapper kernel(allocator, memory_information); auto & active_table = kernel.remap_kernel(); - video::vga::text::write("Kernel remapping successfull", video::vga::text::common_attributes::green_on_black); + video::vga::text::write("Kernel remapping successful", video::vga::text::common_attributes::green_on_black); video::vga::text::newline(); remap_heap(allocator, active_table); - video::vga::text::write("Heap remapping successfull", video::vga::text::common_attributes::green_on_black); + video::vga::text::write("Heap remapping successful", video::vga::text::common_attributes::green_on_black); video::vga::text::newline(); } } // namespace teachos::arch::memory -- cgit v1.2.3