~kris/9p

9hist

9d669d4b3256f89b71098bfc5ee2467f27af03dc — David du Colombier 25 years ago ad04103
Plan 9 from Bell Labs 2000-10-15
M bitsy/clock.c => bitsy/clock.c +27 -1
@@ 69,8 69,10 @@ fastticks(uvlong *hz)
}

static void
clockintr(Ureg*, void*)
clockintr(Ureg *ureg, void*)
{
	Clock0link *lp;

	/* reset previous interrupt */
	timerregs->ossr |= 1<<0;



@@ 78,6 80,30 @@ clockintr(Ureg*, void*)
	timerregs->osmr[0] = timerregs->oscr + ClockFreq/HZ;

	m->ticks++;

	if(m->proc)
		m->proc->pc = ureg->pc;

	accounttime();
	if(kproftimer != nil)
		kproftimer(ureg->pc);

	checkalarms();
	ilock(&clock0lock);
	for(lp = clock0link; lp; lp = lp->link)
		lp->clock();
	iunlock(&clock0lock);

	if(up == 0 || up->state != Running)
		return;

	if(anyready())
		sched();
	
	if((ureg->psr & PsrMask) == PsrMusr) {
		(*(ulong*)(USTKTOP-BY2WD)) += TK2MS(1);
		segclock(ureg->pc);
	}
}

void

M bitsy/dat.h => bitsy/dat.h +3 -2
@@ 16,7 16,7 @@ typedef struct Uart	Uart;
/*
 *  parameters for sysproc.c
 */
#define AOUT_MAGIC	(I_MAGIC)
#define AOUT_MAGIC	(E_MAGIC)

struct Lock
{


@@ 82,6 82,7 @@ struct PMMU
{
	Page	*l1page[Nmeg];	/* this's process' level 1 entries */
	ulong	l1table[Nmeg];	/* ... */
	Page	*mmufree;	/* free mmu pages */
};

/*


@@ 167,7 168,7 @@ struct
	int	ispanic;		/* shutdown in response to a panic */
}active;

#define	MACHP(n)	((Mach*)MACHADDR)
#define	MACHP(n)	((Mach *)(MACHADDR+(n)*BY2PG))

extern Mach	*m;
#define up	(((Mach*)MACHADDR)->externup)

A bitsy/devsac.c => bitsy/devsac.c +530 -0
@@ 0,0 1,530 @@
#include "u.h"
#include "../port/lib.h"
#include "mem.h"
#include "dat.h"
#include "fns.h"
#include "io.h"
#include "../port/error.h"

enum
{
	OPERM	= 0x3,		/* mask of all permission types in open mode */
	Nram	= 512,
	CacheSize = 20,
	OffsetSize = 4,		/* size in bytes of an offset */
};

typedef struct SacPath SacPath;
typedef struct Sac Sac;
typedef struct SacHeader SacHeader;
typedef struct SacDir SacDir;
typedef struct Cache Cache;

enum {
	Magic = 0x5acf5,
};

struct SacDir
{
	char	name[NAMELEN];
	char	uid[NAMELEN];
	char	gid[NAMELEN];
	uchar	qid[4];
	uchar	mode[4];
	uchar	atime[4];
	uchar	mtime[4];
	uchar	length[8];
	uchar	blocks[8];
};

struct SacHeader
{
	uchar	magic[4];
	uchar	length[8];
	uchar	blocksize[4];
	uchar	md5[16];
};


struct Sac
{
	SacDir;
	SacPath *path;
};

struct SacPath
{
	Ref;
	SacPath *up;
	long blocks;
	int entry;
	int nentry;
};

struct Cache
{
	long block;
	ulong age;
	uchar *data;
};

enum
{
	Pexec =		1,
	Pwrite = 	2,
	Pread = 	4,
	Pother = 	1,
	Pgroup = 	8,
	Powner =	64,
};

static char *sacfs = "fs.sac";
static uchar *data;
static int blocksize;
static Sac root;
static Cache cache[CacheSize];
static ulong cacheage;

static void	sacdir(Chan *, SacDir*, char*);
static ulong	getl(void *p);
static Sac	*saccpy(Sac *s);
static Sac *saclookup(Sac *s, char *name);
static int sacdirread(Chan *, char *p, long off, long cnt);
static void loadblock(void *buf, uchar *offset, int blocksize);
static void sacfree(Sac*);

