~kris/9p

9hist

fcf95869e73b7416517583b51bbf3e9694beb5f4 — David du Colombier 35 years ago 0c132ec
Plan 9 from Bell Labs 1991-07-18
15 files changed, 232 insertions(+), 72 deletions(-)

M gnot/lib.h
M gnot/trap.c
M pc/dat.h
M pc/fault386.c
M pc/fns.h
M pc/l.s
M pc/main.c
M pc/mem.h
M pc/mmu.c
M pc/trap.c
M port/fault.c
M port/lib.h
M port/page.c
M power/trap.c
M ss/trap.c
M gnot/lib.h => gnot/lib.h +1 -1
@@ 75,7 75,7 @@ extern	long	end;
#define	ORCLOSE	64	/* or'ed in, remove on close */

#define	NCONT	0	/* continue after note */
#define	NTERM	1	/* terminate after note */
#define	NDFLT	1	/* terminate after note */

typedef struct Qid	Qid;
typedef struct Dir	Dir;

M gnot/trap.c => gnot/trap.c +1 -1
@@ 216,7 216,7 @@ noted(Ureg *ur, ulong arg0)
		u->lastnote.flag = NDebug;
		/* fall through */
		
	case NTERM:
	case NDFLT:
		if(u->lastnote.flag == NDebug)
			pprint("suicide: %s\n", u->lastnote.msg);
		unlock(&u->p->debug);

M pc/dat.h => pc/dat.h +5 -3
@@ 98,10 98,12 @@ struct Conf
 *  MMU stuff in proc
 */
#define MAXMMU	4
#define MAXSMMU	1
struct PMMU
{
	ulong	mmuent[MAXMMU];	/* a process' mmu entries */
	Page	*mmupg[MAXMMU];	/* mmu pages */
	int	mmuvalid;
	Page	*mmu[MAXMMU+MAXSMMU];	/* bottom level page tables */
	ulong	mmue[MAXMMU+MAXSMMU];	/* top level pointers to mmup pages */
};

#include "../port/portdat.h"


@@ 138,7 140,7 @@ struct Mach
 */
typedef void		KMap;
#define	VA(k)		((ulong)(k))
#define	kmap(p)		(KMap*)(p->pa|KZERO)
#define	kmap(p)		(KMap*)((p)->pa|KZERO)
#define	kunmap(k)

#define	NERR	15

M pc/fault386.c => pc/fault386.c +23 -4
@@ 7,13 7,32 @@
#include	"io.h"

void
faultinit(void)
fault386(Ureg *ur)
{
	setvec(Faultvec, fault386);
	ulong addr;
	int read;
	int user;

print("fault386\n");
dumpregs(ur);
for(;;);
	addr = getcr2();
	read = !(ur->ecode & 2);
	user = (ur->ecode & 4);
	if(fault(addr, read) < 0){
		if(user){
			pprint("user %s error addr=0x%lux\n", read? "read" : "write", addr);
			pprint("status=0x%lux pc=0x%lux sp=0x%lux\n", ur->flags, ur->pc, ur->usp);
			pexit("Suicide", 0);
		}
		u->p->state = MMUing;
		dumpregs(ur);
		panic("fault: 0x%lux", addr);
	}
}

void
fault386(Ureg *ur)
faultinit(void)
{
	panic("fault");
	setvec(Faultvec, fault386);
}

M pc/fns.h => pc/fns.h +6 -4
@@ 6,6 6,7 @@ void	clockinit(void);
void	delay(int);
#define	evenaddr(x)		/* 386 doesn't care */
void	fault386(Ureg*);
void	faultinit(void);
void	floppyinit(void);
void	floppyintr(Ureg*);
long	floppyseek(int, long);


@@ 13,6 14,7 @@ long	floppyread(int, void*, long);
#define	flushvirt();
void	fpsave(FPsave*);
void	fprestore(FPsave*);
ulong	getcr2(void);
void	idle(void);
int	inb(int);
void	intr0(void);


@@ 43,16 45,16 @@ void	intr64(void);
void	intrbad(void);
void	kbdinit(void);
void	kbdintr(Ureg*);
void	lgdt(Segdesc*, int);
void	lidt(Segdesc*, int);
void	lcr3(ulong);
void	ltr(ulong);
void	mmuinit(void);
void	outb(int, int);
void	prhex(ulong);
void	procrestore(Proc*, uchar*);
void	procsave(uchar*, int);
void	procsetup(Proc*);
void	putgdt(Segdesc*, int);
void	putidt(Segdesc*, int);
void	putcr3(ulong);
void	puttr(ulong);
void	screeninit(void);
void	screenputc(int);
void	screenputs(char*, int);

