mirror of
https://github.com/Tom-on64/kern.git
synced 2026-11-03 18:22:22 +00:00
Got decent exception handling
This commit is contained in:
@@ -4,7 +4,7 @@ TODO
|
|||||||
Architectural Milestones
|
Architectural Milestones
|
||||||
[-] 64-bit rewrite
|
[-] 64-bit rewrite
|
||||||
[x] Limine (Bootloader)
|
[x] Limine (Bootloader)
|
||||||
[ ] Decent build system (Makefile/CMake with cross-compiler)
|
[ ] Decent build system (feat. cross-compiler)
|
||||||
[x] kernel.h rewrite & header cleanup
|
[x] kernel.h rewrite & header cleanup
|
||||||
[x] debugf() cleanup, kprintf() & pr_*() (Standardized logging levels)
|
[x] debugf() cleanup, kprintf() & pr_*() (Standardized logging levels)
|
||||||
[x] errno.h errors and "errno-in-pointer" macros
|
[x] errno.h errors and "errno-in-pointer" macros
|
||||||
@@ -13,7 +13,7 @@ Low-Level Hardware & Interrupts
|
|||||||
[x] GDT
|
[x] GDT
|
||||||
[x] IDT
|
[x] IDT
|
||||||
[x] Basic IRQs (Internal/Legacy)
|
[x] Basic IRQs (Internal/Legacy)
|
||||||
[ ] Proper fault handling (Exceptions, Page Faults, #GP)
|
[x] Proper fault handling (Exceptions, Page Faults, #GP)
|
||||||
[ ] Check for features with CPUID (NX-bit, SSE, AVX)
|
[ ] Check for features with CPUID (NX-bit, SSE, AVX)
|
||||||
[ ] APIC driver (Local APIC & I/O APIC)
|
[ ] APIC driver (Local APIC & I/O APIC)
|
||||||
[ ] ACPI driver (Parsing RSDP/MADT for multi-core/APIC)
|
[ ] ACPI driver (Parsing RSDP/MADT for multi-core/APIC)
|
||||||
@@ -55,7 +55,8 @@ Drivers & IO
|
|||||||
[ ] Storage driver (SATA/AHCI or VirtIO)
|
[ ] Storage driver (SATA/AHCI or VirtIO)
|
||||||
|
|
||||||
The Final TODOs
|
The Final TODOs
|
||||||
[ ] Run DOOM (Requires: VFS, Input, Timer, LibC, and Graphics)
|
[ ] Gaming???!!??
|
||||||
|
[ ] Run DOOM
|
||||||
[-] Finish all the TODOs
|
[-] Finish all the TODOs
|
||||||
|
|
||||||
Legend
|
Legend
|
||||||
|
|||||||
@@ -0,0 +1,24 @@
|
|||||||
|
#ifndef _EXCEPTIONS_H
|
||||||
|
#define _EXCEPTIONS_H
|
||||||
|
|
||||||
|
#include "isr.h"
|
||||||
|
|
||||||
|
#define EXCEPTION_DE 0
|
||||||
|
#define EXCEPTION_BP 3
|
||||||
|
#define EXCEPTION_OF 4
|
||||||
|
#define EXCEPTION_BR 5
|
||||||
|
#define EXCEPTION_UD 6
|
||||||
|
#define EXCEPTION_NM 7
|
||||||
|
#define EXCEPTION_DF 8
|
||||||
|
#define EXCEPTION_GP 13
|
||||||
|
#define EXCEPTION_PF 14
|
||||||
|
#define EXCEPTION_AC 17
|
||||||
|
|
||||||
|
typedef void (*exception_handler_ptr)(struct isr_int_frame* iframe, bool user);
|
||||||
|
|
||||||
|
const extern char* exception_strings[];
|
||||||
|
|
||||||
|
int exception_init(void);
|
||||||
|
void exception_handle(struct isr_int_frame* iframe);
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -9,6 +9,7 @@
|
|||||||
#define PTE_FLAG_USER (1UL << 2) // User-mode (DPL3) access allowed
|
#define PTE_FLAG_USER (1UL << 2) // User-mode (DPL3) access allowed
|
||||||
#define PTE_FLAG_PWT (1UL << 3) // Page write-thru
|
#define PTE_FLAG_PWT (1UL << 3) // Page write-thru
|
||||||
#define PTE_FLAG_NOCACHE (1UL << 4) // Cache disable
|
#define PTE_FLAG_NOCACHE (1UL << 4) // Cache disable
|
||||||
|
#define PTE_FLAG_FETCH (1UL << 4) // Fetch
|
||||||
#define PTE_FLAG_ACCESSED (1UL << 5) // Indicates whether page was read/written
|
#define PTE_FLAG_ACCESSED (1UL << 5) // Indicates whether page was read/written
|
||||||
#define PTE_FLAG_DIRTY (1UL << 6) // Indicates whether page was written to (valid for PT only)
|
#define PTE_FLAG_DIRTY (1UL << 6) // Indicates whether page was written to (valid for PT only)
|
||||||
#define PTE_FLAG_PAT (1UL << 7) // Page Attribute Table (valid for PT only)
|
#define PTE_FLAG_PAT (1UL << 7) // Page Attribute Table (valid for PT only)
|
||||||
|
|||||||
@@ -0,0 +1,152 @@
|
|||||||
|
#include "paging.h"
|
||||||
|
#include <exceptions.h>
|
||||||
|
#include <kernel.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <isr.h>
|
||||||
|
|
||||||
|
exception_handler_ptr exception_handlers[EXCEPTION_COUNT];
|
||||||
|
|
||||||
|
const char* exception_strings[] = {
|
||||||
|
"Division Error",
|
||||||
|
"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 Exception",
|
||||||
|
"Alignment Check",
|
||||||
|
"Machine Check",
|
||||||
|
"SIMD Floating-Point Exception",
|
||||||
|
"Virtualization Exception",
|
||||||
|
"Control Protection Exception",
|
||||||
|
"Reserved",
|
||||||
|
"Reserved",
|
||||||
|
"Reserved",
|
||||||
|
"Reserved",
|
||||||
|
"Reserved",
|
||||||
|
"Reserved",
|
||||||
|
"Hypervisor Injection Exception",
|
||||||
|
"VMM Communication Exception",
|
||||||
|
"Security Exception",
|
||||||
|
"Reserved",
|
||||||
|
};
|
||||||
|
|
||||||
|
void exception_handle(struct isr_int_frame* iframe) {
|
||||||
|
bool user = (iframe->cs & 3) == 3;
|
||||||
|
|
||||||
|
if (exception_handlers[iframe->interrupt]) {
|
||||||
|
exception_handlers[iframe->interrupt](iframe, user);
|
||||||
|
} else {
|
||||||
|
panic(iframe, "Unhandled %s exception, err 0x%lx", exception_strings[iframe->interrupt], iframe->error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void handle_division_error(struct isr_int_frame* iframe, bool user) {
|
||||||
|
if (user) {
|
||||||
|
// TODO: Kill process
|
||||||
|
} else panic(iframe, "Division by 0 @ %p", (void*)iframe->rip);
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void handle_invalid_opcode(struct isr_int_frame* iframe, bool user) {
|
||||||
|
if (user) {
|
||||||
|
pr_error("Userspace #UD @ %p\n", (void*)iframe->rip);
|
||||||
|
// TODO: Kill process
|
||||||
|
} else {
|
||||||
|
panic(iframe, "Kernel #UD");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void handle_device_not_available(struct isr_int_frame* iframe, bool user) {
|
||||||
|
(void)iframe;
|
||||||
|
(void)user;
|
||||||
|
|
||||||
|
__asm__ volatile("clts");
|
||||||
|
|
||||||
|
// TODO:
|
||||||
|
// if (last_fpu_user != current) {
|
||||||
|
// if (last_fpu_user) {
|
||||||
|
// __asm__ volatile("fxsaveq %0" : "=m"(last_fpu_user->fpu_state));
|
||||||
|
// }
|
||||||
|
// __asm__ volatile("fxrstorq %0" : : "m"(current->fpu_state));
|
||||||
|
// set_last_fpu_owner(current);
|
||||||
|
// }
|
||||||
|
|
||||||
|
pr_notice("FPU/SSE initialized lazily for current thread.\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Do not attempt to log gracefully using complex structures or locks
|
||||||
|
// The kernel stack might be completely shredded
|
||||||
|
void handle_double_fault(struct isr_int_frame* iframe, bool user) {
|
||||||
|
(void)user;
|
||||||
|
|
||||||
|
pr_emerg(
|
||||||
|
"Beware human. This thing is beyond comprehension. Beyond this corporeal realm.\n"
|
||||||
|
"Oh may the those unlucky enough to encouter it be spared of their pain.\n"
|
||||||
|
"Through it you pass into the city of woe.\n"
|
||||||
|
"Through it you pass into eternal pain.\n"
|
||||||
|
"To rear it was the task of power divine.\n"
|
||||||
|
"Supremes wisdom, and primeval love.\n"
|
||||||
|
"Before it things create were none, save things.\n"
|
||||||
|
"Eternal, and eternal It endures.\n"
|
||||||
|
"Abandon all hope, all ye who enter here.\n\n"
|
||||||
|
);
|
||||||
|
panic(iframe, "[ D O U B L E F A U L T ]");
|
||||||
|
}
|
||||||
|
|
||||||
|
void handle_general_protection_fault(struct isr_int_frame* iframe, bool user) {
|
||||||
|
if (user) {
|
||||||
|
pr_error("Userspace #GP @ %p (err: 0x%lx)\n", (void*)iframe->rip, iframe->error);
|
||||||
|
// TODO: Kill process
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void handle_page_fault(struct isr_int_frame* iframe, bool user) {
|
||||||
|
uint64_t fault_addr;
|
||||||
|
__asm__ volatile("mov %%cr2, %0" : "=r"(fault_addr));
|
||||||
|
|
||||||
|
uint64_t err = iframe->error;
|
||||||
|
bool present = err & 0x1;
|
||||||
|
bool write = err & 0x2;
|
||||||
|
bool usersp = err & 0x4;
|
||||||
|
bool fetch = err & 0xA;
|
||||||
|
|
||||||
|
if (user) {
|
||||||
|
pr_error("Userspace #PF: Segfault @ %p, tried to access %p\n", (void*)iframe->rip, (void*)fault_addr);
|
||||||
|
pr_error("\x1b[9m Reason: Retard\x1b[m\n"); // reference
|
||||||
|
pr_error(" Reason: %s %s in %s mode %s\n",
|
||||||
|
present ? "Protection violation" : "Non-present page",
|
||||||
|
write ? "during WRITE" : "during READ",
|
||||||
|
usersp ? "user" : "supervisor",
|
||||||
|
fetch ? "during instruction fetch" : ""
|
||||||
|
);
|
||||||
|
// TODO: Kill process
|
||||||
|
} else {
|
||||||
|
panic(iframe, "Kernel: Segmentation fault @ %p, tried to access %p (err: 0x%lx)", (void*)iframe->rip, (void*)fault_addr, err);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int exception_init(void) {
|
||||||
|
memset(exception_handlers, 0, sizeof(exception_handlers));
|
||||||
|
|
||||||
|
exception_handlers[EXCEPTION_DE] = handle_division_error;
|
||||||
|
exception_handlers[EXCEPTION_UD] = handle_invalid_opcode;
|
||||||
|
exception_handlers[EXCEPTION_NM] = handle_device_not_available;
|
||||||
|
exception_handlers[EXCEPTION_DF] = handle_double_fault;
|
||||||
|
exception_handlers[EXCEPTION_PF] = handle_page_fault;
|
||||||
|
|
||||||
|
return SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
+5
-46
@@ -1,3 +1,4 @@
|
|||||||
|
#include <exceptions.h>
|
||||||
#include <kernel.h>
|
#include <kernel.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <system.h>
|
#include <system.h>
|
||||||
@@ -5,44 +6,8 @@
|
|||||||
#include <idt.h>
|
#include <idt.h>
|
||||||
#include <isr.h>
|
#include <isr.h>
|
||||||
|
|
||||||
isr_handler_ptr exception_handlers[EXCEPTION_COUNT];
|
|
||||||
isr_handler_ptr irq_handlers[ISR_COUNT];
|
isr_handler_ptr irq_handlers[ISR_COUNT];
|
||||||
|
|
||||||
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",
|
|
||||||
"SIMD Floating-Point",
|
|
||||||
"Virtualization",
|
|
||||||
"Control Protection",
|
|
||||||
"Reserved",
|
|
||||||
"Reserved",
|
|
||||||
"Reserved",
|
|
||||||
"Reserved",
|
|
||||||
"Reserved",
|
|
||||||
"Reserved",
|
|
||||||
"Reserved",
|
|
||||||
"Reserved",
|
|
||||||
"Reserved",
|
|
||||||
"Reserved"
|
|
||||||
};
|
|
||||||
|
|
||||||
void pic_disable(void) {
|
void pic_disable(void) {
|
||||||
outb(0x21, 0xFF); iowait();
|
outb(0x21, 0xFF); iowait();
|
||||||
outb(0xA1, 0xFF); iowait();
|
outb(0xA1, 0xFF); iowait();
|
||||||
@@ -63,7 +28,7 @@ void pic_remap(void) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
int isr_init(void) {
|
int isr_init(void) {
|
||||||
memset(exception_handlers, 0, sizeof(exception_handlers));
|
exception_init();
|
||||||
memset(irq_handlers, 0, sizeof(irq_handlers));
|
memset(irq_handlers, 0, sizeof(irq_handlers));
|
||||||
|
|
||||||
idt_init();
|
idt_init();
|
||||||
@@ -99,18 +64,12 @@ void isr_send_eoi(uint8_t irq) {
|
|||||||
void isr_handle_interrupt(size_t rsp) {
|
void isr_handle_interrupt(size_t rsp) {
|
||||||
struct isr_int_frame* iframe = (void*)rsp;
|
struct isr_int_frame* iframe = (void*)rsp;
|
||||||
|
|
||||||
if (iframe->interrupt < 32) {
|
if (iframe->interrupt < 32) exception_handle(iframe);
|
||||||
if (exception_handlers[iframe->interrupt]) {
|
else if (iframe->interrupt >= 32 && iframe->interrupt < 48) {
|
||||||
exception_handlers[iframe->interrupt](iframe);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
panic(iframe, "Unhandled %s exception, err 0x%lx", exceptions[iframe->interrupt], iframe->error);
|
|
||||||
} else if (iframe->interrupt >= 32 && iframe->interrupt < 48) {
|
|
||||||
uint8_t irq = iframe->interrupt - 32;
|
uint8_t irq = iframe->interrupt - 32;
|
||||||
|
|
||||||
if (irq_handlers[irq]) irq_handlers[irq](iframe);
|
if (irq_handlers[irq]) irq_handlers[irq](iframe);
|
||||||
else pr_warn("Unhandled IRQ #%d\n", irq);
|
// else pr_debug("Unhandled IRQ #%d\n", irq);
|
||||||
|
|
||||||
isr_send_eoi(irq);
|
isr_send_eoi(irq);
|
||||||
} else if (iframe->interrupt == 0x80) {
|
} else if (iframe->interrupt == 0x80) {
|
||||||
|
|||||||
Reference in New Issue
Block a user