From fd21a503ae1d591cf9cea82f15cbada4c4e245e9 Mon Sep 17 00:00:00 2001 From: David du Colombier <0intro@gmail.com> Date: Wed, 5 Aug 1992 00:00:00 +0000 Subject: [PATCH] Plan 9 from Bell Labs 1992-08-05 --- gnot/clock.c | 4 +++- gnot/trap.c | 23 ++++++++--------------- pc/fault386.c | 1 + pc/l.s | 2 +- pc/main.c | 18 ++++++++++-------- pc/mem.h | 6 +++--- pc/mmu.c | 26 +++++++++++++++++--------- pc/trap.c | 19 +++++++++++++------ port/fault.c | 18 +++--------------- port/lib.h | 1 + port/page.c | 18 ++++++++++++++---- port/portdat.h | 6 +++--- port/proc.c | 21 +++++++++++++++++---- port/swap.c | 43 ++++++++++++++++++++++--------------------- power/clock.c | 2 ++ power/trap.c | 8 ++++---- ss/fptrap.c | 17 +++++++---------- ss/trap.c | 7 +++---- 18 files changed, 132 insertions(+), 108 deletions(-) diff --git a/gnot/clock.c b/gnot/clock.c index b04510b9fab22c5ae77274cddd037de8a5eb07f9..e7860a4912808761071f10d365be755a0a5f1f6c 100644 --- a/gnot/clock.c +++ b/gnot/clock.c @@ -24,8 +24,10 @@ clock(Ureg *ur) int user, nrun = 0; user = (ur->sr&SUPER) == 0; - if(user) + if(user){ u->dbgreg = ur; + u->p->pc = ur->pc; + } SYNCREG[1] = 0x5F; /* clear interrupt */ m->ticks++; diff --git a/gnot/trap.c b/gnot/trap.c index 2a709ce88c94ab0b2e7bc7e25f38177676600b69..9268d0982818a60d50af09e6d517d7499df2e9cc 100644 --- a/gnot/trap.c +++ b/gnot/trap.c @@ -105,10 +105,9 @@ trap(Ureg *ur) user = !(ur->sr&SUPER); - if(u) { - u->p->pc = ur->pc; /* BUG */ + if(u) u->dbgreg = ur; - } + if(user){ sprint(buf, "sys: %s", excname(ur->vo, ur->pc)); postnote(u->p, 1, buf, NDebug); @@ -283,19 +282,13 @@ syscall(Ureg *aur) u->p->pc = ur->pc; if(ur->sr & SUPER) panic("recursive system call"); - /* - * since the system call interface does not - * guarantee anything about registers, but the fpcr is more than - * just a register... BUG - */ - splhi(); - fpsave(&u->fpsave); - if(u->p->fpstate==FPactive || u->fpsave.type){ - fprestore(&initfp); - u->p->fpstate = FPinit; - m->fpstate = FPinit; + + /* must save FP registers before fork */ + if(u->p->fpstate==FPactive && ur->r0==RFORK){ + splhi(); + procsave(u->p); + spllo(); } - spllo(); if(u->p->procctl) procctl(u->p); diff --git a/pc/fault386.c b/pc/fault386.c index 28366ba2415bc31ad00d076689f9cfe3b41925c7..26ec224499e4c3fe3b3e51ea21e77a3684bb90e7 100644 --- a/pc/fault386.c +++ b/pc/fault386.c @@ -23,6 +23,7 @@ fault386(Ureg *ur) addr = getcr2(); read = !(ur->ecode & 2); user = (ur->cs&0xffff) == UESEL; + spllo(); n = fault(addr, read); if(n < 0){ if(user){ diff --git a/pc/l.s b/pc/l.s index 2343c7a46d791d9eb2a780b6046d631d00909d4f..930bda05a2c1297e9ab171edc83ad99f39236b41 100644 --- a/pc/l.s +++ b/pc/l.s @@ -290,7 +290,7 @@ TEXT getcr2(SB),$0 /* fault address */ #define FPOFF\ WAIT;\ MOVL CR0,AX;\ - ORL $0x4,AX /* EM=1 */;\ + ORL $0x24,AX /* EM=1, NE=1 */;\ MOVL AX,CR0 #define FPON\ diff --git a/pc/main.c b/pc/main.c index 889efe829e3ad7ebd489684dbc44c958ba370ab6..9f3c8c9f629917410bc0578bb1915b0c0aea0209 100644 --- a/pc/main.c +++ b/pc/main.c @@ -295,6 +295,7 @@ matherror(Ureg *ur) break; } sprint(note, "sys: fp: %s, status 0x%ux, pc 0x%lux", msg, status, ur->pc); +print("%s cr0 %lux\n", note, getcr0()); postnote(u->p, 1, note, NDebug); } @@ -315,7 +316,7 @@ mathemu(Ureg *ur) u->p->fpstate = FPactive; break; case FPactive: - pexit("Math emu", 0); + panic("math emu", 0); break; } } @@ -327,7 +328,8 @@ void mathover(Ureg *ur) { USED(ur); - pexit("Math overrun", 0); +print("sys: fp: math overrun pc 0x%lux pid %d\n", ur->pc, u->p->pid); + pexit("math overrun", 0); } void @@ -355,12 +357,12 @@ procsetup(Proc *p) void procsave(Proc *p) { - USED(p); - if(u->p->state == Moribund) - return; - if(u->p->fpstate == FPactive){ - fpsave(&u->fpsave); - u->p->fpstate = FPinactive; + if(p->fpstate == FPactive){ + if(p->state == Moribund) + fpoff(); + else + fpsave(&u->fpsave); + p->fpstate = FPinactive; } } diff --git a/pc/mem.h b/pc/mem.h index 5cd0e85ba5db5a5b9dc807a0a0b8ab849d86c968..1a8672e50ac9a5c1221b2c87a0f491bcbefebc68 100644 --- a/pc/mem.h +++ b/pc/mem.h @@ -99,9 +99,9 @@ /* * virtual MMU */ -#define PTEMAPMEM (1024*1024) /* ??? */ -#define SEGMAPSIZE 16 /* ??? */ -#define PTEPERTAB (PTEMAPMEM/BY2PG) /* ??? */ +#define PTEMAPMEM (1024*1024) +#define SEGMAPSIZE 64 +#define PTEPERTAB (PTEMAPMEM/BY2PG) #define PPN(x) ((x)&~(BY2PG-1)) /* diff --git a/pc/mmu.c b/pc/mmu.c index 75b57a5c2e43b39e520dd3e242fe4da7e001e838..0ac9ad0e8b17f27a9a8d6e6052d67288df58c000 100644 --- a/pc/mmu.c +++ b/pc/mmu.c @@ -180,24 +180,31 @@ flushmmu(void) void mapstack(Proc *p) { - Page *pg, **l; + Page *pg; + ulong *top; if(p->upage->va != (USERADDR|(p->pid&0xFFFF)) && p->pid != 0) panic("mapstack %d 0x%lux 0x%lux", p->pid, p->upage->pa, p->upage->va); if(p->newtlb){ /* - * bin the current second level page tables. * newtlb set means that they are inconsistent * with the segment.c data structures. + * + * bin the current second level page tables and + * the pointers to them in the top level page. + * pg->daddr is used by putmmu to save the offset into + * the top level page. */ - if(p->mmutop) - memmove((void*)p->mmutop->va, (void*)ktoppg.va, BY2PG); - l = &p->mmufree; - for(pg = p->mmufree; pg; pg = pg->next) - l = &pg->next; - *l = p->mmuused; - p->mmuused = 0; + if(p->mmutop && p->mmuused){ + top = (ulong*)p->mmutop->va; + for(pg = p->mmuused; pg->next; pg = pg->next) + top[pg->daddr] = 0; + top[pg->daddr] = 0; + pg->next = p->mmufree; + p->mmufree = p->mmuused; + p->mmuused = 0; + } p->newtlb = 0; } @@ -289,6 +296,7 @@ putmmu(ulong va, ulong pa, Page *pg) memset((void*)pg->va, 0, BY2PG); } top[topoff] = PPN(pg->pa) | PTEVALID | PTEUSER | PTEWRITE; + pg->daddr = topoff; pg->next = p->mmuused; p->mmuused = pg; } diff --git a/pc/trap.c b/pc/trap.c index b8cd6978af4996dd8422fa45b44cbf3948acc088..de25fa3be35909c8ef21102741531cd0ded9c5bd 100644 --- a/pc/trap.c +++ b/pc/trap.c @@ -110,7 +110,7 @@ trapinit(void) sethvec(11, intr11, SEGTG, 0); sethvec(12, intr12, SEGTG, 0); sethvec(13, intr13, SEGTG, 0); - sethvec(14, intr14, SEGTG, 0); + sethvec(14, intr14, SEGIG, 0); sethvec(15, intr15, SEGTG, 0); sethvec(16, intr16, SEGTG, 0); @@ -333,10 +333,19 @@ syscall(Ureg *ur) if((ur->cs)&0xffff == KESEL) panic("recursive system call"); - /* - * do something about floating point!!! - */ u->scallnr = ur->ax; + if(u->scallnr == RFORK && u->p->fpstate == FPactive){ + /* + * so that the child starts out with the + * same registers as the parent + */ + splhi(); + if(u->p->fpstate == FPactive){ + fpsave(&u->fpsave); + u->p->fpstate = FPinactive; + } + spllo(); + } sp = ur->usp; u->nerrlab = 0; ret = -1; @@ -353,10 +362,8 @@ syscall(Ureg *ur) u->s = *((Sargs*)(sp+1*BY2WD)); u->p->psstate = sysctab[u->scallnr]; -if(u->p->fgrp->ref <= 0) print("before syscall %s\n", u->p->psstate); ret = (*systab[u->scallnr])(u->s.args); poperror(); -if(u->p->fgrp->ref <= 0) print("after syscall %s\n", u->p->psstate); } if(u->nerrlab){ print("bad errstack [%d]: %d extra\n", u->scallnr, u->nerrlab); diff --git a/port/fault.c b/port/fault.c index add79d030ce451be1a3ba9cabe56371c873b98bf..60694a1b9f73f12d81c6b5edcc35194b95679122 100644 --- a/port/fault.c +++ b/port/fault.c @@ -43,7 +43,7 @@ int fixfault(Segment *s, ulong addr, int read, int doputmmu) { ulong mmuphys=0, soff; - Page **pg, *lkp, *new = 0; + Page **pg, *lkp, *new; Pte **p, *etp; int type; @@ -85,13 +85,11 @@ fixfault(Segment *s, ulong addr, int read, int doputmmu) case SG_SHARED: /* Zero fill on demand */ case SG_STACK: if(*pg == 0) { - if(new == 0) - if(new = newpage(1, &s, addr)) + new = newpage(1, &s, addr); if(s == 0) return -1; *pg = new; - new = 0; } /* NO break */ @@ -112,12 +110,10 @@ fixfault(Segment *s, ulong addr, int read, int doputmmu) lock(lkp); if(lkp->ref > 1) { unlock(lkp); - if(new == 0) - if(new = newpage(0, &s, addr)) + new = newpage(0, &s, addr); if(s == 0) return -1; *pg = new; - new = 0; copypage(lkp, *pg); putpage(lkp); } @@ -147,13 +143,6 @@ fixfault(Segment *s, ulong addr, int read, int doputmmu) qunlock(&s->lk); - /* - * A race may provide a page we never used when - * a fault is fixed while process slept in newpage - */ - if(new) - putpage(new); - if(doputmmu) putmmu(addr, mmuphys, *pg); @@ -255,7 +244,6 @@ pio(Segment *s, ulong addr, ulong soff, Page **p) cachepage(new, &swapimage); putswap(*p); *p = new; -/* print("l %lux %d\n", addr, daddr);*/ } else putpage(new); diff --git a/port/lib.h b/port/lib.h index a47eababc62403d45314ba20f36101077a07c3c4..e4fb34b3285c2f39f3731ed3c5091de5635afaaf 100644 --- a/port/lib.h +++ b/port/lib.h @@ -31,6 +31,7 @@ extern int runetochar(char*, Rune*); extern int chartorune(Rune*, char*); extern int countrune(char*); extern char* utfrune(char*, long); +extern int utflen(char*); /* * print routines diff --git a/port/page.c b/port/page.c index 18b837b3a087fcf05eea660b359f4aa5d20b04fb..317b1d16e4a72379b855e18fd005628330a674c4 100644 --- a/port/page.c +++ b/port/page.c @@ -64,18 +64,19 @@ newpage(int clear, Segment **s, ulong va) { Page *p; KMap *k; - int i; + int hw, i, dontalloc; lock(&palloc); - /* The kp test is a poor guard against the pager deadlocking */ - while((palloc.freecount < swapalloc.highwater && u->p->kp == 0) || - palloc.freecount == 0) { + hw = swapalloc.highwater; + while((palloc.freecount < hw && u->p->kp == 0) || palloc.freecount == 0) { palloc.wanted++; unlock(&palloc); + dontalloc = 0; if(s && *s) { qunlock(&((*s)->lk)); *s = 0; + dontalloc = 1; } qlock(&palloc.pwait); /* Hold memory requesters here */ @@ -88,6 +89,15 @@ newpage(int clear, Segment **s, ulong va) poperror(); qunlock(&palloc.pwait); + + /* + * If called from fault and we lost the segment from underneath + * don't waste time allocating and freeing a page. Fault will call + * newpage again when it has reaquired the segment locks + */ + if(dontalloc) + return 0; + lock(&palloc); palloc.wanted--; } diff --git a/port/portdat.h b/port/portdat.h index 64b3d362a988e22acb634a3573029164046b52af..645be390e8322725dfc9cc6b5342263df8118162 100644 --- a/port/portdat.h +++ b/port/portdat.h @@ -351,9 +351,9 @@ enum }; #define PG_ONSWAP 1 -#define pagedout(s) (((ulong)s)==0 || (((ulong)s)&PG_ONSWAP)) -#define swapaddr(s) (((ulong)s)&~PG_ONSWAP) #define onswap(s) (((ulong)s)&PG_ONSWAP) +#define pagedout(s) (((ulong)s)==0 || onswap(s)) +#define swapaddr(s) (((ulong)s)&~PG_ONSWAP) #define SEGMAXSIZE (SEGMAPSIZE*PTEMAPMEM) @@ -511,7 +511,7 @@ struct Proc ulong qlockpc; /* pc of last call to qlock */ int state; char *psstate; /* What /proc/#/status reports */ - Page *upage; /* BUG: should be unlinked from page list */ + Page *upage; /* page from palloc */ Segment *seg[NSEG]; ulong pid; ulong noteid; /* Equivalent of note group */ diff --git a/port/proc.c b/port/proc.c index e590bf6c10ecad920910e8ea266b92b69603197d..0ef2cd044203551e479fc344dd75720b29aa30ed 100644 --- a/port/proc.c +++ b/port/proc.c @@ -531,8 +531,12 @@ pexit(char *exitstr, int freemem) if(c->kp == 0) { if((p = c->parent) == 0) panic("boot process died"); - + + while(waserror()) + ; wq = smalloc(sizeof(Waitq)); + poperror(); + readnum(0, wq->w.pid, NUMSIZE, c->pid, NUMSIZE); utime = c->time[TUser] + c->time[TCUser]; stime = c->time[TSys] + c->time[TCSys]; @@ -657,15 +661,24 @@ void procdump(void) { int i; + char *s; Proc *p; + ulong bss; for(i=0; istate != Dead){ - print("%d:%s %s upc %lux %s ut %ld st %ld r %lux qpc %lux\n", + bss = 0; + if(p->seg[BSEG]) + bss = p->seg[BSEG]->top; + + s = p->psstate; + if(s == 0) + s = "kproc"; + print("%3d:%10s %10s pc %8lux %8s (%s) ut %ld st %ld r %lux qpc %lux bss %lux\n", p->pid, p->text, p->user, p->pc, - statename[p->state], p->time[0], - p->time[1], p->r, p->qlockpc); + s, statename[p->state], p->time[0], + p->time[1], p->r, p->qlockpc, bss); } } } diff --git a/port/swap.c b/port/swap.c index 78f6b3aba1b18daaf936e580bbb4bd18d88b8ca0..b47aa17738e839da007dda42aeb2c8a6612b01cc 100644 --- a/port/swap.c +++ b/port/swap.c @@ -21,7 +21,7 @@ enum Image swapimage; static int swopen; Page *iolist[Maxpages]; -int ioptr, npage; +int ioptr; void swapinit(void) @@ -87,7 +87,7 @@ pager(void *junk) { Proc *p, *ep; Segment *s; - int i, type; + int i; if(waserror()) panic("pager: os error\n"); @@ -99,9 +99,7 @@ pager(void *junk) loop: u->p->psstate = "Idle"; sleep(&swapalloc.r, needpages, 0); - u->p->psstate = "Pageout"; - npage = 0; for(;;) { p++; if(p >= ep) @@ -116,22 +114,28 @@ loop: goto loop; if(s = p->seg[i]) { - type = s->type&SG_TYPE; - switch(type) { + switch(s->type&SG_TYPE) { default: break; case SG_TEXT: + pageout(p, s); + break; case SG_DATA: case SG_BSS: case SG_STACK: case SG_SHARED: + u->p->psstate = "Pageout"; pageout(p, s); - executeio(); + if(ioptr != 0) { + u->p->psstate = "I/O"; + executeio(); + } } } } + continue; } - else + if(palloc.freecount < swapalloc.highwater) { if(!cpuserver) freebroken(); /* can use the memory */ @@ -142,17 +146,15 @@ loop: wakeup(&palloc.r); } } - if(npage == 0) - print("swap: pass took no pages\n"); goto loop; } void pageout(Proc *p, Segment *s) { - Pte **sm, **endsm, *l; + int type, i; + Pte *l; Page **pg, *entry; - int type; if(!canqlock(&s->lk)) /* We cannot afford to wait, we will surely deadlock */ return; @@ -177,9 +179,8 @@ pageout(Proc *p, Segment *s) /* Pass through the pte tables looking for memory pages to swap out */ type = s->type&SG_TYPE; - endsm = &s->map[SEGMAPSIZE]; - for(sm = s->map; sm < endsm; sm++) { - l = *sm; + for(i = 0; i < SEGMAPSIZE; i++) { + l = s->map[i]; if(l == 0) continue; for(pg = l->first; pg < l->last; pg++) { @@ -187,10 +188,12 @@ pageout(Proc *p, Segment *s) if(pagedout(entry)) continue; - if(entry->modref & PG_REF) + if(entry->modref & PG_REF) { entry->modref &= ~PG_REF; - else - pagepte(type, pg); + continue; + } + + pagepte(type, pg); if(ioptr >= Maxpages) goto out; @@ -206,8 +209,8 @@ out: int canflush(Proc *p, Segment *s) { - Proc *ep; int i; + Proc *ep; lock(s); if(s->ref == 1) { /* Easy if we are the only user */ @@ -232,7 +235,6 @@ canflush(Proc *p, Segment *s) } p++; } - return 1; } @@ -272,7 +274,6 @@ pagepte(int type, Page **pg) /* Add me to IO transaction list */ iolist[ioptr++] = outp; } - npage++; } void diff --git a/power/clock.c b/power/clock.c index a5b9fe13eeb5eecc0a78ecf115a347de2c4c09c9..67dd5f71d785de6640cf1196bc1a3f9f36d1ddc5 100644 --- a/power/clock.c +++ b/power/clock.c @@ -86,6 +86,8 @@ clock(Ureg *ur) LEDON(LEDpulse); else LEDOFF(LEDpulse); + if(m->proc) + m->proc->pc = ur->pc; if(m->machno == 0){ p = m->proc; diff --git a/power/trap.c b/power/trap.c index 704853c7b58d3b02e59768122a0e7e6724f78a0d..778a188a66e87d469964b3ff615a1d9cfd288f54 100644 --- a/power/trap.c +++ b/power/trap.c @@ -83,10 +83,9 @@ trap(Ureg *ur) ecode = EXCCODE(ur->cause); LEDON(ecode); user = ur->status&KUP; - if(u) { - u->p->pc = ur->pc; /* BUG */ + if(u) u->dbgreg = ur; - } + switch(ecode){ case CINT: if(u && u->p->state==Running){ @@ -505,7 +504,7 @@ syscall(Ureg *aur) p = u->p; p->insyscall = 1; ur = aur; - p->pc = ur->pc; /* BUG */ + p->pc = ur->pc; u->dbgreg = aur; ur->cause = 15<<2; /* for debugging: system call is undef 15; /* @@ -574,6 +573,7 @@ execregs(ulong entry, ulong ssize, ulong nargs) *--sp = nargs; ((Ureg*)UREGADDR)->usp = (ulong)sp; ((Ureg*)UREGADDR)->pc = entry - 4; /* syscall advances it */ + u->fpsave.fpstatus = initfp.fpstatus; return USTKTOP-BY2WD; /* address of user-level clock */ } diff --git a/ss/fptrap.c b/ss/fptrap.c index a4047bbfcf6d1447ad086efe70cc04eec03f6213..1426fa448ba9e554dbf2b2367c263874792c9adb 100644 --- a/ss/fptrap.c +++ b/ss/fptrap.c @@ -187,15 +187,8 @@ fixq(FPsave *f, int n) instr = f->q[0].i; /* * Sparc says you have to emulate. To hell with that. - * Let's compile! - */ - ip = bbmalloc(3*sizeof(ulong)); - ip[0] = instr; - ip[1] = 0x81c3e008; /* JMPL #8(R15), R0 [RETURN] */ - ip[2] = 0x01000000; /* SETHI #0, R0 [NOP] */ - /* - * You can always pump one instruction without immediate trap. - * Therefore run one and wait for it to complete or trap. + * We can compile on the fly instead. + * Run one instruction and wait for it to complete or trap. * If it traps, we'll recurse but we won't overwrite * our own data structures because there will be only * one instruction uncompleted in the FPU. @@ -206,8 +199,12 @@ fixq(FPsave *f, int n) * the trap by examining the non-zero members of the FPQ. * Tough. */ + ip = bbmalloc(3*sizeof(ulong)); + ip[0] = instr; + ip[1] = 0x81c3e008; /* JMPL #8(R15), R0 [RETURN] */ + ip[2] = 0x01000000; /* SETHI #0, R0 [NOP] */ f->fppc = f->q[0].a; - (*(void(*)(void))ip)(); + (*(void(*)(void))ip)(); /* You are expected to understand this cast */ f->fppc = 0; if(!fpquiet()) break; diff --git a/ss/trap.c b/ss/trap.c index 95b40b1c2301ed863c6a124ce5a8bf86195814b9..0cd4232ce2f9ff3ebfde76c159632afef8d12d4b 100644 --- a/ss/trap.c +++ b/ss/trap.c @@ -102,10 +102,8 @@ trap(Ureg *ur) char buf[64]; ulong tbr, iw; - if(u) { - u->p->pc = ur->pc; /* BUG */ + if(u) u->dbgreg = ur; - } fpunsafe = 0; user = !(ur->psr&PSRPSUPER); @@ -166,7 +164,7 @@ trap(Ureg *ur) case 4: /* floating point disabled */ if(u && u->p){ if(u->p->fpstate == FPinit) - restfpregs(initfpp, initfpp->fsr); + restfpregs(initfpp, u->fpsave.fsr); else if(u->p->fpstate == FPinactive) restfpregs(&u->fpsave, u->fpsave.fsr); else @@ -590,6 +588,7 @@ execregs(ulong entry, ulong ssize, ulong nargs) *--sp = nargs; ((Ureg*)UREGADDR)->usp = (ulong)sp; ((Ureg*)UREGADDR)->pc = entry - 4; /* syscall advances it */ + u->fpsave.fsr = initfpp->fsr; return USTKTOP-BY2WD; /* address of user-level clock */ }