#include "exception.h" #include "cpu_context.h" #include "idt.h" #include "interrupt.h" #include "irq.h" #include "klibc.h" #include "process.h" #include "thread.h" #include "types.h" #include "uaddrspace.h" #include "vga.h" exception_handler exception_handler_array[EXCEPTION_NUM] = { NULL, }; extern vaddr_t exception_handler_wrapper_array[EXCEPTION_NUM]; void exception_handler_wrap(int intr, struct cpu_state *frame) { if (0 > intr || EXCEPTION_NUM <= intr) { pr_err("Trying to handle unknow exception %d\n", intr); return; } if (exception_handler_array[intr] != NULL) exception_handler_array[intr](frame, intr); } 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)exception_handler_wrapper_array[exception], 0); restore_IRQs(flags); return 0; } void print_handler(struct cpu_state *frame, ulong intr) { VGAPrintf(RED, BLACK, 0, VGA_HEIGHT - 1, "EXCEPTION %lu", intr); printf("Exception %lu at 0x%p\n", intr, (void *)cpu_context_get_PC(frame)); asm("hlt"); } void pagefault_handler(struct cpu_state *frame, ulong intr) { // PAGE_FAULT is a interrupt with an error code (see exception_wrapper.S) uint32_t error_code = cpu_context_get_EX_err(frame); struct thread *current = getCurrentThread(); if (cpu_context_is_in_user_mode(current->cpuState)) { assert(frame == current->cpuState); // pagefault in kernel not supported ATM struct uAddrSpace *as = processGetAddrSpace(current->process); vaddr_t faultAddr = cpu_context_get_EX_faulting_vaddr(frame); int needMMUSetup = (uAddrSpaceGetMMUContext(as) != getCurrentThread()->squattedContext); if (needMMUSetup) { threadChangeCurrentContext(uAddrSpaceGetMMUContext(as)); } if (!uAddrSpaceHeapCheckNAlloc(as, faultAddr)) goto release_context; int ret = uAddrSpaceSolvePageFault(as, faultAddr, error_code & 0x2); if (!ret) goto release_context; printf( "page fault while in thread [%s] at 0x%p when trying to access 0x%p err_code 0x%x ressource ret %d\n", current->name, (void *)cpu_context_get_PC(frame), (void *)faultAddr, error_code, ret); printf("Killing User Thread\n"); threadExit(); release_context: if (needMMUSetup) threadChangeCurrentContext(NULL); return; } VGAPrintf(RED, BLACK, 0, VGA_HEIGHT - 1, "PAGE FAULT %d", intr); for (;;) continue; } int exceptionSetup() { for (int i = 0; i < EXCEPTION_NUM; i++) { exceptionSetRoutine(i, print_handler); } exceptionSetRoutine(EXCEPTION_PAGE_FAULT, pagefault_handler); return 0; }