aboutsummaryrefslogtreecommitdiff
path: root/arch/x86_64/kapi
diff options
context:
space:
mode:
authorLukas Oesch <lukas.oesch@ost.ch>2026-06-10 10:40:46 +0200
committerLukas Oesch <lukas.oesch@ost.ch>2026-06-10 10:40:46 +0200
commit33abd5cf264cb9e34121082105b0bc17b3cf7a36 (patch)
tree36b15d53fea04f4f9d9af817100f7ad013bd9b5c /arch/x86_64/kapi
parentd01caf1c4aef3c89c68b9d1cc9fe56445f0860b5 (diff)
parent7e27130c342b7299a1d2188a7192a7f17b5ac2ad (diff)
downloadkernel-33abd5cf264cb9e34121082105b0bc17b3cf7a36.tar.xz
kernel-33abd5cf264cb9e34121082105b0bc17b3cf7a36.zip
Merge branch 'develop-BA-FS26' into 'develop'HEADdevelop
Merge of BA-FS26 branch into develop See merge request teachos/kernel!49
Diffstat (limited to 'arch/x86_64/kapi')
-rw-r--r--arch/x86_64/kapi/boot_modules.cpp53
-rw-r--r--arch/x86_64/kapi/cio.cpp6
-rw-r--r--arch/x86_64/kapi/cpu.cpp80
-rw-r--r--arch/x86_64/kapi/devices.cpp14
-rw-r--r--arch/x86_64/kapi/interrupts.cpp16
-rw-r--r--arch/x86_64/kapi/memory.cpp67
-rw-r--r--arch/x86_64/kapi/system.cpp118
7 files changed, 216 insertions, 138 deletions
diff --git a/arch/x86_64/kapi/boot_modules.cpp b/arch/x86_64/kapi/boot_modules.cpp
new file mode 100644
index 0000000..fb6bf46
--- /dev/null
+++ b/arch/x86_64/kapi/boot_modules.cpp
@@ -0,0 +1,53 @@
+#include <kapi/boot_modules.hpp>
+
+#include <arch/boot/boot.hpp>
+#include <arch/boot/ld.hpp>
+
+#include <kapi/boot.hpp>
+#include <kapi/boot_module/boot_module.hpp>
+#include <kapi/boot_module/boot_module_registry.hpp>
+#include <kapi/memory.hpp>
+#include <kapi/system.hpp>
+
+#include <kstd/print>
+
+#include <multiboot2/information.hpp>
+
+#include <algorithm>
+#include <atomic>
+#include <bit>
+#include <cstdint>
+#include <optional>
+
+namespace kapi::boot_modules
+{
+ namespace
+ {
+ auto constinit registry = std::optional<kapi::boot_modules::boot_module_registry>{};
+ } // namespace
+
+ auto init() -> void
+ {
+ auto static constinit is_initialized = std::atomic_flag{};
+ if (is_initialized.test_and_set())
+ {
+ system::panic("[x86_64] Boot module registry has already been initialized.");
+ }
+
+ kstd::println("[x86_64:BOOT_MODULES] Initializing boot module registry.");
+
+ registry.emplace(kapi::boot_modules::boot_module_registry{});
+
+ auto modules = boot::bootstrap_information.mbi->modules();
+ std::ranges::for_each(modules, [](auto const & module) {
+ registry->add_boot_module(kapi::boot_modules::boot_module{
+ .name = module.string(),
+ .start_address =
+ memory::linear_address{module.start_address + std::bit_cast<std::uintptr_t>(&arch::boot::TEACHOS_VMA)},
+ .size = module.end_address - module.start_address,
+ });
+ });
+
+ set_boot_module_registry(*registry);
+ }
+} // namespace kapi::boot_modules \ No newline at end of file
diff --git a/arch/x86_64/kapi/cio.cpp b/arch/x86_64/kapi/cio.cpp
index 015cf5e..b33c6e0 100644
--- a/arch/x86_64/kapi/cio.cpp
+++ b/arch/x86_64/kapi/cio.cpp
@@ -1,7 +1,7 @@
-#include "kapi/cio.hpp"
+#include <kapi/cio.hpp>
-#include "arch/debug/qemu_output.hpp"
-#include "arch/vga/text.hpp"
+#include <arch/debug/qemu_output.hpp>
+#include <arch/vga/text.hpp>
#include <optional>
diff --git a/arch/x86_64/kapi/cpu.cpp b/arch/x86_64/kapi/cpu.cpp
index 2a0f8f7..40dc228 100644
--- a/arch/x86_64/kapi/cpu.cpp
+++ b/arch/x86_64/kapi/cpu.cpp
@@ -1,12 +1,90 @@
-#include "kapi/cpu.hpp"
+#include <kapi/cpu.hpp>
+
+#include <arch/cpu/initialization.hpp>
+#include <arch/devices/local_apic.hpp>
+
+#include <kapi/acpi.hpp>
+#include <kapi/devices.hpp>
+#include <kapi/devices/cpu.hpp>
+#include <kapi/memory.hpp>
+#include <kapi/system.hpp>
+
+#include <acpi/acpi.hpp>
+
+#include <kstd/memory>
+#include <kstd/print>
+
+#include <atomic>
+#include <ranges>
+#include <utility>
namespace kapi::cpu
{
+ namespace
+ {
+ constexpr auto candidate_flags = ::acpi::processor_local_apic_entry::flags::processor_enabled //
+ | ::acpi::processor_local_apic_entry::flags::online_capable;
+ }
+
+ auto init() -> void
+ {
+ auto static constinit is_initialized = std::atomic_flag{};
+
+ if (is_initialized.test_and_set())
+ {
+ system::panic("[x86_64] CPU has already been initialized.");
+ }
+
+ arch::cpu::initialize_descriptors();
+ arch::cpu::initialize_legacy_interrupts();
+ }
+
auto halt() -> void
{
asm volatile("1: hlt\njmp 1b");
__builtin_unreachable();
}
+ auto discover_topology() -> bool
+ {
+ auto static const cpu_major = kapi::devices::allocate_major_number();
+ auto static const core_major = kapi::devices::allocate_major_number();
+ auto static const interrupt_controller_major = kapi::devices::allocate_major_number();
+
+ auto madt = kapi::acpi::get_table<::acpi::table_signature_v<::acpi::madt>>();
+ if (!madt)
+ {
+ kstd::println("[x86_64:PLT] Failed to find ACPI APIC table");
+ return false;
+ }
+
+ auto lapic_entries = *madt | std::views::filter([](auto const & entry) {
+ return entry.type() == ::acpi::madt_entry::type::processor_local_apic;
+ }) | std::views::transform([](auto const & entry) {
+ return static_cast<::acpi::processor_local_apic_entry const &>(entry);
+ }) | std::views::filter([](auto const & entry) { return static_cast<bool>(entry.flags() & candidate_flags); });
+
+ auto bsp_found = false;
+ auto core_count = 0uz;
+ auto local_apic_address = memory::physical_address{madt->local_interrupt_controller_address()};
+ auto cpu_bus = kstd::make_unique<devices::cpu>(cpu_major, 0);
+
+ for (auto const & apic : lapic_entries)
+ {
+ auto is_bsp = !bsp_found;
+ bsp_found = true;
+ auto core = kstd::make_unique<devices::cpu::core>(core_major, core_count, apic.processor_id(), is_bsp);
+ core->add_child(kstd::make_unique<arch::devices::local_apic>(interrupt_controller_major, core_count, apic.id(),
+ local_apic_address, is_bsp));
+ cpu_bus->add_child(std::move(core));
+ ++core_count;
+ }
+
+ devices::get_root_bus().add_child(std::move(cpu_bus));
+
+ kstd::println("[x86_64:PLT] Found {} CPU cores", core_count);
+ return core_count > 0;
+ }
+
} // namespace kapi::cpu
diff --git a/arch/x86_64/kapi/devices.cpp b/arch/x86_64/kapi/devices.cpp
new file mode 100644
index 0000000..f188c92
--- /dev/null
+++ b/arch/x86_64/kapi/devices.cpp
@@ -0,0 +1,14 @@
+#include <kapi/devices.hpp>
+
+#include <arch/devices/init.hpp>
+
+namespace kapi::devices
+{
+
+ auto init_platform_devices() -> void
+ {
+ arch::devices::init_acpi_devices();
+ arch::devices::init_legacy_devices();
+ }
+
+} // namespace kapi::devices \ No newline at end of file
diff --git a/arch/x86_64/kapi/interrupts.cpp b/arch/x86_64/kapi/interrupts.cpp
new file mode 100644
index 0000000..85acc0f
--- /dev/null
+++ b/arch/x86_64/kapi/interrupts.cpp
@@ -0,0 +1,16 @@
+#include <kapi/interrupts.hpp>
+
+namespace kapi::interrupts
+{
+
+ auto enable() -> void
+ {
+ asm volatile("sti");
+ }
+
+ auto disable() -> void
+ {
+ asm volatile("cli");
+ }
+
+} // namespace kapi::interrupts \ No newline at end of file
diff --git a/arch/x86_64/kapi/memory.cpp b/arch/x86_64/kapi/memory.cpp
index a9e1216..5b870d5 100644
--- a/arch/x86_64/kapi/memory.cpp
+++ b/arch/x86_64/kapi/memory.cpp
@@ -1,18 +1,19 @@
-#include "kapi/memory.hpp"
+#include <kapi/memory.hpp>
-#include "kapi/boot.hpp"
-#include "kapi/system.hpp"
+#include <arch/boot/boot.hpp>
+#include <arch/boot/ld.hpp>
+#include <arch/cpu/registers.hpp>
+#include <arch/memory/higher_half_mapper.hpp>
+#include <arch/memory/kernel_mapper.hpp>
+#include <arch/memory/page_table.hpp>
+#include <arch/memory/page_utilities.hpp>
+#include <arch/memory/region_allocator.hpp>
-#include "arch/boot/boot.hpp"
-#include "arch/boot/ld.hpp"
-#include "arch/cpu/registers.hpp"
-#include "arch/memory/higher_half_mapper.hpp"
-#include "arch/memory/kernel_mapper.hpp"
-#include "arch/memory/page_table.hpp"
-#include "arch/memory/page_utilities.hpp"
-#include "arch/memory/region_allocator.hpp"
+#include <kapi/boot.hpp>
+#include <kapi/system.hpp>
#include <kstd/print>
+#include <kstd/units>
#include <multiboot2/constants.hpp>
#include <multiboot2/information.hpp>
@@ -28,6 +29,8 @@
#include <span>
#include <utility>
+using namespace kstd::units_literals;
+
namespace kapi::memory
{
@@ -46,13 +49,14 @@ namespace kapi::memory
}
auto const & mbi = boot::bootstrap_information.mbi;
- auto mbi_span = std::span{std::bit_cast<std::byte *>(mbi), mbi->size_bytes()};
+ auto mbi_span = std::span{std::bit_cast<std::byte *>(mbi), static_cast<std::size_t>(mbi->size())};
auto image_span = std::span{&arch::boot::_start_physical, &arch::boot::_end_physical};
return arch::memory::region_allocator::memory_information{
.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,
+ .mbi = mbi,
};
}
@@ -106,10 +110,10 @@ namespace kapi::memory
[[maybe_unused]] auto remap_multiboot_information(page_mapper & mapper) -> void
{
auto mbi_base = std::bit_cast<std::uintptr_t>(boot::bootstrap_information.mbi);
- auto mbi_size = boot::bootstrap_information.mbi->size_bytes();
+ auto mbi_size = boot::bootstrap_information.mbi->size();
auto mbi_physical_start = physical_address{mbi_base & ~std::bit_cast<std::uintptr_t>(&arch::boot::TEACHOS_VMA)};
auto mbi_virtual_start = linear_address{mbi_base};
- auto mbi_block_count = (mbi_size + PLATFORM_FRAME_SIZE - 1) / PLATFORM_FRAME_SIZE;
+ auto mbi_block_count = (mbi_size + frame::size - 1_B) / frame::size;
for (auto i = 0uz; i < mbi_block_count; ++i)
{
@@ -119,6 +123,24 @@ namespace kapi::memory
}
}
+ [[maybe_unused]] auto remap_bootloader_modules(page_mapper & mapper) -> void
+ {
+ std::ranges::for_each(boot::bootstrap_information.mbi->modules(), [&mapper](auto const & module) {
+ auto module_physical_start = physical_address{module.start_address};
+ auto module_virtual_start =
+ linear_address{module.start_address + std::bit_cast<std::uintptr_t>(&arch::boot::TEACHOS_VMA)};
+ auto module_size = static_cast<kstd::units::bytes>(module.end_address - module.start_address);
+ auto module_block_count = (module_size + frame::size - 1_B) / frame::size;
+
+ for (auto i = 0uz; i < module_block_count; ++i)
+ {
+ auto page = page::containing(module_virtual_start) + i;
+ auto frame = frame::containing(module_physical_start) + i;
+ mapper.map(page, frame, page_mapper::flags::writable | page_mapper::flags::supervisor_only);
+ }
+ });
+ }
+
[[maybe_unused]] auto handoff_to_kernel_pmm(frame_allocator & new_allocator) -> void
{
auto memory_map = boot::bootstrap_information.mbi->memory_map();
@@ -128,7 +150,7 @@ namespace kapi::memory
}))
{
auto start = frame::containing(physical_address{region.base});
- auto count = region.size_in_B / page::size;
+ auto count = kstd::units::bytes{region.size_in_B} / page::size;
new_allocator.release_many({start, count});
}
@@ -148,14 +170,22 @@ namespace kapi::memory
[&](auto frame) { new_allocator.mark_used(frame); });
auto mbi_base = std::bit_cast<std::uintptr_t>(boot::bootstrap_information.mbi);
- auto mbi_size = boot::bootstrap_information.mbi->size_bytes();
+ auto mbi_size = boot::bootstrap_information.mbi->size();
auto mbi_address = physical_address{mbi_base & ~std::bit_cast<std::uintptr_t>(&arch::boot::TEACHOS_VMA)};
auto mbi_start = frame::containing(mbi_address);
auto mbi_end = frame::containing(mbi_address + mbi_size) + 1;
- // TODO BA-FS26: Protect MB2 boot modules
-
std::ranges::for_each(std::views::iota(mbi_start, mbi_end), [&](auto frame) { new_allocator.mark_used(frame); });
+
+ std::ranges::for_each(boot::bootstrap_information.mbi->modules(), [&](auto const & module) {
+ auto module_physical_start = physical_address{module.start_address};
+ auto module_size = module.end_address - module.start_address;
+ auto module_start = frame::containing(module_physical_start);
+ auto module_end = frame::containing(module_physical_start + module_size) + 1;
+
+ std::ranges::for_each(std::views::iota(module_start, module_end),
+ [&](auto frame) { new_allocator.mark_used(frame); });
+ });
}
} // namespace
@@ -196,6 +226,7 @@ namespace kapi::memory
remap_kernel(*higher_half_mapper);
remap_vga_text_mode_buffer(*higher_half_mapper);
remap_multiboot_information(*higher_half_mapper);
+ remap_bootloader_modules(*higher_half_mapper);
auto current_cr3 = arch::cpu::cr3::read();
auto old_pml4 = static_cast<arch::memory::page_table *>(current_cr3.address());
diff --git a/arch/x86_64/kapi/system.cpp b/arch/x86_64/kapi/system.cpp
index ca4418e..73a77e5 100644
--- a/arch/x86_64/kapi/system.cpp
+++ b/arch/x86_64/kapi/system.cpp
@@ -1,122 +1,8 @@
-#include "kapi/system.hpp"
-
-#include "arch/cpu/global_descriptor_table.hpp"
-#include "arch/cpu/segment_descriptor.hpp"
-#include "arch/cpu/task_state_segment.hpp"
-
-#include <kstd/print>
-
-#include <bit>
-#include <cstdint>
+#include <kapi/system.hpp>
namespace kapi::system
{
- namespace
- {
- constexpr auto gdt_null_descriptor = arch::cpu::segment_descriptor{};
-
- constexpr auto gdt_kernel_code_descriptor = arch::cpu::segment_descriptor{
- .limit_low = 0xffff,
- .base_low = 0,
- .accessed = false,
- .read_write = false,
- .direction_or_conforming = false,
- .executable = true,
- .type = arch::cpu::segment_type::code_or_data,
- .privilege_level = 0,
- .present = true,
- .limit_high = 0xf,
- .long_mode = true,
- .protected_mode = false,
- .granularity = arch::cpu::segment_granularity::page,
- .base_high = 0,
- };
-
- constexpr auto gdt_kernel_data_descriptor = arch::cpu::segment_descriptor{
- .limit_low = 0xffff,
- .base_low = 0,
- .accessed = false,
- .read_write = true,
- .direction_or_conforming = false,
- .executable = false,
- .type = arch::cpu::segment_type::code_or_data,
- .privilege_level = 0,
- .present = true,
- .limit_high = 0xf,
- .long_mode = false,
- .protected_mode = true,
- .granularity = arch::cpu::segment_granularity::page,
- .base_high = 0,
- };
-
- constexpr auto gdt_user_code_descriptor = arch::cpu::segment_descriptor{
- .limit_low = 0xffff,
- .base_low = 0,
- .accessed = false,
- .read_write = false,
- .direction_or_conforming = false,
- .executable = true,
- .type = arch::cpu::segment_type::code_or_data,
- .privilege_level = 3,
- .present = true,
- .limit_high = 0xf,
- .long_mode = true,
- .protected_mode = false,
- .granularity = arch::cpu::segment_granularity::page,
- .base_high = 0,
- };
-
- constexpr auto gdt_user_data_descriptor = arch::cpu::segment_descriptor{
- .limit_low = 0xffff,
- .base_low = 0,
- .accessed = false,
- .read_write = true,
- .direction_or_conforming = false,
- .executable = false,
- .type = arch::cpu::segment_type::code_or_data,
- .privilege_level = 3,
- .present = true,
- .limit_high = 0xf,
- .long_mode = false,
- .protected_mode = false,
- .granularity = arch::cpu::segment_granularity::page,
- .base_high = 0,
- };
- } // namespace
-
- auto memory_initialized() -> void
- {
- auto static tss = arch::cpu::task_state_segment{};
- auto static tss_descriptor = arch::cpu::system_segment_descriptor{
- {
- .limit_low = (sizeof(tss) - 1) & 0xffff, // NOLINT(readability-magic-numbers)
- .base_low = std::bit_cast<std::uintptr_t>(&tss) & 0xffffff, // NOLINT(readability-magic-numbers)
- .accessed = false,
- .read_write = false,
- .direction_or_conforming = false,
- .executable = false,
- .type = arch::cpu::segment_type::system,
- .privilege_level = 0,
- .present = true,
- .limit_high = ((sizeof(tss) - 1) >> 16) & 0xf, // NOLINT(readability-magic-numbers)
- .long_mode = false,
- .protected_mode = false,
- .granularity = arch::cpu::segment_granularity::byte,
- .base_high = (std::bit_cast<std::uintptr_t>(&tss) >> 24) & 0xff, // NOLINT(readability-magic-numbers)
- },
- (std::bit_cast<std::uintptr_t>(&tss) >> 32) & 0xffff'ffff, // NOLINT(readability-magic-numbers)
- };
-
- auto static gdt = arch::cpu::global_descriptor_table{
- gdt_null_descriptor, gdt_kernel_code_descriptor, gdt_kernel_data_descriptor,
- gdt_user_code_descriptor, gdt_user_data_descriptor, tss_descriptor,
- };
-
- kstd::println("[x86_64:SYS] Reloading Global Descriptor Table.");
- gdt.load(1, 2);
-
- kstd::println("[x86_64:SYS] TODO: initialize Interrupt Descriptor Table.");
- }
+ auto memory_initialized() -> void {}
} // namespace kapi::system \ No newline at end of file