Add extra argument to VOP_BMAP.
[unix-history] / usr / src / sys / vm / vm_page.c
CommitLineData
175f072e 1/*
175f072e
KM
2 * Copyright (c) 1991 Regents of the University of California.
3 * All rights reserved.
4 *
5 * This code is derived from software contributed to Berkeley by
6 * The Mach Operating System project at Carnegie-Mellon University.
7 *
0e24ad83 8 * %sccs.include.redist.c%
175f072e 9 *
2cbf9af3 10 * @(#)vm_page.c 7.14 (Berkeley) %G%
0e24ad83
KM
11 *
12 *
13 * Copyright (c) 1987, 1990 Carnegie-Mellon University.
14 * All rights reserved.
15 *
16 * Authors: Avadis Tevanian, Jr., Michael Wayne Young
17 *
18 * Permission to use, copy, modify and distribute this software and
19 * its documentation is hereby granted, provided that both the copyright
20 * notice and this permission notice appear in all copies of the
21 * software, derivative works or modified versions, and any portions
22 * thereof, and that both notices appear in supporting documentation.
23 *
24 * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
25 * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND
26 * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
27 *
28 * Carnegie Mellon requests users of this software to return to
29 *
30 * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
31 * School of Computer Science
32 * Carnegie Mellon University
33 * Pittsburgh PA 15213-3890
34 *
35 * any improvements or extensions that they make and grant Carnegie the
36 * rights to redistribute these changes.
175f072e
KM
37 */
38
39/*
40 * Resident memory management module.
41 */
42
88036809
KB
43#include <sys/param.h>
44#include <sys/systm.h>
ffe0d082 45
88036809
KB
46#include <vm/vm.h>
47#include <vm/vm_page.h>
48#include <vm/vm_map.h>
49#include <vm/vm_pageout.h>
175f072e
KM
50
51/*
52 * Associated with page of user-allocatable memory is a
53 * page structure.
54 */
55
56queue_head_t *vm_page_buckets; /* Array of buckets */
57int vm_page_bucket_count = 0; /* How big is array? */
58int vm_page_hash_mask; /* Mask for hash function */
59simple_lock_data_t bucket_lock; /* lock for all buckets XXX */
60
175f072e
KM
61queue_head_t vm_page_queue_free;
62queue_head_t vm_page_queue_active;
63queue_head_t vm_page_queue_inactive;
64simple_lock_data_t vm_page_queue_lock;
65simple_lock_data_t vm_page_queue_free_lock;
66
544634b8
WN
67/* has physical page allocation been initialized? */
68boolean_t vm_page_startup_initialized;
69
175f072e
KM
70vm_page_t vm_page_array;
71long first_page;
72long last_page;
73vm_offset_t first_phys_addr;
74vm_offset_t last_phys_addr;
1ebacb93
KM
75vm_size_t page_mask;
76int page_shift;
175f072e
KM
77
78/*
79 * vm_set_page_size:
80 *
81 * Sets the page size, perhaps based upon the memory
82 * size. Must be called before any use of page-size
83 * dependent functions.
84 *
f92ce83a 85 * Sets page_shift and page_mask from cnt.v_page_size.
175f072e
KM
86 */
87void vm_set_page_size()
88{
175f072e 89
f92ce83a
KM
90 if (cnt.v_page_size == 0)
91 cnt.v_page_size = DEFAULT_PAGE_SIZE;
92 page_mask = cnt.v_page_size - 1;
93 if ((page_mask & cnt.v_page_size) != 0)
175f072e 94 panic("vm_set_page_size: page size not a power of two");
175f072e 95 for (page_shift = 0; ; page_shift++)
f92ce83a 96 if ((1 << page_shift) == cnt.v_page_size)
175f072e
KM
97 break;
98}
99
100
101/*
102 * vm_page_startup:
103 *
104 * Initializes the resident memory module.
105 *
106 * Allocates memory for the page cells, and
107 * for the object/offset-to-page hash table headers.
108 * Each page cell is initialized and placed on the free list.
109 */
544634b8
WN
110void vm_page_startup(start, end)
111 vm_offset_t *start;
112 vm_offset_t *end;
175f072e 113{
175f072e
KM
114 register vm_page_t m;
115 register queue_t bucket;
116 vm_size_t npages;
175f072e
KM
117 int i;
118 vm_offset_t pa;
175f072e
KM
119 extern vm_offset_t kentry_data;
120 extern vm_size_t kentry_data_size;
121
122
123 /*
124 * Initialize the locks
125 */
126
127 simple_lock_init(&vm_page_queue_free_lock);
128 simple_lock_init(&vm_page_queue_lock);
129
130 /*
131 * Initialize the queue headers for the free queue,
132 * the active queue and the inactive queue.
133 */
134
135 queue_init(&vm_page_queue_free);
136 queue_init(&vm_page_queue_active);
137 queue_init(&vm_page_queue_inactive);
138
139 /*
544634b8 140 * Calculate the number of hash table buckets.
175f072e
KM
141 *
142 * The number of buckets MUST BE a power of 2, and
143 * the actual value is the next power of 2 greater
144 * than the number of physical pages in the system.
145 *
146 * Note:
147 * This computation can be tweaked if desired.
148 */
149
175f072e
KM
150 if (vm_page_bucket_count == 0) {
151 vm_page_bucket_count = 1;
544634b8 152 while (vm_page_bucket_count < atop(*end - *start))
175f072e
KM
153 vm_page_bucket_count <<= 1;
154 }
155
156 vm_page_hash_mask = vm_page_bucket_count - 1;
157
158 /*
544634b8 159 * Allocate (and initialize) the hash table buckets.
175f072e 160 */
544634b8
WN
161 vm_page_buckets = (queue_t) pmap_bootstrap_alloc(vm_page_bucket_count
162 * sizeof(struct queue_entry));
163 bucket = vm_page_buckets;
175f072e
KM
164
165 for (i = vm_page_bucket_count; i--;) {
166 queue_init(bucket);
167 bucket++;
168 }
169
170 simple_lock_init(&bucket_lock);
171
172 /*
544634b8 173 * Truncate the remainder of physical memory to our page size.
175f072e
KM
174 */
175
544634b8 176 *end = trunc_page(*end);
175f072e
KM
177
178 /*
179 * Pre-allocate maps and map entries that cannot be dynamically
180 * allocated via malloc(). The maps include the kernel_map and
181 * kmem_map which must be initialized before malloc() will
182 * work (obviously). Also could include pager maps which would
183 * be allocated before kmeminit.
184 *
185 * Allow some kernel map entries... this should be plenty
186 * since people shouldn't be cluttering up the kernel
187 * map (they should use their own maps).
188 */
189
190 kentry_data_size = MAX_KMAP * sizeof(struct vm_map) +
191 MAX_KMAPENT * sizeof(struct vm_map_entry);
544634b8 192 kentry_data = (vm_offset_t) pmap_bootstrap_alloc(kentry_data_size);
175f072e
KM
193
194 /*
195 * Compute the number of pages of memory that will be
196 * available for use (taking into account the overhead
197 * of a page structure per page).
198 */
199
f92ce83a 200 cnt.v_free_count = npages =
544634b8 201 (*end - *start)/(PAGE_SIZE + sizeof(struct vm_page));
175f072e
KM
202
203 /*
544634b8
WN
204 * Record the extent of physical memory that the
205 * virtual memory system manages.
175f072e
KM
206 */
207
544634b8 208 first_page = *start;
175f072e
KM
209 first_page += npages*sizeof(struct vm_page);
210 first_page = atop(round_page(first_page));
211 last_page = first_page + npages - 1;
212
213 first_phys_addr = ptoa(first_page);
214 last_phys_addr = ptoa(last_page) + PAGE_MASK;
215
cb5fb9b0 216
175f072e 217 /*
544634b8 218 * Allocate and clear the mem entry structures.
175f072e
KM
219 */
220
544634b8
WN
221 m = vm_page_array = (vm_page_t)
222 pmap_bootstrap_alloc(npages * sizeof(struct vm_page));
175f072e
KM
223
224 /*
544634b8
WN
225 * Initialize the mem entry structures now, and
226 * put them in the free queue.
175f072e 227 */
175f072e
KM
228
229 pa = first_phys_addr;
230 while (npages--) {
2cbf9af3 231 m->flags = 0;
ffe0d082 232 m->object = NULL;
175f072e 233 m->phys_addr = pa;
cb5fb9b0
WN
234#ifdef i386
235 if (pmap_isvalidphys(m->phys_addr)) {
236 queue_enter(&vm_page_queue_free, m, vm_page_t, pageq);
237 } else {
238 /* perhaps iomem needs it's own type, or dev pager? */
2cbf9af3 239 m->flags |= PG_FICTITIOUS | PG_BUSY;
f92ce83a 240 cnt.v_free_count--;
cb5fb9b0
WN
241 }
242#else /* i386 */
175f072e 243 queue_enter(&vm_page_queue_free, m, vm_page_t, pageq);
cb5fb9b0 244#endif /* i386 */
175f072e
KM
245 m++;
246 pa += PAGE_SIZE;
247 }
248
249 /*
250 * Initialize vm_pages_needed lock here - don't wait for pageout
251 * daemon XXX
252 */
253 simple_lock_init(&vm_pages_needed_lock);
254
544634b8
WN
255 /* from now on, pmap_bootstrap_alloc can't be used */
256 vm_page_startup_initialized = TRUE;
175f072e
KM
257}
258
259/*
260 * vm_page_hash:
261 *
262 * Distributes the object/offset key pair among hash buckets.
263 *
264 * NOTE: This macro depends on vm_page_bucket_count being a power of 2.
265 */
266#define vm_page_hash(object, offset) \
267 (((unsigned)object+(unsigned)atop(offset))&vm_page_hash_mask)
268
269/*
270 * vm_page_insert: [ internal use only ]
271 *
272 * Inserts the given mem entry into the object/object-page
273 * table and object list.
274 *
275 * The object and page must be locked.
276 */
277
a11b4cc1 278void vm_page_insert(mem, object, offset)
175f072e
KM
279 register vm_page_t mem;
280 register vm_object_t object;
281 register vm_offset_t offset;
282{
283 register queue_t bucket;
284 int spl;
285
286 VM_PAGE_CHECK(mem);
287
2cbf9af3 288 if (mem->flags & PG_TABLED)
175f072e
KM
289 panic("vm_page_insert: already inserted");
290
291 /*
292 * Record the object/offset pair in this page
293 */
294
295 mem->object = object;
296 mem->offset = offset;
297
298 /*
299 * Insert it into the object_object/offset hash table
300 */
301
302 bucket = &vm_page_buckets[vm_page_hash(object, offset)];
303 spl = splimp();
304 simple_lock(&bucket_lock);
305 queue_enter(bucket, mem, vm_page_t, hashq);
306 simple_unlock(&bucket_lock);
307 (void) splx(spl);
308
309 /*
310 * Now link into the object's list of backed pages.
311 */
312
313 queue_enter(&object->memq, mem, vm_page_t, listq);
2cbf9af3 314 mem->flags |= PG_TABLED;
175f072e
KM
315
316 /*
317 * And show that the object has one more resident
318 * page.
319 */
320
321 object->resident_page_count++;
322}
323
324/*
325 * vm_page_remove: [ internal use only ]
544634b8 326 * NOTE: used by device pager as well -wfj
175f072e
KM
327 *
328 * Removes the given mem entry from the object/offset-page
329 * table and the object page list.
330 *
331 * The object and page must be locked.
332 */
333
334void vm_page_remove(mem)
335 register vm_page_t mem;
336{
337 register queue_t bucket;
338 int spl;
339
340 VM_PAGE_CHECK(mem);
341
2cbf9af3 342 if (!(mem->flags & PG_TABLED))
175f072e
KM
343 return;
344
345 /*
346 * Remove from the object_object/offset hash table
347 */
348
349 bucket = &vm_page_buckets[vm_page_hash(mem->object, mem->offset)];
350 spl = splimp();
351 simple_lock(&bucket_lock);
352 queue_remove(bucket, mem, vm_page_t, hashq);
353 simple_unlock(&bucket_lock);
354 (void) splx(spl);
355
356 /*
357 * Now remove from the object's list of backed pages.
358 */
359
360 queue_remove(&mem->object->memq, mem, vm_page_t, listq);
361
362 /*
363 * And show that the object has one fewer resident
364 * page.
365 */
366
367 mem->object->resident_page_count--;
368
2cbf9af3 369 mem->flags &= ~PG_TABLED;
175f072e
KM
370}
371
372/*
373 * vm_page_lookup:
374 *
375 * Returns the page associated with the object/offset
ffe0d082 376 * pair specified; if none is found, NULL is returned.
175f072e
KM
377 *
378 * The object must be locked. No side effects.
379 */
380
381vm_page_t vm_page_lookup(object, offset)
382 register vm_object_t object;
383 register vm_offset_t offset;
384{
385 register vm_page_t mem;
386 register queue_t bucket;
387 int spl;
388
389 /*
390 * Search the hash table for this object/offset pair
391 */
392
393 bucket = &vm_page_buckets[vm_page_hash(object, offset)];
394
395 spl = splimp();
396 simple_lock(&bucket_lock);
397 mem = (vm_page_t) queue_first(bucket);
398 while (!queue_end(bucket, (queue_entry_t) mem)) {
399 VM_PAGE_CHECK(mem);
400 if ((mem->object == object) && (mem->offset == offset)) {
401 simple_unlock(&bucket_lock);
402 splx(spl);
403 return(mem);
404 }
405 mem = (vm_page_t) queue_next(&mem->hashq);
406 }
407
408 simple_unlock(&bucket_lock);
409 splx(spl);
ffe0d082 410 return(NULL);
175f072e
KM
411}
412
413/*
414 * vm_page_rename:
415 *
416 * Move the given memory entry from its
417 * current object to the specified target object/offset.
418 *
419 * The object must be locked.
420 */
421void vm_page_rename(mem, new_object, new_offset)
422 register vm_page_t mem;
423 register vm_object_t new_object;
424 vm_offset_t new_offset;
425{
426 if (mem->object == new_object)
427 return;
428
429 vm_page_lock_queues(); /* keep page from moving out from
430 under pageout daemon */
431 vm_page_remove(mem);
432 vm_page_insert(mem, new_object, new_offset);
433 vm_page_unlock_queues();
434}
435
175f072e
KM
436/*
437 * vm_page_alloc:
438 *
439 * Allocate and return a memory cell associated
440 * with this VM object/offset pair.
441 *
442 * Object must be locked.
443 */
444vm_page_t vm_page_alloc(object, offset)
445 vm_object_t object;
446 vm_offset_t offset;
447{
448 register vm_page_t mem;
449 int spl;
450
451 spl = splimp(); /* XXX */
452 simple_lock(&vm_page_queue_free_lock);
453 if (queue_empty(&vm_page_queue_free)) {
454 simple_unlock(&vm_page_queue_free_lock);
455 splx(spl);
ffe0d082 456 return(NULL);
175f072e
KM
457 }
458
459 queue_remove_first(&vm_page_queue_free, mem, vm_page_t, pageq);
460
f92ce83a 461 cnt.v_free_count--;
175f072e
KM
462 simple_unlock(&vm_page_queue_free_lock);
463 splx(spl);
464
328c9775 465 VM_PAGE_INIT(mem, object, offset);
175f072e
KM
466
467 /*
468 * Decide if we should poke the pageout daemon.
469 * We do this if the free count is less than the low
470 * water mark, or if the free count is less than the high
471 * water mark (but above the low water mark) and the inactive
472 * count is less than its target.
473 *
474 * We don't have the counts locked ... if they change a little,
475 * it doesn't really matter.
476 */
477
328c9775
CT
478 if (cnt.v_free_count < cnt.v_free_min ||
479 (cnt.v_free_count < cnt.v_free_target &&
480 cnt.v_inactive_count < cnt.v_inactive_target))
90314fa1 481 thread_wakeup((int)&vm_pages_needed);
328c9775 482 return (mem);
175f072e
KM
483}
484
485/*
486 * vm_page_free:
487 *
488 * Returns the given page to the free list,
489 * disassociating it with any VM object.
490 *
491 * Object and page must be locked prior to entry.
492 */
493void vm_page_free(mem)
494 register vm_page_t mem;
495{
496 vm_page_remove(mem);
2cbf9af3 497 if (mem->flags & PG_ACTIVE) {
175f072e 498 queue_remove(&vm_page_queue_active, mem, vm_page_t, pageq);
2cbf9af3 499 mem->flags &= ~PG_ACTIVE;
f92ce83a 500 cnt.v_active_count--;
175f072e
KM
501 }
502
2cbf9af3 503 if (mem->flags & PG_INACTIVE) {
175f072e 504 queue_remove(&vm_page_queue_inactive, mem, vm_page_t, pageq);
2cbf9af3 505 mem->flags &= ~PG_INACTIVE;
f92ce83a 506 cnt.v_inactive_count--;
175f072e
KM
507 }
508
2cbf9af3 509 if (!(mem->flags & PG_FICTITIOUS)) {
175f072e
KM
510 int spl;
511
512 spl = splimp();
513 simple_lock(&vm_page_queue_free_lock);
514 queue_enter(&vm_page_queue_free, mem, vm_page_t, pageq);
515
f92ce83a 516 cnt.v_free_count++;
175f072e
KM
517 simple_unlock(&vm_page_queue_free_lock);
518 splx(spl);
519 }
520}
521
522/*
523 * vm_page_wire:
524 *
525 * Mark this page as wired down by yet
526 * another map, removing it from paging queues
527 * as necessary.
528 *
529 * The page queues must be locked.
530 */
531void vm_page_wire(mem)
532 register vm_page_t mem;
533{
534 VM_PAGE_CHECK(mem);
535
536 if (mem->wire_count == 0) {
2cbf9af3 537 if (mem->flags & PG_ACTIVE) {
175f072e
KM
538 queue_remove(&vm_page_queue_active, mem, vm_page_t,
539 pageq);
f92ce83a 540 cnt.v_active_count--;
2cbf9af3 541 mem->flags &= ~PG_ACTIVE;
175f072e 542 }
2cbf9af3 543 if (mem->flags & PG_INACTIVE) {
175f072e
KM
544 queue_remove(&vm_page_queue_inactive, mem, vm_page_t,
545 pageq);
f92ce83a 546 cnt.v_inactive_count--;
2cbf9af3 547 mem->flags &= ~PG_INACTIVE;
175f072e 548 }
f92ce83a 549 cnt.v_wire_count++;
175f072e
KM
550 }
551 mem->wire_count++;
552}
553
554/*
555 * vm_page_unwire:
556 *
557 * Release one wiring of this page, potentially
558 * enabling it to be paged again.
559 *
560 * The page queues must be locked.
561 */
562void vm_page_unwire(mem)
563 register vm_page_t mem;
564{
565 VM_PAGE_CHECK(mem);
566
567 mem->wire_count--;
568 if (mem->wire_count == 0) {
569 queue_enter(&vm_page_queue_active, mem, vm_page_t, pageq);
f92ce83a 570 cnt.v_active_count++;
2cbf9af3 571 mem->flags |= PG_ACTIVE;
f92ce83a 572 cnt.v_wire_count--;
175f072e
KM
573 }
574}
575
576/*
577 * vm_page_deactivate:
578 *
579 * Returns the given page to the inactive list,
580 * indicating that no physical maps have access
581 * to this page. [Used by the physical mapping system.]
582 *
583 * The page queues must be locked.
584 */
585void vm_page_deactivate(m)
586 register vm_page_t m;
587{
588 VM_PAGE_CHECK(m);
589
590 /*
591 * Only move active pages -- ignore locked or already
592 * inactive ones.
593 */
594
2cbf9af3 595 if (m->flags & PG_ACTIVE) {
175f072e
KM
596 pmap_clear_reference(VM_PAGE_TO_PHYS(m));
597 queue_remove(&vm_page_queue_active, m, vm_page_t, pageq);
598 queue_enter(&vm_page_queue_inactive, m, vm_page_t, pageq);
2cbf9af3
KM
599 m->flags &= ~PG_ACTIVE;
600 m->flags |= PG_INACTIVE;
f92ce83a
KM
601 cnt.v_active_count--;
602 cnt.v_inactive_count++;
175f072e 603 if (pmap_is_modified(VM_PAGE_TO_PHYS(m)))
2cbf9af3
KM
604 m->flags &= ~PG_CLEAN;
605 if (m->flags & PG_CLEAN)
606 m->flags &= ~PG_LAUNDRY;
607 else
608 m->flags |= PG_LAUNDRY;
175f072e
KM
609 }
610}
611
612/*
613 * vm_page_activate:
614 *
615 * Put the specified page on the active list (if appropriate).
616 *
617 * The page queues must be locked.
618 */
619
620void vm_page_activate(m)
621 register vm_page_t m;
622{
623 VM_PAGE_CHECK(m);
624
2cbf9af3 625 if (m->flags & PG_INACTIVE) {
175f072e
KM
626 queue_remove(&vm_page_queue_inactive, m, vm_page_t,
627 pageq);
f92ce83a 628 cnt.v_inactive_count--;
2cbf9af3 629 m->flags &= ~PG_INACTIVE;
175f072e
KM
630 }
631 if (m->wire_count == 0) {
2cbf9af3 632 if (m->flags & PG_ACTIVE)
175f072e
KM
633 panic("vm_page_activate: already active");
634
635 queue_enter(&vm_page_queue_active, m, vm_page_t, pageq);
2cbf9af3 636 m->flags |= PG_ACTIVE;
f92ce83a 637 cnt.v_active_count++;
175f072e
KM
638 }
639}
640
641/*
642 * vm_page_zero_fill:
643 *
644 * Zero-fill the specified page.
645 * Written as a standard pagein routine, to
646 * be used by the zero-fill object.
647 */
648
649boolean_t vm_page_zero_fill(m)
650 vm_page_t m;
651{
652 VM_PAGE_CHECK(m);
653
2cbf9af3 654 m->flags &= ~PG_CLEAN;
175f072e
KM
655 pmap_zero_page(VM_PAGE_TO_PHYS(m));
656 return(TRUE);
657}
658
659/*
660 * vm_page_copy:
661 *
662 * Copy one page to another
663 */
664
665void vm_page_copy(src_m, dest_m)
666 vm_page_t src_m;
667 vm_page_t dest_m;
668{
669 VM_PAGE_CHECK(src_m);
670 VM_PAGE_CHECK(dest_m);
671
2cbf9af3 672 dest_m->flags &= ~PG_CLEAN;
175f072e
KM
673 pmap_copy_page(VM_PAGE_TO_PHYS(src_m), VM_PAGE_TO_PHYS(dest_m));
674}