M pc/l.s => pc/l.s +25 -15
@@ 215,10 215,10 @@ TEXT	tas(SB),$0
	RET

/*
 *  routines to load various system registers
 *  routines to load/read various system registers
 */
GLOBL	idtptr(SB),$6
TEXT	lidt(SB),$0
TEXT	putidt(SB),$0		/* interrupt descriptor table */
	MOVL	t+0(FP),AX
	MOVL	AX,idtptr+2(SB)
	MOVL	l+4(FP),AX


@@ 227,7 227,7 @@ TEXT	lidt(SB),$0
	RET

GLOBL	gdtptr(SB),$6
TEXT	lgdt(SB),$0
TEXT	putgdt(SB),$0		/* global descriptor table */
	MOVL	t+0(FP),AX
	MOVL	AX,gdtptr+2(SB)
	MOVL	l+4(FP),AX


@@ 235,16 235,20 @@ TEXT	lgdt(SB),$0
	MOVL	gdtptr(SB),GDTR
	RET

TEXT	lcr3(SB),$0
TEXT	putcr3(SB),$0		/* top level page table pointer */
	MOVL	t+0(FP),AX
	MOVL	AX,CR3
	RET

TEXT	ltr(SB),$0
TEXT	puttr(SB),$0		/* task register */
	MOVL	t+0(FP),AX
	MOVW	AX,TASK
	RET

TEXT	getcr2(SB),$0		/* fault address */
	MOVL	CR2,AX
	RET

/*
 *  special traps
 */


@@ 350,6 354,8 @@ TEXT	intrbad(SB),$0
intrcommon:
	PUSHL	DS
	PUSHAL
	MOVL	$(KDSEL),AX
	MOVW	AX,DS
	LEAL	0(SP),AX
	PUSHL	AX
	CALL	trap(SB)


@@ 358,11 364,12 @@ intrcommon:
	POPL	DS
	ADDL	$8,SP	/* error code and trap type */
	IRETL
	RET		/* this has to be here because of ken */

intrscommon:
	PUSHL	DS
	PUSHAL
	MOVL	$(KDSEL),AX
	MOVW	AX,DS
	LEAL	0(SP),AX
	PUSHL	AX
	CALL	trap(SB)


@@ 371,7 378,6 @@ intrscommon:
	POPL	DS
	ADDL	$8,SP	/* error code and trap type */
	IRETL
	RET		/* this has to be here because of ken */

/*
 *  interrupt level is interrupts on or off


@@ 409,6 415,7 @@ TEXT	gotolabel(SB),$0
	MOVL	0(AX),SP	/* restore sp */
	MOVL	4(AX),AX	/* put return pc on the stack */
	MOVL	AX,0(SP)
	MOVL	$1,AX		/* return 1 */
	RET

TEXT	setlabel(SB),$0


@@ 416,17 423,20 @@ TEXT	setlabel(SB),$0
	MOVL	SP,0(AX)	/* store sp */
	MOVL	0(SP),BX	/* store return pc */
	MOVL	BX,4(AX)
	MOVL	$0,AX		/* return 0 */
	RET

/*
 *  Used to get to the first process.
 *  Set up an interrupt return frame and IRET to user level.
 */
TEXT	touser(SB),$0
	MOVL	$(USERADDR+BY2PG-6*BY2WD),AX
	MOVL	$(UTZERO+32),0(AX)	/* header is in text */
	MOVL	$(UESEL),4(AX)
	MOVL	$(IFLAG|2),8(AX)
	MOVL	$(USTKTOP-4*BY2WD),12(AX)
	MOVL	$(UDSEL),16(AX)
	MOVL	AX,SP
	MOVL	$(UDSEL),AX		/* set up data segment */
	PUSHL	$(UDSEL)			/* old ss */
	PUSHL	$(USTKTOP-4*BY2WD)		/* old sp */
	PUSHFL					/* old flags */
	PUSHL	$(UESEL)			/* old cs */
	PUSHL	$(UTZERO+32)			/* old pc */
	MOVL	$(UDSEL),AX		/* set up user's data segment */
	MOVW	AX,DS
	IRETL


