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