static void
sacinit(void)
{
	SacHeader *hdr;
	uchar *p;
	char *s;
	int i;

print("sacinit\n");
	s = getconf("flash");
	if(s == nil) {
		print("devsac: no flash file system\n");
		return;
	}

	p = (uchar*)strtoul(s, 0, 0);
	if(p == 0) {
		print("devsac: bad address for flash file system\n");
		return;
	}
	data = tarlookup(p, sacfs, &i);
	if(data == 0) {
		print("devsac: could not find file: %s\n", sacfs);
		return;
	}
	hdr = (SacHeader*)data;
	if(getl(hdr->magic) != Magic) {
print("devsac: bad magic\n");
		return;
	}
	blocksize = getl(hdr->blocksize);
	root.SacDir = *(SacDir*)(data + sizeof(SacHeader));
	p = malloc(CacheSize*blocksize);
	if(p == nil)
		error("allocating cache");
	for(i=0; i<CacheSize; i++) {
		cache[i].data = p;
		p += blocksize;
	}
}

static Chan*
sacattach(char* spec)
{
	Chan *c;
	int dev;

	dev = atoi(spec);
	if(dev != 0)
		error("bad specification");

	// check if init found sac file system in memory
	if(blocksize == 0)
		error("devsac: bad magic");

	c = devattach('C', spec);
	c->qid = (Qid){getl(root.qid), 0};
	c->dev = dev;
	c->aux = saccpy(&root);
	return c;
}

static Chan*
sacclone(Chan *c, Chan *nc)
{
	nc = devclone(c, nc);
	nc->aux = saccpy(c->aux);
	return nc;
}

static int
sacwalk(Chan *c, char *name)
{
	Sac *sac;

//print("walk %s\n", name);

	isdir(c);
	if(name[0]=='.' && name[1]==0)
		return 1;
	if(name[0]=='.' && name[1]=='.' && name[2]==0)
		return 1;
	sac = c->aux;
	sac = saclookup(sac, name);
	if(sac == nil) {
		strncpy(up->error, Enonexist, NAMELEN);
		return 0;
	}
	c->aux = sac;
	c->qid = (Qid){getl(sac->qid), 0};
	return 1;
}

static Chan*
sacopen(Chan *c, int omode)
{
	ulong t, mode;
	Sac *sac;
	static int access[] = { 0400, 0200, 0600, 0100 };

	sac = c->aux;
	mode = getl(sac->mode);
	if(strcmp(up->user, sac->uid) == 0)
		mode = mode;
	else if(strcmp(up->user, sac->gid) == 0)
		mode = mode<<3;
	else
		mode = mode<<6;

	t = access[omode&3];
	if((t & mode) != t)
			error(Eperm);
	c->offset = 0;
	c->mode = openmode(omode);
	c->flag |= COPEN;
	return c;
}


static long
sacread(Chan *c, void *a, long n, vlong voff)
{
	Sac *sac;
	char *buf, *buf2;
	int nn, cnt, i, j;
	uchar *blocks;
	long length;
	long off = voff;

	buf = a;
	cnt = n;
	if(c->qid.path & CHDIR){
		cnt = (cnt/DIRLEN)*DIRLEN;
		if(off%DIRLEN)
			error("i/o error");
		return sacdirread(c, buf, off, cnt);
	}
	sac = c->aux;
	length = getl(sac->length);
	if(off >= length)
		return 0;
	if(cnt > length-off)
		cnt = length-off;
	if(cnt == 0)
		return 0;
	n = cnt;
	blocks = data + getl(sac->blocks);
	buf2 = malloc(blocksize);
	while(cnt > 0) {
		i = off/blocksize;
		nn = blocksize;
		if(nn > length-i*blocksize)
			nn = length-i*blocksize;
		loadblock(buf2, blocks+i*OffsetSize, nn);
		j = off-i*blocksize;
		nn -= j;
		if(nn > cnt)
			nn = cnt;
		memmove(buf, buf2+j, nn);
		cnt -= nn;
		off += nn;
		buf += nn;
	}
	free(buf2);
	return n;
}

static long
sacwrite(Chan *, void *, long, vlong)
{
	error(Eperm);
	return 0;
}

static void
sacclose(Chan* c)
{
	Sac *sac = c->aux;
	c->aux = nil;
	sacfree(sac);
}


static void
sacstat(Chan *c, char *db)
{
	sacdir(c, c->aux, db);
}

static Sac*
saccpy(Sac *s)
{
	Sac *ss;
	
	ss = malloc(sizeof(Sac));
	*ss = *s;
	if(ss->path)
		incref(ss->path);
	return ss;
}

static SacPath *
sacpathalloc(SacPath *p, long blocks, int entry, int nentry)
{
	SacPath *pp = malloc(sizeof(SacPath));
	pp->ref = 1;
	pp->blocks = blocks;
	pp->entry = entry;
	pp->nentry = nentry;
	pp->up = p;
	return pp;
}

static void
sacpathfree(SacPath *p)
{
	if(p == nil)
		return;
	if(decref(p) > 0)
		return;
	sacpathfree(p->up);
	free(p);
}


static void
sacfree(Sac *s)
{
	sacpathfree(s->path);
	free(s);
}

