77 lines
2.3 KiB
C++
77 lines
2.3 KiB
C++
#define MODULE "isr"
|
|
|
|
#include "assert.h"
|
|
#include "interrupts/Context.h"
|
|
#include "interrupts/IRQ.h"
|
|
#include "interrupts/Interrupts.h"
|
|
#include "log/Log.h"
|
|
#include "misc/hang.h"
|
|
#include "std/stdio.h"
|
|
#include "thread/Scheduler.h"
|
|
#include "trace/StackTracer.h"
|
|
|
|
extern "C" void common_handler(Context* context)
|
|
{
|
|
ASSERT(Interrupts::is_in_handler());
|
|
if (context->number >= 0x20 && context->number < 0x30)
|
|
{
|
|
Interrupts::ensure_handler(); // restore the "in interrupt flag" if an interrupt happened in the middle of this
|
|
// one
|
|
IRQ::interrupt_handler(context);
|
|
return;
|
|
}
|
|
if (context->number == 13)
|
|
{
|
|
kerrorln("General protection fault at RIP %lx, cs %ld, ss %ld, RSP %lx, error code %ld", context->rip,
|
|
context->cs, context->ss, context->rsp, context->error_code);
|
|
kinfoln("Stack trace:");
|
|
|
|
StackTracer tracer(context->rbp);
|
|
tracer.trace_with_ip(context->rip);
|
|
if (context->cs == 0x8) { PANIC("Fatal: GPF in kernel task"); }
|
|
else
|
|
{
|
|
Interrupts::ensure_handler();
|
|
Scheduler::task_misbehave(context);
|
|
}
|
|
}
|
|
if (context->number == 14)
|
|
{
|
|
Interrupts::disable();
|
|
kerrorln("Page fault in %s (RIP %lx), while trying to access %lx, error code %ld",
|
|
context->cs == 8 ? "ring 0" : "ring 3", context->rip, context->cr2, context->error_code);
|
|
kinfoln("Stack trace:");
|
|
|
|
StackTracer tracer(context->rbp);
|
|
tracer.trace_with_ip(context->rip);
|
|
|
|
if (context->cs == 0x8) { PANIC("Fatal: Page fault in kernel task"); }
|
|
else
|
|
{
|
|
Interrupts::ensure_handler();
|
|
Scheduler::task_misbehave(context);
|
|
}
|
|
}
|
|
if (context->number == 8)
|
|
{
|
|
kerrorln("Double fault, halting");
|
|
kinfoln("Stack trace:");
|
|
|
|
StackTracer tracer(context->rbp);
|
|
tracer.trace_with_ip(context->rip);
|
|
|
|
hang();
|
|
}
|
|
if (context->number == 48)
|
|
{
|
|
Interrupts::ensure_handler();
|
|
Scheduler::task_yield(context);
|
|
}
|
|
if (context->number == 49)
|
|
{
|
|
Interrupts::ensure_handler();
|
|
Scheduler::task_exit(context);
|
|
}
|
|
if (context->number == 256) { kwarnln("Unused interrupt"); }
|
|
return;
|
|
} |