matos/arch/x86/exception.c

76 lines
2.0 KiB
C

#include "exception.h"
#include "cpu_context.h"
#include "idt.h"
#include "interrupt.h"
#include "irq.h"
#include "klibc.h"
#include "kthread.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)
{
int intNbInt = intr;
VGAPrintf(RED, BLACK, 0, VGA_HEIGHT - 1, "EXCEPTION %d %d", intNbInt, intr);
printf("Exception %d (Err %d) at 0x%x\n", intr, intr,
cpu_context_get_PC(frame));
asm("hlt");
}
void pagefault_handler(struct cpu_state *frame, ulong intr)
{
// A page fault has occurred.
// The faulting address is stored in the CR2 register.
uint32_t faulting_address;
asm volatile("mov %%cr2, %0" : "=r"(faulting_address));
struct kthread *current = getCurrentThread();
printf("page fault while in thread %s at 0x%x 0x%x\n", current->name, faulting_address,
cpu_context_get_PC(frame));
VGAPrintf(RED, BLACK, 0, VGA_HEIGHT - 1, "PAGE FAULT %d", intr);
(void)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;
}