diff options
-rw-r--r-- | kernel/include/hilbert/kernel/serial.hpp | 27 | ||||
-rw-r--r-- | kernel/makefile | 2 | ||||
-rw-r--r-- | kernel/source/entry.cpp | 3 | ||||
-rw-r--r-- | kernel/source/interrupts.asm | 80 | ||||
-rw-r--r-- | kernel/source/interrupts.cpp | 37 | ||||
-rw-r--r-- | kernel/source/serial.asm | 58 |
6 files changed, 169 insertions, 38 deletions
diff --git a/kernel/include/hilbert/kernel/serial.hpp b/kernel/include/hilbert/kernel/serial.hpp new file mode 100644 index 0000000..e7a44f2 --- /dev/null +++ b/kernel/include/hilbert/kernel/serial.hpp @@ -0,0 +1,27 @@ +#pragma once + +#include <stdint.h> + +namespace hilbert::kernel { + + extern "C" void serial_init(); + + extern "C" void serial_putchar(char ch); + + static inline void serial_putstr(const char *str) { + while (*str) { + serial_putchar(*str); + ++str; + } + } + + template <int digits, int dot_every = 4> + static inline void serial_puthex(uint64_t n) { + for (int d = digits - 1; d >= 0; --d) { + serial_putchar("0123456789abcdef"[(n >> (d * 4)) & 0xf]); + if (d % dot_every == 0 && d != 0) + serial_putchar('.'); + } + } + +} diff --git a/kernel/makefile b/kernel/makefile index 1cb2d52..27565f7 100644 --- a/kernel/makefile +++ b/kernel/makefile @@ -2,7 +2,7 @@ SOURCES = \ storage/bd/memory.cpp storage/fs/tarfs.cpp application.asm application.cpp \ framebuffer.cpp interrupts.asm interrupts.cpp allocator.cpp storage.cpp \ syscall.cpp utility.cpp paging.asm paging.cpp entry.cpp input.cpp panic.cpp \ - vfile.cpp + vfile.cpp serial.asm build/%.asm.o: source/%.asm @mkdir -p $(@D) diff --git a/kernel/source/entry.cpp b/kernel/source/entry.cpp index 820b107..5db3515 100644 --- a/kernel/source/entry.cpp +++ b/kernel/source/entry.cpp @@ -3,6 +3,7 @@ #include <hilbert/kernel/application.hpp> #include <hilbert/kernel/framebuffer.hpp> #include <hilbert/kernel/paging.hpp> +#include <hilbert/kernel/serial.hpp> #include <hilbert/kernel/input.hpp> #include <hilbert/kernel/panic.hpp> #include <hilbert/kernel/vfile.hpp> @@ -97,6 +98,8 @@ static bool have_initfs; extern "C" [[noreturn]] void entry() { + serial_init(); + //TODO?: maybe we should check if the limine requests were // fulfilled and display some error message if not diff --git a/kernel/source/interrupts.asm b/kernel/source/interrupts.asm index e0c3cdb..e4912ee 100644 --- a/kernel/source/interrupts.asm +++ b/kernel/source/interrupts.asm @@ -227,19 +227,51 @@ section .bss section .text +isr_start: + + push rcx + mov rcx, qword [rsp + 8] + mov qword [rsp + 8], rax + push rdx + push rdi + push rsi + push r8 + push r9 + push r10 + push r11 + push rcx + + ;this is a complete hack but it works + mov rdi, qword [rsp + 10 * 8 + 4 * 8] + cmp rdi, 0x38 + je .fix_ss + ret + +.fix_ss: + mov qword [rsp + 10 * 8 + 4 * 8], 0x3b + ret + +isr_end: + + pop rcx + pop r11 + pop r10 + pop r9 + pop r8 + pop rsi + pop rdi + pop rdx + mov rax, qword [rsp + 8] + mov qword [rsp + 8], rcx + pop rcx + + ret + extern on_keyboard_interrupt keyboard_isr: - push r11 - push r10 - push r9 - push r8 - push rsi - push rdi - push rdx - push rcx - push rax + call isr_start call wait_read_ps2 in al, 0x60 @@ -250,15 +282,7 @@ keyboard_isr: mov al, 0x20 out 0x20, al - pop rax - pop rcx - pop rdx - pop rdi - pop rsi - pop r8 - pop r9 - pop r10 - pop r11 + call isr_end iretq @@ -266,15 +290,7 @@ extern on_mouse_interrupt mouse_isr: - push r11 - push r10 - push r9 - push r8 - push rsi - push rdi - push rdx - push rcx - push rax + call isr_start call wait_read_ps2 in al, 0x60 @@ -286,15 +302,7 @@ mouse_isr: out 0x20, al out 0xa0, al - pop rax - pop rcx - pop rdx - pop rdi - pop rsi - pop r8 - pop r9 - pop r10 - pop r11 + call isr_end iretq diff --git a/kernel/source/interrupts.cpp b/kernel/source/interrupts.cpp index f8e613e..4046021 100644 --- a/kernel/source/interrupts.cpp +++ b/kernel/source/interrupts.cpp @@ -1,4 +1,5 @@ #include <hilbert/kernel/framebuffer.hpp> +#include <hilbert/kernel/serial.hpp> #include <hilbert/kernel/input.hpp> #include <hilbert/kernel/panic.hpp> @@ -36,13 +37,47 @@ struct [[gnu::packed]] exception_info_t { extern exception_info_t exception_info; +static inline void print_reg(const char *regname, uint64_t value) { + serial_putstr(" "); + serial_putstr(regname); + serial_putstr(" = 0x"); + serial_puthex<16>(value); + serial_putchar('\n'); +} + extern "C" [[noreturn]] void print_exception() { //so exception_info's type is known by gdb exception_info_t the_exception_info = exception_info; (void)the_exception_info; - //TODO: log exception, and recover if possible. + serial_putstr("exception 0x"); + serial_puthex<2>(exception_info.exception_number); + serial_putchar('\n'); + + if (exception_info.has_error) + print_reg("error code", exception_info.error); + + print_reg("rflags", exception_info.rflags); + print_reg("rip", exception_info.rip); + print_reg("cr2", exception_info.cr2); + print_reg("cr3", exception_info.cr3); + print_reg("rax", exception_info.rax); + print_reg("rbx", exception_info.rbx); + print_reg("rcx", exception_info.rcx); + print_reg("rdx", exception_info.rdx); + print_reg("rdi", exception_info.rdi); + print_reg("rsi", exception_info.rsi); + print_reg("rbp", exception_info.rbp); + print_reg("rsp", exception_info.rsp); + print_reg("r8 ", exception_info.r8 ); + print_reg("r9 ", exception_info.r9 ); + print_reg("r10", exception_info.r10); + print_reg("r11", exception_info.r11); + print_reg("r12", exception_info.r12); + print_reg("r13", exception_info.r13); + print_reg("r14", exception_info.r14); + print_reg("r15", exception_info.r15); panic(0xba40bb); diff --git a/kernel/source/serial.asm b/kernel/source/serial.asm new file mode 100644 index 0000000..071e525 --- /dev/null +++ b/kernel/source/serial.asm @@ -0,0 +1,58 @@ +bits 64 + +global serial_init +global serial_putchar + +section .text + +serial_init: + + xor al, al + mov dx, 0x03f9 + out dx, al + + mov al, 0x80 + mov dx, 0x03fb + out dx, al + + mov al, 0x03 + mov dx, 0x03f8 + out dx, al + + xor al, al + mov dx, 0x03f9 + out dx, al + + mov al, 0x03 + mov dx, 0x03fb + out dx, al + + mov al, 0xc7 + mov dx, 0x03fa + out dx, al + + ret + +serial_putchar: + + cmp dil, 0x0a + je .do_cr +.cr_ret: + + mov dx, 0x03fd + +.loop: + in al, dx + test al, 0x20 + jz .loop + + mov al, dil + mov dx, 0x03f8 + out dx, al + ret + +.do_cr: + mov dil, 0x0d + call serial_putchar + mov dil, 0x0a + jmp .cr_ret |