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