#include "arch/cpu/initialization.hpp" #include "arch/cpu/global_descriptor_table.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, }; } // namespace auto initialize_descriptors() -> void { auto static tss = task_state_segment{}; auto static tss_descriptor = system_segment_descriptor{ { .limit_low = (sizeof(tss) - 1) & 0xffff, // NOLINT(readability-magic-numbers) .base_low = std::bit_cast(&tss) & 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 = ((sizeof(tss) - 1) >> 16) & 0xf, // NOLINT(readability-magic-numbers) .long_mode = false, .protected_mode = false, .granularity = segment_granularity::byte, .base_high = (std::bit_cast(&tss) >> 24) & 0xff, // NOLINT(readability-magic-numbers) }, (std::bit_cast(&tss) >> 32) & 0xffff'ffff, // NOLINT(readability-magic-numbers) }; 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] TODO: initialize Interrupt Descriptor Table."); } } // namespace arch::cpu