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