1 /* $OpenBSD: uvm_page_i.h,v 1.17 2007/04/13 18:57:49 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
92 uvm_lock_fpageq(void)
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
109 uvm_unlock_fpageq(int s)
110 {
111
112 simple_unlock(&uvm.fpageqlock);
113 splx(s);
114 }
115
116 /*
117 * uvm_pagelookup: look up a page
118 *
119 * => caller should lock object to keep someone from pulling the page
120 * out from under it
121 */
122
123 struct vm_page *
124 uvm_pagelookup(struct uvm_object *obj, voff_t off)
125 {
126 struct vm_page *pg;
127 struct pglist *buck;
128 int s;
129
130 buck = &uvm.page_hash[uvm_pagehash(obj,off)];
131
132 s = splvm();
133 simple_lock(&uvm.hashlock);
134 TAILQ_FOREACH(pg, buck, hashq) {
135 if (pg->uobject == obj && pg->offset == off) {
136 break;
137 }
138 }
139 simple_unlock(&uvm.hashlock);
140 splx(s);
141 return(pg);
142 }
143
144 /*
145 * uvm_pagewire: wire the page, thus removing it from the daemon's grasp
146 *
147 * => caller must lock page queues
148 */
149
150 PAGE_INLINE void
151 uvm_pagewire(struct vm_page *pg)
152 {
153 if (pg->wire_count == 0) {
154 if (pg->pg_flags & PQ_ACTIVE) {
155 TAILQ_REMOVE(&uvm.page_active, pg, pageq);
156 atomic_clearbits_int(&pg->pg_flags, PQ_ACTIVE);
157 uvmexp.active--;
158 }
159 if (pg->pg_flags & PQ_INACTIVE) {
160 if (pg->pg_flags & PQ_SWAPBACKED)
161 TAILQ_REMOVE(&uvm.page_inactive_swp, pg, pageq);
162 else
163 TAILQ_REMOVE(&uvm.page_inactive_obj, pg, pageq);
164 atomic_clearbits_int(&pg->pg_flags, PQ_INACTIVE);
165 uvmexp.inactive--;
166 }
167 uvmexp.wired++;
168 }
169 pg->wire_count++;
170 }
171
172 /*
173 * uvm_pageunwire: unwire the page.
174 *
175 * => activate if wire count goes to zero.
176 * => caller must lock page queues
177 */
178
179 PAGE_INLINE void
180 uvm_pageunwire(struct vm_page *pg)
181 {
182 pg->wire_count--;
183 if (pg->wire_count == 0) {
184 TAILQ_INSERT_TAIL(&uvm.page_active, pg, pageq);
185 uvmexp.active++;
186 atomic_setbits_int(&pg->pg_flags, PQ_ACTIVE);
187 uvmexp.wired--;
188 }
189 }
190
191 /*
192 * uvm_pagedeactivate: deactivate page -- no pmaps have access to page
193 *
194 * => caller must lock page queues
195 * => caller must check to make sure page is not wired
196 * => object that page belongs to must be locked (so we can adjust pg->flags)
197 */
198
199 PAGE_INLINE void
200 uvm_pagedeactivate(struct vm_page *pg)
201 {
202 if (pg->pg_flags & PQ_ACTIVE) {
203 TAILQ_REMOVE(&uvm.page_active, pg, pageq);
204 atomic_clearbits_int(&pg->pg_flags, PQ_ACTIVE);
205 uvmexp.active--;
206 }
207 if ((pg->pg_flags & PQ_INACTIVE) == 0) {
208 KASSERT(pg->wire_count == 0);
209 if (pg->pg_flags & PQ_SWAPBACKED)
210 TAILQ_INSERT_TAIL(&uvm.page_inactive_swp, pg, pageq);
211 else
212 TAILQ_INSERT_TAIL(&uvm.page_inactive_obj, pg, pageq);
213 atomic_setbits_int(&pg->pg_flags, PQ_INACTIVE);
214 uvmexp.inactive++;
215 pmap_clear_reference(pg);
216 /*
217 * update the "clean" bit. this isn't 100%
218 * accurate, and doesn't have to be. we'll
219 * re-sync it after we zap all mappings when
220 * scanning the inactive list.
221 */
222 if ((pg->pg_flags & PG_CLEAN) != 0 &&
223 pmap_is_modified(pg))
224 atomic_clearbits_int(&pg->pg_flags, PG_CLEAN);
225 }
226 }
227
228 /*
229 * uvm_pageactivate: activate page
230 *
231 * => caller must lock page queues
232 */
233
234 PAGE_INLINE void
235 uvm_pageactivate(struct vm_page *pg)
236 {
237 if (pg->pg_flags & PQ_INACTIVE) {
238 if (pg->pg_flags & PQ_SWAPBACKED)
239 TAILQ_REMOVE(&uvm.page_inactive_swp, pg, pageq);
240 else
241 TAILQ_REMOVE(&uvm.page_inactive_obj, pg, pageq);
242 atomic_clearbits_int(&pg->pg_flags, PQ_INACTIVE);
243 uvmexp.inactive--;
244 }
245 if (pg->wire_count == 0) {
246
247 /*
248 * if page is already active, remove it from list so we
249 * can put it at tail. if it wasn't active, then mark
250 * it active and bump active count
251 */
252 if (pg->pg_flags & PQ_ACTIVE)
253 TAILQ_REMOVE(&uvm.page_active, pg, pageq);
254 else {
255 atomic_setbits_int(&pg->pg_flags, PQ_ACTIVE);
256 uvmexp.active++;
257 }
258
259 TAILQ_INSERT_TAIL(&uvm.page_active, pg, pageq);
260 }
261 }
262
263 /*
264 * uvm_pagezero: zero fill a page
265 *
266 * => if page is part of an object then the object should be locked
267 * to protect pg->flags.
268 */
269
270 PAGE_INLINE void
271 uvm_pagezero(struct vm_page *pg)
272 {
273 atomic_clearbits_int(&pg->pg_flags, PG_CLEAN);
274 pmap_zero_page(pg);
275 }
276
277 /*
278 * uvm_pagecopy: copy a page
279 *
280 * => if page is part of an object then the object should be locked
281 * to protect pg->flags.
282 */
283
284 PAGE_INLINE void
285 uvm_pagecopy(struct vm_page *src, struct vm_page *dst)
286 {
287 atomic_clearbits_int(&dst->pg_flags, PG_CLEAN);
288 pmap_copy_page(src, dst);
289 }
290
291 /*
292 * uvm_page_lookup_freelist: look up the free list for the specified page
293 */
294
295 PAGE_INLINE int
296 uvm_page_lookup_freelist(struct vm_page *pg)
297 {
298 int lcv;
299
300 lcv = vm_physseg_find(atop(VM_PAGE_TO_PHYS(pg)), NULL);
301 KASSERT(lcv != -1);
302 return (vm_physmem[lcv].free_list);
303 }
304
305 #endif /* defined(UVM_PAGE_INLINE) || defined(UVM_PAGE) */
306
307 #endif /* _UVM_UVM_PAGE_I_H_ */