commit 99cfd9068c53ef246f7f08a1573d03ce89c3fcf0
parent 3b9beed3020a69117793163daad3832a44138677
Author: Roberto E. Vargas Caballero <k0ga@shike2.com>
Date: Wed, 4 Nov 2020 09:28:23 +0100
os9: Add basic proc() infraestructure
Change-Id: I93bef38ad69bb2db393dd2390aaeb085aedbda78
Diffstat:
9 files changed, 348 insertions(+), 122 deletions(-)
diff --git a/include/bits/arm64/arch/types.h b/include/bits/arm64/arch/types.h
@@ -1,4 +1,12 @@
/* TODO: Move these bits to other place */
+
+#define MAXTID 32767
+#define NR_TASKS 16
+#define NR_WINS 32
+
+#define NR_MPOINTS 4
+#define NR_CHANS 20
+
enum regidx {
X0,
X1,
@@ -41,12 +49,18 @@ enum regidx {
NR_REGS ,
};
-struct context {
- unsigned long long r[NR_REGS];
-};
-
typedef int atomic_t;
typedef unsigned long mutex_t;
typedef unsigned long long pte_t;
typedef unsigned long long phyaddr_t;
typedef struct context Context;
+
+struct context {
+ unsigned long long r[NR_REGS];
+};
+
+struct ptable {
+ pte_t high;
+ pte_t low;
+ int assid;
+};
diff --git a/include/os9/os9.h b/include/os9/os9.h
@@ -14,12 +14,6 @@
#define dbg
#endif
-#define NR_TASKS 16
-#define NR_WINS 32
-
-#define NR_MPOINTS 4
-#define NR_CHANS 20
-
#define KiB 1024u
#define MiB (1024u * KiB)
#define GiB (1024ul * MiB)
@@ -37,6 +31,7 @@
#define SEEK_END 2
#define EOF -1
+typedef struct ptable Ptable;
typedef struct context Context;
typedef struct proc Proc;
typedef struct task Task;
@@ -169,7 +164,9 @@ struct mpoint {
struct task {
int tid;
+ int ptid;
int pid;
+ int ppid;
char *name;
void *entry;
@@ -192,21 +189,24 @@ struct task {
int state;
int flags;
- char mode;
+ atomic_t mode;
int start;
mutex_t m;
Context ctx;
+ Ptable ptable;
/* communication ports */
/* healt monitor table */
/* Task *errhdl; */
Map *text;
Map *data;
- Map *stack;
+ Map stack;
Nspace *ns;
Fdset *fds;
+
+ Task *next;
};
struct win {
@@ -216,9 +216,19 @@ struct win {
int pid;
};
+/* proc.c */
+extern void iproc(void);
+extern void initref(Ref *);
+extern void incref(Ref *);
+extern int decref(Ref *);
+extern int getntask(int n, Task **);
+extern Task *gettask(int);
+extern int mapseg(Map *);
+
/* alloc.c */
-extern void *alloc(size_t size);
+extern void *alloc(size_t);
extern void *allocb(int);
+extern void freeb(void *);
/* init.c */
extern void isys(void);
@@ -226,6 +236,9 @@ extern void isys(void);
/* dlang.c */
extern int debug(void);
+/* arch mmu.c */
+extern int vmap(phyaddr_t, uintptr_t, int);
+
/* arch functions */
extern Context *getctx(Context *ctx);
extern void interrupt(int);
@@ -253,8 +266,6 @@ extern int devread(Chan *c, void *buf, int n);
extern int devclose(Chan *c);
/* sched.c */
-extern int getntask(int n, Task **tpp);
-extern Task *gettask(int tid);
extern void sched(void);
/* globals */
diff --git a/scripts/rules.mk b/scripts/rules.mk
@@ -12,7 +12,6 @@ SRCDIR = $(PROJECTDIR)/src
SCRIPTDIR = $(PROJECTDIR)/scripts
CONFDIR = $(PROJECTDIR)/config
INCLUDES = -I$(INCDIR) -I$(INCDIR)/bits/$(ARCH)/ -I$(INCDIR)/bits/$(SYS)
-LIBS = -lk -lc
ENVIRON = $(SCRIPTDIR)/env.sh
LIBDEP = $(LIBDIR)/libk.a \
@@ -37,7 +36,6 @@ PROJ_ASFLAGS = $(MOREASFLAGS) \
$(ASFLAGS)
PROJ_LDLIBS = $(MORELDLIBS) \
- $(LIBS) \
$(TOOLLDLIBS) \
$(SYSLDLIBS) \
$(LDLIBS)
diff --git a/src/os9/alloc.c b/src/os9/alloc.c
@@ -18,6 +18,12 @@ union bucket {
char buffertab[NR_BUFFERS][PAGESIZE];
+void
+freeb(void *bp)
+{
+ /* TODO */
+}
+
void *
allocb(int n)
{
diff --git a/src/os9/arch/arm64/Makefile b/src/os9/arch/arm64/Makefile
@@ -40,7 +40,7 @@ version.h:
mkver
$(BINDIR)/os9.elf: $(OBJS) $(LIBDEP)
- $(LD) $(PROJ_LDFLAGS) $(LINKSCRIPT) $(OBJS) $(PROJ_LDLIBS) -o $@
+ $(LD) $(PROJ_LDFLAGS) $(LINKSCRIPT) $(OBJS) -lk -lc $(PROJ_LDLIBS) -o $@
clean:
rm -f ecstr.c
diff --git a/src/os9/arch/arm64/fvp.c b/src/os9/arch/arm64/fvp.c
@@ -39,9 +39,9 @@ imach(void)
datap->perm = MR | MW;
stackp->name = "stack";
- stackp->pa = mach.phystack - 4*KiB;
- stackp->va = datap->va + datap->siz + 4*KiB;
- stackp->siz = 4*KiB;
+ stackp->pa = mach.phystack - PAGESIZE;
+ stackp->va = datap->va + datap->siz + PAGESIZE;
+ stackp->siz = PAGESIZE;
stackp->perm = MR | MW;
pagep->name = "ptable";
diff --git a/src/os9/arch/arm64/mmu.c b/src/os9/arch/arm64/mmu.c
@@ -140,15 +140,47 @@
#define NRALLOC 0ull
#define NWALLOC 0ull
+#define STACKADDR 0x7FFFFFFFFFFFFFF0
+
int inlowmem = 1;
+Ptable *
+initptable(Task *tp)
+{
+ struct ptable *pt, *ppt;
+ Task *parent;
+
+ parent = gettask(tp->ptid);
+ if (!parent)
+ panic("orphan task at creation");
+
+ pt = &tp->ptable;
+ ppt = &parent->ptable;
+
+ pt->high = ppt->high;
+ pt->low = ppt->low;
+ pt->assid = tp->tid;
+
+ return pt;
+}
+
+static void *
+newpage(void)
+{
+ char *bp;
+
+ if ((bp = allocb(1)) == NULL)
+ return NULL;
+ return memset(bp, 0, PAGESIZE);
+}
+
static pte_t
newtable(void)
{
char *bp;
- bp = allocb(1);
- memset(bp, 0, PAGESIZE);
+ if ((bp = newpage()) == NULL)
+ return INVALID;
if (!inlowmem)
bp = PMEM(bp);
@@ -172,7 +204,8 @@ walker(uintptr_t va)
e = bp[n];
if (e == INVALID) {
- e = newtable();
+ if ((e = newtable()) == INVALID)
+ return NULL;
bp[n] = e | TABLE;
barrier(DATA);
}
@@ -184,7 +217,7 @@ walker(uintptr_t va)
return &bp[TINDEX(3, va)];
}
-void
+int
vmap(phyaddr_t pa, uintptr_t va, int perm)
{
static mutex_t m;
@@ -206,7 +239,10 @@ vmap(phyaddr_t pa, uintptr_t va, int perm)
* with SMMUv3 and page tables are shared.
*/
lock(&m);
- p = walker(va);
+ if ((p = walker(va)) == NULL) {
+ unlock(&m);
+ return -1;
+ }
/*
* Here is needed to do a break-before-make as
@@ -223,35 +259,32 @@ vmap(phyaddr_t pa, uintptr_t va, int perm)
unlock(&m);
dbg("page %p: %llx\n", p, MASK(pa) | attr);
+ return 0;
}
-void
-mapseg(Map *mp)
+Map *
+newstack(Task *tp)
{
- phyaddr_t pa;
- uintptr_t va;
- unsigned long i, n;
-
- assert(mp->perm & MR);
-
- dbg("map %s: %llx -> %llx %c %c%c%c (%llu)\n",
- (mp->name) ? mp->name : "unnamed",
- mp->va, mp->pa,
- (mp->perm & MD) ? 'd' : 'n',
- (mp->perm & MR) ? 'r' : '-',
- (mp->perm & MW) ? 'w' : '-',
- (mp->perm & MX) ? 'x' : '-',
- mp->siz);
-
- pa = mp->pa;
- va = mp->va;
-
- n = (mp->siz + PAGESIZE-1)/PAGESIZE;
- for (i = 0; i < n; i++) {
- vmap(pa, va, mp->perm);
- pa += PAGESIZE;
- va += PAGESIZE;
+ void *va;
+ Map *mp = &tp->stack;
+
+ if ((va = newpage()) == NULL)
+ return NULL;
+
+ initref(&mp->ref);
+ mp->name = "stack";
+ mp->perm = MW | MR;
+
+ mp->pa =(phyaddr_t) PMEM(va);
+ mp->va = STACKADDR;
+ mp->siz = PAGESIZE;
+
+ if (mapseg(mp) < 0) {
+ freeb(va);
+ return NULL;
}
+
+ return mp;
}
void
@@ -290,8 +323,10 @@ kernelmap(void)
dbg("TTBR1_EL1=%llx\n", sysrd(TTBR1_EL1));
- for (mp = mach.maps; mp->siz != 0; mp++)
- mapseg(mp);
+ for (mp = mach.maps; mp->siz != 0; mp++) {
+ if (mapseg(mp) < 0)
+ panic("no kernel map");
+ }
barrier(DATA);
barrier(CODE);
}
diff --git a/src/os9/init.c b/src/os9/init.c
@@ -36,5 +36,6 @@ isys(void)
{
idev();
icons();
+ iproc();
debug();
}
diff --git a/src/os9/proc.c b/src/os9/proc.c
@@ -3,6 +3,8 @@
#include <errno.h>
#include <limits.h>
+#include <libk.h>
+
struct nspace {
Ref ref;
mutex_t m;
@@ -16,15 +18,28 @@ struct fdset {
};
static Task tasktab[NR_TASKS];
+static Task *freel;
-static void
+void
+iproc(void)
+{
+ Task *tp;
+
+ for (tp = tasktab; tp < &tasktab[NR_TASKS]; ++tp) {
+ tp->tid = tp->ptid = tp->pid = tp->ppid = -1;
+ tp->next = (tp < &tasktab[NR_TASKS-1]) ? tp+1 : NULL;
+ }
+ freel = tasktab;
+}
+
+void
initref(Ref *rp)
{
rp->m = 0;
- rp->cnt = 0;
+ rp->cnt = 1;
}
-static void
+void
incref(Ref *rp)
{
lock(&rp->m);
@@ -32,12 +47,16 @@ incref(Ref *rp)
unlock(&rp->m);
}
-static void
+int
decref(Ref *rp)
{
+ int r;
+
lock(&rp->m);
- rp->cnt--;
+ r = --rp->cnt == 0;
unlock(&rp->m);
+
+ return r;
}
int
@@ -45,12 +64,17 @@ getntask(int n, Task **tpp)
{
Task *tp;
- if (n >= NR_TASKS)
+ if (n >= NR_TASKS) {
+ errno = EINVAL;
return -1;
+ }
tp = &tasktab[n];
- if (tp->mode == PDISABLED)
+ lock(&tp->m);
+ if (tp->mode == PDISABLED) {
+ unlock(&tp->m);
return 0;
+ }
*tpp = tp;
return 1;
@@ -62,45 +86,107 @@ gettask(int tid)
Task *tp;
for (tp = tasktab; tp < &tasktab[NR_TASKS]; ++tp) {
+ lock(&tp->m);
if (tp->mode != PDISABLED && tp->tid == tid)
- break;
+ return tp;
+ unlock(&tp->m);
}
- return (tp != &tasktab[NR_TASKS]) ? tp : NULL;
+ return NULL;
}
-static int
-newtid(void)
+int
+mapseg(Map *mp)
{
- int tid, id;
- static int last;
+ phyaddr_t pa;
+ uintptr_t va;
+ unsigned long i, n;
+
+ assert(mp->perm & MR);
+
+ dbg("map %s: %llx -> %llx %c %c%c%c (%llu)\n",
+ (mp->name) ? mp->name : "unnamed",
+ mp->va, mp->pa,
+ (mp->perm & MD) ? 'd' : 'n',
+ (mp->perm & MR) ? 'r' : '-',
+ (mp->perm & MW) ? 'w' : '-',
+ (mp->perm & MX) ? 'x' : '-',
+ mp->siz);
+
+ pa = mp->pa;
+ va = mp->va;
+
+ n = (mp->siz + PAGESIZE-1)/PAGESIZE;
+ for (i = 0; i < n; i++) {
+ if (vmap(pa, va, mp->perm) < 0)
+ return -1;
+ pa += PAGESIZE;
+ va += PAGESIZE;
+ }
- id = tid = last;
+ return 0;
+}
- do {
- if (tid == INT_MAX)
- tid = -1;
- tid++;
- if (gettask(tid) == NULL)
- break;
- } while (tid != last);
+static Task *
+newslot(void)
+{
+ Task *tp;
+ static mutex_t m;
+
+ lock(&m);
+ if (!freel) {
+ tp = NULL;
+ errno = ENOMEM;
+ } else {
+ tp = freel;
+ freel = tp->next;
+ }
+ lock(&tp->m);
+ unlock(&m);
- last = tid;
+ tp->next = NULL;
- return (tid != id) ? tid : -1;
+ return tp;
}
static Task *
-newslot(void)
+newtask(void)
{
+ int tid;
Task *tp;
+ static int last;
+ static mutex_t m;
- for (tp = tasktab; tp < &tasktab[NR_TASKS]; ++tp) {
- if (tp->mode == PDISABLED)
+ assert(NR_TASKS < MAXTID);
+
+ lock(&m);
+ tp = NULL;
+ tid = last;
+
+ for (;;) {
+ if (tid == MAXTID)
+ tid = -1;
+ tid++;
+ if (tid == last)
+ goto err;
+ if ((tp = gettask(tid)) == NULL)
break;
+ unlock(&tp->m);
}
- return (tp != &tasktab[NR_TASKS]) ? tp : NULL;
+ if ((tp = newslot()) == NULL)
+ goto err;
+
+ last = tid;
+ tp->tid = tid;
+ unlock(&m);
+
+ return tp;
+err:
+ unlock(&m);
+ errno = ENOMEM;
+
+ return NULL;
}
static Nspace *
@@ -140,75 +226,150 @@ newmap(Map *from)
return NULL;
*mp = *from;
initref(&mp->ref);
+ mapseg(mp); /* FIXME: we have to duplicate the pages */
return mp;
}
+static void
+freespace(Nspace *ns)
+{
+ /* TODO */
+}
+
+static void
+freefds(Fdset *fds)
+{
+ /* TODO */
+}
+
+static void
+freemap(Map *mp)
+{
+ /* TODO */
+}
+
+static void
+deltask(Task *tp)
+{
+}
+
+static Task *
+clone(Task *parent)
+{
+ Task *tp;
+
+ if ((tp = newtask()) == NULL)
+ return NULL;
+
+ tp->ptid = parent->tid;
+ tp->pid = parent->pid;
+ tp->ppid = parent->ppid;
+
+ if (!initptable(tp) || !newstack(tp))
+ goto err;
+
+ incref(&parent->text->ref);
+ tp->text = parent->text;
+
+ incref(&parent->data->ref);
+ tp->data = parent->data;
+
+ incref(&parent->ns->ref);
+ tp->ns = parent->ns;
+
+ incref(&parent->fds->ref);
+ tp->fds = parent->fds;
+
+ return tp;
+
+err:
+ unlock(&tp->m);
+ deltask(tp);
+ return NULL;
+}
+
int
rfork(int flags)
{
Task *tp, *parent;
+ Nspace *ns;
+ Fdset *fds;
+ Map *data;
tp = parent = task;
- if ((flags & (RFPROC|RFMEM)) == (RFPROC|RFMEM)
- || (flags & (RFNAMEG|RFCNAMEG)) == (RFNAMEG|RFCNAMEG)
- || (flags & (RFFDG|RFCFDG)) == (RFFDG|RFCFDG)) {
+ if ((flags & (RFMEM|RFPROC)) == 0
+ || (flags & (RFNAMEG|RFCNAMEG)) == (RFNAMEG|RFCNAMEG)
+ || (flags & (RFFDG|RFCFDG)) == (RFFDG|RFCFDG)) {
errno = EINVAL;
return -1;
}
- if ((flags & RFPROC) != 0) {
- if ((tp = newslot()) == NULL)
- goto enomem;
- if ((tp->tid = newtid()) < 0)
- goto enomem;
-
- incref(&parent->text->ref);
- tp->text = parent->text;
-
- incref(&parent->data->ref);
- tp->data = parent->data;
-
- incref(&parent->stack->ref);
- tp->stack = parent->stack;
+ ns = NULL;
+ fds = NULL;
+ data = NULL;
- incref(&parent->ns->ref);
- tp->ns = parent->ns;
-
- incref(&parent->fds->ref);
- tp->fds = parent->fds;
+ if ((flags & RFPROC) != 0) {
+ if ((tp = clone(parent)) == NULL)
+ return -1;
}
-
if ((flags & RFCNAMEG) != 0) {
- decref(&tp->ns->ref);
- tp->ns = newspace(NULL);
- incref(&tp->ns->ref);
+ if ((ns = newspace(NULL)) == NULL)
+ goto err;
}
if ((flags & RFNAMEG) != 0) {
- decref(&tp->ns->ref);
- tp->ns = newspace(parent->ns);
- incref(&tp->ns->ref);
+ if ((ns = newspace(parent->ns)) == NULL)
+ goto err;
}
if ((flags & RFCFDG) != 0) {
- decref(&tp->fds->ref);
- tp->fds = newfds(NULL);
- incref(&tp->fds->ref);
+ if ((fds = newfds(NULL)) == NULL)
+ goto err;
}
if ((flags & RFFDG) != 0) {
- decref(&tp->fds->ref);
- tp->fds = newfds(parent->fds);
- incref(&tp->fds->ref);
+ if ((fds = newfds(parent->fds)) == NULL)
+ goto err;
}
- if ((flags & RFCFDG) != 0) {
- decref(&tp->data->ref);
- tp->data = newmap(parent->data);
- incref(&tp->data->ref);
+ if ((flags & RFMEM) == 0) {
+ if ((data = newmap(parent->data)) == NULL)
+ goto err;
}
- return (flags & RFPROC) ? tp->tid : 0;
+ if (tp->ns != ns) {
+ if (decref(&tp->ns->ref))
+ freespace(tp->ns);
+ tp->ns = ns;
+ }
+ if (tp->fds != fds) {
+ if (decref(&tp->fds->ref))
+ freefds(tp->fds);
+ tp->fds = fds;
+ }
+ if (tp->data != data) {
+ if (decref(&tp->data->ref))
+ freemap(tp->data);
+ tp->data = data;
+ }
+
+ if (flags & RFPROC) {
+ unlock(&tp->m);
+ return tp->tid;
+ }
+
+ return 0;
+
+err:
+ if (data)
+ freemap(data);
+ if (fds)
+ freefds(fds);
+ if (ns)
+ freespace(ns);
+
+ if (flags & RFPROC) {
+ unlock(&tp->m);
+ deltask(tp);
+ }
-enomem:
- errno = ENOMEM;
return -1;
}