|
|
1.1 root 1: /*
2: * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
3: *
4: * @APPLE_LICENSE_HEADER_START@
5: *
6: * Portions Copyright (c) 1999 Apple Computer, Inc. All Rights
7: * Reserved. This file contains Original Code and/or Modifications of
8: * Original Code as defined in and that are subject to the Apple Public
9: * Source License Version 1.1 (the "License"). You may not use this file
10: * except in compliance with the License. Please obtain a copy of the
11: * License at http://www.apple.com/publicsource and read it before using
12: * this file.
13: *
14: * The Original Code and all software distributed under the License are
15: * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
16: * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
17: * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
18: * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
19: * License for the specific language governing rights and limitations
20: * under the License.
21: *
22: * @APPLE_LICENSE_HEADER_END@
23: */
24:
25: /*
26: * Mach Operating System
27: * Copyright (c) 1993-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 [email protected]
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: * File: vm/vm_page.c
52: * Author: Avadis Tevanian, Jr., Michael Wayne Young
53: *
54: * Resident memory management module.
55: */
56:
57: #import <mach/features.h>
58:
59: #include <mach/vm_prot.h>
60: #include <kern/counters.h>
61: #include <kern/sched_prim.h>
62: #include <kern/task.h>
63: #include <kern/thread.h>
64: #include <mach/vm_statistics.h>
65: #include <kern/xpr.h>
66: #include <kern/zalloc.h>
67: #include <vm/pmap.h>
68: #include <vm/vm_map.h>
69: #include <vm/vm_page.h>
70: #include <vm/vm_pageout.h>
71:
72: #include <mach/vm_policy.h>
73:
74: /*
75: * Associated with eacn page of user-allocatable memory is a
76: * page structure.
77: */
78:
79: /*
80: * These variables record the values returned by vm_page_bootstrap,
81: * for debugging purposes. The implementation of pmap_steal_memory
82: * and pmap_startup here also uses them internally.
83: */
84:
85: vm_offset_t virtual_space_start;
86: vm_offset_t virtual_space_end;
87:
88: /*
89: * The vm_page_lookup() routine, which provides for fast
90: * (virtual memory object, offset) to page lookup, employs
91: * the following hash table. The vm_page_{insert,remove}
92: * routines install and remove associations in the table.
93: * [This table is often called the virtual-to-physical,
94: * or VP, table.]
95: */
96: typedef struct {
97: decl_simple_lock_data(,lock)
98: vm_page_t pages;
99: } vm_page_bucket_t;
100:
101: vm_page_bucket_t *vm_page_buckets; /* Array of buckets */
102: unsigned int vm_page_bucket_count = 0; /* How big is array? */
103: unsigned int vm_page_hash_mask; /* Mask for hash function */
104:
105: /*
106: * The virtual page size is currently implemented as a runtime
107: * variable, but is constant once initialized using vm_set_page_size.
108: * This initialization must be done in the machine-dependent
109: * bootstrap sequence, before calling other machine-independent
110: * initializations.
111: *
112: * All references to the virtual page size outside this
113: * module must use the PAGE_SIZE constant.
114: */
115: vm_size_t page_size = 0;
116: vm_size_t page_mask;
117: int page_shift;
118:
119: vm_offset_t map_data;
120: vm_size_t map_data_size;
121:
122: vm_offset_t kentry_data;
123: vm_size_t kentry_data_size;
124:
125: extern vm_offset_t zdata;
126: extern vm_size_t zdata_size;
127:
128: queue_head_t vm_page_queue_free;
129: queue_head_t vm_page_queue_active;
130: queue_head_t vm_page_queue_inactive;
131: simple_lock_data_t vm_page_queue_lock;
132: simple_lock_data_t vm_page_queue_free_lock;
133:
134: vm_page_t vm_page_array;
135: long first_page;
136: long last_page;
137: vm_offset_t first_phys_addr;
138: vm_offset_t last_phys_addr;
139:
140: int vm_page_free_count;
141: int vm_page_active_count;
142: int vm_page_inactive_count;
143: int vm_page_wire_count;
144:
145: /*
146: * Several page replacement parameters are also
147: * shared with this module, so that page allocation
148: * (done here in vm_page_alloc) can trigger the
149: * pageout daemon.
150: */
151: int vm_page_free_target = 0;
152: int vm_page_free_min = 0;
153: int vm_page_inactive_target = 0;
154: int vm_page_free_reserved = 0;
155: int vm_page_laundry_count = 0;
156:
157: struct vm_page vm_page_template;
158:
159: #if SHOW_SPACE
160: extern int show_space;
161: #endif SHOW_SPACE
162:
163: /*
164: * vm_set_page_size:
165: *
166: * Sets the page size, perhaps based upon the memory
167: * size. Must be called before any use of page-size
168: * dependent functions.
169: *
170: * Sets page_shift and page_mask from page_size.
171: */
172: void vm_set_page_size(void)
173: {
174: page_mask = page_size - 1;
175:
176: if ((page_mask & page_size) != 0)
177: panic("vm_set_page_size: page size not a power of two");
178:
179: for (page_shift = 0; ; page_shift++)
180: if ((1 << page_shift) == page_size)
181: break;
182: }
183:
184: /*
185: * vm_page_startup:
186: *
187: * Initializes the resident memory module.
188: *
189: * Allocates memory for the page cells, and
190: * for the object/offset-to-page hash table headers.
191: * Each page cell is initialized and placed on the free list.
192: */
193:
194: #if SHOW_SPACE
195: #define PALLOC(name, type, num) \
196: MACRO_BEGIN \
197: (type *)(name) = (type *) \
198: vm_alloc_from_regions((num) * sizeof(type), \
199: __alignof__(type)); \
200: bzero((name), (num) * sizeof(type)); \
201: if (show_space) { \
202: printf(#name " = %d (0x%x) bytes @%x," \
203: " %d cells of %d bytes\n", \
204: (num)*sizeof(type), (num)*sizeof(type), name, \
205: num, sizeof(type)); \
206: } \
207: MACRO_END
208:
209: #define PALLOC_SIZE(name, size, type, num) \
210: MACRO_BEGIN \
211: (size) = (num) * sizeof(type); \
212: (type *)(name) = (type *) \
213: vm_alloc_from_regions((size), \
214: __alignof__(type)); \
215: bzero((name), (size)); \
216: if (show_space) { \
217: printf(#name " = %d (0x%x) bytes @%x," \
218: " %d cells of %d bytes\n", \
219: (size), (size), name, \
220: num, sizeof(type)); \
221: } \
222: MACRO_END
223:
224: #define PALLOC_PAGES(name, type, size) \
225: MACRO_BEGIN \
226: (size) = round_page(size); \
227: (type *)(name) = (type *) \
228: vm_alloc_from_regions((size), PAGE_SIZE); \
229: bzero((name), (size)); \
230: if (show_space) { \
231: printf(#name " = %d (0x%x) bytes @%x," \
232: " %d pages of %d bytes\n", \
233: (size), (size), name, \
234: (size) / PAGE_SIZE, PAGE_SIZE); \
235: } \
236: MACRO_END
237: #else SHOW_SPACE
238: #define PALLOC(name, type, num) \
239: MACRO_BEGIN \
240: (type *)(name) = (type *) \
241: vm_alloc_from_regions((num) * sizeof(type), \
242: __alignof__(type)); \
243: bzero((name), (num) * sizeof(type)); \
244: MACRO_END
245:
246: #define PALLOC_SIZE(name, size, type, num) \
247: MACRO_BEGIN \
248: (size) = (num) * sizeof(type); \
249: (type *)(name) = (type *) \
250: vm_alloc_from_regions((size), \
251: __alignof__(type)); \
252: bzero((name), (size)); \
253: MACRO_END
254:
255: #define PALLOC_PAGES(name, type, size) \
256: MACRO_BEGIN \
257: (size) = round_page(size); \
258: (type *)(name) = (type *) \
259: vm_alloc_from_regions((size), PAGE_SIZE); \
260: bzero((name), (size)); \
261: MACRO_END
262: #endif SHOW_SPACE
263:
264: vm_offset_t vm_page_startup(mem_region, num_regions, vavail)
265: mem_region_t mem_region;
266: int num_regions;
267: vm_offset_t vavail;
268: {
269: int mem_size;
270: mem_region_t rp;
271: vm_page_t m;
272: queue_t bucket;
273: int i;
274: vm_offset_t pa;
275: extern vm_offset_t virtual_avail;
276:
277: /*
278: * Initialize the vm_page template.
279: */
280:
281: m = &vm_page_template;
282: m->object = VM_OBJECT_NULL; /* reset later */
283: m->offset = 0; /* reset later */
284: m->wire_count = 0;
285:
286: #if OLD_VM_CODE
287: m->clean = TRUE;
288: m->nfspagereq = FALSE;
289: m->copy_on_write = FALSE;
290: m->asyncrw = FALSE;
291: #endif
292: m->inactive = FALSE;
293: m->active = FALSE;
294: m->laundry = FALSE;
295: m->free = FALSE;
296:
297: m->busy = TRUE;
298: m->wanted = FALSE;
299: m->tabled = FALSE;
300: m->fictitious = FALSE;
301: m->private = FALSE;
302: m->absent = FALSE;
303: m->error = FALSE;
304: m->dirty = FALSE;
305: m->precious = FALSE;
306: m->reference = FALSE;
307:
308: m->phys_addr = 0; /* reset later */
309:
310: m->page_lock = VM_PROT_NONE;
311: m->unlock_request = VM_PROT_NONE;
312:
313: /*
314: * Initialize the locks
315: */
316:
317: simple_lock_init(&vm_page_queue_free_lock);
318: simple_lock_init(&vm_page_queue_lock);
319:
320: /*
321: * Initialize the queue headers for the free queue,
322: * the active queue and the inactive queue.
323: */
324:
325: queue_init(&vm_page_queue_free);
326: queue_init(&vm_page_queue_active);
327: queue_init(&vm_page_queue_inactive);
328:
329: /*
330: * Allocate (and initialize) the virtual-to-physical
331: * table hash buckets.
332: *
333: * The number of buckets should be a power of two to
334: * get a good hash function. The following computation
335: * chooses the first power of two that is greater
336: * than the number of physical pages in the system.
337: */
338: mem_size = 0;
339: for (rp = mem_region; rp < &mem_region[num_regions]; rp += 1) {
340: mem_size += trunc_page(rp->last_phys_addr)
341: - round_page(rp->first_phys_addr);
342: }
343:
344: if (vm_page_bucket_count == 0) {
345: vm_page_bucket_count = 1;
346: while (vm_page_bucket_count < atop(mem_size))
347: vm_page_bucket_count <<= 1;
348: }
349:
350: vm_page_hash_mask = vm_page_bucket_count - 1;
351:
352: if (vm_page_hash_mask & vm_page_bucket_count)
353: printf("vm_page_bootstrap: WARNING -- strange page hash\n");
354:
355: PALLOC(vm_page_buckets, vm_page_bucket_t, vm_page_bucket_count);
356:
357: for (i = 0; i < vm_page_bucket_count; i++) {
358: register vm_page_bucket_t *bucket = &vm_page_buckets[i];
359:
360: bucket->pages = VM_PAGE_NULL;
361: simple_lock_init(&bucket->lock);
362: }
363:
364: /*
365: * Steal pages for some zones that cannot be
366: * dynamically allocated.
367: */
368: #if 1
369: zdata_size = 8*PAGE_SIZE;
370: PALLOC_PAGES(zdata, void, zdata_size);
371: #else
372: PALLOC_SIZE(zdata, zdata_size, struct zone, 40);
373: #endif
374: PALLOC_SIZE(map_data, map_data_size, struct vm_map, 10);
375:
376: /*
377: * Allow 2048 kernel map entries... this should be plenty
378: * since people shouldn't be cluttering up the kernel
379: * map (they should use their own maps).
380: */
381: PALLOC_SIZE(kentry_data, kentry_data_size, struct vm_map_entry, 2048);
382:
383: /*
384: * First make a pass over each region and allocate
385: * vm_page_arrays. Later go back and size the pages in the
386: * region (since some of the region may have been taken
387: * by the vm_page_array).
388: */
389: for (rp = mem_region; rp < &mem_region[num_regions]; rp += 1) {
390: ASSERT(rp->first_phys_addr <= rp->last_phys_addr);
391: PALLOC(rp->vm_page_array, struct vm_page,
392: atop(trunc_page(rp->last_phys_addr) -
393: round_page(rp->first_phys_addr)));
394: }
395: vm_page_free_count = 0;
396: for (rp = mem_region; rp < &mem_region[num_regions]; rp += 1) {
397: rp->first_phys_addr = round_page(rp->first_phys_addr);
398: rp->last_phys_addr = trunc_page(rp->last_phys_addr);
399: rp->first_page = atop(rp->first_phys_addr);
400: rp->last_page = atop(rp->last_phys_addr);
401: rp->num_pages = rp->last_page - rp->first_page;
402: ASSERT((int)rp->num_pages >= 0);
403: vm_page_free_count += rp->num_pages;
404:
405: m = rp->vm_page_array;
406: pa = rp->first_phys_addr;
407:
408: for (i = 0; i < rp->num_pages; i += 1) {
409: m->phys_addr = pa;
410: queue_enter(&vm_page_queue_free, m, vm_page_t, pageq);
411: m->free = TRUE;
412: m++;
413: pa += page_size;
414: }
415: }
416:
417: /*
418: * Initialize vm_pages_needed lock here - don't wait for pageout
419: * daemon XXX
420: */
421: simple_lock_init(&vm_pages_needed_lock);
422:
423: return(virtual_avail);
424: }
425:
426: /*
427: * vm_page_hash:
428: *
429: * Distributes the object/offset key pair among hash buckets.
430: *
431: * NOTE: To get a good hash function, the bucket count should
432: * be a power of two.
433: */
434: #define vm_page_hash(object, offset) \
435: (((unsigned int)(vm_offset_t)object + (unsigned int)atop(offset)) \
436: & vm_page_hash_mask)
437:
438: /*
439: * vm_page_insert: [ internal use only ]
440: *
441: * Inserts the given mem entry into the object/object-page
442: * table and object list.
443: *
444: * The object and page must be locked.
445: */
446:
447: void vm_page_insert(
448: register vm_page_t mem,
449: register vm_object_t object,
450: register vm_offset_t offset)
451: {
452: register vm_page_bucket_t *bucket;
453:
454: VM_PAGE_CHECK(mem);
455:
456: if (mem->tabled)
457: panic("vm_page_insert");
458:
459: /*
460: * Record the object/offset pair in this page
461: */
462:
463: mem->object = object;
464: mem->offset = offset;
465:
466: /*
467: * Insert it into the object_object/offset hash table
468: */
469:
470: bucket = &vm_page_buckets[vm_page_hash(object, offset)];
471: {
472: int spl = splimp();
473:
474: simple_lock(&bucket->lock);
475: mem->next = bucket->pages;
476: bucket->pages = mem;
477: simple_unlock(&bucket->lock);
478: (void) splx(spl);
479: }
480:
481: /*
482: * Now link into the object's list of backed pages.
483: */
484:
485: queue_enter(&object->memq, mem, vm_page_t, listq);
486: mem->tabled = TRUE;
487:
488: /*
489: * Show that the object has one more resident page.
490: */
491:
492: object->resident_page_count++;
493: }
494:
495: /*
496: * vm_page_remove: [ internal use only ]
497: *
498: * Removes the given mem entry from the object/offset-page
499: * table and the object page list.
500: *
501: * The object and page must be locked.
502: */
503:
504: void vm_page_remove(
505: register vm_page_t mem)
506: {
507: register vm_page_bucket_t *bucket;
508: register vm_page_t this;
509:
510: assert(mem->tabled);
511: VM_PAGE_CHECK(mem);
512:
513: if (!mem->tabled)
514: return;
515:
516: /*
517: * Remove from the object_object/offset hash table
518: */
519:
520: bucket = &vm_page_buckets[vm_page_hash(mem->object, mem->offset)];
521: {
522: int spl = splimp();
523:
524: simple_lock(&bucket->lock);
525: if ((this = bucket->pages) == mem) {
526: /* optimize for common case */
527:
528: bucket->pages = mem->next;
529: } else {
530: register vm_page_t *prev;
531:
532: for (prev = &this->next;
533: (this = *prev) != mem;
534: prev = &this->next)
535: continue;
536: *prev = this->next;
537: }
538: simple_unlock(&bucket->lock);
539: splx(spl);
540: }
541:
542: /*
543: * Now remove from the object's list of backed pages.
544: */
545:
546: queue_remove(&mem->object->memq, mem, vm_page_t, listq);
547:
548: /*
549: * And show that the object has one fewer resident
550: * page.
551: */
552:
553: mem->object->resident_page_count--;
554:
555: mem->tabled = FALSE;
556: }
557:
558: /*
559: * vm_page_lookup:
560: *
561: * Returns the page associated with the object/offset
562: * pair specified; if none is found, VM_PAGE_NULL is returned.
563: *
564: * The object must be locked. No side effects.
565: */
566:
567: vm_page_t vm_page_lookup(
568: register vm_object_t object,
569: register vm_offset_t offset)
570: {
571: register vm_page_t mem;
572: register vm_page_bucket_t *bucket;
573:
574: /*
575: * Search the hash table for this object/offset pair
576: */
577:
578: bucket = &vm_page_buckets[vm_page_hash(object, offset)];
579:
580: {
581: int spl = splimp();
582:
583: simple_lock(&bucket->lock);
584: for (mem = bucket->pages; mem != VM_PAGE_NULL; mem = mem->next) {
585: VM_PAGE_CHECK(mem);
586: if ((mem->object == object) && (mem->offset == offset))
587: break;
588: }
589: simple_unlock(&bucket->lock);
590: splx(spl);
591: }
592: return mem;
593: }
594:
595: /*
596: * vm_page_rename:
597: *
598: * Move the given memory entry from its
599: * current object to the specified target object/offset.
600: *
601: * The object must be locked.
602: */
603: void vm_page_rename(
604: register vm_page_t mem,
605: register vm_object_t new_object,
606: vm_offset_t new_offset)
607: {
608: /*
609: * Changes to mem->object require the page lock because
610: * the pageout daemon uses that lock to get the object.
611: */
612:
613: vm_page_lock_queues();
614: vm_page_remove(mem);
615: vm_page_insert(mem, new_object, new_offset);
616: vm_page_unlock_queues();
617: }
618:
619: /*
620: * vm_page_init:
621: *
622: * Initialize the given vm_page, entering it into
623: * the VP table at the given (object, offset),
624: * and noting its physical address.
625: *
626: * Implemented using a template set up in vm_page_startup.
627: * All fields except those passed as arguments are static.
628: */
629: void vm_page_init(mem, object, offset, phys_addr)
630: vm_page_t mem;
631: vm_object_t object;
632: vm_offset_t offset;
633: vm_offset_t phys_addr;
634: {
635: #define vm_page_init(page, object, offset, pa) { \
636: register \
637: vm_offset_t a = (pa); \
638: *(page) = vm_page_template; \
639: (page)->phys_addr = a; \
640: vm_page_insert((page), (object), (offset)); \
641: }
642:
643: vm_page_init(mem, object, offset, phys_addr);
644: }
645:
646: /*
647: * vm_page_alloc_sequential:
648: *
649: * vm_page_alloc: is a macro calling
650: * vm_page_alloc_sequential(object,offset,TRUE)
651: *
652: * Allocate and return a memory cell associated
653: * with this VM object/offset pair. Don't perform sequential
654: * access checks if called from ICS.
655: *
656: * Object must be locked.
657: */
658: vm_page_t vm_page_alloc_sequential(object, offset, sequential_unmap)
659: vm_object_t object;
660: vm_offset_t offset;
661: boolean_t sequential_unmap;
662: {
663: register vm_page_t mem;
664: int spl;
665:
666: spl = splimp();
667: simple_lock(&vm_page_queue_free_lock);
668:
669: if (queue_empty(&vm_page_queue_free)) {
670: simple_unlock(&vm_page_queue_free_lock);
671: splx(spl);
672: return(VM_PAGE_NULL);
673: }
674:
675: if ((vm_page_free_count < vm_page_free_reserved) &&
676: !current_thread()->vm_privilege) {
677: simple_unlock(&vm_page_queue_free_lock);
678: splx(spl);
679: return(VM_PAGE_NULL);
680: }
681:
682: queue_remove_first(&vm_page_queue_free, mem, vm_page_t, pageq);
683: mem->free = FALSE;
684:
685: vm_page_free_count--;
686: simple_unlock(&vm_page_queue_free_lock);
687: splx(spl);
688:
689: vm_page_remove(mem); /* in case it is still in hash table */
690:
691: vm_page_init(mem, object, offset, mem->phys_addr);
692:
693: /*
694: * Decide if we should poke the pageout daemon.
695: * We do this if the free count is less than the low
696: * water mark, or if the free count is less than the high
697: * water mark (but above the low water mark) and the inactive
698: * count is less than its target.
699: *
700: * We don't have the counts locked ... if they change a little,
701: * it doesn't really matter.
702: */
703:
704: if ((vm_page_free_count < vm_page_free_min) ||
705: ((vm_page_free_count < vm_page_free_target) &&
706: (vm_page_inactive_count < vm_page_inactive_target))){
707: thread_wakeup(&vm_pages_needed);
708: }
709:
710: /*
711: * Detect sequential access and inactivate previous page
712: */
713: if (object->policy & VM_POLICY_SEQUENTIAL && sequential_unmap &&
714: (abs(offset - object->last_alloc) == PAGE_SIZE)) {
715: vm_page_t last_mem;
716:
717: last_mem = vm_page_lookup(object, object->last_alloc);
718: if (last_mem != VM_PAGE_NULL) {
719: int when;
720:
721: switch (object->policy) {
722: case VM_POLICY_SEQ_DEACTIVATE:
723: when = VM_DEACTIVATE_SOON;
724: break;
725: case VM_POLICY_SEQ_FREE:
726: default:
727: when = VM_DEACTIVATE_NOW;
728: break;
729: }
730: vm_policy_apply(object, last_mem, when);
731: }
732: }
733: // else if (object->policy & VM_SEQUENTIAL && sequential_unmap)
734: // object->policy = VM_RANDOM;
735:
736: object->last_alloc = offset;
737: return(mem);
738: }
739:
740: /*
741: * vm_page_free:
742: *
743: * Returns the given page to the free list,
744: * disassociating it with any VM object.
745: *
746: * Object and page must be locked prior to entry.
747: */
748: void vm_page_free(mem)
749: register vm_page_t mem;
750: {
751: vm_page_remove(mem);
752: if (!mem->free) {
753: vm_page_addfree(mem);
754: }
755: }
756:
757: void vm_page_addfree(mem)
758: register vm_page_t mem;
759: {
760: if (mem->active) {
761: queue_remove(&vm_page_queue_active, mem, vm_page_t, pageq);
762: mem->active = FALSE;
763: vm_page_active_count--;
764: }
765:
766: if (mem->inactive) {
767: queue_remove(&vm_page_queue_inactive, mem, vm_page_t, pageq);
768: mem->inactive = FALSE;
769: vm_page_inactive_count--;
770: }
771:
772: if (!mem->fictitious) {
773: int spl;
774:
775: spl = splimp();
776: simple_lock(&vm_page_queue_free_lock);
777: queue_enter(&vm_page_queue_free, mem, vm_page_t, pageq);
778: mem->free = TRUE;
779: vm_page_free_count++;
780: simple_unlock(&vm_page_queue_free_lock);
781: splx(spl);
782: }
783: }
784:
785: /*
786: * vm_page_wire:
787: *
788: * Mark this page as wired down by yet
789: * another map, removing it from paging queues
790: * as necessary.
791: *
792: * The page queues must be locked.
793: */
794: void vm_page_wire(mem)
795: register vm_page_t mem;
796: {
797: VM_PAGE_CHECK(mem);
798:
799: if (mem->wire_count == 0) {
800: if (mem->active) {
801: queue_remove(&vm_page_queue_active, mem, vm_page_t,
802: pageq);
803: vm_page_active_count--;
804: mem->active = FALSE;
805: }
806: if (mem->inactive) {
807: queue_remove(&vm_page_queue_inactive, mem, vm_page_t,
808: pageq);
809: vm_page_inactive_count--;
810: mem->inactive = FALSE;
811: }
812: if (mem->free) {
813: queue_remove(&vm_page_queue_free, mem, vm_page_t,
814: pageq);
815: vm_page_free_count--;
816: mem->free = FALSE;
817: }
818: vm_page_wire_count++;
819: }
820: mem->wire_count++;
821: }
822:
823: /*
824: * vm_page_unwire:
825: *
826: * Release one wiring of this page, potentially
827: * enabling it to be paged again.
828: *
829: * The page queues must be locked.
830: */
831: void vm_page_unwire(mem)
832: register vm_page_t mem;
833: {
834: VM_PAGE_CHECK(mem);
835:
836: if (--mem->wire_count == 0) {
837: queue_enter(&vm_page_queue_active, mem, vm_page_t, pageq);
838: vm_page_active_count++;
839: mem->active = TRUE;
840: vm_page_wire_count--;
841: }
842: }
843:
844: /*
845: * _vm_page_deactivate:
846: *
847: * Internal routine to Returns the given page to the inactive list,
848: * Page is put at the head of the inactive list if age is TRUE.
849: * indicating that no physical maps have access
850: * to this page. [Used by the physical mapping system.]
851: *
852: * The page queues must be locked.
853: */
854: static void _vm_page_deactivate(m, age)
855: register vm_page_t m;
856: register boolean_t age;
857: {
858: VM_PAGE_CHECK(m);
859:
860: /*
861: * Only move active pages -- ignore locked or already
862: * inactive ones.
863: */
864:
865: if (m->active) {
866: pmap_clear_reference(VM_PAGE_TO_PHYS(m));
867: queue_remove(&vm_page_queue_active, m, vm_page_t, pageq);
868: if (age)
869: queue_enter_first(&vm_page_queue_inactive, m, vm_page_t, pageq);
870: else
871: queue_enter(&vm_page_queue_inactive, m, vm_page_t, pageq);
872: m->active = FALSE;
873: m->inactive = TRUE;
874: vm_page_active_count--;
875: vm_page_inactive_count++;
876: if (m->clean && pmap_is_modified(VM_PAGE_TO_PHYS(m)))
877: m->clean = FALSE;
878: m->laundry = !m->clean;
879: }
880: }
881:
882: /*
883: * vm_page_deactivate:
884: *
885: * Returns the given page to the inactive list,
886: * indicating that no physical maps have access
887: * to this page. [Used by the physical mapping system.]
888: *
889: * The page queues must be locked.
890: */
891: void vm_page_deactivate(m)
892: register vm_page_t m;
893: {
894: _vm_page_deactivate(m, FALSE);
895: }
896:
897: /*
898: * vm_page_deactivate_first:
899: *
900: * Returns the given page to the head of inactive list,
901: * indicating that no physical maps have access
902: * to this page. [Used by the physical mapping system.]
903: *
904: * The page queues must be locked.
905: */
906: void vm_page_deactivate_first(m)
907: register vm_page_t m;
908: {
909: _vm_page_deactivate(m, FALSE);
910: }
911:
912: /*
913: * vm_page_activate:
914: *
915: * Put the specified page on the active list (if appropriate).
916: *
917: * The page queues must be locked.
918: */
919:
920: void vm_page_activate(m)
921: register vm_page_t m;
922: {
923: VM_PAGE_CHECK(m);
924:
925:
926: if (m->inactive) {
927: queue_remove(&vm_page_queue_inactive, m, vm_page_t,
928: pageq);
929: vm_page_inactive_count--;
930: m->inactive = FALSE;
931: }
932: if (m->free) {
933: queue_remove(&vm_page_queue_free, m, vm_page_t,
934: pageq);
935: vm_page_free_count--;
936: m->free = FALSE;
937: }
938: if (m->wire_count == 0) {
939: if (m->active)
940: panic("vm_page_activate: already active");
941:
942: queue_enter(&vm_page_queue_active, m, vm_page_t, pageq);
943: m->active = TRUE;
944: vm_page_active_count++;
945: }
946: }
947:
948: /*
949: * vm_page_zero_fill:
950: *
951: * Zero-fill the specified page.
952: * Written as a standard pagein routine, to
953: * be used by the zero-fill object.
954: */
955:
956: boolean_t vm_page_zero_fill(m)
957: vm_page_t m;
958: {
959: VM_PAGE_CHECK(m);
960:
961: pmap_zero_page(VM_PAGE_TO_PHYS(m));
962: return(TRUE);
963: }
964:
965: /*
966: * vm_page_copy:
967: *
968: * Copy one page to another
969: */
970:
971: void vm_page_copy(src_m, dest_m)
972: vm_page_t src_m;
973: vm_page_t dest_m;
974: {
975: VM_PAGE_CHECK(src_m);
976: VM_PAGE_CHECK(dest_m);
977:
978: pmap_copy_page(VM_PAGE_TO_PHYS(src_m), VM_PAGE_TO_PHYS(dest_m));
979: }
980:
981:
982: /*
983: * vm_page_to_phys:
984: *
985: * return the physical page, this routine is here so that
986: * loadable drivers like macfs do not have to deref vm_page_t
987: * directly.
988: */
989:
990: vm_offset_t
991: vm_page_to_phys(m)
992: vm_page_t m;
993: {
994: return(VM_PAGE_TO_PHYS(m));
995: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.