From a44fe20674d40b698ece9de0cc52a77328c7bcd0 Mon Sep 17 00:00:00 2001 From: David du Colombier <0intro@gmail.com> Date: Wed, 12 Dec 1990 00:00:00 +0000 Subject: [PATCH] Plan 9 from Bell Labs 1990-12-12 --- gnot/dat.h | 4 +- gnot/devcons.c | 3 + gnot/devincon.c | 11 + gnot/fault.c | 347 ------------------------ gnot/fault68020.c | 105 ++++++++ gnot/fns.h | 14 +- gnot/l.s | 2 +- gnot/main.c | 11 +- gnot/mem.h | 1 + gnot/page.c | 674 ---------------------------------------------- port/fault.c | 66 ++--- port/page.c | 12 +- port/proc.c | 7 +- port/stream.c | 14 +- port/sturp.c | 1 + port/sysproc.c | 21 +- power/conf.h | 1 + power/dat.h | 6 +- power/devrtc.c | 5 +- power/faultmips.c | 47 ++++ power/fns.h | 15 +- power/main.c | 25 +- power/mem.h | 1 + power/trap.c | 2 +- 24 files changed, 261 insertions(+), 1134 deletions(-) delete mode 100644 gnot/fault.c create mode 100644 gnot/fault68020.c delete mode 100644 gnot/page.c create mode 100644 power/faultmips.c diff --git a/gnot/dat.h b/gnot/dat.h index 3efad63762598461b81336b853ff3006b5fe0170..446dd5b1c5638def6ff39d9fc1c31087ba75cced 100644 --- a/gnot/dat.h +++ b/gnot/dat.h @@ -153,6 +153,7 @@ struct Conf int nservice; /* number of services */ int nfsyschan; /* number of filsys open channels */ ulong maxialloc; /* maximum bytes used by ialloc */ + int copymode; /* 0 is copy on write, 1 is copy on reference */ }; struct Dev @@ -448,7 +449,8 @@ struct Queue { Queue *next; /* next queue in the stream */ void (*put)(Queue*, Block*); QLock rlock; /* mutex for processes sleeping at r */ - Rendez r; + Rendez r; /* standard place to wait for flow control */ + Rendez *rp; /* where flow control wakeups go to */ void *ptr; /* private info for the queue */ }; #define QHUNGUP 0x1 /* flag bit meaning the stream has been hung up */ diff --git a/gnot/devcons.c b/gnot/devcons.c index 8892ed8c58595c8d7a06dc434fe8a8ce831638f3..2adef054de0a9c67fe3bb6de848505d826568300 100644 --- a/gnot/devcons.c +++ b/gnot/devcons.c @@ -311,6 +311,9 @@ echo(int c) case 'm': mntdump(); return; + case 'i': + incontoggle(); + return; } }else if(c == 0x14){ ctrlt++; diff --git a/gnot/devincon.c b/gnot/devincon.c index 18c105003deda8eab6c48766879077d4cb7546f2..19e8f558e555faac43af27346f6f1e5a2b86a658 100644 --- a/gnot/devincon.c +++ b/gnot/devincon.c @@ -600,9 +600,20 @@ inconoput(Queue *q, Block *bp) if(size >= 16){ dev->cdata = 0; MICROSECOND; + for(end = NOW+1000; dev->status & TX_FULL;){ + nop(); /* make sure we don't optimize too much */ + if(NOW > end){ + print("incon output stuck\n"); + freemsg(q, bp); + qunlock(&ip->xmit); + return; + } + } dev->cdata = chan; MICROSECOND; } + if(dev->status & TX_FULL) + print("inconfull\n"); dev->cdata = ctl; } MICROSECOND; diff --git a/gnot/fault.c b/gnot/fault.c deleted file mode 100644 index 665c59575abc6f4d79756af69dd929f691128f75..0000000000000000000000000000000000000000 --- a/gnot/fault.c +++ /dev/null @@ -1,347 +0,0 @@ -#include "u.h" -#include "lib.h" -#include "mem.h" -#include "dat.h" -#include "fns.h" -#include "ureg.h" -#include "errno.h" - -#define FORMAT(ur) ((((ur)->vo)>>12)&0xF) -#define OFFSET(ur) (((ur)->vo)&0xFFF) - - -struct FFrame -{ - ushort ireg0; /* internal register */ - ushort ssw; /* special status word */ - ushort ipsc; /* instr. pipe stage c */ - ushort ipsb; /* instr. pipe stage b */ - ulong addr; /* data cycle fault address */ - ushort ireg1; /* internal register */ - ushort ireg2; /* internal register */ - ulong dob; /* data output buffer */ - ushort ireg3[4]; /* more stuff */ - ulong baddr; /* stage b address */ - ushort ireg4[26]; /* more more stuff */ -}; - -/* - * SSW bits - */ -#define RW 0x0040 /* read/write for data cycle */ -#define FC 0x8000 /* fault on stage C of instruction pipe */ -#define FB 0x4000 /* fault on stage B of instruction pipe */ -#define RC 0x2000 /* rerun flag for stage C of instruction pipe */ -#define RB 0x1000 /* rerun flag for stage B of instruction pipe */ -#define DF 0x0100 /* fault/rerun flag for data cycle */ -#define RM 0x0080 /* read-modify-write on data cycle */ -#define READ 0x0040 -#define WRITE 0x0000 -#define SIZ 0x0030 /* size code for data cycle */ -#define FC2 0x0004 /* address space for data cycle */ -#define FC1 0x0002 -#define FC0 0x0001 - -void -fault(Ureg *ur, FFrame *f) -{ - ulong addr, mmuvirt, mmuphys, n, badvaddr; - Seg *s; - PTE *opte, *pte, *npte; - Orig *o; - char *l; - Page *pg; - KMap *k, *k1; - int zeroed = 0, head = 1; - int i, user, read, insyscall; - - if(u == 0){ - dumpregs(ur); - panic("fault u==0 pc=%lux", ur->pc); - } - insyscall = u->p->insyscall; - u->p->insyscall = 1; - addr = 0; /* set */ - if(f->ssw & DF) - addr = f->addr; - else if(FORMAT(ur) == 0xA){ - if(f->ssw & FC) - addr = ur->pc+2; - else if(f->ssw & FB) - addr = ur->pc+4; - else - panic("prefetch pagefault"); - }else if(FORMAT(ur) == 0xB){ - if(f->ssw & FC) - addr = f->baddr-2; - else if(f->ssw & FB) - addr = f->baddr; - else - panic("prefetch pagefault"); - }else - panic("prefetch format"); - addr &= VAMASK; - badvaddr = addr; - addr &= ~(BY2PG-1); - user = !(ur->sr&SUPER); - if(f->ssw & DF) - read = (f->ssw&READ) && !(f->ssw&RM); - else - read = f->ssw&(FB|FC); -/* print("fault pc=%lux addr=%lux read %d\n", ur->pc, badvaddr, read); /**/ - - s = seg(u->p, addr); - if(s == 0){ - if(addr>USTKTOP){ - cant: - if(user){ - pprint("user %s error addr=0x%lux\n", read? "read" : "write", badvaddr); - pprint("status=0x%lux pc=0x%lux sp=0x%lux\n", ur->sr, ur->pc, ur->sp); - pexit("Suicide", 0); - } - u->p->state = MMUing; - dumpregs(ur); - panic("fault: 0x%lux", badvaddr); - exit(); - } - s = &u->p->seg[SSEG]; - if(s->o==0 || addrmaxva-USTACKSIZE || addr>=s->maxva) - goto cant; - /* grow stack */ - o = s->o; - n = o->npte; - if(waserror()){ - pprint("can't allocate stack page\n"); - goto cant; - } - growpte(o, (s->maxva-addr)>>PGSHIFT); - poperror(); - /* stacks grown down, sigh */ - lock(o); - memcpy(o->pte+(o->npte-n), o->pte, n*sizeof(PTE)); - memset(o->pte, 0, (o->npte-n)*sizeof(PTE)); - unlock(o); - s->minva = addr; - o->va = addr; - }else - o = s->o; - if(!read && (o->flag&OWRPERM)==0) - goto cant; - lock(o); - opte = &o->pte[(addr-o->va)>>PGSHIFT]; - pte = opte; - if(s->mod){ - while(pte = pte->nextmod) /* assign = */ - if(pte->proc == u->p){ - if(pte->page==0 || pte->page->va!=addr) - panic("bad page %lux", pte->page); - head = 0; - break; - } - if(pte == 0) - pte = opte; - } - if(pte->page == 0){ - if(o->chan==0 || addr>(o->va+(o->maxca-o->minca))){ - /* - * Zero fill page. If we are really doing a copy-on-write - * (e.g. into shared bss) we'll move the page later. - */ - pte->page = newpage(0, o, addr); - o->npage++; - zeroed = 1; - }else{ - /* - * Demand load. Release o because it could take a while. - */ - unlock(o); - n = (o->va+(o->maxca-o->minca)) - addr; - if(n > BY2PG) - n = BY2PG; - pg = newpage(1, o, addr); - k = kmap(pg); - qlock(o->chan); - if(waserror()){ - kunmap(k); - qunlock(o->chan); - pg->o = 0; - pg->ref--; - pexit("load i/o error", 0); - } - o->chan->offset = (addr-o->va) + o->minca; - l = (char*)VA(k); - if((*devtab[o->chan->type].read)(o->chan, l, n) != n) - error(Eioload); - qunlock(o->chan); - if(npte[(addr-s->minva)>>PGSHIFT]; /* could move */ - pte = opte; - if(pte->page == 0){ - pte->page = pg; - o->npage++; - }else{ /* someone beat us to it */ - pg->o = 0; - pg->ref--; - } - } - } - /* - * Copy on write - */ - if((o->flag & OWRPERM) && !read - && ((head && ((o->flag&OPURE) || o->nproc>1)) - || (!head && pte->page->ref>1))){ - - /* - * Look for the easy way out: are we the last non-modified? - */ - if(head && !(o->flag&OPURE)){ - npte = opte; - for(i=0; npte; i++) - npte = npte->nextmod; - if(i == o->nproc) - goto easy; - } - if(head){ - /* - * Add to mod list - */ - pte = newmod(); - pte->proc = u->p; - pte->page = opte->page; - pte->page->ref++; - o->npage++; - /* - * Link into opte mod list (same va) - */ - pte->nextmod = opte->nextmod; - opte->nextmod = pte; - /* - * Link into proc mod list (increasing va) - */ - npte = s->mod; - if(npte == 0){ - s->mod = pte; - pte->nextva = 0; - }else{ - while(npte->nextva && npte->nextva->page->vanextva; - pte->nextva = npte->nextva; - npte->nextva = pte; - } - head = 0; - } - pg = pte->page; - if(zeroed){ /* move page */ - pg->ref--; - o->npage--; - opte->page = 0; - }else{ /* copy page */ - pte->page = newpage(1, o, addr); - k = kmap(pte->page); - k1 = kmap(pg); - memcpy((void*)VA(k), (void*)VA(k1), BY2PG); - kunmap(k); - kunmap(k1); - if(pg->ref <= 1) - panic("pg->ref <= 1"); - pg->ref--; - } - easy: - mmuphys = 0; - }else{ - mmuphys = PTERONLY; - if(o->flag & OWRPERM) - if(o->flag & OPURE){ - if(!head && pte->page->ref==1) - mmuphys = 0; - }else - if((head && o->nproc==1) - || (!head && pte->page->ref==1)) - mmuphys = 0; - } - mmuvirt = addr; - mmuphys |= PPN(pte->page->pa) | PTEVALID; - usepage(pte->page, 1); - if(pte->page->va != addr) - panic("wrong addr in tail %lux %lux", pte->page->va, addr); - if(pte->proc && pte->proc != u->p){ - print("wrong proc in tail %d %s\n", head, u->p->text); - print("u->p %lux pte->proc %lux\n", u->p, pte->proc); - panic("addr %lux seg %d wrong proc in tail", addr, s-u->p->seg); - } - unlock(o); - putmmu(mmuvirt, mmuphys); - u->p->insyscall = insyscall; -} - -/* - * Called only in a system call - */ -void -validaddr(ulong addr, ulong len, int write) -{ - Seg *s, *ns; - - if((long)len < 0){ - Err: - pprint("invalid address in sys call pc %lux sp %lux\n", ((Ureg*)UREGADDR)->pc, ((Ureg*)UREGADDR)->sp); - postnote(u->p, 1, "sys: bad address", NDebug); - error(Ebadarg); - } - Again: - s = seg(u->p, addr); - if(s==0){ - s = &u->p->seg[SSEG]; - if(s->o==0 || addrmaxva-USTACKSIZE || addr>=s->maxva) - goto Err; - } - if(write && (s->o->flag&OWRPERM)==0) - goto Err; - if(addr+len > s->maxva){ - len -= s->maxva - addr; - addr = s->maxva; - goto Again; - } -} -/* - * &s[0] is known to be a valid address. - */ -void* -vmemchr(void *s, int c, int n) -{ - int m; - char *t; - ulong a; - - a = (ulong)s; - m = BY2PG - (a & (BY2PG-1)); - if(m < n){ - t = vmemchr(s, c, m); - if(t) - return t; - if(!(a & KZERO)) - validaddr(a+m, 1, 0); - return vmemchr((void*)(a+m), c, n-m); - } - /* - * All in one page - */ - return memchr(s, c, n); -} - -Seg* -seg(Proc *p, ulong addr) -{ - int i; - Seg *s; - - for(i=0,s=p->seg; io && s->minva<=addr && addrmaxva) - return s; - return 0; -} diff --git a/gnot/fault68020.c b/gnot/fault68020.c new file mode 100644 index 0000000000000000000000000000000000000000..70f6d8c3a4832818502eaca811c0bb37afc07f52 --- /dev/null +++ b/gnot/fault68020.c @@ -0,0 +1,105 @@ +#include "u.h" +#include "lib.h" +#include "mem.h" +#include "dat.h" +#include "fns.h" +#include "ureg.h" +#include "errno.h" + +#define FORMAT(ur) ((((ur)->vo)>>12)&0xF) +#define OFFSET(ur) (((ur)->vo)&0xFFF) + + +struct FFrame +{ + ushort ireg0; /* internal register */ + ushort ssw; /* special status word */ + ushort ipsc; /* instr. pipe stage c */ + ushort ipsb; /* instr. pipe stage b */ + ulong addr; /* data cycle fault address */ + ushort ireg1; /* internal register */ + ushort ireg2; /* internal register */ + ulong dob; /* data output buffer */ + ushort ireg3[4]; /* more stuff */ + ulong baddr; /* stage b address */ + ushort ireg4[26]; /* more more stuff */ +}; + +/* + * SSW bits + */ +#define RW 0x0040 /* read/write for data cycle */ +#define FC 0x8000 /* fault on stage C of instruction pipe */ +#define FB 0x4000 /* fault on stage B of instruction pipe */ +#define RC 0x2000 /* rerun flag for stage C of instruction pipe */ +#define RB 0x1000 /* rerun flag for stage B of instruction pipe */ +#define DF 0x0100 /* fault/rerun flag for data cycle */ +#define RM 0x0080 /* read-modify-write on data cycle */ +#define READ 0x0040 +#define WRITE 0x0000 +#define SIZ 0x0030 /* size code for data cycle */ +#define FC2 0x0004 /* address space for data cycle */ +#define FC1 0x0002 +#define FC0 0x0001 + +void +fault68020(Ureg *ur, FFrame *f) +{ + ulong addr, mmuvirt, mmuphys, n, badvaddr; + Seg *s; + PTE *opte, *pte, *npte; + Orig *o; + char *l; + Page *pg; + KMap *k, *k1; + int zeroed = 0, head = 1; + int i, user, read, insyscall; + + if(u == 0){ + dumpregs(ur); + panic("fault u==0 pc=%lux", ur->pc); + } + insyscall = u->p->insyscall; + u->p->insyscall = 1; + addr = 0; /* set */ + if(f->ssw & DF) + addr = f->addr; + else if(FORMAT(ur) == 0xA){ + if(f->ssw & FC) + addr = ur->pc+2; + else if(f->ssw & FB) + addr = ur->pc+4; + else + panic("prefetch pagefault"); + }else if(FORMAT(ur) == 0xB){ + if(f->ssw & FC) + addr = f->baddr-2; + else if(f->ssw & FB) + addr = f->baddr; + else + panic("prefetch pagefault"); + }else + panic("prefetch format"); + addr &= VAMASK; + badvaddr = addr; + addr &= ~(BY2PG-1); + user = !(ur->sr&SUPER); + if(f->ssw & DF) + read = (f->ssw&READ) && !(f->ssw&RM); + else + read = f->ssw&(FB|FC); +/* print("fault pc=%lux addr=%lux read %d\n", ur->pc, badvaddr, read); /**/ + + if(fault(addr, read) < 0){ + if(user){ + pprint("user %s error addr=0x%lux\n", read? "read" : "write", badvaddr); + pprint("status=0x%lux pc=0x%lux sp=0x%lux\n", ur->sr, ur->pc, ur->sp); + pexit("Suicide", 0); + } + u->p->state = MMUing; + dumpregs(ur); + panic("fault: 0x%lux", badvaddr); + exit(); + } + u->p->insyscall = insyscall; +} diff --git a/gnot/fns.h b/gnot/fns.h index 261630ad4f2042de9c1117271f1458adfc1aea38..b310c0ed23bd2d8d6d21de7f55ba6efc461ef2ee 100644 --- a/gnot/fns.h +++ b/gnot/fns.h @@ -49,7 +49,8 @@ void envpgclose(Env *); void error(int); void errors(char*); void exit(void); -void fault(Ureg*, FFrame*); +int fault(ulong, int); +void fault68020(Ureg*, FFrame*); void fdclose(int); Chan *fdtochan(int, int); void filsys(Chan*, char*, long); @@ -65,8 +66,9 @@ void fpregsave(char*); void fprestore(FPsave*); void fpregrestore(char*); void freeb(Block*); +int freebroken(void); void freenextmod(PTE*); -void freepage(Orig*); +void freepage(Orig*, int); void freepte(Orig*); void freesegs(int); void freealarm(Alarm*); @@ -102,7 +104,7 @@ Chan *namec(char*, int, int, ulong); void nexterror(void); Alarm *newalarm(void); Chan *newchan(void); -PTE *newmod(void); +PTE *newmod(Orig *o); Mount *newmount(void); Orig *neworig(ulong, ulong, int, Chan*); Page *newpage(int, Orig*, ulong); @@ -126,6 +128,9 @@ int pprint(char*, ...); void printinit(void); void printslave(void); void procinit0(void); +void procrestore(Proc*, uchar*); +void procsave(uchar*, int); +void procsetup(Proc*); Proc *proctab(int); Queue *pushq(Stream*, Qinfo*); void putbq(Blist*, Block*); @@ -144,8 +149,6 @@ void qlock(QLock*); void qunlock(QLock*); void restartprint(Alarm*); void restfpregs(FPsave*); -void restore(Proc*, uchar*); -void save(uchar*, int); void savefpregs(FPsave*); void sched(void); void schedinit(void); @@ -157,7 +160,6 @@ int segaddr(Seg*, ulong, ulong); void serviceinit(void); void service(char*, Chan*, Chan*, void (*)(Chan*, char*, long)); int setlabel(Label*); -void setup(Proc*); char *skipslash(char*); void sleep(Rendez*, int(*)(void*), void*); int splhi(void); diff --git a/gnot/l.s b/gnot/l.s index 420fd6f8c7b25231f590e02dc4b408d0e5fd46fb..00a004b838b31444a19b39eed16ecbfcdc30905f 100644 --- a/gnot/l.s +++ b/gnot/l.s @@ -200,7 +200,7 @@ TEXT buserror(SB), $0 MOVL A0, ((8+8)*BY2WD)(A7) PEA ((8+8+1+2)*BY2WD)(A7) PEA 4(A7) - BSR fault(SB) + BSR fault68020(SB) ADDL $8, A7 MOVL ((8+8)*BY2WD)(A7), A0 MOVL A0, USP diff --git a/gnot/main.c b/gnot/main.c index 499100cb404cb4cbc8f93b4fb21a002005a7aa13..fe61f1896071ce6bf5c76e7144ccf95bbc0a0648 100644 --- a/gnot/main.c +++ b/gnot/main.c @@ -339,13 +339,14 @@ confinit(void) conf.npipe = conf.nstream/2; conf.nservice = 3*mul; /* was conf.nproc/5 */ conf.nfsyschan = 31 + conf.nchan/20; + conf.copymode = 0; /* copy on write */ } /* * set up floating point for a new process */ void -setup(Proc *p) +procsetup(Proc *p) { long fpnull; @@ -361,7 +362,7 @@ setup(Proc *p) * Save the part of the process state. */ void -save(uchar *state, int len) +procsave(uchar *state, int len) { Balu *balu; @@ -385,12 +386,12 @@ save(uchar *state, int len) } /* - * Restore what save() saves + * Restore what procsave() saves * - * Save() makes sure that what state points to is long enough + * Procsave() makes sure that what state points to is long enough */ void -restore(Proc *p, uchar *state) +procrestore(Proc *p, uchar *state) { Balu *balu; diff --git a/gnot/mem.h b/gnot/mem.h index a8093fb9dd4400ca111e7c2ff5ddf774dd80996b..79a07e02a157d492695d87c8aa7f72bed7840150 100644 --- a/gnot/mem.h +++ b/gnot/mem.h @@ -68,6 +68,7 @@ * MMU entries */ #define PTEVALID (1<<13) +#define PTEWRITE 0 #define PTERONLY (1<<14) #define PTEKERNEL (1<<15) #define INVALIDPTE 0 diff --git a/gnot/page.c b/gnot/page.c deleted file mode 100644 index 8ed70149694b956beff472e8a92a6b42908c2bbd..0000000000000000000000000000000000000000 --- a/gnot/page.c +++ /dev/null @@ -1,674 +0,0 @@ -#include "u.h" -#include "lib.h" -#include "mem.h" -#include "dat.h" -#include "fns.h" -#include "ureg.h" -#include "errno.h" - -struct -{ - Lock; - ulong addr; - int active; - Page *page; /* base of Page structures, indexed by phys page number */ - ulong minppn; /* index of first usable page */ - Page *head; /* most recently used */ - Page *tail; /* least recently used */ -}palloc; - -struct -{ - Lock; - Orig *arena; - Orig *free; -}origalloc; - -typedef union PTEA PTEA; -union PTEA{ - PTE; - struct{ - ulong n; /* for growpte */ - Orig *o; /* for growpte */ - PTEA *next; /* for newmod */ - }; -}; - -struct -{ - Lock; - PTEA *arena; - PTEA *free; - PTEA *end; -}ptealloc; - -struct{ - Lock; - PTEA *free; -}modalloc; - -/* - * Called to allocate permanent data structures, before calling pageinit(). - */ -void* -ialloc(ulong n, int align) -{ - ulong p; - - if(palloc.addr == 0) - palloc.addr = ((ulong)&end)&~KZERO; - if(n == 0) /* done by kmapinit */ - return (void*)(palloc.addr|KZERO); - if(palloc.active) - print("ialloc bad\n"); - if(align){ - palloc.addr += BY2PG-1; - palloc.addr &= ~(BY2PG-1); - } - memset((void*)(palloc.addr|KZERO), 0, n); - p = palloc.addr; - palloc.addr += n; - if(align){ - palloc.addr += BY2PG-1; - palloc.addr &= ~(BY2PG-1); - } - if(palloc.addr >= (4*1024*1024-256*1024-BY2PG)) - panic("keep bill joy away"); - return (void*)(p|KZERO); -} - -void -audit(char *s) -{ - int nf, nb; - Page *p; - static int here; - - do;while(here); - here=1; - p = palloc.head; - nf=nb=0; - while(p){ - print("%lux %lux %d\n", p->pa, p->va, p->ref); - if(p->o){ - print("\t%d %lux %c\n", p->o->nproc, p->o->qid, devchar[p->o->type]); - delay(100); /* let it drain; there's a lot here */ - } - nf++; - p = p->next; - } - p = palloc.tail; - while(p){ - nb++; - p = p->prev; - } - print("%s: nf: %d nb: %d\n", s, nf, nb); - delay(1000); - here=0; -} - -void -pageinit(void) -{ - ulong pa, nb, ppn; - ulong i; - Page *p; - PTEA *pte; - Orig *o; - - ptealloc.arena = ialloc(conf.npte*sizeof(PTEA), 0); - ptealloc.free = ptealloc.arena; - ptealloc.end = ptealloc.arena+conf.npte; - - modalloc.free = ialloc(conf.nmod*sizeof(PTEA), 0); - - pte = modalloc.free; - for(i=0; inext = pte+1; - pte->next = 0; - - origalloc.free = ialloc(conf.norig*sizeof(Orig), 0); - origalloc.arena = origalloc.free; - - o = origalloc.free; - for(i=0; inext = o+1; - o->next = 0; - palloc.active = 1; - - nb = (conf.npage<>PGSHIFT)*sizeof(Page); /* safe overestimate */ - nb &= ~(BY2PG-1); - pa = (conf.npage<> PGSHIFT; /* physical page number of first free page */ - palloc.page = (Page *)((palloc.addr - ppn*sizeof(Page))|KZERO); - /* - * Now palloc.page[ppn] describes first free page - */ - palloc.minppn = ppn; - palloc.addr = ppn<next = p+1; - p->prev = p-1; - if(ppn < conf.npage0) - p->pa = conf.base0+(ppn<pa = conf.base1+((ppn-conf.npage0)<prev = 0; - palloc.tail->next = 0; -} - -Page* -newpage(int noclear, Orig *o, ulong va) -{ - Page *p; - Orig *o1; - KMap *k; - - if(palloc.active == 0) - print("newpage inactive\n"); -loop: - lock(&palloc); - for(p=palloc.tail; p; p=p->prev){ - if(p->ref == 0) - goto out; -#ifdef asdf - if(p->ref == 1){ /* a pageout daemon should do this */ - o1 = p->o; - if(o1 && o1->nproc==0 && canlock(o1)){ - if(o1->nproc){ - unlock(o1); - continue; - } - print("free %d pages va %lux %lux %c\n", o1->npage, o->va, o1->qid, devchar[o1->type]); - freepage(o1); - /* neworig will free the orig and pte's later */ - unlock(o1); - if(p->ref == 0) - goto out; - print("newpage ref != 0"); - } - } -#endif - } - print("no physical memory\n"); - unlock(&palloc); - if(u == 0) - panic("newpage"); - u->p->state = Wakeme; - alarm(1000, wakeme, u->p); - sched(); - goto loop; - out: - if(p->o){ - print("page in use %lux %lux %lux\n", p->va, p->o, origalloc.arena); - print("%c %lux %lux, %d %d %d\n", devchar[p->o->type], p->o->va, p->o->qid, p->o->flag, p->o->nproc, p->o->npte); - panic("shit"); - } - p->ref = 1; - usepage(p, 0); - unlock(&palloc); - if(!noclear){ - k = kmap(p); - memset((void*)VA(k), 0, BY2PG); - kunmap(k); - } - p->o = o; - p->va = va; - - return p; -} - -/* - * Move page to head of list - */ -void -usepage(Page *p, int dolock) -{ - if(dolock) - lock(&palloc); - /* - * Unlink - */ - if(p->prev) - p->prev->next = p->next; - else - palloc.head = p->next; - if(p->next) - p->next->prev = p->prev; - else - palloc.tail = p->prev; - /* - * Link - */ - p->next = palloc.head; - p->prev = 0; - if(p->next) - p->next->prev = p; - else - palloc.tail = p; - palloc.head = p; - if(dolock) - unlock(&palloc); -} - -/* - * Move page to tail of list - */ -void -unusepage(Page *p, int dolock) -{ -} - -Orig* -lookorig(ulong va, ulong npte, int flag, Chan *c) -{ - Orig *o; - ulong i; - - for(o=origalloc.arena,i=0; inpage && eqqid(o->qid, c->qid) && o->va==va){ - lock(o); - if(o->npage && eqqid(o->qid, c->qid)) - if(o->va==va && o->npte==npte && o->flag==flag) - if(o->mchan==c->mchan && eqqid(o->mqid, c->mqid) && o->type==c->type){ - if(o->chan == 0){ - o->chan = c; - incref(c); - } - o->nproc++; - unlock(o); - return o; - } - unlock(o); - } - return 0; -} - -Orig* -neworig(ulong va, ulong npte, int flag, Chan *c) -{ - Orig *o; - int i, freed; - - lock(&origalloc); -loop: - if(o = origalloc.free){ /* assign = */ - origalloc.free = o->next; - o->va = va; - o->pte = 0; - o->flag = flag; - o->nproc = 1; - o->npage = 0; - o->chan = c; - if(c){ - o->type = c->type; - o->qid = c->qid; - o->mchan = c->mchan; - o->mqid = c->mqid; - incref(c); - }else{ - o->type = ~0; - o->qid.path = -1; - o->qid.vers = 0; - o->mqid.path = -1; - o->mqid.vers = 0; - o->mchan = 0; - } - if(u && u->p && waserror()){ - unlock(&origalloc); - nexterror(); - } - growpte(o, npte); - if(u && u->p) - poperror(); - unlock(&origalloc); - return o; - } - /* - * This is feeble. Orig's should perhaps be held in - * an LRU list. This algorithm is too aggressive. - */ - freed = 0; - for(o=origalloc.arena,i=0; inproc==0 && canlock(o)){ - if(o->nproc){ - unlock(o); - continue; - } - freepage(o); - freepte(o); - unlock(o); - o->next = origalloc.free; - origalloc.free = o; - freed++; - } - } - if(freed) - goto loop; - print("no origs freed\n"); - unlock(&origalloc); - if(u == 0) - panic("neworig"); - u->p->state = Wakeme; - alarm(1000, wakeme, u->p); - sched(); - lock(&origalloc); - goto loop; -} - -PTE* -newmod(void) -{ - PTEA *pte; - -loop: - lock(&modalloc); - if(pte = modalloc.free){ /* assign = */ - modalloc.free = pte->next; - unlock(&modalloc); - memset(pte, 0, sizeof(PTE)); - return pte; - } - unlock(&modalloc); - print("no mods\n"); - if(u == 0) - panic("newmod"); - u->p->state = Wakeme; - alarm(1000, wakeme, u->p); - sched(); - goto loop; -} - -/* - * Duplicate mod structure for this segment (old) in new process p. - * old->o must be locked. - */ -void -forkmod(Seg *old, Seg *new, Proc *p) -{ - Orig *o; - PTE *pte, *ppte, *opte, *npte; - ulong va; - - o = old->o; - ppte = 0; - pte = old->mod; - while(pte){ -if(pte->page==0) panic("forkmod zero page"); -if(pte->proc != u->p) panic("forkmod wrong page"); - npte = newmod(); - npte->proc = p; - npte->page = pte->page; - pte->page->ref++; - o->npage++; - /* - * Link into mod list for this va - */ - npte->nextmod = pte->nextmod; - pte->nextmod = npte; - /* - * Link into mod list for new segment - */ - if(ppte == 0) - new->mod = npte; - else - ppte->nextva = npte; - npte->nextva = 0; - ppte = npte; - pte = pte->nextva; - } -} - -void -freesegs(int save) -{ - int i, j; - Seg *s; - Orig *o; - PTE *pte, *opte; - PTEA *old; - Page *pg; - Chan *c; - - s = u->p->seg; - for(i=0; io; - if(o == 0) - continue; - lock(o); - if(pte = s->mod){ /* assign = */ - while(pte){ - opte = &o->pte[(pte->page->va-o->va)>>PGSHIFT]; - while(opte->nextmod != pte){ - if(opte->page && opte->page->va != pte->page->va) - panic("pte %lux %lux\n", opte->page->va, pte->page->va); - opte = opte->nextmod; - if(opte == 0) - panic("freeseg opte==0"); - } - opte->nextmod = pte->nextmod; - pg = pte->page; - if(pg->ref == 1){ - pte->page = 0; - pg->o = 0; - } - pg->ref--; - o->npage--; - old = (PTEA*)pte; - pte = pte->nextva; - lock(&modalloc); - old->next = modalloc.free; - modalloc.free = old; - unlock(&modalloc); - } - } - o->nproc--; - if(o->nproc == 0){ - if(c = o->chan){ /* assign = */ - o->chan = 0; - close(c); - } - if(!(o->flag&OCACHED) || o->npage==0){ - freepage(o); - freepte(o); - unlock(o); - lock(&origalloc); - o->next = origalloc.free; - origalloc.free = o; - unlock(&origalloc); - }else - unlock(o); - }else{ - /* - * BUG: there is a leak here. if the origin pte is being used only - * by the exiting process, the associated page will linger. the fix - * is to remember either the length of the mod list at each va or - * the number of processes sharing the origin pte, and to promote one - * of the mods to the origin pte when no process is left using the - * origin pte. - */ - unlock(o); - } - } -} - -/* - * Adjust segment to desired size. This implementation is rudimentary. - */ -int -segaddr(Seg *s, ulong min, ulong max) -{ - Orig *o; - - if(max < min) - return 0; - if(min != s->minva) /* can't grow down yet (stacks: fault.c) */ - return 0; - max = (max+(BY2PG-1)) & ~(BY2PG-1); - o = s->o; - if(max == s->maxva) - return 1; - if(max > s->maxva){ - /* - * Grow - */ - /* BUG: check spill onto other segments */ - if(o->va+BY2PG*o->npte < max) - growpte(o, (max-o->va)>>PGSHIFT); - s->maxva = max; - return 1; - } - /* - * Shrink - */ - print("segaddr shrink"); - for(;;); -} - -/* - * o is locked - */ -void -freepage(Orig *o) -{ - PTE *pte; - Page *pg; - int i; - - pte = o->pte; - for(i=0; inpte; i++,pte++) - if(pg = pte->page){ /* assign = */ - if(pg->ref == 1){ - pte->page = 0; - pg->o = 0; - } - pg->ref--; - } - o->npage = 0; -} - -/* - * Compacting allocator - */ - -void -freepte(Orig *o) /* o is locked */ -{ - PTEA *p; - p = (PTEA*)(o->pte - 1); - p->o = 0; -} - -/* - * o is locked. this will always do a grow; if n<=o->npte someone - * else got here first and we can just return. - */ -void -growpte(Orig *o, ulong n) -{ - PTEA *p; - ulong nfree; - - lock(&ptealloc); - lock(o); - if(o->pte){ - if(o->npte >= n) - goto Return; - p = (PTEA*)(o->pte - 1); - n++; - if(p+p->n == ptealloc.free){ - if(!compactpte(o, n - p->n)) - goto Trouble; - p = (PTEA*)(o->pte - 1); - ptealloc.free += n - p->n; - }else{ - if(!compactpte(o, n)) - goto Trouble; - p = ptealloc.free; - ptealloc.free += n; - memcpy(p+1, o->pte, o->npte*sizeof(PTE)); - p->o = o; - ((PTEA*)(o->pte-1))->o = 0; - o->pte = p+1; - } - memset(p+1+o->npte, 0, (n-(1+o->npte))*sizeof(PTE)); - p->n = n; - o->npte = n-1; - goto Return; - } - n++; - if(!compactpte(o, n)) - goto Trouble; - p = ptealloc.free; - ptealloc.free += n; - memset(p, 0, n*sizeof(PTE)); - p->n = n; - p->o = o; - o->pte = p+1; - o->npte = n-1; - Return: - unlock(&ptealloc); - unlock(o); - return; - - Trouble: - unlock(&ptealloc); - unlock(o); - if(u && u->p) - error(Enovmem); - panic("growpte fails %d %lux %d\n", n, o->va, o->npte); -} - -int -compactpte(Orig *o, ulong n) -{ - PTEA *p1, *p2; - Orig *p2o; - - if(ptealloc.end-ptealloc.free >= n) - return 1; - p1 = ptealloc.arena; /* dest */ - p2 = ptealloc.arena; /* source */ - while(p2 < ptealloc.free){ - p2o = p2->o; - if(p2o == 0){ - Free: - p2 += p2->n; - continue; - } - if(p1 != p2){ - if(p2o != o) - lock(p2o); - if(p2->o != p2o){ /* freepte()d very recently */ - if(p2->o) - panic("compactpte p2->o %lux\n", p2->o); - unlock(p2o); - goto Free; - } - memcpy(p1, p2, p2->n*sizeof(PTE)); - p2o->pte = p1+1; - if(p2o != o) - unlock(p2o); - } - p2 += p1->n; - p1 += p1->n; - } - ptealloc.free = p1; - if(ptealloc.end-ptealloc.free >= n) - return 1; - unlock(o); - unlock(&ptealloc); - if(u && u->p) - print("%s: %s: ", u->p->text, u->p->pgrp->user); - print("compactpte fails addr %lux\n", o->va+n*BY2PG); - return 0; -} diff --git a/port/fault.c b/port/fault.c index 8bf8af46170546ae45a2dd01e064b4791b87bd6b..174fe71cc157f0478d817d6429991b5761d8f0c1 100644 --- a/port/fault.c +++ b/port/fault.c @@ -6,11 +6,10 @@ #include "ureg.h" #include "errno.h" -void -fault(Ureg *ur, int user, int code) +int +fault(ulong addr, int read) { - ulong addr, mmuvirt, mmuphys, n; - extern char *excname[]; + ulong mmuvirt, mmuphys, n; Seg *s; PTE *opte, *pte, *npte; Orig *o; @@ -18,34 +17,21 @@ fault(Ureg *ur, int user, int code) Page *pg; int zeroed = 0, head = 1; int i; - - addr = ur->badvaddr; - addr &= ~(BY2PG-1); + KMap *k, *k1; s = seg(u->p, addr); if(s == 0){ - if(addr>USTKTOP){ - cant: - if(user){ - pprint("user %s badvaddr=0x%lux\n", excname[code], ur->badvaddr); - pprint("status=0x%lux pc=0x%lux sp=0x%lux\n", ur->status, ur->pc, ur->sp); - pexit("Suicide", 0); - } - print("kernel %s badvaddr=0x%lux\n", excname[code], ur->badvaddr); - print("status=0x%lux pc=0x%lux sp=0x%lux\n", ur->status, ur->pc, ur->sp); - u->p->state = MMUing; - dumpregs(ur); - panic("fault"); - } + if(addr>USTKTOP) + return -1; s = &u->p->seg[SSEG]; if(s->o==0 || addrmaxva-USTACKSIZE || addr>=s->maxva) - goto cant; + return -1; /* grow stack */ o = s->o; n = o->npte; if(waserror()){ pprint("can't allocate stack page\n"); - goto cant; + return -1; } growpte(o, (s->maxva-addr)>>PGSHIFT); poperror(); @@ -58,8 +44,8 @@ fault(Ureg *ur, int user, int code) o->va = addr; }else o = s->o; - if((code==CTLBM || code==CTLBS) && (o->flag&OWRPERM)==0) - goto cant; + if(!read && (o->flag&OWRPERM)==0) + return -1; lock(o); opte = &o->pte[(addr-o->va)>>PGSHIFT]; pte = opte; @@ -92,23 +78,25 @@ fault(Ureg *ur, int user, int code) if(n > BY2PG) n = BY2PG; pg = newpage(1, o, addr); + k = kmap(pg); qlock(o->chan); if(waserror()){ + kunmap(k); qunlock(o->chan); pg->o = 0; pg->ref--; pexit("load i/o error", 0); } o->chan->offset = (addr-o->va) + o->minca; - l = (char*)(pg->pa|KZERO); + l = (char*)VA(k); if((*devtab[o->chan->type].read)(o->chan, l, n) != n) error(Eioload); qunlock(o->chan); - poperror(); - /* BUG: if was first page of bss, move to data */ if(npte[(addr-s->minva)>>PGSHIFT]; /* could move */ pte = opte; if(pte->page == 0){ @@ -121,9 +109,9 @@ fault(Ureg *ur, int user, int code) } } /* - * Copy on reference + * Copy on reference (conf.copymode==1) or write (conf.copymode==0) */ - if((o->flag & OWRPERM) + if((o->flag & OWRPERM) && (conf.copymode || !read) && ((head && ((o->flag&OPURE) || o->nproc>1)) || (!head && pte->page->ref>1))){ @@ -173,7 +161,11 @@ fault(Ureg *ur, int user, int code) opte->page = 0; }else{ /* copy page */ pte->page = newpage(1, o, addr); - memcpy((void*)(pte->page->pa|KZERO), (void*)(pg->pa|KZERO), BY2PG); + k = kmap(pte->page); + k1 = kmap(pg); + memcpy((void*)VA(k), (void*)VA(k1), BY2PG); + kunmap(k); + kunmap(k1); if(pg->ref <= 1) panic("pg->ref <= 1"); pg->ref--; @@ -181,7 +173,7 @@ fault(Ureg *ur, int user, int code) easy: mmuphys = PTEWRITE; }else{ - mmuphys = 0; + mmuphys = PTERONLY; if(o->flag & OWRPERM) if(o->flag & OPURE){ if(!head && pte->page->ref==1) @@ -192,7 +184,7 @@ fault(Ureg *ur, int user, int code) mmuphys = PTEWRITE; } mmuvirt = addr; - mmuphys |= pte->page->pa | PTEVALID; + mmuphys |= PPN(pte->page->pa) | PTEVALID; usepage(pte->page, 1); if(pte->page->va != addr) panic("wrong addr in tail %lux %lux", pte->page->va, addr); @@ -203,6 +195,7 @@ fault(Ureg *ur, int user, int code) } unlock(o); putmmu(mmuvirt, mmuphys); + return 0; } /* @@ -235,15 +228,6 @@ validaddr(ulong addr, ulong len, int write) } } -void -evenaddr(ulong addr) -{ - if(addr & 3){ - postnote(u->p, 1, "sys: odd address", NDebug); - error(Ebadarg); - } -} - /* * &s[0] is known to be a valid address. */ diff --git a/port/page.c b/port/page.c index e7695ecc80759f150fe2221cf97b413a4bc7cc90..5560499bcdd8bf773ec402a0dcd3e3640561b6fa 100644 --- a/port/page.c +++ b/port/page.c @@ -55,7 +55,7 @@ ialloc(ulong n, int align) { ulong p; - if(palloc.active) + if(palloc.active && n!=0) print("ialloc bad\n"); if(palloc.addr == 0) palloc.addr = ((ulong)&end)&~KZERO; @@ -185,7 +185,7 @@ loop: continue; } print("free %d pages va %lux %lux %c\n", o1->npage, o->va, o1->qid, devchar[o1->type]); - freepage(o1); + freepage(o1, 0); /* neworig will free the orig and pte's later */ unlock(o1); if(p->ref == 0) @@ -367,7 +367,7 @@ loop: unlock(o); continue; } - freepage(o); + freepage(o, 1); freepte(o); unlock(o); o->next = origalloc.free; @@ -506,7 +506,7 @@ freesegs(int save) close(c); } if(!(o->flag&OCACHED) || o->npage==0){ - freepage(o); + freepage(o, 1); freepte(o); unlock(o); lock(&origalloc); @@ -566,7 +566,7 @@ segaddr(Seg *s, ulong min, ulong max) * o is locked */ void -freepage(Orig *o) +freepage(Orig *o, int dolock) { PTE *pte; Page *pg; @@ -576,7 +576,7 @@ freepage(Orig *o) for(i=0; inpte; i++,pte++) if(pg = pte->page){ /* assign = */ if(pg->ref == 1){ - unusepage(pg, 1); + unusepage(pg, dolock); pte->page = 0; pg->o = 0; } diff --git a/port/proc.c b/port/proc.c index 23d32889af7e8eb19dae2fc7d9833dc499faeac5..7f6339f9fc74cee2d0894516a732c7f2859eaf96 100644 --- a/port/proc.c +++ b/port/proc.c @@ -59,7 +59,6 @@ schedinit(void) /* never returns */ else if(p->state == Moribund){ p->pid = 0; unlock(&p->debug); - unusepage(p->upage, 1); p->upage->ref--; /* procalloc already locked */ p->qnext = procalloc.free; @@ -83,13 +82,13 @@ sched(void) if(u){ splhi(); - save(procstate, sizeof(procstate)); + procsave(procstate, sizeof(procstate)); if(setlabel(&u->p->sched)){ /* woke up */ p = u->p; p->state = Running; p->mach = m; m->proc = p; - restore(p, procstate); + procrestore(p, procstate); spllo(); return; } @@ -481,6 +480,7 @@ pexit(char *s, int freemem) lock(&procalloc); /* sched() can't do this */ lock(&c->debug); /* sched() can't do this */ + unusepage(c->upage, 1); /* sched() can't do this (it locks) */ c->state = Moribund; sched(); /* never returns */ } @@ -567,6 +567,7 @@ kproc(char *name, void (*func)(void *), void *arg) * Kernel stack */ p = newproc(); + p->kp = 1; p->upage = newpage(1, 0, USERADDR|(p->pid&0xFFFF)); k = kmap(p->upage); upa = VA(k); diff --git a/port/stream.c b/port/stream.c index 00ce77f3cc80389fb5a59c967b339266de2fa9fc..d2139d5f15674b42e1c41af1cfdff0f1cfc938f0 100644 --- a/port/stream.c +++ b/port/stream.c @@ -314,6 +314,7 @@ allocq(Qinfo *qi) q->put = qi->iput; q->len = q->nb = 0; q->ptr = 0; + q->rp = &q->r; wq = q->other = q + 1; wq->flag = QINUSE; @@ -323,6 +324,7 @@ allocq(Qinfo *qi) wq->other = q; wq->ptr = 0; wq->len = wq->nb = 0; + wq->rp = &wq->r; unlock(q); @@ -495,7 +497,7 @@ getq(Queue *q) q->len -= BLEN(bp); q->nb--; if((q->flag&QHIWAT) && q->lennbother->next->other->r); + wakeup(q->other->next->other->rp); q->flag &= ~QHIWAT; } bp->next = 0; @@ -928,7 +930,7 @@ stputq(Queue *q, Block *bp) freeb(bp); q->flag |= QHUNGUP; q->other->flag |= QHUNGUP; - wakeup(&q->other->r); + wakeup(q->other->rp); delim = 1; } else { delim = 0; @@ -954,7 +956,7 @@ stputq(Queue *q, Block *bp) unlock(q); } if(delim) - wakeup(&q->r); + wakeup(q->rp); } /* @@ -1048,7 +1050,8 @@ streamread(Chan *c, void *vbuf, long n) else error(Ehungup); } - sleep(&q->r, &isinput, (void *)q); + q->rp = &q->r; + sleep(q->rp, &isinput, (void *)q); continue; } @@ -1167,7 +1170,8 @@ flowctl(Queue *q) qunlock(&q->rlock); nexterror(); } - sleep(&q->r, notfull, q->next); + q->rp = &q->r; + sleep(q->rp, notfull, q->next); qunlock(&q->rlock); poperror(); } diff --git a/port/sturp.c b/port/sturp.c index 109696ab52a52ef5abebc60e880397201f9a079a..0013e443f4489d6409692cff57b7466e72abf2a2 100644 --- a/port/sturp.c +++ b/port/sturp.c @@ -169,6 +169,7 @@ urpopen(Queue *q, Stream *s) } q->ptr = q->other->ptr = up; + q->rp = &urpkr; up->rq = q; up->wq = q->other; up->state = OPEN; diff --git a/port/sysproc.c b/port/sysproc.c index ae2c7f05d747e025ed6111b762c6ad68b610a63e..8d188048a10141c139caa04e9d05facb8d13b462 100644 --- a/port/sysproc.c +++ b/port/sysproc.c @@ -205,10 +205,7 @@ sysexec(ulong *arg) Binary: t = (UTZERO+sizeof(Exec)+exec.text+(BY2PG-1)) & ~(BY2PG-1); - /* - * Last partial page of data goes into BSS. - */ - d = (t + exec.data) & ~(BY2PG-1); + d = (t + exec.data + (BY2PG-1)) & ~(BY2PG-1); bssend = t + exec.data + exec.bss; b = (bssend + (BY2PG-1)) & ~(BY2PG-1); if((t|d|b) & KZERO) @@ -311,7 +308,7 @@ sysexec(ulong *arg) if(o == 0){ o = neworig(t, (d-t)>>PGSHIFT, OWRPERM|OPURE|OCACHED, tc); o->minca = p->seg[TSEG].o->maxca; - o->maxca = o->minca + (exec.data & ~(BY2PG-1)); + o->maxca = o->minca + exec.data; } s->o = o; s->minva = t; @@ -319,15 +316,13 @@ sysexec(ulong *arg) s->mod = 0; /* - * BSS. Created afresh, starting with last page of data. - * BUG: should pick up the last page of data, which should be cached in the - * data segment. + * BSS. Created afresh. */ s = &p->seg[BSEG]; s->proc = p; - o = neworig(d, (b-d)>>PGSHIFT, OWRPERM, tc); - o->minca = p->seg[DSEG].o->maxca; - o->maxca = o->minca + (exec.data & (BY2PG-1)); + o = neworig(d, (b-d)>>PGSHIFT, OWRPERM, 0); + o->minca = 0; + o->maxca = 0; s->o = o; s->minva = d; s->maxva = b; @@ -353,7 +348,7 @@ sysexec(ulong *arg) unlock(o); flushmmu(); - clearmmucache(); + clearmmucache(); ((Ureg*)UREGADDR)->pc = exec.entry + ENTRYOFFSET; sp = (ulong*)(USTKTOP - ssize); *--sp = nargs; @@ -362,7 +357,7 @@ sysexec(ulong *arg) u->nnote = 0; u->notify = 0; u->notified = 0; - setup(p); + procsetup(p); unlock(&p->debug); return 0; } diff --git a/power/conf.h b/power/conf.h index b2f150c02ce0cac454f236d9dd96b6f005d852be..4df01549f968d084cd92bee4ce515128010e75e6 100644 --- a/power/conf.h +++ b/power/conf.h @@ -29,6 +29,7 @@ Conftab conftab[] = { {"maxialloc", &conf.maxialloc }, {"base0", &conf.base0 }, {"base1", &conf.base1 }, + {"copymode", &conf.copymode }, { 0, 0 }, }; diff --git a/power/dat.h b/power/dat.h index e307035e81b6b2bf67de07da3d8091b52e7cdc32..7b9ef9260904c8359199a4c384a43190dcf8a603 100644 --- a/power/dat.h +++ b/power/dat.h @@ -152,6 +152,7 @@ struct Conf ulong maxialloc; /* maximum bytes used by ialloc */ ulong base0; /* base of bank 0 */ ulong base1; /* base of bank 1 */ + ulong copymode; /* 0 is copy on write, 1 is copy on reference */ }; struct Dev @@ -336,6 +337,7 @@ struct Proc Rendez sleep; /* place for tsleep and syssleep */ int wokeup; /* whether sleep was interrupted */ ulong pc; /* DEBUG only */ + int kp; /* true if kernel process */ }; @@ -378,6 +380,7 @@ typedef void KMap; #define VA(k) ((ulong)(k)) #define kmap(p) (KMap*)(p->pa|KZERO) #define kunmap(k) +#define PPN(x) x /* * operations available to a queue @@ -438,7 +441,8 @@ struct Queue { Queue *next; /* next queue in the stream */ void (*put)(Queue*, Block*); QLock rlock; /* mutex for r */ - Rendez r; + Rendez r; /* standard place to wait for flow control */ + Rendez *rp; /* where flow control wakeups go to */ void *ptr; /* private info for the queue */ }; #define QHUNGUP 0x1 /* flag bit meaning the stream has been hung up */ diff --git a/power/devrtc.c b/power/devrtc.c index a13ac555a7383f1aba1db40a9cb7b67454b044ca..7a074ab66c81b2d16a1ea7220f83380aab610ae9 100644 --- a/power/devrtc.c +++ b/power/devrtc.c @@ -27,7 +27,7 @@ struct Rtc QLock rtclock; /* mutex on clock operations */ static Dirtab rtcdir[]={ - "rtc", {1}, 0, 0600, + "rtc", {1, 0}, 0, 0600, }; static uchar pattern[] = @@ -145,6 +145,9 @@ rtcread(Chan *c, void *buf, long n) char atime[64]; Rtc rtc; + if(c->qid.path & CHDIR) + return devdirread(c, buf, n, rtcdir, 1, devgen); + nv = RTC; /* diff --git a/power/faultmips.c b/power/faultmips.c new file mode 100644 index 0000000000000000000000000000000000000000..a86a63ca34e92ac2026d008dbfbe9d8bd292b379 --- /dev/null +++ b/power/faultmips.c @@ -0,0 +1,47 @@ +#include "u.h" +#include "lib.h" +#include "mem.h" +#include "dat.h" +#include "fns.h" +#include "ureg.h" +#include "errno.h" + +/* + * find out fault address and type of access. + * Call common fault handler. + */ +void +faultmips(Ureg *ur, int user, int code) +{ + ulong addr; + extern char *excname[]; + int read; + + addr = ur->badvaddr; + addr &= ~(BY2PG-1); + read = !(code==CTLBM || code==CTLBS); + if(fault(addr, read) < 0){ + if(user){ + pprint("user %s badvaddr=0x%lux\n", excname[code], ur->badvaddr); + pprint("status=0x%lux pc=0x%lux sp=0x%lux\n", ur->status, ur->pc, ur->sp); + pexit("Suicide", 0); + } + print("kernel %s badvaddr=0x%lux\n", excname[code], ur->badvaddr); + print("status=0x%lux pc=0x%lux sp=0x%lux\n", ur->status, ur->pc, ur->sp); + u->p->state = MMUing; + dumpregs(ur); + panic("fault"); + } +} + +/* + * called in sysfile.c + */ +void +evenaddr(ulong addr) +{ + if(addr & 3){ + postnote(u->p, 1, "sys: odd address", NDebug); + error(Ebadarg); + } +} diff --git a/power/fns.h b/power/fns.h index ee4a8ab4e669c4ac53b1ceb0403c8faedec5b805..2faf77217de92e6bd7b46f67c1748b90147e3fb8 100644 --- a/power/fns.h +++ b/power/fns.h @@ -57,7 +57,8 @@ void error(int); void errors(char*); void evenaddr(ulong); void exit(void); -void fault(Ureg*, int, int); +int fault(ulong, int); +void faultmips(Ureg*, int, int); void fdclose(int); Chan* fdtochan(int, int); void firmware(void); @@ -66,7 +67,7 @@ void flushmmu(void); void forkmod(Seg*, Seg*, Proc*); void freeb(Block*); int freebroken(void); -void freepage(Orig*); +void freepage(Orig*, int); void freepte(Orig*); void freesegs(int); void freealarm(Alarm*); @@ -155,11 +156,9 @@ int readnum(ulong, char*, ulong, ulong, int); void ready(Proc*); void qlock(QLock*); void qunlock(QLock*); -void restore(Proc*, uchar*); void restfpregs(FPsave*); int return0(void*); Proc *runproc(void); -void save(uchar*, int); void savefpregs(FPsave*); void sched(void); void schedinit(void); @@ -167,7 +166,6 @@ long seconds(void); Seg *seg(Proc*, ulong); int segaddr(Seg*, ulong, ulong); int setlabel(Label*); -void setup(Proc*); void setvmevec(int, void (*)(int)); void sinit(void); char* skipslash(char*); @@ -212,3 +210,10 @@ void wbflush(void); #define waserror() setlabel(&u->errlab[u->nerrlab++]) #define poperror() u->nerrlab-- + +/* + * no external state to save on the SGI + */ +#define procsetup(x) +#define procsave(x,y) +#define procrestore(x,y) diff --git a/power/main.c b/power/main.c index 7225ba25baf0fe8f1cf4d455e8d35540ebfc2383..3f2b1582984ffda018e4b2f51c063a8e9e997a39 100644 --- a/power/main.c +++ b/power/main.c @@ -631,6 +631,7 @@ confinit(void) if(conf.nmach > MAXMACH) panic("confinit"); + conf.copymode = 1; /* copy on reference */ } @@ -695,27 +696,3 @@ arginit(void) _argv = argv; argsize = ssize; } - -/* - * set up machine dependent process state for a new process - */ -void -setup(Proc *p) -{ -} - -/* - * Save machine dependent process state - */ -void -save(uchar *state, int len) -{ -} - -/* - * Restore what save() saves - */ -void -restore(Proc *p, uchar *state) -{ -} diff --git a/power/mem.h b/power/mem.h index 4c82935e39585ca021a0e1602fc16908a711b5e6..337765d664aad328a77a121552b2977e0bfb393c 100644 --- a/power/mem.h +++ b/power/mem.h @@ -94,6 +94,7 @@ #define PTEGLOBL (1<<8) #define PTEVALID (1<<9) #define PTEWRITE (1<<10) +#define PTERONLY 0 #define PTEPID(n) ((n)<<6) #define NTLBPID 64 /* number of pids */ diff --git a/power/trap.c b/power/trap.c index a99f561d436306a2de115a7014f743fc74ddee1c..41368cc33582ecb8bb1b6e35374851111af67a44 100644 --- a/power/trap.c +++ b/power/trap.c @@ -122,7 +122,7 @@ trap(Ureg *ur) spllo(); x = u->p->insyscall; u->p->insyscall = 1; - fault(ur, user, ecode); + faultmips(ur, user, ecode); u->p->insyscall = x; break;