1 /*- 2 * Copyright (c) 2002-2006 Rice University 3 * Copyright (c) 2007 Alan L. Cox <alc@cs.rice.edu> 4 * All rights reserved. 5 * 6 * This software was developed for the FreeBSD Project by Alan L. Cox, 7 * Olivier Crameri, Peter Druschel, Sitaram Iyer, and Juan Navarro. 8 * 9 * Redistribution and use in source and binary forms, with or without 10 * modification, are permitted provided that the following conditions 11 * are met: 12 * 1. Redistributions of source code must retain the above copyright 13 * notice, this list of conditions and the following disclaimer. 14 * 2. Redistributions in binary form must reproduce the above copyright 15 * notice, this list of conditions and the following disclaimer in the 16 * documentation and/or other materials provided with the distribution. 17 * 18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 21 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 22 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 23 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 24 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS 25 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 26 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY 28 * WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 * POSSIBILITY OF SUCH DAMAGE. 30 */ 31 32 #include <sys/cdefs.h> 33 __FBSDID("$FreeBSD$"); 34 35 #include "opt_ddb.h" 36 37 #include <sys/param.h> 38 #include <sys/systm.h> 39 #include <sys/lock.h> 40 #include <sys/kernel.h> 41 #include <sys/malloc.h> 42 #include <sys/mutex.h> 43 #include <sys/queue.h> 44 #include <sys/sbuf.h> 45 #include <sys/sysctl.h> 46 #include <sys/vmmeter.h> 47 48 #include <ddb/ddb.h> 49 50 #include <vm/vm.h> 51 #include <vm/vm_param.h> 52 #include <vm/vm_kern.h> 53 #include <vm/vm_object.h> 54 #include <vm/vm_page.h> 55 #include <vm/vm_phys.h> 56 57 struct vm_freelist { 58 struct pglist pl; 59 int lcnt; 60 }; 61 62 struct vm_phys_seg { 63 vm_paddr_t start; 64 vm_paddr_t end; 65 vm_page_t first_page; 66 struct vm_freelist (*free_queues)[VM_NFREEPOOL][VM_NFREEORDER]; 67 }; 68 69 static struct vm_phys_seg vm_phys_segs[VM_PHYSSEG_MAX]; 70 71 static int vm_phys_nsegs; 72 73 static struct vm_freelist 74 vm_phys_free_queues[VM_NFREELIST][VM_NFREEPOOL][VM_NFREEORDER]; 75 76 static int vm_nfreelists = VM_FREELIST_DEFAULT + 1; 77 78 static int cnt_prezero; 79 SYSCTL_INT(_vm_stats_misc, OID_AUTO, cnt_prezero, CTLFLAG_RD, 80 &cnt_prezero, 0, "The number of physical pages prezeroed at idle time"); 81 82 static int sysctl_vm_phys_free(SYSCTL_HANDLER_ARGS); 83 SYSCTL_OID(_vm, OID_AUTO, phys_free, CTLTYPE_STRING | CTLFLAG_RD, 84 NULL, 0, sysctl_vm_phys_free, "A", "Phys Free Info"); 85 86 static int sysctl_vm_phys_segs(SYSCTL_HANDLER_ARGS); 87 SYSCTL_OID(_vm, OID_AUTO, phys_segs, CTLTYPE_STRING | CTLFLAG_RD, 88 NULL, 0, sysctl_vm_phys_segs, "A", "Phys Seg Info"); 89 90 static void vm_phys_create_seg(vm_paddr_t start, vm_paddr_t end, int flind); 91 static int vm_phys_paddr_to_segind(vm_paddr_t pa); 92 static void vm_phys_set_pool(int pool, vm_page_t m, int order); 93 static void vm_phys_split_pages(vm_page_t m, int oind, struct vm_freelist *fl, 94 int order); 95 96 /* 97 * Outputs the state of the physical memory allocator, specifically, 98 * the amount of physical memory in each free list. 99 */ 100 static int 101 sysctl_vm_phys_free(SYSCTL_HANDLER_ARGS) 102 { 103 struct sbuf sbuf; 104 struct vm_freelist *fl; 105 char *cbuf; 106 const int cbufsize = vm_nfreelists*(VM_NFREEORDER + 1)*81; 107 int error, flind, oind, pind; 108 109 cbuf = malloc(cbufsize, M_TEMP, M_WAITOK | M_ZERO); 110 sbuf_new(&sbuf, cbuf, cbufsize, SBUF_FIXEDLEN); 111 for (flind = 0; flind < vm_nfreelists; flind++) { 112 sbuf_printf(&sbuf, "\nFREE LIST %d:\n" 113 "\n ORDER (SIZE) | NUMBER" 114 "\n ", flind); 115 for (pind = 0; pind < VM_NFREEPOOL; pind++) 116 sbuf_printf(&sbuf, " | POOL %d", pind); 117 sbuf_printf(&sbuf, "\n-- "); 118 for (pind = 0; pind < VM_NFREEPOOL; pind++) 119 sbuf_printf(&sbuf, "-- -- "); 120 sbuf_printf(&sbuf, "--\n"); 121 for (oind = VM_NFREEORDER - 1; oind >= 0; oind--) { 122 sbuf_printf(&sbuf, " %2.2d (%6.6dK)", oind, 123 1 << (PAGE_SHIFT - 10 + oind)); 124 for (pind = 0; pind < VM_NFREEPOOL; pind++) { 125 fl = vm_phys_free_queues[flind][pind]; 126 sbuf_printf(&sbuf, " | %6.6d", fl[oind].lcnt); 127 } 128 sbuf_printf(&sbuf, "\n"); 129 } 130 } 131 sbuf_finish(&sbuf); 132 error = SYSCTL_OUT(req, sbuf_data(&sbuf), sbuf_len(&sbuf)); 133 sbuf_delete(&sbuf); 134 free(cbuf, M_TEMP); 135 return (error); 136 } 137 138 /* 139 * Outputs the set of physical memory segments. 140 */ 141 static int 142 sysctl_vm_phys_segs(SYSCTL_HANDLER_ARGS) 143 { 144 struct sbuf sbuf; 145 struct vm_phys_seg *seg; 146 char *cbuf; 147 const int cbufsize = VM_PHYSSEG_MAX*(VM_NFREEORDER + 1)*81; 148 int error, segind; 149 150 cbuf = malloc(cbufsize, M_TEMP, M_WAITOK | M_ZERO); 151 sbuf_new(&sbuf, cbuf, cbufsize, SBUF_FIXEDLEN); 152 for (segind = 0; segind < vm_phys_nsegs; segind++) { 153 sbuf_printf(&sbuf, "\nSEGMENT %d:\n\n", segind); 154 seg = &vm_phys_segs[segind]; 155 sbuf_printf(&sbuf, "start: %#jx\n", 156 (uintmax_t)seg->start); 157 sbuf_printf(&sbuf, "end: %#jx\n", 158 (uintmax_t)seg->end); 159 sbuf_printf(&sbuf, "free list: %p\n", seg->free_queues); 160 } 161 sbuf_finish(&sbuf); 162 error = SYSCTL_OUT(req, sbuf_data(&sbuf), sbuf_len(&sbuf)); 163 sbuf_delete(&sbuf); 164 free(cbuf, M_TEMP); 165 return (error); 166 } 167 168 /* 169 * Create a physical memory segment. 170 */ 171 static void 172 vm_phys_create_seg(vm_paddr_t start, vm_paddr_t end, int flind) 173 { 174 struct vm_phys_seg *seg; 175 #ifdef VM_PHYSSEG_SPARSE 176 long pages; 177 int segind; 178 179 pages = 0; 180 for (segind = 0; segind < vm_phys_nsegs; segind++) { 181 seg = &vm_phys_segs[segind]; 182 pages += atop(seg->end - seg->start); 183 } 184 #endif 185 KASSERT(vm_phys_nsegs < VM_PHYSSEG_MAX, 186 ("vm_phys_create_seg: increase VM_PHYSSEG_MAX")); 187 seg = &vm_phys_segs[vm_phys_nsegs++]; 188 seg->start = start; 189 seg->end = end; 190 #ifdef VM_PHYSSEG_SPARSE 191 seg->first_page = &vm_page_array[pages]; 192 #else 193 seg->first_page = PHYS_TO_VM_PAGE(start); 194 #endif 195 seg->free_queues = &vm_phys_free_queues[flind]; 196 } 197 198 /* 199 * Initialize the physical memory allocator. 200 */ 201 void 202 vm_phys_init(void) 203 { 204 struct vm_freelist *fl; 205 int flind, i, oind, pind; 206 207 for (i = 0; phys_avail[i + 1] != 0; i += 2) { 208 #ifdef VM_FREELIST_ISADMA 209 if (phys_avail[i] < 16777216) { 210 if (phys_avail[i + 1] > 16777216) { 211 vm_phys_create_seg(phys_avail[i], 16777216, 212 VM_FREELIST_ISADMA); 213 vm_phys_create_seg(16777216, phys_avail[i + 1], 214 VM_FREELIST_DEFAULT); 215 } else { 216 vm_phys_create_seg(phys_avail[i], 217 phys_avail[i + 1], VM_FREELIST_ISADMA); 218 } 219 if (VM_FREELIST_ISADMA >= vm_nfreelists) 220 vm_nfreelists = VM_FREELIST_ISADMA + 1; 221 } else 222 #endif 223 #ifdef VM_FREELIST_HIGHMEM 224 if (phys_avail[i + 1] > VM_HIGHMEM_ADDRESS) { 225 if (phys_avail[i] < VM_HIGHMEM_ADDRESS) { 226 vm_phys_create_seg(phys_avail[i], 227 VM_HIGHMEM_ADDRESS, VM_FREELIST_DEFAULT); 228 vm_phys_create_seg(VM_HIGHMEM_ADDRESS, 229 phys_avail[i + 1], VM_FREELIST_HIGHMEM); 230 } else { 231 vm_phys_create_seg(phys_avail[i], 232 phys_avail[i + 1], VM_FREELIST_HIGHMEM); 233 } 234 if (VM_FREELIST_HIGHMEM >= vm_nfreelists) 235 vm_nfreelists = VM_FREELIST_HIGHMEM + 1; 236 } else 237 #endif 238 vm_phys_create_seg(phys_avail[i], phys_avail[i + 1], 239 VM_FREELIST_DEFAULT); 240 } 241 for (flind = 0; flind < vm_nfreelists; flind++) { 242 for (pind = 0; pind < VM_NFREEPOOL; pind++) { 243 fl = vm_phys_free_queues[flind][pind]; 244 for (oind = 0; oind < VM_NFREEORDER; oind++) 245 TAILQ_INIT(&fl[oind].pl); 246 } 247 } 248 } 249 250 /* 251 * Split a contiguous, power of two-sized set of physical pages. 252 */ 253 static __inline void 254 vm_phys_split_pages(vm_page_t m, int oind, struct vm_freelist *fl, int order) 255 { 256 vm_page_t m_buddy; 257 258 while (oind > order) { 259 oind--; 260 m_buddy = &m[1 << oind]; 261 KASSERT(m_buddy->order == VM_NFREEORDER, 262 ("vm_phys_split_pages: page %p has unexpected order %d", 263 m_buddy, m_buddy->order)); 264 m_buddy->order = oind; 265 TAILQ_INSERT_HEAD(&fl[oind].pl, m_buddy, pageq); 266 fl[oind].lcnt++; 267 } 268 } 269 270 /* 271 * Initialize a physical page and add it to the free lists. 272 */ 273 void 274 vm_phys_add_page(vm_paddr_t pa) 275 { 276 vm_page_t m; 277 278 cnt.v_page_count++; 279 m = vm_phys_paddr_to_vm_page(pa); 280 m->phys_addr = pa; 281 m->segind = vm_phys_paddr_to_segind(pa); 282 m->flags = PG_FREE; 283 KASSERT(m->order == VM_NFREEORDER, 284 ("vm_phys_add_page: page %p has unexpected order %d", 285 m, m->order)); 286 m->pool = VM_FREEPOOL_DEFAULT; 287 pmap_page_init(m); 288 vm_phys_free_pages(m, 0); 289 } 290 291 /* 292 * Allocate a contiguous, power of two-sized set of physical pages 293 * from the free lists. 294 */ 295 vm_page_t 296 vm_phys_alloc_pages(int pool, int order) 297 { 298 vm_page_t m; 299 300 mtx_lock(&vm_page_queue_free_mtx); 301 m = vm_phys_alloc_pages_locked(pool, order); 302 mtx_unlock(&vm_page_queue_free_mtx); 303 return (m); 304 } 305 306 /* 307 * Allocate a contiguous, power of two-sized set of physical pages 308 * from the free lists. 309 */ 310 vm_page_t 311 vm_phys_alloc_pages_locked(int pool, int order) 312 { 313 struct vm_freelist *fl; 314 struct vm_freelist *alt; 315 int flind, oind, pind; 316 vm_page_t m; 317 318 KASSERT(pool < VM_NFREEPOOL, 319 ("vm_phys_alloc_pages_locked: pool %d is out of range", pool)); 320 KASSERT(order < VM_NFREEORDER, 321 ("vm_phys_alloc_pages_locked: order %d is out of range", order)); 322 mtx_assert(&vm_page_queue_free_mtx, MA_OWNED); 323 for (flind = 0; flind < vm_nfreelists; flind++) { 324 fl = vm_phys_free_queues[flind][pool]; 325 for (oind = order; oind < VM_NFREEORDER; oind++) { 326 m = TAILQ_FIRST(&fl[oind].pl); 327 if (m != NULL) { 328 TAILQ_REMOVE(&fl[oind].pl, m, pageq); 329 fl[oind].lcnt--; 330 m->order = VM_NFREEORDER; 331 vm_phys_split_pages(m, oind, fl, order); 332 cnt.v_free_count -= 1 << order; 333 return (m); 334 } 335 } 336 337 /* 338 * The given pool was empty. Find the largest 339 * contiguous, power-of-two-sized set of pages in any 340 * pool. Transfer these pages to the given pool, and 341 * use them to satisfy the allocation. 342 */ 343 for (oind = VM_NFREEORDER - 1; oind >= order; oind--) { 344 for (pind = 0; pind < VM_NFREEPOOL; pind++) { 345 alt = vm_phys_free_queues[flind][pind]; 346 m = TAILQ_FIRST(&alt[oind].pl); 347 if (m != NULL) { 348 TAILQ_REMOVE(&alt[oind].pl, m, pageq); 349 alt[oind].lcnt--; 350 m->order = VM_NFREEORDER; 351 vm_phys_set_pool(pool, m, oind); 352 vm_phys_split_pages(m, oind, fl, order); 353 cnt.v_free_count -= 1 << order; 354 return (m); 355 } 356 } 357 } 358 } 359 return (NULL); 360 } 361 362 /* 363 * Allocate physical memory from phys_avail[]. 364 */ 365 vm_paddr_t 366 vm_phys_bootstrap_alloc(vm_size_t size, unsigned long alignment) 367 { 368 vm_paddr_t pa; 369 int i; 370 371 size = round_page(size); 372 for (i = 0; phys_avail[i + 1] != 0; i += 2) { 373 if (phys_avail[i + 1] - phys_avail[i] < size) 374 continue; 375 pa = phys_avail[i]; 376 phys_avail[i] += size; 377 return (pa); 378 } 379 panic("vm_phys_bootstrap_alloc"); 380 } 381 382 /* 383 * Find the vm_page corresponding to the given physical address. 384 */ 385 vm_page_t 386 vm_phys_paddr_to_vm_page(vm_paddr_t pa) 387 { 388 struct vm_phys_seg *seg; 389 int segind; 390 391 for (segind = 0; segind < vm_phys_nsegs; segind++) { 392 seg = &vm_phys_segs[segind]; 393 if (pa >= seg->start && pa < seg->end) 394 return (&seg->first_page[atop(pa - seg->start)]); 395 } 396 panic("vm_phys_paddr_to_vm_page: paddr %#jx is not in any segment", 397 (uintmax_t)pa); 398 } 399 400 /* 401 * Find the segment containing the given physical address. 402 */ 403 static int 404 vm_phys_paddr_to_segind(vm_paddr_t pa) 405 { 406 struct vm_phys_seg *seg; 407 int segind; 408 409 for (segind = 0; segind < vm_phys_nsegs; segind++) { 410 seg = &vm_phys_segs[segind]; 411 if (pa >= seg->start && pa < seg->end) 412 return (segind); 413 } 414 panic("vm_phys_paddr_to_segind: paddr %#jx is not in any segment" , 415 (uintmax_t)pa); 416 } 417 418 /* 419 * Free a contiguous, power of two-sized set of physical pages. 420 */ 421 void 422 vm_phys_free_pages(vm_page_t m, int order) 423 { 424 425 mtx_lock(&vm_page_queue_free_mtx); 426 vm_phys_free_pages_locked(m, order); 427 mtx_unlock(&vm_page_queue_free_mtx); 428 } 429 430 /* 431 * Free a contiguous, power of two-sized set of physical pages. 432 */ 433 void 434 vm_phys_free_pages_locked(vm_page_t m, int order) 435 { 436 struct vm_freelist *fl; 437 struct vm_phys_seg *seg; 438 vm_paddr_t pa, pa_buddy; 439 vm_page_t m_buddy; 440 441 KASSERT(m->order == VM_NFREEORDER, 442 ("vm_phys_free_pages_locked: page %p has unexpected order %d", 443 m, m->order)); 444 KASSERT(m->pool < VM_NFREEPOOL, 445 ("vm_phys_free_pages_locked: page %p has unexpected pool %d", 446 m, m->pool)); 447 KASSERT(order < VM_NFREEORDER, 448 ("vm_phys_free_pages_locked: order %d is out of range", order)); 449 mtx_assert(&vm_page_queue_free_mtx, MA_OWNED); 450 pa = VM_PAGE_TO_PHYS(m); 451 seg = &vm_phys_segs[m->segind]; 452 cnt.v_free_count += 1 << order; 453 while (order < VM_NFREEORDER - 1) { 454 pa_buddy = pa ^ (1 << (PAGE_SHIFT + order)); 455 if (pa_buddy < seg->start || 456 pa_buddy >= seg->end) 457 break; 458 m_buddy = &seg->first_page[atop(pa_buddy - seg->start)]; 459 if (m_buddy->order != order) 460 break; 461 fl = (*seg->free_queues)[m_buddy->pool]; 462 TAILQ_REMOVE(&fl[m_buddy->order].pl, m_buddy, pageq); 463 fl[m_buddy->order].lcnt--; 464 m_buddy->order = VM_NFREEORDER; 465 if (m_buddy->pool != m->pool) 466 vm_phys_set_pool(m->pool, m_buddy, order); 467 order++; 468 pa &= ~((1 << (PAGE_SHIFT + order)) - 1); 469 m = &seg->first_page[atop(pa - seg->start)]; 470 } 471 m->order = order; 472 fl = (*seg->free_queues)[m->pool]; 473 TAILQ_INSERT_TAIL(&fl[order].pl, m, pageq); 474 fl[order].lcnt++; 475 } 476 477 /* 478 * Set the pool for a contiguous, power of two-sized set of physical pages. 479 */ 480 static void 481 vm_phys_set_pool(int pool, vm_page_t m, int order) 482 { 483 vm_page_t m_tmp; 484 485 for (m_tmp = m; m_tmp < &m[1 << order]; m_tmp++) 486 m_tmp->pool = pool; 487 } 488 489 /* 490 * Try to zero one or more physical pages. Used by an idle priority thread. 491 */ 492 boolean_t 493 vm_phys_zero_pages_idle(void) 494 { 495 struct vm_freelist *fl; 496 vm_page_t m, m_tmp; 497 int flind, pind, q, zeroed; 498 499 mtx_assert(&vm_page_queue_free_mtx, MA_OWNED); 500 for (flind = 0; flind < vm_nfreelists; flind++) { 501 pind = VM_FREEPOOL_DEFAULT; 502 fl = vm_phys_free_queues[flind][pind]; 503 for (q = 0; q < VM_NFREEORDER; q++) { 504 m = TAILQ_FIRST(&fl[q].pl); 505 if (m != NULL && (m->flags & PG_ZERO) == 0) { 506 TAILQ_REMOVE(&fl[q].pl, m, pageq); 507 fl[q].lcnt--; 508 m->order = VM_NFREEORDER; 509 cnt.v_free_count -= 1 << q; 510 mtx_unlock(&vm_page_queue_free_mtx); 511 zeroed = 0; 512 for (m_tmp = m; m_tmp < &m[1 << q]; m_tmp++) { 513 if ((m_tmp->flags & PG_ZERO) == 0) { 514 pmap_zero_page_idle(m_tmp); 515 m_tmp->flags |= PG_ZERO; 516 zeroed++; 517 } 518 } 519 cnt_prezero += zeroed; 520 mtx_lock(&vm_page_queue_free_mtx); 521 vm_phys_free_pages_locked(m, q); 522 vm_page_zero_count += zeroed; 523 return (TRUE); 524 } 525 } 526 } 527 return (FALSE); 528 } 529 530 /* 531 * Allocate a contiguous set of physical pages of the given size 532 * "npages" from the free lists. All of the physical pages must be at 533 * or above the given physical address "low" and below the given 534 * physical address "high". The given value "alignment" determines the 535 * alignment of the first physical page in the set. If the given value 536 * "boundary" is non-zero, then the set of physical pages cannot cross 537 * any physical address boundary that is a multiple of that value. Both 538 * "alignment" and "boundary" must be a power of two. 539 */ 540 vm_page_t 541 vm_phys_alloc_contig(unsigned long npages, vm_paddr_t low, vm_paddr_t high, 542 unsigned long alignment, unsigned long boundary) 543 { 544 struct vm_freelist *fl; 545 struct vm_phys_seg *seg; 546 vm_paddr_t pa, pa_last, size; 547 vm_page_t m, m_ret; 548 int flind, i, oind, order, pind; 549 550 size = npages << PAGE_SHIFT; 551 KASSERT(size != 0, 552 ("vm_phys_alloc_contig: size must not be 0")); 553 KASSERT((alignment & (alignment - 1)) == 0, 554 ("vm_phys_alloc_contig: alignment must be a power of 2")); 555 KASSERT((boundary & (boundary - 1)) == 0, 556 ("vm_phys_alloc_contig: boundary must be a power of 2")); 557 /* Compute the queue that is the best fit for npages. */ 558 for (order = 0; (1 << order) < npages; order++); 559 mtx_lock(&vm_page_queue_free_mtx); 560 for (flind = 0; flind < vm_nfreelists; flind++) { 561 for (oind = min(order, VM_NFREEORDER - 1); oind < VM_NFREEORDER; oind++) { 562 for (pind = 0; pind < VM_NFREEPOOL; pind++) { 563 fl = vm_phys_free_queues[flind][pind]; 564 TAILQ_FOREACH(m_ret, &fl[oind].pl, pageq) { 565 /* 566 * A free list may contain physical pages 567 * from one or more segments. 568 */ 569 seg = &vm_phys_segs[m_ret->segind]; 570 if (seg->start > high || 571 low >= seg->end) 572 continue; 573 574 /* 575 * Is the size of this allocation request 576 * larger than the largest block size? 577 */ 578 if (order >= VM_NFREEORDER) { 579 /* 580 * Determine if a sufficient number 581 * of subsequent blocks to satisfy 582 * the allocation request are free. 583 */ 584 pa = VM_PAGE_TO_PHYS(m_ret); 585 pa_last = pa + size; 586 for (;;) { 587 pa += 1 << (PAGE_SHIFT + VM_NFREEORDER - 1); 588 if (pa >= pa_last) 589 break; 590 if (pa < seg->start || 591 pa >= seg->end) 592 break; 593 m = &seg->first_page[atop(pa - seg->start)]; 594 if (m->order != VM_NFREEORDER - 1) 595 break; 596 } 597 /* If not, continue to the next block. */ 598 if (pa < pa_last) 599 continue; 600 } 601 602 /* 603 * Determine if the blocks are within the given range, 604 * satisfy the given alignment, and do not cross the 605 * given boundary. 606 */ 607 pa = VM_PAGE_TO_PHYS(m_ret); 608 if (pa >= low && 609 pa + size <= high && 610 (pa & (alignment - 1)) == 0 && 611 ((pa ^ (pa + size - 1)) & ~(boundary - 1)) == 0) 612 goto done; 613 } 614 } 615 } 616 } 617 mtx_unlock(&vm_page_queue_free_mtx); 618 return (NULL); 619 done: 620 for (m = m_ret; m < &m_ret[npages]; m = &m[1 << oind]) { 621 fl = (*seg->free_queues)[m->pool]; 622 TAILQ_REMOVE(&fl[m->order].pl, m, pageq); 623 fl[m->order].lcnt--; 624 m->order = VM_NFREEORDER; 625 } 626 if (m_ret->pool != VM_FREEPOOL_DEFAULT) 627 vm_phys_set_pool(VM_FREEPOOL_DEFAULT, m_ret, oind); 628 fl = (*seg->free_queues)[m_ret->pool]; 629 vm_phys_split_pages(m_ret, oind, fl, order); 630 cnt.v_free_count -= roundup2(npages, 1 << imin(oind, order)); 631 for (i = 0; i < npages; i++) { 632 m = &m_ret[i]; 633 KASSERT(m->queue == PQ_NONE, 634 ("vm_phys_alloc_contig: page %p has unexpected queue %d", 635 m, m->queue)); 636 m->valid = VM_PAGE_BITS_ALL; 637 if (m->flags & PG_ZERO) 638 vm_page_zero_count--; 639 /* Don't clear the PG_ZERO flag; we'll need it later. */ 640 m->flags = PG_UNMANAGED | (m->flags & PG_ZERO); 641 m->oflags = 0; 642 KASSERT(m->dirty == 0, 643 ("vm_phys_alloc_contig: page %p was dirty", m)); 644 m->wire_count = 0; 645 m->busy = 0; 646 } 647 for (; i < roundup2(npages, 1 << imin(oind, order)); i++) { 648 m = &m_ret[i]; 649 KASSERT(m->order == VM_NFREEORDER, 650 ("vm_phys_alloc_contig: page %p has unexpected order %d", 651 m, m->order)); 652 vm_phys_free_pages_locked(m, 0); 653 } 654 mtx_unlock(&vm_page_queue_free_mtx); 655 return (m_ret); 656 } 657 658 #ifdef DDB 659 /* 660 * Show the number of physical pages in each of the free lists. 661 */ 662 DB_SHOW_COMMAND(freepages, db_show_freepages) 663 { 664 struct vm_freelist *fl; 665 int flind, oind, pind; 666 667 for (flind = 0; flind < vm_nfreelists; flind++) { 668 db_printf("FREE LIST %d:\n" 669 "\n ORDER (SIZE) | NUMBER" 670 "\n ", flind); 671 for (pind = 0; pind < VM_NFREEPOOL; pind++) 672 db_printf(" | POOL %d", pind); 673 db_printf("\n-- "); 674 for (pind = 0; pind < VM_NFREEPOOL; pind++) 675 db_printf("-- -- "); 676 db_printf("--\n"); 677 for (oind = VM_NFREEORDER - 1; oind >= 0; oind--) { 678 db_printf(" %2.2d (%6.6dK)", oind, 679 1 << (PAGE_SHIFT - 10 + oind)); 680 for (pind = 0; pind < VM_NFREEPOOL; pind++) { 681 fl = vm_phys_free_queues[flind][pind]; 682 db_printf(" | %6.6d", fl[oind].lcnt); 683 } 684 db_printf("\n"); 685 } 686 db_printf("\n"); 687 } 688 } 689 #endif 690