xref: /csrg-svn/sys/vm/vm_pager.c (revision 48493)
145748Smckusick /*
245748Smckusick  * Copyright (c) 1991 Regents of the University of California.
345748Smckusick  * All rights reserved.
445748Smckusick  *
545748Smckusick  * This code is derived from software contributed to Berkeley by
645748Smckusick  * The Mach Operating System project at Carnegie-Mellon University.
745748Smckusick  *
8*48493Smckusick  * %sccs.include.redist.c%
945748Smckusick  *
10*48493Smckusick  *	@(#)vm_pager.c	7.3 (Berkeley) 04/21/91
11*48493Smckusick  *
12*48493Smckusick  *
13*48493Smckusick  * Copyright (c) 1987, 1990 Carnegie-Mellon University.
14*48493Smckusick  * All rights reserved.
15*48493Smckusick  *
16*48493Smckusick  * Authors: Avadis Tevanian, Jr., Michael Wayne Young
17*48493Smckusick  *
18*48493Smckusick  * Permission to use, copy, modify and distribute this software and
19*48493Smckusick  * its documentation is hereby granted, provided that both the copyright
20*48493Smckusick  * notice and this permission notice appear in all copies of the
21*48493Smckusick  * software, derivative works or modified versions, and any portions
22*48493Smckusick  * thereof, and that both notices appear in supporting documentation.
23*48493Smckusick  *
24*48493Smckusick  * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
25*48493Smckusick  * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND
26*48493Smckusick  * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
27*48493Smckusick  *
28*48493Smckusick  * Carnegie Mellon requests users of this software to return to
29*48493Smckusick  *
30*48493Smckusick  *  Software Distribution Coordinator  or  Software.Distribution@CS.CMU.EDU
31*48493Smckusick  *  School of Computer Science
32*48493Smckusick  *  Carnegie Mellon University
33*48493Smckusick  *  Pittsburgh PA 15213-3890
34*48493Smckusick  *
35*48493Smckusick  * any improvements or extensions that they make and grant Carnegie the
36*48493Smckusick  * rights to redistribute these changes.
3745748Smckusick  */
3845748Smckusick 
3945748Smckusick /*
4045748Smckusick  *	Paging space routine stubs.  Emulates a matchmaker-like interface
4145748Smckusick  *	for builtin pagers.
4245748Smckusick  */
4345748Smckusick 
4445748Smckusick #include "param.h"
4545748Smckusick #include "malloc.h"
4645748Smckusick 
4748386Skarels #include "vm.h"
4848386Skarels #include "vm_page.h"
4948386Skarels #include "vm_kern.h"
5045748Smckusick 
5148386Skarels #ifdef hp300
5248386Skarels #include "../hp300/hp300/pte.h"			/* XXX XXX XXX */
5348386Skarels #endif
5445748Smckusick 
5545748Smckusick #include "swappager.h"
5648386Skarels 
5745748Smckusick #if NSWAPPAGER > 0
5845748Smckusick extern struct pagerops swappagerops;
5945748Smckusick #else
6048386Skarels #define	swappagerops	NULL
6145748Smckusick #endif
6245748Smckusick #include "vnodepager.h"
6345748Smckusick #if NVNODEPAGER > 0
6445748Smckusick extern struct pagerops vnodepagerops;
6545748Smckusick #else
6648386Skarels #define	vnodepagerops	NULL
6745748Smckusick #endif
6845748Smckusick #include "devpager.h"
6945748Smckusick #if NDEVPAGER > 0
7045748Smckusick extern struct pagerops devicepagerops;
7145748Smckusick #else
7248386Skarels #define	devicepagerops	NULL
7345748Smckusick #endif
7445748Smckusick 
7545748Smckusick struct pagerops *pagertab[] = {
7645748Smckusick 	&swappagerops,		/* PG_SWAP */
7745748Smckusick 	&vnodepagerops,		/* PG_VNODE */
7845748Smckusick 	&devicepagerops,	/* PG_DEV */
7945748Smckusick };
8045748Smckusick int npagers = sizeof (pagertab) / sizeof (pagertab[0]);
8145748Smckusick 
8248386Skarels struct pagerops *dfltpagerops = NULL;	/* default pager */
8345748Smckusick 
8445748Smckusick /*
8545748Smckusick  * Kernel address space for mapping pages.
8645748Smckusick  * Used by pagers where KVAs are needed for IO.
8745748Smckusick  */
8845748Smckusick #define PAGER_MAP_SIZE	(256 * PAGE_SIZE)
8945748Smckusick vm_map_t pager_map;
9045748Smckusick 
9145748Smckusick void
9245748Smckusick vm_pager_init()
9345748Smckusick {
9445748Smckusick 	vm_offset_t whocares1, whocares2;
9545748Smckusick 	struct pagerops **pgops;
9645748Smckusick 
9745748Smckusick 	/*
9845748Smckusick 	 * Allocate a kernel submap for tracking get/put page mappings
9945748Smckusick 	 */
10045748Smckusick 	pager_map = kmem_suballoc(kernel_map, &whocares1, &whocares2,
10145748Smckusick 				  PAGER_MAP_SIZE, FALSE);
10245748Smckusick 	/*
10345748Smckusick 	 * Initialize known pagers
10445748Smckusick 	 */
10545748Smckusick 	for (pgops = pagertab; pgops < &pagertab[npagers]; pgops++)
10645748Smckusick 		(*(*pgops)->pgo_init)();
10748386Skarels 	if (dfltpagerops == NULL)
10845748Smckusick 		panic("no default pager");
10945748Smckusick }
11045748Smckusick 
11145748Smckusick /*
11245748Smckusick  * Allocate an instance of a pager of the given type.
11345748Smckusick  */
11445748Smckusick vm_pager_t
11545748Smckusick vm_pager_allocate(type, handle, size, prot)
11645748Smckusick 	int type;
11745748Smckusick 	caddr_t handle;
11845748Smckusick 	vm_size_t size;
11945748Smckusick 	vm_prot_t prot;
12045748Smckusick {
12145748Smckusick 	vm_pager_t pager;
12245748Smckusick 	struct pagerops *ops;
12345748Smckusick 
12445748Smckusick 	ops = (type == PG_DFLT) ? dfltpagerops : pagertab[type];
12545748Smckusick 	return((*ops->pgo_alloc)(handle, size, prot));
12645748Smckusick }
12745748Smckusick 
12845748Smckusick void
12945748Smckusick vm_pager_deallocate(pager)
13045748Smckusick 	vm_pager_t	pager;
13145748Smckusick {
13248386Skarels 	if (pager == NULL)
13345748Smckusick 		panic("vm_pager_deallocate: null pager");
13445748Smckusick 
13545748Smckusick 	VM_PAGER_DEALLOC(pager);
13645748Smckusick }
13745748Smckusick 
13845748Smckusick vm_pager_get(pager, m, sync)
13945748Smckusick 	vm_pager_t	pager;
14045748Smckusick 	vm_page_t	m;
14145748Smckusick 	boolean_t	sync;
14245748Smckusick {
14345748Smckusick 	extern boolean_t vm_page_zero_fill();
14445748Smckusick 
14548386Skarels 	if (pager == NULL)
14645748Smckusick 		return(vm_page_zero_fill(m) ? VM_PAGER_OK : VM_PAGER_FAIL);
14745748Smckusick 	return(VM_PAGER_GET(pager, m, sync));
14845748Smckusick }
14945748Smckusick 
15045748Smckusick vm_pager_put(pager, m, sync)
15145748Smckusick 	vm_pager_t	pager;
15245748Smckusick 	vm_page_t	m;
15345748Smckusick 	boolean_t	sync;
15445748Smckusick {
15548386Skarels 	if (pager == NULL)
15645748Smckusick 		panic("vm_pager_put: null pager");
15745748Smckusick 	return(VM_PAGER_PUT(pager, m, sync));
15845748Smckusick }
15945748Smckusick 
16045748Smckusick boolean_t
16145748Smckusick vm_pager_has_page(pager, offset)
16245748Smckusick 	vm_pager_t	pager;
16345748Smckusick 	vm_offset_t	offset;
16445748Smckusick {
16548386Skarels 	if (pager == NULL)
16645748Smckusick 		panic("vm_pager_has_page");
16745748Smckusick 	return(VM_PAGER_HASPAGE(pager, offset));
16845748Smckusick }
16945748Smckusick 
17045748Smckusick /*
17145748Smckusick  * Called by pageout daemon before going back to sleep.
17245748Smckusick  * Gives pagers a chance to clean up any completed async pageing operations.
17345748Smckusick  */
17445748Smckusick void
17545748Smckusick vm_pager_sync()
17645748Smckusick {
17745748Smckusick 	struct pagerops **pgops;
17845748Smckusick 
17945748Smckusick 	for (pgops = pagertab; pgops < &pagertab[npagers]; pgops++)
18048386Skarels 		(*(*pgops)->pgo_putpage)(NULL, NULL, FALSE);
18145748Smckusick }
18245748Smckusick 
18345748Smckusick vm_offset_t
18445748Smckusick vm_pager_map_page(m)
18545748Smckusick 	vm_page_t	m;
18645748Smckusick {
18745748Smckusick 	vm_offset_t kva;
18845748Smckusick 
18945748Smckusick 	kva = kmem_alloc_wait(pager_map, PAGE_SIZE);
19048386Skarels #ifdef hp300
19145748Smckusick 	/*
19245748Smckusick 	 * XXX: cannot use pmap_enter as the mapping would be
19345748Smckusick 	 * removed by a pmap_remove_all().
19445748Smckusick 	 */
19545748Smckusick 	*(int *)kvtopte(kva) = VM_PAGE_TO_PHYS(m) | PG_CI | PG_V;
19645748Smckusick 	TBIS(kva);
19745748Smckusick #else
19845748Smckusick 	pmap_enter(vm_map_pmap(pager_map), kva, VM_PAGE_TO_PHYS(m),
19945748Smckusick 		   VM_PROT_DEFAULT, TRUE);
20045748Smckusick #endif
20145748Smckusick 	return(kva);
20245748Smckusick }
20345748Smckusick 
20445748Smckusick void
20545748Smckusick vm_pager_unmap_page(kva)
20645748Smckusick 	vm_offset_t	kva;
20745748Smckusick {
20848386Skarels #ifdef hp300
20945748Smckusick 	*(int *)kvtopte(kva) = PG_NV;
21045748Smckusick 	TBIS(kva);
21145748Smckusick #endif
21245748Smckusick 	kmem_free_wakeup(pager_map, kva, PAGE_SIZE);
21345748Smckusick }
21445748Smckusick 
21545748Smckusick vm_pager_t
21645748Smckusick vm_pager_lookup(list, handle)
21745748Smckusick 	register queue_head_t *list;
21845748Smckusick 	caddr_t handle;
21945748Smckusick {
22045748Smckusick 	register vm_pager_t pager;
22145748Smckusick 
22245748Smckusick 	pager = (vm_pager_t) queue_first(list);
22345748Smckusick 	while (!queue_end(list, (queue_entry_t)pager)) {
22445748Smckusick 		if (pager->pg_handle == handle)
22545748Smckusick 			return(pager);
22645748Smckusick 		pager = (vm_pager_t) queue_next(&pager->pg_list);
22745748Smckusick 	}
22848386Skarels 	return(NULL);
22945748Smckusick }
23045748Smckusick 
23145748Smckusick /*
23245748Smckusick  * This routine gains a reference to the object.
23345748Smckusick  * Explicit deallocation is necessary.
23445748Smckusick  */
23545748Smckusick pager_cache(object, should_cache)
23645748Smckusick 	vm_object_t	object;
23745748Smckusick 	boolean_t	should_cache;
23845748Smckusick {
23948386Skarels 	if (object == NULL)
24045748Smckusick 		return(KERN_INVALID_ARGUMENT);
24145748Smckusick 
24245748Smckusick 	vm_object_cache_lock();
24345748Smckusick 	vm_object_lock(object);
24445748Smckusick 	object->can_persist = should_cache;
24545748Smckusick 	vm_object_unlock(object);
24645748Smckusick 	vm_object_cache_unlock();
24745748Smckusick 
24845748Smckusick 	vm_object_deallocate(object);
24945748Smckusick 
25045748Smckusick 	return(KERN_SUCCESS);
25145748Smckusick }
252