|
|
1.1 root 1: /*
2: * Copyright (c) 1991 Regents of the University of California.
3: * All rights reserved.
4: *
5: * This code is derived from software contributed to Berkeley by
6: * The Mach Operating System project at Carnegie-Mellon University.
7: *
8: * Redistribution and use in source and binary forms, with or without
9: * modification, are permitted provided that the following conditions
10: * are met:
11: * 1. Redistributions of source code must retain the above copyright
12: * notice, this list of conditions and the following disclaimer.
13: * 2. Redistributions in binary form must reproduce the above copyright
14: * notice, this list of conditions and the following disclaimer in the
15: * documentation and/or other materials provided with the distribution.
16: * 3. All advertising materials mentioning features or use of this software
17: * must display the following acknowledgement:
18: * This product includes software developed by the University of
19: * California, Berkeley and its contributors.
20: * 4. Neither the name of the University nor the names of its contributors
21: * may be used to endorse or promote products derived from this software
22: * without specific prior written permission.
23: *
24: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
25: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
28: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
30: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34: * SUCH DAMAGE.
35: *
1.1.1.4 ! root 36: * from: @(#)vm_map.c 7.3 (Berkeley) 4/21/91
! 37: * vm_map.c,v 1.6 1993/07/15 14:25:28 cgd Exp
1.1 root 38: *
39: *
40: * Copyright (c) 1987, 1990 Carnegie-Mellon University.
41: * All rights reserved.
42: *
43: * Authors: Avadis Tevanian, Jr., Michael Wayne Young
44: *
45: * Permission to use, copy, modify and distribute this software and
46: * its documentation is hereby granted, provided that both the copyright
47: * notice and this permission notice appear in all copies of the
48: * software, derivative works or modified versions, and any portions
49: * thereof, and that both notices appear in supporting documentation.
50: *
51: * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
52: * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND
53: * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
54: *
55: * Carnegie Mellon requests users of this software to return to
56: *
57: * Software Distribution Coordinator or [email protected]
58: * School of Computer Science
59: * Carnegie Mellon University
60: * Pittsburgh PA 15213-3890
61: *
62: * any improvements or extensions that they make and grant Carnegie the
63: * rights to redistribute these changes.
64: */
65:
66: /*
67: * Virtual memory mapping module.
68: */
69:
70: #include "param.h"
71: #include "malloc.h"
1.1.1.4 ! root 72: #include "systm.h"
1.1 root 73: #include "vm.h"
74: #include "vm_page.h"
75: #include "vm_object.h"
76:
77: /*
78: * Virtual memory maps provide for the mapping, protection,
79: * and sharing of virtual memory objects. In addition,
80: * this module provides for an efficient virtual copy of
81: * memory from one map to another.
82: *
83: * Synchronization is required prior to most operations.
84: *
85: * Maps consist of an ordered doubly-linked list of simple
86: * entries; a single hint is used to speed up lookups.
87: *
88: * In order to properly represent the sharing of virtual
89: * memory regions among maps, the map structure is bi-level.
90: * Top-level ("address") maps refer to regions of sharable
91: * virtual memory. These regions are implemented as
92: * ("sharing") maps, which then refer to the actual virtual
93: * memory objects. When two address maps "share" memory,
94: * their top-level maps both have references to the same
95: * sharing map. When memory is virtual-copied from one
96: * address map to another, the references in the sharing
97: * maps are actually copied -- no copying occurs at the
98: * virtual memory object level.
99: *
100: * Since portions of maps are specified by start/end addreses,
101: * which may not align with existing map entries, all
102: * routines merely "clip" entries to these start/end values.
103: * [That is, an entry is split into two, bordering at a
104: * start or end value.] Note that these clippings may not
105: * always be necessary (as the two resulting entries are then
106: * not changed); however, the clipping is done for convenience.
107: * No attempt is currently made to "glue back together" two
108: * abutting entries.
109: *
110: * As mentioned above, virtual copy operations are performed
111: * by copying VM object references from one sharing map to
112: * another, and then marking both regions as copy-on-write.
113: * It is important to note that only one writeable reference
114: * to a VM object region exists in any map -- this means that
115: * shadow object creation can be delayed until a write operation
116: * occurs.
117: */
118:
1.1.1.4 ! root 119: int vm_map_delete(vm_map_t, vm_offset_t, vm_offset_t);
! 120:
1.1 root 121: /*
122: * vm_map_startup:
123: *
124: * Initialize the vm_map module. Must be called before
125: * any other vm_map routines.
126: *
127: * Map and entry structures are allocated from the general
128: * purpose memory pool with some exceptions:
129: *
130: * - The kernel map and kmem submap are allocated statically.
131: * - Kernel map entries are allocated out of a static pool.
132: *
133: * These restrictions are necessary since malloc() uses the
134: * maps and requires map entries.
135: */
136:
137: vm_offset_t kentry_data;
138: vm_size_t kentry_data_size;
139: vm_map_entry_t kentry_free;
140: vm_map_t kmap_free;
141:
1.1.1.4 ! root 142: void
! 143: vm_map_startup()
1.1 root 144: {
145: register int i;
146: register vm_map_entry_t mep;
147: vm_map_t mp;
148:
149: /*
150: * Static map structures for allocation before initialization of
151: * kernel map or kmem map. vm_map_create knows how to deal with them.
152: */
153: kmap_free = mp = (vm_map_t) kentry_data;
154: i = MAX_KMAP;
155: while (--i > 0) {
156: mp->header.next = (vm_map_entry_t) (mp + 1);
157: mp++;
158: }
159: mp++->header.next = NULL;
160:
161: /*
162: * Form a free list of statically allocated kernel map entries
163: * with the rest.
164: */
165: kentry_free = mep = (vm_map_entry_t) mp;
166: i = (kentry_data_size - MAX_KMAP * sizeof *mp) / sizeof *mep;
167: while (--i > 0) {
168: mep->next = mep + 1;
169: mep++;
170: }
171: mep->next = NULL;
172: }
173:
174: /*
175: * Allocate a vmspace structure, including a vm_map and pmap,
176: * and initialize those structures. The refcnt is set to 1.
177: * The remaining fields must be initialized by the caller.
178: */
179: struct vmspace *
180: vmspace_alloc(min, max, pageable)
181: vm_offset_t min, max;
182: int pageable;
183: {
184: register struct vmspace *vm;
185:
186: MALLOC(vm, struct vmspace *, sizeof(struct vmspace), M_VMMAP, M_WAITOK);
187: bzero(vm, (caddr_t) &vm->vm_startcopy - (caddr_t) vm);
188: vm_map_init(&vm->vm_map, min, max, pageable);
189: pmap_pinit(&vm->vm_pmap);
190: vm->vm_map.pmap = &vm->vm_pmap; /* XXX */
191: vm->vm_refcnt = 1;
192: return (vm);
193: }
194:
195: void
196: vmspace_free(vm)
197: register struct vmspace *vm;
198: {
199:
200: if (--vm->vm_refcnt == 0) {
201: /*
202: * Lock the map, to wait out all other references to it.
203: * Delete all of the mappings and pages they hold,
204: * then call the pmap module to reclaim anything left.
205: */
206: vm_map_lock(&vm->vm_map);
207: (void) vm_map_delete(&vm->vm_map, vm->vm_map.min_offset,
208: vm->vm_map.max_offset);
209: pmap_release(&vm->vm_pmap);
210: FREE(vm, M_VMMAP);
211: }
212: }
213:
214: /*
215: * vm_map_create:
216: *
217: * Creates and returns a new empty VM map with
218: * the given physical map structure, and having
219: * the given lower and upper address bounds.
220: */
221: vm_map_t vm_map_create(pmap, min, max, pageable)
222: pmap_t pmap;
223: vm_offset_t min, max;
224: boolean_t pageable;
225: {
226: register vm_map_t result;
1.1.1.4 ! root 227: extern vm_map_t kmem_map;
1.1 root 228:
229: if (kmem_map == NULL) {
230: result = kmap_free;
231: kmap_free = (vm_map_t) result->header.next;
232: if (result == NULL)
233: panic("vm_map_create: out of maps");
234: } else
235: MALLOC(result, vm_map_t, sizeof(struct vm_map),
236: M_VMMAP, M_WAITOK);
237:
238: vm_map_init(result, min, max, pageable);
239: result->pmap = pmap;
240: return(result);
241: }
242:
243: /*
244: * Initialize an existing vm_map structure
245: * such as that in the vmspace structure.
246: * The pmap is set elsewhere.
247: */
248: void
249: vm_map_init(map, min, max, pageable)
250: register struct vm_map *map;
251: vm_offset_t min, max;
252: boolean_t pageable;
253: {
254: map->header.next = map->header.prev = &map->header;
255: map->nentries = 0;
256: map->size = 0;
257: map->ref_count = 1;
258: map->is_main_map = TRUE;
259: map->min_offset = min;
260: map->max_offset = max;
261: map->entries_pageable = pageable;
262: map->first_free = &map->header;
263: map->hint = &map->header;
264: map->timestamp = 0;
265: lock_init(&map->lock, TRUE);
266: simple_lock_init(&map->ref_lock);
267: simple_lock_init(&map->hint_lock);
268: }
269:
270: /*
271: * vm_map_entry_create: [ internal use only ]
272: *
273: * Allocates a VM map entry for insertion.
274: * No entry fields are filled in. This routine is
275: */
276: vm_map_entry_t vm_map_entry_create(map)
277: vm_map_t map;
278: {
279: vm_map_entry_t entry;
1.1.1.4 ! root 280: extern vm_map_t kernel_map, kmem_map, mb_map, buffer_map, pager_map;
1.1 root 281:
1.1.1.2 root 282: if (map == kernel_map || map == kmem_map || map == mb_map
1.1.1.3 root 283: || map == buffer_map || map == pager_map) {
1.1 root 284: if (entry = kentry_free)
285: kentry_free = kentry_free->next;
286: } else
287: MALLOC(entry, vm_map_entry_t, sizeof(struct vm_map_entry),
288: M_VMMAPENT, M_WAITOK);
289: if (entry == NULL)
290: panic("vm_map_entry_create: out of map entries");
291:
292: return(entry);
293: }
294:
295: /*
296: * vm_map_entry_dispose: [ internal use only ]
297: *
298: * Inverse of vm_map_entry_create.
299: */
1.1.1.4 ! root 300: void
! 301: vm_map_entry_dispose(map, entry)
1.1 root 302: vm_map_t map;
303: vm_map_entry_t entry;
304: {
1.1.1.3 root 305: extern vm_map_t kernel_map, kmem_map, mb_map, buffer_map, pager_map;
1.1 root 306:
1.1.1.2 root 307: if (map == kernel_map || map == kmem_map || map == mb_map
1.1.1.3 root 308: || map == buffer_map || map == pager_map) {
1.1 root 309: entry->next = kentry_free;
310: kentry_free = entry;
311: } else
312: FREE(entry, M_VMMAPENT);
313: }
314:
315: /*
316: * vm_map_entry_{un,}link:
317: *
318: * Insert/remove entries from maps.
319: */
320: #define vm_map_entry_link(map, after_where, entry) \
321: { \
322: (map)->nentries++; \
323: (entry)->prev = (after_where); \
324: (entry)->next = (after_where)->next; \
325: (entry)->prev->next = (entry); \
326: (entry)->next->prev = (entry); \
327: }
328: #define vm_map_entry_unlink(map, entry) \
329: { \
330: (map)->nentries--; \
331: (entry)->next->prev = (entry)->prev; \
332: (entry)->prev->next = (entry)->next; \
333: }
334:
335: /*
336: * vm_map_reference:
337: *
338: * Creates another valid reference to the given map.
339: *
340: */
1.1.1.4 ! root 341: void
! 342: vm_map_reference(map)
1.1 root 343: register vm_map_t map;
344: {
345: if (map == NULL)
346: return;
347:
348: simple_lock(&map->ref_lock);
349: map->ref_count++;
350: simple_unlock(&map->ref_lock);
351: }
352:
353: /*
354: * vm_map_deallocate:
355: *
356: * Removes a reference from the specified map,
357: * destroying it if no references remain.
358: * The map should not be locked.
359: */
1.1.1.4 ! root 360: void
! 361: vm_map_deallocate(map)
1.1 root 362: register vm_map_t map;
363: {
364: register int c;
365:
366: if (map == NULL)
367: return;
368:
369: simple_lock(&map->ref_lock);
370: c = --map->ref_count;
371: simple_unlock(&map->ref_lock);
372:
373: if (c > 0) {
374: return;
375: }
376:
377: /*
378: * Lock the map, to wait out all other references
379: * to it.
380: */
381:
382: vm_map_lock(map);
383:
384: (void) vm_map_delete(map, map->min_offset, map->max_offset);
385:
386: pmap_destroy(map->pmap);
387:
388: FREE(map, M_VMMAP);
389: }
390:
391: /*
392: * vm_map_insert: [ internal use only ]
393: *
394: * Inserts the given whole VM object into the target
395: * map at the specified address range. The object's
396: * size should match that of the address range.
397: *
398: * Requires that the map be locked, and leaves it so.
399: */
1.1.1.4 ! root 400: int
1.1 root 401: vm_map_insert(map, object, offset, start, end)
402: vm_map_t map;
403: vm_object_t object;
404: vm_offset_t offset;
405: vm_offset_t start;
406: vm_offset_t end;
407: {
408: register vm_map_entry_t new_entry;
409: register vm_map_entry_t prev_entry;
410: vm_map_entry_t temp_entry;
411:
412: /*
413: * Check that the start and end points are not bogus.
414: */
415:
416: if ((start < map->min_offset) || (end > map->max_offset) ||
417: (start >= end))
418: return(KERN_INVALID_ADDRESS);
419:
420: /*
421: * Find the entry prior to the proposed
422: * starting address; if it's part of an
423: * existing entry, this range is bogus.
424: */
425:
426: if (vm_map_lookup_entry(map, start, &temp_entry))
427: return(KERN_NO_SPACE);
428:
429: prev_entry = temp_entry;
430:
431: /*
432: * Assert that the next entry doesn't overlap the
433: * end point.
434: */
435:
436: if ((prev_entry->next != &map->header) &&
437: (prev_entry->next->start < end))
438: return(KERN_NO_SPACE);
439:
440: /*
441: * See if we can avoid creating a new entry by
442: * extending one of our neighbors.
443: */
444:
445: if (object == NULL) {
446: if ((prev_entry != &map->header) &&
447: (prev_entry->end == start) &&
448: (map->is_main_map) &&
449: (prev_entry->is_a_map == FALSE) &&
450: (prev_entry->is_sub_map == FALSE) &&
451: (prev_entry->inheritance == VM_INHERIT_DEFAULT) &&
452: (prev_entry->protection == VM_PROT_DEFAULT) &&
453: (prev_entry->max_protection == VM_PROT_DEFAULT) &&
454: (prev_entry->wired_count == 0)) {
455:
456: if (vm_object_coalesce(prev_entry->object.vm_object,
457: NULL,
458: prev_entry->offset,
459: (vm_offset_t) 0,
460: (vm_size_t)(prev_entry->end
461: - prev_entry->start),
462: (vm_size_t)(end - prev_entry->end))) {
463: /*
464: * Coalesced the two objects - can extend
465: * the previous map entry to include the
466: * new range.
467: */
468: map->size += (end - prev_entry->end);
469: prev_entry->end = end;
470: return(KERN_SUCCESS);
471: }
472: }
473: }
474:
475: /*
476: * Create a new entry
477: */
478:
479: new_entry = vm_map_entry_create(map);
480: new_entry->start = start;
481: new_entry->end = end;
482:
483: new_entry->is_a_map = FALSE;
484: new_entry->is_sub_map = FALSE;
485: new_entry->object.vm_object = object;
486: new_entry->offset = offset;
487:
488: new_entry->copy_on_write = FALSE;
489: new_entry->needs_copy = FALSE;
490:
491: if (map->is_main_map) {
492: new_entry->inheritance = VM_INHERIT_DEFAULT;
493: new_entry->protection = VM_PROT_DEFAULT;
494: new_entry->max_protection = VM_PROT_DEFAULT;
495: new_entry->wired_count = 0;
496: }
497:
498: /*
499: * Insert the new entry into the list
500: */
501:
502: vm_map_entry_link(map, prev_entry, new_entry);
503: map->size += new_entry->end - new_entry->start;
504:
505: /*
506: * Update the free space hint
507: */
508:
509: if ((map->first_free == prev_entry) && (prev_entry->end >= new_entry->start))
510: map->first_free = new_entry;
511:
512: return(KERN_SUCCESS);
513: }
514:
515: /*
516: * SAVE_HINT:
517: *
518: * Saves the specified entry as the hint for
519: * future lookups. Performs necessary interlocks.
520: */
521: #define SAVE_HINT(map,value) \
522: simple_lock(&(map)->hint_lock); \
523: (map)->hint = (value); \
524: simple_unlock(&(map)->hint_lock);
525:
526: /*
527: * vm_map_lookup_entry: [ internal use only ]
528: *
529: * Finds the map entry containing (or
530: * immediately preceding) the specified address
531: * in the given map; the entry is returned
532: * in the "entry" parameter. The boolean
533: * result indicates whether the address is
534: * actually contained in the map.
535: */
536: boolean_t vm_map_lookup_entry(map, address, entry)
537: register vm_map_t map;
538: register vm_offset_t address;
539: vm_map_entry_t *entry; /* OUT */
540: {
541: register vm_map_entry_t cur;
542: register vm_map_entry_t last;
543:
544: /*
545: * Start looking either from the head of the
546: * list, or from the hint.
547: */
548:
549: simple_lock(&map->hint_lock);
550: cur = map->hint;
551: simple_unlock(&map->hint_lock);
552:
553: if (cur == &map->header)
554: cur = cur->next;
555:
556: if (address >= cur->start) {
557: /*
558: * Go from hint to end of list.
559: *
560: * But first, make a quick check to see if
561: * we are already looking at the entry we
562: * want (which is usually the case).
563: * Note also that we don't need to save the hint
564: * here... it is the same hint (unless we are
565: * at the header, in which case the hint didn't
566: * buy us anything anyway).
567: */
568: last = &map->header;
569: if ((cur != last) && (cur->end > address)) {
570: *entry = cur;
571: return(TRUE);
572: }
573: }
574: else {
575: /*
576: * Go from start to hint, *inclusively*
577: */
578: last = cur->next;
579: cur = map->header.next;
580: }
581:
582: /*
583: * Search linearly
584: */
585:
586: while (cur != last) {
587: if (cur->end > address) {
588: if (address >= cur->start) {
589: /*
590: * Save this lookup for future
591: * hints, and return
592: */
593:
594: *entry = cur;
595: SAVE_HINT(map, cur);
596: return(TRUE);
597: }
598: break;
599: }
600: cur = cur->next;
601: }
602: *entry = cur->prev;
603: SAVE_HINT(map, *entry);
604: return(FALSE);
605: }
606:
607: /*
608: * vm_map_find finds an unallocated region in the target address
609: * map with the given length. The search is defined to be
610: * first-fit from the specified address; the region found is
611: * returned in the same parameter.
612: *
613: */
1.1.1.4 ! root 614: int
1.1 root 615: vm_map_find(map, object, offset, addr, length, find_space)
616: vm_map_t map;
617: vm_object_t object;
618: vm_offset_t offset;
619: vm_offset_t *addr; /* IN/OUT */
620: vm_size_t length;
621: boolean_t find_space;
622: {
623: register vm_map_entry_t entry;
624: register vm_offset_t start;
625: register vm_offset_t end;
626: int result;
627:
628: start = *addr;
629:
630: vm_map_lock(map);
631:
632: if (find_space) {
633: /*
634: * Calculate the first possible address.
635: */
636:
637: if (start < map->min_offset)
638: start = map->min_offset;
639: if (start > map->max_offset) {
640: vm_map_unlock(map);
641: return (KERN_NO_SPACE);
642: }
643:
644: /*
645: * Look for the first possible address;
646: * if there's already something at this
647: * address, we have to start after it.
648: */
649:
650: if (start == map->min_offset) {
651: if ((entry = map->first_free) != &map->header)
652: start = entry->end;
653: } else {
654: vm_map_entry_t tmp_entry;
655: if (vm_map_lookup_entry(map, start, &tmp_entry))
656: start = tmp_entry->end;
657: entry = tmp_entry;
658: }
659:
660: /*
661: * In any case, the "entry" always precedes
662: * the proposed new region throughout the
663: * loop:
664: */
665:
666: while (TRUE) {
667: register vm_map_entry_t next;
668:
669: /*
670: * Find the end of the proposed new region.
671: * Be sure we didn't go beyond the end, or
672: * wrap around the address.
673: */
674:
675: end = start + length;
676:
677: if ((end > map->max_offset) || (end < start)) {
678: vm_map_unlock(map);
679: return (KERN_NO_SPACE);
680: }
681:
682: /*
683: * If there are no more entries, we must win.
684: */
685:
686: next = entry->next;
687: if (next == &map->header)
688: break;
689:
690: /*
691: * If there is another entry, it must be
692: * after the end of the potential new region.
693: */
694:
695: if (next->start >= end)
696: break;
697:
698: /*
699: * Didn't fit -- move to the next entry.
700: */
701:
702: entry = next;
703: start = entry->end;
704: }
705: *addr = start;
706:
707: SAVE_HINT(map, entry);
708: }
709:
710: result = vm_map_insert(map, object, offset, start, start + length);
711:
712: vm_map_unlock(map);
713: return(result);
714: }
715:
716: /*
717: * vm_map_simplify_entry: [ internal use only ]
718: *
719: * Simplify the given map entry by:
720: * removing extra sharing maps
721: * [XXX maybe later] merging with a neighbor
722: */
1.1.1.4 ! root 723: void
! 724: vm_map_simplify_entry(map, entry)
1.1 root 725: vm_map_t map;
726: vm_map_entry_t entry;
727: {
728: #ifdef lint
729: map++;
730: #endif lint
731:
732: /*
733: * If this entry corresponds to a sharing map, then
734: * see if we can remove the level of indirection.
735: * If it's not a sharing map, then it points to
736: * a VM object, so see if we can merge with either
737: * of our neighbors.
738: */
739:
740: if (entry->is_sub_map)
741: return;
742: if (entry->is_a_map) {
743: #if 0
744: vm_map_t my_share_map;
745: int count;
746:
747: my_share_map = entry->object.share_map;
748: simple_lock(&my_share_map->ref_lock);
749: count = my_share_map->ref_count;
750: simple_unlock(&my_share_map->ref_lock);
751:
752: if (count == 1) {
753: /* Can move the region from
754: * entry->start to entry->end (+ entry->offset)
755: * in my_share_map into place of entry.
756: * Later.
757: */
758: }
759: #endif 0
760: }
761: else {
762: /*
763: * Try to merge with our neighbors.
764: *
765: * Conditions for merge are:
766: *
767: * 1. entries are adjacent.
768: * 2. both entries point to objects
769: * with null pagers.
770: *
771: * If a merge is possible, we replace the two
772: * entries with a single entry, then merge
773: * the two objects into a single object.
774: *
775: * Now, all that is left to do is write the
776: * code!
777: */
778: }
779: }
780:
781: /*
782: * vm_map_clip_start: [ internal use only ]
783: *
784: * Asserts that the given entry begins at or after
785: * the specified address; if necessary,
786: * it splits the entry into two.
787: */
788: #define vm_map_clip_start(map, entry, startaddr) \
789: { \
790: if (startaddr > entry->start) \
791: _vm_map_clip_start(map, entry, startaddr); \
792: }
793:
794: /*
795: * This routine is called only when it is known that
796: * the entry must be split.
797: */
1.1.1.4 ! root 798: void
! 799: _vm_map_clip_start(map, entry, start)
1.1 root 800: register vm_map_t map;
801: register vm_map_entry_t entry;
802: register vm_offset_t start;
803: {
804: register vm_map_entry_t new_entry;
805:
806: /*
807: * See if we can simplify this entry first
808: */
809:
810: vm_map_simplify_entry(map, entry);
811:
812: /*
813: * Split off the front portion --
814: * note that we must insert the new
815: * entry BEFORE this one, so that
816: * this entry has the specified starting
817: * address.
818: */
819:
820: new_entry = vm_map_entry_create(map);
821: *new_entry = *entry;
822:
823: new_entry->end = start;
824: entry->offset += (start - entry->start);
825: entry->start = start;
826:
827: vm_map_entry_link(map, entry->prev, new_entry);
828:
829: if (entry->is_a_map || entry->is_sub_map)
830: vm_map_reference(new_entry->object.share_map);
831: else
832: vm_object_reference(new_entry->object.vm_object);
833: }
834:
835: /*
836: * vm_map_clip_end: [ internal use only ]
837: *
838: * Asserts that the given entry ends at or before
839: * the specified address; if necessary,
840: * it splits the entry into two.
841: */
842:
843: void _vm_map_clip_end();
844: #define vm_map_clip_end(map, entry, endaddr) \
845: { \
846: if (endaddr < entry->end) \
847: _vm_map_clip_end(map, entry, endaddr); \
848: }
849:
850: /*
851: * This routine is called only when it is known that
852: * the entry must be split.
853: */
1.1.1.4 ! root 854: void
! 855: _vm_map_clip_end(map, entry, end)
1.1 root 856: register vm_map_t map;
857: register vm_map_entry_t entry;
858: register vm_offset_t end;
859: {
860: register vm_map_entry_t new_entry;
861:
862: /*
863: * Create a new entry and insert it
864: * AFTER the specified entry
865: */
866:
867: new_entry = vm_map_entry_create(map);
868: *new_entry = *entry;
869:
870: new_entry->start = entry->end = end;
871: new_entry->offset += (end - entry->start);
872:
873: vm_map_entry_link(map, entry, new_entry);
874:
875: if (entry->is_a_map || entry->is_sub_map)
876: vm_map_reference(new_entry->object.share_map);
877: else
878: vm_object_reference(new_entry->object.vm_object);
879: }
880:
881: /*
882: * VM_MAP_RANGE_CHECK: [ internal use only ]
883: *
884: * Asserts that the starting and ending region
885: * addresses fall within the valid range of the map.
886: */
887: #define VM_MAP_RANGE_CHECK(map, start, end) \
888: { \
889: if (start < vm_map_min(map)) \
890: start = vm_map_min(map); \
891: if (end > vm_map_max(map)) \
892: end = vm_map_max(map); \
893: if (start > end) \
894: start = end; \
895: }
896:
897: /*
898: * vm_map_submap: [ kernel use only ]
899: *
900: * Mark the given range as handled by a subordinate map.
901: *
902: * This range must have been created with vm_map_find,
903: * and no other operations may have been performed on this
904: * range prior to calling vm_map_submap.
905: *
906: * Only a limited number of operations can be performed
907: * within this rage after calling vm_map_submap:
908: * vm_fault
909: * [Don't try vm_map_copy!]
910: *
911: * To remove a submapping, one must first remove the
912: * range from the superior map, and then destroy the
913: * submap (if desired). [Better yet, don't try it.]
914: */
1.1.1.4 ! root 915: int
1.1 root 916: vm_map_submap(map, start, end, submap)
917: register vm_map_t map;
918: register vm_offset_t start;
919: register vm_offset_t end;
920: vm_map_t submap;
921: {
922: vm_map_entry_t entry;
923: register int result = KERN_INVALID_ARGUMENT;
924:
925: vm_map_lock(map);
926:
927: VM_MAP_RANGE_CHECK(map, start, end);
928:
929: if (vm_map_lookup_entry(map, start, &entry)) {
930: vm_map_clip_start(map, entry, start);
931: }
932: else
933: entry = entry->next;
934:
935: vm_map_clip_end(map, entry, end);
936:
937: if ((entry->start == start) && (entry->end == end) &&
938: (!entry->is_a_map) &&
939: (entry->object.vm_object == NULL) &&
940: (!entry->copy_on_write)) {
941: entry->is_a_map = FALSE;
942: entry->is_sub_map = TRUE;
943: vm_map_reference(entry->object.sub_map = submap);
944: result = KERN_SUCCESS;
945: }
946: vm_map_unlock(map);
947:
948: return(result);
949: }
950:
951: /*
952: * vm_map_protect:
953: *
954: * Sets the protection of the specified address
955: * region in the target map. If "set_max" is
956: * specified, the maximum protection is to be set;
957: * otherwise, only the current protection is affected.
958: */
1.1.1.4 ! root 959: int
1.1 root 960: vm_map_protect(map, start, end, new_prot, set_max)
961: register vm_map_t map;
962: register vm_offset_t start;
963: register vm_offset_t end;
964: register vm_prot_t new_prot;
965: register boolean_t set_max;
966: {
967: register vm_map_entry_t current;
968: vm_map_entry_t entry;
969:
970: vm_map_lock(map);
971:
972: VM_MAP_RANGE_CHECK(map, start, end);
973:
974: if (vm_map_lookup_entry(map, start, &entry)) {
975: vm_map_clip_start(map, entry, start);
976: }
977: else
978: entry = entry->next;
979:
980: /*
981: * Make a first pass to check for protection
982: * violations.
983: */
984:
985: current = entry;
986: while ((current != &map->header) && (current->start < end)) {
987: if (current->is_sub_map)
988: return(KERN_INVALID_ARGUMENT);
989: if ((new_prot & current->max_protection) != new_prot) {
990: vm_map_unlock(map);
991: return(KERN_PROTECTION_FAILURE);
992: }
993:
994: current = current->next;
995: }
996:
997: /*
998: * Go back and fix up protections.
999: * [Note that clipping is not necessary the second time.]
1000: */
1001:
1002: current = entry;
1003:
1004: while ((current != &map->header) && (current->start < end)) {
1005: vm_prot_t old_prot;
1006:
1007: vm_map_clip_end(map, current, end);
1008:
1009: old_prot = current->protection;
1010: if (set_max)
1011: current->protection =
1012: (current->max_protection = new_prot) &
1013: old_prot;
1014: else
1015: current->protection = new_prot;
1016:
1017: /*
1018: * Update physical map if necessary.
1019: * Worry about copy-on-write here -- CHECK THIS XXX
1020: */
1021:
1022: if (current->protection != old_prot) {
1023:
1024: #define MASK(entry) ((entry)->copy_on_write ? ~VM_PROT_WRITE : \
1025: VM_PROT_ALL)
1026: #define max(a,b) ((a) > (b) ? (a) : (b))
1027:
1028: if (current->is_a_map) {
1029: vm_map_entry_t share_entry;
1030: vm_offset_t share_end;
1031:
1032: vm_map_lock(current->object.share_map);
1033: (void) vm_map_lookup_entry(
1034: current->object.share_map,
1035: current->offset,
1036: &share_entry);
1037: share_end = current->offset +
1038: (current->end - current->start);
1039: while ((share_entry !=
1040: ¤t->object.share_map->header) &&
1041: (share_entry->start < share_end)) {
1042:
1043: pmap_protect(map->pmap,
1044: (max(share_entry->start,
1045: current->offset) -
1046: current->offset +
1047: current->start),
1048: min(share_entry->end,
1049: share_end) -
1050: current->offset +
1051: current->start,
1052: current->protection &
1053: MASK(share_entry));
1054:
1055: share_entry = share_entry->next;
1056: }
1057: vm_map_unlock(current->object.share_map);
1058: }
1059: else
1060: pmap_protect(map->pmap, current->start,
1061: current->end,
1062: current->protection & MASK(entry));
1063: #undef max
1064: #undef MASK
1065: }
1066: current = current->next;
1067: }
1068:
1069: vm_map_unlock(map);
1070: return(KERN_SUCCESS);
1071: }
1072:
1073: /*
1074: * vm_map_inherit:
1075: *
1076: * Sets the inheritance of the specified address
1077: * range in the target map. Inheritance
1078: * affects how the map will be shared with
1079: * child maps at the time of vm_map_fork.
1080: */
1.1.1.4 ! root 1081: int
1.1 root 1082: vm_map_inherit(map, start, end, new_inheritance)
1083: register vm_map_t map;
1084: register vm_offset_t start;
1085: register vm_offset_t end;
1086: register vm_inherit_t new_inheritance;
1087: {
1088: register vm_map_entry_t entry;
1089: vm_map_entry_t temp_entry;
1090:
1091: switch (new_inheritance) {
1092: case VM_INHERIT_NONE:
1093: case VM_INHERIT_COPY:
1094: case VM_INHERIT_SHARE:
1095: break;
1096: default:
1097: return(KERN_INVALID_ARGUMENT);
1098: }
1099:
1100: vm_map_lock(map);
1101:
1102: VM_MAP_RANGE_CHECK(map, start, end);
1103:
1104: if (vm_map_lookup_entry(map, start, &temp_entry)) {
1105: entry = temp_entry;
1106: vm_map_clip_start(map, entry, start);
1107: }
1108: else
1109: entry = temp_entry->next;
1110:
1111: while ((entry != &map->header) && (entry->start < end)) {
1112: vm_map_clip_end(map, entry, end);
1113:
1114: entry->inheritance = new_inheritance;
1115:
1116: entry = entry->next;
1117: }
1118:
1119: vm_map_unlock(map);
1120: return(KERN_SUCCESS);
1121: }
1122:
1123: /*
1124: * vm_map_pageable:
1125: *
1126: * Sets the pageability of the specified address
1127: * range in the target map. Regions specified
1128: * as not pageable require locked-down physical
1129: * memory and physical page maps.
1130: *
1131: * The map must not be locked, but a reference
1132: * must remain to the map throughout the call.
1133: */
1.1.1.4 ! root 1134: int
1.1 root 1135: vm_map_pageable(map, start, end, new_pageable)
1136: register vm_map_t map;
1137: register vm_offset_t start;
1138: register vm_offset_t end;
1139: register boolean_t new_pageable;
1140: {
1141: register vm_map_entry_t entry;
1142: vm_map_entry_t temp_entry;
1143:
1144: vm_map_lock(map);
1145:
1146: VM_MAP_RANGE_CHECK(map, start, end);
1147:
1148: /*
1149: * Only one pageability change may take place at one
1150: * time, since vm_fault assumes it will be called
1151: * only once for each wiring/unwiring. Therefore, we
1152: * have to make sure we're actually changing the pageability
1153: * for the entire region. We do so before making any changes.
1154: */
1155:
1156: if (vm_map_lookup_entry(map, start, &temp_entry)) {
1157: entry = temp_entry;
1158: vm_map_clip_start(map, entry, start);
1159: }
1160: else
1161: entry = temp_entry->next;
1162: temp_entry = entry;
1163:
1164: /*
1165: * Actions are rather different for wiring and unwiring,
1166: * so we have two separate cases.
1167: */
1168:
1169: if (new_pageable) {
1170:
1171: /*
1172: * Unwiring. First ensure that the range to be
1173: * unwired is really wired down.
1174: */
1175: while ((entry != &map->header) && (entry->start < end)) {
1176:
1177: if (entry->wired_count == 0) {
1178: vm_map_unlock(map);
1179: return(KERN_INVALID_ARGUMENT);
1180: }
1181: entry = entry->next;
1182: }
1183:
1184: /*
1185: * Now decrement the wiring count for each region.
1186: * If a region becomes completely unwired,
1187: * unwire its physical pages and mappings.
1188: */
1189: lock_set_recursive(&map->lock);
1190:
1191: entry = temp_entry;
1192: while ((entry != &map->header) && (entry->start < end)) {
1193: vm_map_clip_end(map, entry, end);
1194:
1195: entry->wired_count--;
1196: if (entry->wired_count == 0)
1197: vm_fault_unwire(map, entry->start, entry->end);
1198:
1199: entry = entry->next;
1200: }
1201: lock_clear_recursive(&map->lock);
1202: }
1203:
1204: else {
1205: /*
1206: * Wiring. We must do this in two passes:
1207: *
1208: * 1. Holding the write lock, we increment the
1209: * wiring count. For any area that is not already
1210: * wired, we create any shadow objects that need
1211: * to be created.
1212: *
1213: * 2. We downgrade to a read lock, and call
1214: * vm_fault_wire to fault in the pages for any
1215: * newly wired area (wired_count is 1).
1216: *
1217: * Downgrading to a read lock for vm_fault_wire avoids
1218: * a possible deadlock with another thread that may have
1219: * faulted on one of the pages to be wired (it would mark
1220: * the page busy, blocking us, then in turn block on the
1221: * map lock that we hold). Because of problems in the
1222: * recursive lock package, we cannot upgrade to a write
1223: * lock in vm_map_lookup. Thus, any actions that require
1224: * the write lock must be done beforehand. Because we
1225: * keep the read lock on the map, the copy-on-write status
1226: * of the entries we modify here cannot change.
1227: */
1228:
1229: /*
1230: * Pass 1.
1231: */
1232: entry = temp_entry;
1233: while ((entry != &map->header) && (entry->start < end)) {
1234: vm_map_clip_end(map, entry, end);
1235:
1236: entry->wired_count++;
1237: if (entry->wired_count == 1) {
1238:
1239: /*
1240: * Perform actions of vm_map_lookup that need
1241: * the write lock on the map: create a shadow
1242: * object for a copy-on-write region, or an
1243: * object for a zero-fill region.
1244: *
1245: * We don't have to do this for entries that
1246: * point to sharing maps, because we won't hold
1247: * the lock on the sharing map.
1248: */
1249: if (!entry->is_a_map) {
1250: if (entry->needs_copy &&
1251: ((entry->protection & VM_PROT_WRITE) != 0)) {
1252:
1253: vm_object_shadow(&entry->object.vm_object,
1254: &entry->offset,
1255: (vm_size_t)(entry->end
1256: - entry->start));
1257: entry->needs_copy = FALSE;
1258: }
1259: else if (entry->object.vm_object == NULL) {
1260: entry->object.vm_object =
1261: vm_object_allocate((vm_size_t)(entry->end
1262: - entry->start));
1263: entry->offset = (vm_offset_t)0;
1264: }
1265: }
1266: }
1267:
1268: entry = entry->next;
1269: }
1270:
1271: /*
1272: * Pass 2.
1273: */
1274:
1275: /*
1276: * HACK HACK HACK HACK
1277: *
1278: * If we are wiring in the kernel map or a submap of it,
1279: * unlock the map to avoid deadlocks. We trust that the
1280: * kernel threads are well-behaved, and therefore will
1281: * not do anything destructive to this region of the map
1282: * while we have it unlocked. We cannot trust user threads
1283: * to do the same.
1284: *
1285: * HACK HACK HACK HACK
1286: */
1287: if (vm_map_pmap(map) == kernel_pmap) {
1288: vm_map_unlock(map); /* trust me ... */
1289: }
1290: else {
1291: lock_set_recursive(&map->lock);
1292: lock_write_to_read(&map->lock);
1293: }
1294:
1295: entry = temp_entry;
1296: while (entry != &map->header && entry->start < end) {
1.1.1.4 ! root 1297: if (entry->wired_count == 1) {
! 1298: vm_fault_wire(map, entry->start, entry->end);
1.1 root 1299: }
1300: entry = entry->next;
1301: }
1302:
1303: if (vm_map_pmap(map) == kernel_pmap) {
1304: vm_map_lock(map);
1305: }
1306: else {
1307: lock_clear_recursive(&map->lock);
1308: }
1309: }
1310:
1311: vm_map_unlock(map);
1312:
1313: return(KERN_SUCCESS);
1314: }
1315:
1316: /*
1317: * vm_map_entry_unwire: [ internal use only ]
1318: *
1319: * Make the region specified by this entry pageable.
1320: *
1321: * The map in question should be locked.
1322: * [This is the reason for this routine's existence.]
1323: */
1.1.1.4 ! root 1324: void
! 1325: vm_map_entry_unwire(map, entry)
1.1 root 1326: vm_map_t map;
1327: register vm_map_entry_t entry;
1328: {
1329: vm_fault_unwire(map, entry->start, entry->end);
1330: entry->wired_count = 0;
1331: }
1332:
1333: /*
1334: * vm_map_entry_delete: [ internal use only ]
1335: *
1336: * Deallocate the given entry from the target map.
1337: */
1.1.1.4 ! root 1338: void
! 1339: vm_map_entry_delete(map, entry)
1.1 root 1340: register vm_map_t map;
1341: register vm_map_entry_t entry;
1342: {
1343: if (entry->wired_count != 0)
1344: vm_map_entry_unwire(map, entry);
1345:
1346: vm_map_entry_unlink(map, entry);
1347: map->size -= entry->end - entry->start;
1348:
1349: if (entry->is_a_map || entry->is_sub_map)
1350: vm_map_deallocate(entry->object.share_map);
1351: else
1352: vm_object_deallocate(entry->object.vm_object);
1353:
1354: vm_map_entry_dispose(map, entry);
1355: }
1356:
1357: /*
1358: * vm_map_delete: [ internal use only ]
1359: *
1360: * Deallocates the given address range from the target
1361: * map.
1362: *
1363: * When called with a sharing map, removes pages from
1364: * that region from all physical maps.
1365: */
1.1.1.4 ! root 1366: int
1.1 root 1367: vm_map_delete(map, start, end)
1368: register vm_map_t map;
1369: vm_offset_t start;
1370: register vm_offset_t end;
1371: {
1372: register vm_map_entry_t entry;
1373: vm_map_entry_t first_entry;
1374:
1375: /*
1376: * Find the start of the region, and clip it
1377: */
1378:
1379: if (!vm_map_lookup_entry(map, start, &first_entry))
1380: entry = first_entry->next;
1381: else {
1382: entry = first_entry;
1383: vm_map_clip_start(map, entry, start);
1384:
1385: /*
1386: * Fix the lookup hint now, rather than each
1387: * time though the loop.
1388: */
1389:
1390: SAVE_HINT(map, entry->prev);
1391: }
1392:
1393: /*
1394: * Save the free space hint
1395: */
1396:
1397: if (map->first_free->start >= start)
1398: map->first_free = entry->prev;
1399:
1400: /*
1401: * Step through all entries in this region
1402: */
1403:
1404: while ((entry != &map->header) && (entry->start < end)) {
1405: vm_map_entry_t next;
1406: register vm_offset_t s, e;
1407: register vm_object_t object;
1408:
1409: vm_map_clip_end(map, entry, end);
1410:
1411: next = entry->next;
1412: s = entry->start;
1413: e = entry->end;
1414:
1415: /*
1416: * Unwire before removing addresses from the pmap;
1417: * otherwise, unwiring will put the entries back in
1418: * the pmap.
1419: */
1420:
1421: object = entry->object.vm_object;
1422: if (entry->wired_count != 0)
1423: vm_map_entry_unwire(map, entry);
1424:
1425: /*
1426: * If this is a sharing map, we must remove
1427: * *all* references to this data, since we can't
1428: * find all of the physical maps which are sharing
1429: * it.
1430: */
1431:
1432: if (object == kernel_object || object == kmem_object)
1433: vm_object_page_remove(object, entry->offset,
1434: entry->offset + (e - s));
1435: else if (!map->is_main_map)
1436: vm_object_pmap_remove(object,
1437: entry->offset,
1438: entry->offset + (e - s));
1439: else
1440: pmap_remove(map->pmap, s, e);
1441:
1442: /*
1443: * Delete the entry (which may delete the object)
1444: * only after removing all pmap entries pointing
1445: * to its pages. (Otherwise, its page frames may
1446: * be reallocated, and any modify bits will be
1447: * set in the wrong object!)
1448: */
1449:
1450: vm_map_entry_delete(map, entry);
1451: entry = next;
1452: }
1453: return(KERN_SUCCESS);
1454: }
1455:
1456: /*
1457: * vm_map_remove:
1458: *
1459: * Remove the given address range from the target map.
1460: * This is the exported form of vm_map_delete.
1461: */
1.1.1.4 ! root 1462: int
1.1 root 1463: vm_map_remove(map, start, end)
1464: register vm_map_t map;
1465: register vm_offset_t start;
1466: register vm_offset_t end;
1467: {
1468: register int result;
1469:
1470: vm_map_lock(map);
1471: VM_MAP_RANGE_CHECK(map, start, end);
1472: result = vm_map_delete(map, start, end);
1473: vm_map_unlock(map);
1474:
1475: return(result);
1476: }
1477:
1478: /*
1479: * vm_map_check_protection:
1480: *
1481: * Assert that the target map allows the specified
1482: * privilege on the entire address region given.
1483: * The entire region must be allocated.
1484: */
1485: boolean_t vm_map_check_protection(map, start, end, protection)
1486: register vm_map_t map;
1487: register vm_offset_t start;
1488: register vm_offset_t end;
1489: register vm_prot_t protection;
1490: {
1491: register vm_map_entry_t entry;
1492: vm_map_entry_t tmp_entry;
1493:
1494: if (!vm_map_lookup_entry(map, start, &tmp_entry)) {
1495: return(FALSE);
1496: }
1497:
1498: entry = tmp_entry;
1499:
1500: while (start < end) {
1501: if (entry == &map->header) {
1502: return(FALSE);
1503: }
1504:
1505: /*
1506: * No holes allowed!
1507: */
1508:
1509: if (start < entry->start) {
1510: return(FALSE);
1511: }
1512:
1513: /*
1514: * Check protection associated with entry.
1515: */
1516:
1517: if ((entry->protection & protection) != protection) {
1518: return(FALSE);
1519: }
1520:
1521: /* go to next entry */
1522:
1523: start = entry->end;
1524: entry = entry->next;
1525: }
1526: return(TRUE);
1527: }
1528:
1529: /*
1530: * vm_map_copy_entry:
1531: *
1532: * Copies the contents of the source entry to the destination
1533: * entry. The entries *must* be aligned properly.
1534: */
1.1.1.4 ! root 1535: void
! 1536: vm_map_copy_entry(src_map, dst_map, src_entry, dst_entry)
1.1 root 1537: vm_map_t src_map, dst_map;
1538: register vm_map_entry_t src_entry, dst_entry;
1539: {
1540: vm_object_t temp_object;
1541:
1542: if (src_entry->is_sub_map || dst_entry->is_sub_map)
1543: return;
1544:
1545: if (dst_entry->object.vm_object != NULL &&
1546: !dst_entry->object.vm_object->internal)
1547: printf("vm_map_copy_entry: copying over permanent data!\n");
1548:
1549: /*
1550: * If our destination map was wired down,
1551: * unwire it now.
1552: */
1553:
1554: if (dst_entry->wired_count != 0)
1555: vm_map_entry_unwire(dst_map, dst_entry);
1556:
1557: /*
1558: * If we're dealing with a sharing map, we
1559: * must remove the destination pages from
1560: * all maps (since we cannot know which maps
1561: * this sharing map belongs in).
1562: */
1563:
1564: if (dst_map->is_main_map)
1565: pmap_remove(dst_map->pmap, dst_entry->start, dst_entry->end);
1566: else
1567: vm_object_pmap_remove(dst_entry->object.vm_object,
1568: dst_entry->offset,
1569: dst_entry->offset +
1570: (dst_entry->end - dst_entry->start));
1571:
1572: if (src_entry->wired_count == 0) {
1573:
1574: boolean_t src_needs_copy;
1575:
1576: /*
1577: * If the source entry is marked needs_copy,
1578: * it is already write-protected.
1579: */
1580: if (!src_entry->needs_copy) {
1581:
1582: boolean_t su;
1583:
1584: /*
1585: * If the source entry has only one mapping,
1586: * we can just protect the virtual address
1587: * range.
1588: */
1589: if (!(su = src_map->is_main_map)) {
1590: simple_lock(&src_map->ref_lock);
1591: su = (src_map->ref_count == 1);
1592: simple_unlock(&src_map->ref_lock);
1593: }
1594:
1595: if (su) {
1596: pmap_protect(src_map->pmap,
1597: src_entry->start,
1598: src_entry->end,
1599: src_entry->protection & ~VM_PROT_WRITE);
1600: }
1601: else {
1602: vm_object_pmap_copy(src_entry->object.vm_object,
1603: src_entry->offset,
1604: src_entry->offset + (src_entry->end
1605: -src_entry->start));
1606: }
1607: }
1608:
1609: /*
1610: * Make a copy of the object.
1611: */
1612: temp_object = dst_entry->object.vm_object;
1613: vm_object_copy(src_entry->object.vm_object,
1614: src_entry->offset,
1615: (vm_size_t)(src_entry->end -
1616: src_entry->start),
1617: &dst_entry->object.vm_object,
1618: &dst_entry->offset,
1619: &src_needs_copy);
1620: /*
1621: * If we didn't get a copy-object now, mark the
1622: * source map entry so that a shadow will be created
1623: * to hold its changed pages.
1624: */
1625: if (src_needs_copy)
1626: src_entry->needs_copy = TRUE;
1627:
1628: /*
1629: * The destination always needs to have a shadow
1630: * created.
1631: */
1632: dst_entry->needs_copy = TRUE;
1633:
1634: /*
1635: * Mark the entries copy-on-write, so that write-enabling
1636: * the entry won't make copy-on-write pages writable.
1637: */
1638: src_entry->copy_on_write = TRUE;
1639: dst_entry->copy_on_write = TRUE;
1640: /*
1641: * Get rid of the old object.
1642: */
1643: vm_object_deallocate(temp_object);
1644:
1645: pmap_copy(dst_map->pmap, src_map->pmap, dst_entry->start,
1646: dst_entry->end - dst_entry->start, src_entry->start);
1647: }
1648: else {
1649: /*
1650: * Of course, wired down pages can't be set copy-on-write.
1651: * Cause wired pages to be copied into the new
1652: * map by simulating faults (the new pages are
1653: * pageable)
1654: */
1655: vm_fault_copy_entry(dst_map, src_map, dst_entry, src_entry);
1656: }
1657: }
1658:
1659: /*
1660: * vm_map_copy:
1661: *
1662: * Perform a virtual memory copy from the source
1663: * address map/range to the destination map/range.
1664: *
1665: * If src_destroy or dst_alloc is requested,
1666: * the source and destination regions should be
1667: * disjoint, not only in the top-level map, but
1668: * in the sharing maps as well. [The best way
1669: * to guarantee this is to use a new intermediate
1670: * map to make copies. This also reduces map
1671: * fragmentation.]
1672: */
1.1.1.4 ! root 1673: int
1.1 root 1674: vm_map_copy(dst_map, src_map,
1675: dst_addr, len, src_addr,
1676: dst_alloc, src_destroy)
1677: vm_map_t dst_map;
1678: vm_map_t src_map;
1679: vm_offset_t dst_addr;
1680: vm_size_t len;
1681: vm_offset_t src_addr;
1682: boolean_t dst_alloc;
1683: boolean_t src_destroy;
1684: {
1685: register
1686: vm_map_entry_t src_entry;
1687: register
1688: vm_map_entry_t dst_entry;
1689: vm_map_entry_t tmp_entry;
1690: vm_offset_t src_start;
1691: vm_offset_t src_end;
1692: vm_offset_t dst_start;
1693: vm_offset_t dst_end;
1694: vm_offset_t src_clip;
1695: vm_offset_t dst_clip;
1696: int result;
1697: boolean_t old_src_destroy;
1698:
1699: /*
1700: * XXX While we figure out why src_destroy screws up,
1701: * we'll do it by explicitly vm_map_delete'ing at the end.
1702: */
1703:
1704: old_src_destroy = src_destroy;
1705: src_destroy = FALSE;
1706:
1707: /*
1708: * Compute start and end of region in both maps
1709: */
1710:
1711: src_start = src_addr;
1712: src_end = src_start + len;
1713: dst_start = dst_addr;
1714: dst_end = dst_start + len;
1715:
1716: /*
1717: * Check that the region can exist in both source
1718: * and destination.
1719: */
1720:
1721: if ((dst_end < dst_start) || (src_end < src_start))
1722: return(KERN_NO_SPACE);
1723:
1724: /*
1725: * Lock the maps in question -- we avoid deadlock
1726: * by ordering lock acquisition by map value
1727: */
1728:
1729: if (src_map == dst_map) {
1730: vm_map_lock(src_map);
1731: }
1732: else if ((int) src_map < (int) dst_map) {
1733: vm_map_lock(src_map);
1734: vm_map_lock(dst_map);
1735: } else {
1736: vm_map_lock(dst_map);
1737: vm_map_lock(src_map);
1738: }
1739:
1740: result = KERN_SUCCESS;
1741:
1742: /*
1743: * Check protections... source must be completely readable and
1744: * destination must be completely writable. [Note that if we're
1745: * allocating the destination region, we don't have to worry
1746: * about protection, but instead about whether the region
1747: * exists.]
1748: */
1749:
1750: if (src_map->is_main_map && dst_map->is_main_map) {
1751: if (!vm_map_check_protection(src_map, src_start, src_end,
1752: VM_PROT_READ)) {
1753: result = KERN_PROTECTION_FAILURE;
1754: goto Return;
1755: }
1756:
1757: if (dst_alloc) {
1758: /* XXX Consider making this a vm_map_find instead */
1759: if ((result = vm_map_insert(dst_map, NULL,
1760: (vm_offset_t) 0, dst_start, dst_end)) != KERN_SUCCESS)
1761: goto Return;
1762: }
1763: else if (!vm_map_check_protection(dst_map, dst_start, dst_end,
1764: VM_PROT_WRITE)) {
1765: result = KERN_PROTECTION_FAILURE;
1766: goto Return;
1767: }
1768: }
1769:
1770: /*
1771: * Find the start entries and clip.
1772: *
1773: * Note that checking protection asserts that the
1774: * lookup cannot fail.
1775: *
1776: * Also note that we wait to do the second lookup
1777: * until we have done the first clip, as the clip
1778: * may affect which entry we get!
1779: */
1780:
1781: (void) vm_map_lookup_entry(src_map, src_addr, &tmp_entry);
1782: src_entry = tmp_entry;
1783: vm_map_clip_start(src_map, src_entry, src_start);
1784:
1785: (void) vm_map_lookup_entry(dst_map, dst_addr, &tmp_entry);
1786: dst_entry = tmp_entry;
1787: vm_map_clip_start(dst_map, dst_entry, dst_start);
1788:
1789: /*
1790: * If both source and destination entries are the same,
1791: * retry the first lookup, as it may have changed.
1792: */
1793:
1794: if (src_entry == dst_entry) {
1795: (void) vm_map_lookup_entry(src_map, src_addr, &tmp_entry);
1796: src_entry = tmp_entry;
1797: }
1798:
1799: /*
1800: * If source and destination entries are still the same,
1801: * a null copy is being performed.
1802: */
1803:
1804: if (src_entry == dst_entry)
1805: goto Return;
1806:
1807: /*
1808: * Go through entries until we get to the end of the
1809: * region.
1810: */
1811:
1812: while (src_start < src_end) {
1813: /*
1814: * Clip the entries to the endpoint of the entire region.
1815: */
1816:
1817: vm_map_clip_end(src_map, src_entry, src_end);
1818: vm_map_clip_end(dst_map, dst_entry, dst_end);
1819:
1820: /*
1821: * Clip each entry to the endpoint of the other entry.
1822: */
1823:
1824: src_clip = src_entry->start + (dst_entry->end - dst_entry->start);
1825: vm_map_clip_end(src_map, src_entry, src_clip);
1826:
1827: dst_clip = dst_entry->start + (src_entry->end - src_entry->start);
1828: vm_map_clip_end(dst_map, dst_entry, dst_clip);
1829:
1830: /*
1831: * Both entries now match in size and relative endpoints.
1832: *
1833: * If both entries refer to a VM object, we can
1834: * deal with them now.
1835: */
1836:
1837: if (!src_entry->is_a_map && !dst_entry->is_a_map) {
1838: vm_map_copy_entry(src_map, dst_map, src_entry,
1839: dst_entry);
1840: }
1841: else {
1842: register vm_map_t new_dst_map;
1843: vm_offset_t new_dst_start;
1844: vm_size_t new_size;
1845: vm_map_t new_src_map;
1846: vm_offset_t new_src_start;
1847:
1848: /*
1849: * We have to follow at least one sharing map.
1850: */
1851:
1852: new_size = (dst_entry->end - dst_entry->start);
1853:
1854: if (src_entry->is_a_map) {
1855: new_src_map = src_entry->object.share_map;
1856: new_src_start = src_entry->offset;
1857: }
1858: else {
1859: new_src_map = src_map;
1860: new_src_start = src_entry->start;
1861: lock_set_recursive(&src_map->lock);
1862: }
1863:
1864: if (dst_entry->is_a_map) {
1865: vm_offset_t new_dst_end;
1866:
1867: new_dst_map = dst_entry->object.share_map;
1868: new_dst_start = dst_entry->offset;
1869:
1870: /*
1871: * Since the destination sharing entries
1872: * will be merely deallocated, we can
1873: * do that now, and replace the region
1874: * with a null object. [This prevents
1875: * splitting the source map to match
1876: * the form of the destination map.]
1877: * Note that we can only do so if the
1878: * source and destination do not overlap.
1879: */
1880:
1881: new_dst_end = new_dst_start + new_size;
1882:
1883: if (new_dst_map != new_src_map) {
1884: vm_map_lock(new_dst_map);
1885: (void) vm_map_delete(new_dst_map,
1886: new_dst_start,
1887: new_dst_end);
1888: (void) vm_map_insert(new_dst_map,
1889: NULL,
1890: (vm_offset_t) 0,
1891: new_dst_start,
1892: new_dst_end);
1893: vm_map_unlock(new_dst_map);
1894: }
1895: }
1896: else {
1897: new_dst_map = dst_map;
1898: new_dst_start = dst_entry->start;
1899: lock_set_recursive(&dst_map->lock);
1900: }
1901:
1902: /*
1903: * Recursively copy the sharing map.
1904: */
1905:
1906: (void) vm_map_copy(new_dst_map, new_src_map,
1907: new_dst_start, new_size, new_src_start,
1908: FALSE, FALSE);
1909:
1910: if (dst_map == new_dst_map)
1911: lock_clear_recursive(&dst_map->lock);
1912: if (src_map == new_src_map)
1913: lock_clear_recursive(&src_map->lock);
1914: }
1915:
1916: /*
1917: * Update variables for next pass through the loop.
1918: */
1919:
1920: src_start = src_entry->end;
1921: src_entry = src_entry->next;
1922: dst_start = dst_entry->end;
1923: dst_entry = dst_entry->next;
1924:
1925: /*
1926: * If the source is to be destroyed, here is the
1927: * place to do it.
1928: */
1929:
1930: if (src_destroy && src_map->is_main_map &&
1931: dst_map->is_main_map)
1932: vm_map_entry_delete(src_map, src_entry->prev);
1933: }
1934:
1935: /*
1936: * Update the physical maps as appropriate
1937: */
1938:
1939: if (src_map->is_main_map && dst_map->is_main_map) {
1940: if (src_destroy)
1941: pmap_remove(src_map->pmap, src_addr, src_addr + len);
1942: }
1943:
1944: /*
1945: * Unlock the maps
1946: */
1947:
1948: Return: ;
1949:
1950: if (old_src_destroy)
1951: vm_map_delete(src_map, src_addr, src_addr + len);
1952:
1953: vm_map_unlock(src_map);
1954: if (src_map != dst_map)
1955: vm_map_unlock(dst_map);
1956:
1957: return(result);
1958: }
1959:
1960: /*
1961: * vmspace_fork:
1962: * Create a new process vmspace structure and vm_map
1963: * based on those of an existing process. The new map
1964: * is based on the old map, according to the inheritance
1965: * values on the regions in that map.
1966: *
1967: * The source map must not be locked.
1968: */
1969: struct vmspace *
1970: vmspace_fork(vm1)
1971: register struct vmspace *vm1;
1972: {
1973: register struct vmspace *vm2;
1974: vm_map_t old_map = &vm1->vm_map;
1975: vm_map_t new_map;
1976: vm_map_entry_t old_entry;
1977: vm_map_entry_t new_entry;
1978: pmap_t new_pmap;
1979:
1980: vm_map_lock(old_map);
1981:
1982: vm2 = vmspace_alloc(old_map->min_offset, old_map->max_offset,
1983: old_map->entries_pageable);
1984: bcopy(&vm1->vm_startcopy, &vm2->vm_startcopy,
1985: (caddr_t) (vm1 + 1) - (caddr_t) &vm1->vm_startcopy);
1986: new_pmap = &vm2->vm_pmap; /* XXX */
1987: new_map = &vm2->vm_map; /* XXX */
1988:
1989: old_entry = old_map->header.next;
1990:
1991: while (old_entry != &old_map->header) {
1992: if (old_entry->is_sub_map)
1993: panic("vm_map_fork: encountered a submap");
1994:
1995: switch (old_entry->inheritance) {
1996: case VM_INHERIT_NONE:
1997: break;
1998:
1999: case VM_INHERIT_SHARE:
2000: /*
2001: * If we don't already have a sharing map:
2002: */
2003:
2004: if (!old_entry->is_a_map) {
2005: vm_map_t new_share_map;
2006: vm_map_entry_t new_share_entry;
2007:
2008: /*
2009: * Create a new sharing map
2010: */
2011:
2012: new_share_map = vm_map_create(NULL,
2013: old_entry->start,
2014: old_entry->end,
2015: TRUE);
2016: new_share_map->is_main_map = FALSE;
2017:
2018: /*
2019: * Create the only sharing entry from the
2020: * old task map entry.
2021: */
2022:
2023: new_share_entry =
2024: vm_map_entry_create(new_share_map);
2025: *new_share_entry = *old_entry;
2026:
2027: /*
2028: * Insert the entry into the new sharing
2029: * map
2030: */
2031:
2032: vm_map_entry_link(new_share_map,
2033: new_share_map->header.prev,
2034: new_share_entry);
2035:
2036: /*
2037: * Fix up the task map entry to refer
2038: * to the sharing map now.
2039: */
2040:
2041: old_entry->is_a_map = TRUE;
2042: old_entry->object.share_map = new_share_map;
2043: old_entry->offset = old_entry->start;
2044: }
2045:
2046: /*
2047: * Clone the entry, referencing the sharing map.
2048: */
2049:
2050: new_entry = vm_map_entry_create(new_map);
2051: *new_entry = *old_entry;
2052: vm_map_reference(new_entry->object.share_map);
2053:
2054: /*
2055: * Insert the entry into the new map -- we
2056: * know we're inserting at the end of the new
2057: * map.
2058: */
2059:
2060: vm_map_entry_link(new_map, new_map->header.prev,
2061: new_entry);
2062:
2063: /*
2064: * Update the physical map
2065: */
2066:
2067: pmap_copy(new_map->pmap, old_map->pmap,
2068: new_entry->start,
2069: (old_entry->end - old_entry->start),
2070: old_entry->start);
2071: break;
2072:
2073: case VM_INHERIT_COPY:
2074: /*
2075: * Clone the entry and link into the map.
2076: */
2077:
2078: new_entry = vm_map_entry_create(new_map);
2079: *new_entry = *old_entry;
2080: new_entry->wired_count = 0;
2081: new_entry->object.vm_object = NULL;
2082: new_entry->is_a_map = FALSE;
2083: vm_map_entry_link(new_map, new_map->header.prev,
2084: new_entry);
2085: if (old_entry->is_a_map) {
2086: int check;
2087:
2088: check = vm_map_copy(new_map,
2089: old_entry->object.share_map,
2090: new_entry->start,
2091: (vm_size_t)(new_entry->end -
2092: new_entry->start),
2093: old_entry->offset,
2094: FALSE, FALSE);
2095: if (check != KERN_SUCCESS)
2096: printf("vm_map_fork: copy in share_map region failed\n");
2097: }
2098: else {
2099: vm_map_copy_entry(old_map, new_map, old_entry,
2100: new_entry);
2101: }
2102: break;
2103: }
2104: old_entry = old_entry->next;
2105: }
2106:
2107: new_map->size = old_map->size;
2108: vm_map_unlock(old_map);
2109:
2110: return(vm2);
2111: }
2112:
2113: /*
2114: * vm_map_lookup:
2115: *
2116: * Finds the VM object, offset, and
2117: * protection for a given virtual address in the
2118: * specified map, assuming a page fault of the
2119: * type specified.
2120: *
2121: * Leaves the map in question locked for read; return
2122: * values are guaranteed until a vm_map_lookup_done
2123: * call is performed. Note that the map argument
2124: * is in/out; the returned map must be used in
2125: * the call to vm_map_lookup_done.
2126: *
2127: * A handle (out_entry) is returned for use in
2128: * vm_map_lookup_done, to make that fast.
2129: *
2130: * If a lookup is requested with "write protection"
2131: * specified, the map may be changed to perform virtual
2132: * copying operations, although the data referenced will
2133: * remain the same.
2134: */
2135: vm_map_lookup(var_map, vaddr, fault_type, out_entry,
2136: object, offset, out_prot, wired, single_use)
2137: vm_map_t *var_map; /* IN/OUT */
2138: register vm_offset_t vaddr;
2139: register vm_prot_t fault_type;
2140:
2141: vm_map_entry_t *out_entry; /* OUT */
2142: vm_object_t *object; /* OUT */
2143: vm_offset_t *offset; /* OUT */
2144: vm_prot_t *out_prot; /* OUT */
2145: boolean_t *wired; /* OUT */
2146: boolean_t *single_use; /* OUT */
2147: {
2148: vm_map_t share_map;
2149: vm_offset_t share_offset;
2150: register vm_map_entry_t entry;
2151: register vm_map_t map = *var_map;
2152: register vm_prot_t prot;
2153: register boolean_t su;
2154:
2155: RetryLookup: ;
2156:
2157: /*
2158: * Lookup the faulting address.
2159: */
2160:
2161: vm_map_lock_read(map);
2162:
2163: #define RETURN(why) \
2164: { \
2165: vm_map_unlock_read(map); \
2166: return(why); \
2167: }
2168:
2169: /*
2170: * If the map has an interesting hint, try it before calling
2171: * full blown lookup routine.
2172: */
2173:
2174: simple_lock(&map->hint_lock);
2175: entry = map->hint;
2176: simple_unlock(&map->hint_lock);
2177:
2178: *out_entry = entry;
2179:
2180: if ((entry == &map->header) ||
2181: (vaddr < entry->start) || (vaddr >= entry->end)) {
2182: vm_map_entry_t tmp_entry;
2183:
2184: /*
2185: * Entry was either not a valid hint, or the vaddr
2186: * was not contained in the entry, so do a full lookup.
2187: */
2188: if (!vm_map_lookup_entry(map, vaddr, &tmp_entry))
2189: RETURN(KERN_INVALID_ADDRESS);
2190:
2191: entry = tmp_entry;
2192: *out_entry = entry;
2193: }
2194:
2195: /*
2196: * Handle submaps.
2197: */
2198:
2199: if (entry->is_sub_map) {
2200: vm_map_t old_map = map;
2201:
2202: *var_map = map = entry->object.sub_map;
2203: vm_map_unlock_read(old_map);
2204: goto RetryLookup;
2205: }
2206:
2207: /*
2208: * Check whether this task is allowed to have
2209: * this page.
2210: */
2211:
2212: prot = entry->protection;
2213: if ((fault_type & (prot)) != fault_type)
2214: RETURN(KERN_PROTECTION_FAILURE);
2215:
2216: /*
2217: * If this page is not pageable, we have to get
2218: * it for all possible accesses.
2219: */
2220:
2221: if (*wired = (entry->wired_count != 0))
2222: prot = fault_type = entry->protection;
2223:
2224: /*
2225: * If we don't already have a VM object, track
2226: * it down.
2227: */
2228:
2229: if (su = !entry->is_a_map) {
2230: share_map = map;
2231: share_offset = vaddr;
2232: }
2233: else {
2234: vm_map_entry_t share_entry;
2235:
2236: /*
2237: * Compute the sharing map, and offset into it.
2238: */
2239:
2240: share_map = entry->object.share_map;
2241: share_offset = (vaddr - entry->start) + entry->offset;
2242:
2243: /*
2244: * Look for the backing store object and offset
2245: */
2246:
2247: vm_map_lock_read(share_map);
2248:
2249: if (!vm_map_lookup_entry(share_map, share_offset,
2250: &share_entry)) {
2251: vm_map_unlock_read(share_map);
2252: RETURN(KERN_INVALID_ADDRESS);
2253: }
2254: entry = share_entry;
2255: }
2256:
2257: /*
2258: * If the entry was copy-on-write, we either ...
2259: */
2260:
2261: if (entry->needs_copy) {
2262: /*
2263: * If we want to write the page, we may as well
2264: * handle that now since we've got the sharing
2265: * map locked.
2266: *
2267: * If we don't need to write the page, we just
2268: * demote the permissions allowed.
2269: */
2270:
2271: if (fault_type & VM_PROT_WRITE) {
2272: /*
2273: * Make a new object, and place it in the
2274: * object chain. Note that no new references
2275: * have appeared -- one just moved from the
2276: * share map to the new object.
2277: */
2278:
2279: if (lock_read_to_write(&share_map->lock)) {
2280: if (share_map != map)
2281: vm_map_unlock_read(map);
2282: goto RetryLookup;
2283: }
2284:
2285: vm_object_shadow(
2286: &entry->object.vm_object,
2287: &entry->offset,
2288: (vm_size_t) (entry->end - entry->start));
2289:
2290: entry->needs_copy = FALSE;
2291:
2292: lock_write_to_read(&share_map->lock);
2293: }
2294: else {
2295: /*
2296: * We're attempting to read a copy-on-write
2297: * page -- don't allow writes.
2298: */
2299:
2300: prot &= (~VM_PROT_WRITE);
2301: }
2302: }
2303:
2304: /*
2305: * Create an object if necessary.
2306: */
2307: if (entry->object.vm_object == NULL) {
2308:
2309: if (lock_read_to_write(&share_map->lock)) {
2310: if (share_map != map)
2311: vm_map_unlock_read(map);
2312: goto RetryLookup;
2313: }
2314:
2315: entry->object.vm_object = vm_object_allocate(
2316: (vm_size_t)(entry->end - entry->start));
2317: entry->offset = 0;
2318: lock_write_to_read(&share_map->lock);
2319: }
2320:
2321: /*
2322: * Return the object/offset from this entry. If the entry
2323: * was copy-on-write or empty, it has been fixed up.
2324: */
2325:
2326: *offset = (share_offset - entry->start) + entry->offset;
2327: *object = entry->object.vm_object;
2328:
2329: /*
2330: * Return whether this is the only map sharing this data.
2331: */
2332:
2333: if (!su) {
2334: simple_lock(&share_map->ref_lock);
2335: su = (share_map->ref_count == 1);
2336: simple_unlock(&share_map->ref_lock);
2337: }
2338:
2339: *out_prot = prot;
2340: *single_use = su;
2341:
2342: return(KERN_SUCCESS);
2343:
2344: #undef RETURN
2345: }
2346:
2347: /*
2348: * vm_map_lookup_done:
2349: *
2350: * Releases locks acquired by a vm_map_lookup
2351: * (according to the handle returned by that lookup).
2352: */
2353:
1.1.1.4 ! root 2354: void
! 2355: vm_map_lookup_done(map, entry)
1.1 root 2356: register vm_map_t map;
2357: vm_map_entry_t entry;
2358: {
2359: /*
2360: * If this entry references a map, unlock it first.
2361: */
2362:
2363: if (entry->is_a_map)
2364: vm_map_unlock_read(entry->object.share_map);
2365:
2366: /*
2367: * Unlock the main-level map
2368: */
2369:
2370: vm_map_unlock_read(map);
2371: }
2372:
2373: /*
2374: * Routine: vm_map_simplify
2375: * Purpose:
2376: * Attempt to simplify the map representation in
2377: * the vicinity of the given starting address.
2378: * Note:
2379: * This routine is intended primarily to keep the
2380: * kernel maps more compact -- they generally don't
2381: * benefit from the "expand a map entry" technology
2382: * at allocation time because the adjacent entry
2383: * is often wired down.
2384: */
1.1.1.4 ! root 2385: void
! 2386: vm_map_simplify(map, start)
1.1 root 2387: vm_map_t map;
2388: vm_offset_t start;
2389: {
2390: vm_map_entry_t this_entry;
2391: vm_map_entry_t prev_entry;
2392:
2393: vm_map_lock(map);
2394: if (
2395: (vm_map_lookup_entry(map, start, &this_entry)) &&
2396: ((prev_entry = this_entry->prev) != &map->header) &&
2397:
2398: (prev_entry->end == start) &&
2399: (map->is_main_map) &&
2400:
2401: (prev_entry->is_a_map == FALSE) &&
2402: (prev_entry->is_sub_map == FALSE) &&
2403:
2404: (this_entry->is_a_map == FALSE) &&
2405: (this_entry->is_sub_map == FALSE) &&
2406:
2407: (prev_entry->inheritance == this_entry->inheritance) &&
2408: (prev_entry->protection == this_entry->protection) &&
2409: (prev_entry->max_protection == this_entry->max_protection) &&
2410: (prev_entry->wired_count == this_entry->wired_count) &&
2411:
2412: (prev_entry->copy_on_write == this_entry->copy_on_write) &&
2413: (prev_entry->needs_copy == this_entry->needs_copy) &&
2414:
2415: (prev_entry->object.vm_object == this_entry->object.vm_object) &&
2416: ((prev_entry->offset + (prev_entry->end - prev_entry->start))
2417: == this_entry->offset)
2418: ) {
2419: if (map->first_free == this_entry)
2420: map->first_free = prev_entry;
2421:
2422: SAVE_HINT(map, prev_entry);
2423: vm_map_entry_unlink(map, this_entry);
2424: prev_entry->end = this_entry->end;
2425: vm_object_deallocate(this_entry->object.vm_object);
2426: vm_map_entry_dispose(map, this_entry);
2427: }
2428: vm_map_unlock(map);
2429: }
2430:
2431: /*
2432: * vm_map_print: [ debug ]
2433: */
1.1.1.4 ! root 2434: void
! 2435: vm_map_print(map, full)
1.1 root 2436: register vm_map_t map;
2437: boolean_t full;
2438: {
2439: register vm_map_entry_t entry;
2440: extern int indent;
2441:
2442: iprintf("%s map 0x%x: pmap=0x%x,ref=%d,nentries=%d,version=%d\n",
2443: (map->is_main_map ? "Task" : "Share"),
2444: (int) map, (int) (map->pmap), map->ref_count, map->nentries,
2445: map->timestamp);
2446:
2447: if (!full && indent)
2448: return;
2449:
2450: indent += 2;
2451: for (entry = map->header.next; entry != &map->header;
2452: entry = entry->next) {
2453: iprintf("map entry 0x%x: start=0x%x, end=0x%x, ",
2454: (int) entry, (int) entry->start, (int) entry->end);
2455: if (map->is_main_map) {
2456: static char *inheritance_name[4] =
2457: { "share", "copy", "none", "donate_copy"};
2458: printf("prot=%x/%x/%s, ",
2459: entry->protection,
2460: entry->max_protection,
2461: inheritance_name[entry->inheritance]);
2462: if (entry->wired_count != 0)
2463: printf("wired, ");
2464: }
2465:
2466: if (entry->is_a_map || entry->is_sub_map) {
2467: printf("share=0x%x, offset=0x%x\n",
2468: (int) entry->object.share_map,
2469: (int) entry->offset);
2470: if ((entry->prev == &map->header) ||
2471: (!entry->prev->is_a_map) ||
2472: (entry->prev->object.share_map !=
2473: entry->object.share_map)) {
2474: indent += 2;
2475: vm_map_print(entry->object.share_map, full);
2476: indent -= 2;
2477: }
2478:
2479: }
2480: else {
2481: printf("object=0x%x, offset=0x%x",
2482: (int) entry->object.vm_object,
2483: (int) entry->offset);
2484: if (entry->copy_on_write)
2485: printf(", copy (%s)",
2486: entry->needs_copy ? "needed" : "done");
2487: printf("\n");
2488:
2489: if ((entry->prev == &map->header) ||
2490: (entry->prev->is_a_map) ||
2491: (entry->prev->object.vm_object !=
2492: entry->object.vm_object)) {
2493: indent += 2;
2494: vm_object_print(entry->object.vm_object, full);
2495: indent -= 2;
2496: }
2497: }
2498: }
2499: indent -= 2;
2500: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.