~kris/9p

9hist

be298dcb85dd8adf7687157ed8d2abba932d3040 — David du Colombier 34 years ago 27f2f4a
Plan 9 from Bell Labs 1991-11-13
M gnot/boot.h => gnot/boot.h +1 -1
@@ 4602,7 4602,7 @@ ulong bootcode[]={
	0x02f6b6673,
	0x00063616e,
	0x027742066,
	0x0696e6520,
	0x0696e6420,
	0x02f6b6673,
	0x00a002573,
	0x066730063,

M gnot/clock.c => gnot/clock.c +4 -1
@@ 22,7 22,7 @@ void
clock(Ureg *ur)
{
	Proc *p;
	int user;
	int user, nrun = 0;

	user = (ur->sr&SUPER) == 0;
	if(user)


@@ 32,10 32,13 @@ clock(Ureg *ur)
	m->ticks++;
	p = m->proc;
	if(p){
		nrun = 1;
		p->pc = ur->pc;
		if (p->state==Running)
			p->time[p->insyscall]++;
	}
	nrun = (nrdy+nrun)*1000;
	MACHP(0)->load = (MACHP(0)->load*19+nrun)/20;
	checkalarms();
	kbdclock();
	mouseclock();

M gnot/main.c => gnot/main.c +2 -0
@@ 37,6 37,8 @@ main(void)
	u = 0;
	unloadboot();
	machinit();
	active.exiting = 0;
	active.machs = 1;
	mmuinit();
	confinit();
	kmapinit();

M gnot/trap.c => gnot/trap.c +8 -4
@@ 68,14 68,18 @@ char *trapname[]={
};

char*
excname(unsigned vo)
excname(unsigned vo, ulong pc)
{
	static char buf[32];	/* BUG: not reentrant! */

	vo &= 0x0FFF;
	vo >>= 2;
	if(vo < sizeof trapname/sizeof(char*))
	if(vo < sizeof trapname/sizeof(char*)){
		/* special case, and pc will be o.k. */
		if(vo==4 && *(ushort*)pc==0x4848)
			return "breakpoint";
		return trapname[vo];
	}
	sprint(buf, "offset 0x%ux", vo<<2);
	return buf;
}


@@ 93,10 97,10 @@ trap(Ureg *ur)
		u->dbgreg = ur;
	}
	if(user){
		sprint(buf, "sys: %s pc=0x%lux", excname(ur->vo), ur->pc);
		sprint(buf, "sys: %s pc=0x%lux", excname(ur->vo, ur->pc), ur->pc);
		postnote(u->p, 1, buf, NDebug);
	}else{
		print("kernel trap vo=0x%ux pc=0x%lux\n", ur->vo, ur->pc);
		print("kernel trap %s pc=0x%lux\n", excname(ur->vo, ur->pc), ur->pc);
		dumpregs(ur);
		exit();
	}

M pc/clock.c => pc/clock.c +5 -1
@@ 21,7 21,6 @@ enum
					 *  period is the counter period
					 */
	Freq=		1193182,	/* Real clock frequency */
	FHZ=		1000,		/* hertz for fast clock */
};

/*


@@ 58,20 57,25 @@ void
clock(Ureg *ur)
{
	Proc *p;
	int nrun = 0;

	m->ticks++;

	checkalarms();
	uartclock();

	/*
	 *  process time accounting
	 */
	p = m->proc;
	if(p){
		nrun = 1;
		p->pc = ur->pc;
		if (p->state==Running)
			p->time[p->insyscall]++;
	}
	nrun = (nrdy+nrun)*1000;
	MACHP(0)->load = (MACHP(0)->load*19+nrun)/20;

	if(u && p && p->state==Running){
		/*

M pc/devuart.c => pc/devuart.c +18 -25
@@ 72,7 72,6 @@ struct Uart
	Rendez	r;		/* kproc waiting for input */
	Alarm	*a;		/* alarm for waking the kernel process */
 	int	kstarted;	/* kproc started */
	uchar	delim[256/8];	/* characters that act as delimiters */

	/* error statistics */
	ulong	frame;


@@ 239,11 238,8 @@ uartintr(Uart *up)
			ch = uartrdreg(up, Data) & 0xff;
			if(cq->putc)
				(*cq->putc)(cq, ch);
			else {
			else
				putc(cq, ch);
				if(up->delim[ch/8] & (1<<(ch&7)) )
					wakeup(&cq->r);
			}
			break;
	
		case 2:	/* transmitter empty */


@@ 281,6 277,20 @@ uartintr1(Ureg *ur)
	uartintr(&uart[1]);
}

