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