massive overhaul to my exception system

This commit is contained in:
2025-06-05 20:28:17 -04:00
parent 79f04df82e
commit 3e01dc2074
5 changed files with 223 additions and 40 deletions

View File

@ -1,10 +1,9 @@
#include <stdatomic.h>
#include <stdbool.h>
#include <stdint.h>
#ifdef __TESTING__
#include <kernel/_kernel.h>
#include <stdio.h>
#endif
#include <kernel/_kernel.h>
#include <kernel/x86/idt.h>
#include <kernel/x86/pic.h>
#include <kernel/x86/io.h>
@ -19,21 +18,218 @@ static bool vectors[IDT_MAX_DESCRIPTORS];
extern struct keyboard_state keyb_state;
void exception_handler(struct cpu_state __attribute__((unused)) cpu, uint32_t interrupt, struct stack_state stack)
#define EXTERNAL_BIT (0x1)
#define TBL_GDT (0x0)
#define TBL_LDT (0x2)
#define TBL_IDT (0x1)
#define TBL_IDT_TWO (0x3)
static void examine_selector(uint32_t selector)
{
printf("%1 %2\n", interrupt, stack.eflags);
if (interrupt <= 31) { // TODO: implement proper handling for each exception, also implement the proper gates & error code checking
#ifdef __TESTING__
kerror("EXCEPTION");
printf("Exeption: %2\n", interrupt);
#endif
//__asm__ volatile ("cli; hlt"); // hangs the computer
printf("The interrupt arised %s.\n", (selector & EXTERNAL_BIT) == EXTERNAL_BIT ? "externally" : "internally");
printf("The descriptor 0x%x, is located in the ", selector, (selector & 0x0000FFFF) >> 3);
if ((((selector >> 1) & TBL_IDT) == TBL_IDT)
|| ((selector >> 1) & TBL_IDT_TWO) == TBL_IDT_TWO) {
puts("IDT.");
} else if (((selector >> 1) & TBL_LDT) == TBL_LDT) {
puts("LDT.");
} else {
puts("GDT.");
}
return;
}
#undef TBL_GDT
#undef TBL_LDT
#undef TBL_IDT
#undef TBL_IDT_TWO
#define PF_P (1 << 0)
#define PF_W (1 << 1)
#define PF_U (1 << 2)
#define PF_R (1 << 3)
#define PF_I (1 << 4)
#define PF_PK (1 << 5)
#define PF_SS (1 << 6)
#define PF_SGX (1 << 15)
static void examine_page_fault(uint32_t error_code)
{
puts("Page fault:");
if (error_code & PF_P) {
puts("Page-protection violation.");
} else {
puts("Not present page.");
}
if (interrupt == PIC_KEYB) {
unsigned char in = inb(0x60);
do_keypress(decode_scancode(in));
PIC_sendEOI(1);
if (error_code & PF_W) {
puts("Write access.");
} else {
puts("Read access.");
}
if (error_code & PF_U) {
puts("In CPL 3.");
}
if (error_code & PF_R) { // Only applies if PSE or PAE are set in CR4
puts("One or more page directory entires contain reserved bits which are set to 1.");
}
if (error_code & PF_I) { // Only applicable when the No-Execute bit is supported and enabled
puts("Instruction fetch.");
}
if (error_code & PF_PK) {
puts("Protection-key violation"); //TODO PRKU (user mode access) or PRKS MSR (supervisor mode access) specifies the key rights
}
if (error_code & PF_SS) {
puts("Shadow stack access.");
}
if (error_code & PF_SGX) { // Unrelated to ordinary paging
puts("SGX vioilation");
}
// TODO, also sets CR2 reg to the virtual address which caused the page fault
}
#undef PF_P
#undef PF_W
#undef PF_U
#undef PF_R
#undef PF_I
#undef PF_PK
#undef PF_SS
#undef PF_SGX
#define EXCEPTION_LOCATION() printf("Exception occurred at 0x%2\n", stack.eip)
void exception_handler(struct cpu_state __attribute__((unused)) cpu, uint32_t interrupt, struct stack_state stack)
{
uint32_t inbyte;
switch (interrupt) {
/** EXCEPTIONS BEGIN **/
case EXCEPT_DIV_ERR:
kerror("EXCEPTION: DIV BY ZERO");
EXCEPTION_LOCATION();
break;
case EXCEPT_DEBUG:
kinfo("EXCEPTION: DEBUG"); // TODO: this one has more specific requirements
break;
case EXCEPT_NMI:
kinfo("EXCEPTION: NON-MASKABLE INTERRUPT"); // TODO
break;
case EXCEPT_BREAKPOINT:
kinfo("EXCEPTION: BREAKPOINT");
// TODO
break;
case EXCEPT_OVERFLOW:
kerror("EXCEPTION: OVERFLOW");
break;
case EXCEPT_BOUND_RANGE_EXCEEDED:
kerror("EXCEPTION: BOUND RANGE EXCEEDED");
EXCEPTION_LOCATION();
break;
case EXCEPT_INVALID_OPCODE:
kerror("EXCEPTION: INVALID OPCODE");
EXCEPTION_LOCATION();
break;
case EXCEPT_DEVICE_NOT_AVAILABLE:
kerror("EXCEPTION: DEVICE NOT AVAILABLE");
printf("Instructions expecting an FPU were used, but no FPU was found. Is it disabled in CR0? Do you have an FPU?\n");
EXCEPTION_LOCATION();
break;
case EXCEPT_DOUBLE_FAULT:
kerror("EXCEPTION: DOUBLE FAULT");
__asm__ volatile ("cli; hlt"); // boned
break;
case EXCEPT_INVALID_TSS:
kerror("EXCEPTION: INVALID TSS");
examine_selector(stack.error_code);
// TODO: when i implement the TSS, the EIP will be one of two things
// if this occurs before loading segmenet selectors from the TSS, EIP will be the instruction that caused the instruction
// otherwise its the first instruction in the new task
break;
case EXCEPT_SEG_NOT_PRESENT:
kerror("EXCEPTION: SEGMENT NOT PRESENT");
EXCEPTION_LOCATION();
examine_selector(stack.error_code);
break;
case EXCEPT_STACK_SEG_FAULT:
kerror("EXCEPTION: STACK-SEGMENT FAULT");
if (stack.error_code == 0) {
EXCEPTION_LOCATION();
} else {
printf("Tried loading non-present stack segment during hardware task switch.\n");
examine_selector(stack.error_code);
}
break;
case EXCEPT_GENERAL_PROTECTION:
kerror("EXCEPTION: GENERAL PROTECTION FAULT");
EXCEPTION_LOCATION();
if (stack.error_code != 0)
examine_selector(stack.error_code);
break;
case EXCEPT_PAGE_FAULT:
kerror("EXCEPTION: PAGE FAULT");
EXCEPTION_LOCATION();
examine_page_fault(stack.error_code);
break;
case EXCEPT_FLOATING_POINT_ERR_FPU:
kerror("EXCEPTION: FLOATING POINT ERROR FPU");
// TODO: this requires a custom handler, it needs another register
break;
case EXCEPT_ALIGNMENT_CHECK:
kerror("EXCEPTION: ALIGNMENT CHECK");
// TODO: only in CPL3
break;
case EXCEPT_MACHINE_CHECK:
kerror("EXCEPTION: MACHINE CHECK");
// TODO disabled by default
break;
case EXCEPT_FLOATING_POINT_ERR_SIMD:
kerror("EXCEPTION: FLOATING POINT ERROR SIMD");
// TODO disabled by default
break;
case EXCEPT_VIRT:
kerror("EXCEPTION: VIRTUALIZATION");
break;
case EXCEPT_CTRL_PROT:
kerror("EXCEPTION: CONTROL PROTECTION");
printf("Error code: 0x%2\n", stack.error_code);
break;
case EXCEPT_HYPERVISOR_INJECTION:
kerror("EXCEPTION: HYPERVISOR INJECTION");
break;
case EXCEPT_VMM_COMMUNICATION:
kerror("EXCEPTION: VMM COMMUNICATION");
printf("Error code: 0x%2\n", stack.error_code);
break;
case EXCEPT_SECURITY_EXCEPTION:
kerror("EXCEPTION: SECURITY");
printf("Error code: 0x%2\n", stack.error_code);
break;
/** EXCEPTIONS END **/
/** PIC BEGIN **/
case PIC_KEYB:
inbyte = inb(0x60);
do_keypress(decode_scancode(inbyte));
PIC_sendEOI(1);
break;
/** PIC END **/
default:
kerror("EXCEPTION: UNHANDLED EXCEPTION OR INTERRUPT");
printf("Error code: 0x%2\n", stack.error_code);
break;
}
}
@ -68,7 +264,7 @@ void idt_init(void)
PIC_remap(0x20, 0x28);
pic_disable(); // mask everything
IRQ_clear_mask(1);
__asm__ volatile("sti"); // set the interrupt flag
#ifdef __TESTING__
kinfo("Initialized the IDT");