~kris/9p

9hist

790abd1bce4d3c0ae9a1da631e72d38b5ec37039 — David du Colombier 34 years ago f36a677
Plan 9 from Bell Labs 1992-08-04
10 files changed, 90 insertions(+), 96 deletions(-)

M pc/main.c
M pc/mem.h
M pc/mmu.c
M pc/trap.c
M port/swap.c
M ss/dat.h
M ss/fns.h
M ss/fptrap.c
M ss/l.s
M ss/trap.c
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 */