diff --git a/src/idt.c b/src/idt.c index d90c3b7..e4ed5da 100644 --- a/src/idt.c +++ b/src/idt.c @@ -4,6 +4,13 @@ #include #include +#define IDT_SIZE 256 + +#define PIC1_COMMAND 0x20 +#define PIC1_DATA 0x21 +#define PIC2_COMMAND 0xA0 +#define PIC2_DATA 0xA1 + typedef struct { uint16_t address_low; @@ -21,22 +28,95 @@ typedef struct uint64_t base; } __attribute__((packed)) idtr_t; -typedef struct -{ - uint64_t r15, r14, r13, r12, r11, r10, r9, r8; - uint64_t rbp, rdi, rsi, rdx, rcx, rbx, rax; - uint64_t int_no; - uint64_t err_code; - uint64_t rip, cs, rflags, rsp, ss; -} __attribute__((packed)) isr_frame_t; - -#define IDT_SIZE 256 - extern void* isr_stub_table[]; +static irq_handler_t irq_handlers[16] = { 0 }; + +static const char* exception_messages[32] = { "divide by zero", + "debug", + "non maskable interrupt", + "breakpoint", + "overflow", + "bound range exceeded", + "invalid opcode", + "device not available", + "double fault", + "coprocessor segment overrun", + "invalid tss", + "segment not present", + "stack-segment fault", + "general protection fault", + "page fault", + "reserved", + "x87 floating point exception", + "alignment check", + "machine check", + "simd floating point exception", + "virtualization exception", + "control protection exception", + "reserved", + "reserved", + "reserved", + "reserved", + "reserved", + "reserved", + "hypervisor injection exception", + "vmm communication exception", + "security exception", + "reserved" }; static interrupt_descriptor idt[IDT_SIZE]; -void idt_set_descriptor(uint8_t vector, void* handler, uint8_t dpl) +static inline void outb(uint16_t port, uint8_t val) +{ + __asm__ volatile("outb %0, %1" : : "a"(val), "Nd"(port)); +} + +static inline uint8_t inb(uint16_t port) +{ + uint8_t ret; + __asm__ volatile("inb %1, %0" : "=a"(ret) : "Nd"(port)); + return ret; +} + +static void pic_remap(int offset1, int offset2) +{ + uint8_t a1, a2; + + 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); +} + +static void pic_send_eoi(uint8_t irq) +{ + if (irq >= 8) + { + outb(PIC2_COMMAND, 0x20); + } + + outb(PIC1_COMMAND, 0x20); +} + +void register_irq_handler(uint8_t irq, irq_handler_t handler) +{ + irq_handlers[irq] = handler; +} + +static inline void idt_set_descriptor(uint8_t vector, void* handler, uint8_t dpl) { interrupt_descriptor* entry = &idt[vector]; @@ -49,21 +129,11 @@ void idt_set_descriptor(uint8_t vector, void* handler, uint8_t dpl) entry->reserved = 0; } -void exception_handler(isr_frame_t* frame) -{ - vga_print("Interrupt\n"); - vga_print(" int_no: "); - vga_print_uint(frame->int_no); - vga_print("\n"); - vga_print(" err_code: "); - vga_print_uint(frame->err_code); - vga_print("\n"); - __asm__ volatile("cli; hlt"); -} - void idt_init(void) { - for (int i = 0; i < 32; i++) + pic_remap(0x20, 0x28); + + for (int i = 0; i < 256; i++) { idt_set_descriptor(i, isr_stub_table[i], 0); } @@ -71,4 +141,47 @@ void idt_init(void) idtr_t idtr = { .base = (uintptr_t)&idt[0], .limit = (uint16_t)sizeof(interrupt_descriptor) * IDT_SIZE - 1 }; __asm__ volatile("lidt %0" : : "m"(idtr)); -} \ No newline at end of file + __asm__ volatile("sti"); +} + +void idt_enable(void) +{ + __asm__ volatile("sti"); +} + +void handle_isr(isr_frame_t* frame) +{ + if (frame->int_no < 32) + { + vga_print_error(); + vga_print(" exception["); + vga_print_uint(frame->int_no); + vga_print("]: "); + vga_print(exception_messages[frame->int_no]); + + vga_print(", error code: "); + vga_print_uint(frame->err_code); + vga_print("\n"); + + __asm__ volatile("cli; hlt"); + } + else if (frame->int_no < 48) + { + uint8_t irq = frame->int_no - 32; + + if (irq_handlers[irq]) + { + irq_handlers[irq](frame); + } + + pic_send_eoi(irq); + } + else + { + vga_print_error(); + vga_print(" interrupt["); + vga_print_uint(frame->int_no); + vga_print("]: "); + vga_print("not implemented\n"); + } +} diff --git a/src/idt.h b/src/idt.h index a1ce9a2..1459cf7 100644 --- a/src/idt.h +++ b/src/idt.h @@ -2,5 +2,17 @@ #include +typedef struct +{ + uint64_t r15, r14, r13, r12, r11, r10, r9, r8; + uint64_t rbp, rdi, rsi, rdx, rcx, rbx, rax; + uint64_t int_no; + uint64_t err_code; + uint64_t rip, cs, rflags, rsp, ss; +} __attribute__((packed)) isr_frame_t; + +typedef void (*irq_handler_t)(isr_frame_t*); + void idt_init(void); -void idt_set_descriptor(uint8_t vector, void* isr, uint8_t flags); +void idt_enable(void); +void register_irq_handler(uint8_t irq, irq_handler_t handler); \ No newline at end of file diff --git a/src/idt_stub.asm b/src/idt_stub.asm index 8035efc..bed39b3 100644 --- a/src/idt_stub.asm +++ b/src/idt_stub.asm @@ -1,17 +1,4 @@ -extern exception_handler - -%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 +extern handle_isr isr_common: push rax @@ -31,7 +18,7 @@ isr_common: push r15 mov rdi, rsp - call exception_handler + call handle_isr pop r15 pop r14 @@ -52,6 +39,20 @@ isr_common: add rsp, 16 iretq +%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 + +; CPU exceptions 0-31 ISR_NOERR 0 ISR_NOERR 1 ISR_NOERR 2 @@ -85,37 +86,24 @@ ISR_NOERR 29 ISR_ERR 30 ISR_NOERR 31 +%macro GENERATE_ISRS 2 + %assign i %1 + %rep (%2 - %1 + 1) + ISR_NOERR i + %assign i i+1 + %endrep +%endmacro + +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 + global isr_stub_table isr_stub_table: - dq isr_stub_0 - dq isr_stub_1 - dq isr_stub_2 - dq isr_stub_3 - dq isr_stub_4 - dq isr_stub_5 - dq isr_stub_6 - dq isr_stub_7 - dq isr_stub_8 - dq isr_stub_9 - dq isr_stub_10 - dq isr_stub_11 - dq isr_stub_12 - dq isr_stub_13 - dq isr_stub_14 - dq isr_stub_15 - dq isr_stub_16 - dq isr_stub_17 - dq isr_stub_18 - dq isr_stub_19 - dq isr_stub_20 - dq isr_stub_21 - dq isr_stub_22 - dq isr_stub_23 - dq isr_stub_24 - dq isr_stub_25 - dq isr_stub_26 - dq isr_stub_27 - dq isr_stub_28 - dq isr_stub_29 - dq isr_stub_30 - dq isr_stub_31 \ No newline at end of file +GENERATE_ISR_TABLE 0, 255 \ No newline at end of file diff --git a/src/kernel.c b/src/kernel.c index 4283b86..a80db5e 100644 --- a/src/kernel.c +++ b/src/kernel.c @@ -1,5 +1,6 @@ #include "idt.h" #include "vga.h" +#include void kernel_main(void) { @@ -8,11 +9,13 @@ void kernel_main(void) vga_print(" VGA intialzied\n"); idt_init(); + idt_enable(); vga_print_success(); vga_print(" IDT intialzied\n"); vga_print("\nWelcome to nub OS\n"); - vga_print(">"); - int x = 1 / 0; + while (true) + { + } } \ No newline at end of file