mirror of
https://gitlab.os-k.eu/os-k-team/kvisc.git
synced 2023-08-25 14:05:46 +02:00
devices
This commit is contained in:
parent
eb23154e70
commit
51f91c8fb1
1
Makefile
1
Makefile
@ -4,6 +4,7 @@
|
||||
all: kas
|
||||
|
||||
kpc:
|
||||
@rm -f vm/a.out
|
||||
@cd vm && make --no-print-directory
|
||||
|
||||
kas: kpc as/k-as.py as/regs.lst
|
||||
|
18
as/k-as.py
18
as/k-as.py
@ -233,6 +233,24 @@ def parse_preproc(line):
|
||||
assert(written == 8)
|
||||
pdata += written
|
||||
|
||||
# buffer / bss
|
||||
elif tok[2][0] == '[':
|
||||
assert(tok[2][-1] == ']')
|
||||
|
||||
s = tok[2][1:-1].strip()
|
||||
if not is_number(s):
|
||||
print("Invalid bss format: {}".format(line))
|
||||
leave()
|
||||
sys.exit(1)
|
||||
|
||||
i = int(s, base=0)
|
||||
i = i + (8 - i % 8)
|
||||
written = b_data.write(bytearray(i))
|
||||
assert(written == i)
|
||||
|
||||
pdefs[label + "_len"] = s
|
||||
pdata += written
|
||||
|
||||
# string data
|
||||
elif tok[2][0] in "'\"":
|
||||
s = tok[2].strip()
|
||||
|
16
ka/main.k
16
ka/main.k
@ -7,10 +7,20 @@
|
||||
main:
|
||||
enter
|
||||
|
||||
mov ax0, .buf
|
||||
devctl 0, 1
|
||||
|
||||
mov ax0, .buf
|
||||
call print
|
||||
|
||||
prn 10
|
||||
leave
|
||||
ret
|
||||
|
||||
.buf = [32]
|
||||
|
||||
test:
|
||||
enter
|
||||
|
||||
mov ax0, .msg
|
||||
call print
|
||||
|
||||
@ -28,13 +38,11 @@ main:
|
||||
mov ax1, .msg
|
||||
call strcmp
|
||||
|
||||
movt rax, rbx
|
||||
|
||||
leave
|
||||
ret
|
||||
|
||||
.msg = "HelloWorld :)"
|
||||
.buf = "!!!!!!!!!!!!!"
|
||||
.buf = [32]
|
||||
|
||||
;
|
||||
; Exit function
|
||||
|
14
vm/Makefile
14
vm/Makefile
@ -6,26 +6,30 @@ all: k.exe
|
||||
.PHONY: clean
|
||||
.INTERMEDIATE: %.o
|
||||
|
||||
dv_src = $(shell ls dv/*.c)
|
||||
in_src = $(shell ls in/*.c)
|
||||
pc_src = $(shell ls pc/*.c)
|
||||
|
||||
obj = pc/disd.o $(patsubst %.c,%.o,$(pc_src)) $(patsubst %.c,%.o,$(in_src))
|
||||
obj = pc/disd.o
|
||||
obj += $(patsubst %.c,%.o,$(dv_src))
|
||||
obj += $(patsubst %.c,%.o,$(in_src))
|
||||
obj += $(patsubst %.c,%.o,$(pc_src))
|
||||
|
||||
FLAGS=-O2 -g -Wall -fno-builtin-log -I.
|
||||
|
||||
pc/disd.o: i_arch.h */*.h pc/decd.c
|
||||
pc/disd.o: in/i_arch.h */*.h pc/decd.c
|
||||
@cc $(FLAGS) -D_NEED_DISASM -c pc/decd.c -o $@
|
||||
|
||||
%.o: %.c i_arch.h */*.h $(src)
|
||||
%.o: %.c in/i_arch.h */*.h $(src)
|
||||
@cc $(FLAGS) -c $< -o $@
|
||||
|
||||
i_arch.h: in/INSTRS in/arch_i.py
|
||||
in/i_arch.h: in/INSTRS in/arch_i.py
|
||||
@cd in && python3 arch_i.py
|
||||
|
||||
clean:
|
||||
@rm -f */*.o in/arch_i.h
|
||||
|
||||
k.exe: i_arch.h $(obj)
|
||||
k.exe: in/i_arch.h $(obj)
|
||||
@gcc -O2 -Wall $(obj) -o k.exe
|
||||
@rm in/arch_i.h
|
||||
@rm -f */*.o
|
||||
|
39
vm/dv/DEVAPI
Normal file
39
vm/dv/DEVAPI
Normal file
@ -0,0 +1,39 @@
|
||||
# The OS/K Team licenses this file to you under the MIT license.
|
||||
# See the LICENSE file in the project root for more information.
|
||||
|
||||
To communicate with devices, use:
|
||||
devctl #dev #slot
|
||||
iocall #dev #slot
|
||||
|
||||
This will call a function from the device's slot table.
|
||||
It will take registers ax0-ax7 as its parameters, and
|
||||
return a value in rdx:rax.
|
||||
|
||||
The return value in rax is a status value:
|
||||
≥0 ok (>0 only if meaningful)
|
||||
-1 unspecified error
|
||||
-2 no such device
|
||||
-3 device powered off
|
||||
-4 device fatal error
|
||||
-5 device not plugged
|
||||
-6 no such function slot
|
||||
-7 slot not implemented
|
||||
-8 slot reserved
|
||||
-9 invalid parameters
|
||||
-10 to -256 (reserved)
|
||||
< -256 (left to device)
|
||||
|
||||
The slots for "devctl" are architecture-rerserved.
|
||||
They consist of the following functions:
|
||||
Slot Param (ax0) Description
|
||||
0 ptr Write device type into buffer
|
||||
1 ptr Write device name into buffer
|
||||
2 ptr Write device model into buffer
|
||||
3 ptr Write device vendor into buffer
|
||||
4 rax=major, rdx=minor
|
||||
5 rax=feats, rdx=revis
|
||||
6-31 (reserved)
|
||||
|
||||
The slots for "iocall" are device-defined. (They correspond
|
||||
to the "fslots" array of the dev_t structure.) See that
|
||||
particular device's documentation (if any).
|
17
vm/dv/cpu.c
Normal file
17
vm/dv/cpu.c
Normal file
@ -0,0 +1,17 @@
|
||||
// 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 <dv/dev.h>
|
||||
|
||||
dev_t cpudev =
|
||||
{
|
||||
.type = "cpu",
|
||||
.name = "K-CPU",
|
||||
.modl = "K-CPU",
|
||||
.vend = "The OS/K Team",
|
||||
|
||||
.major = 0,
|
||||
.minor = 1,
|
||||
.revis = 0,
|
||||
};
|
||||
|
128
vm/dv/dev.c
Normal file
128
vm/dv/dev.c
Normal file
@ -0,0 +1,128 @@
|
||||
// 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 <dv/dev.h>
|
||||
|
||||
static_assert(sizeof(dev_t) % 8 == 0, "");
|
||||
|
||||
dev_t *devalloc(void)
|
||||
{
|
||||
return calloc(sizeof(dev_t)/sizeof(ulong), sizeof(ulong));
|
||||
}
|
||||
|
||||
void devfree(dev_t *dev)
|
||||
{
|
||||
assert(dev != NULL);
|
||||
|
||||
free(dev);
|
||||
}
|
||||
|
||||
dev_t *devget(ctx_t *ctx, int idx)
|
||||
{
|
||||
if (idx < 0)
|
||||
return NULL;
|
||||
|
||||
int i;
|
||||
dev_t *dev;
|
||||
|
||||
for (i = 0, dev = ctx->dh; dev && i != idx; dev = dev->next, i++);
|
||||
|
||||
return dev;
|
||||
}
|
||||
|
||||
void devattach(ctx_t *ctx, dev_t *dev)
|
||||
{
|
||||
dev_t *it;
|
||||
|
||||
assert(dev != NULL);
|
||||
|
||||
if (ctx->dh) {
|
||||
for (it = ctx->dh; it->next != NULL; it = it->next);
|
||||
|
||||
it->next = dev;
|
||||
}
|
||||
|
||||
else ctx->dh = dev;
|
||||
}
|
||||
|
||||
int devinit(ctx_t *ctx, dev_t *dev)
|
||||
{
|
||||
if (!dev || dev->state != DEVPWOF)
|
||||
return -1;
|
||||
|
||||
if (dev->fpwon)
|
||||
dev->fpwon(ctx, dev);
|
||||
|
||||
else dev->state = DEVGOOD;
|
||||
|
||||
if (!(dev->state == DEVPLUG || dev->state == DEVGOOD))
|
||||
return -1;
|
||||
|
||||
dev->id = random();
|
||||
|
||||
devattach(ctx, dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// NEVER detach while some assembly code
|
||||
// may still be running on the vm!
|
||||
void devdetach(ctx_t *ctx, dev_t *dev)
|
||||
{
|
||||
dev_t *it;
|
||||
|
||||
assert(dev != NULL);
|
||||
|
||||
if (dev == ctx->dh) {
|
||||
ctx->dh = dev->next;
|
||||
}
|
||||
|
||||
for (it = ctx->dh; it; it = it->next) {
|
||||
if (!it)
|
||||
break;
|
||||
|
||||
if (it->next == dev) {
|
||||
it->next = dev->next;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int devfini(ctx_t *ctx, dev_t *dev)
|
||||
{
|
||||
if (dev->state == DEVPWOF || dev->state == DEVFERR) {
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (dev->fpwoff)
|
||||
dev->fpwoff(ctx, dev);
|
||||
|
||||
else dev->state = DEVPWOF;
|
||||
|
||||
if (dev->state != DEVPWOF)
|
||||
goto err;
|
||||
|
||||
devdetach(ctx, dev);
|
||||
return 0;
|
||||
|
||||
err:
|
||||
devdetach(ctx, dev);
|
||||
return -1;
|
||||
}
|
||||
|
||||
int devinitall(ctx_t *ctx)
|
||||
{
|
||||
return devinit(ctx, &cpudev);
|
||||
}
|
||||
|
||||
int devfiniall(ctx_t *ctx)
|
||||
{
|
||||
int failed = 0;
|
||||
|
||||
while (ctx->dh)
|
||||
if (devfini(ctx, ctx->dh) < 0)
|
||||
failed = -1;
|
||||
|
||||
return failed;
|
||||
}
|
||||
|
61
vm/dv/dev.h
Normal file
61
vm/dv/dev.h
Normal file
@ -0,0 +1,61 @@
|
||||
// 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>
|
||||
|
||||
#define DEVLEN 32
|
||||
#define DEVSLOTS 256
|
||||
|
||||
typedef void (*devfn_t)(ctx_t *, dev_t *);
|
||||
|
||||
enum
|
||||
{
|
||||
DEVPWOF, // Power off
|
||||
DEVPLUG, // Unplugged or plugging
|
||||
DEVGOOD, // Plugged and working
|
||||
DEVFERR, // Fatal error
|
||||
};
|
||||
|
||||
struct dev_t
|
||||
{
|
||||
dev_t *next;
|
||||
|
||||
char type[DEVLEN];
|
||||
char name[DEVLEN];
|
||||
char modl[DEVLEN];
|
||||
char vend[DEVLEN];
|
||||
|
||||
int major;
|
||||
int minor;
|
||||
int revis;
|
||||
ulong feats;
|
||||
|
||||
long id;
|
||||
uint state;
|
||||
void *data;
|
||||
|
||||
devfn_t fpwon;
|
||||
devfn_t fpwoff;
|
||||
|
||||
devfn_t fplug;
|
||||
devfn_t funplug;
|
||||
|
||||
devfn_t fslots[DEVSLOTS];
|
||||
};
|
||||
|
||||
dev_t *devalloc(void);
|
||||
void devfree(dev_t *);
|
||||
|
||||
dev_t *devget(ctx_t *, int);
|
||||
|
||||
void devattach(ctx_t *, dev_t *);
|
||||
void devdetach(ctx_t *, dev_t *);
|
||||
|
||||
int devinit(ctx_t *, dev_t *);
|
||||
int devfini(ctx_t *, dev_t *);
|
||||
|
||||
int devinitall(ctx_t *);
|
||||
int devfiniall(ctx_t *);
|
||||
|
||||
extern dev_t cpudev;
|
||||
|
90
vm/dv/devctl.c
Normal file
90
vm/dv/devctl.c
Normal file
@ -0,0 +1,90 @@
|
||||
// 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 <dv/dev.h>
|
||||
#include <in/instrs.h>
|
||||
|
||||
//
|
||||
// code common to devctl and iocall
|
||||
//
|
||||
dev_t *devctl_common(ctx_t *ctx, ulong v1, ulong v2)
|
||||
{
|
||||
|
||||
dev_t *dev = devget(ctx, v1);
|
||||
|
||||
if (!dev)
|
||||
rax = -2;
|
||||
|
||||
else if (dev->state == DEVPWOF)
|
||||
rax = -3;
|
||||
|
||||
else if (dev->state == DEVFERR)
|
||||
rax = -4;
|
||||
|
||||
else if (dev->state == DEVPLUG)
|
||||
rax = -5;
|
||||
|
||||
else
|
||||
return dev;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void copystr(ctx_t *ctx, ulong addr, ulong maxn, char *str)
|
||||
{
|
||||
for (; *str && maxn > 0; str++, addr++, maxn--) {
|
||||
writemem8(ctx, *str, addr);
|
||||
}
|
||||
|
||||
writemem8(ctx, 0, addr);
|
||||
}
|
||||
|
||||
IMPL_START_2(devctl)
|
||||
{
|
||||
CHK_SUPERV();
|
||||
|
||||
dev_t *dev = devctl_common(ctx, v1, v2);
|
||||
|
||||
if (dev == NULL)
|
||||
return;
|
||||
|
||||
switch (v2) {
|
||||
case 0:
|
||||
copystr(ctx, ax0, DEVLEN, dev->type);
|
||||
break;
|
||||
|
||||
case 1:
|
||||
copystr(ctx, ax0, DEVLEN, dev->name);
|
||||
break;
|
||||
|
||||
case 2:
|
||||
copystr(ctx, ax0, DEVLEN, dev->modl);
|
||||
break;
|
||||
|
||||
case 3:
|
||||
copystr(ctx, ax0, DEVLEN, dev->vend);
|
||||
break;
|
||||
|
||||
case 4:
|
||||
rax = dev->major;
|
||||
rdx = dev->minor;
|
||||
break;
|
||||
|
||||
case 5:
|
||||
rax = dev->feats;
|
||||
rdx = dev->revis;
|
||||
break;
|
||||
|
||||
default:
|
||||
rax = -6;
|
||||
break;
|
||||
}
|
||||
}
|
||||
IMPL_END;
|
||||
|
||||
IMPL_START_2(iocall)
|
||||
{
|
||||
CHK_SUPERV();
|
||||
}
|
||||
IMPL_END;
|
||||
|
@ -177,6 +177,9 @@ popf
|
||||
cli
|
||||
sti
|
||||
|
||||
devctl rim rim
|
||||
iocall rim rim
|
||||
|
||||
#
|
||||
# Misc. instructions
|
||||
#
|
||||
|
12
vm/pc/arch.h
12
vm/pc/arch.h
@ -1,6 +1,11 @@
|
||||
// The OS/K Team licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
#ifndef _ARCH_H
|
||||
#define _ARCH_H
|
||||
|
||||
#define dev_t stddev_t
|
||||
|
||||
#include <ctype.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
@ -8,6 +13,7 @@
|
||||
#include <assert.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
#undef dev_t
|
||||
#define packed __attribute__ ((__packed__))
|
||||
#define static_assert _Static_assert
|
||||
#define alignof _Alignof
|
||||
@ -23,6 +29,7 @@ typedef struct ctx_t ctx_t;
|
||||
typedef struct instr_t instr_t;
|
||||
typedef struct acc_t acc_t;
|
||||
typedef struct arch_t arch_t;
|
||||
typedef struct dev_t dev_t;
|
||||
|
||||
void log(const char *, ...);
|
||||
void vlog(const char *, va_list);
|
||||
@ -101,6 +108,9 @@ struct ctx_t
|
||||
|
||||
// For disassembly
|
||||
FILE *disf;
|
||||
|
||||
// Devices list head
|
||||
dev_t *dh;
|
||||
};
|
||||
|
||||
#define R(X) ctx->r[X].val
|
||||
@ -160,3 +170,5 @@ void writemem(ctx_t *, ulong val, ulong addr, uint len);
|
||||
extern reg_t arch_r[NREGS];
|
||||
extern instr_t arch_i[NINSTRS];
|
||||
|
||||
#endif
|
||||
|
||||
|
@ -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 <dv/dev.h>
|
||||
|
||||
void _except(ctx_t *ctx, int code, char *fmt, ...)
|
||||
{
|
||||
@ -22,6 +22,12 @@ void _except(ctx_t *ctx, int code, char *fmt, ...)
|
||||
|
||||
if (ctx->mp)
|
||||
free(ctx->mp);
|
||||
|
||||
if (devfiniall(ctx) < 0) {
|
||||
log("Couldn't deinitialize devices\n");
|
||||
exit(-100 - code);
|
||||
}
|
||||
|
||||
exit(code);
|
||||
}
|
||||
|
||||
|
17
vm/pc/main.c
17
vm/pc/main.c
@ -1,7 +1,8 @@
|
||||
// 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 <dv/dev.h>
|
||||
#include <sys/time.h>
|
||||
|
||||
#define FWPROGSIZE (1024 * 1024 * 1024)
|
||||
static ssize_t fwsize;
|
||||
@ -40,11 +41,17 @@ ushort dget(ctx_t *ctx)
|
||||
return fwprog[i++];
|
||||
}
|
||||
|
||||
ctx_t main_ctx;
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
ctx_t main_ctx;
|
||||
FILE *fwfile;
|
||||
|
||||
struct timeval time;
|
||||
|
||||
gettimeofday(&time, NULL);
|
||||
srandom((time.tv_sec * 1000) + (time.tv_usec / 1000));
|
||||
|
||||
main_ctx.r = arch_r;
|
||||
main_ctx.i = arch_i;
|
||||
|
||||
@ -91,6 +98,12 @@ int main(int argc, char **argv)
|
||||
|
||||
memcpy(&main_ctx.mp[addr2real(main_ctx.r[RIP].val)], fwprog, fwsize);
|
||||
|
||||
main_ctx.dh = 0;
|
||||
if (devinitall(&main_ctx) < 0) {
|
||||
log("Couldn't initialize devices\n");
|
||||
exit(-10);
|
||||
}
|
||||
|
||||
while (1) {
|
||||
decode(&main_ctx);
|
||||
}
|
||||
|
29
vm/pc/regs.h
29
vm/pc/regs.h
@ -24,9 +24,26 @@ enum
|
||||
|
||||
NX0, NX1, NX2, NX3,
|
||||
NX4, NX5, NX6, NX7,
|
||||
#define nx0 R(NX0)
|
||||
#define nx1 R(NX1)
|
||||
#define nx2 R(NX2)
|
||||
#define nx3 R(NX3)
|
||||
#define nx4 R(NX4)
|
||||
#define nx5 R(NX5)
|
||||
#define nx6 R(NX6)
|
||||
#define nx7 R(NX7)
|
||||
|
||||
AX0, AX1, AX2, AX3,
|
||||
AX4, AX5, AX6, AX7,
|
||||
#define ax0 R(AX0)
|
||||
#define ax1 R(AX1)
|
||||
#define ax2 R(AX2)
|
||||
#define ax3 R(AX3)
|
||||
#define ax4 R(AX4)
|
||||
#define ax5 R(AX5)
|
||||
#define ax6 R(AX6)
|
||||
#define ax7 R(AX7)
|
||||
|
||||
|
||||
CR0, CR1, CR2, CR3,
|
||||
CR4, CR5, CR6, CR7,
|
||||
@ -34,9 +51,21 @@ enum
|
||||
#define cr1 R(CR1)
|
||||
#define cr2 R(CR2)
|
||||
#define cr3 R(CR3)
|
||||
#define cr4 R(CR4)
|
||||
#define cr5 R(CR5)
|
||||
#define cr6 R(CR6)
|
||||
#define cr7 R(CR7)
|
||||
|
||||
SA0, SA1, SA2, SA3,
|
||||
SA4, SA5, SA6, SA7,
|
||||
#define sa0 R(SA0)
|
||||
#define sa1 R(SA1)
|
||||
#define sa2 R(SA2)
|
||||
#define sa3 R(SA3)
|
||||
#define sa4 R(SA4)
|
||||
#define sa5 R(SA5)
|
||||
#define sa6 R(SA6)
|
||||
#define sa7 R(SA7)
|
||||
|
||||
NREGS
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user