~kris/9p

9hist

53e22ebac2a4352c4f4463df1c020eedbfd18e00 — David du Colombier 36 years ago 0345182
Plan 9 from Bell Labs 1990-06-03
11 files changed, 225 insertions(+), 66 deletions(-)

M gnot/chan.c
M gnot/dat.h
M gnot/devproc.c
M gnot/fault.c
M gnot/fns.h
M gnot/main.c
M gnot/mmu.c
M gnot/page.c
M gnot/proc.c
M gnot/sysproc.c
M port/chan.c
M gnot/chan.c => gnot/chan.c +4 -6
@@ 134,7 134,7 @@ mountsplit(Mount *omnt)
	nmnt->mountid = omnt->mountid;
	nmnt->next = omnt->next;
	if(nmnt->next)
		incref(nmnt);
		incref(nmnt->next);
	nmnt->c = omnt->c;
	incref(nmnt->c);
	omnt->ref--;


@@ 207,14 207,12 @@ mount(Chan *new, Chan *old, int flag)
		/* fall through */

	case MREPL:
		omnt = mt->mnt;
		if(omnt)
			incref(omnt);
		mnt->next = omnt;
		mnt->next = mt->mnt;
		mt->mnt = mnt;
		mnt->term = 1;
		if((flag&MORDER) == MBEFORE)
			mnt->term = 0;
		else
			mnt->term = 1;
		break;

	/*

M gnot/dat.h => gnot/dat.h +13 -1
@@ 12,6 12,7 @@ typedef struct Envval	Envval;
typedef struct Error	Error;
typedef struct FFrame	FFrame;
typedef struct FPsave	FPsave;
typedef struct KMap	KMap;
typedef struct Label	Label;
typedef struct List	List;
typedef struct Lock	Lock;


@@ 112,6 113,10 @@ struct Conf
	int	nmach;		/* processors */
	int	nproc;		/* processes */
	int	npgrp;		/* process groups */
	ulong	npage0;		/* total physical pages of memory, bank 0 */
	ulong	npage1;		/* total physical pages of memory, bank 1 */
	ulong	base0;		/* base of bank 0 */
	ulong	base1;		/* base of bank 1 */
	ulong	npage;		/* total physical pages of memory */
	ulong	norig;		/* origins */
	ulong	npte;		/* contiguous page table entries */


@@ 176,6 181,13 @@ struct Envp
	int	chref;			/* # chans from pgrp pointing here */
};

struct KMap
{
	KMap	*next;
	ulong	pa;
	ulong	va;
};

struct Mach
{
	int	machno;			/* physical id of processor */


@@ 298,7 310,7 @@ struct Proc
	Proc	*sib;			/* non-ascendant relatives (circular list) */
	int	nchild;
	QLock	wait;			/* exiting children to be waited for */
	Waitmsg	*waitmsg;
	ulong	waitmsg;
	Proc	*child;
	Proc	*parent;
	Pgrp	*pgrp;

M gnot/devproc.c => gnot/devproc.c +19 -7
@@ 201,6 201,7 @@ procread(Chan *c, void *va, long n)
	Seg *s;
	Orig *o;
	Page *pg;
	KMap *k;
	PTE *pte, *opte;
	int i;
	long l;


@@ 253,8 254,10 @@ procread(Chan *c, void *va, long n)
				pprint("nonresident page addr %lux (complain to rob)\n", c->offset);
				memset(a, 0, n);
			}else{
				b = (char*)(pg->pa|KZERO);
				k = kmap(pg);
				b = (char*)k->va;
				memcpy(a, b+(c->offset&(BY2PG-1)), n);
				kunmap(k);
			}
			return n;
		}