static void
sacdir(Chan *c, SacDir *s, char *buf)
{
	Dir dir;

	memmove(dir.name, s->name, NAMELEN);
	dir.qid = (Qid){getl(s->qid), 0};
	dir.mode = getl(s->mode);
	dir.length = getl(s->length);
	if(dir.mode &CHDIR)
		dir.length *= DIRLEN;
	memmove(dir.uid, s->uid, NAMELEN);
	memmove(dir.gid, s->gid, NAMELEN);
	dir.atime = getl(s->atime);
	dir.mtime = getl(s->mtime);
	dir.type = devtab[c->type]->dc;
	dir.dev = c->dev;
	convD2M(&dir, buf);
}

static void
loadblock(void *buf, uchar *offset, int blocksize)
{
	long block, n;
	ulong age;
	int i, j;

	block = getl(offset);
	if(block < 0) {
		block = -block;
		cacheage++;
		// age has wraped
		if(cacheage == 0) {
			for(i=0; i<CacheSize; i++)
				cache[i].age = 0;
		}
		j = 0;
		age = cache[0].age;
		for(i=0; i<CacheSize; i++) {
			if(cache[i].age < age) {
				age = cache[i].age;
				j = i;
			}
			if(cache[i].block != block)
				continue;
			memmove(buf, cache[i].data, blocksize);
			cache[i].age = cacheage;
			return;
		}

		n = getl(offset+OffsetSize);
		if(n < 0)
			n = -n;
		n -= block;
		if(unsac(buf, data+block, blocksize, n)<0)
			panic("unsac failed!");
		memmove(cache[j].data, buf, blocksize);
		cache[j].age = cacheage;
		cache[j].block = block;
	} else {
		memmove(buf, data+block, blocksize);
	}
}

static Sac*
sacparent(Sac *s)
{
	uchar *blocks;
	SacDir *buf;
	int per, i, n;
	SacPath *p;

	p = s->path;
	if(p == nil || p->up == nil) {
		sacpathfree(p);
		*s = root;
		return s;
	}
	p = p->up;

	blocks = data + p->blocks;
	per = blocksize/sizeof(SacDir);
	i = p->entry/per;
	n = per;
	if(n > p->nentry-i*per)
		n = p->nentry-i*per;
	buf = malloc(per*sizeof(SacDir));
	loadblock(buf, blocks + i*OffsetSize, n*sizeof(SacDir));
	s->SacDir = buf[p->entry-i*per];
	free(buf);
	incref(p);
	sacpathfree(s->path);
	s->path = p;
	return s;
}

static int
sacdirread(Chan *c, char *p, long off, long cnt)
{
	uchar *blocks;
	SacDir *buf;
	int iblock, per, i, j, n, ndir;
	Sac *s;

	s = c->aux;
	blocks = data + getl(s->blocks);
	per = blocksize/sizeof(SacDir);
	ndir = getl(s->length);
	off /= DIRLEN;
	cnt /= DIRLEN;
	if(off >= ndir)
		return 0;
	if(cnt > ndir-off)
		cnt = ndir-off;
	iblock = -1;
	buf = malloc(per*sizeof(SacDir));
	for(i=off; i<off+cnt; i++) {
		j = i/per;
		if(j != iblock) {
			n = per;
			if(n > ndir-j*per)
				n = ndir-j*per;
			loadblock(buf, blocks + j*OffsetSize, n*sizeof(SacDir));
			iblock = j;
		}
		j *= per;
		sacdir(c, buf+i-j, p);
		p += DIRLEN;
	}
	free(buf);
	return cnt*DIRLEN;
}

static Sac*
saclookup(Sac *s, char *name)
{
	int ndir;
	int i, j, k, n, per;
	uchar *blocks;
	SacDir *buf;
	int iblock;
	SacDir *sd;
	
	if(strcmp(name, "..") == 0)
		return sacparent(s);
	blocks = data + getl(s->blocks);
	per = blocksize/sizeof(SacDir);
	ndir = getl(s->length);
	buf = malloc(per*sizeof(SacDir));
	iblock = -1;

	// linear search
	for(i=0; i<ndir; i++) {
		j = i/per;
		if(j != iblock) {
			n = per;
			if(n > ndir-j*per)
				n = ndir-j*per;
			loadblock(buf, blocks + j*OffsetSize, n*sizeof(SacDir));
			iblock = j;
		}
		j *= per;
		sd = buf+i-j;
		k = strcmp(name, sd->name);
		if(k == 0) {
		s->path = sacpathalloc(s->path, getl(s->blocks), i, ndir);
			s->SacDir = *sd;
			free(buf);
			return s;
		}
	}
	free(buf);
	return 0;
}

static ulong
getl(void *p)
{
	uchar *a = p;

	return (a[0]<<24) | (a[1]<<16) | (a[2]<<8) | a[3];
}

