plan 9 kernel history: overview | file list | diff list

pc/mmu.c (diff list | history)

1991/0612/sys/src/9/pc/mmu.c:5,131991/0613/sys/src/9/pc/mmu.c:5,20 (short | long)
1991/0612    
#include	"fns.h" 
#include	"io.h" 
 
                 
                 
void 
mapstack(Proc *p) 
1991/0613    
/* 
 *  global descriptor table describing all segments 
 */ 
Segdesc gdt[1024] = 
1991/0612    
{ 
} 
1991/0613    
[NULLSEG]	{ 0, 0},		/* null descriptor */ 
[KESEG]		EXECSEG(0),		/* kernel code */ 
[KDSEG]		DATASEG(0),		/* kernel data/stack */ 
[UESEG]		EXECSEG(3),		/* user code */ 
[UDSEG]		DATASEG(3),		/* user data/stack */ 
[SYSGATE]	CALLGATE(KESEG, syscall, 3),	/* call gate for system calls */ 
		{ 0, 0},		/* the rest */ 
}; 
1991/0613/sys/src/9/pc/mmu.c:6,111991/0625/sys/src/9/pc/mmu.c:6,86 (short | long)
1991/0612    
#include	"io.h" 
 
1991/0613    
/* 
1991/0625    
 *  segment descriptor/gate 
 */ 
typedef struct Segdesc	Segdesc; 
struct Segdesc 
{ 
	ulong	d0; 
	ulong	d1; 
}; 
#define SEGDATA	(0x10<<8)	/* data/stack segment */ 
#define SEGEXEC	(0x18<<8)	/* executable segment */ 
#define SEGCG	(0x0C<<8)	/* call gate */ 
#define	SEGIG	(0x0E<<8)	/* interrupt gate */ 
#define SEGTG	(0x0F<<8)	/* task gate */ 
 
#define SEGP	(1<<15)		/* segment present */ 
#define SEGPL(x) ((x)<<13)	/* priority level */ 
#define SEGB	(1<<22)		/* granularity 1==4k (for expand-down) */ 
#define SEGG	(1<<23)		/* granularity 1==4k (for other) */ 
#define SEGE	(1<<10)		/* expand down */ 
#define SEGW	(1<<9)		/* writable (for data/stack) */ 
#define	SEGR	(1<<9)		/* readable (for code) */ 
#define SEGD	(1<<22)		/* default 1==32bit (for code) */ 
 
/* 
 *  gate initializers 
 */ 
#define TRAPGATE(s,o,p)	{ (o)&0xFFFF0000|SEGP|SEGPL(p)|SEGTG, (o)&0xFFFF|((s)<<16) } 
#define INTRGATE(s,o,p)	{ (o)&0xFFFF0000|SEGP|SEGPL(p)|SEGIG, (o)&0xFFFF|((s)<<16) } 
#define CALLGATE(s,o,p)	{ (o)&0xFFFF0000|SEGP|SEGPL(p)|SEGCG, (o)&0xFFFF|((s)<<16) } 
 
/* 
 *  segment descriptor initializers 
 */ 
#define	DATASEG(p) 	{ SEGG|SEGB|(0xF<<16)|SEGP|SEGPL(p)|SEGDATA|SEGW, 0xFFFF } 
#define	EXECSEG(p) 	{ SEGG|SEGD|(0xF<<16)|SEGP|SEGPL(p)|SEGEXEC|SEGR, 0xFFFF } 
 
/* 
 *  task state segment.  Plan 9 ignores all the task switching goo and just 
 *  uses the tss for esp0 and ss0 on gate's into the kernel, interrupts, 
 *  and exceptions.  The rest is completely ignored. 
 * 
 *  This means that we only need one tss in the whole system. 
 */ 
typedef struct Tss	Tss; 
struct Tss 
{ 
	ulong	backlink;	/* unused */ 
	ulong	esp0;		/* pl0 stack pointer */ 
	ulong	ss0;		/* pl0 stack selector */ 
	ulong	esp1;		/* pl1 stack pointer */ 
	ulong	ss1;		/* pl1 stack selector */ 
	ulong	esp2;		/* pl2 stack pointer */ 
	ulong	ss2;		/* pl2 stack selector */ 
	ulong	cr3;		/* page table descriptor */ 
	ulong	eip;		/* instruction pointer */ 
	ulong	eflags;		/* processor flags */ 
	ulong	eax;		/* general (hah?) registers */ 
	ulong 	ecx; 
	ulong	edx; 
	ulong	ebx; 
	ulong	esp; 
	ulong	ebp; 
	ulong	esi; 
	ulong	edi; 
	ulong	es;		/* segment selectors */ 
	ulong	cs; 
	ulong	ss; 
	ulong	ds; 
	ulong	fs; 
	ulong	gs; 
	ulong	ldt;		/* local descriptor table */ 
	ulong	iomap;		/* io map base */ 
}; 
 
/* 
1991/0613    
 *  global descriptor table describing all segments 
 */ 
Segdesc gdt[1024] = 
1991/0613/sys/src/9/pc/mmu.c:16,201991/0625/sys/src/9/pc/mmu.c:91,94
1991/0613    
[UESEG]		EXECSEG(3),		/* user code */ 
[UDSEG]		DATASEG(3),		/* user data/stack */ 
[SYSGATE]	CALLGATE(KESEG, syscall, 3),	/* call gate for system calls */ 
		{ 0, 0},		/* the rest */ 
}; 
1991/0625/sys/src/9/pc/mmu.c:14,331991/0627/sys/src/9/pc/mmu.c:14,19 (short | long)
1991/0625    
	ulong	d0; 
	ulong	d1; 
}; 
#define SEGDATA	(0x10<<8)	/* data/stack segment */ 
#define SEGEXEC	(0x18<<8)	/* executable segment */ 
#define SEGCG	(0x0C<<8)	/* call gate */ 
#define	SEGIG	(0x0E<<8)	/* interrupt gate */ 
#define SEGTG	(0x0F<<8)	/* task gate */ 
                 
#define SEGP	(1<<15)		/* segment present */ 
#define SEGPL(x) ((x)<<13)	/* priority level */ 
#define SEGB	(1<<22)		/* granularity 1==4k (for expand-down) */ 
#define SEGG	(1<<23)		/* granularity 1==4k (for other) */ 
#define SEGE	(1<<10)		/* expand down */ 
#define SEGW	(1<<9)		/* writable (for data/stack) */ 
#define	SEGR	(1<<9)		/* readable (for code) */ 
#define SEGD	(1<<22)		/* default 1==32bit (for code) */ 
 
/* 
 *  gate initializers 
1991/0627/sys/src/9/pc/mmu.c:6,341991/0703/sys/src/9/pc/mmu.c:6,11 (short | long)
1991/0612    
#include	"io.h" 
 
1991/0613    
/* 
1991/0625    
 *  segment descriptor/gate 
 */ 
typedef struct Segdesc	Segdesc; 
struct Segdesc 
{ 
	ulong	d0; 
	ulong	d1; 
}; 
                 
/* 
 *  gate initializers 
 */ 
#define TRAPGATE(s,o,p)	{ (o)&0xFFFF0000|SEGP|SEGPL(p)|SEGTG, (o)&0xFFFF|((s)<<16) } 
#define INTRGATE(s,o,p)	{ (o)&0xFFFF0000|SEGP|SEGPL(p)|SEGIG, (o)&0xFFFF|((s)<<16) } 
#define CALLGATE(s,o,p)	{ (o)&0xFFFF0000|SEGP|SEGPL(p)|SEGCG, (o)&0xFFFF|((s)<<16) } 
                 
/* 
 *  segment descriptor initializers 
 */ 
#define	DATASEG(p) 	{ SEGG|SEGB|(0xF<<16)|SEGP|SEGPL(p)|SEGDATA|SEGW, 0xFFFF } 
#define	EXECSEG(p) 	{ SEGG|SEGD|(0xF<<16)|SEGP|SEGPL(p)|SEGEXEC|SEGR, 0xFFFF } 
                 
/* 
 *  task state segment.  Plan 9 ignores all the task switching goo and just 
 *  uses the tss for esp0 and ss0 on gate's into the kernel, interrupts, 
 *  and exceptions.  The rest is completely ignored. 
1991/0627/sys/src/9/pc/mmu.c:67,801991/0703/sys/src/9/pc/mmu.c:44,78
1991/0625    
}; 
 
/* 
1991/0703    
 *  segment descriptor initializers 
 */ 
