xref: /openbsd-src/sys/uvm/uvm_amap.c (revision b2ea75c1b17e1a9a339660e7ed45cd24946b230e)
1 /*	$OpenBSD: uvm_amap.c,v 1.9 2001/07/18 10:47:05 art Exp $	*/
2 /*	$NetBSD: uvm_amap.c,v 1.22 1999/09/12 01:17:33 chs Exp $	*/
3 
4 /*
5  *
6  * Copyright (c) 1997 Charles D. Cranor and Washington University.
7  * All rights reserved.
8  *
9  * Redistribution and use in source and binary forms, with or without
10  * modification, are permitted provided that the following conditions
11  * are met:
12  * 1. Redistributions of source code must retain the above copyright
13  *    notice, this list of conditions and the following disclaimer.
14  * 2. Redistributions in binary form must reproduce the above copyright
15  *    notice, this list of conditions and the following disclaimer in the
16  *    documentation and/or other materials provided with the distribution.
17  * 3. All advertising materials mentioning features or use of this software
18  *    must display the following acknowledgement:
19  *      This product includes software developed by Charles D. Cranor and
20  *      Washington University.
21  * 4. The name of the author may not be used to endorse or promote products
22  *    derived from this software without specific prior written permission.
23  *
24  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
25  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
26  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
27  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
28  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
29  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
30  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
31  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
33  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34  */
35 
36 /*
37  * uvm_amap.c: amap operations
38  */
39 
40 /*
41  * this file contains functions that perform operations on amaps.  see
42  * uvm_amap.h for a brief explanation of the role of amaps in uvm.
43  */
44 
45 #undef UVM_AMAP_INLINE		/* enable/disable amap inlines */
46 
47 #include <sys/param.h>
48 #include <sys/systm.h>
49 #include <sys/proc.h>
50 #include <sys/malloc.h>
51 #include <sys/pool.h>
52 
53 #include <vm/vm.h>
54 #include <vm/vm_page.h>
55 #include <vm/vm_kern.h>
56 
57 #define UVM_AMAP_C		/* ensure disabled inlines are in */
58 #include <uvm/uvm.h>
59 #include <uvm/uvm_swap.h>
60 
61 /*
62  * pool for allocation of vm_map structures.  note that the pool has
63  * its own simplelock for its protection.  also note that in order to
64  * avoid an endless loop, the amap pool's allocator cannot allocate
65  * memory from an amap (it currently goes through the kernel uobj, so
66  * we are ok).
67  */
68 
69 struct pool uvm_amap_pool;
70 
71 /*
72  * local functions
73  */
74 
75 static struct vm_amap *amap_alloc1 __P((int, int, int));
76 
77 #ifdef UVM_AMAP_PPREF
78 /*
79  * what is ppref?   ppref is an _optional_ amap feature which is used
80  * to keep track of reference counts on a per-page basis.  it is enabled
81  * when UVM_AMAP_PPREF is defined.
82  *
83  * when enabled, an array of ints is allocated for the pprefs.  this
84  * array is allocated only when a partial reference is added to the
85  * map (either by unmapping part of the amap, or gaining a reference
86  * to only a part of an amap).  if the malloc of the array fails
87  * (M_NOWAIT), then we set the array pointer to PPREF_NONE to indicate
88  * that we tried to do ppref's but couldn't alloc the array so just
89  * give up (after all, this is an optional feature!).
90  *
91  * the array is divided into page sized "chunks."   for chunks of length 1,
92  * the chunk reference count plus one is stored in that chunk's slot.
93  * for chunks of length > 1 the first slot contains (the reference count
94  * plus one) * -1.    [the negative value indicates that the length is
95  * greater than one.]   the second slot of the chunk contains the length
96  * of the chunk.   here is an example:
97  *
98  * actual REFS:  2  2  2  2  3  1  1  0  0  0  4  4  0  1  1  1
99  *       ppref: -3  4  x  x  4 -2  2 -1  3  x -5  2  1 -2  3  x
100  *              <----------><-><----><-------><----><-><------->
101  * (x = don't care)
102  *
103  * this allows us to allow one int to contain the ref count for the whole
104  * chunk.    note that the "plus one" part is needed because a reference
105  * count of zero is neither positive or negative (need a way to tell
106  * if we've got one zero or a bunch of them).
107  *
108  * here are some in-line functions to help us.
109  */
110 
111 static __inline void pp_getreflen __P((int *, int, int *, int *));
112 static __inline void pp_setreflen __P((int *, int, int, int));
113 
114 /*
115  * pp_getreflen: get the reference and length for a specific offset
116  *
117  * => ppref's amap must be locked
118  */
119 static __inline void
120 pp_getreflen(ppref, offset, refp, lenp)
121 	int *ppref, offset, *refp, *lenp;
122 {
123 
124 	if (ppref[offset] > 0) {		/* chunk size must be 1 */
125 		*refp = ppref[offset] - 1;	/* don't forget to adjust */
126 		*lenp = 1;
127 	} else {
128 		*refp = (ppref[offset] * -1) - 1;
129 		*lenp = ppref[offset+1];
130 	}
131 }
132 
133 /*
134  * pp_setreflen: set the reference and length for a specific offset
135  *
136  * => ppref's amap must be locked
137  */
138 static __inline void
139 pp_setreflen(ppref, offset, ref, len)
140 	int *ppref, offset, ref, len;
141 {
142 	if (len == 1) {
143 		ppref[offset] = ref + 1;
144 	} else {
145 		ppref[offset] = (ref + 1) * -1;
146 		ppref[offset+1] = len;
147 	}
148 }
149 #endif
150 
151 /*
152  * amap_init: called at boot time to init global amap data structures
153  */
154 
155 void
156 amap_init()
157 
158 {
159 	/*
160 	 * Initialize the vm_amap pool.
161 	 */
162 	pool_init(&uvm_amap_pool, sizeof(struct vm_amap), 0, 0, 0,
163 	    "amappl", 0, pool_page_alloc_nointr, pool_page_free_nointr,
164 	    M_UVMAMAP);
165 }
166 
167 /*
168  * amap_alloc1: internal function that allocates an amap, but does not
169  *	init the overlay.
170  *
171  * => lock on returned amap is init'd
172  */
173 static inline struct vm_amap *
174 amap_alloc1(slots, padslots, waitf)
175 	int slots, padslots, waitf;
176 {
177 	struct vm_amap *amap;
178 	int totalslots = slots + padslots;
179 
180 	amap = pool_get(&uvm_amap_pool, (waitf == M_WAITOK) ? PR_WAITOK : 0);
181 	if (amap == NULL)
182 		return(NULL);
183 
184 	simple_lock_init(&amap->am_l);
185 	amap->am_ref = 1;
186 	amap->am_flags = 0;
187 #ifdef UVM_AMAP_PPREF
188 	amap->am_ppref = NULL;
189 #endif
190 	amap->am_maxslot = totalslots;
191 	amap->am_nslot = slots;
192 	amap->am_nused = 0;
193 
194 	amap->am_slots = malloc(totalslots * sizeof(int), M_UVMAMAP,
195 	    waitf);
196 	if (amap->am_slots == NULL)
197 		goto fail1;
198 
199 	amap->am_bckptr = malloc(totalslots * sizeof(int), M_UVMAMAP, waitf);
200 	if (amap->am_bckptr == NULL)
201 		goto fail2;
202 
203 	amap->am_anon = malloc(totalslots * sizeof(struct vm_anon *),
204 	    M_UVMAMAP, waitf);
205 	if (amap->am_anon == NULL)
206 		goto fail3;
207 
208 	return(amap);
209 
210 fail3:
211 	free(amap->am_bckptr, M_UVMAMAP);
212 fail2:
213 	free(amap->am_slots, M_UVMAMAP);
214 fail1:
215 	pool_put(&uvm_amap_pool, amap);
216 	return (NULL);
217 }
218 
219 /*
220  * amap_alloc: allocate an amap to manage "sz" bytes of anonymous VM
221  *
222  * => caller should ensure sz is a multiple of PAGE_SIZE
223  * => reference count to new amap is set to one
224  * => new amap is returned unlocked
225  */
226 
227 struct vm_amap *
228 amap_alloc(sz, padsz, waitf)
229 	vaddr_t sz, padsz;
230 	int waitf;
231 {
232 	struct vm_amap *amap;
233 	int slots, padslots;
234 	UVMHIST_FUNC("amap_alloc"); UVMHIST_CALLED(maphist);
235 
236 	AMAP_B2SLOT(slots, sz);		/* load slots */
237 	AMAP_B2SLOT(padslots, padsz);
238 
239 	amap = amap_alloc1(slots, padslots, waitf);
240 	if (amap)
241 		memset(amap->am_anon, 0, (slots + padslots) * sizeof(struct vm_anon *));
242 
243 	UVMHIST_LOG(maphist,"<- done, amap = 0x%x, sz=%d", amap, sz, 0, 0);
244 	return(amap);
245 }
246 
247 
248 /*
249  * amap_free: free an amap
250  *
251  * => the amap must be locked (mainly for simplelock accounting)
252  * => the amap should have a zero reference count and be empty
253  */
254 void
255 amap_free(amap)
256 	struct vm_amap *amap;
257 {
258 	UVMHIST_FUNC("amap_free"); UVMHIST_CALLED(maphist);
259 
260 #ifdef DIAGNOSTIC
261 	if (amap->am_ref || amap->am_nused)
262 		panic("amap_free");
263 #endif
264 
265 	FREE(amap->am_slots, M_UVMAMAP);
266 	FREE(amap->am_bckptr, M_UVMAMAP);
267 	FREE(amap->am_anon, M_UVMAMAP);
268 #ifdef UVM_AMAP_PPREF
269 	if (amap->am_ppref && amap->am_ppref != PPREF_NONE)
270 		FREE(amap->am_ppref, M_UVMAMAP);
271 #endif
272 	amap_unlock(amap);	/* mainly for lock debugging */
273 	pool_put(&uvm_amap_pool, amap);
274 
275 	UVMHIST_LOG(maphist,"<- done, freed amap = 0x%x", amap, 0, 0, 0);
276 }
277 
278 /*
279  * amap_extend: extend the size of an amap (if needed)
280  *
281  * => called from uvm_map when we want to extend an amap to cover
282  *    a new mapping (rather than allocate a new one)
283  * => amap should be unlocked (we will lock it)
284  * => to safely extend an amap it should have a reference count of
285  *    one (thus it can't be shared)
286  * => XXXCDC: needs a waitflag or failure return value?
287  * => XXXCDC: support padding at this level?
288  */
289 void
290 amap_extend(entry, addsize)
291 	vm_map_entry_t entry;
292 	vsize_t addsize;
293 {
294 	struct vm_amap *amap = entry->aref.ar_amap;
295 	int slotoff = entry->aref.ar_pageoff;
296 	int slotmapped, slotadd, slotneed;
297 #ifdef UVM_AMAP_PPREF
298 	int *newppref, *oldppref;
299 #endif
300 	u_int *newsl, *newbck, *oldsl, *oldbck;
301 	struct vm_anon **newover, **oldover;
302 	int slotadded;
303 	UVMHIST_FUNC("amap_extend"); UVMHIST_CALLED(maphist);
304 
305 	UVMHIST_LOG(maphist, "  (entry=0x%x, addsize=0x%x)", entry,addsize,0,0);
306 
307 	/*
308 	 * first, determine how many slots we need in the amap.  don't
309 	 * forget that ar_pageoff could be non-zero: this means that
310 	 * there are some unused slots before us in the amap.
311 	 */
312 
313 	amap_lock(amap);					/* lock! */
314 
315 	AMAP_B2SLOT(slotmapped, entry->end - entry->start); /* slots mapped */
316 	AMAP_B2SLOT(slotadd, addsize);			/* slots to add */
317 	slotneed = slotoff + slotmapped + slotadd;
318 
319 	/*
320 	 * case 1: we already have enough slots in the map and thus
321 	 * only need to bump the reference counts on the slots we are
322 	 * adding.
323 	 */
324 
325 	if (amap->am_nslot >= slotneed) {
326 #ifdef UVM_AMAP_PPREF
327 		if (amap->am_ppref && amap->am_ppref != PPREF_NONE) {
328 			amap_pp_adjref(amap, slotoff + slotmapped, addsize, 1);
329 		}
330 #endif
331 		amap_unlock(amap);
332 		UVMHIST_LOG(maphist,"<- done (case 1), amap = 0x%x, sltneed=%d",
333 		    amap, slotneed, 0, 0);
334 		return;				/* done! */
335 	}
336 
337 	/*
338 	 * case 2: we pre-allocated slots for use and we just need to
339 	 * bump nslot up to take account for these slots.
340 	 */
341 	if (amap->am_maxslot >= slotneed) {
342 #ifdef UVM_AMAP_PPREF
343 		if (amap->am_ppref && amap->am_ppref != PPREF_NONE) {
344 			if ((slotoff + slotmapped) < amap->am_nslot)
345 				amap_pp_adjref(amap, slotoff + slotmapped,
346 				    (amap->am_nslot - (slotoff + slotmapped)) <<
347 				    PAGE_SHIFT, 1);
348 			pp_setreflen(amap->am_ppref, amap->am_nslot, 1,
349 			   slotneed - amap->am_nslot);
350 		}
351 #endif
352 		amap->am_nslot = slotneed;
353 		amap_unlock(amap);
354 		/*
355 		 * no need to zero am_anon since that was done at
356 		 * alloc time and we never shrink an allocation.
357 		 */
358 		UVMHIST_LOG(maphist,"<- done (case 2), amap = 0x%x, slotneed=%d",
359 		    amap, slotneed, 0, 0);
360 		return;
361 	}
362 
363 	/*
364 	 * case 3: we need to malloc a new amap and copy all the amap
365 	 * data over from old amap to the new one.
366 	 *
367 	 * XXXCDC: could we take advantage of a kernel realloc()?
368 	 */
369 
370 	amap_unlock(amap);	/* unlock in case we sleep in malloc */
371 #ifdef UVM_AMAP_PPREF
372 	newppref = NULL;
373 	if (amap->am_ppref && amap->am_ppref != PPREF_NONE) {
374 		MALLOC(newppref, int *, slotneed * sizeof(int), M_UVMAMAP,
375 		    M_NOWAIT);
376 		if (newppref == NULL) {
377 			/* give up if malloc fails */
378 			FREE(amap->am_ppref, M_UVMAMAP);
379 			    amap->am_ppref = PPREF_NONE;
380 		}
381 	}
382 #endif
383 	MALLOC(newsl, int *, slotneed * sizeof(int), M_UVMAMAP, M_WAITOK);
384 	MALLOC(newbck, int *, slotneed * sizeof(int), M_UVMAMAP, M_WAITOK);
385 	MALLOC(newover, struct vm_anon **, slotneed * sizeof(struct vm_anon *),
386 						   M_UVMAMAP, M_WAITOK);
387 	amap_lock(amap);			/* re-lock! */
388 
389 #ifdef DIAGNOSTIC
390 	if (amap->am_maxslot >= slotneed)
391 		panic("amap_extend: amap changed during malloc");
392 #endif
393 
394 	/*
395 	 * now copy everything over to new malloc'd areas...
396 	 */
397 
398 	slotadded = slotneed - amap->am_nslot;
399 
400 	/* do am_slots */
401 	oldsl = amap->am_slots;
402 	memcpy(newsl, oldsl, sizeof(int) * amap->am_nused);
403 	amap->am_slots = newsl;
404 
405 	/* do am_anon */
406 	oldover = amap->am_anon;
407 	memcpy(newover, oldover, sizeof(struct vm_anon *) * amap->am_nslot);
408 	memset(newover + amap->am_nslot, 0, sizeof(struct vm_anon *) * slotadded);
409 	amap->am_anon = newover;
410 
411 	/* do am_bckptr */
412 	oldbck = amap->am_bckptr;
413 	memcpy(newbck, oldbck, sizeof(int) * amap->am_nslot);
414 	memset(newbck + amap->am_nslot, 0, sizeof(int) * slotadded); /* XXX: needed? */
415 	amap->am_bckptr = newbck;
416 
417 #ifdef UVM_AMAP_PPREF
418 	/* do ppref */
419 	oldppref = amap->am_ppref;
420 	if (newppref) {
421 		memcpy(newppref, oldppref, sizeof(int) * amap->am_nslot);
422 		memset(newppref + amap->am_nslot, 0, sizeof(int) * slotadded);
423 		amap->am_ppref = newppref;
424 		if ((slotoff + slotmapped) < amap->am_nslot)
425 			amap_pp_adjref(amap, slotoff + slotmapped,
426 			    (amap->am_nslot - (slotoff + slotmapped)) <<
427 			    PAGE_SHIFT, 1);
428 		pp_setreflen(newppref, amap->am_nslot, 1, slotadded);
429 	}
430 #endif
431 
432 	/* update master values */
433 	amap->am_nslot = slotneed;
434 	amap->am_maxslot = slotneed;
435 
436 	/* unlock */
437 	amap_unlock(amap);
438 
439 	/* and free */
440 	FREE(oldsl, M_UVMAMAP);
441 	FREE(oldbck, M_UVMAMAP);
442 	FREE(oldover, M_UVMAMAP);
443 #ifdef UVM_AMAP_PPREF
444 	if (oldppref && oldppref != PPREF_NONE)
445 		FREE(oldppref, M_UVMAMAP);
446 #endif
447 	UVMHIST_LOG(maphist,"<- done (case 3), amap = 0x%x, slotneed=%d",
448 	    amap, slotneed, 0, 0);
449 }
450 
451 /*
452  * amap_share_protect: change protection of anons in a shared amap
453  *
454  * for shared amaps, given the current data structure layout, it is
455  * not possible for us to directly locate all maps referencing the
456  * shared anon (to change the protection).  in order to protect data
457  * in shared maps we use pmap_page_protect().  [this is useful for IPC
458  * mechanisms like map entry passing that may want to write-protect
459  * all mappings of a shared amap.]  we traverse am_anon or am_slots
460  * depending on the current state of the amap.
461  *
462  * => entry's map and amap must be locked by the caller
463  */
464 void
465 amap_share_protect(entry, prot)
466 	vm_map_entry_t entry;
467 	vm_prot_t prot;
468 {
469 	struct vm_amap *amap = entry->aref.ar_amap;
470 	int slots, lcv, slot, stop;
471 
472 	AMAP_B2SLOT(slots, (entry->end - entry->start));
473 	stop = entry->aref.ar_pageoff + slots;
474 
475 	if (slots < amap->am_nused) {
476 		/* cheaper to traverse am_anon */
477 		for (lcv = entry->aref.ar_pageoff ; lcv < stop ; lcv++) {
478 			if (amap->am_anon[lcv] == NULL)
479 				continue;
480 			if (amap->am_anon[lcv]->u.an_page != NULL)
481 				pmap_page_protect(amap->am_anon[lcv]->u.an_page,
482 						  prot);
483 		}
484 		return;
485 	}
486 
487 	/* cheaper to traverse am_slots */
488 	for (lcv = 0 ; lcv < amap->am_nused ; lcv++) {
489 		slot = amap->am_slots[lcv];
490 		if (slot < entry->aref.ar_pageoff || slot >= stop)
491 			continue;
492 		if (amap->am_anon[slot]->u.an_page != NULL)
493 			pmap_page_protect(amap->am_anon[slot]->u.an_page, prot);
494 	}
495 	return;
496 }
497 
498 /*
499  * amap_wipeout: wipeout all anon's in an amap; then free the amap!
500  *
501  * => called from amap_unref when the final reference to an amap is
502  *	discarded (i.e. when reference count == 1)
503  * => the amap should be locked (by the caller)
504  */
505 
506 void
507 amap_wipeout(amap)
508 	struct vm_amap *amap;
509 {
510 	int lcv, slot;
511 	struct vm_anon *anon;
512 	UVMHIST_FUNC("amap_wipeout"); UVMHIST_CALLED(maphist);
513 	UVMHIST_LOG(maphist,"(amap=0x%x)", amap, 0,0,0);
514 
515 	for (lcv = 0 ; lcv < amap->am_nused ; lcv++) {
516 		int refs;
517 
518 		slot = amap->am_slots[lcv];
519 		anon = amap->am_anon[slot];
520 
521 		if (anon == NULL || anon->an_ref == 0)
522 			panic("amap_wipeout: corrupt amap");
523 
524 		simple_lock(&anon->an_lock); /* lock anon */
525 
526 		UVMHIST_LOG(maphist,"  processing anon 0x%x, ref=%d", anon,
527 		    anon->an_ref, 0, 0);
528 
529 		refs = --anon->an_ref;
530 		simple_unlock(&anon->an_lock);
531 		if (refs == 0) {
532 			/*
533 			 * we had the last reference to a vm_anon. free it.
534 			 */
535 			uvm_anfree(anon);
536 		}
537 	}
538 
539 	/*
540 	 * now we free the map
541 	 */
542 
543 	amap->am_ref = 0;	/* ... was one */
544 	amap->am_nused = 0;
545 	amap_free(amap);	/* will unlock and free amap */
546 	UVMHIST_LOG(maphist,"<- done!", 0,0,0,0);
547 }
548 
549 /*
550  * amap_copy: ensure that a map entry's "needs_copy" flag is false
551  *	by copying the amap if necessary.
552  *
553  * => an entry with a null amap pointer will get a new (blank) one.
554  * => the map that the map entry belongs to must be locked by caller.
555  * => the amap currently attached to "entry" (if any) must be unlocked.
556  * => if canchunk is true, then we may clip the entry into a chunk
557  * => "startva" and "endva" are used only if canchunk is true.  they are
558  *     used to limit chunking (e.g. if you have a large space that you
559  *     know you are going to need to allocate amaps for, there is no point
560  *     in allowing that to be chunked)
561  */
562 
563 void
564 amap_copy(map, entry, waitf, canchunk, startva, endva)
565 	vm_map_t map;
566 	vm_map_entry_t entry;
567 	int waitf;
568 	boolean_t canchunk;
569 	vaddr_t startva, endva;
570 {
571 	struct vm_amap *amap, *srcamap;
572 	int slots, lcv;
573 	vaddr_t chunksize;
574 	UVMHIST_FUNC("amap_copy"); UVMHIST_CALLED(maphist);
575 	UVMHIST_LOG(maphist, "  (map=%p, entry=%p, waitf=%d)", map, entry, waitf, 0);
576 
577 	/*
578 	 * is there a map to copy?   if not, create one from scratch.
579 	 */
580 
581 	if (entry->aref.ar_amap == NULL) {
582 
583 		/*
584 		 * check to see if we have a large amap that we can
585 		 * chunk.  we align startva/endva to chunk-sized
586 		 * boundaries and then clip to them.
587 		 */
588 
589 		if (canchunk && atop(entry->end - entry->start) >=
590 		    UVM_AMAP_LARGE) {
591 			/* convert slots to bytes */
592 			chunksize = UVM_AMAP_CHUNK << PAGE_SHIFT;
593 			startva = (startva / chunksize) * chunksize;
594 			endva = roundup(endva, chunksize);
595 			UVMHIST_LOG(maphist, "  chunk amap ==> clip 0x%x->0x%x"
596 			    "to 0x%x->0x%x", entry->start, entry->end, startva,
597 			    endva);
598 			UVM_MAP_CLIP_START(map, entry, startva);
599 			/* watch out for endva wrap-around! */
600 			if (endva >= startva)
601 				UVM_MAP_CLIP_END(map, entry, endva);
602 		}
603 
604 		UVMHIST_LOG(maphist, "<- done [creating new amap 0x%x->0x%x]",
605 		entry->start, entry->end, 0, 0);
606 		entry->aref.ar_pageoff = 0;
607 		entry->aref.ar_amap = amap_alloc(entry->end - entry->start, 0,
608 		    waitf);
609 		if (entry->aref.ar_amap != NULL)
610 			entry->etype &= ~UVM_ET_NEEDSCOPY;
611 		return;
612 	}
613 
614 	/*
615 	 * first check and see if we are the only map entry
616 	 * referencing the amap we currently have.  if so, then we can
617 	 * just take it over rather than copying it.  note that we are
618 	 * reading am_ref with the amap unlocked... the value can only
619 	 * be one if we have the only reference to the amap (via our
620 	 * locked map).  if we are greater than one we fall through to
621 	 * the next case (where we double check the value).
622 	 */
623 
624 	if (entry->aref.ar_amap->am_ref == 1) {
625 		entry->etype &= ~UVM_ET_NEEDSCOPY;
626 		UVMHIST_LOG(maphist, "<- done [ref cnt = 1, took it over]",
627 		    0, 0, 0, 0);
628 		return;
629 	}
630 
631 	/*
632 	 * looks like we need to copy the map.
633 	 */
634 
635 	UVMHIST_LOG(maphist,"  amap=%p, ref=%d, must copy it",
636 	    entry->aref.ar_amap, entry->aref.ar_amap->am_ref, 0, 0);
637 	AMAP_B2SLOT(slots, entry->end - entry->start);
638 	amap = amap_alloc1(slots, 0, waitf);
639 	if (amap == NULL) {
640 		UVMHIST_LOG(maphist, "  amap_alloc1 failed", 0,0,0,0);
641 		return;
642 	}
643 	srcamap = entry->aref.ar_amap;
644 	amap_lock(srcamap);
645 
646 	/*
647 	 * need to double check reference count now that we've got the
648 	 * src amap locked down.  the reference count could have
649 	 * changed while we were in malloc.  if the reference count
650 	 * dropped down to one we take over the old map rather than
651 	 * copying the amap.
652 	 */
653 
654 	if (srcamap->am_ref == 1) {		/* take it over? */
655 		entry->etype &= ~UVM_ET_NEEDSCOPY;
656 		amap->am_ref--;		/* drop final reference to map */
657 		amap_free(amap);	/* dispose of new (unused) amap */
658 		amap_unlock(srcamap);
659 		return;
660 	}
661 
662 	/*
663 	 * we must copy it now.
664 	 */
665 
666 	UVMHIST_LOG(maphist, "  copying amap now",0, 0, 0, 0);
667 	for (lcv = 0 ; lcv < slots; lcv++) {
668 		amap->am_anon[lcv] =
669 		    srcamap->am_anon[entry->aref.ar_pageoff + lcv];
670 		if (amap->am_anon[lcv] == NULL)
671 			continue;
672 		simple_lock(&amap->am_anon[lcv]->an_lock);
673 		amap->am_anon[lcv]->an_ref++;
674 		simple_unlock(&amap->am_anon[lcv]->an_lock);
675 		amap->am_bckptr[lcv] = amap->am_nused;
676 		amap->am_slots[amap->am_nused] = lcv;
677 		amap->am_nused++;
678 	}
679 
680 	/*
681 	 * drop our reference to the old amap (srcamap) and unlock.
682 	 * we know that the reference count on srcamap is greater than
683 	 * one (we checked above), so there is no way we could drop
684 	 * the count to zero.  [and no need to worry about freeing it]
685 	 */
686 
687 	srcamap->am_ref--;
688 	if (srcamap->am_ref == 1 && (srcamap->am_flags & AMAP_SHARED) != 0)
689 		srcamap->am_flags &= ~AMAP_SHARED;   /* clear shared flag */
690 #ifdef UVM_AMAP_PPREF
691 	if (srcamap->am_ppref && srcamap->am_ppref != PPREF_NONE) {
692 		amap_pp_adjref(srcamap, entry->aref.ar_pageoff,
693 		    entry->end - entry->start, -1);
694 	}
695 #endif
696 
697 	amap_unlock(srcamap);
698 
699 	/*
700 	 * install new amap.
701 	 */
702 
703 	entry->aref.ar_pageoff = 0;
704 	entry->aref.ar_amap = amap;
705 	entry->etype &= ~UVM_ET_NEEDSCOPY;
706 
707 	/*
708 	 * done!
709 	 */
710 	UVMHIST_LOG(maphist, "<- done",0, 0, 0, 0);
711 }
712 
713 /*
714  * amap_cow_now: resolve all copy-on-write faults in an amap now for fork(2)
715  *
716  *	called during fork(2) when the parent process has a wired map
717  *	entry.   in that case we want to avoid write-protecting pages
718  *	in the parent's map (e.g. like what you'd do for a COW page)
719  *	so we resolve the COW here.
720  *
721  * => assume parent's entry was wired, thus all pages are resident.
722  * => assume pages that are loaned out (loan_count) are already mapped
723  *	read-only in all maps, and thus no need for us to worry about them
724  * => assume both parent and child vm_map's are locked
725  * => caller passes child's map/entry in to us
726  * => if we run out of memory we will unlock the amap and sleep _with_ the
727  *	parent and child vm_map's locked(!).    we have to do this since
728  *	we are in the middle of a fork(2) and we can't let the parent
729  *	map change until we are done copying all the map entrys.
730  * => XXXCDC: out of memory should cause fork to fail, but there is
731  *	currently no easy way to do this (needs fix)
732  * => page queues must be unlocked (we may lock them)
733  */
734 
735 void
736 amap_cow_now(map, entry)
737 	struct vm_map *map;
738 	struct vm_map_entry *entry;
739 {
740 	struct vm_amap *amap = entry->aref.ar_amap;
741 	int lcv, slot;
742 	struct vm_anon *anon, *nanon;
743 	struct vm_page *pg, *npg;
744 
745 	/*
746 	 * note that if we unlock the amap then we must ReStart the "lcv" for
747 	 * loop because some other process could reorder the anon's in the
748 	 * am_anon[] array on us while the lock is dropped.
749 	 */
750 ReStart:
751 	amap_lock(amap);
752 
753 	for (lcv = 0 ; lcv < amap->am_nused ; lcv++) {
754 
755 		/*
756 		 * get the page
757 		 */
758 
759 		slot = amap->am_slots[lcv];
760 		anon = amap->am_anon[slot];
761 		simple_lock(&anon->an_lock);
762 		pg = anon->u.an_page;
763 
764 		/*
765 		 * page must be resident since parent is wired
766 		 */
767 
768 		if (pg == NULL)
769 		    panic("amap_cow_now: non-resident wired page in anon %p",
770 			anon);
771 
772 		/*
773 		 * if the anon ref count is one and the page is not loaned,
774 		 * then we are safe (the child has exclusive access to the
775 		 * page).  if the page is loaned, then it must already be
776 		 * mapped read-only.
777 		 *
778 		 * we only need to get involved when these are not true.
779 		 * [note: if loan_count == 0, then the anon must own the page]
780 		 */
781 
782 		if (anon->an_ref > 1 && pg->loan_count == 0) {
783 
784 			/*
785 			 * if the page is busy then we have to unlock, wait for
786 			 * it and then restart.
787 			 */
788 			if (pg->flags & PG_BUSY) {
789 				pg->flags |= PG_WANTED;
790 				amap_unlock(amap);
791 				UVM_UNLOCK_AND_WAIT(pg, &anon->an_lock, FALSE,
792 				    "cownow", 0);
793 				goto ReStart;
794 			}
795 
796 			/*
797 			 * ok, time to do a copy-on-write to a new anon
798 			 */
799 			nanon = uvm_analloc();
800 			if (nanon)
801 				npg = uvm_pagealloc(NULL, 0, nanon, 0);
802 			else
803 				npg = NULL;	/* XXX: quiet gcc warning */
804 
805 			if (nanon == NULL || npg == NULL) {
806 				/* out of memory */
807 				/*
808 				 * XXXCDC: we should cause fork to fail, but
809 				 * we can't ...
810 				 */
811 				if (nanon)
812 					uvm_anfree(nanon);
813 				simple_unlock(&anon->an_lock);
814 				amap_unlock(amap);
815 				uvm_wait("cownowpage");
816 				goto ReStart;
817 			}
818 
819 			/*
820 			 * got it... now we can copy the data and replace anon
821 			 * with our new one...
822 			 */
823 			uvm_pagecopy(pg, npg);		/* old -> new */
824 			anon->an_ref--;			/* can't drop to zero */
825 			amap->am_anon[slot] = nanon;	/* replace */
826 
827 			/*
828 			 * drop PG_BUSY on new page ... since we have had it's
829 			 * owner locked the whole time it can't be
830 			 * PG_RELEASED | PG_WANTED.
831 			 */
832 			npg->flags &= ~(PG_BUSY|PG_FAKE);
833 			UVM_PAGE_OWN(npg, NULL);
834 			uvm_lock_pageq();
835 			uvm_pageactivate(npg);
836 			uvm_unlock_pageq();
837 		}
838 
839 		simple_unlock(&anon->an_lock);
840 		/*
841 		 * done with this anon, next ...!
842 		 */
843 
844 	}	/* end of 'for' loop */
845 
846 	return;
847 }
848 
849 /*
850  * amap_splitref: split a single reference into two separate references
851  *
852  * => called from uvm_map's clip routines
853  * => origref's map should be locked
854  * => origref->ar_amap should be unlocked (we will lock)
855  */
856 void
857 amap_splitref(origref, splitref, offset)
858 	struct vm_aref *origref, *splitref;
859 	vaddr_t offset;
860 {
861 	int leftslots;
862 	UVMHIST_FUNC("amap_splitref"); UVMHIST_CALLED(maphist);
863 
864 	AMAP_B2SLOT(leftslots, offset);
865 	if (leftslots == 0)
866 		panic("amap_splitref: split at zero offset");
867 
868 	/*
869 	 * lock the amap
870 	 */
871 	amap_lock(origref->ar_amap);
872 
873 	/*
874 	 * now: amap is locked and we have a valid am_mapped array.
875 	 */
876 
877 	if (origref->ar_amap->am_nslot - origref->ar_pageoff - leftslots <= 0)
878 		panic("amap_splitref: map size check failed");
879 
880 #ifdef UVM_AMAP_PPREF
881         /*
882 	 * establish ppref before we add a duplicate reference to the amap
883 	 */
884 	if (origref->ar_amap->am_ppref == NULL)
885 		amap_pp_establish(origref->ar_amap);
886 #endif
887 
888 	splitref->ar_amap = origref->ar_amap;
889 	splitref->ar_amap->am_ref++;		/* not a share reference */
890 	splitref->ar_pageoff = origref->ar_pageoff + leftslots;
891 
892 	amap_unlock(origref->ar_amap);
893 }
894 
895 #ifdef UVM_AMAP_PPREF
896 
897 /*
898  * amap_pp_establish: add a ppref array to an amap, if possible
899  *
900  * => amap locked by caller
901  */
902 void
903 amap_pp_establish(amap)
904 	struct vm_amap *amap;
905 {
906 
907 	MALLOC(amap->am_ppref, int *, sizeof(int) * amap->am_maxslot,
908 	    M_UVMAMAP, M_NOWAIT);
909 
910 	/*
911 	 * if we fail then we just won't use ppref for this amap
912 	 */
913 	if (amap->am_ppref == NULL) {
914 		amap->am_ppref = PPREF_NONE;	/* not using it */
915 		return;
916 	}
917 
918 	/*
919 	 * init ppref
920 	 */
921 	memset(amap->am_ppref, 0, sizeof(int) * amap->am_maxslot);
922 	pp_setreflen(amap->am_ppref, 0, amap->am_ref, amap->am_nslot);
923 	return;
924 }
925 
926 /*
927  * amap_pp_adjref: adjust reference count to a part of an amap using the
928  * per-page reference count array.
929  *
930  * => map and amap locked by caller
931  * => caller must check that ppref != PPREF_NONE before calling
932  */
933 void
934 amap_pp_adjref(amap, curslot, bytelen, adjval)
935 	struct vm_amap *amap;
936 	int curslot;
937 	vsize_t bytelen;
938 	int adjval;
939 {
940 	int slots, stopslot, *ppref, lcv;
941 	int ref, len;
942 
943 	/*
944 	 * get init values
945 	 */
946 
947 	AMAP_B2SLOT(slots, bytelen);
948 	stopslot = curslot + slots;
949 	ppref = amap->am_ppref;
950 
951 	/*
952 	 * first advance to the correct place in the ppref array, fragment
953 	 * if needed.
954 	 */
955 
956 	for (lcv = 0 ; lcv < curslot ; lcv += len) {
957 		pp_getreflen(ppref, lcv, &ref, &len);
958 		if (lcv + len > curslot) {     /* goes past start? */
959 			pp_setreflen(ppref, lcv, ref, curslot - lcv);
960 			pp_setreflen(ppref, curslot, ref, len - (curslot -lcv));
961 			len = curslot - lcv;   /* new length of entry @ lcv */
962 		}
963 	}
964 
965 	/*
966 	 * now adjust reference counts in range (make sure we dont overshoot)
967 	 */
968 
969 	if (lcv != curslot)
970 		panic("amap_pp_adjref: overshot target");
971 
972 	for (/* lcv already set */; lcv < stopslot ; lcv += len) {
973 		pp_getreflen(ppref, lcv, &ref, &len);
974 		if (lcv + len > stopslot) {     /* goes past end? */
975 			pp_setreflen(ppref, lcv, ref, stopslot - lcv);
976 			pp_setreflen(ppref, stopslot, ref,
977 			    len - (stopslot - lcv));
978 			len = stopslot - lcv;
979 		}
980 		ref = ref + adjval;    /* ADJUST! */
981 		if (ref < 0)
982 			panic("amap_pp_adjref: negative reference count");
983 		pp_setreflen(ppref, lcv, ref, len);
984 		if (ref == 0)
985 			amap_wiperange(amap, lcv, len);
986 	}
987 
988 }
989 
990 /*
991  * amap_wiperange: wipe out a range of an amap
992  * [different from amap_wipeout because the amap is kept intact]
993  *
994  * => both map and amap must be locked by caller.
995  */
996 void
997 amap_wiperange(amap, slotoff, slots)
998 	struct vm_amap *amap;
999 	int slotoff, slots;
1000 {
1001 	int byanon, lcv, stop, curslot, ptr;
1002 	struct vm_anon *anon;
1003 	UVMHIST_FUNC("amap_wiperange"); UVMHIST_CALLED(maphist);
1004 
1005 	/*
1006 	 * we can either traverse the amap by am_anon or by am_slots depending
1007 	 * on which is cheaper.    decide now.
1008 	 */
1009 
1010 	if (slots < amap->am_nused) {
1011 		byanon = TRUE;
1012 		lcv = slotoff;
1013 		stop = slotoff + slots;
1014 	} else {
1015 		byanon = FALSE;
1016 		lcv = 0;
1017 		stop = amap->am_nused;
1018 	}
1019 
1020 	/*
1021 	 * ok, now do it!
1022 	 */
1023 
1024 	for (; lcv < stop; lcv++) {
1025 		int refs;
1026 
1027 		/*
1028 		 * verify the anon is ok.
1029 		 */
1030 		if (byanon) {
1031 			if (amap->am_anon[lcv] == NULL)
1032 				continue;
1033 			curslot = lcv;
1034 		} else {
1035 			curslot = amap->am_slots[lcv];
1036 			if (curslot < slotoff || curslot >= stop)
1037 				continue;
1038 		}
1039 		anon = amap->am_anon[curslot];
1040 
1041 		/*
1042 		 * remove it from the amap
1043 		 */
1044 		amap->am_anon[curslot] = NULL;
1045 		ptr = amap->am_bckptr[curslot];
1046 		if (ptr != (amap->am_nused - 1)) {
1047 			amap->am_slots[ptr] =
1048 			    amap->am_slots[amap->am_nused - 1];
1049 			amap->am_bckptr[amap->am_slots[ptr]] =
1050 			    ptr;    /* back ptr. */
1051 		}
1052 		amap->am_nused--;
1053 
1054 		/*
1055 		 * drop anon reference count
1056 		 */
1057 		simple_lock(&anon->an_lock);
1058 		refs = --anon->an_ref;
1059 		simple_unlock(&anon->an_lock);
1060 		if (refs == 0) {
1061 			/*
1062 			 * we just eliminated the last reference to an anon.
1063 			 * free it.
1064 			 */
1065 			uvm_anfree(anon);
1066 		}
1067 	}
1068 }
1069 
1070 #endif
1071