mirror of
https://github.com/Tom-on64/kern.git
synced 2026-11-03 18:22:22 +00:00
Include file restructure!
- include/ now has subdirs - standard C headers will be in 'include/c'. Any program can include these - all other header shall only be used by the kernel
This commit is contained in:
@@ -0,0 +1,185 @@
|
||||
#ifndef ISRS_H
|
||||
#define ISRS_H
|
||||
|
||||
#include <interrupt/idt.h>
|
||||
#include <screen/text.h>
|
||||
|
||||
// Exception handlers
|
||||
__attribute__ ((interrupt))
|
||||
void excp_divideErr(intFrame_t* iframe) { // ISR 0
|
||||
fgColor = RED;
|
||||
print("[ Division Error ]\n");
|
||||
__asm__ volatile ("cli; hlt"); // Halt system
|
||||
}
|
||||
|
||||
__attribute__ ((interrupt))
|
||||
void excp_debugErr(intFrame_t* iframe) { // ISR 1
|
||||
fgColor = RED;
|
||||
print("[ Debug Exception ]\n");
|
||||
__asm__ volatile ("cli; hlt");
|
||||
}
|
||||
|
||||
__attribute__ ((interrupt))
|
||||
void excp_nmiInterrupt(intFrame_t* iframe) { // ISR 2
|
||||
fgColor = RED;
|
||||
print("[ Non-maskable Interrupt ]\n");
|
||||
__asm__ volatile ("cli; hlt");
|
||||
}
|
||||
|
||||
__attribute__ ((interrupt))
|
||||
void excp_breakpoint(intFrame_t* iframe) { // ISR 3
|
||||
fgColor = RED;
|
||||
print("[ Breakpoint ]\n");
|
||||
__asm__ volatile ("cli; hlt");
|
||||
}
|
||||
|
||||
__attribute__ ((interrupt))
|
||||
void excp_overflow(intFrame_t* iframe) { // ISR 4
|
||||
fgColor = RED;
|
||||
print("[ Overflow Error ]\n");
|
||||
__asm__ volatile ("cli; hlt");
|
||||
}
|
||||
|
||||
__attribute__ ((interrupt))
|
||||
void excp_boundRangeExceed(intFrame_t* iframe) { // ISR 5
|
||||
fgColor = RED;
|
||||
print("[ Bound Range Exceeded ]\n");
|
||||
__asm__ volatile ("cli; hlt");
|
||||
}
|
||||
|
||||
__attribute__ ((interrupt))
|
||||
void excp_invalidOpcode(intFrame_t* iframe) { // ISR 6
|
||||
fgColor = RED;
|
||||
print("[ Invalid OpCode ]\n");
|
||||
__asm__ volatile ("cli; hlt");
|
||||
}
|
||||
|
||||
__attribute__ ((interrupt))
|
||||
void excp_deviceNA(intFrame_t* iframe) { // ISR 7
|
||||
fgColor = RED;
|
||||
print("[ Device Not Available ]\n");
|
||||
__asm__ volatile ("cli; hlt");
|
||||
}
|
||||
|
||||
__attribute__ ((interrupt))
|
||||
void excp_doubleFault(intFrame_t* iframe, uint32_t errCode) { // ISR 8
|
||||
fgColor = RED;
|
||||
print("[ Double Fault : 0x");
|
||||
print(itoa(errCode, 16));
|
||||
print(" ]\n");
|
||||
__asm__ volatile ("cli; hlt");
|
||||
}
|
||||
|
||||
__attribute__ ((interrupt))
|
||||
void excp_coprocOverrun(intFrame_t* iframe) { // ISR 9
|
||||
fgColor = RED;
|
||||
print("[ Coprocessor Segment Overrun ]\n");
|
||||
__asm__ volatile ("cli; hlt");
|
||||
}
|
||||
|
||||
__attribute__ ((interrupt))
|
||||
void excp_invalidTss(intFrame_t* iframe, uint32_t errCode) { // ISR 10
|
||||
fgColor = RED;
|
||||
print("[ Invalid TSS : 0x");
|
||||
print(itoa(errCode, 16));
|
||||
print(" ]\n");
|
||||
__asm__ volatile ("cli; hlt");
|
||||
}
|
||||
|
||||
__attribute__ ((interrupt))
|
||||
void excp_noSegment(intFrame_t* iframe, uint32_t errCode) { // ISR 11
|
||||
fgColor = RED;
|
||||
print("[ Segment Not Present : 0x");
|
||||
print(itoa(errCode, 16));
|
||||
print(" ]\n");
|
||||
__asm__ volatile ("cli; hlt");
|
||||
}
|
||||
|
||||
__attribute__ ((interrupt))
|
||||
void excp_stackSegmentFault(intFrame_t* iframe, uint32_t errCode) { // ISR 12
|
||||
fgColor = RED;
|
||||
print("[ Stack-Segment Fault : 0x");
|
||||
print(itoa(errCode, 16));
|
||||
print(" ]\n");
|
||||
__asm__ volatile ("cli; hlt");
|
||||
}
|
||||
|
||||
__attribute__ ((interrupt))
|
||||
void excp_generalProtectionFault(intFrame_t* iframe, uint32_t errCode) { // ISR 13
|
||||
fgColor = RED;
|
||||
print("[ General Protection Fault : 0x");
|
||||
print(itoa(errCode, 16));
|
||||
print(" ]\n");
|
||||
__asm__ volatile ("cli; hlt");
|
||||
}
|
||||
|
||||
__attribute__ ((interrupt))
|
||||
void excp_pageFault(intFrame_t* iframe, uint32_t errCode) { // ISR 14
|
||||
fgColor = RED;
|
||||
print("[ Page Fault : 0x");
|
||||
print(itoa(errCode, 16));
|
||||
print(" ]\n");
|
||||
__asm__ volatile ("cli; hlt");
|
||||
}
|
||||
|
||||
__attribute__ ((interrupt))
|
||||
void excp_reserved(intFrame_t* iframe) { // ISR 15
|
||||
fgColor = RED;
|
||||
print("[ Reserved Exception ]\n"); // Shouldn't get this one
|
||||
__asm__ volatile ("cli; hlt");
|
||||
}
|
||||
|
||||
__attribute__ ((interrupt))
|
||||
void excp_floatingPointErr(intFrame_t* iframe) { // ISR 16
|
||||
fgColor = RED;
|
||||
print("[ x87 FPU Floating-Point Error ]\n");
|
||||
__asm__ volatile ("cli; hlt");
|
||||
}
|
||||
|
||||
__attribute__ ((interrupt))
|
||||
void excp_alignCheck(intFrame_t* iframe, uint32_t errCode) { // ISR 17
|
||||
fgColor = RED;
|
||||
print("[ Alignment Check : 0x");
|
||||
print(itoa(errCode, 16));
|
||||
print(" ]\n");
|
||||
__asm__ volatile ("cli; hlt");
|
||||
}
|
||||
|
||||
__attribute__ ((interrupt))
|
||||
void excp_machineCheck(intFrame_t* iframe) { // ISR 18
|
||||
fgColor = RED;
|
||||
print("[ Machine Check ]\n");
|
||||
__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);
|
||||
}
|
||||
|
||||
idtSetGate(0, excp_divideErr, TRAP_GATE_FLAGS);
|
||||
idtSetGate(1, excp_debugErr, TRAP_GATE_FLAGS);
|
||||
idtSetGate(2, excp_nmiInterrupt, TRAP_GATE_FLAGS);
|
||||
idtSetGate(3, excp_breakpoint, TRAP_GATE_FLAGS);
|
||||
idtSetGate(4, excp_overflow, TRAP_GATE_FLAGS);
|
||||
idtSetGate(5, excp_boundRangeExceed, TRAP_GATE_FLAGS);
|
||||
idtSetGate(6, excp_invalidOpcode, TRAP_GATE_FLAGS);
|
||||
idtSetGate(7, excp_deviceNA, TRAP_GATE_FLAGS);
|
||||
idtSetGate(8, excp_doubleFault, TRAP_GATE_FLAGS);
|
||||
idtSetGate(9, excp_coprocOverrun, TRAP_GATE_FLAGS);
|
||||
idtSetGate(10, excp_invalidTss, TRAP_GATE_FLAGS);
|
||||
idtSetGate(11, excp_noSegment, TRAP_GATE_FLAGS);
|
||||
idtSetGate(12, excp_stackSegmentFault, TRAP_GATE_FLAGS);
|
||||
idtSetGate(13, excp_generalProtectionFault, TRAP_GATE_FLAGS);
|
||||
idtSetGate(14, excp_pageFault, TRAP_GATE_FLAGS);
|
||||
idtSetGate(15, excp_reserved, TRAP_GATE_FLAGS);
|
||||
idtSetGate(16, excp_floatingPointErr, TRAP_GATE_FLAGS);
|
||||
idtSetGate(17, excp_alignCheck, TRAP_GATE_FLAGS);
|
||||
idtSetGate(18, excp_machineCheck, TRAP_GATE_FLAGS);
|
||||
// Other are reserved
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,55 @@
|
||||
#ifndef IDT_H
|
||||
#define IDT_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <screen/text.h>
|
||||
|
||||
#define TRAP_GATE_FLAGS 0x8f // P = 1, DPL = 00, S = 0, Type = 1111 (32-bit Trap gate)
|
||||
#define INT_GATE_FLAGS 0x8e // P = 1, DPL = 00, S = 0, Type = 1110 (32-bit Int gate)
|
||||
#define USR_INT_GAME_FLAGS 0xee // P = 1, DPL = 11, S = 0, Type = 1110 (32-bit Int gate)
|
||||
|
||||
typedef struct {
|
||||
uint16_t offsetLow;
|
||||
uint16_t selector;
|
||||
uint8_t zero;
|
||||
uint8_t typeAttr;
|
||||
uint16_t offsetHigh;
|
||||
} __attribute__ ((packed)) idtEntry_t;
|
||||
|
||||
typedef struct {
|
||||
uint16_t limit;
|
||||
uint32_t base;
|
||||
} __attribute__ ((packed)) idtp_t;
|
||||
|
||||
typedef struct {
|
||||
uint32_t eip;
|
||||
uint32_t cs;
|
||||
uint32_t eflags;
|
||||
uint32_t esp;
|
||||
uint32_t ss;
|
||||
} __attribute__ ((packed)) intFrame_t;
|
||||
|
||||
__attribute__ ((aligned(0x10))) // For performance
|
||||
idtEntry_t idt[256] = { 0 };
|
||||
idtp_t idtp;
|
||||
|
||||
void idtSetGate(uint8_t i, void* handler, uint8_t flags) {
|
||||
uint32_t offset = (uint32_t)handler;
|
||||
idtEntry_t* entry = &idt[i];
|
||||
|
||||
entry->offsetLow = (uint16_t)offset;
|
||||
entry->selector = 0x08;
|
||||
entry->zero = 0;
|
||||
entry->typeAttr = flags;
|
||||
entry->offsetHigh = (uint16_t)(offset >> 16);
|
||||
}
|
||||
|
||||
void setupIdt() {
|
||||
idtp.limit = sizeof(idtEntry_t) * 256;
|
||||
idtp.base = (uint32_t)&idt;
|
||||
|
||||
__asm__ volatile ("lidt %0" : : "m"(idtp));
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,95 @@
|
||||
#ifndef PIC_H
|
||||
#define PIC_H
|
||||
|
||||
#include <ports/io.h>
|
||||
|
||||
// PIC I/O Ports
|
||||
#define PIC_1_CMD 0x20
|
||||
#define PIC_1_DATA 0x21
|
||||
#define PIC_2_CMD 0xA0
|
||||
#define PIC_2_DATA 0xA1
|
||||
|
||||
// IRQs
|
||||
#define NEW_IRQ_0 0x20 // IRQ 0 : int 32
|
||||
#define NEW_IRQ_8 0x28 // IRQ 8 : int 40
|
||||
|
||||
// Commands
|
||||
#define PIC_EOI 0x20 // End Of Interrupt
|
||||
#define PIC_DISABLE 0xff
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,47 @@
|
||||
#ifndef TIMER_H
|
||||
#define TIMER_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <interrupt/idt.h>
|
||||
#include <interrupt/pic.h>
|
||||
#include <screen/text.h>
|
||||
|
||||
#define CHANNEL_0 0x40 // Offset it by 1 or 2 for ch1 and ch2
|
||||
#define COMMAND 0x43
|
||||
#define INPUT_CLK 1193182
|
||||
|
||||
static uint32_t* timerTicks = (uint32_t*)0x1000;
|
||||
|
||||
__attribute__ ((interrupt))
|
||||
void timerHandler(intFrame_t* iframe) {
|
||||
*timerTicks += 1;
|
||||
|
||||
// TODO: Improve the cursor rendering
|
||||
if (*timerTicks % 500 == 0) putcAt(' ', cursor.x, cursor.y);
|
||||
else if (*timerTicks % 250 == 0) putcAt(127, cursor.x, cursor.y);
|
||||
|
||||
sendPicEOI(0);
|
||||
}
|
||||
|
||||
void setPitPhase(uint8_t channel, uint8_t opMode, uint16_t hz) {
|
||||
if (channel > 2 || opMode > 7) { return; }
|
||||
__asm__ volatile ("cli");
|
||||
|
||||
// Send command - bits 7-6 channel, 5-4 Access mode, 3-1 operating mode, 0 - Should be zero in x86
|
||||
outb(COMMAND, ((channel << 6) | (3 << 4) | (opMode << 1)));
|
||||
|
||||
// Send frequency
|
||||
uint16_t freq = INPUT_CLK / hz; // I solved an equation to figure this out
|
||||
outb(CHANNEL_0 + channel, (uint8_t)freq);
|
||||
outb(CHANNEL_0 + channel, (uint8_t)(freq >> 8));
|
||||
|
||||
__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
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,75 @@
|
||||
#ifndef SYSCALL_H
|
||||
#define SYSCALL_H
|
||||
|
||||
#include <interrupt/pit.h>
|
||||
|
||||
// System call count
|
||||
#define MAX_SYSCALLS 2
|
||||
|
||||
// Args: ebx - number of miliseconds
|
||||
void sys_sleep() {
|
||||
uint32_t ms;
|
||||
__asm__ volatile ("movl %%ebx, %0" : "=r"(ms));
|
||||
|
||||
uint32_t requiredTicks = *timerTicks + ms;
|
||||
while (*timerTicks != requiredTicks) { // Wait...
|
||||
__asm__ volatile ("sti;hlt;cli;");
|
||||
}
|
||||
}
|
||||
|
||||
// System call table
|
||||
void* syscalls[MAX_SYSCALLS] = {
|
||||
sys_sleep,
|
||||
};
|
||||
|
||||
// int 0x80 - Syscall interrupt, handled by this function
|
||||
// eax : Syscall number
|
||||
__attribute__ ((naked)) // No prologue or epilogue, just assembly
|
||||
void syscallHandler(void) {
|
||||
// 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, 2\n" // Define MAX_SYSCALLS again
|
||||
|
||||
// Check if syscall exists
|
||||
"cmp eax, MAX_SYSCALLS - 1\n"
|
||||
"ja invalidSyscall\n"
|
||||
|
||||
// Call the syscall
|
||||
"push eax\n" // Push required values
|
||||
"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"
|
||||
"pop ebx\n" // Pop pushed values
|
||||
"pop ecx\n"
|
||||
"pop edx\n"
|
||||
"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
|
||||
|
||||
// TODO: Send an error or something here
|
||||
"invalidSyscall:\n"
|
||||
"iretd\n"
|
||||
|
||||
".att_syntax" // Switch back to Att Syntax (Just in case)
|
||||
);
|
||||
}
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user