aboutsummaryrefslogtreecommitdiff
path: root/arch/x86_64/src
diff options
context:
space:
mode:
authorFelix Morgner <felix.morgner@ost.ch>2025-07-17 21:09:02 +0000
committerFelix Morgner <felix.morgner@ost.ch>2025-07-18 13:02:34 +0200
commit14ed096fc5de6844cb116f3319c0d03043d26ea2 (patch)
treee78cc753b2d6dcabd703aebc4b9bea1783cc2e6d /arch/x86_64/src
parent891ca8834122e55638d33a129baab7292b8ed6d0 (diff)
downloadteachos-14ed096fc5de6844cb116f3319c0d03043d26ea2.tar.xz
teachos-14ed096fc5de6844cb116f3319c0d03043d26ea2.zip
x86-64: prepare new architecture
Diffstat (limited to 'arch/x86_64/src')
-rw-r--r--arch/x86_64/src/boot/boot.s2
-rw-r--r--arch/x86_64/src/memory.cpp90
-rw-r--r--arch/x86_64/src/memory/allocator/physical_frame.cpp24
-rw-r--r--arch/x86_64/src/memory/region_allocator.cpp95
4 files changed, 137 insertions, 74 deletions
diff --git a/arch/x86_64/src/boot/boot.s b/arch/x86_64/src/boot/boot.s
index ada6426..e0cff7c 100644
--- a/arch/x86_64/src/boot/boot.s
+++ b/arch/x86_64/src/boot/boot.s
@@ -12,7 +12,7 @@
* Reserve some space for the Multiboot 2 information pointer.
*/
.global multiboot_information_pointer
-multiboot_information_pointer: .skip 4
+multiboot_information_pointer: .skip 8
/**
* Align page maps to 4 KiB or the assembler code, will cause crashes when attempting to enable paging.
diff --git a/arch/x86_64/src/memory.cpp b/arch/x86_64/src/memory.cpp
index 245d7bd..2b16beb 100644
--- a/arch/x86_64/src/memory.cpp
+++ b/arch/x86_64/src/memory.cpp
@@ -1,62 +1,54 @@
#include "arch/memory.hpp"
-// #include "noarch/error.hpp"
-// #include "noarch/print.hpp"
-// #include "x86_64/bootstrap/mutiboot.hpp"
-// #include "x86_64/memory/frame_allocator.hpp"
-// #include "x86_64/memory/mbi_frame_allocator.hpp"
+#include "kern/error.hpp"
-// #include <elf/constants.hpp>
-// #include <elf/section_header.hpp>
-// #include <elf/section_header_table.hpp>
-// #include <multiboot2/information.hpp>
+#include "arch/asm_pointer.hpp"
+#include "x86_64/memory/region_allocator.hpp"
-namespace teachos::arch::memory
-{
+#include <multiboot2/information.hpp>
- // namespace
- // {
- // /**
- // * @brief Remap the kernel according to the ELF information.
- // *
- // * After initial bootup, a basic identity mapping of the lower 1GiB is set up. This mapping allows execution
- // from,
- // * as well as read and write access to, the mapped memory. In order to protect the kernel, remap it according to
- // the
- // * information supplied by the ELF file. This means remapping code sections as read-only and data sections as
- // * no-execute (and read only for .rodata).
- // *
- // * @param sections Information about the sections in the loaded kernel binary.
- // * @param allocator The frame allocator used to create new page mappings.
- // */
- // auto remap_kernel(elf::section_header_table const & sections, x86_64::memory::frame_allocator & allocator) ->
- // void
- // {
- // static_cast<void>(sections);
- // static_cast<void>(allocator);
- // }
- // } // namespace
+#include <atomic>
- auto init() -> void
- {
- // kernel::println("Initializing memory");
+extern "C" teachos::arch::asm_pointer<multiboot2::information_view> multiboot_information_pointer;
- // if (!x86_64::bootstrap::multiboot_information_pointer->has<multiboot2::memory_map>())
- // {
- // kernel::panic("Received no memory map from the boot loader!");
- // }
+namespace teachos::arch::memory
+{
+ namespace
+ {
+ auto constinit is_initialized = std::atomic_flag{};
- // if (!x86_64::bootstrap::multiboot_information_pointer->has<multiboot2::elf_symbols>())
- // {
- // kernel::panic("Received no ELF symbol information from the boot loader!");
- // }
+ // auto create_memory_information() -> x86_64::memory::region_allocator::memory_information {
- // auto memory_map = x86_64::bootstrap::multiboot_information_pointer->memory_map();
- // auto elf_symbols = x86_64::bootstrap::multiboot_information_pointer->elf_symbols();
- // auto section_header_table = elf::section_header_table{elf_symbols.data(), elf::file_class::bits_64};
- // auto allocator = x86_64::memory::mbi_frame_allocator{memory_map, section_header_table};
+ // };
+ } // namespace
- // remap_kernel(section_header_table, allocator);
+ auto init() -> void
+ {
+ if (is_initialized.test_and_set())
+ {
+ teachos::panic("[x86_64] Memory management has already been initialized.");
+ }
+
+ auto memory_map = multiboot_information_pointer->maybe_memory_map();
+ if (!memory_map)
+ {
+ teachos::panic("[x86_64] No memory map available.");
+ }
+
+ // auto mem_info = x86_64::memory::region_allocator::memory_information{};
+ // auto allocator = x86_64::memory::region_allocator{mem_info};
+
+ // kernel::cpu::set_cr0_bit(kernel::cpu::cr0_flags::WRITE_PROTECT);
+ // kernel::cpu::set_efer_bit(kernel::cpu::efer_flags::NXE);
+
+ // paging::kernel_mapper kernel(allocator, memory_information);
+ // kernel.remap_kernel();
+ // video::vga::text::write("Kernel remapping successful", video::vga::text::common_attributes::green_on_black);
+ // video::vga::text::newline();
+
+ // remap_heap(heap::KERNEL_HEAP_START, heap::KERNEL_HEAP_SIZE);
+ // video::vga::text::write("Heap remapping successful", video::vga::text::common_attributes::green_on_black);
+ // video::vga::text::newline();
}
} // namespace teachos::arch::memory
diff --git a/arch/x86_64/src/memory/allocator/physical_frame.cpp b/arch/x86_64/src/memory/allocator/physical_frame.cpp
deleted file mode 100644
index ec387a1..0000000
--- a/arch/x86_64/src/memory/allocator/physical_frame.cpp
+++ /dev/null
@@ -1,24 +0,0 @@
-#include "arch/memory/allocator/physical_frame.hpp"
-
-namespace teachos::arch::memory::allocator
-{
- auto physical_frame::containing_address(physical_address address) -> physical_frame
- {
- return physical_frame{address / PAGE_FRAME_SIZE};
- }
-
- auto physical_frame::start_address() const -> physical_address { return frame_number * PAGE_FRAME_SIZE; }
-
- auto physical_frame::operator++(int) -> physical_frame
- {
- physical_frame const old_value = *this;
- ++frame_number;
- return old_value;
- }
-
- auto physical_frame::operator++() -> physical_frame &
- {
- ++frame_number;
- return *this;
- }
-} // namespace teachos::arch::memory::allocator
diff --git a/arch/x86_64/src/memory/region_allocator.cpp b/arch/x86_64/src/memory/region_allocator.cpp
new file mode 100644
index 0000000..c9a98b4
--- /dev/null
+++ b/arch/x86_64/src/memory/region_allocator.cpp
@@ -0,0 +1,95 @@
+// #include "arch/memory/allocator/region_allocator.hpp"
+
+// #include "arch/exception_handling/assert.hpp"
+
+// #include <algorithm>
+// #include <array>
+// #include <ranges>
+
+#include "x86_64/memory/region_allocator.hpp"
+
+#include "x86_64/memory/address.hpp"
+#include "x86_64/memory/frame.hpp"
+
+#include <multiboot2/information.hpp>
+
+#include <algorithm>
+#include <ranges>
+
+namespace teachos::x86_64::memory
+{
+ namespace
+ {
+ auto constexpr last_frame(multiboot2::memory_map::region const & region)
+ {
+ return frame::containing(physical_address{region.base + region.size_in_B - 1});
+ }
+ } // namespace
+
+ region_allocator::region_allocator(memory_information const & mem_info)
+ : m_next_frame{}
+ , m_current_region{}
+ , m_memory_map{}
+ , m_kernel_start(frame::containing(mem_info.image_range.first))
+ , m_kernel_end(frame::containing(mem_info.image_range.second))
+ , m_multiboot_start(frame::containing(mem_info.mbi_range.first))
+ , m_multiboot_end(frame::containing(mem_info.mbi_range.second))
+ {
+ choose_next_area();
+ }
+
+ auto region_allocator::choose_next_area() -> void
+ {
+ m_current_region.reset();
+ auto next_area_with_free_frames =
+ m_memory_map | std::views::filter(&multiboot2::memory_map::region::available) |
+ std::views::filter([next = m_next_frame](auto const & region) { return last_frame(region) >= next; });
+
+ auto lowest_region_with_free_frames =
+ std::ranges::min_element(next_area_with_free_frames, [](auto lhs, auto rhs) { return lhs.base < rhs.base; });
+
+ if (lowest_region_with_free_frames != next_area_with_free_frames.end())
+ {
+ m_current_region = *lowest_region_with_free_frames;
+ auto start_frame = frame::containing(physical_address{m_current_region->base});
+ if (m_next_frame < start_frame)
+ {
+ m_next_frame = start_frame;
+ }
+ }
+ }
+
+ auto region_allocator::allocate_frame() -> std::optional<frame>
+ {
+ if (!m_current_region)
+ {
+ return {};
+ }
+
+ auto const end_address = physical_address{m_current_region->base + m_current_region->size_in_B - 1};
+ auto end_frame = frame::containing(end_address);
+
+ if (m_next_frame > end_frame)
+ {
+ choose_next_area();
+ }
+ else if (m_next_frame >= m_kernel_start && m_next_frame <= m_kernel_end)
+ {
+ m_next_frame = m_kernel_end + 1;
+ }
+ else if (m_next_frame >= m_multiboot_start && m_next_frame <= m_multiboot_end)
+ {
+ m_next_frame = m_multiboot_end + 1;
+ }
+ else
+ {
+ auto allocated = m_next_frame;
+ ++m_next_frame;
+ return allocated;
+ }
+
+ return allocate_frame();
+ }
+
+ auto region_allocator::deallocate_frame(frame const &) -> void {}
+} // namespace teachos::x86_64::memory