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_ */