diff options
| author | Felix Morgner <felix.morgner@ost.ch> | 2025-12-15 17:13:12 +0100 |
|---|---|---|
| committer | Felix Morgner <felix.morgner@ost.ch> | 2025-12-15 17:13:12 +0100 |
| commit | 7b9482ae637126ac9337876e60f519b493437711 (patch) | |
| tree | 6fc71a253c8b0325d303bd34c95b564ba536ed14 /arch/x86_64/src/memory/kernel_mapper.cpp | |
| parent | 116f9332a206767c45095950f09f7c7447b561cf (diff) | |
| parent | a9eeec745e29d89afd48ee43d09432eb6fc35be7 (diff) | |
| download | kernel-7b9482ae637126ac9337876e60f519b493437711.tar.xz kernel-7b9482ae637126ac9337876e60f519b493437711.zip | |
os: rework kernel architecture
Rework the code structure and architecture of the kernel by separating
platform-dependent and platform-independent code more cleanly. As of
this patchset, full feature parity has not been achieved. Nonetheless, a
sufficient subset of functionality has been ported to the new
architecture to demonstrate the feasibility of the new structure.
Diffstat (limited to 'arch/x86_64/src/memory/kernel_mapper.cpp')
| -rw-r--r-- | arch/x86_64/src/memory/kernel_mapper.cpp | 111 |
1 files changed, 111 insertions, 0 deletions
diff --git a/arch/x86_64/src/memory/kernel_mapper.cpp b/arch/x86_64/src/memory/kernel_mapper.cpp new file mode 100644 index 0000000..4781d64 --- /dev/null +++ b/arch/x86_64/src/memory/kernel_mapper.cpp @@ -0,0 +1,111 @@ +#include "x86_64/memory/kernel_mapper.hpp" + +#include "kapi/cio.hpp" +#include "kapi/memory.hpp" +#include "kapi/system.hpp" + +#include "x86_64/boot/ld.hpp" + +#include <elf/format.hpp> +#include <elf/section_header.hpp> +#include <multiboot2/information.hpp> + +#include <algorithm> +#include <array> +#include <bit> +#include <cstdint> +#include <ranges> +#include <string_view> +#include <utility> + +namespace teachos::memory::x86_64 +{ + + namespace + { + using namespace std::string_view_literals; + + 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>(&boot::x86_64::TEACHOS_VMA)} + {} + + auto kernel_mapper::remap_kernel(page_mapper & mapper) -> void + { + auto elf_information = m_mbi->maybe_elf_symbols<elf::format::elf64>(); + if (!elf_information) + { + 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()) + { + 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, page_mapper & mapper) + -> void + { + cio::print("[x86_64:MEM] mapping "); + cio::println(name); + + auto number_of_pages = (section.size + (PLATFORM_PAGE_SIZE - 1)) / PLATFORM_PAGE_SIZE; + + auto linear_start_address = linear_address{section.virtual_load_address}; + auto physical_start_address = physical_address{section.virtual_load_address & ~m_kernel_load_base}; + + auto first_page = page::containing(linear_start_address); + auto first_frame = frame::containing(physical_start_address); + + auto page_flags = page_mapper::flags::empty; + + if (section.writable()) + { + page_flags |= page_mapper::flags::writable; + } + + if (section.executable()) + { + page_flags |= 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 |= 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 teachos::memory::x86_64
\ No newline at end of file |
