1 /* $NetBSD: uvm_amap.c,v 1.122 2020/07/09 05:57:15 skrll Exp $ */ 2 3 /* 4 * Copyright (c) 1997 Charles D. Cranor and Washington University. 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 17 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 18 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 19 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 20 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 21 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 22 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 23 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 25 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 */ 27 28 /* 29 * uvm_amap.c: amap operations 30 */ 31 32 /* 33 * this file contains functions that perform operations on amaps. see 34 * uvm_amap.h for a brief explanation of the role of amaps in uvm. 35 */ 36 37 #include <sys/cdefs.h> 38 __KERNEL_RCSID(0, "$NetBSD: uvm_amap.c,v 1.122 2020/07/09 05:57:15 skrll Exp $"); 39 40 #include "opt_uvmhist.h" 41 42 #include <sys/param.h> 43 #include <sys/systm.h> 44 #include <sys/kernel.h> 45 #include <sys/kmem.h> 46 #include <sys/pool.h> 47 #include <sys/atomic.h> 48 49 #include <uvm/uvm.h> 50 #include <uvm/uvm_swap.h> 51 52 /* 53 * cache for allocation of vm_map structures. note that in order to 54 * avoid an endless loop, the amap cache's allocator cannot allocate 55 * memory from an amap (it currently goes through the kernel uobj, so 56 * we are ok). 57 */ 58 static struct pool_cache uvm_amap_cache; 59 static kmutex_t amap_list_lock __cacheline_aligned; 60 static LIST_HEAD(, vm_amap) amap_list; 61 62 /* 63 * local functions 64 */ 65 66 static int 67 amap_roundup_slots(int slots) 68 { 69 70 return kmem_roundup_size(slots * sizeof(int)) / sizeof(int); 71 } 72 73 #ifdef UVM_AMAP_PPREF 74 /* 75 * what is ppref? ppref is an _optional_ amap feature which is used 76 * to keep track of reference counts on a per-page basis. it is enabled 77 * when UVM_AMAP_PPREF is defined. 78 * 79 * when enabled, an array of ints is allocated for the pprefs. this 80 * array is allocated only when a partial reference is added to the 81 * map (either by unmapping part of the amap, or gaining a reference 82 * to only a part of an amap). if the allocation of the array fails 83 * (KM_NOSLEEP), then we set the array pointer to PPREF_NONE to indicate 84 * that we tried to do ppref's but couldn't alloc the array so just 85 * give up (after all, this is an optional feature!). 86 * 87 * the array is divided into page sized "chunks." for chunks of length 1, 88 * the chunk reference count plus one is stored in that chunk's slot. 89 * for chunks of length > 1 the first slot contains (the reference count 90 * plus one) * -1. [the negative value indicates that the length is 91 * greater than one.] the second slot of the chunk contains the length 92 * of the chunk. here is an example: 93 * 94 * actual REFS: 2 2 2 2 3 1 1 0 0 0 4 4 0 1 1 1 95 * ppref: -3 4 x x 4 -2 2 -1 3 x -5 2 1 -2 3 x 96 * <----------><-><----><-------><----><-><-------> 97 * (x = don't care) 98 * 99 * this allows us to allow one int to contain the ref count for the whole 100 * chunk. note that the "plus one" part is needed because a reference 101 * count of zero is neither positive or negative (need a way to tell 102 * if we've got one zero or a bunch of them). 103 * 104 * here are some in-line functions to help us. 105 */ 106 107 /* 108 * pp_getreflen: get the reference and length for a specific offset 109 * 110 * => ppref's amap must be locked 111 */ 112 static inline void 113 pp_getreflen(int *ppref, int offset, int *refp, int *lenp) 114 { 115 116 if (ppref[offset] > 0) { /* chunk size must be 1 */ 117 *refp = ppref[offset] - 1; /* don't forget to adjust */ 118 *lenp = 1; 119 } else { 120 *refp = (ppref[offset] * -1) - 1; 121 *lenp = ppref[offset+1]; 122 } 123 } 124 125 /* 126 * pp_setreflen: set the reference and length for a specific offset 127 * 128 * => ppref's amap must be locked 129 */ 130 static inline void 131 pp_setreflen(int *ppref, int offset, int ref, int len) 132 { 133 if (len == 0) 134 return; 135 if (len == 1) { 136 ppref[offset] = ref + 1; 137 } else { 138 ppref[offset] = (ref + 1) * -1; 139 ppref[offset+1] = len; 140 } 141 } 142 #endif /* UVM_AMAP_PPREF */ 143 144 /* 145 * amap_alloc1: allocate an amap, but do not initialise the overlay. 146 * 147 * => Note: lock is not set. 148 */ 149 static struct vm_amap * 150 amap_alloc1(int slots, int padslots, int flags) 151 { 152 const bool nowait = (flags & UVM_FLAG_NOWAIT) != 0; 153 const km_flag_t kmflags = nowait ? KM_NOSLEEP : KM_SLEEP; 154 struct vm_amap *amap; 155 krwlock_t *newlock, *oldlock; 156 int totalslots; 157 158 amap = pool_cache_get(&uvm_amap_cache, nowait ? PR_NOWAIT : PR_WAITOK); 159 if (amap == NULL) { 160 return NULL; 161 } 162 KASSERT(amap->am_lock != NULL); 163 KASSERT(amap->am_nused == 0); 164 165 /* Try to privatize the lock if currently shared. */ 166 if (rw_obj_refcnt(amap->am_lock) > 1) { 167 newlock = rw_obj_tryalloc(); 168 if (newlock != NULL) { 169 oldlock = amap->am_lock; 170 mutex_enter(&amap_list_lock); 171 amap->am_lock = newlock; 172 mutex_exit(&amap_list_lock); 173 rw_obj_free(oldlock); 174 } 175 } 176 177 totalslots = amap_roundup_slots(slots + padslots); 178 amap->am_ref = 1; 179 amap->am_flags = 0; 180 #ifdef UVM_AMAP_PPREF 181 amap->am_ppref = NULL; 182 #endif 183 amap->am_maxslot = totalslots; 184 amap->am_nslot = slots; 185 186 /* 187 * Note: since allocations are likely big, we expect to reduce the 188 * memory fragmentation by allocating them in separate blocks. 189 */ 190 amap->am_slots = kmem_alloc(totalslots * sizeof(int), kmflags); 191 if (amap->am_slots == NULL) 192 goto fail1; 193 194 amap->am_bckptr = kmem_alloc(totalslots * sizeof(int), kmflags); 195 if (amap->am_bckptr == NULL) 196 goto fail2; 197 198 amap->am_anon = kmem_alloc(totalslots * sizeof(struct vm_anon *), 199 kmflags); 200 if (amap->am_anon == NULL) 201 goto fail3; 202 203 return amap; 204 205 fail3: 206 kmem_free(amap->am_bckptr, totalslots * sizeof(int)); 207 fail2: 208 kmem_free(amap->am_slots, totalslots * sizeof(int)); 209 fail1: 210 pool_cache_put(&uvm_amap_cache, amap); 211 212 /* 213 * XXX hack to tell the pagedaemon how many pages we need, 214 * since we can need more than it would normally free. 215 */ 216 if (nowait) { 217 extern u_int uvm_extrapages; 218 atomic_add_int(&uvm_extrapages, 219 ((sizeof(int) * 2 + sizeof(struct vm_anon *)) * 220 totalslots) >> PAGE_SHIFT); 221 } 222 return NULL; 223 } 224 225 /* 226 * amap_alloc: allocate an amap to manage "sz" bytes of anonymous VM 227 * 228 * => caller should ensure sz is a multiple of PAGE_SIZE 229 * => reference count to new amap is set to one 230 * => new amap is returned unlocked 231 */ 232 233 struct vm_amap * 234 amap_alloc(vaddr_t sz, vaddr_t padsz, int waitf) 235 { 236 struct vm_amap *amap; 237 int slots, padslots; 238 UVMHIST_FUNC(__func__); UVMHIST_CALLED(maphist); 239 240 AMAP_B2SLOT(slots, sz); 241 AMAP_B2SLOT(padslots, padsz); 242 243 amap = amap_alloc1(slots, padslots, waitf); 244 if (amap) { 245 memset(amap->am_anon, 0, 246 amap->am_maxslot * sizeof(struct vm_anon *)); 247 } 248 249 UVMHIST_LOG(maphist,"<- done, amap = %#jx, sz=%jd", (uintptr_t)amap, 250 sz, 0, 0); 251 return(amap); 252 } 253 254 /* 255 * amap_ctor: pool_cache constructor for new amaps 256 * 257 * => carefully synchronize with amap_swap_off() 258 */ 259 static int 260 amap_ctor(void *arg, void *obj, int flags) 261 { 262 struct vm_amap *amap = obj; 263 264 if ((flags & PR_NOWAIT) != 0) { 265 amap->am_lock = rw_obj_tryalloc(); 266 if (amap->am_lock == NULL) { 267 return ENOMEM; 268 } 269 } else { 270 amap->am_lock = rw_obj_alloc(); 271 } 272 amap->am_nused = 0; 273 amap->am_flags = 0; 274 275 mutex_enter(&amap_list_lock); 276 LIST_INSERT_HEAD(&amap_list, amap, am_list); 277 mutex_exit(&amap_list_lock); 278 return 0; 279 } 280 281 /* 282 * amap_ctor: pool_cache destructor for amaps 283 * 284 * => carefully synchronize with amap_swap_off() 285 */ 286 static void 287 amap_dtor(void *arg, void *obj) 288 { 289 struct vm_amap *amap = obj; 290 291 KASSERT(amap->am_nused == 0); 292 293 mutex_enter(&amap_list_lock); 294 LIST_REMOVE(amap, am_list); 295 mutex_exit(&amap_list_lock); 296 rw_obj_free(amap->am_lock); 297 } 298 299 /* 300 * uvm_amap_init: initialize the amap system. 301 */ 302 void 303 uvm_amap_init(void) 304 { 305 306 mutex_init(&amap_list_lock, MUTEX_DEFAULT, IPL_NONE); 307 308 pool_cache_bootstrap(&uvm_amap_cache, sizeof(struct vm_amap), 0, 0, 309 PR_LARGECACHE, "amappl", NULL, IPL_NONE, amap_ctor, amap_dtor, 310 NULL); 311 } 312 313 /* 314 * amap_free: free an amap 315 * 316 * => the amap must be unlocked 317 * => the amap should have a zero reference count and be empty 318 */ 319 void 320 amap_free(struct vm_amap *amap) 321 { 322 int slots; 323 324 UVMHIST_FUNC(__func__); UVMHIST_CALLED(maphist); 325 326 KASSERT(amap->am_ref == 0 && amap->am_nused == 0); 327 KASSERT((amap->am_flags & AMAP_SWAPOFF) == 0); 328 slots = amap->am_maxslot; 329 kmem_free(amap->am_slots, slots * sizeof(*amap->am_slots)); 330 kmem_free(amap->am_bckptr, slots * sizeof(*amap->am_bckptr)); 331 kmem_free(amap->am_anon, slots * sizeof(*amap->am_anon)); 332 #ifdef UVM_AMAP_PPREF 333 if (amap->am_ppref && amap->am_ppref != PPREF_NONE) 334 kmem_free(amap->am_ppref, slots * sizeof(*amap->am_ppref)); 335 #endif 336 pool_cache_put(&uvm_amap_cache, amap); 337 UVMHIST_LOG(maphist,"<- done, freed amap = %#jx", (uintptr_t)amap, 338 0, 0, 0); 339 } 340 341 /* 342 * amap_extend: extend the size of an amap (if needed) 343 * 344 * => called from uvm_map when we want to extend an amap to cover 345 * a new mapping (rather than allocate a new one) 346 * => amap should be unlocked (we will lock it) 347 * => to safely extend an amap it should have a reference count of 348 * one (thus it can't be shared) 349 */ 350 int 351 amap_extend(struct vm_map_entry *entry, vsize_t addsize, int flags) 352 { 353 struct vm_amap *amap = entry->aref.ar_amap; 354 int slotoff = entry->aref.ar_pageoff; 355 int slotmapped, slotadd, slotneed, slotadded, slotalloc; 356 int slotadj, slotarea; 357 int oldnslots; 358 #ifdef UVM_AMAP_PPREF 359 int *newppref, *oldppref; 360 #endif 361 int i, *newsl, *newbck, *oldsl, *oldbck; 362 struct vm_anon **newover, **oldover; 363 const km_flag_t kmflags = 364 (flags & AMAP_EXTEND_NOWAIT) ? KM_NOSLEEP : KM_SLEEP; 365 366 UVMHIST_FUNC(__func__); 367 UVMHIST_CALLARGS(maphist, " (entry=%#jx, addsize=%#jx, flags=%#jx)", 368 (uintptr_t)entry, addsize, flags, 0); 369 370 /* 371 * first, determine how many slots we need in the amap. don't 372 * forget that ar_pageoff could be non-zero: this means that 373 * there are some unused slots before us in the amap. 374 */ 375 376 amap_lock(amap, RW_WRITER); 377 KASSERT(amap_refs(amap) == 1); /* amap can't be shared */ 378 AMAP_B2SLOT(slotmapped, entry->end - entry->start); /* slots mapped */ 379 AMAP_B2SLOT(slotadd, addsize); /* slots to add */ 380 if (flags & AMAP_EXTEND_FORWARDS) { 381 slotneed = slotoff + slotmapped + slotadd; 382 slotadj = 0; 383 slotarea = 0; 384 } else { 385 slotneed = slotadd + slotmapped; 386 slotadj = slotadd - slotoff; 387 slotarea = amap->am_maxslot - slotmapped; 388 } 389 390 /* 391 * case 1: we already have enough slots in the map and thus 392 * only need to bump the reference counts on the slots we are 393 * adding. 394 */ 395 396 if (flags & AMAP_EXTEND_FORWARDS) { 397 if (amap->am_nslot >= slotneed) { 398 #ifdef UVM_AMAP_PPREF 399 if (amap->am_ppref && amap->am_ppref != PPREF_NONE) { 400 amap_pp_adjref(amap, slotoff + slotmapped, 401 slotadd, 1); 402 } 403 #endif 404 amap_unlock(amap); 405 UVMHIST_LOG(maphist, 406 "<- done (case 1f), amap = %#jx, sltneed=%jd", 407 (uintptr_t)amap, slotneed, 0, 0); 408 return 0; 409 } 410 } else { 411 if (slotadj <= 0) { 412 slotoff -= slotadd; 413 entry->aref.ar_pageoff = slotoff; 414 #ifdef UVM_AMAP_PPREF 415 if (amap->am_ppref && amap->am_ppref != PPREF_NONE) { 416 amap_pp_adjref(amap, slotoff, slotadd, 1); 417 } 418 #endif 419 amap_unlock(amap); 420 UVMHIST_LOG(maphist, 421 "<- done (case 1b), amap = %#jx, sltneed=%jd", 422 (uintptr_t)amap, slotneed, 0, 0); 423 return 0; 424 } 425 } 426 427 /* 428 * case 2: we pre-allocated slots for use and we just need to 429 * bump nslot up to take account for these slots. 430 */ 431 432 if (amap->am_maxslot >= slotneed) { 433 if (flags & AMAP_EXTEND_FORWARDS) { 434 #ifdef UVM_AMAP_PPREF 435 if (amap->am_ppref && amap->am_ppref != PPREF_NONE) { 436 if ((slotoff + slotmapped) < amap->am_nslot) 437 amap_pp_adjref(amap, 438 slotoff + slotmapped, 439 (amap->am_nslot - 440 (slotoff + slotmapped)), 1); 441 pp_setreflen(amap->am_ppref, amap->am_nslot, 1, 442 slotneed - amap->am_nslot); 443 } 444 #endif 445 amap->am_nslot = slotneed; 446 amap_unlock(amap); 447 448 /* 449 * no need to zero am_anon since that was done at 450 * alloc time and we never shrink an allocation. 451 */ 452 453 UVMHIST_LOG(maphist,"<- done (case 2f), amap = %#jx, " 454 "slotneed=%jd", (uintptr_t)amap, slotneed, 0, 0); 455 return 0; 456 } else { 457 #ifdef UVM_AMAP_PPREF 458 if (amap->am_ppref && amap->am_ppref != PPREF_NONE) { 459 /* 460 * Slide up the ref counts on the pages that 461 * are actually in use. 462 */ 463 memmove(amap->am_ppref + slotarea, 464 amap->am_ppref + slotoff, 465 slotmapped * sizeof(int)); 466 /* 467 * Mark the (adjusted) gap at the front as 468 * referenced/not referenced. 469 */ 470 pp_setreflen(amap->am_ppref, 471 0, 0, slotarea - slotadd); 472 pp_setreflen(amap->am_ppref, 473 slotarea - slotadd, 1, slotadd); 474 } 475 #endif 476 477 /* 478 * Slide the anon pointers up and clear out 479 * the space we just made. 480 */ 481 memmove(amap->am_anon + slotarea, 482 amap->am_anon + slotoff, 483 slotmapped * sizeof(struct vm_anon*)); 484 memset(amap->am_anon + slotoff, 0, 485 (slotarea - slotoff) * sizeof(struct vm_anon *)); 486 487 /* 488 * Slide the backpointers up, but don't bother 489 * wiping out the old slots. 490 */ 491 memmove(amap->am_bckptr + slotarea, 492 amap->am_bckptr + slotoff, 493 slotmapped * sizeof(int)); 494 495 /* 496 * Adjust all the useful active slot numbers. 497 */ 498 for (i = 0; i < amap->am_nused; i++) 499 amap->am_slots[i] += (slotarea - slotoff); 500 501 /* 502 * We just filled all the empty space in the 503 * front of the amap by activating a few new 504 * slots. 505 */ 506 amap->am_nslot = amap->am_maxslot; 507 entry->aref.ar_pageoff = slotarea - slotadd; 508 amap_unlock(amap); 509 510 UVMHIST_LOG(maphist,"<- done (case 2b), amap = %#jx, " 511 "slotneed=%jd", (uintptr_t)amap, slotneed, 0, 0); 512 return 0; 513 } 514 } 515 516 /* 517 * Case 3: we need to allocate a new amap and copy all the amap 518 * data over from old amap to the new one. Drop the lock before 519 * performing allocation. 520 * 521 * Note: since allocations are likely big, we expect to reduce the 522 * memory fragmentation by allocating them in separate blocks. 523 */ 524 525 amap_unlock(amap); 526 527 if (slotneed >= UVM_AMAP_LARGE) { 528 return E2BIG; 529 } 530 531 slotalloc = amap_roundup_slots(slotneed); 532 #ifdef UVM_AMAP_PPREF 533 newppref = NULL; 534 if (amap->am_ppref && amap->am_ppref != PPREF_NONE) { 535 /* Will be handled later if fails. */ 536 newppref = kmem_alloc(slotalloc * sizeof(*newppref), kmflags); 537 } 538 #endif 539 newsl = kmem_alloc(slotalloc * sizeof(*newsl), kmflags); 540 newbck = kmem_alloc(slotalloc * sizeof(*newbck), kmflags); 541 newover = kmem_alloc(slotalloc * sizeof(*newover), kmflags); 542 if (newsl == NULL || newbck == NULL || newover == NULL) { 543 #ifdef UVM_AMAP_PPREF 544 if (newppref != NULL) { 545 kmem_free(newppref, slotalloc * sizeof(*newppref)); 546 } 547 #endif 548 if (newsl != NULL) { 549 kmem_free(newsl, slotalloc * sizeof(*newsl)); 550 } 551 if (newbck != NULL) { 552 kmem_free(newbck, slotalloc * sizeof(*newbck)); 553 } 554 if (newover != NULL) { 555 kmem_free(newover, slotalloc * sizeof(*newover)); 556 } 557 return ENOMEM; 558 } 559 amap_lock(amap, RW_WRITER); 560 KASSERT(amap->am_maxslot < slotneed); 561 562 /* 563 * Copy everything over to new allocated areas. 564 */ 565 566 slotadded = slotalloc - amap->am_nslot; 567 if (!(flags & AMAP_EXTEND_FORWARDS)) 568 slotarea = slotalloc - slotmapped; 569 570 /* do am_slots */ 571 oldsl = amap->am_slots; 572 if (flags & AMAP_EXTEND_FORWARDS) 573 memcpy(newsl, oldsl, sizeof(int) * amap->am_nused); 574 else 575 for (i = 0; i < amap->am_nused; i++) 576 newsl[i] = oldsl[i] + slotarea - slotoff; 577 amap->am_slots = newsl; 578 579 /* do am_anon */ 580 oldover = amap->am_anon; 581 if (flags & AMAP_EXTEND_FORWARDS) { 582 memcpy(newover, oldover, 583 sizeof(struct vm_anon *) * amap->am_nslot); 584 memset(newover + amap->am_nslot, 0, 585 sizeof(struct vm_anon *) * slotadded); 586 } else { 587 memcpy(newover + slotarea, oldover + slotoff, 588 sizeof(struct vm_anon *) * slotmapped); 589 memset(newover, 0, 590 sizeof(struct vm_anon *) * slotarea); 591 } 592 amap->am_anon = newover; 593 594 /* do am_bckptr */ 595 oldbck = amap->am_bckptr; 596 if (flags & AMAP_EXTEND_FORWARDS) 597 memcpy(newbck, oldbck, sizeof(int) * amap->am_nslot); 598 else 599 memcpy(newbck + slotarea, oldbck + slotoff, 600 sizeof(int) * slotmapped); 601 amap->am_bckptr = newbck; 602 603 #ifdef UVM_AMAP_PPREF 604 /* do ppref */ 605 oldppref = amap->am_ppref; 606 if (newppref) { 607 if (flags & AMAP_EXTEND_FORWARDS) { 608 memcpy(newppref, oldppref, 609 sizeof(int) * amap->am_nslot); 610 memset(newppref + amap->am_nslot, 0, 611 sizeof(int) * slotadded); 612 } else { 613 memcpy(newppref + slotarea, oldppref + slotoff, 614 sizeof(int) * slotmapped); 615 } 616 amap->am_ppref = newppref; 617 if ((flags & AMAP_EXTEND_FORWARDS) && 618 (slotoff + slotmapped) < amap->am_nslot) 619 amap_pp_adjref(amap, slotoff + slotmapped, 620 (amap->am_nslot - (slotoff + slotmapped)), 1); 621 if (flags & AMAP_EXTEND_FORWARDS) 622 pp_setreflen(newppref, amap->am_nslot, 1, 623 slotneed - amap->am_nslot); 624 else { 625 pp_setreflen(newppref, 0, 0, 626 slotalloc - slotneed); 627 pp_setreflen(newppref, slotalloc - slotneed, 1, 628 slotneed - slotmapped); 629 } 630 } else { 631 if (amap->am_ppref) 632 amap->am_ppref = PPREF_NONE; 633 } 634 #endif 635 636 /* update master values */ 637 if (flags & AMAP_EXTEND_FORWARDS) 638 amap->am_nslot = slotneed; 639 else { 640 entry->aref.ar_pageoff = slotarea - slotadd; 641 amap->am_nslot = slotalloc; 642 } 643 oldnslots = amap->am_maxslot; 644 amap->am_maxslot = slotalloc; 645 amap_unlock(amap); 646 647 kmem_free(oldsl, oldnslots * sizeof(*oldsl)); 648 kmem_free(oldbck, oldnslots * sizeof(*oldbck)); 649 kmem_free(oldover, oldnslots * sizeof(*oldover)); 650 #ifdef UVM_AMAP_PPREF 651 if (oldppref && oldppref != PPREF_NONE) 652 kmem_free(oldppref, oldnslots * sizeof(*oldppref)); 653 #endif 654 UVMHIST_LOG(maphist,"<- done (case 3), amap = %#jx, slotneed=%jd", 655 (uintptr_t)amap, slotneed, 0, 0); 656 return 0; 657 } 658 659 /* 660 * amap_share_protect: change protection of anons in a shared amap 661 * 662 * for shared amaps, given the current data structure layout, it is 663 * not possible for us to directly locate all maps referencing the 664 * shared anon (to change the protection). in order to protect data 665 * in shared maps we use pmap_page_protect(). [this is useful for IPC 666 * mechanisms like map entry passing that may want to write-protect 667 * all mappings of a shared amap.] we traverse am_anon or am_slots 668 * depending on the current state of the amap. 669 * 670 * => entry's map and amap must be locked by the caller 671 */ 672 void 673 amap_share_protect(struct vm_map_entry *entry, vm_prot_t prot) 674 { 675 struct vm_amap *amap = entry->aref.ar_amap; 676 u_int slots, lcv, slot, stop; 677 struct vm_anon *anon; 678 679 KASSERT(rw_write_held(amap->am_lock)); 680 681 AMAP_B2SLOT(slots, (entry->end - entry->start)); 682 stop = entry->aref.ar_pageoff + slots; 683 684 if (slots < amap->am_nused) { 685 /* 686 * Cheaper to traverse am_anon. 687 */ 688 for (lcv = entry->aref.ar_pageoff ; lcv < stop ; lcv++) { 689 anon = amap->am_anon[lcv]; 690 if (anon == NULL) { 691 continue; 692 } 693 if (anon->an_page) { 694 pmap_page_protect(anon->an_page, prot); 695 } 696 } 697 return; 698 } 699 700 /* 701 * Cheaper to traverse am_slots. 702 */ 703 for (lcv = 0 ; lcv < amap->am_nused ; lcv++) { 704 slot = amap->am_slots[lcv]; 705 if (slot < entry->aref.ar_pageoff || slot >= stop) { 706 continue; 707 } 708 anon = amap->am_anon[slot]; 709 if (anon->an_page) { 710 pmap_page_protect(anon->an_page, prot); 711 } 712 } 713 } 714 715 /* 716 * amap_wipeout: wipeout all anon's in an amap; then free the amap! 717 * 718 * => Called from amap_unref(), when reference count drops to zero. 719 * => amap must be locked. 720 */ 721 722 void 723 amap_wipeout(struct vm_amap *amap) 724 { 725 u_int lcv; 726 727 UVMHIST_FUNC(__func__); 728 UVMHIST_CALLARGS(maphist,"(amap=%#jx)", (uintptr_t)amap, 0,0,0); 729 730 KASSERT(rw_write_held(amap->am_lock)); 731 KASSERT(amap->am_ref == 0); 732 733 if (__predict_false(amap->am_flags & AMAP_SWAPOFF)) { 734 /* 735 * Note: amap_swap_off() will call us again. 736 */ 737 amap_unlock(amap); 738 return; 739 } 740 741 for (lcv = 0 ; lcv < amap->am_nused ; lcv++) { 742 struct vm_anon *anon; 743 u_int slot; 744 745 slot = amap->am_slots[lcv]; 746 anon = amap->am_anon[slot]; 747 KASSERT(anon != NULL && anon->an_ref != 0); 748 749 KASSERT(anon->an_lock == amap->am_lock); 750 UVMHIST_LOG(maphist," processing anon %#jx, ref=%jd", 751 (uintptr_t)anon, anon->an_ref, 0, 0); 752 753 /* 754 * Drop the reference. 755 */ 756 757 if (__predict_true(--anon->an_ref == 0)) { 758 uvm_anfree(anon); 759 } 760 if (__predict_false((lcv & 31) == 31)) { 761 preempt_point(); 762 } 763 } 764 765 /* 766 * Finally, destroy the amap. 767 */ 768 769 amap->am_nused = 0; 770 amap_unlock(amap); 771 amap_free(amap); 772 UVMHIST_LOG(maphist,"<- done!", 0,0,0,0); 773 } 774 775 /* 776 * amap_copy: ensure that a map entry's "needs_copy" flag is false 777 * by copying the amap if necessary. 778 * 779 * => an entry with a null amap pointer will get a new (blank) one. 780 * => the map that the map entry belongs to must be locked by caller. 781 * => the amap currently attached to "entry" (if any) must be unlocked. 782 * => if canchunk is true, then we may clip the entry into a chunk 783 * => "startva" and "endva" are used only if canchunk is true. they are 784 * used to limit chunking (e.g. if you have a large space that you 785 * know you are going to need to allocate amaps for, there is no point 786 * in allowing that to be chunked) 787 */ 788 789 void 790 amap_copy(struct vm_map *map, struct vm_map_entry *entry, int flags, 791 vaddr_t startva, vaddr_t endva) 792 { 793 const int waitf = (flags & AMAP_COPY_NOWAIT) ? UVM_FLAG_NOWAIT : 0; 794 struct vm_amap *amap, *srcamap; 795 u_int slots, lcv; 796 krwlock_t *oldlock; 797 vsize_t len; 798 799 UVMHIST_FUNC(__func__); 800 UVMHIST_CALLARGS(maphist, " (map=%#j, entry=%#j, flags=%jd)", 801 (uintptr_t)map, (uintptr_t)entry, flags, -2); 802 803 KASSERT(map != kernel_map); /* we use nointr pool */ 804 805 srcamap = entry->aref.ar_amap; 806 len = entry->end - entry->start; 807 808 /* 809 * Is there an amap to copy? If not, create one. 810 */ 811 812 if (srcamap == NULL) { 813 const bool canchunk = (flags & AMAP_COPY_NOCHUNK) == 0; 814 815 /* 816 * Check to see if we have a large amap that we can 817 * chunk. We align startva/endva to chunk-sized 818 * boundaries and then clip to them. 819 */ 820 821 if (canchunk && atop(len) >= UVM_AMAP_LARGE) { 822 vsize_t chunksize; 823 824 /* Convert slots to bytes. */ 825 chunksize = UVM_AMAP_CHUNK << PAGE_SHIFT; 826 startva = (startva / chunksize) * chunksize; 827 endva = roundup(endva, chunksize); 828 UVMHIST_LOG(maphist, 829 " chunk amap ==> clip %#jx->%#jx to %#jx->%#jx", 830 entry->start, entry->end, startva, endva); 831 UVM_MAP_CLIP_START(map, entry, startva); 832 833 /* Watch out for endva wrap-around! */ 834 if (endva >= startva) { 835 UVM_MAP_CLIP_END(map, entry, endva); 836 } 837 } 838 839 if ((flags & AMAP_COPY_NOMERGE) == 0 && 840 uvm_mapent_trymerge(map, entry, UVM_MERGE_COPYING)) { 841 return; 842 } 843 844 UVMHIST_LOG(maphist, "<- done [creating new amap %#jx->%#jx]", 845 entry->start, entry->end, 0, 0); 846 847 /* 848 * Allocate an initialised amap and install it. 849 * Note: we must update the length after clipping. 850 */ 851 len = entry->end - entry->start; 852 entry->aref.ar_pageoff = 0; 853 entry->aref.ar_amap = amap_alloc(len, 0, waitf); 854 if (entry->aref.ar_amap != NULL) { 855 entry->etype &= ~UVM_ET_NEEDSCOPY; 856 } 857 return; 858 } 859 860 /* 861 * First check and see if we are the only map entry referencing 862 * he amap we currently have. If so, then just take it over instead 863 * of copying it. Note that we are reading am_ref without lock held 864 * as the value value can only be one if we have the only reference 865 * to the amap (via our locked map). If the value is greater than 866 * one, then allocate amap and re-check the value. 867 */ 868 869 if (srcamap->am_ref == 1) { 870 entry->etype &= ~UVM_ET_NEEDSCOPY; 871 UVMHIST_LOG(maphist, "<- done [ref cnt = 1, took it over]", 872 0, 0, 0, 0); 873 return; 874 } 875 876 UVMHIST_LOG(maphist," amap=%#j, ref=%jd, must copy it", 877 (uintptr_t)srcamap, srcamap->am_ref, 0, 0); 878 879 /* 880 * Allocate a new amap (note: not initialised, etc). 881 */ 882 883 AMAP_B2SLOT(slots, len); 884 amap = amap_alloc1(slots, 0, waitf); 885 if (amap == NULL) { 886 UVMHIST_LOG(maphist, " amap_alloc1 failed", 0,0,0,0); 887 return; 888 } 889 890 /* 891 * Make the new amap share the source amap's lock, and then lock 892 * both. We must do this before we set am_nused != 0, otherwise 893 * amap_swap_off() can become interested in the amap. 894 */ 895 896 oldlock = amap->am_lock; 897 mutex_enter(&amap_list_lock); 898 amap->am_lock = srcamap->am_lock; 899 mutex_exit(&amap_list_lock); 900 rw_obj_hold(amap->am_lock); 901 rw_obj_free(oldlock); 902 903 amap_lock(srcamap, RW_WRITER); 904 905 /* 906 * Re-check the reference count with the lock held. If it has 907 * dropped to one - we can take over the existing map. 908 */ 909 910 if (srcamap->am_ref == 1) { 911 /* Just take over the existing amap. */ 912 entry->etype &= ~UVM_ET_NEEDSCOPY; 913 amap_unlock(srcamap); 914 /* Destroy the new (unused) amap. */ 915 amap->am_ref--; 916 amap_free(amap); 917 return; 918 } 919 920 /* 921 * Copy the slots. Zero the padded part. 922 */ 923 924 UVMHIST_LOG(maphist, " copying amap now",0, 0, 0, 0); 925 for (lcv = 0 ; lcv < slots; lcv++) { 926 amap->am_anon[lcv] = 927 srcamap->am_anon[entry->aref.ar_pageoff + lcv]; 928 if (amap->am_anon[lcv] == NULL) 929 continue; 930 KASSERT(amap->am_anon[lcv]->an_lock == srcamap->am_lock); 931 KASSERT(amap->am_anon[lcv]->an_ref > 0); 932 KASSERT(amap->am_nused < amap->am_maxslot); 933 amap->am_anon[lcv]->an_ref++; 934 amap->am_bckptr[lcv] = amap->am_nused; 935 amap->am_slots[amap->am_nused] = lcv; 936 amap->am_nused++; 937 } 938 memset(&amap->am_anon[lcv], 0, 939 (amap->am_maxslot - lcv) * sizeof(struct vm_anon *)); 940 941 /* 942 * Drop our reference to the old amap (srcamap) and unlock. 943 * Since the reference count on srcamap is greater than one, 944 * (we checked above), it cannot drop to zero while it is locked. 945 */ 946 947 srcamap->am_ref--; 948 KASSERT(srcamap->am_ref > 0); 949 950 if (srcamap->am_ref == 1 && (srcamap->am_flags & AMAP_SHARED) != 0) { 951 srcamap->am_flags &= ~AMAP_SHARED; 952 } 953 #ifdef UVM_AMAP_PPREF 954 if (srcamap->am_ppref && srcamap->am_ppref != PPREF_NONE) { 955 amap_pp_adjref(srcamap, entry->aref.ar_pageoff, 956 len >> PAGE_SHIFT, -1); 957 } 958 #endif 959 960 amap_unlock(srcamap); 961 962 /* 963 * Install new amap. 964 */ 965 966 entry->aref.ar_pageoff = 0; 967 entry->aref.ar_amap = amap; 968 entry->etype &= ~UVM_ET_NEEDSCOPY; 969 UVMHIST_LOG(maphist, "<- done",0, 0, 0, 0); 970 } 971 972 /* 973 * amap_cow_now: resolve all copy-on-write faults in an amap now for fork(2) 974 * 975 * called during fork(2) when the parent process has a wired map 976 * entry. in that case we want to avoid write-protecting pages 977 * in the parent's map (e.g. like what you'd do for a COW page) 978 * so we resolve the COW here. 979 * 980 * => assume parent's entry was wired, thus all pages are resident. 981 * => assume pages that are loaned out (loan_count) are already mapped 982 * read-only in all maps, and thus no need for us to worry about them 983 * => assume both parent and child vm_map's are locked 984 * => caller passes child's map/entry in to us 985 * => if we run out of memory we will unlock the amap and sleep _with_ the 986 * parent and child vm_map's locked(!). we have to do this since 987 * we are in the middle of a fork(2) and we can't let the parent 988 * map change until we are done copying all the map entrys. 989 * => XXXCDC: out of memory should cause fork to fail, but there is 990 * currently no easy way to do this (needs fix) 991 */ 992 993 void 994 amap_cow_now(struct vm_map *map, struct vm_map_entry *entry) 995 { 996 struct vm_amap *amap = entry->aref.ar_amap; 997 struct vm_anon *anon, *nanon; 998 struct vm_page *pg, *npg; 999 u_int lcv, slot; 1000 1001 /* 1002 * note that if we unlock the amap then we must ReStart the "lcv" for 1003 * loop because some other process could reorder the anon's in the 1004 * am_anon[] array on us while the lock is dropped. 1005 */ 1006 1007 ReStart: 1008 amap_lock(amap, RW_WRITER); 1009 for (lcv = 0 ; lcv < amap->am_nused ; lcv++) { 1010 slot = amap->am_slots[lcv]; 1011 anon = amap->am_anon[slot]; 1012 KASSERT(anon->an_lock == amap->am_lock); 1013 1014 /* 1015 * If anon has only one reference - we must have already 1016 * copied it. This can happen if we needed to sleep waiting 1017 * for memory in a previous run through this loop. The new 1018 * page might even have been paged out, since is not wired. 1019 */ 1020 1021 if (anon->an_ref == 1) { 1022 KASSERT(anon->an_page != NULL || anon->an_swslot != 0); 1023 continue; 1024 } 1025 1026 /* 1027 * The old page must be resident since the parent is wired. 1028 */ 1029 1030 pg = anon->an_page; 1031 KASSERT(pg != NULL); 1032 KASSERT(pg->wire_count > 0); 1033 1034 /* 1035 * If the page is loaned then it must already be mapped 1036 * read-only and we don't need to copy it. 1037 */ 1038 1039 if (pg->loan_count != 0) { 1040 continue; 1041 } 1042 KASSERT(pg->uanon == anon && pg->uobject == NULL); 1043 1044 /* 1045 * If the page is busy, then we have to unlock, wait for 1046 * it and then restart. 1047 */ 1048 1049 if (pg->flags & PG_BUSY) { 1050 uvm_pagewait(pg, amap->am_lock, "cownow"); 1051 goto ReStart; 1052 } 1053 1054 /* 1055 * Perform a copy-on-write. 1056 * First - get a new anon and a page. 1057 */ 1058 1059 nanon = uvm_analloc(); 1060 if (nanon) { 1061 nanon->an_lock = amap->am_lock; 1062 npg = uvm_pagealloc(NULL, 0, nanon, 0); 1063 } else { 1064 npg = NULL; 1065 } 1066 if (nanon == NULL || npg == NULL) { 1067 amap_unlock(amap); 1068 if (nanon) { 1069 nanon->an_lock = NULL; 1070 nanon->an_ref--; 1071 KASSERT(nanon->an_ref == 0); 1072 uvm_anfree(nanon); 1073 } 1074 uvm_wait("cownowpage"); 1075 goto ReStart; 1076 } 1077 1078 /* 1079 * Copy the data and replace anon with the new one. 1080 * Also, setup its lock (share the with amap's lock). 1081 */ 1082 1083 uvm_pagecopy(pg, npg); 1084 anon->an_ref--; 1085 KASSERT(anon->an_ref > 0); 1086 amap->am_anon[slot] = nanon; 1087 1088 /* 1089 * Drop PG_BUSY on new page. Since its owner was write 1090 * locked all this time - it cannot be PG_RELEASED or 1091 * waited on. 1092 */ 1093 uvm_pagelock(npg); 1094 uvm_pageactivate(npg); 1095 uvm_pageunlock(npg); 1096 npg->flags &= ~(PG_BUSY|PG_FAKE); 1097 UVM_PAGE_OWN(npg, NULL); 1098 } 1099 amap_unlock(amap); 1100 } 1101 1102 /* 1103 * amap_splitref: split a single reference into two separate references 1104 * 1105 * => called from uvm_map's clip routines 1106 * => origref's map should be locked 1107 * => origref->ar_amap should be unlocked (we will lock) 1108 */ 1109 void 1110 amap_splitref(struct vm_aref *origref, struct vm_aref *splitref, vaddr_t offset) 1111 { 1112 struct vm_amap *amap = origref->ar_amap; 1113 u_int leftslots; 1114 1115 KASSERT(splitref->ar_amap == origref->ar_amap); 1116 AMAP_B2SLOT(leftslots, offset); 1117 KASSERT(leftslots != 0); 1118 1119 amap_lock(amap, RW_WRITER); 1120 KASSERT(amap->am_nslot - origref->ar_pageoff - leftslots > 0); 1121 1122 #ifdef UVM_AMAP_PPREF 1123 /* Establish ppref before we add a duplicate reference to the amap. */ 1124 if (amap->am_ppref == NULL) { 1125 amap_pp_establish(amap, origref->ar_pageoff); 1126 } 1127 #endif 1128 /* Note: not a share reference. */ 1129 amap->am_ref++; 1130 splitref->ar_pageoff = origref->ar_pageoff + leftslots; 1131 amap_unlock(amap); 1132 } 1133 1134 #ifdef UVM_AMAP_PPREF 1135 1136 /* 1137 * amap_pp_establish: add a ppref array to an amap, if possible. 1138 * 1139 * => amap should be locked by caller. 1140 */ 1141 void 1142 amap_pp_establish(struct vm_amap *amap, vaddr_t offset) 1143 { 1144 const size_t sz = amap->am_maxslot * sizeof(*amap->am_ppref); 1145 1146 KASSERT(rw_write_held(amap->am_lock)); 1147 1148 amap->am_ppref = kmem_zalloc(sz, KM_NOSLEEP); 1149 if (amap->am_ppref == NULL) { 1150 /* Failure - just do not use ppref. */ 1151 amap->am_ppref = PPREF_NONE; 1152 return; 1153 } 1154 pp_setreflen(amap->am_ppref, 0, 0, offset); 1155 pp_setreflen(amap->am_ppref, offset, amap->am_ref, 1156 amap->am_nslot - offset); 1157 } 1158 1159 /* 1160 * amap_pp_adjref: adjust reference count to a part of an amap using the 1161 * per-page reference count array. 1162 * 1163 * => caller must check that ppref != PPREF_NONE before calling. 1164 * => map and amap must be locked. 1165 */ 1166 void 1167 amap_pp_adjref(struct vm_amap *amap, int curslot, vsize_t slotlen, int adjval) 1168 { 1169 int stopslot, *ppref, lcv, prevlcv; 1170 int ref, len, prevref, prevlen; 1171 1172 KASSERT(rw_write_held(amap->am_lock)); 1173 1174 stopslot = curslot + slotlen; 1175 ppref = amap->am_ppref; 1176 prevlcv = 0; 1177 1178 /* 1179 * Advance to the correct place in the array, fragment if needed. 1180 */ 1181 1182 for (lcv = 0 ; lcv < curslot ; lcv += len) { 1183 pp_getreflen(ppref, lcv, &ref, &len); 1184 if (lcv + len > curslot) { /* goes past start? */ 1185 pp_setreflen(ppref, lcv, ref, curslot - lcv); 1186 pp_setreflen(ppref, curslot, ref, len - (curslot -lcv)); 1187 len = curslot - lcv; /* new length of entry @ lcv */ 1188 } 1189 prevlcv = lcv; 1190 } 1191 if (lcv == 0) { 1192 /* 1193 * Ensure that the "prevref == ref" test below always 1194 * fails, since we are starting from the beginning of 1195 * the ppref array; that is, there is no previous chunk. 1196 */ 1197 prevref = -1; 1198 prevlen = 0; 1199 } else { 1200 pp_getreflen(ppref, prevlcv, &prevref, &prevlen); 1201 } 1202 1203 /* 1204 * Now adjust reference counts in range. Merge the first 1205 * changed entry with the last unchanged entry if possible. 1206 */ 1207 KASSERT(lcv == curslot); 1208 for (/* lcv already set */; lcv < stopslot ; lcv += len) { 1209 pp_getreflen(ppref, lcv, &ref, &len); 1210 if (lcv + len > stopslot) { /* goes past end? */ 1211 pp_setreflen(ppref, lcv, ref, stopslot - lcv); 1212 pp_setreflen(ppref, stopslot, ref, 1213 len - (stopslot - lcv)); 1214 len = stopslot - lcv; 1215 } 1216 ref += adjval; 1217 KASSERT(ref >= 0); 1218 KASSERT(ref <= amap->am_ref); 1219 if (lcv == prevlcv + prevlen && ref == prevref) { 1220 pp_setreflen(ppref, prevlcv, ref, prevlen + len); 1221 } else { 1222 pp_setreflen(ppref, lcv, ref, len); 1223 } 1224 if (ref == 0) { 1225 amap_wiperange(amap, lcv, len); 1226 } 1227 } 1228 } 1229 1230 /* 1231 * amap_wiperange: wipe out a range of an amap. 1232 * Note: different from amap_wipeout because the amap is kept intact. 1233 * 1234 * => Both map and amap must be locked by caller. 1235 */ 1236 void 1237 amap_wiperange(struct vm_amap *amap, int slotoff, int slots) 1238 { 1239 u_int lcv, stop, slotend; 1240 bool byanon; 1241 1242 KASSERT(rw_write_held(amap->am_lock)); 1243 1244 /* 1245 * We can either traverse the amap by am_anon or by am_slots. 1246 * Determine which way is less expensive. 1247 */ 1248 1249 if (slots < amap->am_nused) { 1250 byanon = true; 1251 lcv = slotoff; 1252 stop = slotoff + slots; 1253 slotend = 0; 1254 } else { 1255 byanon = false; 1256 lcv = 0; 1257 stop = amap->am_nused; 1258 slotend = slotoff + slots; 1259 } 1260 1261 while (lcv < stop) { 1262 struct vm_anon *anon; 1263 u_int curslot, ptr, last; 1264 1265 if (byanon) { 1266 curslot = lcv++; /* lcv advances here */ 1267 if (amap->am_anon[curslot] == NULL) 1268 continue; 1269 } else { 1270 curslot = amap->am_slots[lcv]; 1271 if (curslot < slotoff || curslot >= slotend) { 1272 lcv++; /* lcv advances here */ 1273 continue; 1274 } 1275 stop--; /* drop stop, since anon will be removed */ 1276 } 1277 anon = amap->am_anon[curslot]; 1278 KASSERT(anon->an_lock == amap->am_lock); 1279 1280 /* 1281 * Remove anon from the amap. 1282 */ 1283 1284 amap->am_anon[curslot] = NULL; 1285 ptr = amap->am_bckptr[curslot]; 1286 last = amap->am_nused - 1; 1287 if (ptr != last) { 1288 amap->am_slots[ptr] = amap->am_slots[last]; 1289 amap->am_bckptr[amap->am_slots[ptr]] = ptr; 1290 } 1291 amap->am_nused--; 1292 1293 /* 1294 * Drop its reference count. 1295 */ 1296 1297 KASSERT(anon->an_lock == amap->am_lock); 1298 if (--anon->an_ref == 0) { 1299 uvm_anfree(anon); 1300 } 1301 } 1302 } 1303 1304 #endif 1305 1306 #if defined(VMSWAP) 1307 1308 /* 1309 * amap_swap_off: pagein anonymous pages in amaps and drop swap slots. 1310 * 1311 * => called with swap_syscall_lock held. 1312 * => note that we don't always traverse all anons. 1313 * eg. amaps being wiped out, released anons. 1314 * => return true if failed. 1315 */ 1316 1317 bool 1318 amap_swap_off(int startslot, int endslot) 1319 { 1320 struct vm_amap *am; 1321 struct vm_amap *am_next; 1322 struct vm_amap marker_prev; 1323 struct vm_amap marker_next; 1324 bool rv = false; 1325 1326 #if defined(DIAGNOSTIC) 1327 memset(&marker_prev, 0, sizeof(marker_prev)); 1328 memset(&marker_next, 0, sizeof(marker_next)); 1329 #endif /* defined(DIAGNOSTIC) */ 1330 1331 mutex_enter(&amap_list_lock); 1332 for (am = LIST_FIRST(&amap_list); am != NULL && !rv; am = am_next) { 1333 int i; 1334 1335 LIST_INSERT_BEFORE(am, &marker_prev, am_list); 1336 LIST_INSERT_AFTER(am, &marker_next, am_list); 1337 1338 /* amap_list_lock prevents the lock pointer from changing. */ 1339 if (!amap_lock_try(am, RW_WRITER)) { 1340 (void)kpause("amapswpo", false, 1, &amap_list_lock); 1341 am_next = LIST_NEXT(&marker_prev, am_list); 1342 if (am_next == &marker_next) { 1343 am_next = LIST_NEXT(am_next, am_list); 1344 } else { 1345 KASSERT(LIST_NEXT(am_next, am_list) == 1346 &marker_next); 1347 } 1348 LIST_REMOVE(&marker_prev, am_list); 1349 LIST_REMOVE(&marker_next, am_list); 1350 continue; 1351 } 1352 1353 mutex_exit(&amap_list_lock); 1354 1355 /* If am_nused == 0, the amap could be free - careful. */ 1356 for (i = 0; i < am->am_nused; i++) { 1357 int slot; 1358 int swslot; 1359 struct vm_anon *anon; 1360 1361 slot = am->am_slots[i]; 1362 anon = am->am_anon[slot]; 1363 KASSERT(anon->an_lock == am->am_lock); 1364 1365 swslot = anon->an_swslot; 1366 if (swslot < startslot || endslot <= swslot) { 1367 continue; 1368 } 1369 1370 am->am_flags |= AMAP_SWAPOFF; 1371 1372 rv = uvm_anon_pagein(am, anon); 1373 amap_lock(am, RW_WRITER); 1374 1375 am->am_flags &= ~AMAP_SWAPOFF; 1376 if (amap_refs(am) == 0) { 1377 amap_wipeout(am); 1378 am = NULL; 1379 break; 1380 } 1381 if (rv) { 1382 break; 1383 } 1384 i = 0; 1385 } 1386 1387 if (am) { 1388 amap_unlock(am); 1389 } 1390 1391 mutex_enter(&amap_list_lock); 1392 KASSERT(LIST_NEXT(&marker_prev, am_list) == &marker_next || 1393 LIST_NEXT(LIST_NEXT(&marker_prev, am_list), am_list) == 1394 &marker_next); 1395 am_next = LIST_NEXT(&marker_next, am_list); 1396 LIST_REMOVE(&marker_prev, am_list); 1397 LIST_REMOVE(&marker_next, am_list); 1398 } 1399 mutex_exit(&amap_list_lock); 1400 1401 return rv; 1402 } 1403 1404 #endif /* defined(VMSWAP) */ 1405 1406 /* 1407 * amap_lookup: look up a page in an amap. 1408 * 1409 * => amap should be locked by caller. 1410 */ 1411 struct vm_anon * 1412 amap_lookup(struct vm_aref *aref, vaddr_t offset) 1413 { 1414 struct vm_amap *amap = aref->ar_amap; 1415 struct vm_anon *an; 1416 u_int slot; 1417 1418 UVMHIST_FUNC(__func__); UVMHIST_CALLED(maphist); 1419 KASSERT(rw_lock_held(amap->am_lock)); 1420 1421 AMAP_B2SLOT(slot, offset); 1422 slot += aref->ar_pageoff; 1423 an = amap->am_anon[slot]; 1424 1425 UVMHIST_LOG(maphist, 1426 "<- done (amap=%#jx, offset=%#jx, result=%#jx)", 1427 (uintptr_t)amap, offset, (uintptr_t)an, 0); 1428 1429 KASSERT(slot < amap->am_nslot); 1430 KASSERT(an == NULL || an->an_ref != 0); 1431 KASSERT(an == NULL || an->an_lock == amap->am_lock); 1432 return an; 1433 } 1434 1435 /* 1436 * amap_lookups: look up a range of pages in an amap. 1437 * 1438 * => amap should be locked by caller. 1439 */ 1440 void 1441 amap_lookups(struct vm_aref *aref, vaddr_t offset, struct vm_anon **anons, 1442 int npages) 1443 { 1444 struct vm_amap *amap = aref->ar_amap; 1445 u_int slot; 1446 1447 UVMHIST_FUNC(__func__); UVMHIST_CALLED(maphist); 1448 KASSERT(rw_lock_held(amap->am_lock)); 1449 1450 AMAP_B2SLOT(slot, offset); 1451 slot += aref->ar_pageoff; 1452 1453 UVMHIST_LOG(maphist, " slot=%u, npages=%d, nslot=%d", 1454 slot, npages, amap->am_nslot, 0); 1455 1456 KASSERT((slot + (npages - 1)) < amap->am_nslot); 1457 memcpy(anons, &amap->am_anon[slot], npages * sizeof(struct vm_anon *)); 1458 1459 #if defined(DIAGNOSTIC) 1460 for (int i = 0; i < npages; i++) { 1461 struct vm_anon * const an = anons[i]; 1462 if (an == NULL) { 1463 continue; 1464 } 1465 KASSERT(an->an_ref != 0); 1466 KASSERT(an->an_lock == amap->am_lock); 1467 } 1468 #endif 1469 UVMHIST_LOG(maphist, "<- done", 0, 0, 0, 0); 1470 } 1471 1472 /* 1473 * amap_add: add (or replace) a page to an amap. 1474 * 1475 * => amap should be locked by caller. 1476 * => anon must have the lock associated with this amap. 1477 */ 1478 void 1479 amap_add(struct vm_aref *aref, vaddr_t offset, struct vm_anon *anon, 1480 bool replace) 1481 { 1482 struct vm_amap *amap = aref->ar_amap; 1483 u_int slot; 1484 1485 UVMHIST_FUNC(__func__); UVMHIST_CALLED(maphist); 1486 KASSERT(rw_write_held(amap->am_lock)); 1487 KASSERT(anon->an_lock == amap->am_lock); 1488 1489 AMAP_B2SLOT(slot, offset); 1490 slot += aref->ar_pageoff; 1491 KASSERT(slot < amap->am_nslot); 1492 1493 if (replace) { 1494 struct vm_anon *oanon = amap->am_anon[slot]; 1495 1496 KASSERT(oanon != NULL); 1497 if (oanon->an_page && (amap->am_flags & AMAP_SHARED) != 0) { 1498 pmap_page_protect(oanon->an_page, VM_PROT_NONE); 1499 /* 1500 * XXX: suppose page is supposed to be wired somewhere? 1501 */ 1502 } 1503 } else { 1504 KASSERT(amap->am_anon[slot] == NULL); 1505 KASSERT(amap->am_nused < amap->am_maxslot); 1506 amap->am_bckptr[slot] = amap->am_nused; 1507 amap->am_slots[amap->am_nused] = slot; 1508 amap->am_nused++; 1509 } 1510 amap->am_anon[slot] = anon; 1511 UVMHIST_LOG(maphist, 1512 "<- done (amap=%#jx, offset=%#x, anon=%#jx, rep=%d)", 1513 (uintptr_t)amap, offset, (uintptr_t)anon, replace); 1514 } 1515 1516 /* 1517 * amap_unadd: remove a page from an amap. 1518 * 1519 * => amap should be locked by caller. 1520 */ 1521 void 1522 amap_unadd(struct vm_aref *aref, vaddr_t offset) 1523 { 1524 struct vm_amap *amap = aref->ar_amap; 1525 u_int slot, ptr, last; 1526 1527 UVMHIST_FUNC(__func__); UVMHIST_CALLED(maphist); 1528 KASSERT(rw_write_held(amap->am_lock)); 1529 1530 AMAP_B2SLOT(slot, offset); 1531 slot += aref->ar_pageoff; 1532 KASSERT(slot < amap->am_nslot); 1533 KASSERT(amap->am_anon[slot] != NULL); 1534 KASSERT(amap->am_anon[slot]->an_lock == amap->am_lock); 1535 1536 amap->am_anon[slot] = NULL; 1537 ptr = amap->am_bckptr[slot]; 1538 1539 last = amap->am_nused - 1; 1540 if (ptr != last) { 1541 /* Move the last entry to keep the slots contiguous. */ 1542 amap->am_slots[ptr] = amap->am_slots[last]; 1543 amap->am_bckptr[amap->am_slots[ptr]] = ptr; 1544 } 1545 amap->am_nused--; 1546 UVMHIST_LOG(maphist, "<- done (amap=%#jx, slot=%#jx)", 1547 (uintptr_t)amap, slot,0, 0); 1548 } 1549 1550 /* 1551 * amap_adjref_anons: adjust the reference count(s) on amap and its anons. 1552 */ 1553 static void 1554 amap_adjref_anons(struct vm_amap *amap, vaddr_t offset, vsize_t len, 1555 int refv, bool all) 1556 { 1557 1558 #ifdef UVM_AMAP_PPREF 1559 KASSERT(rw_write_held(amap->am_lock)); 1560 1561 /* 1562 * We must establish the ppref array before changing am_ref 1563 * so that the ppref values match the current amap refcount. 1564 */ 1565 1566 if (amap->am_ppref == NULL && !all && len != amap->am_nslot) { 1567 amap_pp_establish(amap, offset); 1568 } 1569 #endif 1570 1571 amap->am_ref += refv; 1572 1573 #ifdef UVM_AMAP_PPREF 1574 if (amap->am_ppref && amap->am_ppref != PPREF_NONE) { 1575 if (all) { 1576 amap_pp_adjref(amap, 0, amap->am_nslot, refv); 1577 } else { 1578 amap_pp_adjref(amap, offset, len, refv); 1579 } 1580 } 1581 #endif 1582 amap_unlock(amap); 1583 } 1584 1585 /* 1586 * amap_ref: gain a reference to an amap. 1587 * 1588 * => amap must not be locked (we will lock). 1589 * => "offset" and "len" are in units of pages. 1590 * => Called at fork time to gain the child's reference. 1591 */ 1592 void 1593 amap_ref(struct vm_amap *amap, vaddr_t offset, vsize_t len, int flags) 1594 { 1595 UVMHIST_FUNC(__func__); UVMHIST_CALLED(maphist); 1596 1597 amap_lock(amap, RW_WRITER); 1598 if (flags & AMAP_SHARED) { 1599 amap->am_flags |= AMAP_SHARED; 1600 } 1601 amap_adjref_anons(amap, offset, len, 1, (flags & AMAP_REFALL) != 0); 1602 1603 UVMHIST_LOG(maphist,"<- done! amap=%#jx", (uintptr_t)amap, 0, 0, 0); 1604 } 1605 1606 /* 1607 * amap_unref: remove a reference to an amap. 1608 * 1609 * => All pmap-level references to this amap must be already removed. 1610 * => Called from uvm_unmap_detach(); entry is already removed from the map. 1611 * => We will lock amap, so it must be unlocked. 1612 */ 1613 void 1614 amap_unref(struct vm_amap *amap, vaddr_t offset, vsize_t len, bool all) 1615 { 1616 UVMHIST_FUNC(__func__); UVMHIST_CALLED(maphist); 1617 1618 amap_lock(amap, RW_WRITER); 1619 1620 UVMHIST_LOG(maphist," amap=%#jx refs=%d, nused=%d", 1621 (uintptr_t)amap, amap->am_ref, amap->am_nused, 0); 1622 KASSERT(amap->am_ref > 0); 1623 1624 if (amap->am_ref == 1) { 1625 1626 /* 1627 * If the last reference - wipeout and destroy the amap. 1628 */ 1629 amap->am_ref--; 1630 amap_wipeout(amap); 1631 UVMHIST_LOG(maphist,"<- done (was last ref)!", 0, 0, 0, 0); 1632 return; 1633 } 1634 1635 /* 1636 * Otherwise, drop the reference count(s) on anons. 1637 */ 1638 1639 if (amap->am_ref == 2 && (amap->am_flags & AMAP_SHARED) != 0) { 1640 amap->am_flags &= ~AMAP_SHARED; 1641 } 1642 amap_adjref_anons(amap, offset, len, -1, all); 1643 1644 UVMHIST_LOG(maphist,"<- done!", 0, 0, 0, 0); 1645 } 1646