diff options
Diffstat (limited to 'arch/x86_64/src')
| -rw-r--r-- | arch/x86_64/src/boot/boot32.S | 443 | ||||
| -rw-r--r-- | arch/x86_64/src/boot/entry64.s | 62 | ||||
| -rw-r--r-- | arch/x86_64/src/boot/initialize_runtime.cpp | 22 | ||||
| -rw-r--r-- | arch/x86_64/src/boot/multiboot.s | 33 | ||||
| -rw-r--r-- | arch/x86_64/src/bus/isa.cpp | 14 | ||||
| -rw-r--r-- | arch/x86_64/src/cpu/initialization.cpp | 164 | ||||
| -rw-r--r-- | arch/x86_64/src/cpu/interrupt_stubs.S | 112 | ||||
| -rw-r--r-- | arch/x86_64/src/cpu/interrupts.cpp | 203 | ||||
| -rw-r--r-- | arch/x86_64/src/debug/qemu_output.cpp | 25 | ||||
| -rw-r--r-- | arch/x86_64/src/devices/init.cpp | 76 | ||||
| -rw-r--r-- | arch/x86_64/src/devices/legacy_pit.cpp | 60 | ||||
| -rw-r--r-- | arch/x86_64/src/devices/local_apic.cpp | 134 | ||||
| -rw-r--r-- | arch/x86_64/src/memory/higher_half_mapper.cpp | 119 | ||||
| -rw-r--r-- | arch/x86_64/src/memory/kernel_mapper.cpp | 117 | ||||
| -rw-r--r-- | arch/x86_64/src/memory/mmu.cpp | 19 | ||||
| -rw-r--r-- | arch/x86_64/src/memory/page_table.cpp | 82 | ||||
| -rw-r--r-- | arch/x86_64/src/memory/region_allocator.cpp | 165 | ||||
| -rw-r--r-- | arch/x86_64/src/vga/text/buffer.cpp | 101 | ||||
| -rw-r--r-- | arch/x86_64/src/vga/text/device.cpp | 60 |
19 files changed, 0 insertions, 2011 deletions
diff --git a/arch/x86_64/src/boot/boot32.S b/arch/x86_64/src/boot/boot32.S deleted file mode 100644 index e6fcd85..0000000 --- a/arch/x86_64/src/boot/boot32.S +++ /dev/null @@ -1,443 +0,0 @@ -#include <arch/boot/boot.hpp> - -/** - * @brief Uninitialized data for the bootstrapping process. - */ -.section .boot_bss, "aw", @nobits - -page_maps_start: -page_map_level_4: .skip 512 * 8 -page_map_level_3_high: .skip 512 * 8 -page_map_level_3_low: .skip 512 * 8 -page_map_level_2: .skip 512 * 8 -page_maps_end = . -page_maps_size = page_maps_end - page_maps_start - -/** - * @brief Storage for the multiboot2 information pointer. - */ -.global multiboot_information_pointer -multiboot_information_pointer: .skip 8 - -/** - * @brief Storage for the bootstrap stack. - */ -.section .boot_stack, "aw", @nobits -.align 16 - -early_stack_bottom: .skip 1 << 8 -early_stack_top: -early_stack_size = early_stack_top - early_stack_bottom - -/** - * @brief Constants for the bootstrapping process. - */ -.section .boot_rodata, "a", @progbits - -.global global_descriptor_table_data - -/** - * @brief A basic GDT for long mode. - */ -global_descriptor_table: -global_descriptor_table_null = . - global_descriptor_table -.quad 0 -global_descriptor_table_code = . - global_descriptor_table -.quad GDT_READ_WRITE | GDT_EXECUTABLE | GDT_DESCRIPTOR_TYPE | GDT_PRESENT | GDT_LONG_MODE | (1 << 55) -global_descriptor_table_data = . - global_descriptor_table -.quad GDT_READ_WRITE | GDT_DESCRIPTOR_TYPE | GDT_PRESENT | (1 << 54) | (1 << 55) -global_descriptor_table_end: - -message_prefix_panic: .string "Panic: " -message_not_loaded_by_multiboot2: .string "The operating system was not loaded by a Multiboot 2 loader." -message_cpuid_instruction_no_supported: .string "The 'cpuid' instruction is not supported on this platform." -message_long_mode_not_supported: .string "Long mode is not supported by this platform." -message_return_from_kernel_main: .string "Execution returned from kernel main." - -/** - * @brief Initialized data for the bootstrapping process. - */ -.section .boot_data, "aw", @progbits - -/** - * @brief A pointer to the current position within the VGA text buffer. - */ -.global vga_buffer_pointer -vga_buffer_pointer: .quad 0xb8000 - -/** - * @brief Code for the bootstrapping process. - */ -.section .boot_text, "ax", @progbits -.align 16 -.code32 - -.macro pie_base - push %esi - call 0f - 0: - pop %esi -.endm - -.macro function_start - push %ebp - mov %esp, %ebp -.endm - -.macro function_end - leave - ret -.endm - -.macro pie_function_start - function_start - pie_base -.endm - -.macro pie_function_end - pop %esi - function_end -.endm - -/** - * @brief Prepare the environment and start the kernel. - * - * This function performs all necessary checks to ensure the system was loaded - * by the expected loader and supports all features required to run the kernel. - * If successful, it prepares the system by setting up memory virtualization - * and then start the kernel proper. - * - * @param %eax The Multiboot 2 magic marker. - * @param %ebx The Multiboot 2 information pointer. - * @return void This function does not return. - */ -.global _start -_start: - call 0f -0: - pop %esi - - lea (early_stack_top - 0b)(%esi), %ecx - - mov %ecx, %esp - mov %esp, %ebp - - call _assert_loaded_by_multiboot2_loader - call _save_multiboot_information_pointer - - call _assert_cpuid_instruction_is_supported - call _assert_cpu_supports_long_mode - - push $HUGE_PAGES_TO_MAP - call _prepare_page_maps - add $4, %esp - - call _enable_paging - call _enable_sse - call _reload_gdt - - lea (_entry64 - 0b)(%esi), %eax - pushl $global_descriptor_table_code - pushl %eax - lret - -/** - * @brief Halt the system. - * - * This function will instruct the CPU to halt. It will try to keep the CPU - * halted, even if interrupts occur. - * - * @return This function never returns. - */ -_halt: - function_start - -1: - hlt - jmp 1b - - function_end - -/** - * @brief Print a message via the VGA text buffer. - * - * @param ebp+12 The message to print. - * @param ebp+8 The color to print the message in. - */ -_print: - pie_function_start - - push %edi - push %ebx - - mov 8(%ebp), %al - mov 12(%ebp), %edx - mov $0, %ecx - lea (vga_buffer_pointer - 0b)(%esi), %edi - mov (%edi), %edi - -1: - mov (%edx, %ecx), %bl - test %bl, %bl - je 2f - mov %bl, (%edi, %ecx, 2) - mov %al, 1(%edi, %ecx, 2) - inc %ecx - jmp 1b - -2: - shl $1, %ecx - add %ecx, %edi - lea (vga_buffer_pointer - 0b)(%esi), %ecx - mov %edi, (%ecx) - - pop %ebx - pop %edi - - pie_function_end - -/** - * @brief Print a given panic message and then halt the machine as if by calling ::halt() - * - * @param ebp+4 A message to print. - * @return This function does not return. - */ -_panic: - pie_function_start - - lea (message_prefix_panic - 0b)(%esi), %eax - - push %eax - push $0x4f - call _print - - mov 8(%ebp), %eax - mov %eax, 4(%esp) - call _print - add $8, %esp - - call _halt - - pie_function_end - -/** - * Assert that we were loaded by a Multiboot 2 compliant bootloader. - * - * This assertion will panic the system if the magic signature was not found. - * If we were loaded my an appropriate bootloader, this function also saves - * the provided MBI pointer to `multiboot_information_pointer`. - */ -_assert_loaded_by_multiboot2_loader: - pie_function_start - - cmp $MULTIBOOT2_MAGIC, %eax - je 1f - lea (message_not_loaded_by_multiboot2 - 0b)(%esi), %eax - push %eax - call _panic -1: - pie_function_end - -/** - * @brief Store the multiboot 2 information pointer in the global memory. - * - * @return void - */ -_save_multiboot_information_pointer: - pie_function_start - - lea (multiboot_information_pointer - 0b)(%esi), %eax - mov %ebx, (%eax) - - pie_function_end - -/** - * @brief Assert that the CPU supports the CPUID instruction. - * - * The primary way to check for support of the instruction is to flip the ID - * bin in EFLAGS and then check if this changed was accepted. If so, the CPU - * supports the CPUID instruction, otherwise it most-likely doesn't. - */ -_assert_cpuid_instruction_is_supported: - pie_function_start - - pushfl - pop %eax - mov %eax, %ecx - - xor $(1 << 21), %eax /* Flip the ID bit */ - push %eax /* Move the new bitset on the stack for loading */ - popfl /* Load the flags with ID set back into EFLAGS */ - pushfl /* Copy the flags back onto the stack */ - pop %eax /* Load the flags for further checking */ - - push %ecx - popfl - - cmp %ecx, %eax - jne 1f - lea (message_cpuid_instruction_no_supported - 0b)(%esi), %eax - push %eax - call _panic - -1: - pie_function_end - -/** - * @brief Assert that the CPU supports going into long mode. - */ -_assert_cpu_supports_long_mode: - pie_function_start - - mov $0x80000000, %eax - cpuid - cmp $0x80000001, %eax - jb 1f - - mov $0x80000001, %eax - cpuid - test $(1 << 29), %edx - jnz 2f -1: - lea (message_long_mode_not_supported - 0b)(%esi), %eax - push %eax - call _panic -2: - pie_function_end - -/** - * @brief Prepare a basic page map hierarchy - * - * @param ebp+8 The number of huge pages to map - * @return void - */ -_prepare_page_maps: - pie_function_start - - push %edi - - call _clear_page_map_memory - - lea (page_map_level_4 - 0b)(%esi), %edi - lea (page_map_level_3_low - 0b)(%esi), %eax - or $0b11, %eax - mov %eax, (%edi) - - lea (page_map_level_3_high - 0b)(%esi), %eax - or $0b11, %eax - mov %eax, (511 * 8)(%edi) - - lea (page_map_level_3_low - 0b)(%esi), %edi - lea (page_map_level_2 - 0b)(%esi), %eax - or $0b11, %eax - mov %eax, (%edi) - - lea (page_map_level_3_high - 0b)(%esi), %edi - lea (page_map_level_2 - 0b)(%esi), %eax - or $0b11, %eax - mov %eax, (510 * 8)(%edi) - - lea (page_map_level_2 - 0b)(%esi), %edi - mov 8(%ebp), %ecx - -1: - dec %ecx - mov $(1 << 21), %eax - mul %ecx - or $0b10000011, %eax - mov %eax, (%edi, %ecx, 8) - - test %ecx, %ecx - jnz 1b - - pop %edi - - pie_function_end - -/** - * @brief Clear all page map memory by filling it with 0s. - * - * @return void - */ -_clear_page_map_memory: - pie_function_start - - push %edi - - xor %eax, %eax - mov $page_maps_size, %ecx - shr $2, %ecx - lea (page_maps_start - 0b)(%esi), %edi - rep stosl - - pop %edi - - pie_function_end - -/** - * @p Enable memory virtualization via paging. - * - * Note: This routine expects for there to be a valid set of page maps already - * set up for use. - * - * @return void - */ -_enable_paging: - pie_function_start - - lea (page_map_level_4 - 0b)(%esi), %eax - mov %eax, %cr3 - - /* Enable Physical Address Extension */ - mov %cr4, %eax - or $(1 << 5), %eax - mov %eax, %cr4 - - /* Enable long mode support */ - mov $0xC0000080, %ecx - rdmsr - or $(1 << 8), %eax - wrmsr - - /* Enable paging */ - mov %cr0, %eax - or $(1 << 31), %eax - mov %eax, %cr0 - - pie_function_end - -/** - * @brief Enable use of SSE instructions. - */ -_enable_sse: - function_start - - mov %cr0, %eax - and $0xfffffffb, %eax - or $0x00000002, %eax - mov %eax, %cr0 - - mov %cr4, %eax - or $(3 << 9), %eax - mov %eax, %cr4 - - function_end - -/** - * @brief Prepare a new GTD and load make it active. - * - * @return void - */ -_reload_gdt: - pie_function_start - - sub $10, %esp - lea (global_descriptor_table - 0b)(%esi), %eax - movw $(global_descriptor_table_end - global_descriptor_table -1), (%esp) - mov %eax, 2(%esp) - movl $0, 6(%esp) - - lgdt (%esp) - add $10, %esp - - pie_function_end diff --git a/arch/x86_64/src/boot/entry64.s b/arch/x86_64/src/boot/entry64.s deleted file mode 100644 index 29fb778..0000000 --- a/arch/x86_64/src/boot/entry64.s +++ /dev/null @@ -1,62 +0,0 @@ -.section .stack, "aw", @nobits - -.align 16 -.global stack_top -stack_bottom: .skip 1 << 20 -stack_top: -stack_size = stack_top - stack_bottom - -.section .bss, "aw", @nobits - -//! A structure containing information gathered during the bootstrap process. -//! Expected layout (as described by teachos::boot::information): -//! -//! struct -//! { -//! multiboot2::information_view const * mbi; -//! std::size_t vga_buffer_index; -//! } -.global bootstrap_information -bootstrap_information: .skip 16 - -.section .boot_text, "ax", @progbits -.code64 - -.global _entry64 -_entry64: - mov $global_descriptor_table_data, %rax - mov %rax, %ss - mov %rax, %ds - mov %rax, %es - mov %rax, %fs - mov %rax, %gs - - mov $stack_top, %rsp - mov %rsp, %rbp - - mov multiboot_information_pointer, %rax - or $TEACHOS_VMA, %rax - mov vga_buffer_pointer, %rdx - sub $0xb8000, %rdx - mov %rax, (bootstrap_information) - mov %rdx, (bootstrap_information + 8) - - call invoke_global_constructors - - xor %rax, %rax - mov %rax, %rbp - mov %rax, %rdx - mov %rax, %rsi - - mov $stack_size, %rcx - shr $3, %rcx - lea (stack_bottom), %rdi - rep stosq - - mov %rax, %rdi - - call main - -1: - hlt - jmp 1b diff --git a/arch/x86_64/src/boot/initialize_runtime.cpp b/arch/x86_64/src/boot/initialize_runtime.cpp deleted file mode 100644 index b08c13c..0000000 --- a/arch/x86_64/src/boot/initialize_runtime.cpp +++ /dev/null @@ -1,22 +0,0 @@ -#include <algorithm> -#include <functional> -#include <span> - -namespace arch::boot -{ - - extern "C" - { - using global_initializer = auto (*)() -> void; - - extern global_initializer __init_array_start; - extern global_initializer __init_array_end; - - auto invoke_global_constructors() -> void - { - auto initializers = std::span{&__init_array_start, &__init_array_end}; - std::ranges::for_each(initializers, [](auto invokable) { std::invoke(invokable); }); - } - } - -} // namespace arch::boot
\ No newline at end of file diff --git a/arch/x86_64/src/boot/multiboot.s b/arch/x86_64/src/boot/multiboot.s deleted file mode 100644 index 37d8afe..0000000 --- a/arch/x86_64/src/boot/multiboot.s +++ /dev/null @@ -1,33 +0,0 @@ -.section .boot_mbh, "a" -.align 8 - -multiboot_header_start: -.Lmagic: - .long 0xe85250d6 -.Larch: - .long 0 -.Llength: - .long multiboot_header_end - multiboot_header_start -.Lchecksum: - .long 0x100000000 - (0xe85250d6 + 0 + (multiboot_header_end - multiboot_header_start)) -.align 8 -.Lflags_start: - .word 4 - .word 1 - .long .Lflags_end - .Lflags_start - .long 3 -.Lflags_end: -.align 8 -.Linformation_request_start: - .word 1 - .word 0 - .long .Linformation_request_end - .Linformation_request_start - .long 3 -.Linformation_request_end: -.align 8 -.Lend_start: - .word 0 - .word 0 - .long .Lend_end - .Lend_start -.Lend_end: -multiboot_header_end: diff --git a/arch/x86_64/src/bus/isa.cpp b/arch/x86_64/src/bus/isa.cpp deleted file mode 100644 index f6cc72d..0000000 --- a/arch/x86_64/src/bus/isa.cpp +++ /dev/null @@ -1,14 +0,0 @@ -#include <arch/bus/isa.hpp> - -#include <kapi/devices.hpp> - -#include <cstddef> - -namespace arch::bus -{ - - isa::isa(std::size_t major) - : kapi::devices::bus{major, 0, "isa"} - {} - -} // namespace arch::bus
\ No newline at end of file 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-number |
