Major interrupt change

This commit is contained in:
2024-10-23 14:11:22 +02:00
parent 11feab5014
commit f163659f0c
38 changed files with 498 additions and 468 deletions
-48
View File
@@ -1,48 +0,0 @@
#include <interrupt/exceptions.h>
#include <interrupt/idt.h>
#include <stdio.h>
// Exception handlers
__attribute__ ((interrupt))
void excp_divideErr(intFrame_t* iframe) { // ISR 0
printf("\x1b[1M[ Division Error ]\n\x1b[8M");
iframe->eip++;
}
__attribute__ ((interrupt))
void excp_doubleFault(intFrame_t* iframe, uint32_t errCode) { // ISR 8
printf("\x1b[1M[ Double Fault ]\n\x1b[8M"); // Error code should be 0 (TODO: Maybe check if it's != 0?)
__asm__ volatile ("cli; hlt");
}
__attribute__ ((interrupt))
void excp_pageFault(intFrame_t* iframe, uint32_t errCode) { // ISR 14
uint32_t badAddress = 0;
// cr2 should contain invalid address
__asm__ volatile("movl %%cr2, %0" : "=r"(badAddress));
printf("\x1b[1M[ Page Fault : 0x%x ] - Tried to access 0x%x.\n\x1b[8M", errCode, badAddress);
__asm__ volatile ("cli; hlt");
}
__attribute__ ((interrupt))
void excp_reserved(intFrame_t* iframe) { // ISR 15
print("\x1b[1M[ Unknown Exception ]\n\x1b[8M");
__asm__ volatile ("cli; hlt");
}
// TODO: Add more (because there's always more)
// Repetative isr definitions
void setupExceptions() {
for (uint8_t i = 0; i < 32; i++) {
idtSetGate(i, excp_reserved, TRAP_GATE_FLAGS); // Doesn't account for err codes, will just halt anyways
}
idtSetGate(0, excp_divideErr, TRAP_GATE_FLAGS);
idtSetGate(8, excp_doubleFault, TRAP_GATE_FLAGS);
idtSetGate(14, excp_pageFault, TRAP_GATE_FLAGS);
idtSetGate(15, excp_reserved, TRAP_GATE_FLAGS);
}
+3 -1
View File
@@ -1,8 +1,10 @@
#include <interrupt/idt.h>
#include <stdint.h>
#define IDT_ENTRIES 256
__attribute__ ((aligned(0x10))) // For performance
idtEntry_t idt[256] = { 0 };
idtEntry_t idt[IDT_ENTRIES] = { 0 };
idtp_t idtp;
void idtSetGate(uint8_t i, void* handler, uint8_t flags) {
+103
View File
@@ -0,0 +1,103 @@
#include <interrupt/isr.h>
#include <interrupt/idt.h>
#include <syscalls/syscalls.h>
#include <error/panic.h>
#include <error/debug.h>
#include <ports/io.h>
const char* format = "\x1b[31mPanic: %s!\n";
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"
};
void remapPic() {
outb(0x20, 0x11);
outb(0xa0, 0x11);
outb(0x21, 0x20);
outb(0xa1, 0x28);
outb(0x21, 0x04);
outb(0xa1, 0x02);
outb(0x21, 0x01);
outb(0xa1, 0x01);
outb(0x21, 0x00);
outb(0xa1, 0x00);
}
HandlerPtr irqHandlers[16] = { 0 }; // IRQ 0-15
void setupIsrs() {
setupIdt();
remapPic(); // Remap IRQs 0-15 -> 32-48
for (int i = 0; i < 48; i++) {
idtSetGate(i, asm_isrRedirectTable[i], TRAP_GATE_FLAGS);
}
// System call
idtSetGate(0x80, isr128, USR_INT_GATE_FLAGS);
__asm__ volatile ("sti");
}
void registerIrq(uint8_t id, HandlerPtr handler) {
irqHandlers[id] = handler;
}
void sendPicEOI(uint8_t irq) {
if (irq >= 8) {
outb(0xA0, 0x20); // PIC2 Command
}
outb(0x20, 0x20); // PIC1 Command
}
int handleInterrupt(intFrame_t iframe) {
if (iframe.interrupt < 32) {
// ISRs 0-31 - Exceptions
debugf(format, exceptions[iframe.interrupt]);
panic();
} 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);
sendPicEOI(irq);
}
} else if (iframe.interrupt == 128) {
// ISR 128 - System call
return syscallHandler(&iframe);
}
return 0;
}
+116
View File
@@ -0,0 +1,116 @@
; ISR Assembly
[bits 32]
isrCommon:
;; 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 handleInterrupt]
call handleInterrupt
isrReturn:
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 isrCommon
%endmacro
%macro ISR_WITHOUT_ERRNO 1
isr%1:
push dword 0 ; Instead of error code
push dword %1
jmp isrCommon
%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]
ISR_WITHOUT_ERRNO 128
;; Create table of ISRs
[global asm_isrRedirectTable]
asm_isrRedirectTable:
%assign i 0
%rep 48
dd isr%+i
%assign i i+1
%endrep
-79
View File
@@ -1,79 +0,0 @@
#include <interrupt/pic.h>
#include <ports/io.h>
#include <stdint.h>
void sendPicEOI(uint8_t irq) {
if (irq >= 8) {
outb(PIC_2_CMD, PIC_EOI);
}
outb(PIC_1_CMD, PIC_EOI);
}
void disableIrqs() {
outb(PIC_2_DATA, PIC_DISABLE);
outb(PIC_1_DATA, PIC_DISABLE);
}
void setIrqMask(uint8_t irq) {
uint16_t port;
uint8_t value;
if (irq < 8) {
port = PIC_1_DATA;
} else {
irq -= 8;
port = PIC_2_DATA;
}
value = inb(port) | (1 << irq);
outb(port, value);
}
void unsetIrqMask(uint8_t irq) {
uint16_t port;
uint8_t value;
if (irq < 8) {
port = PIC_1_DATA;
} else {
irq -= 8;
port = PIC_2_DATA;
}
value = inb(port) & ~(1 << irq);
outb(port, value);
}
void remapPic() {
uint8_t pic1Mask = inb(PIC_1_DATA);
uint8_t pic2Mask = inb(PIC_2_DATA);
// Send Init Control Word 1-4 to both PICs
// ICW 1: bit 0 - send up to 4 ICWs, bit 4 - Init PIC
outb(PIC_1_CMD, 0x11);
ioWait(); // For slower machines
outb(PIC_2_CMD, 0x11);
ioWait();
// ICW 2: Where to map IRW bases in IDT
outb(PIC_1_DATA, NEW_IRQ_0);
ioWait();
outb(PIC_2_DATA, NEW_IRQ_8);
ioWait();
// ICW 3: Which IRQ in PIC1 is PIC2; Mapping PIC2 to IRQ 2
outb(PIC_1_DATA, 0x04);
ioWait();
outb(PIC_2_DATA, 0x02);
ioWait();
// ICW 4 - Set x86 mode
outb(PIC_1_DATA, 0x01);
ioWait();
outb(PIC_2_DATA, 0x01);
ioWait();
outb(PIC_1_DATA, pic1Mask);
outb(PIC_2_DATA, pic2Mask);
}
+3 -13
View File
@@ -1,23 +1,19 @@
#include <interrupt/pit.h>
#include <interrupt/idt.h>
#include <interrupt/pic.h>
#include <interrupt/isr.h>
#include <tty/tty.h>
#include <memory/addresses.h>
#include <ports/io.h>
#include <stdint.h>
__attribute__ ((interrupt))
void timerHandler(intFrame_t* iframe) {
void timerHandler(intFrame_t*) {
static uint32_t cursorTicks = 0;
cursorTicks++;
if (!terminal->hideCursor) { // TODO: Make a better cursor drawing thing
if (!console->hideCursor) { // TODO: Make a better cursor drawing thing
if (cursorTicks % 500 == 0) toggleCursor();
}
if (*(uint32_t*)SLEEP_TIMER > 0) { --(*(uint32_t*)SLEEP_TIMER); }
sendPicEOI(0);
}
void setPitPhase(uint8_t channel, uint8_t opMode, uint16_t hz) {
@@ -35,9 +31,3 @@ void setPitPhase(uint8_t channel, uint8_t opMode, uint16_t hz) {
__asm__ volatile ("sti");
}
void setupTimer() { // Sets up IRQ 0 - PIT
idtSetGate(0x20, timerHandler, INT_GATE_FLAGS);
unsetIrqMask(0);
setPitPhase(0, 2, 1000); // Default setup: 1000Hz - 1 tick per 1ms
}
+3 -11
View File
@@ -1,6 +1,5 @@
#include <interrupt/rtc.h>
#include <interrupt/pic.h>
#include <interrupt/idt.h>
#include <interrupt/isr.h>
#include <screen/text.h>
#include <screen/gfxmode.h>
#include <tty/tty.h>
@@ -36,7 +35,7 @@ void disableRtc() {
__asm__ volatile ("sti");
}
__attribute__ ((interrupt)) void rtcHandler(intFrame_t* iframe) {
void rtcHandler(intFrame_t* iframe) {
datetime_t newDatetime, oldDatetime;
static uint16_t rtcTicks = 0;
@@ -121,20 +120,13 @@ __attribute__ ((interrupt)) void rtcHandler(intFrame_t* iframe) {
uint32_t x = gfxMode->xRes - len - 1;
char* str = &buf[0];
for (uint8_t i = 0; i != len; i++, x++) {
drawChar(str[i], x, 0, terminal->fg, terminal->bg);
drawChar(str[i], x, 0, console->fg, console->bg);
}
}
}
getRtcRegister(0x0c);
sendPicEOI(8);
__asm__ volatile ("sti");
}
void setupRtc() { // IRQ 8 - Real Time Clock
idtSetGate(0x28, rtcHandler, INT_GATE_FLAGS);
unsetIrqMask(8);
enableRtc();
}
-194
View File
@@ -1,194 +0,0 @@
#include <interrupt/syscalls.h>
#include <interrupt/idt.h>
#include <tty/tty.h>
#include <keyboard/keyboard.h>
#include <memory/malloc.h>
#include <memory/addresses.h>
#include <memory/physical.h>
#include <fs/fs.h>
#include <fs/impl.h>
#include <stdio.h>
#include <syscall.h>
#include <stdint.h>
#include <stdlib.h>
/*
* XXX WARNING - Update MAX_SYSCALLS in the handler XXX
*/
int sys_reserved(sys_regs_t) {
printf("\e[1N\e[6M Illegal use of Reserved() system call! \e[8M\e[8N\n");
return -1;
}
// Args: ebx - number of miliseconds
int sys_sleep(sys_regs_t regs) {
uint32_t* sleepTimerTicks = (uint32_t*)SLEEP_TIMER;
*sleepTimerTicks = regs.ebx;
while (*sleepTimerTicks > 0) { // Wait...
__asm__ volatile ("sti;hlt;cli;");
}
return 0;
}
// Args: ebx - int fd
// ecx - void* buf
// edx - uint32_t len
// Rets: Number of bytes written
int sys_write(sys_regs_t regs) {
int32_t fd = regs.ebx;
void* buf = (void*)regs.ecx;
uint32_t len = regs.edx;
// TODO: Open fd table?
if (fd == 1) {
return terminalWrite(buf, len); // Call a terminal print function
} else { return -1; }
}
// TODO: Use a Read() sycall and read from stdin
// Args: ebx - char* buffer
int sys_read(sys_regs_t regs) {
char* s = (char*)regs.ebx;
reads(s);
return 0;
}
// Args: ebx - size_t count
// Rets: Pointer to malloc-ed memory
int sys_malloc(sys_regs_t regs) {
uint32_t count = regs.ebx;
// First Malloc()
if (!mallocListHead) {
mallocInit(count); // Setup malloc linked list
}
void* ptr = mallocNextNode(count);
mallocMergeFree();
return (uint32_t)ptr;
}
// Args: ebx - void* ptr
int sys_free(sys_regs_t regs) {
void* ptr = (void*)regs.ebx;
mallocFree(ptr);
return 0;
}
// Args: ebx - path,
// ecx - oflag
// Rets: Opened file descriptor
int sys_open(sys_regs_t regs) {
int fd = 0;
char* path = (char*)regs.ebx;
uint32_t oflag = regs.ecx;
// TODO: better file finding
inode_t* root = (inode_t*)impl_superblock->rootInodePtr;
loadFile(root, (void*)SCRATCH_BLOCK_LOC);
inode_t* inode = getInode(path, (dirEntry_t*)SCRATCH_BLOCK_LOC);
if (inode == NULL) {
return -1;
}
// TODO: check if max open files have'nt been reached
fd = fsInfo->openFiles++;
FILE* fp = fsInfo->openFileTable + fd;
fp->_ptr = (void*)0xd000;
fp->_offset = 0;
fp->_size = inode->sizeBytes;
fp->_flag = oflag;
fp->_file = fd;
loadFile(inode, fp->_ptr);
return fd;
}
// Args: ebx - int fd
// Rets: status
int sys_close(sys_regs_t regs) {
int fd = regs.ebx;
FILE* fp = fsInfo->openFileTable + fd;
free(fp->_ptr);
fsInfo->openFiles--;
return 0;
}
// TODO
int sys_seek(sys_regs_t regs) { return -1; }
// System call table
int (*syscalls[MAX_SYSCALLS])(sys_regs_t) = {
[SYS_RESERVED] = sys_reserved,
[SYS_SLEEP] = sys_sleep,
[SYS_WRITE] = sys_write,
[SYS_READ] = sys_read,
[SYS_MALLOC] = sys_malloc,
[SYS_FREE] = sys_free,
[SYS_OPEN] = sys_open,
[SYS_CLOSE] = sys_close,
[SYS_SEEK] = sys_seek,
};
// int 0x80 - Syscall interrupt, handled by this function
// eax : Syscall number
__attribute__ ((naked)) // No prologue or epilogue, just assembly
void syscallHandler(intFrame_t* iframe) {
// Interrupt - Stack should contain: ss, esp, eflags, cs, eip
// We should also push these regs: ax, gs, fs, es, ds, bp, di, si, dx, cx, bx
__asm__ volatile (
".intel_syntax noprefix\n" // We use intel syntax
".equ MAX_SYSCALLS, 9\n" // Define MAX_SYSCALLS again TODO: I don't want to have to do this
// Check if syscall exists
"cmp eax, MAX_SYSCALLS - 1\n"
"ja invalidSyscall\n"
// Call the syscall
"push eax\n"
"push gs\n"
"push fs\n"
"push es\n"
"push ds\n"
"push ebp\n"
"push edi\n"
"push esi\n"
"push edx\n"
"push ecx\n"
"push ebx\n"
"push esp\n" // Push stack pointer again (for variables and such idk)
"call [syscalls + eax * 4]\n" // Call syscall from table. Syscall number should be in eax
"add esp, 4\n" // Do not override ESP
"pop ebx\n"
"pop ecx\n"
"add esp, 4\n" // Do not override EDX, some syscalls use it
"pop esi\n"
"pop edi\n"
"pop ebp\n"
"pop ds\n"
"pop es\n"
"pop fs\n"
"pop gs\n"
"add esp, 4\n" // Save eax value
"iretd\n" // Return from interrupt (32 bit)
// TODO: Send an error or something here
"invalidSyscall:\n"
"mov eax, -1\n" // Current error thing
"iretd\n"
".att_syntax" // Switch back to AT&T Syntax (Just in case)
);
}