M pc/main.c => pc/main.c +12 -6
@@ 17,19 17,17 @@ main(void)
	confinit();
	screeninit();
	printinit();
	print("%d pages in bank0, %d pages in bank1\n", conf.npage0, conf.npage1);
	print("edata == %lux, end == %lux\n", &edata, &end);
	mmuinit();
print("mmu inited\n");
	trapinit();
	clockinit();
	faultinit();
	procinit0();
print("proc inited\n");
	initseg();
	grpinit();
	chaninit();
	alarminit();
	chandevreset();
	streaminit();
	trapinit();
	swapinit();
	pageinit();
	userinit();


@@ 54,6 52,8 @@ machinit(void)
	active.machs = 1;
}

long useless;

void
init0(void)
{


@@ 65,6 65,7 @@ init0(void)
	u->p->mach = m;

	spllo();
print("interrupts on\n");

	/*
	 * These are o.k. because rootinit is null.


@@ 74,8 75,13 @@ init0(void)
	u->dot = clone(u->slash, 0);

	chandevinit();
print("going to user\n");

	/*
	 *  fault in the first executable page
	 */
	useless = *((ulong *)UTZERO);

/*	kickpager();	/* BUG */
	touser();
}


M pc/mem.h => pc/mem.h +17 -12
@@ 27,23 27,28 @@
/*
 * Fundamental addresses
 */
#define	USERADDR	0xC0000000
#define	UREGADDR	(USERADDR+BY2PG-4*16)

/*
 * Address spaces
 *  Address spaces
 *
 * User is at 0-2GB
 * Kernel is at 2GB-4GB
 *  User is at 0-2GB
 *  Kernel is at 2GB-4GB
 *
 *  To avoid an extra page map, both the user stack (USTKTOP) and
 *  the temporary user stack (TSTKTOP) should be in the the same
 *  4 meg.
 */
#define	UZERO	0			/* base of user address space */
#define	UTZERO	(UZERO+BY2PG)		/* first address in user text */
#define	TSTKTOP	USERADDR		/* end of new stack in sysexec */
#define	UZERO		0			/* base of user address space */
#define	UTZERO		(UZERO+BY2PG)		/* first address in user text */
#define	KZERO		0x80000000		/* base of kernel address space */
#define	KTZERO		KZERO			/* first address in kernel text */
#define	USERADDR	0xC0000000		/* struct User */
#define	UREGADDR	(USERADDR+BY2PG-4*16)	
#define	TSTKTOP		USERADDR		/* end of new stack in sysexec */
#define TSTKSIZ 10
#define	USTKTOP	(TSTKTOP-TSTKSIZ*BY2PG)	/* byte just beyond user stack */
#define	KZERO	0x80000000		/* base of kernel address space */
#define	KTZERO	KZERO			/* first address in kernel text */
#define	USTKSIZE	(4*1024*1024)	/* size of user stack */
#define	USTKTOP		(TSTKTOP-TSTKSIZ*BY2PG)	/* byte just beyond user stack */
#define	USTKSIZE	(4*1024*1024 - TSTKSIZ*BY2PG)	/* size of user stack */
#define USTKBTM		USTKTOP - USTKSIZE

#define	MACHSIZE	4096


M pc/mmu.c => pc/mmu.c +112 -18
@@ 76,6 76,17 @@ static ulong	*kpt;		/* kernel level page tables */
static ulong	*upt;		/* page table for struct User */

#define ROUNDUP(s,v)	(((s)+(v-1))&~(v-1))
/*
 *  offset of virtual address into
 *  top level page table
 */
#define TOPOFF(v)	((v)>>(2*PGSHIFT-2))

/*
 *  offset of virtual address into
 *  bottom level page table
 */
#define BTMOFF(v)	(((v)>>(PGSHIFT))&(BY2PG-1))

void
mmuinit(void)


