minimal cpu exception handling
This commit is contained in:
parent
4130562b15
commit
e9898e829b
6 changed files with 378 additions and 61 deletions
|
@ -9,6 +9,7 @@ uint32_t fb_height;
|
|||
uint32_t fb_pitch;
|
||||
|
||||
int main(int, char **) {
|
||||
|
||||
mercury::syscall::get_framebuffer(fb, fb_width, fb_height, fb_pitch);
|
||||
for (uint32_t y = 0; y < fb_height; ++y)
|
||||
for (uint32_t x = 0; x < fb_width; ++x) {
|
||||
|
@ -20,5 +21,6 @@ int main(int, char **) {
|
|||
fb[y * fb_pitch + x] = mercury::syscall::encode_color(c);
|
||||
}
|
||||
mercury::syscall::draw_framebuffer();
|
||||
return 0;
|
||||
|
||||
return 1 / 0;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
254
kernel/interrupts.asm
Normal file
254
kernel/interrupts.asm
Normal file
|
@ -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
|
119
kernel/interrupts.cpp
Normal file
119
kernel/interrupts.cpp
Normal file
|
@ -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");
|
||||
|
||||
}
|
|
@ -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:
|
||||
|
|
3
makefile
3
makefile
|
@ -41,7 +41,8 @@ obj/kernel/%.asm.o: kernel/%.asm
|
|||
|
||||
KERNEL_OBJECTS = allocator.cpp application.cpp entry.cpp framebuffer.cpp \
|
||||
paging.asm paging.cpp storage.cpp storage/bd/memory.cpp terminal.cpp \
|
||||
storage/fs/tarfs.cpp utility.cpp vfile.cpp syscall.asm syscall.cpp
|
||||
storage/fs/tarfs.cpp utility.cpp vfile.cpp syscall.asm syscall.cpp \
|
||||
interrupts.asm interrupts.cpp
|
||||
obj/kernel.elf: ${KERNEL_OBJECTS:%=obj/kernel/%.o}
|
||||
ld ${KLD_ARGS} $^ -o $@
|
||||
|
||||
|
|
Reference in a new issue