diff options
Diffstat (limited to 'arch/x86_64/kapi')
| -rw-r--r-- | arch/x86_64/kapi/boot_modules.cpp | 53 | ||||
| -rw-r--r-- | arch/x86_64/kapi/cio.cpp | 6 | ||||
| -rw-r--r-- | arch/x86_64/kapi/cpu.cpp | 80 | ||||
| -rw-r--r-- | arch/x86_64/kapi/devices.cpp | 14 | ||||
| -rw-r--r-- | arch/x86_64/kapi/interrupts.cpp | 16 | ||||
| -rw-r--r-- | arch/x86_64/kapi/memory.cpp | 67 | ||||
| -rw-r--r-- | arch/x86_64/kapi/system.cpp | 118 |
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 |
