kvisc/vm/pc/except.c

121 lines
2.1 KiB
C

// The OS/K Team licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
#include <pc/device.h>
int dying = 0;
void _except(int _code, char *fmt, ...)
{
va_list ap;
ulong handler;
uint code = _code;
uint effcode;
ulong orig_frame;
//
// Interrupted earlier?
//
if (dying)
{
logerr("Exception thrown while dying=1\n");
exit(-12);
}
if (code >= IDT_SLOTS || code == 1023)
goto actually_die;
//
// Check for E/I handlers
//
if (idt[code] == 0)
{
if (code == E_DBF)
effcode = E_DBF;
else if (code < 512)
effcode = 0;
else if (code < 768)
effcode = 512;
else
effcode = 768;
}
else
effcode = code;
handler = idt[effcode];
// Found nothing?
if (handler == 0)
goto actually_die; // oh well
// Is another handler already running?
if (idt_handling[code] > 0)
{
// Triple fault?
if (code == E_DBF)
goto actually_die;
// Double fault then?
if (code < 512)
_except(E_DBF, "Double Fault; previously handling: #%u", code);
// Todo: queue INTs
else
goto actually_die;
}
// Is this a valid frame?
if (rfs[handler] != NULL)
{
if (ctx->dumpsw)
{
trace("\n(Caught) Exception %u - ", code);
va_start(ap, fmt);
vprintf(fmt, ap);
va_end(ap);
trace("\n\n");
}
orig_frame = rfs_current_idx;
ctx->rf = rfs[handler];
rfs_current_idx = handler;
R(R12) = code;
R(R13) = effcode;
R(R14) = orig_frame;
R(R15) = R(RIP);
idt_handling[effcode]++;
longjmp(exc_jmp_buf, code);
__builtin_unreachable();
}
actually_die:
logerr("\nException %u - ", code);
va_start(ap, fmt);
vfprintf(stderr, fmt, ap);
va_end(ap);
logerr("\n\n");
dying = 1;
dumpregs();
logerr("\n");
die(code);
}