diff options
Diffstat (limited to 'kernel/interrupts.cpp')
-rw-r--r-- | kernel/interrupts.cpp | 119 |
1 files changed, 119 insertions, 0 deletions
diff --git a/kernel/interrupts.cpp b/kernel/interrupts.cpp new file mode 100644 index 0000000..65daf91 --- /dev/null +++ b/kernel/interrupts.cpp @@ -0,0 +1,119 @@ +#include <mercury/kernel/terminal.hpp> + +using namespace mercury::kernel; + +struct [[gnu::packed]] exception_info_t { + + uint64_t rax; + uint64_t rbx; + uint64_t rcx; + uint64_t rdx; + uint64_t rdi; + uint64_t rsi; + uint64_t rbp; + uint64_t rsp; + uint64_t r8; + uint64_t r9; + uint64_t r10; + uint64_t r11; + uint64_t r12; + uint64_t r13; + uint64_t r14; + uint64_t r15; + + uint64_t cr3; + uint64_t rip; + uint64_t rflags; + + uint64_t error; + uint8_t has_error;//0 or 1 + uint8_t exception_number; + +}; + +extern exception_info_t exception_info; + +const char *exception_types[] = { + "division error", + "", + "non-maskable interrupt", + "", + "", + "", + "invalid opcode", + "", + "double fault (uh oh)", + "", + "", + "", + "stack fault", + "general protection fault", + "page fault", + "" +}; + +const char *flag_names[] = { + " cf", + "", + " pf", + "", + " af", + "", + " zf", + " sf", + " tf", + " if", + " df", + " of", + "", + "", + " nt", + " md" +}; + +void print_line(const char *r1, const char *r2, uint64_t r1v, uint64_t r2v) { + terminal::put_string_sz("\n "); + terminal::put_string_sz(r1); + terminal::put_string_sz(": 0x"); + terminal::put_int_hex(r1v, 16); + terminal::put_string_sz(" "); + terminal::put_string_sz(r2); + terminal::put_string_sz(": 0x"); + terminal::put_int_hex(r2v, 16); +} + +extern "C" [[noreturn]] void print_exception() { + + terminal::put_string_sz("exception handler:\n type: "); + terminal::put_string_sz(exception_types[exception_info.exception_number]); + terminal::put_string_sz(" (0x"); + terminal::put_int_hex(exception_info.exception_number, 2); + terminal::put_char(')'); + + if (exception_info.has_error == 1) { + terminal::put_string_sz("\n error code: 0x"); + terminal::put_int_hex(exception_info.error, 16); + } + + terminal::put_string_sz("\n flags:"); + if (exception_info.rflags == 0) + terminal::put_string_sz(" [none]"); + else + for (int i = 0; i < 16; ++i) + if (((exception_info.rflags >> i) & 1) == 1) + terminal::put_string_sz(flag_names[i]); + + print_line("rip", "cr3", exception_info.rip, exception_info.cr3); + print_line("rax", "rbx", exception_info.rax, exception_info.rbx); + print_line("rcx", "rdx", exception_info.rcx, exception_info.rdx); + print_line("rdi", "rsi", exception_info.rdi, exception_info.rsi); + print_line("rbp", "rsp", exception_info.rbp, exception_info.rsp); + print_line("r8 ", "r9 ", exception_info.r8 , exception_info.r9 ); + print_line("r10", "r11", exception_info.r10, exception_info.r11); + print_line("r12", "r13", exception_info.r12, exception_info.r13); + print_line("r14", "r15", exception_info.r14, exception_info.r15); + + while (1) + asm ("hlt"); + +} |