M gnot/clock.c => gnot/clock.c +3 -1
@@ 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++;
M gnot/trap.c => gnot/trap.c +8 -15
@@ 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);
M pc/fault386.c => pc/fault386.c +1 -0
@@ 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){
M pc/l.s => pc/l.s +1 -1
@@ 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\
M pc/main.c => pc/main.c +10 -8
@@ 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;
}
}
M pc/mem.h => pc/mem.h +3 -3
@@ 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))
/*
M pc/mmu.c => pc/mmu.c +17 -9
@@ 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;
}
M pc/trap.c => pc/trap.c +13 -6
@@ 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);
M port/fault.c => port/fault.c +3 -15
@@ 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);
M port/lib.h => port/lib.h +1 -0
@@ 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
M port/page.c => port/page.c +14 -4
@@ 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--;
}
M port/portdat.h => port/portdat.h +3 -3
@@ 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 */
M port/proc.c => port/proc.c +17 -4
@@ 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; i<conf.nproc; i++){
p = procalloc.arena+i;
if(p->state != 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);
}
}
}
M port/swap.c => port/swap.c +22 -21
@@ 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
M power/clock.c => power/clock.c +2 -0
@@ 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;
M power/trap.c => power/trap.c +4 -4
@@ 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 */
}
M ss/fptrap.c => ss/fptrap.c +7 -10
@@ 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;
M ss/trap.c => ss/trap.c +3 -4
@@ 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 */
}