@@ 90,10 101,10 @@ mmuinit(void)
	x = (ulong)systrap;
	gdt[SYSGATE].d0 = (x&0xFFFF)|(KESEL<<16);
	gdt[SYSGATE].d1 = (x&0xFFFF0000)|SEGP|SEGPL(3)|SEGCG;
	x = (long)&tss;
	x = (ulong)&tss;
	gdt[TSSSEG].d0 = (x<<16)|sizeof(Tss);
	gdt[TSSSEG].d1 = (x&0xFF000000)|((x>>16)&0xFF)|SEGTSS|SEGPL(0)|SEGP;
	lgdt(gdt, sizeof gdt);
	putgdt(gdt, sizeof gdt);

	/*
	 *  set up system page tables.


@@ 107,59 118,142 @@ mmuinit(void)
	kpt = ialloc(nkpt*BY2PG, 1);
	n = ROUNDUP(conf.npage0+conf.npage1, 1*1024*1024);
	n = n/(4*1024);
	for(i = 0; i < n; i++){
		kpt[i] = (i<<PGSHIFT)|PTEVALID|PTEKERNEL|PTEWRITE;
	}
	for(i = 0; i < n; i++)
		kpt[i] = (i<<PGSHIFT) | PTEVALID | PTEKERNEL | PTEWRITE;

	/*  allocate page table for u-> */
	upt = ialloc(BY2PG, 1);

	/*  allocate top level table and put pointers to lower tables in it */
	toppt = ialloc(BY2PG, 1);
	x = KZERO>>(2*PGSHIFT-2);
	x = TOPOFF(KZERO);
	y = ((ulong)kpt)&~KZERO;
	for(i = 0; i < nkpt; i++){
/*		toppt[i] = (y+i*BY2PG)|PTEVALID|PTEKERNEL|PTEWRITE;/**/
		toppt[x+i] = (y+i*BY2PG)|PTEVALID|PTEKERNEL|PTEWRITE;
	}
	x = USERADDR>>(2*PGSHIFT-2);
	for(i = 0; i < nkpt; i++)
		toppt[x+i] = (y+i*BY2PG) | PTEVALID | PTEKERNEL | PTEWRITE;
	x = TOPOFF(USERADDR);
	y = ((ulong)upt)&~KZERO;
	toppt[x] = y|PTEVALID|PTEKERNEL|PTEWRITE;
	lcr3(((ulong)toppt)&~KZERO);
	toppt[x] = y | PTEVALID | PTEKERNEL | PTEWRITE;
	putcr3(((ulong)toppt)&~KZERO);

	/*
	 *  set up the task segment
	 */
	tss.sp0 = USERADDR;
	tss.sp0 = USERADDR+BY2PG;
	tss.ss0 = KDSEL;
	tss.cr3 = (ulong)toppt;
	ltr(TSSSEL);
	puttr(TSSSEL);
}

void
mapstack(Proc *p)
{
	
	ulong tlbphys;
	int i;

print("mapstack\n");

	if(p->upage->va != (USERADDR|(p->pid&0xFFFF)))
		panic("mapstack %d 0x%lux 0x%lux", p->pid, p->upage->pa, p->upage->va);

	/*
 	 *  dump any invalid mappings
	 */
	if(p->mmuvalid == 0){
		for(i = 0; i < MAXMMU+MAXSMMU; i++){
			if(p->mmu[i]==0)
				continue;
			memset(kmap(p->mmu[i]), 0, BY2PG);
		}
		p->mmuvalid = 1;
	}

	/*
	 *  point top level page table to bottom level ones
	 */
	memmove(toppt, p->mmu, MAXMMU*sizeof(ulong));
	memmove(&toppt[TOPOFF(USTKBTM)], &p->mmu[MAXMMU], MAXSMMU*sizeof(ulong));

	/* map in u area */
	upt[0] = PPN(p->upage->pa) | PTEVALID | PTEKERNEL | PTEWRITE;

	/* flush cached mmu entries */
	putcr3(((ulong)toppt)&~KZERO);

	u = (User*)USERADDR;
}

void
flushmmu(void)
{
	int s;

	if(u == 0)
		return;

	u->p->mmuvalid = 0;
	s = splhi();
	mapstack(u->p);
	splx(s);
}

void
mmurelease(Proc *p)
{
	p->mmuvalid = 0;
}

void
putmmu(ulong x, ulong y, Page *z)
putmmu(ulong va, ulong pa, Page *pg)
{
	int topoff;
	ulong *pt;
	Proc *p;
	int i;

print("putmmu %lux %lux USTKTOP %lux\n", va, pa, USTKTOP); /**/
	if(u==0)
		panic("putmmu");
	p = u->p;

	/*
	 *  check for exec/data vs stack vs illegal
	 */
	topoff = TOPOFF(va);
	if(topoff < TOPOFF(TSTKTOP) && topoff >= TOPOFF(USTKBTM))
		i = MAXMMU + topoff - TOPOFF(USTKBTM);
	else if(topoff < MAXMMU)
		i = topoff;
	else
		panic("putmmu bad addr %lux", va);

	/*
	 *  if bottom level page table missing, allocate one
	 */
	pg = p->mmu[i];
	if(pg == 0){
		pg = p->mmu[i] = newpage(1, 0, 0);
		p->mmue[i] = PPN(pg->pa) | PTEVALID | PTEKERNEL | PTEWRITE;
		toppt[topoff] = p->mmue[i];
	}

	/*
	 *  fill in the bottom level page table
	 */
	pt = (ulong*)(p->mmu[i]->pa|KZERO);
	pt[BTMOFF(va)] = pa | PTEUSER;

	/* flush cached mmu entries */
	putcr3(((ulong)toppt)&~KZERO);
}

