diff --git a/src/boot.asm b/src/boot.asm index c427022..9a2f546 100644 --- a/src/boot.asm +++ b/src/boot.asm @@ -1,5 +1,6 @@ global _start extern kernel_main +extern setup_idt %define FLAGS 0b10 %define MAGIC 0x1BADB002 @@ -25,6 +26,17 @@ section .bss pd: resb 4096 +section .bss + align 8 + idt64: + resb 4096 + +section .data + align 8 + idt64_descriptor: + dw 4095 ; IDT size (256 entries * 16 bytes - 1) + dq idt64 ; IDT base address + section .data align 8 gdt64: @@ -140,6 +152,10 @@ section .text mov fs, ax mov gs, ax mov ss, ax + + call setup_idt + sti + call kernel_main .hang: hlt diff --git a/src/idt.asm b/src/idt.asm new file mode 100644 index 0000000..9019ca7 --- /dev/null +++ b/src/idt.asm @@ -0,0 +1,114 @@ +global setup_idt +extern handle_isr + +%macro ISR_NOERR 1 +isr_stub_%1: + push qword 0 + push qword %1 + jmp isr_common +%endmacro + +%macro ISR_ERR 1 +isr_stub_%1: + push qword %1 + jmp isr_common +%endmacro + +%macro GENERATE_NUB_ISR_NOERR 2 + %assign i %1 + %rep (%2 - %1 + 1) + ISR_NOERR i + %assign i i+1 + %endrep +%endmacro + +section .text + bits 64 + setup_idt: + ret + + isr_common: + push rax + push rbx + push rcx + push rdx + push rsi + push rdi + push rbp + push r8 + push r9 + push r10 + push r11 + push r12 + push r13 + push r14 + push r15 + mov rdi, rsp + call handle_isr + pop r15 + pop r14 + pop r13 + pop r12 + pop r11 + pop r10 + pop r9 + pop r8 + pop rbp + pop rdi + pop rsi + pop rdx + pop rcx + pop rbx + pop rax + add rsp, 16 + iretq + + ; CPU exceptions 0-31. Some of there contain error codes, so we define them manually + ISR_NOERR 0 + ISR_NOERR 1 + ISR_NOERR 2 + ISR_NOERR 3 + ISR_NOERR 4 + ISR_NOERR 5 + ISR_NOERR 6 + ISR_NOERR 7 + ISR_ERR 8 + ISR_NOERR 9 + ISR_ERR 10 + ISR_ERR 11 + ISR_ERR 12 + ISR_ERR 13 + ISR_ERR 14 + ISR_NOERR 15 + ISR_NOERR 16 + ISR_ERR 17 + ISR_NOERR 18 + ISR_NOERR 19 + ISR_NOERR 20 + ISR_NOERR 21 + ISR_NOERR 22 + ISR_NOERR 23 + ISR_NOERR 24 + ISR_NOERR 25 + ISR_NOERR 26 + ISR_NOERR 27 + ISR_NOERR 28 + ISR_NOERR 29 + ISR_ERR 30 + ISR_NOERR 31 + + ; The remaining isr-s does not have an error code + GENERATE_ISRS 32, 255 + +%macro GENERATE_ISR_TABLE 2 + %assign i %1 + %rep (%2 - %1 + 1) + dq isr_stub_%[i] + %assign i i+1 + %endrep +%endmacro + +section .data + global isr_stub_table + isr_stub_table: + GENERATE_ISR_TABLE 0, 255 \ No newline at end of file diff --git a/src/idt.c b/src/idt.c index 38d8d83..b333a19 100644 --- a/src/idt.c +++ b/src/idt.c @@ -1,31 +1,18 @@ #include "idt.h" #include "vga.h" - -#define IDT_SIZE 256 +#include "kernel.h" #define PIC1_COMMAND 0x20 #define PIC1_DATA 0x21 #define PIC2_COMMAND 0xA0 #define PIC2_DATA 0xA1 -typedef struct -{ - u16 address_low; - u16 selector; - u8 ist; - u8 flags; - u16 address_mid; - u32 address_high; - u32 reserved; -} __attribute__((packed)) interrupt_descriptor; - typedef struct { u16 limit; u64 base; } __attribute__((packed)) idtr_t; -extern void* isr_stub_table[]; static irq_handler_t irq_handlers[16] = {0}; static const char* exception_messages[32] = { @@ -63,32 +50,17 @@ static const char* exception_messages[32] = { "reserved", }; -static interrupt_descriptor idt[IDT_SIZE]; - -static void pic_remap(int offset1, int offset2) +void register_irq_handler(u8 irq, irq_handler_t handler) { - u8 a1, a2; + if (irq >= 16) + { + kernel_panic(); + } - a1 = inb(PIC1_DATA); - a2 = inb(PIC2_DATA); - - outb(PIC1_COMMAND, 0x11); - outb(PIC2_COMMAND, 0x11); - - outb(PIC1_DATA, offset1); - outb(PIC2_DATA, offset2); - - outb(PIC1_DATA, 4); - outb(PIC2_DATA, 2); - - outb(PIC1_DATA, 0x01); - outb(PIC2_DATA, 0x01); - - outb(PIC1_DATA, a1); - outb(PIC2_DATA, a2); + irq_handlers[irq] = handler; } -static void pic_send_eoi(u8 irq) +static inline void pic_send_eoi(u8 irq) { if (irq >= 8) { @@ -98,42 +70,6 @@ static void pic_send_eoi(u8 irq) outb(PIC1_COMMAND, 0x20); } -void register_irq_handler(u8 irq, irq_handler_t handler) -{ - irq_handlers[irq] = handler; -} - -static inline void idt_set_descriptor(u8 vector, void* handler, u8 dpl) -{ - interrupt_descriptor* entry = &idt[vector]; - - entry->address_low = (u64)handler & 0xFFFF; - entry->address_mid = ((u64)handler >> 16) & 0xFFFF; - entry->address_high = (u64)handler >> 32; - entry->selector = 0x08; - entry->flags = 0b1110 | ((dpl & 0b11) << 5) | (1 << 7); - entry->ist = 0; - entry->reserved = 0; -} - -void init_idt(void) -{ - pic_remap(0x20, 0x28); - - for (int i = 0; i < 256; i++) - { - idt_set_descriptor(i, isr_stub_table[i], 0); - } - - idtr_t idtr = { - .base = (uintptr_t)&idt[0], - .limit = (u16)sizeof(interrupt_descriptor) * IDT_SIZE - 1, - }; - - __asm__ volatile("lidt %0" : : "m"(idtr)); - __asm__ volatile("sti"); -} - void handle_isr(isr_frame_t* frame) { if (frame->int_no < 32) diff --git a/src/idt.h b/src/idt.h index c5e84f1..f176ae3 100644 --- a/src/idt.h +++ b/src/idt.h @@ -13,8 +13,6 @@ typedef struct typedef void (*irq_handler_t)(const isr_frame_t*); -void init_idt(void); - static inline void outb(u16 port, u8 val) { __asm__ volatile("outb %0, %1" : : "a"(val), "Nd"(port)); diff --git a/src/kernel.c b/src/kernel.c index 1127b88..1d82691 100644 --- a/src/kernel.c +++ b/src/kernel.c @@ -9,10 +9,6 @@ void kernel_main() vga_print_success(); vga_print(" VGA intialzied\n"); - init_idt(); - vga_print_success(); - vga_print(" IDT intialzied\n"); - init_keyboard(); vga_print_success(); vga_print(" Keyboard intialzied\n");