diff --git a/kernel/src/arch/CPU.h b/kernel/src/arch/CPU.h index cff9919d..a471b0d0 100644 --- a/kernel/src/arch/CPU.h +++ b/kernel/src/arch/CPU.h @@ -1,6 +1,8 @@ #pragma once #include +struct Registers; + namespace CPU { Result identify(); diff --git a/kernel/src/arch/x86_64/CPU.asm b/kernel/src/arch/x86_64/CPU.asm index 918931f9..329f576f 100644 --- a/kernel/src/arch/x86_64/CPU.asm +++ b/kernel/src/arch/x86_64/CPU.asm @@ -1,3 +1,9 @@ +section .data +global __divisor +__divisor: + dd 0 + +section .text global enable_sse enable_sse: mov rax, cr0 @@ -45,4 +51,73 @@ global load_tr load_tr: mov rax, rdi ltr ax - ret \ No newline at end of file + ret + +%macro ISR 1 + global _isr%1 + _isr%1: + push byte 0 + push byte %1 + jmp _asm_interrupt_entry +%endmacro + +%macro ISR_ERROR 1 + global _isr%1 + _isr%1: + push byte %1 + jmp _asm_interrupt_entry +%endmacro + +%macro IRQ 2 + global _isr%1 + _isr%1: + push byte %2 + push byte %1 + jmp _asm_interrupt_entry +%endmacro + +extern arch_interrupt_entry + +_asm_interrupt_entry: + push rax + push rbx + push rcx + push rdx + push rsi + push rdi + push rbp + push r8 + push r9 + push r10 + push r11 + push r12 + push r13 + push r14 + push r15 + + cld + + mov rdi, rsp + call arch_interrupt_entry + + pop r15 + pop r14 + pop r13 + pop r12 + pop r11 + pop r10 + pop r9 + pop r8 + pop rbp + pop rdi + pop rsi + pop rdx + pop rcx + pop rbx + pop rax + + add rsp, 16 + + iretq + +ISR 0 ; divide by zero \ No newline at end of file diff --git a/kernel/src/arch/x86_64/CPU.cpp b/kernel/src/arch/x86_64/CPU.cpp index a1436d65..941f464f 100644 --- a/kernel/src/arch/x86_64/CPU.cpp +++ b/kernel/src/arch/x86_64/CPU.cpp @@ -1,4 +1,5 @@ -#include "arch/CPU.h" +#include "arch/x86_64/CPU.h" +#include "arch/Serial.h" #include #include #include @@ -147,7 +148,7 @@ struct IDTR uint64_t offset; } __attribute__((packed)); -[[maybe_unused]] static void idt_add_handler(short num, void* handler, u8 type_attr) +static void idt_add_handler(short num, void* handler, u8 type_attr) { check(handler != nullptr); check(num < 256); @@ -157,14 +158,38 @@ struct IDTR entry_for_handler->set_offset((u64)handler); } -static void setup_idt() // FIXME: Add entries to the IDT. +#define INT(x) extern "C" void _isr##x() +#define TRAP(x) idt_add_handler(x, (void*)_isr##x, IDT_TA_TrapGate) + +INT(0); + +static void setup_idt() { + TRAP(0); // divide by zero + static IDTR idtr; idtr.limit = 0x0FFF; idtr.offset = (u64)idt; asm("lidt %0" : : "m"(idtr)); } +// Interrupt handling + +// Called from _asm_interrupt_entry +extern "C" void arch_interrupt_entry(Registers* regs) +{ + if (regs->isr < 32) + { + Serial::println("Exception catched! Halting."); + CPU::efficient_halt(); + } + else + { + Serial::println("IRQ catched! Halting."); + CPU::efficient_halt(); + } +} + // Generic CPU code static bool test_nx() diff --git a/kernel/src/arch/x86_64/CPU.h b/kernel/src/arch/x86_64/CPU.h new file mode 100644 index 00000000..f156e80d --- /dev/null +++ b/kernel/src/arch/x86_64/CPU.h @@ -0,0 +1,10 @@ +#include "arch/CPU.h" +#include + +struct Registers // Saved CPU registers for x86-64 +{ + u64 r15, r14, r13, r12, r11, r10, r9, r8; + u64 rbp, rdi, rsi, rdx, rcx, rbx, rax; + u64 isr, error; + u64 rip, cs, rflags, rsp, ss; +}; \ No newline at end of file diff --git a/kernel/src/main.cpp b/kernel/src/main.cpp index 17499474..a7be3ce5 100644 --- a/kernel/src/main.cpp +++ b/kernel/src/main.cpp @@ -84,7 +84,11 @@ extern "C" [[noreturn]] void _start() Serial::println("Successfully unmapped address"); - check(false); + extern int __divisor; // divisor is defined as 0, we do it this way so the compiler doesn't catch it (this is + // testing exception handling) + [[maybe_unused]] volatile int div_rc = 4 / __divisor; + + Serial::println("ERROR: Still here after division by zero"); CPU::efficient_halt(); } \ No newline at end of file diff --git a/tools/check-formatting.sh b/tools/check-formatting.sh index fa7c7449..366c5748 100755 --- a/tools/check-formatting.sh +++ b/tools/check-formatting.sh @@ -4,9 +4,7 @@ source $(dirname $0)/env.sh cd $LUNA_ROOT -SOURCES=($(find kernel/src -type f | grep "\.c") $(find kernel/include -type f)) -SOURCES+=($(find libs/libc/src -type f | grep "\.c") $(find libs/libc/include -type f)) -SOURCES+=($(find apps/src -type f)) +SOURCES=($(find kernel/src -type f | grep -v "\.asm")) ALL_OK=1 diff --git a/tools/run-clang-format.sh b/tools/run-clang-format.sh index 4e88d1ec..43963d0f 100755 --- a/tools/run-clang-format.sh +++ b/tools/run-clang-format.sh @@ -5,9 +5,7 @@ source $(dirname $0)/env.sh cd $LUNA_ROOT -SOURCES=($(find kernel/src -type f | grep "\.c") $(find kernel/include -type f)) -SOURCES+=($(find libs/libc/src -type f | grep "\.c") $(find libs/libc/include -type f)) -SOURCES+=($(find apps/src -type f)) +SOURCES=($(find kernel/src -type f | grep -v "\.asm")) for f in ${SOURCES[@]} do