vm_page.c revision 32702
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.86 1998/01/17 09:16:59 dyson 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/malloc.h> 74#include <sys/proc.h> 75#include <sys/vmmeter.h> 76#include <sys/vnode.h> 77 78#include <vm/vm.h> 79#include <vm/vm_param.h> 80#include <vm/vm_prot.h> 81#include <sys/lock.h> 82#include <vm/vm_kern.h> 83#include <vm/vm_object.h> 84#include <vm/vm_page.h> 85#include <vm/vm_pageout.h> 86#include <vm/vm_extern.h> 87 88static void vm_page_queue_init __P((void)); 89static vm_page_t vm_page_select_free __P((vm_object_t object, 90 vm_pindex_t pindex, int prefqueue)); 91 92/* 93 * Associated with page of user-allocatable memory is a 94 * page structure. 95 */ 96 97static int vm_page_bucket_generation; /* generation id for buckets */ 98static struct pglist *vm_page_buckets; /* Array of buckets */ 99static int vm_page_bucket_count; /* How big is array? */ 100static int vm_page_hash_mask; /* Mask for hash function */ 101 102struct pglist vm_page_queue_free[PQ_L2_SIZE] = {0}; 103struct pglist vm_page_queue_zero[PQ_L2_SIZE] = {0}; 104struct pglist vm_page_queue_active = {0}; 105struct pglist vm_page_queue_inactive = {0}; 106struct pglist vm_page_queue_cache[PQ_L2_SIZE] = {0}; 107 108int no_queue=0; 109 110struct vpgqueues vm_page_queues[PQ_COUNT] = {0}; 111int pqcnt[PQ_COUNT] = {0}; 112 113static void 114vm_page_queue_init(void) { 115 int i; 116 117 vm_page_queues[PQ_NONE].pl = NULL; 118 vm_page_queues[PQ_NONE].cnt = &no_queue; 119 for(i=0;i<PQ_L2_SIZE;i++) { 120 vm_page_queues[PQ_FREE+i].pl = &vm_page_queue_free[i]; 121 vm_page_queues[PQ_FREE+i].cnt = &cnt.v_free_count; 122 } 123 for(i=0;i<PQ_L2_SIZE;i++) { 124 vm_page_queues[PQ_ZERO+i].pl = &vm_page_queue_zero[i]; 125 vm_page_queues[PQ_ZERO+i].cnt = &cnt.v_free_count; 126 } 127 vm_page_queues[PQ_INACTIVE].pl = &vm_page_queue_inactive; 128 vm_page_queues[PQ_INACTIVE].cnt = &cnt.v_inactive_count; 129 130 vm_page_queues[PQ_ACTIVE].pl = &vm_page_queue_active; 131 vm_page_queues[PQ_ACTIVE].cnt = &cnt.v_active_count; 132 for(i=0;i<PQ_L2_SIZE;i++) { 133 vm_page_queues[PQ_CACHE+i].pl = &vm_page_queue_cache[i]; 134 vm_page_queues[PQ_CACHE+i].cnt = &cnt.v_cache_count; 135 } 136 for(i=0;i<PQ_COUNT;i++) { 137 if (vm_page_queues[i].pl) { 138 TAILQ_INIT(vm_page_queues[i].pl); 139 } else if (i != 0) { 140 panic("vm_page_queue_init: queue %d is null", i); 141 } 142 vm_page_queues[i].lcnt = &pqcnt[i]; 143 } 144} 145 146vm_page_t vm_page_array = 0; 147int vm_page_array_size = 0; 148long first_page = 0; 149static long last_page; 150static vm_size_t page_mask; 151static int page_shift; 152int vm_page_zero_count = 0; 153 154/* 155 * map of contiguous valid DEV_BSIZE chunks in a page 156 * (this list is valid for page sizes upto 16*DEV_BSIZE) 157 */ 158static u_short vm_page_dev_bsize_chunks[] = { 159 0x0, 0x1, 0x3, 0x7, 0xf, 0x1f, 0x3f, 0x7f, 0xff, 160 0x1ff, 0x3ff, 0x7ff, 0xfff, 0x1fff, 0x3fff, 0x7fff, 0xffff 161}; 162 163static inline int vm_page_hash __P((vm_object_t object, vm_pindex_t pindex)); 164static int vm_page_freechk_and_unqueue __P((vm_page_t m)); 165static void vm_page_free_wakeup __P((void)); 166 167/* 168 * vm_set_page_size: 169 * 170 * Sets the page size, perhaps based upon the memory 171 * size. Must be called before any use of page-size 172 * dependent functions. 173 * 174 * Sets page_shift and page_mask from cnt.v_page_size. 175 */ 176void 177vm_set_page_size() 178{ 179 180 if (cnt.v_page_size == 0) 181 cnt.v_page_size = DEFAULT_PAGE_SIZE; 182 page_mask = cnt.v_page_size - 1; 183 if ((page_mask & cnt.v_page_size) != 0) 184 panic("vm_set_page_size: page size not a power of two"); 185 for (page_shift = 0;; page_shift++) 186 if ((1 << page_shift) == cnt.v_page_size) 187 break; 188} 189 190/* 191 * vm_page_startup: 192 * 193 * Initializes the resident memory module. 194 * 195 * Allocates memory for the page cells, and 196 * for the object/offset-to-page hash table headers. 197 * Each page cell is initialized and placed on the free list. 198 */ 199 200vm_offset_t 201vm_page_startup(starta, enda, vaddr) 202 register vm_offset_t starta; 203 vm_offset_t enda; 204 register vm_offset_t vaddr; 205{ 206 register vm_offset_t mapped; 207 register vm_page_t m; 208 register struct pglist *bucket; 209 vm_size_t npages, page_range; 210 register vm_offset_t new_start; 211 int i; 212 vm_offset_t pa; 213 int nblocks; 214 vm_offset_t first_managed_page; 215 216 /* the biggest memory array is the second group of pages */ 217 vm_offset_t start; 218 vm_offset_t biggestone, biggestsize; 219 220 vm_offset_t total; 221 222 total = 0; 223 biggestsize = 0; 224 biggestone = 0; 225 nblocks = 0; 226 vaddr = round_page(vaddr); 227 228 for (i = 0; phys_avail[i + 1]; i += 2) { 229 phys_avail[i] = round_page(phys_avail[i]); 230 phys_avail[i + 1] = trunc_page(phys_avail[i + 1]); 231 } 232 233 for (i = 0; phys_avail[i + 1]; i += 2) { 234 int size = phys_avail[i + 1] - phys_avail[i]; 235 236 if (size > biggestsize) { 237 biggestone = i; 238 biggestsize = size; 239 } 240 ++nblocks; 241 total += size; 242 } 243 244 start = phys_avail[biggestone]; 245 246 /* 247 * Initialize the queue headers for the free queue, the active queue 248 * and the inactive queue. 249 */ 250 251 vm_page_queue_init(); 252 253 /* 254 * Allocate (and initialize) the hash table buckets. 255 * 256 * The number of buckets MUST BE a power of 2, and the actual value is 257 * the next power of 2 greater than the number of physical pages in 258 * the system. 259 * 260 * Note: This computation can be tweaked if desired. 261 */ 262 vm_page_buckets = (struct pglist *) vaddr; 263 bucket = vm_page_buckets; 264 if (vm_page_bucket_count == 0) { 265 vm_page_bucket_count = 1; 266 while (vm_page_bucket_count < atop(total)) 267 vm_page_bucket_count <<= 1; 268 } 269 vm_page_hash_mask = vm_page_bucket_count - 1; 270 271 /* 272 * Validate these addresses. 273 */ 274 275 new_start = start + vm_page_bucket_count * sizeof(struct pglist); 276 new_start = round_page(new_start); 277 mapped = vaddr; 278 vaddr = pmap_map(mapped, start, new_start, 279 VM_PROT_READ | VM_PROT_WRITE); 280 start = new_start; 281 bzero((caddr_t) mapped, vaddr - mapped); 282 mapped = vaddr; 283 284 for (i = 0; i < vm_page_bucket_count; i++) { 285 TAILQ_INIT(bucket); 286 bucket++; 287 } 288 289 /* 290 * Validate these zone addresses. 291 */ 292 293 new_start = start + (vaddr - mapped); 294 pmap_map(mapped, start, new_start, VM_PROT_READ | VM_PROT_WRITE); 295 bzero((caddr_t) mapped, (vaddr - mapped)); 296 start = round_page(new_start); 297 298 /* 299 * Compute the number of pages of memory that will be available for 300 * use (taking into account the overhead of a page structure per 301 * page). 302 */ 303 304 first_page = phys_avail[0] / PAGE_SIZE; 305 last_page = phys_avail[(nblocks - 1) * 2 + 1] / PAGE_SIZE; 306 307 page_range = last_page - (phys_avail[0] / PAGE_SIZE); 308 npages = (total - (page_range * sizeof(struct vm_page)) - 309 (start - phys_avail[biggestone])) / PAGE_SIZE; 310 311 /* 312 * Initialize the mem entry structures now, and put them in the free 313 * queue. 314 */ 315 316 vm_page_array = (vm_page_t) vaddr; 317 mapped = vaddr; 318 319 /* 320 * Validate these addresses. 321 */ 322 323 new_start = round_page(start + page_range * sizeof(struct vm_page)); 324 mapped = pmap_map(mapped, start, new_start, 325 VM_PROT_READ | VM_PROT_WRITE); 326 start = new_start; 327 328 first_managed_page = start / PAGE_SIZE; 329 330 /* 331 * Clear all of the page structures 332 */ 333 bzero((caddr_t) vm_page_array, page_range * sizeof(struct vm_page)); 334 vm_page_array_size = page_range; 335 336 cnt.v_page_count = 0; 337 cnt.v_free_count = 0; 338 for (i = 0; phys_avail[i + 1] && npages > 0; i += 2) { 339 if (i == biggestone) 340 pa = ptoa(first_managed_page); 341 else 342 pa = phys_avail[i]; 343 while (pa < phys_avail[i + 1] && npages-- > 0) { 344 ++cnt.v_page_count; 345 ++cnt.v_free_count; 346 m = PHYS_TO_VM_PAGE(pa); 347 m->phys_addr = pa; 348 m->flags = 0; 349 m->pc = (pa >> PAGE_SHIFT) & PQ_L2_MASK; 350 m->queue = PQ_FREE + m->pc; 351 TAILQ_INSERT_TAIL(vm_page_queues[m->queue].pl, m, pageq); 352 ++(*vm_page_queues[m->queue].lcnt); 353 pa += PAGE_SIZE; 354 } 355 } 356 357 return (mapped); 358} 359 360/* 361 * vm_page_hash: 362 * 363 * Distributes the object/offset key pair among hash buckets. 364 * 365 * NOTE: This macro depends on vm_page_bucket_count being a power of 2. 366 */ 367static inline int 368vm_page_hash(object, pindex) 369 vm_object_t object; 370 vm_pindex_t pindex; 371{ 372 return ((((unsigned) object) >> 5) + (pindex >> 1)) & vm_page_hash_mask; 373} 374 375/* 376 * vm_page_insert: [ internal use only ] 377 * 378 * Inserts the given mem entry into the object/object-page 379 * table and object list. 380 * 381 * The object and page must be locked, and must be splhigh. 382 */ 383 384void 385vm_page_insert(m, object, pindex) 386 register vm_page_t m; 387 register vm_object_t object; 388 register vm_pindex_t pindex; 389{ 390 register struct pglist *bucket; 391 392 if (m->flags & PG_TABLED) 393 panic("vm_page_insert: already inserted"); 394 395 /* 396 * Record the object/offset pair in this page 397 */ 398 399 m->object = object; 400 m->pindex = pindex; 401 402 /* 403 * Insert it into the object_object/offset hash table 404 */ 405 406 bucket = &vm_page_buckets[vm_page_hash(object, pindex)]; 407 TAILQ_INSERT_TAIL(bucket, m, hashq); 408 vm_page_bucket_generation++; 409 410 /* 411 * Now link into the object's list of backed pages. 412 */ 413 414 TAILQ_INSERT_TAIL(&object->memq, m, listq); 415 m->flags |= PG_TABLED; 416 m->object->page_hint = m; 417 m->object->generation++; 418 419 /* 420 * And show that the object has one more resident page. 421 */ 422 423 object->resident_page_count++; 424} 425 426/* 427 * vm_page_remove: [ internal use only ] 428 * NOTE: used by device pager as well -wfj 429 * 430 * Removes the given mem entry from the object/offset-page 431 * table and the object page list. 432 * 433 * The object and page must be locked, and at splhigh. 434 */ 435 436void 437vm_page_remove(m) 438 register vm_page_t m; 439{ 440 register struct pglist *bucket; 441 442 if (!(m->flags & PG_TABLED)) 443 return; 444 445 if (m->object->page_hint == m) 446 m->object->page_hint = NULL; 447 448 /* 449 * Remove from the object_object/offset hash table 450 */ 451 452 bucket = &vm_page_buckets[vm_page_hash(m->object, m->pindex)]; 453 TAILQ_REMOVE(bucket, m, hashq); 454 vm_page_bucket_generation++; 455 456 /* 457 * Now remove from the object's list of backed pages. 458 */ 459 460 TAILQ_REMOVE(&m->object->memq, m, listq); 461 462 /* 463 * And show that the object has one fewer resident page. 464 */ 465 466 m->object->resident_page_count--; 467 m->object->generation++; 468 469 m->flags &= ~PG_TABLED; 470} 471 472/* 473 * vm_page_lookup: 474 * 475 * Returns the page associated with the object/offset 476 * pair specified; if none is found, NULL is returned. 477 * 478 * The object must be locked. No side effects. 479 */ 480 481vm_page_t 482vm_page_lookup(object, pindex) 483 register vm_object_t object; 484 register vm_pindex_t pindex; 485{ 486 register vm_page_t m; 487 register struct pglist *bucket; 488 int curgeneration; 489 int s; 490 491 /* 492 * Search the hash table for this object/offset pair 493 */ 494 495 bucket = &vm_page_buckets[vm_page_hash(object, pindex)]; 496 497restart: 498 curgeneration = vm_page_bucket_generation; 499 for (m = TAILQ_FIRST(bucket); m != NULL; m = TAILQ_NEXT(m,hashq)) { 500 if (curgeneration != vm_page_bucket_generation) 501 goto restart; 502 if ((m->object == object) && (m->pindex == pindex)) { 503 m->object->page_hint = m; 504 return (m); 505 } 506 } 507 return (NULL); 508} 509 510/* 511 * vm_page_rename: 512 * 513 * Move the given memory entry from its 514 * current object to the specified target object/offset. 515 * 516 * The object must be locked. 517 */ 518void 519vm_page_rename(m, new_object, new_pindex) 520 register vm_page_t m; 521 register vm_object_t new_object; 522 vm_pindex_t new_pindex; 523{ 524 int s; 525 526 s = splvm(); 527 vm_page_remove(m); 528 vm_page_insert(m, new_object, new_pindex); 529 splx(s); 530} 531 532/* 533 * vm_page_unqueue without any wakeup 534 */ 535void 536vm_page_unqueue_nowakeup(m) 537 vm_page_t m; 538{ 539 int queue = m->queue; 540 struct vpgqueues *pq; 541 if (queue != PQ_NONE) { 542 pq = &vm_page_queues[queue]; 543 m->queue = PQ_NONE; 544 TAILQ_REMOVE(pq->pl, m, pageq); 545 --(*pq->cnt); 546 --(*pq->lcnt); 547 } 548} 549 550/* 551 * vm_page_unqueue must be called at splhigh(); 552 */ 553void 554vm_page_unqueue(m) 555 vm_page_t m; 556{ 557 int queue = m->queue; 558 struct vpgqueues *pq; 559 if (queue != PQ_NONE) { 560 m->queue = PQ_NONE; 561 pq = &vm_page_queues[queue]; 562 TAILQ_REMOVE(pq->pl, m, pageq); 563 --(*pq->cnt); 564 --(*pq->lcnt); 565 if ((queue - m->pc) == PQ_CACHE) { 566 if ((cnt.v_cache_count + cnt.v_free_count) < 567 (cnt.v_free_reserved + cnt.v_cache_min)) 568 pagedaemon_wakeup(); 569 } 570 } 571} 572 573/* 574 * Find a page on the specified queue with color optimization. 575 */ 576vm_page_t 577vm_page_list_find(basequeue, index) 578 int basequeue, index; 579{ 580#if PQ_L2_SIZE > 1 581 582 int i,j; 583 vm_page_t m; 584 int hindex; 585 struct vpgqueues *pq; 586 587 pq = &vm_page_queues[basequeue]; 588 589 m = TAILQ_FIRST(pq[index].pl); 590 if (m) 591 return m; 592 593 for(j = 0; j < PQ_L1_SIZE; j++) { 594 int ij; 595 for(i = (PQ_L2_SIZE / 2) - PQ_L1_SIZE; 596 (ij = i + j) > 0; 597 i -= PQ_L1_SIZE) { 598 599 hindex = index + ij; 600 if (hindex >= PQ_L2_SIZE) 601 hindex -= PQ_L2_SIZE; 602 if (m = TAILQ_FIRST(pq[hindex].pl)) 603 return m; 604 605 hindex = index - ij; 606 if (hindex < 0) 607 hindex += PQ_L2_SIZE; 608 if (m = TAILQ_FIRST(pq[hindex].pl)) 609 return m; 610 } 611 } 612 613 hindex = index + PQ_L2_SIZE / 2; 614 if (hindex >= PQ_L2_SIZE) 615 hindex -= PQ_L2_SIZE; 616 m = TAILQ_FIRST(pq[hindex].pl); 617 if (m) 618 return m; 619 620 return NULL; 621#else 622 return TAILQ_FIRST(vm_page_queues[basequeue].pl); 623#endif 624 625} 626 627/* 628 * Find a page on the specified queue with color optimization. 629 */ 630vm_page_t 631vm_page_select(object, pindex, basequeue) 632 vm_object_t object; 633 vm_pindex_t pindex; 634 int basequeue; 635{ 636 637#if PQ_L2_SIZE > 1 638 int index; 639 index = (pindex + object->pg_color) & PQ_L2_MASK; 640 return vm_page_list_find(basequeue, index); 641 642#else 643 return TAILQ_FIRST(vm_page_queues[basequeue].pl); 644#endif 645 646} 647 648/* 649 * Find a free or zero page, with specified preference. 650 */ 651static vm_page_t 652vm_page_select_free(object, pindex, prefqueue) 653 vm_object_t object; 654 vm_pindex_t pindex; 655 int prefqueue; 656{ 657#if PQ_L2_SIZE > 1 658 int i,j; 659 int index, hindex; 660#endif 661 vm_page_t m, mh; 662 int oqueuediff; 663 struct vpgqueues *pq; 664 665 if (prefqueue == PQ_ZERO) 666 oqueuediff = PQ_FREE - PQ_ZERO; 667 else 668 oqueuediff = PQ_ZERO - PQ_FREE; 669 670 if (mh = object->page_hint) { 671 if (mh->pindex == (pindex - 1)) { 672 if ((mh->flags & PG_FICTITIOUS) == 0) { 673 if ((mh < &vm_page_array[cnt.v_page_count-1]) && 674 (mh >= &vm_page_array[0])) { 675 int queue; 676 m = mh + 1; 677 if (VM_PAGE_TO_PHYS(m) == (VM_PAGE_TO_PHYS(mh) + PAGE_SIZE)) { 678 queue = m->queue - m->pc; 679 if (queue == PQ_FREE || queue == PQ_ZERO) { 680 return m; 681 } 682 } 683 } 684 } 685 } 686 } 687 688 pq = &vm_page_queues[prefqueue]; 689 690#if PQ_L2_SIZE > 1 691 692 index = (pindex + object->pg_color) & PQ_L2_MASK; 693 694 if (m = TAILQ_FIRST(pq[index].pl)) 695 return m; 696 if (m = TAILQ_FIRST(pq[index + oqueuediff].pl)) 697 return m; 698 699 for(j = 0; j < PQ_L1_SIZE; j++) { 700 int ij; 701 for(i = (PQ_L2_SIZE / 2) - PQ_L1_SIZE; 702 (ij = i + j) >= 0; 703 i -= PQ_L1_SIZE) { 704 705 hindex = index + ij; 706 if (hindex >= PQ_L2_SIZE) 707 hindex -= PQ_L2_SIZE; 708 if (m = TAILQ_FIRST(pq[hindex].pl)) 709 return m; 710 if (m = TAILQ_FIRST(pq[hindex + oqueuediff].pl)) 711 return m; 712 713 hindex = index - ij; 714 if (hindex < 0) 715 hindex += PQ_L2_SIZE; 716 if (m = TAILQ_FIRST(pq[hindex].pl)) 717 return m; 718 if (m = TAILQ_FIRST(pq[hindex + oqueuediff].pl)) 719 return m; 720 } 721 } 722 723 hindex = index + PQ_L2_SIZE / 2; 724 if (hindex >= PQ_L2_SIZE) 725 hindex -= PQ_L2_SIZE; 726 if (m = TAILQ_FIRST(pq[hindex].pl)) 727 return m; 728 if (m = TAILQ_FIRST(pq[hindex+oqueuediff].pl)) 729 return m; 730 731#else 732 if (m = TAILQ_FIRST(pq[0].pl)) 733 return m; 734 else 735 return TAILQ_FIRST(pq[oqueuediff].pl); 736#endif 737 738 return NULL; 739} 740 741/* 742 * vm_page_alloc: 743 * 744 * Allocate and return a memory cell associated 745 * with this VM object/offset pair. 746 * 747 * page_req classes: 748 * VM_ALLOC_NORMAL normal process request 749 * VM_ALLOC_SYSTEM system *really* needs a page 750 * VM_ALLOC_INTERRUPT interrupt time request 751 * VM_ALLOC_ZERO zero page 752 * 753 * Object must be locked. 754 */ 755vm_page_t 756vm_page_alloc(object, pindex, page_req) 757 vm_object_t object; 758 vm_pindex_t pindex; 759 int page_req; 760{ 761 register vm_page_t m; 762 struct vpgqueues *pq; 763 vm_object_t oldobject; 764 int queue, qtype; 765 int s; 766 767#ifdef DIAGNOSTIC 768 m = vm_page_lookup(object, pindex); 769 if (m) 770 panic("vm_page_alloc: page already allocated"); 771#endif 772 773 if ((curproc == pageproc) && (page_req != VM_ALLOC_INTERRUPT)) { 774 page_req = VM_ALLOC_SYSTEM; 775 }; 776 777 s = splvm(); 778 779 switch (page_req) { 780 781 case VM_ALLOC_NORMAL: 782 if (cnt.v_free_count >= cnt.v_free_reserved) { 783 m = vm_page_select_free(object, pindex, PQ_FREE); 784#if defined(DIAGNOSTIC) 785 if (m == NULL) 786 panic("vm_page_alloc(NORMAL): missing page on free queue\n"); 787#endif 788 } else { 789 m = vm_page_select(object, pindex, PQ_CACHE); 790 if (m == NULL) { 791 splx(s); 792#if defined(DIAGNOSTIC) 793 if (cnt.v_cache_count > 0) 794 printf("vm_page_alloc(NORMAL): missing pages on cache queue: %d\n", cnt.v_cache_count); 795#endif 796 vm_pageout_deficit++; 797 pagedaemon_wakeup(); 798 return (NULL); 799 } 800 } 801 break; 802 803 case VM_ALLOC_ZERO: 804 if (cnt.v_free_count >= cnt.v_free_reserved) { 805 m = vm_page_select_free(object, pindex, PQ_ZERO); 806#if defined(DIAGNOSTIC) 807 if (m == NULL) 808 panic("vm_page_alloc(ZERO): missing page on free queue\n"); 809#endif 810 } else { 811 m = vm_page_select(object, pindex, PQ_CACHE); 812 if (m == NULL) { 813 splx(s); 814#if defined(DIAGNOSTIC) 815 if (cnt.v_cache_count > 0) 816 printf("vm_page_alloc(ZERO): missing pages on cache queue: %d\n", cnt.v_cache_count); 817#endif 818 vm_pageout_deficit++; 819 pagedaemon_wakeup(); 820 return (NULL); 821 } 822 } 823 break; 824 825 case VM_ALLOC_SYSTEM: 826 if ((cnt.v_free_count >= cnt.v_free_reserved) || 827 ((cnt.v_cache_count == 0) && 828 (cnt.v_free_count >= cnt.v_interrupt_free_min))) { 829 m = vm_page_select_free(object, pindex, PQ_FREE); 830#if defined(DIAGNOSTIC) 831 if (m == NULL) 832 panic("vm_page_alloc(SYSTEM): missing page on free queue\n"); 833#endif 834 } else { 835 m = vm_page_select(object, pindex, PQ_CACHE); 836 if (m == NULL) { 837 splx(s); 838#if defined(DIAGNOSTIC) 839 if (cnt.v_cache_count > 0) 840 printf("vm_page_alloc(SYSTEM): missing pages on cache queue: %d\n", cnt.v_cache_count); 841#endif 842 vm_pageout_deficit++; 843 pagedaemon_wakeup(); 844 return (NULL); 845 } 846 } 847 break; 848 849 case VM_ALLOC_INTERRUPT: 850 if (cnt.v_free_count > 0) { 851 m = vm_page_select_free(object, pindex, PQ_FREE); 852#if defined(DIAGNOSTIC) 853 if (m == NULL) 854 panic("vm_page_alloc(INTERRUPT): missing page on free queue\n"); 855#endif 856 } else { 857 splx(s); 858 vm_pageout_deficit++; 859 pagedaemon_wakeup(); 860 return (NULL); 861 } 862 break; 863 864 default: 865 panic("vm_page_alloc: invalid allocation class"); 866 } 867 868 queue = m->queue; 869 qtype = queue - m->pc; 870 if (qtype == PQ_ZERO) 871 --vm_page_zero_count; 872 pq = &vm_page_queues[queue]; 873 TAILQ_REMOVE(pq->pl, m, pageq); 874 --(*pq->cnt); 875 --(*pq->lcnt); 876 oldobject = NULL; 877 if (qtype == PQ_ZERO) { 878 m->flags = PG_ZERO|PG_BUSY; 879 } else if (qtype == PQ_CACHE) { 880 oldobject = m->object; 881 vm_page_remove(m); 882 m->flags = PG_BUSY; 883 } else { 884 m->flags = PG_BUSY; 885 } 886 m->wire_count = 0; 887 m->hold_count = 0; 888 m->act_count = 0; 889 m->busy = 0; 890 m->valid = 0; 891 m->dirty = 0; 892 m->queue = PQ_NONE; 893 894 /* XXX before splx until vm_page_insert is safe */ 895 vm_page_insert(m, object, pindex); 896 897 /* 898 * Don't wakeup too often - wakeup the pageout daemon when 899 * we would be nearly out of memory. 900 */ 901 if (((cnt.v_free_count + cnt.v_cache_count) < 902 (cnt.v_free_reserved + cnt.v_cache_min)) || 903 (cnt.v_free_count < cnt.v_pageout_free_min)) 904 pagedaemon_wakeup(); 905 906 if ((qtype == PQ_CACHE) && 907 ((page_req == VM_ALLOC_NORMAL) || (page_req == VM_ALLOC_ZERO)) && 908 oldobject && (oldobject->type == OBJT_VNODE) && 909 ((oldobject->flags & OBJ_DEAD) == 0)) { 910 struct vnode *vp; 911 vp = (struct vnode *) oldobject->handle; 912 if (vp && VSHOULDFREE(vp)) { 913 if ((vp->v_flag & (VFREE|VTBFREE|VDOOMED)) == 0) { 914 TAILQ_INSERT_TAIL(&vnode_tobefree_list, vp, v_freelist); 915 vp->v_flag |= VTBFREE; 916 } 917 } 918 } 919 splx(s); 920 921 return (m); 922} 923 924void 925vm_wait() 926{ 927 int s; 928 929 s = splvm(); 930 if (curproc == pageproc) { 931 vm_pageout_pages_needed = 1; 932 tsleep(&vm_pageout_pages_needed, PSWP, "vmwait", 0); 933 } else { 934 if (!vm_pages_needed) { 935 vm_pages_needed++; 936 wakeup(&vm_pages_needed); 937 } 938 tsleep(&cnt.v_free_count, PVM, "vmwait", 0); 939 } 940 splx(s); 941} 942 943 944/* 945 * vm_page_activate: 946 * 947 * Put the specified page on the active list (if appropriate). 948 * 949 * The page queues must be locked. 950 */ 951void 952vm_page_activate(m) 953 register vm_page_t m; 954{ 955 int s; 956 957 s = splvm(); 958 if (m->queue == PQ_ACTIVE) 959 panic("vm_page_activate: already active"); 960 961 if ((m->queue - m->pc) == PQ_CACHE) 962 cnt.v_reactivated++; 963 964 vm_page_unqueue(m); 965 966 if (m->wire_count == 0) { 967 m->queue = PQ_ACTIVE; 968 ++(*vm_page_queues[PQ_ACTIVE].lcnt); 969 TAILQ_INSERT_TAIL(&vm_page_queue_active, m, pageq); 970 if (m->act_count < ACT_INIT) 971 m->act_count = ACT_INIT; 972 cnt.v_active_count++; 973 } 974 splx(s); 975} 976 977/* 978 * helper routine for vm_page_free and vm_page_free_zero 979 */ 980static int 981vm_page_freechk_and_unqueue(m) 982 vm_page_t m; 983{ 984 vm_object_t oldobject; 985 986 oldobject = m->object; 987 988#if !defined(MAX_PERF) 989 if (m->busy || 990 (m->flags & PG_BUSY) || 991 ((m->queue - m->pc) == PQ_FREE) || 992 (m->hold_count != 0)) { 993 printf("vm_page_free: pindex(%ld), busy(%d), PG_BUSY(%d), hold(%d)\n", 994 m->pindex, m->busy, 995 (m->flags & PG_BUSY) ? 1 : 0, m->hold_count); 996 if ((m->queue - m->pc) == PQ_FREE) 997 panic("vm_page_free: freeing free page"); 998 else 999 panic("vm_page_free: freeing busy page"); 1000 } 1001#endif 1002 1003 vm_page_remove(m); 1004 vm_page_unqueue_nowakeup(m); 1005 if ((m->flags & PG_FICTITIOUS) != 0) { 1006 return 0; 1007 } 1008 if (m->wire_count != 0) { 1009 if (m->wire_count > 1) { 1010 panic("vm_page_free: invalid wire count (%d), pindex: 0x%x", 1011 m->wire_count, m->pindex); 1012 } 1013 m->wire_count = 0; 1014 cnt.v_wire_count--; 1015 } 1016 1017 if (oldobject && (oldobject->type == OBJT_VNODE) && 1018 ((oldobject->flags & OBJ_DEAD) == 0)) { 1019 struct vnode *vp; 1020 vp = (struct vnode *) oldobject->handle; 1021 if (vp && VSHOULDFREE(vp)) { 1022 if ((vp->v_flag & (VTBFREE|VDOOMED|VFREE)) == 0) { 1023 TAILQ_INSERT_TAIL(&vnode_tobefree_list, vp, v_freelist); 1024 vp->v_flag |= VTBFREE; 1025 } 1026 } 1027 } 1028 1029 return 1; 1030} 1031 1032/* 1033 * helper routine for vm_page_free and vm_page_free_zero 1034 */ 1035static __inline void 1036vm_page_free_wakeup() 1037{ 1038 1039/* 1040 * if pageout daemon needs pages, then tell it that there are 1041 * some free. 1042 */ 1043 if (vm_pageout_pages_needed) { 1044 wakeup(&vm_pageout_pages_needed); 1045 vm_pageout_pages_needed = 0; 1046 } 1047 /* 1048 * wakeup processes that are waiting on memory if we hit a 1049 * high water mark. And wakeup scheduler process if we have 1050 * lots of memory. this process will swapin processes. 1051 */ 1052 if (vm_pages_needed && 1053 ((cnt.v_free_count + cnt.v_cache_count) >= cnt.v_free_min)) { 1054 wakeup(&cnt.v_free_count); 1055 vm_pages_needed = 0; 1056 } 1057} 1058 1059/* 1060 * vm_page_free: 1061 * 1062 * Returns the given page to the free list, 1063 * disassociating it with any VM object. 1064 * 1065 * Object and page must be locked prior to entry. 1066 */ 1067void 1068vm_page_free(m) 1069 register vm_page_t m; 1070{ 1071 int s; 1072 struct vpgqueues *pq; 1073 1074 s = splvm(); 1075 1076 cnt.v_tfree++; 1077 1078 if (!vm_page_freechk_and_unqueue(m)) { 1079 splx(s); 1080 return; 1081 } 1082 1083 m->queue = PQ_FREE + m->pc; 1084 pq = &vm_page_queues[m->queue]; 1085 ++(*pq->lcnt); 1086 ++(*pq->cnt); 1087 /* 1088 * If the pageout process is grabbing the page, it is likely 1089 * that the page is NOT in the cache. It is more likely that 1090 * the page will be partially in the cache if it is being 1091 * explicitly freed. 1092 */ 1093 if (curproc == pageproc) { 1094 TAILQ_INSERT_TAIL(pq->pl, m, pageq); 1095 } else { 1096 TAILQ_INSERT_HEAD(pq->pl, m, pageq); 1097 } 1098 1099 vm_page_free_wakeup(); 1100 splx(s); 1101} 1102 1103void 1104vm_page_free_zero(m) 1105 register vm_page_t m; 1106{ 1107 int s; 1108 struct vpgqueues *pq; 1109 1110 s = splvm(); 1111 1112 cnt.v_tfree++; 1113 1114 if (!vm_page_freechk_and_unqueue(m)) { 1115 splx(s); 1116 return; 1117 } 1118 1119 m->queue = PQ_ZERO + m->pc; 1120 pq = &vm_page_queues[m->queue]; 1121 ++(*pq->lcnt); 1122 ++(*pq->cnt); 1123 1124 TAILQ_INSERT_HEAD(pq->pl, m, pageq); 1125 ++vm_page_zero_count; 1126 vm_page_free_wakeup(); 1127 splx(s); 1128} 1129 1130/* 1131 * vm_page_wire: 1132 * 1133 * Mark this page as wired down by yet 1134 * another map, removing it from paging queues 1135 * as necessary. 1136 * 1137 * The page queues must be locked. 1138 */ 1139void 1140vm_page_wire(m) 1141 register vm_page_t m; 1142{ 1143 int s; 1144 1145 if (m->wire_count == 0) { 1146 s = splvm(); 1147 vm_page_unqueue(m); 1148 splx(s); 1149 cnt.v_wire_count++; 1150 } 1151 ++(*vm_page_queues[PQ_NONE].lcnt); 1152 m->wire_count++; 1153 m->flags |= PG_MAPPED; 1154} 1155 1156/* 1157 * vm_page_unwire: 1158 * 1159 * Release one wiring of this page, potentially 1160 * enabling it to be paged again. 1161 * 1162 * The page queues must be locked. 1163 */ 1164void 1165vm_page_unwire(m) 1166 register vm_page_t m; 1167{ 1168 int s; 1169 1170 s = splvm(); 1171 1172 if (m->wire_count > 0) 1173 m->wire_count--; 1174 1175 if (m->wire_count == 0) { 1176 cnt.v_wire_count--; 1177 TAILQ_INSERT_TAIL(&vm_page_queue_active, m, pageq); 1178 m->queue = PQ_ACTIVE; 1179 ++(*vm_page_queues[PQ_ACTIVE].lcnt); 1180 cnt.v_active_count++; 1181 } 1182 splx(s); 1183} 1184 1185 1186/* 1187 * vm_page_deactivate: 1188 * 1189 * Returns the given page to the inactive list, 1190 * indicating that no physical maps have access 1191 * to this page. [Used by the physical mapping system.] 1192 * 1193 * The page queues must be locked. 1194 */ 1195void 1196vm_page_deactivate(m) 1197 register vm_page_t m; 1198{ 1199 int s; 1200 1201 /* 1202 * Only move active pages -- ignore locked or already inactive ones. 1203 * 1204 * XXX: sometimes we get pages which aren't wired down or on any queue - 1205 * we need to put them on the inactive queue also, otherwise we lose 1206 * track of them. Paul Mackerras (paulus@cs.anu.edu.au) 9-Jan-93. 1207 */ 1208 if (m->queue == PQ_INACTIVE) 1209 return; 1210 1211 s = splvm(); 1212 if (m->wire_count == 0 && m->hold_count == 0) { 1213 if ((m->queue - m->pc) == PQ_CACHE) 1214 cnt.v_reactivated++; 1215 vm_page_unqueue(m); 1216 TAILQ_INSERT_TAIL(&vm_page_queue_inactive, m, pageq); 1217 m->queue = PQ_INACTIVE; 1218 ++(*vm_page_queues[PQ_INACTIVE].lcnt); 1219 cnt.v_inactive_count++; 1220 } 1221 splx(s); 1222} 1223 1224/* 1225 * vm_page_cache 1226 * 1227 * Put the specified page onto the page cache queue (if appropriate). 1228 */ 1229void 1230vm_page_cache(m) 1231 register vm_page_t m; 1232{ 1233 int s; 1234 1235 if ((m->flags & PG_BUSY) || m->busy || m->wire_count) { 1236 printf("vm_page_cache: attempting to cache busy page\n"); 1237 return; 1238 } 1239 if ((m->queue - m->pc) == PQ_CACHE) 1240 return; 1241 1242 vm_page_protect(m, VM_PROT_NONE); 1243 if (m->dirty != 0) { 1244 panic("vm_page_cache: caching a dirty page, pindex: %d", m->pindex); 1245 } 1246 s = splvm(); 1247 vm_page_unqueue_nowakeup(m); 1248 m->queue = PQ_CACHE + m->pc; 1249 ++(*vm_page_queues[m->queue].lcnt); 1250 TAILQ_INSERT_TAIL(vm_page_queues[m->queue].pl, m, pageq); 1251 cnt.v_cache_count++; 1252 vm_page_free_wakeup(); 1253 splx(s); 1254} 1255 1256 1257/* 1258 * mapping function for valid bits or for dirty bits in 1259 * a page 1260 */ 1261inline int 1262vm_page_bits(int base, int size) 1263{ 1264 u_short chunk; 1265 1266 if ((base == 0) && (size >= PAGE_SIZE)) 1267 return VM_PAGE_BITS_ALL; 1268 size = (size + DEV_BSIZE - 1) & ~(DEV_BSIZE - 1); 1269 base = (base % PAGE_SIZE) / DEV_BSIZE; 1270 chunk = vm_page_dev_bsize_chunks[size / DEV_BSIZE]; 1271 return (chunk << base) & VM_PAGE_BITS_ALL; 1272} 1273 1274/* 1275 * set a page valid and clean 1276 */ 1277void 1278vm_page_set_validclean(m, base, size) 1279 vm_page_t m; 1280 int base; 1281 int size; 1282{ 1283 int pagebits = vm_page_bits(base, size); 1284 m->valid |= pagebits; 1285 m->dirty &= ~pagebits; 1286 if( base == 0 && size == PAGE_SIZE) 1287 pmap_clear_modify(VM_PAGE_TO_PHYS(m)); 1288} 1289 1290/* 1291 * set a page (partially) invalid 1292 */ 1293void 1294vm_page_set_invalid(m, base, size) 1295 vm_page_t m; 1296 int base; 1297 int size; 1298{ 1299 int bits; 1300 1301 m->valid &= ~(bits = vm_page_bits(base, size)); 1302 if (m->valid == 0) 1303 m->dirty &= ~bits; 1304} 1305 1306/* 1307 * is (partial) page valid? 1308 */ 1309int 1310vm_page_is_valid(m, base, size) 1311 vm_page_t m; 1312 int base; 1313 int size; 1314{ 1315 int bits = vm_page_bits(base, size); 1316 1317 if (m->valid && ((m->valid & bits) == bits)) 1318 return 1; 1319 else 1320 return 0; 1321} 1322 1323void 1324vm_page_test_dirty(m) 1325 vm_page_t m; 1326{ 1327 if ((m->dirty != VM_PAGE_BITS_ALL) && 1328 pmap_is_modified(VM_PAGE_TO_PHYS(m))) { 1329 m->dirty = VM_PAGE_BITS_ALL; 1330 } 1331} 1332 1333/* 1334 * This interface is for merging with malloc() someday. 1335 * Even if we never implement compaction so that contiguous allocation 1336 * works after initialization time, malloc()'s data structures are good 1337 * for statistics and for allocations of less than a page. 1338 */ 1339void * 1340contigmalloc1(size, type, flags, low, high, alignment, boundary, map) 1341 unsigned long size; /* should be size_t here and for malloc() */ 1342 struct malloc_type *type; 1343 int flags; 1344 unsigned long low; 1345 unsigned long high; 1346 unsigned long alignment; 1347 unsigned long boundary; 1348 vm_map_t map; 1349{ 1350 int i, s, start; 1351 vm_offset_t addr, phys, tmp_addr; 1352 int pass; 1353 vm_page_t pga = vm_page_array; 1354 1355 size = round_page(size); 1356 if (size == 0) 1357 panic("contigmalloc1: size must not be 0"); 1358 if ((alignment & (alignment - 1)) != 0) 1359 panic("contigmalloc1: alignment must be a power of 2"); 1360 if ((boundary & (boundary - 1)) != 0) 1361 panic("contigmalloc1: boundary must be a power of 2"); 1362 1363 start = 0; 1364 for (pass = 0; pass <= 1; pass++) { 1365 s = splvm(); 1366again: 1367 /* 1368 * Find first page in array that is free, within range, aligned, and 1369 * such that the boundary won't be crossed. 1370 */ 1371 for (i = start; i < cnt.v_page_count; i++) { 1372 int pqtype; 1373 phys = VM_PAGE_TO_PHYS(&pga[i]); 1374 pqtype = pga[i].queue - pga[i].pc; 1375 if (((pqtype == PQ_ZERO) || (pqtype == PQ_FREE) || (pqtype == PQ_CACHE)) && 1376 (phys >= low) && (phys < high) && 1377 ((phys & (alignment - 1)) == 0) && 1378 (((phys ^ (phys + size - 1)) & ~(boundary - 1)) == 0)) 1379 break; 1380 } 1381 1382 /* 1383 * If the above failed or we will exceed the upper bound, fail. 1384 */ 1385 if ((i == cnt.v_page_count) || 1386 ((VM_PAGE_TO_PHYS(&pga[i]) + size) > high)) { 1387 vm_page_t m, next; 1388 1389again1: 1390 for (m = TAILQ_FIRST(&vm_page_queue_inactive); 1391 m != NULL; 1392 m = next) { 1393 1394 if (m->queue != PQ_INACTIVE) { 1395 break; 1396 } 1397 1398 next = TAILQ_NEXT(m, pageq); 1399 if (m->flags & PG_BUSY) { 1400 m->flags |= PG_WANTED; 1401 tsleep(m, PVM, "vpctw0", 0); 1402 goto again1; 1403 } 1404 vm_page_test_dirty(m); 1405 if (m->dirty) { 1406 if (m->object->type == OBJT_VNODE) { 1407 vn_lock(m->object->handle, LK_EXCLUSIVE | LK_RETRY, curproc); 1408 vm_object_page_clean(m->object, 0, 0, TRUE); 1409 VOP_UNLOCK(m->object->handle, 0, curproc); 1410 goto again1; 1411 } else if (m->object->type == OBJT_SWAP || 1412 m->object->type == OBJT_DEFAULT) { 1413 vm_page_protect(m, VM_PROT_NONE); 1414 vm_pageout_flush(&m, 1, 0); 1415 goto again1; 1416 } 1417 } 1418 if ((m->dirty == 0) && 1419 (m->busy == 0) && 1420 (m->hold_count == 0)) 1421 vm_page_cache(m); 1422 } 1423 1424 for (m = TAILQ_FIRST(&vm_page_queue_active); 1425 m != NULL; 1426 m = next) { 1427 1428 if (m->queue != PQ_ACTIVE) { 1429 break; 1430 } 1431 1432 next = TAILQ_NEXT(m, pageq); 1433 if (m->flags & PG_BUSY) { 1434 m->flags |= PG_WANTED; 1435 tsleep(m, PVM, "vpctw1", 0); 1436 goto again1; 1437 } 1438 vm_page_test_dirty(m); 1439 if (m->dirty) { 1440 if (m->object->type == OBJT_VNODE) { 1441 vn_lock(m->object->handle, LK_EXCLUSIVE | LK_RETRY, curproc); 1442 vm_object_page_clean(m->object, 0, 0, TRUE); 1443 VOP_UNLOCK(m->object->handle, 0, curproc); 1444 goto again1; 1445 } else if (m->object->type == OBJT_SWAP || 1446 m->object->type == OBJT_DEFAULT) { 1447 vm_page_protect(m, VM_PROT_NONE); 1448 vm_pageout_flush(&m, 1, 0); 1449 goto again1; 1450 } 1451 } 1452 if ((m->dirty == 0) && 1453 (m->busy == 0) && 1454 (m->hold_count == 0)) 1455 vm_page_cache(m); 1456 } 1457 1458 splx(s); 1459 continue; 1460 } 1461 start = i; 1462 1463 /* 1464 * Check successive pages for contiguous and free. 1465 */ 1466 for (i = start + 1; i < (start + size / PAGE_SIZE); i++) { 1467 int pqtype; 1468 pqtype = pga[i].queue - pga[i].pc; 1469 if ((VM_PAGE_TO_PHYS(&pga[i]) != 1470 (VM_PAGE_TO_PHYS(&pga[i - 1]) + PAGE_SIZE)) || 1471 ((pqtype != PQ_ZERO) && (pqtype != PQ_FREE) && (pqtype != PQ_CACHE))) { 1472 start++; 1473 goto again; 1474 } 1475 } 1476 1477 for (i = start; i < (start + size / PAGE_SIZE); i++) { 1478 int pqtype; 1479 vm_page_t m = &pga[i]; 1480 1481 pqtype = m->queue - m->pc; 1482 if (pqtype == PQ_CACHE) 1483 vm_page_free(m); 1484 1485 TAILQ_REMOVE(vm_page_queues[m->queue].pl, m, pageq); 1486 --(*vm_page_queues[m->queue].lcnt); 1487 cnt.v_free_count--; 1488 m->valid = VM_PAGE_BITS_ALL; 1489 m->flags = 0; 1490 m->dirty = 0; 1491 m->wire_count = 0; 1492 m->busy = 0; 1493 m->queue = PQ_NONE; 1494 m->object = NULL; 1495 vm_page_wire(m); 1496 } 1497 1498 /* 1499 * We've found a contiguous chunk that meets are requirements. 1500 * Allocate kernel VM, unfree and assign the physical pages to it and 1501 * return kernel VM pointer. 1502 */ 1503 tmp_addr = addr = kmem_alloc_pageable(map, size); 1504 if (addr == 0) { 1505 /* 1506 * XXX We almost never run out of kernel virtual 1507 * space, so we don't make the allocated memory 1508 * above available. 1509 */ 1510 splx(s); 1511 return (NULL); 1512 } 1513 1514 for (i = start; i < (start + size / PAGE_SIZE); i++) { 1515 vm_page_t m = &pga[i]; 1516 vm_page_insert(m, kernel_object, 1517 OFF_TO_IDX(tmp_addr - VM_MIN_KERNEL_ADDRESS)); 1518 pmap_kenter(tmp_addr, VM_PAGE_TO_PHYS(m)); 1519 tmp_addr += PAGE_SIZE; 1520 } 1521 1522 splx(s); 1523 return ((void *)addr); 1524 } 1525 return NULL; 1526} 1527 1528void * 1529contigmalloc(size, type, flags, low, high, alignment, boundary) 1530 unsigned long size; /* should be size_t here and for malloc() */ 1531 struct malloc_type *type; 1532 int flags; 1533 unsigned long low; 1534 unsigned long high; 1535 unsigned long alignment; 1536 unsigned long boundary; 1537{ 1538 return contigmalloc1(size, type, flags, low, high, alignment, boundary, 1539 kernel_map); 1540} 1541 1542vm_offset_t 1543vm_page_alloc_contig(size, low, high, alignment) 1544 vm_offset_t size; 1545 vm_offset_t low; 1546 vm_offset_t high; 1547 vm_offset_t alignment; 1548{ 1549 return ((vm_offset_t)contigmalloc1(size, M_DEVBUF, M_NOWAIT, low, high, 1550 alignment, 0ul, kernel_map)); 1551} 1552 1553#include "opt_ddb.h" 1554#ifdef DDB 1555#include <sys/kernel.h> 1556 1557#include <ddb/ddb.h> 1558 1559DB_SHOW_COMMAND(page, vm_page_print_page_info) 1560{ 1561 db_printf("cnt.v_free_count: %d\n", cnt.v_free_count); 1562 db_printf("cnt.v_cache_count: %d\n", cnt.v_cache_count); 1563 db_printf("cnt.v_inactive_count: %d\n", cnt.v_inactive_count); 1564 db_printf("cnt.v_active_count: %d\n", cnt.v_active_count); 1565 db_printf("cnt.v_wire_count: %d\n", cnt.v_wire_count); 1566 db_printf("cnt.v_free_reserved: %d\n", cnt.v_free_reserved); 1567 db_printf("cnt.v_free_min: %d\n", cnt.v_free_min); 1568 db_printf("cnt.v_free_target: %d\n", cnt.v_free_target); 1569 db_printf("cnt.v_cache_min: %d\n", cnt.v_cache_min); 1570 db_printf("cnt.v_inactive_target: %d\n", cnt.v_inactive_target); 1571} 1572 1573DB_SHOW_COMMAND(pageq, vm_page_print_pageq_info) 1574{ 1575 int i; 1576 db_printf("PQ_FREE:"); 1577 for(i=0;i<PQ_L2_SIZE;i++) { 1578 db_printf(" %d", *vm_page_queues[PQ_FREE + i].lcnt); 1579 } 1580 db_printf("\n"); 1581 1582 db_printf("PQ_CACHE:"); 1583 for(i=0;i<PQ_L2_SIZE;i++) { 1584 db_printf(" %d", *vm_page_queues[PQ_CACHE + i].lcnt); 1585 } 1586 db_printf("\n"); 1587 1588 db_printf("PQ_ZERO:"); 1589 for(i=0;i<PQ_L2_SIZE;i++) { 1590 db_printf(" %d", *vm_page_queues[PQ_ZERO + i].lcnt); 1591 } 1592 db_printf("\n"); 1593 1594 db_printf("PQ_ACTIVE: %d, PQ_INACTIVE: %d\n", 1595 *vm_page_queues[PQ_ACTIVE].lcnt, 1596 *vm_page_queues[PQ_INACTIVE].lcnt); 1597} 1598#endif /* DDB */ 1599