diff --git a/bin/os b/bin/os index 13da876..52b90eb 100755 Binary files a/bin/os and b/bin/os differ diff --git a/bochs.bxrc b/bochs.bxrc new file mode 100644 index 0000000..d431cae --- /dev/null +++ b/bochs.bxrc @@ -0,0 +1,4 @@ +vga: extension=vgahw +ata0-master: type=disk, path="image.hdd", mode=flat +boot: disk +memory: guest=1024, host=1024 diff --git a/bochs.txt b/bochs.txt deleted file mode 100644 index b4d164d..0000000 --- a/bochs.txt +++ /dev/null @@ -1,3 +0,0 @@ -vga: extension=vgahw -display_library: x, options="gui_debug" - diff --git a/flake.lock b/flake.lock deleted file mode 100644 index 48701bd..0000000 --- a/flake.lock +++ /dev/null @@ -1,26 +0,0 @@ -{ - "nodes": { - "nixpkgs": { - "locked": { - "lastModified": 1770057536, - "narHash": "sha256-Y/Dqu+7StqRVlzQEbow5l2Ws02P9IrHO3eVnpVWbLTE=", - "owner": "NixOS", - "repo": "nixpkgs", - "rev": "79faf5ae0424fe8cd1d07064a513667e6b6ae65a", - "type": "github" - }, - "original": { - "owner": "NixOS", - "repo": "nixpkgs", - "type": "github" - } - }, - "root": { - "inputs": { - "nixpkgs": "nixpkgs" - } - } - }, - "root": "root", - "version": 7 -} diff --git a/image.hdd b/image.hdd index 4ceb3f3..1ace025 100644 Binary files a/image.hdd and b/image.hdd differ diff --git a/image.hdd.lock b/image.hdd.lock new file mode 100644 index 0000000..e69de29 diff --git a/obj/src/int.c.o b/obj/src/int.c.o index d33f5b5..b317f52 100644 Binary files a/obj/src/int.c.o and b/obj/src/int.c.o differ diff --git a/obj/src/main.c.d b/obj/src/main.c.d index eb63212..9650bd8 100644 --- a/obj/src/main.c.d +++ b/obj/src/main.c.d @@ -1,6 +1,7 @@ obj/src/main.c.o: src/main.c src/../include/limine.h src/acpi.h \ - src/common.h src/print.h + src/common.h src/alloc.h src/print.h src/../include/limine.h: src/acpi.h: src/common.h: +src/alloc.h: src/print.h: diff --git a/obj/src/main.c.o b/obj/src/main.c.o index c7b2fdb..1f3405b 100644 Binary files a/obj/src/main.c.o and b/obj/src/main.c.o differ diff --git a/src/acpi.c b/src/acpi.c index 9578db8..06a0ffb 100644 --- a/src/acpi.c +++ b/src/acpi.c @@ -1,17 +1,17 @@ -#include "common.h" -#include "print.h" - -#include "../include/limine.h" - -// credit to dreamportdev's OSDev-Notes and the OSDev Wiki for table layouts -// - -#include "acpi.h" -#define RSDT_SIGNATURE "RSDT" -#define XSDT_SIGNATURE "XSDT" - - -static struct acpi_rsdt* rsdt; - -struct acpi_rsdp_header* rsdp; - +#include "common.h" +#include "print.h" + +#include "../include/limine.h" + +// credit to dreamportdev's OSDev-Notes and the OSDev Wiki for table layouts +// + +#include "acpi.h" +#define RSDT_SIGNATURE "RSDT" +#define XSDT_SIGNATURE "XSDT" + + +static struct acpi_rsdt* rsdt; + +struct acpi_rsdp_header* rsdp; + diff --git a/src/acpi.h b/src/acpi.h index 0080d1d..0941e9e 100644 --- a/src/acpi.h +++ b/src/acpi.h @@ -1,44 +1,44 @@ -#pragma once - -#include "common.h" - - -#define RSDP_SIGNATURE "RSDT PTR " - - -pstruct acpi_rsdp_header { - u8 signature[8]; - u8 checksum; - u8 OEMID[6]; - u8 revision; - /* - union { - struct acpi_rsdt* rsdt :32; - struct acpi_xsdt* xsdt :32; - } ptr; - */ - u32 ptr32; - // v2 - u32 len; - u64 ptr64; - u8 extended_checksum; - u8 resv[3]; -}; - -struct acpi_rsdt { - u8 signature[4]; - u32 len; - u8 revision; - u8 checksum; - u8 OEMID[6]; - u8 OEM_table_id[8]; - u32 OEM_revision; - u32 creator_id; - u32 creator_revision; - union { - u32 addrs32[]; - u64 addrs64[]; - }; -}; - -extern struct acpi_rsdp_header* rsdp; +#pragma once + +#include "common.h" + + +#define RSDP_SIGNATURE "RSDT PTR " + + +pstruct acpi_rsdp_header { + u8 signature[8]; + u8 checksum; + u8 OEMID[6]; + u8 revision; + /* + union { + struct acpi_rsdt* rsdt :32; + struct acpi_xsdt* xsdt :32; + } ptr; + */ + u32 ptr32; + // v2 + u32 len; + u64 ptr64; + u8 extended_checksum; + u8 resv[3]; +}; + +struct acpi_rsdt { + u8 signature[4]; + u32 len; + u8 revision; + u8 checksum; + u8 OEMID[6]; + u8 OEM_table_id[8]; + u32 OEM_revision; + u32 creator_id; + u32 creator_revision; + union { + u32 addrs32[]; + u64 addrs64[]; + }; +}; + +extern struct acpi_rsdp_header* rsdp; diff --git a/src/alloc.c b/src/alloc.c new file mode 100644 index 0000000..19fa70c --- /dev/null +++ b/src/alloc.c @@ -0,0 +1,196 @@ +#include "alloc.h" +#include "common.h" +#include "print.h" +#include "../include/limine.h" + + +__attribute__((used, section(".limine_requests"))) +static volatile struct limine_memmap_request mem_req = { + .id = LIMINE_MEMMAP_REQUEST_ID, + .revision = 0, +}; + +extern u32 fg, bg; + +static void print_memmap_entry(struct limine_memmap_entry* entry) { + u32 savefg = fg; + u32 savebg = bg; + static const char* type_strs[] = { + "Usable", + "Reserved", + "ACPI Reclaimable", + "ACPI NVS", + "BAD!!!", + "Bootloader Reclaimable", + "Executable and Modules", + "Framebuffer", + "ACPI Tables", + }; + + static u32 type_colors[] = { + 0x00AF00, + 0xAF1F00, + 0x7f7f00, + 0x7f7f00, + 0xFF0000, + 0x007f7f, + 0x408000, + 0x0000FF, + 0x00FF00 + }; + + bg = type_colors[entry->type]; + fg = ~bg; + + u64 addr = entry->base; + u64 end = addr + entry->length; + print("["); + print(type_strs[entry->type]); + print("]"); + print64(addr); + print(" - "); + print64(end); + print("\n"); + fg = savefg; + bg = savebg; +} + + + +static size_t total_pages; +static u8* alloc_start; +static u8* alloc_end; +static u8* alloc_next; +static u64* alloc_bitmap; + +void alloc_init() { + print("Initializing Page Allocator\n"); + + if(!mem_req.response) { + print("Failed to get memory map :(\n)"); + hang(); + } + + u64 largest_base = 0; + size_t largest_size = 0; + + for(size_t i = 0; i < mem_req.response->entry_count; i++) { + struct limine_memmap_entry* entry = mem_req.response->entries[i]; + print_memmap_entry(entry); + + if(entry->type == LIMINE_MEMMAP_USABLE) { + if(entry->length > largest_size) { + largest_base = entry->base; + largest_size = entry->length; + print("\t\\LARGEST USABLE: "); + print64(entry->length >> 20); + print("MiB\n"); + } + } + } + + if(!largest_size) { + print("Couldn't find a free page!!!\n"); + hang(); + } + + + total_pages = largest_size / PAGE_SIZE; + size_t usage_bitmap_size = (total_pages + 7) / 8; + total_pages -= (usage_bitmap_size + PAGE_SIZE-1) / PAGE_SIZE; + alloc_bitmap = (u64*)(phys_to_virt(largest_base)); + alloc_start = (u8*)(phys_to_virt(largest_base + usage_bitmap_size)); + alloc_next = alloc_start; + alloc_end = (u8*)(phys_to_virt(largest_base + largest_size)); +} + +static size_t page(void* addr) { + return ((u8*)addr - alloc_start) / PAGE_SIZE; +} + +static void* addr(size_t page) { + return alloc_start + page*PAGE_SIZE; +} + +static void usepage(size_t page) { + size_t idx = page / 64; + size_t bit = page & 63; + alloc_bitmap[idx] |= (1 << bit); +} + +static void usepagerange(size_t page, size_t len) { + for(size_t i = 0; i < len; len++) { + usepage(i + page); + } +} + +static void unusepage(size_t page) { + size_t idx = page / 64; + size_t bit = page & 63; + alloc_bitmap[idx] &= ~(1 << bit); +} + +static void unusepagerange(size_t page, size_t len) { + for(size_t i = 0; i < len; len++) { + unusepage(i+page); + } +} + +static u8 getpageusage(size_t page) { + return (alloc_bitmap[page / 8] >> (page & 7)) & 1; +} + +void dealloc(void* addr, size_t size) { + // adjust to page size + size_t pages = (size+PAGE_SIZE-1) / PAGE_SIZE; + unusepagerange(page(addr), pages); +} + +void* alloc(size_t size) { + size_t pages = (size + PAGE_SIZE - 1) / PAGE_SIZE; + size_t page = 0; + + if(pages == 0 || pages >= total_pages) { + return NULL; + } + + size_t consecutive = 0; + + for(size_t i = 0; i < pages; i++) { + u64 word = alloc_bitmap[i]; + if(word == 0) { + if(!consecutive) + page = i * 64; + consecutive += 64; + if(consecutive >= pages) { + usepagerange(page, pages); + return addr(page); + } + continue; + } + + if(word == ~0ULL) { + consecutive = 0; + page = -1; + } + + for(size_t bit = 0; bit < 64; bit++) { + if((word & (1ULL << bit)) == 0) { + if(!consecutive) + page = i * 64 + bit; + + if(++consecutive >= pages) { + usepagerange(page, pages); + return addr(pages); + } + } else { + consecutive = 0; + page = -1; + } + } + } + + + return NULL; +} + diff --git a/src/alloc.h b/src/alloc.h new file mode 100644 index 0000000..29d7a6e --- /dev/null +++ b/src/alloc.h @@ -0,0 +1,16 @@ +#pragma once +#include "common.h" +static const size_t PAGE_SIZE = (1 << 12); + +void alloc_init(); +void* alloc(size_t size); +void dealloc(void* arg, size_t size); + +static inline u64 virt_to_phys(void* virt) { + return (u64)virt - hhdm_offset; +} + +static inline void* phys_to_virt(u64 phys) { + return (void*)(phys + hhdm_offset); +} + diff --git a/src/apic.c b/src/apic.c index 331288a..84562aa 100644 --- a/src/apic.c +++ b/src/apic.c @@ -1,73 +1,131 @@ -#include "common.h" -#include "print.h" - -// stub of a PIC layout, we don't need the whole thing -// as we only care about initializing it to disable it -enum { - PIC_COMM_MASTER = 0x20, - PIC_COMM_SLAVE = 0x21, - PIC_DATA_MASTER = 0xA0, - PIC_DATA_SLAVE = 0xA1, -}; - -static void pic_disable() { - outb(PIC_DATA_MASTER, ~0); - outb(PIC_DATA_SLAVE, ~0); -} - -static inline u64 rdmsr(u32 msr) { - u32 hi, lo; - asm volatile ( - "rdmsr" - : "=a"(lo), "=d"(hi) - : "c"(msr) - ); - - return (((u64)hi) << 32) | (u64)lo; -} - -static inline void wrmsr(u32 msr, u64 val) { - u32 eax = (u32) val; - u32 edx = (u32) (val >> 32); - asm volatile ( - "wrmsr" - : - : "c"(msr), "a" (eax), "d" (edx) - ); -} - - -static u64 apic_base; - -u64 apic_get_local_base() { - const u8 APIC_BASE_MSR = 0x1B; - - u64 msr = rdmsr(APIC_BASE_MSR); - - return (apic_base = (msr & 0xfffff000)); -} - -static u64 apic_set_local_base(u64 base) { - const u8 APIC_BASE_MSR = 0x1B; - - wrmsr(APIC_BASE_MSR, base & 0xfffff000); - - return base & 0xfffff000; -} - -static u32* apic_reg(u32 reg) { - return (u32*) (apic_base + reg); -} - -void apic_enable() { - pic_disable(); - print("\nPIC Disabled\n"); - apic_set_local_base(apic_get_local_base()); - volatile u32* reg = apic_reg(0xF0); - print("Local Base Set\nReg 0xF0 at 0x"); - print64((u64) reg); - // set enable flag - *reg = (*reg | 0x100); - print("\nReg written\n"); -} - +#include "common.h" +#include "print.h" +#include "map.h" + +// stub of a PIC layout, we don't need the whole thing +// as we only care about initializing it to disable it +enum { + PIC_COMM_MASTER = 0x20, + PIC_COMM_SLAVE = 0xA0, + PIC_DATA_MASTER = 0x21, + PIC_DATA_SLAVE = 0xA1, +}; + +#define IOAPIC_REG_REDIR(n) (0x10 + 2(n)) + +enum { + IOAPIC_REG_SELECT = 0x00, + IOAPIC_REG_WINDOW = 0x10, +}; + +// I/O APIC redirection entry bits +#define IOAPIC_DST_PHYS (0 << 11) +#define IOAPIC_DST_LOGICAL (1 << 11) +#define IOAPIC_MASKED (1 << 16) +#define IOAPIC_LVL_TRIGG (1 << 15) +#define IOAPIC_EDGE_TRIGG (0 << 15) +#define IOAPIC_ACTIVE_LOW (1 << 13) +#define IOAPIC_ACTIVE_HIGH (0 << 13) + +static void pic_init() { + // Start initialization sequence + outb(PIC_COMM_MASTER, 0x11); // ICW1: Initialize in cascading mode + outb(PIC_DATA_MASTER, 0x20); // ICW2: Master PIC vector offset + outb(PIC_DATA_MASTER, 0x04); // ICW3: Slave PIC at IRQ2 + outb(PIC_DATA_MASTER, 0x01); // ICW4: 8086/88 (MCS-80 compatible) + + outb(PIC_COMM_SLAVE, 0x11); // ICW1: Initialize slave PIC + outb(PIC_DATA_SLAVE, 0x28); // ICW2: Slave PIC vector offset + outb(PIC_DATA_SLAVE, 0x02); // ICW3: It's connected to master PIC + outb(PIC_DATA_SLAVE, 0x01); // ICW4: 8086/88 mode + + // Mask all interrupts + outb(PIC_DATA_MASTER, 0xFF); + outb(PIC_DATA_SLAVE, 0xFF); +} + +static void pic_disable() { + pic_init(); + outb(PIC_DATA_MASTER, ~0); + outb(PIC_DATA_SLAVE, ~0); +} + +static inline u64 rdmsr(u32 msr) { + u32 hi, lo; + asm volatile ( + "rdmsr" + : "=a"(lo), "=d"(hi) + : "c"(msr) + ); + + return (((u64)hi) << 32) | (u64)lo; +} + +static inline void wrmsr(u32 msr, u64 val) { + u32 eax = (u32) val; + u32 edx = (u32) (val >> 32); + asm volatile ( + "wrmsr" + : + : "c"(msr), "a" (eax), "d" (edx) + ); +} + + +static u64 apic_base; + +u64 apic_get_local_base() { + const u8 APIC_BASE_MSR = 0x1B; + + u64 msr = rdmsr(APIC_BASE_MSR); + + return (apic_base = (msr & 0xfffff000)); +} + +static u64 apic_set_local_base(u64 base) { + const u8 APIC_BASE_MSR = 0x1B; + + wrmsr(APIC_BASE_MSR, base & 0xfffff000); + + return base & 0xfffff000; +} + +static u32* apic_reg(u32 reg) { + return (u32*) (apic_base + reg); +} + +void apic_enable() { + pic_disable(); + print("\nPIC Disabled\n"); + apic_set_local_base(apic_get_local_base()); + + if(!map_mmio((u64)apic_base, 1<<12)) { + print("Failed to map APIC registers!\n"); + hang(); + } + + volatile u32* reg = apic_reg(0xF0); + print("Reg 0xF0 at 0x"); + print64((u64) reg); + // set enable flag + *reg = (*reg | 0x100); + print("\nReg written\n"); +} + +static u32* ioapic_base; + +void ioapic_write(u8 reg, u32 value) { + ioapic_base[IOAPIC_REG_SELECT / 4] = reg; + ioapic_base[IOAPIC_REG_WINDOW / 4] = value; +} + +u32 ioapic_read(u8 reg) { + ioapic_base[IOAPIC_REG_SELECT / 4] = reg; + return ioapic_base[IOAPIC_REG_WINDOW / 4]; +} + + + +void ioapic_init() { + +} diff --git a/src/common.h b/src/common.h index a6c9664..5c8e7d2 100644 --- a/src/common.h +++ b/src/common.h @@ -1,42 +1,42 @@ -#pragma once - -#include -#include -#include - -#define pstruct struct __attribute__((packed)) - -typedef uint8_t u8; -typedef uint16_t u16; -typedef uint32_t u32; -typedef uint64_t u64; -typedef int8_t i8; -typedef int16_t i16; -typedef int32_t i32; -typedef int64_t i64; - -static inline void INT(int n) { - asm volatile ( - "int %0" - : - : "i"(n) - ); -} - -static inline void outb(u16 port, u8 value) { - asm volatile ("outb %0, %1" : : "a"(value), "Nd"(port)); -} -static inline void outw(u16 port, u16 value) { - asm volatile ("outw %0, %1" : : "a"(value), "Nd"(port)); -} -static inline void outd(u16 port, u32 value) { - asm volatile ("outl %0, %1" : : "a"(value), "Nd"(port)); -} - - -void* memcpy(void* restrict dst, const void* src, size_t n); -void* memset(void* s, int c, size_t n); -void* memmove(void* dst, const void* src, size_t n); -int memcmp(const void* s1, const void* s2, size_t n); - -extern u64 hhdm_offset; +#pragma once + +#include +#include +#include + +#define pstruct struct __attribute__((packed)) + +typedef uint8_t u8; +typedef uint16_t u16; +typedef uint32_t u32; +typedef uint64_t u64; +typedef int8_t i8; +typedef int16_t i16; +typedef int32_t i32; +typedef int64_t i64; + +static inline void INT(int n) { + asm volatile ( + "int %0" + : + : "i"(n) + ); +} + +static inline void outb(u16 port, u8 value) { + asm volatile ("outb %0, %1" : : "a"(value), "Nd"(port)); +} +static inline void outw(u16 port, u16 value) { + asm volatile ("outw %0, %1" : : "a"(value), "Nd"(port)); +} +static inline void outd(u16 port, u32 value) { + asm volatile ("outl %0, %1" : : "a"(value), "Nd"(port)); +} + + +void* memcpy(void* dst, const void* src, size_t n); +void* memset(void* s, int c, size_t n); +void* memmove(void* dst, const void* src, size_t n); +int memcmp(const void* s1, const void* s2, size_t n); +void hang(); +extern u64 hhdm_offset; diff --git a/src/int.c b/src/int.c index e76b128..ec7f739 100644 --- a/src/int.c +++ b/src/int.c @@ -1,282 +1,282 @@ -#include - -// for debugging -#include "print.h" - -#include "common.h" - - -// for trap debugging -u64 dbg_var = 0; - -pstruct int_desc { - u16 addr_low; - u16 selector; - u8 ist; - u8 flags; - u16 addr_mid; - u32 addr_high; - u32 resv; -}; - -enum INT_DESC_FLAGS { - ID_GATE_INT = 0b00001110, - ID_GATE_TRAP = 0b00001111, - ID_DPL = 0b00100000, - ID_PRESENT = 0b10000000, -}; - - -#define CODE64_SELECTOR 0x28 - -struct int_desc idt[256]; - -void set_idt(u8 vect, void* handler, u8 dpl) { - struct int_desc* ent = &idt[vect]; - u64 addr = (u64) handler; - ent->addr_low = addr & 0xFFFF; - ent->addr_mid = (addr >> 16) & 0xFFFF; - ent->addr_high = addr >> 32; - - ent->selector = CODE64_SELECTOR; - ent->flags = ID_GATE_INT | dpl*ID_DPL | ID_PRESENT; - ent->ist = 0; -} - -pstruct idtr { - u16 limit; - u64 base; -}; - -#define IDTR_LIMIT (sizeof(struct int_desc)*256 - 1) - -void load_idt(void* addr) { - struct idtr ir = (struct idtr) { - .limit = IDTR_LIMIT, - .base = (u64) addr, - }; - - asm volatile("lidt %0" :: "m"(ir)); -} - -extern void draw(u8 vect); - -struct cpu_ctx { - u64 r15, r14, r13, r12, r11, r10, r9, r8, rdi, rsi, rdx, rcx, rbx, rax; - - u64 vect; - u64 err; - - u64 iret_rip; - u64 iret_cs; - u64 iret_flags; - u64 iret_rsp; - u64 iret_ss; -}; - -struct cpu_ctx* interrupt_dispatch(struct cpu_ctx* ctx) { - print("\n[IRQ "); - print8(ctx->vect); - print("] with message: "); - print64(dbg_var); - print("\n"); - while(1); - return ctx; -} - -__attribute__((naked)) -void int_stub(void) { - __asm__ volatile ( - "push %%rax\n" - "push %%rbx\n" - "push %%rcx\n" - "push %%rdx\n" - "push %%rsi\n" - "push %%rdi\n" - "push %%r8\n" - "push %%r9\n" - "push %%r10\n" - "push %%r11\n" - "push %%r12\n" - "push %%r13\n" - "push %%r14\n" - "push %%r15\n" - "mov %%rsp, %%rdi\n" - "call interrupt_dispatch\n" - "mov %%rax, %%rsp\n" - "pop %%r15\n" - "pop %%r14\n" - "pop %%r13\n" - "pop %%r12\n" - "pop %%r11\n" - "pop %%r10\n" - "pop %%r9\n" - "pop %%r8\n" - "pop %%rdi\n" - "pop %%rsi\n" - "pop %%rdx\n" - "pop %%rcx\n" - "pop %%rbx\n" - "pop %%rax\n" - "add $16, %%rsp\n" - "iretq\n" - : - : - : "memory" - ); -} - -// Macro to generate interrupt stubs without error codes (push dummy 0) -#define ISR_NO_ERR(num) \ - __attribute__((naked)) void isr##num(void) { \ - asm volatile( \ - "push $0\n" \ - "push %0\n" \ - "jmp int_stub\n" \ - : : "i"(num)); \ - } - -// Macro to generate interrupt stubs with error codes -#define ISR_ERR(num) \ - __attribute__((naked)) void isr##num(void) { \ - asm volatile( \ - "push %0\n" \ - "jmp int_stub\n" \ - : : "i"(num)); \ - } - -// CPU exceptions (0-31) -ISR_NO_ERR(0) // Divide by zero -ISR_NO_ERR(1) // Debug -ISR_NO_ERR(2) // NMI -ISR_NO_ERR(3) // Breakpoint -ISR_NO_ERR(4) // Overflow -ISR_NO_ERR(5) // Bound range exceeded -ISR_NO_ERR(6) // Invalid opcode -ISR_NO_ERR(7) // Device not available -ISR_ERR(8) // Double fault (pushes error code) -ISR_NO_ERR(9) // Coprocessor segment overrun -ISR_ERR(10) // Invalid TSS (pushes error code) -ISR_ERR(11) // Segment not present (pushes error code) -ISR_ERR(12) // Stack-segment fault (pushes error code) -ISR_ERR(13) // General protection fault (pushes error code) -ISR_ERR(14) // Page fault (pushes error code) -ISR_NO_ERR(15) // Reserved -ISR_NO_ERR(16) // x87 FPU error -ISR_ERR(17) // Alignment check (pushes error code) -ISR_NO_ERR(18) // Machine check -ISR_NO_ERR(19) // SIMD floating-point exception -ISR_NO_ERR(20) // Virtualization exception -ISR_ERR(21) // Control protection exception (pushes error code) -ISR_NO_ERR(22) // Reserved -ISR_NO_ERR(23) // Reserved -ISR_NO_ERR(24) // Reserved -ISR_NO_ERR(25) // Reserved -ISR_NO_ERR(26) // Reserved -ISR_NO_ERR(27) // Reserved -ISR_NO_ERR(28) // Reserved -ISR_NO_ERR(29) // Reserved -ISR_ERR(30) // Security exception (pushes error code) -ISR_NO_ERR(31) // Reserved - -// IRQs and user-defined interrupts (32-255) -ISR_NO_ERR(32) ISR_NO_ERR(33) ISR_NO_ERR(34) ISR_NO_ERR(35) -ISR_NO_ERR(36) ISR_NO_ERR(37) ISR_NO_ERR(38) ISR_NO_ERR(39) -ISR_NO_ERR(40) ISR_NO_ERR(41) ISR_NO_ERR(42) ISR_NO_ERR(43) -ISR_NO_ERR(44) ISR_NO_ERR(45) ISR_NO_ERR(46) ISR_NO_ERR(47) -ISR_NO_ERR(48) ISR_NO_ERR(49) ISR_NO_ERR(50) ISR_NO_ERR(51) -ISR_NO_ERR(52) ISR_NO_ERR(53) ISR_NO_ERR(54) ISR_NO_ERR(55) -ISR_NO_ERR(56) ISR_NO_ERR(57) ISR_NO_ERR(58) ISR_NO_ERR(59) -ISR_NO_ERR(60) ISR_NO_ERR(61) ISR_NO_ERR(62) ISR_NO_ERR(63) -ISR_NO_ERR(64) ISR_NO_ERR(65) ISR_NO_ERR(66) ISR_NO_ERR(67) -ISR_NO_ERR(68) ISR_NO_ERR(69) ISR_NO_ERR(70) ISR_NO_ERR(71) -ISR_NO_ERR(72) ISR_NO_ERR(73) ISR_NO_ERR(74) ISR_NO_ERR(75) -ISR_NO_ERR(76) ISR_NO_ERR(77) ISR_NO_ERR(78) ISR_NO_ERR(79) -ISR_NO_ERR(80) ISR_NO_ERR(81) ISR_NO_ERR(82) ISR_NO_ERR(83) -ISR_NO_ERR(84) ISR_NO_ERR(85) ISR_NO_ERR(86) ISR_NO_ERR(87) -ISR_NO_ERR(88) ISR_NO_ERR(89) ISR_NO_ERR(90) ISR_NO_ERR(91) -ISR_NO_ERR(92) ISR_NO_ERR(93) ISR_NO_ERR(94) ISR_NO_ERR(95) -ISR_NO_ERR(96) ISR_NO_ERR(97) ISR_NO_ERR(98) ISR_NO_ERR(99) -ISR_NO_ERR(100) ISR_NO_ERR(101) ISR_NO_ERR(102) ISR_NO_ERR(103) -ISR_NO_ERR(104) ISR_NO_ERR(105) ISR_NO_ERR(106) ISR_NO_ERR(107) -ISR_NO_ERR(108) ISR_NO_ERR(109) ISR_NO_ERR(110) ISR_NO_ERR(111) -ISR_NO_ERR(112) ISR_NO_ERR(113) ISR_NO_ERR(114) ISR_NO_ERR(115) -ISR_NO_ERR(116) ISR_NO_ERR(117) ISR_NO_ERR(118) ISR_NO_ERR(119) -ISR_NO_ERR(120) ISR_NO_ERR(121) ISR_NO_ERR(122) ISR_NO_ERR(123) -ISR_NO_ERR(124) ISR_NO_ERR(125) ISR_NO_ERR(126) ISR_NO_ERR(127) -ISR_NO_ERR(128) ISR_NO_ERR(129) ISR_NO_ERR(130) ISR_NO_ERR(131) -ISR_NO_ERR(132) ISR_NO_ERR(133) ISR_NO_ERR(134) ISR_NO_ERR(135) -ISR_NO_ERR(136) ISR_NO_ERR(137) ISR_NO_ERR(138) ISR_NO_ERR(139) -ISR_NO_ERR(140) ISR_NO_ERR(141) ISR_NO_ERR(142) ISR_NO_ERR(143) -ISR_NO_ERR(144) ISR_NO_ERR(145) ISR_NO_ERR(146) ISR_NO_ERR(147) -ISR_NO_ERR(148) ISR_NO_ERR(149) ISR_NO_ERR(150) ISR_NO_ERR(151) -ISR_NO_ERR(152) ISR_NO_ERR(153) ISR_NO_ERR(154) ISR_NO_ERR(155) -ISR_NO_ERR(156) ISR_NO_ERR(157) ISR_NO_ERR(158) ISR_NO_ERR(159) -ISR_NO_ERR(160) ISR_NO_ERR(161) ISR_NO_ERR(162) ISR_NO_ERR(163) -ISR_NO_ERR(164) ISR_NO_ERR(165) ISR_NO_ERR(166) ISR_NO_ERR(167) -ISR_NO_ERR(168) ISR_NO_ERR(169) ISR_NO_ERR(170) ISR_NO_ERR(171) -ISR_NO_ERR(172) ISR_NO_ERR(173) ISR_NO_ERR(174) ISR_NO_ERR(175) -ISR_NO_ERR(176) ISR_NO_ERR(177) ISR_NO_ERR(178) ISR_NO_ERR(179) -ISR_NO_ERR(180) ISR_NO_ERR(181) ISR_NO_ERR(182) ISR_NO_ERR(183) -ISR_NO_ERR(184) ISR_NO_ERR(185) ISR_NO_ERR(186) ISR_NO_ERR(187) -ISR_NO_ERR(188) ISR_NO_ERR(189) ISR_NO_ERR(190) ISR_NO_ERR(191) -ISR_NO_ERR(192) ISR_NO_ERR(193) ISR_NO_ERR(194) ISR_NO_ERR(195) -ISR_NO_ERR(196) ISR_NO_ERR(197) ISR_NO_ERR(198) ISR_NO_ERR(199) -ISR_NO_ERR(200) ISR_NO_ERR(201) ISR_NO_ERR(202) ISR_NO_ERR(203) -ISR_NO_ERR(204) ISR_NO_ERR(205) ISR_NO_ERR(206) ISR_NO_ERR(207) -ISR_NO_ERR(208) ISR_NO_ERR(209) ISR_NO_ERR(210) ISR_NO_ERR(211) -ISR_NO_ERR(212) ISR_NO_ERR(213) ISR_NO_ERR(214) ISR_NO_ERR(215) -ISR_NO_ERR(216) ISR_NO_ERR(217) ISR_NO_ERR(218) ISR_NO_ERR(219) -ISR_NO_ERR(220) ISR_NO_ERR(221) ISR_NO_ERR(222) ISR_NO_ERR(223) -ISR_NO_ERR(224) ISR_NO_ERR(225) ISR_NO_ERR(226) ISR_NO_ERR(227) -ISR_NO_ERR(228) ISR_NO_ERR(229) ISR_NO_ERR(230) ISR_NO_ERR(231) -ISR_NO_ERR(232) ISR_NO_ERR(233) ISR_NO_ERR(234) ISR_NO_ERR(235) -ISR_NO_ERR(236) ISR_NO_ERR(237) ISR_NO_ERR(238) ISR_NO_ERR(239) -ISR_NO_ERR(240) ISR_NO_ERR(241) ISR_NO_ERR(242) ISR_NO_ERR(243) -ISR_NO_ERR(244) ISR_NO_ERR(245) ISR_NO_ERR(246) ISR_NO_ERR(247) -ISR_NO_ERR(248) ISR_NO_ERR(249) ISR_NO_ERR(250) ISR_NO_ERR(251) -ISR_NO_ERR(252) ISR_NO_ERR(253) ISR_NO_ERR(254) ISR_NO_ERR(255) - -// Array of all ISR handlers for easy initialization -void* isr_table[256] = { - isr0, isr1, isr2, isr3, isr4, isr5, isr6, isr7, - isr8, isr9, isr10, isr11, isr12, isr13, isr14, isr15, - isr16, isr17, isr18, isr19, isr20, isr21, isr22, isr23, - isr24, isr25, isr26, isr27, isr28, isr29, isr30, isr31, - isr32, isr33, isr34, isr35, isr36, isr37, isr38, isr39, - isr40, isr41, isr42, isr43, isr44, isr45, isr46, isr47, - isr48, isr49, isr50, isr51, isr52, isr53, isr54, isr55, - isr56, isr57, isr58, isr59, isr60, isr61, isr62, isr63, - isr64, isr65, isr66, isr67, isr68, isr69, isr70, isr71, - isr72, isr73, isr74, isr75, isr76, isr77, isr78, isr79, - isr80, isr81, isr82, isr83, isr84, isr85, isr86, isr87, - isr88, isr89, isr90, isr91, isr92, isr93, isr94, isr95, - isr96, isr97, isr98, isr99, isr100, isr101, isr102, isr103, - isr104, isr105, isr106, isr107, isr108, isr109, isr110, isr111, - isr112, isr113, isr114, isr115, isr116, isr117, isr118, isr119, - isr120, isr121, isr122, isr123, isr124, isr125, isr126, isr127, - isr128, isr129, isr130, isr131, isr132, isr133, isr134, isr135, - isr136, isr137, isr138, isr139, isr140, isr141, isr142, isr143, - isr144, isr145, isr146, isr147, isr148, isr149, isr150, isr151, - isr152, isr153, isr154, isr155, isr156, isr157, isr158, isr159, - isr160, isr161, isr162, isr163, isr164, isr165, isr166, isr167, - isr168, isr169, isr170, isr171, isr172, isr173, isr174, isr175, - isr176, isr177, isr178, isr179, isr180, isr181, isr182, isr183, - isr184, isr185, isr186, isr187, isr188, isr189, isr190, isr191, - isr192, isr193, isr194, isr195, isr196, isr197, isr198, isr199, - isr200, isr201, isr202, isr203, isr204, isr205, isr206, isr207, - isr208, isr209, isr210, isr211, isr212, isr213, isr214, isr215, - isr216, isr217, isr218, isr219, isr220, isr221, isr222, isr223, - isr224, isr225, isr226, isr227, isr228, isr229, isr230, isr231, - isr232, isr233, isr234, isr235, isr236, isr237, isr238, isr239, - isr240, isr241, isr242, isr243, isr244, isr245, isr246, isr247, - isr248, isr249, isr250, isr251, isr252, isr253, isr254, isr255, -}; - -// Initialize all IDT entries -void init_idt(void) { - for (int i = 0; i < 256; i++) { - set_idt(i, isr_table[i], 0); - } - load_idt(idt); -} +#include + +// for debugging +#include "print.h" + +#include "common.h" + + +// for trap debugging +u64 dbg_var = 0; + +pstruct int_desc { + u16 addr_low; + u16 selector; + u8 ist; + u8 flags; + u16 addr_mid; + u32 addr_high; + u32 resv; +}; + +enum INT_DESC_FLAGS { + ID_GATE_INT = 0b00001110, + ID_GATE_TRAP = 0b00001111, + ID_DPL = 0b00100000, + ID_PRESENT = 0b10000000, +}; + + +#define CODE64_SELECTOR 0x28 + +struct int_desc idt[256]; + +void set_idt(u8 vect, void* handler, u8 dpl) { + struct int_desc* ent = &idt[vect]; + u64 addr = (u64) handler; + ent->addr_low = addr & 0xFFFF; + ent->addr_mid = (addr >> 16) & 0xFFFF; + ent->addr_high = addr >> 32; + + ent->selector = CODE64_SELECTOR; + ent->flags = ID_GATE_INT | dpl*ID_DPL | ID_PRESENT; + ent->ist = 0; +} + +pstruct idtr { + u16 limit; + u64 base; +}; + +#define IDTR_LIMIT (sizeof(struct int_desc)*256 - 1) + +void load_idt(void* addr) { + struct idtr ir = (struct idtr) { + .limit = IDTR_LIMIT, + .base = (u64) addr, + }; + + asm volatile("lidt %0" :: "m"(ir)); +} + +extern void draw(u8 vect); + +struct cpu_ctx { + u64 r15, r14, r13, r12, r11, r10, r9, r8, rdi, rsi, rdx, rcx, rbx, rax; + + u64 vect; + u64 err; + + u64 iret_rip; + u64 iret_cs; + u64 iret_flags; + u64 iret_rsp; + u64 iret_ss; +}; + +struct cpu_ctx* interrupt_dispatch(struct cpu_ctx* ctx) { + print("\n[IRQ "); + print8(ctx->vect); + print("] with message: "); + print64(dbg_var); + print("\n"); + while(1); + return ctx; +} + +__attribute__((naked)) +void int_stub(void) { + __asm__ volatile ( + "push %%rax\n" + "push %%rbx\n" + "push %%rcx\n" + "push %%rdx\n" + "push %%rsi\n" + "push %%rdi\n" + "push %%r8\n" + "push %%r9\n" + "push %%r10\n" + "push %%r11\n" + "push %%r12\n" + "push %%r13\n" + "push %%r14\n" + "push %%r15\n" + "mov %%rsp, %%rdi\n" + "call interrupt_dispatch\n" + "mov %%rax, %%rsp\n" + "pop %%r15\n" + "pop %%r14\n" + "pop %%r13\n" + "pop %%r12\n" + "pop %%r11\n" + "pop %%r10\n" + "pop %%r9\n" + "pop %%r8\n" + "pop %%rdi\n" + "pop %%rsi\n" + "pop %%rdx\n" + "pop %%rcx\n" + "pop %%rbx\n" + "pop %%rax\n" + "add $16, %%rsp\n" + "iretq\n" + : + : + : "memory" + ); +} + +// Macro to generate interrupt stubs without error codes (push dummy 0) +#define ISR_NO_ERR(num) \ + __attribute__((naked)) void isr##num(void) { \ + asm volatile( \ + "push $0\n" \ + "push %0\n" \ + "jmp int_stub\n" \ + : : "i"(num)); \ + } + +// Macro to generate interrupt stubs with error codes +#define ISR_ERR(num) \ + __attribute__((naked)) void isr##num(void) { \ + asm volatile( \ + "push %0\n" \ + "jmp int_stub\n" \ + : : "i"(num)); \ + } + +// CPU exceptions (0-31) +ISR_NO_ERR(0) // Divide by zero +ISR_NO_ERR(1) // Debug +ISR_NO_ERR(2) // NMI +ISR_NO_ERR(3) // Breakpoint +ISR_NO_ERR(4) // Overflow +ISR_NO_ERR(5) // Bound range exceeded +ISR_NO_ERR(6) // Invalid opcode +ISR_NO_ERR(7) // Device not available +ISR_ERR(8) // Double fault (pushes error code) +ISR_NO_ERR(9) // Coprocessor segment overrun +ISR_ERR(10) // Invalid TSS (pushes error code) +ISR_ERR(11) // Segment not present (pushes error code) +ISR_ERR(12) // Stack-segment fault (pushes error code) +ISR_ERR(13) // General protection fault (pushes error code) +ISR_ERR(14) // Page fault (pushes error code) +ISR_NO_ERR(15) // Reserved +ISR_NO_ERR(16) // x87 FPU error +ISR_ERR(17) // Alignment check (pushes error code) +ISR_NO_ERR(18) // Machine check +ISR_NO_ERR(19) // SIMD floating-point exception +ISR_NO_ERR(20) // Virtualization exception +ISR_ERR(21) // Control protection exception (pushes error code) +ISR_NO_ERR(22) // Reserved +ISR_NO_ERR(23) // Reserved +ISR_NO_ERR(24) // Reserved +ISR_NO_ERR(25) // Reserved +ISR_NO_ERR(26) // Reserved +ISR_NO_ERR(27) // Reserved +ISR_NO_ERR(28) // Reserved +ISR_NO_ERR(29) // Reserved +ISR_ERR(30) // Security exception (pushes error code) +ISR_NO_ERR(31) // Reserved + +// IRQs and user-defined interrupts (32-255) +ISR_NO_ERR(32) ISR_NO_ERR(33) ISR_NO_ERR(34) ISR_NO_ERR(35) +ISR_NO_ERR(36) ISR_NO_ERR(37) ISR_NO_ERR(38) ISR_NO_ERR(39) +ISR_NO_ERR(40) ISR_NO_ERR(41) ISR_NO_ERR(42) ISR_NO_ERR(43) +ISR_NO_ERR(44) ISR_NO_ERR(45) ISR_NO_ERR(46) ISR_NO_ERR(47) +ISR_NO_ERR(48) ISR_NO_ERR(49) ISR_NO_ERR(50) ISR_NO_ERR(51) +ISR_NO_ERR(52) ISR_NO_ERR(53) ISR_NO_ERR(54) ISR_NO_ERR(55) +ISR_NO_ERR(56) ISR_NO_ERR(57) ISR_NO_ERR(58) ISR_NO_ERR(59) +ISR_NO_ERR(60) ISR_NO_ERR(61) ISR_NO_ERR(62) ISR_NO_ERR(63) +ISR_NO_ERR(64) ISR_NO_ERR(65) ISR_NO_ERR(66) ISR_NO_ERR(67) +ISR_NO_ERR(68) ISR_NO_ERR(69) ISR_NO_ERR(70) ISR_NO_ERR(71) +ISR_NO_ERR(72) ISR_NO_ERR(73) ISR_NO_ERR(74) ISR_NO_ERR(75) +ISR_NO_ERR(76) ISR_NO_ERR(77) ISR_NO_ERR(78) ISR_NO_ERR(79) +ISR_NO_ERR(80) ISR_NO_ERR(81) ISR_NO_ERR(82) ISR_NO_ERR(83) +ISR_NO_ERR(84) ISR_NO_ERR(85) ISR_NO_ERR(86) ISR_NO_ERR(87) +ISR_NO_ERR(88) ISR_NO_ERR(89) ISR_NO_ERR(90) ISR_NO_ERR(91) +ISR_NO_ERR(92) ISR_NO_ERR(93) ISR_NO_ERR(94) ISR_NO_ERR(95) +ISR_NO_ERR(96) ISR_NO_ERR(97) ISR_NO_ERR(98) ISR_NO_ERR(99) +ISR_NO_ERR(100) ISR_NO_ERR(101) ISR_NO_ERR(102) ISR_NO_ERR(103) +ISR_NO_ERR(104) ISR_NO_ERR(105) ISR_NO_ERR(106) ISR_NO_ERR(107) +ISR_NO_ERR(108) ISR_NO_ERR(109) ISR_NO_ERR(110) ISR_NO_ERR(111) +ISR_NO_ERR(112) ISR_NO_ERR(113) ISR_NO_ERR(114) ISR_NO_ERR(115) +ISR_NO_ERR(116) ISR_NO_ERR(117) ISR_NO_ERR(118) ISR_NO_ERR(119) +ISR_NO_ERR(120) ISR_NO_ERR(121) ISR_NO_ERR(122) ISR_NO_ERR(123) +ISR_NO_ERR(124) ISR_NO_ERR(125) ISR_NO_ERR(126) ISR_NO_ERR(127) +ISR_NO_ERR(128) ISR_NO_ERR(129) ISR_NO_ERR(130) ISR_NO_ERR(131) +ISR_NO_ERR(132) ISR_NO_ERR(133) ISR_NO_ERR(134) ISR_NO_ERR(135) +ISR_NO_ERR(136) ISR_NO_ERR(137) ISR_NO_ERR(138) ISR_NO_ERR(139) +ISR_NO_ERR(140) ISR_NO_ERR(141) ISR_NO_ERR(142) ISR_NO_ERR(143) +ISR_NO_ERR(144) ISR_NO_ERR(145) ISR_NO_ERR(146) ISR_NO_ERR(147) +ISR_NO_ERR(148) ISR_NO_ERR(149) ISR_NO_ERR(150) ISR_NO_ERR(151) +ISR_NO_ERR(152) ISR_NO_ERR(153) ISR_NO_ERR(154) ISR_NO_ERR(155) +ISR_NO_ERR(156) ISR_NO_ERR(157) ISR_NO_ERR(158) ISR_NO_ERR(159) +ISR_NO_ERR(160) ISR_NO_ERR(161) ISR_NO_ERR(162) ISR_NO_ERR(163) +ISR_NO_ERR(164) ISR_NO_ERR(165) ISR_NO_ERR(166) ISR_NO_ERR(167) +ISR_NO_ERR(168) ISR_NO_ERR(169) ISR_NO_ERR(170) ISR_NO_ERR(171) +ISR_NO_ERR(172) ISR_NO_ERR(173) ISR_NO_ERR(174) ISR_NO_ERR(175) +ISR_NO_ERR(176) ISR_NO_ERR(177) ISR_NO_ERR(178) ISR_NO_ERR(179) +ISR_NO_ERR(180) ISR_NO_ERR(181) ISR_NO_ERR(182) ISR_NO_ERR(183) +ISR_NO_ERR(184) ISR_NO_ERR(185) ISR_NO_ERR(186) ISR_NO_ERR(187) +ISR_NO_ERR(188) ISR_NO_ERR(189) ISR_NO_ERR(190) ISR_NO_ERR(191) +ISR_NO_ERR(192) ISR_NO_ERR(193) ISR_NO_ERR(194) ISR_NO_ERR(195) +ISR_NO_ERR(196) ISR_NO_ERR(197) ISR_NO_ERR(198) ISR_NO_ERR(199) +ISR_NO_ERR(200) ISR_NO_ERR(201) ISR_NO_ERR(202) ISR_NO_ERR(203) +ISR_NO_ERR(204) ISR_NO_ERR(205) ISR_NO_ERR(206) ISR_NO_ERR(207) +ISR_NO_ERR(208) ISR_NO_ERR(209) ISR_NO_ERR(210) ISR_NO_ERR(211) +ISR_NO_ERR(212) ISR_NO_ERR(213) ISR_NO_ERR(214) ISR_NO_ERR(215) +ISR_NO_ERR(216) ISR_NO_ERR(217) ISR_NO_ERR(218) ISR_NO_ERR(219) +ISR_NO_ERR(220) ISR_NO_ERR(221) ISR_NO_ERR(222) ISR_NO_ERR(223) +ISR_NO_ERR(224) ISR_NO_ERR(225) ISR_NO_ERR(226) ISR_NO_ERR(227) +ISR_NO_ERR(228) ISR_NO_ERR(229) ISR_NO_ERR(230) ISR_NO_ERR(231) +ISR_NO_ERR(232) ISR_NO_ERR(233) ISR_NO_ERR(234) ISR_NO_ERR(235) +ISR_NO_ERR(236) ISR_NO_ERR(237) ISR_NO_ERR(238) ISR_NO_ERR(239) +ISR_NO_ERR(240) ISR_NO_ERR(241) ISR_NO_ERR(242) ISR_NO_ERR(243) +ISR_NO_ERR(244) ISR_NO_ERR(245) ISR_NO_ERR(246) ISR_NO_ERR(247) +ISR_NO_ERR(248) ISR_NO_ERR(249) ISR_NO_ERR(250) ISR_NO_ERR(251) +ISR_NO_ERR(252) ISR_NO_ERR(253) ISR_NO_ERR(254) ISR_NO_ERR(255) + +// Array of all ISR handlers for easy initialization +void* isr_table[256] = { + isr0, isr1, isr2, isr3, isr4, isr5, isr6, isr7, + isr8, isr9, isr10, isr11, isr12, isr13, isr14, isr15, + isr16, isr17, isr18, isr19, isr20, isr21, isr22, isr23, + isr24, isr25, isr26, isr27, isr28, isr29, isr30, isr31, + isr32, isr33, isr34, isr35, isr36, isr37, isr38, isr39, + isr40, isr41, isr42, isr43, isr44, isr45, isr46, isr47, + isr48, isr49, isr50, isr51, isr52, isr53, isr54, isr55, + isr56, isr57, isr58, isr59, isr60, isr61, isr62, isr63, + isr64, isr65, isr66, isr67, isr68, isr69, isr70, isr71, + isr72, isr73, isr74, isr75, isr76, isr77, isr78, isr79, + isr80, isr81, isr82, isr83, isr84, isr85, isr86, isr87, + isr88, isr89, isr90, isr91, isr92, isr93, isr94, isr95, + isr96, isr97, isr98, isr99, isr100, isr101, isr102, isr103, + isr104, isr105, isr106, isr107, isr108, isr109, isr110, isr111, + isr112, isr113, isr114, isr115, isr116, isr117, isr118, isr119, + isr120, isr121, isr122, isr123, isr124, isr125, isr126, isr127, + isr128, isr129, isr130, isr131, isr132, isr133, isr134, isr135, + isr136, isr137, isr138, isr139, isr140, isr141, isr142, isr143, + isr144, isr145, isr146, isr147, isr148, isr149, isr150, isr151, + isr152, isr153, isr154, isr155, isr156, isr157, isr158, isr159, + isr160, isr161, isr162, isr163, isr164, isr165, isr166, isr167, + isr168, isr169, isr170, isr171, isr172, isr173, isr174, isr175, + isr176, isr177, isr178, isr179, isr180, isr181, isr182, isr183, + isr184, isr185, isr186, isr187, isr188, isr189, isr190, isr191, + isr192, isr193, isr194, isr195, isr196, isr197, isr198, isr199, + isr200, isr201, isr202, isr203, isr204, isr205, isr206, isr207, + isr208, isr209, isr210, isr211, isr212, isr213, isr214, isr215, + isr216, isr217, isr218, isr219, isr220, isr221, isr222, isr223, + isr224, isr225, isr226, isr227, isr228, isr229, isr230, isr231, + isr232, isr233, isr234, isr235, isr236, isr237, isr238, isr239, + isr240, isr241, isr242, isr243, isr244, isr245, isr246, isr247, + isr248, isr249, isr250, isr251, isr252, isr253, isr254, isr255, +}; + +// Initialize all IDT entries +void init_idt(void) { + for (int i = 0; i < 256; i++) { + set_idt(i, isr_table[i], 0); + } + load_idt(idt); +} diff --git a/src/main.c b/src/main.c index bc6174a..1d5fb09 100644 --- a/src/main.c +++ b/src/main.c @@ -1,246 +1,196 @@ -#include -#include -#include - -#include "../include/limine.h" - -#include "acpi.h" -#include "common.h" -#include "print.h" - -// credit owed to https://wiki.osdev.org/Limine_Bare_Bones for the limine setup code - -__attribute__((used, section(".limine_requests"))) -static volatile u64 limine_base_revision[] = LIMINE_BASE_REVISION(4); - -__attribute__((used, section(".limine_requests"))) -static volatile struct limine_framebuffer_request fb_req = { - .id = LIMINE_FRAMEBUFFER_REQUEST_ID, - .revision = 0 -}; - - -__attribute__((used, section(".limine_requests"))) -static volatile struct limine_memmap_request mem_req = { - .id = LIMINE_MEMMAP_REQUEST_ID, - .revision = 0, -}; - -__attribute__((used, section(".limine_requests"))) -static volatile struct limine_hhdm_request hhdm_req = { - .id = LIMINE_HHDM_REQUEST_ID, - .revision = 0 -}; - -__attribute__((used, section(".limine_requests"))) -static volatile struct limine_rsdp_request rsdp_req = { - .id = LIMINE_RSDP_REQUEST_ID, - .revision = 0 -}; - -u64 hhdm_offset; - -__attribute__((used, section(".limine_requests_start"))) -static volatile u64 limine_requests_start_marker[] = LIMINE_REQUESTS_START_MARKER; - -__attribute__((used, section(".limine_requests_end"))) -static volatile u64 limine_requests_end_marker[] = LIMINE_REQUESTS_END_MARKER; - -void* memcpy(void* restrict dst, const void* src, size_t n) { - u8* restrict pdst = (u8* restrict)dst; - const u8* restrict psrc = (const u8* restrict)src; - - for(size_t i = 0; i < n; i++) { - pdst[i] = psrc[i]; - } - - return dst; -} - -void* memset(void* s, int c, size_t n) { - u8* p = (u8*) s; - - for(size_t i = 0; i < n; i++) { - p[i] = (u8)c; - } - - return s; -} - -void* memmove(void* dst, const void* src, size_t n) { - u8* restrict pdst = (u8* restrict)dst; - const u8* restrict psrc = (const u8* restrict)src; - - if(src > dst) { - for(size_t i = 0; i < n; i++) { - pdst[i] = psrc[i]; - } - } else if(src < dst) { - for(size_t i = n; i > 0; i--) { - pdst[i-1] = psrc[i-1]; - } - } - - return dst; -} - -int memcmp(const void* s1, const void* s2, size_t n) { - const u8* p1 = (const u8* )s1; - const u8* p2 = (const u8* )s2; - - for(size_t i = 0; i < n; i++) { - if(p1[i] != p2[i]) { - return p1[i] < p2[i] ? -1 : 1; - } - } - - return 0; -} - -static void hang() { - for(;;) { - asm ("hlt"); - } -} - - -struct limine_framebuffer* fb; - -void draw(u8 vect) { - for(size_t y = 0; y < fb->height; y++) { - for(size_t x = 0; x < fb->width; x++) { - volatile u32* fb_ptr = fb->address; - fb_ptr[y * fb->width + x] = ( - (x + y) * 0x00010000 | - (x ^ y) * 0x00000100 | - (x - y) * 0x00000001 - )*vect; - } - } -} - -extern void init_idt(void); - -extern u32 fg; -extern u32 bg; -void print_memmap_entry(struct limine_memmap_entry* entry) { - u32 savefg = fg; - u32 savebg = bg; - static const char* type_strs[] = { - "Usable", - "Reserved", - "ACPI Reclaimable", - "ACPI NVS", - "BAD!!!", - "Bootloader Reclaimable", - "Executable and Modules", - "Framebuffer", - "ACPI Tables", - }; - - static u32 type_colors[] = { - 0x00AF00, - 0xAF1F00, - 0x7f7f00, - 0x7f7f00, - 0xFF0000, - 0x007f7f, - 0x408000, - 0x0000FF, - 0x00FF00 - }; - - bg = type_colors[entry->type]; - fg = ~bg; - - u64 addr = entry->base; - u64 end = addr + entry->length; - print("["); - print(type_strs[entry->type]); - print("]"); - print64(addr); - print(" - "); - print64(end); - print("\n"); - fg = savefg; - bg = savebg; -} - - - -u32 apic_get_local_base(); -void apic_enable(); - -void kmain() { - if(LIMINE_BASE_REVISION_SUPPORTED(limine_base_revision) == false) { - hang(); - } - - if(fb_req.response == NULL || fb_req.response->framebuffer_count < 1) { - hang(); - } - - fb = fb_req.response->framebuffers[0]; - - print_init(fb); - init_idt(); - - if(!mem_req.response) { - print("Failed to get memory map :(\n)"); - hang(); - } - - if(!hhdm_req.response) { - print("Failed to get higher half direct mapping\n."); - hang(); - } - - hhdm_offset = hhdm_req.response->offset; - - if(!rsdp_req.response) { - print ("Failed to find rsdp\n."); - hang(); - } - - rsdp = (struct acpi_rsdp_header*)(rsdp_req.response->address); - - for(size_t i = 0; i < mem_req.response->entry_count; i++) { - print_memmap_entry(mem_req.response->entries[i]); - } - - print("Found RSDP @ 0x"); - print64((u64)rsdp); - put('\n'); - - print("With signature: "); - printn((char*)rsdp->signature, sizeof(rsdp->signature)); - - print(" v"); - print8(rsdp->revision); - print("\nRSDT at 0x"); - struct acpi_rsdt* rsdt = - (struct acpi_rsdt*)( - (rsdp->revision? rsdp->ptr64:rsdp->ptr32) + hhdm_offset - ); - print64((u64)rsdt); - print("\nSDT Signature: "); - - - printn((const char*) rsdt->signature, sizeof(rsdt->signature)); - print("\nAPIC Local Base: "); - - /* I should check cpuid to ensure its supported but it will - * be for my machines ;^) */ - /* APIC stuff */ - u32 r = 0xDEADBEEF; - r = apic_get_local_base(); - print32(r); - - apic_enable(); - - print("\nAPIC Enabled"); - - hang(); - -} - +#include +#include +#include + +#include "../include/limine.h" + +#include "acpi.h" +#include "alloc.h" +#include "common.h" +#include "print.h" + +// credit owed to https://wiki.osdev.org/Limine_Bare_Bones for the limine setup code + +__attribute__((used, section(".limine_requests"))) +static volatile u64 limine_base_revision[] = LIMINE_BASE_REVISION(4); + +__attribute__((used, section(".limine_requests"))) +static volatile struct limine_framebuffer_request fb_req = { + .id = LIMINE_FRAMEBUFFER_REQUEST_ID, + .revision = 0 +}; + + +__attribute__((used, section(".limine_requests"))) +static volatile struct limine_hhdm_request hhdm_req = { + .id = LIMINE_HHDM_REQUEST_ID, + .revision = 0 +}; + +__attribute__((used, section(".limine_requests"))) +static volatile struct limine_rsdp_request rsdp_req = { + .id = LIMINE_RSDP_REQUEST_ID, + .revision = 0 +}; + +u64 hhdm_offset; + +__attribute__((used, section(".limine_requests_start"))) +static volatile u64 limine_requests_start_marker[] = LIMINE_REQUESTS_START_MARKER; + +__attribute__((used, section(".limine_requests_end"))) +static volatile u64 limine_requests_end_marker[] = LIMINE_REQUESTS_END_MARKER; + +void* memcpy(void* restrict dst, const void* src, size_t n) { + u8* restrict pdst = (u8* restrict)dst; + const u8* restrict psrc = (const u8* restrict)src; + + for(size_t i = 0; i < n; i++) { + pdst[i] = psrc[i]; + } + + return dst; +} + +void* memset(void* s, int c, size_t n) { + u8* p = (u8*) s; + + for(size_t i = 0; i < n; i++) { + p[i] = (u8)c; + } + + return s; +} + +void* memmove(void* dst, const void* src, size_t n) { + u8* restrict pdst = (u8* restrict)dst; + const u8* restrict psrc = (const u8* restrict)src; + + if(src > dst) { + for(size_t i = 0; i < n; i++) { + pdst[i] = psrc[i]; + } + } else if(src < dst) { + for(size_t i = n; i > 0; i--) { + pdst[i-1] = psrc[i-1]; + } + } + + return dst; +} + +int memcmp(const void* s1, const void* s2, size_t n) { + const u8* p1 = (const u8* )s1; + const u8* p2 = (const u8* )s2; + + for(size_t i = 0; i < n; i++) { + if(p1[i] != p2[i]) { + return p1[i] < p2[i] ? -1 : 1; + } + } + + return 0; +} + +void hang() { + for(;;) { + asm ("hlt"); + } +} + + +struct limine_framebuffer* fb; + +void draw(u8 vect) { + for(size_t y = 0; y < fb->height; y++) { + for(size_t x = 0; x < fb->width; x++) { + volatile u32* fb_ptr = fb->address; + fb_ptr[y * fb->width + x] = ( + (x + y) * 0x00010000 | + (x ^ y) * 0x00000100 | + (x - y) * 0x00000001 + )*vect; + } + } +} + +extern void init_idt(void); + +extern u32 fg; +extern u32 bg; + + + +u32 apic_get_local_base(); +void apic_enable(); +void setup_identity_mapping(); + +void kmain() { + if(LIMINE_BASE_REVISION_SUPPORTED(limine_base_revision) == false) { + hang(); + } + + if(fb_req.response == NULL || fb_req.response->framebuffer_count < 1) { + hang(); + } + + fb = fb_req.response->framebuffers[0]; + + print_init(fb); + init_idt(); + + + + if(!hhdm_req.response) { + print("Failed to get higher half direct mapping\n."); + hang(); + } + + hhdm_offset = hhdm_req.response->offset; + + if(!rsdp_req.response) { + print ("Failed to find rsdp\n."); + hang(); + } + + alloc_init(); + + rsdp = (struct acpi_rsdp_header*)(rsdp_req.response->address); + + + print("Found RSDP @ 0x"); + print64((u64)rsdp); + put('\n'); + + print("With signature: "); + printn((char*)rsdp->signature, sizeof(rsdp->signature)); + + print(" v"); + print8(rsdp->revision); + print("\nRSDT at 0x"); + struct acpi_rsdt* rsdt = + (struct acpi_rsdt*)( + (rsdp->revision? rsdp->ptr64:rsdp->ptr32) + hhdm_offset + ); + print64((u64)rsdt); + print("\nSDT Signature: "); + + + printn((const char*) rsdt->signature, sizeof(rsdt->signature)); + print("\nAPIC Local Base: "); + + /* I should check cpuid to ensure its supported but it will + * be for my machines ;^) */ + /* APIC stuff */ + u32 r = 0xDEADBEEF; + r = apic_get_local_base(); + print32(r); + + apic_enable(); + + print("\nAPIC Enabled"); + + hang(); + +} + diff --git a/src/map.c b/src/map.c new file mode 100644 index 0000000..b8a28de --- /dev/null +++ b/src/map.c @@ -0,0 +1,388 @@ +#include "alloc.h" +#include "common.h" +#include "print.h" + +// MMIO (Memory-Mapped I/O) Mapping for ACPI and other hardware registers +// +// CRITICAL: MMIO regions are NOT regular RAM! +// - They're not in Limine's memory map as "usable" +// - They're often above the RAM limit +// - Limine does NOT map them automatically +// - You must manually map them before accessing + +// Page table entry structure +struct page_entry { + u64 present : 1; + u64 writable : 1; + u64 user : 1; + u64 write_through : 1; + u64 cache_disabled : 1; // IMPORTANT for MMIO! + u64 accessed : 1; + u64 dirty : 1; + u64 huge_page : 1; + u64 global : 1; + u64 unused : 3; + u64 frame : 40; + u64 reserved : 11; + u64 no_execute : 1; +}; + +extern u64 hhdm_offset; + + +// Get current page tables +static u64 get_cr3() { + u64 cr3; + asm volatile("mov %%cr3, %0" : "=r"(cr3)); + return cr3 & ~0xFFF; +} + +static u64 alloc_page_table() { + void* a = alloc((1<<12) / PAGE_SIZE); + return a? virt_to_phys(a) : 0; +} + +// Get or create a page table entry at any level +static struct page_entry* get_or_create_table(struct page_entry *table, u64 index) { + if (!table[index].present) { + u64 new_table_phys = alloc_page_table(); + if (new_table_phys == 0) { + return NULL; + } + + table[index].present = 1; + table[index].writable = 1; + table[index].user = 0; + table[index].frame = new_table_phys >> 12; + } + + u64 next_table_phys = (u64)table[index].frame << 12; + return (struct page_entry*)phys_to_virt(next_table_phys); +} + +// Map a MMIO page with proper cache settings +// physical_addr: Physical address of MMIO region +// size: Size in bytes (will be rounded up to 4KB pages) +// Returns: Virtual address to access the MMIO region +void* map_mmio(u64 physical_addr, u64 size) { + print("Mapping MMIO region:\n"); + print(" Physical: 0x"); + print64(physical_addr); + print("\n Size: 0x"); + print64(size); + print(" ("); + print64(size); + print(" bytes)\n"); + + // Align physical address down to page boundary + u64 phys_base = physical_addr & ~(PAGE_SIZE-1); + u64 offset_in_page = physical_addr & (PAGE_SIZE-1); + + // Calculate number of pages needed + u64 total_size = size + offset_in_page; + u64 num_pages = (total_size + PAGE_SIZE - 1) / PAGE_SIZE; + + print(" Aligned physical: 0x"); + print64(phys_base); + print("\n Offset in page: 0x"); + print64(offset_in_page); + print("\n Pages needed: "); + print64(num_pages); + print("\n"); + + // For MMIO, we typically map to the HHDM region + // Virtual address = Physical address + HHDM offset + u64 virt_base = phys_base + hhdm_offset; + + print(" Target virtual: 0x"); + print64(virt_base); + print("\n"); + + // Get current page tables + u64 pml4_phys = get_cr3(); + struct page_entry *pml4 = (struct page_entry*)phys_to_virt(pml4_phys); + + // Map each page + for (u64 i = 0; i < num_pages; i++) { + u64 current_phys = phys_base + (i * PAGE_SIZE); + u64 current_virt = virt_base + (i * PAGE_SIZE); + + // Extract indices + u64 pml4_index = (current_virt >> 39) & 0x1FF; + u64 pdpt_index = (current_virt >> 30) & 0x1FF; + u64 pd_index = (current_virt >> 21) & 0x1FF; + u64 pt_index = (current_virt >> 12) & 0x1FF; + + // Walk/create page table hierarchy + struct page_entry *pdpt = get_or_create_table(pml4, pml4_index); + if (!pdpt) { + print("ERROR: Failed to get/create PDPT\n"); + return NULL; + } + + struct page_entry *pd = get_or_create_table(pdpt, pdpt_index); + if (!pd) { + print("ERROR: Failed to get/create PD\n"); + return NULL; + } + + struct page_entry *pt = get_or_create_table(pd, pd_index); + if (!pt) { + print("ERROR: Failed to get/create PT\n"); + return NULL; + } + + // Map the page with MMIO-appropriate settings + pt[pt_index].present = 1; + pt[pt_index].writable = 1; + pt[pt_index].user = 0; + pt[pt_index].cache_disabled = 1; // CRITICAL: Disable caching for MMIO! + pt[pt_index].write_through = 0; + pt[pt_index].no_execute = 1; // Don't execute from MMIO + pt[pt_index].frame = current_phys >> 12; + + // Flush TLB for this page + asm volatile("invlpg (%0)" :: "r"(current_virt) : "memory"); + } + + print(" MMIO mapped successfully!\n"); + print(" Access at virtual: 0x"); + print64(virt_base + offset_in_page); + print("\n\n"); + + // Return virtual address (with original offset) + return (void*)(virt_base + offset_in_page); +} + +// Unmap MMIO region +void unmap_mmio(void *virtual_addr, u64 size) { + u64 virt_base = (u64)virtual_addr & ~0xFFF; + u64 num_pages = (size + ((u64)virtual_addr & 0xFFF) + 0xFFF) / 4096; + + u64 pml4_phys = get_cr3(); + struct page_entry *pml4 = (struct page_entry*)phys_to_virt(pml4_phys); + + for (u64 i = 0; i < num_pages; i++) { + u64 current_virt = virt_base + (i * 4096); + + u64 pml4_index = (current_virt >> 39) & 0x1FF; + u64 pdpt_index = (current_virt >> 30) & 0x1FF; + u64 pd_index = (current_virt >> 21) & 0x1FF; + u64 pt_index = (current_virt >> 12) & 0x1FF; + + if (!pml4[pml4_index].present) continue; + struct page_entry *pdpt = phys_to_virt((u64)pml4[pml4_index].frame << 12); + + if (!pdpt[pdpt_index].present) continue; + struct page_entry *pd = phys_to_virt((u64)pdpt[pdpt_index].frame << 12); + + if (!pd[pd_index].present) continue; + struct page_entry *pt = phys_to_virt((u64)pd[pd_index].frame << 12); + + if (!pt[pt_index].present) continue; + + // Clear the entry + *((u64*)&pt[pt_index]) = 0; + + // Flush TLB + asm volatile("invlpg (%0)" :: "r"(current_virt) : "memory"); + } +} + +// Check if a physical address is already mapped +int is_mapped(u64 physical_addr) { + u64 virtual_addr = physical_addr + hhdm_offset; + + u64 pml4_phys = get_cr3(); + struct page_entry *pml4 = phys_to_virt(pml4_phys); + + u64 pml4_index = (virtual_addr >> 39) & 0x1FF; + u64 pdpt_index = (virtual_addr >> 30) & 0x1FF; + u64 pd_index = (virtual_addr >> 21) & 0x1FF; + u64 pt_index = (virtual_addr >> 12) & 0x1FF; + + if (!pml4[pml4_index].present) return 0; + struct page_entry *pdpt = phys_to_virt((u64)pml4[pml4_index].frame << 12); + + if (!pdpt[pdpt_index].present) return 0; + + // Check for 1GB huge page + if (pdpt[pdpt_index].huge_page) return 1; + + struct page_entry *pd = phys_to_virt((u64)pdpt[pdpt_index].frame << 12); + + if (!pd[pd_index].present) return 0; + + // Check for 2MB huge page + if (pd[pd_index].huge_page) return 1; + + struct page_entry *pt = phys_to_virt((u64)pd[pd_index].frame << 12); + + return pt[pt_index].present; +} + + +// Read from ACPI register (8-bit) +u8 acpi_read8(void *mmio_base, u64 offset) { + volatile u8 *addr = (volatile u8*)((u64)mmio_base + offset); + return *addr; +} + +// Read from ACPI register (16-bit) +u16 acpi_read16(void *mmio_base, u64 offset) { + volatile u16 *addr = (volatile u16*)((u64)mmio_base + offset); + return *addr; +} + +// Read from ACPI register (32-bit) +u32 acpi_read32(void *mmio_base, u64 offset) { + volatile u32 *addr = (volatile u32*)((u64)mmio_base + offset); + return *addr; +} + +// Read from ACPI register (64-bit) +u64 acpi_read64(void *mmio_base, u64 offset) { + volatile u64 *addr = (volatile u64*)((u64)mmio_base + offset); + return *addr; +} + +// Write to ACPI register (8-bit) +void acpi_write8(void *mmio_base, u64 offset, u8 value) { + volatile u8 *addr = (volatile u8*)((u64)mmio_base + offset); + *addr = value; +} + +// Write to ACPI register (16-bit) +void acpi_write16(void *mmio_base, u64 offset, u16 value) { + volatile u16 *addr = (volatile u16*)((u64)mmio_base + offset); + *addr = value; +} + +// Write to ACPI register (32-bit) +void acpi_write32(void *mmio_base, u64 offset, u32 value) { + volatile u32 *addr = (volatile u32*)((u64)mmio_base + offset); + *addr = value; +} + +// Write to ACPI register (64-bit) +void acpi_write64(void *mmio_base, u64 offset, u64 value) { + volatile u64 *addr = (volatile u64*)((u64)mmio_base + offset); + *addr = value; +} + +// Example: Map and access ACPI PM1a Control Block +void* map_acpi_pm1a_control(u64 physical_addr) { + print("Mapping ACPI PM1a Control Block...\n"); + + // PM1a Control is typically 2 bytes, but map at least one page + void *mmio = map_mmio(physical_addr, 4096); + + if (mmio) { + print("PM1a Control Block mapped at virtual: 0x"); + print64((u64)mmio); + print("\n"); + } + + return mmio; +} + +// Example: Map ACPI tables (FADT, MADT, etc.) +void* map_acpi_table(u64 physical_addr, u64 size) { + print("Mapping ACPI table...\n"); + print(" Physical: 0x"); + print64(physical_addr); + print("\n Size: "); + print64(size); + print(" bytes\n"); + + void *table = map_mmio(physical_addr, size); + + if (table) { + print("ACPI table mapped at virtual: 0x"); + print64((u64)table); + print("\n"); + } + + return table; +} + + +void print_page_mapping(u64 virtual_addr) { + print("Page mapping for virtual 0x"); + print64(virtual_addr); + print(":\n"); + + u64 pml4_phys = get_cr3(); + struct page_entry *pml4 = phys_to_virt(pml4_phys); + + u64 pml4_index = (virtual_addr >> 39) & 0x1FF; + u64 pdpt_index = (virtual_addr >> 30) & 0x1FF; + u64 pd_index = (virtual_addr >> 21) & 0x1FF; + u64 pt_index = (virtual_addr >> 12) & 0x1FF; + + print(" Indices: PML4["); + print64(pml4_index); + print("] PDPT["); + print64(pdpt_index); + print("] PD["); + print64(pd_index); + print("] PT["); + print64(pt_index); + print("]\n"); + + if (!pml4[pml4_index].present) { + print(" PML4 entry not present!\n"); + return; + } + print(" PML4 entry present, frame=0x"); + print64((u64)pml4[pml4_index].frame << 12); + print("\n"); + + struct page_entry *pdpt = phys_to_virt((u64)pml4[pml4_index].frame << 12); + + if (!pdpt[pdpt_index].present) { + print(" PDPT entry not present!\n"); + return; + } + print(" PDPT entry present, frame=0x"); + print64((u64)pdpt[pdpt_index].frame << 12); + print("\n"); + + if (pdpt[pdpt_index].huge_page) { + print(" 1GB huge page!\n"); + return; + } + + struct page_entry *pd = phys_to_virt((u64)pdpt[pdpt_index].frame << 12); + + if (!pd[pd_index].present) { + print(" PD entry not present!\n"); + return; + } + print(" PD entry present, frame=0x"); + print64((u64)pd[pd_index].frame << 12); + print("\n"); + + if (pd[pd_index].huge_page) { + print(" 2MB huge page!\n"); + return; + } + + struct page_entry *pt = phys_to_virt((u64)pd[pd_index].frame << 12); + + if (!pt[pt_index].present) { + print(" PT entry not present!\n"); + return; + } + + print(" PT entry present:\n"); + print(" Physical frame: 0x"); + print64((u64)pt[pt_index].frame << 12); + print("\n Writable: "); + print64(pt[pt_index].writable); + print("\n Cache disabled: "); + print64(pt[pt_index].cache_disabled); + print("\n No execute: "); + print64(pt[pt_index].no_execute); + print("\n"); +} diff --git a/src/map.h b/src/map.h new file mode 100644 index 0000000..4ce0ccd --- /dev/null +++ b/src/map.h @@ -0,0 +1,6 @@ +#pragma once + +#include "common.h" + +void* map_mmio(u64, u64); +