xref: /openbsd/sys/uvm/uvm_amap.c (revision d415bd75)
1 /*	$OpenBSD: uvm_amap.c,v 1.92 2023/04/11 00:45:09 jsg Exp $	*/
2 /*	$NetBSD: uvm_amap.c,v 1.27 2000/11/25 06:27:59 chs Exp $	*/
3 
4 /*
5  * Copyright (c) 1997 Charles D. Cranor and Washington University.
6  * All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  * 1. Redistributions of source code must retain the above copyright
12  *    notice, this list of conditions and the following disclaimer.
13  * 2. Redistributions in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in the
15  *    documentation and/or other materials provided with the distribution.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27  */
28 
29 /*
30  * uvm_amap.c: amap operations
31  *
32  * this file contains functions that perform operations on amaps.  see
33  * uvm_amap.h for a brief explanation of the role of amaps in uvm.
34  */
35 
36 #include <sys/param.h>
37 #include <sys/systm.h>
38 #include <sys/malloc.h>
39 #include <sys/kernel.h>
40 #include <sys/pool.h>
41 #include <sys/atomic.h>
42 
43 #include <uvm/uvm.h>
44 #include <uvm/uvm_swap.h>
45 
46 /*
47  * pools for allocation of vm_amap structures.  note that in order to
48  * avoid an endless loop, the amap pool's allocator cannot allocate
49  * memory from an amap (it currently goes through the kernel uobj, so
50  * we are ok).
51  */
52 
53 struct pool uvm_amap_pool;
54 struct pool uvm_small_amap_pool[UVM_AMAP_CHUNK];
55 struct pool uvm_amap_chunk_pool;
56 
57 LIST_HEAD(, vm_amap) amap_list;
58 struct rwlock amap_list_lock = RWLOCK_INITIALIZER("amaplstlk");
59 #define amap_lock_list()	rw_enter_write(&amap_list_lock)
60 #define amap_unlock_list()	rw_exit_write(&amap_list_lock)
61 
62 static char amap_small_pool_names[UVM_AMAP_CHUNK][9];
63 
64 /*
65  * local functions
66  */
67 
68 static struct vm_amap *amap_alloc1(int, int, int);
69 static inline void amap_list_insert(struct vm_amap *);
70 static inline void amap_list_remove(struct vm_amap *);
71 
72 struct vm_amap_chunk *amap_chunk_get(struct vm_amap *, int, int, int);
73 void amap_chunk_free(struct vm_amap *, struct vm_amap_chunk *);
74 
75 /*
76  * if we enable PPREF, then we have a couple of extra functions that
77  * we need to prototype here...
78  */
79 
80 #ifdef UVM_AMAP_PPREF
81 
82 #define PPREF_NONE ((int *) -1)	/* not using ppref */
83 
84 void	amap_pp_adjref(struct vm_amap *, int, vsize_t, int);
85 void	amap_pp_establish(struct vm_amap *);
86 void	amap_wiperange_chunk(struct vm_amap *, struct vm_amap_chunk *, int,
87 	    int);
88 void	amap_wiperange(struct vm_amap *, int, int);
89 
90 #endif	/* UVM_AMAP_PPREF */
91 
92 static inline void
93 amap_list_insert(struct vm_amap *amap)
94 {
95 	amap_lock_list();
96 	LIST_INSERT_HEAD(&amap_list, amap, am_list);
97 	amap_unlock_list();
98 }
99 
100 static inline void
101 amap_list_remove(struct vm_amap *amap)
102 {
103 	amap_lock_list();
104 	LIST_REMOVE(amap, am_list);
105 	amap_unlock_list();
106 }
107 
108 /*
109  * amap_chunk_get: lookup a chunk for slot. if create is non-zero,
110  * the chunk is created if it does not yet exist.
111  *
112  * => returns the chunk on success or NULL on error
113  */
114 struct vm_amap_chunk *
115 amap_chunk_get(struct vm_amap *amap, int slot, int create, int waitf)
116 {
117 	int bucket = UVM_AMAP_BUCKET(amap, slot);
118 	int baseslot = AMAP_BASE_SLOT(slot);
119 	int n;
120 	struct vm_amap_chunk *chunk, *newchunk, *pchunk = NULL;
121 
122 	if (UVM_AMAP_SMALL(amap))
123 		return &amap->am_small;
124 
125 	for (chunk = amap->am_buckets[bucket]; chunk != NULL;
126 	    chunk = TAILQ_NEXT(chunk, ac_list)) {
127 		if (UVM_AMAP_BUCKET(amap, chunk->ac_baseslot) != bucket)
128 			break;
129 		if (chunk->ac_baseslot == baseslot)
130 			return chunk;
131 		pchunk = chunk;
132 	}
133 	if (!create)
134 		return NULL;
135 
136 	if (amap->am_nslot - baseslot >= UVM_AMAP_CHUNK)
137 		n = UVM_AMAP_CHUNK;
138 	else
139 		n = amap->am_nslot - baseslot;
140 
141 	newchunk = pool_get(&uvm_amap_chunk_pool, waitf | PR_ZERO);
142 	if (newchunk == NULL)
143 		return NULL;
144 
145 	if (pchunk == NULL) {
146 		TAILQ_INSERT_TAIL(&amap->am_chunks, newchunk, ac_list);
147 		KASSERT(amap->am_buckets[bucket] == NULL);
148 		amap->am_buckets[bucket] = newchunk;
149 	} else
150 		TAILQ_INSERT_AFTER(&amap->am_chunks, pchunk, newchunk,
151 		    ac_list);
152 
153 	amap->am_ncused++;
154 	newchunk->ac_baseslot = baseslot;
155 	newchunk->ac_nslot = n;
156 	return newchunk;
157 }
158 
159 void
160 amap_chunk_free(struct vm_amap *amap, struct vm_amap_chunk *chunk)
161 {
162 	int bucket = UVM_AMAP_BUCKET(amap, chunk->ac_baseslot);
163 	struct vm_amap_chunk *nchunk;
164 
165 	if (UVM_AMAP_SMALL(amap))
166 		return;
167 
168 	nchunk = TAILQ_NEXT(chunk, ac_list);
169 	TAILQ_REMOVE(&amap->am_chunks, chunk, ac_list);
170 	if (amap->am_buckets[bucket] == chunk) {
171 		if (nchunk != NULL &&
172 		    UVM_AMAP_BUCKET(amap, nchunk->ac_baseslot) == bucket)
173 			amap->am_buckets[bucket] = nchunk;
174 		else
175 			amap->am_buckets[bucket] = NULL;
176 
177 	}
178 	pool_put(&uvm_amap_chunk_pool, chunk);
179 	amap->am_ncused--;
180 }
181 
182 #ifdef UVM_AMAP_PPREF
183 /*
184  * what is ppref?   ppref is an _optional_ amap feature which is used
185  * to keep track of reference counts on a per-page basis.  it is enabled
186  * when UVM_AMAP_PPREF is defined.
187  *
188  * when enabled, an array of ints is allocated for the pprefs.  this
189  * array is allocated only when a partial reference is added to the
190  * map (either by unmapping part of the amap, or gaining a reference
191  * to only a part of an amap).  if the allocation of the array fails
192  * (M_NOWAIT), then we set the array pointer to PPREF_NONE to indicate
193  * that we tried to do ppref's but couldn't alloc the array so just
194  * give up (after all, this is an optional feature!).
195  *
196  * the array is divided into page sized "chunks."   for chunks of length 1,
197  * the chunk reference count plus one is stored in that chunk's slot.
198  * for chunks of length > 1 the first slot contains (the reference count
199  * plus one) * -1.    [the negative value indicates that the length is
200  * greater than one.]   the second slot of the chunk contains the length
201  * of the chunk.   here is an example:
202  *
203  * actual REFS:  2  2  2  2  3  1  1  0  0  0  4  4  0  1  1  1
204  *       ppref: -3  4  x  x  4 -2  2 -1  3  x -5  2  1 -2  3  x
205  *              <----------><-><----><-------><----><-><------->
206  * (x = don't care)
207  *
208  * this allows us to allow one int to contain the ref count for the whole
209  * chunk.    note that the "plus one" part is needed because a reference
210  * count of zero is neither positive or negative (need a way to tell
211  * if we've got one zero or a bunch of them).
212  *
213  * here are some in-line functions to help us.
214  */
215 
216 /*
217  * pp_getreflen: get the reference and length for a specific offset
218  *
219  * => ppref's amap must be locked
220  */
221 static inline void
222 pp_getreflen(int *ppref, int offset, int *refp, int *lenp)
223 {
224 
225 	if (ppref[offset] > 0) {		/* chunk size must be 1 */
226 		*refp = ppref[offset] - 1;	/* don't forget to adjust */
227 		*lenp = 1;
228 	} else {
229 		*refp = (ppref[offset] * -1) - 1;
230 		*lenp = ppref[offset+1];
231 	}
232 }
233 
234 /*
235  * pp_setreflen: set the reference and length for a specific offset
236  *
237  * => ppref's amap must be locked
238  */
239 static inline void
240 pp_setreflen(int *ppref, int offset, int ref, int len)
241 {
242 	if (len == 1) {
243 		ppref[offset] = ref + 1;
244 	} else {
245 		ppref[offset] = (ref + 1) * -1;
246 		ppref[offset+1] = len;
247 	}
248 }
249 #endif /* UVM_AMAP_PPREF */
250 
251 /*
252  * amap_init: called at boot time to init global amap data structures
253  */
254 
255 void
256 amap_init(void)
257 {
258 	int i;
259 	size_t size;
260 
261 	/* Initialize the vm_amap pool. */
262 	pool_init(&uvm_amap_pool, sizeof(struct vm_amap),
263 	    0, IPL_MPFLOOR, PR_WAITOK, "amappl", NULL);
264 	pool_sethiwat(&uvm_amap_pool, 4096);
265 
266 	/* initialize small amap pools */
267 	for (i = 0; i < nitems(uvm_small_amap_pool); i++) {
268 		snprintf(amap_small_pool_names[i],
269 		    sizeof(amap_small_pool_names[0]), "amappl%d", i + 1);
270 		size = offsetof(struct vm_amap, am_small.ac_anon) +
271 		    (i + 1) * sizeof(struct vm_anon *);
272 		pool_init(&uvm_small_amap_pool[i], size, 0, IPL_MPFLOOR,
273 		    PR_WAITOK, amap_small_pool_names[i], NULL);
274 	}
275 
276 	pool_init(&uvm_amap_chunk_pool, sizeof(struct vm_amap_chunk) +
277 	    UVM_AMAP_CHUNK * sizeof(struct vm_anon *),
278 	    0, IPL_MPFLOOR, PR_WAITOK, "amapchunkpl", NULL);
279 	pool_sethiwat(&uvm_amap_chunk_pool, 4096);
280 }
281 
282 /*
283  * amap_alloc1: allocate an amap, but do not initialise the overlay.
284  *
285  * => Note: lock is not set.
286  */
287 static inline struct vm_amap *
288 amap_alloc1(int slots, int waitf, int lazyalloc)
289 {
290 	struct vm_amap *amap;
291 	struct vm_amap_chunk *chunk, *tmp;
292 	int chunks, log_chunks, chunkperbucket = 1, hashshift = 0;
293 	int buckets, i, n;
294 	int pwaitf = (waitf & M_WAITOK) ? PR_WAITOK : PR_NOWAIT;
295 
296 	KASSERT(slots > 0);
297 
298 	/*
299 	 * Cast to unsigned so that rounding up cannot cause integer overflow
300 	 * if slots is large.
301 	 */
302 	chunks = roundup((unsigned int)slots, UVM_AMAP_CHUNK) / UVM_AMAP_CHUNK;
303 
304 	if (lazyalloc) {
305 		/*
306 		 * Basically, the amap is a hash map where the number of
307 		 * buckets is fixed. We select the number of buckets using the
308 		 * following strategy:
309 		 *
310 		 * 1. The maximal number of entries to search in a bucket upon
311 		 * a collision should be less than or equal to
312 		 * log2(slots / UVM_AMAP_CHUNK). This is the worst-case number
313 		 * of lookups we would have if we could chunk the amap. The
314 		 * log2(n) comes from the fact that amaps are chunked by
315 		 * splitting up their vm_map_entries and organizing those
316 		 * in a binary search tree.
317 		 *
318 		 * 2. The maximal number of entries in a bucket must be a
319 		 * power of two.
320 		 *
321 		 * The maximal number of entries per bucket is used to hash
322 		 * a slot to a bucket.
323 		 *
324 		 * In the future, this strategy could be refined to make it
325 		 * even harder/impossible that the total amount of KVA needed
326 		 * for the hash buckets of all amaps to exceed the maximal
327 		 * amount of KVA memory reserved for amaps.
328 		 */
329 		for (log_chunks = 1; (chunks >> log_chunks) > 0; log_chunks++)
330 			continue;
331 
332 		chunkperbucket = 1 << hashshift;
333 		while (chunkperbucket + 1 < log_chunks) {
334 			hashshift++;
335 			chunkperbucket = 1 << hashshift;
336 		}
337 	}
338 
339 	if (slots > UVM_AMAP_CHUNK)
340 		amap = pool_get(&uvm_amap_pool, pwaitf);
341 	else
342 		amap = pool_get(&uvm_small_amap_pool[slots - 1],
343 		    pwaitf | PR_ZERO);
344 	if (amap == NULL)
345 		return NULL;
346 
347 	amap->am_lock = NULL;
348 	amap->am_ref = 1;
349 	amap->am_flags = 0;
350 #ifdef UVM_AMAP_PPREF
351 	amap->am_ppref = NULL;
352 #endif
353 	amap->am_nslot = slots;
354 	amap->am_nused = 0;
355 
356 	if (UVM_AMAP_SMALL(amap)) {
357 		amap->am_small.ac_nslot = slots;
358 		return amap;
359 	}
360 
361 	amap->am_ncused = 0;
362 	TAILQ_INIT(&amap->am_chunks);
363 	amap->am_hashshift = hashshift;
364 	amap->am_buckets = NULL;
365 
366 	buckets = howmany(chunks, chunkperbucket);
367 	amap->am_buckets = mallocarray(buckets, sizeof(*amap->am_buckets),
368 	    M_UVMAMAP, waitf | (lazyalloc ? M_ZERO : 0));
369 	if (amap->am_buckets == NULL)
370 		goto fail1;
371 	amap->am_nbuckets = buckets;
372 
373 	if (!lazyalloc) {
374 		for (i = 0; i < buckets; i++) {
375 			if (i == buckets - 1) {
376 				n = slots % UVM_AMAP_CHUNK;
377 				if (n == 0)
378 					n = UVM_AMAP_CHUNK;
379 			} else
380 				n = UVM_AMAP_CHUNK;
381 
382 			chunk = pool_get(&uvm_amap_chunk_pool,
383 			    PR_ZERO | pwaitf);
384 			if (chunk == NULL)
385 				goto fail1;
386 
387 			amap->am_buckets[i] = chunk;
388 			amap->am_ncused++;
389 			chunk->ac_baseslot = i * UVM_AMAP_CHUNK;
390 			chunk->ac_nslot = n;
391 			TAILQ_INSERT_TAIL(&amap->am_chunks, chunk, ac_list);
392 		}
393 	}
394 
395 	return amap;
396 
397 fail1:
398 	free(amap->am_buckets, M_UVMAMAP, buckets * sizeof(*amap->am_buckets));
399 	TAILQ_FOREACH_SAFE(chunk, &amap->am_chunks, ac_list, tmp)
400 		pool_put(&uvm_amap_chunk_pool, chunk);
401 	pool_put(&uvm_amap_pool, amap);
402 	return NULL;
403 }
404 
405 static void
406 amap_lock_alloc(struct vm_amap *amap)
407 {
408 	rw_obj_alloc(&amap->am_lock, "amaplk");
409 }
410 
411 /*
412  * amap_alloc: allocate an amap to manage "sz" bytes of anonymous VM
413  *
414  * => caller should ensure sz is a multiple of PAGE_SIZE
415  * => reference count to new amap is set to one
416  * => new amap is returned unlocked
417  */
418 struct vm_amap *
419 amap_alloc(vaddr_t sz, int waitf, int lazyalloc)
420 {
421 	struct vm_amap *amap;
422 	size_t slots;
423 
424 	AMAP_B2SLOT(slots, sz);		/* load slots */
425 	if (slots > INT_MAX)
426 		return NULL;
427 
428 	amap = amap_alloc1(slots, waitf, lazyalloc);
429 	if (amap != NULL) {
430 		amap_lock_alloc(amap);
431 		amap_list_insert(amap);
432 	}
433 
434 	return amap;
435 }
436 
437 
438 /*
439  * amap_free: free an amap
440  *
441  * => the amap must be unlocked
442  * => the amap should have a zero reference count and be empty
443  */
444 void
445 amap_free(struct vm_amap *amap)
446 {
447 	struct vm_amap_chunk *chunk, *tmp;
448 
449 	KASSERT(amap->am_ref == 0 && amap->am_nused == 0);
450 	KASSERT((amap->am_flags & AMAP_SWAPOFF) == 0);
451 
452 	if (amap->am_lock != NULL) {
453 		KASSERT(amap->am_lock == NULL || !rw_write_held(amap->am_lock));
454 		rw_obj_free(amap->am_lock);
455 	}
456 
457 #ifdef UVM_AMAP_PPREF
458 	if (amap->am_ppref && amap->am_ppref != PPREF_NONE)
459 		free(amap->am_ppref, M_UVMAMAP, amap->am_nslot * sizeof(int));
460 #endif
461 
462 	if (UVM_AMAP_SMALL(amap))
463 		pool_put(&uvm_small_amap_pool[amap->am_nslot - 1], amap);
464 	else {
465 		TAILQ_FOREACH_SAFE(chunk, &amap->am_chunks, ac_list, tmp)
466 		    pool_put(&uvm_amap_chunk_pool, chunk);
467 		free(amap->am_buckets, M_UVMAMAP,
468 		    amap->am_nbuckets * sizeof(*amap->am_buckets));
469 		pool_put(&uvm_amap_pool, amap);
470 	}
471 }
472 
473 /*
474  * amap_wipeout: wipeout all anon's in an amap; then free the amap!
475  *
476  * => Called from amap_unref(), when reference count drops to zero.
477  * => amap must be locked.
478  */
479 void
480 amap_wipeout(struct vm_amap *amap)
481 {
482 	int slot;
483 	struct vm_anon *anon;
484 	struct vm_amap_chunk *chunk;
485 	struct pglist pgl;
486 
487 	KASSERT(rw_write_held(amap->am_lock));
488 	KASSERT(amap->am_ref == 0);
489 
490 	if (__predict_false((amap->am_flags & AMAP_SWAPOFF) != 0)) {
491 		/*
492 		 * Note: amap_swap_off() will call us again.
493 		 */
494 		amap_unlock(amap);
495 		return;
496 	}
497 
498 	TAILQ_INIT(&pgl);
499 	amap_list_remove(amap);
500 
501 	AMAP_CHUNK_FOREACH(chunk, amap) {
502 		int i, refs, map = chunk->ac_usedmap;
503 
504 		for (i = ffs(map); i != 0; i = ffs(map)) {
505 			slot = i - 1;
506 			map ^= 1 << slot;
507 			anon = chunk->ac_anon[slot];
508 
509 			if (anon == NULL || anon->an_ref == 0)
510 				panic("amap_wipeout: corrupt amap");
511 			KASSERT(anon->an_lock == amap->am_lock);
512 
513 			/*
514 			 * Drop the reference.
515 			 */
516 			refs = --anon->an_ref;
517 			if (refs == 0) {
518 				uvm_anfree_list(anon, &pgl);
519 			}
520 		}
521 	}
522 	/* free the pages */
523 	uvm_pglistfree(&pgl);
524 
525 	/*
526 	 * Finally, destroy the amap.
527 	 */
528 	amap->am_ref = 0;	/* ... was one */
529 	amap->am_nused = 0;
530 	amap_unlock(amap);
531 	amap_free(amap);
532 }
533 
534 /*
535  * amap_copy: ensure that a map entry's "needs_copy" flag is false
536  *	by copying the amap if necessary.
537  *
538  * => an entry with a null amap pointer will get a new (blank) one.
539  * => the map that the map entry belongs to must be locked by caller.
540  * => the amap currently attached to "entry" (if any) must be unlocked.
541  * => if canchunk is true, then we may clip the entry into a chunk
542  * => "startva" and "endva" are used only if canchunk is true.  they are
543  *     used to limit chunking (e.g. if you have a large space that you
544  *     know you are going to need to allocate amaps for, there is no point
545  *     in allowing that to be chunked)
546  */
547 
548 void
549 amap_copy(struct vm_map *map, struct vm_map_entry *entry, int waitf,
550     boolean_t canchunk, vaddr_t startva, vaddr_t endva)
551 {
552 	struct vm_amap *amap, *srcamap;
553 	int slots, lcv, lazyalloc = 0;
554 	vaddr_t chunksize;
555 	int i, j, k, n, srcslot;
556 	struct vm_amap_chunk *chunk = NULL, *srcchunk = NULL;
557 	struct vm_anon *anon;
558 
559 	KASSERT(map != kernel_map);		/* we use sleeping locks */
560 
561 	/*
562 	 * Is there an amap to copy?  If not, create one.
563 	 */
564 	if (entry->aref.ar_amap == NULL) {
565 		/*
566 		 * Check to see if we have a large amap that we can
567 		 * chunk.  We align startva/endva to chunk-sized
568 		 * boundaries and then clip to them.
569 		 *
570 		 * If we cannot chunk the amap, allocate it in a way
571 		 * that makes it grow or shrink dynamically with
572 		 * the number of slots.
573 		 */
574 		if (atop(entry->end - entry->start) >= UVM_AMAP_LARGE) {
575 			if (canchunk) {
576 				/* convert slots to bytes */
577 				chunksize = UVM_AMAP_CHUNK << PAGE_SHIFT;
578 				startva = (startva / chunksize) * chunksize;
579 				endva = roundup(endva, chunksize);
580 				UVM_MAP_CLIP_START(map, entry, startva);
581 				/* watch out for endva wrap-around! */
582 				if (endva >= startva)
583 					UVM_MAP_CLIP_END(map, entry, endva);
584 			} else
585 				lazyalloc = 1;
586 		}
587 
588 		entry->aref.ar_pageoff = 0;
589 		entry->aref.ar_amap = amap_alloc(entry->end - entry->start,
590 		    waitf, lazyalloc);
591 		if (entry->aref.ar_amap != NULL)
592 			entry->etype &= ~UVM_ET_NEEDSCOPY;
593 		return;
594 	}
595 
596 	/*
597 	 * First check and see if we are the only map entry referencing
598 	 * he amap we currently have.  If so, then just take it over instead
599 	 * of copying it.  Note that we are reading am_ref without lock held
600 	 * as the value can only be one if we have the only reference
601 	 * to the amap (via our locked map).  If the value is greater than
602 	 * one, then allocate amap and re-check the value.
603 	 */
604 	if (entry->aref.ar_amap->am_ref == 1) {
605 		entry->etype &= ~UVM_ET_NEEDSCOPY;
606 		return;
607 	}
608 
609 	/*
610 	 * Allocate a new amap (note: not initialised, etc).
611 	 */
612 	AMAP_B2SLOT(slots, entry->end - entry->start);
613 	if (!UVM_AMAP_SMALL(entry->aref.ar_amap) &&
614 	    entry->aref.ar_amap->am_hashshift != 0)
615 		lazyalloc = 1;
616 	amap = amap_alloc1(slots, waitf, lazyalloc);
617 	if (amap == NULL)
618 		return;
619 	srcamap = entry->aref.ar_amap;
620 
621 	/*
622 	 * Make the new amap share the source amap's lock, and then lock
623 	 * both.
624 	 */
625 	amap->am_lock = srcamap->am_lock;
626 	rw_obj_hold(amap->am_lock);
627 
628 	amap_lock(srcamap);
629 
630 	/*
631 	 * Re-check the reference count with the lock held.  If it has
632 	 * dropped to one - we can take over the existing map.
633 	 */
634 	if (srcamap->am_ref == 1) {
635 		/* Just take over the existing amap. */
636 		entry->etype &= ~UVM_ET_NEEDSCOPY;
637 		amap_unlock(srcamap);
638 		/* Destroy the new (unused) amap. */
639 		amap->am_ref--;
640 		amap_free(amap);
641 		return;
642 	}
643 
644 	/*
645 	 * Copy the slots.
646 	 */
647 	for (lcv = 0; lcv < slots; lcv += n) {
648 		srcslot = entry->aref.ar_pageoff + lcv;
649 		i = UVM_AMAP_SLOTIDX(lcv);
650 		j = UVM_AMAP_SLOTIDX(srcslot);
651 		n = UVM_AMAP_CHUNK;
652 		if (i > j)
653 			n -= i;
654 		else
655 			n -= j;
656 		if (lcv + n > slots)
657 			n = slots - lcv;
658 
659 		srcchunk = amap_chunk_get(srcamap, srcslot, 0, PR_NOWAIT);
660 		if (srcchunk == NULL)
661 			continue;
662 
663 		chunk = amap_chunk_get(amap, lcv, 1, PR_NOWAIT);
664 		if (chunk == NULL) {
665 			/* amap_wipeout() releases the lock. */
666 			amap->am_ref = 0;
667 			amap_wipeout(amap);
668 			return;
669 		}
670 
671 		for (k = 0; k < n; i++, j++, k++) {
672 			chunk->ac_anon[i] = anon = srcchunk->ac_anon[j];
673 			if (anon == NULL)
674 				continue;
675 
676 			KASSERT(anon->an_lock == srcamap->am_lock);
677 			KASSERT(anon->an_ref > 0);
678 			chunk->ac_usedmap |= (1 << i);
679 			anon->an_ref++;
680 			amap->am_nused++;
681 		}
682 	}
683 
684 	/*
685 	 * Drop our reference to the old amap (srcamap) and unlock.
686 	 * Since the reference count on srcamap is greater than one,
687 	 * (we checked above), it cannot drop to zero while it is locked.
688 	 */
689 	srcamap->am_ref--;
690 	KASSERT(srcamap->am_ref > 0);
691 
692 	if (srcamap->am_ref == 1 && (srcamap->am_flags & AMAP_SHARED) != 0)
693 		srcamap->am_flags &= ~AMAP_SHARED;   /* clear shared flag */
694 #ifdef UVM_AMAP_PPREF
695 	if (srcamap->am_ppref && srcamap->am_ppref != PPREF_NONE) {
696 		amap_pp_adjref(srcamap, entry->aref.ar_pageoff,
697 		    (entry->end - entry->start) >> PAGE_SHIFT, -1);
698 	}
699 #endif
700 
701 	/*
702 	 * If we referenced any anons, then share the source amap's lock.
703 	 * Otherwise, we have nothing in common, so allocate a new one.
704 	 */
705 	KASSERT(amap->am_lock == srcamap->am_lock);
706 	if (amap->am_nused == 0) {
707 		rw_obj_free(amap->am_lock);
708 		amap->am_lock = NULL;
709 	}
710 	amap_unlock(srcamap);
711 
712 	if (amap->am_lock == NULL)
713 		amap_lock_alloc(amap);
714 
715 	/*
716 	 * Install new amap.
717 	 */
718 	entry->aref.ar_pageoff = 0;
719 	entry->aref.ar_amap = amap;
720 	entry->etype &= ~UVM_ET_NEEDSCOPY;
721 
722 	amap_list_insert(amap);
723 }
724 
725 /*
726  * amap_cow_now: resolve all copy-on-write faults in an amap now for fork(2)
727  *
728  *	called during fork(2) when the parent process has a wired map
729  *	entry.   in that case we want to avoid write-protecting pages
730  *	in the parent's map (e.g. like what you'd do for a COW page)
731  *	so we resolve the COW here.
732  *
733  * => assume parent's entry was wired, thus all pages are resident.
734  * => the parent and child vm_map must both be locked.
735  * => caller passes child's map/entry in to us
736  * => XXXCDC: out of memory should cause fork to fail, but there is
737  *	currently no easy way to do this (needs fix)
738  */
739 
740 void
741 amap_cow_now(struct vm_map *map, struct vm_map_entry *entry)
742 {
743 	struct vm_amap *amap = entry->aref.ar_amap;
744 	int slot;
745 	struct vm_anon *anon, *nanon;
746 	struct vm_page *pg, *npg;
747 	struct vm_amap_chunk *chunk;
748 
749 	/*
750 	 * note that if we unlock the amap then we must ReStart the "lcv" for
751 	 * loop because some other process could reorder the anon's in the
752 	 * am_anon[] array on us while the lock is dropped.
753 	 */
754 ReStart:
755 	amap_lock(amap);
756 	AMAP_CHUNK_FOREACH(chunk, amap) {
757 		int i, map = chunk->ac_usedmap;
758 
759 		for (i = ffs(map); i != 0; i = ffs(map)) {
760 			slot = i - 1;
761 			map ^= 1 << slot;
762 			anon = chunk->ac_anon[slot];
763 			pg = anon->an_page;
764 			KASSERT(anon->an_lock == amap->am_lock);
765 
766 			/*
767 			 * The old page must be resident since the parent is
768 			 * wired.
769 			 */
770 			KASSERT(pg != NULL);
771 
772 			/*
773 			 * if the anon ref count is one, we are safe (the child
774 			 * has exclusive access to the page).
775 			 */
776 			if (anon->an_ref <= 1)
777 				continue;
778 
779 			/*
780 			 * If the page is busy, then we have to unlock, wait for
781 			 * it and then restart.
782 			 */
783 			if (pg->pg_flags & PG_BUSY) {
784 				uvm_pagewait(pg, amap->am_lock, "cownow");
785 				goto ReStart;
786 			}
787 
788 			/*
789 			 * Perform a copy-on-write.
790 			 * First - get a new anon and a page.
791 			 */
792 			nanon = uvm_analloc();
793 			if (nanon != NULL) {
794 				/* the new anon will share the amap's lock */
795 				nanon->an_lock = amap->am_lock;
796 				npg = uvm_pagealloc(NULL, 0, nanon, 0);
797 			} else
798 				npg = NULL;	/* XXX: quiet gcc warning */
799 
800 			if (nanon == NULL || npg == NULL) {
801 				/* out of memory */
802 				amap_unlock(amap);
803 				if (nanon != NULL) {
804 					nanon->an_lock = NULL;
805 					nanon->an_ref--;
806 					KASSERT(nanon->an_ref == 0);
807 					uvm_anfree(nanon);
808 				}
809 				uvm_wait("cownowpage");
810 				goto ReStart;
811 			}
812 
813 			/*
814 			 * Copy the data and replace anon with the new one.
815 			 * Also, setup its lock (share the with amap's lock).
816 			 */
817 			uvm_pagecopy(pg, npg);
818 			anon->an_ref--;
819 			KASSERT(anon->an_ref > 0);
820 			chunk->ac_anon[slot] = nanon;
821 
822 			/*
823 			 * Drop PG_BUSY on new page.  Since its owner was write
824 			 * locked all this time - it cannot be PG_RELEASED or
825 			 * PG_WANTED.
826 			 */
827 			atomic_clearbits_int(&npg->pg_flags, PG_BUSY|PG_FAKE);
828 			UVM_PAGE_OWN(npg, NULL);
829 			uvm_lock_pageq();
830 			uvm_pageactivate(npg);
831 			uvm_unlock_pageq();
832 		}
833 	}
834 	amap_unlock(amap);
835 }
836 
837 /*
838  * amap_splitref: split a single reference into two separate references
839  *
840  * => called from uvm_map's clip routines
841  * => origref's map should be locked
842  * => origref->ar_amap should be unlocked (we will lock)
843  */
844 void
845 amap_splitref(struct vm_aref *origref, struct vm_aref *splitref, vaddr_t offset)
846 {
847 	struct vm_amap *amap = origref->ar_amap;
848 	int leftslots;
849 
850 	KASSERT(splitref->ar_amap == amap);
851 	AMAP_B2SLOT(leftslots, offset);
852 	if (leftslots == 0)
853 		panic("amap_splitref: split at zero offset");
854 
855 	amap_lock(amap);
856 
857 	if (amap->am_nslot - origref->ar_pageoff - leftslots <= 0)
858 		panic("amap_splitref: map size check failed");
859 
860 #ifdef UVM_AMAP_PPREF
861 	/* Establish ppref before we add a duplicate reference to the amap. */
862 	if (amap->am_ppref == NULL)
863 		amap_pp_establish(amap);
864 #endif
865 
866 	/* Note: not a share reference. */
867 	amap->am_ref++;
868 	splitref->ar_amap = amap;
869 	splitref->ar_pageoff = origref->ar_pageoff + leftslots;
870 	amap_unlock(amap);
871 }
872 
873 #ifdef UVM_AMAP_PPREF
874 
875 /*
876  * amap_pp_establish: add a ppref array to an amap, if possible.
877  *
878  * => amap should be locked by caller* => amap should be locked by caller
879  */
880 void
881 amap_pp_establish(struct vm_amap *amap)
882 {
883 
884 	KASSERT(rw_write_held(amap->am_lock));
885 	amap->am_ppref = mallocarray(amap->am_nslot, sizeof(int),
886 	    M_UVMAMAP, M_NOWAIT|M_ZERO);
887 
888 	if (amap->am_ppref == NULL) {
889 		/* Failure - just do not use ppref. */
890 		amap->am_ppref = PPREF_NONE;
891 		return;
892 	}
893 
894 	pp_setreflen(amap->am_ppref, 0, amap->am_ref, amap->am_nslot);
895 }
896 
897 /*
898  * amap_pp_adjref: adjust reference count to a part of an amap using the
899  * per-page reference count array.
900  *
901  * => caller must check that ppref != PPREF_NONE before calling.
902  * => map and amap must be locked.
903  */
904 void
905 amap_pp_adjref(struct vm_amap *amap, int curslot, vsize_t slotlen, int adjval)
906 {
907  	int stopslot, *ppref, lcv, prevlcv;
908  	int ref, len, prevref, prevlen;
909 
910 	KASSERT(rw_write_held(amap->am_lock));
911 
912 	stopslot = curslot + slotlen;
913 	ppref = amap->am_ppref;
914  	prevlcv = 0;
915 
916 	/*
917 	 * Advance to the correct place in the array, fragment if needed.
918 	 */
919 	for (lcv = 0 ; lcv < curslot ; lcv += len) {
920 		pp_getreflen(ppref, lcv, &ref, &len);
921 		if (lcv + len > curslot) {     /* goes past start? */
922 			pp_setreflen(ppref, lcv, ref, curslot - lcv);
923 			pp_setreflen(ppref, curslot, ref, len - (curslot -lcv));
924 			len = curslot - lcv;   /* new length of entry @ lcv */
925 		}
926 		prevlcv = lcv;
927 	}
928 	if (lcv != 0)
929 		pp_getreflen(ppref, prevlcv, &prevref, &prevlen);
930 	else {
931 		/*
932 		 * Ensure that the "prevref == ref" test below always
933 		 * fails, since we are starting from the beginning of
934 		 * the ppref array; that is, there is no previous chunk.
935 		 */
936 		prevref = -1;
937 		prevlen = 0;
938 	}
939 
940 	/*
941 	 * Now adjust reference counts in range.  Merge the first
942 	 * changed entry with the last unchanged entry if possible.
943 	 */
944 	if (lcv != curslot)
945 		panic("amap_pp_adjref: overshot target");
946 
947 	for (/* lcv already set */; lcv < stopslot ; lcv += len) {
948 		pp_getreflen(ppref, lcv, &ref, &len);
949 		if (lcv + len > stopslot) {     /* goes past end? */
950 			pp_setreflen(ppref, lcv, ref, stopslot - lcv);
951 			pp_setreflen(ppref, stopslot, ref,
952 			    len - (stopslot - lcv));
953 			len = stopslot - lcv;
954 		}
955 		ref += adjval;
956 		if (ref < 0)
957 			panic("amap_pp_adjref: negative reference count");
958 		if (lcv == prevlcv + prevlen && ref == prevref) {
959 			pp_setreflen(ppref, prevlcv, ref, prevlen + len);
960 		} else {
961 			pp_setreflen(ppref, lcv, ref, len);
962 		}
963 		if (ref == 0)
964 			amap_wiperange(amap, lcv, len);
965 	}
966 
967 }
968 
969 void
970 amap_wiperange_chunk(struct vm_amap *amap, struct vm_amap_chunk *chunk,
971     int slotoff, int slots)
972 {
973 	int curslot, i, map;
974 	int startbase, endbase;
975 	struct vm_anon *anon;
976 
977 	startbase = AMAP_BASE_SLOT(slotoff);
978 	endbase = AMAP_BASE_SLOT(slotoff + slots - 1);
979 
980 	map = chunk->ac_usedmap;
981 	if (startbase == chunk->ac_baseslot)
982 		map &= ~((1 << (slotoff - startbase)) - 1);
983 	if (endbase == chunk->ac_baseslot)
984 		map &= (1 << (slotoff + slots - endbase)) - 1;
985 
986 	for (i = ffs(map); i != 0; i = ffs(map)) {
987 		int refs;
988 
989 		curslot = i - 1;
990 		map ^= 1 << curslot;
991 		chunk->ac_usedmap ^= 1 << curslot;
992 		anon = chunk->ac_anon[curslot];
993 		KASSERT(anon->an_lock == amap->am_lock);
994 
995 		/* remove it from the amap */
996 		chunk->ac_anon[curslot] = NULL;
997 
998 		amap->am_nused--;
999 
1000 		/* drop anon reference count */
1001 		refs = --anon->an_ref;
1002 		if (refs == 0) {
1003 			uvm_anfree(anon);
1004 		}
1005 
1006 		/*
1007 		 * done with this anon, next ...!
1008 		 */
1009 
1010 	}	/* end of 'for' loop */
1011 }
1012 
1013 /*
1014  * amap_wiperange: wipe out a range of an amap.
1015  * Note: different from amap_wipeout because the amap is kept intact.
1016  *
1017  * => Both map and amap must be locked by caller.
1018  */
1019 void
1020 amap_wiperange(struct vm_amap *amap, int slotoff, int slots)
1021 {
1022 	int bucket, startbucket, endbucket;
1023 	struct vm_amap_chunk *chunk, *nchunk;
1024 
1025 	KASSERT(rw_write_held(amap->am_lock));
1026 
1027 	startbucket = UVM_AMAP_BUCKET(amap, slotoff);
1028 	endbucket = UVM_AMAP_BUCKET(amap, slotoff + slots - 1);
1029 
1030 	/*
1031 	 * We can either traverse the amap by am_chunks or by am_buckets.
1032 	 * Determine which way is less expensive.
1033 	 */
1034 	if (UVM_AMAP_SMALL(amap))
1035 		amap_wiperange_chunk(amap, &amap->am_small, slotoff, slots);
1036 	else if (endbucket + 1 - startbucket >= amap->am_ncused) {
1037 		TAILQ_FOREACH_SAFE(chunk, &amap->am_chunks, ac_list, nchunk) {
1038 			if (chunk->ac_baseslot + chunk->ac_nslot <= slotoff)
1039 				continue;
1040 			if (chunk->ac_baseslot >= slotoff + slots)
1041 				continue;
1042 
1043 			amap_wiperange_chunk(amap, chunk, slotoff, slots);
1044 			if (chunk->ac_usedmap == 0)
1045 				amap_chunk_free(amap, chunk);
1046 		}
1047 	} else {
1048 		for (bucket = startbucket; bucket <= endbucket; bucket++) {
1049 			for (chunk = amap->am_buckets[bucket]; chunk != NULL;
1050 			    chunk = nchunk) {
1051 				nchunk = TAILQ_NEXT(chunk, ac_list);
1052 
1053 				if (UVM_AMAP_BUCKET(amap, chunk->ac_baseslot) !=
1054 				    bucket)
1055 					break;
1056 				if (chunk->ac_baseslot + chunk->ac_nslot <=
1057 				    slotoff)
1058 					continue;
1059 				if (chunk->ac_baseslot >= slotoff + slots)
1060 					continue;
1061 
1062 				amap_wiperange_chunk(amap, chunk, slotoff,
1063 				    slots);
1064 				if (chunk->ac_usedmap == 0)
1065 					amap_chunk_free(amap, chunk);
1066 			}
1067 		}
1068 	}
1069 }
1070 
1071 #endif
1072 
1073 /*
1074  * amap_swap_off: pagein anonymous pages in amaps and drop swap slots.
1075  *
1076  * => note that we don't always traverse all anons.
1077  *    eg. amaps being wiped out, released anons.
1078  * => return TRUE if failed.
1079  */
1080 
1081 boolean_t
1082 amap_swap_off(int startslot, int endslot)
1083 {
1084 	struct vm_amap *am;
1085 	struct vm_amap *am_next;
1086 	struct vm_amap marker;
1087 	boolean_t rv = FALSE;
1088 
1089 	amap_lock_list();
1090 	for (am = LIST_FIRST(&amap_list); am != NULL && !rv; am = am_next) {
1091 		int i, map;
1092 		struct vm_amap_chunk *chunk;
1093 
1094 		amap_lock(am);
1095 		if (am->am_nused == 0) {
1096 			amap_unlock(am);
1097 			am_next = LIST_NEXT(am, am_list);
1098 			continue;
1099 		}
1100 
1101 		LIST_INSERT_AFTER(am, &marker, am_list);
1102 		amap_unlock_list();
1103 
1104 again:
1105 		AMAP_CHUNK_FOREACH(chunk, am) {
1106 			map = chunk->ac_usedmap;
1107 
1108 			for (i = ffs(map); i != 0; i = ffs(map)) {
1109 				int swslot;
1110 				int slot = i - 1;
1111 				struct vm_anon *anon;
1112 
1113 				map ^= 1 << slot;
1114 				anon = chunk->ac_anon[slot];
1115 
1116 				swslot = anon->an_swslot;
1117 				if (swslot < startslot || endslot <= swslot) {
1118 					continue;
1119 				}
1120 
1121 				am->am_flags |= AMAP_SWAPOFF;
1122 
1123 				rv = uvm_anon_pagein(am, anon);
1124 				amap_lock(am);
1125 
1126 				am->am_flags &= ~AMAP_SWAPOFF;
1127 				if (amap_refs(am) == 0) {
1128 					amap_wipeout(am);
1129 					am = NULL;
1130 					goto nextamap;
1131 				}
1132 				if (rv)
1133 					goto nextamap;
1134 				goto again;
1135 			}
1136 		}
1137 nextamap:
1138 		if (am != NULL)
1139 			amap_unlock(am);
1140 		amap_lock_list();
1141 		am_next = LIST_NEXT(&marker, am_list);
1142 		LIST_REMOVE(&marker, am_list);
1143 	}
1144 	amap_unlock_list();
1145 
1146 	return rv;
1147 }
1148 
1149 /*
1150  * amap_lookup: look up a page in an amap.
1151  *
1152  * => amap should be locked by caller.
1153  */
1154 struct vm_anon *
1155 amap_lookup(struct vm_aref *aref, vaddr_t offset)
1156 {
1157 	int slot;
1158 	struct vm_amap *amap = aref->ar_amap;
1159 	struct vm_amap_chunk *chunk;
1160 
1161 	AMAP_B2SLOT(slot, offset);
1162 	slot += aref->ar_pageoff;
1163 	KASSERT(slot < amap->am_nslot);
1164 
1165 	chunk = amap_chunk_get(amap, slot, 0, PR_NOWAIT);
1166 	if (chunk == NULL)
1167 		return NULL;
1168 
1169 	return chunk->ac_anon[UVM_AMAP_SLOTIDX(slot)];
1170 }
1171 
1172 /*
1173  * amap_lookups: look up a range of pages in an amap.
1174  *
1175  * => amap should be locked by caller.
1176  * => XXXCDC: this interface is biased toward array-based amaps.  fix.
1177  */
1178 void
1179 amap_lookups(struct vm_aref *aref, vaddr_t offset,
1180     struct vm_anon **anons, int npages)
1181 {
1182 	int i, lcv, n, slot;
1183 	struct vm_amap *amap = aref->ar_amap;
1184 	struct vm_amap_chunk *chunk = NULL;
1185 
1186 	AMAP_B2SLOT(slot, offset);
1187 	slot += aref->ar_pageoff;
1188 
1189 	KASSERT((slot + (npages - 1)) < amap->am_nslot);
1190 
1191 	for (i = 0, lcv = slot; lcv < slot + npages; i += n, lcv += n) {
1192 		n = UVM_AMAP_CHUNK - UVM_AMAP_SLOTIDX(lcv);
1193 		if (lcv + n > slot + npages)
1194 			n = slot + npages - lcv;
1195 
1196 		chunk = amap_chunk_get(amap, lcv, 0, PR_NOWAIT);
1197 		if (chunk == NULL)
1198 			memset(&anons[i], 0, n * sizeof(*anons));
1199 		else
1200 			memcpy(&anons[i],
1201 			    &chunk->ac_anon[UVM_AMAP_SLOTIDX(lcv)],
1202 			    n * sizeof(*anons));
1203 	}
1204 }
1205 
1206 /*
1207  * amap_populate: ensure that the amap can store an anon for the page at
1208  * offset. This function can sleep until memory to store the anon is
1209  * available.
1210  */
1211 void
1212 amap_populate(struct vm_aref *aref, vaddr_t offset)
1213 {
1214 	int slot;
1215 	struct vm_amap *amap = aref->ar_amap;
1216 	struct vm_amap_chunk *chunk;
1217 
1218 	AMAP_B2SLOT(slot, offset);
1219 	slot += aref->ar_pageoff;
1220 	KASSERT(slot < amap->am_nslot);
1221 
1222 	chunk = amap_chunk_get(amap, slot, 1, PR_WAITOK);
1223 	KASSERT(chunk != NULL);
1224 }
1225 
1226 /*
1227  * amap_add: add (or replace) a page to an amap.
1228  *
1229  * => amap should be locked by caller.
1230  * => anon must have the lock associated with this amap.
1231  */
1232 int
1233 amap_add(struct vm_aref *aref, vaddr_t offset, struct vm_anon *anon,
1234     boolean_t replace)
1235 {
1236 	int slot;
1237 	struct vm_amap *amap = aref->ar_amap;
1238 	struct vm_amap_chunk *chunk;
1239 
1240 	AMAP_B2SLOT(slot, offset);
1241 	slot += aref->ar_pageoff;
1242 	KASSERT(slot < amap->am_nslot);
1243 
1244 	chunk = amap_chunk_get(amap, slot, 1, PR_NOWAIT);
1245 	if (chunk == NULL)
1246 		return 1;
1247 
1248 	slot = UVM_AMAP_SLOTIDX(slot);
1249 	if (replace) {
1250 		struct vm_anon *oanon  = chunk->ac_anon[slot];
1251 
1252 		KASSERT(oanon != NULL);
1253 		if (oanon->an_page && (amap->am_flags & AMAP_SHARED) != 0) {
1254 			pmap_page_protect(oanon->an_page, PROT_NONE);
1255 			/*
1256 			 * XXX: suppose page is supposed to be wired somewhere?
1257 			 */
1258 		}
1259 	} else {   /* !replace */
1260 		if (chunk->ac_anon[slot] != NULL)
1261 			panic("amap_add: slot in use");
1262 
1263 		chunk->ac_usedmap |= 1 << slot;
1264 		amap->am_nused++;
1265 	}
1266 	chunk->ac_anon[slot] = anon;
1267 
1268 	return 0;
1269 }
1270 
1271 /*
1272  * amap_unadd: remove a page from an amap.
1273  *
1274  * => amap should be locked by caller.
1275  */
1276 void
1277 amap_unadd(struct vm_aref *aref, vaddr_t offset)
1278 {
1279 	struct vm_amap *amap = aref->ar_amap;
1280 	struct vm_amap_chunk *chunk;
1281 	int slot;
1282 
1283 	KASSERT(rw_write_held(amap->am_lock));
1284 
1285 	AMAP_B2SLOT(slot, offset);
1286 	slot += aref->ar_pageoff;
1287 	KASSERT(slot < amap->am_nslot);
1288 	chunk = amap_chunk_get(amap, slot, 0, PR_NOWAIT);
1289 	KASSERT(chunk != NULL);
1290 
1291 	slot = UVM_AMAP_SLOTIDX(slot);
1292 	KASSERT(chunk->ac_anon[slot] != NULL);
1293 
1294 	chunk->ac_anon[slot] = NULL;
1295 	chunk->ac_usedmap &= ~(1 << slot);
1296 	amap->am_nused--;
1297 
1298 	if (chunk->ac_usedmap == 0)
1299 		amap_chunk_free(amap, chunk);
1300 }
1301 
1302 /*
1303  * amap_adjref_anons: adjust the reference count(s) on amap and its anons.
1304  */
1305 static void
1306 amap_adjref_anons(struct vm_amap *amap, vaddr_t offset, vsize_t len,
1307     int refv, boolean_t all)
1308 {
1309 #ifdef UVM_AMAP_PPREF
1310 	KASSERT(rw_write_held(amap->am_lock));
1311 
1312 	/*
1313 	 * We must establish the ppref array before changing am_ref
1314 	 * so that the ppref values match the current amap refcount.
1315 	 */
1316 	if (amap->am_ppref == NULL && !all && len != amap->am_nslot) {
1317 		amap_pp_establish(amap);
1318 	}
1319 #endif
1320 
1321 	amap->am_ref += refv;
1322 
1323 #ifdef UVM_AMAP_PPREF
1324 	if (amap->am_ppref && amap->am_ppref != PPREF_NONE) {
1325 		if (all) {
1326 			amap_pp_adjref(amap, 0, amap->am_nslot, refv);
1327 		} else {
1328 			amap_pp_adjref(amap, offset, len, refv);
1329 		}
1330 	}
1331 #endif
1332 	amap_unlock(amap);
1333 }
1334 
1335 /*
1336  * amap_ref: gain a reference to an amap.
1337  *
1338  * => amap must not be locked (we will lock).
1339  * => "offset" and "len" are in units of pages.
1340  * => Called at fork time to gain the child's reference.
1341  */
1342 void
1343 amap_ref(struct vm_amap *amap, vaddr_t offset, vsize_t len, int flags)
1344 {
1345 	amap_lock(amap);
1346 	if (flags & AMAP_SHARED)
1347 		amap->am_flags |= AMAP_SHARED;
1348 	amap_adjref_anons(amap, offset, len, 1, (flags & AMAP_REFALL) != 0);
1349 }
1350 
1351 /*
1352  * amap_unref: remove a reference to an amap.
1353  *
1354  * => All pmap-level references to this amap must be already removed.
1355  * => Called from uvm_unmap_detach(); entry is already removed from the map.
1356  * => We will lock amap, so it must be unlocked.
1357  */
1358 void
1359 amap_unref(struct vm_amap *amap, vaddr_t offset, vsize_t len, boolean_t all)
1360 {
1361 	amap_lock(amap);
1362 
1363 	KASSERT(amap->am_ref > 0);
1364 
1365 	if (amap->am_ref == 1) {
1366 		/*
1367 		 * If the last reference - wipeout and destroy the amap.
1368 		 */
1369 		amap->am_ref--;
1370 		amap_wipeout(amap);
1371 		return;
1372 	}
1373 
1374 	/*
1375 	 * Otherwise, drop the reference count(s) on anons.
1376 	 */
1377 	if (amap->am_ref == 2 && (amap->am_flags & AMAP_SHARED) != 0) {
1378 		amap->am_flags &= ~AMAP_SHARED;
1379 	}
1380 	amap_adjref_anons(amap, offset, len, -1, all);
1381 }
1382