Dev sacdevtab = {
	'C',
	"sac",

	devreset,
	sacinit,
	sacattach,
	sacclone,
	sacwalk,
	sacstat,
	sacopen,
	devcreate,
	sacclose,
	sacread,
	devbread,
	sacwrite,
	devbwrite,
	devremove,
	devwstat,
};

M bitsy/devuart.c => bitsy/devuart.c +195 -4
@@ 20,9 20,18 @@ static int uartndir;
 */
static char	Ekinuse[] = "device in use by kernel";

struct Uartalloc {
	Lock;
	Uart *elist;	/* list of enabled interfaces */
} uartalloc;

static void	uartdcdhup(Uart*, int);
static void	uartdcdts(Uart*, int);
static void	uartdsrhup(Uart*, int);
static void	uartenable(Uart*);
static void	uartdisable(Uart*);
static void	uartclock(void);
static void	uartflow(void*);

/*
 *  define a Uart


@@ 54,8 63,8 @@ uartsetup(PhysUart *phys, void *regs, ulong freq, char *name)
	(*p->phys->baud)(p, 115200);
	(*p->phys->enable)(p, 0);

	p->iq = qopen(4*1024, 0, p->phys->flow, p);
	p->oq = qopen(4*1024, 0, p->phys->kick, p);
	p->iq = qopen(4*1024, 0, uartflow, p);
	p->oq = qopen(4*1024, 0, uartkick, p);
	if(p->iq == nil || p->oq == nil)
		panic("uartsetup");



@@ 66,6 75,52 @@ uartsetup(PhysUart *phys, void *regs, ulong freq, char *name)
	return p;
}

/*
 *  enable/diable uart and add/remove to list of enabled uarts
 */
static void
uartenable(Uart *p)
{
	Uart **l;

	p->hup_dsr = p->hup_dcd = 0;
	p->dsr = p->dcd = 0;

	/* assume we can send */
	p->cts = 1;

	(*p->phys->enable)(p, 1);

	lock(&uartalloc);
	for(l = &uartalloc.elist; *l; l = &(*l)->elist){
		if(*l == p)
			break;
	}
	if(*l == 0){
		p->elist = uartalloc.elist;
		uartalloc.elist = p;
	}
	p->enabled = 1;
	unlock(&uartalloc);
}
static void
uartdisable(Uart *p)
{
	Uart **l;

	(*p->phys->disable)(p);

	lock(&uartalloc);
	for(l = &uartalloc.elist; *l; l = &(*l)->elist){
		if(*l == p){
			*l = p->elist;
			break;
		}
	}
	p->enabled = 0;
	unlock(&uartalloc);
}

static void
setlength(int i)
{


@@ 109,6 164,8 @@ uartreset(void)
		dp->perm = 0444;
		dp++;
	}

	addclock0link(uartclock);
}




@@ 147,7 204,7 @@ uartopen(Chan *c, int omode)
			error(Ekinuse);
		qlock(p);
		if(p->opens++ == 0){
			(*p->phys->enable)(p, 1);
			uartenable(p);
			qreopen(p->iq);
			qreopen(p->oq);
		}


@@ 175,7 232,7 @@ uartclose(Chan *c)
			error(Ekinuse);
		qlock(p);
		if(--(p->opens) == 0){
			(*p->phys->disable)(p);
			uartdisable(p);
			qclose(p->iq);
			qclose(p->oq);
			p->ip = p->istage;


@@ 400,6 457,23 @@ uartdcdts(Uart *p, int n)
}

/*
 *  restart input if it's off
 */
static void
uartflow(void *v)
{
	Uart *p;

	p = v;
	if(p->modem){
		(*p->phys->rts)(p, 1);
		ilock(&p->rlock);
		p->haveinput = 1;
		iunlock(&p->rlock);
	}
}

/*
 *  put some bytes into the local queue to avoid calling
 *  qconsume for every character
 */


@@ 415,3 489,120 @@ uartstageoutput(Uart *p)
	p->oe = p->ostage + n;
	return n;
}

/*
 *  restart output
 */
void
uartkick(void *v)
{
	Uart *p = v;

	ilock(&p->tlock);
	(*p->phys->kick)(p);
	iunlock(&p->tlock);
}

/*
 *  streceiveage a character at interrupt time
 */
void
uartrecv(Uart *p,  char ch)
{
	/* software flow control */
	if(p->xonoff){
		if(ch == CTLS){
			p->blocked = 1;
		}else if (ch == CTLQ){
			p->blocked = 0;
			p->ctsbackoff = 2; /* clock gets output going again */
		}
	}

	/* receive the character */
	if(p->putc)
		p->putc(p->iq, ch);
	else {
		ilock(&p->rlock);
		if(p->ip < p->ie)
			*p->ip++ = ch;
		p->haveinput = 1;
		iunlock(&p->rlock);
	}
}