@@ 266,15 269,17 @@ procread(Chan *c, void *va, long n)
			pg = p->upage;
			if(pg==0 || (p->pid&PIDMASK)!=PID(c->qid))
				error(0, Eprocdied);
			b = (char*)(pg->pa|KZERO);
			k = kmap(pg);
			b = (char*)k->va;
			memcpy(a, b+(c->offset-USERADDR), n);
			kunmap(k);
			return n;
		}

		/* kernel memory.  BUG: shouldn't be so easygoing. BUG: mem mapping? */
		if(c->offset>=KZERO && c->offset<KZERO+conf.npage*BY2PG){
			if(c->offset+n > KZERO+conf.npage*BY2PG)
				n = KZERO+conf.npage*BY2PG - c->offset;
		if(c->offset>=KZERO && c->offset<KZERO+conf.npage0*BY2PG){
			if(c->offset+n > KZERO+conf.npage0*BY2PG)
				n = KZERO+conf.npage0*BY2PG - c->offset;
			memcpy(a, (char*)c->offset, n);
			return n;
		}


@@ 289,8 294,10 @@ procread(Chan *c, void *va, long n)
		}
		if((p->pid&PIDMASK) != PID(c->qid))
			error(0, Eprocdied);
		up = (User*)(p->upage->pa|KZERO);
		k = kmap(p->upage);
		up = (User*)k->va;
		if(up->p != p){
			kunmap(k);
			pprint("note read u/p mismatch");
			error(0, Egreg);
		}


@@ 304,6 311,7 @@ procread(Chan *c, void *va, long n)
			memcpy(&up->note[0], &up->note[1], up->nnote*sizeof(Note));
			n = ERRLEN;
		}
		kunmap(k);
		unlock(&p->debug);
		return n;



@@ 340,6 348,7 @@ procwrite(Chan *c, void *va, long n)
{
	Proc *p;
	User *up;
	KMap *k;
	char buf[ERRLEN];

	if(c->qid & CHDIR)


@@ 362,11 371,14 @@ procwrite(Chan *c, void *va, long n)
			error(0, Ebadctl);
		break;
	case Qnote:
		up = (User*)(p->upage->pa|KZERO);
		k = kmap(p->upage);
		up = (User*)k->va;
		if(up->p != p){
			kunmap(k);
			pprint("note write u/p mismatch");
			error(0, Egreg);
		}
		kunmap(k);
		if(n >= ERRLEN-1)
			error(0, Etoobig);
		if(n>=4 && strncmp(va, "sys:", 4)==0)

M gnot/fault.c => gnot/fault.c +15 -5
@@ 51,11 51,14 @@ fault(Ureg *ur, FFrame *f)
	Orig *o;
	char *l;
	Page *pg;
	KMap *k, *k1;
	int zeroed = 0, head = 1;
	int i, user, read, insyscall;

	if(u == 0)
		panic("fault");
	if(u == 0){
		dumpregs(ur);
		panic("fault u==0 pc=%lux", ur->pc);
	}
	insyscall = u->p->insyscall;
	u->p->insyscall = 1;
	if(f->ssw & DF)


@@ 149,24 152,27 @@ fault(Ureg *ur, FFrame *f)
			if(n > BY2PG)
				n = BY2PG;
			pg = newpage(1, o, addr);
			k = kmap(pg);
			qlock(o->chan);
			if(waserror()){
				print("demand load i/o error %d\n", u->error.code);
				kunmap(k);
				qunlock(o->chan);
				pg->o = 0;
				pg->ref--;
				goto cant;
			}
			o->chan->offset = (addr-o->va) + o->minca;
			l = (char*)(pg->pa|KZERO);
			l = (char*)k->va;
			if((*devtab[o->chan->type].read)(o->chan, l, n) != n)
				error(0, Eioload);
			qunlock(o->chan);
			poperror();
			/* BUG: if was first page of bss, move to data */
			if(n<BY2PG)
				memset(l+n, 0, BY2PG-n);
			lock(o);
			kunmap(k);
			poperror();
			opte = &o->pte[(addr-s->minva)>>PGSHIFT];	/* could move */
			pte = opte;
			if(pte->page == 0){


@@ 231,7 237,11 @@ fault(Ureg *ur, FFrame *f)
			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*)k->va, (void*)k1->va, BY2PG);
			kunmap(k);
			kunmap(k1);
			if(pg->ref <= 1)
				panic("pg->ref <= 1");
			pg->ref--;

