Annotation of src/sys/uvm/uvm_map.c, Revision 1.97
1.97 ! ross 1: /* $NetBSD: uvm_map.c,v 1.96 2001/04/29 04:23:21 thorpej Exp $ */
1.1 mrg 2:
3: /*
4: * Copyright (c) 1997 Charles D. Cranor and Washington University.
5: * Copyright (c) 1991, 1993, The Regents of the University of California.
6: *
7: * All rights reserved.
8: *
9: * This code is derived from software contributed to Berkeley by
10: * The Mach Operating System project at Carnegie-Mellon University.
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,
23: * Washington University, the University of California, Berkeley and
24: * its contributors.
25: * 4. Neither the name of the University nor the names of its contributors
26: * may be used to endorse or promote products derived from this software
27: * without specific prior written permission.
28: *
29: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
30: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
31: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
32: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
33: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
34: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
35: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
36: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
37: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
38: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
39: * SUCH DAMAGE.
40: *
41: * @(#)vm_map.c 8.3 (Berkeley) 1/12/94
1.3 mrg 42: * from: Id: uvm_map.c,v 1.1.2.27 1998/02/07 01:16:54 chs Exp
1.1 mrg 43: *
44: *
45: * Copyright (c) 1987, 1990 Carnegie-Mellon University.
46: * All rights reserved.
47: *
48: * Permission to use, copy, modify and distribute this software and
49: * its documentation is hereby granted, provided that both the copyright
50: * notice and this permission notice appear in all copies of the
51: * software, derivative works or modified versions, and any portions
52: * thereof, and that both notices appear in supporting documentation.
53: *
54: * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
55: * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND
56: * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
57: *
58: * Carnegie Mellon requests users of this software to return to
59: *
60: * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
61: * School of Computer Science
62: * Carnegie Mellon University
63: * Pittsburgh PA 15213-3890
64: *
65: * any improvements or extensions that they make and grant Carnegie the
66: * rights to redistribute these changes.
67: */
68:
1.21 jonathan 69: #include "opt_ddb.h"
1.6 mrg 70: #include "opt_uvmhist.h"
1.31 tron 71: #include "opt_sysv.h"
1.6 mrg 72:
1.1 mrg 73: /*
74: * uvm_map.c: uvm map operations
75: */
76:
77: #include <sys/param.h>
78: #include <sys/systm.h>
79: #include <sys/mman.h>
80: #include <sys/proc.h>
81: #include <sys/malloc.h>
1.25 thorpej 82: #include <sys/pool.h>
1.1 mrg 83:
84: #ifdef SYSVSHM
85: #include <sys/shm.h>
86: #endif
87:
88: #define UVM_MAP
89: #include <uvm/uvm.h>
1.21 jonathan 90:
91: #ifdef DDB
92: #include <uvm/uvm_ddb.h>
93: #endif
94:
1.1 mrg 95:
96: struct uvm_cnt uvm_map_call, map_backmerge, map_forwmerge;
97: struct uvm_cnt uvm_mlk_call, uvm_mlk_hint;
1.87 enami 98: const char vmmapbsy[] = "vmmapbsy";
1.1 mrg 99:
100: /*
1.25 thorpej 101: * pool for vmspace structures.
102: */
103:
104: struct pool uvm_vmspace_pool;
105:
1.26 thorpej 106: /*
107: * pool for dynamically-allocated map entries.
108: */
109:
110: struct pool uvm_map_entry_pool;
1.25 thorpej 111:
1.40 thorpej 112: #ifdef PMAP_GROWKERNEL
113: /*
114: * This global represents the end of the kernel virtual address
115: * space. If we want to exceed this, we must grow the kernel
116: * virtual address space dynamically.
117: *
118: * Note, this variable is locked by kernel_map's lock.
119: */
120: vaddr_t uvm_maxkaddr;
121: #endif
122:
1.25 thorpej 123: /*
1.1 mrg 124: * macros
125: */
126:
127: /*
128: * uvm_map_entry_link: insert entry into a map
129: *
130: * => map must be locked
131: */
1.10 mrg 132: #define uvm_map_entry_link(map, after_where, entry) do { \
133: (map)->nentries++; \
134: (entry)->prev = (after_where); \
135: (entry)->next = (after_where)->next; \
136: (entry)->prev->next = (entry); \
137: (entry)->next->prev = (entry); \
138: } while (0)
139:
1.1 mrg 140: /*
141: * uvm_map_entry_unlink: remove entry from a map
142: *
143: * => map must be locked
144: */
1.10 mrg 145: #define uvm_map_entry_unlink(map, entry) do { \
146: (map)->nentries--; \
147: (entry)->next->prev = (entry)->prev; \
148: (entry)->prev->next = (entry)->next; \
149: } while (0)
1.1 mrg 150:
151: /*
152: * SAVE_HINT: saves the specified entry as the hint for future lookups.
153: *
154: * => map need not be locked (protected by hint_lock).
155: */
1.82 thorpej 156: #define SAVE_HINT(map,check,value) do { \
1.10 mrg 157: simple_lock(&(map)->hint_lock); \
1.82 thorpej 158: if ((map)->hint == (check)) \
159: (map)->hint = (value); \
1.10 mrg 160: simple_unlock(&(map)->hint_lock); \
161: } while (0)
1.1 mrg 162:
163: /*
164: * VM_MAP_RANGE_CHECK: check and correct range
165: *
166: * => map must at least be read locked
167: */
168:
1.10 mrg 169: #define VM_MAP_RANGE_CHECK(map, start, end) do { \
170: if (start < vm_map_min(map)) \
171: start = vm_map_min(map); \
172: if (end > vm_map_max(map)) \
173: end = vm_map_max(map); \
174: if (start > end) \
175: start = end; \
176: } while (0)
1.1 mrg 177:
178: /*
179: * local prototypes
180: */
181:
182: static vm_map_entry_t uvm_mapent_alloc __P((vm_map_t));
183: static void uvm_mapent_copy __P((vm_map_entry_t,vm_map_entry_t));
184: static void uvm_mapent_free __P((vm_map_entry_t));
185: static void uvm_map_entry_unwire __P((vm_map_t, vm_map_entry_t));
1.85 chs 186: static void uvm_map_reference_amap __P((vm_map_entry_t, int));
187: static void uvm_map_unreference_amap __P((vm_map_entry_t, int));
1.1 mrg 188:
189: /*
190: * local inlines
191: */
192:
193: /*
194: * uvm_mapent_alloc: allocate a map entry
195: *
196: * => XXX: static pool for kernel map?
197: */
198:
1.10 mrg 199: static __inline vm_map_entry_t
200: uvm_mapent_alloc(map)
201: vm_map_t map;
202: {
203: vm_map_entry_t me;
204: int s;
205: UVMHIST_FUNC("uvm_mapent_alloc");
206: UVMHIST_CALLED(maphist);
1.1 mrg 207:
1.45 thorpej 208: if ((map->flags & VM_MAP_INTRSAFE) == 0 &&
209: map != kernel_map && kernel_map != NULL /* XXX */) {
1.26 thorpej 210: me = pool_get(&uvm_map_entry_pool, PR_WAITOK);
1.10 mrg 211: me->flags = 0;
212: /* me can't be null, wait ok */
213: } else {
1.88 thorpej 214: s = splvm(); /* protect kentry_free list with splvm */
1.10 mrg 215: simple_lock(&uvm.kentry_lock);
216: me = uvm.kentry_free;
217: if (me) uvm.kentry_free = me->next;
218: simple_unlock(&uvm.kentry_lock);
219: splx(s);
220: if (!me)
1.45 thorpej 221: panic("mapent_alloc: out of static map entries, check MAX_KMAPENT");
1.10 mrg 222: me->flags = UVM_MAP_STATIC;
223: }
1.1 mrg 224:
1.45 thorpej 225: UVMHIST_LOG(maphist, "<- new entry=0x%x [kentry=%d]",
226: me, ((map->flags & VM_MAP_INTRSAFE) != 0 || map == kernel_map)
227: ? TRUE : FALSE, 0, 0);
1.10 mrg 228: return(me);
1.1 mrg 229: }
230:
231: /*
232: * uvm_mapent_free: free map entry
233: *
234: * => XXX: static pool for kernel map?
235: */
236:
1.10 mrg 237: static __inline void
238: uvm_mapent_free(me)
239: vm_map_entry_t me;
1.1 mrg 240: {
1.10 mrg 241: int s;
242: UVMHIST_FUNC("uvm_mapent_free");
243: UVMHIST_CALLED(maphist);
244: UVMHIST_LOG(maphist,"<- freeing map entry=0x%x [flags=%d]",
1.1 mrg 245: me, me->flags, 0, 0);
1.10 mrg 246: if ((me->flags & UVM_MAP_STATIC) == 0) {
1.26 thorpej 247: pool_put(&uvm_map_entry_pool, me);
1.10 mrg 248: } else {
1.88 thorpej 249: s = splvm(); /* protect kentry_free list with splvm */
1.10 mrg 250: simple_lock(&uvm.kentry_lock);
251: me->next = uvm.kentry_free;
252: uvm.kentry_free = me;
253: simple_unlock(&uvm.kentry_lock);
254: splx(s);
255: }
1.1 mrg 256: }
257:
258: /*
259: * uvm_mapent_copy: copy a map entry, preserving flags
260: */
261:
1.10 mrg 262: static __inline void
263: uvm_mapent_copy(src, dst)
264: vm_map_entry_t src;
265: vm_map_entry_t dst;
266: {
1.1 mrg 267:
1.23 perry 268: memcpy(dst, src, ((char *)&src->uvm_map_entry_stop_copy) - ((char*)src));
1.1 mrg 269: }
270:
271: /*
272: * uvm_map_entry_unwire: unwire a map entry
273: *
274: * => map should be locked by caller
275: */
276:
1.10 mrg 277: static __inline void
278: uvm_map_entry_unwire(map, entry)
279: vm_map_t map;
280: vm_map_entry_t entry;
281: {
1.1 mrg 282:
1.10 mrg 283: entry->wired_count = 0;
1.57 thorpej 284: uvm_fault_unwire_locked(map, entry->start, entry->end);
1.1 mrg 285: }
286:
1.85 chs 287:
288: /*
289: * wrapper for calling amap_ref()
290: */
291: static __inline void
292: uvm_map_reference_amap(entry, flags)
293: vm_map_entry_t entry;
294: int flags;
295: {
296: amap_ref(entry->aref.ar_amap, entry->aref.ar_pageoff,
297: (entry->end - entry->start) >> PAGE_SHIFT, flags);
298: }
299:
300:
301: /*
302: * wrapper for calling amap_unref()
303: */
304: static __inline void
305: uvm_map_unreference_amap(entry, flags)
306: vm_map_entry_t entry;
307: int flags;
308: {
309: amap_unref(entry->aref.ar_amap, entry->aref.ar_pageoff,
310: (entry->end - entry->start) >> PAGE_SHIFT, flags);
311: }
312:
313:
1.1 mrg 314: /*
315: * uvm_map_init: init mapping system at boot time. note that we allocate
316: * and init the static pool of vm_map_entry_t's for the kernel here.
317: */
318:
1.10 mrg 319: void
320: uvm_map_init()
1.1 mrg 321: {
1.10 mrg 322: static struct vm_map_entry kernel_map_entry[MAX_KMAPENT];
1.1 mrg 323: #if defined(UVMHIST)
1.10 mrg 324: static struct uvm_history_ent maphistbuf[100];
325: static struct uvm_history_ent pdhistbuf[100];
1.1 mrg 326: #endif
1.10 mrg 327: int lcv;
328:
329: /*
330: * first, init logging system.
331: */
1.1 mrg 332:
1.10 mrg 333: UVMHIST_FUNC("uvm_map_init");
334: UVMHIST_INIT_STATIC(maphist, maphistbuf);
335: UVMHIST_INIT_STATIC(pdhist, pdhistbuf);
336: UVMHIST_CALLED(maphist);
337: UVMHIST_LOG(maphist,"<starting uvm map system>", 0, 0, 0, 0);
338: UVMCNT_INIT(uvm_map_call, UVMCNT_CNT, 0,
339: "# uvm_map() successful calls", 0);
340: UVMCNT_INIT(map_backmerge, UVMCNT_CNT, 0, "# uvm_map() back merges", 0);
341: UVMCNT_INIT(map_forwmerge, UVMCNT_CNT, 0, "# uvm_map() missed forward",
342: 0);
343: UVMCNT_INIT(uvm_mlk_call, UVMCNT_CNT, 0, "# map lookup calls", 0);
344: UVMCNT_INIT(uvm_mlk_hint, UVMCNT_CNT, 0, "# map lookup hint hits", 0);
345:
346: /*
347: * now set up static pool of kernel map entrys ...
348: */
349:
350: simple_lock_init(&uvm.kentry_lock);
351: uvm.kentry_free = NULL;
352: for (lcv = 0 ; lcv < MAX_KMAPENT ; lcv++) {
353: kernel_map_entry[lcv].next = uvm.kentry_free;
354: uvm.kentry_free = &kernel_map_entry[lcv];
355: }
1.1 mrg 356:
1.25 thorpej 357: /*
358: * initialize the map-related pools.
359: */
360: pool_init(&uvm_vmspace_pool, sizeof(struct vmspace),
361: 0, 0, 0, "vmsppl", 0,
1.26 thorpej 362: pool_page_alloc_nointr, pool_page_free_nointr, M_VMMAP);
363: pool_init(&uvm_map_entry_pool, sizeof(struct vm_map_entry),
364: 0, 0, 0, "vmmpepl", 0,
1.25 thorpej 365: pool_page_alloc_nointr, pool_page_free_nointr, M_VMMAP);
1.1 mrg 366: }
367:
368: /*
369: * clippers
370: */
371:
372: /*
373: * uvm_map_clip_start: ensure that the entry begins at or after
374: * the starting address, if it doesn't we split the entry.
375: *
376: * => caller should use UVM_MAP_CLIP_START macro rather than calling
377: * this directly
378: * => map must be locked by caller
379: */
380:
381: void uvm_map_clip_start(map, entry, start)
1.32 mrg 382: vm_map_t map;
383: vm_map_entry_t entry;
384: vaddr_t start;
1.1 mrg 385: {
1.32 mrg 386: vm_map_entry_t new_entry;
1.24 eeh 387: vaddr_t new_adj;
1.1 mrg 388:
389: /* uvm_map_simplify_entry(map, entry); */ /* XXX */
390:
1.10 mrg 391: /*
392: * Split off the front portion. note that we must insert the new
393: * entry BEFORE this one, so that this entry has the specified
1.1 mrg 394: * starting address.
1.10 mrg 395: */
1.1 mrg 396:
1.10 mrg 397: new_entry = uvm_mapent_alloc(map);
1.1 mrg 398: uvm_mapent_copy(entry, new_entry); /* entry -> new_entry */
1.85 chs 399:
1.10 mrg 400: new_entry->end = start;
1.1 mrg 401: new_adj = start - new_entry->start;
402: if (entry->object.uvm_obj)
1.10 mrg 403: entry->offset += new_adj; /* shift start over */
404: entry->start = start;
1.1 mrg 405:
406: if (new_entry->aref.ar_amap) {
1.10 mrg 407: amap_splitref(&new_entry->aref, &entry->aref, new_adj);
1.1 mrg 408: }
409:
1.10 mrg 410: uvm_map_entry_link(map, entry->prev, new_entry);
1.85 chs 411:
1.29 chuck 412: if (UVM_ET_ISSUBMAP(entry)) {
413: /* ... unlikely to happen, but play it safe */
414: uvm_map_reference(new_entry->object.sub_map);
1.1 mrg 415: } else {
1.10 mrg 416: if (UVM_ET_ISOBJ(entry) &&
417: entry->object.uvm_obj->pgops &&
418: entry->object.uvm_obj->pgops->pgo_reference)
419: entry->object.uvm_obj->pgops->pgo_reference(
420: entry->object.uvm_obj);
1.1 mrg 421: }
422: }
423:
424: /*
425: * uvm_map_clip_end: ensure that the entry ends at or before
426: * the ending address, if it does't we split the reference
427: *
428: * => caller should use UVM_MAP_CLIP_END macro rather than calling
429: * this directly
430: * => map must be locked by caller
431: */
432:
1.10 mrg 433: void
434: uvm_map_clip_end(map, entry, end)
435: vm_map_t map;
436: vm_map_entry_t entry;
1.24 eeh 437: vaddr_t end;
1.1 mrg 438: {
1.10 mrg 439: vm_map_entry_t new_entry;
1.24 eeh 440: vaddr_t new_adj; /* #bytes we move start forward */
1.1 mrg 441:
442: /*
443: * Create a new entry and insert it
444: * AFTER the specified entry
445: */
446:
447: new_entry = uvm_mapent_alloc(map);
448: uvm_mapent_copy(entry, new_entry); /* entry -> new_entry */
449:
450: new_entry->start = entry->end = end;
451: new_adj = end - entry->start;
452: if (new_entry->object.uvm_obj)
453: new_entry->offset += new_adj;
454:
1.10 mrg 455: if (entry->aref.ar_amap)
456: amap_splitref(&entry->aref, &new_entry->aref, new_adj);
1.1 mrg 457:
458: uvm_map_entry_link(map, entry, new_entry);
459:
1.29 chuck 460: if (UVM_ET_ISSUBMAP(entry)) {
461: /* ... unlikely to happen, but play it safe */
462: uvm_map_reference(new_entry->object.sub_map);
1.1 mrg 463: } else {
1.10 mrg 464: if (UVM_ET_ISOBJ(entry) &&
465: entry->object.uvm_obj->pgops &&
466: entry->object.uvm_obj->pgops->pgo_reference)
467: entry->object.uvm_obj->pgops->pgo_reference(
468: entry->object.uvm_obj);
1.1 mrg 469: }
470: }
471:
472:
473: /*
474: * M A P - m a i n e n t r y p o i n t
475: */
476: /*
477: * uvm_map: establish a valid mapping in a map
478: *
479: * => assume startp is page aligned.
480: * => assume size is a multiple of PAGE_SIZE.
481: * => assume sys_mmap provides enough of a "hint" to have us skip
482: * over text/data/bss area.
483: * => map must be unlocked (we will lock it)
484: * => <uobj,uoffset> value meanings (4 cases):
485: * [1] <NULL,uoffset> == uoffset is a hint for PMAP_PREFER
486: * [2] <NULL,UVM_UNKNOWN_OFFSET> == don't PMAP_PREFER
487: * [3] <uobj,uoffset> == normal mapping
488: * [4] <uobj,UVM_UNKNOWN_OFFSET> == uvm_map finds offset based on VA
489: *
490: * case [4] is for kernel mappings where we don't know the offset until
1.8 chuck 491: * we've found a virtual address. note that kernel object offsets are
492: * always relative to vm_map_min(kernel_map).
1.81 thorpej 493: *
494: * => if `align' is non-zero, we try to align the virtual address to
495: * the specified alignment. this is only a hint; if we can't
496: * do it, the address will be unaligned. this is provided as
497: * a mechanism for large pages.
498: *
1.1 mrg 499: * => XXXCDC: need way to map in external amap?
500: */
501:
1.10 mrg 502: int
1.81 thorpej 503: uvm_map(map, startp, size, uobj, uoffset, align, flags)
1.10 mrg 504: vm_map_t map;
1.24 eeh 505: vaddr_t *startp; /* IN/OUT */
506: vsize_t size;
1.10 mrg 507: struct uvm_object *uobj;
1.70 kleink 508: voff_t uoffset;
1.81 thorpej 509: vsize_t align;
1.10 mrg 510: uvm_flag_t flags;
511: {
512: vm_map_entry_t prev_entry, new_entry;
513: vm_prot_t prot = UVM_PROTECTION(flags), maxprot =
514: UVM_MAXPROTECTION(flags);
515: vm_inherit_t inherit = UVM_INHERIT(flags);
516: int advice = UVM_ADVICE(flags);
517: UVMHIST_FUNC("uvm_map");
518: UVMHIST_CALLED(maphist);
1.1 mrg 519:
1.10 mrg 520: UVMHIST_LOG(maphist, "(map=0x%x, *startp=0x%x, size=%d, flags=0x%x)",
521: map, *startp, size, flags);
522: UVMHIST_LOG(maphist, " uobj/offset 0x%x/%d", uobj, uoffset,0,0);
1.1 mrg 523:
1.10 mrg 524: /*
525: * step 0: sanity check of protection code
526: */
1.1 mrg 527:
1.10 mrg 528: if ((prot & maxprot) != prot) {
529: UVMHIST_LOG(maphist, "<- prot. failure: prot=0x%x, max=0x%x",
530: prot, maxprot,0,0);
1.94 chs 531: return EACCES;
1.10 mrg 532: }
1.1 mrg 533:
1.10 mrg 534: /*
535: * step 1: figure out where to put new VM range
536: */
1.1 mrg 537:
1.10 mrg 538: if (vm_map_lock_try(map) == FALSE) {
539: if (flags & UVM_FLAG_TRYLOCK)
1.94 chs 540: return EAGAIN;
1.10 mrg 541: vm_map_lock(map); /* could sleep here */
542: }
543: if ((prev_entry = uvm_map_findspace(map, *startp, size, startp,
1.81 thorpej 544: uobj, uoffset, align, flags)) == NULL) {
1.10 mrg 545: UVMHIST_LOG(maphist,"<- uvm_map_findspace failed!",0,0,0,0);
546: vm_map_unlock(map);
1.94 chs 547: return ENOMEM;
1.10 mrg 548: }
1.1 mrg 549:
1.40 thorpej 550: #ifdef PMAP_GROWKERNEL
1.10 mrg 551: {
552: /*
1.40 thorpej 553: * If the kernel pmap can't map the requested space,
554: * then allocate more resources for it.
1.10 mrg 555: */
1.40 thorpej 556: if (map == kernel_map && uvm_maxkaddr < (*startp + size))
557: uvm_maxkaddr = pmap_growkernel(*startp + size);
1.10 mrg 558: }
559: #endif
560:
561: UVMCNT_INCR(uvm_map_call);
562:
563: /*
564: * if uobj is null, then uoffset is either a VAC hint for PMAP_PREFER
565: * [typically from uvm_map_reserve] or it is UVM_UNKNOWN_OFFSET. in
566: * either case we want to zero it before storing it in the map entry
567: * (because it looks strange and confusing when debugging...)
568: *
569: * if uobj is not null
570: * if uoffset is not UVM_UNKNOWN_OFFSET then we have a normal mapping
571: * and we do not need to change uoffset.
572: * if uoffset is UVM_UNKNOWN_OFFSET then we need to find the offset
573: * now (based on the starting address of the map). this case is
574: * for kernel object mappings where we don't know the offset until
575: * the virtual address is found (with uvm_map_findspace). the
576: * offset is the distance we are from the start of the map.
577: */
578:
579: if (uobj == NULL) {
580: uoffset = 0;
581: } else {
582: if (uoffset == UVM_UNKNOWN_OFFSET) {
1.85 chs 583: KASSERT(UVM_OBJ_IS_KERN_OBJECT(uobj));
1.10 mrg 584: uoffset = *startp - vm_map_min(kernel_map);
585: }
586: }
587:
588: /*
589: * step 2: try and insert in map by extending previous entry, if
590: * possible
591: * XXX: we don't try and pull back the next entry. might be useful
592: * for a stack, but we are currently allocating our stack in advance.
593: */
594:
595: if ((flags & UVM_FLAG_NOMERGE) == 0 &&
596: prev_entry->end == *startp && prev_entry != &map->header &&
597: prev_entry->object.uvm_obj == uobj) {
598:
599: if (uobj && prev_entry->offset +
600: (prev_entry->end - prev_entry->start) != uoffset)
601: goto step3;
602:
1.29 chuck 603: if (UVM_ET_ISSUBMAP(prev_entry))
1.10 mrg 604: goto step3;
605:
606: if (prev_entry->protection != prot ||
607: prev_entry->max_protection != maxprot)
608: goto step3;
609:
610: if (prev_entry->inheritance != inherit ||
611: prev_entry->advice != advice)
612: goto step3;
613:
1.56 thorpej 614: /* wiring status must match (new area is unwired) */
1.55 thorpej 615: if (VM_MAPENT_ISWIRED(prev_entry))
1.10 mrg 616: goto step3;
617:
618: /*
619: * can't extend a shared amap. note: no need to lock amap to
1.34 chuck 620: * look at refs since we don't care about its exact value.
1.10 mrg 621: * if it is one (i.e. we have only reference) it will stay there
622: */
1.85 chs 623:
1.10 mrg 624: if (prev_entry->aref.ar_amap &&
1.34 chuck 625: amap_refs(prev_entry->aref.ar_amap) != 1) {
1.10 mrg 626: goto step3;
627: }
1.85 chs 628:
1.10 mrg 629: /* got it! */
630:
631: UVMCNT_INCR(map_backmerge);
632: UVMHIST_LOG(maphist," starting back merge", 0, 0, 0, 0);
633:
634: /*
635: * drop our reference to uobj since we are extending a reference
636: * that we already have (the ref count can not drop to zero).
637: */
638: if (uobj && uobj->pgops->pgo_detach)
639: uobj->pgops->pgo_detach(uobj);
640:
641: if (prev_entry->aref.ar_amap) {
642: amap_extend(prev_entry, size);
643: }
644:
645: prev_entry->end += size;
646: map->size += size;
647:
648: UVMHIST_LOG(maphist,"<- done (via backmerge)!", 0, 0, 0, 0);
649: vm_map_unlock(map);
1.94 chs 650: return 0;
1.10 mrg 651:
1.1 mrg 652: }
1.10 mrg 653: step3:
654: UVMHIST_LOG(maphist," allocating new map entry", 0, 0, 0, 0);
655:
656: /*
657: * check for possible forward merge (which we don't do) and count
658: * the number of times we missed a *possible* chance to merge more
659: */
1.1 mrg 660:
1.10 mrg 661: if ((flags & UVM_FLAG_NOMERGE) == 0 &&
662: prev_entry->next != &map->header &&
663: prev_entry->next->start == (*startp + size))
664: UVMCNT_INCR(map_forwmerge);
1.1 mrg 665:
666: /*
1.10 mrg 667: * step 3: allocate new entry and link it in
1.1 mrg 668: */
669:
1.10 mrg 670: new_entry = uvm_mapent_alloc(map);
671: new_entry->start = *startp;
672: new_entry->end = new_entry->start + size;
673: new_entry->object.uvm_obj = uobj;
674: new_entry->offset = uoffset;
675:
676: if (uobj)
677: new_entry->etype = UVM_ET_OBJ;
678: else
679: new_entry->etype = 0;
680:
681: if (flags & UVM_FLAG_COPYONW) {
682: new_entry->etype |= UVM_ET_COPYONWRITE;
683: if ((flags & UVM_FLAG_OVERLAY) == 0)
684: new_entry->etype |= UVM_ET_NEEDSCOPY;
685: }
686:
687: new_entry->protection = prot;
688: new_entry->max_protection = maxprot;
689: new_entry->inheritance = inherit;
690: new_entry->wired_count = 0;
691: new_entry->advice = advice;
692: if (flags & UVM_FLAG_OVERLAY) {
693: /*
694: * to_add: for BSS we overallocate a little since we
695: * are likely to extend
696: */
1.24 eeh 697: vaddr_t to_add = (flags & UVM_FLAG_AMAPPAD) ?
1.30 chs 698: UVM_AMAP_CHUNK << PAGE_SHIFT : 0;
1.10 mrg 699: struct vm_amap *amap = amap_alloc(size, to_add, M_WAITOK);
1.34 chuck 700: new_entry->aref.ar_pageoff = 0;
1.10 mrg 701: new_entry->aref.ar_amap = amap;
702: } else {
1.77 chs 703: new_entry->aref.ar_pageoff = 0;
1.10 mrg 704: new_entry->aref.ar_amap = NULL;
1.1 mrg 705: }
706:
1.10 mrg 707: uvm_map_entry_link(map, prev_entry, new_entry);
708:
1.1 mrg 709: map->size += size;
710:
1.10 mrg 711: /*
712: * Update the free space hint
713: */
714:
715: if ((map->first_free == prev_entry) &&
716: (prev_entry->end >= new_entry->start))
717: map->first_free = new_entry;
718:
719: UVMHIST_LOG(maphist,"<- done!", 0, 0, 0, 0);
1.1 mrg 720: vm_map_unlock(map);
1.94 chs 721: return 0;
1.1 mrg 722: }
723:
724: /*
725: * uvm_map_lookup_entry: find map entry at or before an address
726: *
727: * => map must at least be read-locked by caller
728: * => entry is returned in "entry"
729: * => return value is true if address is in the returned entry
730: */
731:
1.10 mrg 732: boolean_t
733: uvm_map_lookup_entry(map, address, entry)
1.32 mrg 734: vm_map_t map;
735: vaddr_t address;
1.10 mrg 736: vm_map_entry_t *entry; /* OUT */
1.1 mrg 737: {
1.32 mrg 738: vm_map_entry_t cur;
739: vm_map_entry_t last;
1.1 mrg 740: UVMHIST_FUNC("uvm_map_lookup_entry");
741: UVMHIST_CALLED(maphist);
742:
743: UVMHIST_LOG(maphist,"(map=0x%x,addr=0x%x,ent=0x%x)",
1.10 mrg 744: map, address, entry, 0);
1.1 mrg 745:
746: /*
1.10 mrg 747: * start looking either from the head of the
748: * list, or from the hint.
1.1 mrg 749: */
750:
751: simple_lock(&map->hint_lock);
752: cur = map->hint;
753: simple_unlock(&map->hint_lock);
754:
755: if (cur == &map->header)
756: cur = cur->next;
757:
758: UVMCNT_INCR(uvm_mlk_call);
759: if (address >= cur->start) {
760: /*
1.10 mrg 761: * go from hint to end of list.
1.1 mrg 762: *
1.10 mrg 763: * but first, make a quick check to see if
764: * we are already looking at the entry we
765: * want (which is usually the case).
766: * note also that we don't need to save the hint
767: * here... it is the same hint (unless we are
768: * at the header, in which case the hint didn't
769: * buy us anything anyway).
1.1 mrg 770: */
771: last = &map->header;
772: if ((cur != last) && (cur->end > address)) {
773: UVMCNT_INCR(uvm_mlk_hint);
774: *entry = cur;
775: UVMHIST_LOG(maphist,"<- got it via hint (0x%x)",
1.10 mrg 776: cur, 0, 0, 0);
777: return (TRUE);
1.1 mrg 778: }
1.10 mrg 779: } else {
1.1 mrg 780: /*
1.10 mrg 781: * go from start to hint, *inclusively*
1.1 mrg 782: */
783: last = cur->next;
784: cur = map->header.next;
785: }
786:
787: /*
1.10 mrg 788: * search linearly
1.1 mrg 789: */
790:
791: while (cur != last) {
792: if (cur->end > address) {
793: if (address >= cur->start) {
794: /*
1.10 mrg 795: * save this lookup for future
796: * hints, and return
1.1 mrg 797: */
798:
799: *entry = cur;
1.82 thorpej 800: SAVE_HINT(map, map->hint, cur);
1.1 mrg 801: UVMHIST_LOG(maphist,"<- search got it (0x%x)",
1.10 mrg 802: cur, 0, 0, 0);
803: return (TRUE);
1.1 mrg 804: }
805: break;
806: }
807: cur = cur->next;
808: }
809: *entry = cur->prev;
1.82 thorpej 810: SAVE_HINT(map, map->hint, *entry);
1.1 mrg 811: UVMHIST_LOG(maphist,"<- failed!",0,0,0,0);
1.10 mrg 812: return (FALSE);
1.1 mrg 813: }
814:
815: /*
816: * uvm_map_findspace: find "length" sized space in "map".
817: *
1.81 thorpej 818: * => "hint" is a hint about where we want it, unless FINDSPACE_FIXED is
819: * set (in which case we insist on using "hint").
1.1 mrg 820: * => "result" is VA returned
821: * => uobj/uoffset are to be used to handle VAC alignment, if required
1.81 thorpej 822: * => if `align' is non-zero, we attempt to align to that value.
1.1 mrg 823: * => caller must at least have read-locked map
824: * => returns NULL on failure, or pointer to prev. map entry if success
825: * => note this is a cross between the old vm_map_findspace and vm_map_find
826: */
827:
1.10 mrg 828: vm_map_entry_t
1.81 thorpej 829: uvm_map_findspace(map, hint, length, result, uobj, uoffset, align, flags)
1.10 mrg 830: vm_map_t map;
1.24 eeh 831: vaddr_t hint;
832: vsize_t length;
833: vaddr_t *result; /* OUT */
1.10 mrg 834: struct uvm_object *uobj;
1.70 kleink 835: voff_t uoffset;
1.81 thorpej 836: vsize_t align;
837: int flags;
1.1 mrg 838: {
839: vm_map_entry_t entry, next, tmp;
1.81 thorpej 840: vaddr_t end, orig_hint;
1.1 mrg 841: UVMHIST_FUNC("uvm_map_findspace");
842: UVMHIST_CALLED(maphist);
843:
1.81 thorpej 844: UVMHIST_LOG(maphist, "(map=0x%x, hint=0x%x, len=%d, flags=0x%x)",
1.85 chs 845: map, hint, length, flags);
846: KASSERT((align & (align - 1)) == 0);
847: KASSERT((flags & UVM_FLAG_FIXED) == 0 || align == 0);
1.81 thorpej 848:
849: /*
850: * remember the original hint. if we are aligning, then we
851: * may have to try again with no alignment constraint if
852: * we fail the first time.
853: */
1.85 chs 854:
1.81 thorpej 855: orig_hint = hint;
1.1 mrg 856: if (hint < map->min_offset) { /* check ranges ... */
1.81 thorpej 857: if (flags & UVM_FLAG_FIXED) {
1.1 mrg 858: UVMHIST_LOG(maphist,"<- VA below map range",0,0,0,0);
859: return(NULL);
860: }
861: hint = map->min_offset;
862: }
863: if (hint > map->max_offset) {
864: UVMHIST_LOG(maphist,"<- VA 0x%x > range [0x%x->0x%x]",
865: hint, map->min_offset, map->max_offset, 0);
866: return(NULL);
867: }
868:
869: /*
870: * Look for the first possible address; if there's already
871: * something at this address, we have to start after it.
872: */
873:
1.81 thorpej 874: if ((flags & UVM_FLAG_FIXED) == 0 && hint == map->min_offset) {
1.1 mrg 875: if ((entry = map->first_free) != &map->header)
876: hint = entry->end;
877: } else {
878: if (uvm_map_lookup_entry(map, hint, &tmp)) {
879: /* "hint" address already in use ... */
1.81 thorpej 880: if (flags & UVM_FLAG_FIXED) {
1.1 mrg 881: UVMHIST_LOG(maphist,"<- fixed & VA in use",
1.10 mrg 882: 0, 0, 0, 0);
1.1 mrg 883: return(NULL);
884: }
885: hint = tmp->end;
886: }
887: entry = tmp;
888: }
889:
890: /*
891: * Look through the rest of the map, trying to fit a new region in
892: * the gap between existing regions, or after the very last region.
893: * note: entry->end = base VA of current gap,
894: * next->start = VA of end of current gap
895: */
896: for (;; hint = (entry = next)->end) {
897: /*
898: * Find the end of the proposed new region. Be sure we didn't
899: * go beyond the end of the map, or wrap around the address;
900: * if so, we lose. Otherwise, if this is the last entry, or
901: * if the proposed new region fits before the next entry, we
902: * win.
903: */
904:
905: #ifdef PMAP_PREFER
906: /*
907: * push hint forward as needed to avoid VAC alias problems.
908: * we only do this if a valid offset is specified.
909: */
1.81 thorpej 910: if ((flags & UVM_FLAG_FIXED) == 0 &&
911: uoffset != UVM_UNKNOWN_OFFSET)
912: PMAP_PREFER(uoffset, &hint);
1.1 mrg 913: #endif
1.81 thorpej 914: if (align != 0) {
915: if ((hint & (align - 1)) != 0)
916: hint = roundup(hint, align);
917: /*
918: * XXX Should we PMAP_PREFER() here again?
919: */
920: }
1.1 mrg 921: end = hint + length;
922: if (end > map->max_offset || end < hint) {
923: UVMHIST_LOG(maphist,"<- failed (off end)", 0,0,0,0);
1.81 thorpej 924: if (align != 0) {
925: UVMHIST_LOG(maphist,
926: "calling recursively, no align",
927: 0,0,0,0);
928: return (uvm_map_findspace(map, orig_hint,
929: length, result, uobj, uoffset, 0, flags));
930: }
1.1 mrg 931: return (NULL);
932: }
933: next = entry->next;
934: if (next == &map->header || next->start >= end)
935: break;
1.81 thorpej 936: if (flags & UVM_FLAG_FIXED) {
1.1 mrg 937: UVMHIST_LOG(maphist,"<- fixed mapping failed", 0,0,0,0);
938: return(NULL); /* only one shot at it ... */
939: }
940: }
1.82 thorpej 941: SAVE_HINT(map, map->hint, entry);
1.1 mrg 942: *result = hint;
943: UVMHIST_LOG(maphist,"<- got it! (result=0x%x)", hint, 0,0,0);
944: return (entry);
945: }
946:
947: /*
948: * U N M A P - m a i n h e l p e r f u n c t i o n s
949: */
950:
951: /*
952: * uvm_unmap_remove: remove mappings from a vm_map (from "start" up to "stop")
953: *
954: * => caller must check alignment and size
955: * => map must be locked by caller
956: * => we return a list of map entries that we've remove from the map
957: * in "entry_list"
958: */
959:
1.94 chs 960: void
1.29 chuck 961: uvm_unmap_remove(map, start, end, entry_list)
1.10 mrg 962: vm_map_t map;
1.24 eeh 963: vaddr_t start,end;
1.10 mrg 964: vm_map_entry_t *entry_list; /* OUT */
965: {
966: vm_map_entry_t entry, first_entry, next;
1.24 eeh 967: vaddr_t len;
1.10 mrg 968: UVMHIST_FUNC("uvm_unmap_remove");
969: UVMHIST_CALLED(maphist);
970:
971: UVMHIST_LOG(maphist,"(map=0x%x, start=0x%x, end=0x%x)",
972: map, start, end, 0);
973:
974: VM_MAP_RANGE_CHECK(map, start, end);
975:
976: /*
977: * find first entry
978: */
979: if (uvm_map_lookup_entry(map, start, &first_entry) == TRUE) {
1.29 chuck 980: /* clip and go... */
1.10 mrg 981: entry = first_entry;
982: UVM_MAP_CLIP_START(map, entry, start);
983: /* critical! prevents stale hint */
1.82 thorpej 984: SAVE_HINT(map, entry, entry->prev);
1.10 mrg 985:
986: } else {
987: entry = first_entry->next;
988: }
989:
990: /*
991: * Save the free space hint
992: */
993:
994: if (map->first_free->start >= start)
995: map->first_free = entry->prev;
996:
997: /*
998: * note: we now re-use first_entry for a different task. we remove
999: * a number of map entries from the map and save them in a linked
1000: * list headed by "first_entry". once we remove them from the map
1001: * the caller should unlock the map and drop the references to the
1002: * backing objects [c.f. uvm_unmap_detach]. the object is to
1003: * seperate unmapping from reference dropping. why?
1004: * [1] the map has to be locked for unmapping
1005: * [2] the map need not be locked for reference dropping
1006: * [3] dropping references may trigger pager I/O, and if we hit
1007: * a pager that does synchronous I/O we may have to wait for it.
1008: * [4] we would like all waiting for I/O to occur with maps unlocked
1009: * so that we don't block other threads.
1010: */
1011: first_entry = NULL;
1012: *entry_list = NULL; /* to be safe */
1013:
1014: /*
1015: * break up the area into map entry sized regions and unmap. note
1016: * that all mappings have to be removed before we can even consider
1017: * dropping references to amaps or VM objects (otherwise we could end
1018: * up with a mapping to a page on the free list which would be very bad)
1019: */
1020:
1021: while ((entry != &map->header) && (entry->start < end)) {
1022:
1023: UVM_MAP_CLIP_END(map, entry, end);
1024: next = entry->next;
1025: len = entry->end - entry->start;
1.81 thorpej 1026:
1.10 mrg 1027: /*
1028: * unwire before removing addresses from the pmap; otherwise
1029: * unwiring will put the entries back into the pmap (XXX).
1030: */
1.1 mrg 1031:
1.55 thorpej 1032: if (VM_MAPENT_ISWIRED(entry))
1.10 mrg 1033: uvm_map_entry_unwire(map, entry);
1034:
1035: /*
1036: * special case: handle mappings to anonymous kernel objects.
1037: * we want to free these pages right away...
1038: */
1039: if (UVM_ET_ISOBJ(entry) &&
1.42 thorpej 1040: UVM_OBJ_IS_KERN_OBJECT(entry->object.uvm_obj)) {
1.85 chs 1041: KASSERT(vm_map_pmap(map) == pmap_kernel());
1.1 mrg 1042:
1.10 mrg 1043: /*
1044: * note: kernel object mappings are currently used in
1045: * two ways:
1046: * [1] "normal" mappings of pages in the kernel object
1047: * [2] uvm_km_valloc'd allocations in which we
1048: * pmap_enter in some non-kernel-object page
1049: * (e.g. vmapbuf).
1050: *
1051: * for case [1], we need to remove the mapping from
1052: * the pmap and then remove the page from the kernel
1053: * object (because, once pages in a kernel object are
1054: * unmapped they are no longer needed, unlike, say,
1055: * a vnode where you might want the data to persist
1056: * until flushed out of a queue).
1057: *
1058: * for case [2], we need to remove the mapping from
1059: * the pmap. there shouldn't be any pages at the
1060: * specified offset in the kernel object [but it
1061: * doesn't hurt to call uvm_km_pgremove just to be
1062: * safe?]
1063: *
1064: * uvm_km_pgremove currently does the following:
1065: * for pages in the kernel object in range:
1.43 thorpej 1066: * - drops the swap slot
1.10 mrg 1067: * - uvm_pagefree the page
1068: *
1.43 thorpej 1069: * note there is version of uvm_km_pgremove() that
1070: * is used for "intrsafe" objects.
1.10 mrg 1071: */
1072:
1073: /*
1.43 thorpej 1074: * remove mappings from pmap and drop the pages
1075: * from the object. offsets are always relative
1076: * to vm_map_min(kernel_map).
1.10 mrg 1077: */
1.43 thorpej 1078: if (UVM_OBJ_IS_INTRSAFE_OBJECT(entry->object.uvm_obj)) {
1079: pmap_kremove(entry->start, len);
1080: uvm_km_pgremove_intrsafe(entry->object.uvm_obj,
1081: entry->start - vm_map_min(kernel_map),
1082: entry->end - vm_map_min(kernel_map));
1083: } else {
1084: pmap_remove(pmap_kernel(), entry->start,
1085: entry->start + len);
1086: uvm_km_pgremove(entry->object.uvm_obj,
1087: entry->start - vm_map_min(kernel_map),
1088: entry->end - vm_map_min(kernel_map));
1089: }
1.10 mrg 1090:
1091: /*
1092: * null out kernel_object reference, we've just
1093: * dropped it
1094: */
1095: entry->etype &= ~UVM_ET_OBJ;
1096: entry->object.uvm_obj = NULL; /* to be safe */
1097:
1098: } else {
1.29 chuck 1099: /*
1100: * remove mappings the standard way.
1101: */
1102: pmap_remove(map->pmap, entry->start, entry->end);
1.10 mrg 1103: }
1104:
1105: /*
1.29 chuck 1106: * remove entry from map and put it on our list of entries
1107: * that we've nuked. then go do next entry.
1.10 mrg 1108: */
1109: UVMHIST_LOG(maphist, " removed map entry 0x%x", entry, 0, 0,0);
1.82 thorpej 1110:
1111: /* critical! prevents stale hint */
1112: SAVE_HINT(map, entry, entry->prev);
1113:
1.10 mrg 1114: uvm_map_entry_unlink(map, entry);
1115: map->size -= len;
1116: entry->next = first_entry;
1117: first_entry = entry;
1118: entry = next; /* next entry, please */
1119: }
1.95 thorpej 1120: pmap_update();
1.10 mrg 1121:
1122: /*
1123: * now we've cleaned up the map and are ready for the caller to drop
1124: * references to the mapped objects.
1125: */
1126:
1127: *entry_list = first_entry;
1128: UVMHIST_LOG(maphist,"<- done!", 0, 0, 0, 0);
1.1 mrg 1129: }
1130:
1131: /*
1132: * uvm_unmap_detach: drop references in a chain of map entries
1133: *
1134: * => we will free the map entries as we traverse the list.
1135: */
1136:
1.10 mrg 1137: void
1.85 chs 1138: uvm_unmap_detach(first_entry, flags)
1.10 mrg 1139: vm_map_entry_t first_entry;
1.85 chs 1140: int flags;
1.1 mrg 1141: {
1.10 mrg 1142: vm_map_entry_t next_entry;
1143: UVMHIST_FUNC("uvm_unmap_detach"); UVMHIST_CALLED(maphist);
1.1 mrg 1144:
1.10 mrg 1145: while (first_entry) {
1.85 chs 1146: KASSERT(!VM_MAPENT_ISWIRED(first_entry));
1.10 mrg 1147: UVMHIST_LOG(maphist,
1.29 chuck 1148: " detach 0x%x: amap=0x%x, obj=0x%x, submap?=%d",
1149: first_entry, first_entry->aref.ar_amap,
1150: first_entry->object.uvm_obj,
1151: UVM_ET_ISSUBMAP(first_entry));
1.1 mrg 1152:
1.10 mrg 1153: /*
1154: * drop reference to amap, if we've got one
1155: */
1156:
1157: if (first_entry->aref.ar_amap)
1.85 chs 1158: uvm_map_unreference_amap(first_entry, flags);
1.10 mrg 1159:
1160: /*
1161: * drop reference to our backing object, if we've got one
1162: */
1.85 chs 1163:
1.29 chuck 1164: if (UVM_ET_ISSUBMAP(first_entry)) {
1165: /* ... unlikely to happen, but play it safe */
1166: uvm_map_deallocate(first_entry->object.sub_map);
1.10 mrg 1167: } else {
1168: if (UVM_ET_ISOBJ(first_entry) &&
1169: first_entry->object.uvm_obj->pgops->pgo_detach)
1170: first_entry->object.uvm_obj->pgops->
1171: pgo_detach(first_entry->object.uvm_obj);
1172: }
1173:
1174: next_entry = first_entry->next;
1175: uvm_mapent_free(first_entry);
1176: first_entry = next_entry;
1177: }
1178: UVMHIST_LOG(maphist, "<- done", 0,0,0,0);
1.1 mrg 1179: }
1180:
1181: /*
1182: * E X T R A C T I O N F U N C T I O N S
1183: */
1184:
1185: /*
1186: * uvm_map_reserve: reserve space in a vm_map for future use.
1187: *
1188: * => we reserve space in a map by putting a dummy map entry in the
1189: * map (dummy means obj=NULL, amap=NULL, prot=VM_PROT_NONE)
1190: * => map should be unlocked (we will write lock it)
1191: * => we return true if we were able to reserve space
1192: * => XXXCDC: should be inline?
1193: */
1194:
1.10 mrg 1195: int
1.81 thorpej 1196: uvm_map_reserve(map, size, offset, align, raddr)
1.10 mrg 1197: vm_map_t map;
1.24 eeh 1198: vsize_t size;
1.81 thorpej 1199: vaddr_t offset; /* hint for pmap_prefer */
1200: vsize_t align; /* alignment hint */
1.75 pk 1201: vaddr_t *raddr; /* IN:hint, OUT: reserved VA */
1.1 mrg 1202: {
1.10 mrg 1203: UVMHIST_FUNC("uvm_map_reserve"); UVMHIST_CALLED(maphist);
1.85 chs 1204:
1.10 mrg 1205: UVMHIST_LOG(maphist, "(map=0x%x, size=0x%x, offset=0x%x,addr=0x%x)",
1.1 mrg 1206: map,size,offset,raddr);
1.85 chs 1207:
1.10 mrg 1208: size = round_page(size);
1209: if (*raddr < vm_map_min(map))
1210: *raddr = vm_map_min(map); /* hint */
1.85 chs 1211:
1.10 mrg 1212: /*
1213: * reserve some virtual space.
1214: */
1.85 chs 1215:
1.81 thorpej 1216: if (uvm_map(map, raddr, size, NULL, offset, 0,
1.10 mrg 1217: UVM_MAPFLAG(UVM_PROT_NONE, UVM_PROT_NONE, UVM_INH_NONE,
1.94 chs 1218: UVM_ADV_RANDOM, UVM_FLAG_NOMERGE)) != 0) {
1.10 mrg 1219: UVMHIST_LOG(maphist, "<- done (no VM)", 0,0,0,0);
1220: return (FALSE);
1221: }
1.85 chs 1222:
1.10 mrg 1223: UVMHIST_LOG(maphist, "<- done (*raddr=0x%x)", *raddr,0,0,0);
1224: return (TRUE);
1.1 mrg 1225: }
1226:
1227: /*
1228: * uvm_map_replace: replace a reserved (blank) area of memory with
1229: * real mappings.
1230: *
1231: * => caller must WRITE-LOCK the map
1232: * => we return TRUE if replacement was a success
1233: * => we expect the newents chain to have nnewents entrys on it and
1234: * we expect newents->prev to point to the last entry on the list
1235: * => note newents is allowed to be NULL
1236: */
1237:
1.10 mrg 1238: int
1239: uvm_map_replace(map, start, end, newents, nnewents)
1240: struct vm_map *map;
1.24 eeh 1241: vaddr_t start, end;
1.10 mrg 1242: vm_map_entry_t newents;
1243: int nnewents;
1244: {
1245: vm_map_entry_t oldent, last;
1.1 mrg 1246:
1.10 mrg 1247: /*
1248: * first find the blank map entry at the specified address
1249: */
1.85 chs 1250:
1.10 mrg 1251: if (!uvm_map_lookup_entry(map, start, &oldent)) {
1252: return(FALSE);
1253: }
1.85 chs 1254:
1.10 mrg 1255: /*
1256: * check to make sure we have a proper blank entry
1257: */
1.1 mrg 1258:
1.10 mrg 1259: if (oldent->start != start || oldent->end != end ||
1260: oldent->object.uvm_obj != NULL || oldent->aref.ar_amap != NULL) {
1261: return (FALSE);
1262: }
1.1 mrg 1263:
1264: #ifdef DIAGNOSTIC
1.10 mrg 1265: /*
1266: * sanity check the newents chain
1267: */
1268: {
1269: vm_map_entry_t tmpent = newents;
1270: int nent = 0;
1.24 eeh 1271: vaddr_t cur = start;
1.10 mrg 1272:
1273: while (tmpent) {
1274: nent++;
1275: if (tmpent->start < cur)
1276: panic("uvm_map_replace1");
1277: if (tmpent->start > tmpent->end || tmpent->end > end) {
1278: printf("tmpent->start=0x%lx, tmpent->end=0x%lx, end=0x%lx\n",
1279: tmpent->start, tmpent->end, end);
1280: panic("uvm_map_replace2");
1281: }
1282: cur = tmpent->end;
1283: if (tmpent->next) {
1284: if (tmpent->next->prev != tmpent)
1285: panic("uvm_map_replace3");
1286: } else {
1287: if (newents->prev != tmpent)
1288: panic("uvm_map_replace4");
1289: }
1290: tmpent = tmpent->next;
1291: }
1292: if (nent != nnewents)
1293: panic("uvm_map_replace5");
1294: }
1295: #endif
1296:
1297: /*
1298: * map entry is a valid blank! replace it. (this does all the
1299: * work of map entry link/unlink...).
1300: */
1301:
1302: if (newents) {
1303:
1304: last = newents->prev; /* we expect this */
1305:
1306: /* critical: flush stale hints out of map */
1.82 thorpej 1307: SAVE_HINT(map, map->hint, newents);
1.10 mrg 1308: if (map->first_free == oldent)
1309: map->first_free = last;
1310:
1311: last->next = oldent->next;
1312: last->next->prev = last;
1313: newents->prev = oldent->prev;
1314: newents->prev->next = newents;
1315: map->nentries = map->nentries + (nnewents - 1);
1316:
1317: } else {
1318:
1319: /* critical: flush stale hints out of map */
1.82 thorpej 1320: SAVE_HINT(map, map->hint, oldent->prev);
1.10 mrg 1321: if (map->first_free == oldent)
1322: map->first_free = oldent->prev;
1323:
1324: /* NULL list of new entries: just remove the old one */
1325: uvm_map_entry_unlink(map, oldent);
1326: }
1327:
1328:
1329: /*
1330: * now we can free the old blank entry, unlock the map and return.
1331: */
1.1 mrg 1332:
1.10 mrg 1333: uvm_mapent_free(oldent);
1334: return(TRUE);
1.1 mrg 1335: }
1336:
1337: /*
1338: * uvm_map_extract: extract a mapping from a map and put it somewhere
1339: * (maybe removing the old mapping)
1340: *
1341: * => maps should be unlocked (we will write lock them)
1342: * => returns 0 on success, error code otherwise
1343: * => start must be page aligned
1344: * => len must be page sized
1345: * => flags:
1346: * UVM_EXTRACT_REMOVE: remove mappings from srcmap
1347: * UVM_EXTRACT_CONTIG: abort if unmapped area (advisory only)
1348: * UVM_EXTRACT_QREF: for a temporary extraction do quick obj refs
1349: * UVM_EXTRACT_FIXPROT: set prot to maxprot as we go
1350: * >>>NOTE: if you set REMOVE, you are not allowed to use CONTIG or QREF!<<<
1351: * >>>NOTE: QREF's must be unmapped via the QREF path, thus should only
1352: * be used from within the kernel in a kernel level map <<<
1353: */
1354:
1.10 mrg 1355: int
1356: uvm_map_extract(srcmap, start, len, dstmap, dstaddrp, flags)
1357: vm_map_t srcmap, dstmap;
1.24 eeh 1358: vaddr_t start, *dstaddrp;
1359: vsize_t len;
1.10 mrg 1360: int flags;
1361: {
1.24 eeh 1362: vaddr_t dstaddr, end, newend, oldoffset, fudge, orig_fudge,
1.10 mrg 1363: oldstart;
1364: vm_map_entry_t chain, endchain, entry, orig_entry, newentry, deadentry;
1.20 chuck 1365: vm_map_entry_t oldentry;
1.24 eeh 1366: vsize_t elen;
1.10 mrg 1367: int nchain, error, copy_ok;
1368: UVMHIST_FUNC("uvm_map_extract"); UVMHIST_CALLED(maphist);
1.85 chs 1369:
1.10 mrg 1370: UVMHIST_LOG(maphist,"(srcmap=0x%x,start=0x%x, len=0x%x", srcmap, start,
1371: len,0);
1372: UVMHIST_LOG(maphist," ...,dstmap=0x%x, flags=0x%x)", dstmap,flags,0,0);
1373:
1374: /*
1375: * step 0: sanity check: start must be on a page boundary, length
1376: * must be page sized. can't ask for CONTIG/QREF if you asked for
1377: * REMOVE.
1378: */
1379:
1.85 chs 1380: KASSERT((start & PAGE_MASK) == 0 && (len & PAGE_MASK) == 0);
1381: KASSERT((flags & UVM_EXTRACT_REMOVE) == 0 ||
1382: (flags & (UVM_EXTRACT_CONTIG|UVM_EXTRACT_QREF)) == 0);
1.10 mrg 1383:
1384: /*
1385: * step 1: reserve space in the target map for the extracted area
1386: */
1387:
1.76 pk 1388: dstaddr = vm_map_min(dstmap);
1.81 thorpej 1389: if (uvm_map_reserve(dstmap, len, start, 0, &dstaddr) == FALSE)
1.10 mrg 1390: return(ENOMEM);
1391: *dstaddrp = dstaddr; /* pass address back to caller */
1392: UVMHIST_LOG(maphist, " dstaddr=0x%x", dstaddr,0,0,0);
1393:
1394: /*
1395: * step 2: setup for the extraction process loop by init'ing the
1396: * map entry chain, locking src map, and looking up the first useful
1397: * entry in the map.
1398: */
1.1 mrg 1399:
1.10 mrg 1400: end = start + len;
1401: newend = dstaddr + len;
1402: chain = endchain = NULL;
1403: nchain = 0;
1404: vm_map_lock(srcmap);
1405:
1406: if (uvm_map_lookup_entry(srcmap, start, &entry)) {
1407:
1408: /* "start" is within an entry */
1409: if (flags & UVM_EXTRACT_QREF) {
1.85 chs 1410:
1.10 mrg 1411: /*
1412: * for quick references we don't clip the entry, so
1413: * the entry may map space "before" the starting
1414: * virtual address... this is the "fudge" factor
1415: * (which can be non-zero only the first time
1416: * through the "while" loop in step 3).
1417: */
1.85 chs 1418:
1.10 mrg 1419: fudge = start - entry->start;
1420: } else {
1.85 chs 1421:
1.10 mrg 1422: /*
1423: * normal reference: we clip the map to fit (thus
1424: * fudge is zero)
1425: */
1.85 chs 1426:
1.10 mrg 1427: UVM_MAP_CLIP_START(srcmap, entry, start);
1.82 thorpej 1428: SAVE_HINT(srcmap, srcmap->hint, entry->prev);
1.10 mrg 1429: fudge = 0;
1430: }
1.85 chs 1431: } else {
1.1 mrg 1432:
1.10 mrg 1433: /* "start" is not within an entry ... skip to next entry */
1434: if (flags & UVM_EXTRACT_CONTIG) {
1435: error = EINVAL;
1436: goto bad; /* definite hole here ... */
1437: }
1.1 mrg 1438:
1.10 mrg 1439: entry = entry->next;
1440: fudge = 0;
1441: }
1.85 chs 1442:
1.10 mrg 1443: /* save values from srcmap for step 6 */
1444: orig_entry = entry;
1445: orig_fudge = fudge;
1.1 mrg 1446:
1.10 mrg 1447: /*
1448: * step 3: now start looping through the map entries, extracting
1449: * as we go.
1450: */
1.1 mrg 1451:
1.10 mrg 1452: while (entry->start < end && entry != &srcmap->header) {
1.85 chs 1453:
1.10 mrg 1454: /* if we are not doing a quick reference, clip it */
1455: if ((flags & UVM_EXTRACT_QREF) == 0)
1456: UVM_MAP_CLIP_END(srcmap, entry, end);
1457:
1458: /* clear needs_copy (allow chunking) */
1459: if (UVM_ET_ISNEEDSCOPY(entry)) {
1460: if (fudge)
1461: oldstart = entry->start;
1462: else
1463: oldstart = 0; /* XXX: gcc */
1464: amap_copy(srcmap, entry, M_NOWAIT, TRUE, start, end);
1465: if (UVM_ET_ISNEEDSCOPY(entry)) { /* failed? */
1466: error = ENOMEM;
1467: goto bad;
1468: }
1.85 chs 1469:
1.10 mrg 1470: /* amap_copy could clip (during chunk)! update fudge */
1471: if (fudge) {
1472: fudge = fudge - (entry->start - oldstart);
1473: orig_fudge = fudge;
1474: }
1475: }
1.1 mrg 1476:
1.10 mrg 1477: /* calculate the offset of this from "start" */
1478: oldoffset = (entry->start + fudge) - start;
1.1 mrg 1479:
1.10 mrg 1480: /* allocate a new map entry */
1481: newentry = uvm_mapent_alloc(dstmap);
1482: if (newentry == NULL) {
1483: error = ENOMEM;
1484: goto bad;
1485: }
1486:
1487: /* set up new map entry */
1488: newentry->next = NULL;
1489: newentry->prev = endchain;
1490: newentry->start = dstaddr + oldoffset;
1491: newentry->end =
1492: newentry->start + (entry->end - (entry->start + fudge));
1.37 chs 1493: if (newentry->end > newend || newentry->end < newentry->start)
1.10 mrg 1494: newentry->end = newend;
1495: newentry->object.uvm_obj = entry->object.uvm_obj;
1496: if (newentry->object.uvm_obj) {
1497: if (newentry->object.uvm_obj->pgops->pgo_reference)
1498: newentry->object.uvm_obj->pgops->
1499: pgo_reference(newentry->object.uvm_obj);
1500: newentry->offset = entry->offset + fudge;
1501: } else {
1502: newentry->offset = 0;
1503: }
1504: newentry->etype = entry->etype;
1505: newentry->protection = (flags & UVM_EXTRACT_FIXPROT) ?
1506: entry->max_protection : entry->protection;
1507: newentry->max_protection = entry->max_protection;
1508: newentry->inheritance = entry->inheritance;
1509: newentry->wired_count = 0;
1510: newentry->aref.ar_amap = entry->aref.ar_amap;
1511: if (newentry->aref.ar_amap) {
1.34 chuck 1512: newentry->aref.ar_pageoff =
1513: entry->aref.ar_pageoff + (fudge >> PAGE_SHIFT);
1.85 chs 1514: uvm_map_reference_amap(newentry, AMAP_SHARED |
1.10 mrg 1515: ((flags & UVM_EXTRACT_QREF) ? AMAP_REFALL : 0));
1516: } else {
1.34 chuck 1517: newentry->aref.ar_pageoff = 0;
1.10 mrg 1518: }
1519: newentry->advice = entry->advice;
1520:
1521: /* now link it on the chain */
1522: nchain++;
1523: if (endchain == NULL) {
1524: chain = endchain = newentry;
1525: } else {
1526: endchain->next = newentry;
1527: endchain = newentry;
1528: }
1529:
1530: /* end of 'while' loop! */
1531: if ((flags & UVM_EXTRACT_CONTIG) && entry->end < end &&
1532: (entry->next == &srcmap->header ||
1533: entry->next->start != entry->end)) {
1534: error = EINVAL;
1535: goto bad;
1536: }
1537: entry = entry->next;
1538: fudge = 0;
1539: }
1540:
1541: /*
1542: * step 4: close off chain (in format expected by uvm_map_replace)
1543: */
1544:
1545: if (chain)
1546: chain->prev = endchain;
1547:
1548: /*
1549: * step 5: attempt to lock the dest map so we can pmap_copy.
1550: * note usage of copy_ok:
1551: * 1 => dstmap locked, pmap_copy ok, and we "replace" here (step 5)
1552: * 0 => dstmap unlocked, NO pmap_copy, and we will "replace" in step 7
1553: */
1.85 chs 1554:
1.10 mrg 1555: if (srcmap == dstmap || vm_map_lock_try(dstmap) == TRUE) {
1556: copy_ok = 1;
1557: if (!uvm_map_replace(dstmap, dstaddr, dstaddr+len, chain,
1558: nchain)) {
1559: if (srcmap != dstmap)
1560: vm_map_unlock(dstmap);
1561: error = EIO;
1562: goto bad;
1563: }
1564: } else {
1565: copy_ok = 0;
1566: /* replace defered until step 7 */
1567: }
1568:
1569: /*
1570: * step 6: traverse the srcmap a second time to do the following:
1571: * - if we got a lock on the dstmap do pmap_copy
1572: * - if UVM_EXTRACT_REMOVE remove the entries
1573: * we make use of orig_entry and orig_fudge (saved in step 2)
1574: */
1575:
1576: if (copy_ok || (flags & UVM_EXTRACT_REMOVE)) {
1577:
1578: /* purge possible stale hints from srcmap */
1579: if (flags & UVM_EXTRACT_REMOVE) {
1.82 thorpej 1580: SAVE_HINT(srcmap, srcmap->hint, orig_entry->prev);
1.10 mrg 1581: if (srcmap->first_free->start >= start)
1582: srcmap->first_free = orig_entry->prev;
1583: }
1584:
1585: entry = orig_entry;
1586: fudge = orig_fudge;
1587: deadentry = NULL; /* for UVM_EXTRACT_REMOVE */
1588:
1589: while (entry->start < end && entry != &srcmap->header) {
1590: if (copy_ok) {
1.74 thorpej 1591: oldoffset = (entry->start + fudge) - start;
1.90 chs 1592: elen = MIN(end, entry->end) -
1.74 thorpej 1593: (entry->start + fudge);
1594: pmap_copy(dstmap->pmap, srcmap->pmap,
1595: dstaddr + oldoffset, elen,
1596: entry->start + fudge);
1.10 mrg 1597: }
1598:
1.74 thorpej 1599: /* we advance "entry" in the following if statement */
1.10 mrg 1600: if (flags & UVM_EXTRACT_REMOVE) {
1.20 chuck 1601: pmap_remove(srcmap->pmap, entry->start,
1602: entry->end);
1603: oldentry = entry; /* save entry */
1604: entry = entry->next; /* advance */
1605: uvm_map_entry_unlink(srcmap, oldentry);
1606: /* add to dead list */
1607: oldentry->next = deadentry;
1608: deadentry = oldentry;
1609: } else {
1610: entry = entry->next; /* advance */
1.10 mrg 1611: }
1612:
1613: /* end of 'while' loop */
1614: fudge = 0;
1615: }
1.95 thorpej 1616: pmap_update();
1.10 mrg 1617:
1618: /*
1619: * unlock dstmap. we will dispose of deadentry in
1620: * step 7 if needed
1621: */
1.85 chs 1622:
1.10 mrg 1623: if (copy_ok && srcmap != dstmap)
1624: vm_map_unlock(dstmap);
1625:
1626: }
1627: else
1628: deadentry = NULL; /* XXX: gcc */
1629:
1630: /*
1631: * step 7: we are done with the source map, unlock. if copy_ok
1632: * is 0 then we have not replaced the dummy mapping in dstmap yet
1633: * and we need to do so now.
1634: */
1635:
1636: vm_map_unlock(srcmap);
1637: if ((flags & UVM_EXTRACT_REMOVE) && deadentry)
1638: uvm_unmap_detach(deadentry, 0); /* dispose of old entries */
1639:
1640: /* now do the replacement if we didn't do it in step 5 */
1641: if (copy_ok == 0) {
1642: vm_map_lock(dstmap);
1643: error = uvm_map_replace(dstmap, dstaddr, dstaddr+len, chain,
1644: nchain);
1645: vm_map_unlock(dstmap);
1646:
1647: if (error == FALSE) {
1648: error = EIO;
1649: goto bad2;
1650: }
1651: }
1652: return(0);
1653:
1654: /*
1655: * bad: failure recovery
1656: */
1657: bad:
1658: vm_map_unlock(srcmap);
1659: bad2: /* src already unlocked */
1660: if (chain)
1661: uvm_unmap_detach(chain,
1662: (flags & UVM_EXTRACT_QREF) ? AMAP_REFALL : 0);
1.29 chuck 1663: uvm_unmap(dstmap, dstaddr, dstaddr+len); /* ??? */
1.10 mrg 1664: return(error);
1665: }
1666:
1667: /* end of extraction functions */
1.1 mrg 1668:
1669: /*
1670: * uvm_map_submap: punch down part of a map into a submap
1671: *
1672: * => only the kernel_map is allowed to be submapped
1673: * => the purpose of submapping is to break up the locking granularity
1674: * of a larger map
1675: * => the range specified must have been mapped previously with a uvm_map()
1676: * call [with uobj==NULL] to create a blank map entry in the main map.
1677: * [And it had better still be blank!]
1678: * => maps which contain submaps should never be copied or forked.
1679: * => to remove a submap, use uvm_unmap() on the main map
1680: * and then uvm_map_deallocate() the submap.
1681: * => main map must be unlocked.
1682: * => submap must have been init'd and have a zero reference count.
1683: * [need not be locked as we don't actually reference it]
1684: */
1.85 chs 1685:
1.10 mrg 1686: int
1687: uvm_map_submap(map, start, end, submap)
1688: vm_map_t map, submap;
1.24 eeh 1689: vaddr_t start, end;
1.10 mrg 1690: {
1691: vm_map_entry_t entry;
1.94 chs 1692: int error;
1.1 mrg 1693:
1.10 mrg 1694: vm_map_lock(map);
1.85 chs 1695: VM_MAP_RANGE_CHECK(map, start, end);
1.1 mrg 1696:
1.10 mrg 1697: if (uvm_map_lookup_entry(map, start, &entry)) {
1698: UVM_MAP_CLIP_START(map, entry, start);
1699: UVM_MAP_CLIP_END(map, entry, end); /* to be safe */
1.94 chs 1700: } else {
1.10 mrg 1701: entry = NULL;
1702: }
1.1 mrg 1703:
1.10 mrg 1704: if (entry != NULL &&
1705: entry->start == start && entry->end == end &&
1706: entry->object.uvm_obj == NULL && entry->aref.ar_amap == NULL &&
1707: !UVM_ET_ISCOPYONWRITE(entry) && !UVM_ET_ISNEEDSCOPY(entry)) {
1.29 chuck 1708: entry->etype |= UVM_ET_SUBMAP;
1.10 mrg 1709: entry->object.sub_map = submap;
1710: entry->offset = 0;
1711: uvm_map_reference(submap);
1.94 chs 1712: error = 0;
1.10 mrg 1713: } else {
1.94 chs 1714: error = EINVAL;
1.10 mrg 1715: }
1716: vm_map_unlock(map);
1.94 chs 1717: return error;
1.1 mrg 1718: }
1719:
1720:
1721: /*
1722: * uvm_map_protect: change map protection
1723: *
1724: * => set_max means set max_protection.
1725: * => map must be unlocked.
1726: */
1727:
1.36 mycroft 1728: #define MASK(entry) (UVM_ET_ISCOPYONWRITE(entry) ? \
1729: ~VM_PROT_WRITE : VM_PROT_ALL)
1.1 mrg 1730:
1.10 mrg 1731: int
1732: uvm_map_protect(map, start, end, new_prot, set_max)
1733: vm_map_t map;
1.24 eeh 1734: vaddr_t start, end;
1.10 mrg 1735: vm_prot_t new_prot;
1736: boolean_t set_max;
1737: {
1738: vm_map_entry_t current, entry;
1.94 chs 1739: int error = 0;
1.10 mrg 1740: UVMHIST_FUNC("uvm_map_protect"); UVMHIST_CALLED(maphist);
1741: UVMHIST_LOG(maphist,"(map=0x%x,start=0x%x,end=0x%x,new_prot=0x%x)",
1.85 chs 1742: map, start, end, new_prot);
1743:
1.10 mrg 1744: vm_map_lock(map);
1745: VM_MAP_RANGE_CHECK(map, start, end);
1746: if (uvm_map_lookup_entry(map, start, &entry)) {
1747: UVM_MAP_CLIP_START(map, entry, start);
1748: } else {
1749: entry = entry->next;
1750: }
1751:
1.1 mrg 1752: /*
1.10 mrg 1753: * make a first pass to check for protection violations.
1.1 mrg 1754: */
1755:
1.10 mrg 1756: current = entry;
1757: while ((current != &map->header) && (current->start < end)) {
1.65 thorpej 1758: if (UVM_ET_ISSUBMAP(current)) {
1.94 chs 1759: error = EINVAL;
1.65 thorpej 1760: goto out;
1761: }
1.10 mrg 1762: if ((new_prot & current->max_protection) != new_prot) {
1.94 chs 1763: error = EACCES;
1.65 thorpej 1764: goto out;
1.10 mrg 1765: }
1.65 thorpej 1766: current = current->next;
1.10 mrg 1767: }
1768:
1769: /* go back and fix up protections (no need to clip this time). */
1770:
1771: current = entry;
1772: while ((current != &map->header) && (current->start < end)) {
1773: vm_prot_t old_prot;
1.85 chs 1774:
1.10 mrg 1775: UVM_MAP_CLIP_END(map, current, end);
1776: old_prot = current->protection;
1777: if (set_max)
1778: current->protection =
1779: (current->max_protection = new_prot) & old_prot;
1780: else
1781: current->protection = new_prot;
1782:
1783: /*
1784: * update physical map if necessary. worry about copy-on-write
1785: * here -- CHECK THIS XXX
1786: */
1787:
1788: if (current->protection != old_prot) {
1.29 chuck 1789: /* update pmap! */
1790: pmap_protect(map->pmap, current->start, current->end,
1791: current->protection & MASK(entry));
1.65 thorpej 1792: }
1.10 mrg 1793:
1.65 thorpej 1794: /*
1795: * If the map is configured to lock any future mappings,
1796: * wire this entry now if the old protection was VM_PROT_NONE
1797: * and the new protection is not VM_PROT_NONE.
1798: */
1799:
1800: if ((map->flags & VM_MAP_WIREFUTURE) != 0 &&
1801: VM_MAPENT_ISWIRED(entry) == 0 &&
1802: old_prot == VM_PROT_NONE &&
1803: new_prot != VM_PROT_NONE) {
1804: if (uvm_map_pageable(map, entry->start,
1805: entry->end, FALSE,
1.94 chs 1806: UVM_LK_ENTER|UVM_LK_EXIT) != 0) {
1.65 thorpej 1807: /*
1808: * If locking the entry fails, remember the
1809: * error if it's the first one. Note we
1810: * still continue setting the protection in
1.94 chs 1811: * the map, but will return the error
1812: * condition regardless.
1.65 thorpej 1813: *
1814: * XXX Ignore what the actual error is,
1815: * XXX just call it a resource shortage
1816: * XXX so that it doesn't get confused
1817: * XXX what uvm_map_protect() itself would
1818: * XXX normally return.
1819: */
1.94 chs 1820: error = ENOMEM;
1.65 thorpej 1821: }
1.10 mrg 1822: }
1.65 thorpej 1823:
1.10 mrg 1824: current = current->next;
1825: }
1.95 thorpej 1826: pmap_update();
1.85 chs 1827:
1.65 thorpej 1828: out:
1.10 mrg 1829: vm_map_unlock(map);
1.94 chs 1830: UVMHIST_LOG(maphist, "<- done, error=%d",error,0,0,0);
1831: return error;
1.1 mrg 1832: }
1833:
1834: #undef MASK
1835:
1836: /*
1837: * uvm_map_inherit: set inheritance code for range of addrs in map.
1838: *
1839: * => map must be unlocked
1840: * => note that the inherit code is used during a "fork". see fork
1841: * code for details.
1842: */
1843:
1.10 mrg 1844: int
1845: uvm_map_inherit(map, start, end, new_inheritance)
1846: vm_map_t map;
1.24 eeh 1847: vaddr_t start;
1848: vaddr_t end;
1.10 mrg 1849: vm_inherit_t new_inheritance;
1850: {
1851: vm_map_entry_t entry, temp_entry;
1852: UVMHIST_FUNC("uvm_map_inherit"); UVMHIST_CALLED(maphist);
1853: UVMHIST_LOG(maphist,"(map=0x%x,start=0x%x,end=0x%x,new_inh=0x%x)",
1854: map, start, end, new_inheritance);
1855:
1856: switch (new_inheritance) {
1.80 wiz 1857: case MAP_INHERIT_NONE:
1858: case MAP_INHERIT_COPY:
1859: case MAP_INHERIT_SHARE:
1.10 mrg 1860: break;
1861: default:
1862: UVMHIST_LOG(maphist,"<- done (INVALID ARG)",0,0,0,0);
1.94 chs 1863: return EINVAL;
1.10 mrg 1864: }
1.1 mrg 1865:
1.10 mrg 1866: vm_map_lock(map);
1.85 chs 1867:
1.10 mrg 1868: VM_MAP_RANGE_CHECK(map, start, end);
1.85 chs 1869:
1.10 mrg 1870: if (uvm_map_lookup_entry(map, start, &temp_entry)) {
1871: entry = temp_entry;
1872: UVM_MAP_CLIP_START(map, entry, start);
1873: } else {
1874: entry = temp_entry->next;
1875: }
1876: while ((entry != &map->header) && (entry->start < end)) {
1877: UVM_MAP_CLIP_END(map, entry, end);
1878: entry->inheritance = new_inheritance;
1879: entry = entry->next;
1880: }
1881:
1882: vm_map_unlock(map);
1883: UVMHIST_LOG(maphist,"<- done (OK)",0,0,0,0);
1.94 chs 1884: return 0;
1.41 mrg 1885: }
1886:
1887: /*
1888: * uvm_map_advice: set advice code for range of addrs in map.
1889: *
1890: * => map must be unlocked
1891: */
1892:
1893: int
1894: uvm_map_advice(map, start, end, new_advice)
1895: vm_map_t map;
1896: vaddr_t start;
1897: vaddr_t end;
1898: int new_advice;
1899: {
1900: vm_map_entry_t entry, temp_entry;
1901: UVMHIST_FUNC("uvm_map_advice"); UVMHIST_CALLED(maphist);
1902: UVMHIST_LOG(maphist,"(map=0x%x,start=0x%x,end=0x%x,new_adv=0x%x)",
1903: map, start, end, new_advice);
1904:
1905: vm_map_lock(map);
1906: VM_MAP_RANGE_CHECK(map, start, end);
1907: if (uvm_map_lookup_entry(map, start, &temp_entry)) {
1908: entry = temp_entry;
1909: UVM_MAP_CLIP_START(map, entry, start);
1910: } else {
1911: entry = temp_entry->next;
1912: }
1.61 thorpej 1913:
1914: /*
1915: * XXXJRT: disallow holes?
1916: */
1917:
1.41 mrg 1918: while ((entry != &map->header) && (entry->start < end)) {
1919: UVM_MAP_CLIP_END(map, entry, end);
1920:
1921: switch (new_advice) {
1922: case MADV_NORMAL:
1923: case MADV_RANDOM:
1924: case MADV_SEQUENTIAL:
1925: /* nothing special here */
1926: break;
1927:
1928: default:
1.50 mrg 1929: vm_map_unlock(map);
1.41 mrg 1930: UVMHIST_LOG(maphist,"<- done (INVALID ARG)",0,0,0,0);
1.94 chs 1931: return EINVAL;
1.41 mrg 1932: }
1933: entry->advice = new_advice;
1934: entry = entry->next;
1935: }
1936:
1937: vm_map_unlock(map);
1938: UVMHIST_LOG(maphist,"<- done (OK)",0,0,0,0);
1.94 chs 1939: return 0;
1.1 mrg 1940: }
1941:
1942: /*
1943: * uvm_map_pageable: sets the pageability of a range in a map.
1944: *
1.56 thorpej 1945: * => wires map entries. should not be used for transient page locking.
1946: * for that, use uvm_fault_wire()/uvm_fault_unwire() (see uvm_vslock()).
1.1 mrg 1947: * => regions sepcified as not pageable require lock-down (wired) memory
1948: * and page tables.
1.59 thorpej 1949: * => map must never be read-locked
1950: * => if islocked is TRUE, map is already write-locked
1951: * => we always unlock the map, since we must downgrade to a read-lock
1952: * to call uvm_fault_wire()
1.1 mrg 1953: * => XXXCDC: check this and try and clean it up.
1954: */
1955:
1.19 kleink 1956: int
1.64 thorpej 1957: uvm_map_pageable(map, start, end, new_pageable, lockflags)
1.11 mrg 1958: vm_map_t map;
1.24 eeh 1959: vaddr_t start, end;
1.64 thorpej 1960: boolean_t new_pageable;
1961: int lockflags;
1.1 mrg 1962: {
1.54 thorpej 1963: vm_map_entry_t entry, start_entry, failed_entry;
1.10 mrg 1964: int rv;
1.60 thorpej 1965: #ifdef DIAGNOSTIC
1966: u_int timestamp_save;
1967: #endif
1.10 mrg 1968: UVMHIST_FUNC("uvm_map_pageable"); UVMHIST_CALLED(maphist);
1969: UVMHIST_LOG(maphist,"(map=0x%x,start=0x%x,end=0x%x,new_pageable=0x%x)",
1.85 chs 1970: map, start, end, new_pageable);
1971: KASSERT(map->flags & VM_MAP_PAGEABLE);
1.45 thorpej 1972:
1.64 thorpej 1973: if ((lockflags & UVM_LK_ENTER) == 0)
1.59 thorpej 1974: vm_map_lock(map);
1.10 mrg 1975: VM_MAP_RANGE_CHECK(map, start, end);
1976:
1977: /*
1978: * only one pageability change may take place at one time, since
1979: * uvm_fault_wire assumes it will be called only once for each
1980: * wiring/unwiring. therefore, we have to make sure we're actually
1981: * changing the pageability for the entire region. we do so before
1982: * making any changes.
1983: */
1984:
1985: if (uvm_map_lookup_entry(map, start, &start_entry) == FALSE) {
1.64 thorpej 1986: if ((lockflags & UVM_LK_EXIT) == 0)
1987: vm_map_unlock(map);
1.85 chs 1988:
1.94 chs 1989: UVMHIST_LOG(maphist,"<- done (fault)",0,0,0,0);
1990: return EFAULT;
1.10 mrg 1991: }
1992: entry = start_entry;
1993:
1994: /*
1995: * handle wiring and unwiring seperately.
1996: */
1.1 mrg 1997:
1.56 thorpej 1998: if (new_pageable) { /* unwire */
1.10 mrg 1999: UVM_MAP_CLIP_START(map, entry, start);
1.85 chs 2000:
1.10 mrg 2001: /*
2002: * unwiring. first ensure that the range to be unwired is
2003: * really wired down and that there are no holes.
2004: */
1.85 chs 2005:
1.10 mrg 2006: while ((entry != &map->header) && (entry->start < end)) {
2007: if (entry->wired_count == 0 ||
2008: (entry->end < end &&
1.55 thorpej 2009: (entry->next == &map->header ||
2010: entry->next->start > entry->end))) {
1.64 thorpej 2011: if ((lockflags & UVM_LK_EXIT) == 0)
2012: vm_map_unlock(map);
1.94 chs 2013: UVMHIST_LOG(maphist, "<- done (INVAL)",0,0,0,0);
2014: return EINVAL;
1.10 mrg 2015: }
2016: entry = entry->next;
2017: }
2018:
2019: /*
1.56 thorpej 2020: * POSIX 1003.1b - a single munlock call unlocks a region,
2021: * regardless of the number of mlock calls made on that
2022: * region.
1.10 mrg 2023: */
1.85 chs 2024:
1.10 mrg 2025: entry = start_entry;
2026: while ((entry != &map->header) && (entry->start < end)) {
2027: UVM_MAP_CLIP_END(map, entry, end);
1.56 thorpej 2028: if (VM_MAPENT_ISWIRED(entry))
1.10 mrg 2029: uvm_map_entry_unwire(map, entry);
2030: entry = entry->next;
2031: }
1.64 thorpej 2032: if ((lockflags & UVM_LK_EXIT) == 0)
2033: vm_map_unlock(map);
1.10 mrg 2034: UVMHIST_LOG(maphist,"<- done (OK UNWIRE)",0,0,0,0);
1.94 chs 2035: return 0;
1.10 mrg 2036: }
2037:
2038: /*
2039: * wire case: in two passes [XXXCDC: ugly block of code here]
2040: *
2041: * 1: holding the write lock, we create any anonymous maps that need
2042: * to be created. then we clip each map entry to the region to
2043: * be wired and increment its wiring count.
2044: *
2045: * 2: we downgrade to a read lock, and call uvm_fault_wire to fault
1.56 thorpej 2046: * in the pages for any newly wired area (wired_count == 1).
1.10 mrg 2047: *
2048: * downgrading to a read lock for uvm_fault_wire avoids a possible
2049: * deadlock with another thread that may have faulted on one of
2050: * the pages to be wired (it would mark the page busy, blocking
2051: * us, then in turn block on the map lock that we hold). because
2052: * of problems in the recursive lock package, we cannot upgrade
2053: * to a write lock in vm_map_lookup. thus, any actions that
2054: * require the write lock must be done beforehand. because we
2055: * keep the read lock on the map, the copy-on-write status of the
2056: * entries we modify here cannot change.
2057: */
2058:
2059: while ((entry != &map->header) && (entry->start < end)) {
1.55 thorpej 2060: if (VM_MAPENT_ISWIRED(entry) == 0) { /* not already wired? */
1.85 chs 2061:
2062: /*
1.10 mrg 2063: * perform actions of vm_map_lookup that need the
2064: * write lock on the map: create an anonymous map
2065: * for a copy-on-write region, or an anonymous map
1.29 chuck 2066: * for a zero-fill region. (XXXCDC: submap case
2067: * ok?)
1.10 mrg 2068: */
1.85 chs 2069:
1.29 chuck 2070: if (!UVM_ET_ISSUBMAP(entry)) { /* not submap */
1.54 thorpej 2071: if (UVM_ET_ISNEEDSCOPY(entry) &&
2072: ((entry->protection & VM_PROT_WRITE) ||
2073: (entry->object.uvm_obj == NULL))) {
1.10 mrg 2074: amap_copy(map, entry, M_WAITOK, TRUE,
2075: start, end);
2076: /* XXXCDC: wait OK? */
2077: }
2078: }
1.55 thorpej 2079: }
1.10 mrg 2080: UVM_MAP_CLIP_START(map, entry, start);
2081: UVM_MAP_CLIP_END(map, entry, end);
2082: entry->wired_count++;
2083:
2084: /*
2085: * Check for holes
2086: */
1.85 chs 2087:
1.54 thorpej 2088: if (entry->protection == VM_PROT_NONE ||
2089: (entry->end < end &&
2090: (entry->next == &map->header ||
2091: entry->next->start > entry->end))) {
1.85 chs 2092:
1.10 mrg 2093: /*
2094: * found one. amap creation actions do not need to
2095: * be undone, but the wired counts need to be restored.
2096: */
1.85 chs 2097:
1.10 mrg 2098: while (entry != &map->header && entry->end > start) {
2099: entry->wired_count--;
2100: entry = entry->prev;
2101: }
1.64 thorpej 2102: if ((lockflags & UVM_LK_EXIT) == 0)
2103: vm_map_unlock(map);
1.10 mrg 2104: UVMHIST_LOG(maphist,"<- done (INVALID WIRE)",0,0,0,0);
1.94 chs 2105: return EINVAL;
1.10 mrg 2106: }
2107: entry = entry->next;
2108: }
2109:
2110: /*
2111: * Pass 2.
2112: */
1.51 thorpej 2113:
1.60 thorpej 2114: #ifdef DIAGNOSTIC
2115: timestamp_save = map->timestamp;
2116: #endif
2117: vm_map_busy(map);
1.51 thorpej 2118: vm_map_downgrade(map);
1.10 mrg 2119:
2120: rv = 0;
2121: entry = start_entry;
2122: while (entry != &map->header && entry->start < end) {
1.51 thorpej 2123: if (entry->wired_count == 1) {
1.44 thorpej 2124: rv = uvm_fault_wire(map, entry->start, entry->end,
1.46 thorpej 2125: entry->protection);
1.10 mrg 2126: if (rv) {
1.94 chs 2127:
1.51 thorpej 2128: /*
2129: * wiring failed. break out of the loop.
2130: * we'll clean up the map below, once we
2131: * have a write lock again.
2132: */
1.94 chs 2133:
1.51 thorpej 2134: break;
1.10 mrg 2135: }
2136: }
2137: entry = entry->next;
2138: }
2139:
1.52 thorpej 2140: if (rv) { /* failed? */
1.85 chs 2141:
1.52 thorpej 2142: /*
2143: * Get back to an exclusive (write) lock.
2144: */
1.85 chs 2145:
1.52 thorpej 2146: vm_map_upgrade(map);
1.60 thorpej 2147: vm_map_unbusy(map);
2148:
2149: #ifdef DIAGNOSTIC
2150: if (timestamp_save != map->timestamp)
2151: panic("uvm_map_pageable: stale map");
2152: #endif
1.10 mrg 2153:
1.51 thorpej 2154: /*
2155: * first drop the wiring count on all the entries
2156: * which haven't actually been wired yet.
2157: */
1.85 chs 2158:
1.54 thorpej 2159: failed_entry = entry;
2160: while (entry != &map->header && entry->start < end) {
1.51 thorpej 2161: entry->wired_count--;
1.54 thorpej 2162: entry = entry->next;
2163: }
1.51 thorpej 2164:
2165: /*
1.54 thorpej 2166: * now, unwire all the entries that were successfully
2167: * wired above.
1.51 thorpej 2168: */
1.85 chs 2169:
1.54 thorpej 2170: entry = start_entry;
2171: while (entry != failed_entry) {
2172: entry->wired_count--;
1.55 thorpej 2173: if (VM_MAPENT_ISWIRED(entry) == 0)
1.54 thorpej 2174: uvm_map_entry_unwire(map, entry);
2175: entry = entry->next;
2176: }
1.64 thorpej 2177: if ((lockflags & UVM_LK_EXIT) == 0)
2178: vm_map_unlock(map);
1.10 mrg 2179: UVMHIST_LOG(maphist, "<- done (RV=%d)", rv,0,0,0);
2180: return(rv);
2181: }
1.51 thorpej 2182:
1.52 thorpej 2183: /* We are holding a read lock here. */
1.64 thorpej 2184: if ((lockflags & UVM_LK_EXIT) == 0) {
2185: vm_map_unbusy(map);
2186: vm_map_unlock_read(map);
2187: } else {
1.85 chs 2188:
1.64 thorpej 2189: /*
2190: * Get back to an exclusive (write) lock.
2191: */
1.85 chs 2192:
1.64 thorpej 2193: vm_map_upgrade(map);
2194: vm_map_unbusy(map);
2195: }
2196:
1.10 mrg 2197: UVMHIST_LOG(maphist,"<- done (OK WIRE)",0,0,0,0);
1.94 chs 2198: return 0;
1.1 mrg 2199: }
2200:
2201: /*
1.54 thorpej 2202: * uvm_map_pageable_all: special case of uvm_map_pageable - affects
2203: * all mapped regions.
2204: *
2205: * => map must not be locked.
2206: * => if no flags are specified, all regions are unwired.
2207: * => XXXJRT: has some of the same problems as uvm_map_pageable() above.
2208: */
2209:
2210: int
2211: uvm_map_pageable_all(map, flags, limit)
2212: vm_map_t map;
2213: int flags;
2214: vsize_t limit;
2215: {
2216: vm_map_entry_t entry, failed_entry;
2217: vsize_t size;
2218: int rv;
1.60 thorpej 2219: #ifdef DIAGNOSTIC
2220: u_int timestamp_save;
2221: #endif
1.54 thorpej 2222: UVMHIST_FUNC("uvm_map_pageable_all"); UVMHIST_CALLED(maphist);
2223: UVMHIST_LOG(maphist,"(map=0x%x,flags=0x%x)", map, flags, 0, 0);
2224:
1.85 chs 2225: KASSERT(map->flags & VM_MAP_PAGEABLE);
1.54 thorpej 2226:
2227: vm_map_lock(map);
2228:
2229: /*
2230: * handle wiring and unwiring separately.
2231: */
2232:
2233: if (flags == 0) { /* unwire */
2234: /*
1.56 thorpej 2235: * POSIX 1003.1b -- munlockall unlocks all regions,
2236: * regardless of how many times mlockall has been called.
1.54 thorpej 2237: */
2238: for (entry = map->header.next; entry != &map->header;
2239: entry = entry->next) {
1.56 thorpej 2240: if (VM_MAPENT_ISWIRED(entry))
2241: uvm_map_entry_unwire(map, entry);
1.54 thorpej 2242: }
1.61 thorpej 2243: vm_map_modflags(map, 0, VM_MAP_WIREFUTURE);
1.54 thorpej 2244: vm_map_unlock(map);
2245: UVMHIST_LOG(maphist,"<- done (OK UNWIRE)",0,0,0,0);
1.94 chs 2246: return 0;
1.54 thorpej 2247:
2248: /*
2249: * end of unwire case!
2250: */
2251: }
2252:
2253: if (flags & MCL_FUTURE) {
2254: /*
2255: * must wire all future mappings; remember this.
2256: */
1.61 thorpej 2257: vm_map_modflags(map, VM_MAP_WIREFUTURE, 0);
1.54 thorpej 2258: }
2259:
2260: if ((flags & MCL_CURRENT) == 0) {
2261: /*
2262: * no more work to do!
2263: */
2264: UVMHIST_LOG(maphist,"<- done (OK no wire)",0,0,0,0);
2265: vm_map_unlock(map);
1.94 chs 2266: return 0;
1.54 thorpej 2267: }
2268:
2269: /*
2270: * wire case: in three passes [XXXCDC: ugly block of code here]
2271: *
2272: * 1: holding the write lock, count all pages mapped by non-wired
2273: * entries. if this would cause us to go over our limit, we fail.
2274: *
2275: * 2: still holding the write lock, we create any anonymous maps that
2276: * need to be created. then we increment its wiring count.
2277: *
2278: * 3: we downgrade to a read lock, and call uvm_fault_wire to fault
1.56 thorpej 2279: * in the pages for any newly wired area (wired_count == 1).
1.54 thorpej 2280: *
2281: * downgrading to a read lock for uvm_fault_wire avoids a possible
2282: * deadlock with another thread that may have faulted on one of
2283: * the pages to be wired (it would mark the page busy, blocking
2284: * us, then in turn block on the map lock that we hold). because
2285: * of problems in the recursive lock package, we cannot upgrade
2286: * to a write lock in vm_map_lookup. thus, any actions that
2287: * require the write lock must be done beforehand. because we
2288: * keep the read lock on the map, the copy-on-write status of the
2289: * entries we modify here cannot change.
2290: */
2291:
2292: for (size = 0, entry = map->header.next; entry != &map->header;
2293: entry = entry->next) {
2294: if (entry->protection != VM_PROT_NONE &&
1.55 thorpej 2295: VM_MAPENT_ISWIRED(entry) == 0) { /* not already wired? */
1.54 thorpej 2296: size += entry->end - entry->start;
2297: }
2298: }
2299:
2300: if (atop(size) + uvmexp.wired > uvmexp.wiredmax) {
2301: vm_map_unlock(map);
1.94 chs 2302: return ENOMEM;
1.54 thorpej 2303: }
2304:
2305: /* XXX non-pmap_wired_count case must be handled by caller */
2306: #ifdef pmap_wired_count
2307: if (limit != 0 &&
2308: (size + ptoa(pmap_wired_count(vm_map_pmap(map))) > limit)) {
2309: vm_map_unlock(map);
1.94 chs 2310: return ENOMEM;
1.54 thorpej 2311: }
2312: #endif
2313:
2314: /*
2315: * Pass 2.
2316: */
2317:
2318: for (entry = map->header.next; entry != &map->header;
2319: entry = entry->next) {
2320: if (entry->protection == VM_PROT_NONE)
2321: continue;
1.55 thorpej 2322: if (VM_MAPENT_ISWIRED(entry) == 0) { /* not already wired? */
1.54 thorpej 2323: /*
2324: * perform actions of vm_map_lookup that need the
2325: * write lock on the map: create an anonymous map
2326: * for a copy-on-write region, or an anonymous map
2327: * for a zero-fill region. (XXXCDC: submap case
2328: * ok?)
2329: */
2330: if (!UVM_ET_ISSUBMAP(entry)) { /* not submap */
2331: if (UVM_ET_ISNEEDSCOPY(entry) &&
2332: ((entry->protection & VM_PROT_WRITE) ||
2333: (entry->object.uvm_obj == NULL))) {
2334: amap_copy(map, entry, M_WAITOK, TRUE,
2335: entry->start, entry->end);
2336: /* XXXCDC: wait OK? */
2337: }
2338: }
1.55 thorpej 2339: }
1.54 thorpej 2340: entry->wired_count++;
2341: }
2342:
2343: /*
2344: * Pass 3.
2345: */
2346:
1.60 thorpej 2347: #ifdef DIAGNOSTIC
2348: timestamp_save = map->timestamp;
2349: #endif
2350: vm_map_busy(map);
1.54 thorpej 2351: vm_map_downgrade(map);
2352:
1.94 chs 2353: rv = 0;
1.54 thorpej 2354: for (entry = map->header.next; entry != &map->header;
2355: entry = entry->next) {
2356: if (entry->wired_count == 1) {
2357: rv = uvm_fault_wire(map, entry->start, entry->end,
2358: entry->protection);
2359: if (rv) {
2360: /*
2361: * wiring failed. break out of the loop.
2362: * we'll clean up the map below, once we
2363: * have a write lock again.
2364: */
2365: break;
2366: }
2367: }
2368: }
2369:
2370: if (rv) { /* failed? */
2371: /*
2372: * Get back an exclusive (write) lock.
2373: */
2374: vm_map_upgrade(map);
1.60 thorpej 2375: vm_map_unbusy(map);
2376:
2377: #ifdef DIAGNOSTIC
2378: if (timestamp_save != map->timestamp)
2379: panic("uvm_map_pageable_all: stale map");
2380: #endif
1.54 thorpej 2381:
2382: /*
2383: * first drop the wiring count on all the entries
2384: * which haven't actually been wired yet.
1.67 thorpej 2385: *
2386: * Skip VM_PROT_NONE entries like we did above.
1.54 thorpej 2387: */
2388: failed_entry = entry;
2389: for (/* nothing */; entry != &map->header;
1.67 thorpej 2390: entry = entry->next) {
2391: if (entry->protection == VM_PROT_NONE)
2392: continue;
1.54 thorpej 2393: entry->wired_count--;
1.67 thorpej 2394: }
1.54 thorpej 2395:
2396: /*
2397: * now, unwire all the entries that were successfully
2398: * wired above.
1.67 thorpej 2399: *
2400: * Skip VM_PROT_NONE entries like we did above.
1.54 thorpej 2401: */
2402: for (entry = map->header.next; entry != failed_entry;
2403: entry = entry->next) {
1.67 thorpej 2404: if (entry->protection == VM_PROT_NONE)
2405: continue;
1.54 thorpej 2406: entry->wired_count--;
1.67 thorpej 2407: if (VM_MAPENT_ISWIRED(entry))
1.54 thorpej 2408: uvm_map_entry_unwire(map, entry);
2409: }
2410: vm_map_unlock(map);
2411: UVMHIST_LOG(maphist,"<- done (RV=%d)", rv,0,0,0);
2412: return (rv);
2413: }
2414:
2415: /* We are holding a read lock here. */
1.60 thorpej 2416: vm_map_unbusy(map);
1.54 thorpej 2417: vm_map_unlock_read(map);
2418:
2419: UVMHIST_LOG(maphist,"<- done (OK WIRE)",0,0,0,0);
1.94 chs 2420: return 0;
1.54 thorpej 2421: }
2422:
2423: /*
1.61 thorpej 2424: * uvm_map_clean: clean out a map range
1.1 mrg 2425: *
2426: * => valid flags:
1.61 thorpej 2427: * if (flags & PGO_CLEANIT): dirty pages are cleaned first
1.1 mrg 2428: * if (flags & PGO_SYNCIO): dirty pages are written synchronously
2429: * if (flags & PGO_DEACTIVATE): any cached pages are deactivated after clean
2430: * if (flags & PGO_FREE): any cached pages are freed after clean
2431: * => returns an error if any part of the specified range isn't mapped
2432: * => never a need to flush amap layer since the anonymous memory has
1.61 thorpej 2433: * no permanent home, but may deactivate pages there
2434: * => called from sys_msync() and sys_madvise()
1.1 mrg 2435: * => caller must not write-lock map (read OK).
2436: * => we may sleep while cleaning if SYNCIO [with map read-locked]
2437: */
2438:
1.10 mrg 2439: int
2440: uvm_map_clean(map, start, end, flags)
2441: vm_map_t map;
1.24 eeh 2442: vaddr_t start, end;
1.10 mrg 2443: int flags;
2444: {
1.61 thorpej 2445: vm_map_entry_t current, entry;
2446: struct uvm_object *uobj;
2447: struct vm_amap *amap;
2448: struct vm_anon *anon;
2449: struct vm_page *pg;
2450: vaddr_t offset;
1.24 eeh 2451: vsize_t size;
1.61 thorpej 2452: int rv, error, refs;
1.10 mrg 2453: UVMHIST_FUNC("uvm_map_clean"); UVMHIST_CALLED(maphist);
1.85 chs 2454:
1.10 mrg 2455: UVMHIST_LOG(maphist,"(map=0x%x,start=0x%x,end=0x%x,flags=0x%x)",
1.85 chs 2456: map, start, end, flags);
2457: KASSERT((flags & (PGO_FREE|PGO_DEACTIVATE)) !=
2458: (PGO_FREE|PGO_DEACTIVATE));
1.61 thorpej 2459:
1.10 mrg 2460: vm_map_lock_read(map);
2461: VM_MAP_RANGE_CHECK(map, start, end);
1.61 thorpej 2462: if (uvm_map_lookup_entry(map, start, &entry) == FALSE) {
1.10 mrg 2463: vm_map_unlock_read(map);
1.94 chs 2464: return EFAULT;
1.10 mrg 2465: }
2466:
2467: /*
2468: * Make a first pass to check for holes.
2469: */
1.85 chs 2470:
1.10 mrg 2471: for (current = entry; current->start < end; current = current->next) {
2472: if (UVM_ET_ISSUBMAP(current)) {
2473: vm_map_unlock_read(map);
1.94 chs 2474: return EINVAL;
1.10 mrg 2475: }
1.90 chs 2476: if (end <= current->end) {
2477: break;
2478: }
2479: if (current->end != current->next->start) {
1.10 mrg 2480: vm_map_unlock_read(map);
1.94 chs 2481: return EFAULT;
1.10 mrg 2482: }
2483: }
2484:
1.94 chs 2485: error = 0;
1.90 chs 2486: for (current = entry; start < end; current = current->next) {
1.61 thorpej 2487: amap = current->aref.ar_amap; /* top layer */
2488: uobj = current->object.uvm_obj; /* bottom layer */
1.85 chs 2489: KASSERT(start >= current->start);
1.1 mrg 2490:
1.10 mrg 2491: /*
1.61 thorpej 2492: * No amap cleaning necessary if:
2493: *
2494: * (1) There's no amap.
2495: *
2496: * (2) We're not deactivating or freeing pages.
1.10 mrg 2497: */
1.85 chs 2498:
1.90 chs 2499: if (amap == NULL || (flags & (PGO_DEACTIVATE|PGO_FREE)) == 0)
1.61 thorpej 2500: goto flush_object;
2501:
2502: amap_lock(amap);
2503: offset = start - current->start;
1.90 chs 2504: size = MIN(end, current->end) - start;
2505: for ( ; size != 0; size -= PAGE_SIZE, offset += PAGE_SIZE) {
1.61 thorpej 2506: anon = amap_lookup(¤t->aref, offset);
2507: if (anon == NULL)
2508: continue;
2509:
2510: simple_lock(&anon->an_lock);
2511:
1.63 thorpej 2512: pg = anon->u.an_page;
2513: if (pg == NULL) {
2514: simple_unlock(&anon->an_lock);
2515: continue;
2516: }
2517:
1.61 thorpej 2518: switch (flags & (PGO_CLEANIT|PGO_FREE|PGO_DEACTIVATE)) {
1.85 chs 2519:
1.61 thorpej 2520: /*
2521: * XXX In these first 3 cases, we always just
2522: * XXX deactivate the page. We may want to
2523: * XXX handle the different cases more
2524: * XXX specifically, in the future.
2525: */
1.85 chs 2526:
1.61 thorpej 2527: case PGO_CLEANIT|PGO_FREE:
2528: case PGO_CLEANIT|PGO_DEACTIVATE:
2529: case PGO_DEACTIVATE:
1.68 thorpej 2530: deactivate_it:
1.61 thorpej 2531: /* skip the page if it's loaned or wired */
2532: if (pg->loan_count != 0 ||
2533: pg->wire_count != 0) {
2534: simple_unlock(&anon->an_lock);
2535: continue;
2536: }
2537:
2538: uvm_lock_pageq();
2539:
2540: /*
2541: * skip the page if it's not actually owned
2542: * by the anon (may simply be loaned to the
2543: * anon).
2544: */
1.85 chs 2545:
1.61 thorpej 2546: if ((pg->pqflags & PQ_ANON) == 0) {
1.85 chs 2547: KASSERT(pg->uobject == NULL);
1.61 thorpej 2548: uvm_unlock_pageq();
2549: simple_unlock(&anon->an_lock);
2550: continue;
2551: }
1.85 chs 2552: KASSERT(pg->uanon == anon);
1.61 thorpej 2553:
2554: /* ...and deactivate the page. */
1.89 thorpej 2555: pmap_clear_reference(pg);
1.61 thorpej 2556: uvm_pagedeactivate(pg);
2557:
2558: uvm_unlock_pageq();
2559: simple_unlock(&anon->an_lock);
2560: continue;
2561:
2562: case PGO_FREE:
1.85 chs 2563:
1.68 thorpej 2564: /*
2565: * If there are multiple references to
2566: * the amap, just deactivate the page.
2567: */
1.85 chs 2568:
1.68 thorpej 2569: if (amap_refs(amap) > 1)
2570: goto deactivate_it;
2571:
1.62 thorpej 2572: /* XXX skip the page if it's wired */
2573: if (pg->wire_count != 0) {
2574: simple_unlock(&anon->an_lock);
2575: continue;
2576: }
1.66 thorpej 2577: amap_unadd(¤t->aref, offset);
1.61 thorpej 2578: refs = --anon->an_ref;
2579: simple_unlock(&anon->an_lock);
2580: if (refs == 0)
2581: uvm_anfree(anon);
2582: continue;
2583:
2584: default:
2585: panic("uvm_map_clean: wierd flags");
2586: }
2587: }
2588: amap_unlock(amap);
1.1 mrg 2589:
1.61 thorpej 2590: flush_object:
1.10 mrg 2591: /*
1.33 chuck 2592: * flush pages if we've got a valid backing object.
1.10 mrg 2593: */
1.1 mrg 2594:
1.61 thorpej 2595: offset = current->offset + (start - current->start);
1.90 chs 2596: size = MIN(end, current->end) - start;
1.61 thorpej 2597: if (uobj != NULL) {
2598: simple_lock(&uobj->vmobjlock);
2599: rv = uobj->pgops->pgo_flush(uobj, offset,
2600: offset + size, flags);
2601: simple_unlock(&uobj->vmobjlock);
2602:
2603: if (rv == FALSE)
1.94 chs 2604: error = EIO;
1.10 mrg 2605: }
2606: start += size;
2607: }
1.1 mrg 2608: vm_map_unlock_read(map);
1.61 thorpej 2609: return (error);
1.1 mrg 2610: }
2611:
2612:
2613: /*
2614: * uvm_map_checkprot: check protection in map
2615: *
2616: * => must allow specified protection in a fully allocated region.
2617: * => map must be read or write locked by caller.
2618: */
2619:
1.10 mrg 2620: boolean_t
2621: uvm_map_checkprot(map, start, end, protection)
2622: vm_map_t map;
1.24 eeh 2623: vaddr_t start, end;
1.10 mrg 2624: vm_prot_t protection;
2625: {
1.94 chs 2626: vm_map_entry_t entry;
2627: vm_map_entry_t tmp_entry;
1.10 mrg 2628:
1.94 chs 2629: if (!uvm_map_lookup_entry(map, start, &tmp_entry)) {
2630: return(FALSE);
2631: }
2632: entry = tmp_entry;
2633: while (start < end) {
2634: if (entry == &map->header) {
2635: return(FALSE);
2636: }
1.85 chs 2637:
1.10 mrg 2638: /*
2639: * no holes allowed
2640: */
2641:
1.94 chs 2642: if (start < entry->start) {
2643: return(FALSE);
2644: }
1.10 mrg 2645:
2646: /*
2647: * check protection associated with entry
2648: */
1.1 mrg 2649:
1.94 chs 2650: if ((entry->protection & protection) != protection) {
2651: return(FALSE);
2652: }
2653:
2654: /* go to next entry */
2655:
2656: start = entry->end;
2657: entry = entry->next;
2658: }
2659: return(TRUE);
1.1 mrg 2660: }
2661:
2662: /*
2663: * uvmspace_alloc: allocate a vmspace structure.
2664: *
2665: * - structure includes vm_map and pmap
2666: * - XXX: no locking on this structure
2667: * - refcnt set to 1, rest must be init'd by caller
2668: */
1.10 mrg 2669: struct vmspace *
2670: uvmspace_alloc(min, max, pageable)
1.24 eeh 2671: vaddr_t min, max;
1.10 mrg 2672: int pageable;
2673: {
2674: struct vmspace *vm;
2675: UVMHIST_FUNC("uvmspace_alloc"); UVMHIST_CALLED(maphist);
2676:
1.25 thorpej 2677: vm = pool_get(&uvm_vmspace_pool, PR_WAITOK);
1.15 thorpej 2678: uvmspace_init(vm, NULL, min, max, pageable);
2679: UVMHIST_LOG(maphist,"<- done (vm=0x%x)", vm,0,0,0);
2680: return (vm);
2681: }
2682:
2683: /*
2684: * uvmspace_init: initialize a vmspace structure.
2685: *
2686: * - XXX: no locking on this structure
2687: * - refcnt set to 1, rest must me init'd by caller
2688: */
2689: void
2690: uvmspace_init(vm, pmap, min, max, pageable)
2691: struct vmspace *vm;
2692: struct pmap *pmap;
1.24 eeh 2693: vaddr_t min, max;
1.15 thorpej 2694: boolean_t pageable;
2695: {
2696: UVMHIST_FUNC("uvmspace_init"); UVMHIST_CALLED(maphist);
2697:
1.23 perry 2698: memset(vm, 0, sizeof(*vm));
1.45 thorpej 2699: uvm_map_setup(&vm->vm_map, min, max, pageable ? VM_MAP_PAGEABLE : 0);
1.15 thorpej 2700: if (pmap)
2701: pmap_reference(pmap);
2702: else
2703: pmap = pmap_create();
2704: vm->vm_map.pmap = pmap;
1.10 mrg 2705: vm->vm_refcnt = 1;
1.15 thorpej 2706: UVMHIST_LOG(maphist,"<- done",0,0,0,0);
1.1 mrg 2707: }
2708:
2709: /*
2710: * uvmspace_share: share a vmspace between two proceses
2711: *
2712: * - XXX: no locking on vmspace
2713: * - used for vfork, threads(?)
2714: */
2715:
1.10 mrg 2716: void
2717: uvmspace_share(p1, p2)
2718: struct proc *p1, *p2;
1.1 mrg 2719: {
1.10 mrg 2720: p2->p_vmspace = p1->p_vmspace;
2721: p1->p_vmspace->vm_refcnt++;
1.1 mrg 2722: }
2723:
2724: /*
2725: * uvmspace_unshare: ensure that process "p" has its own, unshared, vmspace
2726: *
2727: * - XXX: no locking on vmspace
2728: */
2729:
1.10 mrg 2730: void
2731: uvmspace_unshare(p)
2732: struct proc *p;
2733: {
2734: struct vmspace *nvm, *ovm = p->p_vmspace;
1.85 chs 2735:
1.10 mrg 2736: if (ovm->vm_refcnt == 1)
2737: /* nothing to do: vmspace isn't shared in the first place */
2738: return;
1.85 chs 2739:
1.10 mrg 2740: /* make a new vmspace, still holding old one */
2741: nvm = uvmspace_fork(ovm);
2742:
1.12 thorpej 2743: pmap_deactivate(p); /* unbind old vmspace */
1.10 mrg 2744: p->p_vmspace = nvm;
2745: pmap_activate(p); /* switch to new vmspace */
1.13 thorpej 2746:
1.10 mrg 2747: uvmspace_free(ovm); /* drop reference to old vmspace */
1.1 mrg 2748: }
2749:
2750: /*
2751: * uvmspace_exec: the process wants to exec a new program
2752: *
2753: * - XXX: no locking on vmspace
2754: */
2755:
1.10 mrg 2756: void
1.91 eeh 2757: uvmspace_exec(p, start, end)
1.10 mrg 2758: struct proc *p;
1.91 eeh 2759: vaddr_t start, end;
1.1 mrg 2760: {
1.10 mrg 2761: struct vmspace *nvm, *ovm = p->p_vmspace;
2762: vm_map_t map = &ovm->vm_map;
1.1 mrg 2763:
1.71 chs 2764: #ifdef __sparc__
1.10 mrg 2765: /* XXX cgd 960926: the sparc #ifdef should be a MD hook */
2766: kill_user_windows(p); /* before stack addresses go away */
1.1 mrg 2767: #endif
2768:
1.10 mrg 2769: /*
2770: * see if more than one process is using this vmspace...
2771: */
1.1 mrg 2772:
1.10 mrg 2773: if (ovm->vm_refcnt == 1) {
1.1 mrg 2774:
1.10 mrg 2775: /*
2776: * if p is the only process using its vmspace then we can safely
2777: * recycle that vmspace for the program that is being exec'd.
2778: */
1.1 mrg 2779:
2780: #ifdef SYSVSHM
1.10 mrg 2781: /*
2782: * SYSV SHM semantics require us to kill all segments on an exec
2783: */
2784: if (ovm->vm_shm)
2785: shmexit(ovm);
2786: #endif
1.54 thorpej 2787:
2788: /*
2789: * POSIX 1003.1b -- "lock future mappings" is revoked
2790: * when a process execs another program image.
2791: */
2792: vm_map_lock(map);
1.61 thorpej 2793: vm_map_modflags(map, 0, VM_MAP_WIREFUTURE);
1.54 thorpej 2794: vm_map_unlock(map);
1.10 mrg 2795:
2796: /*
2797: * now unmap the old program
2798: */
1.91 eeh 2799: uvm_unmap(map, map->min_offset, map->max_offset);
1.93 eeh 2800:
2801: /*
2802: * resize the map
2803: */
2804: vm_map_lock(map);
2805: map->min_offset = start;
2806: map->max_offset = end;
2807: vm_map_unlock(map);
1.10 mrg 2808: } else {
2809:
2810: /*
2811: * p's vmspace is being shared, so we can't reuse it for p since
2812: * it is still being used for others. allocate a new vmspace
2813: * for p
2814: */
1.91 eeh 2815: nvm = uvmspace_alloc(start, end,
1.45 thorpej 2816: (map->flags & VM_MAP_PAGEABLE) ? TRUE : FALSE);
1.1 mrg 2817:
1.10 mrg 2818: /*
2819: * install new vmspace and drop our ref to the old one.
2820: */
2821:
1.12 thorpej 2822: pmap_deactivate(p);
1.10 mrg 2823: p->p_vmspace = nvm;
2824: pmap_activate(p);
1.13 thorpej 2825:
1.10 mrg 2826: uvmspace_free(ovm);
2827: }
1.1 mrg 2828: }
2829:
2830: /*
2831: * uvmspace_free: free a vmspace data structure
2832: *
2833: * - XXX: no locking on vmspace
2834: */
2835:
1.10 mrg 2836: void
2837: uvmspace_free(vm)
2838: struct vmspace *vm;
1.1 mrg 2839: {
1.10 mrg 2840: vm_map_entry_t dead_entries;
2841: UVMHIST_FUNC("uvmspace_free"); UVMHIST_CALLED(maphist);
1.1 mrg 2842:
1.10 mrg 2843: UVMHIST_LOG(maphist,"(vm=0x%x) ref=%d", vm, vm->vm_refcnt,0,0);
2844: if (--vm->vm_refcnt == 0) {
2845: /*
2846: * lock the map, to wait out all other references to it. delete
2847: * all of the mappings and pages they hold, then call the pmap
2848: * module to reclaim anything left.
2849: */
1.92 thorpej 2850: #ifdef SYSVSHM
2851: /* Get rid of any SYSV shared memory segments. */
2852: if (vm->vm_shm != NULL)
2853: shmexit(vm);
2854: #endif
1.10 mrg 2855: vm_map_lock(&vm->vm_map);
2856: if (vm->vm_map.nentries) {
1.94 chs 2857: uvm_unmap_remove(&vm->vm_map,
1.10 mrg 2858: vm->vm_map.min_offset, vm->vm_map.max_offset,
1.29 chuck 2859: &dead_entries);
1.10 mrg 2860: if (dead_entries != NULL)
2861: uvm_unmap_detach(dead_entries, 0);
2862: }
2863: pmap_destroy(vm->vm_map.pmap);
2864: vm->vm_map.pmap = NULL;
1.25 thorpej 2865: pool_put(&uvm_vmspace_pool, vm);
1.10 mrg 2866: }
2867: UVMHIST_LOG(maphist,"<- done", 0,0,0,0);
1.1 mrg 2868: }
2869:
2870: /*
2871: * F O R K - m a i n e n t r y p o i n t
2872: */
2873: /*
2874: * uvmspace_fork: fork a process' main map
2875: *
2876: * => create a new vmspace for child process from parent.
2877: * => parent's map must not be locked.
2878: */
2879:
1.10 mrg 2880: struct vmspace *
2881: uvmspace_fork(vm1)
2882: struct vmspace *vm1;
2883: {
2884: struct vmspace *vm2;
2885: vm_map_t old_map = &vm1->vm_map;
2886: vm_map_t new_map;
2887: vm_map_entry_t old_entry;
2888: vm_map_entry_t new_entry;
2889: pmap_t new_pmap;
1.14 chuck 2890: boolean_t protect_child;
1.10 mrg 2891: UVMHIST_FUNC("uvmspace_fork"); UVMHIST_CALLED(maphist);
1.1 mrg 2892:
1.10 mrg 2893: vm_map_lock(old_map);
1.1 mrg 2894:
1.10 mrg 2895: vm2 = uvmspace_alloc(old_map->min_offset, old_map->max_offset,
1.45 thorpej 2896: (old_map->flags & VM_MAP_PAGEABLE) ? TRUE : FALSE);
1.23 perry 2897: memcpy(&vm2->vm_startcopy, &vm1->vm_startcopy,
1.1 mrg 2898: (caddr_t) (vm1 + 1) - (caddr_t) &vm1->vm_startcopy);
1.10 mrg 2899: new_map = &vm2->vm_map; /* XXX */
2900: new_pmap = new_map->pmap;
2901:
2902: old_entry = old_map->header.next;
2903:
2904: /*
2905: * go entry-by-entry
2906: */
1.1 mrg 2907:
1.10 mrg 2908: while (old_entry != &old_map->header) {
1.1 mrg 2909:
1.10 mrg 2910: /*
2911: * first, some sanity checks on the old entry
2912: */
1.94 chs 2913: KASSERT(!UVM_ET_ISSUBMAP(old_entry));
2914: KASSERT(UVM_ET_ISCOPYONWRITE(old_entry) ||
2915: !UVM_ET_ISNEEDSCOPY(old_entry));
1.1 mrg 2916:
1.10 mrg 2917: switch (old_entry->inheritance) {
1.80 wiz 2918: case MAP_INHERIT_NONE:
1.10 mrg 2919: /*
2920: * drop the mapping
2921: */
2922: break;
2923:
1.80 wiz 2924: case MAP_INHERIT_SHARE:
1.10 mrg 2925: /*
2926: * share the mapping: this means we want the old and
2927: * new entries to share amaps and backing objects.
2928: */
2929:
2930: /*
2931: * if the old_entry needs a new amap (due to prev fork)
2932: * then we need to allocate it now so that we have
2933: * something we own to share with the new_entry. [in
2934: * other words, we need to clear needs_copy]
2935: */
2936:
2937: if (UVM_ET_ISNEEDSCOPY(old_entry)) {
2938: /* get our own amap, clears needs_copy */
2939: amap_copy(old_map, old_entry, M_WAITOK, FALSE,
2940: 0, 0);
2941: /* XXXCDC: WAITOK??? */
2942: }
2943:
2944: new_entry = uvm_mapent_alloc(new_map);
2945: /* old_entry -> new_entry */
2946: uvm_mapent_copy(old_entry, new_entry);
2947:
2948: /* new pmap has nothing wired in it */
2949: new_entry->wired_count = 0;
2950:
2951: /*
1.29 chuck 2952: * gain reference to object backing the map (can't
2953: * be a submap, already checked this case).
1.10 mrg 2954: */
2955: if (new_entry->aref.ar_amap)
2956: /* share reference */
1.85 chs 2957: uvm_map_reference_amap(new_entry, AMAP_SHARED);
1.10 mrg 2958:
2959: if (new_entry->object.uvm_obj &&
2960: new_entry->object.uvm_obj->pgops->pgo_reference)
2961: new_entry->object.uvm_obj->
2962: pgops->pgo_reference(
2963: new_entry->object.uvm_obj);
2964:
2965: /* insert entry at end of new_map's entry list */
2966: uvm_map_entry_link(new_map, new_map->header.prev,
2967: new_entry);
2968:
2969: /*
2970: * pmap_copy the mappings: this routine is optional
2971: * but if it is there it will reduce the number of
2972: * page faults in the new proc.
2973: */
2974:
2975: pmap_copy(new_pmap, old_map->pmap, new_entry->start,
2976: (old_entry->end - old_entry->start),
2977: old_entry->start);
2978:
2979: break;
2980:
1.80 wiz 2981: case MAP_INHERIT_COPY:
1.10 mrg 2982:
2983: /*
2984: * copy-on-write the mapping (using mmap's
2985: * MAP_PRIVATE semantics)
1.29 chuck 2986: *
2987: * allocate new_entry, adjust reference counts.
2988: * (note that new references are read-only).
1.10 mrg 2989: */
2990:
2991: new_entry = uvm_mapent_alloc(new_map);
2992: /* old_entry -> new_entry */
2993: uvm_mapent_copy(old_entry, new_entry);
2994:
2995: if (new_entry->aref.ar_amap)
1.85 chs 2996: uvm_map_reference_amap(new_entry, 0);
1.10 mrg 2997:
2998: if (new_entry->object.uvm_obj &&
2999: new_entry->object.uvm_obj->pgops->pgo_reference)
3000: new_entry->object.uvm_obj->pgops->pgo_reference
3001: (new_entry->object.uvm_obj);
3002:
3003: /* new pmap has nothing wired in it */
3004: new_entry->wired_count = 0;
3005:
3006: new_entry->etype |=
3007: (UVM_ET_COPYONWRITE|UVM_ET_NEEDSCOPY);
3008: uvm_map_entry_link(new_map, new_map->header.prev,
3009: new_entry);
1.85 chs 3010:
1.14 chuck 3011: /*
1.10 mrg 3012: * the new entry will need an amap. it will either
3013: * need to be copied from the old entry or created
1.14 chuck 3014: * from scratch (if the old entry does not have an
3015: * amap). can we defer this process until later
3016: * (by setting "needs_copy") or do we need to copy
3017: * the amap now?
1.10 mrg 3018: *
1.14 chuck 3019: * we must copy the amap now if any of the following
1.10 mrg 3020: * conditions hold:
1.14 chuck 3021: * 1. the old entry has an amap and that amap is
3022: * being shared. this means that the old (parent)
3023: * process is sharing the amap with another
3024: * process. if we do not clear needs_copy here
3025: * we will end up in a situation where both the
3026: * parent and child process are refering to the
3027: * same amap with "needs_copy" set. if the
3028: * parent write-faults, the fault routine will
3029: * clear "needs_copy" in the parent by allocating
3030: * a new amap. this is wrong because the
3031: * parent is supposed to be sharing the old amap
3032: * and the new amap will break that.
1.10 mrg 3033: *
1.14 chuck 3034: * 2. if the old entry has an amap and a non-zero
3035: * wire count then we are going to have to call
3036: * amap_cow_now to avoid page faults in the
3037: * parent process. since amap_cow_now requires
3038: * "needs_copy" to be clear we might as well
3039: * clear it here as well.
1.10 mrg 3040: *
3041: */
3042:
1.14 chuck 3043: if (old_entry->aref.ar_amap != NULL) {
3044:
1.34 chuck 3045: if ((amap_flags(old_entry->aref.ar_amap) &
1.14 chuck 3046: AMAP_SHARED) != 0 ||
1.55 thorpej 3047: VM_MAPENT_ISWIRED(old_entry)) {
1.14 chuck 3048:
3049: amap_copy(new_map, new_entry, M_WAITOK, FALSE,
3050: 0, 0);
3051: /* XXXCDC: M_WAITOK ... ok? */
3052: }
1.10 mrg 3053: }
1.85 chs 3054:
1.10 mrg 3055: /*
1.14 chuck 3056: * if the parent's entry is wired down, then the
3057: * parent process does not want page faults on
3058: * access to that memory. this means that we
3059: * cannot do copy-on-write because we can't write
3060: * protect the old entry. in this case we
3061: * resolve all copy-on-write faults now, using
3062: * amap_cow_now. note that we have already
3063: * allocated any needed amap (above).
1.10 mrg 3064: */
3065:
1.55 thorpej 3066: if (VM_MAPENT_ISWIRED(old_entry)) {
1.1 mrg 3067:
1.14 chuck 3068: /*
3069: * resolve all copy-on-write faults now
3070: * (note that there is nothing to do if
3071: * the old mapping does not have an amap).
3072: * XXX: is it worthwhile to bother with pmap_copy
3073: * in this case?
3074: */
3075: if (old_entry->aref.ar_amap)
3076: amap_cow_now(new_map, new_entry);
3077:
3078: } else {
3079:
3080: /*
3081: * setup mappings to trigger copy-on-write faults
3082: * we must write-protect the parent if it has
3083: * an amap and it is not already "needs_copy"...
3084: * if it is already "needs_copy" then the parent
3085: * has already been write-protected by a previous
3086: * fork operation.
3087: *
3088: * if we do not write-protect the parent, then
3089: * we must be sure to write-protect the child
3090: * after the pmap_copy() operation.
3091: *
3092: * XXX: pmap_copy should have some way of telling
3093: * us that it didn't do anything so we can avoid
3094: * calling pmap_protect needlessly.
3095: */
3096:
3097: if (old_entry->aref.ar_amap) {
3098:
3099: if (!UVM_ET_ISNEEDSCOPY(old_entry)) {
3100: if (old_entry->max_protection & VM_PROT_WRITE) {
3101: pmap_protect(old_map->pmap,
3102: old_entry->start,
3103: old_entry->end,
3104: old_entry->protection &
3105: ~VM_PROT_WRITE);
1.95 thorpej 3106: pmap_update();
1.14 chuck 3107: }
3108: old_entry->etype |= UVM_ET_NEEDSCOPY;
3109: }
3110:
3111: /*
3112: * parent must now be write-protected
3113: */
3114: protect_child = FALSE;
3115: } else {
3116:
3117: /*
3118: * we only need to protect the child if the
3119: * parent has write access.
3120: */
3121: if (old_entry->max_protection & VM_PROT_WRITE)
3122: protect_child = TRUE;
3123: else
3124: protect_child = FALSE;
3125:
3126: }
3127:
3128: /*
3129: * copy the mappings
3130: * XXX: need a way to tell if this does anything
3131: */
1.1 mrg 3132:
1.14 chuck 3133: pmap_copy(new_pmap, old_map->pmap,
1.10 mrg 3134: new_entry->start,
1.14 chuck 3135: (old_entry->end - old_entry->start),
1.10 mrg 3136: old_entry->start);
1.85 chs 3137:
1.14 chuck 3138: /*
3139: * protect the child's mappings if necessary
3140: */
3141: if (protect_child) {
3142: pmap_protect(new_pmap, new_entry->start,
3143: new_entry->end,
3144: new_entry->protection &
3145: ~VM_PROT_WRITE);
1.95 thorpej 3146: pmap_update();
1.14 chuck 3147: }
1.10 mrg 3148:
3149: }
3150: break;
1.14 chuck 3151: } /* end of switch statement */
1.10 mrg 3152: old_entry = old_entry->next;
1.1 mrg 3153: }
3154:
1.10 mrg 3155: new_map->size = old_map->size;
3156: vm_map_unlock(old_map);
1.1 mrg 3157:
3158: #ifdef SYSVSHM
1.10 mrg 3159: if (vm1->vm_shm)
3160: shmfork(vm1, vm2);
1.39 thorpej 3161: #endif
3162:
3163: #ifdef PMAP_FORK
3164: pmap_fork(vm1->vm_map.pmap, vm2->vm_map.pmap);
1.1 mrg 3165: #endif
3166:
1.10 mrg 3167: UVMHIST_LOG(maphist,"<- done",0,0,0,0);
3168: return(vm2);
1.1 mrg 3169: }
3170:
3171:
3172: #if defined(DDB)
3173:
3174: /*
3175: * DDB hooks
3176: */
3177:
3178: /*
3179: * uvm_map_printit: actually prints the map
3180: */
3181:
1.10 mrg 3182: void
3183: uvm_map_printit(map, full, pr)
3184: vm_map_t map;
3185: boolean_t full;
3186: void (*pr) __P((const char *, ...));
3187: {
3188: vm_map_entry_t entry;
3189:
3190: (*pr)("MAP %p: [0x%lx->0x%lx]\n", map, map->min_offset,map->max_offset);
1.53 thorpej 3191: (*pr)("\t#ent=%d, sz=%d, ref=%d, version=%d, flags=0x%x\n",
3192: map->nentries, map->size, map->ref_count, map->timestamp,
3193: map->flags);
1.16 chuck 3194: #ifdef pmap_resident_count
3195: (*pr)("\tpmap=%p(resident=%d)\n", map->pmap,
3196: pmap_resident_count(map->pmap));
3197: #else
3198: /* XXXCDC: this should be required ... */
3199: (*pr)("\tpmap=%p(resident=<<NOT SUPPORTED!!!>>)\n", map->pmap);
3200: #endif
1.10 mrg 3201: if (!full)
3202: return;
3203: for (entry = map->header.next; entry != &map->header;
3204: entry = entry->next) {
1.70 kleink 3205: (*pr)(" - %p: 0x%lx->0x%lx: obj=%p/0x%llx, amap=%p/%d\n",
1.10 mrg 3206: entry, entry->start, entry->end, entry->object.uvm_obj,
1.85 chs 3207: (long long)entry->offset, entry->aref.ar_amap,
3208: entry->aref.ar_pageoff);
1.10 mrg 3209: (*pr)(
1.85 chs 3210: "\tsubmap=%c, cow=%c, nc=%c, prot(max)=%d/%d, inh=%d, "
3211: "wc=%d, adv=%d\n",
1.10 mrg 3212: (entry->etype & UVM_ET_SUBMAP) ? 'T' : 'F',
3213: (entry->etype & UVM_ET_COPYONWRITE) ? 'T' : 'F',
3214: (entry->etype & UVM_ET_NEEDSCOPY) ? 'T' : 'F',
3215: entry->protection, entry->max_protection,
3216: entry->inheritance, entry->wired_count, entry->advice);
3217: }
1.1 mrg 3218: }
3219:
3220: /*
3221: * uvm_object_printit: actually prints the object
3222: */
3223:
1.10 mrg 3224: void
3225: uvm_object_printit(uobj, full, pr)
3226: struct uvm_object *uobj;
3227: boolean_t full;
3228: void (*pr) __P((const char *, ...));
3229: {
3230: struct vm_page *pg;
3231: int cnt = 0;
3232:
1.71 chs 3233: (*pr)("OBJECT %p: locked=%d, pgops=%p, npages=%d, ",
3234: uobj, uobj->vmobjlock.lock_data, uobj->pgops, uobj->uo_npages);
1.42 thorpej 3235: if (UVM_OBJ_IS_KERN_OBJECT(uobj))
1.10 mrg 3236: (*pr)("refs=<SYSTEM>\n");
3237: else
3238: (*pr)("refs=%d\n", uobj->uo_refs);
3239:
1.71 chs 3240: if (!full) {
3241: return;
3242: }
1.10 mrg 3243: (*pr)(" PAGES <pg,offset>:\n ");
1.71 chs 3244: for (pg = TAILQ_FIRST(&uobj->memq);
3245: pg != NULL;
3246: pg = TAILQ_NEXT(pg, listq), cnt++) {
1.85 chs 3247: (*pr)("<%p,0x%llx> ", pg, (long long)pg->offset);
1.71 chs 3248: if ((cnt % 3) == 2) {
3249: (*pr)("\n ");
3250: }
3251: }
3252: if ((cnt % 3) != 2) {
3253: (*pr)("\n");
1.10 mrg 3254: }
1.1 mrg 3255: }
3256:
3257: /*
3258: * uvm_page_printit: actually print the page
3259: */
3260:
1.86 chs 3261: static const char page_flagbits[] =
3262: "\20\1BUSY\2WANTED\3TABLED\4CLEAN\5CLEANCHK\6RELEASED\7FAKE\10RDONLY"
3263: "\11ZERO\15PAGER1";
3264: static const char page_pqflagbits[] =
3265: "\20\1FREE\2INACTIVE\3ACTIVE\4LAUNDRY\5ANON\6AOBJ";
3266:
1.10 mrg 3267: void
3268: uvm_page_printit(pg, full, pr)
3269: struct vm_page *pg;
3270: boolean_t full;
3271: void (*pr) __P((const char *, ...));
3272: {
1.85 chs 3273: struct vm_page *tpg;
1.10 mrg 3274: struct uvm_object *uobj;
3275: struct pglist *pgl;
1.71 chs 3276: char pgbuf[128];
3277: char pqbuf[128];
1.1 mrg 3278:
1.10 mrg 3279: (*pr)("PAGE %p:\n", pg);
1.71 chs 3280: bitmask_snprintf(pg->flags, page_flagbits, pgbuf, sizeof(pgbuf));
3281: bitmask_snprintf(pg->pqflags, page_pqflagbits, pqbuf, sizeof(pqbuf));
3282: (*pr)(" flags=%s, pqflags=%s, vers=%d, wire_count=%d, pa=0x%lx\n",
3283: pgbuf, pqbuf, pg->version, pg->wire_count, (long)pg->phys_addr);
1.86 chs 3284: (*pr)(" uobject=%p, uanon=%p, offset=0x%llx loan_count=%d\n",
3285: pg->uobject, pg->uanon, (long long)pg->offset, pg->loan_count);
1.1 mrg 3286: #if defined(UVM_PAGE_TRKOWN)
1.10 mrg 3287: if (pg->flags & PG_BUSY)
3288: (*pr)(" owning process = %d, tag=%s\n",
3289: pg->owner, pg->owner_tag);
3290: else
3291: (*pr)(" page not busy, no owner\n");
1.1 mrg 3292: #else
1.10 mrg 3293: (*pr)(" [page ownership tracking disabled]\n");
1.1 mrg 3294: #endif
3295:
1.10 mrg 3296: if (!full)
3297: return;
3298:
3299: /* cross-verify object/anon */
3300: if ((pg->pqflags & PQ_FREE) == 0) {
3301: if (pg->pqflags & PQ_ANON) {
3302: if (pg->uanon == NULL || pg->uanon->u.an_page != pg)
1.85 chs 3303: (*pr)(" >>> ANON DOES NOT POINT HERE <<< (%p)\n",
1.10 mrg 3304: (pg->uanon) ? pg->uanon->u.an_page : NULL);
3305: else
3306: (*pr)(" anon backpointer is OK\n");
3307: } else {
3308: uobj = pg->uobject;
3309: if (uobj) {
3310: (*pr)(" checking object list\n");
1.85 chs 3311: TAILQ_FOREACH(tpg, &uobj->memq, listq) {
3312: if (tpg == pg) {
3313: break;
3314: }
1.10 mrg 3315: }
1.85 chs 3316: if (tpg)
1.10 mrg 3317: (*pr)(" page found on object list\n");
3318: else
3319: (*pr)(" >>> PAGE NOT FOUND ON OBJECT LIST! <<<\n");
3320: }
3321: }
3322: }
1.1 mrg 3323:
1.10 mrg 3324: /* cross-verify page queue */
1.73 thorpej 3325: if (pg->pqflags & PQ_FREE) {
3326: int fl = uvm_page_lookup_freelist(pg);
1.96 thorpej 3327: int color = VM_PGCOLOR_BUCKET(pg);
3328: pgl = &uvm.page_free[fl].pgfl_buckets[color].pgfl_queues[
3329: ((pg)->flags & PG_ZERO) ? PGFL_ZEROS : PGFL_UNKNOWN];
1.85 chs 3330: } else if (pg->pqflags & PQ_INACTIVE) {
1.97 ! ross 3331: pgl = &uvm.page_inactive;
1.85 chs 3332: } else if (pg->pqflags & PQ_ACTIVE) {
1.10 mrg 3333: pgl = &uvm.page_active;
1.85 chs 3334: } else {
1.10 mrg 3335: pgl = NULL;
1.85 chs 3336: }
1.10 mrg 3337:
3338: if (pgl) {
3339: (*pr)(" checking pageq list\n");
1.85 chs 3340: TAILQ_FOREACH(tpg, pgl, pageq) {
3341: if (tpg == pg) {
3342: break;
3343: }
1.10 mrg 3344: }
1.85 chs 3345: if (tpg)
1.10 mrg 3346: (*pr)(" page found on pageq list\n");
3347: else
3348: (*pr)(" >>> PAGE NOT FOUND ON PAGEQ LIST! <<<\n");
3349: }
1.1 mrg 3350: }
3351: #endif
CVSweb <webmaster@jp.NetBSD.org>