forked from PoliEcho-holding-org/kern
Got IDT & ISRs working!
This commit is contained in:
@@ -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
|
||||
@@ -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
|
||||
@@ -0,0 +1,8 @@
|
||||
#ifndef _SYSCALL_H
|
||||
#define _SYSCALL_H
|
||||
|
||||
#include <isr.h>
|
||||
|
||||
int syscallHandler(struct isr_intFrame* iframe) { return 1; }
|
||||
|
||||
#endif
|
||||
@@ -6,6 +6,7 @@
|
||||
void cpuid(uint32_t* eax, uint32_t* ebx, uint32_t* ecx, uint32_t* edx);
|
||||
|
||||
// Ports
|
||||
void iowait(void);
|
||||
uint8_t inb(uint16_t port);
|
||||
void outb(uint16_t port, uint8_t data);
|
||||
uint16_t inw(uint16_t port);
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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
@@ -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");
|
||||
|
||||
@@ -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));
|
||||
|
||||
Reference in New Issue
Block a user