void
uartclock(void)
{
	Uart *up;
	IOQ *cq;

	for(up = uart; up < &uart[2]; up++){
		cq = up->iq;
		if(up->wq && cangetc(cq))
			wakeup(&cq->r);
	}
}


/*
 *  turn on a port's interrupts.  set DTR and RTS
 */


@@ 301,11 311,6 @@ uartenable(Uart *up)
	}

	/*
	 *  speed up the clock to poll the uart
	fclockinit();
	 */

	/*
	 *  set up i/o routines
	 */
	if(up->oq){


@@ 431,9 436,6 @@ uartstopen(Queue *q, Stream *s)
	RD(q)->ptr = up;
	qunlock(up);

	/* start with all characters as delimiters */
	memset(up->delim, 0xff, sizeof(up->delim));
	
	if(up->kstarted == 0){
		up->kstarted = 1;
		sprint(name, "uart%d", s->id);


@@ 486,18 488,6 @@ uartoput(Queue *q, Block *bp)
		case 'd':
			uartdtr(up, n);
			break;
		case 'e':
		case 'E':
			/*
			 *  the characters in the block are the message
			 *  delimiters to use upstream
			 */
			memset(up->delim, 0, sizeof(up->delim));
			while(++(bp->rptr) < bp->wptr){
				m = *bp->rptr;
				up->delim[m/8] |= 1<<(m&7);
			}
			break;
		case 'K':
		case 'k':
			uartbreak(up, n);


@@ 531,6 521,7 @@ uartkproc(void *a)
	Block *bp;
	int n;
	ulong frame, overrun;
	static ulong ints;

	frame = 0;
	overrun = 0;


@@ 540,6 531,8 @@ uartkproc(void *a)

	for(;;){
		sleep(&cq->r, cangetc, cq);
		if((ints++ & 0x1f) == 0)
			owl(ints>>5);
		qlock(up);
		if(up->wq == 0){
			cq->out = cq->in;

M pc/fns.h => pc/fns.h +3 -0
@@ 1,6 1,7 @@
#include "../port/portfns.h"

void	meminit(void);
void	bigcursor(void);
#define	clearmmucache()		/* 386 doesn't have one */
void	clock(Ureg*);
void	clockinit(void);


@@ 30,6 31,7 @@ void	mmuinit(void);
int	modem(int);
void	outb(int, int);
void	outss(int, void*, int);
void	owl(int);
int	pmuwrbit(int, int, int);
void	prhex(ulong);
void	procrestore(Proc*, uchar*);


@@ 48,6 50,7 @@ void	systrap(void);
void	touser(void);
void	trapinit(void);
int	tas(Lock*);
void	uartclock(void);
void	uartintr0(Ureg*);
void	vgainit(void);
#define	waserror()	(u->nerrlab++, setlabel(&u->errlab[u->nerrlab-1]))

M pc/main.c => pc/main.c +9 -9
@@ 14,11 14,12 @@ main(void)
{
	meminit();
	machinit();
	active.exiting = 0;
	active.machs = 1;
	confinit();
	screeninit();
	printinit();
	print("%ludK bytes of physical memory\n", (conf.base1 + conf.npage1*BY2PG)/1024);
vgadump();
	mmuinit();
	trapinit();
	mathinit();


@@ 30,6 31,7 @@ vgadump();
	grpinit();
	chaninit();
	alarminit();
	bigcursor();
	chandevreset();
	streaminit();
	swapinit();


@@ 39,9 41,6 @@ vgadump();
	schedinit();
}

/*
 *	BUG -- needs floating point support
 */
void
machinit(void)
{


@@ 51,7 50,6 @@ machinit(void)
	memset(m, 0, sizeof(Mach));
	m->machno = n;
	m->mmask = 1<<m->machno;
	active.machs = 1;
}

ulong garbage;


@@ 504,10 502,12 @@ buzz(int f, int d)
void
lights(int val)
{
	static QLock ll;

	qlock(&ll);
	pmuwrbit(0, (val&1), 4);		/* owl */
	pmuwrbit(0, ((val>>1)&1), 1);		/* mail */
	qunlock(&ll);
}

void
owl(int val)
{
	pmuwrbit(0, (val&1), 4);		/* owl */
}

M pc/trap.c => pc/trap.c +29 -4
@@ 179,6 179,20 @@ trapinit(void)
	outb(Int0aux, int0mask);
}

char *excname[] =
{
[0]	"divide error",
[1]	"debug exception",
[4]	"overflow",
[5]	"bounds check",
[6]	"invalid opcode",
[8]	"double fault",
[10]	"invalid TSS",
[11]	"segment not present",
[12]	"stack exception",
[13]	"general protection violation",
};

/*
 *  All traps
 */


@@ 187,7 201,7 @@ trap(Ureg *ur)
{
	int v, user;
	int c;
	static int spuriousfloppy;
	char buf[ERRLEN];

	v = ur->trap;



@@ 195,9 209,6 @@ trap(Ureg *ur)
	if(user)
		u->dbgreg = ur;

	if(v>=256 || ivec[v] == 0)
		panic("bad trap type %d %lux %lux %lux\n", v, ur->pc, int0mask, int1mask);

	/*
	 *  tell the 8259 that we're done with the
	 *  highest level interrupt (interrupts are still


@@ 212,6 223,20 @@ trap(Ureg *ur)
			uartintr0(ur);
	}

	if(v>=256 || ivec[v] == 0){
		if(v <= 16){
			if(user){
				sprint(buf, "sys: %s pc=0x%lux", excname[v], ur->pc);
				postnote(u->p, 1, buf, NDebug);
				return;
			} else {
				dumpregs(ur);
				panic("%s pc=0x%lux", excname[v], ur->pc);
			}
		}
		panic("bad trap type %d pc=0x%lux\n", v, ur->pc);
	}

	(*ivec[v])(ur);

	/*

M pc/vga.c => pc/vga.c +86 -78
@@ 24,9 24,6 @@ struct{
 */
#define MAXX	640
#define MAXY	480
int	xperiod = 800;	/* Hsync freq == 31.47 KHZ */
int	yperiod	= 525;	/* Vsync freq == 59.9 HZ */
int	yborder = 7;	/* top/bottom border of screen */

#define SCREENMEM	(0xA0000 | KZERO)



@@ 48,35 45,58 @@ enum
	EFCR=		0x3CA,
	GRX=		0x3CE,		/* index to graphics registers */
	GR=		0x3CF,		/* graphics registers */
	 Grot=		 0x03,		/*  data rotate register */
	 Gmode=		 0x05,		/*  mode register */
	 Gmisc=		 0x06,		/*  miscillaneous register */
	 Grms=		 0x04,		/*  read map select register */
	SRX=		0x3C4,		/* index to sequence registers */
	SR=		0x3C5,		/* sequence registers */
	 Sclock=	 0x01,		/*  clocking register */
	 Smode=		 0x04,		/*  mode register */
	 Smmask=	 0x02,		/*  map mask */
	CRX=		0x3D4,		/* index to crt registers */
	CR=		0x3D5,		/* crt registers */
	 Cvt=		 0x06,		/*  vertical total */
	 Cvover=	 0x07,		/*  bits that didn't fit elsewhere */
	 Cmsl=		 0x09,		/*  max scan line */
	 Cvrs=		 0x10,		/*  vertical retrace start */
	 Cvre=		 0x11,		/*  vertical retrace end */
	 Cvde=	 	 0x12,		/*  vertical display end */
	 Cvbs=		 0x15,		/*  vertical blank start */
	 Cvbe=		 0x16,		/*  vertical blank end */
	 Cmode=		 0x17,		/*  mode register */
	ARX=		0x3C0,		/* index to attribute registers */
	AR=		0x3C1,		/* attribute registers */
	 Amode=		 0x10,		/*  mode register */
	 Acpe=		 0x12,		/*  color plane enable */
};

typedef struct VGAmode	VGAmode;
struct VGAmode
{
	uchar	general[4];
	uchar	sequencer[5];
	uchar	crt[0x19];
	uchar	graphics[9];
	uchar	attribute[0x15];
};

/*
 *  routines for setting vga registers
 *  640x480 display, 16 bit color
 */
VGAmode mode12 = 
{
	/* general */
	0xe3, 0x00, 0x70, 0x04,
	/* sequence */
	0x03, 0x01, 0x0f, 0x00, 0x06,
	/* crt */
	0x5f, 0x4f, 0x50, 0x82, 0x54, 0x80, 0x0b, 0x3e,
	0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x59,
	0xea, 0x0c, 0xdf, 0x28, 0x00, 0xe7, 0x04, 0xe3,
	0xff,
	/* graphics */
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x0f,
	0xff,
	/* attribute */
	0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x14, 0x07,
	0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
	0x01, 0x00, 0x0f, 0x00, 0x00,
};

void
genout(int reg, int val)
{
	if(reg == 0)
		outb(EMISCW, val);
	else if (reg == 1)
		outb(EFCW, val);
}
void
srout(int reg, int val)
{


@@ 122,68 142,28 @@ vgardplane(int p)
vgadump(void)
{
	print("misc is 0x%ux fc is 0x%ux\n", inb(EMISCR), inb(EFCR));
	outb(EMISCW, 0xc7);/**/
}

vgaclock(void)
void
setmode(VGAmode *v)
{
	outb(EMISCW, 0xc7);/**/
}
	int i;

/*
 *  set up like vga mode 0x12
 *	16 color (though we only use values 0x0 and 0xf)
 *	640x480
 *
 *  we assume the BIOS left the registers in a
 *  CGA-like mode.  Thus we don't set all the registers.
 */
vga12(void)
{
	int overflow;
	int msl;

	arout(Acpe, 0x00);	/* disable planes for output */

	gscreen.ldepth = 0;
	arout(Amode, 0x01);	/* color graphics mode */
	grout(Gmisc, 0x01);	/* graphics mode */
	grout(Gmode, 0x00);	/* 1 bit deep */
	grout(Grot, 0x00);	/* CPU writes bytes to video
				 * mem without modifications */

	msl = overflow = 0;
	/* turn off address wrap & word mode */
	crout(Cmode, 0xe3);
	/* last scan line displayed (first is 0) */
	crout(Cvde, MAXY-1);
	overflow |= ((MAXY-1)&0x200) ? 0x40 : 0;
	overflow |= ((MAXY-1)&0x100) ? 0x2 : 0;
	/* total scan lines (including retrace) - 2 */
	crout(Cvt, (yperiod-2));
	overflow |= ((yperiod-2)&0x200) ? 0x20 : 0;
	overflow |= ((yperiod-2)&0x100) ? 0x1 : 0;
	/* scan lines at which vertcal retrace starts & ends */
	crout(Cvrs, (MAXY+0x0a)); /**/
	overflow |= ((MAXY+0x0a)&0x200) ? 0x80 : 0;
	overflow |= ((MAXY+0x0a)&0x100) ? 0x4 : 0;
	crout(Cvre, ((yperiod-1)&0xf)|0xa0);	/* also disable vertical interrupts */
	/* scan lines at which vertical blanking starts & ends */
	crout(Cvbs, (MAXY+yborder));
	msl |= ((MAXY+yborder)&0x100) ? 0x20 : 0;
	overflow |= ((MAXY+yborder)&0x100) ? 0x8 : 0;
	crout(Cvbe, (yperiod-yborder)&0x7f);
	/* the overflow bits from the other registers */
	crout(Cvover, 0x10|overflow);	/* also 9th bit of line compare */
	/* pixels per scan line (always 0 for graphics) */
	crout(Cmsl, 0x40|msl);	/* also 10th bit of line compare */

	srout(Smode, 0x06);	/* extended memory,
				 * odd/even off */
	srout(Sclock, 0x01);	/* 8 bits/char */
	srout(Smmask, 0x0f);	/* enable 4 planes for writing */

	arout(Acpe, 0x0f);	/* enable 4 planes for output */
	for(i = 0; i < sizeof(v->general); i++)
		genout(i, v->general[i]);

	for(i = 0; i < sizeof(v->sequencer); i++)
		srout(i, v->sequencer[i]);

	crout(Cvre, 0);	/* allow writes to CRT registers 0-7 */
	for(i = 0; i < sizeof(v->crt); i++)
		crout(i, v->crt[i]);

	for(i = 0; i < sizeof(v->graphics); i++)
		grout(i, v->graphics[i]);

	for(i = 0; i < sizeof(v->attribute); i++)
		arout(i, v->attribute[i]);
}

void


@@ 193,7 173,8 @@ screeninit(void)
	int c;
	ulong *l;

	vga12();
	setmode(&mode12);
	bigcursor();

	/*
	 *  swizzle the font longs.


@@ 322,3 303,30 @@ vgaset(char *cmd)
		break;
	}
}


/*
 *  a fatter than usual cursor for the safari
 */
Cursor fatarrow = {
	{ -1, -1 },
	{
		0xff, 0xff, 0x80, 0x01, 0x80, 0x02, 0x80, 0x0c, 
		0x80, 0x10, 0x80, 0x10, 0x80, 0x08, 0x80, 0x04, 
		0x80, 0x02, 0x80, 0x01, 0x80, 0x02, 0x8c, 0x04, 
		0x92, 0x08, 0x91, 0x10, 0xa0, 0xa0, 0xc0, 0x40, 
	},
	{
		0x00, 0x00, 0x7f, 0xfe, 0x7f, 0xfc, 0x7f, 0xf0, 
		0x7f, 0xe0, 0x7f, 0xe0, 0x7f, 0xf0, 0x7f, 0xf8, 
		0x7f, 0xfc, 0x7f, 0xfe, 0x7f, 0xfc, 0x73, 0xf8, 
		0x61, 0xf0, 0x60, 0xe0, 0x40, 0x40, 0x00, 0x00, 
	},
};
void
bigcursor(void)
{
	extern Cursor arrow;

	memmove(&arrow, &fatarrow, sizeof(fatarrow));
}

M port/alarm.c => port/alarm.c +6 -7
@@ 134,14 134,13 @@ procalarm(ulong time)
	Proc **l, *f;
	ulong when, old;

	when = MS2TK(time);
	old = u->p->alarm - MACHP(0)->ticks;
	if(when == 0){
	old = TK2MS(u->p->alarm - MACHP(0)->ticks);
	if(time == 0){
		u->p->alarm = 0;
		return TK2MS(old);
		return old;
	}
	else
		when += MACHP(0)->ticks;
	when = MS2TK(time);
	when += MACHP(0)->ticks;

	lock(&alarms);
	l = &alarms.head;


@@ 172,7 171,7 @@ done:
	u->p->alarm = when;
	unlock(&alarms);

	return TK2MS(old);			
	return old;			
}

/*

M port/devcons.c => port/devcons.c +4 -1
@@ 475,7 475,7 @@ consread(Chan *c, void *buf, long n, ulong offset)
	char *cbuf = buf;
	char *user;
	int userlen;
	char tmp[6*NUMSIZE], xbuf[1024];
	char tmp[6*NUMSIZE], xbuf[512];
	Mach *mp;

	if(n <= 0)


@@ 603,6 603,7 @@ consread(Chan *c, void *buf, long n, ulong offset)

	case Qsysstat:
		j = 0;
		xbuf[0] = 0;
		for(id = 0; id < 32; id++) {
			if(active.machs & (1<<id)) {
				mp = MACHP(id);


@@ 621,6 622,8 @@ consread(Chan *c, void *buf, long n, ulong offset)
		return readstr(offset, buf, n, xbuf);
	case Qlights:
		errors("write only");
	case Qnoise:
		return 0;
	default:
		panic("consread %lux\n", c->qid);
		return 0;

M port/devlance.c => port/devlance.c +2 -0
@@ 17,6 17,8 @@ enum {

#define NOW (MACHP(0)->ticks*MS2HZ)

static int netlight;

/*
 *  Communication with the lance is via a transmit and receive ring of
 *  message descriptors.  The Initblock contains pointers to and sizes of

M port/devproc.c => port/devproc.c +22 -38
@@ 106,7 106,6 @@ procreset(void)
Chan*
procattach(char *spec)
{
	Chan *c;
	return devattach('p', spec);
}



@@ 596,58 595,43 @@ procstopped(void *a)
int
procctlmemio(Proc *p, ulong offset, int n, void *va, int read)
{
	Pte **pte;
	Pte *pte;
	Page *pg;
	KMap *k;
	Segment *s;
	ulong soff;
	char *a = va, *b;

Again:
	s = seg(p, offset, 1);
	if(s == 0)
		errors("not in address space");
	for(;;) {
		s = seg(p, offset, 1);
		if(s == 0)
			errors("not in address space");

	if(offset+n >= s->top)
		n = s->top-offset;
		if(offset+n >= s->top)
			n = s->top-offset;

	if(read == 0 && (s->type&SG_TYPE) == SG_TEXT)
		s = txt2data(p, s);
		if((s->type&SG_TYPE) == SG_TEXT)
			s = txt2data(p, s);

	s->steal++;
	soff = offset-s->base;
	pte = &s->map[soff/PTEMAPMEM];
	if(*pte == 0) {
		if(waserror()) {
			s->steal--;
			nexterror();
		}
		if(fixfault(s, offset, read, 0) != 0) {
			s->steal--;
			poperror();
			goto Again;
		}
		poperror();
		if(*pte == 0)
			panic("procctlmemio"); 
	}
	pg = (*pte)->pages[(soff&(PTEMAPMEM-1))/BY2PG];
	if(pagedout(pg)) {
		s->steal++;
		soff = offset-s->base;
		if(waserror()) {
			s->steal--;
			nexterror();
		}
		if(fixfault(s, offset, read, 0) != 0) {
			s->steal--;
			poperror();
			goto Again;
		}
		if(fixfault(s, offset, read, 0) == 0)
			break;
		poperror();
		pg = (*pte)->pages[(soff&(PTEMAPMEM-1))/BY2PG];
		if(pg == 0)
			panic("procctlmemio1");
		s->steal--;
	}

	poperror();
	pte = s->map[soff/PTEMAPMEM];
	if(pte == 0)
		panic("procctlmemio"); 
	pg = pte->pages[(soff&(PTEMAPMEM-1))/BY2PG];
	if(pagedout(pg))
		panic("procctlmemio1"); 
		
	k = kmap(pg);
	b = (char*)VA(k);
	if(read == 1)

M port/fault.c => port/fault.c +2 -2
@@ 76,11 76,11 @@ fixfault(Segment *s, ulong addr, int read, int doputmmu)
			*pg = new;
			new = 0;
		}
						/* NO break */
		/* NO break */
	case SG_DATA:
		if(pagedout(*pg))
			pio(s, addr, soff, pg);

		
		if(type == SG_SHARED)
			goto done;


M port/pgrp.c => port/pgrp.c +4 -3
@@ 313,20 313,21 @@ envcpy(Egrp *to, Egrp *from)
void
pgrpcpy(Pgrp *to, Pgrp *from)
{
	Mhead **h, **e, *f, **l, *mh;
	Mhead **h, **e, *f, **tom, **l, *mh;
	Mount *n, *m, **link;

	rlock(&from->ns);

	e = &from->mnthash[MNTHASH];
	tom = to->mnthash;
	for(h = from->mnthash; h < e; h++) {
		l = tom++;
		for(f = *h; f; f = f->hash) {
			mh = newmnthead();
			mh->from = f->from;
			incref(mh->from);
			l = &MOUNTH(to, mh->from);
			mh->hash = *l;
			*l = mh;
			l = &mh->hash;
			link = &mh->mount;
			for(m = f->mount; m; m = m->next) {
				n = newmount(mh, m->to);

M power/clock.c => power/clock.c +1 -1
@@ 99,7 99,7 @@ clock(Ureg *ur)
				}
			}
			nrun = (nrdy+nrun)*1000;
			m->load = (m->load+nrun)/2;
			m->load = (m->load*19+nrun)/20;
		}
		duartslave();
		if(active.exiting && active.machs&(1<<m->machno)){

M power/devduart.c => power/devduart.c +1 -1
@@ 841,4 841,4 @@ duartactive(void)
	for(i = 0; i < nduartport; i++)
		if(duartport[i].printing)
			return 1;
	return 0;                                                                         }
	return 0;                                                             }

M ss/clock.c => ss/clock.c +9 -2
@@ 42,17 42,22 @@ void
clock(Ureg *ur)
{
	Proc *p;
	ulong i;
	ulong i, ss, nrun = 0;
	Segment *s;

	i = ctr->lim1;	/* clear interrupt */
	USED(i);
	m->ticks++;
	p = m->proc;
	if(p){
		nrun = 1;
		p->pc = ur->pc;
		if (p->state==Running)
			p->time[p->insyscall]++;
	}
	nrun = (nrdy+nrun)*1000;
	MACHP(0)->load = (MACHP(0)->load*19+nrun)/20;

	checkalarms();
	kbdclock();
	mouseclock();


@@ 66,8 71,10 @@ clock(Ureg *ur)
				sched();
		}
		if((ur->psr&PSRPSUPER) == 0){
/*			*(ulong*)(USTKTOP-BY2WD) += TK2MS(1); /**/
			ss = spllo();				/* Low because we may fault */
			*(ulong*)(USTKTOP-BY2WD) += TK2MS(1);
			notify(ur);
			splx(ss);				/* return hi for restore */
		}
	}
}

M ss/dat.h => ss/dat.h +3 -2
@@ 51,7 51,7 @@ enum
struct	FPsave
{
	long	fsr;
	long	fpreg[32+1];	/* +1 so we can double-align */
	long	fpreg[32];
};

struct Conf


@@ 156,10 156,11 @@ struct Mach
struct User
{
	Proc	*p;
					/* &fpsave must be 4 mod 8 */
	FPsave	fpsave;			/* address of this is known by db */
	int	nerrlab;
	Label	errlab[NERR];
	char	error[ERRLEN];
	FPsave	fpsave;			/* address of this is known by vdb */
	char	elem[NAMELEN];		/* last name element from namec */
	Chan	*slash;
	Chan	*dot;

M ss/l.s => ss/l.s +30 -36
@@ 1,6 1,7 @@
#include "mem.h"

#define	SYSPSR	(SPL(0x0)|PSREF|PSRSUPER)
#define	SYSPSR	(SPL(0x0)|PSREF|PSRSUPER|0)
#define	NOOP	OR R0, R0; OR R0, R0; OR R0, R0

TEXT	start(SB), $-4



@@ 16,6 17,7 @@ TEXT	start(SB), $-4
	MOVW	$setSB(SB), R2
	MOVW	$startvirt(SB), R7
	JMPL	(R7)
	MOVW	$_mul(SB), R0	/* touch _mul etc.; doesn't need to execute */
	RETURN			/* can't get here */

TEXT	startvirt(SB), $-4


@@ 47,8 49,8 @@ TEXT	startvirt(SB), $-4
	FMOVD	F24, F22

	MOVW	$mach0(SB), R(MACH)
	MOVW	$0x8, R7
	MOVW	R7, WIM
/*	MOVW	$0x8, R7 /**/
	MOVW	R0, WIM
	JMPL	main(SB)
	MOVW	(R0), R0
	RETURN


@@ 71,9 73,7 @@ TEXT	swap1x(SB), $0
	MOVW	R9, R10
	AND	$~PSRET, R10		/* BUG: book says this is buggy */
	MOVW	R10, PSR
	OR	R0, R0
	OR	R0, R0
	OR	R0, R0
	NOOP
	MOVW	(R7), R7
	CMP	R7, R0
	BNE	was1


@@ 89,9 89,7 @@ TEXT	spllo(SB), $0
	MOVW	R7, R10
	OR	$PSRET, R10
	MOVW	R10, PSR
	OR	R0, R0
	OR	R0, R0
	OR	R0, R0
	NOOP
	RETURN

TEXT	splhi(SB), $0


@@ 101,18 99,14 @@ TEXT	splhi(SB), $0
	MOVW	R7, R10
	AND	$~PSRET, R10	/* BUG: book says this is buggy */
	MOVW	R10, PSR
	OR	R0, R0
	OR	R0, R0
	OR	R0, R0
	NOOP
	RETURN

TEXT	splx(SB), $0

	MOVW	R15, 4(R(MACH))	/* save PC in m->splpc */
	MOVW	R7, PSR		/* BUG: book says this is buggy */
	OR	R0, R0
	OR	R0, R0
	OR	R0, R0
	NOOP
	RETURN

TEXT	spldone(SB), $0


@@ 122,9 116,7 @@ TEXT	spldone(SB), $0
TEXT	touser(SB), $0
	MOVW	$(SYSPSR&~PSREF), R8
	MOVW	R8, PSR
	OR	R0, R0
	OR	R0, R0
	OR	R0, R0
	NOOP

	MOVW	R7, R1
	SAVE	R0, R0			/* RETT is implicit RESTORE */


@@ 143,6 135,7 @@ TEXT	traplink(SB), $-4
	/* R8 to R23 are free to play with */
	/* R17 contains PC, R18 contains nPC */
	/* R19 has PSR loaded from vector code */

	ANDCC	$PSRPSUPER, R19, R0
	BE	usertrap



@@ 191,18 184,14 @@ trap1:
	SUB	$8, R1
	MOVW	$SYSPSR, R8
	MOVW	R8, PSR
	OR	R0, R0
	OR	R0, R0
	OR	R0, R0
	NOOP
	JMPL	trap(SB)

	ADD	$8, R1
restore:
	MOVW	(4*(32+2))(R1), R8		/* PSR */
	MOVW	R8, PSR
	OR	R0, R0
	OR	R0, R0
	OR	R0, R0
	NOOP

	MOVD	(4*30)(R1), R30
	MOVD	(4*28)(R1), R28


@@ 250,6 239,7 @@ TEXT	syslink(SB), $-4
	/* R17 contains PC, R18 contains nPC */
	/* R19 has PSR loaded from vector code */
	/* assume user did it; syscall checks */

	MOVW	R1, R8
	MOVW	R2, R9
	MOVW	$setSB(SB), R2


@@ 282,9 272,7 @@ TEXT	syslink(SB), $-4
	ADD	$8, R1
	MOVW	(4*(32+2))(R1), R8		/* PSR */
	MOVW	R8, PSR
	OR	R0, R0
	OR	R0, R0
	OR	R0, R0
	NOOP

	MOVW	(4*15)(R1), R15
	SAVE	R0, R0


@@ 299,9 287,7 @@ TEXT	syslink(SB), $-4
TEXT	puttbr(SB), $0

	MOVW	R7, TBR
	OR	R0, R0
	OR	R0, R0
	OR	R0, R0
	NOOP
	RETURN

TEXT	gettbr(SB), $0


@@ 342,6 328,11 @@ TEXT	putcxsegm(SB), $0
	JMPL	(R7)
	RETURN

TEXT	getpsr(SB), $0

	MOVW	PSR, R7
	RETURN

TEXT	putcxreg(SB), $0

	MOVW	$CONTEXT, R8


@@ 376,6 367,11 @@ TEXT	putw4(SB), $0
	MOVW	R8, (R7, 4)
	RETURN

TEXT	getw4(SB), $0

	MOVW	(R7, 4), R7
	RETURN

TEXT	putwC(SB), $0

	MOVW	4(FP), R8


@@ 475,9 471,7 @@ TEXT	putsegm(SB), $0
TEXT	savefpregs(SB), $0

	MOVW	FSR, 0(R7)

	ADD	$(4+7), R7		/* double-align so can MOVD */
	ANDN	$7, R7
	ADD	$4, R7		/* assumes R7 is now MOVD-aligned */

	MOVD	F0, (0*4)(R7)
	MOVD	F2, (2*4)(R7)


@@ 507,10 501,10 @@ TEXT	restfpregs(SB), $0
	OR	$PSREF, R8
	MOVW	R8, PSR

	MOVW	(R7), FSR
	NOOP

	ADD	$(4+7), R7		/* double-align so can MOVD */
	ANDN	$7, R7
	MOVW	(R7), FSR
	ADD	$4, R7		/* assumes R7 is now MOVD-aligned */

	MOVD	(0*4)(R7), F0
	MOVD	(2*4)(R7), F2

M ss/main.c => ss/main.c +2 -0
@@ 21,6 21,8 @@ main(void)
	memset(&edata, 0, (char*)&end-(char*)&edata);

	machinit();
	active.exiting = 0;
	active.machs = 1;
	confinit();
	mmuinit();
	screeninit();

M ss/trap.c => ss/trap.c +21 -9
@@ 33,20 33,27 @@ char *trapname[]={
char*
excname(ulong tbr)
{
	static char buf[32];	/* BUG: not reentrant! */
	static char buf[64];	/* BUG: not reentrant! */

	if(tbr < sizeof trapname/sizeof(char*))
		return trapname[tbr];
	if(tbr == 36)
		return "cp disabled";
	if(tbr == 40)
		return "cp exception";
	if(tbr >= 128)
	if(tbr >= 130)
		sprint(buf, "trap instruction %d", tbr-128);
	else if(17<=tbr && tbr<=31)
		sprint(buf, "interrupt level %d", tbr-16);
	else
	else switch(tbr){
	case 36:
		return "cp disabled";
	case 40:
		return "cp exception";
	case 128:
		return "syscall";
	case 129:
		return "breakpoint";
	default:
		sprint(buf, "unknown trap %d", tbr);
	}
    Return:
	return buf;
}



@@ 57,8 64,11 @@ trap(Ureg *ur)
	char buf[64];
	ulong tbr;

	if(u)
	if(u) {
		u->p->pc = ur->pc;		/* BUG */
		u->dbgreg = ur;
	}

	user = !(ur->psr&PSRPSUPER);
	tbr = (ur->tbr&0xFFF)>>4;
	if(tbr > 16){			/* interrupt */


@@ 124,7 134,7 @@ trap(Ureg *ur)
    Error:
		if(user){
			spllo();
			sprint(buf, "sys: trap: pc=0x%lux %s", ur->pc, excname(tbr));
			sprint(buf, "sys: %s pc=0x%lux", excname(tbr), ur->pc);
			if(tbr == 8)
				sprint(buf+strlen(buf), " FSR %lux", u->fpsave.fsr);
			postnote(u->p, 1, buf, NDebug);


@@ 168,6 178,7 @@ trapinit(void)
	a += 0x40000000;
	*(ulong*)t = a;			/* CALL syscall(SB) */
	*(ulong*)(t+4) = 0xa7480000;	/* MOVW PSR, R19 */

	puttbr(TRAPS);
}



@@ 220,6 231,7 @@ notify(Ureg *ur)
		procctl(u->p);
	if(u->nnote == 0)
		return;

	lock(&u->p->debug);
	u->p->notepending = 0;
	if(u->nnote==0){