1 /*- 2 * SPDX-License-Identifier: BSD-2-Clause 3 * 4 * Copyright (c) 2002-2006 Rice University 5 * Copyright (c) 2007 Alan L. Cox <alc@cs.rice.edu> 6 * All rights reserved. 7 * 8 * This software was developed for the FreeBSD Project by Alan L. Cox, 9 * Olivier Crameri, Peter Druschel, Sitaram Iyer, and Juan Navarro. 10 * 11 * Redistribution and use in source and binary forms, with or without 12 * modification, are permitted provided that the following conditions 13 * are met: 14 * 1. Redistributions of source code must retain the above copyright 15 * notice, this list of conditions and the following disclaimer. 16 * 2. Redistributions in binary form must reproduce the above copyright 17 * notice, this list of conditions and the following disclaimer in the 18 * documentation and/or other materials provided with the distribution. 19 * 20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 21 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 22 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 23 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 24 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 25 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 26 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS 27 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 28 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY 30 * WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 31 * POSSIBILITY OF SUCH DAMAGE. 32 */ 33 34 /* 35 * Physical memory system implementation 36 * 37 * Any external functions defined by this module are only to be used by the 38 * virtual memory system. 39 */ 40 41 #include <sys/cdefs.h> 42 #include "opt_ddb.h" 43 #include "opt_vm.h" 44 45 #include <sys/param.h> 46 #include <sys/systm.h> 47 #include <sys/domainset.h> 48 #include <sys/lock.h> 49 #include <sys/kernel.h> 50 #include <sys/kthread.h> 51 #include <sys/malloc.h> 52 #include <sys/mutex.h> 53 #include <sys/proc.h> 54 #include <sys/queue.h> 55 #include <sys/rwlock.h> 56 #include <sys/sbuf.h> 57 #include <sys/sched.h> 58 #include <sys/sysctl.h> 59 #include <sys/tree.h> 60 #include <sys/tslog.h> 61 #include <sys/unistd.h> 62 #include <sys/vmmeter.h> 63 64 #include <ddb/ddb.h> 65 66 #include <vm/vm.h> 67 #include <vm/vm_extern.h> 68 #include <vm/vm_param.h> 69 #include <vm/vm_kern.h> 70 #include <vm/vm_page.h> 71 #include <vm/vm_phys.h> 72 #include <vm/vm_pagequeue.h> 73 74 _Static_assert(sizeof(long) * NBBY >= VM_PHYSSEG_MAX, 75 "Too many physsegs."); 76 _Static_assert(sizeof(long long) >= sizeof(vm_paddr_t), 77 "vm_paddr_t too big for ffsll, flsll."); 78 79 #ifdef NUMA 80 struct mem_affinity __read_mostly *mem_affinity; 81 int __read_mostly *mem_locality; 82 83 static int numa_disabled; 84 static SYSCTL_NODE(_vm, OID_AUTO, numa, CTLFLAG_RD | CTLFLAG_MPSAFE, 0, 85 "NUMA options"); 86 SYSCTL_INT(_vm_numa, OID_AUTO, disabled, CTLFLAG_RDTUN | CTLFLAG_NOFETCH, 87 &numa_disabled, 0, "NUMA-awareness in the allocators is disabled"); 88 #endif 89 90 int __read_mostly vm_ndomains = 1; 91 domainset_t __read_mostly all_domains = DOMAINSET_T_INITIALIZER(0x1); 92 93 struct vm_phys_seg __read_mostly vm_phys_segs[VM_PHYSSEG_MAX]; 94 int __read_mostly vm_phys_nsegs; 95 static struct vm_phys_seg vm_phys_early_segs[8]; 96 static int vm_phys_early_nsegs; 97 98 struct vm_phys_fictitious_seg; 99 static int vm_phys_fictitious_cmp(struct vm_phys_fictitious_seg *, 100 struct vm_phys_fictitious_seg *); 101 102 RB_HEAD(fict_tree, vm_phys_fictitious_seg) vm_phys_fictitious_tree = 103 RB_INITIALIZER(&vm_phys_fictitious_tree); 104 105 struct vm_phys_fictitious_seg { 106 RB_ENTRY(vm_phys_fictitious_seg) node; 107 /* Memory region data */ 108 vm_paddr_t start; 109 vm_paddr_t end; 110 vm_page_t first_page; 111 vm_memattr_t memattr; 112 }; 113 114 RB_GENERATE_STATIC(fict_tree, vm_phys_fictitious_seg, node, 115 vm_phys_fictitious_cmp); 116 117 static struct rwlock_padalign vm_phys_fictitious_reg_lock; 118 MALLOC_DEFINE(M_FICT_PAGES, "vm_fictitious", "Fictitious VM pages"); 119 120 static struct vm_freelist __aligned(CACHE_LINE_SIZE) 121 vm_phys_free_queues[MAXMEMDOM][VM_NFREELIST][VM_NFREEPOOL] 122 [VM_NFREEORDER_MAX]; 123 124 static int __read_mostly vm_nfreelists; 125 126 /* 127 * These "avail lists" are globals used to communicate boot-time physical 128 * memory layout to other parts of the kernel. Each physically contiguous 129 * region of memory is defined by a start address at an even index and an 130 * end address at the following odd index. Each list is terminated by a 131 * pair of zero entries. 132 * 133 * dump_avail tells the dump code what regions to include in a crash dump, and 134 * phys_avail is all of the remaining physical memory that is available for 135 * the vm system. 136 * 137 * Initially dump_avail and phys_avail are identical. Boot time memory 138 * allocations remove extents from phys_avail that may still be included 139 * in dumps. 140 */ 141 vm_paddr_t phys_avail[PHYS_AVAIL_COUNT]; 142 vm_paddr_t dump_avail[PHYS_AVAIL_COUNT]; 143 144 /* 145 * Provides the mapping from VM_FREELIST_* to free list indices (flind). 146 */ 147 static int __read_mostly vm_freelist_to_flind[VM_NFREELIST]; 148 static int __read_mostly vm_default_freepool; 149 150 CTASSERT(VM_FREELIST_DEFAULT == 0); 151 152 #ifdef VM_FREELIST_DMA32 153 #define VM_DMA32_BOUNDARY ((vm_paddr_t)1 << 32) 154 #endif 155 156 /* 157 * Enforce the assumptions made by vm_phys_add_seg() and vm_phys_init() about 158 * the ordering of the free list boundaries. 159 */ 160 #if defined(VM_LOWMEM_BOUNDARY) && defined(VM_DMA32_BOUNDARY) 161 CTASSERT(VM_LOWMEM_BOUNDARY < VM_DMA32_BOUNDARY); 162 #endif 163 164 static int sysctl_vm_phys_free(SYSCTL_HANDLER_ARGS); 165 SYSCTL_OID(_vm, OID_AUTO, phys_free, 166 CTLTYPE_STRING | CTLFLAG_RD | CTLFLAG_MPSAFE, NULL, 0, 167 sysctl_vm_phys_free, "A", 168 "Phys Free Info"); 169 170 static int sysctl_vm_phys_segs(SYSCTL_HANDLER_ARGS); 171 SYSCTL_OID(_vm, OID_AUTO, phys_segs, 172 CTLTYPE_STRING | CTLFLAG_RD | CTLFLAG_MPSAFE, NULL, 0, 173 sysctl_vm_phys_segs, "A", 174 "Phys Seg Info"); 175 176 static int sysctl_vm_phys_fictitious_segs(SYSCTL_HANDLER_ARGS); 177 SYSCTL_OID(_vm, OID_AUTO, phys_fictitious_segs, 178 CTLTYPE_STRING | CTLFLAG_RD | CTLFLAG_MPSAFE, NULL, 0, 179 sysctl_vm_phys_fictitious_segs, "A", 180 "Fictitious Phys Seg Info"); 181 182 #ifdef NUMA 183 static int sysctl_vm_phys_locality(SYSCTL_HANDLER_ARGS); 184 SYSCTL_OID(_vm, OID_AUTO, phys_locality, 185 CTLTYPE_STRING | CTLFLAG_RD | CTLFLAG_MPSAFE, NULL, 0, 186 sysctl_vm_phys_locality, "A", 187 "Phys Locality Info"); 188 #endif 189 190 SYSCTL_INT(_vm, OID_AUTO, ndomains, CTLFLAG_RD, 191 &vm_ndomains, 0, "Number of physical memory domains available."); 192 193 static void _vm_phys_create_seg(vm_paddr_t start, vm_paddr_t end, int domain); 194 static void vm_phys_create_seg(vm_paddr_t start, vm_paddr_t end); 195 static void vm_phys_split_pages(vm_page_t m, int oind, struct vm_freelist *fl, 196 int order, int pool, int tail); 197 198 static bool __diagused 199 vm_phys_pool_valid(int pool) 200 { 201 #ifdef VM_FREEPOOL_LAZYINIT 202 if (pool == VM_FREEPOOL_LAZYINIT) 203 return (false); 204 #endif 205 return (pool >= 0 && pool < VM_NFREEPOOL); 206 } 207 208 /* 209 * Red-black tree helpers for vm fictitious range management. 210 */ 211 static inline int 212 vm_phys_fictitious_in_range(struct vm_phys_fictitious_seg *p, 213 struct vm_phys_fictitious_seg *range) 214 { 215 if (p->start >= range->end) 216 return (1); 217 if (p->start < range->start) 218 return (-1); 219 220 return (0); 221 } 222 223 static int 224 vm_phys_fictitious_cmp(struct vm_phys_fictitious_seg *p1, 225 struct vm_phys_fictitious_seg *p2) 226 { 227 228 /* Check if this is a search for a page */ 229 if (p1->end == 0) 230 return (vm_phys_fictitious_in_range(p1, p2)); 231 232 KASSERT(p2->end != 0, 233 ("Invalid range passed as second parameter to vm fictitious comparison")); 234 235 /* Searching to add a new range */ 236 if (p1->end <= p2->start) 237 return (-1); 238 if (p1->start >= p2->end) 239 return (1); 240 241 panic("Trying to add overlapping vm fictitious ranges:\n" 242 "[%#jx:%#jx] and [%#jx:%#jx]", (uintmax_t)p1->start, 243 (uintmax_t)p1->end, (uintmax_t)p2->start, (uintmax_t)p2->end); 244 } 245 246 int 247 vm_phys_domain_match(int prefer __numa_used, vm_paddr_t low __numa_used, 248 vm_paddr_t high __numa_used) 249 { 250 #ifdef NUMA 251 domainset_t mask; 252 int i; 253 254 if (vm_ndomains == 1 || mem_affinity == NULL) 255 return (0); 256 257 DOMAINSET_ZERO(&mask); 258 /* 259 * Check for any memory that overlaps low, high. 260 */ 261 for (i = 0; mem_affinity[i].end != 0; i++) 262 if (mem_affinity[i].start <= high && 263 mem_affinity[i].end >= low) 264 DOMAINSET_SET(mem_affinity[i].domain, &mask); 265 if (prefer != -1 && DOMAINSET_ISSET(prefer, &mask)) 266 return (prefer); 267 if (DOMAINSET_EMPTY(&mask)) 268 panic("vm_phys_domain_match: Impossible constraint"); 269 return (DOMAINSET_FFS(&mask) - 1); 270 #else 271 return (0); 272 #endif 273 } 274 275 /* 276 * Outputs the state of the physical memory allocator, specifically, 277 * the amount of physical memory in each free list. 278 */ 279 static int 280 sysctl_vm_phys_free(SYSCTL_HANDLER_ARGS) 281 { 282 struct sbuf sbuf; 283 struct vm_freelist *fl; 284 int dom, error, flind, oind, pind; 285 286 error = sysctl_wire_old_buffer(req, 0); 287 if (error != 0) 288 return (error); 289 sbuf_new_for_sysctl(&sbuf, NULL, 128 * vm_ndomains, req); 290 for (dom = 0; dom < vm_ndomains; dom++) { 291 sbuf_printf(&sbuf,"\nDOMAIN %d:\n", dom); 292 for (flind = 0; flind < vm_nfreelists; flind++) { 293 sbuf_printf(&sbuf, "\nFREE LIST %d:\n" 294 "\n ORDER (SIZE) | NUMBER" 295 "\n ", flind); 296 for (pind = 0; pind < VM_NFREEPOOL; pind++) 297 sbuf_printf(&sbuf, " | POOL %d", pind); 298 sbuf_printf(&sbuf, "\n-- "); 299 for (pind = 0; pind < VM_NFREEPOOL; pind++) 300 sbuf_printf(&sbuf, "-- -- "); 301 sbuf_printf(&sbuf, "--\n"); 302 for (oind = VM_NFREEORDER - 1; oind >= 0; oind--) { 303 sbuf_printf(&sbuf, " %2d (%6dK)", oind, 304 1 << (PAGE_SHIFT - 10 + oind)); 305 for (pind = 0; pind < VM_NFREEPOOL; pind++) { 306 fl = vm_phys_free_queues[dom][flind][pind]; 307 sbuf_printf(&sbuf, " | %6d", 308 fl[oind].lcnt); 309 } 310 sbuf_printf(&sbuf, "\n"); 311 } 312 } 313 } 314 error = sbuf_finish(&sbuf); 315 sbuf_delete(&sbuf); 316 return (error); 317 } 318 319 /* 320 * Outputs the set of physical memory segments. 321 */ 322 static int 323 sysctl_vm_phys_segs(SYSCTL_HANDLER_ARGS) 324 { 325 struct sbuf sbuf; 326 struct vm_phys_seg *seg; 327 int error, segind; 328 329 error = sysctl_wire_old_buffer(req, 0); 330 if (error != 0) 331 return (error); 332 sbuf_new_for_sysctl(&sbuf, NULL, 128, req); 333 for (segind = 0; segind < vm_phys_nsegs; segind++) { 334 sbuf_printf(&sbuf, "\nSEGMENT %d:\n\n", segind); 335 seg = &vm_phys_segs[segind]; 336 sbuf_printf(&sbuf, "start: %#jx\n", 337 (uintmax_t)seg->start); 338 sbuf_printf(&sbuf, "end: %#jx\n", 339 (uintmax_t)seg->end); 340 sbuf_printf(&sbuf, "domain: %d\n", seg->domain); 341 sbuf_printf(&sbuf, "free list: %p\n", seg->free_queues); 342 } 343 error = sbuf_finish(&sbuf); 344 sbuf_delete(&sbuf); 345 return (error); 346 } 347 348 static int 349 sysctl_vm_phys_fictitious_segs(SYSCTL_HANDLER_ARGS) 350 { 351 struct sbuf sbuf; 352 struct vm_phys_fictitious_seg *seg; 353 int error; 354 355 error = sysctl_wire_old_buffer(req, 0); 356 if (error != 0) 357 return (error); 358 sbuf_new_for_sysctl(&sbuf, NULL, 128, req); 359 rw_rlock(&vm_phys_fictitious_reg_lock); 360 RB_FOREACH(seg, fict_tree, &vm_phys_fictitious_tree) { 361 const char *name; 362 char buf[8]; 363 364 sbuf_printf(&sbuf, "\nstart: %#jx\n", 365 (uintmax_t)seg->start); 366 sbuf_printf(&sbuf, "end: %#jx\n", 367 (uintmax_t)seg->end); 368 name = vm_memattr_name(seg->memattr); 369 if (name == NULL) { 370 (void)snprintf(buf, sizeof(buf), "0x%02x", seg->memattr); 371 name = buf; 372 } 373 sbuf_printf(&sbuf, "attr: %s\n", name); 374 } 375 rw_runlock(&vm_phys_fictitious_reg_lock); 376 error = sbuf_finish(&sbuf); 377 sbuf_delete(&sbuf); 378 return (error); 379 } 380 381 /* 382 * Return affinity, or -1 if there's no affinity information. 383 */ 384 int 385 vm_phys_mem_affinity(int f __numa_used, int t __numa_used) 386 { 387 388 #ifdef NUMA 389 if (mem_locality == NULL) 390 return (-1); 391 if (f >= vm_ndomains || t >= vm_ndomains) 392 return (-1); 393 return (mem_locality[f * vm_ndomains + t]); 394 #else 395 return (-1); 396 #endif 397 } 398 399 #ifdef NUMA 400 /* 401 * Outputs the VM locality table. 402 */ 403 static int 404 sysctl_vm_phys_locality(SYSCTL_HANDLER_ARGS) 405 { 406 struct sbuf sbuf; 407 int error, i, j; 408 409 error = sysctl_wire_old_buffer(req, 0); 410 if (error != 0) 411 return (error); 412 sbuf_new_for_sysctl(&sbuf, NULL, 128, req); 413 414 sbuf_printf(&sbuf, "\n"); 415 416 for (i = 0; i < vm_ndomains; i++) { 417 sbuf_printf(&sbuf, "%d: ", i); 418 for (j = 0; j < vm_ndomains; j++) { 419 sbuf_printf(&sbuf, "%d ", vm_phys_mem_affinity(i, j)); 420 } 421 sbuf_printf(&sbuf, "\n"); 422 } 423 error = sbuf_finish(&sbuf); 424 sbuf_delete(&sbuf); 425 return (error); 426 } 427 #endif 428 429 static void 430 vm_freelist_add(struct vm_freelist *fl, vm_page_t m, int order, int pool, 431 int tail) 432 { 433 /* 434 * The paging queues and the free page lists utilize the same field, 435 * plinks.q, within the vm_page structure. When a physical page is 436 * freed, it is lazily removed from the paging queues to reduce the 437 * cost of removal through batching. Here, we must ensure that any 438 * deferred dequeue on the physical page has completed before using 439 * its plinks.q field. 440 */ 441 if (__predict_false(vm_page_astate_load(m).queue != PQ_NONE)) 442 vm_page_dequeue(m); 443 444 m->order = order; 445 m->pool = pool; 446 if (tail) 447 TAILQ_INSERT_TAIL(&fl[order].pl, m, plinks.q); 448 else 449 TAILQ_INSERT_HEAD(&fl[order].pl, m, plinks.q); 450 fl[order].lcnt++; 451 } 452 453 static void 454 vm_freelist_rem(struct vm_freelist *fl, vm_page_t m, int order) 455 { 456 457 TAILQ_REMOVE(&fl[order].pl, m, plinks.q); 458 fl[order].lcnt--; 459 m->order = VM_NFREEORDER; 460 } 461 462 /* 463 * Create a physical memory segment. 464 */ 465 static void 466 _vm_phys_create_seg(vm_paddr_t start, vm_paddr_t end, int domain) 467 { 468 struct vm_phys_seg *seg; 469 470 if (!(0 <= domain && domain < vm_ndomains)) 471 panic("%s: Invalid domain %d ('vm_ndomains' is %d)", 472 __func__, domain, vm_ndomains); 473 if (vm_phys_nsegs >= VM_PHYSSEG_MAX) 474 panic("Not enough storage for physical segments, " 475 "increase VM_PHYSSEG_MAX"); 476 477 seg = &vm_phys_segs[vm_phys_nsegs++]; 478 while (seg > vm_phys_segs && seg[-1].start >= end) { 479 *seg = *(seg - 1); 480 seg--; 481 } 482 seg->start = start; 483 seg->end = end; 484 seg->domain = domain; 485 if (seg != vm_phys_segs && seg[-1].end > start) 486 panic("Overlapping physical segments: Current [%#jx,%#jx) " 487 "at index %zu, previous [%#jx,%#jx)", 488 (uintmax_t)start, (uintmax_t)end, seg - vm_phys_segs, 489 (uintmax_t)seg[-1].start, (uintmax_t)seg[-1].end); 490 } 491 492 static void 493 vm_phys_create_seg(vm_paddr_t start, vm_paddr_t end) 494 { 495 #ifdef NUMA 496 int i; 497 498 if (mem_affinity == NULL) { 499 _vm_phys_create_seg(start, end, 0); 500 return; 501 } 502 503 for (i = 0;; i++) { 504 if (mem_affinity[i].end == 0) 505 panic("Reached end of affinity info"); 506 if (mem_affinity[i].end <= start) 507 continue; 508 if (mem_affinity[i].start > start) 509 panic("No affinity info for start %jx", 510 (uintmax_t)start); 511 if (mem_affinity[i].end >= end) { 512 _vm_phys_create_seg(start, end, 513 mem_affinity[i].domain); 514 break; 515 } 516 _vm_phys_create_seg(start, mem_affinity[i].end, 517 mem_affinity[i].domain); 518 start = mem_affinity[i].end; 519 } 520 #else 521 _vm_phys_create_seg(start, end, 0); 522 #endif 523 } 524 525 /* 526 * Add a physical memory segment. 527 */ 528 void 529 vm_phys_add_seg(vm_paddr_t start, vm_paddr_t end) 530 { 531 vm_paddr_t paddr; 532 533 if ((start & PAGE_MASK) != 0) 534 panic("%s: start (%jx) is not page aligned", __func__, 535 (uintmax_t)start); 536 if ((end & PAGE_MASK) != 0) 537 panic("%s: end (%jx) is not page aligned", __func__, 538 (uintmax_t)end); 539 if (start > end) 540 panic("%s: start (%jx) > end (%jx)!", __func__, 541 (uintmax_t)start, (uintmax_t)end); 542 543 if (start == end) 544 return; 545 546 /* 547 * Split the physical memory segment if it spans two or more free 548 * list boundaries. 549 */ 550 paddr = start; 551 #ifdef VM_FREELIST_LOWMEM 552 if (paddr < VM_LOWMEM_BOUNDARY && end > VM_LOWMEM_BOUNDARY) { 553 vm_phys_create_seg(paddr, VM_LOWMEM_BOUNDARY); 554 paddr = VM_LOWMEM_BOUNDARY; 555 } 556 #endif 557 #ifdef VM_FREELIST_DMA32 558 if (paddr < VM_DMA32_BOUNDARY && end > VM_DMA32_BOUNDARY) { 559 vm_phys_create_seg(paddr, VM_DMA32_BOUNDARY); 560 paddr = VM_DMA32_BOUNDARY; 561 } 562 #endif 563 vm_phys_create_seg(paddr, end); 564 } 565 566 /* 567 * Initialize the physical memory allocator. 568 * 569 * Requires that vm_page_array is initialized! 570 */ 571 void 572 vm_phys_init(void) 573 { 574 struct vm_freelist *fl; 575 struct vm_phys_seg *end_seg, *prev_seg, *seg, *tmp_seg; 576 #if defined(VM_DMA32_NPAGES_THRESHOLD) || defined(VM_PHYSSEG_SPARSE) 577 u_long npages; 578 #endif 579 int dom, flind, freelist, oind, pind, segind; 580 581 /* 582 * Compute the number of free lists, and generate the mapping from the 583 * manifest constants VM_FREELIST_* to the free list indices. 584 * 585 * Initially, the entries of vm_freelist_to_flind[] are set to either 586 * 0 or 1 to indicate which free lists should be created. 587 */ 588 #ifdef VM_DMA32_NPAGES_THRESHOLD 589 npages = 0; 590 #endif 591 for (segind = vm_phys_nsegs - 1; segind >= 0; segind--) { 592 seg = &vm_phys_segs[segind]; 593 #ifdef VM_FREELIST_LOWMEM 594 if (seg->end <= VM_LOWMEM_BOUNDARY) 595 vm_freelist_to_flind[VM_FREELIST_LOWMEM] = 1; 596 else 597 #endif 598 #ifdef VM_FREELIST_DMA32 599 if ( 600 #ifdef VM_DMA32_NPAGES_THRESHOLD 601 /* 602 * Create the DMA32 free list only if the amount of 603 * physical memory above physical address 4G exceeds the 604 * given threshold. 605 */ 606 npages > VM_DMA32_NPAGES_THRESHOLD && 607 #endif 608 seg->end <= VM_DMA32_BOUNDARY) 609 vm_freelist_to_flind[VM_FREELIST_DMA32] = 1; 610 else 611 #endif 612 { 613 #ifdef VM_DMA32_NPAGES_THRESHOLD 614 npages += atop(seg->end - seg->start); 615 #endif 616 vm_freelist_to_flind[VM_FREELIST_DEFAULT] = 1; 617 } 618 } 619 /* Change each entry into a running total of the free lists. */ 620 for (freelist = 1; freelist < VM_NFREELIST; freelist++) { 621 vm_freelist_to_flind[freelist] += 622 vm_freelist_to_flind[freelist - 1]; 623 } 624 vm_nfreelists = vm_freelist_to_flind[VM_NFREELIST - 1]; 625 KASSERT(vm_nfreelists > 0, ("vm_phys_init: no free lists")); 626 /* Change each entry into a free list index. */ 627 for (freelist = 0; freelist < VM_NFREELIST; freelist++) 628 vm_freelist_to_flind[freelist]--; 629 630 /* 631 * Initialize the first_page and free_queues fields of each physical 632 * memory segment. 633 */ 634 #ifdef VM_PHYSSEG_SPARSE 635 npages = 0; 636 #endif 637 for (segind = 0; segind < vm_phys_nsegs; segind++) { 638 seg = &vm_phys_segs[segind]; 639 #ifdef VM_PHYSSEG_SPARSE 640 seg->first_page = &vm_page_array[npages]; 641 npages += atop(seg->end - seg->start); 642 #else 643 seg->first_page = PHYS_TO_VM_PAGE(seg->start); 644 #endif 645 #ifdef VM_FREELIST_LOWMEM 646 if (seg->end <= VM_LOWMEM_BOUNDARY) { 647 flind = vm_freelist_to_flind[VM_FREELIST_LOWMEM]; 648 KASSERT(flind >= 0, 649 ("vm_phys_init: LOWMEM flind < 0")); 650 } else 651 #endif 652 #ifdef VM_FREELIST_DMA32 653 if (seg->end <= VM_DMA32_BOUNDARY) { 654 flind = vm_freelist_to_flind[VM_FREELIST_DMA32]; 655 KASSERT(flind >= 0, 656 ("vm_phys_init: DMA32 flind < 0")); 657 } else 658 #endif 659 { 660 flind = vm_freelist_to_flind[VM_FREELIST_DEFAULT]; 661 KASSERT(flind >= 0, 662 ("vm_phys_init: DEFAULT flind < 0")); 663 } 664 seg->free_queues = &vm_phys_free_queues[seg->domain][flind]; 665 } 666 667 /* 668 * Coalesce physical memory segments that are contiguous and share the 669 * same per-domain free queues. 670 */ 671 prev_seg = vm_phys_segs; 672 seg = &vm_phys_segs[1]; 673 end_seg = &vm_phys_segs[vm_phys_nsegs]; 674 while (seg < end_seg) { 675 if (prev_seg->end == seg->start && 676 prev_seg->free_queues == seg->free_queues) { 677 prev_seg->end = seg->end; 678 KASSERT(prev_seg->domain == seg->domain, 679 ("vm_phys_init: free queues cannot span domains")); 680 vm_phys_nsegs--; 681 end_seg--; 682 for (tmp_seg = seg; tmp_seg < end_seg; tmp_seg++) 683 *tmp_seg = *(tmp_seg + 1); 684 } else { 685 prev_seg = seg; 686 seg++; 687 } 688 } 689 690 /* 691 * Initialize the free queues. 692 */ 693 for (dom = 0; dom < vm_ndomains; dom++) { 694 for (flind = 0; flind < vm_nfreelists; flind++) { 695 for (pind = 0; pind < VM_NFREEPOOL; pind++) { 696 fl = vm_phys_free_queues[dom][flind][pind]; 697 for (oind = 0; oind < VM_NFREEORDER; oind++) 698 TAILQ_INIT(&fl[oind].pl); 699 } 700 } 701 } 702 703 #ifdef VM_FREEPOOL_LAZYINIT 704 vm_default_freepool = VM_FREEPOOL_LAZYINIT; 705 #else 706 vm_default_freepool = VM_FREEPOOL_DEFAULT; 707 #endif 708 709 rw_init(&vm_phys_fictitious_reg_lock, "vmfctr"); 710 } 711 712 /* 713 * Register info about the NUMA topology of the system. 714 * 715 * Invoked by platform-dependent code prior to vm_phys_init(). 716 */ 717 void 718 vm_phys_register_domains(int ndomains __numa_used, 719 struct mem_affinity *affinity __numa_used, int *locality __numa_used) 720 { 721 #ifdef NUMA 722 int i; 723 724 /* 725 * For now the only override value that we support is 1, which 726 * effectively disables NUMA-awareness in the allocators. 727 */ 728 TUNABLE_INT_FETCH("vm.numa.disabled", &numa_disabled); 729 if (numa_disabled) 730 ndomains = 1; 731 732 if (ndomains > 1) { 733 vm_ndomains = ndomains; 734 mem_affinity = affinity; 735 mem_locality = locality; 736 } 737 738 for (i = 0; i < vm_ndomains; i++) 739 DOMAINSET_SET(i, &all_domains); 740 #endif 741 } 742 743 /* 744 * Split a contiguous, power of two-sized set of physical pages. 745 * 746 * When this function is called by a page allocation function, the caller 747 * should request insertion at the head unless the order [order, oind) queues 748 * are known to be empty. The objective being to reduce the likelihood of 749 * long-term fragmentation by promoting contemporaneous allocation and 750 * (hopefully) deallocation. 751 */ 752 static __inline void 753 vm_phys_split_pages(vm_page_t m, int oind, struct vm_freelist *fl, int order, 754 int pool, int tail) 755 { 756 vm_page_t m_buddy; 757 758 while (oind > order) { 759 oind--; 760 m_buddy = &m[1 << oind]; 761 KASSERT(m_buddy->order == VM_NFREEORDER, 762 ("vm_phys_split_pages: page %p has unexpected order %d", 763 m_buddy, m_buddy->order)); 764 vm_freelist_add(fl, m_buddy, oind, pool, tail); 765 } 766 } 767 768 static void 769 vm_phys_enq_chunk(struct vm_freelist *fl, vm_page_t m, int order, int pool, 770 int tail) 771 { 772 KASSERT(order >= 0 && order < VM_NFREEORDER, 773 ("%s: invalid order %d", __func__, order)); 774 775 vm_freelist_add(fl, m, order, pool, tail); 776 #ifdef VM_FREEPOOL_LAZYINIT 777 if (__predict_false(pool == VM_FREEPOOL_LAZYINIT)) { 778 vm_page_t m_next; 779 vm_paddr_t pa; 780 int npages; 781 782 npages = 1 << order; 783 m_next = m + npages; 784 pa = m->phys_addr + ptoa(npages); 785 if (pa < vm_phys_segs[m->segind].end) { 786 vm_page_init_page(m_next, pa, m->segind, 787 VM_FREEPOOL_LAZYINIT); 788 } 789 } 790 #endif 791 } 792 793 /* 794 * Add the physical pages [m, m + npages) at the beginning of a power-of-two 795 * aligned and sized set to the specified free list. 796 * 797 * When this function is called by a page allocation function, the caller 798 * should request insertion at the head unless the lower-order queues are 799 * known to be empty. The objective being to reduce the likelihood of long- 800 * term fragmentation by promoting contemporaneous allocation and (hopefully) 801 * deallocation. 802 * 803 * The physical page m's buddy must not be free. 804 */ 805 static void 806 vm_phys_enq_beg(vm_page_t m, u_int npages, struct vm_freelist *fl, int pool, 807 int tail) 808 { 809 int order; 810 811 KASSERT(npages == 0 || 812 (VM_PAGE_TO_PHYS(m) & 813 ((PAGE_SIZE << ilog2(npages)) - 1)) == 0, 814 ("%s: page %p and npages %u are misaligned", 815 __func__, m, npages)); 816 while (npages > 0) { 817 KASSERT(m->order == VM_NFREEORDER, 818 ("%s: page %p has unexpected order %d", 819 __func__, m, m->order)); 820 order = ilog2(npages); 821 KASSERT(order < VM_NFREEORDER, 822 ("%s: order %d is out of range", __func__, order)); 823 vm_phys_enq_chunk(fl, m, order, pool, tail); 824 m += 1 << order; 825 npages -= 1 << order; 826 } 827 } 828 829 /* 830 * Add the physical pages [m, m + npages) at the end of a power-of-two aligned 831 * and sized set to the specified free list. 832 * 833 * When this function is called by a page allocation function, the caller 834 * should request insertion at the head unless the lower-order queues are 835 * known to be empty. The objective being to reduce the likelihood of long- 836 * term fragmentation by promoting contemporaneous allocation and (hopefully) 837 * deallocation. 838 * 839 * If npages is zero, this function does nothing and ignores the physical page 840 * parameter m. Otherwise, the physical page m's buddy must not be free. 841 */ 842 static vm_page_t 843 vm_phys_enq_range(vm_page_t m, u_int npages, struct vm_freelist *fl, int pool, 844 int tail) 845 { 846 int order; 847 848 KASSERT(npages == 0 || 849 ((VM_PAGE_TO_PHYS(m) + npages * PAGE_SIZE) & 850 ((PAGE_SIZE << ilog2(npages)) - 1)) == 0, 851 ("vm_phys_enq_range: page %p and npages %u are misaligned", 852 m, npages)); 853 while (npages > 0) { 854 KASSERT(m->order == VM_NFREEORDER, 855 ("vm_phys_enq_range: page %p has unexpected order %d", 856 m, m->order)); 857 order = ffs(npages) - 1; 858 vm_phys_enq_chunk(fl, m, order, pool, tail); 859 m += 1 << order; 860 npages -= 1 << order; 861 } 862 return (m); 863 } 864 865 /* 866 * Complete initialization a contiguous, power of two-sized set of physical 867 * pages. 868 * 869 * If the pages currently belong to the lazy init pool, then the corresponding 870 * page structures must be initialized. In this case it is assumed that the 871 * first page in the run has already been initialized. 872 */ 873 static void 874 vm_phys_finish_init(vm_page_t m, int order) 875 { 876 #ifdef VM_FREEPOOL_LAZYINIT 877 if (__predict_false(m->pool == VM_FREEPOOL_LAZYINIT)) { 878 vm_paddr_t pa; 879 int segind; 880 881 TSENTER(); 882 pa = m->phys_addr + PAGE_SIZE; 883 segind = m->segind; 884 for (vm_page_t m_tmp = m + 1; m_tmp < &m[1 << order]; 885 m_tmp++, pa += PAGE_SIZE) 886 vm_page_init_page(m_tmp, pa, segind, VM_NFREEPOOL); 887 TSEXIT(); 888 } 889 #endif 890 } 891 892 /* 893 * Tries to allocate the specified number of pages from the specified pool 894 * within the specified domain. Returns the actual number of allocated pages 895 * and a pointer to each page through the array ma[]. 896 * 897 * The returned pages may not be physically contiguous. However, in contrast 898 * to performing multiple, back-to-back calls to vm_phys_alloc_pages(..., 0), 899 * calling this function once to allocate the desired number of pages will 900 * avoid wasted time in vm_phys_split_pages(). The allocated pages have no 901 * valid pool field set. 902 * 903 * The free page queues for the specified domain must be locked. 904 */ 905 int 906 vm_phys_alloc_npages(int domain, int pool, int npages, vm_page_t ma[]) 907 { 908 struct vm_freelist *alt, *fl; 909 vm_page_t m; 910 int avail, end, flind, freelist, i, oind, pind; 911 912 KASSERT(domain >= 0 && domain < vm_ndomains, 913 ("vm_phys_alloc_npages: domain %d is out of range", domain)); 914 KASSERT(vm_phys_pool_valid(pool), 915 ("vm_phys_alloc_npages: pool %d is out of range", pool)); 916 KASSERT(npages <= 1 << (VM_NFREEORDER - 1), 917 ("vm_phys_alloc_npages: npages %d is out of range", npages)); 918 vm_domain_free_assert_locked(VM_DOMAIN(domain)); 919 i = 0; 920 for (freelist = 0; freelist < VM_NFREELIST; freelist++) { 921 flind = vm_freelist_to_flind[freelist]; 922 if (flind < 0) 923 continue; 924 fl = vm_phys_free_queues[domain][flind][pool]; 925 for (oind = 0; oind < VM_NFREEORDER; oind++) { 926 while ((m = TAILQ_FIRST(&fl[oind].pl)) != NULL) { 927 vm_freelist_rem(fl, m, oind); 928 avail = i + (1 << oind); 929 end = imin(npages, avail); 930 while (i < end) 931 ma[i++] = m++; 932 if (i == npages) { 933 /* 934 * Return excess pages to fl. Its order 935 * [0, oind) queues are empty. 936 */ 937 vm_phys_enq_range(m, avail - i, fl, 938 pool, 1); 939 return (npages); 940 } 941 } 942 } 943 for (oind = VM_NFREEORDER - 1; oind >= 0; oind--) { 944 for (pind = vm_default_freepool; pind < VM_NFREEPOOL; 945 pind++) { 946 alt = vm_phys_free_queues[domain][flind][pind]; 947 while ((m = TAILQ_FIRST(&alt[oind].pl)) != 948 NULL) { 949 vm_freelist_rem(alt, m, oind); 950 vm_phys_finish_init(m, oind); 951 avail = i + (1 << oind); 952 end = imin(npages, avail); 953 while (i < end) 954 ma[i++] = m++; 955 if (i == npages) { 956 /* 957 * Return excess pages to fl. 958 * Its order [0, oind) queues 959 * are empty. 960 */ 961 vm_phys_enq_range(m, avail - i, 962 fl, pool, 1); 963 return (npages); 964 } 965 } 966 } 967 } 968 } 969 return (i); 970 } 971 972 /* 973 * Allocate a contiguous, power of two-sized set of physical pages from the 974 * specified free list. The free list must be specified using one of the 975 * manifest constants VM_FREELIST_*. 976 * 977 * The free page queues must be locked. 978 */ 979 static vm_page_t 980 vm_phys_alloc_freelist_pages(int domain, int freelist, int pool, int order) 981 { 982 struct vm_freelist *alt, *fl; 983 vm_page_t m; 984 int oind, pind, flind; 985 986 KASSERT(domain >= 0 && domain < vm_ndomains, 987 ("vm_phys_alloc_freelist_pages: domain %d is out of range", 988 domain)); 989 KASSERT(freelist < VM_NFREELIST, 990 ("vm_phys_alloc_freelist_pages: freelist %d is out of range", 991 freelist)); 992 KASSERT(vm_phys_pool_valid(pool), 993 ("vm_phys_alloc_freelist_pages: pool %d is out of range", pool)); 994 KASSERT(order < VM_NFREEORDER, 995 ("vm_phys_alloc_freelist_pages: order %d is out of range", order)); 996 997 flind = vm_freelist_to_flind[freelist]; 998 /* Check if freelist is present */ 999 if (flind < 0) 1000 return (NULL); 1001 1002 vm_domain_free_assert_locked(VM_DOMAIN(domain)); 1003 fl = &vm_phys_free_queues[domain][flind][pool][0]; 1004 for (oind = order; oind < VM_NFREEORDER; oind++) { 1005 m = TAILQ_FIRST(&fl[oind].pl); 1006 if (m != NULL) { 1007 vm_freelist_rem(fl, m, oind); 1008 /* The order [order, oind) queues are empty. */ 1009 vm_phys_split_pages(m, oind, fl, order, pool, 1); 1010 return (m); 1011 } 1012 } 1013 1014 /* 1015 * The given pool was empty. Find the largest 1016 * contiguous, power-of-two-sized set of pages in any 1017 * pool. Transfer these pages to the given pool, and 1018 * use them to satisfy the allocation. 1019 */ 1020 for (oind = VM_NFREEORDER - 1; oind >= order; oind--) { 1021 for (pind = vm_default_freepool; pind < VM_NFREEPOOL; pind++) { 1022 alt = &vm_phys_free_queues[domain][flind][pind][0]; 1023 m = TAILQ_FIRST(&alt[oind].pl); 1024 if (m != NULL) { 1025 vm_freelist_rem(alt, m, oind); 1026 vm_phys_finish_init(m, oind); 1027 /* The order [order, oind) queues are empty. */ 1028 vm_phys_split_pages(m, oind, fl, order, pool, 1); 1029 return (m); 1030 } 1031 } 1032 } 1033 return (NULL); 1034 } 1035 1036 /* 1037 * Allocate a contiguous, power of two-sized set of physical pages 1038 * from the free lists. 1039 * 1040 * The free page queues must be locked. 1041 */ 1042 vm_page_t 1043 vm_phys_alloc_pages(int domain, int pool, int order) 1044 { 1045 vm_page_t m; 1046 int freelist; 1047 1048 for (freelist = 0; freelist < VM_NFREELIST; freelist++) { 1049 m = vm_phys_alloc_freelist_pages(domain, freelist, pool, order); 1050 if (m != NULL) 1051 return (m); 1052 } 1053 return (NULL); 1054 } 1055 1056 /* 1057 * Find the vm_page corresponding to the given physical address, which must lie 1058 * within the given physical memory segment. 1059 */ 1060 vm_page_t 1061 vm_phys_seg_paddr_to_vm_page(struct vm_phys_seg *seg, vm_paddr_t pa) 1062 { 1063 KASSERT(pa >= seg->start && pa < seg->end, 1064 ("%s: pa %#jx is out of range", __func__, (uintmax_t)pa)); 1065 1066 return (&seg->first_page[atop(pa - seg->start)]); 1067 } 1068 1069 /* 1070 * Find the vm_page corresponding to the given physical address. 1071 */ 1072 vm_page_t 1073 vm_phys_paddr_to_vm_page(vm_paddr_t pa) 1074 { 1075 struct vm_phys_seg *seg; 1076 1077 if ((seg = vm_phys_paddr_to_seg(pa)) != NULL) 1078 return (vm_phys_seg_paddr_to_vm_page(seg, pa)); 1079 return (NULL); 1080 } 1081 1082 vm_page_t 1083 vm_phys_fictitious_to_vm_page(vm_paddr_t pa) 1084 { 1085 struct vm_phys_fictitious_seg tmp, *seg; 1086 vm_page_t m; 1087 1088 m = NULL; 1089 tmp.start = pa; 1090 tmp.end = 0; 1091 1092 rw_rlock(&vm_phys_fictitious_reg_lock); 1093 seg = RB_FIND(fict_tree, &vm_phys_fictitious_tree, &tmp); 1094 rw_runlock(&vm_phys_fictitious_reg_lock); 1095 if (seg == NULL) 1096 return (NULL); 1097 1098 m = &seg->first_page[atop(pa - seg->start)]; 1099 KASSERT((m->flags & PG_FICTITIOUS) != 0, ("%p not fictitious", m)); 1100 1101 return (m); 1102 } 1103 1104 static inline void 1105 vm_phys_fictitious_init_range(vm_page_t range, vm_paddr_t start, 1106 long page_count, vm_memattr_t memattr) 1107 { 1108 long i; 1109 1110 bzero(range, page_count * sizeof(*range)); 1111 for (i = 0; i < page_count; i++) { 1112 vm_page_initfake(&range[i], start + PAGE_SIZE * i, memattr); 1113 range[i].oflags &= ~VPO_UNMANAGED; 1114 range[i].busy_lock = VPB_UNBUSIED; 1115 } 1116 } 1117 1118 int 1119 vm_phys_fictitious_reg_range(vm_paddr_t start, vm_paddr_t end, 1120 vm_memattr_t memattr) 1121 { 1122 struct vm_phys_fictitious_seg *seg; 1123 vm_page_t fp; 1124 long page_count; 1125 #ifdef VM_PHYSSEG_DENSE 1126 long pi, pe; 1127 long dpage_count; 1128 #endif 1129 1130 KASSERT(start < end, 1131 ("Start of segment isn't less than end (start: %jx end: %jx)", 1132 (uintmax_t)start, (uintmax_t)end)); 1133 1134 page_count = (end - start) / PAGE_SIZE; 1135 1136 #ifdef VM_PHYSSEG_DENSE 1137 pi = atop(start); 1138 pe = atop(end); 1139 if (pi >= first_page && (pi - first_page) < vm_page_array_size) { 1140 fp = &vm_page_array[pi - first_page]; 1141 if ((pe - first_page) > vm_page_array_size) { 1142 /* 1143 * We have a segment that starts inside 1144 * of vm_page_array, but ends outside of it. 1145 * 1146 * Use vm_page_array pages for those that are 1147 * inside of the vm_page_array range, and 1148 * allocate the remaining ones. 1149 */ 1150 dpage_count = vm_page_array_size - (pi - first_page); 1151 vm_phys_fictitious_init_range(fp, start, dpage_count, 1152 memattr); 1153 page_count -= dpage_count; 1154 start += ptoa(dpage_count); 1155 goto alloc; 1156 } 1157 /* 1158 * We can allocate the full range from vm_page_array, 1159 * so there's no need to register the range in the tree. 1160 */ 1161 vm_phys_fictitious_init_range(fp, start, page_count, memattr); 1162 return (0); 1163 } else if (pe > first_page && (pe - first_page) < vm_page_array_size) { 1164 /* 1165 * We have a segment that ends inside of vm_page_array, 1166 * but starts outside of it. 1167 */ 1168 fp = &vm_page_array[0]; 1169 dpage_count = pe - first_page; 1170 vm_phys_fictitious_init_range(fp, ptoa(first_page), dpage_count, 1171 memattr); 1172 end -= ptoa(dpage_count); 1173 page_count -= dpage_count; 1174 goto alloc; 1175 } else if (pi < first_page && pe > (first_page + vm_page_array_size)) { 1176 /* 1177 * Trying to register a fictitious range that expands before 1178 * and after vm_page_array. 1179 */ 1180 return (EINVAL); 1181 } else { 1182 alloc: 1183 #endif 1184 fp = malloc(page_count * sizeof(struct vm_page), M_FICT_PAGES, 1185 M_WAITOK); 1186 #ifdef VM_PHYSSEG_DENSE 1187 } 1188 #endif 1189 vm_phys_fictitious_init_range(fp, start, page_count, memattr); 1190 1191 seg = malloc(sizeof(*seg), M_FICT_PAGES, M_WAITOK | M_ZERO); 1192 seg->start = start; 1193 seg->end = end; 1194 seg->first_page = fp; 1195 seg->memattr = memattr; 1196 1197 rw_wlock(&vm_phys_fictitious_reg_lock); 1198 RB_INSERT(fict_tree, &vm_phys_fictitious_tree, seg); 1199 rw_wunlock(&vm_phys_fictitious_reg_lock); 1200 1201 return (0); 1202 } 1203 1204 void 1205 vm_phys_fictitious_unreg_range(vm_paddr_t start, vm_paddr_t end) 1206 { 1207 struct vm_phys_fictitious_seg *seg, tmp; 1208 #ifdef VM_PHYSSEG_DENSE 1209 long pi, pe; 1210 #endif 1211 1212 KASSERT(start < end, 1213 ("Start of segment isn't less than end (start: %jx end: %jx)", 1214 (uintmax_t)start, (uintmax_t)end)); 1215 1216 #ifdef VM_PHYSSEG_DENSE 1217 pi = atop(start); 1218 pe = atop(end); 1219 if (pi >= first_page && (pi - first_page) < vm_page_array_size) { 1220 if ((pe - first_page) <= vm_page_array_size) { 1221 /* 1222 * This segment was allocated using vm_page_array 1223 * only, there's nothing to do since those pages 1224 * were never added to the tree. 1225 */ 1226 return; 1227 } 1228 /* 1229 * We have a segment that starts inside 1230 * of vm_page_array, but ends outside of it. 1231 * 1232 * Calculate how many pages were added to the 1233 * tree and free them. 1234 */ 1235 start = ptoa(first_page + vm_page_array_size); 1236 } else if (pe > first_page && (pe - first_page) < vm_page_array_size) { 1237 /* 1238 * We have a segment that ends inside of vm_page_array, 1239 * but starts outside of it. 1240 */ 1241 end = ptoa(first_page); 1242 } else if (pi < first_page && pe > (first_page + vm_page_array_size)) { 1243 /* Since it's not possible to register such a range, panic. */ 1244 panic( 1245 "Unregistering not registered fictitious range [%#jx:%#jx]", 1246 (uintmax_t)start, (uintmax_t)end); 1247 } 1248 #endif 1249 tmp.start = start; 1250 tmp.end = 0; 1251 1252 rw_wlock(&vm_phys_fictitious_reg_lock); 1253 seg = RB_FIND(fict_tree, &vm_phys_fictitious_tree, &tmp); 1254 if (seg == NULL || seg->start != start || seg->end != end) { 1255 rw_wunlock(&vm_phys_fictitious_reg_lock); 1256 panic( 1257 "Unregistering not registered fictitious range [%#jx:%#jx]", 1258 (uintmax_t)start, (uintmax_t)end); 1259 } 1260 RB_REMOVE(fict_tree, &vm_phys_fictitious_tree, seg); 1261 rw_wunlock(&vm_phys_fictitious_reg_lock); 1262 free(seg->first_page, M_FICT_PAGES); 1263 free(seg, M_FICT_PAGES); 1264 } 1265 1266 /* 1267 * Free a contiguous, power of two-sized set of physical pages. 1268 * The pool field in the first page determines the destination pool. 1269 * 1270 * The free page queues must be locked. 1271 */ 1272 void 1273 vm_phys_free_pages(vm_page_t m, int pool, int order) 1274 { 1275 struct vm_freelist *fl; 1276 struct vm_phys_seg *seg; 1277 vm_paddr_t pa; 1278 vm_page_t m_buddy; 1279 1280 KASSERT(m->order == VM_NFREEORDER, 1281 ("%s: page %p has unexpected order %d", 1282 __func__, m, m->order)); 1283 KASSERT(vm_phys_pool_valid(pool), 1284 ("%s: unexpected pool param %d", __func__, pool)); 1285 KASSERT(order < VM_NFREEORDER, 1286 ("%s: order %d is out of range", __func__, order)); 1287 seg = &vm_phys_segs[m->segind]; 1288 vm_domain_free_assert_locked(VM_DOMAIN(seg->domain)); 1289 if (order < VM_NFREEORDER - 1) { 1290 pa = VM_PAGE_TO_PHYS(m); 1291 do { 1292 pa ^= ((vm_paddr_t)1 << (PAGE_SHIFT + order)); 1293 if (pa < seg->start || pa >= seg->end) 1294 break; 1295 m_buddy = vm_phys_seg_paddr_to_vm_page(seg, pa); 1296 if (m_buddy->order != order) 1297 break; 1298 fl = (*seg->free_queues)[m_buddy->pool]; 1299 vm_freelist_rem(fl, m_buddy, order); 1300 vm_phys_finish_init(m_buddy, order); 1301 order++; 1302 pa &= ~(((vm_paddr_t)1 << (PAGE_SHIFT + order)) - 1); 1303 m = vm_phys_seg_paddr_to_vm_page(seg, pa); 1304 } while (order < VM_NFREEORDER - 1); 1305 } 1306 fl = (*seg->free_queues)[pool]; 1307 vm_freelist_add(fl, m, order, pool, 1); 1308 } 1309 1310 #ifdef VM_FREEPOOL_LAZYINIT 1311 /* 1312 * Initialize all pages lingering in the lazy init pool of a NUMA domain, moving 1313 * them to the default pool. This is a prerequisite for some rare operations 1314 * which need to scan the page array and thus depend on all pages being 1315 * initialized. 1316 */ 1317 static void 1318 vm_phys_lazy_init_domain(int domain, bool locked) 1319 { 1320 static bool initdone[MAXMEMDOM]; 1321 struct vm_domain *vmd; 1322 struct vm_freelist *fl; 1323 vm_page_t m; 1324 int pind; 1325 bool unlocked; 1326 1327 if (__predict_true(atomic_load_bool(&initdone[domain]))) 1328 return; 1329 1330 vmd = VM_DOMAIN(domain); 1331 if (locked) 1332 vm_domain_free_assert_locked(vmd); 1333 else 1334 vm_domain_free_lock(vmd); 1335 if (atomic_load_bool(&initdone[domain])) 1336 goto out; 1337 pind = VM_FREEPOOL_LAZYINIT; 1338 for (int freelist = 0; freelist < VM_NFREELIST; freelist++) { 1339 int flind; 1340 1341 flind = vm_freelist_to_flind[freelist]; 1342 if (flind < 0) 1343 continue; 1344 fl = vm_phys_free_queues[domain][flind][pind]; 1345 for (int oind = 0; oind < VM_NFREEORDER; oind++) { 1346 if (atomic_load_int(&fl[oind].lcnt) == 0) 1347 continue; 1348 while ((m = TAILQ_FIRST(&fl[oind].pl)) != NULL) { 1349 /* 1350 * Avoid holding the lock across the 1351 * initialization unless there's a free page 1352 * shortage. 1353 */ 1354 vm_freelist_rem(fl, m, oind); 1355 unlocked = vm_domain_allocate(vmd, 1356 VM_ALLOC_NORMAL, 1 << oind); 1357 if (unlocked) 1358 vm_domain_free_unlock(vmd); 1359 vm_phys_finish_init(m, oind); 1360 if (unlocked) { 1361 vm_domain_freecnt_inc(vmd, 1 << oind); 1362 vm_domain_free_lock(vmd); 1363 } 1364 vm_phys_free_pages(m, VM_FREEPOOL_DEFAULT, 1365 oind); 1366 } 1367 } 1368 } 1369 atomic_store_bool(&initdone[domain], true); 1370 out: 1371 if (!locked) 1372 vm_domain_free_unlock(vmd); 1373 } 1374 1375 static void 1376 vm_phys_lazy_init(void) 1377 { 1378 for (int domain = 0; domain < vm_ndomains; domain++) 1379 vm_phys_lazy_init_domain(domain, false); 1380 atomic_store_int(&vm_default_freepool, VM_FREEPOOL_DEFAULT); 1381 } 1382 1383 static void 1384 vm_phys_lazy_init_kthr(void *arg __unused) 1385 { 1386 vm_phys_lazy_init(); 1387 kthread_exit(); 1388 } 1389 1390 static void 1391 vm_phys_lazy_sysinit(void *arg __unused) 1392 { 1393 struct thread *td; 1394 int error; 1395 1396 error = kthread_add(vm_phys_lazy_init_kthr, NULL, curproc, &td, 1397 RFSTOPPED, 0, "vmlazyinit"); 1398 if (error == 0) { 1399 thread_lock(td); 1400 sched_prio(td, PRI_MIN_IDLE); 1401 sched_add(td, SRQ_BORING); 1402 } else { 1403 printf("%s: could not create lazy init thread: %d\n", 1404 __func__, error); 1405 vm_phys_lazy_init(); 1406 } 1407 } 1408 SYSINIT(vm_phys_lazy_init, SI_SUB_SMP, SI_ORDER_ANY, vm_phys_lazy_sysinit, 1409 NULL); 1410 #endif /* VM_FREEPOOL_LAZYINIT */ 1411 1412 /* 1413 * Free a contiguous, arbitrarily sized set of physical pages, without 1414 * merging across set boundaries. Assumes no pages have a valid pool field. 1415 * 1416 * The free page queues must be locked. 1417 */ 1418 void 1419 vm_phys_enqueue_contig(vm_page_t m, int pool, u_long npages) 1420 { 1421 struct vm_freelist *fl; 1422 struct vm_phys_seg *seg; 1423 vm_page_t m_end; 1424 vm_paddr_t diff, lo; 1425 int order; 1426 1427 /* 1428 * Avoid unnecessary coalescing by freeing the pages in the largest 1429 * possible power-of-two-sized subsets. 1430 */ 1431 vm_domain_free_assert_locked(vm_pagequeue_domain(m)); 1432 seg = &vm_phys_segs[m->segind]; 1433 fl = (*seg->free_queues)[pool]; 1434 m_end = m + npages; 1435 /* Free blocks of increasing size. */ 1436 lo = atop(VM_PAGE_TO_PHYS(m)); 1437 if (m < m_end && 1438 (diff = lo ^ (lo + npages - 1)) != 0) { 1439 order = min(ilog2(diff), VM_NFREEORDER - 1); 1440 m = vm_phys_enq_range(m, roundup2(lo, 1 << order) - lo, fl, 1441 pool, 1); 1442 } 1443 1444 /* Free blocks of maximum size. */ 1445 order = VM_NFREEORDER - 1; 1446 while (m + (1 << order) <= m_end) { 1447 KASSERT(seg == &vm_phys_segs[m->segind], 1448 ("%s: page range [%p,%p) spans multiple segments", 1449 __func__, m_end - npages, m)); 1450 vm_phys_enq_chunk(fl, m, order, pool, 1); 1451 m += 1 << order; 1452 } 1453 /* Free blocks of diminishing size. */ 1454 vm_phys_enq_beg(m, m_end - m, fl, pool, 1); 1455 } 1456 1457 /* 1458 * Free a contiguous, arbitrarily sized set of physical pages. 1459 * Assumes that every page but the first has no valid pool field. 1460 * Uses the pool value in the first page if valid, otherwise default. 1461 * 1462 * The free page queues must be locked. 1463 */ 1464 void 1465 vm_phys_free_contig(vm_page_t m, int pool, u_long npages) 1466 { 1467 vm_paddr_t lo; 1468 vm_page_t m_start, m_end; 1469 unsigned max_order, order_start, order_end; 1470 1471 vm_domain_free_assert_locked(vm_pagequeue_domain(m)); 1472 1473 lo = atop(VM_PAGE_TO_PHYS(m)); 1474 max_order = min(ilog2(lo ^ (lo + npages)), VM_NFREEORDER - 1); 1475 1476 m_start = m; 1477 order_start = ffsll(lo) - 1; 1478 if (order_start < max_order) 1479 m_start += 1 << order_start; 1480 m_end = m + npages; 1481 order_end = ffsll(lo + npages) - 1; 1482 if (order_end < max_order) 1483 m_end -= 1 << order_end; 1484 /* 1485 * Avoid unnecessary coalescing by freeing the pages at the start and 1486 * end of the range last. 1487 */ 1488 if (m_start < m_end) 1489 vm_phys_enqueue_contig(m_start, pool, m_end - m_start); 1490 if (order_start < max_order) 1491 vm_phys_free_pages(m, pool, order_start); 1492 if (order_end < max_order) 1493 vm_phys_free_pages(m_end, pool, order_end); 1494 } 1495 1496 /* 1497 * Identify the first address range within segment segind or greater 1498 * that matches the domain, lies within the low/high range, and has 1499 * enough pages. Return -1 if there is none. 1500 */ 1501 int 1502 vm_phys_find_range(vm_page_t bounds[], int segind, int domain, 1503 u_long npages, vm_paddr_t low, vm_paddr_t high) 1504 { 1505 vm_paddr_t pa_end, pa_start; 1506 struct vm_phys_seg *end_seg, *seg; 1507 1508 KASSERT(npages > 0, ("npages is zero")); 1509 KASSERT(domain >= 0 && domain < vm_ndomains, ("domain out of range")); 1510 end_seg = &vm_phys_segs[vm_phys_nsegs]; 1511 for (seg = &vm_phys_segs[segind]; seg < end_seg; seg++) { 1512 if (seg->domain != domain) 1513 continue; 1514 if (seg->start >= high) 1515 return (-1); 1516 pa_start = MAX(low, seg->start); 1517 pa_end = MIN(high, seg->end); 1518 if (pa_end - pa_start < ptoa(npages)) 1519 continue; 1520 #ifdef VM_FREEPOOL_LAZYINIT 1521 /* 1522 * The pages on the free lists must be initialized. 1523 */ 1524 vm_phys_lazy_init_domain(domain, false); 1525 #endif 1526 bounds[0] = vm_phys_seg_paddr_to_vm_page(seg, pa_start); 1527 bounds[1] = &seg->first_page[atop(pa_end - seg->start)]; 1528 return (seg - vm_phys_segs); 1529 } 1530 return (-1); 1531 } 1532 1533 /* 1534 * Search for the given physical page "m" in the free lists. If the search 1535 * succeeds, remove "m" from the free lists and return true. Otherwise, return 1536 * false, indicating that "m" is not in the free lists. 1537 * 1538 * The free page queues must be locked. 1539 */ 1540 bool 1541 vm_phys_unfree_page(vm_paddr_t pa) 1542 { 1543 struct vm_freelist *fl; 1544 struct vm_phys_seg *seg; 1545 vm_paddr_t pa_half; 1546 vm_page_t m, m_set, m_tmp; 1547 int order, pool; 1548 1549 seg = vm_phys_paddr_to_seg(pa); 1550 vm_domain_free_assert_locked(VM_DOMAIN(seg->domain)); 1551 1552 #ifdef VM_FREEPOOL_LAZYINIT 1553 /* 1554 * The pages on the free lists must be initialized. 1555 */ 1556 vm_phys_lazy_init_domain(seg->domain, true); 1557 #endif 1558 1559 /* 1560 * First, find the contiguous, power of two-sized set of free 1561 * physical pages containing the given physical page "m" and 1562 * assign it to "m_set". 1563 */ 1564 m = vm_phys_paddr_to_vm_page(pa); 1565 for (m_set = m, order = 0; m_set->order == VM_NFREEORDER && 1566 order < VM_NFREEORDER - 1; ) { 1567 order++; 1568 pa = m->phys_addr & (~(vm_paddr_t)0 << (PAGE_SHIFT + order)); 1569 if (pa >= seg->start) 1570 m_set = vm_phys_seg_paddr_to_vm_page(seg, pa); 1571 else 1572 return (false); 1573 } 1574 if (m_set->order < order) 1575 return (false); 1576 if (m_set->order == VM_NFREEORDER) 1577 return (false); 1578 KASSERT(m_set->order < VM_NFREEORDER, 1579 ("vm_phys_unfree_page: page %p has unexpected order %d", 1580 m_set, m_set->order)); 1581 1582 /* 1583 * Next, remove "m_set" from the free lists. Finally, extract 1584 * "m" from "m_set" using an iterative algorithm: While "m_set" 1585 * is larger than a page, shrink "m_set" by returning the half 1586 * of "m_set" that does not contain "m" to the free lists. 1587 */ 1588 pool = m_set->pool; 1589 fl = (*seg->free_queues)[pool]; 1590 order = m_set->order; 1591 vm_freelist_rem(fl, m_set, order); 1592 while (order > 0) { 1593 order--; 1594 pa_half = m_set->phys_addr ^ (1 << (PAGE_SHIFT + order)); 1595 if (m->phys_addr < pa_half) 1596 m_tmp = vm_phys_seg_paddr_to_vm_page(seg, pa_half); 1597 else { 1598 m_tmp = m_set; 1599 m_set = vm_phys_seg_paddr_to_vm_page(seg, pa_half); 1600 } 1601 vm_freelist_add(fl, m_tmp, order, pool, 0); 1602 } 1603 KASSERT(m_set == m, ("vm_phys_unfree_page: fatal inconsistency")); 1604 return (true); 1605 } 1606 1607 /* 1608 * Find a run of contiguous physical pages, meeting alignment requirements, from 1609 * a list of max-sized page blocks, where we need at least two consecutive 1610 * blocks to satisfy the (large) page request. 1611 */ 1612 static vm_page_t 1613 vm_phys_find_freelist_contig(struct vm_freelist *fl, u_long npages, 1614 vm_paddr_t low, vm_paddr_t high, u_long alignment, vm_paddr_t boundary) 1615 { 1616 struct vm_phys_seg *seg; 1617 vm_page_t m, m_iter, m_ret; 1618 vm_paddr_t max_size, size; 1619 int max_order; 1620 1621 max_order = VM_NFREEORDER - 1; 1622 size = npages << PAGE_SHIFT; 1623 max_size = (vm_paddr_t)1 << (PAGE_SHIFT + max_order); 1624 KASSERT(size > max_size, ("size is too small")); 1625 1626 /* 1627 * In order to avoid examining any free max-sized page block more than 1628 * twice, identify the ones that are first in a physically-contiguous 1629 * sequence of such blocks, and only for those walk the sequence to 1630 * check if there are enough free blocks starting at a properly aligned 1631 * block. Thus, no block is checked for free-ness more than twice. 1632 */ 1633 TAILQ_FOREACH(m, &fl[max_order].pl, plinks.q) { 1634 /* 1635 * Skip m unless it is first in a sequence of free max page 1636 * blocks >= low in its segment. 1637 */ 1638 seg = &vm_phys_segs[m->segind]; 1639 if (VM_PAGE_TO_PHYS(m) < MAX(low, seg->start)) 1640 continue; 1641 if (VM_PAGE_TO_PHYS(m) >= max_size && 1642 VM_PAGE_TO_PHYS(m) - max_size >= MAX(low, seg->start) && 1643 max_order == m[-1 << max_order].order) 1644 continue; 1645 1646 /* 1647 * Advance m_ret from m to the first of the sequence, if any, 1648 * that satisfies alignment conditions and might leave enough 1649 * space. 1650 */ 1651 m_ret = m; 1652 while (!vm_addr_ok(VM_PAGE_TO_PHYS(m_ret), 1653 size, alignment, boundary) && 1654 VM_PAGE_TO_PHYS(m_ret) + size <= MIN(high, seg->end) && 1655 max_order == m_ret[1 << max_order].order) 1656 m_ret += 1 << max_order; 1657 1658 /* 1659 * Skip m unless some block m_ret in the sequence is properly 1660 * aligned, and begins a sequence of enough pages less than 1661 * high, and in the same segment. 1662 */ 1663 if (VM_PAGE_TO_PHYS(m_ret) + size > MIN(high, seg->end)) 1664 continue; 1665 1666 /* 1667 * Skip m unless the blocks to allocate starting at m_ret are 1668 * all free. 1669 */ 1670 for (m_iter = m_ret; 1671 m_iter < m_ret + npages && max_order == m_iter->order; 1672 m_iter += 1 << max_order) { 1673 } 1674 if (m_iter < m_ret + npages) 1675 continue; 1676 return (m_ret); 1677 } 1678 return (NULL); 1679 } 1680 1681 /* 1682 * Find a run of contiguous physical pages from the specified free list 1683 * table. 1684 */ 1685 static vm_page_t 1686 vm_phys_find_queues_contig( 1687 struct vm_freelist (*queues)[VM_NFREEPOOL][VM_NFREEORDER_MAX], 1688 u_long npages, vm_paddr_t low, vm_paddr_t high, 1689 u_long alignment, vm_paddr_t boundary) 1690 { 1691 struct vm_freelist *fl; 1692 vm_page_t m_ret; 1693 vm_paddr_t pa, pa_end, size; 1694 int oind, order, pind; 1695 1696 KASSERT(npages > 0, ("npages is 0")); 1697 KASSERT(powerof2(alignment), ("alignment is not a power of 2")); 1698 KASSERT(powerof2(boundary), ("boundary is not a power of 2")); 1699 /* Compute the queue that is the best fit for npages. */ 1700 order = flsl(npages - 1); 1701 /* Search for a large enough free block. */ 1702 size = npages << PAGE_SHIFT; 1703 for (oind = order; oind < VM_NFREEORDER; oind++) { 1704 for (pind = vm_default_freepool; pind < VM_NFREEPOOL; pind++) { 1705 fl = (*queues)[pind]; 1706 TAILQ_FOREACH(m_ret, &fl[oind].pl, plinks.q) { 1707 /* 1708 * Determine if the address range starting at pa 1709 * is within the given range, satisfies the 1710 * given alignment, and does not cross the given 1711 * boundary. 1712 */ 1713 pa = VM_PAGE_TO_PHYS(m_ret); 1714 pa_end = pa + size; 1715 if (low <= pa && pa_end <= high && 1716 vm_addr_ok(pa, size, alignment, boundary)) 1717 return (m_ret); 1718 } 1719 } 1720 } 1721 if (order < VM_NFREEORDER) 1722 return (NULL); 1723 /* Search for a long-enough sequence of max-order blocks. */ 1724 for (pind = vm_default_freepool; pind < VM_NFREEPOOL; pind++) { 1725 fl = (*queues)[pind]; 1726 m_ret = vm_phys_find_freelist_contig(fl, npages, 1727 low, high, alignment, boundary); 1728 if (m_ret != NULL) 1729 return (m_ret); 1730 } 1731 return (NULL); 1732 } 1733 1734 /* 1735 * Allocate a contiguous set of physical pages of the given size 1736 * "npages" from the free lists. All of the physical pages must be at 1737 * or above the given physical address "low" and below the given 1738 * physical address "high". The given value "alignment" determines the 1739 * alignment of the first physical page in the set. If the given value 1740 * "boundary" is non-zero, then the set of physical pages cannot cross 1741 * any physical address boundary that is a multiple of that value. Both 1742 * "alignment" and "boundary" must be a power of two. Sets the pool 1743 * field to DEFAULT in the first allocated page. 1744 */ 1745 vm_page_t 1746 vm_phys_alloc_contig(int domain, u_long npages, vm_paddr_t low, vm_paddr_t high, 1747 u_long alignment, vm_paddr_t boundary) 1748 { 1749 vm_paddr_t pa_end, pa_start; 1750 struct vm_freelist *fl; 1751 vm_page_t m, m_run; 1752 struct vm_phys_seg *seg; 1753 struct vm_freelist (*queues)[VM_NFREEPOOL][VM_NFREEORDER_MAX]; 1754 int oind, segind; 1755 1756 KASSERT(npages > 0, ("npages is 0")); 1757 KASSERT(powerof2(alignment), ("alignment is not a power of 2")); 1758 KASSERT(powerof2(boundary), ("boundary is not a power of 2")); 1759 vm_domain_free_assert_locked(VM_DOMAIN(domain)); 1760 if (low >= high) 1761 return (NULL); 1762 queues = NULL; 1763 m_run = NULL; 1764 for (segind = vm_phys_nsegs - 1; segind >= 0; segind--) { 1765 seg = &vm_phys_segs[segind]; 1766 if (seg->start >= high || seg->domain != domain) 1767 continue; 1768 if (low >= seg->end) 1769 break; 1770 if (low <= seg->start) 1771 pa_start = seg->start; 1772 else 1773 pa_start = low; 1774 if (high < seg->end) 1775 pa_end = high; 1776 else 1777 pa_end = seg->end; 1778 if (pa_end - pa_start < ptoa(npages)) 1779 continue; 1780 /* 1781 * If a previous segment led to a search using 1782 * the same free lists as would this segment, then 1783 * we've actually already searched within this 1784 * too. So skip it. 1785 */ 1786 if (seg->free_queues == queues) 1787 continue; 1788 queues = seg->free_queues; 1789 m_run = vm_phys_find_queues_contig(queues, npages, 1790 low, high, alignment, boundary); 1791 if (m_run != NULL) 1792 break; 1793 } 1794 if (m_run == NULL) 1795 return (NULL); 1796 1797 /* Allocate pages from the page-range found. */ 1798 for (m = m_run; m < &m_run[npages]; m = &m[1 << oind]) { 1799 fl = (*queues)[m->pool]; 1800 oind = m->order; 1801 vm_freelist_rem(fl, m, oind); 1802 vm_phys_finish_init(m, oind); 1803 } 1804 /* Return excess pages to the free lists. */ 1805 fl = (*queues)[VM_FREEPOOL_DEFAULT]; 1806 vm_phys_enq_range(&m_run[npages], m - &m_run[npages], fl, 1807 VM_FREEPOOL_DEFAULT, 0); 1808 1809 /* Return page verified to satisfy conditions of request. */ 1810 pa_start = VM_PAGE_TO_PHYS(m_run); 1811 KASSERT(low <= pa_start, 1812 ("memory allocated below minimum requested range")); 1813 KASSERT(pa_start + ptoa(npages) <= high, 1814 ("memory allocated above maximum requested range")); 1815 seg = &vm_phys_segs[m_run->segind]; 1816 KASSERT(seg->domain == domain, 1817 ("memory not allocated from specified domain")); 1818 KASSERT(vm_addr_ok(pa_start, ptoa(npages), alignment, boundary), 1819 ("memory alignment/boundary constraints not satisfied")); 1820 return (m_run); 1821 } 1822 1823 /* 1824 * Return the index of the first unused slot which may be the terminating 1825 * entry. 1826 */ 1827 static int 1828 vm_phys_avail_count(void) 1829 { 1830 int i; 1831 1832 for (i = 0; i < PHYS_AVAIL_COUNT; i += 2) 1833 if (phys_avail[i] == 0 && phys_avail[i + 1] == 0) 1834 return (i); 1835 panic("Improperly terminated phys_avail[]"); 1836 } 1837 1838 /* 1839 * Assert that a phys_avail entry is valid. 1840 */ 1841 static void 1842 vm_phys_avail_check(int i) 1843 { 1844 if (i % 2 != 0) 1845 panic("Chunk start index %d is not even.", i); 1846 if (phys_avail[i] & PAGE_MASK) 1847 panic("Unaligned phys_avail[%d]: %#jx", i, 1848 (intmax_t)phys_avail[i]); 1849 if (phys_avail[i + 1] & PAGE_MASK) 1850 panic("Unaligned phys_avail[%d + 1]: %#jx", i, 1851 (intmax_t)phys_avail[i + 1]); 1852 if (phys_avail[i + 1] < phys_avail[i]) 1853 panic("phys_avail[%d]: start %#jx > end %#jx", i, 1854 (intmax_t)phys_avail[i], (intmax_t)phys_avail[i + 1]); 1855 } 1856 1857 /* 1858 * Return the index of an overlapping phys_avail entry or -1. 1859 */ 1860 #ifdef NUMA 1861 static int 1862 vm_phys_avail_find(vm_paddr_t pa) 1863 { 1864 int i; 1865 1866 for (i = 0; phys_avail[i + 1]; i += 2) 1867 if (phys_avail[i] <= pa && phys_avail[i + 1] > pa) 1868 return (i); 1869 return (-1); 1870 } 1871 #endif 1872 1873 /* 1874 * Return the index of the largest entry. 1875 */ 1876 int 1877 vm_phys_avail_largest(void) 1878 { 1879 vm_paddr_t sz, largesz; 1880 int largest; 1881 int i; 1882 1883 largest = 0; 1884 largesz = 0; 1885 for (i = 0; phys_avail[i + 1]; i += 2) { 1886 sz = vm_phys_avail_size(i); 1887 if (sz > largesz) { 1888 largesz = sz; 1889 largest = i; 1890 } 1891 } 1892 1893 return (largest); 1894 } 1895 1896 vm_paddr_t 1897 vm_phys_avail_size(int i) 1898 { 1899 1900 return (phys_avail[i + 1] - phys_avail[i]); 1901 } 1902 1903 /* 1904 * Split a chunk in phys_avail[] at the address 'pa'. 1905 * 1906 * 'pa' must be within a chunk (slots i and i + 1) or one of its boundaries. 1907 * Returns zero on actual split, in which case the two new chunks occupy slots 1908 * i to i + 3, else EJUSTRETURN if 'pa' was one of the boundaries (and no split 1909 * actually occurred) else ENOSPC if there are not enough slots in phys_avail[] 1910 * to represent the additional chunk caused by the split. 1911 */ 1912 static int 1913 vm_phys_avail_split(vm_paddr_t pa, int i) 1914 { 1915 int cnt; 1916 1917 vm_phys_avail_check(i); 1918 if (pa < phys_avail[i] || pa > phys_avail[i + 1]) 1919 panic("%s: Address %#jx not in range at slot %d [%#jx;%#jx].", 1920 __func__, (uintmax_t)pa, i, 1921 (uintmax_t)phys_avail[i], (uintmax_t)phys_avail[i + 1]); 1922 if (pa == phys_avail[i] || pa == phys_avail[i + 1]) 1923 return (EJUSTRETURN); 1924 cnt = vm_phys_avail_count(); 1925 if (cnt >= PHYS_AVAIL_ENTRIES) 1926 return (ENOSPC); 1927 memmove(&phys_avail[i + 2], &phys_avail[i], 1928 (cnt - i) * sizeof(phys_avail[0])); 1929 phys_avail[i + 1] = pa; 1930 phys_avail[i + 2] = pa; 1931 vm_phys_avail_check(i); 1932 vm_phys_avail_check(i+2); 1933 1934 return (0); 1935 } 1936 1937 /* 1938 * Check if a given physical address can be included as part of a crash dump. 1939 */ 1940 bool 1941 vm_phys_is_dumpable(vm_paddr_t pa) 1942 { 1943 vm_page_t m; 1944 int i; 1945 1946 if ((m = vm_phys_paddr_to_vm_page(pa)) != NULL) 1947 return ((m->flags & PG_NODUMP) == 0); 1948 1949 for (i = 0; dump_avail[i] != 0 || dump_avail[i + 1] != 0; i += 2) { 1950 if (pa >= dump_avail[i] && pa < dump_avail[i + 1]) 1951 return (true); 1952 } 1953 return (false); 1954 } 1955 1956 void 1957 vm_phys_early_add_seg(vm_paddr_t start, vm_paddr_t end) 1958 { 1959 struct vm_phys_seg *seg; 1960 1961 if (vm_phys_early_nsegs == -1) 1962 panic("%s: called after initialization", __func__); 1963 if (vm_phys_early_nsegs == nitems(vm_phys_early_segs)) 1964 panic("%s: ran out of early segments", __func__); 1965 1966 seg = &vm_phys_early_segs[vm_phys_early_nsegs++]; 1967 seg->start = start; 1968 seg->end = end; 1969 } 1970 1971 /* 1972 * This routine allocates NUMA node specific memory before the page 1973 * allocator is bootstrapped. 1974 */ 1975 vm_paddr_t 1976 vm_phys_early_alloc(int domain, size_t alloc_size) 1977 { 1978 #ifdef NUMA 1979 int mem_index; 1980 #endif 1981 int i, biggestone; 1982 vm_paddr_t pa, mem_start, mem_end, size, biggestsize, align; 1983 1984 KASSERT(domain == -1 || (domain >= 0 && domain < vm_ndomains), 1985 ("%s: invalid domain index %d", __func__, domain)); 1986 1987 /* 1988 * Search the mem_affinity array for the biggest address 1989 * range in the desired domain. This is used to constrain 1990 * the phys_avail selection below. 1991 */ 1992 biggestsize = 0; 1993 mem_start = 0; 1994 mem_end = -1; 1995 #ifdef NUMA 1996 mem_index = 0; 1997 if (mem_affinity != NULL) { 1998 for (i = 0;; i++) { 1999 size = mem_affinity[i].end - mem_affinity[i].start; 2000 if (size == 0) 2001 break; 2002 if (domain != -1 && mem_affinity[i].domain != domain) 2003 continue; 2004 if (size > biggestsize) { 2005 mem_index = i; 2006 biggestsize = size; 2007 } 2008 } 2009 mem_start = mem_affinity[mem_index].start; 2010 mem_end = mem_affinity[mem_index].end; 2011 } 2012 #endif 2013 2014 /* 2015 * Now find biggest physical segment in within the desired 2016 * numa domain. 2017 */ 2018 biggestsize = 0; 2019 biggestone = 0; 2020 for (i = 0; phys_avail[i + 1] != 0; i += 2) { 2021 /* skip regions that are out of range */ 2022 if (phys_avail[i+1] - alloc_size < mem_start || 2023 phys_avail[i+1] > mem_end) 2024 continue; 2025 size = vm_phys_avail_size(i); 2026 if (size > biggestsize) { 2027 biggestone = i; 2028 biggestsize = size; 2029 } 2030 } 2031 alloc_size = round_page(alloc_size); 2032 2033 /* 2034 * Grab single pages from the front to reduce fragmentation. 2035 */ 2036 if (alloc_size == PAGE_SIZE) { 2037 pa = phys_avail[biggestone]; 2038 phys_avail[biggestone] += PAGE_SIZE; 2039 vm_phys_avail_check(biggestone); 2040 return (pa); 2041 } 2042 2043 /* 2044 * Naturally align large allocations. 2045 */ 2046 align = phys_avail[biggestone + 1] & (alloc_size - 1); 2047 if (alloc_size + align > biggestsize) 2048 panic("cannot find a large enough size\n"); 2049 if (align != 0 && 2050 vm_phys_avail_split(phys_avail[biggestone + 1] - align, 2051 biggestone) != 0) 2052 /* Wasting memory. */ 2053 phys_avail[biggestone + 1] -= align; 2054 2055 phys_avail[biggestone + 1] -= alloc_size; 2056 vm_phys_avail_check(biggestone); 2057 pa = phys_avail[biggestone + 1]; 2058 return (pa); 2059 } 2060 2061 void 2062 vm_phys_early_startup(void) 2063 { 2064 struct vm_phys_seg *seg; 2065 int i; 2066 2067 if (phys_avail[1] == 0) 2068 panic("phys_avail[] is empty"); 2069 2070 for (i = 0; phys_avail[i + 1] != 0; i += 2) { 2071 phys_avail[i] = round_page(phys_avail[i]); 2072 phys_avail[i + 1] = trunc_page(phys_avail[i + 1]); 2073 } 2074 2075 for (i = 0; i < vm_phys_early_nsegs; i++) { 2076 seg = &vm_phys_early_segs[i]; 2077 vm_phys_add_seg(seg->start, seg->end); 2078 } 2079 vm_phys_early_nsegs = -1; 2080 2081 #ifdef NUMA 2082 /* Force phys_avail to be split by domain. */ 2083 if (mem_affinity != NULL) { 2084 int idx; 2085 2086 for (i = 0; mem_affinity[i].end != 0; i++) { 2087 idx = vm_phys_avail_find(mem_affinity[i].start); 2088 if (idx != -1) 2089 vm_phys_avail_split(mem_affinity[i].start, idx); 2090 idx = vm_phys_avail_find(mem_affinity[i].end); 2091 if (idx != -1) 2092 vm_phys_avail_split(mem_affinity[i].end, idx); 2093 } 2094 } 2095 #endif 2096 } 2097 2098 #ifdef DDB 2099 /* 2100 * Show the number of physical pages in each of the free lists. 2101 */ 2102 DB_SHOW_COMMAND_FLAGS(freepages, db_show_freepages, DB_CMD_MEMSAFE) 2103 { 2104 struct vm_freelist *fl; 2105 int flind, oind, pind, dom; 2106 2107 for (dom = 0; dom < vm_ndomains; dom++) { 2108 db_printf("DOMAIN: %d\n", dom); 2109 for (flind = 0; flind < vm_nfreelists; flind++) { 2110 db_printf("FREE LIST %d:\n" 2111 "\n ORDER (SIZE) | NUMBER" 2112 "\n ", flind); 2113 for (pind = 0; pind < VM_NFREEPOOL; pind++) 2114 db_printf(" | POOL %d", pind); 2115 db_printf("\n-- "); 2116 for (pind = 0; pind < VM_NFREEPOOL; pind++) 2117 db_printf("-- -- "); 2118 db_printf("--\n"); 2119 for (oind = VM_NFREEORDER - 1; oind >= 0; oind--) { 2120 db_printf(" %2.2d (%6.6dK)", oind, 2121 1 << (PAGE_SHIFT - 10 + oind)); 2122 for (pind = 0; pind < VM_NFREEPOOL; pind++) { 2123 fl = vm_phys_free_queues[dom][flind][pind]; 2124 db_printf(" | %6.6d", fl[oind].lcnt); 2125 } 2126 db_printf("\n"); 2127 } 2128 db_printf("\n"); 2129 } 2130 db_printf("\n"); 2131 } 2132 } 2133 #endif 2134