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