aboutsummaryrefslogtreecommitdiff
path: root/arch/x86_64/src/memory/kernel_mapper.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'arch/x86_64/src/memory/kernel_mapper.cpp')
-rw-r--r--arch/x86_64/src/memory/kernel_mapper.cpp107
1 files changed, 107 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..b1d12a4
--- /dev/null
+++ b/arch/x86_64/src/memory/kernel_mapper.cpp
@@ -0,0 +1,107 @@
+#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 "x86_64/memory/page_table.hpp"
+#include "x86_64/memory/paging_root.hpp"
+
+#include <elf/format.hpp>
+#include <elf/section_header.hpp>
+
+#include <algorithm>
+#include <ranges>
+
+namespace teachos::memory::x86_64
+{
+
+ inline 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(frame_allocator & allocator, multiboot2::information_view const * mbi)
+ : m_allocator{&allocator}
+ , 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() -> 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)); });
+ }
+
+ auto kernel_mapper::map_section(section_header_type const & section, std::string_view name) -> 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_table::entry::flags::empty;
+
+ if (section.writable())
+ {
+ page_flags |= page_table::entry::flags::writable;
+ }
+
+ if (!section.executable())
+ {
+ page_flags |= page_table::entry::flags::no_execute;
+ }
+
+ 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_table::entry::flags::user_accessible;
+ }
+
+ for (auto i = 0uz; i < number_of_pages; ++i)
+ {
+ paging_root::get().map(page{first_page.number() + i}, frame{first_frame.number() + i}, page_flags, *m_allocator);
+ }
+ }
+
+} // namespace teachos::memory::x86_64 \ No newline at end of file