|
|
1.1 root 1: /*
2: * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
3: *
4: * @APPLE_LICENSE_HEADER_START@
5: *
6: * Portions Copyright (c) 1999 Apple Computer, Inc. All Rights
7: * Reserved. This file contains Original Code and/or Modifications of
8: * Original Code as defined in and that are subject to the Apple Public
9: * Source License Version 1.1 (the "License"). You may not use this file
10: * except in compliance with the License. Please obtain a copy of the
11: * License at http://www.apple.com/publicsource and read it before using
12: * this file.
13: *
14: * The Original Code and all software distributed under the License are
15: * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
16: * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
17: * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
18: * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
19: * License for the specific language governing rights and limitations
20: * under the License.
21: *
22: * @APPLE_LICENSE_HEADER_END@
23: */
24:
25: /*
26: * Mach Operating System
27: * Copyright (c) 1993-1987 Carnegie Mellon University
28: * All Rights Reserved.
29: *
30: * Permission to use, copy, modify and distribute this software and its
31: * documentation is hereby granted, provided that both the copyright
32: * notice and this permission notice appear in all copies of the
33: * software, derivative works or modified versions, and any portions
34: * thereof, and that both notices appear in supporting documentation.
35: *
36: * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
37: * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
38: * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
39: *
40: * Carnegie Mellon requests users of this software to return to
41: *
42: * Software Distribution Coordinator or [email protected]
43: * School of Computer Science
44: * Carnegie Mellon University
45: * Pittsburgh PA 15213-3890
46: *
47: * any improvements or extensions that they make and grant Carnegie Mellon
48: * the rights to redistribute these changes.
49: */
50: /*
51: * File: vm/vm_map.c
52: * Author: Avadis Tevanian, Jr., Michael Wayne Young
53: * Date: 1985
54: *
55: * Virtual memory mapping module.
56: */
57:
58: #import <mach/features.h>
59:
60: #define USE_VERSIONS MACH_XP
61:
62: #import <mach/vm_param.h>
63: #import <vm/vm_map.h>
64: #import <kern/zalloc.h>
65: #import <mach/kern_return.h>
66: #import <vm/vm_page.h>
67: #import <vm/vm_object.h>
68: #import <mach/port.h>
69: #import <mach/vm_attributes.h>
70:
71:
72: /*
73: * Macros to copy a vm_map_entry. We must be careful to correctly
74: * manage the wired page count. vm_map_entry_copy() creates a new
75: * map entry to the same memory - the wired count in the new entry
76: * must be set to zero. vm_map_entry_copy_full() creates a new
77: * entry that is identical to the old entry. This preserves the
78: * wire count; it's used for map splitting and zone changing in
79: * vm_map_copyout.
80: */
81: #define vm_map_entry_copy(NEW,OLD) \
82: MACRO_BEGIN \
83: *(NEW) = *(OLD); \
84: (NEW)->is_shared = FALSE; \
85: (NEW)->needs_wakeup = FALSE; \
86: (NEW)->in_transition = FALSE; \
87: (NEW)->wired_count = 0; \
88: (NEW)->user_wired_count = 0; \
89: MACRO_END
90:
91: #define vm_map_entry_copy_full(NEW,OLD) (*(NEW) = *(OLD))
92:
93: /*
94: * Virtual memory maps provide for the mapping, protection,
95: * and sharing of virtual memory objects. In addition,
96: * this module provides for an efficient virtual copy of
97: * memory from one map to another.
98: *
99: * Synchronization is required prior to most operations.
100: *
101: * Maps consist of an ordered doubly-linked list of simple
102: * entries; a single hint is used to speed up lookups.
103: *
104: * In order to properly represent the sharing of virtual
105: * memory regions among maps, the map structure is bi-level.
106: * Top-level ("address") maps refer to regions of sharable
107: * virtual memory. These regions are implemented as
108: * ("sharing") maps, which then refer to the actual virtual
109: * memory objects. When two address maps "share" memory,
110: * their top-level maps both have references to the same
111: * sharing map. When memory is virtual-copied from one
112: * address map to another, the references in the sharing
113: * maps are actually copied -- no copying occurs at the
114: * virtual memory object level.
115: *
116: * Since portions of maps are specified by start/end addreses,
117: * which may not align with existing map entries, all
118: * routines merely "clip" entries to these start/end values.
119: * [That is, an entry is split into two, bordering at a
120: * start or end value.] Note that these clippings may not
121: * always be necessary (as the two resulting entries are then
122: * not changed); however, the clipping is done for convenience.
123: * No attempt is currently made to "glue back together" two
124: * abutting entries.
125: *
126: * As mentioned above, virtual copy operations are performed
127: * by copying VM object references from one sharing map to
128: * another, and then marking both regions as copy-on-write.
129: * It is important to note that only one writeable reference
130: * to a VM object region exists in any map -- this means that
131: * shadow object creation can be delayed until a write operation
132: * occurs.
133: */
134:
135: zone_t vm_map_zone; /* zone for vm_map structures */
136: zone_t vm_map_entry_zone; /* zone for vm_map_entry structures */
137: zone_t vm_map_kentry_zone; /* zone for kernel entry structures */
138:
139: vm_object_t vm_submap_object;
140:
141: /*
142: * vm_map_init:
143: *
144: * Initialize the vm_map module. Must be called before
145: * any other vm_map routines.
146: *
147: * Map and entry structures are allocated from zones -- we must
148: * initialize those zones.
149: *
150: * There are three zones of interest:
151: *
152: * vm_map_zone: used to allocate maps.
153: * vm_map_entry_zone: used to allocate map entries.
154: * vm_map_kentry_zone: used to allocate map entries for the kernel.
155: *
156: * The kernel allocates map entries from a special zone that is initially
157: * "crammed" with memory. It would be difficult (perhaps impossible) for
158: * the kernel to allocate more memory to a entry zone when it became
159: * empty since the very act of allocating memory implies the creatio
160: * of a new entry. Further, since the kernel map is created from the
161: * map zone, the map zone is initially "crammed" with enough memory
162: * to fullfill that need.
163: */
164:
165: void vm_map_init()
166: {
167: extern vm_offset_t map_data, kentry_data;
168: extern vm_size_t map_data_size, kentry_data_size;
169:
170: vm_map_zone = zinit((vm_size_t) sizeof(struct vm_map), 100*1024,
171: 0, FALSE, "maps");
172: vm_map_entry_zone = zinit((vm_size_t) sizeof(struct vm_map_entry),
173: 1024*1024, 0,
174: FALSE, "non-kernel map entries");
175: vm_map_kentry_zone = zinit((vm_size_t) sizeof(struct vm_map_entry),
176: kentry_data_size, 0,
177: FALSE, "kernel map entries");
178: zchange(vm_map_kentry_zone, FALSE, FALSE, FALSE, FALSE);
179:
180: /*
181: * Cram the map and kentry zones with initial data.
182: */
183: zcram(vm_map_zone, map_data, map_data_size);
184: zcram(vm_map_kentry_zone, kentry_data, kentry_data_size);
185: }
186:
187: /*
188: * vm_map_create:
189: *
190: * Creates and returns a new empty VM map with
191: * the given physical map structure, and having
192: * the given lower and upper address bounds.
193: */
194: vm_map_t vm_map_create(pmap, min, max, pageable)
195: pmap_t pmap;
196: vm_offset_t min, max;
197: boolean_t pageable;
198: {
199: register vm_map_t result;
200:
201: result = (vm_map_t) zalloc(vm_map_zone);
202: if (result == VM_MAP_NULL)
203: panic("vm_map_create");
204:
205: vm_map_first_entry(result) = vm_map_to_entry(result);
206: vm_map_last_entry(result) = vm_map_to_entry(result);
207: result->hdr.nentries = 0;
208: result->hdr.entries_pageable = pageable;
209:
210: result->size = 0;
211: result->ref_count = 1;
212: result->pmap = pmap;
213: #if OLD_VM_CODE
214: result->is_main_map = TRUE;
215: #endif
216: result->min_offset = min;
217: result->max_offset = max;
218: result->wiring_required = FALSE;
219: result->wait_for_space = FALSE;
220: result->first_free = vm_map_to_entry(result);
221: result->hint = vm_map_to_entry(result);
222: #if OLD_VM_CODE
223: result->timestamp = 0;
224: #endif
225: vm_map_lock_init(result);
226: simple_lock_init(&result->ref_lock);
227: simple_lock_init(&result->hint_lock);
228:
229: return(result);
230: }
231:
232: /*
233: * vm_map_entry_create: [ internal use only ]
234: *
235: * Allocates a VM map entry for insertion in the
236: * given map (or map copy). No fields are filled.
237: */
238: #define vm_map_entry_create(map) \
239: _vm_map_entry_create(&(map)->hdr)
240:
241: #define vm_map_copy_entry_create(copy) \
242: _vm_map_entry_create(&(copy)->cpy_hdr)
243:
244: vm_map_entry_t _vm_map_entry_create(map_header)
245: register struct vm_map_header *map_header;
246: {
247: register zone_t zone;
248: register vm_map_entry_t entry;
249:
250: if (map_header->entries_pageable)
251: zone = vm_map_entry_zone;
252: else
253: zone = vm_map_kentry_zone;
254:
255: entry = (vm_map_entry_t) zalloc(zone);
256: if (entry == VM_MAP_ENTRY_NULL)
257: panic("vm_map_entry_create");
258:
259: return(entry);
260: }
261:
262: /*
263: * vm_map_entry_dispose: [ internal use only ]
264: *
265: * Inverse of vm_map_entry_create.
266: */
267: #define vm_map_entry_dispose(map, entry) \
268: _vm_map_entry_dispose(&(map)->hdr, (entry))
269:
270: #define vm_map_copy_entry_dispose(map, entry) \
271: _vm_map_entry_dispose(&(copy)->cpy_hdr, (entry))
272:
273: void _vm_map_entry_dispose(map_header, entry)
274: register struct vm_map_header *map_header;
275: register vm_map_entry_t entry;
276: {
277: register zone_t zone;
278:
279: if (map_header->entries_pageable)
280: zone = vm_map_entry_zone;
281: else
282: zone = vm_map_kentry_zone;
283:
284: zfree(zone, (vm_offset_t) entry);
285: }
286:
287: /*
288: * vm_map_entry_{un,}link:
289: *
290: * Insert/remove entries from maps (or map copies).
291: */
292: #define vm_map_entry_link(map, after_where, entry) \
293: _vm_map_entry_link(&(map)->hdr, after_where, entry)
294:
295: #define vm_map_copy_entry_link(copy, after_where, entry) \
296: _vm_map_entry_link(&(copy)->cpy_hdr, after_where, entry)
297:
298: #define _vm_map_entry_link(hdr, after_where, entry) \
299: MACRO_BEGIN \
300: (hdr)->nentries++; \
301: (entry)->vme_prev = (after_where); \
302: (entry)->vme_next = (after_where)->vme_next; \
303: (entry)->vme_prev->vme_next = \
304: (entry)->vme_next->vme_prev = (entry); \
305: MACRO_END
306:
307: #define vm_map_entry_unlink(map, entry) \
308: _vm_map_entry_unlink(&(map)->hdr, entry)
309:
310: #define vm_map_copy_entry_unlink(copy, entry) \
311: _vm_map_entry_unlink(&(copy)->cpy_hdr, entry)
312:
313: #define _vm_map_entry_unlink(hdr, entry) \
314: MACRO_BEGIN \
315: (hdr)->nentries--; \
316: (entry)->vme_next->vme_prev = (entry)->vme_prev; \
317: (entry)->vme_prev->vme_next = (entry)->vme_next; \
318: MACRO_END
319:
320: /*
321: * vm_map_reference:
322: *
323: * Creates another valid reference to the given map.
324: *
325: */
326: void vm_map_reference(map)
327: register vm_map_t map;
328: {
329: if (map == VM_MAP_NULL)
330: return;
331:
332: simple_lock(&map->ref_lock);
333: map->ref_count++;
334: simple_unlock(&map->ref_lock);
335: }
336:
337: /*
338: * vm_map_deallocate:
339: *
340: * Removes a reference from the specified map,
341: * destroying it if no references remain.
342: * The map should not be locked.
343: */
344: void vm_map_deallocate(map)
345: register vm_map_t map;
346: {
347: register int c;
348:
349: if (map == VM_MAP_NULL)
350: return;
351:
352: simple_lock(&map->ref_lock);
353: c = --map->ref_count;
354: simple_unlock(&map->ref_lock);
355:
356: if (c > 0) {
357: return;
358: }
359:
360: /*
361: * Lock the map, to wait out all other references
362: * to it.
363: */
364:
365: vm_map_lock(map);
366:
367: (void) vm_map_delete(map, map->min_offset, map->max_offset);
368:
369: pmap_destroy(map->pmap);
370:
371: zfree(vm_map_zone, (vm_offset_t) map);
372: }
373:
374: /*
375: * vm_map_insert: [ internal use only ]
376: *
377: * Inserts the given whole VM object into the target
378: * map at the specified address range. The object's
379: * size should match that of the address range.
380: *
381: * Requires that the map be locked, and leaves it so.
382: */
383: kern_return_t vm_map_insert(map, object, offset, start, end)
384: vm_map_t map;
385: vm_object_t object;
386: vm_offset_t offset;
387: vm_offset_t start;
388: vm_offset_t end;
389: {
390: vm_map_entry_t new_entry;
391: vm_map_entry_t prev_entry;
392: boolean_t vm_map_lookup_entry();
393:
394: /*
395: * Check that the start and end points are not bogus.
396: */
397:
398: if ((start < map->min_offset) || (end > map->max_offset) ||
399: (start >= end))
400: return(KERN_INVALID_ADDRESS);
401:
402: /*
403: * Find the entry prior to the proposed
404: * starting address; if it's part of an
405: * existing entry, this range is bogus.
406: */
407:
408: if (vm_map_lookup_entry(map, start, &prev_entry))
409: return(KERN_NO_SPACE);
410:
411: /*
412: * Assert that the next entry doesn't overlap the
413: * end point.
414: */
415:
416: if ((prev_entry->vme_next != vm_map_to_entry(map)) &&
417: (prev_entry->vme_next->vme_start < end))
418: return(KERN_NO_SPACE);
419:
420: /*
421: * See if we can avoid creating a new entry by
422: * extending one of our neighbors.
423: */
424:
425: if (object == VM_OBJECT_NULL) {
426: if ((prev_entry != vm_map_to_entry(map)) &&
427: (prev_entry->vme_end == start) &&
428: (prev_entry->is_a_map == FALSE) &&
429: (prev_entry->is_sub_map == FALSE) &&
430: (prev_entry->inheritance == VM_INHERIT_DEFAULT) &&
431: (prev_entry->protection == VM_PROT_DEFAULT) &&
432: (prev_entry->max_protection == VM_PROT_ALL) &&
433: (prev_entry->wired_count == 0)) {
434:
435: if (vm_object_coalesce(prev_entry->object.vm_object,
436: VM_OBJECT_NULL,
437: prev_entry->offset,
438: (vm_offset_t) 0,
439: (vm_size_t)(prev_entry->vme_end
440: - prev_entry->vme_start),
441: (vm_size_t)(end -
442: prev_entry->vme_end))) {
443: /*
444: * Coalesced the two objects - can extend
445: * the previous map entry to include the
446: * new range.
447: */
448: map->size += (end - prev_entry->vme_end);
449: prev_entry->vme_end = end;
450: return(KERN_SUCCESS);
451: }
452: }
453: }
454:
455: /*
456: * Create a new entry
457: */
458:
459: new_entry = vm_map_entry_create(map);
460: new_entry->vme_start = start;
461: new_entry->vme_end = end;
462:
463: new_entry->is_a_map = FALSE;
464: new_entry->is_sub_map = FALSE;
465: new_entry->object.vm_object = object;
466: new_entry->offset = offset;
467:
468: new_entry->copy_on_write = FALSE;
469: new_entry->needs_copy = FALSE;
470:
471: if (map->is_main_map) {
472: new_entry->inheritance = VM_INHERIT_DEFAULT;
473: new_entry->protection = VM_PROT_DEFAULT;
474: new_entry->max_protection = VM_PROT_ALL;
475: new_entry->wired_count = 0;
476: }
477:
478: /*
479: * Insert the new entry into the list
480: */
481:
482: vm_map_entry_link(map, prev_entry, new_entry);
483: map->size += new_entry->vme_end - new_entry->vme_start;
484:
485: /*
486: * Update the free space hint
487: */
488:
489: if ((map->first_free == prev_entry) && (prev_entry->vme_end >= new_entry->vme_start))
490: map->first_free = new_entry;
491:
492: return(KERN_SUCCESS);
493: }
494:
495: /*
496: * SAVE_HINT:
497: *
498: * Saves the specified entry as the hint for
499: * future lookups. Performs necessary interlocks.
500: */
501: #define SAVE_HINT(map,value) \
502: simple_lock(&(map)->hint_lock); \
503: (map)->hint = (value); \
504: simple_unlock(&(map)->hint_lock);
505:
506: /*
507: * vm_map_lookup_entry: [ internal use only ]
508: *
509: * Finds the map entry containing (or
510: * immediately preceding) the specified address
511: * in the given map; the entry is returned
512: * in the "entry" parameter. The boolean
513: * result indicates whether the address is
514: * actually contained in the map.
515: */
516: boolean_t vm_map_lookup_entry(map, address, entry)
517: register vm_map_t map;
518: register vm_offset_t address;
519: vm_map_entry_t *entry; /* OUT */
520: {
521: register vm_map_entry_t cur;
522: register vm_map_entry_t last;
523:
524: /*
525: * Start looking either from the head of the
526: * list, or from the hint.
527: */
528:
529: simple_lock(&map->hint_lock);
530: cur = map->hint;
531: simple_unlock(&map->hint_lock);
532:
533: if (cur == vm_map_to_entry(map))
534: cur = cur->vme_next;
535:
536: if (address >= cur->vme_start) {
537: /*
538: * Go from hint to end of list.
539: *
540: * But first, make a quick check to see if
541: * we are already looking at the entry we
542: * want (which is usually the case).
543: * Note also that we don't need to save the hint
544: * here... it is the same hint (unless we are
545: * at the header, in which case the hint didn't
546: * buy us anything anyway).
547: */
548: last = vm_map_to_entry(map);
549: if ((cur != last) && (cur->vme_end > address)) {
550: *entry = cur;
551: return(TRUE);
552: }
553: }
554: else {
555: /*
556: * Go from start to hint, *inclusively*
557: */
558: last = cur->vme_next;
559: cur = vm_map_first_entry(map);
560: }
561:
562: /*
563: * Search linearly
564: */
565:
566: while (cur != last) {
567: if (cur->vme_end > address) {
568: if (address >= cur->vme_start) {
569: /*
570: * Save this lookup for future
571: * hints, and return
572: */
573:
574: *entry = cur;
575: SAVE_HINT(map, cur);
576: return(TRUE);
577: }
578: break;
579: }
580: cur = cur->vme_next;
581: }
582: *entry = cur->vme_prev;
583: SAVE_HINT(map, *entry);
584: return(FALSE);
585: }
586:
587: /*
588: * Routine: vm_map_find_entry
589: * Purpose:
590: * Allocate a range in the specified virtual address map,
591: * returning the entry allocated for that range.
592: * Used by kmem_alloc, etc. Returns wired entries.
593: *
594: * The map must be locked.
595: *
596: * If an entry is allocated, the object/offset fields
597: * are initialized to zero. If an object is supplied,
598: * then an existing entry may be extended.
599: */
600: kern_return_t vm_map_find_entry(map, address, size, mask, object, o_entry)
601: register vm_map_t map;
602: vm_offset_t *address; /* OUT */
603: vm_size_t size;
604: vm_offset_t mask;
605: vm_object_t object;
606: vm_map_entry_t *o_entry; /* OUT */
607: {
608: register vm_map_entry_t entry, new_entry;
609: register vm_offset_t start;
610: register vm_offset_t end;
611:
612: /*
613: * Look for the first possible address;
614: * if there's already something at this
615: * address, we have to start after it.
616: */
617:
618: if ((entry = map->first_free) == vm_map_to_entry(map))
619: start = map->min_offset;
620: else
621: start = entry->vme_end;
622:
623: /*
624: * In any case, the "entry" always precedes
625: * the proposed new region throughout the loop:
626: */
627:
628: while (TRUE) {
629: register vm_map_entry_t next;
630:
631: /*
632: * Find the end of the proposed new region.
633: * Be sure we didn't go beyond the end, or
634: * wrap around the address.
635: */
636:
637: start = ((start + mask) & ~mask);
638: end = start + size;
639:
640: if ((end > map->max_offset) || (end < start))
641: return(KERN_NO_SPACE);
642:
643: /*
644: * If there are no more entries, we must win.
645: */
646:
647: next = entry->vme_next;
648: if (next == vm_map_to_entry(map))
649: break;
650:
651: /*
652: * If there is another entry, it must be
653: * after the end of the potential new region.
654: */
655:
656: if (next->vme_start >= end)
657: break;
658:
659: /*
660: * Didn't fit -- move to the next entry.
661: */
662:
663: entry = next;
664: start = entry->vme_end;
665: }
666:
667: /*
668: * At this point,
669: * "start" and "end" should define the endpoints of the
670: * available new range, and
671: * "entry" should refer to the region before the new
672: * range, and
673: *
674: * the map should be locked.
675: */
676:
677: *address = start;
678:
679: /*
680: * See whether we can avoid creating a new entry by
681: * extending one of our neighbors. [So far, we only attempt to
682: * extend from below.]
683: */
684:
685: if ((object != VM_OBJECT_NULL) &&
686: (entry != vm_map_to_entry(map)) &&
687: (entry->vme_end == start) &&
688: (!entry->is_shared) &&
689: (!entry->is_sub_map) &&
690: (entry->object.vm_object == object) &&
691: (entry->needs_copy == FALSE) &&
692: (entry->inheritance == VM_INHERIT_DEFAULT) &&
693: (entry->protection == VM_PROT_DEFAULT) &&
694: (entry->max_protection == VM_PROT_ALL) &&
695: (entry->wired_count == 1) &&
696: (entry->user_wired_count == 0)) {
697: /*
698: * Because this is a special case,
699: * we don't need to use vm_object_coalesce.
700: */
701:
702: entry->vme_end = end;
703: new_entry = entry;
704: } else {
705: new_entry = vm_map_entry_create(map);
706:
707: new_entry->vme_start = start;
708: new_entry->vme_end = end;
709:
710: new_entry->is_shared = FALSE;
711: new_entry->is_sub_map = FALSE;
712: new_entry->object.vm_object = VM_OBJECT_NULL;
713: new_entry->offset = (vm_offset_t) 0;
714:
715: new_entry->needs_copy = FALSE;
716:
717: new_entry->inheritance = VM_INHERIT_DEFAULT;
718: new_entry->protection = VM_PROT_DEFAULT;
719: new_entry->max_protection = VM_PROT_ALL;
720: new_entry->wired_count = 1;
721: new_entry->user_wired_count = 0;
722:
723: new_entry->in_transition = FALSE;
724: new_entry->needs_wakeup = FALSE;
725:
726: /*
727: * Insert the new entry into the list
728: */
729:
730: vm_map_entry_link(map, entry, new_entry);
731: }
732:
733: map->size += size;
734:
735: /*
736: * Update the free space hint and the lookup hint
737: */
738:
739: map->first_free = new_entry;
740: SAVE_HINT(map, new_entry);
741:
742: *o_entry = new_entry;
743: return(KERN_SUCCESS);
744: }
745:
746: /*
747: * vm_map_find finds an unallocated region in the target address
748: * map with the given length. The search is defined to be
749: * first-fit from the specified address; the region found is
750: * returned in the same parameter.
751: *
752: */
753: kern_return_t vm_map_find(map, object, offset, addr, length, find_space)
754: vm_map_t map;
755: vm_object_t object;
756: vm_offset_t offset;
757: vm_offset_t *addr; /* IN/OUT */
758: vm_size_t length;
759: boolean_t find_space;
760: {
761: register vm_map_entry_t entry;
762: register vm_offset_t start;
763: register vm_offset_t end;
764: kern_return_t result;
765:
766: start = *addr;
767:
768: vm_map_lock(map);
769:
770: if (find_space) {
771: /*
772: * Calculate the first possible address.
773: */
774:
775: if (start < map->min_offset)
776: start = map->min_offset;
777: if (start > map->max_offset) {
778: vm_map_unlock(map);
779: return (KERN_NO_SPACE);
780: }
781:
782: /*
783: * Look for the first possible address;
784: * if there's already something at this
785: * address, we have to start after it.
786: */
787:
788: if (start == map->min_offset) {
789: if ((entry = map->first_free) != vm_map_to_entry(map))
790: start = entry->vme_end;
791: } else {
792: vm_map_entry_t tmp_entry;
793: if (vm_map_lookup_entry(map, start, &tmp_entry))
794: start = tmp_entry->vme_end;
795: entry = tmp_entry;
796: }
797:
798: /*
799: * In any case, the "entry" always precedes
800: * the proposed new region throughout the
801: * loop:
802: */
803:
804: while (TRUE) {
805: register vm_map_entry_t next;
806:
807: /*
808: * Find the end of the proposed new region.
809: * Be sure we didn't go beyond the end, or
810: * wrap around the address.
811: */
812:
813: end = start + length;
814:
815: if ((end > map->max_offset) || (end < start)) {
816: vm_map_unlock(map);
817: return (KERN_NO_SPACE);
818: }
819:
820: /*
821: * If there are no more entries, we must win.
822: */
823:
824: next = entry->vme_next;
825: if (next == vm_map_to_entry(map))
826: break;
827:
828: /*
829: * If there is another entry, it must be
830: * after the end of the potential new region.
831: */
832:
833: if (next->vme_start >= end)
834: break;
835:
836: /*
837: * Didn't fit -- move to the next entry.
838: */
839:
840: entry = next;
841: start = entry->vme_end;
842: }
843: *addr = start;
844:
845: SAVE_HINT(map, entry);
846: }
847:
848: result = vm_map_insert(map, object, offset, start, start + length);
849:
850: vm_map_unlock(map);
851: return(result);
852: }
853:
854: /*
855: * vm_map_clip_start: [ internal use only ]
856: *
857: * Asserts that the given entry begins at or after
858: * the specified address; if necessary,
859: * it splits the entry into two.
860: */
861: void _vm_map_clip_start();
862: #define vm_map_clip_start(map, entry, startaddr) \
863: MACRO_BEGIN \
864: if ((startaddr) > (entry)->vme_start) \
865: _vm_map_clip_start(&(map)->hdr,(entry),(startaddr)); \
866: MACRO_END
867:
868: void _vm_map_copy_clip_start();
869: #define vm_map_copy_clip_start(copy, entry, startaddr) \
870: MACRO_BEGIN \
871: if ((startaddr) > (entry)->vme_start) \
872: _vm_map_clip_start(&(copy)->cpy_hdr,(entry),(startaddr)); \
873: MACRO_END
874:
875: /*
876: * This routine is called only when it is known that
877: * the entry must be split.
878: */
879: void _vm_map_clip_start(map_header, entry, start)
880: register struct vm_map_header *map_header;
881: register vm_map_entry_t entry;
882: register vm_offset_t start;
883: {
884: register vm_map_entry_t new_entry;
885:
886: /*
887: * Split off the front portion --
888: * note that we must insert the new
889: * entry BEFORE this one, so that
890: * this entry has the specified starting
891: * address.
892: */
893:
894: new_entry = _vm_map_entry_create(map_header);
895: vm_map_entry_copy_full(new_entry, entry);
896:
897: new_entry->vme_end = start;
898: entry->offset += (start - entry->vme_start);
899: entry->vme_start = start;
900:
901: _vm_map_entry_link(map_header, entry->vme_prev, new_entry);
902:
903: if (entry->is_a_map || entry->is_sub_map)
904: vm_map_reference(new_entry->object.share_map);
905: else
906: vm_object_reference(new_entry->object.vm_object);
907: }
908:
909: /*
910: * vm_map_clip_end: [ internal use only ]
911: *
912: * Asserts that the given entry ends at or before
913: * the specified address; if necessary,
914: * it splits the entry into two.
915: */
916: void _vm_map_clip_end();
917: #define vm_map_clip_end(map, entry, endaddr) \
918: MACRO_BEGIN \
919: if ((endaddr) < (entry)->vme_end) \
920: _vm_map_clip_end(&(map)->hdr,(entry),(endaddr)); \
921: MACRO_END
922:
923: void _vm_map_copy_clip_end();
924: #define vm_map_copy_clip_end(copy, entry, endaddr) \
925: MACRO_BEGIN \
926: if ((endaddr) < (entry)->vme_end) \
927: _vm_map_clip_end(&(copy)->cpy_hdr,(entry),(endaddr)); \
928: MACRO_END
929:
930: /*
931: * This routine is called only when it is known that
932: * the entry must be split.
933: */
934: void _vm_map_clip_end(map_header, entry, end)
935: register struct vm_map_header *map_header;
936: register vm_map_entry_t entry;
937: register vm_offset_t end;
938: {
939: register vm_map_entry_t new_entry;
940:
941: /*
942: * Create a new entry and insert it
943: * AFTER the specified entry
944: */
945:
946: new_entry = _vm_map_entry_create(map_header);
947: vm_map_entry_copy_full(new_entry, entry);
948:
949: new_entry->vme_start = entry->vme_end = end;
950: new_entry->offset += (end - entry->vme_start);
951:
952: _vm_map_entry_link(map_header, entry, new_entry);
953:
954: if (entry->is_a_map || entry->is_sub_map)
955: vm_map_reference(new_entry->object.share_map);
956: else
957: vm_object_reference(new_entry->object.vm_object);
958: }
959:
960: /*
961: * VM_MAP_RANGE_CHECK: [ internal use only ]
962: *
963: * Asserts that the starting and ending region
964: * addresses fall within the valid range of the map.
965: */
966: #define VM_MAP_RANGE_CHECK(map, start, end) \
967: { \
968: if (start < vm_map_min(map)) \
969: start = vm_map_min(map); \
970: if (end > vm_map_max(map)) \
971: end = vm_map_max(map); \
972: if (start > end) \
973: start = end; \
974: }
975:
976: /*
977: * vm_map_submap: [ kernel use only ]
978: *
979: * Mark the given range as handled by a subordinate map.
980: *
981: * This range must have been created with vm_map_find,
982: * and no other operations may have been performed on this
983: * range prior to calling vm_map_submap.
984: *
985: * Only a limited number of operations can be performed
986: * within this rage after calling vm_map_submap:
987: * vm_fault
988: * [Don't try vm_map_copy!]
989: *
990: * To remove a submapping, one must first remove the
991: * range from the superior map, and then destroy the
992: * submap (if desired). [Better yet, don't try it.]
993: */
994: kern_return_t vm_map_submap(map, start, end, submap)
995: register vm_map_t map;
996: register vm_offset_t start;
997: register vm_offset_t end;
998: vm_map_t submap;
999: {
1000: vm_map_entry_t entry;
1001: register kern_return_t result = KERN_INVALID_ARGUMENT;
1002: register vm_object_t object;
1003:
1004: vm_map_lock(map);
1005:
1006: VM_MAP_RANGE_CHECK(map, start, end);
1007:
1008: if (vm_map_lookup_entry(map, start, &entry)) {
1009: vm_map_clip_start(map, entry, start);
1010: }
1011: else
1012: entry = entry->vme_next;
1013:
1014: vm_map_clip_end(map, entry, end);
1015:
1016: if ((entry->vme_start == start) && (entry->vme_end == end) &&
1017: (!entry->is_a_map) &&
1018: ((object = entry->object.vm_object) == vm_submap_object) &&
1019: (!entry->copy_on_write)) {
1020: entry->object.vm_object = VM_OBJECT_NULL;
1021: vm_object_deallocate(object);
1022: entry->is_sub_map = TRUE;
1023: vm_map_reference(entry->object.sub_map = submap);
1024: result = KERN_SUCCESS;
1025: }
1026: vm_map_unlock(map);
1027:
1028: return(result);
1029: }
1030:
1031: /*
1032: * vm_map_protect:
1033: *
1034: * Sets the protection of the specified address
1035: * region in the target map. If "set_max" is
1036: * specified, the maximum protection is to be set;
1037: * otherwise, only the current protection is affected.
1038: */
1039: kern_return_t vm_map_protect(map, start, end, new_prot, set_max)
1040: register vm_map_t map;
1041: register vm_offset_t start;
1042: register vm_offset_t end;
1043: register vm_prot_t new_prot;
1044: register boolean_t set_max;
1045: {
1046: register vm_map_entry_t current;
1047: vm_map_entry_t entry;
1048:
1049: vm_map_lock(map);
1050:
1051: VM_MAP_RANGE_CHECK(map, start, end);
1052:
1053: if (vm_map_lookup_entry(map, start, &entry)) {
1054: vm_map_clip_start(map, entry, start);
1055: }
1056: else
1057: entry = entry->vme_next;
1058:
1059: /*
1060: * Make a first pass to check for protection
1061: * violations.
1062: */
1063:
1064: current = entry;
1065: while ((current != vm_map_to_entry(map)) &&
1066: (current->vme_start < end)) {
1067: if (current->is_sub_map) {
1068: vm_map_unlock(map);
1069: return(KERN_INVALID_ARGUMENT);
1070: }
1071: if ((new_prot & current->max_protection) != new_prot) {
1072: vm_map_unlock(map);
1073: return(KERN_PROTECTION_FAILURE);
1074: }
1075:
1076: current = current->vme_next;
1077: }
1078:
1079: /*
1080: * Go back and fix up protections.
1081: * [Note that clipping is not necessary the second time.]
1082: */
1083:
1084: current = entry;
1085:
1086: while ((current != vm_map_to_entry(map)) &&
1087: (current->vme_start < end)) {
1088: vm_prot_t old_prot;
1089:
1090: vm_map_clip_end(map, current, end);
1091:
1092: old_prot = current->protection;
1093: if (set_max)
1094: current->protection =
1095: (current->max_protection = new_prot) &
1096: old_prot;
1097: else
1098: current->protection = new_prot;
1099:
1100: /*
1101: * Update physical map if necessary.
1102: * Worry about copy-on-write here -- CHECK THIS XXX
1103: */
1104:
1105: if (current->protection != old_prot) {
1106:
1107: #define MASK(entry) ((entry)->copy_on_write ? ~VM_PROT_WRITE : \
1108: VM_PROT_ALL)
1109: #define max(a,b) ((a) > (b) ? (a) : (b))
1110:
1111: if (current->is_a_map) {
1112: vm_map_entry_t share_entry;
1113: vm_offset_t share_end;
1114:
1115: vm_map_lock(current->object.share_map);
1116: (void) vm_map_lookup_entry(
1117: current->object.share_map,
1118: current->offset,
1119: &share_entry);
1120: share_end = current->offset +
1121: (current->vme_end -
1122: current->vme_start);
1123: while ((share_entry !=
1124: vm_map_to_entry(
1125: current->object.share_map)) &&
1126: (share_entry->vme_start < share_end)) {
1127:
1128: pmap_protect(map->pmap,
1129: (max(share_entry->vme_start,
1130: current->offset) -
1131: current->offset +
1132: current->vme_start),
1133: max(share_entry->vme_end,
1134: share_end) -
1135: current->offset +
1136: current->vme_start,
1137: current->protection &
1138: MASK(share_entry));
1139:
1140: share_entry = share_entry->vme_next;
1141: }
1142: vm_map_unlock(current->object.share_map);
1143: }
1144: else
1145: pmap_protect(map->pmap, current->vme_start,
1146: current->vme_end,
1147: current->protection & MASK(entry));
1148: #undef max
1149: #undef MASK
1150: }
1151: current = current->vme_next;
1152: }
1153:
1154: vm_map_unlock(map);
1155: return(KERN_SUCCESS);
1156: }
1157:
1158: /*
1159: * vm_map_inherit:
1160: *
1161: * Sets the inheritance of the specified address
1162: * range in the target map. Inheritance
1163: * affects how the map will be shared with
1164: * child maps at the time of vm_map_fork.
1165: */
1166: kern_return_t vm_map_inherit(map, start, end, new_inheritance)
1167: register vm_map_t map;
1168: register vm_offset_t start;
1169: register vm_offset_t end;
1170: register vm_inherit_t new_inheritance;
1171: {
1172: register vm_map_entry_t entry;
1173: vm_map_entry_t temp_entry;
1174:
1175: switch (new_inheritance) {
1176: case VM_INHERIT_NONE:
1177: case VM_INHERIT_COPY:
1178: case VM_INHERIT_SHARE:
1179: break;
1180: default:
1181: return(KERN_INVALID_ARGUMENT);
1182: }
1183:
1184: vm_map_lock(map);
1185:
1186: VM_MAP_RANGE_CHECK(map, start, end);
1187:
1188: if (vm_map_lookup_entry(map, start, &temp_entry)) {
1189: entry = temp_entry;
1190: vm_map_clip_start(map, entry, start);
1191: }
1192: else
1193: entry = temp_entry->vme_next;
1194:
1195: while ((entry != vm_map_to_entry(map)) && (entry->vme_start < end)) {
1196: vm_map_clip_end(map, entry, end);
1197:
1198: entry->inheritance = new_inheritance;
1199:
1200: entry = entry->vme_next;
1201: }
1202:
1203: vm_map_unlock(map);
1204: return(KERN_SUCCESS);
1205: }
1206:
1207: #if NeXT
1208: extern vm_map_t kernel_map;
1209: #endif
1210:
1211: /*
1212: * vm_map_pageable:
1213: *
1214: * Sets the pageability of the specified address
1215: * range in the target map. Regions specified
1216: * as not pageable require locked-down physical
1217: * memory and physical page maps.
1218: *
1219: * The map must not be locked, but a reference
1220: * must remain to the map throughout the call.
1221: */
1222: kern_return_t vm_map_pageable(map, start, end, new_pageable)
1223: register vm_map_t map;
1224: register vm_offset_t start;
1225: register vm_offset_t end;
1226: register boolean_t new_pageable;
1227: {
1228: register vm_map_entry_t entry;
1229: vm_map_entry_t temp_entry;
1230: #if NeXT
1231: int map_locked = 1;
1232: #endif
1233:
1234: vm_map_lock(map);
1235:
1236: VM_MAP_RANGE_CHECK(map, start, end);
1237:
1238: /*
1239: * Only one pageability change may take place at one
1240: * time, since vm_fault assumes it will be called
1241: * only once for each wiring/unwiring. Therefore, we
1242: * have to make sure we're actually changing the pageability
1243: * for the entire region. We do so before making any changes.
1244: */
1245:
1246: if (vm_map_lookup_entry(map, start, &temp_entry)) {
1247: entry = temp_entry;
1248: vm_map_clip_start(map, entry, start);
1249: }
1250: else
1251: entry = temp_entry->vme_next;
1252: temp_entry = entry;
1253:
1254: /*
1255: * Actions are rather different for wiring and unwiring,
1256: * so we have two separate cases.
1257: */
1258:
1259: if (new_pageable) {
1260:
1261: /*
1262: * Unwiring. First ensure that the range to be
1263: * unwired is really wired down.
1264: */
1265: while ((entry != vm_map_to_entry(map)) &&
1266: (entry->vme_start < end)) {
1267:
1268: if (entry->wired_count == 0) {
1269: vm_map_unlock(map);
1270: return(KERN_INVALID_ARGUMENT);
1271: }
1272: entry = entry->vme_next;
1273: }
1274:
1275: /*
1276: * Now decrement the wiring count for each region.
1277: * If a region becomes completely unwired,
1278: * unwire its physical pages and mappings.
1279: */
1280: entry = temp_entry;
1281: while ((entry != vm_map_to_entry(map)) &&
1282: (entry->vme_start < end)) {
1283: vm_map_clip_end(map, entry, end);
1284:
1285: entry->wired_count--;
1286: if (entry->wired_count == 0)
1287: vm_fault_unwire(map, entry);
1288:
1289: entry = entry->vme_next;
1290: }
1291: }
1292:
1293: else {
1294: /*
1295: * Wiring. We must do this in two passes:
1296: *
1297: * 1. Holding the write lock, we increment the
1298: * wiring count. For any area that is not already
1299: * wired, we create any shadow objects that need
1300: * to be created.
1301: *
1302: * 2. We downgrade to a read lock, and call
1303: * vm_fault_wire to fault in the pages for any
1304: * newly wired area (wired_count is 1).
1305: *
1306: * Downgrading to a read lock for vm_fault_wire avoids
1307: * a possible deadlock with another thread that may have
1308: * faulted on one of the pages to be wired (it would mark
1309: * the page busy, blocking us, then in turn block on the
1310: * map lock that we hold). Because of problems in the
1311: * recursive lock package, we cannot upgrade to a write
1312: * lock in vm_map_lookup. Thus, any actions that require
1313: * the write lock must be done beforehand. Because we
1314: * keep the read lock on the map, the copy-on-write status
1315: * of the entries we modify here cannot change.
1316: */
1317:
1318: /*
1319: * Pass 1.
1320: */
1321: entry = temp_entry;
1322: while ((entry != vm_map_to_entry(map)) &&
1323: (entry->vme_start < end)) {
1324: vm_map_clip_end(map, entry, end);
1325:
1.1.1.2 ! root 1326: if (++entry->wired_count == 0)
! 1327: panic("vm_map_pageable: wired_count");
1.1 root 1328: if (entry->wired_count == 1) {
1329:
1330: /*
1331: * Perform actions of vm_map_lookup that need
1332: * the write lock on the map: create a shadow
1333: * object for a copy-on-write region, or an
1334: * object for a zero-fill region.
1335: *
1336: * We don't have to do this for entries that
1337: * point to sharing maps, because we won't hold
1338: * the lock on the sharing map.
1339: */
1340: if (!entry->is_a_map) {
1341: if (entry->needs_copy &&
1342: ((entry->protection & VM_PROT_WRITE) != 0)) {
1343:
1344: vm_object_shadow(&entry->object.vm_object,
1345: &entry->offset,
1346: (vm_size_t)(entry->vme_end
1347: - entry->vme_start));
1348: entry->needs_copy = FALSE;
1349: }
1350: else if (entry->object.vm_object == VM_OBJECT_NULL) {
1351: entry->object.vm_object =
1352: vm_object_allocate(
1353: (vm_size_t)(entry->vme_end
1354: - entry->vme_start));
1355: entry->offset = (vm_offset_t)0;
1356: }
1357: }
1358: }
1359:
1360: entry = entry->vme_next;
1361: }
1362:
1363: /*
1364: * Pass 2.
1365: */
1366:
1367: /* If we are wiring pages in the kernel map
1368: * we know that the map will not be modified in a
1369: * destructive way. Drivers call us to wire in
1370: * pages after they do a vm_map_copy into the
1371: * kernel. Enhancing submaps to allow vm_map_copies
1372: * is a better long term solution. For now we will
1373: * release the lock to prevent deadlock.
1374: */
1375: if (map == kernel_map){
1376: map_locked = 0;
1377: vm_map_unlock(map);
1378: } else {
1379: lock_set_recursive(&map->lock);
1380: lock_write_to_read(&map->lock);
1381: }
1382:
1383: entry = temp_entry;
1384: while ((entry != vm_map_to_entry(map)) &&
1385: (entry->vme_start < end)) {
1386: if (entry->wired_count == 1) {
1387: vm_fault_wire(map, entry);
1388: }
1389: entry = entry->vme_next;
1390: }
1391:
1392: if (map_locked){
1393: lock_clear_recursive(&map->lock);
1394: }
1395: }
1396:
1397: if (map_locked){
1398: vm_map_unlock(map);
1399: }
1400:
1401: return(KERN_SUCCESS);
1402: }
1403:
1404: /*
1405: * vm_map_entry_unwire: [ internal use only ]
1406: *
1407: * Make the region specified by this entry pageable.
1408: *
1409: * The map in question should be locked.
1410: * [This is the reason for this routine's existence.]
1411: */
1412: void vm_map_entry_unwire(map, entry)
1413: vm_map_t map;
1414: register vm_map_entry_t entry;
1415: {
1416: vm_fault_unwire(map, entry);
1417: entry->wired_count = 0;
1418: }
1419:
1420: /*
1421: * vm_map_entry_delete: [ internal use only ]
1422: *
1423: * Deallocate the given entry from the target map.
1424: */
1425: void vm_map_entry_delete(map, entry)
1426: register vm_map_t map;
1427: register vm_map_entry_t entry;
1428: {
1429: if (entry->wired_count != 0)
1430: vm_map_entry_unwire(map, entry);
1431:
1432: vm_map_entry_unlink(map, entry);
1433: map->size -= entry->vme_end - entry->vme_start;
1434:
1435: if (entry->is_a_map || entry->is_sub_map)
1436: vm_map_deallocate(entry->object.share_map);
1437: else
1438: vm_object_deallocate(entry->object.vm_object);
1439:
1440: vm_map_entry_dispose(map, entry);
1441: }
1442:
1443: /*
1444: * vm_map_delete: [ internal use only ]
1445: *
1446: * Deallocates the given address range from the target
1447: * map.
1448: *
1449: * When called with a sharing map, removes pages from
1450: * that region from all physical maps.
1451: */
1452: kern_return_t vm_map_delete(map, start, end)
1453: register vm_map_t map;
1454: vm_offset_t start;
1455: register vm_offset_t end;
1456: {
1457: register vm_map_entry_t entry;
1458: vm_map_entry_t first_entry;
1459:
1460: /*
1461: * Find the start of the region, and clip it
1462: */
1463:
1464: if (!vm_map_lookup_entry(map, start, &first_entry))
1465: entry = first_entry->vme_next;
1466: else {
1467: entry = first_entry;
1468: vm_map_clip_start(map, entry, start);
1469:
1470: /*
1471: * Fix the lookup hint now, rather than each
1472: * time though the loop.
1473: */
1474:
1475: SAVE_HINT(map, entry->vme_prev);
1476: }
1477:
1478: /*
1479: * Save the free space hint
1480: */
1481:
1482: if (map->first_free->vme_start >= start)
1483: map->first_free = entry->vme_prev;
1484:
1485: /*
1486: * Step through all entries in this region
1487: */
1488:
1489: while ((entry != vm_map_to_entry(map)) &&
1490: (entry->vme_start < end)) {
1491: vm_map_entry_t next;
1492: register vm_offset_t s, e;
1493: register vm_object_t object;
1494: extern vm_object_t kernel_object;
1495:
1496: vm_map_clip_end(map, entry, end);
1497:
1498: next = entry->vme_next;
1499: s = entry->vme_start;
1500: e = entry->vme_end;
1501:
1502: /*
1503: * Unwire before removing addresses from the pmap;
1504: * otherwise, unwiring will put the entries back in
1505: * the pmap.
1506: */
1507:
1508: object = entry->object.vm_object;
1509: if (entry->wired_count != 0)
1510: vm_map_entry_unwire(map, entry);
1511:
1512: if (object == kernel_object)
1513: vm_object_page_remove(object, entry->offset,
1514: entry->offset + (e - s));
1515:
1516: /*
1517: * If this is a sharing map, we must remove
1518: * *all* references to this data, since we can't
1519: * find all of the physical maps which are sharing
1520: * it.
1521: */
1522:
1523: if (!map->is_main_map)
1524: vm_object_pmap_remove(object,
1525: entry->offset,
1526: entry->offset + (e - s));
1527:
1528: pmap_remove(map->pmap, s, e);
1529:
1530: /*
1531: * Delete the entry (which may delete the object)
1532: * only after removing all pmap entries pointing
1533: * to its pages. (Otherwise, its page frames may
1534: * be reallocated, and any modify bits will be
1535: * set in the wrong object!)
1536: */
1537:
1538: vm_map_entry_delete(map, entry);
1539: entry = next;
1540: }
1541: return(KERN_SUCCESS);
1542: }
1543:
1544: /*
1545: * vm_map_remove:
1546: *
1547: * Remove the given address range from the target map.
1548: * This is the exported form of vm_map_delete.
1549: */
1550: kern_return_t vm_map_remove(map, start, end)
1551: register vm_map_t map;
1552: register vm_offset_t start;
1553: register vm_offset_t end;
1554: {
1555: register kern_return_t result;
1556:
1557: vm_map_lock(map);
1558: VM_MAP_RANGE_CHECK(map, start, end);
1559: result = vm_map_delete(map, start, end);
1560: vm_map_unlock(map);
1561:
1562: return(result);
1563: }
1564:
1565: kern_return_t vm_map_reallocate(map, start, end)
1566: register vm_map_t map;
1567: register vm_offset_t start;
1568: register vm_offset_t end;
1569: {
1570: register vm_map_entry_t entry;
1571: vm_map_entry_t first_entry;
1572:
1573: vm_map_lock(map);
1574: VM_MAP_RANGE_CHECK(map, start, end);
1575:
1576: /*
1577: * Find the start of the region, and clip it
1578: */
1579:
1580: if (!vm_map_lookup_entry(map, start, &first_entry))
1581: entry = first_entry->vme_next;
1582: else {
1583: entry = first_entry;
1584: vm_map_clip_start(map, entry, start);
1585:
1586: /*
1587: * Fix the lookup hint now, rather than each
1588: * time though the loop.
1589: */
1590:
1591: SAVE_HINT(map, entry->vme_prev);
1592: }
1593:
1594: /*
1595: * Step through all entries in this region
1596: */
1597:
1598: while ((entry != vm_map_to_entry(map)) &&
1599: (entry->vme_start < end)) {
1600: vm_map_entry_t next;
1601: register vm_offset_t s, e;
1602: register vm_object_t object;
1603: extern vm_object_t kernel_object;
1604:
1605: vm_map_clip_end(map, entry, end);
1606:
1607: next = entry->vme_next;
1608: s = entry->vme_start;
1609: e = entry->vme_end;
1610:
1611: /*
1612: * Unwire before removing addresses from the pmap;
1613: * otherwise, unwiring will put the entries back in
1614: * the pmap.
1615: */
1616:
1617: object = entry->object.vm_object;
1618: if (entry->wired_count != 0)
1619: vm_map_entry_unwire(map, entry);
1620:
1621: if (object == kernel_object)
1622: vm_object_page_remove(object, entry->offset,
1623: entry->offset + (e - s));
1624:
1625: /*
1626: * If this is a sharing map, we must remove
1627: * *all* references to this data, since we can't
1628: * find all of the physical maps which are sharing
1629: * it.
1630: */
1631:
1632: if (!map->is_main_map)
1633: vm_object_pmap_remove(object,
1634: entry->offset,
1635: entry->offset + (e - s));
1636:
1637: pmap_remove(map->pmap, s, e);
1638:
1639: /*
1640: * Release the reference to the underlying object
1641: * only after removing all pmap entries pointing
1642: * to its pages. (Otherwise, its page frames may
1643: * be reallocated, and any modify bits will be
1644: * set in the wrong object!)
1645: */
1646:
1647: if (entry->is_a_map || entry->is_sub_map)
1648: vm_map_deallocate(entry->object.share_map);
1649: else
1650: vm_object_deallocate(entry->object.vm_object);
1651:
1652: entry->is_a_map = FALSE;
1653: entry->is_sub_map = FALSE;
1654: entry->object.vm_object = VM_OBJECT_NULL;
1655: entry->offset = 0;
1656:
1657: entry->copy_on_write = FALSE;
1658: entry->needs_copy = FALSE;
1659:
1660: if (map->is_main_map) {
1661: entry->protection =
1662: (entry->max_protection & VM_PROT_DEFAULT);
1663: entry->wired_count = 0;
1664: }
1665:
1666: entry = next;
1667: }
1668:
1669: vm_map_unlock(map);
1670:
1671: return(KERN_SUCCESS);
1672: }
1673:
1674: /*
1675: * vm_map_check_protection:
1676: *
1677: * Assert that the target map allows the specified
1678: * privilege on the entire address region given.
1679: * The entire region must be allocated.
1680: */
1681: boolean_t vm_map_check_protection(map, start, end, protection)
1682: register vm_map_t map;
1683: register vm_offset_t start;
1684: register vm_offset_t end;
1685: register vm_prot_t protection;
1686: {
1687: register vm_map_entry_t entry;
1688: vm_map_entry_t tmp_entry;
1689:
1690: if (!vm_map_lookup_entry(map, start, &tmp_entry)) {
1691: return(FALSE);
1692: }
1693:
1694: entry = tmp_entry;
1695:
1696: while (start < end) {
1697: if (entry == vm_map_to_entry(map)) {
1698: return(FALSE);
1699: }
1700:
1701: /*
1702: * No holes allowed!
1703: */
1704:
1705: if (start < entry->vme_start) {
1706: return(FALSE);
1707: }
1708:
1709: /*
1710: * Check protection associated with entry.
1711: */
1712:
1713: if ((entry->protection & protection) != protection) {
1714: return(FALSE);
1715: }
1716:
1717: /* go to next entry */
1718:
1719: start = entry->vme_end;
1720: entry = entry->vme_next;
1721: }
1722: return(TRUE);
1723: }
1724:
1725: /*
1726: * vm_map_copy_entry:
1727: *
1728: * Copies the contents of the source entry to the destination
1729: * entry. The entries *must* be aligned properly.
1730: */
1731: void vm_map_copy_entry(src_map, dst_map, src_entry, dst_entry)
1732: vm_map_t src_map, dst_map;
1733: register vm_map_entry_t src_entry, dst_entry;
1734: {
1735: vm_object_t temp_object;
1736:
1737: if (src_entry->is_sub_map || dst_entry->is_sub_map)
1738: return;
1739:
1740: /*
1741: * If our destination map was wired down,
1742: * unwire it now.
1743: */
1744:
1745: if (dst_entry->wired_count != 0)
1746: vm_map_entry_unwire(dst_map, dst_entry);
1747:
1748: /*
1749: * If we're dealing with a sharing map, we
1750: * must remove the destination pages from
1751: * all maps (since we cannot know which maps
1752: * this sharing map belongs in).
1753: */
1754:
1755: if (!dst_map->is_main_map)
1756: vm_object_pmap_remove(dst_entry->object.vm_object,
1757: dst_entry->offset,
1758: dst_entry->offset +
1759: (dst_entry->vme_end - dst_entry->vme_start));
1760:
1761: pmap_remove(dst_map->pmap, dst_entry->vme_start, dst_entry->vme_end);
1762:
1763: if (src_entry->wired_count == 0) {
1764:
1765: boolean_t src_needs_copy;
1766:
1767: /*
1768: * If the source entry is marked needs_copy,
1769: * it is already write-protected.
1770: */
1771: if (!src_entry->needs_copy) {
1772:
1773: boolean_t su;
1774:
1775: /*
1776: * If the source entry has only one mapping,
1777: * we can just protect the virtual address
1778: * range.
1779: */
1780: if (!(su = src_map->is_main_map)) {
1781: simple_lock(&src_map->ref_lock);
1782: su = (src_map->ref_count == 1);
1783: simple_unlock(&src_map->ref_lock);
1784: }
1785:
1786: if (su) {
1787: pmap_protect(src_map->pmap,
1788: src_entry->vme_start,
1789: src_entry->vme_end,
1790: src_entry->protection & ~VM_PROT_WRITE);
1791: }
1792: else {
1793: vm_object_pmap_copy(src_entry->object.vm_object,
1794: src_entry->offset,
1795: src_entry->offset + (src_entry->vme_end
1796: -src_entry->vme_start));
1797: }
1798: }
1799:
1800: /*
1801: * Make a copy of the object.
1802: */
1803: temp_object = dst_entry->object.vm_object;
1804: vm_object_copy(src_entry->object.vm_object,
1805: src_entry->offset,
1806: (vm_size_t)(src_entry->vme_end -
1807: src_entry->vme_start),
1808: &dst_entry->object.vm_object,
1809: &dst_entry->offset,
1810: &src_needs_copy);
1811: /*
1812: * If we didn't get a copy-object now, mark the
1813: * source map entry so that a shadow will be created
1814: * to hold its changed pages.
1815: */
1816: if (src_needs_copy)
1817: src_entry->needs_copy = TRUE;
1818:
1819: /*
1820: * The destination always needs to have a shadow
1821: * created.
1822: */
1823: dst_entry->needs_copy = TRUE;
1824:
1825: /*
1826: * Mark the entries copy-on-write, so that write-enabling
1827: * the entry won't make copy-on-write pages writable.
1828: */
1829: src_entry->copy_on_write = TRUE;
1830: dst_entry->copy_on_write = TRUE;
1831: /* XXX */
1832: if (src_entry->protection & VM_PROT_EXECUTE)
1833: dst_entry->protection |= (VM_PROT_EXECUTE & dst_entry->max_protection);
1834: /* XXX */
1835: /*
1836: * Get rid of the old object.
1837: */
1838: vm_object_deallocate(temp_object);
1839:
1840: pmap_copy(dst_map->pmap, src_map->pmap, dst_entry->vme_start,
1841: dst_entry->vme_end - dst_entry->vme_start, src_entry->vme_start);
1842: }
1843: else {
1844: /*
1845: * Of course, wired down pages can't be set copy-on-write.
1846: * Cause wired pages to be copied into the new
1847: * map by simulating faults (the new pages are
1848: * pageable)
1849: */
1850: vm_fault_copy_entry(dst_map, src_map, dst_entry, src_entry);
1851: }
1852: }
1853:
1854: /*
1855: * vm_map_copy:
1856: *
1857: * Perform a virtual memory copy from the source
1858: * address map/range to the destination map/range.
1859: *
1860: * If src_destroy or dst_alloc is requested,
1861: * the source and destination regions should be
1862: * disjoint, not only in the top-level map, but
1863: * in the sharing maps as well. [The best way
1864: * to guarantee this is to use a new intermediate
1865: * map to make copies. This also reduces map
1866: * fragmentation.]
1867: */
1868: kern_return_t vm_map_copy(dst_map, src_map,
1869: dst_addr, len, src_addr,
1870: dst_alloc, src_destroy)
1871: vm_map_t dst_map;
1872: vm_map_t src_map;
1873: vm_offset_t dst_addr;
1874: vm_size_t len;
1875: vm_offset_t src_addr;
1876: boolean_t dst_alloc;
1877: boolean_t src_destroy;
1878: {
1879: register
1880: vm_map_entry_t src_entry;
1881: register
1882: vm_map_entry_t dst_entry;
1883: vm_map_entry_t tmp_entry;
1884: vm_offset_t src_start;
1885: vm_offset_t src_end;
1886: vm_offset_t dst_start;
1887: vm_offset_t dst_end;
1888: vm_offset_t src_clip;
1889: vm_offset_t dst_clip;
1890: kern_return_t result;
1891: boolean_t old_src_destroy;
1892:
1893: /*
1894: * XXX While we figure out why src_destroy screws up,
1895: * we'll do it by explicitly vm_map_delete'ing at the end.
1896: */
1897:
1898: old_src_destroy = src_destroy;
1899: src_destroy = FALSE;
1900:
1901: /*
1902: * Compute start and end of region in both maps
1903: */
1904:
1905: src_start = src_addr;
1906: src_end = src_start + len;
1907: dst_start = dst_addr;
1908: dst_end = dst_start + len;
1909:
1910: /*
1911: * Check that the region can exist in both source
1912: * and destination.
1913: */
1914:
1915: if ((dst_end < dst_start) || (src_end < src_start))
1916: return(KERN_NO_SPACE);
1917:
1918: /*
1919: * Lock the maps in question -- we avoid deadlock
1920: * by ordering lock acquisition by map value
1921: */
1922:
1923: if (src_map == dst_map) {
1924: vm_map_lock(src_map);
1925: }
1926: else if ((int) src_map < (int) dst_map) {
1927: vm_map_lock(src_map);
1928: vm_map_lock(dst_map);
1929: } else {
1930: vm_map_lock(dst_map);
1931: vm_map_lock(src_map);
1932: }
1933:
1934: result = KERN_SUCCESS;
1935:
1936: /*
1937: * Check protections... source must be completely readable and
1938: * destination must be completely writable. [Note that if we're
1939: * allocating the destination region, we don't have to worry
1940: * about protection, but instead about whether the region
1941: * exists.]
1942: */
1943:
1944: if (src_map->is_main_map && dst_map->is_main_map) {
1945: if (!vm_map_check_protection(src_map, src_start, src_end,
1946: VM_PROT_READ)) {
1947: result = KERN_PROTECTION_FAILURE;
1948: goto Return;
1949: }
1950:
1951: if (dst_alloc) {
1952: /* XXX Consider making this a vm_map_find instead */
1953: if ((result = vm_map_insert(dst_map, VM_OBJECT_NULL,
1954: (vm_offset_t) 0, dst_start, dst_end)) != KERN_SUCCESS)
1955: goto Return;
1956: }
1957: else if (!vm_map_check_protection(dst_map, dst_start, dst_end,
1958: VM_PROT_WRITE)) {
1959: result = KERN_PROTECTION_FAILURE;
1960: goto Return;
1961: }
1962: }
1963:
1964: /*
1965: * Find the start entries and clip.
1966: *
1967: * Note that checking protection asserts that the
1968: * lookup cannot fail.
1969: *
1970: * Also note that we wait to do the second lookup
1971: * until we have done the first clip, as the clip
1972: * may affect which entry we get!
1973: */
1974:
1975: (void) vm_map_lookup_entry(src_map, src_addr, &tmp_entry);
1976: src_entry = tmp_entry;
1977: vm_map_clip_start(src_map, src_entry, src_start);
1978:
1979: (void) vm_map_lookup_entry(dst_map, dst_addr, &tmp_entry);
1980: dst_entry = tmp_entry;
1981: vm_map_clip_start(dst_map, dst_entry, dst_start);
1982:
1983: /*
1984: * If both source and destination entries are the same,
1985: * retry the first lookup, as it may have changed.
1986: */
1987:
1988: if (src_entry == dst_entry) {
1989: (void) vm_map_lookup_entry(src_map, src_addr, &tmp_entry);
1990: src_entry = tmp_entry;
1991: }
1992:
1993: /*
1994: * If source and destination entries are still the same,
1995: * a null copy is being performed.
1996: */
1997:
1998: if (src_entry == dst_entry)
1999: goto Return;
2000:
2001: /*
2002: * Go through entries until we get to the end of the
2003: * region.
2004: */
2005:
2006: while (src_start < src_end) {
2007: /*
2008: * Clip the entries to the endpoint of the entire region.
2009: */
2010:
2011: vm_map_clip_end(src_map, src_entry, src_end);
2012: vm_map_clip_end(dst_map, dst_entry, dst_end);
2013:
2014: /*
2015: * Clip each entry to the endpoint of the other entry.
2016: */
2017:
2018: src_clip = src_entry->vme_start + (dst_entry->vme_end - dst_entry->vme_start);
2019: vm_map_clip_end(src_map, src_entry, src_clip);
2020:
2021: dst_clip = dst_entry->vme_start + (src_entry->vme_end - src_entry->vme_start);
2022: vm_map_clip_end(dst_map, dst_entry, dst_clip);
2023:
2024: /*
2025: * Both entries now match in size and relative endpoints.
2026: *
2027: * If both entries refer to a VM object, we can
2028: * deal with them now.
2029: */
2030:
2031: if (!src_entry->is_a_map && !dst_entry->is_a_map) {
2032: vm_map_copy_entry(src_map, dst_map, src_entry,
2033: dst_entry);
2034: }
2035: else {
2036: register vm_map_t new_dst_map;
2037: vm_offset_t new_dst_start;
2038: vm_size_t new_size;
2039: vm_map_t new_src_map;
2040: vm_offset_t new_src_start;
2041:
2042: /*
2043: * We have to follow at least one sharing map.
2044: */
2045:
2046: new_size = (dst_entry->vme_end - dst_entry->vme_start);
2047:
2048: if (src_entry->is_a_map) {
2049: new_src_map = src_entry->object.share_map;
2050: new_src_start = src_entry->offset;
2051: }
2052: else {
2053: new_src_map = src_map;
2054: new_src_start = src_entry->vme_start;
2055: lock_set_recursive(&src_map->lock);
2056: }
2057:
2058: if (dst_entry->is_a_map) {
2059: vm_offset_t new_dst_end;
2060:
2061: new_dst_map = dst_entry->object.share_map;
2062: new_dst_start = dst_entry->offset;
2063:
2064: /*
2065: * Since the destination sharing entries
2066: * will be merely deallocated, we can
2067: * do that now, and replace the region
2068: * with a null object. [This prevents
2069: * splitting the source map to match
2070: * the form of the destination map.]
2071: * Note that we can only do so if the
2072: * source and destination do not overlap.
2073: */
2074:
2075: new_dst_end = new_dst_start + new_size;
2076:
2077: if (new_dst_map != new_src_map) {
2078: vm_map_lock(new_dst_map);
2079: (void) vm_map_delete(new_dst_map,
2080: new_dst_start,
2081: new_dst_end);
2082: (void) vm_map_insert(new_dst_map,
2083: VM_OBJECT_NULL,
2084: (vm_offset_t) 0,
2085: new_dst_start,
2086: new_dst_end);
2087: vm_map_unlock(new_dst_map);
2088: }
2089: }
2090: else {
2091: new_dst_map = dst_map;
2092: new_dst_start = dst_entry->vme_start;
2093: lock_set_recursive(&dst_map->lock);
2094: }
2095:
2096: /*
2097: * Recursively copy the sharing map.
2098: */
2099:
2100: (void) vm_map_copy(new_dst_map, new_src_map,
2101: new_dst_start, new_size, new_src_start,
2102: FALSE, FALSE);
2103:
2104: if (dst_map == new_dst_map)
2105: lock_clear_recursive(&dst_map->lock);
2106: if (src_map == new_src_map)
2107: lock_clear_recursive(&src_map->lock);
2108: }
2109:
2110: /*
2111: * Update variables for next pass through the loop.
2112: */
2113:
2114: src_start = src_entry->vme_end;
2115: src_entry = src_entry->vme_next;
2116: dst_start = dst_entry->vme_end;
2117: dst_entry = dst_entry->vme_next;
2118:
2119: /*
2120: * If the source is to be destroyed, here is the
2121: * place to do it.
2122: */
2123:
2124: if (src_destroy && src_map->is_main_map &&
2125: dst_map->is_main_map)
2126: vm_map_entry_delete(src_map, src_entry->vme_prev);
2127: }
2128:
2129: /*
2130: * Update the physical maps as appropriate
2131: */
2132:
2133: if (src_map->is_main_map && dst_map->is_main_map) {
2134: if (src_destroy)
2135: pmap_remove(src_map->pmap, src_addr, src_addr + len);
2136: }
2137:
2138: /*
2139: * Unlock the maps
2140: */
2141:
2142: Return: ;
2143:
2144: if (old_src_destroy)
2145: vm_map_delete(src_map, src_addr, src_addr + len);
2146:
2147: vm_map_unlock(src_map);
2148: if (src_map != dst_map)
2149: vm_map_unlock(dst_map);
2150:
2151: return(result);
2152: }
2153:
2154: /*
2155: * vm_map_fork:
2156: *
2157: * Create and return a new map based on the old
2158: * map, according to the inheritance values on the
2159: * regions in that map.
2160: *
2161: * The source map must not be locked.
2162: */
2163: vm_map_t vm_map_fork(old_map)
2164: vm_map_t old_map;
2165: {
2166: vm_map_t new_map;
2167: vm_map_entry_t old_entry;
2168: vm_map_entry_t new_entry;
2169: pmap_t new_pmap;
2170:
2171: vm_map_lock(old_map);
2172:
2173: new_pmap = pmap_create((vm_size_t) 0);
2174: new_map = vm_map_create(new_pmap,
2175: old_map->min_offset,
2176: old_map->max_offset,
2177: old_map->hdr.entries_pageable);
2178:
2179: old_entry = vm_map_first_entry(old_map);
2180:
2181: while (old_entry != vm_map_to_entry(old_map)) {
2182: if (old_entry->is_sub_map)
2183: panic("vm_map_fork: encountered a submap");
2184:
2185: switch (old_entry->inheritance) {
2186: case VM_INHERIT_NONE:
2187: break;
2188:
2189: case VM_INHERIT_SHARE:
2190: /*
2191: * If we don't already have a sharing map:
2192: */
2193:
2194: if (!old_entry->is_a_map) {
2195: vm_map_t new_share_map;
2196: vm_map_entry_t new_share_entry;
2197:
2198: /*
2199: * Create a new sharing map
2200: */
2201:
2202: new_share_map = vm_map_create(PMAP_NULL,
2203: old_entry->vme_start,
2204: old_entry->vme_end,
2205: TRUE);
2206: new_share_map->is_main_map = FALSE;
2207:
2208: /*
2209: * Create the only sharing entry from the
2210: * old task map entry.
2211: */
2212:
2213: new_share_entry =
2214: vm_map_entry_create(new_share_map);
2215: *new_share_entry = *old_entry;
2216:
2217: /*
2218: * Insert the entry into the new sharing
2219: * map
2220: */
2221:
2222: vm_map_entry_link(new_share_map,
2223: vm_map_last_entry(new_share_map),
2224: new_share_entry);
2225:
2226: /*
2227: * Fix up the task map entry to refer
2228: * to the sharing map now.
2229: */
2230:
2231: old_entry->is_a_map = TRUE;
2232: old_entry->object.share_map = new_share_map;
2233: old_entry->offset = old_entry->vme_start;
2234: }
2235:
2236: /*
2237: * Clone the entry, referencing the sharing map.
2238: */
2239:
2240: new_entry = vm_map_entry_create(new_map);
2241: *new_entry = *old_entry;
2242: vm_map_reference(new_entry->object.share_map);
2243:
2244: /*
2245: * Insert the entry into the new map -- we
2246: * know we're inserting at the end of the new
2247: * map.
2248: */
2249:
2250: vm_map_entry_link(new_map,
2251: vm_map_last_entry(new_map),
2252: new_entry);
2253:
2254: /*
2255: * Update the physical map
2256: */
2257:
2258: pmap_copy(new_map->pmap, old_map->pmap,
2259: new_entry->vme_start,
2260: (old_entry->vme_end - old_entry->vme_start),
2261: old_entry->vme_start);
2262: break;
2263:
2264: case VM_INHERIT_COPY:
2265: /*
2266: * Clone the entry and link into the map.
2267: */
2268:
2269: new_entry = vm_map_entry_create(new_map);
2270: *new_entry = *old_entry;
2271: new_entry->wired_count = 0;
2272: new_entry->object.vm_object = VM_OBJECT_NULL;
2273: new_entry->is_a_map = FALSE;
2274: vm_map_entry_link(new_map,
2275: vm_map_last_entry(new_map),
2276: new_entry);
2277: if (old_entry->is_a_map) {
2278: kern_return_t check;
2279:
2280: check = vm_map_copy(new_map,
2281: old_entry->object.share_map,
2282: new_entry->vme_start,
2283: (vm_size_t)
2284: (new_entry->vme_end -
2285: new_entry->vme_start),
2286: old_entry->offset,
2287: FALSE, FALSE);
2288: if (check != KERN_SUCCESS)
2289: kprintf("vm_map_fork: copy in share_map region failed\n");
2290: }
2291: else {
2292: vm_map_copy_entry(old_map, new_map, old_entry,
2293: new_entry);
2294: }
2295: break;
2296: }
2297: old_entry = old_entry->vme_next;
2298: }
2299:
2300: new_map->size = old_map->size;
2301: vm_map_unlock(old_map);
2302:
2303: return(new_map);
2304: }
2305:
2306: /*
2307: * vm_map_lookup:
2308: *
2309: * Finds the VM object, offset, and
2310: * protection for a given virtual address in the
2311: * specified map, assuming a page fault of the
2312: * type specified.
2313: *
2314: #if USE_VERSIONS
2315: * Returns the (object, offset, protection) for
2316: * this address, whether it is wired down, and whether
2317: * this map has the only reference to the data in question.
2318: * In order to later verify this lookup, a "version"
2319: * is returned.
2320: *
2321: * The map should not be locked; it will not be
2322: * locked on exit. In order to guarantee the
2323: * existence of the returned object, it is returned
2324: * locked.
2325: #else USE_VERSIONS
2326: * Leaves the map in question locked for read; return
2327: * values are guaranteed until a vm_map_lookup_done
2328: * call is performed. Note that the map argument
2329: * is in/out; the returned map must be used in
2330: * the call to vm_map_lookup_done.
2331: *
2332: * A handle (out_entry) is returned for use in
2333: * vm_map_lookup_done, to make that fast.
2334: #endif USE_VERSIONS
2335: *
2336: * If a lookup is requested with "write protection"
2337: * specified, the map may be changed to perform virtual
2338: * copying operations, although the data referenced will
2339: * remain the same.
2340: */
2341: #if USE_VERSIONS
2342: kern_return_t vm_map_lookup(var_map, vaddr, fault_type, out_version,
2343: object, offset, out_prot, wired, single_use)
2344: #else USE_VERSIONS
2345: kern_return_t vm_map_lookup(var_map, vaddr, fault_type, out_entry,
2346: object, offset, out_prot, wired, single_use)
2347: #endif USE_VERSIONS
2348: vm_map_t *var_map; /* IN/OUT */
2349: register vm_offset_t vaddr;
2350: register vm_prot_t fault_type;
2351:
2352: #if USE_VERSIONS
2353: vm_map_version_t *out_version; /* OUT */
2354: #else USE_VERSIONS
2355: vm_map_entry_t *out_entry; /* OUT */
2356: #endif USE_VERSIONS
2357: vm_object_t *object; /* OUT */
2358: vm_offset_t *offset; /* OUT */
2359: vm_prot_t *out_prot; /* OUT */
2360: boolean_t *wired; /* OUT */
2361: boolean_t *single_use; /* OUT */
2362: {
2363: vm_map_t share_map;
2364: vm_offset_t share_offset;
2365: register vm_map_entry_t entry;
2366: register vm_map_t map = *var_map;
2367: register vm_prot_t prot;
2368: register boolean_t su;
2369:
2370: RetryLookup: ;
2371:
2372: /*
2373: * Lookup the faulting address.
2374: */
2375:
2376: vm_map_lock_read(map);
2377:
2378: #define L_RETURN(why) \
2379: { \
2380: vm_map_unlock_read(map); \
2381: return(why); \
2382: }
2383:
2384: /*
2385: * If the map has an interesting hint, try it before calling
2386: * full blown lookup routine.
2387: */
2388:
2389: simple_lock(&map->hint_lock);
2390: entry = map->hint;
2391: simple_unlock(&map->hint_lock);
2392:
2393: #if !USE_VERSIONS
2394: *out_entry = entry;
2395: #endif !USE_VERSIONS
2396:
2397: if ((entry == vm_map_to_entry(map)) ||
2398: (vaddr < entry->vme_start) || (vaddr >= entry->vme_end)) {
2399: vm_map_entry_t tmp_entry;
2400:
2401: /*
2402: * Entry was either not a valid hint, or the vaddr
2403: * was not contained in the entry, so do a full lookup.
2404: */
2405: if (!vm_map_lookup_entry(map, vaddr, &tmp_entry))
2406: L_RETURN(KERN_INVALID_ADDRESS);
2407:
2408: entry = tmp_entry;
2409: #if !USE_VERSIONS
2410: *out_entry = entry;
2411: #endif !USE_VERSIONS
2412: }
2413:
2414: /*
2415: * Handle submaps.
2416: */
2417:
2418: if (entry->is_sub_map) {
2419: vm_map_t old_map = map;
2420:
2421: *var_map = map = entry->object.sub_map;
2422: vm_map_unlock_read(old_map);
2423: goto RetryLookup;
2424: }
2425:
2426: /*
2427: * Check whether this task is allowed to have
2428: * this page.
2429: */
2430:
2431: prot = entry->protection;
2432: if ((fault_type & (prot)) != fault_type)
2433: L_RETURN(KERN_PROTECTION_FAILURE);
2434:
2435: /*
2436: * If this page is not pageable, we have to get
2437: * it for all possible accesses.
2438: */
2439:
2440: if (*wired = (entry->wired_count != 0))
2441: prot = fault_type = entry->protection;
2442:
2443: /*
2444: * If we don't already have a VM object, track
2445: * it down.
2446: */
2447:
2448: if (su = !entry->is_a_map) {
2449: share_map = map;
2450: share_offset = vaddr;
2451: }
2452: else {
2453: vm_map_entry_t share_entry;
2454:
2455: /*
2456: * Compute the sharing map, and offset into it.
2457: */
2458:
2459: share_map = entry->object.share_map;
2460: share_offset = (vaddr - entry->vme_start) + entry->offset;
2461:
2462: /*
2463: * Look for the backing store object and offset
2464: */
2465:
2466: vm_map_lock_read(share_map);
2467:
2468: if (!vm_map_lookup_entry(share_map, share_offset,
2469: &share_entry)) {
2470: vm_map_unlock_read(share_map);
2471: L_RETURN(KERN_INVALID_ADDRESS);
2472: }
2473: entry = share_entry;
2474: }
2475:
2476: /*
2477: * If the entry was copy-on-write, we either ...
2478: */
2479:
2480: if (entry->needs_copy) {
2481: /*
2482: * If we want to write the page, we may as well
2483: * handle that now since we've got the sharing
2484: * map locked.
2485: *
2486: * If we don't need to write the page, we just
2487: * demote the permissions allowed.
2488: */
2489:
2490: if (fault_type & VM_PROT_WRITE) {
2491: /*
2492: * Make a new object, and place it in the
2493: * object chain. Note that no new references
2494: * have appeared -- one just moved from the
2495: * share map to the new object.
2496: */
2497:
2498: if (lock_read_to_write(&share_map->lock)) {
2499: if (share_map != map)
2500: vm_map_unlock_read(map);
2501: goto RetryLookup;
2502: }
2503:
2504: vm_object_shadow(
2505: &entry->object.vm_object,
2506: &entry->offset,
2507: (vm_size_t) (entry->vme_end -
2508: entry->vme_start));
2509:
2510: entry->needs_copy = FALSE;
2511:
2512: lock_write_to_read(&share_map->lock);
2513: }
2514: else {
2515: /*
2516: * We're attempting to read a copy-on-write
2517: * page -- don't allow writes.
2518: */
2519:
2520: prot &= (~VM_PROT_WRITE);
2521: }
2522: }
2523:
2524: /*
2525: * Create an object if necessary.
2526: */
2527: if (entry->object.vm_object == VM_OBJECT_NULL) {
2528:
2529: if (lock_read_to_write(&share_map->lock)) {
2530: if (share_map != map)
2531: vm_map_unlock_read(map);
2532: goto RetryLookup;
2533: }
2534:
2535: entry->object.vm_object = vm_object_allocate(
2536: (vm_size_t)(entry->vme_end -
2537: entry->vme_start));
2538: entry->offset = 0;
2539: lock_write_to_read(&share_map->lock);
2540: }
2541:
2542: /*
2543: * Return the object/offset from this entry. If the entry
2544: * was copy-on-write or empty, it has been fixed up.
2545: */
2546:
2547: *offset = (share_offset - entry->vme_start) + entry->offset;
2548: *object = entry->object.vm_object;
2549:
2550: /*
2551: * Return whether this is the only map sharing this data.
2552: */
2553:
2554: if (!su) {
2555: simple_lock(&share_map->ref_lock);
2556: su = (share_map->ref_count == 1);
2557: simple_unlock(&share_map->ref_lock);
2558: }
2559:
2560: *out_prot = prot;
2561: *single_use = su;
2562:
2563: #if USE_VERSIONS
2564: /*
2565: * Lock the object to prevent it from disappearing
2566: */
2567:
2568: vm_object_lock(*object);
2569:
2570: /*
2571: * Save the version numbers and unlock the map(s).
2572: */
2573:
2574: if (share_map != map) {
2575: out_version->share_timestamp = share_map->timestamp;
2576: vm_map_unlock_read(share_map);
2577: }
2578: out_version->share_map = share_map;
2579: out_version->main_timestamp = map->timestamp;
2580:
2581: vm_map_unlock_read(map);
2582: #endif USE_VERSIONS
2583:
2584: return(KERN_SUCCESS);
2585:
2586: #undef L_RETURN
2587: }
2588:
2589: #if USE_VERSIONS
2590: /*
2591: * vm_map_verify:
2592: *
2593: * Verifies that the map in question has not changed
2594: * since the given version. If successful, the map
2595: * will not change until vm_map_verify_done() is called.
2596: */
2597: boolean_t vm_map_verify(map, version)
2598: register
2599: vm_map_t map;
2600: register
2601: vm_map_version_t *version; /* REF */
2602: {
2603: boolean_t result;
2604:
2605: vm_map_lock_read(map);
2606: if (result = (map->timestamp == version->main_timestamp)) {
2607: register
2608: vm_map_t share_map = version->share_map;
2609:
2610: if (share_map != map) {
2611: vm_map_lock_read(version->share_map);
2612: if (!(result = (share_map->timestamp == version->share_timestamp))) {
2613: vm_map_unlock_read(share_map);
2614: }
2615: }
2616: }
2617:
2618: if (!result)
2619: vm_map_unlock_read(map);
2620:
2621: return(result);
2622: }
2623:
2624: /*
2625: * vm_map_verify_done:
2626: *
2627: * Releases locks acquired by a vm_map_verify.
2628: */
2629: void vm_map_verify_done(map, version)
2630: register vm_map_t map;
2631: vm_map_version_t *version; /* REF */
2632: {
2633: if (version->share_map != map)
2634: vm_map_unlock_read(version->share_map);
2635: vm_map_unlock_read(map);
2636: }
2637:
2638: #else USE_VERSIONS
2639:
2640: /*
2641: * vm_map_lookup_done:
2642: *
2643: * Releases locks acquired by a vm_map_lookup
2644: * (according to the handle returned by that lookup).
2645: */
2646:
2647: void vm_map_lookup_done(map, entry)
2648: register vm_map_t map;
2649: vm_map_entry_t entry;
2650: {
2651: /*
2652: * If this entry references a map, unlock it first.
2653: */
2654:
2655: if (entry->is_a_map)
2656: vm_map_unlock_read(entry->object.share_map);
2657:
2658: /*
2659: * Unlock the main-level map
2660: */
2661:
2662: vm_map_unlock_read(map);
2663: }
2664: #endif USE_VERSIONS
2665:
2666: /*
2667: * Routine: vm_map_machine_attribute
2668: * Purpose:
2669: * Provide machine-specific attributes to mappings,
2670: * such as cachability etc. for machines that provide
2671: * them. NUMA architectures and machines with big/strange
2672: * caches will use this.
2673: * Note:
2674: * Responsibilities for locking and checking are handled here,
2675: * everything else in the pmap module. If any non-volatile
2676: * information must be kept, the pmap module should handle
2677: * it itself. [This assumes that attributes do not
2678: * need to be inherited, which seems ok to me]
2679: */
2680: kern_return_t vm_map_machine_attribute(map, address, size, attribute, value)
2681: vm_map_t map;
2682: vm_offset_t address;
2683: vm_size_t size;
2684: vm_machine_attribute_t attribute;
2685: vm_machine_attribute_val_t* value; /* IN/OUT */
2686: {
2687: kern_return_t ret;
2688:
2689: if (address < vm_map_min(map) ||
2690: (address + size) > vm_map_max(map))
2691: return KERN_INVALID_ARGUMENT;
2692:
2693: vm_map_lock(map);
2694:
2695: ret = pmap_attribute(map->pmap, address, size, attribute, value);
2696:
2697: vm_map_unlock(map);
2698:
2699: return ret;
2700: }
2701:
2702: #if DEBUG
2703: /*
2704: * vm_map_print: [ debug ]
2705: */
2706: #if 1
2707: /*
2708: * vm_map_print() is way out of date...
2709: */
2710: void vm_map_print(vm_map_t map)
2711: {
2712:
2713: }
2714: #else 1
2715: void vm_map_print(map)
2716: register vm_map_t map;
2717: {
2718: register vm_map_entry_t entry;
2719: extern int indent;
2720:
2721: iprintf("%s map 0x%x: pmap=0x%x,ref=%d,nentries=%d,version=%d\n",
2722: (map->is_main_map ? "Task" : "Share"),
2723: (int) map, (int) (map->pmap), map->ref_count, map->nentries,
2724: map->timestamp);
2725: indent += 2;
2726: for (entry = map->header.next; entry != &map->header;
2727: entry = entry->next) {
2728: iprintf("map entry 0x%x: start=0x%x, end=0x%x, ",
2729: (int) entry, (int) entry->start, (int) entry->end);
2730: if (map->is_main_map) {
2731: static char *inheritance_name[4] =
2732: { "share", "copy", "none", "donate_copy"};
2733: printf("prot=%x/%x/%s, ",
2734: entry->protection,
2735: entry->max_protection,
2736: inheritance_name[entry->inheritance]);
2737: if (entry->wired_count != 0)
2738: printf("wired, ");
2739: }
2740:
2741: if (entry->is_a_map) {
2742: printf("share=0x%x, offset=0x%x\n",
2743: (int) entry->object.share_map,
2744: (int) entry->offset);
2745: if ((entry->prev == &map->header) || (!entry->prev->is_a_map) ||
2746: (entry->prev->object.share_map != entry->object.share_map)) {
2747: indent += 2;
2748: vm_map_print(entry->object.share_map);
2749: indent -= 2;
2750: }
2751:
2752: }
2753: else {
2754: printf("object=0x%x, offset=0x%x",
2755: (int) entry->object.vm_object,
2756: (int) entry->offset);
2757: if (entry->copy_on_write)
2758: printf(", copy (%s)", entry->needs_copy ? "needed" : "done");
2759: printf("\n");
2760:
2761: if ((entry->prev == &map->header) || (entry->prev->is_a_map) ||
2762: (entry->prev->object.vm_object != entry->object.vm_object)) {
2763: indent += 2;
2764: vm_object_print(entry->object.vm_object);
2765: indent -= 2;
2766: }
2767: }
2768: }
2769: indent -= 2;
2770: }
2771: #endif 1
2772: #endif DEBUG
2773:
2774: kern_return_t vm_region(map, address, size,
2775: protection, max_protection,
2776: inheritance, is_shared,
2777: object_name, offset_in_object)
2778: vm_map_t map;
2779: vm_offset_t *address; /* IN/OUT */
2780: vm_size_t *size; /* OUT */
2781: vm_prot_t *protection; /* OUT */
2782: vm_prot_t *max_protection; /* OUT */
2783: vm_inherit_t *inheritance; /* OUT */
2784: boolean_t *is_shared; /* OUT */
2785: port_t *object_name; /* OUT */
2786: vm_offset_t *offset_in_object; /* OUT */
2787: {
2788: vm_map_entry_t tmp_entry;
2789: register
2790: vm_map_entry_t entry;
2791: register
2792: vm_offset_t tmp_offset;
2793: vm_offset_t start, inaddress = *address;
2794:
2795: if (map == VM_MAP_NULL)
2796: return(KERN_INVALID_ARGUMENT);
2797:
2798: again_after_submap:
2799: start = *address;
2800:
2801: vm_map_lock_read(map);
2802: if (!vm_map_lookup_entry(map, start, &tmp_entry)) {
2803: if ((entry = tmp_entry->vme_next) == vm_map_to_entry(map)) {
2804: vm_map_unlock_read(map);
2805: return(KERN_NO_SPACE);
2806: }
2807: } else {
2808: entry = tmp_entry;
2809: }
2810:
2811: start = entry->vme_start;
2812: *protection = entry->protection;
2813: *max_protection = entry->max_protection;
2814: *inheritance = entry->inheritance;
2815: *address = start;
2816: *size = (entry->vme_end - start);
2817:
2818: tmp_offset = entry->offset;
2819: #define VM_OBJECT_NAME(object) \
2820: vm_object_name((map == kernel_map) ? object : VM_OBJECT_NULL)
2821:
2822: if (entry->is_a_map) {
2823: register
2824: vm_map_t share_map;
2825: vm_size_t share_size;
2826:
2827: share_map = entry->object.share_map;
2828:
2829: vm_map_lock_read(share_map);
2830: (void) vm_map_lookup_entry(share_map, tmp_offset, &tmp_entry);
2831:
2832: if ((share_size = (tmp_entry->vme_end - tmp_offset)) < *size)
2833: *size = share_size;
2834:
2835: *object_name = VM_OBJECT_NAME(tmp_entry->object.vm_object);
2836: *offset_in_object = tmp_entry->offset +
2837: (tmp_offset - tmp_entry->vme_start);
2838:
2839: *is_shared = (share_map->ref_count != 1);
2840: vm_map_unlock_read(share_map);
2841: } else if (entry->is_sub_map) {
2842: vm_map_t sub_map;
2843: vm_offset_t oldstart = start;
2844:
2845: sub_map = entry->object.sub_map;
2846: vm_map_reference(sub_map);
2847: vm_map_unlock_read(map);
2848:
2849: vm_map_lock_read(sub_map);
2850:
2851: if (!vm_map_lookup_entry(sub_map, inaddress, &tmp_entry)) {
2852: if ((entry = tmp_entry->vme_next) ==
2853: vm_map_to_entry(sub_map)) {
2854: vm_map_unlock_read(sub_map);
2855: vm_map_deallocate(sub_map);
2856: inaddress = *address = oldstart + *size;
2857: goto again_after_submap;
2858: }
2859: }
2860: else
2861: entry = tmp_entry;
2862:
2863: start = entry->vme_start;
2864: *protection = entry->protection;
2865: *max_protection = entry->max_protection;
2866: *inheritance = entry->inheritance;
2867: *address = start;
2868: *size = (entry->vme_end - start);
2869:
2870: *is_shared = sub_map->hdr.entries_pageable;
2871: *object_name = VM_OBJECT_NAME(entry->object.vm_object);
2872: *offset_in_object = entry->offset;
2873:
2874: vm_map_unlock_read(sub_map);
2875:
2876: vm_map_deallocate(sub_map);
2877:
2878: return(KERN_SUCCESS);
2879: } else {
2880: *is_shared = FALSE;
2881: *object_name = VM_OBJECT_NAME(entry->object.vm_object);
2882: *offset_in_object = tmp_offset;
2883: }
2884: #undef VM_OBJECT_NAME
2885:
2886: vm_map_unlock_read(map);
2887:
2888: return(KERN_SUCCESS);
2889: }
2890:
2891: #if MACH_DEBUG
2892: #include <kern/host.h>
2893:
2894: kern_return_t host_vm_region(
2895: host_t host,
2896: vm_offset_t *address, /* IN/OUT */
2897: vm_size_t *size, /* OUT */
2898: vm_prot_t *protection, /* OUT */
2899: vm_prot_t *max_protection, /* OUT */
2900: vm_inherit_t *inheritance, /* OUT */
2901: boolean_t *is_pageable, /* OUT */
2902: port_t *object_name, /* OUT */
2903: vm_offset_t *offset_in_object /* OUT */
2904: )
2905: {
2906: if (host == HOST_NULL)
2907: return(KERN_INVALID_ARGUMENT);
2908:
2909: return vm_region(kernel_map, address, size,
2910: protection, max_protection,
2911: inheritance, is_pageable,
2912: object_name, offset_in_object);
2913: }
2914: #endif /* MACH_DEBUG */
2915:
2916: /*
2917: * vm_move:
2918: *
2919: * Move memory from source to destination map, possibly deallocating
2920: * the source map reference to the memory.
2921: *
2922: * Parameters are as follows:
2923: *
2924: * src_map Source address map
2925: * src_addr Address within source map
2926: * dst_map Destination address map
2927: * num_bytes Amount of data (in bytes) to copy/move
2928: * src_dealloc Should source be removed after copy?
2929: *
2930: * Assumes the src and dst maps are not already locked.
2931: *
2932: * If successful, returns destination address in dst_addr.
2933: */
2934: kern_return_t vm_move(src_map,src_addr,dst_map,num_bytes,src_dealloc,dst_addr)
2935: vm_map_t src_map;
2936: register vm_offset_t src_addr;
2937: register vm_map_t dst_map;
2938: vm_offset_t num_bytes;
2939: boolean_t src_dealloc;
2940: vm_offset_t *dst_addr;
2941: {
2942: register vm_offset_t src_start; /* Beginning of region */
2943: register vm_size_t src_size; /* Size of rounded region */
2944: vm_offset_t dst_start; /* destination address */
2945: register kern_return_t result;
2946:
2947: if (num_bytes == 0) {
2948: *dst_addr = 0;
2949: return KERN_SUCCESS;
2950: }
2951:
2952: /*
2953: * Page-align the source region
2954: */
2955:
2956: src_start = trunc_page(src_addr);
2957: src_size = round_page(src_addr + num_bytes) - src_start;
2958:
2959: /*
2960: * Allocate a place to put the copy
2961: */
2962:
2963: dst_start = (vm_offset_t) 0;
2964: result = vm_allocate(dst_map, &dst_start, src_size, TRUE);
2965: if (result == KERN_SUCCESS) {
2966: /*
2967: * Perform the copy, asking for deallocation if desired
2968: */
2969: result = vm_map_copy(dst_map, src_map, dst_start, src_size,
2970: src_start, FALSE, src_dealloc);
2971:
2972: /*
2973: * Return the destination address corresponding to
2974: * the source address given (rather than the front
2975: * of the newly-allocated page).
2976: */
2977:
2978: if (result == KERN_SUCCESS)
2979: *dst_addr = dst_start + (src_addr - src_start);
2980: else
2981: (void) vm_deallocate(dst_map, dst_start, src_size);
2982: }
2983:
2984: return(result);
2985: }
2986:
2987: pmap_t
2988: vm_map_pmap_EXTERNAL(
2989: vm_map_t map
2990: )
2991: {
2992: return (vm_map_pmap(map));
2993: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.