vm_page.c revision 12662
1/* 2 * Copyright (c) 1991 Regents of the University of California. 3 * All rights reserved. 4 * 5 * This code is derived from software contributed to Berkeley by 6 * The Mach Operating System project at Carnegie-Mellon University. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 3. All advertising materials mentioning features or use of this software 17 * must display the following acknowledgement: 18 * This product includes software developed by the University of 19 * California, Berkeley and its contributors. 20 * 4. Neither the name of the University nor the names of its contributors 21 * may be used to endorse or promote products derived from this software 22 * without specific prior written permission. 23 * 24 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 25 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 27 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 28 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 29 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 30 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 31 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 32 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 33 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 34 * SUCH DAMAGE. 35 * 36 * from: @(#)vm_page.c 7.4 (Berkeley) 5/7/91 37 * $Id: vm_page.c,v 1.39 1995/12/03 12:18:39 bde Exp $ 38 */ 39 40/* 41 * Copyright (c) 1987, 1990 Carnegie-Mellon University. 42 * All rights reserved. 43 * 44 * Authors: Avadis Tevanian, Jr., Michael Wayne Young 45 * 46 * Permission to use, copy, modify and distribute this software and 47 * its documentation is hereby granted, provided that both the copyright 48 * notice and this permission notice appear in all copies of the 49 * software, derivative works or modified versions, and any portions 50 * thereof, and that both notices appear in supporting documentation. 51 * 52 * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" 53 * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND 54 * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. 55 * 56 * Carnegie Mellon requests users of this software to return to 57 * 58 * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU 59 * School of Computer Science 60 * Carnegie Mellon University 61 * Pittsburgh PA 15213-3890 62 * 63 * any improvements or extensions that they make and grant Carnegie the 64 * rights to redistribute these changes. 65 */ 66 67/* 68 * Resident memory management module. 69 */ 70 71#include <sys/param.h> 72#include <sys/systm.h> 73#include <sys/proc.h> 74#include <sys/queue.h> 75#include <sys/vmmeter.h> 76 77#include <vm/vm.h> 78#include <vm/vm_param.h> 79#include <vm/vm_prot.h> 80#include <vm/lock.h> 81#include <vm/vm_kern.h> 82#include <vm/vm_object.h> 83#include <vm/vm_page.h> 84#include <vm/vm_map.h> 85#include <vm/vm_pageout.h> 86#include <vm/vm_extern.h> 87 88#ifdef DDB 89extern void print_page_info __P((void)); 90#endif 91 92/* 93 * Associated with page of user-allocatable memory is a 94 * page structure. 95 */ 96 97struct pglist *vm_page_buckets; /* Array of buckets */ 98int vm_page_bucket_count; /* How big is array? */ 99static int vm_page_hash_mask; /* Mask for hash function */ 100 101struct pglist vm_page_queue_free; 102struct pglist vm_page_queue_zero; 103struct pglist vm_page_queue_active; 104struct pglist vm_page_queue_inactive; 105struct pglist vm_page_queue_cache; 106 107/* has physical page allocation been initialized? */ 108boolean_t vm_page_startup_initialized; 109 110vm_page_t vm_page_array; 111int vm_page_array_size; 112long first_page; 113long last_page; 114vm_offset_t first_phys_addr; 115vm_offset_t last_phys_addr; 116vm_size_t page_mask; 117int page_shift; 118 119/* 120 * map of contiguous valid DEV_BSIZE chunks in a page 121 * (this list is valid for page sizes upto 16*DEV_BSIZE) 122 */ 123static u_short vm_page_dev_bsize_chunks[] = { 124 0x0, 0x1, 0x3, 0x7, 0xf, 0x1f, 0x3f, 0x7f, 0xff, 125 0x1ff, 0x3ff, 0x7ff, 0xfff, 0x1fff, 0x3fff, 0x7fff, 0xffff 126}; 127 128static inline __pure int 129 vm_page_hash __P((vm_object_t object, vm_offset_t offset)) 130 __pure2; 131static void vm_page_unqueue __P((vm_page_t )); 132 133/* 134 * vm_set_page_size: 135 * 136 * Sets the page size, perhaps based upon the memory 137 * size. Must be called before any use of page-size 138 * dependent functions. 139 * 140 * Sets page_shift and page_mask from cnt.v_page_size. 141 */ 142void 143vm_set_page_size() 144{ 145 146 if (cnt.v_page_size == 0) 147 cnt.v_page_size = DEFAULT_PAGE_SIZE; 148 page_mask = cnt.v_page_size - 1; 149 if ((page_mask & cnt.v_page_size) != 0) 150 panic("vm_set_page_size: page size not a power of two"); 151 for (page_shift = 0;; page_shift++) 152 if ((1 << page_shift) == cnt.v_page_size) 153 break; 154} 155 156/* 157 * vm_page_startup: 158 * 159 * Initializes the resident memory module. 160 * 161 * Allocates memory for the page cells, and 162 * for the object/offset-to-page hash table headers. 163 * Each page cell is initialized and placed on the free list. 164 */ 165 166vm_offset_t 167vm_page_startup(starta, enda, vaddr) 168 register vm_offset_t starta; 169 vm_offset_t enda; 170 register vm_offset_t vaddr; 171{ 172 register vm_offset_t mapped; 173 register vm_page_t m; 174 register struct pglist *bucket; 175 vm_size_t npages, page_range; 176 register vm_offset_t new_start; 177 int i; 178 vm_offset_t pa; 179 int nblocks; 180 vm_offset_t first_managed_page; 181 182 /* the biggest memory array is the second group of pages */ 183 vm_offset_t start; 184 vm_offset_t biggestone, biggestsize; 185 186 vm_offset_t total; 187 188 total = 0; 189 biggestsize = 0; 190 biggestone = 0; 191 nblocks = 0; 192 vaddr = round_page(vaddr); 193 194 for (i = 0; phys_avail[i + 1]; i += 2) { 195 phys_avail[i] = round_page(phys_avail[i]); 196 phys_avail[i + 1] = trunc_page(phys_avail[i + 1]); 197 } 198 199 for (i = 0; phys_avail[i + 1]; i += 2) { 200 int size = phys_avail[i + 1] - phys_avail[i]; 201 202 if (size > biggestsize) { 203 biggestone = i; 204 biggestsize = size; 205 } 206 ++nblocks; 207 total += size; 208 } 209 210 start = phys_avail[biggestone]; 211 212 /* 213 * Initialize the queue headers for the free queue, the active queue 214 * and the inactive queue. 215 */ 216 217 TAILQ_INIT(&vm_page_queue_free); 218 TAILQ_INIT(&vm_page_queue_zero); 219 TAILQ_INIT(&vm_page_queue_active); 220 TAILQ_INIT(&vm_page_queue_inactive); 221 TAILQ_INIT(&vm_page_queue_cache); 222 223 /* 224 * Allocate (and initialize) the hash table buckets. 225 * 226 * The number of buckets MUST BE a power of 2, and the actual value is 227 * the next power of 2 greater than the number of physical pages in 228 * the system. 229 * 230 * Note: This computation can be tweaked if desired. 231 */ 232 vm_page_buckets = (struct pglist *) vaddr; 233 bucket = vm_page_buckets; 234 if (vm_page_bucket_count == 0) { 235 vm_page_bucket_count = 1; 236 while (vm_page_bucket_count < atop(total)) 237 vm_page_bucket_count <<= 1; 238 } 239 vm_page_hash_mask = vm_page_bucket_count - 1; 240 241 /* 242 * Validate these addresses. 243 */ 244 245 new_start = start + vm_page_bucket_count * sizeof(struct pglist); 246 new_start = round_page(new_start); 247 mapped = vaddr; 248 vaddr = pmap_map(mapped, start, new_start, 249 VM_PROT_READ | VM_PROT_WRITE); 250 start = new_start; 251 bzero((caddr_t) mapped, vaddr - mapped); 252 mapped = vaddr; 253 254 for (i = 0; i < vm_page_bucket_count; i++) { 255 TAILQ_INIT(bucket); 256 bucket++; 257 } 258 259 /* 260 * round (or truncate) the addresses to our page size. 261 */ 262 263 /* 264 * Pre-allocate maps and map entries that cannot be dynamically 265 * allocated via malloc(). The maps include the kernel_map and 266 * kmem_map which must be initialized before malloc() will work 267 * (obviously). Also could include pager maps which would be 268 * allocated before kmeminit. 269 * 270 * Allow some kernel map entries... this should be plenty since people 271 * shouldn't be cluttering up the kernel map (they should use their 272 * own maps). 273 */ 274 275 kentry_data_size = MAX_KMAP * sizeof(struct vm_map) + 276 MAX_KMAPENT * sizeof(struct vm_map_entry); 277 kentry_data_size = round_page(kentry_data_size); 278 kentry_data = (vm_offset_t) vaddr; 279 vaddr += kentry_data_size; 280 281 /* 282 * Validate these zone addresses. 283 */ 284 285 new_start = start + (vaddr - mapped); 286 pmap_map(mapped, start, new_start, VM_PROT_READ | VM_PROT_WRITE); 287 bzero((caddr_t) mapped, (vaddr - mapped)); 288 start = round_page(new_start); 289 290 /* 291 * Compute the number of pages of memory that will be available for 292 * use (taking into account the overhead of a page structure per 293 * page). 294 */ 295 296 first_page = phys_avail[0] / PAGE_SIZE; 297 last_page = phys_avail[(nblocks - 1) * 2 + 1] / PAGE_SIZE; 298 299 page_range = last_page - (phys_avail[0] / PAGE_SIZE); 300 npages = (total - (page_range * sizeof(struct vm_page)) - 301 (start - phys_avail[biggestone])) / PAGE_SIZE; 302 303 /* 304 * Initialize the mem entry structures now, and put them in the free 305 * queue. 306 */ 307 308 vm_page_array = (vm_page_t) vaddr; 309 mapped = vaddr; 310 311 /* 312 * Validate these addresses. 313 */ 314 315 new_start = round_page(start + page_range * sizeof(struct vm_page)); 316 mapped = pmap_map(mapped, start, new_start, 317 VM_PROT_READ | VM_PROT_WRITE); 318 start = new_start; 319 320 first_managed_page = start / PAGE_SIZE; 321 322 /* 323 * Clear all of the page structures 324 */ 325 bzero((caddr_t) vm_page_array, page_range * sizeof(struct vm_page)); 326 vm_page_array_size = page_range; 327 328 cnt.v_page_count = 0; 329 cnt.v_free_count = 0; 330 for (i = 0; phys_avail[i + 1] && npages > 0; i += 2) { 331 if (i == biggestone) 332 pa = ptoa(first_managed_page); 333 else 334 pa = phys_avail[i]; 335 while (pa < phys_avail[i + 1] && npages-- > 0) { 336 ++cnt.v_page_count; 337 ++cnt.v_free_count; 338 m = PHYS_TO_VM_PAGE(pa); 339 m->flags = PG_FREE; 340 m->phys_addr = pa; 341 TAILQ_INSERT_TAIL(&vm_page_queue_free, m, pageq); 342 pa += PAGE_SIZE; 343 } 344 } 345 346 return (mapped); 347} 348 349/* 350 * vm_page_hash: 351 * 352 * Distributes the object/offset key pair among hash buckets. 353 * 354 * NOTE: This macro depends on vm_page_bucket_count being a power of 2. 355 */ 356static inline __pure int 357vm_page_hash(vm_object_t object, vm_offset_t offset) 358{ 359 return ((unsigned) object + (offset >> PAGE_SHIFT)) & vm_page_hash_mask; 360} 361 362/* 363 * vm_page_insert: [ internal use only ] 364 * 365 * Inserts the given mem entry into the object/object-page 366 * table and object list. 367 * 368 * The object and page must be locked, and must be splhigh. 369 */ 370 371inline void 372vm_page_insert(mem, object, offset) 373 register vm_page_t mem; 374 register vm_object_t object; 375 register vm_offset_t offset; 376{ 377 register struct pglist *bucket; 378 379 if (mem->flags & PG_TABLED) 380 panic("vm_page_insert: already inserted"); 381 382 /* 383 * Record the object/offset pair in this page 384 */ 385 386 mem->object = object; 387 mem->offset = offset; 388 389 /* 390 * Insert it into the object_object/offset hash table 391 */ 392 393 bucket = &vm_page_buckets[vm_page_hash(object, offset)]; 394 TAILQ_INSERT_TAIL(bucket, mem, hashq); 395 396 /* 397 * Now link into the object's list of backed pages. 398 */ 399 400 TAILQ_INSERT_TAIL(&object->memq, mem, listq); 401 mem->flags |= PG_TABLED; 402 403 /* 404 * And show that the object has one more resident page. 405 */ 406 407 object->resident_page_count++; 408} 409 410/* 411 * vm_page_remove: [ internal use only ] 412 * NOTE: used by device pager as well -wfj 413 * 414 * Removes the given mem entry from the object/offset-page 415 * table and the object page list. 416 * 417 * The object and page must be locked, and at splhigh. 418 */ 419 420inline void 421vm_page_remove(mem) 422 register vm_page_t mem; 423{ 424 register struct pglist *bucket; 425 426 if (!(mem->flags & PG_TABLED)) 427 return; 428 429 /* 430 * Remove from the object_object/offset hash table 431 */ 432 433 bucket = &vm_page_buckets[vm_page_hash(mem->object, mem->offset)]; 434 TAILQ_REMOVE(bucket, mem, hashq); 435 436 /* 437 * Now remove from the object's list of backed pages. 438 */ 439 440 TAILQ_REMOVE(&mem->object->memq, mem, listq); 441 442 /* 443 * And show that the object has one fewer resident page. 444 */ 445 446 mem->object->resident_page_count--; 447 448 mem->flags &= ~PG_TABLED; 449} 450 451/* 452 * vm_page_lookup: 453 * 454 * Returns the page associated with the object/offset 455 * pair specified; if none is found, NULL is returned. 456 * 457 * The object must be locked. No side effects. 458 */ 459 460vm_page_t 461vm_page_lookup(object, offset) 462 register vm_object_t object; 463 register vm_offset_t offset; 464{ 465 register vm_page_t mem; 466 register struct pglist *bucket; 467 int s; 468 469 /* 470 * Search the hash table for this object/offset pair 471 */ 472 473 bucket = &vm_page_buckets[vm_page_hash(object, offset)]; 474 475 s = splhigh(); 476 for (mem = bucket->tqh_first; mem != NULL; mem = mem->hashq.tqe_next) { 477 if ((mem->object == object) && (mem->offset == offset)) { 478 splx(s); 479 return (mem); 480 } 481 } 482 483 splx(s); 484 return (NULL); 485} 486 487/* 488 * vm_page_rename: 489 * 490 * Move the given memory entry from its 491 * current object to the specified target object/offset. 492 * 493 * The object must be locked. 494 */ 495void 496vm_page_rename(mem, new_object, new_offset) 497 register vm_page_t mem; 498 register vm_object_t new_object; 499 vm_offset_t new_offset; 500{ 501 int s; 502 503 if (mem->object == new_object) 504 return; 505 506 s = splhigh(); 507 vm_page_remove(mem); 508 vm_page_insert(mem, new_object, new_offset); 509 splx(s); 510} 511 512/* 513 * vm_page_unqueue must be called at splhigh(); 514 */ 515static inline void 516vm_page_unqueue(vm_page_t mem) 517{ 518 int origflags; 519 520 origflags = mem->flags; 521 522 if ((origflags & (PG_ACTIVE|PG_INACTIVE|PG_CACHE)) == 0) 523 return; 524 525 if (origflags & PG_ACTIVE) { 526 TAILQ_REMOVE(&vm_page_queue_active, mem, pageq); 527 cnt.v_active_count--; 528 mem->flags &= ~PG_ACTIVE; 529 } else if (origflags & PG_INACTIVE) { 530 TAILQ_REMOVE(&vm_page_queue_inactive, mem, pageq); 531 cnt.v_inactive_count--; 532 mem->flags &= ~PG_INACTIVE; 533 } else if (origflags & PG_CACHE) { 534 TAILQ_REMOVE(&vm_page_queue_cache, mem, pageq); 535 cnt.v_cache_count--; 536 mem->flags &= ~PG_CACHE; 537 if (cnt.v_cache_count + cnt.v_free_count < cnt.v_free_reserved) 538 pagedaemon_wakeup(); 539 } 540 return; 541} 542 543/* 544 * vm_page_alloc: 545 * 546 * Allocate and return a memory cell associated 547 * with this VM object/offset pair. 548 * 549 * page_req classes: 550 * VM_ALLOC_NORMAL normal process request 551 * VM_ALLOC_SYSTEM system *really* needs a page 552 * VM_ALLOC_INTERRUPT interrupt time request 553 * or in: 554 * VM_ALLOC_ZERO zero page 555 * 556 * Object must be locked. 557 */ 558vm_page_t 559vm_page_alloc(object, offset, page_req) 560 vm_object_t object; 561 vm_offset_t offset; 562 int page_req; 563{ 564 register vm_page_t mem; 565 int s; 566 567#ifdef DIAGNOSTIC 568 if (offset != trunc_page(offset)) 569 panic("vm_page_alloc: offset not page aligned"); 570 571#if 0 572 mem = vm_page_lookup(object, offset); 573 if (mem) 574 panic("vm_page_alloc: page already allocated"); 575#endif 576#endif 577 578 if ((curproc == pageproc) && (page_req != VM_ALLOC_INTERRUPT)) { 579 page_req = VM_ALLOC_SYSTEM; 580 }; 581 582 s = splhigh(); 583 584 switch ((page_req & ~(VM_ALLOC_ZERO))) { 585 case VM_ALLOC_NORMAL: 586 if (cnt.v_free_count >= cnt.v_free_reserved) { 587 if (page_req & VM_ALLOC_ZERO) { 588 mem = vm_page_queue_zero.tqh_first; 589 if (mem) { 590 TAILQ_REMOVE(&vm_page_queue_zero, mem, pageq); 591 mem->flags = PG_BUSY|PG_ZERO; 592 } else { 593 mem = vm_page_queue_free.tqh_first; 594 TAILQ_REMOVE(&vm_page_queue_free, mem, pageq); 595 mem->flags = PG_BUSY; 596 } 597 } else { 598 mem = vm_page_queue_free.tqh_first; 599 if (mem) { 600 TAILQ_REMOVE(&vm_page_queue_free, mem, pageq); 601 mem->flags = PG_BUSY; 602 } else { 603 mem = vm_page_queue_zero.tqh_first; 604 TAILQ_REMOVE(&vm_page_queue_zero, mem, pageq); 605 mem->flags = PG_BUSY|PG_ZERO; 606 } 607 } 608 cnt.v_free_count--; 609 } else { 610 mem = vm_page_queue_cache.tqh_first; 611 if (mem != NULL) { 612 TAILQ_REMOVE(&vm_page_queue_cache, mem, pageq); 613 vm_page_remove(mem); 614 mem->flags = PG_BUSY; 615 cnt.v_cache_count--; 616 } else { 617 splx(s); 618 pagedaemon_wakeup(); 619 return (NULL); 620 } 621 } 622 break; 623 624 case VM_ALLOC_SYSTEM: 625 if ((cnt.v_free_count >= cnt.v_free_reserved) || 626 ((cnt.v_cache_count == 0) && 627 (cnt.v_free_count >= cnt.v_interrupt_free_min))) { 628 if (page_req & VM_ALLOC_ZERO) { 629 mem = vm_page_queue_zero.tqh_first; 630 if (mem) { 631 TAILQ_REMOVE(&vm_page_queue_zero, mem, pageq); 632 mem->flags = PG_BUSY|PG_ZERO; 633 } else { 634 mem = vm_page_queue_free.tqh_first; 635 TAILQ_REMOVE(&vm_page_queue_free, mem, pageq); 636 mem->flags = PG_BUSY; 637 } 638 } else { 639 mem = vm_page_queue_free.tqh_first; 640 if (mem) { 641 TAILQ_REMOVE(&vm_page_queue_free, mem, pageq); 642 mem->flags = PG_BUSY; 643 } else { 644 mem = vm_page_queue_zero.tqh_first; 645 TAILQ_REMOVE(&vm_page_queue_zero, mem, pageq); 646 mem->flags = PG_BUSY|PG_ZERO; 647 } 648 } 649 cnt.v_free_count--; 650 } else { 651 mem = vm_page_queue_cache.tqh_first; 652 if (mem != NULL) { 653 TAILQ_REMOVE(&vm_page_queue_cache, mem, pageq); 654 vm_page_remove(mem); 655 mem->flags = PG_BUSY; 656 cnt.v_cache_count--; 657 } else { 658 splx(s); 659 pagedaemon_wakeup(); 660 return (NULL); 661 } 662 } 663 break; 664 665 case VM_ALLOC_INTERRUPT: 666 if (cnt.v_free_count > 0) { 667 mem = vm_page_queue_free.tqh_first; 668 if (mem) { 669 TAILQ_REMOVE(&vm_page_queue_free, mem, pageq); 670 mem->flags = PG_BUSY; 671 } else { 672 mem = vm_page_queue_zero.tqh_first; 673 TAILQ_REMOVE(&vm_page_queue_zero, mem, pageq); 674 mem->flags = PG_BUSY|PG_ZERO; 675 } 676 cnt.v_free_count--; 677 } else { 678 splx(s); 679 pagedaemon_wakeup(); 680 return NULL; 681 } 682 break; 683 684 default: 685 panic("vm_page_alloc: invalid allocation class"); 686 } 687 688 mem->wire_count = 0; 689 mem->hold_count = 0; 690 mem->act_count = 0; 691 mem->busy = 0; 692 mem->valid = 0; 693 mem->dirty = 0; 694 mem->bmapped = 0; 695 696 /* XXX before splx until vm_page_insert is safe */ 697 vm_page_insert(mem, object, offset); 698 699 splx(s); 700 701 /* 702 * Don't wakeup too often - wakeup the pageout daemon when 703 * we would be nearly out of memory. 704 */ 705 if (((cnt.v_free_count + cnt.v_cache_count) < cnt.v_free_min) || 706 (cnt.v_free_count < cnt.v_pageout_free_min)) 707 pagedaemon_wakeup(); 708 709 return (mem); 710} 711 712vm_offset_t 713vm_page_alloc_contig(size, low, high, alignment) 714 vm_offset_t size; 715 vm_offset_t low; 716 vm_offset_t high; 717 vm_offset_t alignment; 718{ 719 int i, s, start; 720 vm_offset_t addr, phys, tmp_addr; 721 vm_page_t pga = vm_page_array; 722 723 if ((alignment & (alignment - 1)) != 0) 724 panic("vm_page_alloc_contig: alignment must be a power of 2"); 725 726 start = 0; 727 s = splhigh(); 728again: 729 /* 730 * Find first page in array that is free, within range, and aligned. 731 */ 732 for (i = start; i < cnt.v_page_count; i++) { 733 phys = VM_PAGE_TO_PHYS(&pga[i]); 734 if (((pga[i].flags & PG_FREE) == PG_FREE) && 735 (phys >= low) && (phys < high) && 736 ((phys & (alignment - 1)) == 0)) 737 break; 738 } 739 740 /* 741 * If the above failed or we will exceed the upper bound, fail. 742 */ 743 if ((i == cnt.v_page_count) || ((VM_PAGE_TO_PHYS(&pga[i]) + size) > high)) { 744 splx(s); 745 return (NULL); 746 } 747 start = i; 748 749 /* 750 * Check successive pages for contiguous and free. 751 */ 752 for (i = start + 1; i < (start + size / PAGE_SIZE); i++) { 753 if ((VM_PAGE_TO_PHYS(&pga[i]) != 754 (VM_PAGE_TO_PHYS(&pga[i - 1]) + PAGE_SIZE)) || 755 ((pga[i].flags & PG_FREE) != PG_FREE)) { 756 start++; 757 goto again; 758 } 759 } 760 761 /* 762 * We've found a contiguous chunk that meets are requirements. 763 * Allocate kernel VM, unfree and assign the physical pages to it and 764 * return kernel VM pointer. 765 */ 766 tmp_addr = addr = kmem_alloc_pageable(kernel_map, size); 767 768 for (i = start; i < (start + size / PAGE_SIZE); i++) { 769 vm_page_t m = &pga[i]; 770 771 TAILQ_REMOVE(&vm_page_queue_free, m, pageq); 772 cnt.v_free_count--; 773 m->valid = VM_PAGE_BITS_ALL; 774 m->flags = 0; 775 m->dirty = 0; 776 m->wire_count = 0; 777 m->act_count = 0; 778 m->bmapped = 0; 779 m->busy = 0; 780 vm_page_insert(m, kernel_object, tmp_addr - VM_MIN_KERNEL_ADDRESS); 781 vm_page_wire(m); 782 pmap_kenter(tmp_addr, VM_PAGE_TO_PHYS(m)); 783 tmp_addr += PAGE_SIZE; 784 } 785 786 splx(s); 787 return (addr); 788} 789 790/* 791 * vm_page_free: 792 * 793 * Returns the given page to the free list, 794 * disassociating it with any VM object. 795 * 796 * Object and page must be locked prior to entry. 797 */ 798void 799vm_page_free(mem) 800 register vm_page_t mem; 801{ 802 int s; 803 int flags; 804 805 s = splhigh(); 806 vm_page_remove(mem); 807 vm_page_unqueue(mem); 808 809 flags = mem->flags; 810 if (mem->bmapped || mem->busy || flags & (PG_BUSY|PG_FREE)) { 811 if (flags & PG_FREE) 812 panic("vm_page_free: freeing free page"); 813 printf("vm_page_free: offset(%ld), bmapped(%d), busy(%d), PG_BUSY(%d)\n", 814 mem->offset, mem->bmapped, mem->busy, (flags & PG_BUSY) ? 1 : 0); 815 panic("vm_page_free: freeing busy page"); 816 } 817 818 if ((flags & PG_WANTED) != 0) 819 wakeup(mem); 820 if ((flags & PG_FICTITIOUS) == 0) { 821 if (mem->wire_count) { 822 if (mem->wire_count > 1) { 823 printf("vm_page_free: wire count > 1 (%d)", mem->wire_count); 824 panic("vm_page_free: invalid wire count"); 825 } 826 cnt.v_wire_count--; 827 mem->wire_count = 0; 828 } 829 mem->flags |= PG_FREE; 830 TAILQ_INSERT_TAIL(&vm_page_queue_free, mem, pageq); 831 splx(s); 832 /* 833 * if pageout daemon needs pages, then tell it that there are 834 * some free. 835 */ 836 if (vm_pageout_pages_needed) { 837 wakeup(&vm_pageout_pages_needed); 838 vm_pageout_pages_needed = 0; 839 } 840 841 cnt.v_free_count++; 842 /* 843 * wakeup processes that are waiting on memory if we hit a 844 * high water mark. And wakeup scheduler process if we have 845 * lots of memory. this process will swapin processes. 846 */ 847 if ((cnt.v_free_count + cnt.v_cache_count) == cnt.v_free_min) { 848 wakeup(&cnt.v_free_count); 849 wakeup(&proc0); 850 } 851 } else { 852 splx(s); 853 } 854 cnt.v_tfree++; 855} 856 857 858/* 859 * vm_page_wire: 860 * 861 * Mark this page as wired down by yet 862 * another map, removing it from paging queues 863 * as necessary. 864 * 865 * The page queues must be locked. 866 */ 867void 868vm_page_wire(mem) 869 register vm_page_t mem; 870{ 871 int s; 872 873 if (mem->wire_count == 0) { 874 s = splhigh(); 875 vm_page_unqueue(mem); 876 splx(s); 877 cnt.v_wire_count++; 878 } 879 mem->flags |= PG_WRITEABLE|PG_MAPPED; 880 mem->wire_count++; 881} 882 883/* 884 * vm_page_unwire: 885 * 886 * Release one wiring of this page, potentially 887 * enabling it to be paged again. 888 * 889 * The page queues must be locked. 890 */ 891void 892vm_page_unwire(mem) 893 register vm_page_t mem; 894{ 895 int s; 896 897 s = splhigh(); 898 899 if (mem->wire_count) 900 mem->wire_count--; 901 if (mem->wire_count == 0) { 902 TAILQ_INSERT_TAIL(&vm_page_queue_active, mem, pageq); 903 cnt.v_active_count++; 904 mem->flags |= PG_ACTIVE; 905 cnt.v_wire_count--; 906 } 907 splx(s); 908} 909 910/* 911 * vm_page_activate: 912 * 913 * Put the specified page on the active list (if appropriate). 914 * 915 * The page queues must be locked. 916 */ 917void 918vm_page_activate(m) 919 register vm_page_t m; 920{ 921 int s; 922 923 s = splhigh(); 924 if (m->flags & PG_ACTIVE) 925 panic("vm_page_activate: already active"); 926 927 if (m->flags & PG_CACHE) 928 cnt.v_reactivated++; 929 930 vm_page_unqueue(m); 931 932 if (m->wire_count == 0) { 933 TAILQ_INSERT_TAIL(&vm_page_queue_active, m, pageq); 934 m->flags |= PG_ACTIVE; 935 if (m->act_count < 5) 936 m->act_count = 5; 937 else if( m->act_count < ACT_MAX) 938 m->act_count += 1; 939 cnt.v_active_count++; 940 } 941 splx(s); 942} 943 944/* 945 * vm_page_deactivate: 946 * 947 * Returns the given page to the inactive list, 948 * indicating that no physical maps have access 949 * to this page. [Used by the physical mapping system.] 950 * 951 * The page queues must be locked. 952 */ 953void 954vm_page_deactivate(m) 955 register vm_page_t m; 956{ 957 int spl; 958 959 /* 960 * Only move active pages -- ignore locked or already inactive ones. 961 * 962 * XXX: sometimes we get pages which aren't wired down or on any queue - 963 * we need to put them on the inactive queue also, otherwise we lose 964 * track of them. Paul Mackerras (paulus@cs.anu.edu.au) 9-Jan-93. 965 */ 966 967 spl = splhigh(); 968 if (!(m->flags & PG_INACTIVE) && m->wire_count == 0 && 969 m->hold_count == 0) { 970 if (m->flags & PG_CACHE) 971 cnt.v_reactivated++; 972 vm_page_unqueue(m); 973 TAILQ_INSERT_TAIL(&vm_page_queue_inactive, m, pageq); 974 m->flags |= PG_INACTIVE; 975 cnt.v_inactive_count++; 976 m->act_count = 0; 977 } 978 splx(spl); 979} 980 981/* 982 * vm_page_cache 983 * 984 * Put the specified page onto the page cache queue (if appropriate). 985 */ 986void 987vm_page_cache(m) 988 register vm_page_t m; 989{ 990 int s; 991 992 if ((m->flags & (PG_CACHE | PG_BUSY)) || m->busy || m->wire_count || 993 m->bmapped) 994 return; 995 996 s = splhigh(); 997 vm_page_unqueue(m); 998 vm_page_protect(m, VM_PROT_NONE); 999 1000 TAILQ_INSERT_TAIL(&vm_page_queue_cache, m, pageq); 1001 m->flags |= PG_CACHE; 1002 cnt.v_cache_count++; 1003 if ((cnt.v_free_count + cnt.v_cache_count) == cnt.v_free_min) { 1004 wakeup(&cnt.v_free_count); 1005 wakeup(&proc0); 1006 } 1007 if (vm_pageout_pages_needed) { 1008 wakeup(&vm_pageout_pages_needed); 1009 vm_pageout_pages_needed = 0; 1010 } 1011 1012 splx(s); 1013} 1014 1015/* 1016 * vm_page_zero_fill: 1017 * 1018 * Zero-fill the specified page. 1019 * Written as a standard pagein routine, to 1020 * be used by the zero-fill object. 1021 */ 1022boolean_t 1023vm_page_zero_fill(m) 1024 vm_page_t m; 1025{ 1026 pmap_zero_page(VM_PAGE_TO_PHYS(m)); 1027 return (TRUE); 1028} 1029 1030/* 1031 * vm_page_copy: 1032 * 1033 * Copy one page to another 1034 */ 1035void 1036vm_page_copy(src_m, dest_m) 1037 vm_page_t src_m; 1038 vm_page_t dest_m; 1039{ 1040 pmap_copy_page(VM_PAGE_TO_PHYS(src_m), VM_PAGE_TO_PHYS(dest_m)); 1041 dest_m->valid = VM_PAGE_BITS_ALL; 1042} 1043 1044 1045/* 1046 * mapping function for valid bits or for dirty bits in 1047 * a page 1048 */ 1049inline int 1050vm_page_bits(int base, int size) 1051{ 1052 u_short chunk; 1053 1054 if ((base == 0) && (size >= PAGE_SIZE)) 1055 return VM_PAGE_BITS_ALL; 1056 size = (size + DEV_BSIZE - 1) & ~(DEV_BSIZE - 1); 1057 base = (base % PAGE_SIZE) / DEV_BSIZE; 1058 chunk = vm_page_dev_bsize_chunks[size / DEV_BSIZE]; 1059 return (chunk << base) & VM_PAGE_BITS_ALL; 1060} 1061 1062/* 1063 * set a page valid and clean 1064 */ 1065void 1066vm_page_set_validclean(m, base, size) 1067 vm_page_t m; 1068 int base; 1069 int size; 1070{ 1071 int pagebits = vm_page_bits(base, size); 1072 m->valid |= pagebits; 1073 m->dirty &= ~pagebits; 1074 if( base == 0 && size == PAGE_SIZE) 1075 pmap_clear_modify(VM_PAGE_TO_PHYS(m)); 1076} 1077 1078/* 1079 * set a page (partially) invalid 1080 */ 1081void 1082vm_page_set_invalid(m, base, size) 1083 vm_page_t m; 1084 int base; 1085 int size; 1086{ 1087 int bits; 1088 1089 m->valid &= ~(bits = vm_page_bits(base, size)); 1090 if (m->valid == 0) 1091 m->dirty &= ~bits; 1092} 1093 1094/* 1095 * is (partial) page valid? 1096 */ 1097int 1098vm_page_is_valid(m, base, size) 1099 vm_page_t m; 1100 int base; 1101 int size; 1102{ 1103 int bits = vm_page_bits(base, size); 1104 1105 if (m->valid && ((m->valid & bits) == bits)) 1106 return 1; 1107 else 1108 return 0; 1109} 1110 1111 1112 1113void 1114vm_page_test_dirty(m) 1115 vm_page_t m; 1116{ 1117 if ((m->dirty != VM_PAGE_BITS_ALL) && 1118 pmap_is_modified(VM_PAGE_TO_PHYS(m))) { 1119 m->dirty = VM_PAGE_BITS_ALL; 1120 } 1121} 1122 1123#ifdef DDB 1124void 1125print_page_info(void) 1126{ 1127 printf("cnt.v_free_count: %d\n", cnt.v_free_count); 1128 printf("cnt.v_cache_count: %d\n", cnt.v_cache_count); 1129 printf("cnt.v_inactive_count: %d\n", cnt.v_inactive_count); 1130 printf("cnt.v_active_count: %d\n", cnt.v_active_count); 1131 printf("cnt.v_wire_count: %d\n", cnt.v_wire_count); 1132 printf("cnt.v_free_reserved: %d\n", cnt.v_free_reserved); 1133 printf("cnt.v_free_min: %d\n", cnt.v_free_min); 1134 printf("cnt.v_free_target: %d\n", cnt.v_free_target); 1135 printf("cnt.v_cache_min: %d\n", cnt.v_cache_min); 1136 printf("cnt.v_inactive_target: %d\n", cnt.v_inactive_target); 1137} 1138#endif 1139