Commit | Line | Data |
---|---|---|
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 | * |
a9e495d8 | 10 | * @(#)vm_pager.c 7.6 (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 | * Paging space routine stubs. Emulates a matchmaker-like interface | |
41 | * for builtin pagers. | |
42 | */ | |
43 | ||
44 | #include "param.h" | |
175f072e KM |
45 | #include "malloc.h" |
46 | ||
ffe0d082 MK |
47 | #include "vm.h" |
48 | #include "vm_page.h" | |
49 | #include "vm_kern.h" | |
175f072e | 50 | |
175f072e KM |
51 | #include "swappager.h" |
52 | #if NSWAPPAGER > 0 | |
53 | extern struct pagerops swappagerops; | |
5a2135db | 54 | #define swappagerops_p &swappagerops |
175f072e | 55 | #else |
5a2135db | 56 | #define swappagerops_p NULL |
175f072e | 57 | #endif |
5a2135db | 58 | |
175f072e KM |
59 | #include "vnodepager.h" |
60 | #if NVNODEPAGER > 0 | |
61 | extern struct pagerops vnodepagerops; | |
5a2135db | 62 | #define vnodepagerops_p &vnodepagerops |
175f072e | 63 | #else |
5a2135db | 64 | #define vnodepagerops_p NULL |
175f072e | 65 | #endif |
5a2135db | 66 | |
175f072e KM |
67 | #include "devpager.h" |
68 | #if NDEVPAGER > 0 | |
69 | extern struct pagerops devicepagerops; | |
5a2135db | 70 | #define devicepagerops_p &devicepagerops |
175f072e | 71 | #else |
5a2135db | 72 | #define devicepagerops_p NULL |
175f072e KM |
73 | #endif |
74 | ||
75 | struct pagerops *pagertab[] = { | |
5a2135db KM |
76 | swappagerops_p, /* PG_SWAP */ |
77 | vnodepagerops_p, /* PG_VNODE */ | |
78 | devicepagerops_p, /* PG_DEV */ | |
175f072e KM |
79 | }; |
80 | int npagers = sizeof (pagertab) / sizeof (pagertab[0]); | |
81 | ||
ffe0d082 | 82 | struct pagerops *dfltpagerops = NULL; /* default pager */ |
175f072e KM |
83 | |
84 | /* | |
85 | * Kernel address space for mapping pages. | |
86 | * Used by pagers where KVAs are needed for IO. | |
87 | */ | |
88 | #define PAGER_MAP_SIZE (256 * PAGE_SIZE) | |
89 | vm_map_t pager_map; | |
11371b93 | 90 | vm_offset_t pager_sva, pager_eva; |
175f072e KM |
91 | |
92 | void | |
93 | vm_pager_init() | |
94 | { | |
175f072e KM |
95 | struct pagerops **pgops; |
96 | ||
97 | /* | |
98 | * Allocate a kernel submap for tracking get/put page mappings | |
99 | */ | |
11371b93 | 100 | pager_map = kmem_suballoc(kernel_map, &pager_sva, &pager_eva, |
175f072e KM |
101 | PAGER_MAP_SIZE, FALSE); |
102 | /* | |
103 | * Initialize known pagers | |
104 | */ | |
105 | for (pgops = pagertab; pgops < &pagertab[npagers]; pgops++) | |
106 | (*(*pgops)->pgo_init)(); | |
ffe0d082 | 107 | if (dfltpagerops == NULL) |
175f072e KM |
108 | panic("no default pager"); |
109 | } | |
110 | ||
111 | /* | |
112 | * Allocate an instance of a pager of the given type. | |
113 | */ | |
114 | vm_pager_t | |
115 | vm_pager_allocate(type, handle, size, prot) | |
116 | int type; | |
117 | caddr_t handle; | |
118 | vm_size_t size; | |
119 | vm_prot_t prot; | |
120 | { | |
121 | vm_pager_t pager; | |
122 | struct pagerops *ops; | |
123 | ||
124 | ops = (type == PG_DFLT) ? dfltpagerops : pagertab[type]; | |
125 | return((*ops->pgo_alloc)(handle, size, prot)); | |
126 | } | |
127 | ||
128 | void | |
129 | vm_pager_deallocate(pager) | |
130 | vm_pager_t pager; | |
131 | { | |
ffe0d082 | 132 | if (pager == NULL) |
175f072e KM |
133 | panic("vm_pager_deallocate: null pager"); |
134 | ||
135 | VM_PAGER_DEALLOC(pager); | |
136 | } | |
137 | ||
138 | vm_pager_get(pager, m, sync) | |
139 | vm_pager_t pager; | |
140 | vm_page_t m; | |
141 | boolean_t sync; | |
142 | { | |
143 | extern boolean_t vm_page_zero_fill(); | |
144 | ||
ffe0d082 | 145 | if (pager == NULL) |
175f072e KM |
146 | return(vm_page_zero_fill(m) ? VM_PAGER_OK : VM_PAGER_FAIL); |
147 | return(VM_PAGER_GET(pager, m, sync)); | |
148 | } | |
149 | ||
150 | vm_pager_put(pager, m, sync) | |
151 | vm_pager_t pager; | |
152 | vm_page_t m; | |
153 | boolean_t sync; | |
154 | { | |
ffe0d082 | 155 | if (pager == NULL) |
175f072e KM |
156 | panic("vm_pager_put: null pager"); |
157 | return(VM_PAGER_PUT(pager, m, sync)); | |
158 | } | |
159 | ||
160 | boolean_t | |
161 | vm_pager_has_page(pager, offset) | |
162 | vm_pager_t pager; | |
163 | vm_offset_t offset; | |
164 | { | |
ffe0d082 | 165 | if (pager == NULL) |
175f072e KM |
166 | panic("vm_pager_has_page"); |
167 | return(VM_PAGER_HASPAGE(pager, offset)); | |
168 | } | |
169 | ||
170 | /* | |
171 | * Called by pageout daemon before going back to sleep. | |
172 | * Gives pagers a chance to clean up any completed async pageing operations. | |
173 | */ | |
174 | void | |
175 | vm_pager_sync() | |
176 | { | |
177 | struct pagerops **pgops; | |
178 | ||
179 | for (pgops = pagertab; pgops < &pagertab[npagers]; pgops++) | |
ffe0d082 | 180 | (*(*pgops)->pgo_putpage)(NULL, NULL, FALSE); |
175f072e KM |
181 | } |
182 | ||
183 | vm_offset_t | |
184 | vm_pager_map_page(m) | |
185 | vm_page_t m; | |
186 | { | |
187 | vm_offset_t kva; | |
188 | ||
11371b93 MH |
189 | #ifdef DEBUG |
190 | if (!m->busy || m->active) | |
191 | panic("vm_pager_map_page: page active or not busy"); | |
192 | if (m->pagerowned) | |
193 | printf("vm_pager_map_page: page %x already in pager\n", m); | |
194 | #endif | |
175f072e | 195 | kva = kmem_alloc_wait(pager_map, PAGE_SIZE); |
11371b93 MH |
196 | #ifdef DEBUG |
197 | m->pagerowned = 1; | |
198 | #endif | |
175f072e KM |
199 | pmap_enter(vm_map_pmap(pager_map), kva, VM_PAGE_TO_PHYS(m), |
200 | VM_PROT_DEFAULT, TRUE); | |
175f072e KM |
201 | return(kva); |
202 | } | |
203 | ||
204 | void | |
205 | vm_pager_unmap_page(kva) | |
206 | vm_offset_t kva; | |
207 | { | |
11371b93 MH |
208 | #ifdef DEBUG |
209 | vm_page_t m; | |
210 | ||
211 | m = PHYS_TO_VM_PAGE(pmap_extract(vm_map_pmap(pager_map), kva)); | |
175f072e | 212 | #endif |
11371b93 | 213 | pmap_remove(vm_map_pmap(pager_map), kva, kva + PAGE_SIZE); |
175f072e | 214 | kmem_free_wakeup(pager_map, kva, PAGE_SIZE); |
11371b93 MH |
215 | #ifdef DEBUG |
216 | if (m->pagerowned) | |
217 | m->pagerowned = 0; | |
218 | else | |
219 | printf("vm_pager_unmap_page: page %x(%x/%x) not owned\n", | |
220 | m, kva, VM_PAGE_TO_PHYS(m)); | |
221 | #endif | |
175f072e KM |
222 | } |
223 | ||
224 | vm_pager_t | |
225 | vm_pager_lookup(list, handle) | |
226 | register queue_head_t *list; | |
227 | caddr_t handle; | |
228 | { | |
229 | register vm_pager_t pager; | |
230 | ||
231 | pager = (vm_pager_t) queue_first(list); | |
232 | while (!queue_end(list, (queue_entry_t)pager)) { | |
233 | if (pager->pg_handle == handle) | |
234 | return(pager); | |
235 | pager = (vm_pager_t) queue_next(&pager->pg_list); | |
236 | } | |
ffe0d082 | 237 | return(NULL); |
175f072e KM |
238 | } |
239 | ||
240 | /* | |
241 | * This routine gains a reference to the object. | |
242 | * Explicit deallocation is necessary. | |
243 | */ | |
244 | pager_cache(object, should_cache) | |
245 | vm_object_t object; | |
246 | boolean_t should_cache; | |
247 | { | |
ffe0d082 | 248 | if (object == NULL) |
175f072e KM |
249 | return(KERN_INVALID_ARGUMENT); |
250 | ||
251 | vm_object_cache_lock(); | |
252 | vm_object_lock(object); | |
a9e495d8 KM |
253 | if (should_cache) |
254 | object->flags |= OBJ_CANPERSIST; | |
255 | else | |
256 | object->flags &= ~OBJ_CANPERSIST; | |
175f072e KM |
257 | vm_object_unlock(object); |
258 | vm_object_cache_unlock(); | |
259 | ||
260 | vm_object_deallocate(object); | |
261 | ||
262 | return(KERN_SUCCESS); | |
263 | } |