M pc/main.c => pc/main.c +2 -0
@@ 356,6 356,8 @@ void
procsave(Proc *p)
{
USED(p);
+ if(u->p->state == Moribund)
+ return;
if(u->p->fpstate == FPactive){
fpsave(&u->fpsave);
u->p->fpstate = FPinactive;
M pc/mem.h => pc/mem.h +1 -1
@@ 108,7 108,7 @@
* physical MMU
*/
#define PTEVALID (1<<0)
-#define PTEUNCACHED 0 /* everything is uncached */
+#define PTEUNCACHED (1<<4)
#define PTEWRITE (1<<1)
#define PTERONLY (0<<1)
#define PTEKERNEL (0<<2)
M pc/mmu.c => pc/mmu.c +42 -80
@@ 86,6 86,10 @@ static ulong *upt; /* 2nd level page table for struct User */
*/
#define BTMOFF(v) ((((ulong)(v))>>(PGSHIFT))&(WD2PG-1))
+#define MAXUMEG 64 /* maximum memory per user process in megabytes */
+#define ONEMEG (1024*1024)
+
+
/*
* Create a prototype page map that maps all of memory into
* kernel (KZERO) space. This is the default map. It is used
@@ 152,56 156,19 @@ mmuinit(void)
}
/*
- * Get a page for a process's page map.
- *
- * Each process maintains its own free list of page
- * table pages. All page table pages are put on
- * this list in flushmmu(). flushmmu() doesn't
- * putpage() the pages since the process will soon need
- * them back. Also, this avoids worrying about deadlocks
- * twixt flushmmu() and putpage().
- *
- * mmurelease() will give back the pages when the process
- * exits.
- */
-static Page*
-mmugetpage(int clear)
-{
- Proc *p = u->p;
- Page *pg;
-
- if(p->mmufree){
- pg = p->mmufree;
- p->mmufree = pg->next;
- if(clear)
- memset((void*)pg->va, 0, BY2PG);
- } else {
- pg = newpage(clear, 0, 0);
- pg->va = VA(kmap(pg));
- }
- return pg;
-}
-
-/*
- * Put all bottom level page map pages on the process's free list and
- * call mapstack to set up the prototype page map. This
- * effectively forgets all of the process's mappings.
- *
- * Don't free the top level page. Just zero the used entries. This
- * avoids a 4k copy each flushmmu.
+ * Mark the mmu and tlb as inconsistent and call mapstack to fix it up.
*/
void
flushmmu(void)
{
int s;
- Proc *p;
- if(u == 0)
- return;
- p = u->p;
- p->newtlb = 1;
s = splhi();
- mapstack(p);
+ if(u){
+ u->p->newtlb = 1;
+ mapstack(u->p);
+ } else
+ putcr3(ktoppg.pa);
splx(s);
}
@@ 213,27 180,24 @@ flushmmu(void)
void
mapstack(Proc *p)
{
- Page *pg;
- ulong *top;
+ Page *pg, **l;
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.
+ * newtlb set means that they are inconsistent
+ * with the segment.c data structures.
*/
- 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;
- }
+ 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;
p->newtlb = 0;
}
@@ 282,7 246,6 @@ mmurelease(Proc *p)
/*
* Add an entry into the mmu.
*/
-#define FOURMEG (4*1024*1024)
void
putmmu(ulong va, ulong pa, Page *pg)
{
@@ 290,46 253,44 @@ putmmu(ulong va, ulong pa, Page *pg)
ulong *top;
ulong *pt;
Proc *p;
+ int s;
if(u==0)
panic("putmmu");
-
p = u->p;
- if(va >= USERADDR && va < USERADDR + FOURMEG)
- print("putmmu in USERADDR page table 0x%lux\n", va);
- if((va & 0xF0000000) == KZERO)
- print("putmmu in kernel page table 0x%lux\n", va);
-
/*
- * if no top level page, allocate one and copy the prototype
- * into it.
+ * create a top level page if we don't already have one.
+ * copy the kernel top level page into it for kernel mappings.
*/
if(p->mmutop == 0){
- /*
- * N.B. The assignment to pg is neccessary.
- * We can't assign to p->mmutop until after
- * copying ktoppg into the new page since we might
- * get scheded in this code and p->mmutop will be
- * pointing to a bad map.
- */
- pg = mmugetpage(0);
+ pg = newpage(0, 0, 0);
+ pg->va = VA(kmap(pg));
memmove((void*)pg->va, (void*)ktoppg.va, BY2PG);
p->mmutop = pg;
}
top = (ulong*)p->mmutop->va;
+ topoff = TOPOFF(va);
/*
- * if bottom level page table missing, allocate one and point
- * the top level page at it.
+ * if bottom level page table missing, allocate one
+ * and point the top level page at it.
*/
- topoff = TOPOFF(va);
- if(top[topoff] == 0){
- pg = mmugetpage(1);
+ s = splhi();
+ if(PPN(top[topoff]) == 0){
+ if(p->mmufree == 0){
+ spllo();
+ pg = newpage(1, 0, 0);
+ pg->va = VA(kmap(pg));
+ splhi();
+ } else {
+ pg = p->mmufree;
+ p->mmufree = pg->next;
+ memset((void*)pg->va, 0, BY2PG);
+ }
top[topoff] = PPN(pg->pa) | PTEVALID | PTEUSER | PTEWRITE;
pg->next = p->mmuused;
p->mmuused = pg;
- pg->daddr = topoff;
}
/*
@@ 340,6 301,7 @@ putmmu(ulong va, ulong pa, Page *pg)
/* flush cached mmu entries */
putcr3(p->mmutop->pa);
+ splx(s);
}
void
M pc/trap.c => pc/trap.c +22 -0
@@ 274,6 274,25 @@ dumpregs(Ureg *ur)
void
dumpstack(void)
{
+ ulong l, v, i;
+ extern ulong etext;
+
+ if(u == 0)
+ return;
+
+ i = 0;
+ for(l=(ulong)&l; l<USERADDR+BY2PG; l+=4){
+ v = *(ulong*)l;
+ if(KTZERO < v && v < (ulong)&etext){
+ print("%lux ", v);
+ i++;
+ }
+ if(i == 4){
+ i = 0;
+ print("\n");
+ }
+ }
+
}
long
@@ 334,8 353,10 @@ 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);
@@ 361,6 382,7 @@ syscall(Ureg *ur)
splhi(); /* avoid interrupts during the iret */
if(u->scallnr!=RFORK && (u->p->procctl || u->nnote))
notify(ur);
+
return ret;
}
M port/swap.c => port/swap.c +5 -1
@@ 21,7 21,7 @@ enum
Image swapimage;
static int swopen;
Page *iolist[Maxpages];
-int ioptr;
+int ioptr, npage;
void
swapinit(void)
@@ 101,6 101,7 @@ loop:
sleep(&swapalloc.r, needpages, 0);
u->p->psstate = "Pageout";
+ npage = 0;
for(;;) {
p++;
if(p >= ep)
@@ 141,6 142,8 @@ loop:
wakeup(&palloc.r);
}
}
+ if(npage == 0)
+ print("swap: pass took no pages\n");
goto loop;
}
@@ 269,6 272,7 @@ pagepte(int type, Page **pg)
/* Add me to IO transaction list */
iolist[ioptr++] = outp;
}
+ npage++;
}
void
M ss/dat.h => ss/dat.h +1 -0
@@ 58,6 58,7 @@ struct FPsave
ulong a; /* address */
ulong i; /* instruction */
}q[NFPQ];
+ long fppc; /* for recursive traps only */
};
struct Conf
M ss/fns.h => ss/fns.h +1 -1
@@ 63,7 63,7 @@ void putwD(ulong, ulong);
void putwE16(ulong, ulong);
void putwE(ulong, ulong);
void systemreset(void);
-void restfpregs(FPsave*);
+void restfpregs(FPsave*, ulong);
void screeninit(void);
void screenputc(int);
void screenputs(char*, int);
M ss/fptrap.c => ss/fptrap.c +8 -2
@@ 20,7 20,11 @@ fptrap(void)
n = getfpq(&u->fpsave.q[0].a);
if(n > NFPQ)
panic("FPQ %d\n", n);
- again:
+ /*
+ * If faulted during restart, recover PC for debugging
+ */
+ if(u->fpsave.fppc)
+ u->fpsave.q[0].a = u->fpsave.fppc;
fsr = getfsr();
savefpregs(&u->fpsave);
u->fpsave.fsr = fsr;
@@ 33,7 37,7 @@ fptrap(void)
if(ret){
enabfp(); /* savefpregs disables it */
clearftt(fsr & ~0x1F); /* clear ftt and cexc */
- restfpregs(&u->fpsave);
+ restfpregs(&u->fpsave, fsr);
enabfp(); /* restfpregs disables it */
fixq(&u->fpsave, n);
}
@@ 202,7 206,9 @@ fixq(FPsave *f, int n)
* the trap by examining the non-zero members of the FPQ.
* Tough.
*/
+ f->fppc = f->q[0].a;
(*(void(*)(void))ip)();
+ f->fppc = 0;
if(!fpquiet())
break;
}
M ss/l.s => ss/l.s +1 -1
@@ 564,7 564,7 @@ TEXT restfpregs(SB), $0
MOVW R8, PSR
NOOP /* wait for PSR to quiesce */
- MOVW 0(R7), FSR
+ MOVW fsr+4(FP), FSR
ADD $4, R7
MOVD (0*4)(R7), F0
M ss/trap.c => ss/trap.c +7 -10
@@ 166,9 166,9 @@ trap(Ureg *ur)
case 4: /* floating point disabled */
if(u && u->p){
if(u->p->fpstate == FPinit)
- restfpregs(initfpp);
+ restfpregs(initfpp, initfpp->fsr);
else if(u->p->fpstate == FPinactive)
- restfpregs(&u->fpsave);
+ restfpregs(&u->fpsave, u->fpsave.fsr);
else
break;
u->p->fpstate = FPactive;
@@ 205,7 205,7 @@ trap(Ureg *ur)
if(user){
notify(ur);
if(u->p->fpstate == FPinactive) {
- restfpregs(&u->fpsave);
+ restfpregs(&u->fpsave, u->fpsave.fsr);
u->p->fpstate = FPactive;
ur->psr |= PSREF;
}
@@ 525,20 525,14 @@ syscall(Ureg *aur)
if(conf.ss2)
putw2(CACHETAGS+((TRAPS+16*128)&(VACSIZE-1)), 0);
- /*
- * since the system call interface does not
- * guarantee anything about registers,
- */
if(u->p->fpstate == FPactive) {
fpquiet();
u->p->fpstate = FPinit;
+ u->fpsave.fsr = getfsr();
ur->psr &= ~PSREF;
}
spllo();
- if(u->p->procctl)
- procctl(u->p);
-
u->scallnr = ur->r7;
sp = ur->usp;
@@ 570,6 564,9 @@ syscall(Ureg *aur)
ur->pc += 4;
ur->npc = ur->pc+4;
u->nerrlab = 0;
+ if(u->p->procctl)
+ procctl(u->p);
+
u->p->insyscall = 0;
u->p->psstate = 0;
if(u->scallnr == NOTED) /* ugly hack */