aboutsummaryrefslogtreecommitdiff
path: root/arch/x86_64/src/cpu
diff options
context:
space:
mode:
authorFelix Morgner <felix.morgner@ost.ch>2026-04-16 10:29:30 +0200
committerFelix Morgner <felix.morgner@ost.ch>2026-04-29 09:05:04 +0200
commit1b964278762dde86b0b737bd9a34fec569339f54 (patch)
tree7fe0f4707e05f46461f03744d178f413b7bbca28 /arch/x86_64/src/cpu
parentd906d70c94c2a40d5fc6fd26056c7bc57d540002 (diff)
downloadteachos-1b964278762dde86b0b737bd9a34fec569339f54.tar.xz
teachos-1b964278762dde86b0b737bd9a34fec569339f54.zip
x86_64: use p1204 project layout
Diffstat (limited to 'arch/x86_64/src/cpu')
-rw-r--r--arch/x86_64/src/cpu/initialization.cpp164
-rw-r--r--arch/x86_64/src/cpu/interrupt_stubs.S112
-rw-r--r--arch/x86_64/src/cpu/interrupts.cpp203
3 files changed, 0 insertions, 479 deletions
diff --git a/arch/x86_64/src/cpu/initialization.cpp b/arch/x86_64/src/cpu/initialization.cpp
deleted file mode 100644
index 1be9c82..0000000
--- a/arch/x86_64/src/cpu/initialization.cpp
+++ /dev/null
@@ -1,164 +0,0 @@
-#include <arch/cpu/initialization.hpp>
-
-#include <arch/cpu/global_descriptor_table.hpp>
-#include <arch/cpu/interrupts.hpp>
-#include <arch/cpu/legacy_pic.hpp>
-#include <arch/cpu/segment_descriptor.hpp>
-#include <arch/cpu/task_state_segment.hpp>
-
-#include <kstd/print>
-
-#include <bit>
-#include <cstdint>
-
-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<std::uintptr_t>(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();
- }
-
- auto initialize_legacy_interrupts() -> void
- {
- constexpr auto pic_init_command = std::uint8_t{0x11};
- constexpr auto pic_master_offset = std::uint8_t{0x20};
- constexpr auto pic_slave_offset = std::uint8_t{0x28};
- constexpr auto pic_cascade_address = std::uint8_t{0x04};
- constexpr auto pic_cascade_slave_identity = std::uint8_t{0x02};
- constexpr auto pic_use_8086_mode = std::uint8_t{0x01};
- constexpr auto pic_master_mask = std::uint8_t{0x00};
- constexpr auto pic_slave_mask = std::uint8_t{0x00};
-
- pic_master_control_port::write(pic_init_command);
- pic_slave_control_port::write(pic_init_command);
-
- pic_master_data_port::write(pic_master_offset);
- pic_slave_data_port::write(pic_slave_offset);
-
- pic_master_data_port::write(pic_cascade_address);
- pic_slave_data_port::write(pic_cascade_slave_identity);
-
- pic_master_data_port::write(pic_use_8086_mode);
- pic_slave_data_port::write(pic_use_8086_mode);
-
- pic_master_data_port::write(pic_master_mask);
- pic_slave_data_port::write(pic_slave_mask);
-
- pic_master_data_port::write(pic_master_mask);
- pic_slave_data_port::write(pic_slave_mask);
- }
-
-} // namespace arch::cpu
diff --git a/arch/x86_64/src/cpu/interrupt_stubs.S b/arch/x86_64/src/cpu/interrupt_stubs.S
deleted file mode 100644
index e59bdd2..0000000
--- a/arch/x86_64/src/cpu/interrupt_stubs.S
+++ /dev/null
@@ -1,112 +0,0 @@
-.altmacro
-
-.macro ISR_WITHOUT_ERROR_CODE vector
- .global isr\vector
- isr\vector:
- pushq $0
- pushq $\vector
- jmp common_interrupt_handler
-.endm
-
-.macro ISR_WITH_ERROR_CODE vector
- .global isr\vector
- isr\vector:
- pushq $\vector
- jmp common_interrupt_handler
-.endm
-
-.macro ISR_TABLE_ENTRY vector
- .quad isr\vector
-.endm
-
-.section .rodata
-.global isr_stub_table
-.align 16
-
-isr_stub_table:
-.set i, 0
-.rept 256
- ISR_TABLE_ENTRY %i
- .set i, i + 1
-.endr
-
-
-.section .text
-
-common_interrupt_handler:
- push %rax
- push %rbx
- push %rcx
- push %rdx
- push %rbp
- push %rsi
- push %rdi
- push %r8
- push %r9
- push %r10
- push %r11
- push %r12
- push %r13
- push %r14
- push %r15
-
- mov %rsp, %rdi
- call interrupt_dispatch
-
- pop %r15
- pop %r14
- pop %r13
- pop %r12
- pop %r11
- pop %r10
- pop %r9
- pop %r8
- pop %rdi
- pop %rsi
- pop %rbp
- pop %rdx
- pop %rcx
- pop %rbx
- pop %rax
-
- add $16, %rsp
- iretq
-
-ISR_WITHOUT_ERROR_CODE 0
-ISR_WITHOUT_ERROR_CODE 1
-ISR_WITHOUT_ERROR_CODE 2
-ISR_WITHOUT_ERROR_CODE 3
-ISR_WITHOUT_ERROR_CODE 4
-ISR_WITHOUT_ERROR_CODE 5
-ISR_WITHOUT_ERROR_CODE 6
-ISR_WITHOUT_ERROR_CODE 7
-ISR_WITH_ERROR_CODE 8
-ISR_WITHOUT_ERROR_CODE 9
-ISR_WITH_ERROR_CODE 10
-ISR_WITH_ERROR_CODE 11
-ISR_WITH_ERROR_CODE 12
-ISR_WITH_ERROR_CODE 13
-ISR_WITH_ERROR_CODE 14
-ISR_WITHOUT_ERROR_CODE 15
-ISR_WITHOUT_ERROR_CODE 16
-ISR_WITH_ERROR_CODE 17
-ISR_WITHOUT_ERROR_CODE 18
-ISR_WITHOUT_ERROR_CODE 19
-ISR_WITHOUT_ERROR_CODE 20
-ISR_WITH_ERROR_CODE 21
-ISR_WITHOUT_ERROR_CODE 22
-ISR_WITHOUT_ERROR_CODE 23
-ISR_WITHOUT_ERROR_CODE 24
-ISR_WITHOUT_ERROR_CODE 25
-ISR_WITHOUT_ERROR_CODE 26
-ISR_WITHOUT_ERROR_CODE 27
-ISR_WITHOUT_ERROR_CODE 28
-ISR_WITH_ERROR_CODE 29
-ISR_WITH_ERROR_CODE 30
-ISR_WITHOUT_ERROR_CODE 31
-
-.set i, 32
-.rept 256 - 32
- ISR_WITHOUT_ERROR_CODE %i
- .set i, i + 1
-.endr
diff --git a/arch/x86_64/src/cpu/interrupts.cpp b/arch/x86_64/src/cpu/interrupts.cpp
deleted file mode 100644
index f40422f..0000000
--- a/arch/x86_64/src/cpu/interrupts.cpp
+++ /dev/null
@@ -1,203 +0,0 @@
-#include <arch/cpu/interrupts.hpp>
-
-#include <arch/cpu/legacy_pic.hpp>
-#include <arch/cpu/segment_selector.hpp>
-
-#include <kapi/cpu.hpp>
-#include <kapi/interrupts.hpp>
-#include <kapi/memory.hpp>
-
-#include <kstd/print>
-
-#include <cstdint>
-
-namespace arch::cpu
-{
-
- namespace
- {
- enum struct exception
- {
- divide_error,
- debug_exception,
- non_maskable_interrupt,
- breakpoint,
- overflow,
- bound_range_exceeded,
- invalid_opcode,
- device_not_available,
- double_fault,
- coprocessor_segment_overrun,
- invalid_tss,
- segment_not_present,
- stack_segment_fault,
- general_protection_fault,
- page_fault,
- x87_fpu_floating_point_error = 16,
- alignment_check,
- machine_check,
- simd_floating_point_error,
- virtualization_exception,
- control_protection_exception,
- hypervisor_injection_exception = 28,
- vmm_communication_exception,
- security_exception,
- };
-
- constexpr auto number_of_exception_vectors = 32u;
-
- constexpr auto pic_master_irq_start = 0x20;
- constexpr auto pic_master_irq_end = pic_master_irq_start + 8;
- constexpr auto pic_slave_irq_start = pic_master_irq_end;
-
- constexpr auto to_exception_type(exception e)
- {
- switch (e)
- {
- case exception::divide_error:
- case exception::x87_fpu_floating_point_error:
- case exception::simd_floating_point_error:
- return kapi::cpu::exception::type::arithmetic_error;
- case exception::breakpoint:
- return kapi::cpu::exception::type::breakpoint;
- case exception::invalid_opcode:
- return kapi::cpu::exception::type::illegal_instruction;
- case exception::stack_segment_fault:
- return kapi::cpu::exception::type::memory_access_fault;
- case exception::general_protection_fault:
- return kapi::cpu::exception::type::privilege_violation;
- case exception::page_fault:
- return kapi::cpu::exception::type::page_fault;
- case exception::alignment_check:
- return kapi::cpu::exception::type::alignment_fault;
- default:
- return kapi::cpu::exception::type::unknown;
- }
- }
-
- constexpr auto has_error_code(exception e)
- {
- switch (e)
- {
- case exception::double_fault:
- case exception::invalid_tss:
- case exception::segment_not_present:
- case exception::stack_segment_fault:
- case exception::general_protection_fault:
- case exception::page_fault:
- case exception::alignment_check:
- case exception::control_protection_exception:
- case exception::security_exception:
- return true;
- default:
- return false;
- }
- }
-
- auto dispatch_exception(interrupt_frame * frame) -> bool
- {
- auto type = to_exception_type(static_cast<exception>(frame->interrupt.number));
- auto fault_address = kapi::memory::linear_address{};
- auto instruction_pointer = frame->cpu_saved.rip;
-
- switch (type)
- {
- case kapi::cpu::exception::type::page_fault:
- {
- asm volatile("mov %%cr2, %0" : "=r"(fault_address));
- auto present = (frame->interrupt.error_code & 0x1) != 0;
- auto write = (frame->interrupt.error_code & 0x2) != 0;
- auto user = (frame->interrupt.error_code & 0x4) != 0;
-
- return kapi::cpu::dispatch({type, instruction_pointer, fault_address, present, write, user});
- }
- default:
- return kapi::cpu::dispatch({type, instruction_pointer});
- }
- }
-
- auto acknowledge_pic_interrupt(interrupt_frame * frame) -> void
- {
- if (frame->interrupt.number >= pic_slave_irq_start)
- {
- pic_slave_control_port::write(pic_end_of_interrupt);
- }
- pic_master_control_port::write(pic_end_of_interrupt);
- }
- } // namespace
-
- extern "C"
- {
- extern std::uintptr_t const isr_stub_table[256];
-
- auto interrupt_dispatch(interrupt_frame * frame) -> void
- {
- auto [number, code] = frame->interrupt;
-
- if (number < number_of_exception_vectors)
- {
- if (!dispatch_exception(frame))
- {
- if (has_error_code(static_cast<exception>(number)))
- {
- kstd::println(kstd::print_sink::stderr,
- "[x86_64:CPU] Unhandled exception number {:#04x} received with code {:#04x}", number, code);
- }
- else
- {
- kstd::println(kstd::print_sink::stderr, "[x86_64:CPU] Unhandled exception number {:#04x} received", number);
- }
- }
- }
- else
- {
- auto irq_number = number - number_of_exception_vectors;
-
- if (kapi::interrupts::dispatch(irq_number) == kapi::interrupts::status::unhandled)
- {
- kstd::println(kstd::print_sink::stderr, "[x86_64:CPU] Unhandled interrupt {:#04x} (IRQ{})", number,
- irq_number);
- }
-
- acknowledge_pic_interrupt(frame);
- }
- }
- }
-
- interrupt_descriptor_table::interrupt_descriptor_table() noexcept
- {
- for (auto i = 0uz; i < 256; ++i)
- {
- m_descriptors[i] = gate_descriptor{
- .offset_low = static_cast<std::uint16_t>(isr_stub_table[i] & 0xffff), // NOLINT(readability-magic-numbers)
- .m_code_segment = segment_selector{0, false, 1},
- .interrupt_stack_table_selector = 0,
- .gate_type = (i < 32 && i != 2) ? gate_type::trap_gate : gate_type::interrupt_gate,
- .descriptor_privilege_level = 0,
- .present = true,
- .offset_middle =
- static_cast<std::uint16_t>((isr_stub_table[i] >> 16) & 0xffff), // NOLINT(readability-magic-numbers)
- .offset_high =
- static_cast<std::uint32_t>((isr_stub_table[i] >> 32) & 0xffff'ffff), // NOLINT(readability-magic-numbers)
- };
- }
- }
-
- auto interrupt_descriptor_table::load() const -> void
- {
- interrupt_descriptor_table_register{.limit = sizeof(m_descriptors) - 1, .base = m_descriptors.data()}.load();
- }
-
- auto interrupt_descriptor_table_register::load() const -> void
- {
- asm volatile("lidt %0" : : "m"(*this));
- }
-
- auto interrupt_descriptor_table_register::read() -> interrupt_descriptor_table_register
- {
- interrupt_descriptor_table_register idtr{};
- asm volatile("sidt %0" : : "m"(idtr));
- return idtr;
- }
-
-} // namespace arch::cpu \ No newline at end of file