diff options
| author | Felix Morgner <felix.morgner@ost.ch> | 2026-04-16 10:29:30 +0200 |
|---|---|---|
| committer | Felix Morgner <felix.morgner@ost.ch> | 2026-04-29 09:05:04 +0200 |
| commit | 1b964278762dde86b0b737bd9a34fec569339f54 (patch) | |
| tree | 7fe0f4707e05f46461f03744d178f413b7bbca28 /arch/x86_64/src/memory | |
| parent | d906d70c94c2a40d5fc6fd26056c7bc57d540002 (diff) | |
| download | teachos-1b964278762dde86b0b737bd9a34fec569339f54.tar.xz teachos-1b964278762dde86b0b737bd9a34fec569339f54.zip | |
x86_64: use p1204 project layout
Diffstat (limited to 'arch/x86_64/src/memory')
| -rw-r--r-- | arch/x86_64/src/memory/higher_half_mapper.cpp | 119 | ||||
| -rw-r--r-- | arch/x86_64/src/memory/kernel_mapper.cpp | 117 | ||||
| -rw-r--r-- | arch/x86_64/src/memory/mmu.cpp | 19 | ||||
| -rw-r--r-- | arch/x86_64/src/memory/page_table.cpp | 82 | ||||
| -rw-r--r-- | arch/x86_64/src/memory/region_allocator.cpp | 165 |
5 files changed, 0 insertions, 502 deletions
diff --git a/arch/x86_64/src/memory/higher_half_mapper.cpp b/arch/x86_64/src/memory/higher_half_mapper.cpp deleted file mode 100644 index 75adb3c..0000000 --- a/arch/x86_64/src/memory/higher_half_mapper.cpp +++ /dev/null @@ -1,119 +0,0 @@ -#include <arch/memory/higher_half_mapper.hpp> - -#include <arch/memory/page_table.hpp> -#include <arch/memory/page_utilities.hpp> - -#include <kapi/memory.hpp> -#include <kapi/system.hpp> - -#include <algorithm> -#include <array> -#include <cstddef> -#include <memory> -#include <ranges> -#include <utility> - -namespace arch::memory -{ - - higher_half_mapper::higher_half_mapper(page_table * root) - : m_root{root} - {} - - auto higher_half_mapper::map(kapi::memory::page page, kapi::memory::frame frame, flags flags) -> std::byte * - { - auto table = get_or_create_page_table(page); - if (!table) - { - return nullptr; - } - - auto const index = pml_index(1, page); - auto & entry = (*table)[index]; - - if (entry.present()) - { - kapi::system::panic("[x86_64:MEM] Tried to map a page that is already mapped!"); - } - - entry.frame(frame, to_table_flags(flags) | page_table::entry::flags::present); - - return static_cast<std::byte *>(page.start_address()); - } - - auto higher_half_mapper::unmap(kapi::memory::page page) -> void - { - if (!try_unmap(page)) - { - kapi::system::panic("[x86_64:MEM] Tried to unmap a page that is not mapped!"); - } - } - - auto higher_half_mapper::try_unmap(kapi::memory::page page) noexcept -> bool - { - auto table_path = std::array<std::pair<page_table *, std::size_t>, 4>{}; - table_path[0] = std::pair{m_root, pml_index(4, page)}; - - for (auto level = 4uz; level > 1uz; --level) - { - auto [table, index] = table_path[4 - level]; - auto & entry = (*table)[index]; - - if (!entry.present()) - { - return false; - } - - auto next_table = to_higher_half_pointer<page_table>(entry.frame()->start_address()); - auto next_index = pml_index(4 - level - 1, page); - table_path[4 - level - 1] = std::pair{next_table, next_index}; - } - - std::ranges::for_each(std::views::reverse(table_path), [previous_was_empty = true](auto & step) mutable { - auto [table, index] = step; - auto & entry = (*table)[index]; - auto frame = entry.frame(); - - if (previous_was_empty) - { - entry.clear(); - previous_was_empty = table->empty(); - kapi::memory::get_frame_allocator().release(*frame); - } - }); - - return true; - } - - auto higher_half_mapper::get_or_create_page_table(kapi::memory::page page) noexcept -> page_table * - { - auto table = m_root; - - for (auto level = 4uz; level > 1uz; --level) - { - auto index = pml_index(level, page); - auto & entry = (*table)[index]; - - if (!entry.present()) - { - auto table_frame = kapi::memory::allocate_frame(); - if (!table_frame) - { - return nullptr; - } - - auto new_table = to_higher_half_pointer<page_table>(table_frame->start_address()); - std::construct_at(new_table); - - auto const flags = page_table::entry::flags::present | page_table::entry::flags::writable | - page_table::entry::flags::user_accessible; - entry.frame(*table_frame, flags); - } - - table = to_higher_half_pointer<page_table>(entry.frame()->start_address()); - } - - return table; - } - -} // namespace arch::memory
\ No newline at end of file diff --git a/arch/x86_64/src/memory/kernel_mapper.cpp b/arch/x86_64/src/memory/kernel_mapper.cpp deleted file mode 100644 index 74272a0..0000000 --- a/arch/x86_64/src/memory/kernel_mapper.cpp +++ /dev/null @@ -1,117 +0,0 @@ -#include <arch/memory/kernel_mapper.hpp> - -#include <arch/boot/ld.hpp> - -#include <kapi/memory.hpp> -#include <kapi/system.hpp> - -#include <elf/format.hpp> -#include <elf/section_header.hpp> - -#include <kstd/print> -#include <kstd/units> - -#include <multiboot2/information.hpp> - -#include <algorithm> -#include <array> -#include <bit> -#include <cstdint> -#include <ranges> -#include <string_view> -#include <utility> - -using namespace std::string_view_literals; -using namespace kstd::units_literals; - -namespace arch::memory -{ - - namespace - { - constexpr auto static ignored_section_prefixes = std::array{ - ".boot_"sv, - }; - - constexpr auto static user_accessible_prefixes = std::array{ - ".user"sv, - ".stl"sv, - }; - - } // namespace - - kernel_mapper::kernel_mapper(multiboot2::information_view const * mbi) - : m_mbi{std::move(mbi)} - , m_kernel_load_base{std::bit_cast<std::uintptr_t>(&arch::boot::TEACHOS_VMA)} - {} - - auto kernel_mapper::remap_kernel(kapi::memory::page_mapper & mapper) -> void - { - auto elf_information = m_mbi->maybe_elf_symbols<elf::format::elf64>(); - if (!elf_information) - { - kapi::system::panic("[x86_64:MEM] ELF section information is not available."); - } - - auto sections = *elf_information; - auto allocated_sections = - std::views::all(sections) | std::views::filter(&elf::section_header<elf::format::elf64>::allocated) | - std::views::filter([&](auto const & section) -> auto { - auto name = sections.name(section); - return !std::ranges::any_of(ignored_section_prefixes, - [&](auto const & prefix) -> auto { return name.starts_with(prefix); }); - }); - - if (allocated_sections.empty()) - { - kapi::system::panic("[x86_64:MEM] No allocated ELF sections were found."); - } - - std::ranges::for_each(allocated_sections, - [&](auto const & section) -> auto { map_section(section, sections.name(section), mapper); }); - } - - auto kernel_mapper::map_section(section_header_type const & section, std::string_view name, - kapi::memory::page_mapper & mapper) -> void - { - auto number_of_pages = - (kstd::units::bytes{section.size} + (kapi::memory::page::size - 1_B)) / kapi::memory::page::size; - auto linear_start_address = kapi::memory::linear_address{section.virtual_load_address}; - auto physical_start_address = kapi::memory::physical_address{section.virtual_load_address & ~m_kernel_load_base}; - - kstd::println("[x86_64:MEM] mapping {}" - "\n {} bytes -> page count: {}" - "\n {} @ {}", - name, section.size, number_of_pages, linear_start_address, physical_start_address); - - auto first_page = kapi::memory::page::containing(linear_start_address); - auto first_frame = kapi::memory::frame::containing(physical_start_address); - - auto page_flags = kapi::memory::page_mapper::flags::empty; - - if (section.writable()) - { - page_flags |= kapi::memory::page_mapper::flags::writable; - } - - if (section.executable()) - { - page_flags |= kapi::memory::page_mapper::flags::executable; - } - - auto is_prefix_of_name = [=](auto prefix) -> bool { - return name.starts_with(prefix); - }; - - if (!std::ranges::any_of(user_accessible_prefixes, is_prefix_of_name)) - { - page_flags |= kapi::memory::page_mapper::flags::supervisor_only; - } - - for (auto i = 0uz; i < number_of_pages; ++i) - { - mapper.map(first_page + i, first_frame + i, page_flags); - } - } - -} // namespace arch::memory
\ No newline at end of file diff --git a/arch/x86_64/src/memory/mmu.cpp b/arch/x86_64/src/memory/mmu.cpp deleted file mode 100644 index 2b53fa4..0000000 --- a/arch/x86_64/src/memory/mmu.cpp +++ /dev/null @@ -1,19 +0,0 @@ -#include <arch/memory/mmu.hpp> - -#include <arch/cpu/registers.hpp> - -#include <kapi/memory.hpp> - -namespace arch::memory -{ - auto tlb_flush(kapi::memory::linear_address address) -> void - { - asm volatile("invlpg (%[input])" : /* no output from call */ : [input] "r"(address) : "memory"); - } - - auto tlb_flush_all() -> void - { - auto paging_root = cpu::cr3::read(); - cpu::cr3::write(paging_root); - } -} // namespace arch::memory diff --git a/arch/x86_64/src/memory/page_table.cpp b/arch/x86_64/src/memory/page_table.cpp deleted file mode 100644 index 2180420..0000000 --- a/arch/x86_64/src/memory/page_table.cpp +++ /dev/null @@ -1,82 +0,0 @@ -#include <arch/memory/page_table.hpp> - -#include <kapi/memory.hpp> - -#include <algorithm> -#include <bit> -#include <cstddef> -#include <cstdint> -#include <optional> -#include <utility> - -namespace arch::memory -{ - - auto page_table::entry::clear() noexcept -> void - { - m_raw = 0; - } - - auto page_table::entry::present() const noexcept -> bool - { - return (all_flags() & flags::present) != flags::empty; - } - - auto page_table::entry::huge() const noexcept -> bool - { - return (all_flags() & flags::huge_page) != flags::empty; - } - - auto page_table::entry::all_flags() const noexcept -> flags - { - return std::bit_cast<flags>(m_raw & ~frame_number_mask); - } - - auto page_table::entry::all_flags(flags flags) noexcept -> void - { - m_raw = (m_raw & ~frame_number_mask) | std::to_underlying(flags); - } - - auto page_table::entry::operator|=(flags rhs) noexcept -> page_table::entry & - { - auto raw_flags = std::to_underlying(rhs) & ~frame_number_mask; - m_raw |= raw_flags; - return *this; - } - - auto page_table::entry::frame() const noexcept -> std::optional<kapi::memory::frame> - { - if (present()) - { - return kapi::memory::frame::containing(kapi::memory::physical_address{m_raw & frame_number_mask}); - } - return std::nullopt; - } - - auto page_table::entry::frame(kapi::memory::frame frame, flags flags) noexcept -> void - { - m_raw = (frame.start_address().raw() | static_cast<std::uint64_t>(flags)); - }; - - auto page_table::operator[](std::size_t index) -> entry & - { - return m_entries.at(index); - } - - auto page_table::operator[](std::size_t index) const -> entry const & - { - return m_entries.at(index); - } - - auto page_table::clear() noexcept -> void - { - std::ranges::for_each(m_entries, &page_table::entry::clear); - } - - auto page_table::empty() const noexcept -> bool - { - return std::ranges::all_of(m_entries, - [](auto const & entry) -> auto { return entry.all_flags() == entry::flags::empty; }); - } - -} // namespace arch::memory diff --git a/arch/x86_64/src/memory/region_allocator.cpp b/arch/x86_64/src/memory/region_allocator.cpp deleted file mode 100644 index 4086a10..0000000 --- a/arch/x86_64/src/memory/region_allocator.cpp +++ /dev/null @@ -1,165 +0,0 @@ -#include <arch/memory/region_allocator.hpp> - -#include <kapi/memory/address.hpp> -#include <kapi/memory/frame.hpp> - -#include <multiboot2/information.hpp> - -#include <algorithm> -#include <cstddef> -#include <optional> -#include <ranges> -#include <utility> - -namespace arch::memory -{ - namespace - { - constexpr auto last_frame(multiboot2::memory_map::region const & region) - { - return kapi::memory::frame::containing(kapi::memory::physical_address{region.base + region.size_in_B - 1}); - } - - constexpr auto falls_within(kapi::memory::frame const & candidate, kapi::memory::frame const & start, - kapi::memory::frame const & end) - { - return candidate >= start && candidate <= end; - } - } // namespace - - region_allocator::region_allocator(memory_information const & mem_info) - : m_next_frame{} - , m_current_region{} - , m_memory_map{mem_info.memory_map} - , m_kernel_start{kapi::memory::frame::containing(mem_info.image_range.first)} - , m_kernel_end{kapi::memory::frame::containing(mem_info.image_range.second)} - , m_multiboot_start{kapi::memory::frame::containing(mem_info.mbi_range.first)} - , m_multiboot_end{kapi::memory::frame::containing(mem_info.mbi_range.second)} - , m_multiboot_information{mem_info.mbi} - { - choose_next_region(); - } - - auto region_allocator::choose_next_region() -> void - { - m_current_region.reset(); - - auto remaining_regions = - m_memory_map | // - std::views::filter(&multiboot2::memory_map::region::available) | - std::views::filter([this](auto const & region) -> bool { return last_frame(region) >= m_next_frame; }); - - auto lowest_region = - std::ranges::min_element(remaining_regions, [](auto lhs, auto rhs) -> bool { return lhs.base < rhs.base; }); - - if (lowest_region == remaining_regions.end()) - { - return; - } - - m_current_region = *lowest_region; - if (auto start_of_region = kapi::memory::frame::containing(kapi::memory::physical_address{m_current_region->base}); - start_of_region > m_next_frame) - { - m_next_frame = start_of_region; - } - } - - auto region_allocator::find_next_frame() -> std::optional<kapi::memory::frame> - { - if (!m_current_region || m_next_frame > last_frame(*m_current_region)) - { - choose_next_region(); - if (!m_current_region) - { - return std::nullopt; - } - } - - auto advanced = true; - while (advanced) - { - advanced = false; - - if (falls_within(m_next_frame, m_kernel_start, m_kernel_end)) - { - m_next_frame = m_kernel_end + 1; - advanced = true; - continue; - } - - if (falls_within(m_next_frame, m_multiboot_start, m_multiboot_end)) - { - m_next_frame = m_multiboot_end + 1; - advanced = true; - continue; - } - - if (m_multiboot_information) - { - for (auto const & module : m_multiboot_information->modules()) - { - auto module_start = kapi::memory::frame::containing(kapi::memory::physical_address{module.start_address}); - auto module_end = kapi::memory::frame::containing(kapi::memory::physical_address{module.end_address}); - - if (falls_within(m_next_frame, module_start, module_end)) - { - m_next_frame = module_end + 1; - advanced = true; - break; - } - } - } - } - - if (m_next_frame > last_frame(*m_current_region)) - { - choose_next_region(); - } - - return m_current_region.transform([this](auto) -> auto { return m_next_frame; }); - } - - auto region_allocator::allocate_many(std::size_t count) noexcept - -> std::optional<std::pair<kapi::memory::frame, std::size_t>> - { - while (m_current_region) - { - auto result = find_next_frame(); - - if (result) - { - auto region_end = last_frame(*m_current_region); - if ((region_end.number() - result->number()) >= count) - { - m_next_frame = m_next_frame + count; - return std::make_pair(*result, count); - } - else - { - m_next_frame = region_end + 1; - choose_next_region(); - } - } - } - - return std::nullopt; - } - - auto region_allocator::mark_used(kapi::memory::frame frame) -> void - { - if (frame < m_next_frame) - { - m_next_frame = frame; - find_next_frame(); - } - } - - auto region_allocator::release_many(std::pair<kapi::memory::frame, std::size_t>) -> void {} - - auto region_allocator::next_free_frame() noexcept -> std::optional<kapi::memory::frame> - { - return find_next_frame(); - } - -} // namespace arch::memory |