/*
 *  we save up input characters till clock time to reduce
 *  per character interrupt overhead.
 *
 *  There's also a bit of code to get a stalled print going.
 *  It shouldn't happen, but it does.  Obviously I don't
 *  understand something.  Since it was there, I bundled a
 *  restart after flow control with it to give some hysteresis
 *  to the hardware flow control.  This makes compressing
 *  modems happier but will probably bother something else.
 *	 -- presotto
 */
static void
uartclock(void)
{
	int n;
	Uart *p;

	for(p = uartalloc.elist; p; p = p->elist){

		/* this amortizes cost of qproduce to many chars */
		if(p->haveinput){
			ilock(&p->rlock);
			if(p->haveinput){
				n = p->ip - p->istage;
				if(n > 0 && p->iq){
					if(n > Stagesize)
						panic("uartclock");
					if(qproduce(p->iq, p->istage, n) < 0)
						(*p->phys->rts)(p, 0);
					else
						p->ip = p->istage;
				}
				p->haveinput = 0;
			}
			iunlock(&p->rlock);
		}
		if(p->dohup){
			ilock(&p->rlock);
			if(p->dohup){
				qhangup(p->iq, 0);
				qhangup(p->oq, 0);
			}
			p->dohup = 0;
			iunlock(&p->rlock);
		}

		/* this adds hysteresis to hardware/software flow control */
		if(p->ctsbackoff){
			ilock(&p->tlock);
			if(p->ctsbackoff){
				if(--(p->ctsbackoff) == 0)
					(*p->phys->kick)(p);
			}
			iunlock(&p->tlock);
		}
	}
}

/*
 *  configure a uart port as a console or a mouse
 */
void
uartspecial(Uart *p, int baud, Queue **in, Queue **out, int (*putc)(Queue*, int))
{
	uartenable(p);
	if(baud)
		(*p->phys->baud)(p, baud);
	p->putc = putc;
	if(in)
		*in = p->iq;
	if(out)
		*out = p->oq;
	p->opens++;
}

M bitsy/fns.h => bitsy/fns.h +8 -6
@@ 1,15 1,13 @@
#include "../port/portfns.h"

void	cacheflush(void);
void	cacheflushaddr(ulong);
int	cistrcmp(char*, char*);
int	cistrncmp(char*, char*, int);
void	cleancache(void);
void	cleanaddr(ulong);
#define	clearmmucache()				/* x86 doesn't have one */
void	clockinit(void);
#define	coherence()
void	delay(int);
void	evenaddr(ulong);
void	flushcache(void);
void	flushmmu(void);
ulong	getfar(void);
ulong	getfsr(void);


@@ 28,6 26,7 @@ void	meminit(void);
void	mmuinit(void);
void	mmuenable(void);
void	mmudisable(void);
void	mmuinvalidate(void);
void	noted(Ureg*, ulong);
int	notify(Ureg*);
#define	procrestore(p)


@@ 40,16 39,19 @@ void	qpanic(char *, ...);
void	reset(void);
void	rs232power(int);
Uart*	uartsetup(PhysUart*, void*, ulong, char*);
void	sa1100_uartsetup(void);
void	uartspecial(Uart*, int, Queue**, Queue**, int (*)(Queue*, int));
void	sa1100_uartsetup(int);
void	screeninit(void);
int	screenprint(char*, ...);			/* debugging */
void	(*screenputs)(char*, int);
void	screenputs(char*, int);
void	setr13(int, ulong*);
void	touser(void*);
void	trapdump(char *tag);
void	trapinit(void);
int	tas(void*);
int	uartstageoutput(Uart*);
void	uartkick(void*);
void	uartrecv(Uart*, char);
void	vectors(void);
void	vtable(void);
void	wbflush(void);

