Add Exception handling
This commit is contained in:
parent
2bbd40acf6
commit
2f3b34475b
5 changed files with 151 additions and 25 deletions
|
@ -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
71
kernel/exception.c
Normal 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
34
kernel/exception_list.c
Normal 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;
|
|
@ -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);
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
static const size_t VGA_WIDTH = 80;
|
static const size_t VGA_WIDTH = 80;
|
||||||
static const size_t VGA_HEIGHT = 25;
|
static const size_t VGA_HEIGHT = 25;
|
||||||
|
|
||||||
|
@ -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
|
Loading…
Reference in a new issue