M gnot/fns.h => gnot/fns.h +3 -0
@@ 63,8 63,11 @@ void	isdir(Chan*);
void	kbdchar(int);
void	kbdrepeat(int);
void	kbdclock(void);
void	kmapinit(void);
KMap	*kmap(Page*);
void	kproc(char*, void(*)(void*), void*);
void	kproftimer(ulong);
void	kunmap(KMap*);
void	lock(Lock*);
void	lockinit(void);
Orig	*lookorig(ulong, ulong, int, Chan*);

M gnot/main.c => gnot/main.c +61 -19
@@ 17,6 17,7 @@ typedef struct Boot{
#define BOOT ((Boot*)0)

char protouser[NAMELEN];
int bank[2];

void unloadboot(void);



@@ 27,7 28,9 @@ main(void)
	machinit();
	mmuinit();
	confinit();
	kmapinit();
	printinit();
	print("bank 0: %dM  bank 1: %dM\n", bank[0], bank[1]);
	flushmmu();
	procinit0();
	pgrpinit();


@@ 36,6 39,7 @@ main(void)
	chandevreset();
	streaminit();
	pageinit();
	kmapinit();
	userinit();
	schedinit();
}


@@ 102,6 106,7 @@ userinit(void)
	Proc *p;
	Seg *s;
	User *up;
	KMap *k;

	p = newproc();
	p->pgrp = newpgrp();


@@ 121,8 126,10 @@ userinit(void)
	/*
	 * User
	 */
	up = (User*)(p->upage->pa|KZERO);
	k = kmap(p->upage);
	up = (User*)k->va;
	up->p = p;
	kunmap(k);

	/*
	 * User Stack


@@ 140,7 147,9 @@ userinit(void)
	s->proc = p;
	s->o = neworig(UTZERO, 1, 0, 0);
	s->o->pte[0].page = newpage(0, 0, UTZERO);
	memcpy((ulong*)(s->o->pte[0].page->pa|KZERO), initcode, sizeof initcode);
	k = kmap(s->o->pte[0].page);
	memcpy((ulong*)k->va, initcode, sizeof initcode);
	kunmap(k);
	s->minva = UTZERO;
	s->maxva = UTZERO+BY2PG;



@@ 225,34 234,67 @@ delete(List **head, List *where, List *old)
	where->next = old->next;
}

banksize(int base)
{
	ulong va;

	if(&end > (int *)((KZERO|1024L*1024L)-BY2PG))
		return 0;
	va = UZERO;	/* user page 1 is free to play with */
	putmmu(va, PTEVALID|(base+0)*1024L*1024L/BY2PG);
	*(ulong*)va=0;	/* 0 at 0M */
	putmmu(va, PTEVALID|(base+1)*1024L*1024L/BY2PG);
	*(ulong*)va=1;	/* 1 at 1M */
	putmmu(va, PTEVALID|(base+4)*1024L*1024L/BY2PG);
	*(ulong*)va=4;	/* 4 at 4M */
	putmmu(va, PTEVALID|(base+0)*1024L*1024L/BY2PG);
	if(*(ulong*)va==0)
		return 16;
	putmmu(va, PTEVALID|(base+1)*1024L*1024L/BY2PG);
	if(*(ulong*)va==1)
		return 4;
	putmmu(va, PTEVALID|(base+4)*1024L*1024L/BY2PG);
	if(*(ulong*)va==2)
		return 1;
	return 0;
}

Conf	conf;

