diff --git a/Makefile b/Makefile index 78c5085..489054c 100644 --- a/Makefile +++ b/Makefile @@ -13,6 +13,12 @@ cobj=$(csrc:%.c=%.o) kernel:$(asmobj) $(cobj) linker.ld $(CXX) $(LDFLAGS) $(cobj) $(asmobj) -o $@ -T linker.ld +#https://gcc.gnu.org/onlinedocs/gcc/x86-Function-Attributes.html#x86-Function-Attributes +exception_handler.o:exception_handler.c + $(CC) $(CPPFLAGS) $(CFLAGS) -mgeneral-regs-only -c $< +irq_handler.o:irq_handler.c + $(CC) $(CPPFLAGS) $(CFLAGS) -mgeneral-regs-only -c $< + %.o:%.asm $(AS) $(ASFLAGS) -o $@ $< diff --git a/exception.c b/exception.c new file mode 100644 index 0000000..d2743dc --- /dev/null +++ b/exception.c @@ -0,0 +1,24 @@ +#include "exception.h" +#include "idt.h" +#include "interrupt.h" +#include "irq.h" + +exception_handler exception_handler_array[EXCEPTION_NUM] = { + NULL, +}; + +int exceptionSetRoutine(int exception, exception_handler handler) +{ + uint32_t flags; + if ((exception < 0) || exception >= EXCEPTION_NUM) + return -1; + + disable_IRQs(flags); + + exception_handler_array[exception] = handler; + + idt_set_handler(EXCEPTION_INTERRUPT_BASE_ADDRESS + exception, (unsigned int)handler, + 0); + restore_IRQs(flags); + return 0; +} diff --git a/exception.h b/exception.h new file mode 100644 index 0000000..465f752 --- /dev/null +++ b/exception.h @@ -0,0 +1,46 @@ +#pragma once +#include "interrupt.h" +#include "types.h" + +#define EXCEPTION_INTERRUPT_BASE_ADDRESS 0 + +// list and description https://wiki.osdev.org/Exceptions + +#define EXCEPTION_DIVIDE_ZERO 0 +#define EXCEPTION_DEBUG 1 +#define EXCEPTION_NMI 2 +#define EXCEPTION_BREAKPOINT 3 +#define EXCEPTION_OVERFLOW 4 +#define EXCEPTION_BOUND_RANGE_EXCEEDED 5 +#define EXCEPTION_INVALID_OPCODE 6 +#define EXCEPTION_DEVICE_NOT_AVAILABLE 7 +#define EXCEPTION_DOUBLE_FAULT 8 +#define EXCEPTION_COPRO_OVERRUN 9 +#define EXCEPTION_INVALID_TSS 10 +#define EXCEPTION_SEGMENT_NOT_PRESENT 11 +#define EXCEPTION_STACK_SEGMENT_FAULT 12 +#define EXCEPTION_GENERAL_PROTECTION_FAULT 13 +#define EXCEPTION_PAGE_FAULT 14 +#define EXCEPTION_RESERVED_1 15 +#define EXCEPTION_X87_FP_EXCEPTION 16 +#define EXCEPTION_ALIGNMENT_CHECK 17 +#define EXCEPTION_MACHINE_CHECK 18 +#define EXCEPTION_SIMD_FP 19 +#define EXCEPTION_VIRTUALIZATION 20 +#define EXCEPTION_RESERVED_2 21 +#define EXCEPTION_RESERVED_3 22 +#define EXCEPTION_RESERVED_4 23 +#define EXCEPTION_RESERVED_5 24 +#define EXCEPTION_RESERVED_6 25 +#define EXCEPTION_RESERVED_7 26 +#define EXCEPTION_RESERVED_8 27 +#define EXCEPTION_RESERVED_9 28 +#define EXCEPTION_RESERVED_10 29 +#define EXCEPTION_SECURITY 30 +#define EXCEPTION_RESERVED_11 31 + +#define EXCEPTION_NUM 32 + +typedef void (*exception_handler) (struct interrupt_frame *frame, ulong error_code); +int exceptionSetRoutine(int exception, exception_handler handler); + diff --git a/exception_handler.c b/exception_handler.c new file mode 100644 index 0000000..91fcc99 --- /dev/null +++ b/exception_handler.c @@ -0,0 +1,11 @@ +#include "exception.h" +#include "vga.h" + +// Need GCC > 6 +__attribute__ ((interrupt)) +void print_handler(struct interrupt_frame *frame, ulong error_code){ + + printString("EXCEPTION", RED, BLACK, 0, 6); + (void) frame; + (void) error_code; +} diff --git a/interrupt.h b/interrupt.h new file mode 100644 index 0000000..037f069 --- /dev/null +++ b/interrupt.h @@ -0,0 +1,10 @@ +#pragma once +#include "types.h" + +struct interrupt_frame; + +//Exception +void print_handler(struct interrupt_frame *frame, ulong error_code); + +//IRQ +void keyboard_handler(struct interrupt_frame *frame); diff --git a/irq.h b/irq.h index 50c554f..aab25f0 100644 --- a/irq.h +++ b/irq.h @@ -1,4 +1,5 @@ #pragma once +#include "interrupt.h" #define save_flags(flags) asm volatile("pushfl ; popl %0" : "=g"(flags)::"memory") #define restore_flags(flags) asm volatile("push %0; popfl" ::"g"(flags) : "memory") @@ -34,6 +35,6 @@ // An handler should finish by the iret opcode -> https://wiki.osdev.org/Interrupt_Service_Routines // That's why we use wrapper around them or the gcc interrupt attribut // __attribute__((interrupt)) void (*irq_handler)(int irq); -typedef void (*irq_handler)(int *irq); +typedef void (*irq_handler)(struct interrupt_frame *frame); int irqSetup(); int irqSetRoutine(int irq, irq_handler handler); diff --git a/irq_handler.c b/irq_handler.c new file mode 100644 index 0000000..fc50e7a --- /dev/null +++ b/irq_handler.c @@ -0,0 +1,7 @@ +#include "interrupt.h" + +// Need GCC > 6 +__attribute__((interrupt)) void keyboard_handler(struct interrupt_frame *frame) +{ + (void)frame; +} diff --git a/main.c b/main.c index 3850668..243b5d2 100644 --- a/main.c +++ b/main.c @@ -1,5 +1,7 @@ +#include "exception.h" #include "gdt.h" #include "idt.h" +#include "interrupt.h" #include "io.h" #include "irq.h" #include "types.h" @@ -22,15 +24,6 @@ void cpuid(int code, uint32_t *a, uint32_t *d) asm volatile("cpuid" : "=a"(*a), "=d"(*d) : "0"(code) : "ebx", "ecx"); } -void keyboard_handler(int *id) -{ - __asm__("pushal"); - (void)id; - const char *tictac = "tic tac"; - const short color = RED; - printString(tictac, color, BLACK, 0, 3); - __asm__("popal; leave; iret"); -} void kmain() { @@ -42,11 +35,16 @@ void kmain() printString("Setting up IRQ", color, BLACK, 0, 1); irqSetup(); + printString("Setting up IRQ_KEYBOARD", color, BLACK, 0, 1); irqSetRoutine(IRQ_KEYBOARD, keyboard_handler); + printString("Enabling HW interrupts", color, BLACK, 0, 1); + exceptionSetRoutine(EXCEPTION_DOUBLE_FAULT, print_handler); // Enabling the HW interrupts - //asm volatile("sti\n"); + asm volatile("sti\n"); + printString("Idling", color, BLACK, 0, 2); while (1) { char c = getScancode(); printChar(c, color, BLACK, 0, 5); } + printString("exiting", color, BLACK, 0, 3); }