M bitsy/io.h => bitsy/io.h +1 -2
@@ 98,8 98,7 @@ struct PhysUart
{
	void	(*enable)(Uart*, int);
	void	(*disable)(Uart*);
	void	(*kick)(void*);
	void	(*flow)(void*);
	void	(*kick)(Uart*);
	void	(*intr)(Ureg*, void*);
	void	(*dobreak)(Uart*, int);
	void	(*baud)(Uart*, int);

M bitsy/l.s => bitsy/l.s +8 -19
@@ 35,12 35,12 @@ _mainloop:
	BL	_div(SB)			/* hack to get _div etc loaded */

/* flush tlb's */
TEXT flushmmu(SB), $-4
TEXT mmuinvalidate(SB), $-4
	MCR	CpMMU, 0, R0, C(CpTLBFlush), C(0x7)
	RET

/* clean and flush i and d caches */
TEXT cleancache(SB), $-4
/* write back and invalidate i and d caches */
TEXT cacheflush(SB), $-4
	/* write back any dirty data */
	MOVW	$0xe0000000,R0
	ADD	$(8*1024),R0,R1


@@ 49,7 49,8 @@ _wbloop:
	CMP	R0,R1
	BNE	_wbloop
	
	/* flush cache contents */
	/* drain write buffer and flush i&d cache contents */
	MCR	CpMMU, 0, R0, C(CpCacheFlush), C(0xa), 4
	MCR	CpMMU, 0, R0, C(CpCacheFlush), C(0x7), 0

	/* drain prefetch */


@@ 60,22 61,10 @@ _wbloop:
	RET

/* clean a single virtual address */
TEXT cleanaddr(SB), $-4
TEXT cacheflushaddr(SB), $-4
	MCR	CpMMU, 0, R0, C(CpCacheFlush), C(0xa), 1
	RET

/* flush i and d caches */
TEXT flushcache(SB), $-4
	/* flush cache contents */
	MCR	CpMMU, 0, R0, C(CpCacheFlush), C(0x7), 0

	/* drain prefetch */
	MOVW	R0,R0						
	MOVW	R0,R0
	MOVW	R0,R0
	MOVW	R0,R0
	RET

/* drain write buffer */
TEXT wbflush(SB), $-4
	MCR	CpMMU, 0, R0, C(CpCacheFlush), C(0xa), 4


@@ 111,13 100,13 @@ TEXT putttb(SB), $-4
 */
TEXT mmuenable(SB), $-4
	MRC	CpMMU, 0, R0, C(CpControl), C(0x0)
	ORR	$(CpCmmuena), R0
	ORR	$(CpCmmuena|CpCwb|CpCdcache), R0
	MCR     CpMMU, 0, R0, C(CpControl), C(0x0)
	RET

TEXT mmudisable(SB), $-4
	MRC	CpMMU, 0, R0, C(CpControl), C(0x0)
	BIC	$(CpCmmuena|CpCvivec), R0
	BIC	$(CpCmmuena|CpCdcache|CpCwb|CpCvivec), R0
	MCR     CpMMU, 0, R0, C(CpControl), C(0x0)
	RET


M bitsy/main.c => bitsy/main.c +7 -10
@@ 18,7 18,7 @@ int  noprint;
void
main(void)
{
	cleancache();
	mmuinvalidate();

	/* zero out bss */
	memset(edata, 0, end-edata);


@@ 31,22 31,20 @@ main(void)
	rs232power(1);
	iprint("bitsy kernel\n");
	confinit();
	iprint("%d pages %lux(%lud) %lux(%lud)\n", conf.npage, conf.base0, conf.npage0, conf.base1, conf.npage1);
	xinit();
	mmuinit();
	sa1100_uartsetup();
	gpioinit();
	trapinit();
	printinit();
	sa1100_uartsetup(1);
	printinit();	/* from here on, print works, before this we need iprint */
	clockinit();
	procinit0();
	initseg();
	chandevreset();
noprint = 1;
	pageinit();
	swapinit();
	userinit();
iprint("schedinit(), death soon\n");
//iprint("schedinit(), death soon\n");
	schedinit();
}



@@ 62,6 60,7 @@ exit(int ispanic)
	delay(1000);

	iprint("it's a wonderful day to die\n");
	mmuinvalidate();
	mmudisable();
	f = nil;
	(*f)();


@@ 210,7 209,6 @@ userinit(void)
	strcpy(p->text, "*init*");
	strcpy(p->user, eve);


	/*
	 * Kernel Stack
	 */


@@ 239,9 237,7 @@ userinit(void)
	k = kmap(s->map[0]->pages[0]);
	memmove((ulong*)VA(k), initcode, sizeof initcode);
	kunmap(k);
	cleancache();
	wbflush();
iprint("userinit %lux[0x20] = %lux\n", VA(k), *((ulong*)(VA(k)+0x20)));
//iprint("userinit %lux[0x20] = %lux\n", VA(k), *((ulong*)(VA(k)+0x20)));

	ready(p);
}


@@ 361,6 357,7 @@ confinit(void)
		conf.upages = (conf.npage*40)/100;
	conf.ialloc = ((conf.npage-conf.upages)/2)*BY2PG;

	/* only one processor */
	conf.nmach = 1;

	/* set up other configuration parameters */

M bitsy/mmu.c => bitsy/mmu.c +64 -13
@@ 82,6 82,7 @@ mmuinit(void)
	/* map zeros area */
	for(o = 0; o < 128 * OneMeg; o += OneMeg)
		l1table[(NULLZERO+o)>>20] = L1Section | L1KernelRW | L1Domain0
			| L1Cached | L1Buffered
			| ((PHYSNULL0+o)&L1SectBaseMask);

	/* map flash */


@@ 113,9 114,9 @@ mmuinit(void)

	/* enable mmu */
	wbflush();
	flushcache();
	flushmmu();
	mmuinvalidate();
	mmuenable();
	cacheflush();
}

