1 /* 2 * Copyright (c) 1985, Avadis Tevanian, Jr., Michael Wayne Young 3 * Copyright (c) 1987 Carnegie-Mellon University 4 * Copyright (c) 1991 Regents of the University of California. 5 * All rights reserved. 6 * 7 * This code is derived from software contributed to Berkeley by 8 * The Mach Operating System project at Carnegie-Mellon University. 9 * 10 * The CMU software License Agreement specifies the terms and conditions 11 * for use and redistribution. 12 * 13 * @(#)vm_page.c 7.2 (Berkeley) 04/20/91 14 */ 15 16 /* 17 * Resident memory management module. 18 */ 19 20 #include "param.h" 21 22 #include "vm.h" 23 #include "vm_map.h" 24 #include "vm_page.h" 25 #include "vm_pageout.h" 26 27 /* 28 * Associated with page of user-allocatable memory is a 29 * page structure. 30 */ 31 32 queue_head_t *vm_page_buckets; /* Array of buckets */ 33 int vm_page_bucket_count = 0; /* How big is array? */ 34 int vm_page_hash_mask; /* Mask for hash function */ 35 simple_lock_data_t bucket_lock; /* lock for all buckets XXX */ 36 37 vm_size_t page_size = 4096; 38 vm_size_t page_mask = 4095; 39 int page_shift = 12; 40 41 queue_head_t vm_page_queue_free; 42 queue_head_t vm_page_queue_active; 43 queue_head_t vm_page_queue_inactive; 44 simple_lock_data_t vm_page_queue_lock; 45 simple_lock_data_t vm_page_queue_free_lock; 46 47 vm_page_t vm_page_array; 48 long first_page; 49 long last_page; 50 vm_offset_t first_phys_addr; 51 vm_offset_t last_phys_addr; 52 53 int vm_page_free_count; 54 int vm_page_active_count; 55 int vm_page_inactive_count; 56 int vm_page_wire_count; 57 int vm_page_laundry_count; 58 59 int vm_page_free_target = 0; 60 int vm_page_free_min = 0; 61 int vm_page_inactive_target = 0; 62 int vm_page_free_reserved = 0; 63 64 /* 65 * vm_set_page_size: 66 * 67 * Sets the page size, perhaps based upon the memory 68 * size. Must be called before any use of page-size 69 * dependent functions. 70 * 71 * Sets page_shift and page_mask from page_size. 72 */ 73 void vm_set_page_size() 74 { 75 page_mask = page_size - 1; 76 77 if ((page_mask & page_size) != 0) 78 panic("vm_set_page_size: page size not a power of two"); 79 80 for (page_shift = 0; ; page_shift++) 81 if ((1 << page_shift) == page_size) 82 break; 83 } 84 85 86 /* 87 * vm_page_startup: 88 * 89 * Initializes the resident memory module. 90 * 91 * Allocates memory for the page cells, and 92 * for the object/offset-to-page hash table headers. 93 * Each page cell is initialized and placed on the free list. 94 */ 95 vm_offset_t vm_page_startup(start, end, vaddr) 96 register vm_offset_t start; 97 vm_offset_t end; 98 register vm_offset_t vaddr; 99 { 100 register vm_offset_t mapped; 101 register vm_page_t m; 102 register queue_t bucket; 103 vm_size_t npages; 104 register vm_offset_t new_start; 105 int i; 106 vm_offset_t pa; 107 108 extern vm_offset_t kentry_data; 109 extern vm_size_t kentry_data_size; 110 111 112 /* 113 * Initialize the locks 114 */ 115 116 simple_lock_init(&vm_page_queue_free_lock); 117 simple_lock_init(&vm_page_queue_lock); 118 119 /* 120 * Initialize the queue headers for the free queue, 121 * the active queue and the inactive queue. 122 */ 123 124 queue_init(&vm_page_queue_free); 125 queue_init(&vm_page_queue_active); 126 queue_init(&vm_page_queue_inactive); 127 128 /* 129 * Allocate (and initialize) the hash table buckets. 130 * 131 * The number of buckets MUST BE a power of 2, and 132 * the actual value is the next power of 2 greater 133 * than the number of physical pages in the system. 134 * 135 * Note: 136 * This computation can be tweaked if desired. 137 */ 138 139 vm_page_buckets = (queue_t) vaddr; 140 bucket = vm_page_buckets; 141 if (vm_page_bucket_count == 0) { 142 vm_page_bucket_count = 1; 143 while (vm_page_bucket_count < atop(end - start)) 144 vm_page_bucket_count <<= 1; 145 } 146 147 vm_page_hash_mask = vm_page_bucket_count - 1; 148 149 /* 150 * Validate these addresses. 151 */ 152 153 new_start = round_page(((queue_t)start) + vm_page_bucket_count); 154 mapped = vaddr; 155 vaddr = pmap_map(mapped, start, new_start, 156 VM_PROT_READ|VM_PROT_WRITE); 157 start = new_start; 158 blkclr((caddr_t) mapped, vaddr - mapped); 159 mapped = vaddr; 160 161 for (i = vm_page_bucket_count; i--;) { 162 queue_init(bucket); 163 bucket++; 164 } 165 166 simple_lock_init(&bucket_lock); 167 168 /* 169 * round (or truncate) the addresses to our page size. 170 */ 171 172 end = trunc_page(end); 173 174 /* 175 * Pre-allocate maps and map entries that cannot be dynamically 176 * allocated via malloc(). The maps include the kernel_map and 177 * kmem_map which must be initialized before malloc() will 178 * work (obviously). Also could include pager maps which would 179 * be allocated before kmeminit. 180 * 181 * Allow some kernel map entries... this should be plenty 182 * since people shouldn't be cluttering up the kernel 183 * map (they should use their own maps). 184 */ 185 186 kentry_data_size = MAX_KMAP * sizeof(struct vm_map) + 187 MAX_KMAPENT * sizeof(struct vm_map_entry); 188 kentry_data_size = round_page(kentry_data_size); 189 kentry_data = (vm_offset_t) vaddr; 190 vaddr += kentry_data_size; 191 192 /* 193 * Validate these zone addresses. 194 */ 195 196 new_start = start + (vaddr - mapped); 197 pmap_map(mapped, start, new_start, VM_PROT_READ|VM_PROT_WRITE); 198 blkclr((caddr_t) mapped, (vaddr - mapped)); 199 mapped = vaddr; 200 start = new_start; 201 202 /* 203 * Compute the number of pages of memory that will be 204 * available for use (taking into account the overhead 205 * of a page structure per page). 206 */ 207 208 vm_page_free_count = npages = 209 (end - start)/(PAGE_SIZE + sizeof(struct vm_page)); 210 211 /* 212 * Initialize the mem entry structures now, and 213 * put them in the free queue. 214 */ 215 216 m = vm_page_array = (vm_page_t) vaddr; 217 first_page = start; 218 first_page += npages*sizeof(struct vm_page); 219 first_page = atop(round_page(first_page)); 220 last_page = first_page + npages - 1; 221 222 first_phys_addr = ptoa(first_page); 223 last_phys_addr = ptoa(last_page) + PAGE_MASK; 224 225 /* 226 * Validate these addresses. 227 */ 228 229 new_start = start + (round_page(m + npages) - mapped); 230 mapped = pmap_map(mapped, start, new_start, 231 VM_PROT_READ|VM_PROT_WRITE); 232 start = new_start; 233 234 /* 235 * Clear all of the page structures 236 */ 237 blkclr((caddr_t)m, npages * sizeof(*m)); 238 239 pa = first_phys_addr; 240 while (npages--) { 241 m->copy_on_write = FALSE; 242 m->wanted = FALSE; 243 m->inactive = FALSE; 244 m->active = FALSE; 245 m->busy = FALSE; 246 m->object = NULL; 247 m->phys_addr = pa; 248 queue_enter(&vm_page_queue_free, m, vm_page_t, pageq); 249 m++; 250 pa += PAGE_SIZE; 251 } 252 253 /* 254 * Initialize vm_pages_needed lock here - don't wait for pageout 255 * daemon XXX 256 */ 257 simple_lock_init(&vm_pages_needed_lock); 258 259 return(mapped); 260 } 261 262 /* 263 * vm_page_hash: 264 * 265 * Distributes the object/offset key pair among hash buckets. 266 * 267 * NOTE: This macro depends on vm_page_bucket_count being a power of 2. 268 */ 269 #define vm_page_hash(object, offset) \ 270 (((unsigned)object+(unsigned)atop(offset))&vm_page_hash_mask) 271 272 /* 273 * vm_page_insert: [ internal use only ] 274 * 275 * Inserts the given mem entry into the object/object-page 276 * table and object list. 277 * 278 * The object and page must be locked. 279 */ 280 281 void vm_page_insert(mem, object, offset) 282 register vm_page_t mem; 283 register vm_object_t object; 284 register vm_offset_t offset; 285 { 286 register queue_t bucket; 287 int spl; 288 289 VM_PAGE_CHECK(mem); 290 291 if (mem->tabled) 292 panic("vm_page_insert: already inserted"); 293 294 /* 295 * Record the object/offset pair in this page 296 */ 297 298 mem->object = object; 299 mem->offset = offset; 300 301 /* 302 * Insert it into the object_object/offset hash table 303 */ 304 305 bucket = &vm_page_buckets[vm_page_hash(object, offset)]; 306 spl = splimp(); 307 simple_lock(&bucket_lock); 308 queue_enter(bucket, mem, vm_page_t, hashq); 309 simple_unlock(&bucket_lock); 310 (void) splx(spl); 311 312 /* 313 * Now link into the object's list of backed pages. 314 */ 315 316 queue_enter(&object->memq, mem, vm_page_t, listq); 317 mem->tabled = TRUE; 318 319 /* 320 * And show that the object has one more resident 321 * page. 322 */ 323 324 object->resident_page_count++; 325 } 326 327 /* 328 * vm_page_remove: [ internal use only ] 329 * 330 * Removes the given mem entry from the object/offset-page 331 * table and the object page list. 332 * 333 * The object and page must be locked. 334 */ 335 336 void vm_page_remove(mem) 337 register vm_page_t mem; 338 { 339 register queue_t bucket; 340 int spl; 341 342 VM_PAGE_CHECK(mem); 343 344 if (!mem->tabled) 345 return; 346 347 /* 348 * Remove from the object_object/offset hash table 349 */ 350 351 bucket = &vm_page_buckets[vm_page_hash(mem->object, mem->offset)]; 352 spl = splimp(); 353 simple_lock(&bucket_lock); 354 queue_remove(bucket, mem, vm_page_t, hashq); 355 simple_unlock(&bucket_lock); 356 (void) splx(spl); 357 358 /* 359 * Now remove from the object's list of backed pages. 360 */ 361 362 queue_remove(&mem->object->memq, mem, vm_page_t, listq); 363 364 /* 365 * And show that the object has one fewer resident 366 * page. 367 */ 368 369 mem->object->resident_page_count--; 370 371 mem->tabled = FALSE; 372 } 373 374 /* 375 * vm_page_lookup: 376 * 377 * Returns the page associated with the object/offset 378 * pair specified; if none is found, NULL is returned. 379 * 380 * The object must be locked. No side effects. 381 */ 382 383 vm_page_t vm_page_lookup(object, offset) 384 register vm_object_t object; 385 register vm_offset_t offset; 386 { 387 register vm_page_t mem; 388 register queue_t bucket; 389 int spl; 390 391 /* 392 * Search the hash table for this object/offset pair 393 */ 394 395 bucket = &vm_page_buckets[vm_page_hash(object, offset)]; 396 397 spl = splimp(); 398 simple_lock(&bucket_lock); 399 mem = (vm_page_t) queue_first(bucket); 400 while (!queue_end(bucket, (queue_entry_t) mem)) { 401 VM_PAGE_CHECK(mem); 402 if ((mem->object == object) && (mem->offset == offset)) { 403 simple_unlock(&bucket_lock); 404 splx(spl); 405 return(mem); 406 } 407 mem = (vm_page_t) queue_next(&mem->hashq); 408 } 409 410 simple_unlock(&bucket_lock); 411 splx(spl); 412 return(NULL); 413 } 414 415 /* 416 * vm_page_rename: 417 * 418 * Move the given memory entry from its 419 * current object to the specified target object/offset. 420 * 421 * The object must be locked. 422 */ 423 void vm_page_rename(mem, new_object, new_offset) 424 register vm_page_t mem; 425 register vm_object_t new_object; 426 vm_offset_t new_offset; 427 { 428 if (mem->object == new_object) 429 return; 430 431 vm_page_lock_queues(); /* keep page from moving out from 432 under pageout daemon */ 433 vm_page_remove(mem); 434 vm_page_insert(mem, new_object, new_offset); 435 vm_page_unlock_queues(); 436 } 437 438 void vm_page_init(mem, object, offset) 439 vm_page_t mem; 440 vm_object_t object; 441 vm_offset_t offset; 442 { 443 #define vm_page_init(mem, object, offset) {\ 444 (mem)->busy = TRUE; \ 445 (mem)->tabled = FALSE; \ 446 vm_page_insert((mem), (object), (offset)); \ 447 (mem)->absent = FALSE; \ 448 (mem)->fictitious = FALSE; \ 449 (mem)->page_lock = VM_PROT_NONE; \ 450 (mem)->unlock_request = VM_PROT_NONE; \ 451 (mem)->laundry = FALSE; \ 452 (mem)->active = FALSE; \ 453 (mem)->inactive = FALSE; \ 454 (mem)->wire_count = 0; \ 455 (mem)->clean = TRUE; \ 456 (mem)->copy_on_write = FALSE; \ 457 (mem)->fake = TRUE; \ 458 } 459 460 vm_page_init(mem, object, offset); 461 } 462 463 /* 464 * vm_page_alloc: 465 * 466 * Allocate and return a memory cell associated 467 * with this VM object/offset pair. 468 * 469 * Object must be locked. 470 */ 471 vm_page_t vm_page_alloc(object, offset) 472 vm_object_t object; 473 vm_offset_t offset; 474 { 475 register vm_page_t mem; 476 int spl; 477 478 spl = splimp(); /* XXX */ 479 simple_lock(&vm_page_queue_free_lock); 480 if (queue_empty(&vm_page_queue_free)) { 481 simple_unlock(&vm_page_queue_free_lock); 482 splx(spl); 483 return(NULL); 484 } 485 486 queue_remove_first(&vm_page_queue_free, mem, vm_page_t, pageq); 487 488 vm_page_free_count--; 489 simple_unlock(&vm_page_queue_free_lock); 490 splx(spl); 491 492 vm_page_init(mem, object, offset); 493 494 /* 495 * Decide if we should poke the pageout daemon. 496 * We do this if the free count is less than the low 497 * water mark, or if the free count is less than the high 498 * water mark (but above the low water mark) and the inactive 499 * count is less than its target. 500 * 501 * We don't have the counts locked ... if they change a little, 502 * it doesn't really matter. 503 */ 504 505 if ((vm_page_free_count < vm_page_free_min) || 506 ((vm_page_free_count < vm_page_free_target) && 507 (vm_page_inactive_count < vm_page_inactive_target))) 508 thread_wakeup(&vm_pages_needed); 509 return(mem); 510 } 511 512 /* 513 * vm_page_free: 514 * 515 * Returns the given page to the free list, 516 * disassociating it with any VM object. 517 * 518 * Object and page must be locked prior to entry. 519 */ 520 void vm_page_free(mem) 521 register vm_page_t mem; 522 { 523 vm_page_remove(mem); 524 if (mem->active) { 525 queue_remove(&vm_page_queue_active, mem, vm_page_t, pageq); 526 mem->active = FALSE; 527 vm_page_active_count--; 528 } 529 530 if (mem->inactive) { 531 queue_remove(&vm_page_queue_inactive, mem, vm_page_t, pageq); 532 mem->inactive = FALSE; 533 vm_page_inactive_count--; 534 } 535 536 if (!mem->fictitious) { 537 int spl; 538 539 spl = splimp(); 540 simple_lock(&vm_page_queue_free_lock); 541 queue_enter(&vm_page_queue_free, mem, vm_page_t, pageq); 542 543 vm_page_free_count++; 544 simple_unlock(&vm_page_queue_free_lock); 545 splx(spl); 546 } 547 } 548 549 /* 550 * vm_page_wire: 551 * 552 * Mark this page as wired down by yet 553 * another map, removing it from paging queues 554 * as necessary. 555 * 556 * The page queues must be locked. 557 */ 558 void vm_page_wire(mem) 559 register vm_page_t mem; 560 { 561 VM_PAGE_CHECK(mem); 562 563 if (mem->wire_count == 0) { 564 if (mem->active) { 565 queue_remove(&vm_page_queue_active, mem, vm_page_t, 566 pageq); 567 vm_page_active_count--; 568 mem->active = FALSE; 569 } 570 if (mem->inactive) { 571 queue_remove(&vm_page_queue_inactive, mem, vm_page_t, 572 pageq); 573 vm_page_inactive_count--; 574 mem->inactive = FALSE; 575 } 576 vm_page_wire_count++; 577 } 578 mem->wire_count++; 579 } 580 581 /* 582 * vm_page_unwire: 583 * 584 * Release one wiring of this page, potentially 585 * enabling it to be paged again. 586 * 587 * The page queues must be locked. 588 */ 589 void vm_page_unwire(mem) 590 register vm_page_t mem; 591 { 592 VM_PAGE_CHECK(mem); 593 594 mem->wire_count--; 595 if (mem->wire_count == 0) { 596 queue_enter(&vm_page_queue_active, mem, vm_page_t, pageq); 597 vm_page_active_count++; 598 mem->active = TRUE; 599 vm_page_wire_count--; 600 } 601 } 602 603 /* 604 * vm_page_deactivate: 605 * 606 * Returns the given page to the inactive list, 607 * indicating that no physical maps have access 608 * to this page. [Used by the physical mapping system.] 609 * 610 * The page queues must be locked. 611 */ 612 void vm_page_deactivate(m) 613 register vm_page_t m; 614 { 615 VM_PAGE_CHECK(m); 616 617 /* 618 * Only move active pages -- ignore locked or already 619 * inactive ones. 620 */ 621 622 if (m->active) { 623 pmap_clear_reference(VM_PAGE_TO_PHYS(m)); 624 queue_remove(&vm_page_queue_active, m, vm_page_t, pageq); 625 queue_enter(&vm_page_queue_inactive, m, vm_page_t, pageq); 626 m->active = FALSE; 627 m->inactive = TRUE; 628 vm_page_active_count--; 629 vm_page_inactive_count++; 630 if (pmap_is_modified(VM_PAGE_TO_PHYS(m))) 631 m->clean = FALSE; 632 m->laundry = !m->clean; 633 } 634 } 635 636 /* 637 * vm_page_activate: 638 * 639 * Put the specified page on the active list (if appropriate). 640 * 641 * The page queues must be locked. 642 */ 643 644 void vm_page_activate(m) 645 register vm_page_t m; 646 { 647 VM_PAGE_CHECK(m); 648 649 if (m->inactive) { 650 queue_remove(&vm_page_queue_inactive, m, vm_page_t, 651 pageq); 652 vm_page_inactive_count--; 653 m->inactive = FALSE; 654 } 655 if (m->wire_count == 0) { 656 if (m->active) 657 panic("vm_page_activate: already active"); 658 659 queue_enter(&vm_page_queue_active, m, vm_page_t, pageq); 660 m->active = TRUE; 661 vm_page_active_count++; 662 } 663 } 664 665 /* 666 * vm_page_zero_fill: 667 * 668 * Zero-fill the specified page. 669 * Written as a standard pagein routine, to 670 * be used by the zero-fill object. 671 */ 672 673 boolean_t vm_page_zero_fill(m) 674 vm_page_t m; 675 { 676 VM_PAGE_CHECK(m); 677 678 pmap_zero_page(VM_PAGE_TO_PHYS(m)); 679 return(TRUE); 680 } 681 682 /* 683 * vm_page_copy: 684 * 685 * Copy one page to another 686 */ 687 688 void vm_page_copy(src_m, dest_m) 689 vm_page_t src_m; 690 vm_page_t dest_m; 691 { 692 VM_PAGE_CHECK(src_m); 693 VM_PAGE_CHECK(dest_m); 694 695 pmap_copy_page(VM_PAGE_TO_PHYS(src_m), VM_PAGE_TO_PHYS(dest_m)); 696 } 697