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