forked from PoliEcho-holding-org/kern
Got decent exception handling
This commit is contained in:
@@ -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_PWT (1UL << 3) // Page write-thru
|
||||
#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_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)
|
||||
|
||||
@@ -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 <string.h>
|
||||
#include <system.h>
|
||||
@@ -5,44 +6,8 @@
|
||||
#include <idt.h>
|
||||
#include <isr.h>
|
||||
|
||||
isr_handler_ptr exception_handlers[EXCEPTION_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) {
|
||||
outb(0x21, 0xFF); iowait();
|
||||
outb(0xA1, 0xFF); iowait();
|
||||
@@ -63,7 +28,7 @@ void pic_remap(void) {
|
||||
}
|
||||
|
||||
int isr_init(void) {
|
||||
memset(exception_handlers, 0, sizeof(exception_handlers));
|
||||
exception_init();
|
||||
memset(irq_handlers, 0, sizeof(irq_handlers));
|
||||
|
||||
idt_init();
|
||||
@@ -99,18 +64,12 @@ void isr_send_eoi(uint8_t irq) {
|
||||
void isr_handle_interrupt(size_t rsp) {
|
||||
struct isr_int_frame* iframe = (void*)rsp;
|
||||
|
||||
if (iframe->interrupt < 32) {
|
||||
if (exception_handlers[iframe->interrupt]) {
|
||||
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) {
|
||||
if (iframe->interrupt < 32) exception_handle(iframe);
|
||||
else if (iframe->interrupt >= 32 && iframe->interrupt < 48) {
|
||||
uint8_t irq = iframe->interrupt - 32;
|
||||
|
||||
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);
|
||||
} else if (iframe->interrupt == 0x80) {
|
||||
|
||||
Reference in New Issue
Block a user