uvm_page.c revision 1.168 1 /* $NetBSD: uvm_page.c,v 1.168 2010/12/11 22:34:03 matt Exp $ */
2
3 /*
4 * Copyright (c) 2010 The NetBSD Foundation, Inc.
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
17 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
18 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
20 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26 * POSSIBILITY OF SUCH DAMAGE.
27 */
28
29 /*
30 * Copyright (c) 1997 Charles D. Cranor and Washington University.
31 * Copyright (c) 1991, 1993, The Regents of the University of California.
32 *
33 * All rights reserved.
34 *
35 * This code is derived from software contributed to Berkeley by
36 * The Mach Operating System project at Carnegie-Mellon University.
37 *
38 * Redistribution and use in source and binary forms, with or without
39 * modification, are permitted provided that the following conditions
40 * are met:
41 * 1. Redistributions of source code must retain the above copyright
42 * notice, this list of conditions and the following disclaimer.
43 * 2. Redistributions in binary form must reproduce the above copyright
44 * notice, this list of conditions and the following disclaimer in the
45 * documentation and/or other materials provided with the distribution.
46 * 3. All advertising materials mentioning features or use of this software
47 * must display the following acknowledgement:
48 * This product includes software developed by Charles D. Cranor,
49 * Washington University, the University of California, Berkeley and
50 * its contributors.
51 * 4. Neither the name of the University nor the names of its contributors
52 * may be used to endorse or promote products derived from this software
53 * without specific prior written permission.
54 *
55 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
56 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
57 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
58 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
59 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
60 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
61 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
62 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
63 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
64 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
65 * SUCH DAMAGE.
66 *
67 * @(#)vm_page.c 8.3 (Berkeley) 3/21/94
68 * from: Id: uvm_page.c,v 1.1.2.18 1998/02/06 05:24:42 chs Exp
69 *
70 *
71 * Copyright (c) 1987, 1990 Carnegie-Mellon University.
72 * All rights reserved.
73 *
74 * Permission to use, copy, modify and distribute this software and
75 * its documentation is hereby granted, provided that both the copyright
76 * notice and this permission notice appear in all copies of the
77 * software, derivative works or modified versions, and any portions
78 * thereof, and that both notices appear in supporting documentation.
79 *
80 * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
81 * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND
82 * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
83 *
84 * Carnegie Mellon requests users of this software to return to
85 *
86 * Software Distribution Coordinator or Software.Distribution (at) CS.CMU.EDU
87 * School of Computer Science
88 * Carnegie Mellon University
89 * Pittsburgh PA 15213-3890
90 *
91 * any improvements or extensions that they make and grant Carnegie the
92 * rights to redistribute these changes.
93 */
94
95 /*
96 * uvm_page.c: page ops.
97 */
98
99 #include <sys/cdefs.h>
100 __KERNEL_RCSID(0, "$NetBSD: uvm_page.c,v 1.168 2010/12/11 22:34:03 matt Exp $");
101
102 #include "opt_ddb.h"
103 #include "opt_uvmhist.h"
104 #include "opt_readahead.h"
105
106 #include <sys/param.h>
107 #include <sys/systm.h>
108 #include <sys/malloc.h>
109 #include <sys/sched.h>
110 #include <sys/kernel.h>
111 #include <sys/vnode.h>
112 #include <sys/proc.h>
113 #include <sys/atomic.h>
114 #include <sys/cpu.h>
115
116 #include <uvm/uvm.h>
117 #include <uvm/uvm_ddb.h>
118 #include <uvm/uvm_pdpolicy.h>
119
120 /*
121 * global vars... XXXCDC: move to uvm. structure.
122 */
123
124 /*
125 * physical memory config is stored in vm_physmem.
126 */
127
128 struct vm_physseg vm_physmem[VM_PHYSSEG_MAX]; /* XXXCDC: uvm.physmem */
129 int vm_nphysseg = 0; /* XXXCDC: uvm.nphysseg */
130 #define vm_nphysmem vm_nphysseg
131
132 /*
133 * Some supported CPUs in a given architecture don't support all
134 * of the things necessary to do idle page zero'ing efficiently.
135 * We therefore provide a way to enable it from machdep code here.
136 */
137 bool vm_page_zero_enable = false;
138
139 /*
140 * number of pages per-CPU to reserve for the kernel.
141 */
142 int vm_page_reserve_kernel = 5;
143
144 /*
145 * physical memory size;
146 */
147 int physmem;
148
149 /*
150 * local variables
151 */
152
153 /*
154 * these variables record the values returned by vm_page_bootstrap,
155 * for debugging purposes. The implementation of uvm_pageboot_alloc
156 * and pmap_startup here also uses them internally.
157 */
158
159 static vaddr_t virtual_space_start;
160 static vaddr_t virtual_space_end;
161
162 /*
163 * we allocate an initial number of page colors in uvm_page_init(),
164 * and remember them. We may re-color pages as cache sizes are
165 * discovered during the autoconfiguration phase. But we can never
166 * free the initial set of buckets, since they are allocated using
167 * uvm_pageboot_alloc().
168 */
169
170 static bool have_recolored_pages /* = false */;
171
172 MALLOC_DEFINE(M_VMPAGE, "VM page", "VM page");
173
174 #ifdef DEBUG
175 vaddr_t uvm_zerocheckkva;
176 #endif /* DEBUG */
177
178 /*
179 * local prototypes
180 */
181
182 static void uvm_pageinsert(struct uvm_object *, struct vm_page *);
183 static void uvm_pageremove(struct uvm_object *, struct vm_page *);
184
185 /*
186 * per-object tree of pages
187 */
188
189 static signed int
190 uvm_page_compare_nodes(void *ctx, const void *n1, const void *n2)
191 {
192 const struct vm_page *pg1 = n1;
193 const struct vm_page *pg2 = n2;
194 const voff_t a = pg1->offset;
195 const voff_t b = pg2->offset;
196
197 if (a < b)
198 return -1;
199 if (a > b)
200 return 1;
201 return 0;
202 }
203
204 static signed int
205 uvm_page_compare_key(void *ctx, const void *n, const void *key)
206 {
207 const struct vm_page *pg = n;
208 const voff_t a = pg->offset;
209 const voff_t b = *(const voff_t *)key;
210
211 if (a < b)
212 return -1;
213 if (a > b)
214 return 1;
215 return 0;
216 }
217
218 const rb_tree_ops_t uvm_page_tree_ops = {
219 .rbto_compare_nodes = uvm_page_compare_nodes,
220 .rbto_compare_key = uvm_page_compare_key,
221 .rbto_node_offset = offsetof(struct vm_page, rb_node),
222 .rbto_context = NULL
223 };
224
225 /*
226 * inline functions
227 */
228
229 /*
230 * uvm_pageinsert: insert a page in the object.
231 *
232 * => caller must lock object
233 * => caller must lock page queues
234 * => call should have already set pg's object and offset pointers
235 * and bumped the version counter
236 */
237
238 static inline void
239 uvm_pageinsert_list(struct uvm_object *uobj, struct vm_page *pg,
240 struct vm_page *where)
241 {
242
243 KASSERT(uobj == pg->uobject);
244 KASSERT(mutex_owned(&uobj->vmobjlock));
245 KASSERT((pg->flags & PG_TABLED) == 0);
246 KASSERT(where == NULL || (where->flags & PG_TABLED));
247 KASSERT(where == NULL || (where->uobject == uobj));
248
249 if (UVM_OBJ_IS_VNODE(uobj)) {
250 if (uobj->uo_npages == 0) {
251 struct vnode *vp = (struct vnode *)uobj;
252
253 vholdl(vp);
254 }
255 if (UVM_OBJ_IS_VTEXT(uobj)) {
256 atomic_inc_uint(&uvmexp.execpages);
257 } else {
258 atomic_inc_uint(&uvmexp.filepages);
259 }
260 } else if (UVM_OBJ_IS_AOBJ(uobj)) {
261 atomic_inc_uint(&uvmexp.anonpages);
262 }
263
264 if (where)
265 TAILQ_INSERT_AFTER(&uobj->memq, where, pg, listq.queue);
266 else
267 TAILQ_INSERT_TAIL(&uobj->memq, pg, listq.queue);
268 pg->flags |= PG_TABLED;
269 uobj->uo_npages++;
270 }
271
272
273 static inline void
274 uvm_pageinsert_tree(struct uvm_object *uobj, struct vm_page *pg)
275 {
276 struct vm_page *ret;
277
278 KASSERT(uobj == pg->uobject);
279 ret = rb_tree_insert_node(&uobj->rb_tree, pg);
280 KASSERT(ret == pg);
281 }
282
283 static inline void
284 uvm_pageinsert(struct uvm_object *uobj, struct vm_page *pg)
285 {
286
287 KDASSERT(uobj != NULL);
288 uvm_pageinsert_tree(uobj, pg);
289 uvm_pageinsert_list(uobj, pg, NULL);
290 }
291
292 /*
293 * uvm_page_remove: remove page from object.
294 *
295 * => caller must lock object
296 * => caller must lock page queues
297 */
298
299 static inline void
300 uvm_pageremove_list(struct uvm_object *uobj, struct vm_page *pg)
301 {
302
303 KASSERT(uobj == pg->uobject);
304 KASSERT(mutex_owned(&uobj->vmobjlock));
305 KASSERT(pg->flags & PG_TABLED);
306
307 if (UVM_OBJ_IS_VNODE(uobj)) {
308 if (uobj->uo_npages == 1) {
309 struct vnode *vp = (struct vnode *)uobj;
310
311 holdrelel(vp);
312 }
313 if (UVM_OBJ_IS_VTEXT(uobj)) {
314 atomic_dec_uint(&uvmexp.execpages);
315 } else {
316 atomic_dec_uint(&uvmexp.filepages);
317 }
318 } else if (UVM_OBJ_IS_AOBJ(uobj)) {
319 atomic_dec_uint(&uvmexp.anonpages);
320 }
321
322 /* object should be locked */
323 uobj->uo_npages--;
324 TAILQ_REMOVE(&uobj->memq, pg, listq.queue);
325 pg->flags &= ~PG_TABLED;
326 pg->uobject = NULL;
327 }
328
329 static inline void
330 uvm_pageremove_tree(struct uvm_object *uobj, struct vm_page *pg)
331 {
332
333 KASSERT(uobj == pg->uobject);
334 rb_tree_remove_node(&uobj->rb_tree, pg);
335 }
336
337 static inline void
338 uvm_pageremove(struct uvm_object *uobj, struct vm_page *pg)
339 {
340
341 KDASSERT(uobj != NULL);
342 uvm_pageremove_tree(uobj, pg);
343 uvm_pageremove_list(uobj, pg);
344 }
345
346 static void
347 uvm_page_init_buckets(struct pgfreelist *pgfl)
348 {
349 int color, i;
350
351 for (color = 0; color < uvmexp.ncolors; color++) {
352 for (i = 0; i < PGFL_NQUEUES; i++) {
353 LIST_INIT(&pgfl->pgfl_buckets[color].pgfl_queues[i]);
354 }
355 }
356 }
357
358 /*
359 * uvm_page_init: init the page system. called from uvm_init().
360 *
361 * => we return the range of kernel virtual memory in kvm_startp/kvm_endp
362 */
363
364 void
365 uvm_page_init(vaddr_t *kvm_startp, vaddr_t *kvm_endp)
366 {
367 static struct uvm_cpu boot_cpu;
368 psize_t freepages, pagecount, bucketcount, n;
369 struct pgflbucket *bucketarray, *cpuarray;
370 struct vm_physseg *seg;
371 struct vm_page *pagearray;
372 int lcv;
373 u_int i;
374 paddr_t paddr;
375
376 KASSERT(ncpu <= 1);
377 CTASSERT(sizeof(pagearray->offset) >= sizeof(struct uvm_cpu *));
378
379 /*
380 * init the page queues and page queue locks, except the free
381 * list; we allocate that later (with the initial vm_page
382 * structures).
383 */
384
385 uvm.cpus[0] = &boot_cpu;
386 curcpu()->ci_data.cpu_uvm = &boot_cpu;
387 uvm_reclaim_init();
388 uvmpdpol_init();
389 mutex_init(&uvm_pageqlock, MUTEX_DRIVER, IPL_NONE);
390 mutex_init(&uvm_fpageqlock, MUTEX_DRIVER, IPL_VM);
391
392 /*
393 * allocate vm_page structures.
394 */
395
396 /*
397 * sanity check:
398 * before calling this function the MD code is expected to register
399 * some free RAM with the uvm_page_physload() function. our job
400 * now is to allocate vm_page structures for this memory.
401 */
402
403 if (vm_nphysmem == 0)
404 panic("uvm_page_bootstrap: no memory pre-allocated");
405
406 /*
407 * first calculate the number of free pages...
408 *
409 * note that we use start/end rather than avail_start/avail_end.
410 * this allows us to allocate extra vm_page structures in case we
411 * want to return some memory to the pool after booting.
412 */
413
414 freepages = 0;
415 for (lcv = 0 ; lcv < vm_nphysmem ; lcv++) {
416 seg = VM_PHYSMEM_PTR(lcv);
417 freepages += (seg->end - seg->start);
418 }
419
420 /*
421 * Let MD code initialize the number of colors, or default
422 * to 1 color if MD code doesn't care.
423 */
424 if (uvmexp.ncolors == 0)
425 uvmexp.ncolors = 1;
426 uvmexp.colormask = uvmexp.ncolors - 1;
427
428 /*
429 * we now know we have (PAGE_SIZE * freepages) bytes of memory we can
430 * use. for each page of memory we use we need a vm_page structure.
431 * thus, the total number of pages we can use is the total size of
432 * the memory divided by the PAGE_SIZE plus the size of the vm_page
433 * structure. we add one to freepages as a fudge factor to avoid
434 * truncation errors (since we can only allocate in terms of whole
435 * pages).
436 */
437
438 bucketcount = uvmexp.ncolors * VM_NFREELIST;
439 pagecount = ((freepages + 1) << PAGE_SHIFT) /
440 (PAGE_SIZE + sizeof(struct vm_page));
441
442 bucketarray = (void *)uvm_pageboot_alloc((bucketcount *
443 sizeof(struct pgflbucket) * 2) + (pagecount *
444 sizeof(struct vm_page)));
445 cpuarray = bucketarray + bucketcount;
446 pagearray = (struct vm_page *)(bucketarray + bucketcount * 2);
447
448 for (lcv = 0; lcv < VM_NFREELIST; lcv++) {
449 uvm.page_free[lcv].pgfl_buckets =
450 (bucketarray + (lcv * uvmexp.ncolors));
451 uvm_page_init_buckets(&uvm.page_free[lcv]);
452 uvm.cpus[0]->page_free[lcv].pgfl_buckets =
453 (cpuarray + (lcv * uvmexp.ncolors));
454 uvm_page_init_buckets(&uvm.cpus[0]->page_free[lcv]);
455 }
456 memset(pagearray, 0, pagecount * sizeof(struct vm_page));
457
458 /*
459 * init the vm_page structures and put them in the correct place.
460 */
461
462 for (lcv = 0 ; lcv < vm_nphysmem ; lcv++) {
463 seg = VM_PHYSMEM_PTR(lcv);
464 n = seg->end - seg->start;
465
466 /* set up page array pointers */
467 seg->pgs = pagearray;
468 pagearray += n;
469 pagecount -= n;
470 seg->lastpg = seg->pgs + n;
471
472 /* init and free vm_pages (we've already zeroed them) */
473 paddr = ctob(seg->start);
474 for (i = 0 ; i < n ; i++, paddr += PAGE_SIZE) {
475 seg->pgs[i].phys_addr = paddr;
476 #ifdef __HAVE_VM_PAGE_MD
477 VM_MDPAGE_INIT(&seg->pgs[i]);
478 #endif
479 if (atop(paddr) >= seg->avail_start &&
480 atop(paddr) <= seg->avail_end) {
481 uvmexp.npages++;
482 /* add page to free pool */
483 uvm_pagefree(&seg->pgs[i]);
484 }
485 }
486 }
487
488 /*
489 * pass up the values of virtual_space_start and
490 * virtual_space_end (obtained by uvm_pageboot_alloc) to the upper
491 * layers of the VM.
492 */
493
494 *kvm_startp = round_page(virtual_space_start);
495 *kvm_endp = trunc_page(virtual_space_end);
496 #ifdef DEBUG
497 /*
498 * steal kva for uvm_pagezerocheck().
499 */
500 uvm_zerocheckkva = *kvm_startp;
501 *kvm_startp += PAGE_SIZE;
502 #endif /* DEBUG */
503
504 /*
505 * init various thresholds.
506 */
507
508 uvmexp.reserve_pagedaemon = 1;
509 uvmexp.reserve_kernel = vm_page_reserve_kernel;
510
511 /*
512 * determine if we should zero pages in the idle loop.
513 */
514
515 uvm.cpus[0]->page_idle_zero = vm_page_zero_enable;
516
517 /*
518 * done!
519 */
520
521 uvm.page_init_done = true;
522 }
523
524 /*
525 * uvm_setpagesize: set the page size
526 *
527 * => sets page_shift and page_mask from uvmexp.pagesize.
528 */
529
530 void
531 uvm_setpagesize(void)
532 {
533
534 /*
535 * If uvmexp.pagesize is 0 at this point, we expect PAGE_SIZE
536 * to be a constant (indicated by being a non-zero value).
537 */
538 if (uvmexp.pagesize == 0) {
539 if (PAGE_SIZE == 0)
540 panic("uvm_setpagesize: uvmexp.pagesize not set");
541 uvmexp.pagesize = PAGE_SIZE;
542 }
543 uvmexp.pagemask = uvmexp.pagesize - 1;
544 if ((uvmexp.pagemask & uvmexp.pagesize) != 0)
545 panic("uvm_setpagesize: page size %u (%#x) not a power of two",
546 uvmexp.pagesize, uvmexp.pagesize);
547 for (uvmexp.pageshift = 0; ; uvmexp.pageshift++)
548 if ((1 << uvmexp.pageshift) == uvmexp.pagesize)
549 break;
550 }
551
552 /*
553 * uvm_pageboot_alloc: steal memory from physmem for bootstrapping
554 */
555
556 vaddr_t
557 uvm_pageboot_alloc(vsize_t size)
558 {
559 static bool initialized = false;
560 vaddr_t addr;
561 #if !defined(PMAP_STEAL_MEMORY)
562 vaddr_t vaddr;
563 paddr_t paddr;
564 #endif
565
566 /*
567 * on first call to this function, initialize ourselves.
568 */
569 if (initialized == false) {
570 pmap_virtual_space(&virtual_space_start, &virtual_space_end);
571
572 /* round it the way we like it */
573 virtual_space_start = round_page(virtual_space_start);
574 virtual_space_end = trunc_page(virtual_space_end);
575
576 initialized = true;
577 }
578
579 /* round to page size */
580 size = round_page(size);
581
582 #if defined(PMAP_STEAL_MEMORY)
583
584 /*
585 * defer bootstrap allocation to MD code (it may want to allocate
586 * from a direct-mapped segment). pmap_steal_memory should adjust
587 * virtual_space_start/virtual_space_end if necessary.
588 */
589
590 addr = pmap_steal_memory(size, &virtual_space_start,
591 &virtual_space_end);
592
593 return(addr);
594
595 #else /* !PMAP_STEAL_MEMORY */
596
597 /*
598 * allocate virtual memory for this request
599 */
600 if (virtual_space_start == virtual_space_end ||
601 (virtual_space_end - virtual_space_start) < size)
602 panic("uvm_pageboot_alloc: out of virtual space");
603
604 addr = virtual_space_start;
605
606 #ifdef PMAP_GROWKERNEL
607 /*
608 * If the kernel pmap can't map the requested space,
609 * then allocate more resources for it.
610 */
611 if (uvm_maxkaddr < (addr + size)) {
612 uvm_maxkaddr = pmap_growkernel(addr + size);
613 if (uvm_maxkaddr < (addr + size))
614 panic("uvm_pageboot_alloc: pmap_growkernel() failed");
615 }
616 #endif
617
618 virtual_space_start += size;
619
620 /*
621 * allocate and mapin physical pages to back new virtual pages
622 */
623
624 for (vaddr = round_page(addr) ; vaddr < addr + size ;
625 vaddr += PAGE_SIZE) {
626
627 if (!uvm_page_physget(&paddr))
628 panic("uvm_pageboot_alloc: out of memory");
629
630 /*
631 * Note this memory is no longer managed, so using
632 * pmap_kenter is safe.
633 */
634 pmap_kenter_pa(vaddr, paddr, VM_PROT_READ|VM_PROT_WRITE, 0);
635 }
636 pmap_update(pmap_kernel());
637 return(addr);
638 #endif /* PMAP_STEAL_MEMORY */
639 }
640
641 #if !defined(PMAP_STEAL_MEMORY)
642 /*
643 * uvm_page_physget: "steal" one page from the vm_physmem structure.
644 *
645 * => attempt to allocate it off the end of a segment in which the "avail"
646 * values match the start/end values. if we can't do that, then we
647 * will advance both values (making them equal, and removing some
648 * vm_page structures from the non-avail area).
649 * => return false if out of memory.
650 */
651
652 /* subroutine: try to allocate from memory chunks on the specified freelist */
653 static bool uvm_page_physget_freelist(paddr_t *, int);
654
655 static bool
656 uvm_page_physget_freelist(paddr_t *paddrp, int freelist)
657 {
658 struct vm_physseg *seg;
659 int lcv, x;
660
661 /* pass 1: try allocating from a matching end */
662 #if (VM_PHYSSEG_STRAT == VM_PSTRAT_BIGFIRST)
663 for (lcv = vm_nphysmem - 1 ; lcv >= 0 ; lcv--)
664 #else
665 for (lcv = 0 ; lcv < vm_nphysmem ; lcv++)
666 #endif
667 {
668 seg = VM_PHYSMEM_PTR(lcv);
669
670 if (uvm.page_init_done == true)
671 panic("uvm_page_physget: called _after_ bootstrap");
672
673 if (seg->free_list != freelist)
674 continue;
675
676 /* try from front */
677 if (seg->avail_start == seg->start &&
678 seg->avail_start < seg->avail_end) {
679 *paddrp = ctob(seg->avail_start);
680 seg->avail_start++;
681 seg->start++;
682 /* nothing left? nuke it */
683 if (seg->avail_start == seg->end) {
684 if (vm_nphysmem == 1)
685 panic("uvm_page_physget: out of memory!");
686 vm_nphysmem--;
687 for (x = lcv ; x < vm_nphysmem ; x++)
688 /* structure copy */
689 VM_PHYSMEM_PTR_SWAP(x, x + 1);
690 }
691 return (true);
692 }
693
694 /* try from rear */
695 if (seg->avail_end == seg->end &&
696 seg->avail_start < seg->avail_end) {
697 *paddrp = ctob(seg->avail_end - 1);
698 seg->avail_end--;
699 seg->end--;
700 /* nothing left? nuke it */
701 if (seg->avail_end == seg->start) {
702 if (vm_nphysmem == 1)
703 panic("uvm_page_physget: out of memory!");
704 vm_nphysmem--;
705 for (x = lcv ; x < vm_nphysmem ; x++)
706 /* structure copy */
707 VM_PHYSMEM_PTR_SWAP(x, x + 1);
708 }
709 return (true);
710 }
711 }
712
713 /* pass2: forget about matching ends, just allocate something */
714 #if (VM_PHYSSEG_STRAT == VM_PSTRAT_BIGFIRST)
715 for (lcv = vm_nphysmem - 1 ; lcv >= 0 ; lcv--)
716 #else
717 for (lcv = 0 ; lcv < vm_nphysmem ; lcv++)
718 #endif
719 {
720 seg = VM_PHYSMEM_PTR(lcv);
721
722 /* any room in this bank? */
723 if (seg->avail_start >= seg->avail_end)
724 continue; /* nope */
725
726 *paddrp = ctob(seg->avail_start);
727 seg->avail_start++;
728 /* truncate! */
729 seg->start = seg->avail_start;
730
731 /* nothing left? nuke it */
732 if (seg->avail_start == seg->end) {
733 if (vm_nphysmem == 1)
734 panic("uvm_page_physget: out of memory!");
735 vm_nphysmem--;
736 for (x = lcv ; x < vm_nphysmem ; x++)
737 /* structure copy */
738 VM_PHYSMEM_PTR_SWAP(x, x + 1);
739 }
740 return (true);
741 }
742
743 return (false); /* whoops! */
744 }
745
746 bool
747 uvm_page_physget(paddr_t *paddrp)
748 {
749 int i;
750
751 /* try in the order of freelist preference */
752 for (i = 0; i < VM_NFREELIST; i++)
753 if (uvm_page_physget_freelist(paddrp, i) == true)
754 return (true);
755 return (false);
756 }
757 #endif /* PMAP_STEAL_MEMORY */
758
759 /*
760 * uvm_page_physload: load physical memory into VM system
761 *
762 * => all args are PFs
763 * => all pages in start/end get vm_page structures
764 * => areas marked by avail_start/avail_end get added to the free page pool
765 * => we are limited to VM_PHYSSEG_MAX physical memory segments
766 */
767
768 void
769 uvm_page_physload(paddr_t start, paddr_t end, paddr_t avail_start,
770 paddr_t avail_end, int free_list)
771 {
772 int preload, lcv;
773 psize_t npages;
774 struct vm_page *pgs;
775 struct vm_physseg *ps;
776
777 if (uvmexp.pagesize == 0)
778 panic("uvm_page_physload: page size not set!");
779 if (free_list >= VM_NFREELIST || free_list < VM_FREELIST_DEFAULT)
780 panic("uvm_page_physload: bad free list %d", free_list);
781 if (start >= end)
782 panic("uvm_page_physload: start >= end");
783
784 /*
785 * do we have room?
786 */
787
788 if (vm_nphysmem == VM_PHYSSEG_MAX) {
789 printf("uvm_page_physload: unable to load physical memory "
790 "segment\n");
791 printf("\t%d segments allocated, ignoring 0x%llx -> 0x%llx\n",
792 VM_PHYSSEG_MAX, (long long)start, (long long)end);
793 printf("\tincrease VM_PHYSSEG_MAX\n");
794 return;
795 }
796
797 /*
798 * check to see if this is a "preload" (i.e. uvm_page_init hasn't been
799 * called yet, so malloc is not available).
800 */
801
802 for (lcv = 0 ; lcv < vm_nphysmem ; lcv++) {
803 if (VM_PHYSMEM_PTR(lcv)->pgs)
804 break;
805 }
806 preload = (lcv == vm_nphysmem);
807
808 /*
809 * if VM is already running, attempt to malloc() vm_page structures
810 */
811
812 if (!preload) {
813 panic("uvm_page_physload: tried to add RAM after vm_mem_init");
814 } else {
815 pgs = NULL;
816 npages = 0;
817 }
818
819 /*
820 * now insert us in the proper place in vm_physmem[]
821 */
822
823 #if (VM_PHYSSEG_STRAT == VM_PSTRAT_RANDOM)
824 /* random: put it at the end (easy!) */
825 ps = VM_PHYSMEM_PTR(vm_nphysmem);
826 #elif (VM_PHYSSEG_STRAT == VM_PSTRAT_BSEARCH)
827 {
828 int x;
829 /* sort by address for binary search */
830 for (lcv = 0 ; lcv < vm_nphysmem ; lcv++)
831 if (start < VM_PHYSMEM_PTR(lcv)->start)
832 break;
833 ps = VM_PHYSMEM_PTR(lcv);
834 /* move back other entries, if necessary ... */
835 for (x = vm_nphysmem ; x > lcv ; x--)
836 /* structure copy */
837 VM_PHYSMEM_PTR_SWAP(x, x - 1);
838 }
839 #elif (VM_PHYSSEG_STRAT == VM_PSTRAT_BIGFIRST)
840 {
841 int x;
842 /* sort by largest segment first */
843 for (lcv = 0 ; lcv < vm_nphysmem ; lcv++)
844 if ((end - start) >
845 (VM_PHYSMEM_PTR(lcv)->end - VM_PHYSMEM_PTR(lcv)->start))
846 break;
847 ps = VM_PHYSMEM_PTR(lcv);
848 /* move back other entries, if necessary ... */
849 for (x = vm_nphysmem ; x > lcv ; x--)
850 /* structure copy */
851 VM_PHYSMEM_PTR_SWAP(x, x - 1);
852 }
853 #else
854 panic("uvm_page_physload: unknown physseg strategy selected!");
855 #endif
856
857 ps->start = start;
858 ps->end = end;
859 ps->avail_start = avail_start;
860 ps->avail_end = avail_end;
861 if (preload) {
862 ps->pgs = NULL;
863 } else {
864 ps->pgs = pgs;
865 ps->lastpg = pgs + npages;
866 }
867 ps->free_list = free_list;
868 vm_nphysmem++;
869
870 if (!preload) {
871 uvmpdpol_reinit();
872 }
873 }
874
875 /*
876 * when VM_PHYSSEG_MAX is 1, we can simplify these functions
877 */
878
879 #if VM_PHYSSEG_MAX == 1
880 static inline int vm_physseg_find_contig(struct vm_physseg *, int, paddr_t, int *);
881 #elif (VM_PHYSSEG_STRAT == VM_PSTRAT_BSEARCH)
882 static inline int vm_physseg_find_bsearch(struct vm_physseg *, int, paddr_t, int *);
883 #else
884 static inline int vm_physseg_find_linear(struct vm_physseg *, int, paddr_t, int *);
885 #endif
886
887 /*
888 * vm_physseg_find: find vm_physseg structure that belongs to a PA
889 */
890 int
891 vm_physseg_find(paddr_t pframe, int *offp)
892 {
893
894 #if VM_PHYSSEG_MAX == 1
895 return vm_physseg_find_contig(vm_physmem, vm_nphysseg, pframe, offp);
896 #elif (VM_PHYSSEG_STRAT == VM_PSTRAT_BSEARCH)
897 return vm_physseg_find_bsearch(vm_physmem, vm_nphysseg, pframe, offp);
898 #else
899 return vm_physseg_find_linear(vm_physmem, vm_nphysseg, pframe, offp);
900 #endif
901 }
902
903 #if VM_PHYSSEG_MAX == 1
904 static inline int
905 vm_physseg_find_contig(struct vm_physseg *segs, int nsegs, paddr_t pframe, int *offp)
906 {
907
908 /* 'contig' case */
909 if (pframe >= segs[0].start && pframe < segs[0].end) {
910 if (offp)
911 *offp = pframe - segs[0].start;
912 return(0);
913 }
914 return(-1);
915 }
916
917 #elif (VM_PHYSSEG_STRAT == VM_PSTRAT_BSEARCH)
918
919 static inline int
920 vm_physseg_find_bsearch(struct vm_physseg *segs, int nsegs, paddr_t pframe, int *offp)
921 {
922 /* binary search for it */
923 u_int start, len, try;
924
925 /*
926 * if try is too large (thus target is less than try) we reduce
927 * the length to trunc(len/2) [i.e. everything smaller than "try"]
928 *
929 * if the try is too small (thus target is greater than try) then
930 * we set the new start to be (try + 1). this means we need to
931 * reduce the length to (round(len/2) - 1).
932 *
933 * note "adjust" below which takes advantage of the fact that
934 * (round(len/2) - 1) == trunc((len - 1) / 2)
935 * for any value of len we may have
936 */
937
938 for (start = 0, len = nsegs ; len != 0 ; len = len / 2) {
939 try = start + (len / 2); /* try in the middle */
940
941 /* start past our try? */
942 if (pframe >= segs[try].start) {
943 /* was try correct? */
944 if (pframe < segs[try].end) {
945 if (offp)
946 *offp = pframe - segs[try].start;
947 return(try); /* got it */
948 }
949 start = try + 1; /* next time, start here */
950 len--; /* "adjust" */
951 } else {
952 /*
953 * pframe before try, just reduce length of
954 * region, done in "for" loop
955 */
956 }
957 }
958 return(-1);
959 }
960
961 #else
962
963 static inline int
964 vm_physseg_find_linear(struct vm_physseg *segs, int nsegs, paddr_t pframe, int *offp)
965 {
966 /* linear search for it */
967 int lcv;
968
969 for (lcv = 0; lcv < nsegs; lcv++) {
970 if (pframe >= segs[lcv].start &&
971 pframe < segs[lcv].end) {
972 if (offp)
973 *offp = pframe - segs[lcv].start;
974 return(lcv); /* got it */
975 }
976 }
977 return(-1);
978 }
979 #endif
980
981 /*
982 * PHYS_TO_VM_PAGE: find vm_page for a PA. used by MI code to get vm_pages
983 * back from an I/O mapping (ugh!). used in some MD code as well.
984 */
985 struct vm_page *
986 uvm_phys_to_vm_page(paddr_t pa)
987 {
988 paddr_t pf = atop(pa);
989 int off;
990 int psi;
991
992 psi = vm_physseg_find(pf, &off);
993 if (psi != -1)
994 return(&VM_PHYSMEM_PTR(psi)->pgs[off]);
995 return(NULL);
996 }
997
998 paddr_t
999 uvm_vm_page_to_phys(const struct vm_page *pg)
1000 {
1001
1002 return pg->phys_addr;
1003 }
1004
1005 /*
1006 * uvm_page_recolor: Recolor the pages if the new bucket count is
1007 * larger than the old one.
1008 */
1009
1010 void
1011 uvm_page_recolor(int newncolors)
1012 {
1013 struct pgflbucket *bucketarray, *cpuarray, *oldbucketarray;
1014 struct pgfreelist gpgfl, pgfl;
1015 struct vm_page *pg;
1016 vsize_t bucketcount;
1017 int lcv, color, i, ocolors;
1018 struct uvm_cpu *ucpu;
1019
1020 if (newncolors <= uvmexp.ncolors)
1021 return;
1022
1023 if (uvm.page_init_done == false) {
1024 uvmexp.ncolors = newncolors;
1025 return;
1026 }
1027
1028 bucketcount = newncolors * VM_NFREELIST;
1029 bucketarray = malloc(bucketcount * sizeof(struct pgflbucket) * 2,
1030 M_VMPAGE, M_NOWAIT);
1031 cpuarray = bucketarray + bucketcount;
1032 if (bucketarray == NULL) {
1033 printf("WARNING: unable to allocate %ld page color buckets\n",
1034 (long) bucketcount);
1035 return;
1036 }
1037
1038 mutex_spin_enter(&uvm_fpageqlock);
1039
1040 /* Make sure we should still do this. */
1041 if (newncolors <= uvmexp.ncolors) {
1042 mutex_spin_exit(&uvm_fpageqlock);
1043 free(bucketarray, M_VMPAGE);
1044 return;
1045 }
1046
1047 oldbucketarray = uvm.page_free[0].pgfl_buckets;
1048 ocolors = uvmexp.ncolors;
1049
1050 uvmexp.ncolors = newncolors;
1051 uvmexp.colormask = uvmexp.ncolors - 1;
1052
1053 ucpu = curcpu()->ci_data.cpu_uvm;
1054 for (lcv = 0; lcv < VM_NFREELIST; lcv++) {
1055 gpgfl.pgfl_buckets = (bucketarray + (lcv * newncolors));
1056 pgfl.pgfl_buckets = (cpuarray + (lcv * uvmexp.ncolors));
1057 uvm_page_init_buckets(&gpgfl);
1058 uvm_page_init_buckets(&pgfl);
1059 for (color = 0; color < ocolors; color++) {
1060 for (i = 0; i < PGFL_NQUEUES; i++) {
1061 while ((pg = LIST_FIRST(&uvm.page_free[
1062 lcv].pgfl_buckets[color].pgfl_queues[i]))
1063 != NULL) {
1064 LIST_REMOVE(pg, pageq.list); /* global */
1065 LIST_REMOVE(pg, listq.list); /* cpu */
1066 LIST_INSERT_HEAD(&gpgfl.pgfl_buckets[
1067 VM_PGCOLOR_BUCKET(pg)].pgfl_queues[
1068 i], pg, pageq.list);
1069 LIST_INSERT_HEAD(&pgfl.pgfl_buckets[
1070 VM_PGCOLOR_BUCKET(pg)].pgfl_queues[
1071 i], pg, listq.list);
1072 }
1073 }
1074 }
1075 uvm.page_free[lcv].pgfl_buckets = gpgfl.pgfl_buckets;
1076 ucpu->page_free[lcv].pgfl_buckets = pgfl.pgfl_buckets;
1077 }
1078
1079 if (have_recolored_pages) {
1080 mutex_spin_exit(&uvm_fpageqlock);
1081 free(oldbucketarray, M_VMPAGE);
1082 return;
1083 }
1084
1085 have_recolored_pages = true;
1086 mutex_spin_exit(&uvm_fpageqlock);
1087 }
1088
1089 /*
1090 * uvm_cpu_attach: initialize per-CPU data structures.
1091 */
1092
1093 void
1094 uvm_cpu_attach(struct cpu_info *ci)
1095 {
1096 struct pgflbucket *bucketarray;
1097 struct pgfreelist pgfl;
1098 struct uvm_cpu *ucpu;
1099 vsize_t bucketcount;
1100 int lcv;
1101
1102 if (CPU_IS_PRIMARY(ci)) {
1103 /* Already done in uvm_page_init(). */
1104 return;
1105 }
1106
1107 /* Add more reserve pages for this CPU. */
1108 uvmexp.reserve_kernel += vm_page_reserve_kernel;
1109
1110 /* Configure this CPU's free lists. */
1111 bucketcount = uvmexp.ncolors * VM_NFREELIST;
1112 bucketarray = malloc(bucketcount * sizeof(struct pgflbucket),
1113 M_VMPAGE, M_WAITOK);
1114 ucpu = kmem_zalloc(sizeof(*ucpu), KM_SLEEP);
1115 uvm.cpus[cpu_index(ci)] = ucpu;
1116 ci->ci_data.cpu_uvm = ucpu;
1117 for (lcv = 0; lcv < VM_NFREELIST; lcv++) {
1118 pgfl.pgfl_buckets = (bucketarray + (lcv * uvmexp.ncolors));
1119 uvm_page_init_buckets(&pgfl);
1120 ucpu->page_free[lcv].pgfl_buckets = pgfl.pgfl_buckets;
1121 }
1122 }
1123
1124 /*
1125 * uvm_pagealloc_pgfl: helper routine for uvm_pagealloc_strat
1126 */
1127
1128 static struct vm_page *
1129 uvm_pagealloc_pgfl(struct uvm_cpu *ucpu, int flist, int try1, int try2,
1130 int *trycolorp)
1131 {
1132 struct pgflist *freeq;
1133 struct vm_page *pg;
1134 int color, trycolor = *trycolorp;
1135 struct pgfreelist *gpgfl, *pgfl;
1136
1137 KASSERT(mutex_owned(&uvm_fpageqlock));
1138
1139 color = trycolor;
1140 pgfl = &ucpu->page_free[flist];
1141 gpgfl = &uvm.page_free[flist];
1142 do {
1143 /* cpu, try1 */
1144 if ((pg = LIST_FIRST((freeq =
1145 &pgfl->pgfl_buckets[color].pgfl_queues[try1]))) != NULL) {
1146 VM_FREE_PAGE_TO_CPU(pg)->pages[try1]--;
1147 uvmexp.cpuhit++;
1148 goto gotit;
1149 }
1150 /* global, try1 */
1151 if ((pg = LIST_FIRST((freeq =
1152 &gpgfl->pgfl_buckets[color].pgfl_queues[try1]))) != NULL) {
1153 VM_FREE_PAGE_TO_CPU(pg)->pages[try1]--;
1154 uvmexp.cpumiss++;
1155 goto gotit;
1156 }
1157 /* cpu, try2 */
1158 if ((pg = LIST_FIRST((freeq =
1159 &pgfl->pgfl_buckets[color].pgfl_queues[try2]))) != NULL) {
1160 VM_FREE_PAGE_TO_CPU(pg)->pages[try2]--;
1161 uvmexp.cpuhit++;
1162 goto gotit;
1163 }
1164 /* global, try2 */
1165 if ((pg = LIST_FIRST((freeq =
1166 &gpgfl->pgfl_buckets[color].pgfl_queues[try2]))) != NULL) {
1167 VM_FREE_PAGE_TO_CPU(pg)->pages[try2]--;
1168 uvmexp.cpumiss++;
1169 goto gotit;
1170 }
1171 color = (color + 1) & uvmexp.colormask;
1172 } while (color != trycolor);
1173
1174 return (NULL);
1175
1176 gotit:
1177 LIST_REMOVE(pg, pageq.list); /* global list */
1178 LIST_REMOVE(pg, listq.list); /* per-cpu list */
1179 uvmexp.free--;
1180
1181 /* update zero'd page count */
1182 if (pg->flags & PG_ZERO)
1183 uvmexp.zeropages--;
1184
1185 if (color == trycolor)
1186 uvmexp.colorhit++;
1187 else {
1188 uvmexp.colormiss++;
1189 *trycolorp = color;
1190 }
1191
1192 return (pg);
1193 }
1194
1195 /*
1196 * uvm_pagealloc_strat: allocate vm_page from a particular free list.
1197 *
1198 * => return null if no pages free
1199 * => wake up pagedaemon if number of free pages drops below low water mark
1200 * => if obj != NULL, obj must be locked (to put in obj's tree)
1201 * => if anon != NULL, anon must be locked (to put in anon)
1202 * => only one of obj or anon can be non-null
1203 * => caller must activate/deactivate page if it is not wired.
1204 * => free_list is ignored if strat == UVM_PGA_STRAT_NORMAL.
1205 * => policy decision: it is more important to pull a page off of the
1206 * appropriate priority free list than it is to get a zero'd or
1207 * unknown contents page. This is because we live with the
1208 * consequences of a bad free list decision for the entire
1209 * lifetime of the page, e.g. if the page comes from memory that
1210 * is slower to access.
1211 */
1212
1213 struct vm_page *
1214 uvm_pagealloc_strat(struct uvm_object *obj, voff_t off, struct vm_anon *anon,
1215 int flags, int strat, int free_list)
1216 {
1217 int lcv, try1, try2, zeroit = 0, color;
1218 struct uvm_cpu *ucpu;
1219 struct vm_page *pg;
1220 lwp_t *l;
1221
1222 KASSERT(obj == NULL || anon == NULL);
1223 KASSERT(anon == NULL || off == 0);
1224 KASSERT(off == trunc_page(off));
1225 KASSERT(obj == NULL || mutex_owned(&obj->vmobjlock));
1226 KASSERT(anon == NULL || mutex_owned(&anon->an_lock));
1227
1228 mutex_spin_enter(&uvm_fpageqlock);
1229
1230 /*
1231 * This implements a global round-robin page coloring
1232 * algorithm.
1233 *
1234 * XXXJRT: What about virtually-indexed caches?
1235 */
1236
1237 ucpu = curcpu()->ci_data.cpu_uvm;
1238 color = ucpu->page_free_nextcolor;
1239
1240 /*
1241 * check to see if we need to generate some free pages waking
1242 * the pagedaemon.
1243 */
1244
1245 uvm_kick_pdaemon();
1246
1247 /*
1248 * fail if any of these conditions is true:
1249 * [1] there really are no free pages, or
1250 * [2] only kernel "reserved" pages remain and
1251 * reserved pages have not been requested.
1252 * [3] only pagedaemon "reserved" pages remain and
1253 * the requestor isn't the pagedaemon.
1254 * we make kernel reserve pages available if called by a
1255 * kernel thread or a realtime thread.
1256 */
1257 l = curlwp;
1258 if (__predict_true(l != NULL) && lwp_eprio(l) >= PRI_KTHREAD) {
1259 flags |= UVM_PGA_USERESERVE;
1260 }
1261 if ((uvmexp.free <= uvmexp.reserve_kernel &&
1262 (flags & UVM_PGA_USERESERVE) == 0) ||
1263 (uvmexp.free <= uvmexp.reserve_pagedaemon &&
1264 curlwp != uvm.pagedaemon_lwp))
1265 goto fail;
1266
1267 #if PGFL_NQUEUES != 2
1268 #error uvm_pagealloc_strat needs to be updated
1269 #endif
1270
1271 /*
1272 * If we want a zero'd page, try the ZEROS queue first, otherwise
1273 * we try the UNKNOWN queue first.
1274 */
1275 if (flags & UVM_PGA_ZERO) {
1276 try1 = PGFL_ZEROS;
1277 try2 = PGFL_UNKNOWN;
1278 } else {
1279 try1 = PGFL_UNKNOWN;
1280 try2 = PGFL_ZEROS;
1281 }
1282
1283 again:
1284 switch (strat) {
1285 case UVM_PGA_STRAT_NORMAL:
1286 /* Check freelists: descending priority (ascending id) order */
1287 for (lcv = 0; lcv < VM_NFREELIST; lcv++) {
1288 pg = uvm_pagealloc_pgfl(ucpu, lcv,
1289 try1, try2, &color);
1290 if (pg != NULL)
1291 goto gotit;
1292 }
1293
1294 /* No pages free! */
1295 goto fail;
1296
1297 case UVM_PGA_STRAT_ONLY:
1298 case UVM_PGA_STRAT_FALLBACK:
1299 /* Attempt to allocate from the specified free list. */
1300 KASSERT(free_list >= 0 && free_list < VM_NFREELIST);
1301 pg = uvm_pagealloc_pgfl(ucpu, free_list,
1302 try1, try2, &color);
1303 if (pg != NULL)
1304 goto gotit;
1305
1306 /* Fall back, if possible. */
1307 if (strat == UVM_PGA_STRAT_FALLBACK) {
1308 strat = UVM_PGA_STRAT_NORMAL;
1309 goto again;
1310 }
1311
1312 /* No pages free! */
1313 goto fail;
1314
1315 default:
1316 panic("uvm_pagealloc_strat: bad strat %d", strat);
1317 /* NOTREACHED */
1318 }
1319
1320 gotit:
1321 /*
1322 * We now know which color we actually allocated from; set
1323 * the next color accordingly.
1324 */
1325
1326 ucpu->page_free_nextcolor = (color + 1) & uvmexp.colormask;
1327
1328 /*
1329 * update allocation statistics and remember if we have to
1330 * zero the page
1331 */
1332
1333 if (flags & UVM_PGA_ZERO) {
1334 if (pg->flags & PG_ZERO) {
1335 uvmexp.pga_zerohit++;
1336 zeroit = 0;
1337 } else {
1338 uvmexp.pga_zeromiss++;
1339 zeroit = 1;
1340 }
1341 if (ucpu->pages[PGFL_ZEROS] < ucpu->pages[PGFL_UNKNOWN]) {
1342 ucpu->page_idle_zero = vm_page_zero_enable;
1343 }
1344 }
1345 KASSERT(pg->pqflags == PQ_FREE);
1346
1347 pg->offset = off;
1348 pg->uobject = obj;
1349 pg->uanon = anon;
1350 pg->flags = PG_BUSY|PG_CLEAN|PG_FAKE;
1351 if (anon) {
1352 anon->an_page = pg;
1353 pg->pqflags = PQ_ANON;
1354 atomic_inc_uint(&uvmexp.anonpages);
1355 } else {
1356 if (obj) {
1357 uvm_pageinsert(obj, pg);
1358 }
1359 pg->pqflags = 0;
1360 }
1361 mutex_spin_exit(&uvm_fpageqlock);
1362
1363 #if defined(UVM_PAGE_TRKOWN)
1364 pg->owner_tag = NULL;
1365 #endif
1366 UVM_PAGE_OWN(pg, "new alloc");
1367
1368 if (flags & UVM_PGA_ZERO) {
1369 /*
1370 * A zero'd page is not clean. If we got a page not already
1371 * zero'd, then we have to zero it ourselves.
1372 */
1373 pg->flags &= ~PG_CLEAN;
1374 if (zeroit)
1375 pmap_zero_page(VM_PAGE_TO_PHYS(pg));
1376 }
1377
1378 return(pg);
1379
1380 fail:
1381 mutex_spin_exit(&uvm_fpageqlock);
1382 return (NULL);
1383 }
1384
1385 /*
1386 * uvm_pagereplace: replace a page with another
1387 *
1388 * => object must be locked
1389 */
1390
1391 void
1392 uvm_pagereplace(struct vm_page *oldpg, struct vm_page *newpg)
1393 {
1394 struct uvm_object *uobj = oldpg->uobject;
1395
1396 KASSERT((oldpg->flags & PG_TABLED) != 0);
1397 KASSERT(uobj != NULL);
1398 KASSERT((newpg->flags & PG_TABLED) == 0);
1399 KASSERT(newpg->uobject == NULL);
1400 KASSERT(mutex_owned(&uobj->vmobjlock));
1401
1402 newpg->uobject = uobj;
1403 newpg->offset = oldpg->offset;
1404
1405 uvm_pageremove_tree(uobj, oldpg);
1406 uvm_pageinsert_tree(uobj, newpg);
1407 uvm_pageinsert_list(uobj, newpg, oldpg);
1408 uvm_pageremove_list(uobj, oldpg);
1409 }
1410
1411 /*
1412 * uvm_pagerealloc: reallocate a page from one object to another
1413 *
1414 * => both objects must be locked
1415 */
1416
1417 void
1418 uvm_pagerealloc(struct vm_page *pg, struct uvm_object *newobj, voff_t newoff)
1419 {
1420 /*
1421 * remove it from the old object
1422 */
1423
1424 if (pg->uobject) {
1425 uvm_pageremove(pg->uobject, pg);
1426 }
1427
1428 /*
1429 * put it in the new object
1430 */
1431
1432 if (newobj) {
1433 pg->uobject = newobj;
1434 pg->offset = newoff;
1435 uvm_pageinsert(newobj, pg);
1436 }
1437 }
1438
1439 #ifdef DEBUG
1440 /*
1441 * check if page is zero-filled
1442 *
1443 * - called with free page queue lock held.
1444 */
1445 void
1446 uvm_pagezerocheck(struct vm_page *pg)
1447 {
1448 int *p, *ep;
1449
1450 KASSERT(uvm_zerocheckkva != 0);
1451 KASSERT(mutex_owned(&uvm_fpageqlock));
1452
1453 /*
1454 * XXX assuming pmap_kenter_pa and pmap_kremove never call
1455 * uvm page allocator.
1456 *
1457 * it might be better to have "CPU-local temporary map" pmap interface.
1458 */
1459 pmap_kenter_pa(uvm_zerocheckkva, VM_PAGE_TO_PHYS(pg), VM_PROT_READ, 0);
1460 p = (int *)uvm_zerocheckkva;
1461 ep = (int *)((char *)p + PAGE_SIZE);
1462 pmap_update(pmap_kernel());
1463 while (p < ep) {
1464 if (*p != 0)
1465 panic("PG_ZERO page isn't zero-filled");
1466 p++;
1467 }
1468 pmap_kremove(uvm_zerocheckkva, PAGE_SIZE);
1469 /*
1470 * pmap_update() is not necessary here because no one except us
1471 * uses this VA.
1472 */
1473 }
1474 #endif /* DEBUG */
1475
1476 /*
1477 * uvm_pagefree: free page
1478 *
1479 * => erase page's identity (i.e. remove from object)
1480 * => put page on free list
1481 * => caller must lock owning object (either anon or uvm_object)
1482 * => caller must lock page queues
1483 * => assumes all valid mappings of pg are gone
1484 */
1485
1486 void
1487 uvm_pagefree(struct vm_page *pg)
1488 {
1489 struct pgflist *pgfl;
1490 struct uvm_cpu *ucpu;
1491 int index, color, queue;
1492 bool iszero;
1493
1494 #ifdef DEBUG
1495 if (pg->uobject == (void *)0xdeadbeef &&
1496 pg->uanon == (void *)0xdeadbeef) {
1497 panic("uvm_pagefree: freeing free page %p", pg);
1498 }
1499 #endif /* DEBUG */
1500
1501 KASSERT((pg->flags & PG_PAGEOUT) == 0);
1502 KASSERT(!(pg->pqflags & PQ_FREE));
1503 KASSERT(mutex_owned(&uvm_pageqlock) || !uvmpdpol_pageisqueued_p(pg));
1504 KASSERT(pg->uobject == NULL || mutex_owned(&pg->uobject->vmobjlock));
1505 KASSERT(pg->uobject != NULL || pg->uanon == NULL ||
1506 mutex_owned(&pg->uanon->an_lock));
1507
1508 /*
1509 * if the page is loaned, resolve the loan instead of freeing.
1510 */
1511
1512 if (pg->loan_count) {
1513 KASSERT(pg->wire_count == 0);
1514
1515 /*
1516 * if the page is owned by an anon then we just want to
1517 * drop anon ownership. the kernel will free the page when
1518 * it is done with it. if the page is owned by an object,
1519 * remove it from the object and mark it dirty for the benefit
1520 * of possible anon owners.
1521 *
1522 * regardless of previous ownership, wakeup any waiters,
1523 * unbusy the page, and we're done.
1524 */
1525
1526 if (pg->uobject != NULL) {
1527 uvm_pageremove(pg->uobject, pg);
1528 pg->flags &= ~PG_CLEAN;
1529 } else if (pg->uanon != NULL) {
1530 if ((pg->pqflags & PQ_ANON) == 0) {
1531 pg->loan_count--;
1532 } else {
1533 pg->pqflags &= ~PQ_ANON;
1534 atomic_dec_uint(&uvmexp.anonpages);
1535 }
1536 pg->uanon->an_page = NULL;
1537 pg->uanon = NULL;
1538 }
1539 if (pg->flags & PG_WANTED) {
1540 wakeup(pg);
1541 }
1542 pg->flags &= ~(PG_WANTED|PG_BUSY|PG_RELEASED|PG_PAGER1);
1543 #ifdef UVM_PAGE_TRKOWN
1544 pg->owner_tag = NULL;
1545 #endif
1546 if (pg->loan_count) {
1547 KASSERT(pg->uobject == NULL);
1548 if (pg->uanon == NULL) {
1549 uvm_pagedequeue(pg);
1550 }
1551 return;
1552 }
1553 }
1554
1555 /*
1556 * remove page from its object or anon.
1557 */
1558
1559 if (pg->uobject != NULL) {
1560 uvm_pageremove(pg->uobject, pg);
1561 } else if (pg->uanon != NULL) {
1562 pg->uanon->an_page = NULL;
1563 atomic_dec_uint(&uvmexp.anonpages);
1564 }
1565
1566 /*
1567 * now remove the page from the queues.
1568 */
1569
1570 uvm_pagedequeue(pg);
1571
1572 /*
1573 * if the page was wired, unwire it now.
1574 */
1575
1576 if (pg->wire_count) {
1577 pg->wire_count = 0;
1578 uvmexp.wired--;
1579 }
1580
1581 /*
1582 * and put on free queue
1583 */
1584
1585 iszero = (pg->flags & PG_ZERO);
1586 index = uvm_page_lookup_freelist(pg);
1587 color = VM_PGCOLOR_BUCKET(pg);
1588 queue = (iszero ? PGFL_ZEROS : PGFL_UNKNOWN);
1589
1590 #ifdef DEBUG
1591 pg->uobject = (void *)0xdeadbeef;
1592 pg->uanon = (void *)0xdeadbeef;
1593 #endif
1594
1595 mutex_spin_enter(&uvm_fpageqlock);
1596 pg->pqflags = PQ_FREE;
1597
1598 #ifdef DEBUG
1599 if (iszero)
1600 uvm_pagezerocheck(pg);
1601 #endif /* DEBUG */
1602
1603
1604 /* global list */
1605 pgfl = &uvm.page_free[index].pgfl_buckets[color].pgfl_queues[queue];
1606 LIST_INSERT_HEAD(pgfl, pg, pageq.list);
1607 uvmexp.free++;
1608 if (iszero) {
1609 uvmexp.zeropages++;
1610 }
1611
1612 /* per-cpu list */
1613 ucpu = curcpu()->ci_data.cpu_uvm;
1614 pg->offset = (uintptr_t)ucpu;
1615 pgfl = &ucpu->page_free[index].pgfl_buckets[color].pgfl_queues[queue];
1616 LIST_INSERT_HEAD(pgfl, pg, listq.list);
1617 ucpu->pages[queue]++;
1618 if (ucpu->pages[PGFL_ZEROS] < ucpu->pages[PGFL_UNKNOWN]) {
1619 ucpu->page_idle_zero = vm_page_zero_enable;
1620 }
1621
1622 mutex_spin_exit(&uvm_fpageqlock);
1623 }
1624
1625 /*
1626 * uvm_page_unbusy: unbusy an array of pages.
1627 *
1628 * => pages must either all belong to the same object, or all belong to anons.
1629 * => if pages are object-owned, object must be locked.
1630 * => if pages are anon-owned, anons must be locked.
1631 * => caller must lock page queues if pages may be released.
1632 * => caller must make sure that anon-owned pages are not PG_RELEASED.
1633 */
1634
1635 void
1636 uvm_page_unbusy(struct vm_page **pgs, int npgs)
1637 {
1638 struct vm_page *pg;
1639 int i;
1640 UVMHIST_FUNC("uvm_page_unbusy"); UVMHIST_CALLED(ubchist);
1641
1642 for (i = 0; i < npgs; i++) {
1643 pg = pgs[i];
1644 if (pg == NULL || pg == PGO_DONTCARE) {
1645 continue;
1646 }
1647
1648 KASSERT(pg->uobject == NULL ||
1649 mutex_owned(&pg->uobject->vmobjlock));
1650 KASSERT(pg->uobject != NULL ||
1651 (pg->uanon != NULL && mutex_owned(&pg->uanon->an_lock)));
1652
1653 KASSERT(pg->flags & PG_BUSY);
1654 KASSERT((pg->flags & PG_PAGEOUT) == 0);
1655 if (pg->flags & PG_WANTED) {
1656 wakeup(pg);
1657 }
1658 if (pg->flags & PG_RELEASED) {
1659 UVMHIST_LOG(ubchist, "releasing pg %p", pg,0,0,0);
1660 KASSERT(pg->uobject != NULL ||
1661 (pg->uanon != NULL && pg->uanon->an_ref > 0));
1662 pg->flags &= ~PG_RELEASED;
1663 uvm_pagefree(pg);
1664 } else {
1665 UVMHIST_LOG(ubchist, "unbusying pg %p", pg,0,0,0);
1666 KASSERT((pg->flags & PG_FAKE) == 0);
1667 pg->flags &= ~(PG_WANTED|PG_BUSY);
1668 UVM_PAGE_OWN(pg, NULL);
1669 }
1670 }
1671 }
1672
1673 #if defined(UVM_PAGE_TRKOWN)
1674 /*
1675 * uvm_page_own: set or release page ownership
1676 *
1677 * => this is a debugging function that keeps track of who sets PG_BUSY
1678 * and where they do it. it can be used to track down problems
1679 * such a process setting "PG_BUSY" and never releasing it.
1680 * => page's object [if any] must be locked
1681 * => if "tag" is NULL then we are releasing page ownership
1682 */
1683 void
1684 uvm_page_own(struct vm_page *pg, const char *tag)
1685 {
1686 struct uvm_object *uobj;
1687 struct vm_anon *anon;
1688
1689 KASSERT((pg->flags & (PG_PAGEOUT|PG_RELEASED)) == 0);
1690
1691 uobj = pg->uobject;
1692 anon = pg->uanon;
1693 if (uobj != NULL) {
1694 KASSERT(mutex_owned(&uobj->vmobjlock));
1695 } else if (anon != NULL) {
1696 KASSERT(mutex_owned(&anon->an_lock));
1697 }
1698
1699 KASSERT((pg->flags & PG_WANTED) == 0);
1700
1701 /* gain ownership? */
1702 if (tag) {
1703 KASSERT((pg->flags & PG_BUSY) != 0);
1704 if (pg->owner_tag) {
1705 printf("uvm_page_own: page %p already owned "
1706 "by proc %d [%s]\n", pg,
1707 pg->owner, pg->owner_tag);
1708 panic("uvm_page_own");
1709 }
1710 pg->owner = (curproc) ? curproc->p_pid : (pid_t) -1;
1711 pg->lowner = (curlwp) ? curlwp->l_lid : (lwpid_t) -1;
1712 pg->owner_tag = tag;
1713 return;
1714 }
1715
1716 /* drop ownership */
1717 KASSERT((pg->flags & PG_BUSY) == 0);
1718 if (pg->owner_tag == NULL) {
1719 printf("uvm_page_own: dropping ownership of an non-owned "
1720 "page (%p)\n", pg);
1721 panic("uvm_page_own");
1722 }
1723 if (!uvmpdpol_pageisqueued_p(pg)) {
1724 KASSERT((pg->uanon == NULL && pg->uobject == NULL) ||
1725 pg->wire_count > 0);
1726 } else {
1727 KASSERT(pg->wire_count == 0);
1728 }
1729 pg->owner_tag = NULL;
1730 }
1731 #endif
1732
1733 /*
1734 * uvm_pageidlezero: zero free pages while the system is idle.
1735 *
1736 * => try to complete one color bucket at a time, to reduce our impact
1737 * on the CPU cache.
1738 * => we loop until we either reach the target or there is a lwp ready
1739 * to run, or MD code detects a reason to break early.
1740 */
1741 void
1742 uvm_pageidlezero(void)
1743 {
1744 struct vm_page *pg;
1745 struct pgfreelist *pgfl, *gpgfl;
1746 struct uvm_cpu *ucpu;
1747 int free_list, firstbucket, nextbucket;
1748
1749 ucpu = curcpu()->ci_data.cpu_uvm;
1750 if (!ucpu->page_idle_zero ||
1751 ucpu->pages[PGFL_UNKNOWN] < uvmexp.ncolors) {
1752 ucpu->page_idle_zero = false;
1753 return;
1754 }
1755 mutex_enter(&uvm_fpageqlock);
1756 firstbucket = ucpu->page_free_nextcolor;
1757 nextbucket = firstbucket;
1758 do {
1759 for (free_list = 0; free_list < VM_NFREELIST; free_list++) {
1760 if (sched_curcpu_runnable_p()) {
1761 goto quit;
1762 }
1763 pgfl = &ucpu->page_free[free_list];
1764 gpgfl = &uvm.page_free[free_list];
1765 while ((pg = LIST_FIRST(&pgfl->pgfl_buckets[
1766 nextbucket].pgfl_queues[PGFL_UNKNOWN])) != NULL) {
1767 if (sched_curcpu_runnable_p()) {
1768 goto quit;
1769 }
1770 LIST_REMOVE(pg, pageq.list); /* global list */
1771 LIST_REMOVE(pg, listq.list); /* per-cpu list */
1772 ucpu->pages[PGFL_UNKNOWN]--;
1773 uvmexp.free--;
1774 KASSERT(pg->pqflags == PQ_FREE);
1775 pg->pqflags = 0;
1776 mutex_spin_exit(&uvm_fpageqlock);
1777 #ifdef PMAP_PAGEIDLEZERO
1778 if (!PMAP_PAGEIDLEZERO(VM_PAGE_TO_PHYS(pg))) {
1779
1780 /*
1781 * The machine-dependent code detected
1782 * some reason for us to abort zeroing
1783 * pages, probably because there is a
1784 * process now ready to run.
1785 */
1786
1787 mutex_spin_enter(&uvm_fpageqlock);
1788 pg->pqflags = PQ_FREE;
1789 LIST_INSERT_HEAD(&gpgfl->pgfl_buckets[
1790 nextbucket].pgfl_queues[
1791 PGFL_UNKNOWN], pg, pageq.list);
1792 LIST_INSERT_HEAD(&pgfl->pgfl_buckets[
1793 nextbucket].pgfl_queues[
1794 PGFL_UNKNOWN], pg, listq.list);
1795 ucpu->pages[PGFL_UNKNOWN]++;
1796 uvmexp.free++;
1797 uvmexp.zeroaborts++;
1798 goto quit;
1799 }
1800 #else
1801 pmap_zero_page(VM_PAGE_TO_PHYS(pg));
1802 #endif /* PMAP_PAGEIDLEZERO */
1803 pg->flags |= PG_ZERO;
1804
1805 mutex_spin_enter(&uvm_fpageqlock);
1806 pg->pqflags = PQ_FREE;
1807 LIST_INSERT_HEAD(&gpgfl->pgfl_buckets[
1808 nextbucket].pgfl_queues[PGFL_ZEROS],
1809 pg, pageq.list);
1810 LIST_INSERT_HEAD(&pgfl->pgfl_buckets[
1811 nextbucket].pgfl_queues[PGFL_ZEROS],
1812 pg, listq.list);
1813 ucpu->pages[PGFL_ZEROS]++;
1814 uvmexp.free++;
1815 uvmexp.zeropages++;
1816 }
1817 }
1818 if (ucpu->pages[PGFL_UNKNOWN] < uvmexp.ncolors) {
1819 break;
1820 }
1821 nextbucket = (nextbucket + 1) & uvmexp.colormask;
1822 } while (nextbucket != firstbucket);
1823 ucpu->page_idle_zero = false;
1824 quit:
1825 mutex_spin_exit(&uvm_fpageqlock);
1826 }
1827
1828 /*
1829 * uvm_pagelookup: look up a page
1830 *
1831 * => caller should lock object to keep someone from pulling the page
1832 * out from under it
1833 */
1834
1835 struct vm_page *
1836 uvm_pagelookup(struct uvm_object *obj, voff_t off)
1837 {
1838 struct vm_page *pg;
1839
1840 KASSERT(mutex_owned(&obj->vmobjlock));
1841
1842 pg = rb_tree_find_node(&obj->rb_tree, &off);
1843
1844 KASSERT(pg == NULL || obj->uo_npages != 0);
1845 KASSERT(pg == NULL || (pg->flags & (PG_RELEASED|PG_PAGEOUT)) == 0 ||
1846 (pg->flags & PG_BUSY) != 0);
1847 return pg;
1848 }
1849
1850 /*
1851 * uvm_pagewire: wire the page, thus removing it from the daemon's grasp
1852 *
1853 * => caller must lock page queues
1854 */
1855
1856 void
1857 uvm_pagewire(struct vm_page *pg)
1858 {
1859 KASSERT(mutex_owned(&uvm_pageqlock));
1860 #if defined(READAHEAD_STATS)
1861 if ((pg->pqflags & PQ_READAHEAD) != 0) {
1862 uvm_ra_hit.ev_count++;
1863 pg->pqflags &= ~PQ_READAHEAD;
1864 }
1865 #endif /* defined(READAHEAD_STATS) */
1866 if (pg->wire_count == 0) {
1867 uvm_pagedequeue(pg);
1868 uvmexp.wired++;
1869 }
1870 pg->wire_count++;
1871 }
1872
1873 /*
1874 * uvm_pageunwire: unwire the page.
1875 *
1876 * => activate if wire count goes to zero.
1877 * => caller must lock page queues
1878 */
1879
1880 void
1881 uvm_pageunwire(struct vm_page *pg)
1882 {
1883 KASSERT(mutex_owned(&uvm_pageqlock));
1884 pg->wire_count--;
1885 if (pg->wire_count == 0) {
1886 uvm_pageactivate(pg);
1887 uvmexp.wired--;
1888 }
1889 }
1890
1891 /*
1892 * uvm_pagedeactivate: deactivate page
1893 *
1894 * => caller must lock page queues
1895 * => caller must check to make sure page is not wired
1896 * => object that page belongs to must be locked (so we can adjust pg->flags)
1897 * => caller must clear the reference on the page before calling
1898 */
1899
1900 void
1901 uvm_pagedeactivate(struct vm_page *pg)
1902 {
1903
1904 KASSERT(mutex_owned(&uvm_pageqlock));
1905 KASSERT(pg->wire_count != 0 || uvmpdpol_pageisqueued_p(pg));
1906 uvmpdpol_pagedeactivate(pg);
1907 }
1908
1909 /*
1910 * uvm_pageactivate: activate page
1911 *
1912 * => caller must lock page queues
1913 */
1914
1915 void
1916 uvm_pageactivate(struct vm_page *pg)
1917 {
1918
1919 KASSERT(mutex_owned(&uvm_pageqlock));
1920 #if defined(READAHEAD_STATS)
1921 if ((pg->pqflags & PQ_READAHEAD) != 0) {
1922 uvm_ra_hit.ev_count++;
1923 pg->pqflags &= ~PQ_READAHEAD;
1924 }
1925 #endif /* defined(READAHEAD_STATS) */
1926 if (pg->wire_count != 0) {
1927 return;
1928 }
1929 uvmpdpol_pageactivate(pg);
1930 }
1931
1932 /*
1933 * uvm_pagedequeue: remove a page from any paging queue
1934 */
1935
1936 void
1937 uvm_pagedequeue(struct vm_page *pg)
1938 {
1939
1940 if (uvmpdpol_pageisqueued_p(pg)) {
1941 KASSERT(mutex_owned(&uvm_pageqlock));
1942 }
1943
1944 uvmpdpol_pagedequeue(pg);
1945 }
1946
1947 /*
1948 * uvm_pageenqueue: add a page to a paging queue without activating.
1949 * used where a page is not really demanded (yet). eg. read-ahead
1950 */
1951
1952 void
1953 uvm_pageenqueue(struct vm_page *pg)
1954 {
1955
1956 KASSERT(mutex_owned(&uvm_pageqlock));
1957 if (pg->wire_count != 0) {
1958 return;
1959 }
1960 uvmpdpol_pageenqueue(pg);
1961 }
1962
1963 /*
1964 * uvm_pagezero: zero fill a page
1965 *
1966 * => if page is part of an object then the object should be locked
1967 * to protect pg->flags.
1968 */
1969
1970 void
1971 uvm_pagezero(struct vm_page *pg)
1972 {
1973 pg->flags &= ~PG_CLEAN;
1974 pmap_zero_page(VM_PAGE_TO_PHYS(pg));
1975 }
1976
1977 /*
1978 * uvm_pagecopy: copy a page
1979 *
1980 * => if page is part of an object then the object should be locked
1981 * to protect pg->flags.
1982 */
1983
1984 void
1985 uvm_pagecopy(struct vm_page *src, struct vm_page *dst)
1986 {
1987
1988 dst->flags &= ~PG_CLEAN;
1989 pmap_copy_page(VM_PAGE_TO_PHYS(src), VM_PAGE_TO_PHYS(dst));
1990 }
1991
1992 /*
1993 * uvm_pageismanaged: test it see that a page (specified by PA) is managed.
1994 */
1995
1996 bool
1997 uvm_pageismanaged(paddr_t pa)
1998 {
1999
2000 return (vm_physseg_find(atop(pa), NULL) != -1);
2001 }
2002
2003 /*
2004 * uvm_page_lookup_freelist: look up the free list for the specified page
2005 */
2006
2007 int
2008 uvm_page_lookup_freelist(struct vm_page *pg)
2009 {
2010 int lcv;
2011
2012 lcv = vm_physseg_find(atop(VM_PAGE_TO_PHYS(pg)), NULL);
2013 KASSERT(lcv != -1);
2014 return (VM_PHYSMEM_PTR(lcv)->free_list);
2015 }
2016
2017 #if defined(DDB) || defined(DEBUGPRINT)
2018
2019 /*
2020 * uvm_page_printit: actually print the page
2021 */
2022
2023 static const char page_flagbits[] = UVM_PGFLAGBITS;
2024 static const char page_pqflagbits[] = UVM_PQFLAGBITS;
2025
2026 void
2027 uvm_page_printit(struct vm_page *pg, bool full,
2028 void (*pr)(const char *, ...))
2029 {
2030 struct vm_page *tpg;
2031 struct uvm_object *uobj;
2032 struct pgflist *pgl;
2033 char pgbuf[128];
2034 char pqbuf[128];
2035
2036 (*pr)("PAGE %p:\n", pg);
2037 snprintb(pgbuf, sizeof(pgbuf), page_flagbits, pg->flags);
2038 snprintb(pqbuf, sizeof(pqbuf), page_pqflagbits, pg->pqflags);
2039 (*pr)(" flags=%s, pqflags=%s, wire_count=%d, pa=0x%lx\n",
2040 pgbuf, pqbuf, pg->wire_count, (long)VM_PAGE_TO_PHYS(pg));
2041 (*pr)(" uobject=%p, uanon=%p, offset=0x%llx loan_count=%d\n",
2042 pg->uobject, pg->uanon, (long long)pg->offset, pg->loan_count);
2043 #if defined(UVM_PAGE_TRKOWN)
2044 if (pg->flags & PG_BUSY)
2045 (*pr)(" owning process = %d, tag=%s\n",
2046 pg->owner, pg->owner_tag);
2047 else
2048 (*pr)(" page not busy, no owner\n");
2049 #else
2050 (*pr)(" [page ownership tracking disabled]\n");
2051 #endif
2052
2053 if (!full)
2054 return;
2055
2056 /* cross-verify object/anon */
2057 if ((pg->pqflags & PQ_FREE) == 0) {
2058 if (pg->pqflags & PQ_ANON) {
2059 if (pg->uanon == NULL || pg->uanon->an_page != pg)
2060 (*pr)(" >>> ANON DOES NOT POINT HERE <<< (%p)\n",
2061 (pg->uanon) ? pg->uanon->an_page : NULL);
2062 else
2063 (*pr)(" anon backpointer is OK\n");
2064 } else {
2065 uobj = pg->uobject;
2066 if (uobj) {
2067 (*pr)(" checking object list\n");
2068 TAILQ_FOREACH(tpg, &uobj->memq, listq.queue) {
2069 if (tpg == pg) {
2070 break;
2071 }
2072 }
2073 if (tpg)
2074 (*pr)(" page found on object list\n");
2075 else
2076 (*pr)(" >>> PAGE NOT FOUND ON OBJECT LIST! <<<\n");
2077 }
2078 }
2079 }
2080
2081 /* cross-verify page queue */
2082 if (pg->pqflags & PQ_FREE) {
2083 int fl = uvm_page_lookup_freelist(pg);
2084 int color = VM_PGCOLOR_BUCKET(pg);
2085 pgl = &uvm.page_free[fl].pgfl_buckets[color].pgfl_queues[
2086 ((pg)->flags & PG_ZERO) ? PGFL_ZEROS : PGFL_UNKNOWN];
2087 } else {
2088 pgl = NULL;
2089 }
2090
2091 if (pgl) {
2092 (*pr)(" checking pageq list\n");
2093 LIST_FOREACH(tpg, pgl, pageq.list) {
2094 if (tpg == pg) {
2095 break;
2096 }
2097 }
2098 if (tpg)
2099 (*pr)(" page found on pageq list\n");
2100 else
2101 (*pr)(" >>> PAGE NOT FOUND ON PAGEQ LIST! <<<\n");
2102 }
2103 }
2104
2105 /*
2106 * uvm_pages_printthem - print a summary of all managed pages
2107 */
2108
2109 void
2110 uvm_page_printall(void (*pr)(const char *, ...))
2111 {
2112 unsigned i;
2113 struct vm_page *pg;
2114
2115 (*pr)("%18s %4s %4s %18s %18s"
2116 #ifdef UVM_PAGE_TRKOWN
2117 " OWNER"
2118 #endif
2119 "\n", "PAGE", "FLAG", "PQ", "UOBJECT", "UANON");
2120 for (i = 0; i < vm_nphysmem; i++) {
2121 for (pg = VM_PHYSMEM_PTR(i)->pgs; pg < VM_PHYSMEM_PTR(i)->lastpg; pg++) {
2122 (*pr)("%18p %04x %04x %18p %18p",
2123 pg, pg->flags, pg->pqflags, pg->uobject,
2124 pg->uanon);
2125 #ifdef UVM_PAGE_TRKOWN
2126 if (pg->flags & PG_BUSY)
2127 (*pr)(" %d [%s]", pg->owner, pg->owner_tag);
2128 #endif
2129 (*pr)("\n");
2130 }
2131 }
2132 }
2133
2134 #endif /* DDB || DEBUGPRINT */
2135