Add Exception handling

This commit is contained in:
Robbe Van Herck 2020-01-09 16:27:19 +01:00
parent 2bbd40acf6
commit 2f3b34475b
No known key found for this signature in database
GPG key ID: A66F76F7B81BD784
5 changed files with 151 additions and 25 deletions

View file

@ -29,11 +29,11 @@ The kernel is based on [the bare bones kernel from the OSDev wiki](https://wiki.
- [x] _Very_ basic memory management - [x] _Very_ basic memory management
- [x] Interrupt handling - [x] Interrupt handling
- [x] Keyboard input - [x] Keyboard input
- [x] Exception handling
- [ ] Filesystem interaction - [ ] Filesystem interaction
- [ ] Show files in directory - [ ] Show files in directory
- [ ] Read files in directory - [ ] Read files in directory
- [ ] Write files in directory - [ ] Write files in directory
- [ ] Exception handling
- [ ] Tests - [ ] Tests
- [ ] Running executables from filesystem - [ ] Running executables from filesystem
- [ ] Better memory management - [ ] Better memory management

71
kernel/exception.c Normal file
View file

@ -0,0 +1,71 @@
#ifndef EXCEPTION_C
#define EXCEPTION_C
#include "terminal.c"
typedef struct interrupt_frame_struct {
uint32_t eip;
uint32_t cs;
uint32_t eflags;
} interrupt_frame;
#define EXCEPTION_HANDLER_NO_ERR(NAME, STR) \
__attribute__((interrupt)) void NAME (interrupt_frame* frame) { \
outb(0x20, 0x20); \
bsod(frame, STR, -1); \
}
#define EXCEPTION_HANDLER_ERR(NAME, STR) \
__attribute__((interrupt)) void NAME (interrupt_frame* frame, uint32_t err_code) { \
outb(0x20, 0x20); \
bsod(frame, STR, err_code); \
}
void bsod(interrupt_frame* frame, char* err_msg, int32_t err_code) {
terminal_initialize();
terminal_writestring("An exception occured: ");
terminal_writestring(err_msg);
if(err_code != -1) {
terminal_writestring(" (error code = 0x");
terminal_writeint(err_code, 16);
terminal_writestring(")");
}
terminal_writestring("\nHere's what we know:\n");
terminal_writestring("eip = 0x");
terminal_writeint(frame->eip, 16);
terminal_writestring("\ncs = 0x");
terminal_writeint(frame->cs, 16);
terminal_writestring("\neflags = 0b");
terminal_writeint(frame->eflags, 2);
for(;;) {
asm("hlt");
}
}
EXCEPTION_HANDLER_NO_ERR(divide_by_zero_handler, "Divide by zero")
EXCEPTION_HANDLER_NO_ERR(debug_handler, "debug")
EXCEPTION_HANDLER_NO_ERR(non_maskable_interrupt_handler, "Non maskable interrupt")
EXCEPTION_HANDLER_NO_ERR(breakpoint_handler, "Breakpoint")
EXCEPTION_HANDLER_NO_ERR(overflow_handler, "Overflow")
EXCEPTION_HANDLER_NO_ERR(bound_range_exceeded_handler, "Bound range exceeded")
EXCEPTION_HANDLER_NO_ERR(invalid_opcode_handler, "Invalid opcode")
EXCEPTION_HANDLER_NO_ERR(device_not_available_handler, "Device not available")
EXCEPTION_HANDLER_ERR(double_fault_handler, "Double fault")
EXCEPTION_HANDLER_NO_ERR(coprocessor_seg_overrun_handler, "Coprocessor seg overrun")
EXCEPTION_HANDLER_ERR(invalid_tss_handler, "Invalid tss")
EXCEPTION_HANDLER_ERR(segment_not_present_handler, "Segment not present")
EXCEPTION_HANDLER_ERR(stack_segment_fault_handler, "Stack segment fault")
EXCEPTION_HANDLER_ERR(general_protection_fault_handler, "General protection fault")
EXCEPTION_HANDLER_ERR(page_fault_handler, "Page fault")
EXCEPTION_HANDLER_NO_ERR(reserved_handler, "Reserved")
EXCEPTION_HANDLER_NO_ERR(x87_fp_exception_handler, "x87 floating point exception")
EXCEPTION_HANDLER_NO_ERR(alignment_check_handler, "Alignment check");
EXCEPTION_HANDLER_NO_ERR(machine_check_handler, "Machine check");
EXCEPTION_HANDLER_NO_ERR(simd_fp_exception_handler, "SIMD floating point exception");
EXCEPTION_HANDLER_NO_ERR(virtualization_exception_handler, "Virtualization exception");
EXCEPTION_HANDLER_NO_ERR(security_exception_handler, "Security exception");
#endif //EXCEPTION_C

34
kernel/exception_list.c Normal file
View file

@ -0,0 +1,34 @@
typedef enum exception_enum {
DIVIDE_BY_ZERO = 0,
DEBUG = 1,
NON_MASKABLE_INTERRUPT = 2,
BREAKPOINT = 3,
OVERFLOW = 4,
BOUND_RANGE_EXCEEDED = 5,
INVALID_OPCODE = 6,
DEVICE_NOT_AVAILABLE = 7,
DOUBLE_FAULT = 8, // Error code = 0
COPROCESSOR_SEG_OVERRUN = 9,
INVALID_TSS = 10, // Error code = (invalid selector index)
SEGMENT_NOT_PRESENT = 11, // Error code = (segment selector index)
STACK_SEGMENT_FAULT = 12, // Error code = (segment selector index) if invalid ssi, otherwise 0
GENERAL_PROTECTION_FAULT = 13, // Error code = (segment selector index) if invalid ssi, otherwise 0
PAGE_FAULT = 14, // Error code = bitmap, see https://wiki.osdev.org/Exceptions#Page_Fault
RESERVED_15 = 15,
X87_FP_EXCEPTION = 16,
ALIGNMENT_CHECK = 17,
MACHINE_CHECK = 18,
SIMD_FP_EXCEPTION = 19,
VIRTUALIZATION_EXCEPTION = 20,
RESERVED_21 = 21,
RESERVED_22 = 22,
RESERVED_23 = 23,
RESERVED_24 = 24,
RESERVED_25 = 25,
RESERVED_26 = 26,
RESERVED_27 = 27,
RESERVED_28 = 28,
RESERVED_29 = 29,
SECURITY_EXCEPTION = 30,
RESERVED_31 = 31
} exception;

View file

@ -7,6 +7,8 @@
#include "memory.c" #include "memory.c"
#include "terminal.c" #include "terminal.c"
#include "inline_asm.c" #include "inline_asm.c"
#include "exception.c"
#include "exception_list.c"
#include "drivers/keyboard/keyboard.c" #include "drivers/keyboard/keyboard.c"
typedef struct idt_entry_struct { typedef struct idt_entry_struct {
@ -17,28 +19,9 @@ typedef struct idt_entry_struct {
uint16_t offset_2; // offset bits 16..31 uint16_t offset_2; // offset bits 16..31
} idt_entry; } idt_entry;
struct interrupt_frame {
uint32_t esp;
uint32_t ss;
uint32_t gs;
uint32_t fs;
uint32_t es;
uint32_t ds;
uint32_t ebp;
uint32_t edi;
uint32_t esi;
uint32_t edx;
uint32_t ecx;
uint32_t ebx;
uint32_t eax;
uint32_t eip;
uint32_t cs;
uint32_t eflags;
};
idt_entry IDT[256]; idt_entry IDT[256];
void interrupt_new_handler(int intnum, void (*handler)(struct interrupt_frame*)) { void interrupt_new_handler(int intnum, void (*handler)(interrupt_frame*)) {
uint32_t handler_address = (uint32_t) handler; uint32_t handler_address = (uint32_t) handler;
IDT[intnum].offset_1 = (uint16_t) (handler_address & 0xffff); IDT[intnum].offset_1 = (uint16_t) (handler_address & 0xffff);
IDT[intnum].selector = 0x08; IDT[intnum].selector = 0x08;
@ -68,6 +51,40 @@ void interrupt_init() {
outb(0x21 , 0xff); outb(0x21 , 0xff);
outb(0xA1 , 0xff); outb(0xA1 , 0xff);
// Exceptions
interrupt_new_handler(DIVIDE_BY_ZERO, divide_by_zero_handler);
interrupt_new_handler(DEBUG, debug_handler);
interrupt_new_handler(NON_MASKABLE_INTERRUPT, non_maskable_interrupt_handler);
interrupt_new_handler(BREAKPOINT, breakpoint_handler);
interrupt_new_handler(OVERFLOW, overflow_handler);
interrupt_new_handler(BOUND_RANGE_EXCEEDED, bound_range_exceeded_handler);
interrupt_new_handler(INVALID_OPCODE, invalid_opcode_handler);
interrupt_new_handler(DEVICE_NOT_AVAILABLE, device_not_available_handler);
interrupt_new_handler(DOUBLE_FAULT, double_fault_handler);
interrupt_new_handler(COPROCESSOR_SEG_OVERRUN, coprocessor_seg_overrun_handler);
interrupt_new_handler(INVALID_TSS, invalid_tss_handler);
interrupt_new_handler(SEGMENT_NOT_PRESENT, segment_not_present_handler);
interrupt_new_handler(STACK_SEGMENT_FAULT, stack_segment_fault_handler);
interrupt_new_handler(GENERAL_PROTECTION_FAULT, general_protection_fault_handler);
interrupt_new_handler(PAGE_FAULT, page_fault_handler);
interrupt_new_handler(RESERVED_15, reserved_handler);
interrupt_new_handler(X87_FP_EXCEPTION, x87_fp_exception_handler);
interrupt_new_handler(ALIGNMENT_CHECK, alignment_check_handler);
interrupt_new_handler(MACHINE_CHECK, machine_check_handler);
interrupt_new_handler(SIMD_FP_EXCEPTION, simd_fp_exception_handler);
interrupt_new_handler(VIRTUALIZATION_EXCEPTION, virtualization_exception_handler);
interrupt_new_handler(RESERVED_21, reserved_handler);
interrupt_new_handler(RESERVED_22, reserved_handler);
interrupt_new_handler(RESERVED_23, reserved_handler);
interrupt_new_handler(RESERVED_24, reserved_handler);
interrupt_new_handler(RESERVED_25, reserved_handler);
interrupt_new_handler(RESERVED_26, reserved_handler);
interrupt_new_handler(RESERVED_27, reserved_handler);
interrupt_new_handler(RESERVED_28, reserved_handler);
interrupt_new_handler(RESERVED_29, reserved_handler);
interrupt_new_handler(SECURITY_EXCEPTION, security_exception_handler);
interrupt_new_handler(RESERVED_31, reserved_handler);
interrupt_new_handler(0x21, keyboard_handler); interrupt_new_handler(0x21, keyboard_handler);
uint16_t size = (sizeof(idt_entry) * 256); uint16_t size = (sizeof(idt_entry) * 256);

View file

@ -94,7 +94,7 @@ void terminal_writestring(const char* data) {
terminal_write(data, strlen(data)); terminal_write(data, strlen(data));
} }
char* itoa(int value, char* result, int base) { char* itoa(unsigned int value, char* result, int base) {
// check that the base if valid // check that the base if valid
if (base < 2 || base > 36) { *result = '\0'; return result; } if (base < 2 || base > 36) { *result = '\0'; return result; }
@ -107,8 +107,6 @@ char* itoa(int value, char* result, int base) {
*ptr++ = "zyxwvutsrqponmlkjihgfedcba9876543210123456789abcdefghijklmnopqrstuvwxyz" [35 + (tmp_value - value * base)]; *ptr++ = "zyxwvutsrqponmlkjihgfedcba9876543210123456789abcdefghijklmnopqrstuvwxyz" [35 + (tmp_value - value * base)];
} while ( value ); } while ( value );
// Apply negative sign
if (tmp_value < 0) *ptr++ = '-';
*ptr-- = '\0'; *ptr-- = '\0';
while(ptr1 < ptr) { while(ptr1 < ptr) {
tmp_char = *ptr; tmp_char = *ptr;
@ -118,4 +116,10 @@ char* itoa(int value, char* result, int base) {
return result; return result;
} }
void terminal_writeint(int number, int base) {
char* result = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX";
itoa(number, result, base);
terminal_writestring(result);
}
#endif //TERMINAL_C #endif //TERMINAL_C