xref: /minix/minix/servers/vm/pagetable.c (revision 83133719)
1 
2 #define _SYSTEM 1
3 
4 #include <minix/callnr.h>
5 #include <minix/com.h>
6 #include <minix/config.h>
7 #include <minix/const.h>
8 #include <minix/ds.h>
9 #include <minix/endpoint.h>
10 #include <minix/minlib.h>
11 #include <minix/type.h>
12 #include <minix/ipc.h>
13 #include <minix/sysutil.h>
14 #include <minix/syslib.h>
15 #include <minix/safecopies.h>
16 #include <minix/cpufeature.h>
17 #include <minix/bitmap.h>
18 #include <minix/debug.h>
19 
20 #include <errno.h>
21 #include <stdlib.h>
22 #include <assert.h>
23 #include <string.h>
24 #include <env.h>
25 #include <stdio.h>
26 #include <fcntl.h>
27 #include <stdlib.h>
28 
29 #include "proto.h"
30 #include "glo.h"
31 #include "util.h"
32 #include "vm.h"
33 #include "sanitycheck.h"
34 
35 static int vm_self_pages;
36 
37 /* PDE used to map in kernel, kernel physical address. */
38 #define MAX_PAGEDIR_PDES 5
39 static struct pdm {
40 	int		pdeno;
41 	u32_t		val;
42 	phys_bytes	phys;
43 	u32_t		*page_directories;
44 } pagedir_mappings[MAX_PAGEDIR_PDES];
45 
46 static multiboot_module_t *kern_mb_mod = NULL;
47 static size_t kern_size = 0;
48 static int kern_start_pde = -1;
49 
50 /* big page size available in hardware? */
51 static int bigpage_ok = 1;
52 
53 /* Our process table entry. */
54 struct vmproc *vmprocess = &vmproc[VM_PROC_NR];
55 
56 /* Spare memory, ready to go after initialization, to avoid a
57  * circular dependency on allocating memory and writing it into VM's
58  * page table.
59  */
60 #if SANITYCHECKS
61 #define SPAREPAGES 200
62 #define STATIC_SPAREPAGES 190
63 #else
64 #ifdef __arm__
65 # define SPAREPAGES 150
66 # define STATIC_SPAREPAGES 140
67 #else
68 # define SPAREPAGES 20
69 # define STATIC_SPAREPAGES 15
70 #endif /* __arm__ */
71 #endif
72 
73 #ifdef __i386__
74 static u32_t global_bit = 0;
75 #endif
76 
77 #define SPAREPAGEDIRS 1
78 #define STATIC_SPAREPAGEDIRS 1
79 
80 int missing_sparedirs = SPAREPAGEDIRS;
81 static struct {
82 	void *pagedir;
83 	phys_bytes phys;
84 } sparepagedirs[SPAREPAGEDIRS];
85 
86 extern char _end;
87 #define is_staticaddr(v) ((vir_bytes) (v) < (vir_bytes) &_end)
88 
89 #define MAX_KERNMAPPINGS 10
90 static struct {
91 	phys_bytes	phys_addr;	/* Physical addr. */
92 	phys_bytes	len;		/* Length in bytes. */
93 	vir_bytes	vir_addr;	/* Offset in page table. */
94 	int		flags;
95 } kern_mappings[MAX_KERNMAPPINGS];
96 int kernmappings = 0;
97 
98 /* Clicks must be pages, as
99  *  - they must be page aligned to map them
100  *  - they must be a multiple of the page size
101  *  - it's inconvenient to have them bigger than pages, because we often want
102  *    just one page
103  * May as well require them to be equal then.
104  */
105 #if CLICK_SIZE != VM_PAGE_SIZE
106 #error CLICK_SIZE must be page size.
107 #endif
108 
109 static void *spare_pagequeue;
110 static char static_sparepages[VM_PAGE_SIZE*STATIC_SPAREPAGES]
111 	__aligned(VM_PAGE_SIZE);
112 
113 #if defined(__arm__)
114 static char static_sparepagedirs[ARCH_PAGEDIR_SIZE*STATIC_SPAREPAGEDIRS + ARCH_PAGEDIR_SIZE] __aligned(ARCH_PAGEDIR_SIZE);
115 #endif
116 
117 #if SANITYCHECKS
118 /*===========================================================================*
119  *				pt_sanitycheck		     		     *
120  *===========================================================================*/
121 void pt_sanitycheck(pt_t *pt, const char *file, int line)
122 {
123 /* Basic pt sanity check. */
124 	int slot;
125 
126 	MYASSERT(pt);
127 	MYASSERT(pt->pt_dir);
128 	MYASSERT(pt->pt_dir_phys);
129 
130 	for(slot = 0; slot < ELEMENTS(vmproc); slot++) {
131 		if(pt == &vmproc[slot].vm_pt)
132 			break;
133 	}
134 
135 	if(slot >= ELEMENTS(vmproc)) {
136 		panic("pt_sanitycheck: passed pt not in any proc");
137 	}
138 
139 	MYASSERT(usedpages_add(pt->pt_dir_phys, VM_PAGE_SIZE) == OK);
140 }
141 #endif
142 
143 /*===========================================================================*
144  *				findhole		     		     *
145  *===========================================================================*/
146 static u32_t findhole(int pages)
147 {
148 /* Find a space in the virtual address space of VM. */
149 	u32_t curv;
150 	int pde = 0, try_restart;
151 	static u32_t lastv = 0;
152 	pt_t *pt = &vmprocess->vm_pt;
153 	vir_bytes vmin, vmax;
154 	u32_t holev = NO_MEM;
155 	int holesize = -1;
156 
157 	vmin = (vir_bytes) (&_end); /* marks end of VM BSS */
158 	vmin += 1024*1024*1024;	/* reserve 1GB virtual address space for VM heap */
159 	vmin &= ARCH_VM_ADDR_MASK;
160 	vmax = vmin + 100 * 1024 * 1024; /* allow 100MB of address space for VM */
161 
162 	/* Input sanity check. */
163 	assert(vmin + VM_PAGE_SIZE >= vmin);
164 	assert(vmax >= vmin + VM_PAGE_SIZE);
165 	assert((vmin % VM_PAGE_SIZE) == 0);
166 	assert((vmax % VM_PAGE_SIZE) == 0);
167 	assert(pages > 0);
168 
169 	curv = lastv;
170 	if(curv < vmin || curv >= vmax)
171 		curv = vmin;
172 
173 	try_restart = 1;
174 
175 	/* Start looking for a free page starting at vmin. */
176 	while(curv < vmax) {
177 		int pte;
178 
179 		assert(curv >= vmin);
180 		assert(curv < vmax);
181 
182 		pde = ARCH_VM_PDE(curv);
183 		pte = ARCH_VM_PTE(curv);
184 
185 		if((pt->pt_dir[pde] & ARCH_VM_PDE_PRESENT) &&
186 		   (pt->pt_pt[pde][pte] & ARCH_VM_PTE_PRESENT)) {
187 			/* there is a page here - so keep looking for holes */
188 			holev = NO_MEM;
189 			holesize = 0;
190 		} else {
191 			/* there is no page here - so we have a hole, a bigger
192 			 * one if we already had one
193 			 */
194 			if(holev == NO_MEM) {
195 				holev = curv;
196 				holesize = 1;
197 			} else holesize++;
198 
199 			assert(holesize > 0);
200 			assert(holesize <= pages);
201 
202 			/* if it's big enough, return it */
203 			if(holesize == pages) {
204 				lastv = curv + VM_PAGE_SIZE;
205 				return holev;
206 			}
207 		}
208 
209 		curv+=VM_PAGE_SIZE;
210 
211 		/* if we reached the limit, start scanning from the beginning if
212 		 * we haven't looked there yet
213 		 */
214 		if(curv >= vmax && try_restart) {
215 			try_restart = 0;
216 			curv = vmin;
217 		}
218 	}
219 
220 	printf("VM: out of virtual address space in vm\n");
221 
222 	return NO_MEM;
223 }
224 
225 /*===========================================================================*
226  *				vm_freepages		     		     *
227  *===========================================================================*/
228 void vm_freepages(vir_bytes vir, int pages)
229 {
230 	assert(!(vir % VM_PAGE_SIZE));
231 
232 	if(is_staticaddr(vir)) {
233 		printf("VM: not freeing static page\n");
234 		return;
235 	}
236 
237 	if(pt_writemap(vmprocess, &vmprocess->vm_pt, vir,
238 		MAP_NONE, pages*VM_PAGE_SIZE, 0,
239 		WMF_OVERWRITE | WMF_FREE) != OK)
240 		panic("vm_freepages: pt_writemap failed");
241 
242 	vm_self_pages--;
243 
244 #if SANITYCHECKS
245 	/* If SANITYCHECKS are on, flush tlb so accessing freed pages is
246 	 * always trapped, also if not in tlb.
247 	 */
248 	if((sys_vmctl(SELF, VMCTL_FLUSHTLB, 0)) != OK) {
249 		panic("VMCTL_FLUSHTLB failed");
250 	}
251 #endif
252 }
253 
254 /*===========================================================================*
255  *				vm_getsparepage		     		     *
256  *===========================================================================*/
257 static void *vm_getsparepage(phys_bytes *phys)
258 {
259 	void *ptr;
260 	if(reservedqueue_alloc(spare_pagequeue, phys, &ptr) != OK) {
261 		printf("vm_getsparepage: no spare found\n");
262 		return NULL;
263 	}
264 	assert(ptr);
265 	return ptr;
266 }
267 
268 /*===========================================================================*
269  *				vm_getsparepagedir	      		     *
270  *===========================================================================*/
271 static void *vm_getsparepagedir(phys_bytes *phys)
272 {
273 	int s;
274 	assert(missing_sparedirs >= 0 && missing_sparedirs <= SPAREPAGEDIRS);
275 	for(s = 0; s < SPAREPAGEDIRS; s++) {
276 		if(sparepagedirs[s].pagedir) {
277 			void *sp;
278 			sp = sparepagedirs[s].pagedir;
279 			*phys = sparepagedirs[s].phys;
280 			sparepagedirs[s].pagedir = NULL;
281 			missing_sparedirs++;
282 			assert(missing_sparedirs >= 0 && missing_sparedirs <= SPAREPAGEDIRS);
283 			return sp;
284 		}
285 	}
286 	return NULL;
287 }
288 
289 void *vm_mappages(phys_bytes p, int pages)
290 {
291 	vir_bytes loc;
292 	int r;
293 	pt_t *pt = &vmprocess->vm_pt;
294 
295 	/* Where in our virtual address space can we put it? */
296 	loc = findhole(pages);
297 	if(loc == NO_MEM) {
298 		printf("vm_mappages: findhole failed\n");
299 		return NULL;
300 	}
301 
302 	/* Map this page into our address space. */
303 	if((r=pt_writemap(vmprocess, pt, loc, p, VM_PAGE_SIZE*pages,
304 		ARCH_VM_PTE_PRESENT | ARCH_VM_PTE_USER | ARCH_VM_PTE_RW
305 #if defined(__arm__)
306 		| ARM_VM_PTE_CACHED
307 #endif
308 		, 0)) != OK) {
309 		printf("vm_mappages writemap failed\n");
310 		return NULL;
311 	}
312 
313 	if((r=sys_vmctl(SELF, VMCTL_FLUSHTLB, 0)) != OK) {
314 		panic("VMCTL_FLUSHTLB failed: %d", r);
315 	}
316 
317 	assert(loc);
318 
319 	return (void *) loc;
320 }
321 
322 static int pt_init_done;
323 
324 /*===========================================================================*
325  *				vm_allocpage		     		     *
326  *===========================================================================*/
327 void *vm_allocpages(phys_bytes *phys, int reason, int pages)
328 {
329 /* Allocate a page for use by VM itself. */
330 	phys_bytes newpage;
331 	static int level = 0;
332 	void *ret;
333 	u32_t mem_flags = 0;
334 
335 	assert(reason >= 0 && reason < VMP_CATEGORIES);
336 
337 	assert(pages > 0);
338 
339 	level++;
340 
341 	assert(level >= 1);
342 	assert(level <= 2);
343 
344 	if((level > 1) || !pt_init_done) {
345 		void *s;
346 
347 		if(pages == 1) s=vm_getsparepage(phys);
348 		else if(pages == 4) s=vm_getsparepagedir(phys);
349 		else panic("%d pages", pages);
350 
351 		level--;
352 		if(!s) {
353 			util_stacktrace();
354 			printf("VM: warning: out of spare pages\n");
355 		}
356 		if(!is_staticaddr(s)) vm_self_pages++;
357 		return s;
358 	}
359 
360 #if defined(__arm__)
361 	if (reason == VMP_PAGEDIR) {
362 		mem_flags |= PAF_ALIGN16K;
363 	}
364 #endif
365 
366 	/* Allocate page of memory for use by VM. As VM
367 	 * is trusted, we don't have to pre-clear it.
368 	 */
369 	if((newpage = alloc_mem(pages, mem_flags)) == NO_MEM) {
370 		level--;
371 		printf("VM: vm_allocpage: alloc_mem failed\n");
372 		return NULL;
373 	}
374 
375 	*phys = CLICK2ABS(newpage);
376 
377 	if(!(ret = vm_mappages(*phys, pages))) {
378 		level--;
379 		printf("VM: vm_allocpage: vm_mappages failed\n");
380 		return NULL;
381 	}
382 
383 	level--;
384 	vm_self_pages++;
385 
386 	return ret;
387 }
388 
389 void *vm_allocpage(phys_bytes *phys, int reason)
390 {
391 	return vm_allocpages(phys, reason, 1);
392 }
393 
394 /*===========================================================================*
395  *				vm_pagelock		     		     *
396  *===========================================================================*/
397 void vm_pagelock(void *vir, int lockflag)
398 {
399 /* Mark a page allocated by vm_allocpage() unwritable, i.e. only for VM. */
400 	vir_bytes m = (vir_bytes) vir;
401 	int r;
402 	u32_t flags = ARCH_VM_PTE_PRESENT | ARCH_VM_PTE_USER;
403 	pt_t *pt;
404 
405 	pt = &vmprocess->vm_pt;
406 
407 	assert(!(m % VM_PAGE_SIZE));
408 
409 	if(!lockflag)
410 		flags |= ARCH_VM_PTE_RW;
411 #if defined(__arm__)
412 	else
413 		flags |= ARCH_VM_PTE_RO;
414 
415 	flags |= ARM_VM_PTE_CACHED ;
416 #endif
417 
418 	/* Update flags. */
419 	if((r=pt_writemap(vmprocess, pt, m, 0, VM_PAGE_SIZE,
420 		flags, WMF_OVERWRITE | WMF_WRITEFLAGSONLY)) != OK) {
421 		panic("vm_lockpage: pt_writemap failed");
422 	}
423 
424 	if((r=sys_vmctl(SELF, VMCTL_FLUSHTLB, 0)) != OK) {
425 		panic("VMCTL_FLUSHTLB failed: %d", r);
426 	}
427 
428 	return;
429 }
430 
431 /*===========================================================================*
432  *				vm_addrok		     		     *
433  *===========================================================================*/
434 int vm_addrok(void *vir, int writeflag)
435 {
436 	pt_t *pt = &vmprocess->vm_pt;
437 	int pde, pte;
438 	vir_bytes v = (vir_bytes) vir;
439 
440 	pde = ARCH_VM_PDE(v);
441 	pte = ARCH_VM_PTE(v);
442 
443 	if(!(pt->pt_dir[pde] & ARCH_VM_PDE_PRESENT)) {
444 		printf("addr not ok: missing pde %d\n", pde);
445 		return 0;
446 	}
447 
448 #if defined(__i386__)
449 	if(writeflag &&
450 		!(pt->pt_dir[pde] & ARCH_VM_PTE_RW)) {
451 		printf("addr not ok: pde %d present but pde unwritable\n", pde);
452 		return 0;
453 	}
454 #elif defined(__arm__)
455 	if(writeflag &&
456 		 (pt->pt_dir[pde] & ARCH_VM_PTE_RO)) {
457 		printf("addr not ok: pde %d present but pde unwritable\n", pde);
458 		return 0;
459 	}
460 
461 #endif
462 	if(!(pt->pt_pt[pde][pte] & ARCH_VM_PTE_PRESENT)) {
463 		printf("addr not ok: missing pde %d / pte %d\n",
464 			pde, pte);
465 		return 0;
466 	}
467 
468 #if defined(__i386__)
469 	if(writeflag &&
470 		!(pt->pt_pt[pde][pte] & ARCH_VM_PTE_RW)) {
471 		printf("addr not ok: pde %d / pte %d present but unwritable\n",
472 			pde, pte);
473 #elif defined(__arm__)
474 	if(writeflag &&
475 		 (pt->pt_pt[pde][pte] & ARCH_VM_PTE_RO)) {
476 		printf("addr not ok: pde %d / pte %d present but unwritable\n",
477 			pde, pte);
478 #endif
479 		return 0;
480 	}
481 
482 	return 1;
483 }
484 
485 /*===========================================================================*
486  *				pt_ptalloc		     		     *
487  *===========================================================================*/
488 static int pt_ptalloc(pt_t *pt, int pde, u32_t flags)
489 {
490 /* Allocate a page table and write its address into the page directory. */
491 	int i;
492 	phys_bytes pt_phys;
493 	u32_t *p;
494 
495 	/* Argument must make sense. */
496 	assert(pde >= 0 && pde < ARCH_VM_DIR_ENTRIES);
497 	assert(!(flags & ~(PTF_ALLFLAGS)));
498 
499 	/* We don't expect to overwrite page directory entry, nor
500 	 * storage for the page table.
501 	 */
502 	assert(!(pt->pt_dir[pde] & ARCH_VM_PDE_PRESENT));
503 	assert(!pt->pt_pt[pde]);
504 
505 	/* Get storage for the page table. The allocation call may in fact
506 	 * recursively create the directory entry as a side effect. In that
507 	 * case, we free the newly allocated page and do nothing else.
508 	 */
509 	if (!(p = vm_allocpage(&pt_phys, VMP_PAGETABLE)))
510 		return ENOMEM;
511 	if (pt->pt_pt[pde]) {
512 		vm_freepages((vir_bytes) p, 1);
513 		assert(pt->pt_pt[pde]);
514 		return OK;
515 	}
516 	pt->pt_pt[pde] = p;
517 
518 	for(i = 0; i < ARCH_VM_PT_ENTRIES; i++)
519 		pt->pt_pt[pde][i] = 0;	/* Empty entry. */
520 
521 	/* Make page directory entry.
522 	 * The PDE is always 'present,' 'writable,' and 'user accessible,'
523 	 * relying on the PTE for protection.
524 	 */
525 #if defined(__i386__)
526 	pt->pt_dir[pde] = (pt_phys & ARCH_VM_ADDR_MASK) | flags
527 		| ARCH_VM_PDE_PRESENT | ARCH_VM_PTE_USER | ARCH_VM_PTE_RW;
528 #elif defined(__arm__)
529 	pt->pt_dir[pde] = (pt_phys & ARCH_VM_PDE_MASK)
530 		| ARCH_VM_PDE_PRESENT | ARM_VM_PDE_DOMAIN; //LSC FIXME
531 #endif
532 
533 	return OK;
534 }
535 
536 /*===========================================================================*
537  *			    pt_ptalloc_in_range		     		     *
538  *===========================================================================*/
539 int pt_ptalloc_in_range(pt_t *pt, vir_bytes start, vir_bytes end,
540 	u32_t flags, int verify)
541 {
542 /* Allocate all the page tables in the range specified. */
543 	int pde, first_pde, last_pde;
544 
545 	first_pde = ARCH_VM_PDE(start);
546 	last_pde = ARCH_VM_PDE(end-1);
547 
548 	assert(first_pde >= 0);
549 	assert(last_pde < ARCH_VM_DIR_ENTRIES);
550 
551 	/* Scan all page-directory entries in the range. */
552 	for(pde = first_pde; pde <= last_pde; pde++) {
553 		assert(!(pt->pt_dir[pde] & ARCH_VM_BIGPAGE));
554 		if(!(pt->pt_dir[pde] & ARCH_VM_PDE_PRESENT)) {
555 			int r;
556 			if(verify) {
557 				printf("pt_ptalloc_in_range: no pde %d\n", pde);
558 				return EFAULT;
559 			}
560 			assert(!pt->pt_dir[pde]);
561 			if((r=pt_ptalloc(pt, pde, flags)) != OK) {
562 				/* Couldn't do (complete) mapping.
563 				 * Don't bother freeing any previously
564 				 * allocated page tables, they're
565 				 * still writable, don't point to nonsense,
566 				 * and pt_ptalloc leaves the directory
567 				 * and other data in a consistent state.
568 				 */
569 				return r;
570 			}
571 			assert(pt->pt_pt[pde]);
572 		}
573 		assert(pt->pt_pt[pde]);
574 		assert(pt->pt_dir[pde]);
575 		assert(pt->pt_dir[pde] & ARCH_VM_PDE_PRESENT);
576 	}
577 
578 	return OK;
579 }
580 
581 static const char *ptestr(u32_t pte)
582 {
583 #define FLAG(constant, name) {						\
584 	if(pte & (constant)) { strcat(str, name); strcat(str, " "); }	\
585 }
586 
587 	static char str[30];
588 	if(!(pte & ARCH_VM_PTE_PRESENT)) {
589 		return "not present";
590 	}
591 	str[0] = '\0';
592 #if defined(__i386__)
593 	FLAG(ARCH_VM_PTE_RW, "W");
594 #elif defined(__arm__)
595 	if(pte & ARCH_VM_PTE_RO) {
596 	    strcat(str, "R ");
597 	} else {
598 	    strcat(str, "W ");
599 	}
600 #endif
601 	FLAG(ARCH_VM_PTE_USER, "U");
602 #if defined(__i386__)
603 	FLAG(I386_VM_PWT, "PWT");
604 	FLAG(I386_VM_PCD, "PCD");
605 	FLAG(I386_VM_ACC, "ACC");
606 	FLAG(I386_VM_DIRTY, "DIRTY");
607 	FLAG(I386_VM_PS, "PS");
608 	FLAG(I386_VM_GLOBAL, "G");
609 	FLAG(I386_VM_PTAVAIL1, "AV1");
610 	FLAG(I386_VM_PTAVAIL2, "AV2");
611 	FLAG(I386_VM_PTAVAIL3, "AV3");
612 #elif defined(__arm__)
613 	FLAG(ARM_VM_PTE_SUPER, "S");
614 	FLAG(ARM_VM_PTE_S, "SH");
615 	FLAG(ARM_VM_PTE_WB, "WB");
616 	FLAG(ARM_VM_PTE_WT, "WT");
617 #endif
618 
619 	return str;
620 }
621 
622 /*===========================================================================*
623  *			     pt_map_in_range		     		     *
624  *===========================================================================*/
625 int pt_map_in_range(struct vmproc *src_vmp, struct vmproc *dst_vmp,
626 	vir_bytes start, vir_bytes end)
627 {
628 /* Transfer all the mappings from the pt of the source process to the pt of
629  * the destination process in the range specified.
630  */
631 	int pde, pte;
632 	vir_bytes viraddr;
633 	pt_t *pt, *dst_pt;
634 
635 	pt = &src_vmp->vm_pt;
636 	dst_pt = &dst_vmp->vm_pt;
637 
638 	end = end ? end : VM_DATATOP;
639 	assert(start % VM_PAGE_SIZE == 0);
640 	assert(end % VM_PAGE_SIZE == 0);
641 
642 	assert( /* ARCH_VM_PDE(start) >= 0 && */ start <= end);
643 	assert(ARCH_VM_PDE(end) < ARCH_VM_DIR_ENTRIES);
644 
645 #if LU_DEBUG
646 	printf("VM: pt_map_in_range: src = %d, dst = %d\n",
647 		src_vmp->vm_endpoint, dst_vmp->vm_endpoint);
648 	printf("VM: pt_map_in_range: transferring from 0x%08x (pde %d pte %d) to 0x%08x (pde %d pte %d)\n",
649 		start, ARCH_VM_PDE(start), ARCH_VM_PTE(start),
650 		end, ARCH_VM_PDE(end), ARCH_VM_PTE(end));
651 #endif
652 
653 	/* Scan all page-table entries in the range. */
654 	for(viraddr = start; viraddr <= end; viraddr += VM_PAGE_SIZE) {
655 		pde = ARCH_VM_PDE(viraddr);
656 		if(!(pt->pt_dir[pde] & ARCH_VM_PDE_PRESENT)) {
657 			if(viraddr == VM_DATATOP) break;
658 			continue;
659 		}
660 		pte = ARCH_VM_PTE(viraddr);
661 		if(!(pt->pt_pt[pde][pte] & ARCH_VM_PTE_PRESENT)) {
662 			if(viraddr == VM_DATATOP) break;
663 			continue;
664 		}
665 
666 		/* Transfer the mapping. */
667 		dst_pt->pt_pt[pde][pte] = pt->pt_pt[pde][pte];
668 
669                 if(viraddr == VM_DATATOP) break;
670 	}
671 
672 	return OK;
673 }
674 
675 /*===========================================================================*
676  *				pt_ptmap		     		     *
677  *===========================================================================*/
678 int pt_ptmap(struct vmproc *src_vmp, struct vmproc *dst_vmp)
679 {
680 /* Transfer mappings to page dir and page tables from source process and
681  * destination process. Make sure all the mappings are above the stack, not
682  * to corrupt valid mappings in the data segment of the destination process.
683  */
684 	int pde, r;
685 	phys_bytes physaddr;
686 	vir_bytes viraddr;
687 	pt_t *pt;
688 
689 	pt = &src_vmp->vm_pt;
690 
691 #if LU_DEBUG
692 	printf("VM: pt_ptmap: src = %d, dst = %d\n",
693 		src_vmp->vm_endpoint, dst_vmp->vm_endpoint);
694 #endif
695 
696 	/* Transfer mapping to the page directory. */
697 	viraddr = (vir_bytes) pt->pt_dir;
698 	physaddr = pt->pt_dir_phys & ARCH_VM_ADDR_MASK;
699 #if defined(__i386__)
700 	if((r=pt_writemap(dst_vmp, &dst_vmp->vm_pt, viraddr, physaddr, VM_PAGE_SIZE,
701 		ARCH_VM_PTE_PRESENT | ARCH_VM_PTE_USER | ARCH_VM_PTE_RW,
702 #elif defined(__arm__)
703 	if((r=pt_writemap(dst_vmp, &dst_vmp->vm_pt, viraddr, physaddr, ARCH_PAGEDIR_SIZE,
704 		ARCH_VM_PTE_PRESENT | ARCH_VM_PTE_USER |
705 		ARM_VM_PTE_CACHED ,
706 #endif
707 		WMF_OVERWRITE)) != OK) {
708 		return r;
709 	}
710 #if LU_DEBUG
711 	printf("VM: pt_ptmap: transferred mapping to page dir: 0x%08x (0x%08x)\n",
712 		viraddr, physaddr);
713 #endif
714 
715 	/* Scan all non-reserved page-directory entries. */
716 	for(pde=0; pde < ARCH_VM_DIR_ENTRIES; pde++) {
717 		if(!(pt->pt_dir[pde] & ARCH_VM_PDE_PRESENT)) {
718 			continue;
719 		}
720 
721 		/* Transfer mapping to the page table. */
722 		viraddr = (vir_bytes) pt->pt_pt[pde];
723 #if defined(__i386__)
724 		physaddr = pt->pt_dir[pde] & ARCH_VM_ADDR_MASK;
725 #elif defined(__arm__)
726 		physaddr = pt->pt_dir[pde] & ARCH_VM_PDE_MASK;
727 #endif
728 		if((r=pt_writemap(dst_vmp, &dst_vmp->vm_pt, viraddr, physaddr, VM_PAGE_SIZE,
729 			ARCH_VM_PTE_PRESENT | ARCH_VM_PTE_USER | ARCH_VM_PTE_RW
730 #ifdef __arm__
731 			| ARM_VM_PTE_CACHED
732 #endif
733 			,
734 			WMF_OVERWRITE)) != OK) {
735 			return r;
736 		}
737 	}
738 
739 	return OK;
740 }
741 
742 void pt_clearmapcache(void)
743 {
744 	/* Make sure kernel will invalidate tlb when using current
745 	 * pagetable (i.e. vm's) to make new mappings before new cr3
746 	 * is loaded.
747 	 */
748 	if(sys_vmctl(SELF, VMCTL_CLEARMAPCACHE, 0) != OK)
749 		panic("VMCTL_CLEARMAPCACHE failed");
750 }
751 
752 int pt_writable(struct vmproc *vmp, vir_bytes v)
753 {
754 	u32_t entry;
755 	pt_t *pt = &vmp->vm_pt;
756 	assert(!(v % VM_PAGE_SIZE));
757 	int pde = ARCH_VM_PDE(v);
758 	int pte = ARCH_VM_PTE(v);
759 
760 	assert(pt->pt_dir[pde] & ARCH_VM_PDE_PRESENT);
761 	assert(pt->pt_pt[pde]);
762 
763 	entry = pt->pt_pt[pde][pte];
764 
765 #if defined(__i386__)
766 	return((entry & PTF_WRITE) ? 1 : 0);
767 #elif defined(__arm__)
768 	return((entry & ARCH_VM_PTE_RO) ? 0 : 1);
769 #endif
770 }
771 
772 /*===========================================================================*
773  *				pt_writemap		     		     *
774  *===========================================================================*/
775 int pt_writemap(struct vmproc * vmp,
776 			pt_t *pt,
777 			vir_bytes v,
778 			phys_bytes physaddr,
779 			size_t bytes,
780 			u32_t flags,
781 			u32_t writemapflags)
782 {
783 /* Write mapping into page table. Allocate a new page table if necessary. */
784 /* Page directory and table entries for this virtual address. */
785 	int p, pages;
786 	int verify = 0;
787 	int ret = OK;
788 
789 #ifdef CONFIG_SMP
790 	int vminhibit_clear = 0;
791 	/* FIXME
792 	 * don't do it everytime, stop the process only on the first change and
793 	 * resume the execution on the last change. Do in a wrapper of this
794 	 * function
795 	 */
796 	if (vmp && vmp->vm_endpoint != NONE && vmp->vm_endpoint != VM_PROC_NR &&
797 			!(vmp->vm_flags & VMF_EXITING)) {
798 		sys_vmctl(vmp->vm_endpoint, VMCTL_VMINHIBIT_SET, 0);
799 		vminhibit_clear = 1;
800 	}
801 #endif
802 
803 	if(writemapflags & WMF_VERIFY)
804 		verify = 1;
805 
806 	assert(!(bytes % VM_PAGE_SIZE));
807 	assert(!(flags & ~(PTF_ALLFLAGS)));
808 
809 	pages = bytes / VM_PAGE_SIZE;
810 
811 	/* MAP_NONE means to clear the mapping. It doesn't matter
812 	 * what's actually written into the PTE if PRESENT
813 	 * isn't on, so we can just write MAP_NONE into it.
814 	 */
815 	assert(physaddr == MAP_NONE || (flags & ARCH_VM_PTE_PRESENT));
816 	assert(physaddr != MAP_NONE || !flags);
817 
818 	/* First make sure all the necessary page tables are allocated,
819 	 * before we start writing in any of them, because it's a pain
820 	 * to undo our work properly.
821 	 */
822 	ret = pt_ptalloc_in_range(pt, v, v + VM_PAGE_SIZE*pages, flags, verify);
823 	if(ret != OK) {
824 		printf("VM: writemap: pt_ptalloc_in_range failed\n");
825 		goto resume_exit;
826 	}
827 
828 	/* Now write in them. */
829 	for(p = 0; p < pages; p++) {
830 		u32_t entry;
831 		int pde = ARCH_VM_PDE(v);
832 		int pte = ARCH_VM_PTE(v);
833 
834 		assert(!(v % VM_PAGE_SIZE));
835 		assert(pte >= 0 && pte < ARCH_VM_PT_ENTRIES);
836 		assert(pde >= 0 && pde < ARCH_VM_DIR_ENTRIES);
837 
838 		/* Page table has to be there. */
839 		assert(pt->pt_dir[pde] & ARCH_VM_PDE_PRESENT);
840 
841 		/* We do not expect it to be a bigpage. */
842 		assert(!(pt->pt_dir[pde] & ARCH_VM_BIGPAGE));
843 
844 		/* Make sure page directory entry for this page table
845 		 * is marked present and page table entry is available.
846 		 */
847 		assert(pt->pt_pt[pde]);
848 
849 #if SANITYCHECKS
850 		/* We don't expect to overwrite a page. */
851 		if(!(writemapflags & (WMF_OVERWRITE|WMF_VERIFY)))
852 			assert(!(pt->pt_pt[pde][pte] & ARCH_VM_PTE_PRESENT));
853 #endif
854 		if(writemapflags & (WMF_WRITEFLAGSONLY|WMF_FREE)) {
855 #if defined(__i386__)
856 			physaddr = pt->pt_pt[pde][pte] & ARCH_VM_ADDR_MASK;
857 #elif defined(__arm__)
858 			physaddr = pt->pt_pt[pde][pte] & ARM_VM_PTE_MASK;
859 #endif
860 		}
861 
862 		if(writemapflags & WMF_FREE) {
863 			free_mem(ABS2CLICK(physaddr), 1);
864 		}
865 
866 		/* Entry we will write. */
867 #if defined(__i386__)
868 		entry = (physaddr & ARCH_VM_ADDR_MASK) | flags;
869 #elif defined(__arm__)
870 		entry = (physaddr & ARM_VM_PTE_MASK) | flags;
871 #endif
872 
873 		if(verify) {
874 			u32_t maskedentry;
875 			maskedentry = pt->pt_pt[pde][pte];
876 #if defined(__i386__)
877 			maskedentry &= ~(I386_VM_ACC|I386_VM_DIRTY);
878 #endif
879 			/* Verify pagetable entry. */
880 #if defined(__i386__)
881 			if(entry & ARCH_VM_PTE_RW) {
882 				/* If we expect a writable page, allow a readonly page. */
883 				maskedentry |= ARCH_VM_PTE_RW;
884 			}
885 #elif defined(__arm__)
886 			if(!(entry & ARCH_VM_PTE_RO)) {
887 				/* If we expect a writable page, allow a readonly page. */
888 				maskedentry &= ~ARCH_VM_PTE_RO;
889 			}
890 			maskedentry &= ~(ARM_VM_PTE_WB|ARM_VM_PTE_WT);
891 #endif
892 			if(maskedentry != entry) {
893 				printf("pt_writemap: mismatch: ");
894 #if defined(__i386__)
895 				if((entry & ARCH_VM_ADDR_MASK) !=
896 					(maskedentry & ARCH_VM_ADDR_MASK)) {
897 #elif defined(__arm__)
898 				if((entry & ARM_VM_PTE_MASK) !=
899 					(maskedentry & ARM_VM_PTE_MASK)) {
900 #endif
901 					printf("pt_writemap: physaddr mismatch (0x%lx, 0x%lx); ",
902 						(long)entry, (long)maskedentry);
903 				} else printf("phys ok; ");
904 				printf(" flags: found %s; ",
905 					ptestr(pt->pt_pt[pde][pte]));
906 				printf(" masked %s; ",
907 					ptestr(maskedentry));
908 				printf(" expected %s\n", ptestr(entry));
909 				printf("found 0x%x, wanted 0x%x\n",
910 					pt->pt_pt[pde][pte], entry);
911 				ret = EFAULT;
912 				goto resume_exit;
913 			}
914 		} else {
915 			/* Write pagetable entry. */
916 			pt->pt_pt[pde][pte] = entry;
917 		}
918 
919 		physaddr += VM_PAGE_SIZE;
920 		v += VM_PAGE_SIZE;
921 	}
922 
923 resume_exit:
924 
925 #ifdef CONFIG_SMP
926 	if (vminhibit_clear) {
927 		assert(vmp && vmp->vm_endpoint != NONE && vmp->vm_endpoint != VM_PROC_NR &&
928 			!(vmp->vm_flags & VMF_EXITING));
929 		sys_vmctl(vmp->vm_endpoint, VMCTL_VMINHIBIT_CLEAR, 0);
930 	}
931 #endif
932 
933 	return ret;
934 }
935 
936 /*===========================================================================*
937  *				pt_checkrange		     		     *
938  *===========================================================================*/
939 int pt_checkrange(pt_t *pt, vir_bytes v,  size_t bytes,
940 	int write)
941 {
942 	int p, pages;
943 
944 	assert(!(bytes % VM_PAGE_SIZE));
945 
946 	pages = bytes / VM_PAGE_SIZE;
947 
948 	for(p = 0; p < pages; p++) {
949 		int pde = ARCH_VM_PDE(v);
950 		int pte = ARCH_VM_PTE(v);
951 
952 		assert(!(v % VM_PAGE_SIZE));
953 		assert(pte >= 0 && pte < ARCH_VM_PT_ENTRIES);
954 		assert(pde >= 0 && pde < ARCH_VM_DIR_ENTRIES);
955 
956 		/* Page table has to be there. */
957 		if(!(pt->pt_dir[pde] & ARCH_VM_PDE_PRESENT))
958 			return EFAULT;
959 
960 		/* Make sure page directory entry for this page table
961 		 * is marked present and page table entry is available.
962 		 */
963 		assert((pt->pt_dir[pde] & ARCH_VM_PDE_PRESENT) && pt->pt_pt[pde]);
964 
965 		if(!(pt->pt_pt[pde][pte] & ARCH_VM_PTE_PRESENT)) {
966 			return EFAULT;
967 		}
968 
969 #if defined(__i386__)
970 		if(write && !(pt->pt_pt[pde][pte] & ARCH_VM_PTE_RW)) {
971 #elif defined(__arm__)
972 		if(write && (pt->pt_pt[pde][pte] & ARCH_VM_PTE_RO)) {
973 #endif
974 			return EFAULT;
975 		}
976 
977 		v += VM_PAGE_SIZE;
978 	}
979 
980 	return OK;
981 }
982 
983 /*===========================================================================*
984  *				pt_new			     		     *
985  *===========================================================================*/
986 int pt_new(pt_t *pt)
987 {
988 /* Allocate a pagetable root. Allocate a page-aligned page directory
989  * and set them to 0 (indicating no page tables are allocated). Lookup
990  * its physical address as we'll need that in the future. Verify it's
991  * page-aligned.
992  */
993 	int i, r;
994 
995 	/* Don't ever re-allocate/re-move a certain process slot's
996 	 * page directory once it's been created. This is a fraction
997 	 * faster, but also avoids having to invalidate the page
998 	 * mappings from in-kernel page tables pointing to
999 	 * the page directories (the page_directories data).
1000 	 */
1001         if(!pt->pt_dir &&
1002           !(pt->pt_dir = vm_allocpages((phys_bytes *)&pt->pt_dir_phys,
1003 	  	VMP_PAGEDIR, ARCH_PAGEDIR_SIZE/VM_PAGE_SIZE))) {
1004 		return ENOMEM;
1005 	}
1006 
1007 	assert(!((u32_t)pt->pt_dir_phys % ARCH_PAGEDIR_SIZE));
1008 
1009 	for(i = 0; i < ARCH_VM_DIR_ENTRIES; i++) {
1010 		pt->pt_dir[i] = 0; /* invalid entry (PRESENT bit = 0) */
1011 		pt->pt_pt[i] = NULL;
1012 	}
1013 
1014 	/* Where to start looking for free virtual address space? */
1015 	pt->pt_virtop = 0;
1016 
1017         /* Map in kernel. */
1018         if((r=pt_mapkernel(pt)) != OK)
1019 		return r;
1020 
1021 	return OK;
1022 }
1023 
1024 static int freepde(void)
1025 {
1026 	int p = kernel_boot_info.freepde_start++;
1027 	assert(kernel_boot_info.freepde_start < ARCH_VM_DIR_ENTRIES);
1028 	return p;
1029 }
1030 
1031 /*===========================================================================*
1032  *                              pt_init                                      *
1033  *===========================================================================*/
1034 void pt_init(void)
1035 {
1036         pt_t *newpt;
1037         int s, r, p;
1038 	vir_bytes sparepages_mem;
1039 #if defined(__arm__)
1040 	vir_bytes sparepagedirs_mem;
1041 #endif
1042 	static u32_t currentpagedir[ARCH_VM_DIR_ENTRIES];
1043 	int m = kernel_boot_info.kern_mod;
1044 #if defined(__i386__)
1045 	int global_bit_ok = 0;
1046 	u32_t mypdbr; /* Page Directory Base Register (cr3) value */
1047 #elif defined(__arm__)
1048 	u32_t myttbr;
1049 #endif
1050 
1051 	/* Find what the physical location of the kernel is. */
1052 	assert(m >= 0);
1053 	assert(m < kernel_boot_info.mods_with_kernel);
1054 	assert(kernel_boot_info.mods_with_kernel < MULTIBOOT_MAX_MODS);
1055 	kern_mb_mod = &kernel_boot_info.module_list[m];
1056 	kern_size = kern_mb_mod->mod_end - kern_mb_mod->mod_start;
1057 	assert(!(kern_mb_mod->mod_start % ARCH_BIG_PAGE_SIZE));
1058 	assert(!(kernel_boot_info.vir_kern_start % ARCH_BIG_PAGE_SIZE));
1059 	kern_start_pde = kernel_boot_info.vir_kern_start / ARCH_BIG_PAGE_SIZE;
1060 
1061         /* Get ourselves spare pages. */
1062         sparepages_mem = (vir_bytes) static_sparepages;
1063 	assert(!(sparepages_mem % VM_PAGE_SIZE));
1064 
1065 #if defined(__arm__)
1066         /* Get ourselves spare pagedirs. */
1067 	sparepagedirs_mem = (vir_bytes) static_sparepagedirs;
1068 	assert(!(sparepagedirs_mem % ARCH_PAGEDIR_SIZE));
1069 #endif
1070 
1071 	/* Spare pages are used to allocate memory before VM has its own page
1072 	 * table that things (i.e. arbitrary physical memory) can be mapped into.
1073 	 * We get it by pre-allocating it in our bss (allocated and mapped in by
1074 	 * the kernel) in static_sparepages. We also need the physical addresses
1075 	 * though; we look them up now so they are ready for use.
1076 	 */
1077 #if defined(__arm__)
1078         missing_sparedirs = 0;
1079         assert(STATIC_SPAREPAGEDIRS <= SPAREPAGEDIRS);
1080         for(s = 0; s < SPAREPAGEDIRS; s++) {
1081 		vir_bytes v = (sparepagedirs_mem + s*ARCH_PAGEDIR_SIZE);;
1082 		phys_bytes ph;
1083         	if((r=sys_umap(SELF, VM_D, (vir_bytes) v,
1084 	                ARCH_PAGEDIR_SIZE, &ph)) != OK)
1085 				panic("pt_init: sys_umap failed: %d", r);
1086         	if(s >= STATIC_SPAREPAGEDIRS) {
1087         		sparepagedirs[s].pagedir = NULL;
1088         		missing_sparedirs++;
1089         		continue;
1090         	}
1091         	sparepagedirs[s].pagedir = (void *) v;
1092         	sparepagedirs[s].phys = ph;
1093         }
1094 #endif
1095 
1096 	if(!(spare_pagequeue = reservedqueue_new(SPAREPAGES, 1, 1, 0)))
1097 		panic("reservedqueue_new for single pages failed");
1098 
1099         assert(STATIC_SPAREPAGES < SPAREPAGES);
1100         for(s = 0; s < STATIC_SPAREPAGES; s++) {
1101 		void *v = (void *) (sparepages_mem + s*VM_PAGE_SIZE);
1102 		phys_bytes ph;
1103 		if((r=sys_umap(SELF, VM_D, (vir_bytes) v,
1104 	                VM_PAGE_SIZE*SPAREPAGES, &ph)) != OK)
1105 				panic("pt_init: sys_umap failed: %d", r);
1106 		reservedqueue_add(spare_pagequeue, v, ph);
1107         }
1108 
1109 #if defined(__i386__)
1110 	/* global bit and 4MB pages available? */
1111 	global_bit_ok = _cpufeature(_CPUF_I386_PGE);
1112 	bigpage_ok = _cpufeature(_CPUF_I386_PSE);
1113 
1114 	/* Set bit for PTE's and PDE's if available. */
1115 	if(global_bit_ok)
1116 		global_bit = I386_VM_GLOBAL;
1117 #endif
1118 
1119 	/* Now reserve another pde for kernel's own mappings. */
1120 	{
1121 		int kernmap_pde;
1122 		phys_bytes addr, len;
1123 		int flags, pindex = 0;
1124 		u32_t offset = 0;
1125 
1126 		kernmap_pde = freepde();
1127 		offset = kernmap_pde * ARCH_BIG_PAGE_SIZE;
1128 
1129 		while(sys_vmctl_get_mapping(pindex, &addr, &len,
1130 			&flags) == OK)  {
1131 			int usedpde;
1132 			vir_bytes vir;
1133 			if(pindex >= MAX_KERNMAPPINGS)
1134                 		panic("VM: too many kernel mappings: %d", pindex);
1135 			kern_mappings[pindex].phys_addr = addr;
1136 			kern_mappings[pindex].len = len;
1137 			kern_mappings[pindex].flags = flags;
1138 			kern_mappings[pindex].vir_addr = offset;
1139 			kern_mappings[pindex].flags =
1140 				ARCH_VM_PTE_PRESENT;
1141 			if(flags & VMMF_UNCACHED)
1142 #if defined(__i386__)
1143 				kern_mappings[pindex].flags |= PTF_NOCACHE;
1144 #elif defined(__arm__)
1145 				kern_mappings[pindex].flags |= ARM_VM_PTE_DEVICE;
1146 			else {
1147 				kern_mappings[pindex].flags |= ARM_VM_PTE_CACHED;
1148 			}
1149 #endif
1150 			if(flags & VMMF_USER)
1151 				kern_mappings[pindex].flags |= ARCH_VM_PTE_USER;
1152 #if defined(__arm__)
1153 			else
1154 				kern_mappings[pindex].flags |= ARM_VM_PTE_SUPER;
1155 #endif
1156 			if(flags & VMMF_WRITE)
1157 				kern_mappings[pindex].flags |= ARCH_VM_PTE_RW;
1158 #if defined(__arm__)
1159 			else
1160 				kern_mappings[pindex].flags |= ARCH_VM_PTE_RO;
1161 #endif
1162 
1163 #if defined(__i386__)
1164 			if(flags & VMMF_GLO)
1165 				kern_mappings[pindex].flags |= I386_VM_GLOBAL;
1166 #endif
1167 
1168 			if(addr % VM_PAGE_SIZE)
1169                 		panic("VM: addr unaligned: %lu", addr);
1170 			if(len % VM_PAGE_SIZE)
1171                 		panic("VM: len unaligned: %lu", len);
1172 			vir = offset;
1173 			if(sys_vmctl_reply_mapping(pindex, vir) != OK)
1174                 		panic("VM: reply failed");
1175 			offset += len;
1176 			pindex++;
1177 			kernmappings++;
1178 
1179 			usedpde = ARCH_VM_PDE(offset);
1180 			while(usedpde > kernmap_pde) {
1181 				int newpde = freepde();
1182 				assert(newpde == kernmap_pde+1);
1183 				kernmap_pde = newpde;
1184 			}
1185 		}
1186 	}
1187 
1188 	/* Reserve PDEs available for mapping in the page directories. */
1189 	{
1190 		int pd;
1191 		for(pd = 0; pd < MAX_PAGEDIR_PDES; pd++) {
1192 			struct pdm *pdm = &pagedir_mappings[pd];
1193 			pdm->pdeno = freepde();
1194 			phys_bytes ph;
1195 
1196 			/* Allocate us a page table in which to
1197 			 * remember page directory pointers.
1198 			 */
1199 			if(!(pdm->page_directories =
1200 				vm_allocpage(&ph, VMP_PAGETABLE))) {
1201 				panic("no virt addr for vm mappings");
1202 			}
1203 			memset(pdm->page_directories, 0, VM_PAGE_SIZE);
1204 			pdm->phys = ph;
1205 
1206 #if defined(__i386__)
1207 			pdm->val = (ph & ARCH_VM_ADDR_MASK) |
1208 				ARCH_VM_PDE_PRESENT | ARCH_VM_PTE_RW;
1209 #elif defined(__arm__)
1210 			pdm->val = (ph & ARCH_VM_PDE_MASK)
1211 				| ARCH_VM_PDE_PRESENT
1212 				| ARM_VM_PTE_CACHED
1213 				| ARM_VM_PDE_DOMAIN; //LSC FIXME
1214 #endif
1215 		}
1216 	}
1217 
1218 	/* Allright. Now. We have to make our own page directory and page tables,
1219 	 * that the kernel has already set up, accessible to us. It's easier to
1220 	 * understand if we just copy all the required pages (i.e. page directory
1221 	 * and page tables), and set up the pointers as if VM had done it itself.
1222 	 *
1223 	 * This allocation will happen without using any page table, and just
1224 	 * uses spare pages.
1225 	 */
1226         newpt = &vmprocess->vm_pt;
1227 	if(pt_new(newpt) != OK)
1228 		panic("vm pt_new failed");
1229 
1230 	/* Get our current pagedir so we can see it. */
1231 #if defined(__i386__)
1232 	if(sys_vmctl_get_pdbr(SELF, &mypdbr) != OK)
1233 #elif defined(__arm__)
1234 	if(sys_vmctl_get_pdbr(SELF, &myttbr) != OK)
1235 #endif
1236 
1237 		panic("VM: sys_vmctl_get_pdbr failed");
1238 #if defined(__i386__)
1239 	if(sys_vircopy(NONE, mypdbr, SELF,
1240 		(vir_bytes) currentpagedir, VM_PAGE_SIZE, 0) != OK)
1241 #elif defined(__arm__)
1242 	if(sys_vircopy(NONE, myttbr, SELF,
1243 		(vir_bytes) currentpagedir, ARCH_PAGEDIR_SIZE, 0) != OK)
1244 #endif
1245 		panic("VM: sys_vircopy failed");
1246 
1247 	/* We have mapped in kernel ourselves; now copy mappings for VM
1248 	 * that kernel made, including allocations for BSS. Skip identity
1249 	 * mapping bits; just map in VM.
1250 	 */
1251 	for(p = 0; p < ARCH_VM_DIR_ENTRIES; p++) {
1252 		u32_t entry = currentpagedir[p];
1253 		phys_bytes ptaddr_kern, ptaddr_us;
1254 
1255 		/* BIGPAGEs are kernel mapping (do ourselves) or boot
1256 		 * identity mapping (don't want).
1257 		 */
1258 		if(!(entry & ARCH_VM_PDE_PRESENT)) continue;
1259 		if((entry & ARCH_VM_BIGPAGE)) continue;
1260 
1261 		if(pt_ptalloc(newpt, p, 0) != OK)
1262 			panic("pt_ptalloc failed");
1263 		assert(newpt->pt_dir[p] & ARCH_VM_PDE_PRESENT);
1264 
1265 #if defined(__i386__)
1266 		ptaddr_kern = entry & ARCH_VM_ADDR_MASK;
1267 		ptaddr_us = newpt->pt_dir[p] & ARCH_VM_ADDR_MASK;
1268 #elif defined(__arm__)
1269 		ptaddr_kern = entry & ARCH_VM_PDE_MASK;
1270 		ptaddr_us = newpt->pt_dir[p] & ARCH_VM_PDE_MASK;
1271 #endif
1272 
1273 		/* Copy kernel-initialized pagetable contents into our
1274 		 * normally accessible pagetable.
1275 		 */
1276                 if(sys_abscopy(ptaddr_kern, ptaddr_us, VM_PAGE_SIZE) != OK)
1277 			panic("pt_init: abscopy failed");
1278 	}
1279 
1280 	/* Inform kernel vm has a newly built page table. */
1281 	assert(vmproc[VM_PROC_NR].vm_endpoint == VM_PROC_NR);
1282 	pt_bind(newpt, &vmproc[VM_PROC_NR]);
1283 
1284 	pt_init_done = 1;
1285 
1286         /* All OK. */
1287         return;
1288 }
1289 
1290 /*===========================================================================*
1291  *				pt_bind			     		     *
1292  *===========================================================================*/
1293 int pt_bind(pt_t *pt, struct vmproc *who)
1294 {
1295 	int procslot, pdeslot;
1296 	u32_t phys;
1297 	void *pdes;
1298 	int pagedir_pde;
1299 	int slots_per_pde;
1300 	int pages_per_pagedir = ARCH_PAGEDIR_SIZE/VM_PAGE_SIZE;
1301 	struct pdm *pdm;
1302 
1303 	slots_per_pde = ARCH_VM_PT_ENTRIES / pages_per_pagedir;
1304 
1305 	/* Basic sanity checks. */
1306 	assert(who);
1307 	assert(who->vm_flags & VMF_INUSE);
1308 	assert(pt);
1309 
1310 	procslot = who->vm_slot;
1311 	pdm = &pagedir_mappings[procslot/slots_per_pde];
1312 	pdeslot = procslot%slots_per_pde;
1313 	pagedir_pde = pdm->pdeno;
1314 	assert(pdeslot >= 0);
1315 	assert(procslot < ELEMENTS(vmproc));
1316 	assert(pdeslot < ARCH_VM_PT_ENTRIES / pages_per_pagedir);
1317 	assert(pagedir_pde >= 0);
1318 
1319 #if defined(__i386__)
1320 	phys = pt->pt_dir_phys & ARCH_VM_ADDR_MASK;
1321 #elif defined(__arm__)
1322 	phys = pt->pt_dir_phys & ARM_VM_PTE_MASK;
1323 #endif
1324 	assert(pt->pt_dir_phys == phys);
1325 	assert(!(pt->pt_dir_phys % ARCH_PAGEDIR_SIZE));
1326 
1327 	/* Update "page directory pagetable." */
1328 #if defined(__i386__)
1329 	pdm->page_directories[pdeslot] =
1330 		phys | ARCH_VM_PDE_PRESENT|ARCH_VM_PTE_RW;
1331 #elif defined(__arm__)
1332 {
1333 	int i;
1334 	for (i = 0; i < pages_per_pagedir; i++) {
1335 		pdm->page_directories[pdeslot*pages_per_pagedir+i] =
1336 			(phys+i*VM_PAGE_SIZE)
1337 			| ARCH_VM_PTE_PRESENT
1338 			| ARCH_VM_PTE_RW
1339 			| ARM_VM_PTE_CACHED
1340 			| ARCH_VM_PTE_USER; //LSC FIXME
1341 	}
1342 }
1343 #endif
1344 
1345 	/* This is where the PDE's will be visible to the kernel
1346 	 * in its address space.
1347 	 */
1348 	pdes = (void *) (pagedir_pde*ARCH_BIG_PAGE_SIZE +
1349 #if defined(__i386__)
1350 			pdeslot * VM_PAGE_SIZE);
1351 #elif defined(__arm__)
1352 			pdeslot * ARCH_PAGEDIR_SIZE);
1353 #endif
1354 
1355 	/* Tell kernel about new page table root. */
1356 	return sys_vmctl_set_addrspace(who->vm_endpoint, pt->pt_dir_phys , pdes);
1357 }
1358 
1359 /*===========================================================================*
1360  *				pt_free			     		     *
1361  *===========================================================================*/
1362 void pt_free(pt_t *pt)
1363 {
1364 /* Free memory associated with this pagetable. */
1365 	int i;
1366 
1367 	for(i = 0; i < ARCH_VM_DIR_ENTRIES; i++)
1368 		if(pt->pt_pt[i])
1369 			vm_freepages((vir_bytes) pt->pt_pt[i], 1);
1370 
1371 	return;
1372 }
1373 
1374 /*===========================================================================*
1375  *				pt_mapkernel		     		     *
1376  *===========================================================================*/
1377 int pt_mapkernel(pt_t *pt)
1378 {
1379 	int i;
1380 	int kern_pde = kern_start_pde;
1381 	phys_bytes addr, mapped = 0;
1382 
1383         /* Any page table needs to map in the kernel address space. */
1384 	assert(bigpage_ok);
1385 	assert(kern_pde >= 0);
1386 
1387 	/* pt_init() has made sure this is ok. */
1388 	addr = kern_mb_mod->mod_start;
1389 
1390 	/* Actually mapping in kernel */
1391 	while(mapped < kern_size) {
1392 #if defined(__i386__)
1393 		pt->pt_dir[kern_pde] = addr | ARCH_VM_PDE_PRESENT |
1394 			ARCH_VM_BIGPAGE | ARCH_VM_PTE_RW | global_bit;
1395 #elif defined(__arm__)
1396 		pt->pt_dir[kern_pde] = (addr & ARM_VM_SECTION_MASK)
1397 			| ARM_VM_SECTION
1398 			| ARM_VM_SECTION_DOMAIN
1399 			| ARM_VM_SECTION_CACHED
1400 			| ARM_VM_SECTION_SUPER;
1401 #endif
1402 		kern_pde++;
1403 		mapped += ARCH_BIG_PAGE_SIZE;
1404 		addr += ARCH_BIG_PAGE_SIZE;
1405 	}
1406 
1407 	/* Kernel also wants to know about all page directories. */
1408 	{
1409 		int pd;
1410 		for(pd = 0; pd < MAX_PAGEDIR_PDES; pd++) {
1411 			struct pdm *pdm = &pagedir_mappings[pd];
1412 
1413 			assert(pdm->pdeno > 0);
1414 			assert(pdm->pdeno > kern_pde);
1415 			pt->pt_dir[pdm->pdeno] = pdm->val;
1416 		}
1417 	}
1418 
1419 	/* Kernel also wants various mappings of its own. */
1420 	for(i = 0; i < kernmappings; i++) {
1421 		int r;
1422 		if((r=pt_writemap(NULL, pt,
1423 			kern_mappings[i].vir_addr,
1424 			kern_mappings[i].phys_addr,
1425 			kern_mappings[i].len,
1426 			kern_mappings[i].flags, 0)) != OK) {
1427 			return r;
1428 		}
1429 
1430 	}
1431 
1432 	return OK;
1433 }
1434 
1435 int get_vm_self_pages(void) { return vm_self_pages; }
1436