commit 742dda6b47d1621e44c450831d017d80dae060a9
parent 7e254b64801e42ff89392a157f1f1a822099ce1c
Author: Roberto E. Vargas Caballero <roberto.vargas@midokura.com>
Date: Sat, 26 Nov 2022 11:21:12 +0100
os9: Add open() syscall
Open was added as a syscall as a proof of concept
where we can begin to test the full syscall path.
Diffstat:
8 files changed, 140 insertions(+), 58 deletions(-)
diff --git a/include/os9/os9.h b/include/os9/os9.h
@@ -101,6 +101,11 @@ enum map_attr {
MD = 1 << 3,
};
+enum sysnumbers {
+ SYSOPEN,
+ NR_SYSCALLS,
+};
+
struct ref {
mutex_t m;
int cnt;
@@ -193,6 +198,11 @@ struct rendez {
Task *task;
};
+struct syscall {
+ int nargs;
+ int (*fn)(int, ...);
+};
+
/**
* @entry: Entry point for the task.
* @prio:
@@ -343,7 +353,7 @@ extern void idle(void);
/* dev functions */
extern void idev(void);
-extern Chan *chanopen(char *name, int mode);
+extern Chan *namec(char *, int mode);
extern int chanwrite(Chan *c, void *buf, int n);
extern int chanread(Chan *c, void *buf, int n);
extern int chanclose(Chan *c);
@@ -359,6 +369,7 @@ extern Chan *console;
extern Mach mach;
extern char buffertab[NR_BUFFERS][PAGESIZE];
extern char bufto[], buffrom[];
+extern struct syscall systab[];
/* per cpu globals */
extern Task *proc;
diff --git a/src/os9/Makefile b/src/os9/Makefile
@@ -14,6 +14,7 @@ OBJS =\
map.o\
proc.o\
ref.o\
+ syscall.o\
sys.o\
dev/builtin.o\
diff --git a/src/os9/arch/arm64/trap.c b/src/os9/arch/arm64/trap.c
@@ -8,8 +8,30 @@
#include "arch.h"
static void
-svc(int numsvc)
+syscall(Context *ctx)
{
+ int nsys, r;
+ struct syscall *sys;
+ uintmax_t arg1, arg2, arg3, arg4;
+
+ nsys = ctx->r[X0];
+ if (nsys < 0 || nsys >= NR_SYSCALLS) {
+ kprint("trap: %llu: invalid syscall %d number\n",
+ ctx->r[X29], nsys);
+ seterrno(EINVAL);
+ return;
+ }
+
+ arg1 = ctx->r[X1];
+ arg2 = ctx->r[X2];
+ arg3 = ctx->r[X3];
+ arg4 = ctx->r[X4];
+
+ sys = systab[n];
+ if (!sys->fn)
+ panic("null syscall entry");
+ r = (*fn)(sys->narg, arg1, arg2, arg3, arg4);
+ setret(r);
}
void
@@ -17,7 +39,7 @@ trap(Context *ctx)
{
enum ecvals ec;
const char *msg;
- int numsvc;
+ int numsvc, nsyscall;
ec = (ctx->r[ESR] >> 26) & 0x3f;
@@ -29,7 +51,17 @@ trap(Context *ctx)
}
numsvc = ctx->r[ESR] & 0xff;
+ if (numsvc == 0) {
+ syscall(ctx);
+ } else {
+ kprint("trap: %llu: invalid svc %d number\n",
+ ctx->r[X29], numsvc);
+ seterror(EINVAL);
+ setret(-1);
+ }
+
+ ctx->r[X0] = proc->ret;
+ ctx->r[X1] = proc->errno;
- svc(numsvc);
swtch(ctx);
}
diff --git a/src/os9/dev/dev.c b/src/os9/dev/dev.c
@@ -202,22 +202,6 @@ err:
return NULL;
}
-static int
-validmode(int mode)
-{
- if ((mode & O_READ) && (mode & (O_WRITE | O_RDWR)))
- goto err;
- if ((mode & O_WRITE) && (mode & (O_READ | O_RDWR)))
- goto err;
- if ((mode & O_RDWR) && (mode & (O_READ | O_WRITE)))
- goto err;
- return 1;
-
-err:
- seterror(EINVAL);
- return 0;
-}
-
static char *
next(char *s, char *elem)
{
@@ -492,37 +476,6 @@ devgen(Chan *c, Dirtab *tab, int ntab, int n, Dir *dir)
return 1;
}
-Chan *
-chanopen(char *fname, int mode)
-{
- if (!validmode(mode))
- return NULL;
- return namec(fname, mode);
-}
-
-int
-open(char *fname, int mode)
-{
- int fd;
- Chan *c, **bp;
- Fdset *fds = proc->fds;
-
- if ((c = chanopen(fname, mode)) == NULL)
- return -1;
-
- lock(&fds->m);
- for (bp = fds->fdset; bp < &fds->fdset[NR_CHANS]; ++bp) {
- if (*bp == c)
- break;
- }
- fd = (bp == &fds->fdset[NR_CHANS]) ? -1 : (bp - fds->fdset);
- unlock(&fds->m);
-
- if (fd == -1)
- panic("corrupted channel");
- return fd;
-}
-
int
chanclose(Chan *c)
{
diff --git a/src/os9/dev/dev.h b/src/os9/dev/dev.h
@@ -40,7 +40,6 @@ struct attr {
};
extern int sameqid(Qid q1, Qid qid2);
-extern Chan *namec(char *name, int mode);
extern Chan *clone(Chan *c, Chan *nc);
extern Chan *attach(int id, int dev);
extern int buf2chan(Chan *c,
diff --git a/src/os9/dlang.c b/src/os9/dlang.c
@@ -89,7 +89,7 @@ do_read(const struct cmd *cmd, struct args *args)
Chan *c;
char buf[100], *bp;
- if ((c = chanopen(args->argv[1], O_READ)) == NULL)
+ if ((c = namec(args->argv[1], O_READ)) == NULL)
goto err;
ch = -1;
@@ -123,7 +123,7 @@ do_ls(const struct cmd *cmd, struct args *args)
Dir dentry;
unsigned char buf[DIRLEN];
- if ((c = chanopen(args->argv[1], O_READ)) == NULL)
+ if ((c = namec(args->argv[1], O_READ)) == NULL)
goto err;
while ((n = chanread(c, buf, DIRLEN)) > 0) {
@@ -149,7 +149,7 @@ do_write(const struct cmd *cmd, struct args *args)
Chan *c;
char *s, buffer[LINELEN];
- if ((c = chanopen(args->argv[1], O_WRITE)) == NULL)
+ if ((c = namec(args->argv[1], O_WRITE)) == NULL)
goto err;
offset = 0;
diff --git a/src/os9/sys.c b/src/os9/sys.c
@@ -12,7 +12,7 @@ Chan *console;
static void
icons(void)
{
- if ((console = chanopen("#c/raw", O_RDWR)) == NULL)
+ if ((console = namec("#c/raw", O_RDWR)) == NULL)
panic("icons:#c/raw open");
}
@@ -29,7 +29,7 @@ writeline(char *line)
*p++ = '\0';
data = p;
- if ((c = chanopen(file, O_WRITE)) < 0)
+ if ((c = namec(file, O_WRITE)) < 0)
panic("writeline:open");
if (chanwrite(c, data, strlen(data)) < 0)
panic("writeline:write");
@@ -78,7 +78,7 @@ iconf(void)
NULL
}, *bp;
- if ((c = chanopen("/blobs/conf", O_READ)) == NULL) {
+ if ((c = namec("/blobs/conf", O_READ)) == NULL) {
kprint("missed kernel namespace configuration\n");
return;
}
diff --git a/src/os9/syscall.c b/src/os9/syscall.c
@@ -0,0 +1,86 @@
+#include <os9/os9.h>
+
+#include <stdarg.h>
+#include <errno.h>
+
+#include "version.h"
+
+
+static int
+validmode(int mode)
+{
+ if ((mode & O_READ) && (mode & (O_WRITE | O_RDWR)))
+ goto err;
+ if ((mode & O_WRITE) && (mode & (O_READ | O_RDWR)))
+ goto err;
+ if ((mode & O_RDWR) && (mode & (O_READ | O_WRITE)))
+ goto err;
+ if (mode == 0)
+ goto err;
+ return 1;
+
+err:
+ seterror(EINVAL);
+ return 0;
+}
+
+static int
+newfd(Chan *c, int mode)
+{
+ int fd;
+ Chan **bp;
+ Fdset *fds = proc->fds;
+
+ lock(&fds->m);
+ for (bp = fds->fdset; bp < &fds->fdset[NR_CHANS]; ++bp) {
+ if (*bp == c)
+ break;
+ }
+ if (bp == &fds->fdset[NR_CHANS]) {
+ seterror(EMFILE);
+ unlock(&fds->m);
+ return -1;
+ }
+
+ fd = bp - fds->fdset;
+ fds->fdset[fd] = c;
+ unlock(&fds->m);
+
+ return fd;
+}
+
+static int
+validaddr(void *addr, int len, int write)
+{
+ /* TODO */
+ return 1;
+}
+
+static int
+sysopen(int nargs, ...)
+{
+ char *fname;
+ int mode, flags, fd;
+ va_list va;
+ Chan *c;
+
+ va_start(va, nargs);
+ fname = (char *) va_arg(va, uintptr_t);
+ mode = va_arg(va, uintptr_t);
+ flags = va_arg(va, uintptr_t);
+ va_end(va);
+
+ if (!validmode(mode))
+ return -1;
+ if (!validaddr(fname, 1, 0))
+ return -1;
+ if ((c = namec(fname, mode)) == NULL)
+ return -1;
+ if ((fd = newfd(c, mode)) < 0)
+ return -1;
+ return fd;
+}
+
+struct syscall systab[] = {
+ [SYSOPEN] = 3, sysopen,
+};