summaryrefslogtreecommitdiff
path: root/kernel/interrupts.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/interrupts.cpp')
-rw-r--r--kernel/interrupts.cpp119
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");
+
+}