1 /* $OpenBSD: uvm_fault_i.h,v 1.12 2007/05/31 21:20:30 thib Exp $ */
2 /* $NetBSD: uvm_fault_i.h,v 1.11 2000/06/26 14:21:17 mrg Exp $ */
3
4 /*
5 *
6 * Copyright (c) 1997 Charles D. Cranor and Washington University.
7 * All rights reserved.
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
11 * are met:
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution.
17 * 3. All advertising materials mentioning features or use of this software
18 * must display the following acknowledgement:
19 * This product includes software developed by Charles D. Cranor and
20 * Washington University.
21 * 4. The name of the author may not be used to endorse or promote products
22 * derived from this software without specific prior written permission.
23 *
24 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
25 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
26 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
27 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
28 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
29 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
30 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
31 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
33 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34 *
35 * from: Id: uvm_fault_i.h,v 1.1.6.1 1997/12/08 16:07:12 chuck Exp
36 */
37
38 #ifndef _UVM_UVM_FAULT_I_H_
39 #define _UVM_UVM_FAULT_I_H_
40
41 /*
42 * uvm_fault_i.h: fault inline functions
43 */
44 static boolean_t uvmfault_lookup(struct uvm_faultinfo *, boolean_t);
45 static boolean_t uvmfault_relock(struct uvm_faultinfo *);
46 static void uvmfault_unlockall(struct uvm_faultinfo *, struct vm_amap *,
47 struct uvm_object *, struct vm_anon *);
48 static void uvmfault_unlockmaps(struct uvm_faultinfo *, boolean_t);
49
50 /*
51 * uvmfault_unlockmaps: unlock the maps
52 */
53
54 static __inline void
55 uvmfault_unlockmaps(ufi, write_locked)
56 struct uvm_faultinfo *ufi;
57 boolean_t write_locked;
58 {
59 /*
60 * ufi can be NULL when this isn't really a fault,
61 * but merely paging in anon data.
62 */
63
64 if (ufi == NULL) {
65 return;
66 }
67
68 if (write_locked) {
69 vm_map_unlock(ufi->map);
70 } else {
71 vm_map_unlock_read(ufi->map);
72 }
73 }
74
75 /*
76 * uvmfault_unlockall: unlock everything passed in.
77 *
78 * => maps must be read-locked (not write-locked).
79 */
80
81 static __inline void
82 uvmfault_unlockall(ufi, amap, uobj, anon)
83 struct uvm_faultinfo *ufi;
84 struct vm_amap *amap;
85 struct uvm_object *uobj;
86 struct vm_anon *anon;
87 {
88
89 if (anon)
90 simple_unlock(&anon->an_lock);
91 if (uobj)
92 simple_unlock(&uobj->vmobjlock);
93 uvmfault_unlockmaps(ufi, FALSE);
94 }
95
96 /*
97 * uvmfault_lookup: lookup a virtual address in a map
98 *
99 * => caller must provide a uvm_faultinfo structure with the IN
100 * params properly filled in
101 * => we will lookup the map entry (handling submaps) as we go
102 * => if the lookup is a success we will return with the maps locked
103 * => if "write_lock" is TRUE, we write_lock the map, otherwise we only
104 * get a read lock.
105 * => note that submaps can only appear in the kernel and they are
106 * required to use the same virtual addresses as the map they
107 * are referenced by (thus address translation between the main
108 * map and the submap is unnecessary).
109 */
110
111 static __inline boolean_t
112 uvmfault_lookup(ufi, write_lock)
113 struct uvm_faultinfo *ufi;
114 boolean_t write_lock;
115 {
116 vm_map_t tmpmap;
117
118 /*
119 * init ufi values for lookup.
120 */
121
122 ufi->map = ufi->orig_map;
123 ufi->size = ufi->orig_size;
124
125 /*
126 * keep going down levels until we are done. note that there can
127 * only be two levels so we won't loop very long.
128 */
129
130 while (1) {
131
132 /*
133 * lock map
134 */
135 if (write_lock) {
136 vm_map_lock(ufi->map);
137 } else {
138 vm_map_lock_read(ufi->map);
139 }
140
141 /*
142 * lookup
143 */
144 if (!uvm_map_lookup_entry(ufi->map, ufi->orig_rvaddr,
145 &ufi->entry)) {
146 uvmfault_unlockmaps(ufi, write_lock);
147 return(FALSE);
148 }
149
150 /*
151 * reduce size if necessary
152 */
153 if (ufi->entry->end - ufi->orig_rvaddr < ufi->size)
154 ufi->size = ufi->entry->end - ufi->orig_rvaddr;
155
156 /*
157 * submap? replace map with the submap and lookup again.
158 * note: VAs in submaps must match VAs in main map.
159 */
160 if (UVM_ET_ISSUBMAP(ufi->entry)) {
161 tmpmap = ufi->entry->object.sub_map;
162 if (write_lock) {
163 vm_map_unlock(ufi->map);
164 } else {
165 vm_map_unlock_read(ufi->map);
166 }
167 ufi->map = tmpmap;
168 continue;
169 }
170
171 /*
172 * got it!
173 */
174
175 ufi->mapv = ufi->map->timestamp;
176 return(TRUE);
177
178 } /* while loop */
179
180 /*NOTREACHED*/
181 }
182
183 /*
184 * uvmfault_relock: attempt to relock the same version of the map
185 *
186 * => fault data structures should be unlocked before calling.
187 * => if a success (TRUE) maps will be locked after call.
188 */
189
190 static __inline boolean_t
191 uvmfault_relock(ufi)
192 struct uvm_faultinfo *ufi;
193 {
194 /*
195 * ufi can be NULL when this isn't really a fault,
196 * but merely paging in anon data.
197 */
198
199 if (ufi == NULL) {
200 return TRUE;
201 }
202
203 uvmexp.fltrelck++;
204
205 /*
206 * relock map. fail if version mismatch (in which case nothing
207 * gets locked).
208 */
209
210 vm_map_lock_read(ufi->map);
211 if (ufi->mapv != ufi->map->timestamp) {
212 vm_map_unlock_read(ufi->map);
213 return(FALSE);
214 }
215
216 uvmexp.fltrelckok++;
217 return(TRUE); /* got it! */
218 }
219
220 #endif /* _UVM_UVM_FAULT_I_H_ */