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