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