matos/arch/x86/exception.c

108 lines
3.0 KiB
C
Raw Normal View History

2018-07-20 15:41:58 +02:00
#include "exception.h"
2021-10-07 23:54:46 +02:00
#include "cpu_context.h"
2018-07-20 15:41:58 +02:00
#include "idt.h"
#include "interrupt.h"
#include "irq.h"
2021-10-07 23:54:46 +02:00
#include "klibc.h"
2022-09-03 23:32:31 +02:00
#include "process.h"
2021-10-30 14:18:21 +02:00
#include "thread.h"
2022-09-03 23:32:31 +02:00
#include "types.h"
#include "uaddrspace.h"
2021-10-07 23:54:46 +02:00
#include "vga.h"
2018-07-20 15:41:58 +02:00
exception_handler exception_handler_array[EXCEPTION_NUM] = {
NULL,
};
2021-10-07 23:54:46 +02:00
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);
}
2018-07-20 15:41:58 +02:00
int exceptionSetRoutine(int exception, exception_handler handler)
{
uint32_t flags;
if ((exception < 0) || exception >= EXCEPTION_NUM)
return -1;
2018-07-20 15:41:58 +02:00
disable_IRQs(flags);
2018-07-20 15:41:58 +02:00
exception_handler_array[exception] = handler;
2018-07-20 15:41:58 +02:00
2021-10-07 23:54:46 +02:00
idt_set_handler(EXCEPTION_INTERRUPT_BASE_ADDRESS + exception,
(unsigned int)exception_handler_wrapper_array[exception], 0);
restore_IRQs(flags);
return 0;
2018-07-20 15:41:58 +02:00
}
2020-04-29 23:07:01 +02:00
2021-10-07 23:54:46 +02:00
void print_handler(struct cpu_state *frame, ulong intr)
2020-04-29 23:07:01 +02:00
{
VGAPrintf(RED, BLACK, 0, VGA_HEIGHT - 1, "EXCEPTION %lu", intr);
printf("Exception %lu at 0x%p\n", intr, (void *)cpu_context_get_PC(frame));
2021-10-07 23:54:46 +02:00
asm("hlt");
}
2020-04-29 23:07:01 +02:00
2021-10-07 23:54:46 +02:00
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);
2021-10-30 14:08:12 +02:00
struct thread *current = getCurrentThread();
if (cpu_context_is_in_user_mode(current->cpuState)) {
assert(frame == current->cpuState); // pagefault in kernel not supported ATM
2024-02-07 23:14:42 +01:00
struct uAddrSpace *as = processGetAddrSpace(current->process);
vaddr_t faultAddr = cpu_context_get_EX_faulting_vaddr(frame);
2024-02-07 23:14:42 +01:00
int needMMUSetup =
(uAddrSpaceGetMMUContext(as) != getCurrentThread()->squattedContext);
if (needMMUSetup) {
threadChangeCurrentContext(uAddrSpaceGetMMUContext(as));
}
2022-09-03 23:32:31 +02:00
if (!uAddrSpaceHeapCheckNAlloc(as, faultAddr))
2024-02-07 23:14:42 +01:00
goto release_context;
2024-02-07 23:14:42 +01:00
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);
2021-11-05 23:02:23 +01:00
printf("Killing User Thread\n");
threadExit();
2024-02-07 23:14:42 +01:00
release_context:
if (needMMUSetup)
threadChangeCurrentContext(NULL);
return;
2021-11-05 23:02:23 +01:00
}
2024-02-07 23:14:42 +01:00
2021-10-07 23:54:46 +02:00
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);
}
2020-04-29 23:07:01 +02:00
exceptionSetRoutine(EXCEPTION_PAGE_FAULT, pagefault_handler);
2020-04-29 23:07:01 +02:00
return 0;
}