#define	DATASEG(p) 	{ 0xFFFF, SEGG|SEGB|(0xF<<16)|SEGP|SEGPL(p)|SEGDATA|SEGW } 
#define	EXECSEG(p) 	{ 0xFFFF, SEGG|SEGD|(0xF<<16)|SEGP|SEGPL(p)|SEGEXEC|SEGR } 
#define CALLGATE(s,o,p)	{ (o)&0xFFFF|((s)<<16), (o)&0xFFFF0000|SEGP|SEGPL(p)|SEGCG } 
 
/* 
1991/0613    
 *  global descriptor table describing all segments 
 */ 
Segdesc gdt[1024] = 
1991/0703    
Segdesc gdt[6] = 
1991/0612    
{ 
1991/0613    
[NULLSEG]	{ 0, 0},		/* null descriptor */ 
[KESEG]		EXECSEG(0),		/* kernel code */ 
[KDSEG]		DATASEG(0),		/* kernel data/stack */ 
[UESEG]		EXECSEG(3),		/* user code */ 
1991/0703    
[KESEG]		EXECSEG(0),		/* kernel code */ 
1991/0613    
[UDSEG]		DATASEG(3),		/* user data/stack */ 
[SYSGATE]	CALLGATE(KESEG, syscall, 3),	/* call gate for system calls */ 
1991/0703    
[UESEG]		EXECSEG(3),		/* user code */ 
[SYSGATE]	CALLGATE(KESEL,0,3),	/* call gate for system calls */ 
1991/0613    
}; 
1991/0703    
 
void 
mmuinit(void) 
{ 
	gdt[SYSGATE].d0 = ((ulong)systrap)&0xFFFF|(KESEL<<16); 
	gdt[SYSGATE].d1 = ((ulong)systrap)&0xFFFF0000|SEGP|SEGPL(3)|SEGCG; 
	lgdt(gdt, sizeof gdt); 
} 
 
void 
systrap(void) 
{ 
	panic("system trap from user"); 
} 
1991/0703/sys/src/9/pc/mmu.c:49,591991/0706/sys/src/9/pc/mmu.c:49,61 (short | long)
1991/0703    
#define	DATASEG(p) 	{ 0xFFFF, SEGG|SEGB|(0xF<<16)|SEGP|SEGPL(p)|SEGDATA|SEGW } 
#define	EXECSEG(p) 	{ 0xFFFF, SEGG|SEGD|(0xF<<16)|SEGP|SEGPL(p)|SEGEXEC|SEGR } 
#define CALLGATE(s,o,p)	{ (o)&0xFFFF|((s)<<16), (o)&0xFFFF0000|SEGP|SEGPL(p)|SEGCG } 
1991/0706    
#define	D16SEG(p) 	{ 0xFFFF, (0x0<<16)|SEGP|SEGPL(p)|SEGDATA|SEGW } 
#define	E16SEG(p) 	{ 0xFFFF, (0x0<<16)|SEGP|SEGPL(p)|SEGEXEC|SEGR } 
1991/0703    
 
/* 
1991/0613    
 *  global descriptor table describing all segments 
 */ 
1991/0703    
Segdesc gdt[6] = 
1991/0706    
Segdesc gdt[] = 
1991/0612    
{ 
1991/0613    
[NULLSEG]	{ 0, 0},		/* null descriptor */ 
[KDSEG]		DATASEG(0),		/* kernel data/stack */ 
1991/0703/sys/src/9/pc/mmu.c:61,661991/0706/sys/src/9/pc/mmu.c:63,70
1991/0613    
[UDSEG]		DATASEG(3),		/* user data/stack */ 
1991/0703    
[UESEG]		EXECSEG(3),		/* user code */ 
[SYSGATE]	CALLGATE(KESEL,0,3),	/* call gate for system calls */ 
1991/0706    
[RDSEG]		D16SEG(0),		/* reboot data/stack */ 
[RESEG]		E16SEG(0),		/* reboot code */ 
1991/0613    
}; 
1991/0703    
 
void 
1991/0706/sys/src/9/pc/mmu.c:67,781991/0711/sys/src/9/pc/mmu.c:67,106 (short | long)
1991/0706    
[RESEG]		E16SEG(0),		/* reboot code */ 
1991/0613    
}; 
1991/0703    
 
1991/0711    
extern ulong tpt[]; 
 
1991/0703    
void 
mmuinit(void) 
{ 
1991/0711    
 
1991/0703    
	gdt[SYSGATE].d0 = ((ulong)systrap)&0xFFFF|(KESEL<<16); 
	gdt[SYSGATE].d1 = ((ulong)systrap)&0xFFFF0000|SEGP|SEGPL(3)|SEGCG; 
	lgdt(gdt, sizeof gdt); 
1991/0711    
} 
 
void 
mapstack(Proc *p) 
{ 
} 
 
void 
flushmmu(void) 
{ 
} 
 
void 
mmurelease(Proc *p) 
{ 
} 
 
void 
putmmu(ulong x, ulong y, Page*z) 
{ 
} 
 
void 
invalidateu(void) 
{ 
1991/0703    
} 
 
void 
1991/0711/sys/src/9/pc/mmu.c:72,811991/0716/sys/src/9/pc/mmu.c:72,91 (short | long)
1991/0703    
void 
mmuinit(void) 
{ 
1991/0711    
                 
1991/0716    
	/* 
	 *  set up the global descriptor table 
	 */ 
1991/0703    
	gdt[SYSGATE].d0 = ((ulong)systrap)&0xFFFF|(KESEL<<16); 
	gdt[SYSGATE].d1 = ((ulong)systrap)&0xFFFF0000|SEGP|SEGPL(3)|SEGCG; 
	lgdt(gdt, sizeof gdt); 
1991/0716    
 
	/* 
	 *  set up system page tables 
	 */ 
 
	/* 
	 *  set up the task segment 
	 */ 
1991/0711    
} 
 
void 
1991/0716/sys/src/9/pc/mmu.c:16,261991/0717/sys/src/9/pc/mmu.c:16,26 (short | long)
1991/0625    
struct Tss 
{ 
	ulong	backlink;	/* unused */ 
	ulong	esp0;		/* pl0 stack pointer */ 
1991/0717    
	ulong	sp0;		/* pl0 stack pointer */ 
1991/0625    
	ulong	ss0;		/* pl0 stack selector */ 
	ulong	esp1;		/* pl1 stack pointer */ 
1991/0717    
	ulong	sp1;		/* pl1 stack pointer */ 
1991/0625    
	ulong	ss1;		/* pl1 stack selector */ 
	ulong	esp2;		/* pl2 stack pointer */ 
1991/0717    
	ulong	sp2;		/* pl2 stack pointer */ 
1991/0625    
	ulong	ss2;		/* pl2 stack selector */ 
	ulong	cr3;		/* page table descriptor */ 
	ulong	eip;		/* instruction pointer */ 
1991/0716/sys/src/9/pc/mmu.c:42,561991/0717/sys/src/9/pc/mmu.c:42,59
1991/0625    
	ulong	ldt;		/* local descriptor table */ 
	ulong	iomap;		/* io map base */ 
}; 
1991/0717    
Tss tss; 
1991/0625    
 
/* 
1991/0703    
 *  segment descriptor initializers 
 */ 
#define	DATASEG(p) 	{ 0xFFFF, SEGG|SEGB|(0xF<<16)|SEGP|SEGPL(p)|SEGDATA|SEGW } 
#define	EXECSEG(p) 	{ 0xFFFF, SEGG|SEGD|(0xF<<16)|SEGP|SEGPL(p)|SEGEXEC|SEGR } 
#define CALLGATE(s,o,p)	{ (o)&0xFFFF|((s)<<16), (o)&0xFFFF0000|SEGP|SEGPL(p)|SEGCG } 
1991/0706    
#define	D16SEG(p) 	{ 0xFFFF, (0x0<<16)|SEGP|SEGPL(p)|SEGDATA|SEGW } 
#define	E16SEG(p) 	{ 0xFFFF, (0x0<<16)|SEGP|SEGPL(p)|SEGEXEC|SEGR } 
1991/0717    
#define	DATASEGM(p) 	{ 0xFFFF, SEGG|SEGB|(0xF<<16)|SEGP|SEGPL(p)|SEGDATA|SEGW } 
#define	EXECSEGM(p) 	{ 0xFFFF, SEGG|SEGD|(0xF<<16)|SEGP|SEGPL(p)|SEGEXEC|SEGR } 
#define CALLGATE(s,o,p)	{ ((o)&0xFFFF)|((s)<<16), (o)&0xFFFF0000|SEGP|SEGPL(p)|SEGCG } 
#define	D16SEGM(p) 	{ 0xFFFF, (0x0<<16)|SEGP|SEGPL(p)|SEGDATA|SEGW } 
#define	E16SEGM(p) 	{ 0xFFFF, (0x0<<16)|SEGP|SEGPL(p)|SEGEXEC|SEGR } 
#define	TSSSEGM(b,p)	{ ((b)<<16)|sizeof(Tss),\ 
			  ((b)&0xFF000000)|(((b)<<16)&0xFF)|SEGTSS|SEGPL(p)|SEGP } 
1991/0703    
 
/* 
1991/0613    
 *  global descriptor table describing all segments 
1991/0716/sys/src/9/pc/mmu.c:58,961991/0717/sys/src/9/pc/mmu.c:61,145
1991/0706    
Segdesc gdt[] = 
1991/0612    
{ 
1991/0613    
[NULLSEG]	{ 0, 0},		/* null descriptor */ 
[KDSEG]		DATASEG(0),		/* kernel data/stack */ 
1991/0703    
[KESEG]		EXECSEG(0),		/* kernel code */ 
1991/0613    
[UDSEG]		DATASEG(3),		/* user data/stack */ 
1991/0703    
[UESEG]		EXECSEG(3),		/* user code */ 
1991/0717    
[KDSEG]		DATASEGM(0),		/* kernel data/stack */ 
[KESEG]		EXECSEGM(0),		/* kernel code */ 
[UDSEG]		DATASEGM(3),		/* user data/stack */ 
[UESEG]		EXECSEGM(3),		/* user code */ 
1991/0703    
[SYSGATE]	CALLGATE(KESEL,0,3),	/* call gate for system calls */ 
1991/0706    
[RDSEG]		D16SEG(0),		/* reboot data/stack */ 
[RESEG]		E16SEG(0),		/* reboot code */ 
1991/0717    
[RDSEG]		D16SEGM(0),		/* reboot data/stack */ 
[RESEG]		E16SEGM(0),		/* reboot code */ 
[TSSSEG]	TSSSEGM(0,0),		/* tss segment */ 
1991/0613    
}; 
1991/0703    
 
1991/0711    
extern ulong tpt[]; 
1991/0717    
static ulong	*toppt;		/* top level page table */	 
static ulong	*kpt;		/* kernel level page tables */ 
static ulong	*upt;		/* page table for struct User */ 
1991/0711    
 
1991/0717    
#define ROUNDUP(s,v)	(((s)+(v-1))&~(v-1)) 
 
1991/0703    
void 
mmuinit(void) 
{ 
1991/0717    
	int i, n, nkpt; 
	ulong x; 
	ulong y; 
 
1991/0716    
	/* 
	 *  set up the global descriptor table 
	 */ 
1991/0703    
	gdt[SYSGATE].d0 = ((ulong)systrap)&0xFFFF|(KESEL<<16); 
	gdt[SYSGATE].d1 = ((ulong)systrap)&0xFFFF0000|SEGP|SEGPL(3)|SEGCG; 
1991/0717    
	x = (ulong)systrap; 
	gdt[SYSGATE].d0 = (x&0xFFFF)|(KESEL<<16); 
	gdt[SYSGATE].d1 = (x&0xFFFF0000)|SEGP|SEGPL(3)|SEGCG; 
	x = (long)&tss; 
	gdt[TSSSEG].d0 = (x<<16)|sizeof(Tss); 
	gdt[TSSSEG].d1 = (x&0xFF000000)|((x>>16)&0xFF)|SEGTSS|SEGPL(0)|SEGP; 
1991/0703    
	lgdt(gdt, sizeof gdt); 
1991/0716    
 
	/* 
	 *  set up system page tables 
1991/0717    
	 *  set up system page tables. 
	 *  map all of physical memory to start at KZERO. 
	 *  leave a map for a user area. 
1991/0716    
	 */ 
 
1991/0717    
	/*  allocate and fill low level page tables for physical mem */ 
	nkpt = ROUNDUP(conf.npage0+conf.npage1, 4*1024*1024); 
	nkpt = nkpt/(4*1024*1024); 
	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; 
	} 
 
	/*  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); 
	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); 
	y = ((ulong)upt)&~KZERO; 
	toppt[x] = y|PTEVALID|PTEKERNEL|PTEWRITE; 
	lcr3(((ulong)toppt)&~KZERO); 
 
1991/0716    
	/* 
	 *  set up the task segment 
	 */ 
1991/0717    
	tss.sp0 = USERADDR; 
	tss.ss0 = KDSEL; 
	tss.cr3 = (ulong)toppt; 
	ltr(TSSSEL); 
1991/0711    
} 
 
void 
mapstack(Proc *p) 
{ 
1991/0717    
	 
1991/0711    
} 
 
void 
1991/0716/sys/src/9/pc/mmu.c:104,1101991/0717/sys/src/9/pc/mmu.c:153,159
1991/0711    
} 
 
void 
putmmu(ulong x, ulong y, Page*z) 
1991/0717    
putmmu(ulong x, ulong y, Page *z) 
1991/0711    
{ 
} 
 
1991/0716/sys/src/9/pc/mmu.c:117,1201991/0717/sys/src/9/pc/mmu.c:166,181
1991/0703    
systrap(void) 
{ 
	panic("system trap from user"); 
1991/0717    
} 
 
void 
exit(void) 
{ 
	int i; 
 
	u = 0; 
	print("exiting\n"); 
	for(i = 0; i < WD2PG; i++) 
		toppt[i] = 0; 
	lcr3(((ulong)toppt)&~KZERO); 
1991/0703    
} 
1991/0717/sys/src/9/pc/mmu.c:76,821991/0718/sys/src/9/pc/mmu.c:76,93 (short | long)
1991/0717    
static ulong	*upt;		/* page table for struct User */ 
1991/0711    
 
1991/0717    
#define ROUNDUP(s,v)	(((s)+(v-1))&~(v-1)) 
1991/0718    
/* 
 *  offset of virtual address into 
 *  top level page table 
 */ 
#define TOPOFF(v)	((v)>>(2*PGSHIFT-2)) 
1991/0717    
 
1991/0718    
/* 
 *  offset of virtual address into 
 *  bottom level page table 
 */ 
#define BTMOFF(v)	(((v)>>(PGSHIFT))&(BY2PG-1)) 
 
1991/0703    
void 
mmuinit(void) 
{ 
1991/0717/sys/src/9/pc/mmu.c:90,991991/0718/sys/src/9/pc/mmu.c:101,110
1991/0717    
	x = (ulong)systrap; 
	gdt[SYSGATE].d0 = (x&0xFFFF)|(KESEL<<16); 
	gdt[SYSGATE].d1 = (x&0xFFFF0000)|SEGP|SEGPL(3)|SEGCG; 
	x = (long)&tss; 
1991/0718    
	x = (ulong)&tss; 
1991/0717    
	gdt[TSSSEG].d0 = (x<<16)|sizeof(Tss); 
	gdt[TSSSEG].d1 = (x&0xFF000000)|((x>>16)&0xFF)|SEGTSS|SEGPL(0)|SEGP; 
1991/0703    
	lgdt(gdt, sizeof gdt); 
1991/0718    
	putgdt(gdt, sizeof gdt); 
1991/0716    
 
	/* 
1991/0717    
	 *  set up system page tables. 
1991/0717/sys/src/9/pc/mmu.c:107,1151991/0718/sys/src/9/pc/mmu.c:118,125
1991/0717    
	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; 
	} 
1991/0718    
	for(i = 0; i < n; i++) 
		kpt[i] = (i<<PGSHIFT) | PTEVALID | PTEKERNEL | PTEWRITE; 
1991/0717    
 
	/*  allocate page table for u-> */ 
	upt = ialloc(BY2PG, 1); 
1991/0717/sys/src/9/pc/mmu.c:116,1651991/0718/sys/src/9/pc/mmu.c:126,259
1991/0717    
 
	/*  allocate top level table and put pointers to lower tables in it */ 
	toppt = ialloc(BY2PG, 1); 
	x = KZERO>>(2*PGSHIFT-2); 
1991/0718    
	x = TOPOFF(KZERO); 
1991/0717    
	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); 
1991/0718    
	for(i = 0; i < nkpt; i++) 
		toppt[x+i] = (y+i*BY2PG) | PTEVALID | PTEKERNEL | PTEWRITE; 
	x = TOPOFF(USERADDR); 
1991/0717    
	y = ((ulong)upt)&~KZERO; 
	toppt[x] = y|PTEVALID|PTEKERNEL|PTEWRITE; 
	lcr3(((ulong)toppt)&~KZERO); 
1991/0718    
	toppt[x] = y | PTEVALID | PTEKERNEL | PTEWRITE; 
	putcr3(((ulong)toppt)&~KZERO); 
1991/0717    
 
1991/0716    
	/* 
	 *  set up the task segment 
	 */ 
1991/0717    
	tss.sp0 = USERADDR; 
1991/0718    
	tss.sp0 = USERADDR+BY2PG; 
1991/0717    
	tss.ss0 = KDSEL; 
	tss.cr3 = (ulong)toppt; 
	ltr(TSSSEL); 
1991/0718    
	puttr(TSSSEL); 
1991/0711    
} 
 
void 
mapstack(Proc *p) 
{ 
1991/0717    
	                 
1991/0718    
	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; 
1991/0711    
} 
 
void 
flushmmu(void) 
{ 
1991/0718    
	int s; 
 
	if(u == 0) 
		return; 
 
	u->p->mmuvalid = 0; 
	s = splhi(); 
	mapstack(u->p); 
	splx(s); 
1991/0711    
} 
 
void 
mmurelease(Proc *p) 
{ 
1991/0718    
	p->mmuvalid = 0; 
1991/0711    
} 
 
void 
1991/0717    
putmmu(ulong x, ulong y, Page *z) 
1991/0718    
putmmu(ulong va, ulong pa, Page *pg) 
1991/0711    
{ 
1991/0718    
	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); 
1991/0711    
} 
 
void 
invalidateu(void) 
{ 
1991/0718    
	/* unmap u area */ 
	upt[0] = 0; 
 
	/* flush cached mmu entries */ 
	putcr3(((ulong)toppt)&~KZERO); 
1991/0703    
} 
 
void 
1991/0717/sys/src/9/pc/mmu.c:177,1811991/0718/sys/src/9/pc/mmu.c:271,275
1991/0717    
	print("exiting\n"); 
	for(i = 0; i < WD2PG; i++) 
		toppt[i] = 0; 
	lcr3(((ulong)toppt)&~KZERO); 
1991/0718    
	putcr3(((ulong)toppt)&~KZERO); 
1991/0703    
} 
1991/0718/sys/src/9/pc/mmu.c:66,731991/0719/sys/src/9/pc/mmu.c:66,71 (short | long)
1991/0717    
[UDSEG]		DATASEGM(3),		/* user data/stack */ 
[UESEG]		EXECSEGM(3),		/* user code */ 
1991/0703    
[SYSGATE]	CALLGATE(KESEL,0,3),	/* call gate for system calls */ 
1991/0717    
[RDSEG]		D16SEGM(0),		/* reboot data/stack */ 
[RESEG]		E16SEGM(0),		/* reboot code */ 
[TSSSEG]	TSSSEGM(0,0),		/* tss segment */ 
1991/0613    
}; 
1991/0703    
 
1991/0718/sys/src/9/pc/mmu.c:86,941991/0719/sys/src/9/pc/mmu.c:84,105
1991/0718    
 *  offset of virtual address into 
 *  bottom level page table 
 */ 
#define BTMOFF(v)	(((v)>>(PGSHIFT))&(BY2PG-1)) 
1991/0719    
#define BTMOFF(v)	(((v)>>(PGSHIFT))&(WD2PG-1)) 
1991/0718    
 
1991/0703    
void 
1991/0719    
mmudump(void) 
{ 
	int i; 
	ulong *z; 
	z = (ulong*)gdt; 
	for(i = 0; i < sizeof(gdt)/4; i+=2) 
		print("%8.8lux %8.8lux\n", *z++, *z++); 
	print("UESEL %lux UDSEL %lux\n", UESEL, UDSEL); 
	print("KESEL %lux KDSEL %lux\n", KESEL, KDSEL); 
	panic("done"); 
} 
 
void 
1991/0703    
mmuinit(void) 
{ 
1991/0717    
	int i, n, nkpt; 
1991/0718/sys/src/9/pc/mmu.c:112,1231991/0719/sys/src/9/pc/mmu.c:123,133
1991/0717    
	 *  leave a map for a user area. 
1991/0716    
	 */ 
 
1991/0717    
	/*  allocate and fill low level page tables for physical mem */ 
	nkpt = ROUNDUP(conf.npage0+conf.npage1, 4*1024*1024); 
	nkpt = nkpt/(4*1024*1024); 
1991/0719    
	/*  allocate and fill low level page tables for kernel mem */ 
	nkpt = ROUNDUP(conf.npage, 4*1024); 
	nkpt = nkpt/(4*1024); 
1991/0717    
	kpt = ialloc(nkpt*BY2PG, 1); 
	n = ROUNDUP(conf.npage0+conf.npage1, 1*1024*1024); 
	n = n/(4*1024); 
1991/0719    
	n = ROUNDUP(conf.npage, 1024); 
1991/0718    
	for(i = 0; i < n; i++) 
		kpt[i] = (i<<PGSHIFT) | PTEVALID | PTEKERNEL | PTEWRITE; 
1991/0717    
 
1991/0718/sys/src/9/pc/mmu.c:150,1571991/0719/sys/src/9/pc/mmu.c:160,165
1991/0718    
	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); 
 
1991/0718/sys/src/9/pc/mmu.c:210,2161991/0719/sys/src/9/pc/mmu.c:218,224
1991/0718    
	Proc *p; 
	int i; 
 
print("putmmu %lux %lux USTKTOP %lux\n", va, pa, USTKTOP); /**/ 
1991/0719    
print("putmmu %lux %lux\n", va, pa); /**/ 
1991/0718    
	if(u==0) 
		panic("putmmu"); 
	p = u->p; 
1991/0718/sys/src/9/pc/mmu.c:232,2391991/0719/sys/src/9/pc/mmu.c:240,248
1991/0718    
	pg = p->mmu[i]; 
	if(pg == 0){ 
		pg = p->mmu[i] = newpage(1, 0, 0); 
		p->mmue[i] = PPN(pg->pa) | PTEVALID | PTEKERNEL | PTEWRITE; 
1991/0719    
		p->mmue[i] = PPN(pg->pa) | PTEVALID | PTEUSER | PTEWRITE; 
1991/0718    
		toppt[topoff] = p->mmue[i]; 
1991/0719    
print("toppt[%d] = %lux\n", topoff, p->mmue[i]); 
1991/0718    
	} 
 
	/* 
1991/0718/sys/src/9/pc/mmu.c:241,2461991/0719/sys/src/9/pc/mmu.c:250,256
1991/0718    
	 */ 
	pt = (ulong*)(p->mmu[i]->pa|KZERO); 
	pt[BTMOFF(va)] = pa | PTEUSER; 
1991/0719    
print("%lux[%d] = %lux\n", pt, BTMOFF(va), pa | PTEUSER); 
1991/0718    
 
	/* flush cached mmu entries */ 
	putcr3(((ulong)toppt)&~KZERO); 
1991/0718/sys/src/9/pc/mmu.c:260,2751991/0719/sys/src/9/pc/mmu.c:270,273
1991/0703    
systrap(void) 
{ 
	panic("system trap from user"); 
1991/0717    
} 
                 
void 
exit(void) 
{ 
	int i; 
                 
	u = 0; 
	print("exiting\n"); 
	for(i = 0; i < WD2PG; i++) 
		toppt[i] = 0; 
1991/0718    
	putcr3(((ulong)toppt)&~KZERO); 
1991/0703    
} 
1991/0719/sys/src/9/pc/mmu.c:242,2561991/0720/sys/src/9/pc/mmu.c:242,257 (short | long)
1991/0718    
		pg = p->mmu[i] = newpage(1, 0, 0); 
1991/0719    
		p->mmue[i] = PPN(pg->pa) | PTEVALID | PTEUSER | PTEWRITE; 
1991/0718    
		toppt[topoff] = p->mmue[i]; 
1991/0719    
print("toppt[%d] = %lux\n", topoff, p->mmue[i]); 
1991/0720    
print("toppt[%d] = %lux\n", topoff, toppt[topoff]); 
1991/0718    
	} 
 
	/* 
	 *  fill in the bottom level page table 
	 */ 
1991/0720    
print("%lux[%d] was %lux\n", pt, BTMOFF(va), pt[BTMOFF(va)]); 
1991/0718    
	pt = (ulong*)(p->mmu[i]->pa|KZERO); 
	pt[BTMOFF(va)] = pa | PTEUSER; 
1991/0719    
print("%lux[%d] = %lux\n", pt, BTMOFF(va), pa | PTEUSER); 
1991/0720    
print("%lux[%d] now %lux\n", pt, BTMOFF(va), pt[BTMOFF(va)]); 
1991/0718    
 
	/* flush cached mmu entries */ 
	putcr3(((ulong)toppt)&~KZERO); 
1991/0720/sys/src/9/pc/mmu.c:178,1851991/0723/sys/src/9/pc/mmu.c:178,185 (short | long)
1991/0718    
	/* 
	 *  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)); 
1991/0723    
	memmove(toppt, p->mmue, MAXMMU*sizeof(ulong)); 
	memmove(&toppt[TOPOFF(USTKBTM)], &p->mmue[MAXMMU], MAXSMMU*sizeof(ulong)); 
1991/0718    
 
	/* map in u area */ 
	upt[0] = PPN(p->upage->pa) | PTEVALID | PTEKERNEL | PTEWRITE; 
1991/0720/sys/src/9/pc/mmu.c:216,2221991/0723/sys/src/9/pc/mmu.c:216,222
1991/0718    
	int topoff; 
	ulong *pt; 
	Proc *p; 
	int i; 
1991/0723    
	int i = 0; 
1991/0718    
 
1991/0719    
print("putmmu %lux %lux\n", va, pa); /**/ 
1991/0718    
	if(u==0) 
1991/0720/sys/src/9/pc/mmu.c:238,2551991/0723/sys/src/9/pc/mmu.c:238,256
1991/0718    
	 *  if bottom level page table missing, allocate one 
	 */ 
	pg = p->mmu[i]; 
1991/0723    
print("toppt[%d] was %lux\n", topoff, toppt[topoff]); 
1991/0718    
	if(pg == 0){ 
		pg = p->mmu[i] = newpage(1, 0, 0); 
1991/0719    
		p->mmue[i] = PPN(pg->pa) | PTEVALID | PTEUSER | PTEWRITE; 
1991/0718    
		toppt[topoff] = p->mmue[i]; 
1991/0720    
print("toppt[%d] = %lux\n", topoff, toppt[topoff]); 
1991/0723    
print("toppt[%d] now %lux\n", topoff, toppt[topoff]); 
1991/0718    
	} 
 
	/* 
	 *  fill in the bottom level page table 
	 */ 
1991/0720    
print("%lux[%d] was %lux\n", pt, BTMOFF(va), pt[BTMOFF(va)]); 
1991/0718    
	pt = (ulong*)(p->mmu[i]->pa|KZERO); 
1991/0723    
print("%lux[%d] was %lux\n", pt, BTMOFF(va), pt[BTMOFF(va)]); 
1991/0718    
	pt[BTMOFF(va)] = pa | PTEUSER; 
1991/0720    
print("%lux[%d] now %lux\n", pt, BTMOFF(va), pt[BTMOFF(va)]); 
1991/0718    
 
1991/0723/sys/src/9/pc/mmu.c:218,2241991/0801/sys/src/9/pc/mmu.c:218,224 (short | long)
1991/0718    
	Proc *p; 
1991/0723    
	int i = 0; 
1991/0718    
 
1991/0719    
print("putmmu %lux %lux\n", va, pa); /**/ 
1991/0801    
/*print("putmmu %lux %lux\n", va, pa); /**/ 
1991/0718    
	if(u==0) 
		panic("putmmu"); 
	p = u->p; 
1991/0723/sys/src/9/pc/mmu.c:238,2491991/0801/sys/src/9/pc/mmu.c:238,249
1991/0718    
	 *  if bottom level page table missing, allocate one 
	 */ 
	pg = p->mmu[i]; 
1991/0723    
print("toppt[%d] was %lux\n", topoff, toppt[topoff]); 
1991/0801    
/*print("toppt[%d] was %lux\n", topoff, toppt[topoff]);/**/ 
1991/0718    
	if(pg == 0){ 
		pg = p->mmu[i] = newpage(1, 0, 0); 
1991/0719    
		p->mmue[i] = PPN(pg->pa) | PTEVALID | PTEUSER | PTEWRITE; 
1991/0718    
		toppt[topoff] = p->mmue[i]; 
1991/0723    
print("toppt[%d] now %lux\n", topoff, toppt[topoff]); 
1991/0801    
/*print("toppt[%d] now %lux\n", topoff, toppt[topoff]);/**/ 
1991/0718    
	} 
 
	/* 
1991/0723/sys/src/9/pc/mmu.c:250,2581991/0801/sys/src/9/pc/mmu.c:250,258
1991/0718    
	 *  fill in the bottom level page table 
	 */ 
	pt = (ulong*)(p->mmu[i]->pa|KZERO); 
1991/0723    
print("%lux[%d] was %lux\n", pt, BTMOFF(va), pt[BTMOFF(va)]); 
1991/0801    
/*print("%lux[%d] was %lux\n", pt, BTMOFF(va), pt[BTMOFF(va)]);/**/ 
1991/0718    
	pt[BTMOFF(va)] = pa | PTEUSER; 
1991/0720    
print("%lux[%d] now %lux\n", pt, BTMOFF(va), pt[BTMOFF(va)]); 
1991/0801    
/*print("%lux[%d] now %lux\n", pt, BTMOFF(va), pt[BTMOFF(va)]);/**/ 
1991/0718    
 
	/* flush cached mmu entries */ 
	putcr3(((ulong)toppt)&~KZERO); 
1991/0801/sys/src/9/pc/mmu.c:102,1081991/0821/sys/src/9/pc/mmu.c:102,108 (short | long)
1991/0719    
void 
1991/0703    
mmuinit(void) 
{ 
1991/0717    
	int i, n, nkpt; 
1991/0821    
	int i, nkpt, npage, nbytes; 
1991/0717    
	ulong x; 
	ulong y; 
 
1991/0801/sys/src/9/pc/mmu.c:124,1351991/0821/sys/src/9/pc/mmu.c:124,137
1991/0716    
	 */ 
 
1991/0719    
	/*  allocate and fill low level page tables for kernel mem */ 
	nkpt = ROUNDUP(conf.npage, 4*1024); 
	nkpt = nkpt/(4*1024); 
1991/0717    
	kpt = ialloc(nkpt*BY2PG, 1); 
1991/0719    
	n = ROUNDUP(conf.npage, 1024); 
1991/0718    
	for(i = 0; i < n; i++) 
1991/0821    
	npage = (1024*1024)/BY2PG + conf.npage1; 
	nbytes = PGROUND(npage*BY2WD);		/* words of page map */ 
	nkpt = nbytes/BY2PG;			/* pages of page map */ 
	kpt = ialloc(nbytes, 1); 
	for(i = 0; i < npage; i++) 
1991/0718    
		kpt[i] = (i<<PGSHIFT) | PTEVALID | PTEKERNEL | PTEWRITE; 
1991/0821    
 
print("%d low level pte's, %d high level pte's\n", npage, nkpt); 
1991/0717    
 
	/*  allocate page table for u-> */ 
	upt = ialloc(BY2PG, 1); 
1991/0821/sys/src/9/pc/mmu.c:124,1301991/0827/sys/src/9/pc/mmu.c:124,130 (short | long)
1991/0716    
	 */ 
 
1991/0719    
	/*  allocate and fill low level page tables for kernel mem */ 
1991/0821    
	npage = (1024*1024)/BY2PG + conf.npage1; 
1991/0827    
	npage = conf.base1/BY2PG + conf.npage1; 
1991/0821    
	nbytes = PGROUND(npage*BY2WD);		/* words of page map */ 
	nkpt = nbytes/BY2PG;			/* pages of page map */ 
	kpt = ialloc(nbytes, 1); 
1991/0827/sys/src/9/pc/mmu.c:69,741991/0922/sys/src/9/pc/mmu.c:69,77 (short | long)
1991/0717    
[TSSSEG]	TSSSEGM(0,0),		/* tss segment */ 
1991/0613    
}; 
1991/0703    
 
1991/0922    
static ulong	*ktoppt;	/* prototype top level page table 
				 * containing kernel mappings 
				 */ 
1991/0717    
static ulong	*toppt;		/* top level page table */	 
static ulong	*kpt;		/* kernel level page tables */ 
static ulong	*upt;		/* page table for struct User */ 
1991/0922/sys/src/9/pc/mmu.c:165,1711991/0928/sys/src/9/pc/mmu.c:165,171 (short | long)
1991/0718    
	ulong tlbphys; 
	int i; 
 
	if(p->upage->va != (USERADDR|(p->pid&0xFFFF))) 
1991/0928    
	if(p->upage->va != (USERADDR|(p->pid&0xFFFF)) && p->pid != 0) 
1991/0718    
		panic("mapstack %d 0x%lux 0x%lux", p->pid, p->upage->pa, p->upage->va); 
 
	/* 
1991/0928/sys/src/9/pc/mmu.c:159,1641991/1003/sys/src/9/pc/mmu.c:159,165 (short | long)
1991/0718    
	puttr(TSSSEL); 
1991/0711    
} 
 
1991/1003    
 
1991/0711    
void 
mapstack(Proc *p) 
{ 
1991/1003/sys/src/9/pc/mmu.c:69,801991/1004/sys/src/9/pc/mmu.c:69,78 (short | long)
1991/0717    
[TSSSEG]	TSSSEGM(0,0),		/* tss segment */ 
1991/0613    
}; 
1991/0703    
 
1991/0922    
static ulong	*ktoppt;	/* prototype top level page table 
				 * containing kernel mappings 
				 */ 
1991/0717    
static ulong	*toppt;		/* top level page table */	 
static ulong	*kpt;		/* kernel level page tables */ 
static ulong	*upt;		/* page table for struct User */ 
1991/1004    
static Page	ktoppg;		/* prototype top level page table 
				 * containing kernel mappings  */ 
static ulong	*kpt;		/* 2nd level page tables for kernel mem */ 
static ulong	*upt;		/* 2nd level page table for struct User */ 
1991/0711    
 
1991/0717    
#define ROUNDUP(s,v)	(((s)+(v-1))&~(v-1)) 
1991/0718    
/* 
1991/1003/sys/src/9/pc/mmu.c:102,1071991/1004/sys/src/9/pc/mmu.c:100,111
1991/0719    
	panic("done"); 
} 
 
1991/1004    
/* 
 *  Create a prototype page map that maps all of memory into 
 *  kernel (KZERO) space.  This is the default map.  It is used 
 *  whenever the processor not running a process or whenever running 
 *  a process which does not yet have its own map. 
 */ 
1991/0719    
void 
1991/0703    
mmuinit(void) 
{ 
1991/1003/sys/src/9/pc/mmu.c:108,1131991/1004/sys/src/9/pc/mmu.c:112,118
1991/0821    
	int i, nkpt, npage, nbytes; 
1991/0717    
	ulong x; 
	ulong y; 
1991/1004    
	ulong *top; 
1991/0717    
 
1991/0716    
	/* 
	 *  set up the global descriptor table 
1991/1003/sys/src/9/pc/mmu.c:123,1291991/1004/sys/src/9/pc/mmu.c:128,134
1991/0716    
	/* 
1991/0717    
	 *  set up system page tables. 
	 *  map all of physical memory to start at KZERO. 
	 *  leave a map for a user area. 
1991/1004    
	 *  leave a map entry for a user area. 
1991/0716    
	 */ 
 
1991/0719    
	/*  allocate and fill low level page tables for kernel mem */ 
1991/1003/sys/src/9/pc/mmu.c:140,1541991/1004/sys/src/9/pc/mmu.c:145,161
1991/0717    
	upt = ialloc(BY2PG, 1); 
 
	/*  allocate top level table and put pointers to lower tables in it */ 
	toppt = ialloc(BY2PG, 1); 
1991/1004    
	top = ialloc(BY2PG, 1); 
	ktoppg.va = (ulong)top; 
	ktoppg.pa = ktoppg.va & ~KZERO; 
1991/0718    
	x = TOPOFF(KZERO); 
1991/0717    
	y = ((ulong)kpt)&~KZERO; 
1991/0718    
	for(i = 0; i < nkpt; i++) 
		toppt[x+i] = (y+i*BY2PG) | PTEVALID | PTEKERNEL | PTEWRITE; 
1991/1004    
		top[x+i] = (y+i*BY2PG) | PTEVALID | PTEKERNEL | PTEWRITE; 
1991/0718    
	x = TOPOFF(USERADDR); 
1991/0717    
	y = ((ulong)upt)&~KZERO; 
1991/0718    
	toppt[x] = y | PTEVALID | PTEKERNEL | PTEWRITE; 
	putcr3(((ulong)toppt)&~KZERO); 
1991/1004    
	top[x] = y | PTEVALID | PTEKERNEL | PTEWRITE; 
	putcr3(ktoppg.pa); 
1991/0717    
 
1991/0716    
	/* 
	 *  set up the task segment 
1991/1003/sys/src/9/pc/mmu.c:155,2671991/1004/sys/src/9/pc/mmu.c:162,343
1991/0716    
	 */ 
1991/0718    
	tss.sp0 = USERADDR+BY2PG; 
1991/0717    
	tss.ss0 = KDSEL; 
	tss.cr3 = (ulong)toppt; 
1991/1004    
	tss.cr3 = ktoppg.pa; 
1991/0718    
	puttr(TSSSEL); 
1991/0711    
} 
 
1991/1004    
/* 
 *  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; 
1991/1003    
 
1991/1004    
	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 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. 
 */ 
1991/0711    
void 
1991/1004    
flushmmu(void) 
{ 
	int s; 
	Proc *p; 
	Page *pg; 
 
	if(u == 0) 
		return; 
 
	p = u->p; 
	s = splhi(); 
	if(p->mmutop){ 
		p->mmutop->next = p->mmufree; 
		p->mmufree = p->mmutop; 
		for(pg = p->mmufree; pg->next; pg = pg->next) 
			; 
		pg->next = p->mmuused; 
		p->mmutop = 0; 
		p->mmuused = 0; 
	} 
	mapstack(u->p); 
	splx(s); 
} 
 
/* 
 *  Switch to a process's memory map.  If the process doesn't 
 *  have a map yet, just use the prototype one that contains 
 *  mappings for only the kernel and the User struct. 
 */ 
void 
1991/0711    
mapstack(Proc *p) 
{ 
1991/0718    
	ulong tlbphys; 
	int i; 
1991/1004    
	Page *pg; 
1991/0718    
 
1991/0928    
	if(p->upage->va != (USERADDR|(p->pid&0xFFFF)) && p->pid != 0) 
1991/0718    
		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; 
	} 
1991/1004    
	if(p->mmutop) 
		pg = p->mmutop; 
	else 
		pg = &ktoppg; 
1991/0718    
 
	/* 
	 *  point top level page table to bottom level ones 
	 */ 
1991/0723    
	memmove(toppt, p->mmue, MAXMMU*sizeof(ulong)); 
	memmove(&toppt[TOPOFF(USTKBTM)], &p->mmue[MAXMMU], MAXSMMU*sizeof(ulong)); 
1991/0718    
                 
	/* map in u area */ 
	upt[0] = PPN(p->upage->pa) | PTEVALID | PTEKERNEL | PTEWRITE; 
 
	/* flush cached mmu entries */ 
	putcr3(((ulong)toppt)&~KZERO); 
1991/1004    
	/* tell processor about new page table (flushes cached entries) */ 
	putcr3(pg->pa); 
1991/0718    
 
	u = (User*)USERADDR; 
1991/0711    
} 
 
1991/1004    
/* 
 *  give all page table pages back to the free pool.  This is called in sched() 
 *  with palloc locked. 
 */ 
1991/0711    
void 
flushmmu(void) 
1991/1004    
mmurelease(Proc *p) 
1991/0711    
{ 
1991/0718    
	int s; 
1991/1004    
	Page *pg; 
	Page *next; 
1991/0718    
 
	if(u == 0) 
		return; 
1991/1004    
	/* point 386 to protoype page map */ 
	putcr3(ktoppg.pa); 
1991/0718    
 
	u->p->mmuvalid = 0; 
	s = splhi(); 
	mapstack(u->p); 
	splx(s); 
1991/1004    
	/* give away page table pages */ 
	for(pg = p->mmufree; pg; pg = next){ 
		next = pg->next; 
		simpleputpage(pg); 
	} 
	p->mmufree = 0; 
	for(pg = p->mmuused; pg; pg = next){ 
		next = pg->next; 
		simpleputpage(pg); 
	} 
	p->mmuused = 0; 
	if(p->mmutop) 
		simpleputpage(p->mmutop); 
	p->mmutop = 0; 
1991/0711    
} 
 
1991/1004    
/* 
 *  Add an entry into the mmu. 
 */ 
#define FOURMEG (4*1024*1024) 
1991/0711    
void 
mmurelease(Proc *p) 
{ 
1991/0718    
	p->mmuvalid = 0; 
1991/0711    
} 
                 
void 
1991/0718    
putmmu(ulong va, ulong pa, Page *pg) 
1991/0711    
{ 
1991/0718    
	int topoff; 
1991/1004    
	ulong *top; 
1991/0718    
	ulong *pt; 
	Proc *p; 
1991/0723    
	int i = 0; 
1991/1004    
	char err[64]; 
1991/0718    
 
1991/0801    
/*print("putmmu %lux %lux\n", va, pa); /**/ 
1991/0718    
	if(u==0) 
		panic("putmmu"); 
1991/1004    
 
1991/0718    
	p = u->p; 
 
1991/1004    
	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); 
 
1991/0718    
	/* 
	 *  check for exec/data vs stack vs illegal 
1991/1004    
	 *  if no top level page, allocate one and copy the prototype 
	 *  into it. 
1991/0718    
	 */ 
	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); 
1991/1004    
	if(p->mmutop == 0){ 
		p->mmutop = mmugetpage(0); 
		memmove((void*)p->mmutop->va, (void*)ktoppg.va, BY2PG); 
	} 
	top = (ulong*)p->mmutop->va; 
1991/0718    
 
	/* 
	 *  if bottom level page table missing, allocate one 
1991/1004    
	 *  if bottom level page table missing, allocate one and point 
	 *  the top level page at it. 
1991/0718    
	 */ 
	pg = p->mmu[i]; 
1991/0801    
/*print("toppt[%d] was %lux\n", topoff, toppt[topoff]);/**/ 
1991/0718    
	if(pg == 0){ 
		pg = p->mmu[i] = newpage(1, 0, 0); 
1991/0719    
		p->mmue[i] = PPN(pg->pa) | PTEVALID | PTEUSER | PTEWRITE; 
1991/0718    
		toppt[topoff] = p->mmue[i]; 
1991/0801    
/*print("toppt[%d] now %lux\n", topoff, toppt[topoff]);/**/ 
1991/1004    
	topoff = TOPOFF(va); 
	if(top[topoff] == 0){ 
		pg = mmugetpage(1); 
		top[topoff] = PPN(pg->pa) | PTEVALID | PTEUSER | PTEWRITE; 
		pg->next = p->mmuused; 
		p->mmuused = pg; 
1991/0718    
	} 
 
	/* 
	 *  fill in the bottom level page table 
1991/1004    
	 *  put in new mmu entry 
1991/0718    
	 */ 
	pt = (ulong*)(p->mmu[i]->pa|KZERO); 
1991/0801    
/*print("%lux[%d] was %lux\n", pt, BTMOFF(va), pt[BTMOFF(va)]);/**/ 
1991/1004    
	pt = (ulong*)(PPN(top[topoff])|KZERO); 
1991/0718    
	pt[BTMOFF(va)] = pa | PTEUSER; 
1991/0801    
/*print("%lux[%d] now %lux\n", pt, BTMOFF(va), pt[BTMOFF(va)]);/**/ 
1991/0718    
 
	/* flush cached mmu entries */ 
	putcr3(((ulong)toppt)&~KZERO); 
1991/1004    
	putcr3(p->mmutop->pa); 
1991/0711    
} 
 
void 
1991/1003/sys/src/9/pc/mmu.c:271,2771991/1004/sys/src/9/pc/mmu.c:347,353
1991/0718    
	upt[0] = 0; 
 
	/* flush cached mmu entries */ 
	putcr3(((ulong)toppt)&~KZERO); 
1991/1004    
	putcr3(ktoppg.pa); 
1991/0703    
} 
 
void 
1991/1004/sys/src/9/pc/mmu.c:297,3021991/1005/sys/src/9/pc/mmu.c:297,303 (short | long)
1991/0718    
	ulong *pt; 
	Proc *p; 
1991/1004    
	char err[64]; 
1991/1005    
	int x; 
1991/0718    
 
	if(u==0) 
		panic("putmmu"); 
1991/1004/sys/src/9/pc/mmu.c:313,3201991/1005/sys/src/9/pc/mmu.c:314,329
1991/1004    
	 *  into it. 
1991/0718    
	 */ 
1991/1004    
	if(p->mmutop == 0){ 
		p->mmutop = mmugetpage(0); 
		memmove((void*)p->mmutop->va, (void*)ktoppg.va, BY2PG); 
1991/1005    
		/* 
		 *  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); 
		memmove((void*)pg->va, (void*)ktoppg.va, BY2PG); 
		p->mmutop = pg; 
1991/1004    
	} 
	top = (ulong*)p->mmutop->va; 
1991/0718    
 
1991/1005/sys/src/9/pc/mmu.c:128,1601991/1210/sys/src/9/pc/mmu.c:128,160 (short | long)
1991/0716    
	/* 
1991/0717    
	 *  set up system page tables. 
	 *  map all of physical memory to start at KZERO. 
1991/1210    
	 *  map ROM BIOS at the usual place (F0000000). 
1991/1004    
	 *  leave a map entry for a user area. 
1991/0716    
	 */ 
 
1991/0719    
	/*  allocate and fill low level page tables for kernel mem */ 
1991/1210    
	/*  allocate top level table */ 
	top = ialloc(BY2PG, 1); 
	ktoppg.va = (ulong)top; 
	ktoppg.pa = ktoppg.va & ~KZERO; 
 
	/*  map all memory to KZERO */ 
1991/0827    
	npage = conf.base1/BY2PG + conf.npage1; 
1991/0821    
	nbytes = PGROUND(npage*BY2WD);		/* words of page map */ 
	nkpt = nbytes/BY2PG;			/* pages of page map */ 
	kpt = ialloc(nbytes, 1); 
	for(i = 0; i < npage; i++) 
1991/0718    
		kpt[i] = (i<<PGSHIFT) | PTEVALID | PTEKERNEL | PTEWRITE; 
1991/0821    
                 
print("%d low level pte's, %d high level pte's\n", npage, nkpt); 
1991/0717    
                 
	/*  allocate page table for u-> */ 
	upt = ialloc(BY2PG, 1); 
                 
	/*  allocate top level table and put pointers to lower tables in it */ 
1991/1004    
	top = ialloc(BY2PG, 1); 
	ktoppg.va = (ulong)top; 
	ktoppg.pa = ktoppg.va & ~KZERO; 
1991/1210    
		kpt[i] = (0+i*BY2PG) | PTEVALID | PTEKERNEL | PTEWRITE; 
1991/0718    
	x = TOPOFF(KZERO); 
1991/0717    
	y = ((ulong)kpt)&~KZERO; 
1991/0718    
	for(i = 0; i < nkpt; i++) 
1991/1004    
		top[x+i] = (y+i*BY2PG) | PTEVALID | PTEKERNEL | PTEWRITE; 
1991/1210    
 
	/*  page table for u-> */ 
	upt = ialloc(BY2PG, 1); 
1991/0718    
	x = TOPOFF(USERADDR); 
1991/0717    
	y = ((ulong)upt)&~KZERO; 
1991/1004    
	top[x] = y | PTEVALID | PTEKERNEL | PTEWRITE; 
1991/1210    
 
1991/1004    
	putcr3(ktoppg.pa); 
1991/0717    
 
1991/0716    
	/* 
1991/1210/sys/src/9/pc/mmu.c:160,1651991/1211/sys/src/9/pc/mmu.c:160,166 (short | long)
1991/0716    
	/* 
	 *  set up the task segment 
	 */ 
1991/1211    
	memset(&tss, 0, sizeof(tss)); 
1991/0718    
	tss.sp0 = USERADDR+BY2PG; 
1991/0717    
	tss.ss0 = KDSEL; 
1991/1004    
	tss.cr3 = ktoppg.pa; 
1991/1211/sys/src/9/pc/mmu.c:65,711991/1214/sys/src/9/pc/mmu.c:65,70 (short | long)
1991/0717    
[KESEG]		EXECSEGM(0),		/* kernel code */ 
[UDSEG]		DATASEGM(3),		/* user data/stack */ 
[UESEG]		EXECSEGM(3),		/* user code */ 
1991/0703    
[SYSGATE]	CALLGATE(KESEL,0,3),	/* call gate for system calls */ 
1991/0717    
[TSSSEG]	TSSSEGM(0,0),		/* tss segment */ 
1991/0613    
}; 
1991/0703    
 
1991/1211/sys/src/9/pc/mmu.c:87,1051991/1214/sys/src/9/pc/mmu.c:86,91
1991/0718    
 */ 
1991/0719    
#define BTMOFF(v)	(((v)>>(PGSHIFT))&(WD2PG-1)) 
1991/0718    
 
1991/0703    
void 
1991/0719    
mmudump(void) 
{ 
	int i; 
	ulong *z; 
	z = (ulong*)gdt; 
	for(i = 0; i < sizeof(gdt)/4; i+=2) 
		print("%8.8lux %8.8lux\n", *z++, *z++); 
	print("UESEL %lux UDSEL %lux\n", UESEL, UDSEL); 
	print("KESEL %lux KDSEL %lux\n", KESEL, KDSEL); 
	panic("done"); 
} 
                 
1991/1004    
/* 
 *  Create a prototype page map that maps all of memory into 
 *  kernel (KZERO) space.  This is the default map.  It is used 
1991/1211/sys/src/9/pc/mmu.c:115,1251991/1214/sys/src/9/pc/mmu.c:101,110
1991/1004    
	ulong *top; 
1991/0717    
 
1991/0716    
	/* 
	 *  set up the global descriptor table 
1991/1214    
	 *  set up the global descriptor table. we make the tss entry here 
	 *  since it requires arithmetic on an address and hence cannot 
	 *  be a compile or link time constant. 
1991/0716    
	 */ 
1991/0717    
	x = (ulong)systrap; 
	gdt[SYSGATE].d0 = (x&0xFFFF)|(KESEL<<16); 
	gdt[SYSGATE].d1 = (x&0xFFFF0000)|SEGP|SEGPL(3)|SEGCG; 
1991/0718    
	x = (ulong)&tss; 
1991/0717    
	gdt[TSSSEG].d0 = (x<<16)|sizeof(Tss); 
	gdt[TSSSEG].d1 = (x&0xFF000000)|((x>>16)&0xFF)|SEGTSS|SEGPL(0)|SEGP; 
1991/1211/sys/src/9/pc/mmu.c:128,1341991/1214/sys/src/9/pc/mmu.c:113,118
1991/0716    
	/* 
1991/0717    
	 *  set up system page tables. 
	 *  map all of physical memory to start at KZERO. 
1991/1210    
	 *  map ROM BIOS at the usual place (F0000000). 
1991/1004    
	 *  leave a map entry for a user area. 
1991/0716    
	 */ 
 
1991/1211/sys/src/9/pc/mmu.c:358,3671991/1214/sys/src/9/pc/mmu.c:342,345
1991/0718    
 
	/* flush cached mmu entries */ 
1991/1004    
	putcr3(ktoppg.pa); 
1991/0703    
} 
                 
void 
systrap(void) 
{ 
	panic("system trap from user"); 
} 
1991/1214/sys/src/9/pc/mmu.c:53,591992/0116/sys/src/9/pc/mmu.c:53,59 (short | long)
1991/0717    
#define	D16SEGM(p) 	{ 0xFFFF, (0x0<<16)|SEGP|SEGPL(p)|SEGDATA|SEGW } 
#define	E16SEGM(p) 	{ 0xFFFF, (0x0<<16)|SEGP|SEGPL(p)|SEGEXEC|SEGR } 
#define	TSSSEGM(b,p)	{ ((b)<<16)|sizeof(Tss),\ 
			  ((b)&0xFF000000)|(((b)<<16)&0xFF)|SEGTSS|SEGPL(p)|SEGP } 
1992/0116    
			  ((b)&0xFF000000)|(((b)>>16)&0xFF)|SEGTSS|SEGPL(p)|SEGP } 
1991/0703    
 
/* 
1991/0613    
 *  global descriptor table describing all segments 
1992/0116/sys/src/9/pc/mmu.c:183,1911992/0131/sys/src/9/pc/mmu.c:183,194 (short | long)
1991/1004    
} 
 
/* 
 *  Put all page map pages on the process's free list and 
1992/0131    
 *  Put all bottom level page map pages on the process's free list and 
1991/1004    
 *  call mapstack to set up the prototype page map.  This 
 *  effectively forgets all of the process's mappings. 
1992/0131    
 * 
 *  Don't free the top level page.  Just zero the used entries.  This 
 *  avoids a 4k copy each flushmmu. 
1991/1004    
 */ 
1991/0711    
void 
1991/1004    
flushmmu(void) 
1992/0116/sys/src/9/pc/mmu.c:193,1981992/0131/sys/src/9/pc/mmu.c:196,202
1991/1004    
	int s; 
	Proc *p; 
	Page *pg; 
1992/0131    
	ulong *top; 
1991/1004    
 
	if(u == 0) 
		return; 
1992/0116/sys/src/9/pc/mmu.c:199,2111992/0131/sys/src/9/pc/mmu.c:203,215
1991/1004    
 
	p = u->p; 
	s = splhi(); 
	if(p->mmutop){ 
		p->mmutop->next = p->mmufree; 
		p->mmufree = p->mmutop; 
		for(pg = p->mmufree; pg->next; pg = pg->next) 
			; 
		pg->next = p->mmuused; 
		p->mmutop = 0; 
1992/0131    
	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; 
1991/1004    
		p->mmuused = 0; 
	} 
	mapstack(u->p); 
1992/0116/sys/src/9/pc/mmu.c:227,2411992/0131/sys/src/9/pc/mmu.c:231,244
1991/0928    
	if(p->upage->va != (USERADDR|(p->pid&0xFFFF)) && p->pid != 0) 
1991/0718    
		panic("mapstack %d 0x%lux 0x%lux", p->pid, p->upage->pa, p->upage->va); 
 
1991/1004    
	if(p->mmutop) 
		pg = p->mmutop; 
	else 
		pg = &ktoppg; 
1991/0718    
                 
	/* map in u area */ 
	upt[0] = PPN(p->upage->pa) | PTEVALID | PTEKERNEL | PTEWRITE; 
 
1991/1004    
	/* tell processor about new page table (flushes cached entries) */ 
1992/0131    
	if(p->mmutop) 
		pg = p->mmutop; 
	else 
		pg = &ktoppg; 
1991/1004    
	putcr3(pg->pa); 
1991/0718    
 
	u = (User*)USERADDR; 
1992/0116/sys/src/9/pc/mmu.c:322,3271992/0131/sys/src/9/pc/mmu.c:325,331
1991/1004    
		top[topoff] = PPN(pg->pa) | PTEVALID | PTEUSER | PTEWRITE; 
		pg->next = p->mmuused; 
		p->mmuused = pg; 
1992/0131    
		pg->daddr = topoff; 
1991/0718    
	} 
 
	/* 
Too many diffs (26 > 25). Stopping.


source code copyright © 1990-2005 Lucent Technologies; see license
Plan 9 distribution
comments to russ cox (rsc@swtch.com)