mirror of
https://gitlab.os-k.eu/os-k-team/kvisc.git
synced 2023-08-25 14:05:46 +02:00
traps
This commit is contained in:
parent
7f22cd93da
commit
7afa2439bb
@ -597,6 +597,11 @@ def parse_instr(line):
|
||||
if len(word) == 3 and word[0] == word[-1] == "'":
|
||||
word = str(ord(word[1]))
|
||||
|
||||
# register index $reg
|
||||
if len(word) == 4 and word[0] == '$':
|
||||
if word[1:] in pregs:
|
||||
word = str(pregs.index(word[1:]))
|
||||
|
||||
# for now every immediate is 64-bit
|
||||
if is_number(word):
|
||||
# +8 for immediate
|
||||
|
@ -27,7 +27,7 @@ print:
|
||||
|
||||
.1:
|
||||
test b[ax0], b[ax0]
|
||||
jmp.z .2
|
||||
j.z .2
|
||||
|
||||
prn b[ax0]
|
||||
inc ax0
|
||||
|
2
ka/dos.k
2
ka/dos.k
@ -18,7 +18,6 @@ _start:
|
||||
; Preprocessor misc.
|
||||
;
|
||||
include "inc/limits.k"
|
||||
include "inc/regs.k"
|
||||
|
||||
;
|
||||
; Include librairies
|
||||
@ -30,6 +29,7 @@ include "crt/str/string.k"
|
||||
;
|
||||
; Include drivers
|
||||
;
|
||||
include "sys/cpudev.k"
|
||||
include "sys/memdev.k"
|
||||
|
||||
;
|
||||
|
@ -1,66 +0,0 @@
|
||||
; The OS/K Team licenses this file to you under the MIT license.
|
||||
; See the LICENSE file in the project root for more information.
|
||||
|
||||
ID_INV := 0
|
||||
ID_RIP := 1
|
||||
ID_FLG := 2
|
||||
ID_RBP := 3
|
||||
ID_RSP := 4
|
||||
ID_RX0 := 5
|
||||
ID_RX1 := 6
|
||||
ID_RX2 := 7
|
||||
|
||||
ID_RAX := 8
|
||||
ID_RBX := 9
|
||||
ID_RCX := 10
|
||||
ID_RDX := 11
|
||||
ID_RSX := 12
|
||||
ID_RBI := 13
|
||||
ID_RDI := 14
|
||||
ID_RSI := 15
|
||||
|
||||
ID_NX0 := 16
|
||||
ID_NX1 := 17
|
||||
ID_NX2 := 18
|
||||
ID_NX3 := 19
|
||||
ID_NX4 := 20
|
||||
ID_NX5 := 21
|
||||
ID_NX6 := 22
|
||||
ID_NX7 := 23
|
||||
|
||||
ID_AX0 := 24
|
||||
ID_AX1 := 25
|
||||
ID_AX2 := 26
|
||||
ID_AX3 := 27
|
||||
ID_AX4 := 28
|
||||
ID_AX5 := 29
|
||||
ID_AX6 := 30
|
||||
ID_AX7 := 31
|
||||
|
||||
ID_LX0 := 32
|
||||
ID_LX1 := 33
|
||||
ID_LX2 := 34
|
||||
ID_LX3 := 35
|
||||
ID_LX4 := 36
|
||||
ID_LX5 := 37
|
||||
ID_LX6 := 38
|
||||
ID_LX7 := 39
|
||||
|
||||
ID_CR0 := 40
|
||||
ID_CR1 := 41
|
||||
ID_CR2 := 42
|
||||
ID_CR3 := 43
|
||||
ID_CR4 := 44
|
||||
ID_CR5 := 45
|
||||
ID_CR6 := 46
|
||||
ID_CR7 := 47
|
||||
|
||||
ID_SA0 := 48
|
||||
ID_SA1 := 49
|
||||
ID_SA2 := 50
|
||||
ID_SA3 := 51
|
||||
ID_SA4 := 52
|
||||
ID_SA5 := 53
|
||||
ID_SA6 := 54
|
||||
ID_SA7 := 55
|
||||
|
38
ka/main.k
38
ka/main.k
@ -5,9 +5,45 @@
|
||||
; Main function
|
||||
;
|
||||
main:
|
||||
call showoff
|
||||
call cpudev_test
|
||||
ret
|
||||
|
||||
cpudev_test:
|
||||
call RFS.GetLeastAvail
|
||||
mov rbx, rax
|
||||
|
||||
call RFS.GetCurIdx
|
||||
mov rcx, rax
|
||||
|
||||
call RFS.GetMaxIdx
|
||||
mov rdx, rax
|
||||
|
||||
mov ax0, 1
|
||||
call RFS.ActivateFrame
|
||||
|
||||
mov ax0, 1
|
||||
mov ax1, $rip
|
||||
mov ax2, trap0_test
|
||||
call RFS.StoreReg
|
||||
|
||||
mov ax0, 256
|
||||
mov ax1, 1
|
||||
call IDT.AddHandler
|
||||
|
||||
trap 0
|
||||
|
||||
ret
|
||||
|
||||
trap0_test:
|
||||
mov rsp, 0x300000
|
||||
|
||||
mov ax0, .msg
|
||||
call print
|
||||
|
||||
iret
|
||||
|
||||
.msg = "Handling TRAP #0 !"
|
||||
|
||||
showoff:
|
||||
call ramdev_test
|
||||
call bswap_test
|
||||
|
@ -27,14 +27,22 @@ RFS.ActivateFrame:
|
||||
iocall CPUDEV, 21
|
||||
ret
|
||||
|
||||
RFS.CopyFrame:
|
||||
RFS.DeactivateFrame:
|
||||
iocall CPUDEV, 22
|
||||
ret
|
||||
|
||||
RFS.MoveFrame:
|
||||
RFS.CopyFrame:
|
||||
iocall CPUDEV, 23
|
||||
ret
|
||||
|
||||
RFS.MoveFrame:
|
||||
iocall CPUDEV, 24
|
||||
ret
|
||||
|
||||
RFS.SwitchFrame:
|
||||
iocall CPUDEV, 25
|
||||
ret
|
||||
|
||||
RFS.LoadArgs:
|
||||
iocall CPUDEV, 32
|
||||
ret
|
||||
@ -58,3 +66,7 @@ IDT.DelHandler:
|
||||
IDT.QueryHandler:
|
||||
iocall CPUDEV, 66
|
||||
|
||||
IDT.DoneHandling:
|
||||
iocall CPUDEV, 67
|
||||
ret
|
||||
|
||||
|
45
vm/dv/CPUDEV
45
vm/dv/CPUDEV
@ -14,18 +14,53 @@ CPU device function slots:
|
||||
22 i - - y deactivate deactivates register frame #ax0 (losing all its contents!)
|
||||
23 i i - y copyframe copy contents of frame #ax1 into (active) frame #ax0
|
||||
24 i i - y moveframe move frame #ax1 to (inactive) frame index #ax0
|
||||
25-31 - - - - (reserved) (reserved)
|
||||
25 i - - - switchrf switch to register frame #ax0
|
||||
26-31 - - - - (reserved) (reserved)
|
||||
32 i - - - loadargs load registers ax0-ax7 from frame #ax0
|
||||
33 i r - - loadreg rax = register #ax1 from frame #ax0
|
||||
34-47 - - - - (reserved) (reserved)
|
||||
48 i r i y storereg store ax2 into register #ax1 from frame #ax0
|
||||
49-63 - - - - (reserved) (reserved)
|
||||
64 i i - y idtadd mark interrupt #ax0 as handled by register frame #ax1
|
||||
65 i - - y idtdel mark interrupt #ax0 as unhandled
|
||||
66 i - - - idtquery rax = interrupt #ax0 handled? rdx = index of handling frame
|
||||
67+ - - - - (reserved) (reserved)
|
||||
64 i i - y idtadd mark E/I #ax0 as handled by register frame #ax1
|
||||
65 i - - y idtdel mark E/I #ax0 as unhandled
|
||||
66 i - - - idtquery rax = E/I #ax0 has handler? rdx = index of handling frame
|
||||
67 i - - - idtdone signals that handler for E/I #ax0 is done handling
|
||||
68+ - - - - (reserved) (reserved)
|
||||
|
||||
Arguments:
|
||||
i immediate
|
||||
r register index (0=inv, 1=rip, etc...)
|
||||
|
||||
Terminology:
|
||||
interrupt: asynchronous transfer of control to another RFRAME due to some device
|
||||
exception: general term for synchronous transfer of control to another RFRAME
|
||||
fault: hardware exception (slots 1-255)
|
||||
trap: software exception (slots 256-511)
|
||||
|
||||
IDT slots:
|
||||
0 a handler at this slot will receive all exceptions
|
||||
1-255 hardware exceptions (see vm/except.h), OVERRIDES slot 0
|
||||
256-511 software exceptions (TRAP instruction), OVERRIDES slot 0
|
||||
|
||||
512 a handler at this slot will receive all maskable hardware interrupts
|
||||
513-767 maskable hardware interrupts (see ...), OVERRIDES slot 512
|
||||
|
||||
768 a handler in this slot will receive all non-maskable hardware interrupts
|
||||
769-1023 non-maskable hardware interrupts (see ...), OVERRIDES slot 768
|
||||
|
||||
A handler for some E/I must use the 'idtdone' iocall to show that it is done dealing with
|
||||
a certain E/I. If that same E/I happens again before that, the following happens:
|
||||
- if this E/I is a fault (hardware exception), but not #DBF, then a #DBF exception is thrown
|
||||
- if this E/I is #DBF (double fault), the system crashes ("triple fault")
|
||||
- if this E/I is a hardware interrupt, it is queued (*** XXX ***)
|
||||
|
||||
When called, a handler will receive the number of the interrupt it is handling in RAX.
|
||||
(in particular, if exception #25 happens and there are no handler for it, the handler
|
||||
#0 that will be called will receive '25' in its RAX, not 0).
|
||||
This is the value that must be passed to the 'initdone' iocall.
|
||||
|
||||
Clearing the interrupt flag prevents (and queues) maskable hardware interrupts
|
||||
|
||||
Note: RFRAME #0 *cannot* handle interrupts, as a value of 0 in an IDT slot
|
||||
indicates than there are no handler for the corresponding exception/interrupt
|
||||
|
||||
|
207
vm/dv/cpudev.c
207
vm/dv/cpudev.c
@ -10,15 +10,21 @@
|
||||
//
|
||||
// Register frames
|
||||
//
|
||||
reg_t **rfs = NULL;
|
||||
ulong **rfs = NULL;
|
||||
|
||||
size_t current_idx = 0;
|
||||
size_t rfs_used = 0;
|
||||
size_t rfs_current_idx = 0;
|
||||
|
||||
#define CHK_INDEX(idx) \
|
||||
if ((ulong)idx > MAX_RFRAME_IDX) \
|
||||
#define CHK_INDEX(idx) \
|
||||
if ((size_t)idx > MAX_RFRAME_IDX) \
|
||||
_except(ctx, E_UDF, "cpudev: invalid rframe index: #%u", idx);
|
||||
|
||||
#define CHK_FRAME(idx) \
|
||||
CHK_INDEX(idx); \
|
||||
if (rfs[idx] == NULL) \
|
||||
_except(ctx, E_UDF, \
|
||||
"cpudev: operation on inactive reframe #%u", idx);
|
||||
|
||||
//----------------------------------------------------------------------------//
|
||||
|
||||
long cpudev_getmaxidx(ctx_t *ctx, dev_t *dev)
|
||||
@ -35,7 +41,7 @@ long cpudev_getrfusage(ctx_t *ctx, dev_t *dev)
|
||||
|
||||
long cpudev_getcuridx(ctx_t *ctx, dev_t *dev)
|
||||
{
|
||||
rax = current_idx;
|
||||
rax = rfs_current_idx;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -75,21 +81,184 @@ long cpudev_activate(ctx_t *ctx, dev_t *dev)
|
||||
_except(ctx, E_UDF,
|
||||
"cpudev: activating already activated rframe: #%u", ax0);
|
||||
|
||||
rfs[ax0] = calloc(NREGS, sizeof(ulong));
|
||||
|
||||
if (rfs[ax0] == 0)
|
||||
return -1;
|
||||
|
||||
rfs_used++;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
long cpudev_deactivate(ctx_t *ctx, dev_t *dev)
|
||||
{
|
||||
CHK_INDEX(ax0);
|
||||
CHK_FRAME(ax0);
|
||||
|
||||
if (ax0 == 0)
|
||||
_except(ctx, E_UDF, "cpudev: deactivating rframe #0 (arch_r)");
|
||||
_except(ctx, E_UDF, "cpudev: deactivating rframe #0");
|
||||
|
||||
free(rfs[ax0]);
|
||||
rfs[ax0] = NULL;
|
||||
|
||||
rfs_used--;
|
||||
assert(rfs_used > 0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------//
|
||||
|
||||
long cpudev_copyframe(ctx_t *ctx, dev_t *dev)
|
||||
{
|
||||
CHK_FRAME(ax0);
|
||||
CHK_FRAME(ax1);
|
||||
|
||||
if (ax0 == ax1)
|
||||
return -1;
|
||||
|
||||
memcpy(rfs[ax0], rfs[ax1], NREGS * sizeof(ulong));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
long cpudev_moveframe(ctx_t *ctx, dev_t *dev)
|
||||
{
|
||||
CHK_INDEX(ax0);
|
||||
CHK_FRAME(ax1);
|
||||
|
||||
if (ax1 == 0)
|
||||
_except(ctx, E_UDF, "cpudev: trying to move frame #0");
|
||||
|
||||
if (rfs[ax0] != NULL)
|
||||
_except(ctx, E_UDF, "cpudev: trying to move frame #%u "
|
||||
"active frame #%u", ax1, ax0);
|
||||
|
||||
rfs[ax0] = rfs[ax1];
|
||||
rfs[ax1] = NULL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
long cpudev_switchframe(ctx_t *ctx, dev_t *dev)
|
||||
{
|
||||
CHK_FRAME(ax0);
|
||||
|
||||
ulong cur_rx0 = R(RX0);
|
||||
|
||||
rfs_current_idx = ax0;
|
||||
ctx->rf = rfs[ax0];
|
||||
R(RX0) = cur_rx0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------//
|
||||
|
||||
long cpudev_loadargs(ctx_t *ctx, dev_t *dev)
|
||||
{
|
||||
CHK_FRAME(ax0);
|
||||
|
||||
ax7 = rfs[ax0][AX7];
|
||||
ax6 = rfs[ax0][AX6];
|
||||
ax5 = rfs[ax0][AX5];
|
||||
ax4 = rfs[ax0][AX4];
|
||||
ax3 = rfs[ax0][AX3];
|
||||
ax2 = rfs[ax0][AX2];
|
||||
ax1 = rfs[ax0][AX1];
|
||||
ax0 = rfs[ax0][AX0];
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
||||
long cpudev_loadreg(ctx_t *ctx, dev_t *dev)
|
||||
{
|
||||
CHK_FRAME(ax0);
|
||||
|
||||
if ((ushort)ax1 >= NREGS)
|
||||
_except(ctx, E_UDF, "cpudev: register index out of range: #%u", ax1);
|
||||
|
||||
R(ax1) = rfs[ax0][ax1];
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
long cpudev_storereg(ctx_t *ctx, dev_t *dev)
|
||||
{
|
||||
CHK_FRAME(ax0);
|
||||
|
||||
if ((ushort)ax1 >= NREGS)
|
||||
_except(ctx, E_UDF, "cpudev: register index out of range: #%u", ax1);
|
||||
|
||||
rfs[ax0][ax1] = ax2;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------//
|
||||
|
||||
#define CHK_IDT_INDEX(idx) \
|
||||
if ((ulong)idx >= IDT_SLOTS) \
|
||||
_except(ctx, E_UDF, "cpudev: invalid IDT slot index: #%u", idx);
|
||||
|
||||
/* except.h */
|
||||
ulong idt[IDT_SLOTS] = { 0 };
|
||||
bool idt_masked[IDT_SLOTS] = { 0 }; // deliberately masked by software
|
||||
bool idt_handling[IDT_SLOTS] = { 0 }; // a handler is already running
|
||||
|
||||
long cpudev_idtadd(ctx_t *ctx, dev_t *dev)
|
||||
{
|
||||
CHK_FRAME(ax1);
|
||||
CHK_IDT_INDEX(ax0);
|
||||
|
||||
if (idt[ax0] != 0)
|
||||
_except(ctx, E_UDF, "cpudev: IDT slot index already in use: #%u", ax0);
|
||||
|
||||
assert(idt_handling[ax0] == 0);
|
||||
|
||||
idt[ax0] = ax1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
long cpudev_idtdel(ctx_t *ctx, dev_t *dev)
|
||||
{
|
||||
CHK_IDT_INDEX(ax0);
|
||||
|
||||
if (idt[ax0] == 0)
|
||||
_except(ctx, E_UDF, "cpudev: IDT slot index not in use: #%u", ax0);
|
||||
|
||||
idt[ax0] = 0;
|
||||
idt_handling[ax0] = 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
long cpudev_idtquery(ctx_t *ctx, dev_t *dev)
|
||||
{
|
||||
if (ax0 >= IDT_SLOTS || idt[ax0] == 0)
|
||||
rax = rdx = 0;
|
||||
|
||||
else {
|
||||
rax = 1;
|
||||
rdx = idt[ax0];
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
long cpudev_idtdone(ctx_t *ctx, dev_t *dev)
|
||||
{
|
||||
CHK_IDT_INDEX(ax0);
|
||||
|
||||
if (idt_handling[ax0] == 0)
|
||||
_except(ctx, E_UDF, "cpudev: idtdone, not handling E/I #%u", ax0);
|
||||
|
||||
idt_handling[ax0]--;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------//
|
||||
|
||||
long cpudev_poweron(ctx_t *ctx, dev_t *dev)
|
||||
@ -99,7 +268,7 @@ long cpudev_poweron(ctx_t *ctx, dev_t *dev)
|
||||
if (rfs == NULL)
|
||||
return -1;
|
||||
|
||||
rfs[0] = ctx->r;
|
||||
rfs[0] = ctx->rf;
|
||||
rfs_used = 1;
|
||||
|
||||
dev->state = DEVGOOD;
|
||||
@ -111,14 +280,35 @@ long cpudev_poweron(ctx_t *ctx, dev_t *dev)
|
||||
dev->fslots[20] = cpudev_isactive;
|
||||
dev->fslots[21] = cpudev_activate;
|
||||
dev->fslots[22] = cpudev_deactivate;
|
||||
dev->fslots[23] = cpudev_copyframe;
|
||||
dev->fslots[24] = cpudev_moveframe;
|
||||
dev->fslots[25] = cpudev_switchframe;
|
||||
|
||||
dev->fslots[32] = cpudev_loadargs;
|
||||
dev->fslots[33] = cpudev_loadreg;
|
||||
dev->fslots[48] = cpudev_storereg;
|
||||
|
||||
dev->fslots[64] = cpudev_idtadd;
|
||||
dev->fslots[65] = cpudev_idtdel;
|
||||
dev->fslots[66] = cpudev_idtquery;
|
||||
dev->fslots[67] = cpudev_idtdone;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
long cpudev_poweroff(ctx_t *ctx, dev_t *dev)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
if (rfs)
|
||||
{
|
||||
for (i = 0; i <= MAX_RFRAME_IDX; i++)
|
||||
free(rfs[i]);
|
||||
|
||||
free(rfs);
|
||||
}
|
||||
|
||||
dev->state = DEVPWOF;
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -137,5 +327,6 @@ dev_t cpudev =
|
||||
.revis = KARCH_REVIS,
|
||||
|
||||
.fpwon = cpudev_poweron,
|
||||
.fpwoff = cpudev_poweroff,
|
||||
};
|
||||
|
||||
|
17
vm/in/INSTRS
17
vm/in/INSTRS
@ -563,6 +563,23 @@ bswap rm rim
|
||||
wswap rm rim
|
||||
dswap rm rim
|
||||
|
||||
#---------------------------------------------------------------------------#
|
||||
# E/I handling instructions #
|
||||
#---------------------------------------------------------------------------#
|
||||
|
||||
#
|
||||
# Trap into exception handler (TRAP)
|
||||
#
|
||||
# Throw:
|
||||
# #ILL if $1 > 255
|
||||
# #($1+256) otherwise
|
||||
#
|
||||
trap rim
|
||||
|
||||
#
|
||||
# Return from exception/interrupt (IRET)
|
||||
#
|
||||
iret
|
||||
|
||||
#---------------------------------------------------------------------------#
|
||||
# Misc. instructions #
|
||||
|
28
vm/in/trap.c
Normal file
28
vm/in/trap.c
Normal file
@ -0,0 +1,28 @@
|
||||
// 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 <in/instrs.h>
|
||||
|
||||
//----------------------------------------------------------------------------//
|
||||
|
||||
IMPL_START_1(trap)
|
||||
{
|
||||
if (v1 > 255)
|
||||
_except(ctx, E_ILL, "TRAP number greater than 255");
|
||||
|
||||
_except(ctx, v1 + 256, "TRAP instruction");
|
||||
}
|
||||
IMPL_END;
|
||||
|
||||
//----------------------------------------------------------------------------//
|
||||
|
||||
// XXX more checks
|
||||
|
||||
IMPL_START_0(iret)
|
||||
{
|
||||
rip = R(CR6);
|
||||
rfs_current_idx = R(CR7);
|
||||
ctx->rf = rfs[R(CR7)];
|
||||
}
|
||||
IMPL_END;
|
||||
|
@ -5,26 +5,96 @@
|
||||
|
||||
int dying = 0;
|
||||
|
||||
void _except(ctx_t *ctx, int code, char *fmt, ...)
|
||||
void _except(ctx_t *ctx, int _code, char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
ulong handler;
|
||||
uint code = _code;
|
||||
|
||||
enable_stdin_echoing();
|
||||
ulong orig_frame;
|
||||
|
||||
if (dying)
|
||||
{
|
||||
log("Exception thrown while dying=1\n");
|
||||
exit(-12);
|
||||
}
|
||||
else dying = 1;
|
||||
|
||||
log("\nException %d - ", code);
|
||||
log("\nException %u - ", code);
|
||||
|
||||
va_start(ap, fmt);
|
||||
vlog(fmt, ap);
|
||||
va_end(ap);
|
||||
|
||||
log("\n");
|
||||
log("\n\n");
|
||||
|
||||
//
|
||||
// Interrupted earlier?
|
||||
//
|
||||
|
||||
if (dying)
|
||||
{
|
||||
log("Exception thrown while dying=1\n");
|
||||
enable_stdin_echoing();
|
||||
exit(-12);
|
||||
}
|
||||
|
||||
if (code >= IDT_SLOTS)
|
||||
goto actually_die;
|
||||
|
||||
//
|
||||
// Check for E/I handlers
|
||||
//
|
||||
if (idt[code] == 0)
|
||||
{
|
||||
if (code < 512 && code != E_DBF)
|
||||
handler = idt[0];
|
||||
|
||||
else if (code < 768)
|
||||
handler = idt[512];
|
||||
|
||||
else
|
||||
handler = idt[768];
|
||||
}
|
||||
|
||||
else
|
||||
handler = idt[code];
|
||||
|
||||
// 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(ctx, E_DBF, "Double Fault; previously handling: #%u", code);
|
||||
|
||||
// XXX Queue TRAPs and INTs
|
||||
else
|
||||
goto actually_die;
|
||||
}
|
||||
|
||||
// Is this a valid frame?
|
||||
if (rfs[handler] != NULL)
|
||||
{
|
||||
orig_frame = rfs_current_idx;
|
||||
|
||||
ctx->rf = rfs[handler];
|
||||
rfs_current_idx = handler;
|
||||
|
||||
rax = code;
|
||||
R(CR6) = rip;
|
||||
R(CR7) = orig_frame;
|
||||
|
||||
idt_handling[code]++;
|
||||
|
||||
main_loop();
|
||||
}
|
||||
|
||||
actually_die:
|
||||
|
||||
dying = 1;
|
||||
|
||||
enable_stdin_echoing();
|
||||
|
||||
dumpregs(ctx);
|
||||
log("\n");
|
||||
|
@ -1,14 +1,24 @@
|
||||
// The OS/K Team licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
#define IDT_SLOTS 1024
|
||||
|
||||
extern ulong **rfs;
|
||||
extern size_t rfs_current_idx;
|
||||
|
||||
extern ulong idt[IDT_SLOTS];
|
||||
extern bool idt_masked[IDT_SLOTS]; // delibarately masked by software
|
||||
extern bool idt_handling[IDT_SLOTS]; // a handler is already running
|
||||
|
||||
enum
|
||||
{
|
||||
E_SHT, // Shutdown instruction
|
||||
E_UDF, // Undefined behavior
|
||||
E_IMP, // Not implemented
|
||||
E_ILL, // Ill-formed
|
||||
E_ACC, // Invalid access
|
||||
E_ILL, // Ill-formed instruction
|
||||
E_ACC, // Invalid memory access
|
||||
E_SYS, // Supervisor only
|
||||
E_DBF, // Double fault
|
||||
E_IMP, // Not implemented
|
||||
E_ALI, // Alignment error
|
||||
E_STA, // Stack misalignment
|
||||
E_STU, // Stack underflow
|
||||
@ -17,4 +27,5 @@ enum
|
||||
|
||||
extern int dying;
|
||||
|
||||
void main_loop(void) __attribute__((__noreturn__));
|
||||
void _except(ctx_t *, int, char *, ...) __attribute__((__noreturn__));
|
||||
|
25
vm/pc/main.c
25
vm/pc/main.c
@ -62,6 +62,19 @@ void sigsegv(int _)
|
||||
sigcommon();
|
||||
}
|
||||
|
||||
void main_loop(void)
|
||||
{
|
||||
//
|
||||
// Start decoding
|
||||
//
|
||||
while (1) {
|
||||
decode(&main_ctx);
|
||||
|
||||
if (main_ctx.step)
|
||||
getchar();
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
FILE *fwfile;
|
||||
@ -80,6 +93,7 @@ int main(int argc, char **argv)
|
||||
// Signal handling
|
||||
//
|
||||
signal(SIGINT, sigint);
|
||||
signal(SIGBUS, sigsegv);
|
||||
signal(SIGSEGV, sigsegv);
|
||||
|
||||
//
|
||||
@ -150,15 +164,6 @@ int main(int argc, char **argv)
|
||||
}
|
||||
|
||||
disable_stdin_echoing();
|
||||
|
||||
//
|
||||
// Start decoding
|
||||
//
|
||||
while (1) {
|
||||
decode(&main_ctx);
|
||||
|
||||
if (main_ctx.step)
|
||||
getchar();
|
||||
}
|
||||
main_loop();
|
||||
}
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
// 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/arch.h>
|
||||
#include <pc/dev.h>
|
||||
|
||||
reg_t arch_r[] =
|
||||
{
|
||||
@ -79,12 +79,14 @@ reg_t arch_r[] =
|
||||
log("%s=0x%-16lX ", r->name, R(i)); \
|
||||
} \
|
||||
|
||||
extern size_t rfs_current_idx;
|
||||
|
||||
void dumpregs(ctx_t *ctx)
|
||||
{
|
||||
int i;
|
||||
reg_t *r;
|
||||
|
||||
assert(inv == 0);
|
||||
log("Current RFRAME index: #%u\n", rfs_current_idx);
|
||||
|
||||
DUMPREGS(RAX, RDI);
|
||||
DUMPREGS(AX0, AX3);
|
||||
@ -94,6 +96,7 @@ void dumpregs(ctx_t *ctx)
|
||||
DUMPREGS(NX0, NX3);
|
||||
DUMPREGS(SA0, SA3);
|
||||
DUMPREGS(CR0, CR3);
|
||||
DUMPREGS(CR4, CR7);
|
||||
|
||||
|
||||
log("\n\nrip=0x%-16lX rsp=0x%-16lX rbp=0x%-16lX rx0=%-16lu\n\n",
|
||||
@ -107,5 +110,7 @@ void dumpregs(ctx_t *ctx)
|
||||
!!(flg&ZF), !!(flg&SF),
|
||||
!!(flg&PF), !!(flg&DF),
|
||||
!!(cr0&IF), !!(cr0&UF));
|
||||
|
||||
assert(inv == 0);
|
||||
}
|
||||
|
||||
|
@ -12,7 +12,7 @@ void enable_stdin_echoing(void)
|
||||
}
|
||||
|
||||
void disable_stdin_echoing(void)
|
||||
{
|
||||
{return;
|
||||
struct termios t;
|
||||
tcgetattr(0, &t);
|
||||
t.c_lflag &= ~ECHO;
|
||||
|
Loading…
x
Reference in New Issue
Block a user