diff --git a/kernel/CMakeLists.txt b/kernel/CMakeLists.txt index f50383c..d5e2405 100644 --- a/kernel/CMakeLists.txt +++ b/kernel/CMakeLists.txt @@ -1,24 +1,20 @@ cmake_minimum_required(VERSION 3.20) -project(termOS_krn LANGUAGES C ASM) +project(termOS_krn LANGUAGES C ASM_NASM) set(CMAKE_C_STANDARD 23) set(CMAKE_C_STANDARD_REQUIRED ON) set(CMAKE_C_EXTENSIONS OFF) -add_compile_options( - -ffreestanding - -mno-red-zone - -fno-stack-protector - -fno-builtin - -Wall -Wextra - -g -) - add_library(shitgui STATIC src/modules/shitgui.c) target_include_directories(shitgui PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/include") -add_executable(kernel +add_executable(kernel + src/entry.asm + src/asm/interrupts.asm src/kmain.c + src/modules/gdt.c + src/modules/idt.c + src/modules/interrupts.c src/modules/memory.c src/modules/serial.c src/modules/console.c @@ -40,6 +36,17 @@ target_link_options(kernel PRIVATE -T "${CMAKE_CURRENT_SOURCE_DIR}/linker.ld" ) +target_compile_options(kernel PRIVATE + $<$: + -ffreestanding + -mno-red-zone + -fno-stack-protector + -fno-builtin + -Wall -Wextra + -g + > +) + set_target_properties(kernel PROPERTIES OUTPUT_NAME "kernel.elf" RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin" diff --git a/kernel/include/gdt.h b/kernel/include/gdt.h new file mode 100644 index 0000000..24273d2 --- /dev/null +++ b/kernel/include/gdt.h @@ -0,0 +1,24 @@ +#pragma once +#ifndef GDT_H +#define GDT_H + +#include "types.h" + +typedef struct { + u16 limit_low; + u16 base_low; + u8 base_middle; + u8 access; + u8 granularity; + u8 base_high; +} __attribute__((packed)) GDTDescriptor; + + +typedef struct { + u16 limit; + u64 base; +} __attribute__((packed)) GDTPtr; + +void gdt_init(); + +#endif \ No newline at end of file diff --git a/kernel/include/idt.h b/kernel/include/idt.h new file mode 100644 index 0000000..af3aeec --- /dev/null +++ b/kernel/include/idt.h @@ -0,0 +1,19 @@ +#pragma once +#include "types.h" + +typedef struct { + u16 offset_low; + u16 selector; + u8 ist; + u8 attributes; + u16 offset_mid; + u32 offset_high; + u32 reserved; +} __attribute__((packed)) IDTEntry; + +typedef struct { + u16 limit; + u64 base; +} __attribute__((packed)) IDTPtr; + +void idt_init(); \ No newline at end of file diff --git a/kernel/include/panic.h b/kernel/include/panic.h index 3475326..e3f8835 100644 --- a/kernel/include/panic.h +++ b/kernel/include/panic.h @@ -1,3 +1,10 @@ #pragma once +#ifndef PANIC_H +#define PANIC_H +#include "types.h" -__attribute__((noreturn)) void panic(const char *msg); \ No newline at end of file +__attribute__((noreturn)) void panic(Registers *regs); + +extern const char* exception_messages[]; + +#endif \ No newline at end of file diff --git a/kernel/include/types.h b/kernel/include/types.h index de11d34..86478a9 100644 --- a/kernel/include/types.h +++ b/kernel/include/types.h @@ -14,4 +14,10 @@ typedef signed _BitInt(64) i64; typedef u64 usize; typedef u64 uintptr_t; +typedef struct { + u64 rax, rbx, rcx, rdx, rbp, rsi, rdi, r8, r9, r10, r11, r12, r13, r14, r15; // Pushed by us + u64 int_no, err_code; // Pushed by macro + u64 rip, cs, rflags, rsp, ss; // Pushed by CPU +} Registers; + #endif \ No newline at end of file diff --git a/kernel/linker.ld b/kernel/linker.ld index fae8143..daf9e17 100644 --- a/kernel/linker.ld +++ b/kernel/linker.ld @@ -1,4 +1,4 @@ -ENTRY(kmain) +ENTRY(_start) SECTIONS { diff --git a/kernel/src/asm/interrupts.asm b/kernel/src/asm/interrupts.asm new file mode 100644 index 0000000..9adf542 --- /dev/null +++ b/kernel/src/asm/interrupts.asm @@ -0,0 +1,97 @@ +bits 64 + +extern isr_handler_c + +section .text + +%macro ISR_NOERRCODE 1 +global isr%1 +isr%1: + push 0 + push %1 + jmp isr_common_stub +%endmacro + +%macro ISR_ERRCODE 1 +global isr%1 +isr%1: + push %1 + jmp isr_common_stub +%endmacro + +ISR_NOERRCODE 0 ; Divide by zero +ISR_NOERRCODE 1 ; Debug +ISR_NOERRCODE 2 ; NMI +ISR_NOERRCODE 3 ; Breakpoint +ISR_NOERRCODE 4 ; Overflow +ISR_NOERRCODE 5 ; Bound Range Exceeded +ISR_NOERRCODE 6 ; Invalid Opcode +ISR_NOERRCODE 7 ; Device Not Available +ISR_ERRCODE 8 ; Double Fault +ISR_NOERRCODE 9 ; Coprocessor Segment Overrun +ISR_ERRCODE 10 ; Invalid TSS +ISR_ERRCODE 11 ; Segment Not Present +ISR_ERRCODE 12 ; Stack-Segment Fault +ISR_ERRCODE 13 ; General Protection Fault +ISR_ERRCODE 14 ; Page Fault +ISR_NOERRCODE 15 ; Reserved +ISR_NOERRCODE 16 ; x87 Floating-Point Exception +ISR_ERRCODE 17 ; Alignment Check +ISR_NOERRCODE 18 ; Machine Check +ISR_NOERRCODE 19 ; SIMD Floating-Point Exception +ISR_NOERRCODE 20 ; Virtualization Exception +ISR_NOERRCODE 21 ; Reserved +ISR_NOERRCODE 22 ; Reserved +ISR_NOERRCODE 23 ; Reserved +ISR_NOERRCODE 24 ; Reserved +ISR_NOERRCODE 25 ; Reserved +ISR_NOERRCODE 26 ; Reserved +ISR_NOERRCODE 27 ; Reserved +ISR_NOERRCODE 28 ; Reserved +ISR_NOERRCODE 29 ; Reserved +ISR_ERRCODE 30 ; Security Exception +ISR_NOERRCODE 31 ; Reserved + +isr_common_stub: + push r15 + push r14 + push r13 + push r12 + push r11 + push r10 + push r9 + push r8 + push rdi + push rsi + push rbp + push rdx + push rcx + push rbx + push rax + + mov rdi, rsp + call isr_handler_c + + pop rax + pop rbx + pop rcx + pop rdx + pop rbp + pop rsi + pop rdi + pop r8 + pop r9 + pop r10 + pop r11 + pop r12 + pop r13 + pop r14 + pop r15 + + add rsp, 16 + iretq + +global idt_load +idt_load: + lidt [rdi] + ret \ No newline at end of file diff --git a/kernel/src/entry.asm b/kernel/src/entry.asm new file mode 100644 index 0000000..8c16c0f --- /dev/null +++ b/kernel/src/entry.asm @@ -0,0 +1,40 @@ +bits 64 + +section .bss +align 16 +stack_bottom: + resb 16384 +stack_top: + +section .text +global _start +global gdt_flush +extern kmain + +_start: + cli + + mov rsp, stack_top + xor rbp, rbp + + call kmain + +.hang: + hlt + jmp .hang + + +gdt_flush: + lgdt [rdi] + + mov ax, 0x10 + mov ds, ax + mov es, ax + mov fs, ax + mov gs, ax + mov ss, ax + + pop rdi + push 0x08 + push rdi + retfq \ No newline at end of file diff --git a/kernel/src/kmain.c b/kernel/src/kmain.c index be95f41..e7572b2 100644 --- a/kernel/src/kmain.c +++ b/kernel/src/kmain.c @@ -7,6 +7,9 @@ #include "panic.h" // IWYU pragma: keep #include "../data/logo.h" +#include "gdt.h" +#include "idt.h" + void kmain(Bootinfo* info) { u32 *fb = (u32*)info->framebuffer.base; if (!fb) return; @@ -21,12 +24,19 @@ void kmain(Bootinfo* info) { console_init(&sg_ctx); console_clear(0xFFFFFF); console_set_color(0x000000); + + gdt_init(); + idt_init(); + SG_Point logo_point = {sg_ctx.width-100, 100}; sg_put_img(&sg_ctx, &logo_point, &logo_img); + kprint("Welcome to termOS!!!\n"); kprintf("MemoryMap located at %x; \nMemory map size is %d\n", (u64)info->mem.map, (u64)info->mem.map_size); - for (i32 i = 0; i < 1000; i++) kprintf("Test %d\n", i); + int a = 1; + int b = 0; + kprintf("%d", a/b); while (1) { __asm__("hlt"); } } \ No newline at end of file diff --git a/kernel/src/modules/gdt.c b/kernel/src/modules/gdt.c new file mode 100644 index 0000000..ef85447 --- /dev/null +++ b/kernel/src/modules/gdt.c @@ -0,0 +1,44 @@ +// just fucking kill me already + +#include "gdt.h" + +GDTDescriptor gdt[3]; +GDTPtr gdt_ptr; + +void gdt_set_gate(int num, u64 base, u64 limit, u8 access, u8 gran) { + gdt[num].base_low = (base & 0xFFFF); // left only low 16bit + gdt[num].base_middle = (base >> 16) & 0xFF; // 3rd address byte + gdt[num].base_high = (base >> 24) & 0xFF; // 4th address byte + + gdt[num].limit_low = (limit & 0xFFFF); + gdt[num].granularity = (limit >> 16) & 0x0F; // leave only first 4 bits (limit's left 16-19) + gdt[num].granularity |= gran & 0xF0; // get flags and concate two pieces so FFFFLLLL (L -- Limit; F -- flags) + gdt[num].access = access; + + // intel, + // please + // FUCK YOU + // cancer of industry + // AMD FOREVER +} + +extern void gdt_flush(u64 gdt_ptr_addr); // entry.asm + +void gdt_init() { + gdt_ptr.limit = (sizeof(GDTDescriptor) * 3) - 1; + gdt_ptr.base = (u64)&gdt; + + // 0: Null + gdt_set_gate(0, 0, 0, 0, 0); + + // 1: Kernel Code (Ring 0) + // Access: 0x9A (Present, Ring0, Exec/Read) + // Granularity: 0x20 (Long Mode bit) access ring 0 code exec code readable + gdt_set_gate(1, 0, 0, 0x9A, 0x20); // 0x9A = 1 00 1 1 0 1 + // 0x20 = 0010 0000 bit 5 is "Long mode" + // 2: Kernel Data (Ring 0) + // Access: 0x92 (Present, Ring0, Read/Write) + gdt_set_gate(2, 0, 0, 0x92, 0); // 0x92 can't exec + + gdt_flush((u64)&gdt_ptr); +} \ No newline at end of file diff --git a/kernel/src/modules/idt.c b/kernel/src/modules/idt.c new file mode 100644 index 0000000..325e3a5 --- /dev/null +++ b/kernel/src/modules/idt.c @@ -0,0 +1,70 @@ +#include "idt.h" +#include "types.h" + +IDTEntry idt[256]; +IDTPtr idt_ptr; + +extern void isr0(); extern void isr1(); extern void isr2(); extern void isr3(); +extern void isr4(); extern void isr5(); extern void isr6(); extern void isr7(); +extern void isr8(); extern void isr9(); extern void isr10(); extern void isr11(); +extern void isr12(); extern void isr13(); extern void isr14(); extern void isr15(); +extern void isr16(); extern void isr17(); extern void isr18(); extern void isr19(); +extern void isr20(); extern void isr21(); extern void isr22(); extern void isr23(); +extern void isr24(); extern void isr25(); extern void isr26(); extern void isr27(); +extern void isr28(); extern void isr29(); extern void isr30(); extern void isr31(); + +extern void idt_load(u64); // asm: lidt [rdi] / ret + +void idt_set_gate(int num, u64 handler, u16 sel, u8 flags) { + idt[num].offset_low = handler & 0xFFFF; + idt[num].offset_mid = (handler >> 16) & 0xFFFF; + idt[num].offset_high = (handler >> 32) & 0xFFFFFFFF; + + idt[num].selector = sel; // 0x08 (Kernel Code) + idt[num].ist = 0; + idt[num].attributes = flags; + idt[num].reserved = 0; +} + +void idt_init() { + idt_ptr.limit = (sizeof(IDTEntry) * 256) - 1; + idt_ptr.base = (u64)&idt; + + const u8 flags = 0x8E; + const u8 selector = 0x08; + + idt_set_gate(0, (u64)isr0, selector, flags); + idt_set_gate(1, (u64)isr1, selector, flags); + idt_set_gate(2, (u64)isr2, selector, flags); + idt_set_gate(3, (u64)isr3, selector, flags); + idt_set_gate(4, (u64)isr4, selector, flags); + idt_set_gate(5, (u64)isr5, selector, flags); + idt_set_gate(6, (u64)isr6, selector, flags); + idt_set_gate(7, (u64)isr7, selector, flags); + idt_set_gate(8, (u64)isr8, selector, flags); + idt_set_gate(9, (u64)isr9, selector, flags); + idt_set_gate(10, (u64)isr10, selector, flags); + idt_set_gate(11, (u64)isr11, selector, flags); + idt_set_gate(12, (u64)isr12, selector, flags); + idt_set_gate(13, (u64)isr13, selector, flags); // General Protection Fault + idt_set_gate(14, (u64)isr14, selector, flags); // Page Fault + idt_set_gate(15, (u64)isr15, selector, flags); + idt_set_gate(16, (u64)isr16, selector, flags); + idt_set_gate(17, (u64)isr17, selector, flags); + idt_set_gate(18, (u64)isr18, selector, flags); + idt_set_gate(19, (u64)isr19, selector, flags); + idt_set_gate(20, (u64)isr20, selector, flags); + idt_set_gate(21, (u64)isr21, selector, flags); + idt_set_gate(22, (u64)isr22, selector, flags); + idt_set_gate(23, (u64)isr23, selector, flags); + idt_set_gate(24, (u64)isr24, selector, flags); + idt_set_gate(25, (u64)isr25, selector, flags); + idt_set_gate(26, (u64)isr26, selector, flags); + idt_set_gate(27, (u64)isr27, selector, flags); + idt_set_gate(28, (u64)isr28, selector, flags); + idt_set_gate(29, (u64)isr29, selector, flags); + idt_set_gate(30, (u64)isr30, selector, flags); + idt_set_gate(31, (u64)isr31, selector, flags); + + __asm__ volatile ("lidt %0" : : "m"(idt_ptr)); +} diff --git a/kernel/src/modules/interrupts.c b/kernel/src/modules/interrupts.c new file mode 100644 index 0000000..b512f4a --- /dev/null +++ b/kernel/src/modules/interrupts.c @@ -0,0 +1,6 @@ +#include "panic.h" +#include "types.h" + +void isr_handler_c(Registers *regs) { + panic(regs); +} \ No newline at end of file diff --git a/kernel/src/modules/panic.c b/kernel/src/modules/panic.c index 49c423d..0562914 100644 --- a/kernel/src/modules/panic.c +++ b/kernel/src/modules/panic.c @@ -1,24 +1,60 @@ #include "panic.h" #include "console.h" -#include "shitgui.h" - -static void hlt_loop() { - while (1) { - __asm__ volatile ("cli; hlt"); - } -} +#include "types.h" -__attribute__((noreturn)) void panic(const char *msg) { +const char* exception_messages[] = { + "Division By Zero", + "Debug", + "Non Maskable Interrupt", + "Breakpoint", + "Into Detected Overflow", + "Out of Bounds", + "Invalid Opcode", + "No Coprocessor", + "Double Fault", + "Coprocessor Segment Overrun", + "Bad TSS", + "Segment Not Present", + "Stack Fault", + "General Protection Fault", + "Page Fault", + "Unknown Interrupt", + "Coprocessor Fault", + "Alignment Check", + "Machine Check", + "Reserved", + "Reserved", + "Reserved", + "Reserved", + "Reserved", + "Reserved", + "Reserved", + "Reserved", + "Reserved", + "Reserved", + "Reserved", + "Reserved", + "Reserved" +}; + +__attribute__((noreturn)) void panic(Registers *regs) { console_clear(0xFF0000); console_set_color(0xFFFFFF); kprintf("\n\n"); - kprintf(" KERNEL PANIC \n"); - kprintf("-------------------\n"); - kprintf(" Reason: %s\n", msg); - kprintf("-------------------\n"); - kprintf(" System halted.\n"); + kprintf("\t\t KERNEL PANIC :( \n"); + kprintf("\t\t-------------------\n"); + kprintf("\t\tCPU EXCEPTION: %d (%s)\n", regs->int_no, exception_messages[regs->int_no]); + kprintf("\t\tError Code: 0x%x\n", regs->err_code); + kprintf("\t\tInstruction Pointer (RIP): 0x%x\n", regs->rip); + kprintf("\t\tCode Segment (CS): 0x%x\n", regs->cs); + kprintf("\t\tFlags (RFLAGS): 0x%x\n", regs->rflags); + kprintf("\t\tStack Pointer (RSP): 0x%x\n", regs->rsp); + kprintf("\t\t-------------------\n"); + kprintf(" \tSystem halted.\n"); - hlt_loop(); + while (1) { + __asm__ volatile ("cli; hlt"); + } } \ No newline at end of file