1 /* $OpenBSD: uvm_page_i.h,v 1.15 2002/09/10 18:29:44 art Exp $ */
2 /* $NetBSD: uvm_page_i.h,v 1.14 2000/11/27 07:47:42 chs Exp $ */
3
4 /*
5 * Copyright (c) 1997 Charles D. Cranor and Washington University.
6 * Copyright (c) 1991, 1993, The Regents of the University of California.
7 *
8 * All rights reserved.
9 *
10 * This code is derived from software contributed to Berkeley by
11 * The Mach Operating System project at Carnegie-Mellon University.
12 *
13 * Redistribution and use in source and binary forms, with or without
14 * modification, are permitted provided that the following conditions
15 * are met:
16 * 1. Redistributions of source code must retain the above copyright
17 * notice, this list of conditions and the following disclaimer.
18 * 2. Redistributions in binary form must reproduce the above copyright
19 * notice, this list of conditions and the following disclaimer in the
20 * documentation and/or other materials provided with the distribution.
21 * 3. All advertising materials mentioning features or use of this software
22 * must display the following acknowledgement:
23 * This product includes software developed by Charles D. Cranor,
24 * Washington University, the University of California, Berkeley and
25 * its contributors.
26 * 4. Neither the name of the University nor the names of its contributors
27 * may be used to endorse or promote products derived from this software
28 * without specific prior written permission.
29 *
30 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
31 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
32 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
33 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
34 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
35 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
36 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
37 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
38 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
39 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
40 * SUCH DAMAGE.
41 *
42 * @(#)vm_page.c 8.3 (Berkeley) 3/21/94
43 * from: Id: uvm_page_i.h,v 1.1.2.7 1998/01/05 00:26:02 chuck Exp
44 *
45 *
46 * Copyright (c) 1987, 1990 Carnegie-Mellon University.
47 * All rights reserved.
48 *
49 * Permission to use, copy, modify and distribute this software and
50 * its documentation is hereby granted, provided that both the copyright
51 * notice and this permission notice appear in all copies of the
52 * software, derivative works or modified versions, and any portions
53 * thereof, and that both notices appear in supporting documentation.
54 *
55 * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
56 * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND
57 * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
58 *
59 * Carnegie Mellon requests users of this software to return to
60 *
61 * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
62 * School of Computer Science
63 * Carnegie Mellon University
64 * Pittsburgh PA 15213-3890
65 *
66 * any improvements or extensions that they make and grant Carnegie the
67 * rights to redistribute these changes.
68 */
69
70 #ifndef _UVM_UVM_PAGE_I_H_
71 #define _UVM_UVM_PAGE_I_H_
72
73 /*
74 * uvm_page_i.h
75 */
76
77 /*
78 * inline functions [maybe]
79 */
80
81 #if defined(UVM_PAGE_INLINE) || defined(UVM_PAGE)
82
83 /*
84 * uvm_lock_fpageq: lock the free page queue
85 *
86 * => free page queue can be accessed in interrupt context, so this
87 * blocks all interrupts that can cause memory allocation, and
88 * returns the previous interrupt level.
89 */
90
91 PAGE_INLINE int
uvm_lock_fpageq()92 uvm_lock_fpageq()
93 {
94 int s;
95
96 s = splvm();
97 simple_lock(&uvm.fpageqlock);
98 return (s);
99 }
100
101 /*
102 * uvm_unlock_fpageq: unlock the free page queue
103 *
104 * => caller must supply interrupt level returned by uvm_lock_fpageq()
105 * so that it may be restored.
106 */
107
108 PAGE_INLINE void
uvm_unlock_fpageq(s)109 uvm_unlock_fpageq(s)
110 int s;
111 {
112
113 simple_unlock(&uvm.fpageqlock);
114 splx(s);
115 }
116
117 /*
118 * uvm_pagelookup: look up a page
119 *
120 * => caller should lock object to keep someone from pulling the page
121 * out from under it
122 */
123
124 struct vm_page *
uvm_pagelookup(obj,off)125 uvm_pagelookup(obj, off)
126 struct uvm_object *obj;
127 voff_t off;
128 {
129 struct vm_page *pg;
130 struct pglist *buck;
131 int s;
132
133 buck = &uvm.page_hash[uvm_pagehash(obj,off)];
134
135 s = splvm();
136 simple_lock(&uvm.hashlock);
137 TAILQ_FOREACH(pg, buck, hashq) {
138 if (pg->uobject == obj && pg->offset == off) {
139 break;
140 }
141 }
142 simple_unlock(&uvm.hashlock);
143 splx(s);
144 return(pg);
145 }
146
147 /*
148 * uvm_pagewire: wire the page, thus removing it from the daemon's grasp
149 *
150 * => caller must lock page queues
151 */
152
153 PAGE_INLINE void
uvm_pagewire(pg)154 uvm_pagewire(pg)
155 struct vm_page *pg;
156 {
157 if (pg->wire_count == 0) {
158 if (pg->pqflags & PQ_ACTIVE) {
159 TAILQ_REMOVE(&uvm.page_active, pg, pageq);
160 pg->pqflags &= ~PQ_ACTIVE;
161 uvmexp.active--;
162 }
163 if (pg->pqflags & PQ_INACTIVE) {
164 if (pg->pqflags & PQ_SWAPBACKED)
165 TAILQ_REMOVE(&uvm.page_inactive_swp, pg, pageq);
166 else
167 TAILQ_REMOVE(&uvm.page_inactive_obj, pg, pageq);
168 pg->pqflags &= ~PQ_INACTIVE;
169 uvmexp.inactive--;
170 }
171 uvmexp.wired++;
172 }
173 pg->wire_count++;
174 }
175
176 /*
177 * uvm_pageunwire: unwire the page.
178 *
179 * => activate if wire count goes to zero.
180 * => caller must lock page queues
181 */
182
183 PAGE_INLINE void
uvm_pageunwire(pg)184 uvm_pageunwire(pg)
185 struct vm_page *pg;
186 {
187 pg->wire_count--;
188 if (pg->wire_count == 0) {
189 TAILQ_INSERT_TAIL(&uvm.page_active, pg, pageq);
190 uvmexp.active++;
191 pg->pqflags |= PQ_ACTIVE;
192 uvmexp.wired--;
193 }
194 }
195
196 /*
197 * uvm_pagedeactivate: deactivate page -- no pmaps have access to page
198 *
199 * => caller must lock page queues
200 * => caller must check to make sure page is not wired
201 * => object that page belongs to must be locked (so we can adjust pg->flags)
202 */
203
204 PAGE_INLINE void
uvm_pagedeactivate(pg)205 uvm_pagedeactivate(pg)
206 struct vm_page *pg;
207 {
208 if (pg->pqflags & PQ_ACTIVE) {
209 TAILQ_REMOVE(&uvm.page_active, pg, pageq);
210 pg->pqflags &= ~PQ_ACTIVE;
211 uvmexp.active--;
212 }
213 if ((pg->pqflags & PQ_INACTIVE) == 0) {
214 KASSERT(pg->wire_count == 0);
215 if (pg->pqflags & PQ_SWAPBACKED)
216 TAILQ_INSERT_TAIL(&uvm.page_inactive_swp, pg, pageq);
217 else
218 TAILQ_INSERT_TAIL(&uvm.page_inactive_obj, pg, pageq);
219 pg->pqflags |= PQ_INACTIVE;
220 uvmexp.inactive++;
221 #ifndef UBC
222 pmap_clear_reference(pg);
223 #endif
224 /*
225 * update the "clean" bit. this isn't 100%
226 * accurate, and doesn't have to be. we'll
227 * re-sync it after we zap all mappings when
228 * scanning the inactive list.
229 */
230 if ((pg->flags & PG_CLEAN) != 0 &&
231 pmap_is_modified(pg))
232 pg->flags &= ~PG_CLEAN;
233 }
234 }
235
236 /*
237 * uvm_pageactivate: activate page
238 *
239 * => caller must lock page queues
240 */
241
242 PAGE_INLINE void
uvm_pageactivate(pg)243 uvm_pageactivate(pg)
244 struct vm_page *pg;
245 {
246 if (pg->pqflags & PQ_INACTIVE) {
247 if (pg->pqflags & PQ_SWAPBACKED)
248 TAILQ_REMOVE(&uvm.page_inactive_swp, pg, pageq);
249 else
250 TAILQ_REMOVE(&uvm.page_inactive_obj, pg, pageq);
251 pg->pqflags &= ~PQ_INACTIVE;
252 uvmexp.inactive--;
253 }
254 if (pg->wire_count == 0) {
255
256 /*
257 * if page is already active, remove it from list so we
258 * can put it at tail. if it wasn't active, then mark
259 * it active and bump active count
260 */
261 if (pg->pqflags & PQ_ACTIVE)
262 TAILQ_REMOVE(&uvm.page_active, pg, pageq);
263 else {
264 pg->pqflags |= PQ_ACTIVE;
265 uvmexp.active++;
266 }
267
268 TAILQ_INSERT_TAIL(&uvm.page_active, pg, pageq);
269 }
270 }
271
272 /*
273 * uvm_pagezero: zero fill a page
274 *
275 * => if page is part of an object then the object should be locked
276 * to protect pg->flags.
277 */
278
279 PAGE_INLINE void
uvm_pagezero(pg)280 uvm_pagezero(pg)
281 struct vm_page *pg;
282 {
283
284 pg->flags &= ~PG_CLEAN;
285 pmap_zero_page(pg);
286 }
287
288 /*
289 * uvm_pagecopy: copy a page
290 *
291 * => if page is part of an object then the object should be locked
292 * to protect pg->flags.
293 */
294
295 PAGE_INLINE void
uvm_pagecopy(src,dst)296 uvm_pagecopy(src, dst)
297 struct vm_page *src, *dst;
298 {
299
300 dst->flags &= ~PG_CLEAN;
301 pmap_copy_page(src, dst);
302 }
303
304 /*
305 * uvm_page_lookup_freelist: look up the free list for the specified page
306 */
307
308 PAGE_INLINE int
uvm_page_lookup_freelist(pg)309 uvm_page_lookup_freelist(pg)
310 struct vm_page *pg;
311 {
312 int lcv;
313
314 lcv = vm_physseg_find(atop(VM_PAGE_TO_PHYS(pg)), NULL);
315 KASSERT(lcv != -1);
316 return (vm_physmem[lcv].free_list);
317 }
318
319 #endif /* defined(UVM_PAGE_INLINE) || defined(UVM_PAGE) */
320
321 #endif /* _UVM_UVM_PAGE_I_H_ */
322