1*d2a0ebb6Sad /* $NetBSD: uvm_fault_i.h,v 1.33 2020/02/23 15:46:43 ad Exp $ */
2f2caacc7Smrg
3f2caacc7Smrg /*
4f2caacc7Smrg * Copyright (c) 1997 Charles D. Cranor and Washington University.
5f2caacc7Smrg * All rights reserved.
6f2caacc7Smrg *
7f2caacc7Smrg * Redistribution and use in source and binary forms, with or without
8f2caacc7Smrg * modification, are permitted provided that the following conditions
9f2caacc7Smrg * are met:
10f2caacc7Smrg * 1. Redistributions of source code must retain the above copyright
11f2caacc7Smrg * notice, this list of conditions and the following disclaimer.
12f2caacc7Smrg * 2. Redistributions in binary form must reproduce the above copyright
13f2caacc7Smrg * notice, this list of conditions and the following disclaimer in the
14f2caacc7Smrg * documentation and/or other materials provided with the distribution.
15f2caacc7Smrg *
16f2caacc7Smrg * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17f2caacc7Smrg * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18f2caacc7Smrg * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19f2caacc7Smrg * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
20f2caacc7Smrg * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
21f2caacc7Smrg * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22f2caacc7Smrg * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23f2caacc7Smrg * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24f2caacc7Smrg * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
25f2caacc7Smrg * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
261f6b921cSmrg *
271f6b921cSmrg * from: Id: uvm_fault_i.h,v 1.1.6.1 1997/12/08 16:07:12 chuck Exp
28f2caacc7Smrg */
29f2caacc7Smrg
30021fdb64Sperry #ifndef _UVM_UVM_FAULT_I_H_
31021fdb64Sperry #define _UVM_UVM_FAULT_I_H_
32021fdb64Sperry
33f2caacc7Smrg /*
34f2caacc7Smrg * uvm_fault_i.h: fault inline functions
35f2caacc7Smrg */
3661768d92Schristos void uvmfault_update_stats(struct uvm_faultinfo *);
3761768d92Schristos
38f2caacc7Smrg
39f2caacc7Smrg /*
40f2caacc7Smrg * uvmfault_unlockmaps: unlock the maps
41f2caacc7Smrg */
42f2caacc7Smrg
4387fd18f8Schristos static __inline void
uvmfault_unlockmaps(struct uvm_faultinfo * ufi,bool write_locked)44712239e3Sthorpej uvmfault_unlockmaps(struct uvm_faultinfo *ufi, bool write_locked)
45f2caacc7Smrg {
4616f0ca36Schs /*
4716f0ca36Schs * ufi can be NULL when this isn't really a fault,
4816f0ca36Schs * but merely paging in anon data.
4916f0ca36Schs */
5016f0ca36Schs
5116f0ca36Schs if (ufi == NULL) {
5216f0ca36Schs return;
5316f0ca36Schs }
548106d135Smrg
5587287ec1Schristos #ifndef __HAVE_NO_PMAP_STATS
5661768d92Schristos uvmfault_update_stats(ufi);
5787287ec1Schristos #endif
58f2caacc7Smrg if (write_locked) {
59f2caacc7Smrg vm_map_unlock(ufi->map);
60f2caacc7Smrg } else {
61f2caacc7Smrg vm_map_unlock_read(ufi->map);
62f2caacc7Smrg }
63f2caacc7Smrg }
64f2caacc7Smrg
65f2caacc7Smrg /*
66f2caacc7Smrg * uvmfault_unlockall: unlock everything passed in.
67f2caacc7Smrg *
68f2caacc7Smrg * => maps must be read-locked (not write-locked).
69f2caacc7Smrg */
70f2caacc7Smrg
7187fd18f8Schristos static __inline void
uvmfault_unlockall(struct uvm_faultinfo * ufi,struct vm_amap * amap,struct uvm_object * uobj)72e569faccSthorpej uvmfault_unlockall(struct uvm_faultinfo *ufi, struct vm_amap *amap,
73e225b7bdSrmind struct uvm_object *uobj)
74f2caacc7Smrg {
758106d135Smrg
76f2caacc7Smrg if (uobj)
77*d2a0ebb6Sad rw_exit(uobj->vmobjlock);
78f2caacc7Smrg if (amap)
7944f5fc28Schuck amap_unlock(amap);
80b3667adaSthorpej uvmfault_unlockmaps(ufi, false);
81f2caacc7Smrg }
82f2caacc7Smrg
83f2caacc7Smrg /*
84f2caacc7Smrg * uvmfault_lookup: lookup a virtual address in a map
85f2caacc7Smrg *
861b59a238Schuck * => caller must provide a uvm_faultinfo structure with the IN
87f2caacc7Smrg * params properly filled in
881b59a238Schuck * => we will lookup the map entry (handling submaps) as we go
89f2caacc7Smrg * => if the lookup is a success we will return with the maps locked
90b3667adaSthorpej * => if "write_lock" is true, we write_lock the map, otherwise we only
91f2caacc7Smrg * get a read lock.
921b59a238Schuck * => note that submaps can only appear in the kernel and they are
931b59a238Schuck * required to use the same virtual addresses as the map they
941b59a238Schuck * are referenced by (thus address translation between the main
951b59a238Schuck * map and the submap is unnecessary).
96f2caacc7Smrg */
97f2caacc7Smrg
9887fd18f8Schristos static __inline bool
uvmfault_lookup(struct uvm_faultinfo * ufi,bool write_lock)99712239e3Sthorpej uvmfault_lookup(struct uvm_faultinfo *ufi, bool write_lock)
100f2caacc7Smrg {
101821ec03eSchs struct vm_map *tmpmap;
102f2caacc7Smrg
103f2caacc7Smrg /*
104f2caacc7Smrg * init ufi values for lookup.
105f2caacc7Smrg */
106f2caacc7Smrg
107f2caacc7Smrg ufi->map = ufi->orig_map;
108f2caacc7Smrg ufi->size = ufi->orig_size;
109f2caacc7Smrg
110f2caacc7Smrg /*
111f2caacc7Smrg * keep going down levels until we are done. note that there can
112f2caacc7Smrg * only be two levels so we won't loop very long.
113f2caacc7Smrg */
114f2caacc7Smrg
115a4c86c1bSrmind for (;;) {
116f2caacc7Smrg /*
117f2caacc7Smrg * lock map
118f2caacc7Smrg */
119f2caacc7Smrg if (write_lock) {
120f2caacc7Smrg vm_map_lock(ufi->map);
121f2caacc7Smrg } else {
122f2caacc7Smrg vm_map_lock_read(ufi->map);
123f2caacc7Smrg }
124f2caacc7Smrg
125f2caacc7Smrg /*
126f2caacc7Smrg * lookup
127f2caacc7Smrg */
1281b59a238Schuck if (!uvm_map_lookup_entry(ufi->map, ufi->orig_rvaddr,
1291b59a238Schuck &ufi->entry)) {
130f2caacc7Smrg uvmfault_unlockmaps(ufi, write_lock);
131b3667adaSthorpej return(false);
132f2caacc7Smrg }
133f2caacc7Smrg
134f2caacc7Smrg /*
135f2caacc7Smrg * reduce size if necessary
136f2caacc7Smrg */
1371b59a238Schuck if (ufi->entry->end - ufi->orig_rvaddr < ufi->size)
1381b59a238Schuck ufi->size = ufi->entry->end - ufi->orig_rvaddr;
139f2caacc7Smrg
140f2caacc7Smrg /*
141f2caacc7Smrg * submap? replace map with the submap and lookup again.
142f2caacc7Smrg * note: VAs in submaps must match VAs in main map.
143f2caacc7Smrg */
144f2caacc7Smrg if (UVM_ET_ISSUBMAP(ufi->entry)) {
145f2caacc7Smrg tmpmap = ufi->entry->object.sub_map;
146f2caacc7Smrg if (write_lock) {
147f2caacc7Smrg vm_map_unlock(ufi->map);
148f2caacc7Smrg } else {
149f2caacc7Smrg vm_map_unlock_read(ufi->map);
150f2caacc7Smrg }
151f2caacc7Smrg ufi->map = tmpmap;
152f2caacc7Smrg continue;
153f2caacc7Smrg }
154f2caacc7Smrg
155f2caacc7Smrg /*
156f2caacc7Smrg * got it!
157f2caacc7Smrg */
158f2caacc7Smrg
159f2caacc7Smrg ufi->mapv = ufi->map->timestamp;
160b3667adaSthorpej return(true);
161f2caacc7Smrg
162f2caacc7Smrg } /* while loop */
163f2caacc7Smrg
164f2caacc7Smrg /*NOTREACHED*/
165f2caacc7Smrg }
166f2caacc7Smrg
167f2caacc7Smrg /*
168f2caacc7Smrg * uvmfault_relock: attempt to relock the same version of the map
169f2caacc7Smrg *
170f2caacc7Smrg * => fault data structures should be unlocked before calling.
171b3667adaSthorpej * => if a success (true) maps will be locked after call.
172f2caacc7Smrg */
173f2caacc7Smrg
17487fd18f8Schristos static __inline bool
uvmfault_relock(struct uvm_faultinfo * ufi)175e569faccSthorpej uvmfault_relock(struct uvm_faultinfo *ufi)
176f2caacc7Smrg {
17716f0ca36Schs /*
17816f0ca36Schs * ufi can be NULL when this isn't really a fault,
17916f0ca36Schs * but merely paging in anon data.
18016f0ca36Schs */
18116f0ca36Schs
18216f0ca36Schs if (ufi == NULL) {
183b3667adaSthorpej return true;
18416f0ca36Schs }
1858106d135Smrg
186a98966d3Sad cpu_count(CPU_COUNT_FLTRELCK, 1);
18716f0ca36Schs
188f2caacc7Smrg /*
1891b59a238Schuck * relock map. fail if version mismatch (in which case nothing
1901b59a238Schuck * gets locked).
191f2caacc7Smrg */
192f2caacc7Smrg
193f2caacc7Smrg vm_map_lock_read(ufi->map);
194f2caacc7Smrg if (ufi->mapv != ufi->map->timestamp) {
195f2caacc7Smrg vm_map_unlock_read(ufi->map);
196b3667adaSthorpej return(false);
197f2caacc7Smrg }
198f2caacc7Smrg
199a98966d3Sad cpu_count(CPU_COUNT_FLTRELCKOK, 1);
200b3667adaSthorpej return(true);
201f2caacc7Smrg }
202021fdb64Sperry
203021fdb64Sperry #endif /* _UVM_UVM_FAULT_I_H_ */
204