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

@ -3,7 +3,7 @@
CC = i686-elf-gcc CC = i686-elf-gcc
DEBUG_FLAGS = -D__TESTING__ -g -Wno-div-by-zero DEBUG_FLAGS = -D__TESTING__ -g
CFLAGS = -m32 -ffreestanding -Wall -Wextra -Werror -Wpedantic --sysroot=$(PWD)/sysroot -isystem=/usr/include -Iinclude -MD $(DEBUG_FLAGS) CFLAGS = -m32 -ffreestanding -Wall -Wextra -Werror -Wpedantic --sysroot=$(PWD)/sysroot -isystem=/usr/include -Iinclude -MD $(DEBUG_FLAGS)
@ -39,7 +39,7 @@ all: kernel.elf
env: install-headers install-libs # TODO: change this to a file specific target, so it doesnt recompile everytime, and so we can move as a prereq on kernel.elf env: install-headers install-libs # TODO: change this to a file specific target, so it doesnt recompile everytime, and so we can move as a prereq on kernel.elf
util/./gen-clangd.sh util/./gen-clangd.sh
kernel.elf: install-headers install-libs $(c_kern_objects) $(asm_kern_objects) kernel.elf: install-headers install-libs env $(c_kern_objects) $(asm_kern_objects)
$(CC) $(CFLAGS) -T $(shell find . -name "link.ld") -o $@ $(c_kern_objects) $(asm_kern_objects) -nostdlib -lk -lgcc $(CC) $(CFLAGS) -T $(shell find . -name "link.ld") -o $@ $(c_kern_objects) $(asm_kern_objects) -nostdlib -lk -lgcc
os.iso: kernel.elf os.iso: kernel.elf

View File

@ -1,7 +1,6 @@
## What do I need to do? ## What do I need to do?
Exception handling is a must for next part, we need to be able to dianogse issues better ### Features I want
- Want the address of the fault - A kernel bus
- Proper handling of the issue - some kind of driver where I can send messages that can eventually be accessed globally by other drives / applications
- Maybe dump registers?

View File

@ -1,10 +1,9 @@
#include <stdatomic.h>
#include <stdbool.h> #include <stdbool.h>
#include <stdint.h> #include <stdint.h>
#ifdef __TESTING__
#include <kernel/_kernel.h>
#include <stdio.h> #include <stdio.h>
#endif
#include <kernel/_kernel.h>
#include <kernel/x86/idt.h> #include <kernel/x86/idt.h>
#include <kernel/x86/pic.h> #include <kernel/x86/pic.h>
#include <kernel/x86/io.h> #include <kernel/x86/io.h>
@ -19,21 +18,218 @@ static bool vectors[IDT_MAX_DESCRIPTORS];
extern struct keyboard_state keyb_state; 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); printf("The interrupt arised %s.\n", (selector & EXTERNAL_BIT) == EXTERNAL_BIT ? "externally" : "internally");
if (interrupt <= 31) { // TODO: implement proper handling for each exception, also implement the proper gates & error code checking
#ifdef __TESTING__
kerror("EXCEPTION"); printf("The descriptor 0x%x, is located in the ", selector, (selector & 0x0000FFFF) >> 3);
printf("Exeption: %2\n", interrupt); if ((((selector >> 1) & TBL_IDT) == TBL_IDT)
#endif || ((selector >> 1) & TBL_IDT_TWO) == TBL_IDT_TWO) {
//__asm__ volatile ("cli; hlt"); // hangs the computer puts("IDT.");
} else if (((selector >> 1) & TBL_LDT) == TBL_LDT) {
puts("LDT.");
} else {
puts("GDT.");
} }
if (interrupt == PIC_KEYB) { return;
unsigned char in = inb(0x60); }
do_keypress(decode_scancode(in));
#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 (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); PIC_sendEOI(1);
break;
/** PIC END **/
default:
kerror("EXCEPTION: UNHANDLED EXCEPTION OR INTERRUPT");
printf("Error code: 0x%2\n", stack.error_code);
break;
} }
} }

View File

@ -3,14 +3,6 @@ extern exception_handler_err
%macro isr_err_stub 1 %macro isr_err_stub 1
isr_stub_%+%1: isr_stub_%+%1:
;pushad
;cld
;push dword %1
;call exception_handler_err
;pop eax ; pop the error
;pop eax ; make sure to pop off the dword!!
;popad
;iret
push dword %1 ; push the interrupt number push dword %1 ; push the interrupt number
jmp common_interrupt_handler jmp common_interrupt_handler
@ -18,13 +10,6 @@ isr_stub_%+%1:
%macro isr_no_err_stub 1 %macro isr_no_err_stub 1
isr_stub_%+%1: isr_stub_%+%1:
;pushad
;cld
;push dword %1
;call exception_handler
;pop eax
;popad
;iret
push dword 0 push dword 0
push dword %1 push dword %1
jmp common_interrupt_handler jmp common_interrupt_handler
@ -51,7 +36,8 @@ common_interrupt_handler:
pop ebx pop ebx
pop eax pop eax
; restore the esp ; lets move the stack before the error code and interrupt number
; since we don't want these to be popped anywhere
add esp, 8 add esp, 8
iret iret

View File

@ -15,7 +15,6 @@
#define EXCEPT_INVALID_OPCODE 6 #define EXCEPT_INVALID_OPCODE 6
#define EXCEPT_DEVICE_NOT_AVAILABLE 7 #define EXCEPT_DEVICE_NOT_AVAILABLE 7
#define EXCEPT_DOUBLE_FAULT 8 #define EXCEPT_DOUBLE_FAULT 8
#define EXCEPT_SEG_OVERRUN 9
#define EXCEPT_INVALID_TSS 10 #define EXCEPT_INVALID_TSS 10
#define EXCEPT_SEG_NOT_PRESENT 11 #define EXCEPT_SEG_NOT_PRESENT 11
#define EXCEPT_STACK_SEG_FAULT 12 #define EXCEPT_STACK_SEG_FAULT 12
@ -27,6 +26,9 @@
#define EXCEPT_FLOATING_POINT_ERR_SIMD 19 #define EXCEPT_FLOATING_POINT_ERR_SIMD 19
#define EXCEPT_VIRT 20 #define EXCEPT_VIRT 20
#define EXCEPT_CTRL_PROT 21 #define EXCEPT_CTRL_PROT 21
#define EXCEPT_HYPERVISOR_INJECTION 28
#define EXCEPT_VMM_COMMUNICATION 29
#define EXCEPT_SECURITY_EXCEPTION 30
struct cpu_state { struct cpu_state {
uint32_t eax; uint32_t eax;