#include "arch/cpu/initialization.hpp" #include "arch/cpu/global_descriptor_table.hpp" #include "arch/cpu/interrupts.hpp" #include "arch/cpu/segment_descriptor.hpp" #include "arch/cpu/task_state_segment.hpp" #include #include #include namespace arch::cpu { namespace { constexpr auto gdt_null_descriptor = segment_descriptor{}; constexpr auto gdt_kernel_code_descriptor = segment_descriptor{ .limit_low = 0xffff, .base_low = 0, .accessed = false, .read_write = false, .direction_or_conforming = false, .executable = true, .type = segment_type::code_or_data, .privilege_level = 0, .present = true, .limit_high = 0xf, .long_mode = true, .protected_mode = false, .granularity = segment_granularity::page, .base_high = 0, }; constexpr auto gdt_kernel_data_descriptor = segment_descriptor{ .limit_low = 0xffff, .base_low = 0, .accessed = false, .read_write = true, .direction_or_conforming = false, .executable = false, .type = segment_type::code_or_data, .privilege_level = 0, .present = true, .limit_high = 0xf, .long_mode = false, .protected_mode = true, .granularity = segment_granularity::page, .base_high = 0, }; constexpr auto gdt_user_code_descriptor = segment_descriptor{ .limit_low = 0xffff, .base_low = 0, .accessed = false, .read_write = false, .direction_or_conforming = false, .executable = true, .type = segment_type::code_or_data, .privilege_level = 3, .present = true, .limit_high = 0xf, .long_mode = true, .protected_mode = false, .granularity = segment_granularity::page, .base_high = 0, }; constexpr auto gdt_user_data_descriptor = segment_descriptor{ .limit_low = 0xffff, .base_low = 0, .accessed = false, .read_write = true, .direction_or_conforming = false, .executable = false, .type = segment_type::code_or_data, .privilege_level = 3, .present = true, .limit_high = 0xf, .long_mode = false, .protected_mode = false, .granularity = segment_granularity::page, .base_high = 0, }; constexpr auto make_tss_descriptor(task_state_segment const * tss_ptr) -> system_segment_descriptor { auto const address = std::bit_cast(tss_ptr); auto const limit = sizeof(task_state_segment) - 1; return system_segment_descriptor{ { .limit_low = limit & 0xffff, // NOLINT(readability-magic-numbers) .base_low = address & 0xffffff, // NOLINT(readability-magic-numbers) .accessed = false, .read_write = false, .direction_or_conforming = false, .executable = false, .type = segment_type::system, .privilege_level = 0, .present = true, .limit_high = (limit >> 16) & 0xf, // NOLINT(readability-magic-numbers) .long_mode = false, .protected_mode = false, .granularity = segment_granularity::byte, .base_high = (address >> 24) & 0xff, // NOLINT(readability-magic-numbers) }, (address >> 32) & 0xffff'ffff, // NOLINT(readability-magic-numbers) }; } } // namespace auto initialize_descriptors() -> void { auto static tss = task_state_segment{}; auto static tss_descriptor = make_tss_descriptor(&tss); auto static gdt = 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] Initializing Interrupt Descriptor Table."); auto static idt = interrupt_descriptor_table{}; idt.load(); } } // namespace arch::cpu