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