diff --git a/zealbooter/idt.c b/zealbooter/idt.c new file mode 100644 index 00000000..55812750 --- /dev/null +++ b/zealbooter/idt.c @@ -0,0 +1,163 @@ +#include +#include +#include +#include +#include + +struct cpu_ctx { + uint64_t ds; + uint64_t es; + uint64_t rax; + uint64_t rbx; + uint64_t rcx; + uint64_t rdx; + uint64_t rsi; + uint64_t rdi; + uint64_t rbp; + 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 err; + uint64_t rip; + uint64_t cs; + uint64_t rflags; + uint64_t rsp; + uint64_t ss; +}; + +struct idt_entry { + uint16_t offset_low; + uint16_t selector; + uint8_t ist; + uint8_t flags; + uint16_t offset_mid; + uint32_t offset_hi; + uint32_t reserved; +}; + +struct idtr { + uint16_t limit; + uint64_t base; +} __attribute__((packed)); + +static struct idt_entry idt[256]; + +void *isr[256]; + +static void register_handler(uint8_t vector, void *handler, uint8_t flags) { + uint64_t handler_int = (uint64_t)handler; + + idt[vector] = (struct idt_entry){ + .offset_low = (uint16_t)handler_int, + .selector = 0x28, + .ist = 0, + .flags = flags, + .offset_mid = (uint16_t)(handler_int >> 16), + .offset_hi = (uint32_t)(handler_int >> 32), + .reserved = 0 + }; +} + +extern void *isr_thunks[]; + +static const char *exceptions[] = { + "Division exception", + "Debug", + "NMI", + "Breakpoint", + "Overflow", + "Bound range exceeded", + "Invalid opcode", + "Device not available", + "Double fault", + "???", + "Invalid TSS", + "Segment not present", + "Stack-segment fault", + "General protection fault", + "Page fault", + "???", + "x87 exception", + "Alignment check", + "Machine check", + "SIMD exception", + "Virtualisation" +}; + +static inline uint64_t read_cr0(void) { + uint64_t ret; + asm volatile ("mov %%cr0, %0" : "=r"(ret) :: "memory"); + return ret; +} + +static inline uint64_t read_cr2(void) { + uint64_t ret; + asm volatile ("mov %%cr2, %0" : "=r"(ret) :: "memory"); + return ret; +} + +static inline uint64_t read_cr3(void) { + uint64_t ret; + asm volatile ("mov %%cr3, %0" : "=r"(ret) :: "memory"); + return ret; +} + +static inline uint64_t read_cr4(void) { + uint64_t ret; + asm volatile ("mov %%cr4, %0" : "=r"(ret) :: "memory"); + return ret; +} + +static void exception_handler(uint8_t vector, struct cpu_ctx *ctx) { + printf("Exception %s triggered\n\n", exceptions[vector]); + + printf(" RAX=%016lx RBX=%016lx\n" + " RCX=%016lx RDX=%016lx\n" + " RSI=%016lx RDI=%016lx\n" + " RBP=%016lx RSP=%016lx\n" + " R08=%016lx R09=%016lx\n" + " R10=%016lx R11=%016lx\n" + " R12=%016lx R13=%016lx\n" + " R14=%016lx R15=%016lx\n" + " RIP=%016lx RFLAGS=%08lx\n" + " CS=%04lx DS=%04lx ES=%04lx SS=%04lx\n" + " CR0=%016lx CR2=%016lx\n" + " CR3=%016lx CR4=%016lx\n" + " ERR=%016lx", + ctx->rax, ctx->rbx, ctx->rcx, ctx->rdx, + ctx->rsi, ctx->rdi, ctx->rbp, ctx->rsp, + ctx->r8, ctx->r9, ctx->r10, ctx->r11, + ctx->r12, ctx->r13, ctx->r14, ctx->r15, + ctx->rip, ctx->rflags, + ctx->cs, ctx->ds, ctx->es, ctx->ss, + read_cr0(), read_cr2(), + read_cr3(), read_cr4(), + ctx->err); + + for (;;) { + asm ("hlt"); + } + __builtin_unreachable(); +} + +void idt_init(void) { + for (size_t i = 0; i < 256; i++) { + register_handler(i, isr_thunks[i], 0x8e); + } + + for (size_t i = 0; i < sizeof(exceptions) / sizeof(exceptions[0]); i++) { + isr[i] = exception_handler; + } + + struct idtr idtr = { + .limit = sizeof(idt) - 1, + .base = (uint64_t)idt + }; + + asm volatile ("lidt %0" :: "m"(idtr) : "memory"); +} diff --git a/zealbooter/idt.h b/zealbooter/idt.h new file mode 100644 index 00000000..0960cca2 --- /dev/null +++ b/zealbooter/idt.h @@ -0,0 +1,6 @@ +#ifndef _IDT_H +#define _IDT_H + +void idt_init(void); + +#endif diff --git a/zealbooter/int_thunks.S b/zealbooter/int_thunks.S new file mode 100644 index 00000000..caf0926f --- /dev/null +++ b/zealbooter/int_thunks.S @@ -0,0 +1,61 @@ +.altmacro + +.macro THUNK num +interrupt_thunk_\num: +.if \num != 8 && \num != 10 && \num != 11 && \num != 12 && \num != 13 && \num != 14 && \num != 17 && \num != 30 + push $0 +.endif + + push %r15 + push %r14 + push %r13 + push %r12 + push %r11 + push %r10 + push %r9 + push %r8 + push %rbp + push %rdi + push %rsi + push %rdx + push %rcx + push %rbx + push %rax + mov %es, %eax + push %rax + mov %ds, %eax + push %rax + + cld + + mov $\num, %rdi + mov $(\num * 8), %rax + lea isr(%rip), %rbx + add %rax, %rbx + mov %rsp, %rsi + call *(%rbx) + +.endm + +.macro THUNKADDR num + .quad interrupt_thunk_\num +.endm + +.section .data + +.global isr_thunks +.align 8 +isr_thunks: +.set i,0 +.rept 256 + THUNKADDR %i + .set i,i+1 +.endr + +.section .text + +.set i,0 +.rept 256 + THUNK %i + .set i,i+1 +.endr diff --git a/zealbooter/zealbooter.c b/zealbooter/zealbooter.c index 276b0936..5dfe384d 100644 --- a/zealbooter/zealbooter.c +++ b/zealbooter/zealbooter.c @@ -2,6 +2,7 @@ #include #include #include +#include static volatile struct limine_module_request module_request = { .id = LIMINE_MODULE_REQUEST, @@ -152,6 +153,8 @@ void _start(void) { printf("ZealBooter prekernel\n"); printf("____________________\n\n"); + idt_init(); + struct limine_file *module_kernel = module_request.response->modules[0]; struct CKernel *kernel = module_kernel->address;