void
invalidateu(void)
{
	/* unmap u area */
	upt[0] = 0;

	/* flush cached mmu entries */
	putcr3(((ulong)toppt)&~KZERO);
}

void


@@ 177,5 271,5 @@ exit(void)
	print("exiting\n");
	for(i = 0; i < WD2PG; i++)
		toppt[i] = 0;
	lcr3(((ulong)toppt)&~KZERO);
	putcr3(((ulong)toppt)&~KZERO);
}

M pc/trap.c => pc/trap.c +24 -2
@@ 86,7 86,7 @@ trapinit(void)
	sethvec(23, intr23, SEGTG, 0);

	/*
	 *  set all others to unknown
	 *  set all others to unknown interrupts
	 */
	for(i = 24; i < 256; i++)
		sethvec(i, intrbad, SEGIG, 0);


@@ 100,7 100,7 @@ trapinit(void)
	/*
	 *  tell the hardware where the table is (and how long)
	 */
	lidt(ilt, sizeof(ilt));
	putidt(ilt, sizeof(ilt));

	/*
	 *  Set up the first 8259 interrupt processor.


@@ 137,11 137,33 @@ trap(Ureg *ur)
}

/*
 *  dump registers
 */
void
dumpregs(Ureg *ur)
{
	if(u)
		print("registers for %s %d\n", u->p->text, u->p->pid);
	else
		print("registers for kernel\n");
	print("FLAGS=%lux ECODE=%lux CS=%lux PC=%lux SS=%lux USP=%lux\n", ur->flags,
		ur->ecode, ur->cs, ur->pc, ur->ss, ur->usp);

	print("  AX %8.8lux  BX %8.8lux  CX %8.8lux  DX %8.8lux\n",
		ur->ax, ur->bx, ur->cx, ur->dx);
	print("  SI %8.8lux  DI %8.8lux  BP %8.8lux  DS %8.8lux\n",
		ur->si, ur->di, ur->bp, ur->ds);
}

/*
 *  system calls
 */
long
syscall(Ureg *ur)
{
	u->p->insyscall = 1;
	u->p->pc = ur->pc;

	panic("syscall");
}


M port/fault.c => port/fault.c +2 -2
@@ 103,8 103,8 @@ again:
	}

	qunlock(&s->lk);
	if(new)
		putpage(new);
	if(new)				/* A race may provide a page we never used when
		putpage(new);		 * a fault is fixed while process slept in newpage */

	putmmu(addr, mmuphys, *pg);
	return 0;

M port/lib.h => port/lib.h +1 -1
@@ 75,7 75,7 @@ extern	long	end;
#define	ORCLOSE	64	/* or'ed in, remove on close */

#define	NCONT	0	/* continue after note */
#define	NTERM	1	/* terminate after note */
#define	NDFLT	1	/* terminate after note */

typedef struct Qid	Qid;
typedef struct Dir	Dir;

M port/page.c => port/page.c +1 -1
@@ 296,7 296,7 @@ copypage(Page *f, Page *t)
}

void
uncachepage(Page *p)				/* Alway called with a locked page */
uncachepage(Page *p)				/* Always called with a locked page */
{
	Page **l, *f;


M power/trap.c => power/trap.c +1 -1
@@ 451,7 451,7 @@ noted(Ureg **urp, ulong arg0)
		u->lastnote.flag = NDebug;
		/* fall through */
		
	case NTERM:
	case NDFLT:
		if(u->lastnote.flag == NDebug)
			pprint("suicide: %s\n", u->lastnote.msg);
		unlock(&u->p->debug);

M ss/trap.c => ss/trap.c +1 -1
@@ 290,7 290,7 @@ noted(Ureg **urp, ulong arg0)
		u->lastnote.flag = NDebug;
		/* fall through */
		
	case NTERM:
	case NDFLT:
		if(u->lastnote.flag == NDebug)
			pprint("suicide: %s\n", u->lastnote.msg);
		unlock(&u->p->debug);