void
confinit(void)
{
	int mul;
	conf.nmach = 1;
	if(conf.nmach > MAXMACH)
		panic("confinit");
	conf.nproc = 32;
	conf.npgrp = 15;
	conf.npage = (4*1024*1024-256*1024)/BY2PG;
	conf.npte = 500;
	conf.nmod = 200;
	bank[0] = banksize(0);
	bank[1] = banksize(16);
	conf.npage0 = (bank[0]*1024*1024)/BY2PG;
	conf.base0 = 0;
	conf.npage1 = (bank[1]*1024*1024)/BY2PG;
	conf.base1 = 16*1024*1024;
	conf.npage = conf.npage0+conf.npage1;
	mul = 1 + (conf.npage0>0);
	conf.nproc = 32*mul;
	conf.npgrp = 15*mul;
	conf.npte = 700*mul;
	conf.nmod = 400*mul;
	conf.nalarm = 1000;
	conf.norig = 100;
	conf.nchan = 200;
	conf.nenv = 100;
	conf.nenvchar = 8000;
	conf.npgenv = 200;
	conf.nmtab = 50;
	conf.nmount = 100;
	conf.nmntdev = 20;
	conf.norig = 150*mul;
	conf.nchan = 150*mul;
	conf.nenv = 100*mul;
	conf.nenvchar = 8000*mul;
	conf.npgenv = 200*mul;
	conf.nmtab = 50*mul;
	conf.nmount = 100*mul;
	conf.nmntdev = 10*mul;
	conf.nmntbuf = 2*conf.nmntdev;
	conf.nmnthdr = 2*conf.nmntdev;
	conf.nstream = 64;
	conf.nstream = 64*mul;
	conf.nqueue = 5 * conf.nstream;
	conf.nblock = 12 * conf.nstream;
	conf.nsrv = 32;
	conf.nbitmap = 100;
	conf.nbitbyte = 400*1024;
	conf.nsrv = 32*mul;
	conf.nbitmap = 100*mul;
	conf.nbitbyte = 300*1024*mul;
}

M gnot/mmu.c => gnot/mmu.c +58 -0
@@ 4,6 4,14 @@
#include	"dat.h"
#include	"fns.h"

struct
{
	Lock;
	int	init;
	KMap	*free;
	KMap	arena[4*1024*1024/BY2PG];	/* kernel mmu maps up to 4MB */
}kmapalloc;

/*
 * Called splhi, not in Running state
 */


@@ 46,3 54,53 @@ flushmmu(void)
	*PARAM &= ~TLBFLUSH_;
	*PARAM |= TLBFLUSH_;
}

void
kmapinit(void)
{
	KMap *k;
	int i, e;

	if(kmapalloc.init == 0){
		k = &kmapalloc.arena[0];
		k->va = KZERO|(3*1024*1024);
		k->next = 0;
		kmapalloc.free = k;
		kmapalloc.init = 1;
		return;
	}
	e = (4*1024*1024 - 256*1024)/BY2PG;	/* screen lives at top 256K */
	i = (((ulong)ialloc(0, 0))&~KZERO)/BY2PG;
	kmapalloc.free = 0;
	for(k=&kmapalloc.arena[i]; i<e; i++,k++){
		k->va = i*BY2PG|KZERO;
		kunmap(k);
	}
}

KMap*
kmap(Page *pg)
{
	KMap *k;

	lock(&kmapalloc);
	k = kmapalloc.free;
	if(k == 0)
		panic("kmap");
	kmapalloc.free = k->next;
	unlock(&kmapalloc);
	k->pa = pg->pa;
	putkmmu(k->va, PPN(k->pa) | PTEVALID | PTEKERNEL);
	return k;
}

void
kunmap(KMap *k)
{
	k->pa = 0;
	lock(&kmapalloc);
	k->next = kmapalloc.free;
	kmapalloc.free = k;
	putkmmu(k->va, INVALIDPTE);
	unlock(&kmapalloc);
}

M gnot/page.c => gnot/page.c +15 -6
@@ 10,7 10,7 @@ struct
	Lock;
	ulong	addr;
	int	active;
	Page	*page;		/* base of Page structures, indexed by phys addr */
	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 */


