From e5c4139e498220a2d487e1dbb8ece0319dfedb35 Mon Sep 17 00:00:00 2001 From: DualFroz Date: Mon, 24 Aug 2026 19:45:21 +0200 Subject: [PATCH] feat(cpu): install IDT with exception and syscall gate handling --- include/idt.h | 6 +++++ include/isr.h | 16 +++++++++++ src/idt.c | 48 +++++++++++++++++++++++++++++++++ src/isr.c | 75 +++++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 145 insertions(+) create mode 100644 include/idt.h create mode 100644 include/isr.h create mode 100644 src/idt.c create mode 100644 src/isr.c diff --git a/include/idt.h b/include/idt.h new file mode 100644 index 0000000..a41026d --- /dev/null +++ b/include/idt.h @@ -0,0 +1,6 @@ +#ifndef FROSTBYTE_IDT_H +#define FROSTBYTE_IDT_H + +void idtInit(void); + +#endif diff --git a/include/isr.h b/include/isr.h new file mode 100644 index 0000000..026516f --- /dev/null +++ b/include/isr.h @@ -0,0 +1,16 @@ +#ifndef FROSTBYTE_ISR_H +#define FROSTBYTE_ISR_H + +#include "types.h" + +typedef struct Registers { + uint64 r15, r14, r13, r12, r11, r10, r9, r8; + uint64 rbp, rdi, rsi, rdx, rcx, rbx, rax; + uint64 intNo, errCode; + uint64 rip, cs, rflags, rsp, ss; +} __attribute__((packed)) Registers; + +uint64 isrDispatch(Registers* regs); +uint64 syscallDispatch(Registers* regs); + +#endif diff --git a/src/idt.c b/src/idt.c new file mode 100644 index 0000000..8267c68 --- /dev/null +++ b/src/idt.c @@ -0,0 +1,48 @@ +#include "idt.h" +#include "types.h" + +typedef struct IdtEntry { + uint16 offsetLow; + uint16 selector; + uint8 ist; + uint8 typeAttr; + uint16 offsetMid; + uint32 offsetHigh; + uint32 reserved; +} __attribute__((packed)) IdtEntry; + +typedef struct IdtPointer { + uint16 limit; + uint64 base; +} __attribute__((packed)) IdtPointer; + +static IdtEntry idtEntries[256]; +static IdtPointer idtPointer; + +extern void* isrStubTable[]; +extern void isrStub128(void); + +static void setGate(int vector, void* handler, uint8 typeAttr) +{ + uint64 address = (uint64)handler; + idtEntries[vector].offsetLow = (uint16)(address & 0xFFFF); + idtEntries[vector].selector = 0x08; + idtEntries[vector].ist = 0; + idtEntries[vector].typeAttr = typeAttr; + idtEntries[vector].offsetMid = (uint16)((address >> 16) & 0xFFFF); + idtEntries[vector].offsetHigh = (uint32)((address >> 32) & 0xFFFFFFFF); + idtEntries[vector].reserved = 0; +} + +void idtInit(void) +{ + for (int vector = 0; vector < 48; vector++) + setGate(vector, isrStubTable[vector], 0x8E); + + setGate(0x80, (void*)isrStub128, 0xEE); + + idtPointer.limit = (uint16)(sizeof(idtEntries) - 1); + idtPointer.base = (uint64)&idtEntries; + + __asm__ volatile("lidt %0" : : "m"(idtPointer)); +} diff --git a/src/isr.c b/src/isr.c new file mode 100644 index 0000000..9f83d18 --- /dev/null +++ b/src/isr.c @@ -0,0 +1,75 @@ +#include "isr.h" +#include "console.h" +#include "pic.h" +#include "pit.h" +#include "keyboard.h" +#include "sched.h" +#include "ports.h" + +static const char* exceptionNames[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", + "alignment check", + "machine check", + "simd floating point", + "virtualization", + "control protection", + "reserved", "reserved", "reserved", "reserved", + "reserved", "reserved", "reserved", "reserved", + "hypervisor injection", "vmm communication" +}; + +static void panicOnException(Registers* regs) +{ + uint64 faultAddress = 0; + if (regs->intNo == 14) + __asm__ volatile("mov %%cr2, %0" : "=r"(faultAddress)); + + kprintf("\n[PANIC] exception %lu (%s)\n", regs->intNo, exceptionNames[regs->intNo]); + kprintf(" errCode=%lx rip=%lx cs=%lx rflags=%lx\n", + regs->errCode, regs->rip, regs->cs, regs->rflags); + if (regs->intNo == 14) + kprintf(" cr2=%lx (faulting address)\n", faultAddress); + kprintf(" rax=%lx rbx=%lx rcx=%lx rdx=%lx\n", regs->rax, regs->rbx, regs->rcx, regs->rdx); + kprintf(" system halted\n"); + + for (;;) + __asm__ volatile("cli; hlt"); +} + +uint64 isrDispatch(Registers* regs) +{ + if (regs->intNo < 32) + panicOnException(regs); + + if (regs->intNo == 128) + return syscallDispatch(regs); + + uint8 irq = (uint8)(regs->intNo - 32); + uint64 nextRsp = (uint64)regs; + + if (irq == 0) { + pitTick(); + nextRsp = schedule((uint64)regs); + } else if (irq == 1) { + keyboardHandler(); + } + + picSendEoi(irq); + return nextRsp; +}