diff --git a/src/arch/x86_64/start.asm b/src/arch/x86_64/boot/boot.asm similarity index 58% rename from src/arch/x86_64/start.asm rename to src/arch/x86_64/boot/boot.asm index ea3fa45..92c4028 100644 --- a/src/arch/x86_64/start.asm +++ b/src/arch/x86_64/boot/boot.asm @@ -1,6 +1,5 @@ global _start extern entry -extern handle_isr %define FLAGS 0b10 %define MAGIC 0x1BADB002 @@ -139,39 +138,6 @@ section .text hlt jmp .hang -section .bss - align 4096 - idt64: - resb 4096 - -section .data - align 8 - idt64_descriptor: - dw 4095 - dq idt64 - -section .data - align 8 - isr_stub_table: - %assign i 0 - %rep 256 - dq isr_stub_%[i] - %assign i i+1 - %endrep - -%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 - section .text bits 64 long_mode: @@ -183,108 +149,9 @@ section .text mov gs, ax mov ss, ax - ; Fill in the idt table with the stub functions - mov rdi, idt64 - mov rsi, isr_stub_table - mov rcx, 256 - .loop: - mov rax, [rsi] - mov [rdi], ax - mov word [rdi + 2], 0x08 - mov word [rdi + 4], 0x8E00 - shr rax, 16 - mov [rdi + 6], ax - shr rax, 16 - mov [rdi + 8], eax - mov dword [rdi + 12], 0 - add rdi, 16 - add rsi, 8 - loop .loop - lidt [idt64_descriptor] - ; Finally, we call in to c mov rdi, [multiboot_info] call entry .hang: hlt - jmp .hang - - 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 these 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 - - ; Hardware interrupts and user-defined interrupts (32-255). These don't have error codes - %assign i 32 - %rep 224 - ISR_NOERR i - %assign i i+1 - %endrep \ No newline at end of file + jmp .hang \ No newline at end of file diff --git a/src/arch/x86_64/interrupts.c b/src/arch/x86_64/interrupts.c deleted file mode 100644 index f699efc..0000000 --- a/src/arch/x86_64/interrupts.c +++ /dev/null @@ -1,139 +0,0 @@ -#include "interrupts.h" -#include "../arch.h" -#include "util.h" -#include - -#define PIC1_COMMAND 0x20 -#define PIC1_DATA 0x21 -#define PIC2_COMMAND 0xA0 -#define PIC2_DATA 0xA1 - -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 irq_handler_t irq_handlers[16] = {0}; - -bool cpu_has_apic() -{ - uint32_t eax, edx; - cpuid(1, &eax, &edx); - return (edx & CPUID_FEAT_EDX_APIC) != 0; -} - -void enable_apic() -{ - uint64_t apic_base = rdmsr(0x1B); - apic_base |= (1 << 11); - wrmsr(0x1B, apic_base); - printf("APIC enabled\n"); -} - -void remap_pic() -{ - outb(PIC1_COMMAND, 0x11); - outb(PIC2_COMMAND, 0x11); - - outb(PIC1_DATA, 32); - outb(PIC2_DATA, 40); - - outb(PIC1_DATA, 4); - outb(PIC2_DATA, 2); - - outb(PIC1_DATA, 1); - outb(PIC2_DATA, 1); - - outb(PIC1_DATA, 0); - outb(PIC2_DATA, 0); - printf("PIC remapped\n"); -} - -void disable_pic() -{ - outb(PIC1_DATA, 0xFF); - outb(PIC2_DATA, 0xFF); - printf("PIC disabled\n"); -} - -static void handle_exception(const isr_frame_t* frame) -{ - printf("exception[%d]: %s, error code: %d\n", frame->int_no, exception_messages[frame->int_no], frame->err_code); - panic(); -} - -void register_irq_handler(uint8_t irq, irq_handler_t handler) -{ - if (irq >= 16) - { - printf("Cannot register irq %d is out of bounds\n", irq); - } - else - { - irq_handlers[irq] = handler; - printf("Registered irq handler at vector %d\n", irq); - } -} - -static void handle_irq(const isr_frame_t* frame) -{ - uint8_t irq = frame->int_no - 32; - - if (irq_handlers[irq]) - { - irq_handlers[irq](frame); - } - - if (irq >= 8) - { - outb(PIC2_COMMAND, 0x20); - } - - outb(PIC1_COMMAND, 0x20); -} - -void handle_isr(const isr_frame_t* frame) -{ - if (frame->int_no < 32) - { - handle_exception(frame); - } - else if (frame->int_no < 48) - { - handle_irq(frame); - } - else - { - printf("interrupt[%d]: not implemented\n", frame->int_no); - } -} \ No newline at end of file diff --git a/src/arch/x86_64/interrupts/exceptions.c b/src/arch/x86_64/interrupts/exceptions.c new file mode 100644 index 0000000..01112d8 --- /dev/null +++ b/src/arch/x86_64/interrupts/exceptions.c @@ -0,0 +1,43 @@ +#include "exceptions.h" +#include "../../arch.h" + +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", +}; + +void handle_exception(const isr_frame_t* frame) +{ + printf("exception[%d]: %s, error code: %d\n", frame->int_no, exception_messages[frame->int_no], frame->err_code); + panic(); +} \ No newline at end of file diff --git a/src/arch/x86_64/interrupts/exceptions.h b/src/arch/x86_64/interrupts/exceptions.h new file mode 100644 index 0000000..c493644 --- /dev/null +++ b/src/arch/x86_64/interrupts/exceptions.h @@ -0,0 +1,8 @@ +#pragma once + +#include "isr.h" + +typedef void (*exception_handler_t)(const isr_frame_t*); + +void handle_exception(const isr_frame_t* frame); +void register_exception_handler(uint8_t irq, exception_handler_t handler); \ No newline at end of file diff --git a/src/arch/x86_64/interrupts/idt.asm b/src/arch/x86_64/interrupts/idt.asm new file mode 100644 index 0000000..39a9953 --- /dev/null +++ b/src/arch/x86_64/interrupts/idt.asm @@ -0,0 +1,136 @@ +global idt_init +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 + +section .bss + align 4096 + idt64: + resb 4096 + +section .data + align 8 + isr_stub_table: + %assign i 0 + %rep 256 + dq isr_stub_%[i] + %assign i i+1 + %endrep + + idt64_descriptor: + dw 4095 + dq idt64 + +section .text + bits 64 + idt_init: + ; Fill in the idt table with the stub functions + mov rdi, idt64 + mov rsi, isr_stub_table + mov rcx, 256 + .loop: + mov rax, [rsi] + mov [rdi], ax + mov word [rdi + 2], 0x08 + mov word [rdi + 4], 0x8E00 + shr rax, 16 + mov [rdi + 6], ax + shr rax, 16 + mov [rdi + 8], eax + mov dword [rdi + 12], 0 + add rdi, 16 + add rsi, 8 + loop .loop + lidt [idt64_descriptor] + 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 these 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 + + ; Hardware interrupts and user-defined interrupts (32-255). These don't have error codes + %assign i 32 + %rep 224 + ISR_NOERR i + %assign i i+1 + %endrep \ No newline at end of file diff --git a/src/arch/x86_64/interrupts/idt.h b/src/arch/x86_64/interrupts/idt.h new file mode 100644 index 0000000..ad35389 --- /dev/null +++ b/src/arch/x86_64/interrupts/idt.h @@ -0,0 +1,3 @@ +#pragma once + +extern void idt_init(); \ No newline at end of file diff --git a/src/arch/x86_64/interrupts/irq.c b/src/arch/x86_64/interrupts/irq.c new file mode 100644 index 0000000..d455d2f --- /dev/null +++ b/src/arch/x86_64/interrupts/irq.c @@ -0,0 +1,76 @@ +#include "irq.h" +#include "../util.h" + +#define PIC1_COMMAND 0x20 +#define PIC1_DATA 0x21 +#define PIC2_COMMAND 0xA0 +#define PIC2_DATA 0xA1 + +static irq_handler_t irq_handlers[16] = {0}; + +bool cpu_has_apic() +{ + uint32_t eax, edx; + cpuid(1, &eax, &edx); + return (edx & CPUID_FEAT_EDX_APIC) != 0; +} + +void enable_apic() +{ + uint64_t apic_base = rdmsr(0x1B); + apic_base |= (1 << 11); + wrmsr(0x1B, apic_base); +} + +void remap_pic() +{ + outb(PIC1_COMMAND, 0x11); + outb(PIC2_COMMAND, 0x11); + + outb(PIC1_DATA, 32); + outb(PIC2_DATA, 40); + + outb(PIC1_DATA, 4); + outb(PIC2_DATA, 2); + + outb(PIC1_DATA, 1); + outb(PIC2_DATA, 1); + + outb(PIC1_DATA, 0); + outb(PIC2_DATA, 0); +} + +void disable_pic() +{ + outb(PIC1_DATA, 0xFF); + outb(PIC2_DATA, 0xFF); +} + +void register_irq_handler(uint8_t irq, irq_handler_t handler) +{ + if (irq >= 16) + { + printf("Cannot register irq %d is out of bounds\n", irq); + } + else + { + irq_handlers[irq] = handler; + } +} + +void handle_irq(const isr_frame_t* frame) +{ + uint8_t irq = frame->int_no - 32; + + if (irq_handlers[irq]) + { + irq_handlers[irq](frame); + } + + if (irq >= 8) + { + outb(PIC2_COMMAND, 0x20); + } + + outb(PIC1_COMMAND, 0x20); +} \ No newline at end of file diff --git a/src/arch/x86_64/interrupts/irq.h b/src/arch/x86_64/interrupts/irq.h new file mode 100644 index 0000000..2db3211 --- /dev/null +++ b/src/arch/x86_64/interrupts/irq.h @@ -0,0 +1,13 @@ +#pragma once + +#include "isr.h" +#include + +typedef void (*irq_handler_t)(const isr_frame_t*); + +void remap_pic(); +void disable_pic(); +bool cpu_has_apic(); +void enable_apic(); +void handle_irq(const isr_frame_t* frame); +void register_irq_handler(uint8_t irq, irq_handler_t handler); \ No newline at end of file diff --git a/src/arch/x86_64/interrupts/isr.c b/src/arch/x86_64/interrupts/isr.c new file mode 100644 index 0000000..08341e0 --- /dev/null +++ b/src/arch/x86_64/interrupts/isr.c @@ -0,0 +1,20 @@ +#include "isr.h" +#include "exceptions.h" +#include "irq.h" +#include + +void handle_isr(const isr_frame_t* frame) +{ + if (frame->int_no < 32) + { + handle_exception(frame); + } + else if (frame->int_no < 48) + { + handle_irq(frame); + } + else + { + printf("interrupt[%d]: not implemented\n", frame->int_no); + } +} \ No newline at end of file diff --git a/src/arch/x86_64/interrupts.h b/src/arch/x86_64/interrupts/isr.h similarity index 59% rename from src/arch/x86_64/interrupts.h rename to src/arch/x86_64/interrupts/isr.h index 958ea71..cd23032 100644 --- a/src/arch/x86_64/interrupts.h +++ b/src/arch/x86_64/interrupts/isr.h @@ -1,6 +1,5 @@ #pragma once -#include #include #include @@ -13,24 +12,12 @@ typedef struct uint64_t rip, cs, rflags, rsp, ss; } __attribute__((packed)) isr_frame_t; -typedef void (*irq_handler_t)(const isr_frame_t*); - -void remap_pic(); -void disable_pic(); - -bool cpu_has_apic(); -void enable_apic(); - -void register_irq_handler(uint8_t irq, irq_handler_t handler); - static inline void enable_interrupts() { __asm__ volatile("sti"); - printf("Interrupts enabled\n"); } static inline void disable_interrupts() { __asm__ volatile("cli"); - printf("Interrupts disabled\n"); } \ No newline at end of file diff --git a/src/arch/x86_64/keyboard.c b/src/arch/x86_64/keyboard.c index 8bd5d88..156b644 100644 --- a/src/arch/x86_64/keyboard.c +++ b/src/arch/x86_64/keyboard.c @@ -101,7 +101,7 @@ // handler_index += 1; // } -// void init_keyboard() +// void keyboard_init() // { // register_irq_handler(1, handle_keyboard); // } \ No newline at end of file diff --git a/src/arch/x86_64/keyboard.h b/src/arch/x86_64/keyboard.h index eac0d16..7d5ad41 100644 --- a/src/arch/x86_64/keyboard.h +++ b/src/arch/x86_64/keyboard.h @@ -14,6 +14,6 @@ // typedef void (*keyboard_handler_t)(const keyboard_event_t*); -// void init_keyboard(); +// void keyboard_init(); // void register_keypress_handler(keyboard_handler_t handler); // char scan_code_to_ascii(uint8_t scan_code); \ No newline at end of file diff --git a/src/arch/x86_64/x86_64.c b/src/arch/x86_64/x86_64.c index 36b6fbd..d86ea3d 100644 --- a/src/arch/x86_64/x86_64.c +++ b/src/arch/x86_64/x86_64.c @@ -1,6 +1,7 @@ #include "../../kernel.h" #include "../arch.h" -#include "interrupts.h" +#include "interrupts/idt.h" +#include "interrupts/irq.h" #include "mmap.h" #include "multiboot.h" #include "util.h" @@ -10,22 +11,16 @@ void entry(multiboot_info_t* mbd) { vga_clear(); - map_memory(mbd); + idt_init(); remap_pic(); + map_memory(mbd); enable_interrupts(); main(); } -void arch_callback() -{ - printf("Kernel panic!\n"); - disable_interrupts(); - halt(); -} - void panic() { - printf("Kernel panic!"); + printf("Kernel panic!\n"); disable_interrupts(); halt(); } diff --git a/src/kernel.c b/src/kernel.c index 23e6ab3..cc21fb3 100644 --- a/src/kernel.c +++ b/src/kernel.c @@ -4,6 +4,6 @@ void main() { - init_pmm(); + pmm_init(); printf("Welcome to nub OS :)\n"); } diff --git a/src/pmm.c b/src/pmm.c index 0e20b3f..91586e4 100644 --- a/src/pmm.c +++ b/src/pmm.c @@ -11,7 +11,7 @@ static uint8_t page_bitmap[BITMAP_SIZE]; static uint64_t total_pages = 0; static uint64_t free_pages = 0; -void init_pmm() +void pmm_init() { memset(page_bitmap, 0xFF, BITMAP_SIZE); @@ -50,8 +50,6 @@ void init_pmm() } } } - - printf("PMM initialized\n"); } uint64_t pmm_alloc_page() diff --git a/src/pmm.h b/src/pmm.h index 421f758..b04100f 100644 --- a/src/pmm.h +++ b/src/pmm.h @@ -4,6 +4,6 @@ #define PAGE_SIZE 4096 -void init_pmm(); +void pmm_init(); uint64_t pmm_alloc_page(); void pmm_free_page(uint64_t addr); \ No newline at end of file