/*


@@ 224,7 225,7 @@ putmmu(ulong va, ulong pa, Page*)
	Page *p;
	ulong *t;

iprint("putmmu(0x%.8lux, 0x%.8lux)\n", va, pa);
//iprint("putmmu(0x%.8lux, 0x%.8lux)\n", va, pa);
	/* always point L1 entry to L2 page, can't hurt */
	p = up->l1page[va>>20];
	if(p == nil){


@@ 236,47 237,97 @@ iprint("putmmu(0x%.8lux, 0x%.8lux)\n", va, pa);
		memset((uchar*)(p->va), 0, BY2PG);
	}
	l1table[va>>20] = L1PageTable | L1Domain0 | (p->pa & L1PTBaseMask);
	cleanaddr((ulong)&l1table[va>>20]);
iprint("%lux[%lux] = %lux\n", l1table, va>>20, l1table[va>>20]);
	cacheflushaddr((ulong)&l1table[va>>20]);
//iprint("%lux[%lux] = %lux\n", l1table, va>>20, l1table[va>>20]);
	up->l1table[va>>20] = l1table[va>>20];
	t = (ulong*)p->va;

	/* set L2 entry */
	t[(va & (OneMeg-1))>>PGSHIFT] = mmubits[pa & (PTEKERNEL|PTEVALID|PTEUNCACHED|PTEWRITE)]
		| (pa & ~(PTEKERNEL|PTEVALID|PTEUNCACHED|PTEWRITE));
iprint("%lux[%lux] = %lux\n", (ulong)t, (va & (OneMeg-1))>>PGSHIFT, t[(va & (OneMeg-1))>>PGSHIFT]);
	cleanaddr((ulong)&t[(va & (OneMeg-1))>>PGSHIFT]);
//iprint("%lux[%lux] = %lux\n", (ulong)t, (va & (OneMeg-1))>>PGSHIFT, t[(va & (OneMeg-1))>>PGSHIFT]);
	cacheflushaddr((ulong)&t[(va & (OneMeg-1))>>PGSHIFT]);

	wbflush();
}

/*
 *  this is called with palloc locked so the pagechainhead is kosher
 *  free up all page tables for this proc
 */
