aboutsummaryrefslogtreecommitdiff
path: root/arch/x86_64/src/memory
diff options
context:
space:
mode:
authorFelix Morgner <felix.morgner@ost.ch>2026-04-29 09:36:43 +0200
committerFelix Morgner <felix.morgner@ost.ch>2026-04-29 09:36:43 +0200
commitd6ef2153fb32ee7ba04acdf37e7a535a855229db (patch)
treed2cd3275797208b1f78c44baa63739fa8645146f /arch/x86_64/src/memory
parentd906d70c94c2a40d5fc6fd26056c7bc57d540002 (diff)
parentc3d5a155025b445ab9213f131681afe9410b4e66 (diff)
downloadteachos-d6ef2153fb32ee7ba04acdf37e7a535a855229db.tar.xz
teachos-d6ef2153fb32ee7ba04acdf37e7a535a855229db.zip
Merge branch 'fmorgner/develop-BA-FS26/x86-64-use-p1204-layout' into 'develop-BA-FS26'
chore: migrate 'arch' to p1204 project layout See merge request teachos/kernel!28
Diffstat (limited to 'arch/x86_64/src/memory')
-rw-r--r--arch/x86_64/src/memory/higher_half_mapper.cpp119
-rw-r--r--arch/x86_64/src/memory/kernel_mapper.cpp117
-rw-r--r--arch/x86_64/src/memory/mmu.cpp19
-rw-r--r--arch/x86_64/src/memory/page_table.cpp82
-rw-r--r--arch/x86_64/src/memory/region_allocator.cpp165
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