Got IDT & ISRs working!

This commit is contained in:
2025-03-21 14:09:15 +01:00
parent 05c8ee8f67
commit c3f8d7d8f2
9 changed files with 322 additions and 2 deletions
+27
View File
@@ -0,0 +1,27 @@
#ifndef _IDT_H
#define _IDT_H
#include <kernel.h>
#define IDT_ENTRIES 256
#define IDT_FLAG_TRAP 0x8f // P = 1, Priv = 00, S = 0, Type = 1111 (32-bit trap)
#define IDT_FLAG_INT 0x8e // P = 1, Priv = 00, S = 0, Type = 1110 (32-bit int)
#define IDT_FLAG_USER 0xee // P = 1, Priv = 11, S = 0, Type = 1110 (32-bit int)
struct idt_entry {
uint16_t offsetLow;
uint16_t selector;
uint8_t __unused;
uint8_t flags;
uint16_t offsetHigh;
} __packed;
struct idt_pointer {
uint16_t limit;
uint32_t base;
} __packed;
int idt_init(void);
void idt_setGate(uint8_t i, void* handler, uint8_t flags);
#endif
+26
View File
@@ -0,0 +1,26 @@
#ifndef _ISR_H
#define _ISR_H
#include <kernel.h>
// Interrupt frame (ie. what's on the stack on interrupt)
struct isr_intFrame {
// Pushed by OS
uint32_t esp, ebx, ecx, edx, esi, edi, ebp;
uint32_t ds, es, fs, gs, eax;
uint32_t interrupt, error;
// Pushed by CPU
uint32_t eip, cs, eflags, user_esp, user_ss;
};
typedef void (*isr_handlerPtr)(struct isr_intFrame* iframe);
int isr_init(void);
void isr_registerIRQ(uint8_t i, isr_handlerPtr handler);
int isr_handleInterrupt(struct isr_intFrame iframe);
// Assembly definitions (isr.s)
extern void* isr_redirectTable[48]; // ISR Table
extern void isr128(); // int 0x80 - syscall
#endif
+8
View File
@@ -0,0 +1,8 @@
#ifndef _SYSCALL_H
#define _SYSCALL_H
#include <isr.h>
int syscallHandler(struct isr_intFrame* iframe) { return 1; }
#endif
+2 -1
View File
@@ -6,7 +6,8 @@
void cpuid(uint32_t* eax, uint32_t* ebx, uint32_t* ecx, uint32_t* edx);
// Ports
uint8_t inb(uint16_t port);
void iowait(void);
uint8_t inb(uint16_t port);
void outb(uint16_t port, uint8_t data);
uint16_t inw(uint16_t port);
void outw(uint16_t port, uint16_t data);
+28
View File
@@ -0,0 +1,28 @@
#include <kernel.h>
#include <string.h>
#include <gdt.h>
#include <idt.h>
__align(16) // performace :fire:
static struct idt_entry idt[IDT_ENTRIES];
static struct idt_pointer idtp;
void idt_setGate(uint8_t i, void* handler, uint8_t flags) {
uint32_t offset = (uint32_t)handler;
struct idt_entry* entry = &idt[i];
entry->offsetLow = (uint16_t)offset;
entry->selector = GDT_KERNEL_CODE;
entry->flags = flags;
entry->offsetHigh = (uint16_t)(offset >> 16);
}
int idt_init(void) {
memset(&idt, 0, sizeof(idt));
idtp.limit = sizeof(idt);
idtp.base = (uint32_t)&idt;
__asm__ volatile ("lidt %0" : : "m"(idtp));
return 0;
}
+105
View File
@@ -0,0 +1,105 @@
#include <syscall.h>
#include <kernel.h>
#include <string.h>
#include <system.h>
#include <idt.h>
#include <isr.h>
isr_handlerPtr irqHandlers[16];
const char* exceptions[] = {
"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"
};
// I have no clue how this works or what it does, but it doesn't work without it
void isr_remapPIC(void) {
outb(0x20, 0x11); iowait();
outb(0xa0, 0x11); iowait();
outb(0x21, 0x20); iowait();
outb(0xa1, 0x28); iowait();
outb(0x21, 0x04); iowait();
outb(0xa1, 0x02); iowait();
outb(0x21, 0x01); iowait();
outb(0xa1, 0x01); iowait();
outb(0x21, 0x00); iowait();
outb(0xa1, 0x00); iowait();
}
int isr_init(void) {
idt_init();
isr_remapPIC();
for (int i = 0; i < 48; i++) {
// First 32 IRSs are exceptions (traps) and the next 16 are hardware interrupts
idt_setGate(i, isr_redirectTable[i], (i < 32) ? IDT_FLAG_TRAP : IDT_FLAG_INT);
}
// System call (should be callable from userspace)
idt_setGate(0x80, (void*)(uint32_t)isr128, IDT_FLAG_USER);
// Let interrupts interrupt
__asm__ volatile ("sti");
return 0;
}
void isr_registerIRQ(uint8_t i, isr_handlerPtr handler) {
irqHandlers[i] = handler;
}
void isr_sendEOI(uint8_t irq) {
if (irq >= 8) {
outb(0xa0, 0x20);
}
outb(0x20, 0x20);
}
int isr_handleInterrupt(struct isr_intFrame iframe) {
if (iframe.interrupt < 32) {
// ISRs 0-31 - Exceptions
panic(exceptions[iframe.interrupt]);
} else if (iframe.interrupt >= 32 && iframe.interrupt < 48) {
// ISRs 32-47 - Hardware interrupts
uint8_t irq = iframe.interrupt - 32;
if (irqHandlers[irq]) {
irqHandlers[irq](&iframe);
isr_sendEOI(irq);
}
} else if (iframe.interrupt == 128) {
// ISR 128 - System call
return syscallHandler(&iframe);
}
return 0;
}
+119
View File
@@ -0,0 +1,119 @@
; ISR Assembly
[bits 32]
isr_common:
;; Push registers to the intFrame_t struct
push eax
push gs
push fs
push es
push ds
push ebp
push edi
push esi
push edx
push ecx
push ebx
push esp
[extern isr_handleInterrupt]
call isr_handleInterrupt
isr_return:
add esp, 4 ; Keep ESP
pop ebx
pop ecx
pop edx
pop esi
pop edi
pop ebp
pop ds
pop es
pop fs
pop gs
add esp, 4 ; Keep EAX
add esp, 8 ; Pop interupt number and error code
iretd ; Pop CS, EIP & EFLAGS (Also SS & ESP if it's from userspace)
%macro ISR_WITH_ERRNO 1
isr%1:
push dword %1
jmp isr_common
%endmacro
%macro ISR_WITHOUT_ERRNO 1
isr%1:
push dword 0 ; Instead of error code
push dword %1
jmp isr_common
%endmacro
;; Exceptions
ISR_WITHOUT_ERRNO 0
ISR_WITHOUT_ERRNO 1
ISR_WITHOUT_ERRNO 2
ISR_WITHOUT_ERRNO 3
ISR_WITHOUT_ERRNO 4
ISR_WITHOUT_ERRNO 5
ISR_WITHOUT_ERRNO 6
ISR_WITHOUT_ERRNO 7
ISR_WITH_ERRNO 8
ISR_WITHOUT_ERRNO 9
ISR_WITH_ERRNO 10
ISR_WITH_ERRNO 11
ISR_WITH_ERRNO 12
ISR_WITH_ERRNO 13
ISR_WITH_ERRNO 14
ISR_WITHOUT_ERRNO 15
ISR_WITHOUT_ERRNO 16
ISR_WITHOUT_ERRNO 17
ISR_WITHOUT_ERRNO 18
ISR_WITHOUT_ERRNO 19
ISR_WITHOUT_ERRNO 20
ISR_WITHOUT_ERRNO 21
ISR_WITHOUT_ERRNO 22
ISR_WITHOUT_ERRNO 23
ISR_WITHOUT_ERRNO 24
ISR_WITHOUT_ERRNO 25
ISR_WITHOUT_ERRNO 26
ISR_WITHOUT_ERRNO 27
ISR_WITHOUT_ERRNO 28
ISR_WITHOUT_ERRNO 29
ISR_WITHOUT_ERRNO 30
ISR_WITHOUT_ERRNO 31
;; IRQs 0-15 (mapped 32-47)
ISR_WITHOUT_ERRNO 32
ISR_WITHOUT_ERRNO 33
ISR_WITHOUT_ERRNO 34
ISR_WITHOUT_ERRNO 35
ISR_WITHOUT_ERRNO 36
ISR_WITHOUT_ERRNO 37
ISR_WITHOUT_ERRNO 38
ISR_WITHOUT_ERRNO 39
ISR_WITHOUT_ERRNO 40
ISR_WITHOUT_ERRNO 41
ISR_WITHOUT_ERRNO 42
ISR_WITHOUT_ERRNO 43
ISR_WITHOUT_ERRNO 44
ISR_WITHOUT_ERRNO 45
ISR_WITHOUT_ERRNO 46
ISR_WITHOUT_ERRNO 47
;; Syscall ISR128
[global isr128]
isr128:
cli ; Prevent race condition & other issues
push dword 0
push dword 128
jmp isr_common
;; Create table of ISRs
[global isr_redirectTable]
isr_redirectTable:
%assign i 0
%rep 48
dd isr%+i
%assign i i+1
%endrep
+2 -1
View File
@@ -2,6 +2,7 @@
#include <kernel.h>
#include <serial.h>
#include <gdt.h>
#include <isr.h>
#include <tty.h>
// TODO: Commented out stuff
@@ -25,7 +26,7 @@ void kmain(void* ptr, uint32_t magic) {
// vmm_init();
gdt_init();
// isr_init();
isr_init();
// pag_init();
debugf("Basic initialization complete!\n");
+5
View File
@@ -1,4 +1,5 @@
#include <kernel.h>
#include <system.h>
void cpuid(uint32_t* eax, uint32_t* ebx, uint32_t* ecx, uint32_t* edx) {
__asm__ volatile ("cpuid"
@@ -7,6 +8,10 @@ void cpuid(uint32_t* eax, uint32_t* ebx, uint32_t* ecx, uint32_t* edx) {
: "memory");
}
void iowait(void) {
outb(0x80, 0);
}
uint8_t inb(uint16_t port) {
uint8_t r;
__asm__ volatile ("inb %1, %0" : "=a"(r) : "dN"(port));