void
mmurelease(Proc* p)
mmuptefree(Proc *p)
{
	Page *pg;
	int i;

	for(i = 0; i < nelem(p->l1page); i++){
	for(i = 0; i < Nmeg; i++){
		pg = p->l1page[i];
		if(pg == nil)
			continue;
		p->l1page[i] = nil;
		pg->next = p->mmufree;
		p->mmufree = pg;
	}
	memset(p->l1table, 0, sizeof(p->l1table));
}

/*
 *  this is called with palloc locked so the pagechainhead is kosher
 */
void
mmurelease(Proc* p)
{
	Page *pg, *next;

	/* write back dirty cache entries before changing map */
	cacheflush();

	mmuptefree(p);

	for(pg = p->mmufree; pg; pg = next){
		next = pg->next;
		if(--pg->ref)
			panic("mmurelease: pg->ref %d\n", pg->ref);
		pagechainhead(pg);
		p->l1page[i] = nil;
	}
	if(p->mmufree && palloc.r.p)
		wakeup(&palloc.r);
	p->mmufree = nil;

	memset(l1table, 0, sizeof(p->l1table));
}

void
mmuswitch(Proc* p)
{
iprint("switching to proc %d\n", p->pid);
	if(p->newtlb){
		mmuptefree(p);
		p->newtlb = 0;
	}

	/* write back dirty cache entries before changing map */
	cacheflush();

	/* move in new map */
	memmove(l1table, p->l1table, sizeof(p->l1table));
	cleanaddr((ulong)l1table);

	/* make sure map is in memory and drain write buffer */
	cacheflushaddr((ulong)l1table);
	wbflush();

	/* lose any possible stale tlb entries */
	mmuinvalidate();
}

void
flushmmu(void)
{
	int s;

	s = splhi();
	up->newtlb = 1;
	mmuswitch(up);
	splx(s);
}

void

M bitsy/screen.c => bitsy/screen.c +6 -0
@@ 42,3 42,9 @@ blankscreen(int blank)
{
	USED(blank);
}

void
screenputs(char *s, int n)
{
	USED(s, n);
}

M bitsy/trap.c => bitsy/trap.c +26 -23
@@ 131,14 131,15 @@ faultarm(Ureg *ureg, ulong va, int user, int read)

	insyscall = up->insyscall;
	up->insyscall = 1;
peekmmu(va);
//peekmmu(va);
	n = fault(va, read);
iprint("fault returns %d\n", n);
//iprint("fault returns %d\n", n);
	if(n < 0){
		if(!user){
			dumpregs(ureg);
			qpanic("fault: 0x%lux\n", va);
			panic("fault: 0x%lux\n", va);
		}
		dumpregs(ureg);
		sprint(buf, "sys: trap: fault %s va=0x%lux",
			read? "read" : "write", va);
		postnote(up, 1, buf, NDebug);


@@ 152,7 153,7 @@ iprint("fault returns %d\n", n);
void
trap(Ureg *ureg)
{
	int i;
	int i, found;
	Vctl *v;
	int user;
	ulong va;


@@ 171,18 172,18 @@ trap(Ureg *ureg)

	switch(ureg->type){
	default:
		qpanic("unknown trap");
		panic("unknown trap");
		break;
	case PsrMabt:	/* prefetch fault */
		iprint("prefetch abort at 0x%lux\n", ureg->pc);
//iprint("prefetch abort at 0x%lux\n", ureg->pc);
		faultarm(ureg, ureg->pc, user, 1);
		break;
	case PsrMabt+1:	/* data fault */
		va = getfar();
		iprint("data fault pc 0x%lux va 0x%lux fsr 0x%lux\n", ureg->pc, va, getfsr());
//iprint("data fault pc 0x%lux(0x%lux) va 0x%lux fsr 0x%lux\n", ureg->pc, *(ulong*)(ureg->pc), va, getfsr());
		switch(getfsr() & 0xf){
		case 0x0:
			qpanic("vector exception at %lux\n", ureg->pc);
			panic("vector exception at %lux\n", ureg->pc);
			break;
		case 0x1:
		case 0x3:


@@ 191,10 192,10 @@ trap(Ureg *ureg)
					ureg->pc, va);
				postnote(up, 1, buf, NDebug);
			} else
				qpanic("kernel alignment: pc 0x%lux va 0x%lux", ureg->pc, va);
				panic("kernel alignment: pc 0x%lux va 0x%lux", ureg->pc, va);
			break;
		case 0x2:
			qpanic("terminal exception at %lux\n", ureg->pc);
			panic("terminal exception at %lux\n", ureg->pc);
			break;
		case 0x4:
		case 0x6:


@@ 202,12 203,12 @@ trap(Ureg *ureg)
		case 0xa:
		case 0xc:
		case 0xe:
			qpanic("external abort at %lux\n", ureg->pc);
			panic("external abort at %lux\n", ureg->pc);
			break;
		case 0x5:
		case 0x7:
			/* translation fault, i.e., no pte entry */
			faultarm(ureg, va, user, 0);
			faultarm(ureg, va, user, 1);
			break;
		case 0x9:
		case 0xb:


@@ 216,24 217,30 @@ trap(Ureg *ureg)
				sprint(buf, "sys: access violation: pc 0x%lux va 0x%lux\n", ureg->pc, va);
				postnote(up, 1, buf, NDebug);
			} else
				qpanic("kernel access violation: pc 0x%lux va 0x%lux\n", ureg->pc, va);
				panic("kernel access violation: pc 0x%lux va 0x%lux\n", ureg->pc, va);
			break;
		case 0xd:
		case 0xf:
			/* permission error, copy on write or real permission error */
			faultarm(ureg, va, user, 1);
			faultarm(ureg, va, user, 0);
			break;
		}
		break;
	case PsrMund:	/* undefined instruction */
		qpanic("undefined instruction");
		panic("undefined instruction");
		break;
	case PsrMirq:	/* device interrupt */
		for(i = 0; i < 32; i++)
		for(i = 0; i < 32; i++){
			found = 0;
			if((1<<i) & intrregs->icip){
				for(v = vctl[i]; v != nil; v = v->next)
				for(v = vctl[i]; v != nil; v = v->next){
					found = 1;
					v->f(ureg, v->a);
				}
				if(!found)
					iprint("interrupt %d with no handler\n", i);
			}
		}
		break;
	}



@@ 258,10 265,8 @@ syscall(Ureg* ureg)
	long	ret;
	int	i, scallnr;

iprint("syscall in\n");
dumpregs(ureg);
	if((ureg->psr & PsrMask) != PsrMusr)
		qpanic("syscall: cs 0x%4.4uX\n", ureg->psr);
		panic("syscall: cs 0x%4.4uX\n", ureg->psr);

	m->syscall++;
	up->insyscall = 1;


@@ 289,9 294,7 @@ dumpregs(ureg);
		up->s = *((Sargs*)(sp+BY2WD));
		up->psstate = sysctab[scallnr];

iprint("before syscall\n");
		ret = systab[scallnr](up->s.args);
iprint("syscall retuns %d\n", ret);
		poperror();
	}
	if(up->nerrlab){


@@ 299,7 302,7 @@ iprint("syscall retuns %d\n", ret);
		for(i = 0; i < NERR; i++)
			print("sp=%lux pc=%lux\n",
				up->errlab[i].sp, up->errlab[i].pc);
		qpanic("error stack");
		panic("error stack");
	}

	up->insyscall = 0;