1
0
mirror of https://gitlab.os-k.eu/os-k-team/kvisc.git synced 2023-08-25 14:05:46 +02:00
This commit is contained in:
julianb0 2019-06-18 22:56:41 +02:00
parent 7f22cd93da
commit 7afa2439bb
No known key found for this signature in database
GPG Key ID: DDF8325C95299A62
15 changed files with 460 additions and 111 deletions

View File

@ -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

View File

@ -27,7 +27,7 @@ print:
.1:
test b[ax0], b[ax0]
jmp.z .2
j.z .2
prn b[ax0]
inc ax0

View File

@ -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"
;

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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,
};

View File

@ -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
View 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;

View File

@ -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");

View File

@ -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__));

View File

@ -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();
}

View File

@ -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);
}

View File

@ -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;