summaryrefslogtreecommitdiff
path: root/kernel
diff options
context:
space:
mode:
authorBenji Dial <benji@benjidial.net>2024-01-13 19:14:58 -0500
committerBenji Dial <benji@benjidial.net>2024-01-13 19:14:58 -0500
commite9898e829b8df7c0b16faec1ce490369c53fd78e (patch)
tree0959298e7af3e5b9e40ac4d6dec0cec089105eac /kernel
parent4130562b1555cabe441efe9420cebe12e7ed8d39 (diff)
downloadhilbert-os-e9898e829b8df7c0b16faec1ce490369c53fd78e.tar.gz
minimal cpu exception handling
Diffstat (limited to 'kernel')
-rw-r--r--kernel/entry.cpp23
-rw-r--r--kernel/interrupts.asm254
-rw-r--r--kernel/interrupts.cpp119
-rw-r--r--kernel/syscall.asm36
4 files changed, 373 insertions, 59 deletions
diff --git a/kernel/entry.cpp b/kernel/entry.cpp
index f7ba71d..cce8066 100644
--- a/kernel/entry.cpp
+++ b/kernel/entry.cpp
@@ -184,15 +184,6 @@ extern "C" [[noreturn]] void entry() {
}
-static void print_mem() {
- uint64_t used_vram_mib = (paging::get_used_vram_page_count() + 128) / 256;
- uint64_t free_pram_mib = (paging::get_free_pram_page_count() + 128) / 256;
- terminal::put_int_decimal(used_vram_mib);
- terminal::put_string_sz(" MiB kernel memory mapped.\n");
- terminal::put_int_decimal(free_pram_mib);
- terminal::put_string_sz(" MiB physical memory free.\n");
-}
-
[[noreturn]] static void print_and_halt(const char *msg) {
terminal::put_string_sz(msg);
while (1)
@@ -230,25 +221,11 @@ extern "C" [[noreturn]] void start_user_mode(
if (!init_file)
print_and_halt("/bin/init.elf does not exist.");
- terminal::put_string_sz("/bin/init.elf is ");
- terminal::put_int_decimal(init_file->dir_entry.length);
- terminal::put_string_sz(" bytes long.\n");
-
application::app_instance *init;
if (application::create_app(*init_file, init) !=
application::create_app_result::success)
print_and_halt("failed to parse /bin/init.elf.");
- terminal::put_string_sz("/bin/init.elf loaded:\n instruction pointer 0x");
- terminal::put_int_hex(init->saved_regs.rip, 8);
- terminal::put_string_sz("\n stack pointer 0x");
- terminal::put_int_hex(init->saved_regs.rsp, 8);
- terminal::put_string_sz("\n ");
- terminal::put_int_decimal(init->count_mapped_vram_pages() * 2);
- terminal::put_string_sz(" MiB userspace memory used\n");
-
- print_mem();
- terminal::put_string_sz("switching to /bin/init.elf.\n");
application::running_app = init;
start_user_mode(init->saved_regs.rip, init->saved_regs.rsp, init->p4_paddr);
diff --git a/kernel/interrupts.asm b/kernel/interrupts.asm
new file mode 100644
index 0000000..c375ee4
--- /dev/null
+++ b/kernel/interrupts.asm
@@ -0,0 +1,254 @@
+bits 64
+
+global load_gdt_and_idt
+
+section .rodata
+
+;0x28 picked to align with limine choice
+
+;0x18 - tss
+;0x28 - kernel code
+;0x30 - kernel data
+;0x38 - user data
+;0x40 - user code
+
+tss:
+ times 9 dd 0
+ dq 0xffffffffffeff000
+ times 15 dd 0
+
+gdtr:
+ dw 0x47
+ dq gdt
+
+idtr:
+ dw 4095
+ dq idt
+
+section .bss
+
+idt:
+ resq 512
+
+global exception_info
+exception_info:
+.rax:
+ resq 1
+.rbx:
+ resq 1
+.rcx:
+ resq 1
+.rdx:
+ resq 1
+.rdi:
+ resq 1
+.rsi:
+ resq 1
+.rbp:
+ resq 1
+.rsp:
+ resq 1
+.r8:
+ resq 1
+.r9:
+ resq 1
+.r10:
+ resq 1
+.r11:
+ resq 1
+.r12:
+ resq 1
+.r13:
+ resq 1
+.r14:
+ resq 1
+.r15:
+ resq 1
+.cr3:
+ resq 1
+.rip:
+ resq 1
+.rflags:
+ resq 1
+.error:
+ resq 1
+.has_error:
+ resb 1
+.exception_number:
+ resb 1
+
+section .rodata
+
+has_error_code:
+ db 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 1, 1, 1, 1, 0
+
+exception_isrs:
+ dq exception_00, exception_01, exception_02, exception_03
+ dq exception_04, exception_05, exception_06, exception_07
+ dq exception_08, exception_09, exception_0a, exception_0b
+ dq exception_0c, exception_0d, exception_0e, exception_0f
+
+section .text
+
+extern print_exception
+
+exception_00:
+ mov byte [exception_info.exception_number], 0x00
+ jmp exception_common
+exception_01:
+ mov byte [exception_info.exception_number], 0x01
+ jmp exception_common
+exception_02:
+ mov byte [exception_info.exception_number], 0x02
+ jmp exception_common
+exception_03:
+ mov byte [exception_info.exception_number], 0x03
+ jmp exception_common
+exception_04:
+ mov byte [exception_info.exception_number], 0x04
+ jmp exception_common
+exception_05:
+ mov byte [exception_info.exception_number], 0x05
+ jmp exception_common
+exception_06:
+ mov byte [exception_info.exception_number], 0x06
+ jmp exception_common
+exception_07:
+ mov byte [exception_info.exception_number], 0x07
+ jmp exception_common
+exception_08:
+ mov byte [exception_info.exception_number], 0x08
+ jmp exception_common
+exception_09:
+ mov byte [exception_info.exception_number], 0x09
+ jmp exception_common
+exception_0a:
+ mov byte [exception_info.exception_number], 0x0a
+ jmp exception_common
+exception_0b:
+ mov byte [exception_info.exception_number], 0x0b
+ jmp exception_common
+exception_0c:
+ mov byte [exception_info.exception_number], 0x0c
+ jmp exception_common
+exception_0d:
+ mov byte [exception_info.exception_number], 0x0d
+ jmp exception_common
+exception_0e:
+ mov byte [exception_info.exception_number], 0x0e
+ jmp exception_common
+exception_0f:
+ mov byte [exception_info.exception_number], 0x0f
+ jmp exception_common
+
+exception_common:
+ mov qword [exception_info.rax], rax
+
+ movzx rax, byte [exception_info.exception_number]
+ mov al, byte [has_error_code + rax]
+ test al, al
+ jz .no_error_code
+
+ mov byte [exception_info.has_error], 1
+ pop rax
+ mov qword [exception_info.error], rax
+ jmp .post_error_code
+
+.no_error_code:
+ mov byte [exception_info.has_error], 0
+
+.post_error_code:
+ mov qword [exception_info.rbx], rbx
+ mov qword [exception_info.rcx], rcx
+ mov qword [exception_info.rdx], rdx
+ mov qword [exception_info.rdi], rdi
+ mov qword [exception_info.rsi], rsi
+ mov qword [exception_info.rbp], rbp
+ mov qword [exception_info.r8], r8
+ mov qword [exception_info.r9], r9
+ mov qword [exception_info.r10], r10
+ mov qword [exception_info.r11], r11
+ mov qword [exception_info.r12], r12
+ mov qword [exception_info.r13], r13
+ mov qword [exception_info.r14], r14
+ mov qword [exception_info.r15], r15
+
+ pop rax
+ mov qword [exception_info.rip], rax
+ pop rax
+ pop rax
+ mov qword [exception_info.rflags], rax
+ pop rax
+ mov qword [exception_info.rsp], rax
+
+ mov rax, cr3
+ mov qword [exception_info.cr3], rax
+
+ jmp print_exception
+
+set_isr:
+;rdi - index
+;sil - 1 if this is a trap, 0 if it is an interrupt
+;rdx - isr pointer
+
+ shl rdi, 4
+ add rdi, idt
+
+ mov word [rdi], dx
+ shr rdx, 16
+ mov word [rdi + 6], dx
+ shr rdx, 16
+ mov dword [rdi + 8], edx
+
+ or sil, 0xef
+ mov byte [rdi + 5], sil
+ mov word [rdi + 2], 0x28
+ mov byte [rdi + 4], 1
+
+ ret
+
+section .data
+
+gdt:
+ dq 0
+ dq 0
+ dq 0
+.tss:
+ dq 0x0000e90000000067
+ dq 0;tss is 2 qwords wide
+ dq 0x00209b0000000000
+ dq 0x00009b0000000000
+ dq 0x0000fb0000000000
+ dq 0x0020fb0000000000
+
+section .text
+
+load_gdt_and_idt:
+
+ mov rcx, 8
+
+.loop:
+
+ mov rdi, rcx
+ dec rdi
+ mov sil, 1
+ mov rdx, qword [exception_isrs + rdi * 8]
+ call set_isr
+
+ loop .loop
+
+ mov rax, tss
+
+ mov word [gdt.tss + 2], ax
+ shr rax, 16
+ mov byte [gdt.tss + 4], al
+ mov byte [gdt.tss + 7], ah
+ shr rax, 16
+ mov dword [gdt.tss + 8], eax
+
+ lgdt [gdtr]
+ lidt [idtr]
+ mov ax, 0x18
+ ltr ax
+
+ ret
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");
+
+}
diff --git a/kernel/syscall.asm b/kernel/syscall.asm
index 56be8a4..e4e0d77 100644
--- a/kernel/syscall.asm
+++ b/kernel/syscall.asm
@@ -1,45 +1,9 @@
bits 64
-global load_gdt_and_idt
global start_user_mode
-section .rodata
-
-;0x28 picked to align with limine choice
-;0x28 - kernel code
-;0x30 - kernel data
-;0x38 - user data
-;0x40 - user code
-
-gdtr:
- dw 0x47
- dq gdt
-
-gdt:
- dq 0
- dq 0
- dq 0
- dq 0
- dq 0
- dq 0x00209b0000000000
- dq 0x00009b0000000000
- dq 0x0000fb0000000000
- dq 0x0020fb0000000000
-
-idtr:
- dw 4095
- dq idt
-
-idt:
- times 256 - ($ - idt) / 16 dq 0
-
section .text
-load_gdt_and_idt:
- lgdt [gdtr]
- lidt [idtr]
- ret
-
extern syscall_encode_color
encode_color_syscall: