~kris/9p

9hist

ref: 0c132ec3c5acfc131b2f9005c68e3262a0f4a040 9hist/pc/mmu.c -rw-r--r-- 4.0 KiB
0c132ec3 — David du Colombier Plan 9 from Bell Labs 1991-07-17 35 years ago
                                                                                
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
#include	"u.h"
#include	"lib.h"
#include	"mem.h"
#include	"dat.h"
#include	"fns.h"
#include	"io.h"

/*
 *  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	sp0;		/* pl0 stack pointer */
	ulong	ss0;		/* pl0 stack selector */
	ulong	sp1;		/* pl1 stack pointer */
	ulong	ss1;		/* pl1 stack selector */
	ulong	sp2;		/* 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 */
};
Tss tss;

/*
 *  segment descriptor initializers
 */
#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 }

/*
 *  global descriptor table describing all segments
 */
Segdesc gdt[] =
{
[NULLSEG]	{ 0, 0},		/* null descriptor */
[KDSEG]		DATASEGM(0),		/* kernel data/stack */
[KESEG]		EXECSEGM(0),		/* kernel code */
[UDSEG]		DATASEGM(3),		/* user data/stack */
[UESEG]		EXECSEGM(3),		/* user code */
[SYSGATE]	CALLGATE(KESEL,0,3),	/* call gate for system calls */
[RDSEG]		D16SEGM(0),		/* reboot data/stack */
[RESEG]		E16SEGM(0),		/* reboot code */
[TSSSEG]	TSSSEGM(0,0),		/* tss segment */
};

static ulong	*toppt;		/* top level page table */	
static ulong	*kpt;		/* kernel level page tables */
static ulong	*upt;		/* page table for struct User */

#define ROUNDUP(s,v)	(((s)+(v-1))&~(v-1))

void
mmuinit(void)
{
	int i, n, nkpt;
	ulong x;
	ulong y;

	/*
	 *  set up the global descriptor table
	 */
	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;
	lgdt(gdt, sizeof gdt);

	/*
	 *  set up system page tables.
	 *  map all of physical memory to start at KZERO.
	 *  leave a map for a user area.
	 */

	/*  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);

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

void
mapstack(Proc *p)
{
	
}

void
flushmmu(void)
{
}

void
mmurelease(Proc *p)
{
}

void
putmmu(ulong x, ulong y, Page *z)
{
}

void
invalidateu(void)
{
}

void
systrap(void)
{
	panic("system trap from user");
}

void
exit(void)
{
	int i;

	u = 0;
	print("exiting\n");
	for(i = 0; i < WD2PG; i++)
		toppt[i] = 0;
	lcr3(((ulong)toppt)&~KZERO);
}