diff --git a/src/interrupts.c b/src/interrupts.c index 698695c..3b1d69e 100644 --- a/src/interrupts.c +++ b/src/interrupts.c @@ -1,6 +1,4 @@ #include "interrupts.h" -#include "vga.h" -#include "kernel.h" #include "util.h" #define PIC1_COMMAND 0x20 @@ -8,24 +6,6 @@ #define PIC2_COMMAND 0xA0 #define PIC2_DATA 0xA1 -void pic_remap() -{ - 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); -} - static const char* exception_messages[32] = { "divide by zero", "debug", @@ -61,14 +41,52 @@ static const char* exception_messages[32] = { "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); + kprintf("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); + kprintf("PIC remapped\n"); +} + +void disable_pic() { + outb(PIC1_DATA, 0xFF); + outb(PIC2_DATA, 0xFF); + kprintf("PIC disabled\n"); +} + void handle_exception(const isr_frame_t* frame) { kprintf("exception[%d]: %s, error code: %d\n", frame->int_no, exception_messages[frame->int_no], frame->err_code); kpanic(); } -static irq_handler_t irq_handlers[16] = {0}; - void register_irq_handler(uint8_t irq, irq_handler_t handler) { if (irq >= 16) @@ -78,6 +96,7 @@ void register_irq_handler(uint8_t irq, irq_handler_t handler) else { irq_handlers[irq] = handler; + kprintf("Registered irq handler at vector %d\n", irq); } } diff --git a/src/interrupts.h b/src/interrupts.h index 7e2ebde..d160fb9 100644 --- a/src/interrupts.h +++ b/src/interrupts.h @@ -1,5 +1,6 @@ #pragma once +#include "kernel.h" #include typedef struct @@ -13,16 +14,22 @@ typedef struct typedef void (*irq_handler_t)(const isr_frame_t*); -void pic_remap(); +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"); + kprintf("Interrupts enabled\n"); } static inline void disable_interrupts() { __asm__ volatile("cli"); + kprintf("Interrupts disabled\n"); } \ No newline at end of file diff --git a/src/kernel.c b/src/kernel.c index 3a8a97e..446cccb 100644 --- a/src/kernel.c +++ b/src/kernel.c @@ -4,7 +4,7 @@ #include "string.h" #include "vga.h" #include -#include +#include "multiboot.h" void handle_keypress(const keyboard_event_t* event) { @@ -14,12 +14,18 @@ void handle_keypress(const keyboard_event_t* event) } } -void kmain() +void kmain(multiboot_info_t* multiboot_info) { vga_clear(); - pic_remap(); + remap_pic(); + + if (cpu_has_apic()) + { + disable_pic(); + enable_apic(); + } + enable_interrupts(); - init_keyboard(); register_keypress_handler(handle_keypress); kprintf("Welcome to nub OS\n"); diff --git a/src/multiboot.h b/src/multiboot.h index dd9044c..736acb0 100644 --- a/src/multiboot.h +++ b/src/multiboot.h @@ -2,6 +2,18 @@ #include +#define MULTIBOOT_FLAG_MEMIFO 0b0000000000001 +#define MULTIBOOT_FLAG_BOOT_DEVICE 0b0000000000010 +#define MULTIBOOT_FLAG_CMDLINE 0b0000000000100 +#define MULTIBOOT_FLAG_MODINFO 0b0000000001000 +#define MULTIBOOT_FLAG_MMAP 0b0000001000000 +#define MULTIBOOT_FLAG_DRIVES 0b0000010000000 +#define MULTIBOOT_FLAG_CONFIG_TABLE 0b0000100000000 +#define MULTIBOOT_FLAG_BOOTLOADER_NAME 0b0001000000000 +#define MULTIBOOT_FLAG_APM_TABLE 0b0010000000000 +#define MULTIBOOT_FLAG_VBEINFO 0b0100000000000 +#define MULTIBOOT_FLAG_FRAMEBUFFER_INFO 0b1000000000000 + typedef struct multiboot_info { uint32_t flags; // required diff --git a/src/start.asm b/src/start.asm index f1da24f..33e4715 100644 --- a/src/start.asm +++ b/src/start.asm @@ -14,7 +14,7 @@ section .multiboot section .bss align 16 - resb 16384 + resb 32768 stack_top: section .bss @@ -37,6 +37,11 @@ section .data dq gdt64 .end: +section .data + align 8 + multiboot_info: + dq 0 + section .text bits 32 _start: @@ -48,6 +53,9 @@ section .text cmp eax, 0x2BADB002 jne error + ; Save multiboot info pointer for later + mov [multiboot_info], ebx + ; Check if cpuid is available by flipping bit 21 ; in the eflags register and checking if the cpu flipped it back pushfd @@ -93,10 +101,10 @@ section .text mov eax, pd or eax, 0x03 mov [pdpt], eax - ; Fill pd with 2MB entries + ; Map first 32 2mb pages for the kernel for a total of 64mb mov edi, pd mov eax, 0x83 - mov ecx, 512 + mov ecx, 32 .setup_pd: mov [edi], eax add eax, 0x200000 @@ -195,6 +203,7 @@ section .text lidt [idt64_descriptor] ; Finally, we call in to c + mov rdi, [multiboot_info] call kmain .hang: hlt diff --git a/src/util.h b/src/util.h index 87c7e3b..ce10c39 100644 --- a/src/util.h +++ b/src/util.h @@ -2,6 +2,71 @@ #include +enum { + CPUID_FEAT_ECX_SSE3 = 1 << 0, + CPUID_FEAT_ECX_PCLMUL = 1 << 1, + CPUID_FEAT_ECX_DTES64 = 1 << 2, + CPUID_FEAT_ECX_MONITOR = 1 << 3, + CPUID_FEAT_ECX_DS_CPL = 1 << 4, + CPUID_FEAT_ECX_VMX = 1 << 5, + CPUID_FEAT_ECX_SMX = 1 << 6, + CPUID_FEAT_ECX_EST = 1 << 7, + CPUID_FEAT_ECX_TM2 = 1 << 8, + CPUID_FEAT_ECX_SSSE3 = 1 << 9, + CPUID_FEAT_ECX_CID = 1 << 10, + CPUID_FEAT_ECX_SDBG = 1 << 11, + CPUID_FEAT_ECX_FMA = 1 << 12, + CPUID_FEAT_ECX_CX16 = 1 << 13, + CPUID_FEAT_ECX_XTPR = 1 << 14, + CPUID_FEAT_ECX_PDCM = 1 << 15, + CPUID_FEAT_ECX_PCID = 1 << 17, + CPUID_FEAT_ECX_DCA = 1 << 18, + CPUID_FEAT_ECX_SSE4_1 = 1 << 19, + CPUID_FEAT_ECX_SSE4_2 = 1 << 20, + CPUID_FEAT_ECX_X2APIC = 1 << 21, + CPUID_FEAT_ECX_MOVBE = 1 << 22, + CPUID_FEAT_ECX_POPCNT = 1 << 23, + CPUID_FEAT_ECX_TSC = 1 << 24, + CPUID_FEAT_ECX_AES = 1 << 25, + CPUID_FEAT_ECX_XSAVE = 1 << 26, + CPUID_FEAT_ECX_OSXSAVE = 1 << 27, + CPUID_FEAT_ECX_AVX = 1 << 28, + CPUID_FEAT_ECX_F16C = 1 << 29, + CPUID_FEAT_ECX_RDRAND = 1 << 30, + CPUID_FEAT_ECX_HYPERVISOR = 1 << 31, + + CPUID_FEAT_EDX_FPU = 1 << 0, + CPUID_FEAT_EDX_VME = 1 << 1, + CPUID_FEAT_EDX_DE = 1 << 2, + CPUID_FEAT_EDX_PSE = 1 << 3, + CPUID_FEAT_EDX_TSC = 1 << 4, + CPUID_FEAT_EDX_MSR = 1 << 5, + CPUID_FEAT_EDX_PAE = 1 << 6, + CPUID_FEAT_EDX_MCE = 1 << 7, + CPUID_FEAT_EDX_CX8 = 1 << 8, + CPUID_FEAT_EDX_APIC = 1 << 9, + CPUID_FEAT_EDX_SEP = 1 << 11, + CPUID_FEAT_EDX_MTRR = 1 << 12, + CPUID_FEAT_EDX_PGE = 1 << 13, + CPUID_FEAT_EDX_MCA = 1 << 14, + CPUID_FEAT_EDX_CMOV = 1 << 15, + CPUID_FEAT_EDX_PAT = 1 << 16, + CPUID_FEAT_EDX_PSE36 = 1 << 17, + CPUID_FEAT_EDX_PSN = 1 << 18, + CPUID_FEAT_EDX_CLFLUSH = 1 << 19, + CPUID_FEAT_EDX_DS = 1 << 21, + CPUID_FEAT_EDX_ACPI = 1 << 22, + CPUID_FEAT_EDX_MMX = 1 << 23, + CPUID_FEAT_EDX_FXSR = 1 << 24, + CPUID_FEAT_EDX_SSE = 1 << 25, + CPUID_FEAT_EDX_SSE2 = 1 << 26, + CPUID_FEAT_EDX_SS = 1 << 27, + CPUID_FEAT_EDX_HTT = 1 << 28, + CPUID_FEAT_EDX_TM = 1 << 29, + CPUID_FEAT_EDX_IA64 = 1 << 30, + CPUID_FEAT_EDX_PBE = 1 << 31 +}; + static inline void outb(uint16_t port, uint8_t val) { __asm__ volatile("outb %0, %1" : : "a"(val), "Nd"(port)); @@ -17,4 +82,20 @@ static inline uint8_t inb(uint16_t port) static inline void io_wait() { outb(0x80, 0); +} + +static inline void cpuid(uint32_t code, uint32_t* a, uint32_t* d) { + __asm__ volatile("cpuid" : "=a"(*a), "=d"(*d) : "a"(code) : "ecx", "ebx"); +} + +static inline uint64_t rdmsr(uint32_t msr) { + uint32_t lo, hi; + __asm__ volatile("rdmsr" : "=a"(lo), "=d"(hi) : "c"(msr)); + return ((uint64_t)hi << 32) | lo; +} + +static inline void wrmsr(uint32_t msr, uint64_t value) { + uint32_t lo = (uint32_t)value; + uint32_t hi = (uint32_t)(value >> 32); + __asm__ volatile("wrmsr" : : "c"(msr), "a"(lo), "d"(hi)); } \ No newline at end of file diff --git a/src/vga.c b/src/vga.c index 59875f5..580276c 100644 --- a/src/vga.c +++ b/src/vga.c @@ -31,8 +31,8 @@ void vga_put_char(char character, uint8_t color) } case '\t': { - uint8_t remainter = cursor_col % 4; - cursor_col += remainter == 0 ? 4 : remainter; + uint8_t remainder = 4 - (cursor_col % 4); + cursor_col += remainder; break; } case '\b': @@ -86,13 +86,13 @@ void vga_put_char(char character, uint8_t color) { for (size_t col = 0; col < COLUMNS; col++) { - vga_buffer[COLUMNS * row - 1 + col] = vga_buffer[COLUMNS * row + col]; + vga_buffer[COLUMNS * (row - 1) + col] = vga_buffer[COLUMNS * row + col]; } } for (size_t col = 0; col < COLUMNS; col++) { - vga_buffer[ROWS - 1 + col] = (vga_char_t){ + vga_buffer[COLUMNS * (ROWS - 1) + col] = (vga_char_t){ .character = ' ', .color = VGA_DEFAULT_COLOR, }; @@ -108,7 +108,7 @@ void vga_clear() { for (size_t col = 0; col < COLUMNS; col++) { - vga_buffer[COLUMNS * row - 1 + col] = (vga_char_t){ + vga_buffer[COLUMNS * row + col] = (vga_char_t){ .character = ' ', .color = VGA_DEFAULT_COLOR, };