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;
|
uint32_t fb_pitch;
|
||||||
|
|
||||||
int main(int, char **) {
|
int main(int, char **) {
|
||||||
|
|
||||||
mercury::syscall::get_framebuffer(fb, fb_width, fb_height, fb_pitch);
|
mercury::syscall::get_framebuffer(fb, fb_width, fb_height, fb_pitch);
|
||||||
for (uint32_t y = 0; y < fb_height; ++y)
|
for (uint32_t y = 0; y < fb_height; ++y)
|
||||||
for (uint32_t x = 0; x < fb_width; ++x) {
|
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);
|
fb[y * fb_pitch + x] = mercury::syscall::encode_color(c);
|
||||||
}
|
}
|
||||||
mercury::syscall::draw_framebuffer();
|
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) {
|
[[noreturn]] static void print_and_halt(const char *msg) {
|
||||||
terminal::put_string_sz(msg);
|
terminal::put_string_sz(msg);
|
||||||
while (1)
|
while (1)
|
||||||
|
@ -230,25 +221,11 @@ extern "C" [[noreturn]] void start_user_mode(
|
||||||
if (!init_file)
|
if (!init_file)
|
||||||
print_and_halt("/bin/init.elf does not exist.");
|
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;
|
application::app_instance *init;
|
||||||
if (application::create_app(*init_file, init) !=
|
if (application::create_app(*init_file, init) !=
|
||||||
application::create_app_result::success)
|
application::create_app_result::success)
|
||||||
print_and_halt("failed to parse /bin/init.elf.");
|
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;
|
application::running_app = init;
|
||||||
start_user_mode(init->saved_regs.rip, init->saved_regs.rsp, init->p4_paddr);
|
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
|
bits 64
|
||||||
|
|
||||||
global load_gdt_and_idt
|
|
||||||
global start_user_mode
|
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
|
section .text
|
||||||
|
|
||||||
load_gdt_and_idt:
|
|
||||||
lgdt [gdtr]
|
|
||||||
lidt [idtr]
|
|
||||||
ret
|
|
||||||
|
|
||||||
extern syscall_encode_color
|
extern syscall_encode_color
|
||||||
|
|
||||||
encode_color_syscall:
|
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 \
|
KERNEL_OBJECTS = allocator.cpp application.cpp entry.cpp framebuffer.cpp \
|
||||||
paging.asm paging.cpp storage.cpp storage/bd/memory.cpp terminal.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}
|
obj/kernel.elf: ${KERNEL_OBJECTS:%=obj/kernel/%.o}
|
||||||
ld ${KLD_ARGS} $^ -o $@
|
ld ${KLD_ARGS} $^ -o $@
|
||||||
|
|
||||||
|
|
Reference in a new issue