Commit | Line | Data |
---|---|---|
175f072e KM |
1 | /* |
2 | * Copyright (c) 1985, 1986 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_pager.c 7.1 (Berkeley) %G% | |
14 | */ | |
15 | ||
16 | /* | |
17 | * Paging space routine stubs. Emulates a matchmaker-like interface | |
18 | * for builtin pagers. | |
19 | */ | |
20 | ||
21 | #include "param.h" | |
22 | #include "queue.h" | |
23 | #include "malloc.h" | |
24 | ||
25 | #include "../vm/vm_param.h" | |
26 | #include "../vm/vm_pager.h" | |
27 | #include "../vm/vm_page.h" | |
28 | #include "../vm/vm_prot.h" | |
29 | #include "../vm/vm_map.h" | |
30 | #include "../vm/vm_kern.h" | |
31 | ||
32 | #include "../vm/pmap.h" | |
33 | ||
34 | #include "swappager.h" | |
35 | #if NSWAPPAGER > 0 | |
36 | extern struct pagerops swappagerops; | |
37 | #else | |
38 | #define swappagerops PAGER_OPS_NULL | |
39 | #endif | |
40 | #include "vnodepager.h" | |
41 | #if NVNODEPAGER > 0 | |
42 | extern struct pagerops vnodepagerops; | |
43 | #else | |
44 | #define vnodepagerops PAGER_OPS_NULL | |
45 | #endif | |
46 | #include "devpager.h" | |
47 | #if NDEVPAGER > 0 | |
48 | extern struct pagerops devicepagerops; | |
49 | #else | |
50 | #define devicepagerops PAGER_OPS_NULL | |
51 | #endif | |
52 | ||
53 | struct pagerops *pagertab[] = { | |
54 | &swappagerops, /* PG_SWAP */ | |
55 | &vnodepagerops, /* PG_VNODE */ | |
56 | &devicepagerops, /* PG_DEV */ | |
57 | }; | |
58 | int npagers = sizeof (pagertab) / sizeof (pagertab[0]); | |
59 | ||
60 | struct pagerops *dfltpagerops = PAGER_OPS_NULL; /* default pager */ | |
61 | ||
62 | /* | |
63 | * Kernel address space for mapping pages. | |
64 | * Used by pagers where KVAs are needed for IO. | |
65 | */ | |
66 | #define PAGER_MAP_SIZE (256 * PAGE_SIZE) | |
67 | vm_map_t pager_map; | |
68 | ||
69 | void | |
70 | vm_pager_init() | |
71 | { | |
72 | vm_offset_t whocares1, whocares2; | |
73 | struct pagerops **pgops; | |
74 | ||
75 | /* | |
76 | * Allocate a kernel submap for tracking get/put page mappings | |
77 | */ | |
78 | pager_map = kmem_suballoc(kernel_map, &whocares1, &whocares2, | |
79 | PAGER_MAP_SIZE, FALSE); | |
80 | /* | |
81 | * Initialize known pagers | |
82 | */ | |
83 | for (pgops = pagertab; pgops < &pagertab[npagers]; pgops++) | |
84 | (*(*pgops)->pgo_init)(); | |
85 | if (dfltpagerops == PAGER_OPS_NULL) | |
86 | panic("no default pager"); | |
87 | } | |
88 | ||
89 | /* | |
90 | * Allocate an instance of a pager of the given type. | |
91 | */ | |
92 | vm_pager_t | |
93 | vm_pager_allocate(type, handle, size, prot) | |
94 | int type; | |
95 | caddr_t handle; | |
96 | vm_size_t size; | |
97 | vm_prot_t prot; | |
98 | { | |
99 | vm_pager_t pager; | |
100 | struct pagerops *ops; | |
101 | ||
102 | ops = (type == PG_DFLT) ? dfltpagerops : pagertab[type]; | |
103 | return((*ops->pgo_alloc)(handle, size, prot)); | |
104 | } | |
105 | ||
106 | void | |
107 | vm_pager_deallocate(pager) | |
108 | vm_pager_t pager; | |
109 | { | |
110 | if (pager == vm_pager_null) | |
111 | panic("vm_pager_deallocate: null pager"); | |
112 | ||
113 | VM_PAGER_DEALLOC(pager); | |
114 | } | |
115 | ||
116 | vm_pager_get(pager, m, sync) | |
117 | vm_pager_t pager; | |
118 | vm_page_t m; | |
119 | boolean_t sync; | |
120 | { | |
121 | extern boolean_t vm_page_zero_fill(); | |
122 | ||
123 | if (pager == vm_pager_null) | |
124 | return(vm_page_zero_fill(m) ? VM_PAGER_OK : VM_PAGER_FAIL); | |
125 | return(VM_PAGER_GET(pager, m, sync)); | |
126 | } | |
127 | ||
128 | vm_pager_put(pager, m, sync) | |
129 | vm_pager_t pager; | |
130 | vm_page_t m; | |
131 | boolean_t sync; | |
132 | { | |
133 | if (pager == vm_pager_null) | |
134 | panic("vm_pager_put: null pager"); | |
135 | return(VM_PAGER_PUT(pager, m, sync)); | |
136 | } | |
137 | ||
138 | boolean_t | |
139 | vm_pager_has_page(pager, offset) | |
140 | vm_pager_t pager; | |
141 | vm_offset_t offset; | |
142 | { | |
143 | if (pager == vm_pager_null) | |
144 | panic("vm_pager_has_page"); | |
145 | return(VM_PAGER_HASPAGE(pager, offset)); | |
146 | } | |
147 | ||
148 | /* | |
149 | * Called by pageout daemon before going back to sleep. | |
150 | * Gives pagers a chance to clean up any completed async pageing operations. | |
151 | */ | |
152 | void | |
153 | vm_pager_sync() | |
154 | { | |
155 | struct pagerops **pgops; | |
156 | ||
157 | for (pgops = pagertab; pgops < &pagertab[npagers]; pgops++) | |
158 | (*(*pgops)->pgo_putpage)(VM_PAGER_NULL, VM_PAGE_NULL, FALSE); | |
159 | } | |
160 | ||
161 | vm_offset_t | |
162 | vm_pager_map_page(m) | |
163 | vm_page_t m; | |
164 | { | |
165 | vm_offset_t kva; | |
166 | ||
167 | kva = kmem_alloc_wait(pager_map, PAGE_SIZE); | |
168 | #if 1 | |
169 | /* | |
170 | * XXX: cannot use pmap_enter as the mapping would be | |
171 | * removed by a pmap_remove_all(). | |
172 | */ | |
173 | *(int *)kvtopte(kva) = VM_PAGE_TO_PHYS(m) | PG_CI | PG_V; | |
174 | TBIS(kva); | |
175 | #else | |
176 | pmap_enter(vm_map_pmap(pager_map), kva, VM_PAGE_TO_PHYS(m), | |
177 | VM_PROT_DEFAULT, TRUE); | |
178 | #endif | |
179 | return(kva); | |
180 | } | |
181 | ||
182 | void | |
183 | vm_pager_unmap_page(kva) | |
184 | vm_offset_t kva; | |
185 | { | |
186 | #if 1 | |
187 | *(int *)kvtopte(kva) = PG_NV; | |
188 | TBIS(kva); | |
189 | #endif | |
190 | kmem_free_wakeup(pager_map, kva, PAGE_SIZE); | |
191 | } | |
192 | ||
193 | vm_pager_t | |
194 | vm_pager_lookup(list, handle) | |
195 | register queue_head_t *list; | |
196 | caddr_t handle; | |
197 | { | |
198 | register vm_pager_t pager; | |
199 | ||
200 | pager = (vm_pager_t) queue_first(list); | |
201 | while (!queue_end(list, (queue_entry_t)pager)) { | |
202 | if (pager->pg_handle == handle) | |
203 | return(pager); | |
204 | pager = (vm_pager_t) queue_next(&pager->pg_list); | |
205 | } | |
206 | return(VM_PAGER_NULL); | |
207 | } | |
208 | ||
209 | /* | |
210 | * This routine gains a reference to the object. | |
211 | * Explicit deallocation is necessary. | |
212 | */ | |
213 | pager_cache(object, should_cache) | |
214 | vm_object_t object; | |
215 | boolean_t should_cache; | |
216 | { | |
217 | if (object == VM_OBJECT_NULL) | |
218 | return(KERN_INVALID_ARGUMENT); | |
219 | ||
220 | vm_object_cache_lock(); | |
221 | vm_object_lock(object); | |
222 | object->can_persist = should_cache; | |
223 | vm_object_unlock(object); | |
224 | vm_object_cache_unlock(); | |
225 | ||
226 | vm_object_deallocate(object); | |
227 | ||
228 | return(KERN_SUCCESS); | |
229 | } |