xref: /freebsd/sys/i386/i386/vm_machdep.c (revision 8e6b01171e30297084bb0b4457c4183c2746aacc)
1 /*-
2  * Copyright (c) 1982, 1986 The Regents of the University of California.
3  * Copyright (c) 1989, 1990 William Jolitz
4  * Copyright (c) 1994 John Dyson
5  * All rights reserved.
6  *
7  * This code is derived from software contributed to Berkeley by
8  * the Systems Programming Group of the University of Utah Computer
9  * Science Department, and William Jolitz.
10  *
11  * Redistribution and use in source and binary forms, with or without
12  * modification, are permitted provided that the following conditions
13  * are met:
14  * 1. Redistributions of source code must retain the above copyright
15  *    notice, this list of conditions and the following disclaimer.
16  * 2. Redistributions in binary form must reproduce the above copyright
17  *    notice, this list of conditions and the following disclaimer in the
18  *    documentation and/or other materials provided with the distribution.
19  * 3. All advertising materials mentioning features or use of this software
20  *    must display the following acknowledgement:
21  *	This product includes software developed by the University of
22  *	California, Berkeley and its contributors.
23  * 4. Neither the name of the University nor the names of its contributors
24  *    may be used to endorse or promote products derived from this software
25  *    without specific prior written permission.
26  *
27  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
28  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
29  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
30  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
31  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
32  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
33  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
34  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
35  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
36  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
37  * SUCH DAMAGE.
38  *
39  *	from: @(#)vm_machdep.c	7.3 (Berkeley) 5/13/91
40  *	Utah $Hdr: vm_machdep.c 1.16.1.1 89/06/23$
41  *	$Id: vm_machdep.c,v 1.42 1995/09/03 20:39:22 dyson Exp $
42  */
43 
44 #include "npx.h"
45 #include <sys/param.h>
46 #include <sys/systm.h>
47 #include <sys/proc.h>
48 #include <sys/malloc.h>
49 #include <sys/buf.h>
50 #include <sys/vnode.h>
51 #include <sys/user.h>
52 
53 #include <machine/clock.h>
54 #include <machine/cpu.h>
55 #include <machine/md_var.h>
56 
57 #include <vm/vm.h>
58 #include <vm/vm_kern.h>
59 #include <vm/vm_page.h>
60 
61 #include <i386/isa/isa.h>
62 
63 #ifdef BOUNCE_BUFFERS
64 volatile int	kvasfreecnt;
65 
66 caddr_t		bouncememory;
67 int		bouncepages, bpwait;
68 vm_offset_t	*bouncepa;
69 int		bmwait, bmfreeing;
70 
71 #define BITS_IN_UNSIGNED (8*sizeof(unsigned))
72 int		bounceallocarraysize;
73 unsigned	*bounceallocarray;
74 int		bouncefree;
75 
76 #define SIXTEENMEG (4096*4096)
77 #define MAXBKVA 1024
78 int		maxbkva = MAXBKVA*NBPG;
79 
80 /* special list that can be used at interrupt time for eventual kva free */
81 struct kvasfree {
82 	vm_offset_t addr;
83 	vm_offset_t size;
84 } kvaf[MAXBKVA];
85 
86 
87 vm_offset_t vm_bounce_kva();
88 /*
89  * get bounce buffer pages (count physically contiguous)
90  * (only 1 inplemented now)
91  */
92 vm_offset_t
93 vm_bounce_page_find(count)
94 	int count;
95 {
96 	int bit;
97 	int s,i;
98 
99 	if (count != 1)
100 		panic("vm_bounce_page_find -- no support for > 1 page yet!!!");
101 
102 	s = splbio();
103 retry:
104 	for (i = 0; i < bounceallocarraysize; i++) {
105 		if (bounceallocarray[i] != 0xffffffff) {
106 			bit = ffs(~bounceallocarray[i]);
107 			if (bit) {
108 				bounceallocarray[i] |= 1 << (bit - 1) ;
109 				bouncefree -= count;
110 				splx(s);
111 				return bouncepa[(i * BITS_IN_UNSIGNED + (bit - 1))];
112 			}
113 		}
114 	}
115 	bpwait = 1;
116 	tsleep((caddr_t) &bounceallocarray, PRIBIO, "bncwai", 0);
117 	goto retry;
118 }
119 
120 void
121 vm_bounce_kva_free(addr, size, now)
122 	vm_offset_t addr;
123 	vm_offset_t size;
124 	int now;
125 {
126 	int s = splbio();
127 	kvaf[kvasfreecnt].addr = addr;
128 	kvaf[kvasfreecnt].size = size;
129 	++kvasfreecnt;
130 	if( now) {
131 		/*
132 		 * this will do wakeups
133 		 */
134 		vm_bounce_kva(0,0);
135 	} else {
136 		if (bmwait) {
137 		/*
138 		 * if anyone is waiting on the bounce-map, then wakeup
139 		 */
140 			wakeup((caddr_t) io_map);
141 			bmwait = 0;
142 		}
143 	}
144 	splx(s);
145 }
146 
147 /*
148  * free count bounce buffer pages
149  */
150 void
151 vm_bounce_page_free(pa, count)
152 	vm_offset_t pa;
153 	int count;
154 {
155 	int allocindex;
156 	int index;
157 	int bit;
158 
159 	if (count != 1)
160 		panic("vm_bounce_page_free -- no support for > 1 page yet!!!");
161 
162 	for(index=0;index<bouncepages;index++) {
163 		if( pa == bouncepa[index])
164 			break;
165 	}
166 
167 	if( index == bouncepages)
168 		panic("vm_bounce_page_free: invalid bounce buffer");
169 
170 	allocindex = index / BITS_IN_UNSIGNED;
171 	bit = index % BITS_IN_UNSIGNED;
172 
173 	bounceallocarray[allocindex] &= ~(1 << bit);
174 
175 	bouncefree += count;
176 	if (bpwait) {
177 		bpwait = 0;
178 		wakeup((caddr_t) &bounceallocarray);
179 	}
180 }
181 
182 /*
183  * allocate count bounce buffer kva pages
184  */
185 vm_offset_t
186 vm_bounce_kva(size, waitok)
187 	int size;
188 	int waitok;
189 {
190 	int i;
191 	vm_offset_t kva = 0;
192 	vm_offset_t off;
193 	int s = splbio();
194 more:
195 	if (!bmfreeing && kvasfreecnt) {
196 		bmfreeing = 1;
197 		for (i = 0; i < kvasfreecnt; i++) {
198 			for(off=0;off<kvaf[i].size;off+=NBPG) {
199 				pmap_kremove( kvaf[i].addr + off);
200 			}
201 			kmem_free_wakeup(io_map, kvaf[i].addr,
202 				kvaf[i].size);
203 		}
204 		kvasfreecnt = 0;
205 		bmfreeing = 0;
206 		if( bmwait) {
207 			bmwait = 0;
208 			wakeup( (caddr_t) io_map);
209 		}
210 	}
211 
212 	if( size == 0) {
213 		splx(s);
214 		return NULL;
215 	}
216 
217 	if ((kva = kmem_alloc_pageable(io_map, size)) == 0) {
218 		if( !waitok) {
219 			splx(s);
220 			return NULL;
221 		}
222 		bmwait = 1;
223 		tsleep((caddr_t) io_map, PRIBIO, "bmwait", 0);
224 		goto more;
225 	}
226 	splx(s);
227 	return kva;
228 }
229 
230 /*
231  * same as vm_bounce_kva -- but really allocate (but takes pages as arg)
232  */
233 vm_offset_t
234 vm_bounce_kva_alloc(count)
235 int count;
236 {
237 	int i;
238 	vm_offset_t kva;
239 	vm_offset_t pa;
240 	if( bouncepages == 0) {
241 		kva = (vm_offset_t) malloc(count*NBPG, M_TEMP, M_WAITOK);
242 		return kva;
243 	}
244 	kva = vm_bounce_kva(count*NBPG, 1);
245 	for(i=0;i<count;i++) {
246 		pa = vm_bounce_page_find(1);
247 		pmap_kenter(kva + i * NBPG, pa);
248 	}
249 	return kva;
250 }
251 
252 /*
253  * same as vm_bounce_kva_free -- but really free
254  */
255 void
256 vm_bounce_kva_alloc_free(kva, count)
257 	vm_offset_t kva;
258 	int count;
259 {
260 	int i;
261 	vm_offset_t pa;
262 	if( bouncepages == 0) {
263 		free((caddr_t) kva, M_TEMP);
264 		return;
265 	}
266 	for(i = 0; i < count; i++) {
267 		pa = pmap_kextract(kva + i * NBPG);
268 		vm_bounce_page_free(pa, 1);
269 	}
270 	vm_bounce_kva_free(kva, count*NBPG, 0);
271 }
272 
273 /*
274  * do the things necessary to the struct buf to implement
275  * bounce buffers...  inserted before the disk sort
276  */
277 void
278 vm_bounce_alloc(bp)
279 	struct buf *bp;
280 {
281 	int countvmpg;
282 	vm_offset_t vastart, vaend;
283 	vm_offset_t vapstart, vapend;
284 	vm_offset_t va, kva;
285 	vm_offset_t pa;
286 	int dobounceflag = 0;
287 	int i;
288 
289 	if (bouncepages == 0)
290 		return;
291 
292 	if (bp->b_flags & B_BOUNCE) {
293 		printf("vm_bounce_alloc: called recursively???\n");
294 		return;
295 	}
296 
297 	if (bp->b_bufsize < bp->b_bcount) {
298 		printf(
299 		    "vm_bounce_alloc: b_bufsize(0x%lx) < b_bcount(0x%lx) !!\n",
300 			bp->b_bufsize, bp->b_bcount);
301 		panic("vm_bounce_alloc");
302 	}
303 
304 /*
305  *  This is not really necessary
306  *	if( bp->b_bufsize != bp->b_bcount) {
307  *		printf("size: %d, count: %d\n", bp->b_bufsize, bp->b_bcount);
308  *	}
309  */
310 
311 
312 	vastart = (vm_offset_t) bp->b_data;
313 	vaend = (vm_offset_t) bp->b_data + bp->b_bufsize;
314 
315 	vapstart = i386_trunc_page(vastart);
316 	vapend = i386_round_page(vaend);
317 	countvmpg = (vapend - vapstart) / NBPG;
318 
319 /*
320  * if any page is above 16MB, then go into bounce-buffer mode
321  */
322 	va = vapstart;
323 	for (i = 0; i < countvmpg; i++) {
324 		pa = pmap_kextract(va);
325 		if (pa >= SIXTEENMEG)
326 			++dobounceflag;
327 		if( pa == 0)
328 			panic("vm_bounce_alloc: Unmapped page");
329 		va += NBPG;
330 	}
331 	if (dobounceflag == 0)
332 		return;
333 
334 	if (bouncepages < dobounceflag)
335 		panic("Not enough bounce buffers!!!");
336 
337 /*
338  * allocate a replacement kva for b_addr
339  */
340 	kva = vm_bounce_kva(countvmpg*NBPG, 1);
341 #if 0
342 	printf("%s: vapstart: %x, vapend: %x, countvmpg: %d, kva: %x ",
343 		(bp->b_flags & B_READ) ? "read":"write",
344 			vapstart, vapend, countvmpg, kva);
345 #endif
346 	va = vapstart;
347 	for (i = 0; i < countvmpg; i++) {
348 		pa = pmap_kextract(va);
349 		if (pa >= SIXTEENMEG) {
350 			/*
351 			 * allocate a replacement page
352 			 */
353 			vm_offset_t bpa = vm_bounce_page_find(1);
354 			pmap_kenter(kva + (NBPG * i), bpa);
355 #if 0
356 			printf("r(%d): (%x,%x,%x) ", i, va, pa, bpa);
357 #endif
358 			/*
359 			 * if we are writing, the copy the data into the page
360 			 */
361 			if ((bp->b_flags & B_READ) == 0) {
362 				bcopy((caddr_t) va, (caddr_t) kva + (NBPG * i), NBPG);
363 			}
364 		} else {
365 			/*
366 			 * use original page
367 			 */
368 			pmap_kenter(kva + (NBPG * i), pa);
369 		}
370 		va += NBPG;
371 	}
372 
373 /*
374  * flag the buffer as being bounced
375  */
376 	bp->b_flags |= B_BOUNCE;
377 /*
378  * save the original buffer kva
379  */
380 	bp->b_savekva = bp->b_data;
381 /*
382  * put our new kva into the buffer (offset by original offset)
383  */
384 	bp->b_data = (caddr_t) (((vm_offset_t) kva) |
385 				((vm_offset_t) bp->b_savekva & (NBPG - 1)));
386 #if 0
387 	printf("b_savekva: %x, newva: %x\n", bp->b_savekva, bp->b_data);
388 #endif
389 	return;
390 }
391 
392 /*
393  * hook into biodone to free bounce buffer
394  */
395 void
396 vm_bounce_free(bp)
397 	struct buf *bp;
398 {
399 	int i;
400 	vm_offset_t origkva, bouncekva, bouncekvaend;
401 
402 /*
403  * if this isn't a bounced buffer, then just return
404  */
405 	if ((bp->b_flags & B_BOUNCE) == 0)
406 		return;
407 
408 /*
409  *  This check is not necessary
410  *	if (bp->b_bufsize != bp->b_bcount) {
411  *		printf("vm_bounce_free: b_bufsize=%d, b_bcount=%d\n",
412  *			bp->b_bufsize, bp->b_bcount);
413  *	}
414  */
415 
416 	origkva = (vm_offset_t) bp->b_savekva;
417 	bouncekva = (vm_offset_t) bp->b_data;
418 /*
419 	printf("free: %d ", bp->b_bufsize);
420 */
421 
422 /*
423  * check every page in the kva space for b_addr
424  */
425 	for (i = 0; i < bp->b_bufsize; ) {
426 		vm_offset_t mybouncepa;
427 		vm_offset_t copycount;
428 
429 		copycount = i386_round_page(bouncekva + 1) - bouncekva;
430 		mybouncepa = pmap_kextract(i386_trunc_page(bouncekva));
431 
432 /*
433  * if this is a bounced pa, then process as one
434  */
435 		if ( mybouncepa != pmap_kextract( i386_trunc_page( origkva))) {
436 			vm_offset_t tocopy = copycount;
437 			if (i + tocopy > bp->b_bufsize)
438 				tocopy = bp->b_bufsize - i;
439 /*
440  * if this is a read, then copy from bounce buffer into original buffer
441  */
442 			if (bp->b_flags & B_READ)
443 				bcopy((caddr_t) bouncekva, (caddr_t) origkva, tocopy);
444 /*
445  * free the bounce allocation
446  */
447 
448 /*
449 			printf("(kva: %x, pa: %x)", bouncekva, mybouncepa);
450 */
451 			vm_bounce_page_free(mybouncepa, 1);
452 		}
453 
454 		origkva += copycount;
455 		bouncekva += copycount;
456 		i += copycount;
457 	}
458 
459 /*
460 	printf("\n");
461 */
462 /*
463  * add the old kva into the "to free" list
464  */
465 
466 	bouncekva= i386_trunc_page((vm_offset_t) bp->b_data);
467 	bouncekvaend= i386_round_page((vm_offset_t)bp->b_data + bp->b_bufsize);
468 
469 /*
470 	printf("freeva: %d\n", (bouncekvaend - bouncekva) / NBPG);
471 */
472 	vm_bounce_kva_free( bouncekva, (bouncekvaend - bouncekva), 0);
473 	bp->b_data = bp->b_savekva;
474 	bp->b_savekva = 0;
475 	bp->b_flags &= ~B_BOUNCE;
476 
477 	return;
478 }
479 
480 
481 /*
482  * init the bounce buffer system
483  */
484 void
485 vm_bounce_init()
486 {
487 	int i;
488 
489 	kvasfreecnt = 0;
490 
491 	if (bouncepages == 0)
492 		return;
493 
494 	bounceallocarraysize = (bouncepages + BITS_IN_UNSIGNED - 1) / BITS_IN_UNSIGNED;
495 	bounceallocarray = malloc(bounceallocarraysize * sizeof(unsigned), M_TEMP, M_NOWAIT);
496 
497 	if (!bounceallocarray)
498 		panic("Cannot allocate bounce resource array");
499 
500 	bouncepa = malloc(bouncepages * sizeof(vm_offset_t), M_TEMP, M_NOWAIT);
501 	if (!bouncepa)
502 		panic("Cannot allocate physical memory array");
503 
504 	for(i=0;i<bounceallocarraysize;i++) {
505 		bounceallocarray[i] = 0xffffffff;
506 	}
507 
508 	for(i=0;i<bouncepages;i++) {
509 		vm_offset_t pa;
510 		if( (pa = pmap_kextract((vm_offset_t) bouncememory + i * NBPG)) >= SIXTEENMEG)
511 			panic("bounce memory out of range");
512 		if( pa == 0)
513 			panic("bounce memory not resident");
514 		bouncepa[i] = pa;
515 		bounceallocarray[i/(8*sizeof(int))] &= ~(1<<(i%(8*sizeof(int))));
516 	}
517 	bouncefree = bouncepages;
518 
519 }
520 #endif /* BOUNCE_BUFFERS */
521 /*
522  * quick version of vm_fault
523  */
524 
525 void
526 vm_fault_quick( v, prot)
527 	vm_offset_t v;
528 	int prot;
529 {
530 	if (prot & VM_PROT_WRITE)
531 		subyte((char *)v, fubyte((char *)v));
532 	else
533 		(void) fubyte((char *)v);
534 }
535 
536 
537 /*
538  * Finish a fork operation, with process p2 nearly set up.
539  * Copy and update the kernel stack and pcb, making the child
540  * ready to run, and marking it so that it can return differently
541  * than the parent.  Returns 1 in the child process, 0 in the parent.
542  * We currently double-map the user area so that the stack is at the same
543  * address in each process; in the future we will probably relocate
544  * the frame pointers on the stack after copying.
545  */
546 int
547 cpu_fork(p1, p2)
548 	register struct proc *p1, *p2;
549 {
550 	register struct user *up = p2->p_addr;
551 	int offset;
552 
553 	/*
554 	 * Copy pcb and stack from proc p1 to p2.
555 	 * We do this as cheaply as possible, copying only the active
556 	 * part of the stack.  The stack and pcb need to agree;
557 	 * this is tricky, as the final pcb is constructed by savectx,
558 	 * but its frame isn't yet on the stack when the stack is copied.
559 	 * swtch compensates for this when the child eventually runs.
560 	 * This should be done differently, with a single call
561 	 * that copies and updates the pcb+stack,
562 	 * replacing the bcopy and savectx.
563 	 */
564 	p2->p_addr->u_pcb = p1->p_addr->u_pcb;
565 	offset = mvesp() - (int)kstack;
566 	bcopy((caddr_t)kstack + offset, (caddr_t)p2->p_addr + offset,
567 	    (unsigned) ctob(UPAGES) - offset);
568 	p2->p_md.md_regs = p1->p_md.md_regs;
569 
570 	pmap_activate(&p2->p_vmspace->vm_pmap, &up->u_pcb);
571 
572 	/*
573 	 *
574 	 * Arrange for a non-local goto when the new process
575 	 * is started, to resume here, returning nonzero from setjmp.
576 	 */
577 	if (savectx(&up->u_pcb, 1)) {
578 		/*
579 		 * Return 1 in child.
580 		 */
581 		return (1);
582 	}
583 	return (0);
584 }
585 
586 void
587 cpu_exit(p)
588 	register struct proc *p;
589 {
590 
591 #if NNPX > 0
592 	npxexit(p);
593 #endif	/* NNPX */
594 	cnt.v_swtch++;
595 	cpu_switch(p);
596 	panic("cpu_exit");
597 }
598 
599 void
600 cpu_wait(p) struct proc *p; {
601 /*	extern vm_map_t upages_map; */
602 
603 	/* drop per-process resources */
604  	pmap_remove(vm_map_pmap(u_map), (vm_offset_t) p->p_addr,
605 		((vm_offset_t) p->p_addr) + ctob(UPAGES));
606 	kmem_free(u_map, (vm_offset_t)p->p_addr, ctob(UPAGES));
607 	vmspace_free(p->p_vmspace);
608 }
609 
610 /*
611  * Dump the machine specific header information at the start of a core dump.
612  */
613 int
614 cpu_coredump(p, vp, cred)
615 	struct proc *p;
616 	struct vnode *vp;
617 	struct ucred *cred;
618 {
619 
620 	return (vn_rdwr(UIO_WRITE, vp, (caddr_t) p->p_addr, ctob(UPAGES),
621 	    (off_t)0, UIO_SYSSPACE, IO_NODELOCKED|IO_UNIT, cred, (int *)NULL,
622 	    p));
623 }
624 
625 /*
626  * Set a red zone in the kernel stack after the u. area.
627  */
628 void
629 setredzone(pte, vaddr)
630 	u_short *pte;
631 	caddr_t vaddr;
632 {
633 /* eventually do this by setting up an expand-down stack segment
634    for ss0: selector, allowing stack access down to top of u.
635    this means though that protection violations need to be handled
636    thru a double fault exception that must do an integral task
637    switch to a known good context, within which a dump can be
638    taken. a sensible scheme might be to save the initial context
639    used by sched (that has physical memory mapped 1:1 at bottom)
640    and take the dump while still in mapped mode */
641 }
642 
643 /*
644  * Move pages from one kernel virtual address to another.
645  * Both addresses are assumed to reside in the Sysmap,
646  * and size must be a multiple of CLSIZE.
647  */
648 
649 void
650 pagemove(from, to, size)
651 	register caddr_t from, to;
652 	int size;
653 {
654 	register vm_offset_t pa;
655 
656 	if (size & CLOFSET)
657 		panic("pagemove");
658 	while (size > 0) {
659 		pa = pmap_kextract((vm_offset_t)from);
660 		if (pa == 0)
661 			panic("pagemove 2");
662 		if (pmap_kextract((vm_offset_t)to) != 0)
663 			panic("pagemove 3");
664 		pmap_kremove((vm_offset_t)from);
665 		pmap_kenter((vm_offset_t)to, pa);
666 		from += PAGE_SIZE;
667 		to += PAGE_SIZE;
668 		size -= PAGE_SIZE;
669 	}
670 }
671 
672 /*
673  * Convert kernel VA to physical address
674  */
675 u_long
676 kvtop(void *addr)
677 {
678 	vm_offset_t va;
679 
680 	va = pmap_kextract((vm_offset_t)addr);
681 	if (va == 0)
682 		panic("kvtop: zero page frame");
683 	return((int)va);
684 }
685 
686 /*
687  * Map an IO request into kernel virtual address space.
688  *
689  * All requests are (re)mapped into kernel VA space.
690  * Notice that we use b_bufsize for the size of the buffer
691  * to be mapped.  b_bcount might be modified by the driver.
692  */
693 void
694 vmapbuf(bp)
695 	register struct buf *bp;
696 {
697 	register int npf;
698 	register caddr_t addr;
699 	int off;
700 	vm_offset_t kva;
701 	vm_offset_t pa, v;
702 
703 	if ((bp->b_flags & B_PHYS) == 0)
704 		panic("vmapbuf");
705 
706 	/*
707 	 * this is the kva that is to be used for
708 	 * the temporary kernel mapping
709 	 */
710 	kva = (vm_offset_t) bp->b_saveaddr;
711 
712 	for (addr = (caddr_t)trunc_page(bp->b_data);
713 		addr < bp->b_data + bp->b_bufsize;
714 		addr += PAGE_SIZE) {
715 
716 /*
717  * do the vm_fault if needed, do the copy-on-write thing when
718  * reading stuff off device into memory.
719  */
720 		vm_fault_quick(addr,
721 			(bp->b_flags&B_READ)?(VM_PROT_READ|VM_PROT_WRITE):VM_PROT_READ);
722 		pa = pmap_kextract((vm_offset_t) addr);
723 		if (pa == 0)
724 			panic("vmapbuf: page not present");
725 /*
726  * hold the data page
727  */
728 #ifdef DIAGNOSTIC
729 		if( VM_PAGE_TO_PHYS(PHYS_TO_VM_PAGE(pa)) != pa)
730 			panic("vmapbuf: confused PHYS_TO_VM_PAGE mapping");
731 #endif
732 		vm_page_hold(PHYS_TO_VM_PAGE(pa));
733 	}
734 
735 	addr = bp->b_saveaddr = bp->b_data;
736 	off = (int)addr & PGOFSET;
737 	npf = btoc(round_page(bp->b_bufsize + off));
738 	bp->b_data = (caddr_t) (kva + off);
739 	while (npf--) {
740 		pa = pmap_kextract((vm_offset_t)addr);
741 		if (pa == 0)
742 			panic("vmapbuf: null page frame");
743 		pmap_kenter(kva, trunc_page(pa));
744 		addr += PAGE_SIZE;
745 		kva += PAGE_SIZE;
746 	}
747 }
748 
749 /*
750  * Free the io map PTEs associated with this IO operation.
751  * We also invalidate the TLB entries and restore the original b_addr.
752  */
753 void
754 vunmapbuf(bp)
755 	register struct buf *bp;
756 {
757 	register caddr_t addr;
758 	vm_offset_t v,pa;
759 
760 	if ((bp->b_flags & B_PHYS) == 0)
761 		panic("vunmapbuf");
762 
763 	for (addr = (caddr_t)trunc_page((vm_offset_t) bp->b_data);
764 		addr < bp->b_data + bp->b_bufsize;
765 		addr += NBPG)
766 		pmap_kremove((vm_offset_t) addr);
767 
768 	bp->b_data = bp->b_saveaddr;
769 	bp->b_saveaddr = NULL;
770 
771 /*
772  * unhold the pde, and data pages
773  */
774 	for (addr = (caddr_t)trunc_page((vm_offset_t) bp->b_data);
775 		addr < bp->b_data + bp->b_bufsize;
776 		addr += NBPG) {
777 	/*
778 	 * release the data page
779 	 */
780 		pa = pmap_kextract((vm_offset_t) addr);
781 		vm_page_unhold(PHYS_TO_VM_PAGE(pa));
782 	}
783 }
784 
785 /*
786  * Force reset the processor by invalidating the entire address space!
787  */
788 void
789 cpu_reset() {
790 
791 	/*
792 	 * Attempt to do a CPU reset via the keyboard controller,
793 	 * do not turn of the GateA20, as any machine that fails
794 	 * to do the reset here would then end up in no man's land.
795 	 */
796 
797 #ifndef BROKEN_KEYBOARD_RESET
798 	outb(IO_KBD + 4, 0xFE);
799 	DELAY(500000);	/* wait 0.5 sec to see if that did it */
800 	printf("Keyboard reset did not work, attempting CPU shutdown\n");
801 	DELAY(1000000);	/* wait 1 sec for printf to complete */
802 #endif
803 
804 	/* force a shutdown by unmapping entire address space ! */
805 	bzero((caddr_t) PTD, NBPG);
806 
807 	/* "good night, sweet prince .... <THUNK!>" */
808 	pmap_update();
809 	/* NOTREACHED */
810 	while(1);
811 }
812 
813 /*
814  * Grow the user stack to allow for 'sp'. This version grows the stack in
815  *	chunks of SGROWSIZ.
816  */
817 int
818 grow(p, sp)
819 	struct proc *p;
820 	u_int sp;
821 {
822 	unsigned int nss;
823 	caddr_t v;
824 	struct vmspace *vm = p->p_vmspace;
825 
826 	if ((caddr_t)sp <= vm->vm_maxsaddr || (unsigned)sp >= (unsigned)USRSTACK)
827 	    return (1);
828 
829 	nss = roundup(USRSTACK - (unsigned)sp, PAGE_SIZE);
830 
831 	if (nss > p->p_rlimit[RLIMIT_STACK].rlim_cur)
832 		return (0);
833 
834 	if (vm->vm_ssize && roundup(vm->vm_ssize << PAGE_SHIFT,
835 	    SGROWSIZ) < nss) {
836 		int grow_amount;
837 		/*
838 		 * If necessary, grow the VM that the stack occupies
839 		 * to allow for the rlimit. This allows us to not have
840 		 * to allocate all of the VM up-front in execve (which
841 		 * is expensive).
842 		 * Grow the VM by the amount requested rounded up to
843 		 * the nearest SGROWSIZ to provide for some hysteresis.
844 		 */
845 		grow_amount = roundup((nss - (vm->vm_ssize << PAGE_SHIFT)), SGROWSIZ);
846 		v = (char *)USRSTACK - roundup(vm->vm_ssize << PAGE_SHIFT,
847 		    SGROWSIZ) - grow_amount;
848 		/*
849 		 * If there isn't enough room to extend by SGROWSIZ, then
850 		 * just extend to the maximum size
851 		 */
852 		if (v < vm->vm_maxsaddr) {
853 			v = vm->vm_maxsaddr;
854 			grow_amount = MAXSSIZ - (vm->vm_ssize << PAGE_SHIFT);
855 		}
856 		if ((grow_amount == 0) || (vm_map_find(&vm->vm_map, NULL, 0, (vm_offset_t *)&v,
857 		    grow_amount, FALSE) != KERN_SUCCESS)) {
858 			return (0);
859 		}
860 		vm->vm_ssize += grow_amount >> PAGE_SHIFT;
861 	}
862 
863 	return (1);
864 }
865 
866 /*
867  * prototype routine to implement the pre-zeroed page mechanism
868  * this routine is called from the idle loop.
869  */
870 int
871 vm_page_zero_idle() {
872 	vm_page_t m;
873 	if ((cnt.v_free_count > cnt.v_interrupt_free_min) &&
874 		(m = vm_page_queue_free.tqh_first)) {
875 		TAILQ_REMOVE(&vm_page_queue_free, m, pageq);
876 		enable_intr();
877 		pmap_zero_page(VM_PAGE_TO_PHYS(m));
878 		disable_intr();
879 		TAILQ_INSERT_HEAD(&vm_page_queue_zero, m, pageq);
880 		return 1;
881 	}
882 	return 0;
883 }
884