9os

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README | LICENSE

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:
Minclude/bits/arm64/arch/types.h | 22++++++++++++++++++----
Minclude/os9/os9.h | 33++++++++++++++++++++++-----------
Mscripts/rules.mk | 2--
Msrc/os9/alloc.c | 6++++++
Msrc/os9/arch/arm64/Makefile | 2+-
Msrc/os9/arch/arm64/fvp.c | 6+++---
Msrc/os9/arch/arm64/mmu.c | 99+++++++++++++++++++++++++++++++++++++++++++++++++++++--------------------------
Msrc/os9/init.c | 1+
Msrc/os9/proc.c | 299+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-------------------
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; }