]> git.saurik.com Git - apple/xnu.git/blame - osfmk/vm/vm_resident.c
xnu-201.5.tar.gz
[apple/xnu.git] / osfmk / vm / vm_resident.c
CommitLineData
1c79356b
A
1/*
2 * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * The contents of this file constitute Original Code as defined in and
7 * are subject to the Apple Public Source License Version 1.1 (the
8 * "License"). You may not use this file except in compliance with the
9 * License. Please obtain a copy of the License at
10 * http://www.apple.com/publicsource and read it before using this file.
11 *
12 * This Original Code and all software distributed under the License are
13 * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
14 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
15 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
17 * License for the specific language governing rights and limitations
18 * under the License.
19 *
20 * @APPLE_LICENSE_HEADER_END@
21 */
22/*
23 * @OSF_COPYRIGHT@
24 */
25/*
26 * Mach Operating System
27 * Copyright (c) 1991,1990,1989,1988,1987 Carnegie Mellon University
28 * All Rights Reserved.
29 *
30 * Permission to use, copy, modify and distribute this software and its
31 * documentation is hereby granted, provided that both the copyright
32 * notice and this permission notice appear in all copies of the
33 * software, derivative works or modified versions, and any portions
34 * thereof, and that both notices appear in supporting documentation.
35 *
36 * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
37 * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
38 * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
39 *
40 * Carnegie Mellon requests users of this software to return to
41 *
42 * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
43 * School of Computer Science
44 * Carnegie Mellon University
45 * Pittsburgh PA 15213-3890
46 *
47 * any improvements or extensions that they make and grant Carnegie Mellon
48 * the rights to redistribute these changes.
49 */
50/*
51 */
52/*
53 * File: vm/vm_page.c
54 * Author: Avadis Tevanian, Jr., Michael Wayne Young
55 *
56 * Resident memory management module.
57 */
58
59#include <mach/vm_prot.h>
60#include <mach/vm_statistics.h>
61#include <kern/counters.h>
62#include <kern/sched_prim.h>
63#include <kern/task.h>
64#include <kern/thread.h>
65#include <kern/zalloc.h>
66#include <kern/xpr.h>
67#include <vm/pmap.h>
68#include <vm/vm_init.h>
69#include <vm/vm_map.h>
70#include <vm/vm_page.h>
71#include <vm/vm_pageout.h>
72#include <vm/vm_kern.h> /* kernel_memory_allocate() */
73#include <kern/misc_protos.h>
74#include <zone_debug.h>
75#include <vm/cpm.h>
76
0b4e3aa0
A
77/* Variables used to indicate the relative age of pages in the
78 * inactive list
79 */
80
81int vm_page_ticket_roll = 0;
82int vm_page_ticket = 0;
1c79356b
A
83/*
84 * Associated with page of user-allocatable memory is a
85 * page structure.
86 */
87
88/*
89 * These variables record the values returned by vm_page_bootstrap,
90 * for debugging purposes. The implementation of pmap_steal_memory
91 * and pmap_startup here also uses them internally.
92 */
93
94vm_offset_t virtual_space_start;
95vm_offset_t virtual_space_end;
96int vm_page_pages;
97
98/*
99 * The vm_page_lookup() routine, which provides for fast
100 * (virtual memory object, offset) to page lookup, employs
101 * the following hash table. The vm_page_{insert,remove}
102 * routines install and remove associations in the table.
103 * [This table is often called the virtual-to-physical,
104 * or VP, table.]
105 */
106typedef struct {
107 vm_page_t pages;
108#if MACH_PAGE_HASH_STATS
109 int cur_count; /* current count */
110 int hi_count; /* high water mark */
111#endif /* MACH_PAGE_HASH_STATS */
112} vm_page_bucket_t;
113
114vm_page_bucket_t *vm_page_buckets; /* Array of buckets */
115unsigned int vm_page_bucket_count = 0; /* How big is array? */
116unsigned int vm_page_hash_mask; /* Mask for hash function */
117unsigned int vm_page_hash_shift; /* Shift for hash function */
118decl_simple_lock_data(,vm_page_bucket_lock)
119
120#if MACH_PAGE_HASH_STATS
121/* This routine is only for debug. It is intended to be called by
122 * hand by a developer using a kernel debugger. This routine prints
123 * out vm_page_hash table statistics to the kernel debug console.
124 */
125void
126hash_debug(void)
127{
128 int i;
129 int numbuckets = 0;
130 int highsum = 0;
131 int maxdepth = 0;
132
133 for (i = 0; i < vm_page_bucket_count; i++) {
134 if (vm_page_buckets[i].hi_count) {
135 numbuckets++;
136 highsum += vm_page_buckets[i].hi_count;
137 if (vm_page_buckets[i].hi_count > maxdepth)
138 maxdepth = vm_page_buckets[i].hi_count;
139 }
140 }
141 printf("Total number of buckets: %d\n", vm_page_bucket_count);
142 printf("Number used buckets: %d = %d%%\n",
143 numbuckets, 100*numbuckets/vm_page_bucket_count);
144 printf("Number unused buckets: %d = %d%%\n",
145 vm_page_bucket_count - numbuckets,
146 100*(vm_page_bucket_count-numbuckets)/vm_page_bucket_count);
147 printf("Sum of bucket max depth: %d\n", highsum);
148 printf("Average bucket depth: %d.%2d\n",
149 highsum/vm_page_bucket_count,
150 highsum%vm_page_bucket_count);
151 printf("Maximum bucket depth: %d\n", maxdepth);
152}
153#endif /* MACH_PAGE_HASH_STATS */
154
155/*
156 * The virtual page size is currently implemented as a runtime
157 * variable, but is constant once initialized using vm_set_page_size.
158 * This initialization must be done in the machine-dependent
159 * bootstrap sequence, before calling other machine-independent
160 * initializations.
161 *
162 * All references to the virtual page size outside this
163 * module must use the PAGE_SIZE, PAGE_MASK and PAGE_SHIFT
164 * constants.
165 */
166#ifndef PAGE_SIZE_FIXED
167vm_size_t page_size = 4096;
168vm_size_t page_mask = 4095;
169int page_shift = 12;
170#endif /* PAGE_SIZE_FIXED */
171
172/*
173 * Resident page structures are initialized from
174 * a template (see vm_page_alloc).
175 *
176 * When adding a new field to the virtual memory
177 * object structure, be sure to add initialization
178 * (see vm_page_bootstrap).
179 */
180struct vm_page vm_page_template;
181
182/*
183 * Resident pages that represent real memory
184 * are allocated from a free list.
185 */
186vm_page_t vm_page_queue_free;
187vm_page_t vm_page_queue_fictitious;
188decl_mutex_data(,vm_page_queue_free_lock)
189unsigned int vm_page_free_wanted;
190int vm_page_free_count;
191int vm_page_fictitious_count;
192
193unsigned int vm_page_free_count_minimum; /* debugging */
194
195/*
196 * Occasionally, the virtual memory system uses
197 * resident page structures that do not refer to
198 * real pages, for example to leave a page with
199 * important state information in the VP table.
200 *
201 * These page structures are allocated the way
202 * most other kernel structures are.
203 */
204zone_t vm_page_zone;
205decl_mutex_data(,vm_page_alloc_lock)
206
207/*
208 * Fictitious pages don't have a physical address,
209 * but we must initialize phys_addr to something.
210 * For debugging, this should be a strange value
211 * that the pmap module can recognize in assertions.
212 */
213vm_offset_t vm_page_fictitious_addr = (vm_offset_t) -1;
214
215/*
216 * Resident page structures are also chained on
217 * queues that are used by the page replacement
218 * system (pageout daemon). These queues are
219 * defined here, but are shared by the pageout
220 * module.
221 */
222queue_head_t vm_page_queue_active;
223queue_head_t vm_page_queue_inactive;
224decl_mutex_data(,vm_page_queue_lock)
225int vm_page_active_count;
226int vm_page_inactive_count;
227int vm_page_wire_count;
228int vm_page_gobble_count = 0;
229int vm_page_wire_count_warning = 0;
230int vm_page_gobble_count_warning = 0;
231
232/* the following fields are protected by the vm_page_queue_lock */
233queue_head_t vm_page_queue_limbo;
234int vm_page_limbo_count = 0; /* total pages in limbo */
235int vm_page_limbo_real_count = 0; /* real pages in limbo */
236int vm_page_pin_count = 0; /* number of pinned pages */
237
238decl_simple_lock_data(,vm_page_preppin_lock)
239
240/*
241 * Several page replacement parameters are also
242 * shared with this module, so that page allocation
243 * (done here in vm_page_alloc) can trigger the
244 * pageout daemon.
245 */
246int vm_page_free_target = 0;
247int vm_page_free_min = 0;
248int vm_page_inactive_target = 0;
249int vm_page_free_reserved = 0;
250int vm_page_laundry_count = 0;
251
252/*
253 * The VM system has a couple of heuristics for deciding
254 * that pages are "uninteresting" and should be placed
255 * on the inactive queue as likely candidates for replacement.
256 * These variables let the heuristics be controlled at run-time
257 * to make experimentation easier.
258 */
259
260boolean_t vm_page_deactivate_hint = TRUE;
261
262/*
263 * vm_set_page_size:
264 *
265 * Sets the page size, perhaps based upon the memory
266 * size. Must be called before any use of page-size
267 * dependent functions.
268 *
269 * Sets page_shift and page_mask from page_size.
270 */
271void
272vm_set_page_size(void)
273{
274#ifndef PAGE_SIZE_FIXED
275 page_mask = page_size - 1;
276
277 if ((page_mask & page_size) != 0)
278 panic("vm_set_page_size: page size not a power of two");
279
280 for (page_shift = 0; ; page_shift++)
281 if ((1 << page_shift) == page_size)
282 break;
283#endif /* PAGE_SIZE_FIXED */
284}
285
286/*
287 * vm_page_bootstrap:
288 *
289 * Initializes the resident memory module.
290 *
291 * Allocates memory for the page cells, and
292 * for the object/offset-to-page hash table headers.
293 * Each page cell is initialized and placed on the free list.
294 * Returns the range of available kernel virtual memory.
295 */
296
297void
298vm_page_bootstrap(
299 vm_offset_t *startp,
300 vm_offset_t *endp)
301{
302 register vm_page_t m;
303 int i;
304 unsigned int log1;
305 unsigned int log2;
306 unsigned int size;
307
308 /*
309 * Initialize the vm_page template.
310 */
311
312 m = &vm_page_template;
313 m->object = VM_OBJECT_NULL; /* reset later */
314 m->offset = 0; /* reset later */
315 m->wire_count = 0;
316
317 m->inactive = FALSE;
318 m->active = FALSE;
319 m->laundry = FALSE;
320 m->free = FALSE;
765c9de3 321 m->no_isync = TRUE;
1c79356b
A
322 m->reference = FALSE;
323 m->pageout = FALSE;
0b4e3aa0 324 m->dump_cleaning = FALSE;
1c79356b
A
325 m->list_req_pending = FALSE;
326
327 m->busy = TRUE;
328 m->wanted = FALSE;
329 m->tabled = FALSE;
330 m->fictitious = FALSE;
331 m->private = FALSE;
332 m->absent = FALSE;
333 m->error = FALSE;
334 m->dirty = FALSE;
335 m->cleaning = FALSE;
336 m->precious = FALSE;
337 m->clustered = FALSE;
338 m->lock_supplied = FALSE;
339 m->unusual = FALSE;
340 m->restart = FALSE;
1c79356b
A
341
342 m->phys_addr = 0; /* reset later */
343
344 m->page_lock = VM_PROT_NONE;
345 m->unlock_request = VM_PROT_NONE;
346 m->page_error = KERN_SUCCESS;
347
348 /*
349 * Initialize the page queues.
350 */
351
352 mutex_init(&vm_page_queue_free_lock, ETAP_VM_PAGEQ_FREE);
353 mutex_init(&vm_page_queue_lock, ETAP_VM_PAGEQ);
354 simple_lock_init(&vm_page_preppin_lock, ETAP_VM_PREPPIN);
355
356 vm_page_queue_free = VM_PAGE_NULL;
357 vm_page_queue_fictitious = VM_PAGE_NULL;
358 queue_init(&vm_page_queue_active);
359 queue_init(&vm_page_queue_inactive);
360 queue_init(&vm_page_queue_limbo);
361
362 vm_page_free_wanted = 0;
363
364 /*
365 * Steal memory for the map and zone subsystems.
366 */
367
368 vm_map_steal_memory();
369 zone_steal_memory();
370
371 /*
372 * Allocate (and initialize) the virtual-to-physical
373 * table hash buckets.
374 *
375 * The number of buckets should be a power of two to
376 * get a good hash function. The following computation
377 * chooses the first power of two that is greater
378 * than the number of physical pages in the system.
379 */
380
381 simple_lock_init(&vm_page_bucket_lock, ETAP_VM_BUCKET);
382
383 if (vm_page_bucket_count == 0) {
384 unsigned int npages = pmap_free_pages();
385
386 vm_page_bucket_count = 1;
387 while (vm_page_bucket_count < npages)
388 vm_page_bucket_count <<= 1;
389 }
390
391 vm_page_hash_mask = vm_page_bucket_count - 1;
392
393 /*
394 * Calculate object shift value for hashing algorithm:
395 * O = log2(sizeof(struct vm_object))
396 * B = log2(vm_page_bucket_count)
397 * hash shifts the object left by
398 * B/2 - O
399 */
400 size = vm_page_bucket_count;
401 for (log1 = 0; size > 1; log1++)
402 size /= 2;
403 size = sizeof(struct vm_object);
404 for (log2 = 0; size > 1; log2++)
405 size /= 2;
406 vm_page_hash_shift = log1/2 - log2 + 1;
407
408 if (vm_page_hash_mask & vm_page_bucket_count)
409 printf("vm_page_bootstrap: WARNING -- strange page hash\n");
410
411 vm_page_buckets = (vm_page_bucket_t *)
412 pmap_steal_memory(vm_page_bucket_count *
413 sizeof(vm_page_bucket_t));
414
415 for (i = 0; i < vm_page_bucket_count; i++) {
416 register vm_page_bucket_t *bucket = &vm_page_buckets[i];
417
418 bucket->pages = VM_PAGE_NULL;
419#if MACH_PAGE_HASH_STATS
420 bucket->cur_count = 0;
421 bucket->hi_count = 0;
422#endif /* MACH_PAGE_HASH_STATS */
423 }
424
425 /*
426 * Machine-dependent code allocates the resident page table.
427 * It uses vm_page_init to initialize the page frames.
428 * The code also returns to us the virtual space available
429 * to the kernel. We don't trust the pmap module
430 * to get the alignment right.
431 */
432
433 pmap_startup(&virtual_space_start, &virtual_space_end);
434 virtual_space_start = round_page(virtual_space_start);
435 virtual_space_end = trunc_page(virtual_space_end);
436
437 *startp = virtual_space_start;
438 *endp = virtual_space_end;
439
440 /*
441 * Compute the initial "wire" count.
442 * Up until now, the pages which have been set aside are not under
443 * the VM system's control, so although they aren't explicitly
444 * wired, they nonetheless can't be moved. At this moment,
445 * all VM managed pages are "free", courtesy of pmap_startup.
446 */
447 vm_page_wire_count = atop(mem_size) - vm_page_free_count; /* initial value */
448
449 printf("vm_page_bootstrap: %d free pages\n", vm_page_free_count);
450 vm_page_free_count_minimum = vm_page_free_count;
451}
452
453#ifndef MACHINE_PAGES
454/*
455 * We implement pmap_steal_memory and pmap_startup with the help
456 * of two simpler functions, pmap_virtual_space and pmap_next_page.
457 */
458
459vm_offset_t
460pmap_steal_memory(
461 vm_size_t size)
462{
463 vm_offset_t addr, vaddr, paddr;
464
465 /*
466 * We round the size to a round multiple.
467 */
468
469 size = (size + sizeof (void *) - 1) &~ (sizeof (void *) - 1);
470
471 /*
472 * If this is the first call to pmap_steal_memory,
473 * we have to initialize ourself.
474 */
475
476 if (virtual_space_start == virtual_space_end) {
477 pmap_virtual_space(&virtual_space_start, &virtual_space_end);
478
479 /*
480 * The initial values must be aligned properly, and
481 * we don't trust the pmap module to do it right.
482 */
483
484 virtual_space_start = round_page(virtual_space_start);
485 virtual_space_end = trunc_page(virtual_space_end);
486 }
487
488 /*
489 * Allocate virtual memory for this request.
490 */
491
492 addr = virtual_space_start;
493 virtual_space_start += size;
494
495 kprintf("pmap_steal_memory: %08X - %08X; size=%08X\n", addr, virtual_space_start, size); /* (TEST/DEBUG) */
496
497 /*
498 * Allocate and map physical pages to back new virtual pages.
499 */
500
501 for (vaddr = round_page(addr);
502 vaddr < addr + size;
503 vaddr += PAGE_SIZE) {
504 if (!pmap_next_page(&paddr))
505 panic("pmap_steal_memory");
506
507 /*
508 * XXX Logically, these mappings should be wired,
509 * but some pmap modules barf if they are.
510 */
511
512 pmap_enter(kernel_pmap, vaddr, paddr,
513 VM_PROT_READ|VM_PROT_WRITE, FALSE);
514 /*
515 * Account for newly stolen memory
516 */
517 vm_page_wire_count++;
518
519 }
520
521 return addr;
522}
523
524void
525pmap_startup(
526 vm_offset_t *startp,
527 vm_offset_t *endp)
528{
529 unsigned int i, npages, pages_initialized;
530 vm_page_t pages;
531 vm_offset_t paddr;
532
533 /*
534 * We calculate how many page frames we will have
535 * and then allocate the page structures in one chunk.
536 */
537
538 npages = ((PAGE_SIZE * pmap_free_pages() +
539 (round_page(virtual_space_start) - virtual_space_start)) /
540 (PAGE_SIZE + sizeof *pages));
541
542 pages = (vm_page_t) pmap_steal_memory(npages * sizeof *pages);
543
544 /*
545 * Initialize the page frames.
546 */
547
548 for (i = 0, pages_initialized = 0; i < npages; i++) {
549 if (!pmap_next_page(&paddr))
550 break;
551
552 vm_page_init(&pages[i], paddr);
553 vm_page_pages++;
554 pages_initialized++;
555 }
556
557 /*
558 * Release pages in reverse order so that physical pages
559 * initially get allocated in ascending addresses. This keeps
560 * the devices (which must address physical memory) happy if
561 * they require several consecutive pages.
562 */
563
564 for (i = pages_initialized; i > 0; i--) {
565 vm_page_release(&pages[i - 1]);
566 }
567
568 /*
569 * We have to re-align virtual_space_start,
570 * because pmap_steal_memory has been using it.
571 */
572
573 virtual_space_start = round_page(virtual_space_start);
574
575 *startp = virtual_space_start;
576 *endp = virtual_space_end;
577}
578#endif /* MACHINE_PAGES */
579
580/*
581 * Routine: vm_page_module_init
582 * Purpose:
583 * Second initialization pass, to be done after
584 * the basic VM system is ready.
585 */
586void
587vm_page_module_init(void)
588{
589 vm_page_zone = zinit((vm_size_t) sizeof(struct vm_page),
590 0, PAGE_SIZE, "vm pages");
591
592#if ZONE_DEBUG
593 zone_debug_disable(vm_page_zone);
594#endif /* ZONE_DEBUG */
595
596 zone_change(vm_page_zone, Z_EXPAND, FALSE);
597 zone_change(vm_page_zone, Z_EXHAUST, TRUE);
598 zone_change(vm_page_zone, Z_FOREIGN, TRUE);
599
600 /*
601 * Adjust zone statistics to account for the real pages allocated
602 * in vm_page_create(). [Q: is this really what we want?]
603 */
604 vm_page_zone->count += vm_page_pages;
605 vm_page_zone->cur_size += vm_page_pages * vm_page_zone->elem_size;
606
607 mutex_init(&vm_page_alloc_lock, ETAP_VM_PAGE_ALLOC);
608}
609
610/*
611 * Routine: vm_page_create
612 * Purpose:
613 * After the VM system is up, machine-dependent code
614 * may stumble across more physical memory. For example,
615 * memory that it was reserving for a frame buffer.
616 * vm_page_create turns this memory into available pages.
617 */
618
619void
620vm_page_create(
621 vm_offset_t start,
622 vm_offset_t end)
623{
624 vm_offset_t paddr;
625 vm_page_t m;
626
627 for (paddr = round_page(start);
628 paddr < trunc_page(end);
629 paddr += PAGE_SIZE) {
630 while ((m = (vm_page_t) vm_page_grab_fictitious())
631 == VM_PAGE_NULL)
632 vm_page_more_fictitious();
633
634 vm_page_init(m, paddr);
635 vm_page_pages++;
636 vm_page_release(m);
637 }
638}
639
640/*
641 * vm_page_hash:
642 *
643 * Distributes the object/offset key pair among hash buckets.
644 *
645 * NOTE: To get a good hash function, the bucket count should
646 * be a power of two.
647 */
648#define vm_page_hash(object, offset) (\
649 ( ((natural_t)(vm_offset_t)object<<vm_page_hash_shift) + (natural_t)atop(offset))\
650 & vm_page_hash_mask)
651
652/*
653 * vm_page_insert: [ internal use only ]
654 *
655 * Inserts the given mem entry into the object/object-page
656 * table and object list.
657 *
658 * The object must be locked.
659 */
660
661void
662vm_page_insert(
663 register vm_page_t mem,
664 register vm_object_t object,
665 register vm_object_offset_t offset)
666{
667 register vm_page_bucket_t *bucket;
668
669 XPR(XPR_VM_PAGE,
670 "vm_page_insert, object 0x%X offset 0x%X page 0x%X\n",
671 (integer_t)object, (integer_t)offset, (integer_t)mem, 0,0);
672
673 VM_PAGE_CHECK(mem);
674
675 if (mem->tabled)
676 panic("vm_page_insert");
677
678 assert(!object->internal || offset < object->size);
679
680 /* only insert "pageout" pages into "pageout" objects,
681 * and normal pages into normal objects */
682 assert(object->pageout == mem->pageout);
683
684 /*
685 * Record the object/offset pair in this page
686 */
687
688 mem->object = object;
689 mem->offset = offset;
690
691 /*
692 * Insert it into the object_object/offset hash table
693 */
694
695 bucket = &vm_page_buckets[vm_page_hash(object, offset)];
696 simple_lock(&vm_page_bucket_lock);
697 mem->next = bucket->pages;
698 bucket->pages = mem;
699#if MACH_PAGE_HASH_STATS
700 if (++bucket->cur_count > bucket->hi_count)
701 bucket->hi_count = bucket->cur_count;
702#endif /* MACH_PAGE_HASH_STATS */
703 simple_unlock(&vm_page_bucket_lock);
704
705 /*
706 * Now link into the object's list of backed pages.
707 */
708
709 queue_enter(&object->memq, mem, vm_page_t, listq);
710 mem->tabled = TRUE;
711
712 /*
713 * Show that the object has one more resident page.
714 */
715
716 object->resident_page_count++;
717}
718
719/*
720 * vm_page_replace:
721 *
722 * Exactly like vm_page_insert, except that we first
723 * remove any existing page at the given offset in object.
724 *
725 * The object and page queues must be locked.
726 */
727
728void
729vm_page_replace(
730 register vm_page_t mem,
731 register vm_object_t object,
732 register vm_object_offset_t offset)
733{
734 register vm_page_bucket_t *bucket;
735
736 VM_PAGE_CHECK(mem);
737
738 if (mem->tabled)
739 panic("vm_page_replace");
740
741 /*
742 * Record the object/offset pair in this page
743 */
744
745 mem->object = object;
746 mem->offset = offset;
747
748 /*
749 * Insert it into the object_object/offset hash table,
750 * replacing any page that might have been there.
751 */
752
753 bucket = &vm_page_buckets[vm_page_hash(object, offset)];
754 simple_lock(&vm_page_bucket_lock);
755 if (bucket->pages) {
756 vm_page_t *mp = &bucket->pages;
757 register vm_page_t m = *mp;
758 do {
759 if (m->object == object && m->offset == offset) {
760 /*
761 * Remove page from bucket and from object,
762 * and return it to the free list.
763 */
764 *mp = m->next;
765 queue_remove(&object->memq, m, vm_page_t,
766 listq);
767 m->tabled = FALSE;
768 object->resident_page_count--;
769
770 /*
771 * Return page to the free list.
772 * Note the page is not tabled now, so this
773 * won't self-deadlock on the bucket lock.
774 */
775
776 vm_page_free(m);
777 break;
778 }
779 mp = &m->next;
780 } while (m = *mp);
781 mem->next = bucket->pages;
782 } else {
783 mem->next = VM_PAGE_NULL;
784 }
785 bucket->pages = mem;
786 simple_unlock(&vm_page_bucket_lock);
787
788 /*
789 * Now link into the object's list of backed pages.
790 */
791
792 queue_enter(&object->memq, mem, vm_page_t, listq);
793 mem->tabled = TRUE;
794
795 /*
796 * And show that the object has one more resident
797 * page.
798 */
799
800 object->resident_page_count++;
801}
802
803/*
804 * vm_page_remove: [ internal use only ]
805 *
806 * Removes the given mem entry from the object/offset-page
807 * table and the object page list.
808 *
809 * The object and page must be locked.
810 */
811
812void
813vm_page_remove(
814 register vm_page_t mem)
815{
816 register vm_page_bucket_t *bucket;
817 register vm_page_t this;
818
819 XPR(XPR_VM_PAGE,
820 "vm_page_remove, object 0x%X offset 0x%X page 0x%X\n",
821 (integer_t)mem->object, (integer_t)mem->offset,
822 (integer_t)mem, 0,0);
823
824 assert(mem->tabled);
825 assert(!mem->cleaning);
826 VM_PAGE_CHECK(mem);
827
828 /*
829 * Remove from the object_object/offset hash table
830 */
831
832 bucket = &vm_page_buckets[vm_page_hash(mem->object, mem->offset)];
833 simple_lock(&vm_page_bucket_lock);
834 if ((this = bucket->pages) == mem) {
835 /* optimize for common case */
836
837 bucket->pages = mem->next;
838 } else {
839 register vm_page_t *prev;
840
841 for (prev = &this->next;
842 (this = *prev) != mem;
843 prev = &this->next)
844 continue;
845 *prev = this->next;
846 }
847#if MACH_PAGE_HASH_STATS
848 bucket->cur_count--;
849#endif /* MACH_PAGE_HASH_STATS */
850 simple_unlock(&vm_page_bucket_lock);
851
852 /*
853 * Now remove from the object's list of backed pages.
854 */
855
856 queue_remove(&mem->object->memq, mem, vm_page_t, listq);
857
858 /*
859 * And show that the object has one fewer resident
860 * page.
861 */
862
863 mem->object->resident_page_count--;
864
865 mem->tabled = FALSE;
866 mem->object = VM_OBJECT_NULL;
867 mem->offset = 0;
868}
869
870/*
871 * vm_page_lookup:
872 *
873 * Returns the page associated with the object/offset
874 * pair specified; if none is found, VM_PAGE_NULL is returned.
875 *
876 * The object must be locked. No side effects.
877 */
878
879vm_page_t
880vm_page_lookup(
881 register vm_object_t object,
882 register vm_object_offset_t offset)
883{
884 register vm_page_t mem;
885 register vm_page_bucket_t *bucket;
886
887 /*
888 * Search the hash table for this object/offset pair
889 */
890
891 bucket = &vm_page_buckets[vm_page_hash(object, offset)];
892
893 simple_lock(&vm_page_bucket_lock);
894 for (mem = bucket->pages; mem != VM_PAGE_NULL; mem = mem->next) {
895 VM_PAGE_CHECK(mem);
896 if ((mem->object == object) && (mem->offset == offset))
897 break;
898 }
899 simple_unlock(&vm_page_bucket_lock);
900 return(mem);
901}
902
903/*
904 * vm_page_rename:
905 *
906 * Move the given memory entry from its
907 * current object to the specified target object/offset.
908 *
909 * The object must be locked.
910 */
911void
912vm_page_rename(
913 register vm_page_t mem,
914 register vm_object_t new_object,
915 vm_object_offset_t new_offset)
916{
917 assert(mem->object != new_object);
918 /*
919 * Changes to mem->object require the page lock because
920 * the pageout daemon uses that lock to get the object.
921 */
922
923 XPR(XPR_VM_PAGE,
924 "vm_page_rename, new object 0x%X, offset 0x%X page 0x%X\n",
925 (integer_t)new_object, (integer_t)new_offset,
926 (integer_t)mem, 0,0);
927
928 vm_page_lock_queues();
929 vm_page_remove(mem);
930 vm_page_insert(mem, new_object, new_offset);
931 vm_page_unlock_queues();
932}
933
934/*
935 * vm_page_init:
936 *
937 * Initialize the fields in a new page.
938 * This takes a structure with random values and initializes it
939 * so that it can be given to vm_page_release or vm_page_insert.
940 */
941void
942vm_page_init(
943 vm_page_t mem,
944 vm_offset_t phys_addr)
945{
946 *mem = vm_page_template;
947 mem->phys_addr = phys_addr;
948}
949
950/*
951 * vm_page_grab_fictitious:
952 *
953 * Remove a fictitious page from the free list.
954 * Returns VM_PAGE_NULL if there are no free pages.
955 */
956int c_vm_page_grab_fictitious = 0;
957int c_vm_page_release_fictitious = 0;
958int c_vm_page_more_fictitious = 0;
959
960vm_page_t
961vm_page_grab_fictitious(void)
962{
963 register vm_page_t m;
964
965 m = (vm_page_t)zget(vm_page_zone);
966 if (m) {
1c79356b
A
967 vm_page_init(m, vm_page_fictitious_addr);
968 m->fictitious = TRUE;
1c79356b
A
969 }
970
971 c_vm_page_grab_fictitious++;
972 return m;
973}
974
975/*
976 * vm_page_release_fictitious:
977 *
978 * Release a fictitious page to the free list.
979 */
980
981void
982vm_page_release_fictitious(
983 register vm_page_t m)
984{
985 assert(!m->free);
986 assert(m->busy);
987 assert(m->fictitious);
988 assert(m->phys_addr == vm_page_fictitious_addr);
989
990 c_vm_page_release_fictitious++;
991
992 if (m->free)
993 panic("vm_page_release_fictitious");
994 m->free = TRUE;
995 zfree(vm_page_zone, (vm_offset_t)m);
996}
997
998/*
999 * vm_page_more_fictitious:
1000 *
1001 * Add more fictitious pages to the free list.
1002 * Allowed to block. This routine is way intimate
1003 * with the zones code, for several reasons:
1004 * 1. we need to carve some page structures out of physical
1005 * memory before zones work, so they _cannot_ come from
1006 * the zone_map.
1007 * 2. the zone needs to be collectable in order to prevent
1008 * growth without bound. These structures are used by
1009 * the device pager (by the hundreds and thousands), as
1010 * private pages for pageout, and as blocking pages for
1011 * pagein. Temporary bursts in demand should not result in
1012 * permanent allocation of a resource.
1013 * 3. To smooth allocation humps, we allocate single pages
1014 * with kernel_memory_allocate(), and cram them into the
1015 * zone. This also allows us to initialize the vm_page_t's
1016 * on the way into the zone, so that zget() always returns
1017 * an initialized structure. The zone free element pointer
1018 * and the free page pointer are both the first item in the
1019 * vm_page_t.
1020 * 4. By having the pages in the zone pre-initialized, we need
1021 * not keep 2 levels of lists. The garbage collector simply
1022 * scans our list, and reduces physical memory usage as it
1023 * sees fit.
1024 */
1025
1026void vm_page_more_fictitious(void)
1027{
1028 extern vm_map_t zone_map;
1029 register vm_page_t m;
1030 vm_offset_t addr;
1031 kern_return_t retval;
1032 int i;
1033
1034 c_vm_page_more_fictitious++;
1035
1c79356b
A
1036 /*
1037 * Allocate a single page from the zone_map. Do not wait if no physical
1038 * pages are immediately available, and do not zero the space. We need
1039 * our own blocking lock here to prevent having multiple,
1040 * simultaneous requests from piling up on the zone_map lock. Exactly
1041 * one (of our) threads should be potentially waiting on the map lock.
1042 * If winner is not vm-privileged, then the page allocation will fail,
1043 * and it will temporarily block here in the vm_page_wait().
1044 */
1045 mutex_lock(&vm_page_alloc_lock);
1046 /*
1047 * If another thread allocated space, just bail out now.
1048 */
1049 if (zone_free_count(vm_page_zone) > 5) {
1050 /*
1051 * The number "5" is a small number that is larger than the
1052 * number of fictitious pages that any single caller will
1053 * attempt to allocate. Otherwise, a thread will attempt to
1054 * acquire a fictitious page (vm_page_grab_fictitious), fail,
1055 * release all of the resources and locks already acquired,
1056 * and then call this routine. This routine finds the pages
1057 * that the caller released, so fails to allocate new space.
1058 * The process repeats infinitely. The largest known number
1059 * of fictitious pages required in this manner is 2. 5 is
1060 * simply a somewhat larger number.
1061 */
1062 mutex_unlock(&vm_page_alloc_lock);
1063 return;
1064 }
1065
1066 if ((retval = kernel_memory_allocate(zone_map,
1067 &addr, PAGE_SIZE, VM_PROT_ALL,
1068 KMA_KOBJECT|KMA_NOPAGEWAIT)) != KERN_SUCCESS) {
1069 /*
1070 * No page was available. Tell the pageout daemon, drop the
1071 * lock to give another thread a chance at it, and
1072 * wait for the pageout daemon to make progress.
1073 */
1074 mutex_unlock(&vm_page_alloc_lock);
1075 vm_page_wait(THREAD_UNINT);
1076 return;
1077 }
1078 /*
1079 * Initialize as many vm_page_t's as will fit on this page. This
1080 * depends on the zone code disturbing ONLY the first item of
1081 * each zone element.
1082 */
1083 m = (vm_page_t)addr;
1084 for (i = PAGE_SIZE/sizeof(struct vm_page); i > 0; i--) {
1085 vm_page_init(m, vm_page_fictitious_addr);
1086 m->fictitious = TRUE;
1087 m++;
1088 }
1089 zcram(vm_page_zone, addr, PAGE_SIZE);
1090 mutex_unlock(&vm_page_alloc_lock);
1091}
1092
1093/*
1094 * vm_page_convert:
1095 *
1096 * Attempt to convert a fictitious page into a real page.
1097 */
1098
1099boolean_t
1100vm_page_convert(
1101 register vm_page_t m)
1102{
1103 register vm_page_t real_m;
1104
1105 assert(m->busy);
1106 assert(m->fictitious);
1107 assert(!m->dirty);
1108
1109 real_m = vm_page_grab();
1110 if (real_m == VM_PAGE_NULL)
1111 return FALSE;
1112
1113 m->phys_addr = real_m->phys_addr;
1114 m->fictitious = FALSE;
765c9de3 1115 m->no_isync = TRUE;
1c79356b
A
1116
1117 vm_page_lock_queues();
1118 if (m->active)
1119 vm_page_active_count++;
1120 else if (m->inactive)
1121 vm_page_inactive_count++;
1122 vm_page_unlock_queues();
1123
1124 real_m->phys_addr = vm_page_fictitious_addr;
1125 real_m->fictitious = TRUE;
1126
1127 vm_page_release_fictitious(real_m);
1128 return TRUE;
1129}
1130
1131/*
1132 * vm_pool_low():
1133 *
1134 * Return true if it is not likely that a non-vm_privileged thread
1135 * can get memory without blocking. Advisory only, since the
1136 * situation may change under us.
1137 */
1138int
1139vm_pool_low(void)
1140{
1141 /* No locking, at worst we will fib. */
1142 return( vm_page_free_count < vm_page_free_reserved );
1143}
1144
1145/*
1146 * vm_page_grab:
1147 *
1148 * Remove a page from the free list.
1149 * Returns VM_PAGE_NULL if the free list is too small.
1150 */
1151
1152unsigned long vm_page_grab_count = 0; /* measure demand */
1153
1154vm_page_t
1155vm_page_grab(void)
1156{
1157 register vm_page_t mem;
1158
1159 mutex_lock(&vm_page_queue_free_lock);
1160 vm_page_grab_count++;
1161
1162 /*
1163 * Optionally produce warnings if the wire or gobble
1164 * counts exceed some threshold.
1165 */
1166 if (vm_page_wire_count_warning > 0
1167 && vm_page_wire_count >= vm_page_wire_count_warning) {
1168 printf("mk: vm_page_grab(): high wired page count of %d\n",
1169 vm_page_wire_count);
1170 assert(vm_page_wire_count < vm_page_wire_count_warning);
1171 }
1172 if (vm_page_gobble_count_warning > 0
1173 && vm_page_gobble_count >= vm_page_gobble_count_warning) {
1174 printf("mk: vm_page_grab(): high gobbled page count of %d\n",
1175 vm_page_gobble_count);
1176 assert(vm_page_gobble_count < vm_page_gobble_count_warning);
1177 }
1178
1179 /*
1180 * Only let privileged threads (involved in pageout)
1181 * dip into the reserved pool.
1182 */
1183
1184 if ((vm_page_free_count < vm_page_free_reserved) &&
1185 !current_thread()->vm_privilege) {
1186 mutex_unlock(&vm_page_queue_free_lock);
1187 mem = VM_PAGE_NULL;
1188 goto wakeup_pageout;
1189 }
1190
1191 while (vm_page_queue_free == VM_PAGE_NULL) {
1192 printf("vm_page_grab: no free pages, trouble expected...\n");
1193 mutex_unlock(&vm_page_queue_free_lock);
1194 VM_PAGE_WAIT();
1195 mutex_lock(&vm_page_queue_free_lock);
1196 }
1197
1198 if (--vm_page_free_count < vm_page_free_count_minimum)
1199 vm_page_free_count_minimum = vm_page_free_count;
1200 mem = vm_page_queue_free;
1201 vm_page_queue_free = (vm_page_t) mem->pageq.next;
1202 mem->free = FALSE;
0b4e3aa0 1203 mem->no_isync = TRUE;
1c79356b
A
1204 mutex_unlock(&vm_page_queue_free_lock);
1205
1206 /*
1207 * Decide if we should poke the pageout daemon.
1208 * We do this if the free count is less than the low
1209 * water mark, or if the free count is less than the high
1210 * water mark (but above the low water mark) and the inactive
1211 * count is less than its target.
1212 *
1213 * We don't have the counts locked ... if they change a little,
1214 * it doesn't really matter.
1215 */
1216
1217wakeup_pageout:
1218 if ((vm_page_free_count < vm_page_free_min) ||
1219 ((vm_page_free_count < vm_page_free_target) &&
1220 (vm_page_inactive_count < vm_page_inactive_target)))
1221 thread_wakeup((event_t) &vm_page_free_wanted);
1222
1223// dbgLog(mem->phys_addr, vm_page_free_count, vm_page_wire_count, 4); /* (TEST/DEBUG) */
1224
1225 return mem;
1226}
1227
1228/*
1229 * vm_page_release:
1230 *
1231 * Return a page to the free list.
1232 */
1233
1234void
1235vm_page_release(
1236 register vm_page_t mem)
1237{
1238 assert(!mem->private && !mem->fictitious);
1239
1240// dbgLog(mem->phys_addr, vm_page_free_count, vm_page_wire_count, 5); /* (TEST/DEBUG) */
1241
1242 mutex_lock(&vm_page_queue_free_lock);
1243 if (mem->free)
1244 panic("vm_page_release");
1245 mem->free = TRUE;
1246 mem->pageq.next = (queue_entry_t) vm_page_queue_free;
1247 vm_page_queue_free = mem;
1248 vm_page_free_count++;
1249
1250 /*
1251 * Check if we should wake up someone waiting for page.
1252 * But don't bother waking them unless they can allocate.
1253 *
1254 * We wakeup only one thread, to prevent starvation.
1255 * Because the scheduling system handles wait queues FIFO,
1256 * if we wakeup all waiting threads, one greedy thread
1257 * can starve multiple niceguy threads. When the threads
1258 * all wakeup, the greedy threads runs first, grabs the page,
1259 * and waits for another page. It will be the first to run
1260 * when the next page is freed.
1261 *
1262 * However, there is a slight danger here.
1263 * The thread we wake might not use the free page.
1264 * Then the other threads could wait indefinitely
1265 * while the page goes unused. To forestall this,
1266 * the pageout daemon will keep making free pages
1267 * as long as vm_page_free_wanted is non-zero.
1268 */
1269
1270 if ((vm_page_free_wanted > 0) &&
1271 (vm_page_free_count >= vm_page_free_reserved)) {
1272 vm_page_free_wanted--;
1273 thread_wakeup_one((event_t) &vm_page_free_count);
1274 }
1275
1276 mutex_unlock(&vm_page_queue_free_lock);
1277}
1278
1c79356b
A
1279/*
1280 * vm_page_wait:
1281 *
1282 * Wait for a page to become available.
1283 * If there are plenty of free pages, then we don't sleep.
1284 *
1285 * Returns:
1286 * TRUE: There may be another page, try again
1287 * FALSE: We were interrupted out of our wait, don't try again
1288 */
1289
1290boolean_t
1291vm_page_wait(
1292 int interruptible )
1293{
1294 /*
1295 * We can't use vm_page_free_reserved to make this
1296 * determination. Consider: some thread might
1297 * need to allocate two pages. The first allocation
1298 * succeeds, the second fails. After the first page is freed,
1299 * a call to vm_page_wait must really block.
1300 */
1301 kern_return_t wait_result;
0b4e3aa0 1302 int need_wakeup = 0;
1c79356b
A
1303
1304 mutex_lock(&vm_page_queue_free_lock);
1305 if (vm_page_free_count < vm_page_free_target) {
1306 if (vm_page_free_wanted++ == 0)
0b4e3aa0 1307 need_wakeup = 1;
1c79356b
A
1308 assert_wait((event_t)&vm_page_free_count, interruptible);
1309 mutex_unlock(&vm_page_queue_free_lock);
1310 counter(c_vm_page_wait_block++);
0b4e3aa0
A
1311
1312 if (need_wakeup)
1313 thread_wakeup((event_t)&vm_page_free_wanted);
1c79356b 1314 wait_result = thread_block((void (*)(void))0);
0b4e3aa0 1315
1c79356b
A
1316 return(wait_result == THREAD_AWAKENED);
1317 } else {
1318 mutex_unlock(&vm_page_queue_free_lock);
1319 return TRUE;
1320 }
1321}
1322
1323/*
1324 * vm_page_alloc:
1325 *
1326 * Allocate and return a memory cell associated
1327 * with this VM object/offset pair.
1328 *
1329 * Object must be locked.
1330 */
1331
1332vm_page_t
1333vm_page_alloc(
1334 vm_object_t object,
1335 vm_object_offset_t offset)
1336{
1337 register vm_page_t mem;
1338
1339 mem = vm_page_grab();
1340 if (mem == VM_PAGE_NULL)
1341 return VM_PAGE_NULL;
1342
1343 vm_page_insert(mem, object, offset);
1344
1345 return(mem);
1346}
1347
1c79356b
A
1348counter(unsigned int c_laundry_pages_freed = 0;)
1349
1350int vm_pagein_cluster_unused = 0;
1351boolean_t vm_page_free_verify = FALSE;
1352/*
1353 * vm_page_free:
1354 *
1355 * Returns the given page to the free list,
1356 * disassociating it with any VM object.
1357 *
1358 * Object and page queues must be locked prior to entry.
1359 */
1360void
1361vm_page_free(
1362 register vm_page_t mem)
1363{
1364 vm_object_t object = mem->object;
1365
1366 assert(!mem->free);
1367 assert(!mem->cleaning);
1368 assert(!mem->pageout);
1369 assert(!vm_page_free_verify || pmap_verify_free(mem->phys_addr));
1370
1371 if (mem->tabled)
1372 vm_page_remove(mem); /* clears tabled, object, offset */
1373 VM_PAGE_QUEUES_REMOVE(mem); /* clears active or inactive */
1374
1375 if (mem->clustered) {
1376 mem->clustered = FALSE;
1377 vm_pagein_cluster_unused++;
1378 }
1379
1380 if (mem->wire_count) {
1381 if (!mem->private && !mem->fictitious)
1382 vm_page_wire_count--;
1383 mem->wire_count = 0;
1384 assert(!mem->gobbled);
1385 } else if (mem->gobbled) {
1386 if (!mem->private && !mem->fictitious)
1387 vm_page_wire_count--;
1388 vm_page_gobble_count--;
1389 }
1390 mem->gobbled = FALSE;
1391
1392 if (mem->laundry) {
1393 extern int vm_page_laundry_min;
1394 vm_page_laundry_count--;
1395 mem->laundry = FALSE; /* laundry is now clear */
1396 counter(++c_laundry_pages_freed);
1397 if (vm_page_laundry_count < vm_page_laundry_min) {
1398 vm_page_laundry_min = 0;
1399 thread_wakeup((event_t) &vm_page_laundry_count);
1400 }
1401 }
1402
1403 mem->discard_request = FALSE;
1404
1405 PAGE_WAKEUP(mem); /* clears wanted */
1406
1407 if (mem->absent)
1408 vm_object_absent_release(object);
1409
0b4e3aa0 1410 /* Some of these may be unnecessary */
1c79356b
A
1411 mem->page_lock = 0;
1412 mem->unlock_request = 0;
1413 mem->busy = TRUE;
1414 mem->absent = FALSE;
1415 mem->error = FALSE;
1416 mem->dirty = FALSE;
1417 mem->precious = FALSE;
1418 mem->reference = FALSE;
1419
1420 mem->page_error = KERN_SUCCESS;
1421
1422 if (mem->private) {
1423 mem->private = FALSE;
1424 mem->fictitious = TRUE;
1425 mem->phys_addr = vm_page_fictitious_addr;
1426 }
1427 if (mem->fictitious) {
1428 vm_page_release_fictitious(mem);
1429 } else {
1430 vm_page_init(mem, mem->phys_addr);
1431 vm_page_release(mem);
1432 }
1433}
1434
1435/*
1436 * vm_page_wire:
1437 *
1438 * Mark this page as wired down by yet
1439 * another map, removing it from paging queues
1440 * as necessary.
1441 *
1442 * The page's object and the page queues must be locked.
1443 */
1444void
1445vm_page_wire(
1446 register vm_page_t mem)
1447{
1448
1449// dbgLog(current_act(), mem->offset, mem->object, 1); /* (TEST/DEBUG) */
1450
1451 VM_PAGE_CHECK(mem);
1452
1453 if (mem->wire_count == 0) {
1454 VM_PAGE_QUEUES_REMOVE(mem);
1455 if (!mem->private && !mem->fictitious && !mem->gobbled)
1456 vm_page_wire_count++;
1457 if (mem->gobbled)
1458 vm_page_gobble_count--;
1459 mem->gobbled = FALSE;
1460 }
1461 assert(!mem->gobbled);
1462 mem->wire_count++;
1463}
1464
1465/*
1466 * vm_page_gobble:
1467 *
1468 * Mark this page as consumed by the vm/ipc/xmm subsystems.
1469 *
1470 * Called only for freshly vm_page_grab()ed pages - w/ nothing locked.
1471 */
1472void
1473vm_page_gobble(
1474 register vm_page_t mem)
1475{
1476 vm_page_lock_queues();
1477 VM_PAGE_CHECK(mem);
1478
1479 assert(!mem->gobbled);
1480 assert(mem->wire_count == 0);
1481
1482 if (!mem->gobbled && mem->wire_count == 0) {
1483 if (!mem->private && !mem->fictitious)
1484 vm_page_wire_count++;
1485 }
1486 vm_page_gobble_count++;
1487 mem->gobbled = TRUE;
1488 vm_page_unlock_queues();
1489}
1490
1491/*
1492 * vm_page_unwire:
1493 *
1494 * Release one wiring of this page, potentially
1495 * enabling it to be paged again.
1496 *
1497 * The page's object and the page queues must be locked.
1498 */
1499void
1500vm_page_unwire(
1501 register vm_page_t mem)
1502{
1503
1504// dbgLog(current_act(), mem->offset, mem->object, 0); /* (TEST/DEBUG) */
1505
1506 VM_PAGE_CHECK(mem);
1507 assert(mem->wire_count > 0);
1508
1509 if (--mem->wire_count == 0) {
1510 assert(!mem->private && !mem->fictitious);
1511 vm_page_wire_count--;
1512 queue_enter(&vm_page_queue_active, mem, vm_page_t, pageq);
1513 vm_page_active_count++;
1514 mem->active = TRUE;
1515 mem->reference = TRUE;
1516 }
1517}
1518
1519/*
1520 * vm_page_deactivate:
1521 *
1522 * Returns the given page to the inactive list,
1523 * indicating that no physical maps have access
1524 * to this page. [Used by the physical mapping system.]
1525 *
1526 * The page queues must be locked.
1527 */
1528void
1529vm_page_deactivate(
1530 register vm_page_t m)
1531{
1532 VM_PAGE_CHECK(m);
1533
1534// dbgLog(m->phys_addr, vm_page_free_count, vm_page_wire_count, 6); /* (TEST/DEBUG) */
1535
1536 /*
1537 * This page is no longer very interesting. If it was
1538 * interesting (active or inactive/referenced), then we
1539 * clear the reference bit and (re)enter it in the
1540 * inactive queue. Note wired pages should not have
1541 * their reference bit cleared.
1542 */
1543 if (m->gobbled) { /* can this happen? */
1544 assert(m->wire_count == 0);
1545 if (!m->private && !m->fictitious)
1546 vm_page_wire_count--;
1547 vm_page_gobble_count--;
1548 m->gobbled = FALSE;
1549 }
1550 if (m->private || (m->wire_count != 0))
1551 return;
1552 if (m->active || (m->inactive && m->reference)) {
1553 if (!m->fictitious && !m->absent)
1554 pmap_clear_reference(m->phys_addr);
1555 m->reference = FALSE;
1556 VM_PAGE_QUEUES_REMOVE(m);
1557 }
1558 if (m->wire_count == 0 && !m->inactive) {
0b4e3aa0
A
1559 m->page_ticket = vm_page_ticket;
1560 vm_page_ticket_roll++;
1561
1562 if(vm_page_ticket_roll == VM_PAGE_TICKETS_IN_ROLL) {
1563 vm_page_ticket_roll = 0;
1564 if(vm_page_ticket == VM_PAGE_TICKET_ROLL_IDS)
1565 vm_page_ticket= 0;
1566 else
1567 vm_page_ticket++;
1568 }
1569
1c79356b
A
1570 queue_enter(&vm_page_queue_inactive, m, vm_page_t, pageq);
1571 m->inactive = TRUE;
1572 if (!m->fictitious)
1573 vm_page_inactive_count++;
1574 }
1575}
1576
1577/*
1578 * vm_page_activate:
1579 *
1580 * Put the specified page on the active list (if appropriate).
1581 *
1582 * The page queues must be locked.
1583 */
1584
1585void
1586vm_page_activate(
1587 register vm_page_t m)
1588{
1589 VM_PAGE_CHECK(m);
1590
1591 if (m->gobbled) {
1592 assert(m->wire_count == 0);
1593 if (!m->private && !m->fictitious)
1594 vm_page_wire_count--;
1595 vm_page_gobble_count--;
1596 m->gobbled = FALSE;
1597 }
1598 if (m->private)
1599 return;
1600
1601 if (m->inactive) {
1602 queue_remove(&vm_page_queue_inactive, m, vm_page_t, pageq);
1603 if (!m->fictitious)
1604 vm_page_inactive_count--;
1605 m->inactive = FALSE;
1606 }
1607 if (m->wire_count == 0) {
1608 if (m->active)
1609 panic("vm_page_activate: already active");
1610
1611 queue_enter(&vm_page_queue_active, m, vm_page_t, pageq);
1612 m->active = TRUE;
1613 m->reference = TRUE;
1614 if (!m->fictitious)
1615 vm_page_active_count++;
1616 }
1617}
1618
1619/*
1620 * vm_page_part_zero_fill:
1621 *
1622 * Zero-fill a part of the page.
1623 */
1624void
1625vm_page_part_zero_fill(
1626 vm_page_t m,
1627 vm_offset_t m_pa,
1628 vm_size_t len)
1629{
1630 vm_page_t tmp;
1631
1632 VM_PAGE_CHECK(m);
1633#ifdef PMAP_ZERO_PART_PAGE_IMPLEMENTED
1634 pmap_zero_part_page(m->phys_addr, m_pa, len);
1635#else
1636 while (1) {
1637 tmp = vm_page_grab();
1638 if (tmp == VM_PAGE_NULL) {
1639 vm_page_wait(THREAD_UNINT);
1640 continue;
1641 }
1642 break;
1643 }
1644 vm_page_zero_fill(tmp);
1645 if(m_pa != 0) {
1646 vm_page_part_copy(m, 0, tmp, 0, m_pa);
1647 }
1648 if((m_pa + len) < PAGE_SIZE) {
1649 vm_page_part_copy(m, m_pa + len, tmp,
1650 m_pa + len, PAGE_SIZE - (m_pa + len));
1651 }
1652 vm_page_copy(tmp,m);
1653 vm_page_lock_queues();
1654 vm_page_free(tmp);
1655 vm_page_unlock_queues();
1656#endif
1657
1658}
1659
1660/*
1661 * vm_page_zero_fill:
1662 *
1663 * Zero-fill the specified page.
1664 */
1665void
1666vm_page_zero_fill(
1667 vm_page_t m)
1668{
1669 XPR(XPR_VM_PAGE,
1670 "vm_page_zero_fill, object 0x%X offset 0x%X page 0x%X\n",
1671 (integer_t)m->object, (integer_t)m->offset, (integer_t)m, 0,0);
1672
1673 VM_PAGE_CHECK(m);
1674
1675 pmap_zero_page(m->phys_addr);
1676}
1677
1678/*
1679 * vm_page_part_copy:
1680 *
1681 * copy part of one page to another
1682 */
1683
1684void
1685vm_page_part_copy(
1686 vm_page_t src_m,
1687 vm_offset_t src_pa,
1688 vm_page_t dst_m,
1689 vm_offset_t dst_pa,
1690 vm_size_t len)
1691{
1692 VM_PAGE_CHECK(src_m);
1693 VM_PAGE_CHECK(dst_m);
1694
1695 pmap_copy_part_page(src_m->phys_addr, src_pa,
1696 dst_m->phys_addr, dst_pa, len);
1697}
1698
1699/*
1700 * vm_page_copy:
1701 *
1702 * Copy one page to another
1703 */
1704
1705void
1706vm_page_copy(
1707 vm_page_t src_m,
1708 vm_page_t dest_m)
1709{
1710 XPR(XPR_VM_PAGE,
1711 "vm_page_copy, object 0x%X offset 0x%X to object 0x%X offset 0x%X\n",
1712 (integer_t)src_m->object, src_m->offset,
1713 (integer_t)dest_m->object, dest_m->offset,
1714 0);
1715
1716 VM_PAGE_CHECK(src_m);
1717 VM_PAGE_CHECK(dest_m);
1718
1719 pmap_copy_page(src_m->phys_addr, dest_m->phys_addr);
1720}
1721
1c79356b
A
1722/*
1723 * Currently, this is a primitive allocator that grabs
1724 * free pages from the system, sorts them by physical
1725 * address, then searches for a region large enough to
1726 * satisfy the user's request.
1727 *
1728 * Additional levels of effort:
1729 * + steal clean active/inactive pages
1730 * + force pageouts of dirty pages
1731 * + maintain a map of available physical
1732 * memory
1733 */
1734
1735#define SET_NEXT_PAGE(m,n) ((m)->pageq.next = (struct queue_entry *) (n))
1736
1737#if MACH_ASSERT
1738int vm_page_verify_contiguous(
1739 vm_page_t pages,
1740 unsigned int npages);
1741#endif /* MACH_ASSERT */
1742
1743cpm_counter(unsigned int vpfls_pages_handled = 0;)
1744cpm_counter(unsigned int vpfls_head_insertions = 0;)
1745cpm_counter(unsigned int vpfls_tail_insertions = 0;)
1746cpm_counter(unsigned int vpfls_general_insertions = 0;)
1747cpm_counter(unsigned int vpfc_failed = 0;)
1748cpm_counter(unsigned int vpfc_satisfied = 0;)
1749
1750/*
1751 * Sort free list by ascending physical address,
1752 * using a not-particularly-bright sort algorithm.
1753 * Caller holds vm_page_queue_free_lock.
1754 */
1755static void
1756vm_page_free_list_sort(void)
1757{
1758 vm_page_t sort_list;
1759 vm_page_t sort_list_end;
1760 vm_page_t m, m1, *prev, next_m;
1761 vm_offset_t addr;
1762#if MACH_ASSERT
1763 unsigned int npages;
1764 int old_free_count;
1765#endif /* MACH_ASSERT */
1766
1767#if MACH_ASSERT
1768 /*
1769 * Verify pages in the free list..
1770 */
1771 npages = 0;
1772 for (m = vm_page_queue_free; m != VM_PAGE_NULL; m = NEXT_PAGE(m))
1773 ++npages;
1774 if (npages != vm_page_free_count)
1775 panic("vm_sort_free_list: prelim: npages %d free_count %d",
1776 npages, vm_page_free_count);
1777 old_free_count = vm_page_free_count;
1778#endif /* MACH_ASSERT */
1779
1780 sort_list = sort_list_end = vm_page_queue_free;
1781 m = NEXT_PAGE(vm_page_queue_free);
1782 SET_NEXT_PAGE(vm_page_queue_free, VM_PAGE_NULL);
1783 cpm_counter(vpfls_pages_handled = 0);
1784 while (m != VM_PAGE_NULL) {
1785 cpm_counter(++vpfls_pages_handled);
1786 next_m = NEXT_PAGE(m);
1787 if (m->phys_addr < sort_list->phys_addr) {
1788 cpm_counter(++vpfls_head_insertions);
1789 SET_NEXT_PAGE(m, sort_list);
1790 sort_list = m;
1791 } else if (m->phys_addr > sort_list_end->phys_addr) {
1792 cpm_counter(++vpfls_tail_insertions);
1793 SET_NEXT_PAGE(sort_list_end, m);
1794 SET_NEXT_PAGE(m, VM_PAGE_NULL);
1795 sort_list_end = m;
1796 } else {
1797 cpm_counter(++vpfls_general_insertions);
1798 /* general sorted list insertion */
1799 prev = &sort_list;
1800 for (m1=sort_list; m1!=VM_PAGE_NULL; m1=NEXT_PAGE(m1)) {
1801 if (m1->phys_addr > m->phys_addr) {
1802 if (*prev != m1)
1803 panic("vm_sort_free_list: ugh");
1804 SET_NEXT_PAGE(m, *prev);
1805 *prev = m;
1806 break;
1807 }
1808 prev = (vm_page_t *) &m1->pageq.next;
1809 }
1810 }
1811 m = next_m;
1812 }
1813
1814#if MACH_ASSERT
1815 /*
1816 * Verify that pages are sorted into ascending order.
1817 */
1818 for (m = sort_list, npages = 0; m != VM_PAGE_NULL; m = NEXT_PAGE(m)) {
1819 if (m != sort_list &&
1820 m->phys_addr <= addr) {
1821 printf("m 0x%x addr 0x%x\n", m, addr);
1822 panic("vm_sort_free_list");
1823 }
1824 addr = m->phys_addr;
1825 ++npages;
1826 }
1827 if (old_free_count != vm_page_free_count)
1828 panic("vm_sort_free_list: old_free %d free_count %d",
1829 old_free_count, vm_page_free_count);
1830 if (npages != vm_page_free_count)
1831 panic("vm_sort_free_list: npages %d free_count %d",
1832 npages, vm_page_free_count);
1833#endif /* MACH_ASSERT */
1834
1835 vm_page_queue_free = sort_list;
1836}
1837
1838
1839#if MACH_ASSERT
1840/*
1841 * Check that the list of pages is ordered by
1842 * ascending physical address and has no holes.
1843 */
1844int
1845vm_page_verify_contiguous(
1846 vm_page_t pages,
1847 unsigned int npages)
1848{
1849 register vm_page_t m;
1850 unsigned int page_count;
1851 vm_offset_t prev_addr;
1852
1853 prev_addr = pages->phys_addr;
1854 page_count = 1;
1855 for (m = NEXT_PAGE(pages); m != VM_PAGE_NULL; m = NEXT_PAGE(m)) {
1856 if (m->phys_addr != prev_addr + page_size) {
1857 printf("m 0x%x prev_addr 0x%x, current addr 0x%x\n",
1858 m, prev_addr, m->phys_addr);
1859 printf("pages 0x%x page_count %d\n", pages, page_count);
1860 panic("vm_page_verify_contiguous: not contiguous!");
1861 }
1862 prev_addr = m->phys_addr;
1863 ++page_count;
1864 }
1865 if (page_count != npages) {
1866 printf("pages 0x%x actual count 0x%x but requested 0x%x\n",
1867 pages, page_count, npages);
1868 panic("vm_page_verify_contiguous: count error");
1869 }
1870 return 1;
1871}
1872#endif /* MACH_ASSERT */
1873
1874
1875/*
1876 * Find a region large enough to contain at least npages
1877 * of contiguous physical memory.
1878 *
1879 * Requirements:
1880 * - Called while holding vm_page_queue_free_lock.
1881 * - Doesn't respect vm_page_free_reserved; caller
1882 * must not ask for more pages than are legal to grab.
1883 *
1884 * Returns a pointer to a list of gobbled pages or VM_PAGE_NULL.
1885 *
1886 */
1887static vm_page_t
1888vm_page_find_contiguous(
1889 int npages)
1890{
1891 vm_page_t m, *contig_prev, *prev_ptr;
1892 vm_offset_t prev_addr;
1893 unsigned int contig_npages;
1894 vm_page_t list;
1895
1896 if (npages < 1)
1897 return VM_PAGE_NULL;
1898
1899 prev_addr = vm_page_queue_free->phys_addr - (page_size + 1);
1900 prev_ptr = &vm_page_queue_free;
1901 for (m = vm_page_queue_free; m != VM_PAGE_NULL; m = NEXT_PAGE(m)) {
1902
1903 if (m->phys_addr != prev_addr + page_size) {
1904 /*
1905 * Whoops! Pages aren't contiguous. Start over.
1906 */
1907 contig_npages = 0;
1908 contig_prev = prev_ptr;
1909 }
1910
1911 if (++contig_npages == npages) {
1912 /*
1913 * Chop these pages out of the free list.
1914 * Mark them all as gobbled.
1915 */
1916 list = *contig_prev;
1917 *contig_prev = NEXT_PAGE(m);
1918 SET_NEXT_PAGE(m, VM_PAGE_NULL);
1919 for (m = list; m != VM_PAGE_NULL; m = NEXT_PAGE(m)) {
1920 assert(m->free);
1921 assert(!m->wanted);
1922 m->free = FALSE;
765c9de3 1923 m->no_isync = TRUE;
1c79356b
A
1924 m->gobbled = TRUE;
1925 }
1926 vm_page_free_count -= npages;
1927 if (vm_page_free_count < vm_page_free_count_minimum)
1928 vm_page_free_count_minimum = vm_page_free_count;
1929 vm_page_wire_count += npages;
1930 vm_page_gobble_count += npages;
1931 cpm_counter(++vpfc_satisfied);
1932 assert(vm_page_verify_contiguous(list, contig_npages));
1933 return list;
1934 }
1935
1936 assert(contig_npages < npages);
1937 prev_ptr = (vm_page_t *) &m->pageq.next;
1938 prev_addr = m->phys_addr;
1939 }
1940 cpm_counter(++vpfc_failed);
1941 return VM_PAGE_NULL;
1942}
1943
1944/*
1945 * Allocate a list of contiguous, wired pages.
1946 */
1947kern_return_t
1948cpm_allocate(
1949 vm_size_t size,
1950 vm_page_t *list,
1951 boolean_t wire)
1952{
1953 register vm_page_t m;
1954 vm_page_t *first_contig;
1955 vm_page_t free_list, pages;
1956 unsigned int npages, n1pages;
1957 int vm_pages_available;
1958
1959 if (size % page_size != 0)
1960 return KERN_INVALID_ARGUMENT;
1961
1962 vm_page_lock_queues();
1963 mutex_lock(&vm_page_queue_free_lock);
1964
1965 /*
1966 * Should also take active and inactive pages
1967 * into account... One day...
1968 */
1969 vm_pages_available = vm_page_free_count - vm_page_free_reserved;
1970
1971 if (size > vm_pages_available * page_size) {
1972 mutex_unlock(&vm_page_queue_free_lock);
1973 return KERN_RESOURCE_SHORTAGE;
1974 }
1975
1976 vm_page_free_list_sort();
1977
1978 npages = size / page_size;
1979
1980 /*
1981 * Obtain a pointer to a subset of the free
1982 * list large enough to satisfy the request;
1983 * the region will be physically contiguous.
1984 */
1985 pages = vm_page_find_contiguous(npages);
1986 if (pages == VM_PAGE_NULL) {
1987 mutex_unlock(&vm_page_queue_free_lock);
1988 vm_page_unlock_queues();
1989 return KERN_NO_SPACE;
1990 }
1991
1992 mutex_unlock(&vm_page_queue_free_lock);
1993
1994 /*
1995 * Walk the returned list, wiring the pages.
1996 */
1997 if (wire == TRUE)
1998 for (m = pages; m != VM_PAGE_NULL; m = NEXT_PAGE(m)) {
1999 /*
2000 * Essentially inlined vm_page_wire.
2001 */
2002 assert(!m->active);
2003 assert(!m->inactive);
2004 assert(!m->private);
2005 assert(!m->fictitious);
2006 assert(m->wire_count == 0);
2007 assert(m->gobbled);
2008 m->gobbled = FALSE;
2009 m->wire_count++;
2010 --vm_page_gobble_count;
2011 }
2012 vm_page_unlock_queues();
2013
2014 /*
2015 * The CPM pages should now be available and
2016 * ordered by ascending physical address.
2017 */
2018 assert(vm_page_verify_contiguous(pages, npages));
2019
2020 *list = pages;
2021 return KERN_SUCCESS;
2022}
2023
2024
2025#include <mach_vm_debug.h>
2026#if MACH_VM_DEBUG
2027
2028#include <mach_debug/hash_info.h>
2029#include <vm/vm_debug.h>
2030
2031/*
2032 * Routine: vm_page_info
2033 * Purpose:
2034 * Return information about the global VP table.
2035 * Fills the buffer with as much information as possible
2036 * and returns the desired size of the buffer.
2037 * Conditions:
2038 * Nothing locked. The caller should provide
2039 * possibly-pageable memory.
2040 */
2041
2042unsigned int
2043vm_page_info(
2044 hash_info_bucket_t *info,
2045 unsigned int count)
2046{
2047 int i;
2048
2049 if (vm_page_bucket_count < count)
2050 count = vm_page_bucket_count;
2051
2052 for (i = 0; i < count; i++) {
2053 vm_page_bucket_t *bucket = &vm_page_buckets[i];
2054 unsigned int bucket_count = 0;
2055 vm_page_t m;
2056
2057 simple_lock(&vm_page_bucket_lock);
2058 for (m = bucket->pages; m != VM_PAGE_NULL; m = m->next)
2059 bucket_count++;
2060 simple_unlock(&vm_page_bucket_lock);
2061
2062 /* don't touch pageable memory while holding locks */
2063 info[i].hib_count = bucket_count;
2064 }
2065
2066 return vm_page_bucket_count;
2067}
2068#endif /* MACH_VM_DEBUG */
2069
2070#include <mach_kdb.h>
2071#if MACH_KDB
2072
2073#include <ddb/db_output.h>
2074#include <vm/vm_print.h>
2075#define printf kdbprintf
2076
2077/*
2078 * Routine: vm_page_print [exported]
2079 */
2080void
2081vm_page_print(
2082 vm_page_t p)
2083{
2084 extern db_indent;
2085
2086 iprintf("page 0x%x\n", p);
2087
2088 db_indent += 2;
2089
2090 iprintf("object=0x%x", p->object);
2091 printf(", offset=0x%x", p->offset);
2092 printf(", wire_count=%d", p->wire_count);
1c79356b
A
2093
2094 iprintf("%sinactive, %sactive, %sgobbled, %slaundry, %sfree, %sref, %sdiscard\n",
2095 (p->inactive ? "" : "!"),
2096 (p->active ? "" : "!"),
2097 (p->gobbled ? "" : "!"),
2098 (p->laundry ? "" : "!"),
2099 (p->free ? "" : "!"),
2100 (p->reference ? "" : "!"),
2101 (p->discard_request ? "" : "!"));
2102 iprintf("%sbusy, %swanted, %stabled, %sfictitious, %sprivate, %sprecious\n",
2103 (p->busy ? "" : "!"),
2104 (p->wanted ? "" : "!"),
2105 (p->tabled ? "" : "!"),
2106 (p->fictitious ? "" : "!"),
2107 (p->private ? "" : "!"),
2108 (p->precious ? "" : "!"));
2109 iprintf("%sabsent, %serror, %sdirty, %scleaning, %spageout, %sclustered\n",
2110 (p->absent ? "" : "!"),
2111 (p->error ? "" : "!"),
2112 (p->dirty ? "" : "!"),
2113 (p->cleaning ? "" : "!"),
2114 (p->pageout ? "" : "!"),
2115 (p->clustered ? "" : "!"));
0b4e3aa0 2116 iprintf("%slock_supplied, %soverwriting, %srestart, %sunusual\n",
1c79356b
A
2117 (p->lock_supplied ? "" : "!"),
2118 (p->overwriting ? "" : "!"),
2119 (p->restart ? "" : "!"),
0b4e3aa0 2120 (p->unusual ? "" : "!"));
1c79356b
A
2121
2122 iprintf("phys_addr=0x%x", p->phys_addr);
2123 printf(", page_error=0x%x", p->page_error);
2124 printf(", page_lock=0x%x", p->page_lock);
2125 printf(", unlock_request=%d\n", p->unlock_request);
2126
2127 db_indent -= 2;
2128}
2129#endif /* MACH_KDB */