From 7671b1f0e4790b43bb8f8747b63cd44b7a65e10f Mon Sep 17 00:00:00 2001 From: Felix Morgner Date: Mon, 27 Oct 2025 13:58:55 +0000 Subject: x86_64: move kapi implementation to src --- arch/x86_64/src/kapi/cio.cpp | 16 ++++++++++ arch/x86_64/src/kapi/memory.cpp | 66 +++++++++++++++++++++++++++++++++++++++++ arch/x86_64/src/kapi/system.cpp | 12 ++++++++ 3 files changed, 94 insertions(+) create mode 100644 arch/x86_64/src/kapi/cio.cpp create mode 100644 arch/x86_64/src/kapi/memory.cpp create mode 100644 arch/x86_64/src/kapi/system.cpp (limited to 'arch/x86_64/src/kapi') diff --git a/arch/x86_64/src/kapi/cio.cpp b/arch/x86_64/src/kapi/cio.cpp new file mode 100644 index 0000000..ac3ae39 --- /dev/null +++ b/arch/x86_64/src/kapi/cio.cpp @@ -0,0 +1,16 @@ +#include "kapi/cio.hpp" + +#include "x86_64/vga/text.hpp" + +namespace teachos::cio +{ + + auto static constinit vga_device = std::optional{}; + + auto init() -> void + { + vga_device.emplace(); + set_output_device(*vga_device); + } + +} // namespace teachos::cio diff --git a/arch/x86_64/src/kapi/memory.cpp b/arch/x86_64/src/kapi/memory.cpp new file mode 100644 index 0000000..d1c1f03 --- /dev/null +++ b/arch/x86_64/src/kapi/memory.cpp @@ -0,0 +1,66 @@ +#include "kapi/memory.hpp" + +#include "kapi/system.hpp" + +#include "x86_64/boot/boot.hpp" +#include "x86_64/boot/ld.hpp" +#include "x86_64/memory/address.hpp" +#include "x86_64/memory/region_allocator.hpp" + +#include + +#include + +namespace teachos::memory +{ + using namespace x86_64::memory; + using namespace x86_64::boot; + + namespace + { + auto constinit is_initialized = std::atomic_flag{}; + + auto create_memory_information() -> region_allocator::memory_information + { + auto const & mbi = multiboot_information_pointer.get(); + auto map = mbi->memory_map(); + + return {std::make_pair(physical_address{&_start_physical}, physical_address{&_end_physical}), + std::make_pair(physical_address{std::bit_cast(&mbi)}, + physical_address{std::bit_cast(&mbi) + mbi->size_bytes()}), + map}; + }; + } // namespace + + auto init() -> void + { + if (is_initialized.test_and_set()) + { + system::panic("[x86_64] Memory management has already been initialized."); + } + + auto memory_map = multiboot_information_pointer->maybe_memory_map(); + if (!memory_map) + { + system::panic("[x86_64] No memory map available."); + } + + auto mem_info = create_memory_information(); + auto allocator = region_allocator{mem_info}; + + static_cast(allocator); + + // 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::memory diff --git a/arch/x86_64/src/kapi/system.cpp b/arch/x86_64/src/kapi/system.cpp new file mode 100644 index 0000000..2d4c3fe --- /dev/null +++ b/arch/x86_64/src/kapi/system.cpp @@ -0,0 +1,12 @@ +#include "kapi/system.hpp" + +namespace teachos::system +{ + + auto halt() -> void + { + asm volatile("1: hlt\njmp 1b"); + __builtin_unreachable(); + } + +} // namespace teachos::system -- cgit v1.2.3 From 6434de8ff75a9143847ef529bc209790ac4909b3 Mon Sep 17 00:00:00 2001 From: Felix Morgner Date: Wed, 29 Oct 2025 11:09:42 +0100 Subject: kapi: move frame and address to KAPI --- arch/x86_64/src/kapi/cio.cpp | 2 +- arch/x86_64/src/kapi/memory.cpp | 8 +++++--- 2 files changed, 6 insertions(+), 4 deletions(-) (limited to 'arch/x86_64/src/kapi') diff --git a/arch/x86_64/src/kapi/cio.cpp b/arch/x86_64/src/kapi/cio.cpp index ac3ae39..eb0142a 100644 --- a/arch/x86_64/src/kapi/cio.cpp +++ b/arch/x86_64/src/kapi/cio.cpp @@ -5,7 +5,7 @@ namespace teachos::cio { - auto static constinit vga_device = std::optional{}; + auto static constinit vga_device = std::optional{}; auto init() -> void { diff --git a/arch/x86_64/src/kapi/memory.cpp b/arch/x86_64/src/kapi/memory.cpp index d1c1f03..55e6ba9 100644 --- a/arch/x86_64/src/kapi/memory.cpp +++ b/arch/x86_64/src/kapi/memory.cpp @@ -1,10 +1,10 @@ #include "kapi/memory.hpp" +#include "kapi/memory/frame.hpp" #include "kapi/system.hpp" #include "x86_64/boot/boot.hpp" #include "x86_64/boot/ld.hpp" -#include "x86_64/memory/address.hpp" #include "x86_64/memory/region_allocator.hpp" #include @@ -13,8 +13,10 @@ namespace teachos::memory { - using namespace x86_64::memory; - using namespace x86_64::boot; + using namespace boot::x86_64; + using namespace memory::x86_64; + + std::size_t const PLATFORM_FRAME_SIZE{4096}; namespace { -- cgit v1.2.3 From e7b04ef7f5da8e014e8b85fcf65448b317cca8ff Mon Sep 17 00:00:00 2001 From: Felix Morgner Date: Wed, 29 Oct 2025 11:15:50 +0100 Subject: kapi: move halt to cpu namespace --- arch/x86_64/src/kapi/cpu.cpp | 12 ++++++++++++ arch/x86_64/src/kapi/system.cpp | 12 ------------ 2 files changed, 12 insertions(+), 12 deletions(-) create mode 100644 arch/x86_64/src/kapi/cpu.cpp delete mode 100644 arch/x86_64/src/kapi/system.cpp (limited to 'arch/x86_64/src/kapi') diff --git a/arch/x86_64/src/kapi/cpu.cpp b/arch/x86_64/src/kapi/cpu.cpp new file mode 100644 index 0000000..22543ee --- /dev/null +++ b/arch/x86_64/src/kapi/cpu.cpp @@ -0,0 +1,12 @@ +#include "kapi/cpu.hpp" + +namespace teachos::cpu +{ + + auto halt() -> void + { + asm volatile("1: hlt\njmp 1b"); + __builtin_unreachable(); + } + +} // namespace teachos::cpu diff --git a/arch/x86_64/src/kapi/system.cpp b/arch/x86_64/src/kapi/system.cpp deleted file mode 100644 index 2d4c3fe..0000000 --- a/arch/x86_64/src/kapi/system.cpp +++ /dev/null @@ -1,12 +0,0 @@ -#include "kapi/system.hpp" - -namespace teachos::system -{ - - auto halt() -> void - { - asm volatile("1: hlt\njmp 1b"); - __builtin_unreachable(); - } - -} // namespace teachos::system -- cgit v1.2.3 From 845a96f5e6bfbbbeba19bf3df07f0e9de53d9a88 Mon Sep 17 00:00:00 2001 From: Felix Morgner Date: Wed, 29 Oct 2025 11:40:49 +0100 Subject: kapi: export frame_allocator interface --- arch/x86_64/src/kapi/memory.cpp | 12 ++++++++++++ 1 file changed, 12 insertions(+) (limited to 'arch/x86_64/src/kapi') diff --git a/arch/x86_64/src/kapi/memory.cpp b/arch/x86_64/src/kapi/memory.cpp index 55e6ba9..be47941 100644 --- a/arch/x86_64/src/kapi/memory.cpp +++ b/arch/x86_64/src/kapi/memory.cpp @@ -1,6 +1,7 @@ #include "kapi/memory.hpp" #include "kapi/memory/frame.hpp" +#include "kapi/memory/frame_allocator.hpp" #include "kapi/system.hpp" #include "x86_64/boot/boot.hpp" @@ -21,6 +22,7 @@ namespace teachos::memory namespace { auto constinit is_initialized = std::atomic_flag{}; + auto constinit allocator = static_cast(nullptr); auto create_memory_information() -> region_allocator::memory_information { @@ -34,6 +36,16 @@ namespace teachos::memory }; } // namespace + auto active_allocator() -> frame_allocator & + { + if (!allocator) + { + system::panic("[x86_64] The frame allocator has not been set yet."); + } + + return *allocator; + } + auto init() -> void { if (is_initialized.test_and_set()) -- cgit v1.2.3 From c71d18f32e06fb456bc2829d9dfc5b42b78160b0 Mon Sep 17 00:00:00 2001 From: Felix Morgner Date: Wed, 29 Oct 2025 11:53:34 +0100 Subject: x86_64: reduce using namespace use --- arch/x86_64/src/kapi/memory.cpp | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) (limited to 'arch/x86_64/src/kapi') diff --git a/arch/x86_64/src/kapi/memory.cpp b/arch/x86_64/src/kapi/memory.cpp index be47941..46686b6 100644 --- a/arch/x86_64/src/kapi/memory.cpp +++ b/arch/x86_64/src/kapi/memory.cpp @@ -6,6 +6,7 @@ #include "x86_64/boot/boot.hpp" #include "x86_64/boot/ld.hpp" +#include "x86_64/cpu/registers.hpp" #include "x86_64/memory/region_allocator.hpp" #include @@ -14,9 +15,6 @@ namespace teachos::memory { - using namespace boot::x86_64; - using namespace memory::x86_64; - std::size_t const PLATFORM_FRAME_SIZE{4096}; namespace @@ -24,12 +22,13 @@ namespace teachos::memory auto constinit is_initialized = std::atomic_flag{}; auto constinit allocator = static_cast(nullptr); - auto create_memory_information() -> region_allocator::memory_information + auto create_memory_information() -> x86_64::region_allocator::memory_information { - auto const & mbi = multiboot_information_pointer.get(); + auto const & mbi = boot::x86_64::multiboot_information_pointer.get(); auto map = mbi->memory_map(); - return {std::make_pair(physical_address{&_start_physical}, physical_address{&_end_physical}), + return {std::make_pair(physical_address{&boot::x86_64::_start_physical}, + physical_address{&boot::x86_64::_end_physical}), std::make_pair(physical_address{std::bit_cast(&mbi)}, physical_address{std::bit_cast(&mbi) + mbi->size_bytes()}), map}; @@ -53,19 +52,20 @@ namespace teachos::memory system::panic("[x86_64] Memory management has already been initialized."); } - auto memory_map = multiboot_information_pointer->maybe_memory_map(); + auto memory_map = boot::x86_64::multiboot_information_pointer->maybe_memory_map(); if (!memory_map) { system::panic("[x86_64] No memory map available."); } auto mem_info = create_memory_information(); - auto allocator = region_allocator{mem_info}; + auto allocator = x86_64::region_allocator{mem_info}; static_cast(allocator); - // kernel::cpu::set_cr0_bit(kernel::cpu::cr0_flags::WRITE_PROTECT); - // kernel::cpu::set_efer_bit(kernel::cpu::efer_flags::NXE); + cpu::x86_64::set_cr0_bit(cpu::x86_64::cr0_flags::WRITE_PROTECT); + + // set_efer_bit(efer_flags::NXE); // paging::kernel_mapper kernel(allocator, memory_information); // kernel.remap_kernel(); -- cgit v1.2.3 From f5aee1e1ab521d6aeb4c79f6ef276625159e202f Mon Sep 17 00:00:00 2001 From: Felix Morgner Date: Wed, 29 Oct 2025 11:58:12 +0100 Subject: x86_64: extract early boot steps --- arch/x86_64/src/kapi/memory.cpp | 33 +++++++++++++++++++-------------- 1 file changed, 19 insertions(+), 14 deletions(-) (limited to 'arch/x86_64/src/kapi') diff --git a/arch/x86_64/src/kapi/memory.cpp b/arch/x86_64/src/kapi/memory.cpp index 46686b6..a29a0cd 100644 --- a/arch/x86_64/src/kapi/memory.cpp +++ b/arch/x86_64/src/kapi/memory.cpp @@ -33,6 +33,23 @@ namespace teachos::memory physical_address{std::bit_cast(&mbi) + mbi->size_bytes()}), map}; }; + + auto create_early_frame_allocator() + { + auto memory_map = boot::x86_64::multiboot_information_pointer->maybe_memory_map(); + if (!memory_map) + { + system::panic("[x86_64] Failed to create early allocator, no memory map available."); + } + + return x86_64::region_allocator{create_memory_information()}; + } + + auto enable_cpu_protections() -> void + { + cpu::x86_64::set_cr0_bit(cpu::x86_64::cr0_flags::WRITE_PROTECT); + // set_efer_bit(efer_flags::NXE); + } } // namespace auto active_allocator() -> frame_allocator & @@ -52,20 +69,8 @@ namespace teachos::memory system::panic("[x86_64] Memory management has already been initialized."); } - auto memory_map = boot::x86_64::multiboot_information_pointer->maybe_memory_map(); - if (!memory_map) - { - system::panic("[x86_64] No memory map available."); - } - - auto mem_info = create_memory_information(); - auto allocator = x86_64::region_allocator{mem_info}; - - static_cast(allocator); - - cpu::x86_64::set_cr0_bit(cpu::x86_64::cr0_flags::WRITE_PROTECT); - - // set_efer_bit(efer_flags::NXE); + [[maybe_unused]] auto allocator = create_early_frame_allocator(); + enable_cpu_protections(); // paging::kernel_mapper kernel(allocator, memory_information); // kernel.remap_kernel(); -- cgit v1.2.3 From 465817e3e124bafb95de0d8a030b66bc067046b6 Mon Sep 17 00:00:00 2001 From: Felix Morgner Date: Wed, 29 Oct 2025 13:35:58 +0100 Subject: x86_64/memory: fix region_allocator initialization --- arch/x86_64/src/kapi/memory.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'arch/x86_64/src/kapi') diff --git a/arch/x86_64/src/kapi/memory.cpp b/arch/x86_64/src/kapi/memory.cpp index a29a0cd..61d462f 100644 --- a/arch/x86_64/src/kapi/memory.cpp +++ b/arch/x86_64/src/kapi/memory.cpp @@ -29,8 +29,8 @@ namespace teachos::memory return {std::make_pair(physical_address{&boot::x86_64::_start_physical}, physical_address{&boot::x86_64::_end_physical}), - std::make_pair(physical_address{std::bit_cast(&mbi)}, - physical_address{std::bit_cast(&mbi) + mbi->size_bytes()}), + std::make_pair(physical_address{std::bit_cast(mbi)}, + physical_address{std::bit_cast(mbi) + mbi->size_bytes()}), map}; }; -- cgit v1.2.3 From 7b9df8bec5038e0316540d2397df632fb14c9169 Mon Sep 17 00:00:00 2001 From: Felix Morgner Date: Wed, 29 Oct 2025 17:01:22 +0100 Subject: chore: configure clang-tidy --- arch/x86_64/src/kapi/cio.cpp | 1 + arch/x86_64/src/kapi/memory.cpp | 14 +++++++++----- 2 files changed, 10 insertions(+), 5 deletions(-) (limited to 'arch/x86_64/src/kapi') diff --git a/arch/x86_64/src/kapi/cio.cpp b/arch/x86_64/src/kapi/cio.cpp index eb0142a..456477a 100644 --- a/arch/x86_64/src/kapi/cio.cpp +++ b/arch/x86_64/src/kapi/cio.cpp @@ -5,6 +5,7 @@ namespace teachos::cio { + // NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables) auto static constinit vga_device = std::optional{}; auto init() -> void diff --git a/arch/x86_64/src/kapi/memory.cpp b/arch/x86_64/src/kapi/memory.cpp index 61d462f..e05fde9 100644 --- a/arch/x86_64/src/kapi/memory.cpp +++ b/arch/x86_64/src/kapi/memory.cpp @@ -19,19 +19,23 @@ namespace teachos::memory namespace { + // NOLINTBEGIN(cppcoreguidelines-avoid-non-const-global-variables) auto constinit is_initialized = std::atomic_flag{}; auto constinit allocator = static_cast(nullptr); + // NOLINTEND(cppcoreguidelines-avoid-non-const-global-variables) auto create_memory_information() -> x86_64::region_allocator::memory_information { auto const & mbi = boot::x86_64::multiboot_information_pointer.get(); auto map = mbi->memory_map(); - return {std::make_pair(physical_address{&boot::x86_64::_start_physical}, - physical_address{&boot::x86_64::_end_physical}), - std::make_pair(physical_address{std::bit_cast(mbi)}, - physical_address{std::bit_cast(mbi) + mbi->size_bytes()}), - map}; + // NOLINTBEGIN(cppcoreguidelines-pro-bounds-pointer-arithmetic) + return {.image_range = std::make_pair(physical_address{&boot::x86_64::_start_physical}, + physical_address{&boot::x86_64::_end_physical}), + .mbi_range = std::make_pair(physical_address{std::bit_cast(mbi)}, + physical_address{std::bit_cast(mbi) + mbi->size_bytes()}), + .memory_map = map}; + // NOLINTEND(cppcoreguidelines-pro-bounds-pointer-arithmetic) }; auto create_early_frame_allocator() -- cgit v1.2.3 From 49dcbdaaca348784d7fa05e12a06123f4dc252ec Mon Sep 17 00:00:00 2001 From: Felix Morgner Date: Tue, 18 Nov 2025 18:14:30 +0100 Subject: x86_64/memory: perform slight cleanup --- arch/x86_64/src/kapi/memory.cpp | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) (limited to 'arch/x86_64/src/kapi') diff --git a/arch/x86_64/src/kapi/memory.cpp b/arch/x86_64/src/kapi/memory.cpp index e05fde9..aa3eb58 100644 --- a/arch/x86_64/src/kapi/memory.cpp +++ b/arch/x86_64/src/kapi/memory.cpp @@ -27,15 +27,12 @@ namespace teachos::memory auto create_memory_information() -> x86_64::region_allocator::memory_information { auto const & mbi = boot::x86_64::multiboot_information_pointer.get(); - auto map = mbi->memory_map(); - // NOLINTBEGIN(cppcoreguidelines-pro-bounds-pointer-arithmetic) return {.image_range = std::make_pair(physical_address{&boot::x86_64::_start_physical}, physical_address{&boot::x86_64::_end_physical}), .mbi_range = std::make_pair(physical_address{std::bit_cast(mbi)}, physical_address{std::bit_cast(mbi) + mbi->size_bytes()}), - .memory_map = map}; - // NOLINTEND(cppcoreguidelines-pro-bounds-pointer-arithmetic) + .memory_map = mbi->memory_map()}; }; auto create_early_frame_allocator() -- cgit v1.2.3 From a5ca21e45e9c8ead0b5895771c0b2f3fe3baf96b Mon Sep 17 00:00:00 2001 From: Felix Morgner Date: Fri, 21 Nov 2025 14:53:37 +0100 Subject: x86_64: rework control register access --- arch/x86_64/src/kapi/memory.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'arch/x86_64/src/kapi') diff --git a/arch/x86_64/src/kapi/memory.cpp b/arch/x86_64/src/kapi/memory.cpp index aa3eb58..4766bb3 100644 --- a/arch/x86_64/src/kapi/memory.cpp +++ b/arch/x86_64/src/kapi/memory.cpp @@ -6,6 +6,7 @@ #include "x86_64/boot/boot.hpp" #include "x86_64/boot/ld.hpp" +#include "x86_64/cpu/impl/control_registers.hpp" #include "x86_64/cpu/registers.hpp" #include "x86_64/memory/region_allocator.hpp" @@ -48,7 +49,7 @@ namespace teachos::memory auto enable_cpu_protections() -> void { - cpu::x86_64::set_cr0_bit(cpu::x86_64::cr0_flags::WRITE_PROTECT); + cpu::x86_64::cr0::clear(cpu::x86_64::cr0::flags::write_protect); // set_efer_bit(efer_flags::NXE); } } // namespace -- cgit v1.2.3 From 7f935cdc3e57d80c4ef83760e1a616c33684271d Mon Sep 17 00:00:00 2001 From: Felix Morgner Date: Fri, 21 Nov 2025 14:55:10 +0100 Subject: x86_64: fix enabling of write protection --- arch/x86_64/src/kapi/memory.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch/x86_64/src/kapi') diff --git a/arch/x86_64/src/kapi/memory.cpp b/arch/x86_64/src/kapi/memory.cpp index 4766bb3..6102bee 100644 --- a/arch/x86_64/src/kapi/memory.cpp +++ b/arch/x86_64/src/kapi/memory.cpp @@ -49,7 +49,7 @@ namespace teachos::memory auto enable_cpu_protections() -> void { - cpu::x86_64::cr0::clear(cpu::x86_64::cr0::flags::write_protect); + cpu::x86_64::cr0::set(cpu::x86_64::cr0::flags::write_protect); // set_efer_bit(efer_flags::NXE); } } // namespace -- cgit v1.2.3 From 9ee028e52bd60affded3b90ea8dcd20c93bb5025 Mon Sep 17 00:00:00 2001 From: Felix Morgner Date: Mon, 24 Nov 2025 13:16:35 +0100 Subject: x86-64/kapi: reimplement ia32_efer support --- arch/x86_64/src/kapi/memory.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'arch/x86_64/src/kapi') diff --git a/arch/x86_64/src/kapi/memory.cpp b/arch/x86_64/src/kapi/memory.cpp index 6102bee..d0d966b 100644 --- a/arch/x86_64/src/kapi/memory.cpp +++ b/arch/x86_64/src/kapi/memory.cpp @@ -6,7 +6,6 @@ #include "x86_64/boot/boot.hpp" #include "x86_64/boot/ld.hpp" -#include "x86_64/cpu/impl/control_registers.hpp" #include "x86_64/cpu/registers.hpp" #include "x86_64/memory/region_allocator.hpp" @@ -50,7 +49,7 @@ namespace teachos::memory auto enable_cpu_protections() -> void { cpu::x86_64::cr0::set(cpu::x86_64::cr0::flags::write_protect); - // set_efer_bit(efer_flags::NXE); + cpu::x86_64::i32_efer::set(cpu::x86_64::i32_efer::flags::execute_disable_bit_enable); } } // namespace -- cgit v1.2.3 From 2b3dca0d0329b61881ffbecca0f120cfda3314fa Mon Sep 17 00:00:00 2001 From: Felix Morgner Date: Mon, 24 Nov 2025 13:25:12 +0100 Subject: x86_64/kapi: clean up one linter warning --- arch/x86_64/src/kapi/memory.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'arch/x86_64/src/kapi') diff --git a/arch/x86_64/src/kapi/memory.cpp b/arch/x86_64/src/kapi/memory.cpp index d0d966b..5142a2a 100644 --- a/arch/x86_64/src/kapi/memory.cpp +++ b/arch/x86_64/src/kapi/memory.cpp @@ -19,10 +19,8 @@ namespace teachos::memory namespace { - // NOLINTBEGIN(cppcoreguidelines-avoid-non-const-global-variables) - auto constinit is_initialized = std::atomic_flag{}; + // NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables) auto constinit allocator = static_cast(nullptr); - // NOLINTEND(cppcoreguidelines-avoid-non-const-global-variables) auto create_memory_information() -> x86_64::region_allocator::memory_information { @@ -65,6 +63,7 @@ namespace teachos::memory auto init() -> void { + auto static constinit is_initialized = std::atomic_flag{}; if (is_initialized.test_and_set()) { system::panic("[x86_64] Memory management has already been initialized."); -- cgit v1.2.3 From 1a3c20cc9ea191a862eb7e8ac55b3a69ac74ad5e Mon Sep 17 00:00:00 2001 From: Felix Morgner Date: Mon, 24 Nov 2025 16:59:24 +0100 Subject: x86_64/vga: rely less on magic state --- arch/x86_64/src/kapi/memory.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'arch/x86_64/src/kapi') diff --git a/arch/x86_64/src/kapi/memory.cpp b/arch/x86_64/src/kapi/memory.cpp index 5142a2a..3848fb8 100644 --- a/arch/x86_64/src/kapi/memory.cpp +++ b/arch/x86_64/src/kapi/memory.cpp @@ -24,7 +24,7 @@ namespace teachos::memory auto create_memory_information() -> x86_64::region_allocator::memory_information { - auto const & mbi = boot::x86_64::multiboot_information_pointer.get(); + auto const & mbi = boot::bootstrap_information.mbi; return {.image_range = std::make_pair(physical_address{&boot::x86_64::_start_physical}, physical_address{&boot::x86_64::_end_physical}), @@ -35,7 +35,7 @@ namespace teachos::memory auto create_early_frame_allocator() { - auto memory_map = boot::x86_64::multiboot_information_pointer->maybe_memory_map(); + auto memory_map = boot::bootstrap_information.mbi->maybe_memory_map(); if (!memory_map) { system::panic("[x86_64] Failed to create early allocator, no memory map available."); -- cgit v1.2.3 From 1db039ca1c67e8daba8b5ec6d5158cb2110e1410 Mon Sep 17 00:00:00 2001 From: Felix Morgner Date: Fri, 28 Nov 2025 16:06:15 +0100 Subject: x86_64: port basic page and page table abstractions --- arch/x86_64/src/kapi/memory.cpp | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) (limited to 'arch/x86_64/src/kapi') diff --git a/arch/x86_64/src/kapi/memory.cpp b/arch/x86_64/src/kapi/memory.cpp index 3848fb8..99dcb5c 100644 --- a/arch/x86_64/src/kapi/memory.cpp +++ b/arch/x86_64/src/kapi/memory.cpp @@ -12,6 +12,7 @@ #include #include +#include namespace teachos::memory { @@ -25,11 +26,12 @@ namespace teachos::memory auto create_memory_information() -> x86_64::region_allocator::memory_information { auto const & mbi = boot::bootstrap_information.mbi; + auto mbi_span = std::span{std::bit_cast(mbi), mbi->size_bytes()}; + auto image_span = std::span{&boot::x86_64::_start_physical, &boot::x86_64::_end_physical}; - return {.image_range = std::make_pair(physical_address{&boot::x86_64::_start_physical}, - physical_address{&boot::x86_64::_end_physical}), - .mbi_range = std::make_pair(physical_address{std::bit_cast(mbi)}, - physical_address{std::bit_cast(mbi) + mbi->size_bytes()}), + return {.image_range = + std::make_pair(physical_address{&image_span.front()}, physical_address{&image_span.back()}), + .mbi_range = std::make_pair(physical_address{&mbi_span.front()}, physical_address{&mbi_span.back()}), .memory_map = mbi->memory_map()}; }; -- cgit v1.2.3 From 27eddc3fa8d4c6001f223670d6001554fc47b657 Mon Sep 17 00:00:00 2001 From: Felix Morgner Date: Mon, 1 Dec 2025 15:56:58 +0100 Subject: x86_64/memory: implement PML4 injection --- arch/x86_64/src/kapi/memory.cpp | 74 +++++++++++++++++++++++++++++++++++++++-- 1 file changed, 71 insertions(+), 3 deletions(-) (limited to 'arch/x86_64/src/kapi') diff --git a/arch/x86_64/src/kapi/memory.cpp b/arch/x86_64/src/kapi/memory.cpp index 99dcb5c..f34729a 100644 --- a/arch/x86_64/src/kapi/memory.cpp +++ b/arch/x86_64/src/kapi/memory.cpp @@ -1,28 +1,34 @@ #include "kapi/memory.hpp" -#include "kapi/memory/frame.hpp" -#include "kapi/memory/frame_allocator.hpp" +#include "kapi/cio.hpp" #include "kapi/system.hpp" #include "x86_64/boot/boot.hpp" #include "x86_64/boot/ld.hpp" #include "x86_64/cpu/registers.hpp" +#include "x86_64/memory/mmu.hpp" +#include "x86_64/memory/page_table.hpp" +#include "x86_64/memory/paging_root.hpp" #include "x86_64/memory/region_allocator.hpp" #include #include +#include #include namespace teachos::memory { std::size_t const PLATFORM_FRAME_SIZE{4096}; + std::size_t const PLATFORM_PAGE_SIZE{PLATFORM_FRAME_SIZE}; namespace { // NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables) auto constinit allocator = static_cast(nullptr); + constexpr auto static unused_page_address = 0x0000'7fff'cafe'faceuz; + auto create_memory_information() -> x86_64::region_allocator::memory_information { auto const & mbi = boot::bootstrap_information.mbi; @@ -51,6 +57,67 @@ namespace teachos::memory cpu::x86_64::cr0::set(cpu::x86_64::cr0::flags::write_protect); cpu::x86_64::i32_efer::set(cpu::x86_64::i32_efer::flags::execute_disable_bit_enable); } + + auto inject_faux_pml4(frame_allocator & allocator) -> void + { + using entry_flags = x86_64::page_table::entry::flags; + using page_table = x86_64::page_table; + + auto temporary_page = page::containing(linear_address{unused_page_address}); + auto temporary_page_address = temporary_page.start_address(); + + auto & pml4 = x86_64::paging_root::get(); + + // NOLINTBEGIN(cppcoreguidelines-avoid-magic-numbers) + auto faux_pml4_frame = + allocator.allocate() + .and_then([&](auto frame) -> auto { + auto index = temporary_page_address >> 39 & 0x1ffu; + pml4[index].frame(frame, entry_flags::present | entry_flags::writable); + return pml4.next(index); + }) + .and_then([&](auto pml) -> auto { + std::construct_at(pml); + auto index = temporary_page_address >> 30 & 0x1ffu; + (*pml)[index].frame(*allocator.allocate(), entry_flags::present | entry_flags::writable); + return pml->next(index); + }) + .and_then([&](auto pml) -> auto { + std::construct_at(pml); + auto index = temporary_page_address >> 21 & 0x1ffu; + (*pml)[index].frame(*allocator.allocate(), entry_flags::present | entry_flags::writable); + return pml->next(index); + }) + .transform([&](auto pml) -> auto { + std::construct_at(pml); + auto index = temporary_page_address >> 12 & 0x1ffu; + (*pml)[index].frame(*allocator.allocate(), entry_flags::present | entry_flags::writable); + return pml; + }) + .and_then([&](auto pml) -> auto { + auto faux_pml4_pointer = std::bit_cast(temporary_page_address.raw()); + auto faux_pml4 = std::construct_at(faux_pml4_pointer); + + auto index = temporary_page_address >> 12 & 0x1ffu; + auto frame = (*pml)[index].frame(); + + (*faux_pml4)[510].frame(*frame, entry_flags::present | entry_flags::writable); + return frame; + }); + // NOLINTEND(cppcoreguidelines-avoid-magic-numbers) + + if (!faux_pml4_frame) + { + system::panic("[MEM] Failed to map and construct faux PML4"); + } + + // NOLINTNEXTLINE(cppcoreguidelines-avoid-magic-numbers) + pml4[510].frame(*faux_pml4_frame, entry_flags::present | entry_flags::writable); + x86_64::tlb_flush_all(); + + cio::println("[MEM] Injected faux PML4 as recursive map."); + } + } // namespace auto active_allocator() -> frame_allocator & @@ -71,8 +138,9 @@ namespace teachos::memory system::panic("[x86_64] Memory management has already been initialized."); } - [[maybe_unused]] auto allocator = create_early_frame_allocator(); + auto allocator = create_early_frame_allocator(); enable_cpu_protections(); + inject_faux_pml4(allocator); // paging::kernel_mapper kernel(allocator, memory_information); // kernel.remap_kernel(); -- cgit v1.2.3 From 203355e51690073e571d4906d53f2494c3dad41b Mon Sep 17 00:00:00 2001 From: Felix Morgner Date: Mon, 1 Dec 2025 19:32:19 +0100 Subject: x86_64/memory: prepare scoped_mapping extraction --- arch/x86_64/src/kapi/memory.cpp | 12 ++++++++++++ 1 file changed, 12 insertions(+) (limited to 'arch/x86_64/src/kapi') diff --git a/arch/x86_64/src/kapi/memory.cpp b/arch/x86_64/src/kapi/memory.cpp index f34729a..920c82b 100644 --- a/arch/x86_64/src/kapi/memory.cpp +++ b/arch/x86_64/src/kapi/memory.cpp @@ -10,6 +10,7 @@ #include "x86_64/memory/page_table.hpp" #include "x86_64/memory/paging_root.hpp" #include "x86_64/memory/region_allocator.hpp" +#include "x86_64/memory/scoped_mapping.hpp" #include @@ -140,8 +141,19 @@ namespace teachos::memory auto allocator = create_early_frame_allocator(); enable_cpu_protections(); + + // TODO: remove inject_faux_pml4(allocator); + // TODO: implement + auto temporary_mapper = x86_64::scoped_mapping{linear_address{unused_page_address}, allocator}; + auto new_pml4_frame = allocator.allocate(); + + auto new_plm4 = temporary_mapper.map_as( + *new_pml4_frame, x86_64::page_table::entry::flags::present | x86_64::page_table::entry::flags::writable); + (*new_plm4)[510].frame(new_pml4_frame.value(), + x86_64::page_table::entry::flags::present | x86_64::page_table::entry::flags::writable); + // 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); -- cgit v1.2.3 From a96b1b4b43a1ed962b412c3d28db0fe00661d96f Mon Sep 17 00:00:00 2001 From: Felix Morgner Date: Tue, 2 Dec 2025 18:40:10 +0100 Subject: x86_64/memory: extract PML4 injection --- arch/x86_64/src/kapi/memory.cpp | 79 +++++++---------------------------------- 1 file changed, 12 insertions(+), 67 deletions(-) (limited to 'arch/x86_64/src/kapi') diff --git a/arch/x86_64/src/kapi/memory.cpp b/arch/x86_64/src/kapi/memory.cpp index 920c82b..36b1706 100644 --- a/arch/x86_64/src/kapi/memory.cpp +++ b/arch/x86_64/src/kapi/memory.cpp @@ -1,6 +1,5 @@ #include "kapi/memory.hpp" -#include "kapi/cio.hpp" #include "kapi/system.hpp" #include "x86_64/boot/boot.hpp" @@ -28,7 +27,8 @@ namespace teachos::memory // NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables) auto constinit allocator = static_cast(nullptr); - constexpr auto static unused_page_address = 0x0000'7fff'cafe'faceuz; + constexpr auto static unused_page_address = linear_address{0x0000'7fff'cafe'faceuz}; + constexpr auto static recursive_page_map_index = 510; auto create_memory_information() -> x86_64::region_allocator::memory_information { @@ -61,62 +61,18 @@ namespace teachos::memory auto inject_faux_pml4(frame_allocator & allocator) -> void { - using entry_flags = x86_64::page_table::entry::flags; - using page_table = x86_64::page_table; - - auto temporary_page = page::containing(linear_address{unused_page_address}); - auto temporary_page_address = temporary_page.start_address(); - - auto & pml4 = x86_64::paging_root::get(); - - // NOLINTBEGIN(cppcoreguidelines-avoid-magic-numbers) - auto faux_pml4_frame = - allocator.allocate() - .and_then([&](auto frame) -> auto { - auto index = temporary_page_address >> 39 & 0x1ffu; - pml4[index].frame(frame, entry_flags::present | entry_flags::writable); - return pml4.next(index); - }) - .and_then([&](auto pml) -> auto { - std::construct_at(pml); - auto index = temporary_page_address >> 30 & 0x1ffu; - (*pml)[index].frame(*allocator.allocate(), entry_flags::present | entry_flags::writable); - return pml->next(index); - }) - .and_then([&](auto pml) -> auto { - std::construct_at(pml); - auto index = temporary_page_address >> 21 & 0x1ffu; - (*pml)[index].frame(*allocator.allocate(), entry_flags::present | entry_flags::writable); - return pml->next(index); - }) - .transform([&](auto pml) -> auto { - std::construct_at(pml); - auto index = temporary_page_address >> 12 & 0x1ffu; - (*pml)[index].frame(*allocator.allocate(), entry_flags::present | entry_flags::writable); - return pml; - }) - .and_then([&](auto pml) -> auto { - auto faux_pml4_pointer = std::bit_cast(temporary_page_address.raw()); - auto faux_pml4 = std::construct_at(faux_pml4_pointer); - - auto index = temporary_page_address >> 12 & 0x1ffu; - auto frame = (*pml)[index].frame(); - - (*faux_pml4)[510].frame(*frame, entry_flags::present | entry_flags::writable); - return frame; - }); - // NOLINTEND(cppcoreguidelines-avoid-magic-numbers) - - if (!faux_pml4_frame) - { - system::panic("[MEM] Failed to map and construct faux PML4"); - } + using namespace x86_64; + using entry_flags = page_table::entry::flags; + + auto temporary_mapper = scoped_mapping{page::containing(unused_page_address), allocator}; + auto new_pml4_frame = allocator.allocate(); - // NOLINTNEXTLINE(cppcoreguidelines-avoid-magic-numbers) - pml4[510].frame(*faux_pml4_frame, entry_flags::present | entry_flags::writable); - x86_64::tlb_flush_all(); + auto pml4 = std::construct_at(temporary_mapper.map_as(*new_pml4_frame, entry_flags::writable)); + (*pml4)[recursive_page_map_index].frame(new_pml4_frame.value(), entry_flags::present | entry_flags::writable); + paging_root::get()[recursive_page_map_index].frame(new_pml4_frame.value(), + entry_flags::present | entry_flags::writable); - cio::println("[MEM] Injected faux PML4 as recursive map."); + tlb_flush_all(); } } // namespace @@ -141,19 +97,8 @@ namespace teachos::memory auto allocator = create_early_frame_allocator(); enable_cpu_protections(); - - // TODO: remove inject_faux_pml4(allocator); - // TODO: implement - auto temporary_mapper = x86_64::scoped_mapping{linear_address{unused_page_address}, allocator}; - auto new_pml4_frame = allocator.allocate(); - - auto new_plm4 = temporary_mapper.map_as( - *new_pml4_frame, x86_64::page_table::entry::flags::present | x86_64::page_table::entry::flags::writable); - (*new_plm4)[510].frame(new_pml4_frame.value(), - x86_64::page_table::entry::flags::present | x86_64::page_table::entry::flags::writable); - // 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); -- cgit v1.2.3 From 331c070547634a2096c5e2165559fb0f11ee6330 Mon Sep 17 00:00:00 2001 From: Felix Morgner Date: Tue, 2 Dec 2025 18:49:36 +0100 Subject: kapi: make PLATFORM_*_SIZE constexpr --- arch/x86_64/src/kapi/memory.cpp | 2 -- 1 file changed, 2 deletions(-) (limited to 'arch/x86_64/src/kapi') diff --git a/arch/x86_64/src/kapi/memory.cpp b/arch/x86_64/src/kapi/memory.cpp index 36b1706..1a8b36f 100644 --- a/arch/x86_64/src/kapi/memory.cpp +++ b/arch/x86_64/src/kapi/memory.cpp @@ -19,8 +19,6 @@ namespace teachos::memory { - std::size_t const PLATFORM_FRAME_SIZE{4096}; - std::size_t const PLATFORM_PAGE_SIZE{PLATFORM_FRAME_SIZE}; namespace { -- cgit v1.2.3 From 588fe1a3600475bdc312a4fe758d2f1125eb149c Mon Sep 17 00:00:00 2001 From: Felix Morgner Date: Tue, 2 Dec 2025 18:56:12 +0100 Subject: x86_64: basic code cleanup --- arch/x86_64/src/kapi/memory.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch/x86_64/src/kapi') diff --git a/arch/x86_64/src/kapi/memory.cpp b/arch/x86_64/src/kapi/memory.cpp index 1a8b36f..e138641 100644 --- a/arch/x86_64/src/kapi/memory.cpp +++ b/arch/x86_64/src/kapi/memory.cpp @@ -26,7 +26,7 @@ namespace teachos::memory auto constinit allocator = static_cast(nullptr); constexpr auto static unused_page_address = linear_address{0x0000'7fff'cafe'faceuz}; - constexpr auto static recursive_page_map_index = 510; + constexpr auto static recursive_page_map_index = x86_64::page_table::entry_count - 2; auto create_memory_information() -> x86_64::region_allocator::memory_information { -- cgit v1.2.3 From 148c54a3d470c6019ebebe1387a7d889a2b8808e Mon Sep 17 00:00:00 2001 From: Felix Morgner Date: Tue, 2 Dec 2025 19:17:42 +0100 Subject: x86_64/memory: introduce frame allocation buffer --- arch/x86_64/src/kapi/memory.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'arch/x86_64/src/kapi') diff --git a/arch/x86_64/src/kapi/memory.cpp b/arch/x86_64/src/kapi/memory.cpp index e138641..703b3e1 100644 --- a/arch/x86_64/src/kapi/memory.cpp +++ b/arch/x86_64/src/kapi/memory.cpp @@ -5,6 +5,7 @@ #include "x86_64/boot/boot.hpp" #include "x86_64/boot/ld.hpp" #include "x86_64/cpu/registers.hpp" +#include "x86_64/memory/buffered_allocator.hpp" #include "x86_64/memory/mmu.hpp" #include "x86_64/memory/page_table.hpp" #include "x86_64/memory/paging_root.hpp" @@ -95,7 +96,9 @@ namespace teachos::memory auto allocator = create_early_frame_allocator(); enable_cpu_protections(); - inject_faux_pml4(allocator); + + auto allocation_buffer = x86_64::buffered_allocator<4>{&allocator}; + inject_faux_pml4(allocation_buffer); // paging::kernel_mapper kernel(allocator, memory_information); // kernel.remap_kernel(); -- cgit v1.2.3 From 9331afdcbbe95bc1bd79d657f0d7c5b91a19a375 Mon Sep 17 00:00:00 2001 From: Felix Morgner Date: Tue, 2 Dec 2025 19:39:03 +0100 Subject: x86_64/memory: fix temporary page unmapping --- arch/x86_64/src/kapi/memory.cpp | 34 +++++++++++++++++++++++++++++++++- 1 file changed, 33 insertions(+), 1 deletion(-) (limited to 'arch/x86_64/src/kapi') diff --git a/arch/x86_64/src/kapi/memory.cpp b/arch/x86_64/src/kapi/memory.cpp index 703b3e1..0e4b78e 100644 --- a/arch/x86_64/src/kapi/memory.cpp +++ b/arch/x86_64/src/kapi/memory.cpp @@ -8,6 +8,7 @@ #include "x86_64/memory/buffered_allocator.hpp" #include "x86_64/memory/mmu.hpp" #include "x86_64/memory/page_table.hpp" +#include "x86_64/memory/page_utilities.hpp" #include "x86_64/memory/paging_root.hpp" #include "x86_64/memory/region_allocator.hpp" #include "x86_64/memory/scoped_mapping.hpp" @@ -63,15 +64,46 @@ namespace teachos::memory using namespace x86_64; using entry_flags = page_table::entry::flags; - auto temporary_mapper = scoped_mapping{page::containing(unused_page_address), allocator}; + auto page = page::containing(unused_page_address); + + auto temporary_mapper = scoped_mapping{page, allocator}; auto new_pml4_frame = allocator.allocate(); auto pml4 = std::construct_at(temporary_mapper.map_as(*new_pml4_frame, entry_flags::writable)); (*pml4)[recursive_page_map_index].frame(new_pml4_frame.value(), entry_flags::present | entry_flags::writable); + + auto pml4_index = pml_index<4>(page); + auto & old_pml4 = paging_root::get(); + auto pml4_entry = old_pml4[pml4_index]; + + auto pml3_index = pml_index<3>(page); + auto old_pml3 = old_pml4.next(pml4_index); + auto pml3_entry = (**old_pml3)[pml3_index]; + + auto pml2_index = pml_index<2>(page); + auto old_pml2 = (**old_pml3).next(pml3_index); + auto pml2_entry = (**old_pml2)[pml2_index]; + + auto pml1_index = pml_index<1>(page); + auto old_pml1 = (**old_pml2).next(pml2_index); + auto pml1_entry = (**old_pml1)[pml1_index]; + paging_root::get()[recursive_page_map_index].frame(new_pml4_frame.value(), entry_flags::present | entry_flags::writable); tlb_flush_all(); + + auto & new_pml4 = paging_root::get(); + new_pml4[pml4_index] = pml4_entry; + + auto new_pml3 = new_pml4.next(pml4_index); + (**new_pml3)[pml3_index] = pml3_entry; + + auto new_pml2 = (**new_pml3).next(pml3_index); + (**new_pml2)[pml2_index] = pml2_entry; + + auto new_pml1 = (**new_pml2).next(pml2_index); + (**new_pml1)[pml1_index] = pml1_entry; } } // namespace -- cgit v1.2.3 From 36cd516c84cf2edd16defcd39e99e2bee0bca892 Mon Sep 17 00:00:00 2001 From: Felix Morgner Date: Thu, 4 Dec 2025 22:52:35 +0100 Subject: x86_64/memory: simplify initialization implementation --- arch/x86_64/src/kapi/memory.cpp | 27 ++++++++++++++------------- 1 file changed, 14 insertions(+), 13 deletions(-) (limited to 'arch/x86_64/src/kapi') diff --git a/arch/x86_64/src/kapi/memory.cpp b/arch/x86_64/src/kapi/memory.cpp index 0e4b78e..d09a4c1 100644 --- a/arch/x86_64/src/kapi/memory.cpp +++ b/arch/x86_64/src/kapi/memory.cpp @@ -30,18 +30,7 @@ namespace teachos::memory constexpr auto static unused_page_address = linear_address{0x0000'7fff'cafe'faceuz}; constexpr auto static recursive_page_map_index = x86_64::page_table::entry_count - 2; - auto create_memory_information() -> x86_64::region_allocator::memory_information - { - auto const & mbi = boot::bootstrap_information.mbi; - auto mbi_span = std::span{std::bit_cast(mbi), mbi->size_bytes()}; - auto image_span = std::span{&boot::x86_64::_start_physical, &boot::x86_64::_end_physical}; - - return {.image_range = - std::make_pair(physical_address{&image_span.front()}, physical_address{&image_span.back()}), - .mbi_range = std::make_pair(physical_address{&mbi_span.front()}, physical_address{&mbi_span.back()}), - .memory_map = mbi->memory_map()}; - }; - + //! Instantiate a basic, memory region based, early frame allocator for remapping. auto create_early_frame_allocator() { auto memory_map = boot::bootstrap_information.mbi->maybe_memory_map(); @@ -50,15 +39,27 @@ namespace teachos::memory system::panic("[x86_64] Failed to create early allocator, no memory map available."); } - return x86_64::region_allocator{create_memory_information()}; + auto const & mbi = boot::bootstrap_information.mbi; + auto mbi_span = std::span{std::bit_cast(mbi), mbi->size_bytes()}; + auto image_span = std::span{&boot::x86_64::_start_physical, &boot::x86_64::_end_physical}; + + return x86_64::region_allocator{ + { + .image_range = std::make_pair(physical_address{&image_span.front()}, physical_address{&image_span.back()}), + .mbi_range = std::make_pair(physical_address{&mbi_span.front()}, physical_address{&mbi_span.back()}), + .memory_map = *memory_map, + } + }; } + //! Enable additional CPU protection features, required during later stages of the kernel. auto enable_cpu_protections() -> void { cpu::x86_64::cr0::set(cpu::x86_64::cr0::flags::write_protect); cpu::x86_64::i32_efer::set(cpu::x86_64::i32_efer::flags::execute_disable_bit_enable); } + //! Inject, or graft, a faux recursive PML4 into the active page mapping structure. auto inject_faux_pml4(frame_allocator & allocator) -> void { using namespace x86_64; -- cgit v1.2.3 From b9d445bf92725d79269becf978059e040519c00a Mon Sep 17 00:00:00 2001 From: Felix Morgner Date: Wed, 10 Dec 2025 16:51:44 +0100 Subject: x86_64/memory: implement simple kernel remapper --- arch/x86_64/src/kapi/memory.cpp | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) (limited to 'arch/x86_64/src/kapi') diff --git a/arch/x86_64/src/kapi/memory.cpp b/arch/x86_64/src/kapi/memory.cpp index d09a4c1..ed3edef 100644 --- a/arch/x86_64/src/kapi/memory.cpp +++ b/arch/x86_64/src/kapi/memory.cpp @@ -1,11 +1,14 @@ #include "kapi/memory.hpp" +#include "kapi/cio.hpp" #include "kapi/system.hpp" #include "x86_64/boot/boot.hpp" #include "x86_64/boot/ld.hpp" +#include "x86_64/cpu/impl/control_registers.hpp" #include "x86_64/cpu/registers.hpp" #include "x86_64/memory/buffered_allocator.hpp" +#include "x86_64/memory/kernel_mapper.hpp" #include "x86_64/memory/mmu.hpp" #include "x86_64/memory/page_table.hpp" #include "x86_64/memory/page_utilities.hpp" @@ -60,7 +63,7 @@ namespace teachos::memory } //! Inject, or graft, a faux recursive PML4 into the active page mapping structure. - auto inject_faux_pml4(frame_allocator & allocator) -> void + auto inject_faux_pml4(frame_allocator & allocator) { using namespace x86_64; using entry_flags = page_table::entry::flags; @@ -105,6 +108,8 @@ namespace teachos::memory auto new_pml1 = (**new_pml2).next(pml2_index); (**new_pml1)[pml1_index] = pml1_entry; + + return *new_pml4_frame; } } // namespace @@ -131,12 +136,15 @@ namespace teachos::memory enable_cpu_protections(); auto allocation_buffer = x86_64::buffered_allocator<4>{&allocator}; - inject_faux_pml4(allocation_buffer); + auto new_pml4_frame = inject_faux_pml4(allocation_buffer); - // 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(); + auto mapper = x86_64::kernel_mapper{allocation_buffer, boot::bootstrap_information.mbi}; + mapper.remap_kernel(); + cio::println("[x86_64:MEM] prepared new kernel image page maps."); + + auto cr3 = cpu::x86_64::cr3::read(); + cr3.address(new_pml4_frame.start_address()); + cpu::x86_64::cr3::write(cr3); // 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); -- cgit v1.2.3 From eafbf588760c289b7f54a4771b39af0ccfe8cf59 Mon Sep 17 00:00:00 2001 From: Felix Morgner Date: Wed, 10 Dec 2025 21:55:42 +0100 Subject: kapi: extract page_mapper interface --- arch/x86_64/src/kapi/memory.cpp | 29 ++++++++++++++++++++++++----- 1 file changed, 24 insertions(+), 5 deletions(-) (limited to 'arch/x86_64/src/kapi') diff --git a/arch/x86_64/src/kapi/memory.cpp b/arch/x86_64/src/kapi/memory.cpp index ed3edef..00b9de3 100644 --- a/arch/x86_64/src/kapi/memory.cpp +++ b/arch/x86_64/src/kapi/memory.cpp @@ -13,6 +13,7 @@ #include "x86_64/memory/page_table.hpp" #include "x86_64/memory/page_utilities.hpp" #include "x86_64/memory/paging_root.hpp" +#include "x86_64/memory/recursive_page_mapper.hpp" #include "x86_64/memory/region_allocator.hpp" #include "x86_64/memory/scoped_mapping.hpp" @@ -29,6 +30,8 @@ namespace teachos::memory { // NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables) auto constinit allocator = static_cast(nullptr); + // NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables) + auto constinit mapper = static_cast(nullptr); constexpr auto static unused_page_address = linear_address{0x0000'7fff'cafe'faceuz}; constexpr auto static recursive_page_map_index = x86_64::page_table::entry_count - 2; @@ -70,7 +73,7 @@ namespace teachos::memory auto page = page::containing(unused_page_address); - auto temporary_mapper = scoped_mapping{page, allocator}; + auto temporary_mapper = scoped_mapping{page}; auto new_pml4_frame = allocator.allocate(); auto pml4 = std::construct_at(temporary_mapper.map_as(*new_pml4_frame, entry_flags::writable)); @@ -124,6 +127,15 @@ namespace teachos::memory return *allocator; } + auto active_mapper() -> page_mapper & + { + if (!mapper) + { + system::panic("[x86_64] The page mapper has not been set you."); + } + return *mapper; + } + auto init() -> void { auto static constinit is_initialized = std::atomic_flag{}; @@ -132,14 +144,19 @@ namespace teachos::memory system::panic("[x86_64] Memory management has already been initialized."); } - auto allocator = create_early_frame_allocator(); enable_cpu_protections(); - auto allocation_buffer = x86_64::buffered_allocator<4>{&allocator}; + auto early_allocator = create_early_frame_allocator(); + auto allocation_buffer = x86_64::buffered_allocator<4>{&early_allocator}; + allocator = &allocation_buffer; + + auto recursive_mapper = x86_64::recursive_page_mapper{allocation_buffer}; + mapper = &recursive_mapper; + auto new_pml4_frame = inject_faux_pml4(allocation_buffer); - auto mapper = x86_64::kernel_mapper{allocation_buffer, boot::bootstrap_information.mbi}; - mapper.remap_kernel(); + auto kernel_mapper = x86_64::kernel_mapper{boot::bootstrap_information.mbi}; + kernel_mapper.remap_kernel(); cio::println("[x86_64:MEM] prepared new kernel image page maps."); auto cr3 = cpu::x86_64::cr3::read(); @@ -149,6 +166,8 @@ namespace teachos::memory // 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(); + mapper = nullptr; + allocator = nullptr; } } // namespace teachos::memory -- cgit v1.2.3 From cf8d0d899ee17db734ce8ab7ee618333eb1767f2 Mon Sep 17 00:00:00 2001 From: Felix Morgner Date: Thu, 11 Dec 2025 18:36:23 +0100 Subject: kapi: finish documentation --- arch/x86_64/src/kapi/memory.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'arch/x86_64/src/kapi') diff --git a/arch/x86_64/src/kapi/memory.cpp b/arch/x86_64/src/kapi/memory.cpp index 00b9de3..cd0bd77 100644 --- a/arch/x86_64/src/kapi/memory.cpp +++ b/arch/x86_64/src/kapi/memory.cpp @@ -117,7 +117,7 @@ namespace teachos::memory } // namespace - auto active_allocator() -> frame_allocator & + auto active_frame_allocator() -> frame_allocator & { if (!allocator) { @@ -127,7 +127,7 @@ namespace teachos::memory return *allocator; } - auto active_mapper() -> page_mapper & + auto active_page_mapper() -> page_mapper & { if (!mapper) { -- cgit v1.2.3 From 4bb59ebf68351754ab97e722914e0434c4d347fd Mon Sep 17 00:00:00 2001 From: Felix Morgner Date: Fri, 12 Dec 2025 10:51:55 +0100 Subject: x86_64/cio: disable cursor by default --- arch/x86_64/src/kapi/cio.cpp | 1 + 1 file changed, 1 insertion(+) (limited to 'arch/x86_64/src/kapi') diff --git a/arch/x86_64/src/kapi/cio.cpp b/arch/x86_64/src/kapi/cio.cpp index 456477a..3f169a1 100644 --- a/arch/x86_64/src/kapi/cio.cpp +++ b/arch/x86_64/src/kapi/cio.cpp @@ -11,6 +11,7 @@ namespace teachos::cio auto init() -> void { vga_device.emplace(); + vga_device->cursor(false); set_output_device(*vga_device); } -- cgit v1.2.3 From 6fdfe22f75c7202eee84b9b89f6abd5dbc60fedc Mon Sep 17 00:00:00 2001 From: Felix Morgner Date: Fri, 12 Dec 2025 10:54:22 +0100 Subject: x86_64/cpu: flatten file hierarchy --- arch/x86_64/src/kapi/memory.cpp | 1 - 1 file changed, 1 deletion(-) (limited to 'arch/x86_64/src/kapi') diff --git a/arch/x86_64/src/kapi/memory.cpp b/arch/x86_64/src/kapi/memory.cpp index cd0bd77..a20483c 100644 --- a/arch/x86_64/src/kapi/memory.cpp +++ b/arch/x86_64/src/kapi/memory.cpp @@ -5,7 +5,6 @@ #include "x86_64/boot/boot.hpp" #include "x86_64/boot/ld.hpp" -#include "x86_64/cpu/impl/control_registers.hpp" #include "x86_64/cpu/registers.hpp" #include "x86_64/memory/buffered_allocator.hpp" #include "x86_64/memory/kernel_mapper.hpp" -- cgit v1.2.3 From 8fc5f9e3cc28b07b1f120eb1ffedc042fa6662b8 Mon Sep 17 00:00:00 2001 From: Felix Morgner Date: Fri, 12 Dec 2025 13:00:26 +0100 Subject: x86_64/kapi: implement remaining mapping steps --- arch/x86_64/src/kapi/memory.cpp | 54 ++++++++++++++++++++++++++++++++++++----- 1 file changed, 48 insertions(+), 6 deletions(-) (limited to 'arch/x86_64/src/kapi') diff --git a/arch/x86_64/src/kapi/memory.cpp b/arch/x86_64/src/kapi/memory.cpp index a20483c..abc0526 100644 --- a/arch/x86_64/src/kapi/memory.cpp +++ b/arch/x86_64/src/kapi/memory.cpp @@ -1,5 +1,6 @@ #include "kapi/memory.hpp" +#include "kapi/boot.hpp" #include "kapi/cio.hpp" #include "kapi/system.hpp" @@ -19,6 +20,7 @@ #include #include +#include #include #include @@ -114,6 +116,42 @@ namespace teachos::memory return *new_pml4_frame; } + auto remap_kernel() -> void + { + auto kernel_mapper = x86_64::kernel_mapper{boot::bootstrap_information.mbi}; + kernel_mapper.remap_kernel(); + } + + auto remap_vga_text_mode_buffer(page_mapper & mapper) -> void + { + constexpr auto vga_base = std::uintptr_t{0xb8000}; + auto vga_physical_start = physical_address{vga_base}; + auto vga_virtual_start = linear_address{vga_base + std::bit_cast(&boot::x86_64::TEACHOS_VMA)}; + + auto page = page::containing(vga_virtual_start); + auto frame = frame::containing(vga_physical_start); + + mapper.map(page, frame, page_mapper::flags::writable); + } + + auto remap_multiboot_information(page_mapper & mapper) -> void + { + auto mbi_base = std::bit_cast(boot::bootstrap_information.mbi); + auto mbi_size = boot::bootstrap_information.mbi->size_bytes(); + auto mbi_physical_start = physical_address{mbi_base}; + auto mbi_virtual_start = linear_address{mbi_base + std::bit_cast(&boot::x86_64::TEACHOS_VMA)}; + auto mbi_block_count = (mbi_size + PLATFORM_FRAME_SIZE - 1) / PLATFORM_FRAME_SIZE; + + for (auto i = 0uz; i < mbi_block_count; ++i) + { + auto page = page::containing(mbi_virtual_start) + 1; + auto frame = frame::containing(mbi_physical_start) + 1; + mapper.map(page, frame, page_mapper::flags::empty); + } + + boot::bootstrap_information.mbi = std::bit_cast(mbi_virtual_start.raw()); + } + } // namespace auto active_frame_allocator() -> frame_allocator & @@ -138,11 +176,14 @@ namespace teachos::memory auto init() -> void { auto static constinit is_initialized = std::atomic_flag{}; + if (is_initialized.test_and_set()) { system::panic("[x86_64] Memory management has already been initialized."); } + cio::println("[x86_64:MEM] Enabling additional CPU protection features."); + enable_cpu_protections(); auto early_allocator = create_early_frame_allocator(); @@ -154,17 +195,18 @@ namespace teachos::memory auto new_pml4_frame = inject_faux_pml4(allocation_buffer); - auto kernel_mapper = x86_64::kernel_mapper{boot::bootstrap_information.mbi}; - kernel_mapper.remap_kernel(); - cio::println("[x86_64:MEM] prepared new kernel image page maps."); + cio::println("[x86_64:MEM] Preparing new paging hierarchy."); + + remap_kernel(); + remap_vga_text_mode_buffer(recursive_mapper); + remap_multiboot_information(recursive_mapper); + + cio::println("[x86_64:MEM] Switching to new paging hierarchy."); auto cr3 = cpu::x86_64::cr3::read(); cr3.address(new_pml4_frame.start_address()); cpu::x86_64::cr3::write(cr3); - // 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(); mapper = nullptr; allocator = nullptr; } -- cgit v1.2.3 From 50c9c9a1d963e66f7658ab31e9ecd65bf227cfff Mon Sep 17 00:00:00 2001 From: Felix Morgner Date: Fri, 12 Dec 2025 14:07:28 +0100 Subject: x86_64/memory: clean up dependencies --- arch/x86_64/src/kapi/memory.cpp | 36 +++++++++++++++--------------------- 1 file changed, 15 insertions(+), 21 deletions(-) (limited to 'arch/x86_64/src/kapi') diff --git a/arch/x86_64/src/kapi/memory.cpp b/arch/x86_64/src/kapi/memory.cpp index abc0526..ae0401e 100644 --- a/arch/x86_64/src/kapi/memory.cpp +++ b/arch/x86_64/src/kapi/memory.cpp @@ -67,25 +67,25 @@ namespace teachos::memory } //! Inject, or graft, a faux recursive PML4 into the active page mapping structure. - auto inject_faux_pml4(frame_allocator & allocator) + auto inject_faux_pml4(frame_allocator & allocator, page_mapper & mapper) { using namespace x86_64; using entry_flags = page_table::entry::flags; auto page = page::containing(unused_page_address); - auto temporary_mapper = scoped_mapping{page}; + auto temporary_mapper = scoped_mapping{page, mapper}; auto new_pml4_frame = allocator.allocate(); auto pml4 = std::construct_at(temporary_mapper.map_as(*new_pml4_frame, entry_flags::writable)); (*pml4)[recursive_page_map_index].frame(new_pml4_frame.value(), entry_flags::present | entry_flags::writable); auto pml4_index = pml_index<4>(page); - auto & old_pml4 = paging_root::get(); - auto pml4_entry = old_pml4[pml4_index]; + auto old_pml4 = paging_root::get(); + auto pml4_entry = (*old_pml4)[pml4_index]; auto pml3_index = pml_index<3>(page); - auto old_pml3 = old_pml4.next(pml4_index); + auto old_pml3 = old_pml4->next(pml4_index); auto pml3_entry = (**old_pml3)[pml3_index]; auto pml2_index = pml_index<2>(page); @@ -96,15 +96,15 @@ namespace teachos::memory auto old_pml1 = (**old_pml2).next(pml2_index); auto pml1_entry = (**old_pml1)[pml1_index]; - paging_root::get()[recursive_page_map_index].frame(new_pml4_frame.value(), - entry_flags::present | entry_flags::writable); + (*paging_root::get())[recursive_page_map_index].frame(new_pml4_frame.value(), + entry_flags::present | entry_flags::writable); tlb_flush_all(); - auto & new_pml4 = paging_root::get(); - new_pml4[pml4_index] = pml4_entry; + auto new_pml4 = paging_root::get(); + (*new_pml4)[pml4_index] = pml4_entry; - auto new_pml3 = new_pml4.next(pml4_index); + auto new_pml3 = new_pml4->next(pml4_index); (**new_pml3)[pml3_index] = pml3_entry; auto new_pml2 = (**new_pml3).next(pml3_index); @@ -116,10 +116,10 @@ namespace teachos::memory return *new_pml4_frame; } - auto remap_kernel() -> void + auto remap_kernel(page_mapper & mapper) -> void { auto kernel_mapper = x86_64::kernel_mapper{boot::bootstrap_information.mbi}; - kernel_mapper.remap_kernel(); + kernel_mapper.remap_kernel(mapper); } auto remap_vga_text_mode_buffer(page_mapper & mapper) -> void @@ -188,16 +188,13 @@ namespace teachos::memory auto early_allocator = create_early_frame_allocator(); auto allocation_buffer = x86_64::buffered_allocator<4>{&early_allocator}; - allocator = &allocation_buffer; - auto recursive_mapper = x86_64::recursive_page_mapper{allocation_buffer}; - mapper = &recursive_mapper; - - auto new_pml4_frame = inject_faux_pml4(allocation_buffer); cio::println("[x86_64:MEM] Preparing new paging hierarchy."); - remap_kernel(); + auto new_pml4_frame = inject_faux_pml4(allocation_buffer, recursive_mapper); + + remap_kernel(recursive_mapper); remap_vga_text_mode_buffer(recursive_mapper); remap_multiboot_information(recursive_mapper); @@ -206,9 +203,6 @@ namespace teachos::memory auto cr3 = cpu::x86_64::cr3::read(); cr3.address(new_pml4_frame.start_address()); cpu::x86_64::cr3::write(cr3); - - mapper = nullptr; - allocator = nullptr; } } // namespace teachos::memory -- cgit v1.2.3 From 40804526a58ddf2cc0df0750550c8dcfa7b7c57c Mon Sep 17 00:00:00 2001 From: Felix Morgner Date: Mon, 15 Dec 2025 11:34:30 +0100 Subject: x86_64/boot: use high-mem address of MBI --- arch/x86_64/src/kapi/memory.cpp | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'arch/x86_64/src/kapi') diff --git a/arch/x86_64/src/kapi/memory.cpp b/arch/x86_64/src/kapi/memory.cpp index ae0401e..748893a 100644 --- a/arch/x86_64/src/kapi/memory.cpp +++ b/arch/x86_64/src/kapi/memory.cpp @@ -138,8 +138,8 @@ namespace teachos::memory { auto mbi_base = std::bit_cast(boot::bootstrap_information.mbi); auto mbi_size = boot::bootstrap_information.mbi->size_bytes(); - auto mbi_physical_start = physical_address{mbi_base}; - auto mbi_virtual_start = linear_address{mbi_base + std::bit_cast(&boot::x86_64::TEACHOS_VMA)}; + auto mbi_physical_start = physical_address{mbi_base & ~std::bit_cast(&boot::x86_64::TEACHOS_VMA)}; + auto mbi_virtual_start = linear_address{mbi_base}; auto mbi_block_count = (mbi_size + PLATFORM_FRAME_SIZE - 1) / PLATFORM_FRAME_SIZE; for (auto i = 0uz; i < mbi_block_count; ++i) @@ -148,8 +148,6 @@ namespace teachos::memory auto frame = frame::containing(mbi_physical_start) + 1; mapper.map(page, frame, page_mapper::flags::empty); } - - boot::bootstrap_information.mbi = std::bit_cast(mbi_virtual_start.raw()); } } // namespace -- cgit v1.2.3 From 43ddde5e30a0d71aa11025a5ae232cea83e7fbde Mon Sep 17 00:00:00 2001 From: Felix Morgner Date: Mon, 15 Dec 2025 16:28:16 +0100 Subject: kapi: remodel memory API to follow cio API --- arch/x86_64/src/kapi/memory.cpp | 27 +++------------------------ 1 file changed, 3 insertions(+), 24 deletions(-) (limit