@@ 54,10 54,12 @@ ialloc(ulong n, int align)
{
	ulong p;

	if(palloc.active)
		print("ialloc bad\n");
	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);


@@ 150,7 152,10 @@ pageinit(void)
	for(p=palloc.head; p<=palloc.tail; p++,ppn++){
		p->next = p+1;
		p->prev = p-1;
		p->pa = ppn<<PGSHIFT;
		if(ppn < conf.npage0)
			p->pa = conf.base0+(ppn<<PGSHIFT);
		else
			p->pa = conf.base1+((ppn-conf.npage0)<<PGSHIFT);
	}
	palloc.head->prev = 0;
	palloc.tail->next = 0;


@@ 161,6 166,7 @@ newpage(int noclear, Orig *o, ulong va)
{
	Page *p;
	Orig *o1;
	KMap *k;

	if(palloc.active == 0)
		print("newpage inactive\n");


@@ 205,8 211,11 @@ loop:
	p->ref = 1;
	usepage(p, 0);
	unlock(&palloc);
	if(!noclear)
		memset((void*)(p->pa|KZERO), 0, BY2PG);
	if(!noclear){
		k = kmap(p);
		memset((void*)k->va, 0, BY2PG);
		kunmap(k);
	}
	p->o = o;
	p->va = va;


M gnot/proc.c => gnot/proc.c +21 -10
@@ 303,18 303,23 @@ int
postnote(Proc *p, int dolock, char *n, int flag)
{
	User *up;
	KMap *k;
	int s;
	Rendez *r;

	if(dolock)
		lock(&p->debug);
	up = (User*)(p->upage->pa|KZERO);
	k = kmap(p->upage);
	up = (User*)k->va;
	if(flag!=NUser && (up->notify==0 || up->notified))
		up->nnote = 0;	/* force user's hand */
	else if(up->nnote == NNOTE-1)
	else if(up->nnote == NNOTE-1){
		kunmap(k);
		return 0;
	}
	strcpy(up->note[up->nnote].msg, n);
	up->note[up->nnote++].flag = flag;
	kunmap(k);
	if(dolock)
		unlock(&p->debug);
	if(r = p->r){	/* assign = */


@@ 398,7 403,7 @@ pexit(char *s, int freemem)
		/*
		 * Pass info through back door, to avoid huge Proc's
		 */
		p->waitmsg = (Waitmsg*)(c->upage->pa|(((ulong)&w)&(BY2PG-1))|KZERO);
		p->waitmsg = (((ulong)&w)&(BY2PG-1));
		c->state = Exiting;
		if(p->state == Inwait)
			ready(p);


@@ 499,6 504,7 @@ ulong
pwait(Waitmsg *w)
{
	Proc *c, *p;
	KMap *k;
	ulong cpid;

	p = u->p;


@@ 521,9 527,11 @@ again:
		goto again;
	}
	p->child = 0;
	k = kmap(c->upage);
	if(w)
		*w = *p->waitmsg;
	cpid = p->waitmsg->pid;
		*w = *(Waitmsg*)(p->waitmsg|k->va);
	cpid = ((Waitmsg*)(p->waitmsg|k->va))->pid;
	kunmap(k);
	p->time[TCUser] += c->time[TUser] + c->time[TCUser];
	p->time[TCSys] += c->time[TSys] + c->time[TCSys];
	p->time[TCReal] += c->time[TReal];


@@ 564,23 572,25 @@ kproc(char *name, void (*func)(void *), void *arg)
	ulong upa;
	int lastvar;	/* used to compute stack address */
	User *up;
	KMap *k;

	/*
	 * Kernel stack
	 */
	p = newproc();
	p->upage = newpage(1, 0, USERADDR|(p->pid&0xFFFF));
	upa = p->upage->pa|KZERO;
	up = (User *)upa;
	k = kmap(p->upage);
	upa = k->va;
	up = (User*)upa;
	up->p = p;

	/*
	 * Save time: only copy u-> data and useful stack
	 */
	memcpy((void*)upa, u, sizeof(User));
	memcpy(up, u, sizeof(User));
	n = USERADDR+BY2PG - (ulong)&lastvar;
	n = (n+32) & ~(BY2WD-1);	/* be safe & word align */
	memcpy((void*)(upa+BY2PG-n), (void*)((u->p->upage->pa|KZERO)+BY2PG-n), n);
	((User *)upa)->p = p;
	memcpy((void*)(upa+BY2PG-n), (void*)(USERADDR+BY2PG-n), n);

	/*
	 * Refs


@@ 589,6 599,7 @@ kproc(char *name, void (*func)(void *), void *arg)
	for(n=0; n<=up->maxfd; n++)
		up->fd[n] = 0;
	up->maxfd = 0;
	kunmap(k);

	/*
	 * Sched

M gnot/sysproc.c => gnot/sysproc.c +12 -6
@@ 26,6 26,7 @@ sysfork(ulong *arg)
	ulong usp, upa, pid;
	Chan *c;
	Orig *o;
	KMap *k;
	int n, on, i;
	int lastvar;	/* used to compute stack address */



@@ 34,15 35,18 @@ sysfork(ulong *arg)
	 */
	p = newproc();
	p->upage = newpage(1, 0, USERADDR|(p->pid&0xFFFF));
	upa = p->upage->pa|KZERO;
	k = kmap(p->upage);
	upa = k->va;

	/*
	 * Save time: only copy u-> data and useful stack
	 */
	memcpy((void*)upa, u, sizeof(User));
	n = USERADDR+BY2PG - (ulong)&lastvar;
	n = (n+32) & ~(BY2WD-1);	/* be safe & word align */
	memcpy((void*)(upa+BY2PG-n), (void*)((u->p->upage->pa|KZERO)+BY2PG-n), n);
	memcpy((void*)(upa+BY2PG-n), (void*)(USERADDR+BY2PG-n), n);
	((User *)upa)->p = p;
	kunmap(k);

	/*
	 * User stack


@@ 70,13 74,15 @@ sysfork(ulong *arg)
		op = u->p->seg[SSEG].o->pte[i+(on-n)].page;
		if(op){
			np = newpage(1, s->o, op->va);
			k = kmap(np);
			p->seg[SSEG].o->pte[i].page = np;
			if(i == 0){	/* only part of last stack page */
				memset((void*)(np->pa|KZERO), 0, usp);
				memcpy((void*)((np->pa+usp)|KZERO),
					(void*)((op->pa+usp)|KZERO), BY2PG-usp);
				memset((void*)k->va, 0, usp);
				memcpy((void*)(k->va+usp),
					(void*)(op->va+usp), BY2PG-usp);
			}else		/* all of higher pages */
				memcpy((void*)(np->pa|KZERO), (void*)(op->pa|KZERO), BY2PG);
				memcpy((void*)k->va, (void*)op->va, BY2PG);
			kunmap(k);
		}
	}
	unlock(s->o);

M port/chan.c => port/chan.c +4 -6
@@ 134,7 134,7 @@ mountsplit(Mount *omnt)
	nmnt->mountid = omnt->mountid;
	nmnt->next = omnt->next;
	if(nmnt->next)
		incref(nmnt);
		incref(nmnt->next);
	nmnt->c = omnt->c;
	incref(nmnt->c);
	omnt->ref--;


@@ 207,14 207,12 @@ mount(Chan *new, Chan *old, int flag)
		/* fall through */

	case MREPL:
		omnt = mt->mnt;
		if(omnt)
			incref(omnt);
		mnt->next = omnt;
		mnt->next = mt->mnt;
		mt->mnt = mnt;
		mnt->term = 1;
		if((flag&MORDER) == MBEFORE)
			mnt->term = 0;
		else
			mnt->term = 1;
		break;

	/*