|
|
1.1 root 1: /*
2: * Mach Operating System
3: * Copyright (c) 1991,1990,1989,1988,1987 Carnegie Mellon University.
4: * Copyright (c) 1993,1994 The University of Utah and
5: * the Computer Systems Laboratory (CSL).
6: * All rights reserved.
7: *
8: * Permission to use, copy, modify and distribute this software and its
9: * documentation is hereby granted, provided that both the copyright
10: * notice and this permission notice appear in all copies of the
11: * software, derivative works or modified versions, and any portions
12: * thereof, and that both notices appear in supporting documentation.
13: *
14: * CARNEGIE MELLON, THE UNIVERSITY OF UTAH AND CSL ALLOW FREE USE OF
15: * THIS SOFTWARE IN ITS "AS IS" CONDITION, AND DISCLAIM ANY LIABILITY
16: * OF ANY KIND FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF
17: * THIS SOFTWARE.
18: *
19: * Carnegie Mellon requests users of this software to return to
20: *
21: * Software Distribution Coordinator or [email protected]
22: * School of Computer Science
23: * Carnegie Mellon University
24: * Pittsburgh PA 15213-3890
25: *
26: * any improvements or extensions that they make and grant Carnegie Mellon
27: * the rights to redistribute these changes.
28: */
29: /*
30: * File: vm/vm_map.c
31: * Author: Avadis Tevanian, Jr., Michael Wayne Young
32: * Date: 1985
33: *
34: * Virtual memory mapping module.
35: */
36:
37: #include <norma_ipc.h>
38:
39: #include <mach/kern_return.h>
40: #include <mach/port.h>
41: #include <mach/vm_attributes.h>
42: #include <mach/vm_param.h>
43: #include <kern/assert.h>
44: #include <kern/zalloc.h>
45: #include <vm/vm_fault.h>
46: #include <vm/vm_map.h>
47: #include <vm/vm_object.h>
48: #include <vm/vm_page.h>
49: #include <vm/vm_kern.h>
50: #include <ipc/ipc_port.h>
51:
52: /*
53: * Macros to copy a vm_map_entry. We must be careful to correctly
54: * manage the wired page count. vm_map_entry_copy() creates a new
55: * map entry to the same memory - the wired count in the new entry
56: * must be set to zero. vm_map_entry_copy_full() creates a new
57: * entry that is identical to the old entry. This preserves the
58: * wire count; it's used for map splitting and zone changing in
59: * vm_map_copyout.
60: */
61: #define vm_map_entry_copy(NEW,OLD) \
62: MACRO_BEGIN \
63: *(NEW) = *(OLD); \
64: (NEW)->is_shared = FALSE; \
65: (NEW)->needs_wakeup = FALSE; \
66: (NEW)->in_transition = FALSE; \
67: (NEW)->wired_count = 0; \
68: (NEW)->user_wired_count = 0; \
69: MACRO_END
70:
71: #define vm_map_entry_copy_full(NEW,OLD) (*(NEW) = *(OLD))
72:
73: /*
74: * Virtual memory maps provide for the mapping, protection,
75: * and sharing of virtual memory objects. In addition,
76: * this module provides for an efficient virtual copy of
77: * memory from one map to another.
78: *
79: * Synchronization is required prior to most operations.
80: *
81: * Maps consist of an ordered doubly-linked list of simple
82: * entries; a single hint is used to speed up lookups.
83: *
84: * Sharing maps have been deleted from this version of Mach.
85: * All shared objects are now mapped directly into the respective
86: * maps. This requires a change in the copy on write strategy;
87: * the asymmetric (delayed) strategy is used for shared temporary
88: * objects instead of the symmetric (shadow) strategy. This is
89: * selected by the (new) use_shared_copy bit in the object. See
90: * vm_object_copy_temporary in vm_object.c for details. All maps
91: * are now "top level" maps (either task map, kernel map or submap
92: * of the kernel map).
93: *
94: * Since portions of maps are specified by start/end addreses,
95: * which may not align with existing map entries, all
96: * routines merely "clip" entries to these start/end values.
97: * [That is, an entry is split into two, bordering at a
98: * start or end value.] Note that these clippings may not
99: * always be necessary (as the two resulting entries are then
100: * not changed); however, the clipping is done for convenience.
101: * No attempt is currently made to "glue back together" two
102: * abutting entries.
103: *
104: * The symmetric (shadow) copy strategy implements virtual copy
105: * by copying VM object references from one map to
106: * another, and then marking both regions as copy-on-write.
107: * It is important to note that only one writeable reference
108: * to a VM object region exists in any map when this strategy
109: * is used -- this means that shadow object creation can be
110: * delayed until a write operation occurs. The asymmetric (delayed)
111: * strategy allows multiple maps to have writeable references to
112: * the same region of a vm object, and hence cannot delay creating
113: * its copy objects. See vm_object_copy_temporary() in vm_object.c.
114: * Copying of permanent objects is completely different; see
115: * vm_object_copy_strategically() in vm_object.c.
116: */
117:
118: zone_t vm_map_zone; /* zone for vm_map structures */
119: zone_t vm_map_entry_zone; /* zone for vm_map_entry structures */
120: zone_t vm_map_kentry_zone; /* zone for kernel entry structures */
121: zone_t vm_map_copy_zone; /* zone for vm_map_copy structures */
122:
123: boolean_t vm_map_lookup_entry(); /* forward declaration */
124:
125: /*
126: * Placeholder object for submap operations. This object is dropped
127: * into the range by a call to vm_map_find, and removed when
128: * vm_map_submap creates the submap.
129: */
130:
131: vm_object_t vm_submap_object;
132:
133: /*
134: * vm_map_init:
135: *
136: * Initialize the vm_map module. Must be called before
137: * any other vm_map routines.
138: *
139: * Map and entry structures are allocated from zones -- we must
140: * initialize those zones.
141: *
142: * There are three zones of interest:
143: *
144: * vm_map_zone: used to allocate maps.
145: * vm_map_entry_zone: used to allocate map entries.
146: * vm_map_kentry_zone: used to allocate map entries for the kernel.
147: *
148: * The kernel allocates map entries from a special zone that is initially
149: * "crammed" with memory. It would be difficult (perhaps impossible) for
150: * the kernel to allocate more memory to a entry zone when it became
151: * empty since the very act of allocating memory implies the creation
152: * of a new entry.
153: */
154:
155: vm_offset_t kentry_data;
156: vm_size_t kentry_data_size;
157: int kentry_count = 256; /* to init kentry_data_size */
158:
159: void vm_map_init()
160: {
161: vm_map_zone = zinit((vm_size_t) sizeof(struct vm_map), 40*1024,
162: PAGE_SIZE, 0, "maps");
163: vm_map_entry_zone = zinit((vm_size_t) sizeof(struct vm_map_entry),
164: 1024*1024, PAGE_SIZE*5,
165: 0, "non-kernel map entries");
166: vm_map_kentry_zone = zinit((vm_size_t) sizeof(struct vm_map_entry),
167: kentry_data_size, kentry_data_size,
168: ZONE_FIXED /* XXX */, "kernel map entries");
169:
170: vm_map_copy_zone = zinit((vm_size_t) sizeof(struct vm_map_copy),
171: 16*1024, PAGE_SIZE, 0,
172: "map copies");
173:
174: /*
175: * Cram the kentry zone with initial data.
176: */
177: zcram(vm_map_kentry_zone, kentry_data, kentry_data_size);
178:
179: /*
180: * Submap object is initialized by vm_object_init.
181: */
182: }
183:
184: /*
185: * vm_map_create:
186: *
187: * Creates and returns a new empty VM map with
188: * the given physical map structure, and having
189: * the given lower and upper address bounds.
190: */
191: vm_map_t vm_map_create(pmap, min, max, pageable)
192: pmap_t pmap;
193: vm_offset_t min, max;
194: boolean_t pageable;
195: {
196: register vm_map_t result;
197:
198: result = (vm_map_t) zalloc(vm_map_zone);
199: if (result == VM_MAP_NULL)
200: panic("vm_map_create");
201:
202: vm_map_first_entry(result) = vm_map_to_entry(result);
203: vm_map_last_entry(result) = vm_map_to_entry(result);
204: result->hdr.nentries = 0;
205: result->hdr.entries_pageable = pageable;
206:
207: result->size = 0;
208: result->ref_count = 1;
209: result->pmap = pmap;
210: result->min_offset = min;
211: result->max_offset = max;
212: result->wiring_required = FALSE;
213: result->wait_for_space = FALSE;
214: result->first_free = vm_map_to_entry(result);
215: result->hint = vm_map_to_entry(result);
216: vm_map_lock_init(result);
217: simple_lock_init(&result->ref_lock);
218: simple_lock_init(&result->hint_lock);
219:
220: return(result);
221: }
222:
223: /*
224: * vm_map_entry_create: [ internal use only ]
225: *
226: * Allocates a VM map entry for insertion in the
227: * given map (or map copy). No fields are filled.
228: */
229: #define vm_map_entry_create(map) \
230: _vm_map_entry_create(&(map)->hdr)
231:
232: #define vm_map_copy_entry_create(copy) \
233: _vm_map_entry_create(&(copy)->cpy_hdr)
234:
235: vm_map_entry_t _vm_map_entry_create(map_header)
236: register struct vm_map_header *map_header;
237: {
238: register zone_t zone;
239: register vm_map_entry_t entry;
240:
241: if (map_header->entries_pageable)
242: zone = vm_map_entry_zone;
243: else
244: zone = vm_map_kentry_zone;
245:
246: entry = (vm_map_entry_t) zalloc(zone);
247: if (entry == VM_MAP_ENTRY_NULL)
248: panic("vm_map_entry_create");
249:
250: return(entry);
251: }
252:
253: /*
254: * vm_map_entry_dispose: [ internal use only ]
255: *
256: * Inverse of vm_map_entry_create.
257: */
258: #define vm_map_entry_dispose(map, entry) \
259: _vm_map_entry_dispose(&(map)->hdr, (entry))
260:
261: #define vm_map_copy_entry_dispose(map, entry) \
262: _vm_map_entry_dispose(&(copy)->cpy_hdr, (entry))
263:
264: void _vm_map_entry_dispose(map_header, entry)
265: register struct vm_map_header *map_header;
266: register vm_map_entry_t entry;
267: {
268: register zone_t zone;
269:
270: if (map_header->entries_pageable)
271: zone = vm_map_entry_zone;
272: else
273: zone = vm_map_kentry_zone;
274:
275: zfree(zone, (vm_offset_t) entry);
276: }
277:
278: /*
279: * vm_map_entry_{un,}link:
280: *
281: * Insert/remove entries from maps (or map copies).
282: */
283: #define vm_map_entry_link(map, after_where, entry) \
284: _vm_map_entry_link(&(map)->hdr, after_where, entry)
285:
286: #define vm_map_copy_entry_link(copy, after_where, entry) \
287: _vm_map_entry_link(&(copy)->cpy_hdr, after_where, entry)
288:
289: #define _vm_map_entry_link(hdr, after_where, entry) \
290: MACRO_BEGIN \
291: (hdr)->nentries++; \
292: (entry)->vme_prev = (after_where); \
293: (entry)->vme_next = (after_where)->vme_next; \
294: (entry)->vme_prev->vme_next = \
295: (entry)->vme_next->vme_prev = (entry); \
296: MACRO_END
297:
298: #define vm_map_entry_unlink(map, entry) \
299: _vm_map_entry_unlink(&(map)->hdr, entry)
300:
301: #define vm_map_copy_entry_unlink(copy, entry) \
302: _vm_map_entry_unlink(&(copy)->cpy_hdr, entry)
303:
304: #define _vm_map_entry_unlink(hdr, entry) \
305: MACRO_BEGIN \
306: (hdr)->nentries--; \
307: (entry)->vme_next->vme_prev = (entry)->vme_prev; \
308: (entry)->vme_prev->vme_next = (entry)->vme_next; \
309: MACRO_END
310:
311: /*
312: * vm_map_reference:
313: *
314: * Creates another valid reference to the given map.
315: *
316: */
317: void vm_map_reference(map)
318: register vm_map_t map;
319: {
320: if (map == VM_MAP_NULL)
321: return;
322:
323: simple_lock(&map->ref_lock);
324: map->ref_count++;
325: simple_unlock(&map->ref_lock);
326: }
327:
328: /*
329: * vm_map_deallocate:
330: *
331: * Removes a reference from the specified map,
332: * destroying it if no references remain.
333: * The map should not be locked.
334: */
335: void vm_map_deallocate(map)
336: register vm_map_t map;
337: {
338: register int c;
339:
340: if (map == VM_MAP_NULL)
341: return;
342:
343: simple_lock(&map->ref_lock);
344: c = --map->ref_count;
345: simple_unlock(&map->ref_lock);
346:
347: if (c > 0) {
348: return;
349: }
350:
351: projected_buffer_collect(map);
352: (void) vm_map_delete(map, map->min_offset, map->max_offset);
353:
354: pmap_destroy(map->pmap);
355:
356: zfree(vm_map_zone, (vm_offset_t) map);
357: }
358:
359: /*
360: * SAVE_HINT:
361: *
362: * Saves the specified entry as the hint for
363: * future lookups. Performs necessary interlocks.
364: */
365: #define SAVE_HINT(map,value) \
366: simple_lock(&(map)->hint_lock); \
367: (map)->hint = (value); \
368: simple_unlock(&(map)->hint_lock);
369:
370: /*
371: * vm_map_lookup_entry: [ internal use only ]
372: *
373: * Finds the map entry containing (or
374: * immediately preceding) the specified address
375: * in the given map; the entry is returned
376: * in the "entry" parameter. The boolean
377: * result indicates whether the address is
378: * actually contained in the map.
379: */
380: boolean_t vm_map_lookup_entry(map, address, entry)
381: register vm_map_t map;
382: register vm_offset_t address;
383: vm_map_entry_t *entry; /* OUT */
384: {
385: register vm_map_entry_t cur;
386: register vm_map_entry_t last;
387:
388: /*
389: * Start looking either from the head of the
390: * list, or from the hint.
391: */
392:
393: simple_lock(&map->hint_lock);
394: cur = map->hint;
395: simple_unlock(&map->hint_lock);
396:
397: if (cur == vm_map_to_entry(map))
398: cur = cur->vme_next;
399:
400: if (address >= cur->vme_start) {
401: /*
402: * Go from hint to end of list.
403: *
404: * But first, make a quick check to see if
405: * we are already looking at the entry we
406: * want (which is usually the case).
407: * Note also that we don't need to save the hint
408: * here... it is the same hint (unless we are
409: * at the header, in which case the hint didn't
410: * buy us anything anyway).
411: */
412: last = vm_map_to_entry(map);
413: if ((cur != last) && (cur->vme_end > address)) {
414: *entry = cur;
415: return(TRUE);
416: }
417: }
418: else {
419: /*
420: * Go from start to hint, *inclusively*
421: */
422: last = cur->vme_next;
423: cur = vm_map_first_entry(map);
424: }
425:
426: /*
427: * Search linearly
428: */
429:
430: while (cur != last) {
431: if (cur->vme_end > address) {
432: if (address >= cur->vme_start) {
433: /*
434: * Save this lookup for future
435: * hints, and return
436: */
437:
438: *entry = cur;
439: SAVE_HINT(map, cur);
440: return(TRUE);
441: }
442: break;
443: }
444: cur = cur->vme_next;
445: }
446: *entry = cur->vme_prev;
447: SAVE_HINT(map, *entry);
448: return(FALSE);
449: }
450:
451: /*
452: * Routine: invalid_user_access
453: *
454: * Verifies whether user access is valid.
455: */
456:
457: boolean_t
458: invalid_user_access(map, start, end, prot)
459: vm_map_t map;
460: vm_offset_t start, end;
461: vm_prot_t prot;
462: {
463: vm_map_entry_t entry;
464:
465: return (map == VM_MAP_NULL || map == kernel_map ||
466: !vm_map_lookup_entry(map, start, &entry) ||
467: entry->vme_end < end ||
468: (prot & ~(entry->protection)));
469: }
470:
471:
472: /*
473: * Routine: vm_map_find_entry
474: * Purpose:
475: * Allocate a range in the specified virtual address map,
476: * returning the entry allocated for that range.
477: * Used by kmem_alloc, etc. Returns wired entries.
478: *
479: * The map must be locked.
480: *
481: * If an entry is allocated, the object/offset fields
482: * are initialized to zero. If an object is supplied,
483: * then an existing entry may be extended.
484: */
485: kern_return_t vm_map_find_entry(map, address, size, mask, object, o_entry)
486: register vm_map_t map;
487: vm_offset_t *address; /* OUT */
488: vm_size_t size;
489: vm_offset_t mask;
490: vm_object_t object;
491: vm_map_entry_t *o_entry; /* OUT */
492: {
493: register vm_map_entry_t entry, new_entry;
494: register vm_offset_t start;
495: register vm_offset_t end;
496:
497: /*
498: * Look for the first possible address;
499: * if there's already something at this
500: * address, we have to start after it.
501: */
502:
503: if ((entry = map->first_free) == vm_map_to_entry(map))
504: start = map->min_offset;
505: else
506: start = entry->vme_end;
507:
508: /*
509: * In any case, the "entry" always precedes
510: * the proposed new region throughout the loop:
511: */
512:
513: while (TRUE) {
514: register vm_map_entry_t next;
515:
516: /*
517: * Find the end of the proposed new region.
518: * Be sure we didn't go beyond the end, or
519: * wrap around the address.
520: */
521:
522: if (((start + mask) & ~mask) < start)
523: return(KERN_NO_SPACE);
524: start = ((start + mask) & ~mask);
525: end = start + size;
526:
527: if ((end > map->max_offset) || (end < start))
528: return(KERN_NO_SPACE);
529:
530: /*
531: * If there are no more entries, we must win.
532: */
533:
534: next = entry->vme_next;
535: if (next == vm_map_to_entry(map))
536: break;
537:
538: /*
539: * If there is another entry, it must be
540: * after the end of the potential new region.
541: */
542:
543: if (next->vme_start >= end)
544: break;
545:
546: /*
547: * Didn't fit -- move to the next entry.
548: */
549:
550: entry = next;
551: start = entry->vme_end;
552: }
553:
554: /*
555: * At this point,
556: * "start" and "end" should define the endpoints of the
557: * available new range, and
558: * "entry" should refer to the region before the new
559: * range, and
560: *
561: * the map should be locked.
562: */
563:
564: *address = start;
565:
566: /*
567: * See whether we can avoid creating a new entry by
568: * extending one of our neighbors. [So far, we only attempt to
569: * extend from below.]
570: */
571:
572: if ((object != VM_OBJECT_NULL) &&
573: (entry != vm_map_to_entry(map)) &&
574: (entry->vme_end == start) &&
575: (!entry->is_shared) &&
576: (!entry->is_sub_map) &&
577: (entry->object.vm_object == object) &&
578: (entry->needs_copy == FALSE) &&
579: (entry->inheritance == VM_INHERIT_DEFAULT) &&
580: (entry->protection == VM_PROT_DEFAULT) &&
581: (entry->max_protection == VM_PROT_ALL) &&
582: (entry->wired_count == 1) &&
583: (entry->user_wired_count == 0) &&
584: (entry->projected_on == 0)) {
585: /*
586: * Because this is a special case,
587: * we don't need to use vm_object_coalesce.
588: */
589:
590: entry->vme_end = end;
591: new_entry = entry;
592: } else {
593: new_entry = vm_map_entry_create(map);
594:
595: new_entry->vme_start = start;
596: new_entry->vme_end = end;
597:
598: new_entry->is_shared = FALSE;
599: new_entry->is_sub_map = FALSE;
600: new_entry->object.vm_object = VM_OBJECT_NULL;
601: new_entry->offset = (vm_offset_t) 0;
602:
603: new_entry->needs_copy = FALSE;
604:
605: new_entry->inheritance = VM_INHERIT_DEFAULT;
606: new_entry->protection = VM_PROT_DEFAULT;
607: new_entry->max_protection = VM_PROT_ALL;
608: new_entry->wired_count = 1;
609: new_entry->user_wired_count = 0;
610:
611: new_entry->in_transition = FALSE;
612: new_entry->needs_wakeup = FALSE;
613: new_entry->projected_on = 0;
614:
615: /*
616: * Insert the new entry into the list
617: */
618:
619: vm_map_entry_link(map, entry, new_entry);
620: }
621:
622: map->size += size;
623:
624: /*
625: * Update the free space hint and the lookup hint
626: */
627:
628: map->first_free = new_entry;
629: SAVE_HINT(map, new_entry);
630:
631: *o_entry = new_entry;
632: return(KERN_SUCCESS);
633: }
634:
635: int vm_map_pmap_enter_print = FALSE;
636: int vm_map_pmap_enter_enable = FALSE;
637:
638: /*
639: * Routine: vm_map_pmap_enter
640: *
641: * Description:
642: * Force pages from the specified object to be entered into
643: * the pmap at the specified address if they are present.
644: * As soon as a page not found in the object the scan ends.
645: *
646: * Returns:
647: * Nothing.
648: *
649: * In/out conditions:
650: * The source map should not be locked on entry.
651: */
652: void
653: vm_map_pmap_enter(map, addr, end_addr, object, offset, protection)
654: vm_map_t map;
655: register
656: vm_offset_t addr;
657: register
658: vm_offset_t end_addr;
659: register
660: vm_object_t object;
661: vm_offset_t offset;
662: vm_prot_t protection;
663: {
664: while (addr < end_addr) {
665: register vm_page_t m;
666:
667: vm_object_lock(object);
668: vm_object_paging_begin(object);
669:
670: m = vm_page_lookup(object, offset);
671: if (m == VM_PAGE_NULL || m->absent) {
672: vm_object_paging_end(object);
673: vm_object_unlock(object);
674: return;
675: }
676:
677: if (vm_map_pmap_enter_print) {
678: printf("vm_map_pmap_enter:");
679: printf("map: %x, addr: %x, object: %x, offset: %x\n",
680: map, addr, object, offset);
681: }
682:
683: m->busy = TRUE;
684: vm_object_unlock(object);
685:
686: PMAP_ENTER(map->pmap, addr, m,
687: protection, FALSE);
688:
689: vm_object_lock(object);
690: PAGE_WAKEUP_DONE(m);
691: vm_page_lock_queues();
692: if (!m->active && !m->inactive)
693: vm_page_activate(m);
694: vm_page_unlock_queues();
695: vm_object_paging_end(object);
696: vm_object_unlock(object);
697:
698: offset += PAGE_SIZE;
699: addr += PAGE_SIZE;
700: }
701: }
702:
703: /*
704: * Routine: vm_map_enter
705: *
706: * Description:
707: * Allocate a range in the specified virtual address map.
708: * The resulting range will refer to memory defined by
709: * the given memory object and offset into that object.
710: *
711: * Arguments are as defined in the vm_map call.
712: */
713: kern_return_t vm_map_enter(
714: map,
715: address, size, mask, anywhere,
716: object, offset, needs_copy,
717: cur_protection, max_protection, inheritance)
718: register
719: vm_map_t map;
720: vm_offset_t *address; /* IN/OUT */
721: vm_size_t size;
722: vm_offset_t mask;
723: boolean_t anywhere;
724: vm_object_t object;
725: vm_offset_t offset;
726: boolean_t needs_copy;
727: vm_prot_t cur_protection;
728: vm_prot_t max_protection;
729: vm_inherit_t inheritance;
730: {
731: register vm_map_entry_t entry;
732: register vm_offset_t start;
733: register vm_offset_t end;
734: kern_return_t result = KERN_SUCCESS;
735:
736: #define RETURN(value) { result = value; goto BailOut; }
737:
738: StartAgain: ;
739:
740: start = *address;
741:
742: if (anywhere) {
743: vm_map_lock(map);
744:
745: /*
746: * Calculate the first possible address.
747: */
748:
749: if (start < map->min_offset)
750: start = map->min_offset;
751: if (start > map->max_offset)
752: RETURN(KERN_NO_SPACE);
753:
754: /*
755: * Look for the first possible address;
756: * if there's already something at this
757: * address, we have to start after it.
758: */
759:
760: if (start == map->min_offset) {
761: if ((entry = map->first_free) != vm_map_to_entry(map))
762: start = entry->vme_end;
763: } else {
764: vm_map_entry_t tmp_entry;
765: if (vm_map_lookup_entry(map, start, &tmp_entry))
766: start = tmp_entry->vme_end;
767: entry = tmp_entry;
768: }
769:
770: /*
771: * In any case, the "entry" always precedes
772: * the proposed new region throughout the
773: * loop:
774: */
775:
776: while (TRUE) {
777: register vm_map_entry_t next;
778:
779: /*
780: * Find the end of the proposed new region.
781: * Be sure we didn't go beyond the end, or
782: * wrap around the address.
783: */
784:
785: if (((start + mask) & ~mask) < start)
786: return(KERN_NO_SPACE);
787: start = ((start + mask) & ~mask);
788: end = start + size;
789:
790: if ((end > map->max_offset) || (end < start)) {
791: if (map->wait_for_space) {
792: if (size <= (map->max_offset -
793: map->min_offset)) {
794: assert_wait((event_t) map, TRUE);
795: vm_map_unlock(map);
796: thread_block((void (*)()) 0);
797: goto StartAgain;
798: }
799: }
800:
801: RETURN(KERN_NO_SPACE);
802: }
803:
804: /*
805: * If there are no more entries, we must win.
806: */
807:
808: next = entry->vme_next;
809: if (next == vm_map_to_entry(map))
810: break;
811:
812: /*
813: * If there is another entry, it must be
814: * after the end of the potential new region.
815: */
816:
817: if (next->vme_start >= end)
818: break;
819:
820: /*
821: * Didn't fit -- move to the next entry.
822: */
823:
824: entry = next;
825: start = entry->vme_end;
826: }
827: *address = start;
828: } else {
829: vm_map_entry_t temp_entry;
830:
831: /*
832: * Verify that:
833: * the address doesn't itself violate
834: * the mask requirement.
835: */
836:
837: if ((start & mask) != 0)
838: return(KERN_NO_SPACE);
839:
840: vm_map_lock(map);
841:
842: /*
843: * ... the address is within bounds
844: */
845:
846: end = start + size;
847:
848: if ((start < map->min_offset) ||
849: (end > map->max_offset) ||
850: (start >= end)) {
851: RETURN(KERN_INVALID_ADDRESS);
852: }
853:
854: /*
855: * ... the starting address isn't allocated
856: */
857:
858: if (vm_map_lookup_entry(map, start, &temp_entry))
859: RETURN(KERN_NO_SPACE);
860:
861: entry = temp_entry;
862:
863: /*
864: * ... the next region doesn't overlap the
865: * end point.
866: */
867:
868: if ((entry->vme_next != vm_map_to_entry(map)) &&
869: (entry->vme_next->vme_start < end))
870: RETURN(KERN_NO_SPACE);
871: }
872:
873: /*
874: * At this point,
875: * "start" and "end" should define the endpoints of the
876: * available new range, and
877: * "entry" should refer to the region before the new
878: * range, and
879: *
880: * the map should be locked.
881: */
882:
883: /*
884: * See whether we can avoid creating a new entry (and object) by
885: * extending one of our neighbors. [So far, we only attempt to
886: * extend from below.]
887: */
888:
889: if ((object == VM_OBJECT_NULL) &&
890: (entry != vm_map_to_entry(map)) &&
891: (entry->vme_end == start) &&
892: (!entry->is_shared) &&
893: (!entry->is_sub_map) &&
894: (entry->inheritance == inheritance) &&
895: (entry->protection == cur_protection) &&
896: (entry->max_protection == max_protection) &&
897: (entry->wired_count == 0) && /* implies user_wired_count == 0 */
898: (entry->projected_on == 0)) {
899: if (vm_object_coalesce(entry->object.vm_object,
900: VM_OBJECT_NULL,
901: entry->offset,
902: (vm_offset_t) 0,
903: (vm_size_t)(entry->vme_end - entry->vme_start),
904: (vm_size_t)(end - entry->vme_end))) {
905:
906: /*
907: * Coalesced the two objects - can extend
908: * the previous map entry to include the
909: * new range.
910: */
911: map->size += (end - entry->vme_end);
912: entry->vme_end = end;
913: RETURN(KERN_SUCCESS);
914: }
915: }
916:
917: /*
918: * Create a new entry
919: */
920:
921: /**/ {
922: register vm_map_entry_t new_entry;
923:
924: new_entry = vm_map_entry_create(map);
925:
926: new_entry->vme_start = start;
927: new_entry->vme_end = end;
928:
929: new_entry->is_shared = FALSE;
930: new_entry->is_sub_map = FALSE;
931: new_entry->object.vm_object = object;
932: new_entry->offset = offset;
933:
934: new_entry->needs_copy = needs_copy;
935:
936: new_entry->inheritance = inheritance;
937: new_entry->protection = cur_protection;
938: new_entry->max_protection = max_protection;
939: new_entry->wired_count = 0;
940: new_entry->user_wired_count = 0;
941:
942: new_entry->in_transition = FALSE;
943: new_entry->needs_wakeup = FALSE;
944: new_entry->projected_on = 0;
945:
946: /*
947: * Insert the new entry into the list
948: */
949:
950: vm_map_entry_link(map, entry, new_entry);
951: map->size += size;
952:
953: /*
954: * Update the free space hint and the lookup hint
955: */
956:
957: if ((map->first_free == entry) &&
958: ((entry == vm_map_to_entry(map) ? map->min_offset : entry->vme_end)
959: >= new_entry->vme_start))
960: map->first_free = new_entry;
961:
962: SAVE_HINT(map, new_entry);
963:
964: vm_map_unlock(map);
965:
966: if ((object != VM_OBJECT_NULL) &&
967: (vm_map_pmap_enter_enable) &&
968: (!anywhere) &&
969: (!needs_copy) &&
970: (size < (128*1024))) {
971: vm_map_pmap_enter(map, start, end,
972: object, offset, cur_protection);
973: }
974:
975: return(result);
976: /**/ }
977:
978: BailOut: ;
979:
980: vm_map_unlock(map);
981: return(result);
982:
983: #undef RETURN
984: }
985:
986: /*
987: * vm_map_clip_start: [ internal use only ]
988: *
989: * Asserts that the given entry begins at or after
990: * the specified address; if necessary,
991: * it splits the entry into two.
992: */
993: void _vm_map_clip_start();
994: #define vm_map_clip_start(map, entry, startaddr) \
995: MACRO_BEGIN \
996: if ((startaddr) > (entry)->vme_start) \
997: _vm_map_clip_start(&(map)->hdr,(entry),(startaddr)); \
998: MACRO_END
999:
1000: void _vm_map_copy_clip_start();
1001: #define vm_map_copy_clip_start(copy, entry, startaddr) \
1002: MACRO_BEGIN \
1003: if ((startaddr) > (entry)->vme_start) \
1004: _vm_map_clip_start(&(copy)->cpy_hdr,(entry),(startaddr)); \
1005: MACRO_END
1006:
1007: /*
1008: * This routine is called only when it is known that
1009: * the entry must be split.
1010: */
1011: void _vm_map_clip_start(map_header, entry, start)
1012: register struct vm_map_header *map_header;
1013: register vm_map_entry_t entry;
1014: register vm_offset_t start;
1015: {
1016: register vm_map_entry_t new_entry;
1017:
1018: /*
1019: * Split off the front portion --
1020: * note that we must insert the new
1021: * entry BEFORE this one, so that
1022: * this entry has the specified starting
1023: * address.
1024: */
1025:
1026: new_entry = _vm_map_entry_create(map_header);
1027: vm_map_entry_copy_full(new_entry, entry);
1028:
1029: new_entry->vme_end = start;
1030: entry->offset += (start - entry->vme_start);
1031: entry->vme_start = start;
1032:
1033: _vm_map_entry_link(map_header, entry->vme_prev, new_entry);
1034:
1035: if (entry->is_sub_map)
1036: vm_map_reference(new_entry->object.sub_map);
1037: else
1038: vm_object_reference(new_entry->object.vm_object);
1039: }
1040:
1041: /*
1042: * vm_map_clip_end: [ internal use only ]
1043: *
1044: * Asserts that the given entry ends at or before
1045: * the specified address; if necessary,
1046: * it splits the entry into two.
1047: */
1048: void _vm_map_clip_end();
1049: #define vm_map_clip_end(map, entry, endaddr) \
1050: MACRO_BEGIN \
1051: if ((endaddr) < (entry)->vme_end) \
1052: _vm_map_clip_end(&(map)->hdr,(entry),(endaddr)); \
1053: MACRO_END
1054:
1055: void _vm_map_copy_clip_end();
1056: #define vm_map_copy_clip_end(copy, entry, endaddr) \
1057: MACRO_BEGIN \
1058: if ((endaddr) < (entry)->vme_end) \
1059: _vm_map_clip_end(&(copy)->cpy_hdr,(entry),(endaddr)); \
1060: MACRO_END
1061:
1062: /*
1063: * This routine is called only when it is known that
1064: * the entry must be split.
1065: */
1066: void _vm_map_clip_end(map_header, entry, end)
1067: register struct vm_map_header *map_header;
1068: register vm_map_entry_t entry;
1069: register vm_offset_t end;
1070: {
1071: register vm_map_entry_t new_entry;
1072:
1073: /*
1074: * Create a new entry and insert it
1075: * AFTER the specified entry
1076: */
1077:
1078: new_entry = _vm_map_entry_create(map_header);
1079: vm_map_entry_copy_full(new_entry, entry);
1080:
1081: new_entry->vme_start = entry->vme_end = end;
1082: new_entry->offset += (end - entry->vme_start);
1083:
1084: _vm_map_entry_link(map_header, entry, new_entry);
1085:
1086: if (entry->is_sub_map)
1087: vm_map_reference(new_entry->object.sub_map);
1088: else
1089: vm_object_reference(new_entry->object.vm_object);
1090: }
1091:
1092: /*
1093: * VM_MAP_RANGE_CHECK: [ internal use only ]
1094: *
1095: * Asserts that the starting and ending region
1096: * addresses fall within the valid range of the map.
1097: */
1098: #define VM_MAP_RANGE_CHECK(map, start, end) \
1099: { \
1100: if (start < vm_map_min(map)) \
1101: start = vm_map_min(map); \
1102: if (end > vm_map_max(map)) \
1103: end = vm_map_max(map); \
1104: if (start > end) \
1105: start = end; \
1106: }
1107:
1108: /*
1109: * vm_map_submap: [ kernel use only ]
1110: *
1111: * Mark the given range as handled by a subordinate map.
1112: *
1113: * This range must have been created with vm_map_find using
1114: * the vm_submap_object, and no other operations may have been
1115: * performed on this range prior to calling vm_map_submap.
1116: *
1117: * Only a limited number of operations can be performed
1118: * within this rage after calling vm_map_submap:
1119: * vm_fault
1120: * [Don't try vm_map_copyin!]
1121: *
1122: * To remove a submapping, one must first remove the
1123: * range from the superior map, and then destroy the
1124: * submap (if desired). [Better yet, don't try it.]
1125: */
1126: kern_return_t vm_map_submap(map, start, end, submap)
1127: register vm_map_t map;
1128: register vm_offset_t start;
1129: register vm_offset_t end;
1130: vm_map_t submap;
1131: {
1132: vm_map_entry_t entry;
1133: register kern_return_t result = KERN_INVALID_ARGUMENT;
1134: register vm_object_t object;
1135:
1136: vm_map_lock(map);
1137:
1138: VM_MAP_RANGE_CHECK(map, start, end);
1139:
1140: if (vm_map_lookup_entry(map, start, &entry)) {
1141: vm_map_clip_start(map, entry, start);
1142: }
1143: else
1144: entry = entry->vme_next;
1145:
1146: vm_map_clip_end(map, entry, end);
1147:
1148: if ((entry->vme_start == start) && (entry->vme_end == end) &&
1149: (!entry->is_sub_map) &&
1150: ((object = entry->object.vm_object) == vm_submap_object) &&
1151: (object->resident_page_count == 0) &&
1152: (object->copy == VM_OBJECT_NULL) &&
1153: (object->shadow == VM_OBJECT_NULL) &&
1154: (!object->pager_created)) {
1155: entry->object.vm_object = VM_OBJECT_NULL;
1156: vm_object_deallocate(object);
1157: entry->is_sub_map = TRUE;
1158: vm_map_reference(entry->object.sub_map = submap);
1159: result = KERN_SUCCESS;
1160: }
1161: vm_map_unlock(map);
1162:
1163: return(result);
1164: }
1165:
1166: /*
1167: * vm_map_protect:
1168: *
1169: * Sets the protection of the specified address
1170: * region in the target map. If "set_max" is
1171: * specified, the maximum protection is to be set;
1172: * otherwise, only the current protection is affected.
1173: */
1174: kern_return_t vm_map_protect(map, start, end, new_prot, set_max)
1175: register vm_map_t map;
1176: register vm_offset_t start;
1177: register vm_offset_t end;
1178: register vm_prot_t new_prot;
1179: register boolean_t set_max;
1180: {
1181: register vm_map_entry_t current;
1182: vm_map_entry_t entry;
1183:
1184: vm_map_lock(map);
1185:
1186: VM_MAP_RANGE_CHECK(map, start, end);
1187:
1188: if (vm_map_lookup_entry(map, start, &entry)) {
1189: vm_map_clip_start(map, entry, start);
1190: }
1191: else
1192: entry = entry->vme_next;
1193:
1194: /*
1195: * Make a first pass to check for protection
1196: * violations.
1197: */
1198:
1199: current = entry;
1200: while ((current != vm_map_to_entry(map)) &&
1201: (current->vme_start < end)) {
1202:
1203: if (current->is_sub_map) {
1204: vm_map_unlock(map);
1205: return(KERN_INVALID_ARGUMENT);
1206: }
1207: if ((new_prot & (VM_PROT_NOTIFY | current->max_protection))
1208: != new_prot) {
1209: vm_map_unlock(map);
1210: return(KERN_PROTECTION_FAILURE);
1211: }
1212:
1213: current = current->vme_next;
1214: }
1215:
1216: /*
1217: * Go back and fix up protections.
1218: * [Note that clipping is not necessary the second time.]
1219: */
1220:
1221: current = entry;
1222:
1223: while ((current != vm_map_to_entry(map)) &&
1224: (current->vme_start < end)) {
1225:
1226: vm_prot_t old_prot;
1227:
1228: vm_map_clip_end(map, current, end);
1229:
1230: old_prot = current->protection;
1231: if (set_max)
1232: current->protection =
1233: (current->max_protection = new_prot) &
1234: old_prot;
1235: else
1236: current->protection = new_prot;
1237:
1238: /*
1239: * Update physical map if necessary.
1240: */
1241:
1242: if (current->protection != old_prot) {
1243: pmap_protect(map->pmap, current->vme_start,
1244: current->vme_end,
1245: current->protection);
1246: }
1247: current = current->vme_next;
1248: }
1249:
1250: vm_map_unlock(map);
1251: return(KERN_SUCCESS);
1252: }
1253:
1254: /*
1255: * vm_map_inherit:
1256: *
1257: * Sets the inheritance of the specified address
1258: * range in the target map. Inheritance
1259: * affects how the map will be shared with
1260: * child maps at the time of vm_map_fork.
1261: */
1262: kern_return_t vm_map_inherit(map, start, end, new_inheritance)
1263: register vm_map_t map;
1264: register vm_offset_t start;
1265: register vm_offset_t end;
1266: register vm_inherit_t new_inheritance;
1267: {
1268: register vm_map_entry_t entry;
1269: vm_map_entry_t temp_entry;
1270:
1271: vm_map_lock(map);
1272:
1273: VM_MAP_RANGE_CHECK(map, start, end);
1274:
1275: if (vm_map_lookup_entry(map, start, &temp_entry)) {
1276: entry = temp_entry;
1277: vm_map_clip_start(map, entry, start);
1278: }
1279: else
1280: entry = temp_entry->vme_next;
1281:
1282: while ((entry != vm_map_to_entry(map)) && (entry->vme_start < end)) {
1283: vm_map_clip_end(map, entry, end);
1284:
1285: entry->inheritance = new_inheritance;
1286:
1287: entry = entry->vme_next;
1288: }
1289:
1290: vm_map_unlock(map);
1291: return(KERN_SUCCESS);
1292: }
1293:
1294: /*
1295: * vm_map_pageable_common:
1296: *
1297: * Sets the pageability of the specified address
1298: * range in the target map. Regions specified
1299: * as not pageable require locked-down physical
1300: * memory and physical page maps. access_type indicates
1301: * types of accesses that must not generate page faults.
1302: * This is checked against protection of memory being locked-down.
1303: * access_type of VM_PROT_NONE makes memory pageable.
1304: *
1305: * The map must not be locked, but a reference
1306: * must remain to the map throughout the call.
1307: *
1308: * Callers should use macros in vm/vm_map.h (i.e. vm_map_pageable,
1309: * or vm_map_pageable_user); don't call vm_map_pageable directly.
1310: */
1311: kern_return_t vm_map_pageable_common(map, start, end, access_type, user_wire)
1312: register vm_map_t map;
1313: register vm_offset_t start;
1314: register vm_offset_t end;
1315: register vm_prot_t access_type;
1316: boolean_t user_wire;
1317: {
1318: register vm_map_entry_t entry;
1319: vm_map_entry_t start_entry;
1320:
1321: vm_map_lock(map);
1322:
1323: VM_MAP_RANGE_CHECK(map, start, end);
1324:
1325: if (vm_map_lookup_entry(map, start, &start_entry)) {
1326: entry = start_entry;
1327: /*
1328: * vm_map_clip_start will be done later.
1329: */
1330: }
1331: else {
1332: /*
1333: * Start address is not in map; this is fatal.
1334: */
1335: vm_map_unlock(map);
1336: return(KERN_FAILURE);
1337: }
1338:
1339: /*
1340: * Actions are rather different for wiring and unwiring,
1341: * so we have two separate cases.
1342: */
1343:
1344: if (access_type == VM_PROT_NONE) {
1345:
1346: vm_map_clip_start(map, entry, start);
1347:
1348: /*
1349: * Unwiring. First ensure that the range to be
1350: * unwired is really wired down.
1351: */
1352: while ((entry != vm_map_to_entry(map)) &&
1353: (entry->vme_start < end)) {
1354:
1355: if ((entry->wired_count == 0) ||
1356: ((entry->vme_end < end) &&
1357: ((entry->vme_next == vm_map_to_entry(map)) ||
1358: (entry->vme_next->vme_start > entry->vme_end))) ||
1359: (user_wire && (entry->user_wired_count == 0))) {
1360: vm_map_unlock(map);
1361: return(KERN_INVALID_ARGUMENT);
1362: }
1363: entry = entry->vme_next;
1364: }
1365:
1366: /*
1367: * Now decrement the wiring count for each region.
1368: * If a region becomes completely unwired,
1369: * unwire its physical pages and mappings.
1370: */
1371: entry = start_entry;
1372: while ((entry != vm_map_to_entry(map)) &&
1373: (entry->vme_start < end)) {
1374: vm_map_clip_end(map, entry, end);
1375:
1376: if (user_wire) {
1377: if (--(entry->user_wired_count) == 0)
1378: entry->wired_count--;
1379: }
1380: else {
1381: entry->wired_count--;
1382: }
1383:
1384: if (entry->wired_count == 0)
1385: vm_fault_unwire(map, entry);
1386:
1387: entry = entry->vme_next;
1388: }
1389: }
1390:
1391: else {
1392: /*
1393: * Wiring. We must do this in two passes:
1394: *
1395: * 1. Holding the write lock, we create any shadow
1396: * or zero-fill objects that need to be created.
1397: * Then we clip each map entry to the region to be
1398: * wired and increment its wiring count. We
1399: * create objects before clipping the map entries
1400: * to avoid object proliferation.
1401: *
1402: * 2. We downgrade to a read lock, and call
1403: * vm_fault_wire to fault in the pages for any
1404: * newly wired area (wired_count is 1).
1405: *
1406: * Downgrading to a read lock for vm_fault_wire avoids
1407: * a possible deadlock with another thread that may have
1408: * faulted on one of the pages to be wired (it would mark
1409: * the page busy, blocking us, then in turn block on the
1410: * map lock that we hold). Because of problems in the
1411: * recursive lock package, we cannot upgrade to a write
1412: * lock in vm_map_lookup. Thus, any actions that require
1413: * the write lock must be done beforehand. Because we
1414: * keep the read lock on the map, the copy-on-write
1415: * status of the entries we modify here cannot change.
1416: */
1417:
1418: /*
1419: * Pass 1.
1420: */
1421: while ((entry != vm_map_to_entry(map)) &&
1422: (entry->vme_start < end)) {
1423: vm_map_clip_end(map, entry, end);
1424:
1425: if (entry->wired_count == 0) {
1426:
1427: /*
1428: * Perform actions of vm_map_lookup that need
1429: * the write lock on the map: create a shadow
1430: * object for a copy-on-write region, or an
1431: * object for a zero-fill region.
1432: */
1433: if (entry->needs_copy &&
1434: ((entry->protection & VM_PROT_WRITE) != 0)) {
1435:
1436: vm_object_shadow(&entry->object.vm_object,
1437: &entry->offset,
1438: (vm_size_t)(entry->vme_end
1439: - entry->vme_start));
1440: entry->needs_copy = FALSE;
1441: }
1442: if (entry->object.vm_object == VM_OBJECT_NULL) {
1443: entry->object.vm_object =
1444: vm_object_allocate(
1445: (vm_size_t)(entry->vme_end
1446: - entry->vme_start));
1447: entry->offset = (vm_offset_t)0;
1448: }
1449: }
1450: vm_map_clip_start(map, entry, start);
1451: vm_map_clip_end(map, entry, end);
1452:
1453: if (user_wire) {
1454: if ((entry->user_wired_count)++ == 0)
1455: entry->wired_count++;
1456: }
1457: else {
1458: entry->wired_count++;
1459: }
1460:
1461: /*
1462: * Check for holes and protection mismatch.
1463: * Holes: Next entry should be contiguous unless
1464: * this is the end of the region.
1465: * Protection: Access requested must be allowed.
1466: */
1467: if (((entry->vme_end < end) &&
1468: ((entry->vme_next == vm_map_to_entry(map)) ||
1469: (entry->vme_next->vme_start > entry->vme_end))) ||
1470: ((entry->protection & access_type) != access_type)) {
1471: /*
1472: * Found a hole or protection problem.
1473: * Object creation actions
1474: * do not need to be undone, but the
1475: * wired counts need to be restored.
1476: */
1477: while ((entry != vm_map_to_entry(map)) &&
1478: (entry->vme_end > start)) {
1479: if (user_wire) {
1480: if (--(entry->user_wired_count) == 0)
1481: entry->wired_count--;
1482: }
1483: else {
1484: entry->wired_count--;
1485: }
1486:
1487: entry = entry->vme_prev;
1488: }
1489:
1490: vm_map_unlock(map);
1491: return(KERN_FAILURE);
1492: }
1493: entry = entry->vme_next;
1494: }
1495:
1496: /*
1497: * Pass 2.
1498: */
1499:
1500: /*
1501: * HACK HACK HACK HACK
1502: *
1503: * If we are wiring in the kernel map or a submap of it,
1504: * unlock the map to avoid deadlocks. We trust that the
1505: * kernel threads are well-behaved, and therefore will
1506: * not do anything destructive to this region of the map
1507: * while we have it unlocked. We cannot trust user threads
1508: * to do the same.
1509: *
1510: * HACK HACK HACK HACK
1511: */
1512: if (vm_map_pmap(map) == kernel_pmap) {
1513: vm_map_unlock(map); /* trust me ... */
1514: }
1515: else {
1516: vm_map_lock_set_recursive(map);
1517: vm_map_lock_write_to_read(map);
1518: }
1519:
1520: entry = start_entry;
1521: while (entry != vm_map_to_entry(map) &&
1522: entry->vme_start < end) {
1523: /*
1524: * Wiring cases:
1525: * Kernel: wired == 1 && user_wired == 0
1526: * User: wired == 1 && user_wired == 1
1527: *
1528: * Don't need to wire if either is > 1. wired = 0 &&
1529: * user_wired == 1 can't happen.
1530: */
1531:
1532: /*
1533: * XXX This assumes that the faults always succeed.
1534: */
1535: if ((entry->wired_count == 1) &&
1536: (entry->user_wired_count <= 1)) {
1537: vm_fault_wire(map, entry);
1538: }
1539: entry = entry->vme_next;
1540: }
1541:
1542: if (vm_map_pmap(map) == kernel_pmap) {
1543: vm_map_lock(map);
1544: }
1545: else {
1546: vm_map_lock_clear_recursive(map);
1547: }
1548: }
1549:
1550: vm_map_unlock(map);
1551:
1552: return(KERN_SUCCESS);
1553: }
1554:
1555: /*
1556: * vm_map_entry_delete: [ internal use only ]
1557: *
1558: * Deallocate the given entry from the target map.
1559: */
1560: void vm_map_entry_delete(map, entry)
1561: register vm_map_t map;
1562: register vm_map_entry_t entry;
1563: {
1564: register vm_offset_t s, e;
1565: register vm_object_t object;
1566: extern vm_object_t kernel_object;
1567:
1568: s = entry->vme_start;
1569: e = entry->vme_end;
1570:
1571: /*Check if projected buffer*/
1572: if (map != kernel_map && entry->projected_on != 0) {
1573: /*Check if projected kernel entry is persistent;
1574: may only manipulate directly if it is*/
1575: if (entry->projected_on->projected_on == 0)
1576: entry->wired_count = 0; /*Avoid unwire fault*/
1577: else
1578: return;
1579: }
1580:
1581: /*
1582: * Get the object. Null objects cannot have pmap entries.
1583: */
1584:
1585: if ((object = entry->object.vm_object) != VM_OBJECT_NULL) {
1586:
1587: /*
1588: * Unwire before removing addresses from the pmap;
1589: * otherwise, unwiring will put the entries back in
1590: * the pmap.
1591: */
1592:
1593: if (entry->wired_count != 0) {
1594: vm_fault_unwire(map, entry);
1595: entry->wired_count = 0;
1596: entry->user_wired_count = 0;
1597: }
1598:
1599: /*
1600: * If the object is shared, we must remove
1601: * *all* references to this data, since we can't
1602: * find all of the physical maps which are sharing
1603: * it.
1604: */
1605:
1606: if (object == kernel_object) {
1607: vm_object_lock(object);
1608: vm_object_page_remove(object, entry->offset,
1609: entry->offset + (e - s));
1610: vm_object_unlock(object);
1611: } else if (entry->is_shared) {
1612: vm_object_pmap_remove(object,
1613: entry->offset,
1614: entry->offset + (e - s));
1615: }
1616: else {
1617: pmap_remove(map->pmap, s, e);
1618: }
1619: }
1620:
1621: /*
1622: * Deallocate the object only after removing all
1623: * pmap entries pointing to its pages.
1624: */
1625:
1626: if (entry->is_sub_map)
1627: vm_map_deallocate(entry->object.sub_map);
1628: else
1629: vm_object_deallocate(entry->object.vm_object);
1630:
1631: vm_map_entry_unlink(map, entry);
1632: map->size -= e - s;
1633:
1634: vm_map_entry_dispose(map, entry);
1635: }
1636:
1637: /*
1638: * vm_map_delete: [ internal use only ]
1639: *
1640: * Deallocates the given address range from the target
1641: * map.
1642: */
1643:
1644: kern_return_t vm_map_delete(map, start, end)
1645: register vm_map_t map;
1646: register vm_offset_t start;
1647: register vm_offset_t end;
1648: {
1649: vm_map_entry_t entry;
1650: vm_map_entry_t first_entry;
1651:
1652: /*
1653: * Find the start of the region, and clip it
1654: */
1655:
1656: if (!vm_map_lookup_entry(map, start, &first_entry))
1657: entry = first_entry->vme_next;
1658: else {
1659: entry = first_entry;
1660: #if NORMA_IPC_xxx
1661: /*
1662: * XXX Had to disable this code because:
1663:
1664: _vm_map_delete(c0804b78,c2198000,c219a000,0,c219a000)+df
1665: [vm/vm_map.c:2007]
1666: _vm_map_remove(c0804b78,c2198000,c219a000,c0817834,
1667: c081786c)+42 [vm/vm_map.c:2094]
1668: _kmem_io_map_deallocate(c0804b78,c2198000,2000,c0817834,
1669: c081786c)+43 [vm/vm_kern.c:818]
1670: _device_write_dealloc(c081786c)+117 [device/ds_routines.c:814]
1671: _ds_write_done(c081786c,0)+2e [device/ds_routines.c:848]
1672: _io_done_thread_continue(c08150c0,c21d4e14,c21d4e30,c08150c0,
1673: c080c114)+14 [device/ds_routines.c:1350]
1674:
1675: */
1676: if (start > entry->vme_start
1677: && end == entry->vme_end
1678: && ! entry->wired_count /* XXX ??? */
1679: && ! entry->is_shared
1680: && ! entry->projected_on
1681: && ! entry->is_sub_map) {
1682: extern vm_object_t kernel_object;
1683: register vm_object_t object = entry->object.vm_object;
1684:
1685: /*
1686: * The region to be deleted lives at the end
1687: * of this entry, and thus all we have to do is
1688: * truncate the entry.
1689: *
1690: * This special case is necessary if we want
1691: * coalescing to do us any good.
1692: *
1693: * XXX Do we have to adjust object size?
1694: */
1695: if (object == kernel_object) {
1696: vm_object_lock(object);
1697: vm_object_page_remove(object,
1698: entry->offset + start,
1699: entry->offset +
1700: (end - start));
1701: vm_object_unlock(object);
1702: } else if (entry->is_shared) {
1703: vm_object_pmap_remove(object,
1704: entry->offset + start,
1705: entry->offset +
1706: (end - start));
1707: } else {
1708: pmap_remove(map->pmap, start, end);
1709: }
1710: object->size -= (end - start); /* XXX */
1711:
1712: entry->vme_end = start;
1713: map->size -= (end - start);
1714:
1715: if (map->wait_for_space) {
1716: thread_wakeup((event_t) map);
1717: }
1718: return KERN_SUCCESS;
1719: }
1720: #endif /* NORMA_IPC */
1721: vm_map_clip_start(map, entry, start);
1722:
1723: /*
1724: * Fix the lookup hint now, rather than each
1725: * time though the loop.
1726: */
1727:
1728: SAVE_HINT(map, entry->vme_prev);
1729: }
1730:
1731: /*
1732: * Save the free space hint
1733: */
1734:
1735: if (map->first_free->vme_start >= start)
1736: map->first_free = entry->vme_prev;
1737:
1738: /*
1739: * Step through all entries in this region
1740: */
1741:
1742: while ((entry != vm_map_to_entry(map)) && (entry->vme_start < end)) {
1743: vm_map_entry_t next;
1744:
1745: vm_map_clip_end(map, entry, end);
1746:
1747: /*
1748: * If the entry is in transition, we must wait
1749: * for it to exit that state. It could be clipped
1750: * while we leave the map unlocked.
1751: */
1752: if(entry->in_transition) {
1753: /*
1754: * Say that we are waiting, and wait for entry.
1755: */
1756: entry->needs_wakeup = TRUE;
1757: vm_map_entry_wait(map, FALSE);
1758: vm_map_lock(map);
1759:
1760: /*
1761: * The entry could have been clipped or it
1762: * may not exist anymore. look it up again.
1763: */
1764: if(!vm_map_lookup_entry(map, start, &entry)) {
1765: entry = entry->vme_next;
1766: }
1767: continue;
1768: }
1769:
1770: next = entry->vme_next;
1771:
1772: vm_map_entry_delete(map, entry);
1773: entry = next;
1774: }
1775:
1776: if (map->wait_for_space)
1777: thread_wakeup((event_t) map);
1778:
1779: return(KERN_SUCCESS);
1780: }
1781:
1782: /*
1783: * vm_map_remove:
1784: *
1785: * Remove the given address range from the target map.
1786: * This is the exported form of vm_map_delete.
1787: */
1788: kern_return_t vm_map_remove(map, start, end)
1789: register vm_map_t map;
1790: register vm_offset_t start;
1791: register vm_offset_t end;
1792: {
1793: register kern_return_t result;
1794:
1795: vm_map_lock(map);
1796: VM_MAP_RANGE_CHECK(map, start, end);
1797: result = vm_map_delete(map, start, end);
1798: vm_map_unlock(map);
1799:
1800: return(result);
1801: }
1802:
1803:
1804: /*
1805: * vm_map_copy_steal_pages:
1806: *
1807: * Steal all the pages from a vm_map_copy page_list by copying ones
1808: * that have not already been stolen.
1809: */
1810: void
1811: vm_map_copy_steal_pages(copy)
1812: vm_map_copy_t copy;
1813: {
1814: register vm_page_t m, new_m;
1815: register int i;
1816: vm_object_t object;
1817:
1818: for (i = 0; i < copy->cpy_npages; i++) {
1819:
1820: /*
1821: * If the page is not tabled, then it's already stolen.
1822: */
1823: m = copy->cpy_page_list[i];
1824: if (!m->tabled)
1825: continue;
1826:
1827: /*
1828: * Page was not stolen, get a new
1829: * one and do the copy now.
1830: */
1831: while ((new_m = vm_page_grab(FALSE)) == VM_PAGE_NULL) {
1832: VM_PAGE_WAIT((void(*)()) 0);
1833: }
1834:
1835: vm_page_copy(m, new_m);
1836:
1837: object = m->object;
1838: vm_object_lock(object);
1839: vm_page_lock_queues();
1840: if (!m->active && !m->inactive)
1841: vm_page_activate(m);
1842: vm_page_unlock_queues();
1843: PAGE_WAKEUP_DONE(m);
1844: vm_object_paging_end(object);
1845: vm_object_unlock(object);
1846:
1847: copy->cpy_page_list[i] = new_m;
1848: }
1849: }
1850:
1851: /*
1852: * vm_map_copy_page_discard:
1853: *
1854: * Get rid of the pages in a page_list copy. If the pages are
1855: * stolen, they are freed. If the pages are not stolen, they
1856: * are unbusied, and associated state is cleaned up.
1857: */
1858: void vm_map_copy_page_discard(copy)
1859: vm_map_copy_t copy;
1860: {
1861: while (copy->cpy_npages > 0) {
1862: vm_page_t m;
1863:
1864: if((m = copy->cpy_page_list[--(copy->cpy_npages)]) !=
1865: VM_PAGE_NULL) {
1866:
1867: /*
1868: * If it's not in the table, then it's
1869: * a stolen page that goes back
1870: * to the free list. Else it belongs
1871: * to some object, and we hold a
1872: * paging reference on that object.
1873: */
1874: if (!m->tabled) {
1875: VM_PAGE_FREE(m);
1876: }
1877: else {
1878: vm_object_t object;
1879:
1880: object = m->object;
1881:
1882: vm_object_lock(object);
1883: vm_page_lock_queues();
1884: if (!m->active && !m->inactive)
1885: vm_page_activate(m);
1886: vm_page_unlock_queues();
1887:
1888: PAGE_WAKEUP_DONE(m);
1889: vm_object_paging_end(object);
1890: vm_object_unlock(object);
1891: }
1892: }
1893: }
1894: }
1895:
1896: /*
1897: * Routine: vm_map_copy_discard
1898: *
1899: * Description:
1900: * Dispose of a map copy object (returned by
1901: * vm_map_copyin).
1902: */
1903: void
1904: vm_map_copy_discard(copy)
1905: vm_map_copy_t copy;
1906: {
1907: free_next_copy:
1908: if (copy == VM_MAP_COPY_NULL)
1909: return;
1910:
1911: switch (copy->type) {
1912: case VM_MAP_COPY_ENTRY_LIST:
1913: while (vm_map_copy_first_entry(copy) !=
1914: vm_map_copy_to_entry(copy)) {
1915: vm_map_entry_t entry = vm_map_copy_first_entry(copy);
1916:
1917: vm_map_copy_entry_unlink(copy, entry);
1918: vm_object_deallocate(entry->object.vm_object);
1919: vm_map_copy_entry_dispose(copy, entry);
1920: }
1921: break;
1922: case VM_MAP_COPY_OBJECT:
1923: vm_object_deallocate(copy->cpy_object);
1924: break;
1925: case VM_MAP_COPY_PAGE_LIST:
1926:
1927: /*
1928: * To clean this up, we have to unbusy all the pages
1929: * and release the paging references in their objects.
1930: */
1931: if (copy->cpy_npages > 0)
1932: vm_map_copy_page_discard(copy);
1933:
1934: /*
1935: * If there's a continuation, abort it. The
1936: * abort routine releases any storage.
1937: */
1938: if (vm_map_copy_has_cont(copy)) {
1939:
1940: /*
1941: * Special case: recognize
1942: * vm_map_copy_discard_cont and optimize
1943: * here to avoid tail recursion.
1944: */
1945: if (copy->cpy_cont == vm_map_copy_discard_cont) {
1946: register vm_map_copy_t new_copy;
1947:
1948: new_copy = (vm_map_copy_t) copy->cpy_cont_args;
1949: zfree(vm_map_copy_zone, (vm_offset_t) copy);
1950: copy = new_copy;
1951: goto free_next_copy;
1952: }
1953: else {
1954: vm_map_copy_abort_cont(copy);
1955: }
1956: }
1957:
1958: break;
1959: }
1960: zfree(vm_map_copy_zone, (vm_offset_t) copy);
1961: }
1962:
1963: /*
1964: * Routine: vm_map_copy_copy
1965: *
1966: * Description:
1967: * Move the information in a map copy object to
1968: * a new map copy object, leaving the old one
1969: * empty.
1970: *
1971: * This is used by kernel routines that need
1972: * to look at out-of-line data (in copyin form)
1973: * before deciding whether to return SUCCESS.
1974: * If the routine returns FAILURE, the original
1975: * copy object will be deallocated; therefore,
1976: * these routines must make a copy of the copy
1977: * object and leave the original empty so that
1978: * deallocation will not fail.
1979: */
1980: vm_map_copy_t
1981: vm_map_copy_copy(copy)
1982: vm_map_copy_t copy;
1983: {
1984: vm_map_copy_t new_copy;
1985:
1986: if (copy == VM_MAP_COPY_NULL)
1987: return VM_MAP_COPY_NULL;
1988:
1989: /*
1990: * Allocate a new copy object, and copy the information
1991: * from the old one into it.
1992: */
1993:
1994: new_copy = (vm_map_copy_t) zalloc(vm_map_copy_zone);
1995: *new_copy = *copy;
1996:
1997: if (copy->type == VM_MAP_COPY_ENTRY_LIST) {
1998: /*
1999: * The links in the entry chain must be
2000: * changed to point to the new copy object.
2001: */
2002: vm_map_copy_first_entry(copy)->vme_prev
2003: = vm_map_copy_to_entry(new_copy);
2004: vm_map_copy_last_entry(copy)->vme_next
2005: = vm_map_copy_to_entry(new_copy);
2006: }
2007:
2008: /*
2009: * Change the old copy object into one that contains
2010: * nothing to be deallocated.
2011: */
2012: copy->type = VM_MAP_COPY_OBJECT;
2013: copy->cpy_object = VM_OBJECT_NULL;
2014:
2015: /*
2016: * Return the new object.
2017: */
2018: return new_copy;
2019: }
2020:
2021: /*
2022: * Routine: vm_map_copy_discard_cont
2023: *
2024: * Description:
2025: * A version of vm_map_copy_discard that can be called
2026: * as a continuation from a vm_map_copy page list.
2027: */
2028: kern_return_t vm_map_copy_discard_cont(cont_args, copy_result)
2029: vm_map_copyin_args_t cont_args;
2030: vm_map_copy_t *copy_result; /* OUT */
2031: {
2032: vm_map_copy_discard((vm_map_copy_t) cont_args);
2033: if (copy_result != (vm_map_copy_t *)0)
2034: *copy_result = VM_MAP_COPY_NULL;
2035: return(KERN_SUCCESS);
2036: }
2037:
2038: /*
2039: * Routine: vm_map_copy_overwrite
2040: *
2041: * Description:
2042: * Copy the memory described by the map copy
2043: * object (copy; returned by vm_map_copyin) onto
2044: * the specified destination region (dst_map, dst_addr).
2045: * The destination must be writeable.
2046: *
2047: * Unlike vm_map_copyout, this routine actually
2048: * writes over previously-mapped memory. If the
2049: * previous mapping was to a permanent (user-supplied)
2050: * memory object, it is preserved.
2051: *
2052: * The attributes (protection and inheritance) of the
2053: * destination region are preserved.
2054: *
2055: * If successful, consumes the copy object.
2056: * Otherwise, the caller is responsible for it.
2057: *
2058: * Implementation notes:
2059: * To overwrite temporary virtual memory, it is
2060: * sufficient to remove the previous mapping and insert
2061: * the new copy. This replacement is done either on
2062: * the whole region (if no permanent virtual memory
2063: * objects are embedded in the destination region) or
2064: * in individual map entries.
2065: *
2066: * To overwrite permanent virtual memory, it is
2067: * necessary to copy each page, as the external
2068: * memory management interface currently does not
2069: * provide any optimizations.
2070: *
2071: * Once a page of permanent memory has been overwritten,
2072: * it is impossible to interrupt this function; otherwise,
2073: * the call would be neither atomic nor location-independent.
2074: * The kernel-state portion of a user thread must be
2075: * interruptible.
2076: *
2077: * It may be expensive to forward all requests that might
2078: * overwrite permanent memory (vm_write, vm_copy) to
2079: * uninterruptible kernel threads. This routine may be
2080: * called by interruptible threads; however, success is
2081: * not guaranteed -- if the request cannot be performed
2082: * atomically and interruptibly, an error indication is
2083: * returned.
2084: */
2085: kern_return_t vm_map_copy_overwrite(dst_map, dst_addr, copy, interruptible)
2086: vm_map_t dst_map;
2087: vm_offset_t dst_addr;
2088: vm_map_copy_t copy;
2089: boolean_t interruptible;
2090: {
2091: vm_size_t size;
2092: vm_offset_t start;
2093: vm_map_entry_t tmp_entry;
2094: vm_map_entry_t entry;
2095:
2096: boolean_t contains_permanent_objects = FALSE;
2097:
2098: interruptible = FALSE; /* XXX */
2099:
2100: /*
2101: * Check for null copy object.
2102: */
2103:
2104: if (copy == VM_MAP_COPY_NULL)
2105: return(KERN_SUCCESS);
2106:
2107: /*
2108: * Only works for entry lists at the moment. Will
2109: * support page lists LATER.
2110: */
2111:
2112: #if NORMA_IPC
2113: vm_map_convert_from_page_list(copy);
2114: #else
2115: assert(copy->type == VM_MAP_COPY_ENTRY_LIST);
2116: #endif
2117:
2118: /*
2119: * Currently this routine only handles page-aligned
2120: * regions. Eventually, it should handle misalignments
2121: * by actually copying pages.
2122: */
2123:
2124: if (!page_aligned(copy->offset) ||
2125: !page_aligned(copy->size) ||
2126: !page_aligned(dst_addr))
2127: return(KERN_INVALID_ARGUMENT);
2128:
2129: size = copy->size;
2130:
2131: if (size == 0) {
2132: vm_map_copy_discard(copy);
2133: return(KERN_SUCCESS);
2134: }
2135:
2136: /*
2137: * Verify that the destination is all writeable
2138: * initially.
2139: */
2140: start_pass_1:
2141: vm_map_lock(dst_map);
2142: if (!vm_map_lookup_entry(dst_map, dst_addr, &tmp_entry)) {
2143: vm_map_unlock(dst_map);
2144: return(KERN_INVALID_ADDRESS);
2145: }
2146: vm_map_clip_start(dst_map, tmp_entry, dst_addr);
2147: for (entry = tmp_entry;;) {
2148: vm_size_t sub_size = (entry->vme_end - entry->vme_start);
2149: vm_map_entry_t next = entry->vme_next;
2150:
2151: if ( ! (entry->protection & VM_PROT_WRITE)) {
2152: vm_map_unlock(dst_map);
2153: return(KERN_PROTECTION_FAILURE);
2154: }
2155:
2156: /*
2157: * If the entry is in transition, we must wait
2158: * for it to exit that state. Anything could happen
2159: * when we unlock the map, so start over.
2160: */
2161: if (entry->in_transition) {
2162:
2163: /*
2164: * Say that we are waiting, and wait for entry.
2165: */
2166: entry->needs_wakeup = TRUE;
2167: vm_map_entry_wait(dst_map, FALSE);
2168:
2169: goto start_pass_1;
2170: }
2171:
2172: if (size <= sub_size)
2173: break;
2174:
2175: if ((next == vm_map_to_entry(dst_map)) ||
2176: (next->vme_start != entry->vme_end)) {
2177: vm_map_unlock(dst_map);
2178: return(KERN_INVALID_ADDRESS);
2179: }
2180:
2181:
2182: /*
2183: * Check for permanent objects in the destination.
2184: */
2185:
2186: if ((entry->object.vm_object != VM_OBJECT_NULL) &&
2187: !entry->object.vm_object->temporary)
2188: contains_permanent_objects = TRUE;
2189:
2190: size -= sub_size;
2191: entry = next;
2192: }
2193:
2194: /*
2195: * If there are permanent objects in the destination, then
2196: * the copy cannot be interrupted.
2197: */
2198:
2199: if (interruptible && contains_permanent_objects)
2200: return(KERN_FAILURE); /* XXX */
2201:
2202: /*
2203: * XXXO If there are no permanent objects in the destination,
2204: * XXXO and the source and destination map entry zones match,
2205: * XXXO and the destination map entry is not shared,
2206: * XXXO then the map entries can be deleted and replaced
2207: * XXXO with those from the copy. The following code is the
2208: * XXXO basic idea of what to do, but there are lots of annoying
2209: * XXXO little details about getting protection and inheritance
2210: * XXXO right. Should add protection, inheritance, and sharing checks
2211: * XXXO to the above pass and make sure that no wiring is involved.
2212: */
2213: /*
2214: * if (!contains_permanent_objects &&
2215: * copy->cpy_hdr.entries_pageable == dst_map->hdr.entries_pageable) {
2216: *
2217: * *
2218: * * Run over copy and adjust entries. Steal code
2219: * * from vm_map_copyout() to do this.
2220: * *
2221: *
2222: * tmp_entry = tmp_entry->vme_prev;
2223: * vm_map_delete(dst_map, dst_addr, dst_addr + copy->size);
2224: * vm_map_copy_insert(dst_map, tmp_entry, copy);
2225: *
2226: * vm_map_unlock(dst_map);
2227: * vm_map_copy_discard(copy);
2228: * }
2229: */
2230: /*
2231: *
2232: * Make a second pass, overwriting the data
2233: * At the beginning of each loop iteration,
2234: * the next entry to be overwritten is "tmp_entry"
2235: * (initially, the value returned from the lookup above),
2236: * and the starting address expected in that entry
2237: * is "start".
2238: */
2239:
2240: start = dst_addr;
2241:
2242: while (vm_map_copy_first_entry(copy) != vm_map_copy_to_entry(copy)) {
2243: vm_map_entry_t copy_entry = vm_map_copy_first_entry(copy);
2244: vm_size_t copy_size = (copy_entry->vme_end - copy_entry->vme_start);
2245: vm_object_t object;
2246:
2247: entry = tmp_entry;
2248: size = (entry->vme_end - entry->vme_start);
2249: /*
2250: * Make sure that no holes popped up in the
2251: * address map, and that the protection is
2252: * still valid, in case the map was unlocked
2253: * earlier.
2254: */
2255:
2256: if (entry->vme_start != start) {
2257: vm_map_unlock(dst_map);
2258: return(KERN_INVALID_ADDRESS);
2259: }
2260: assert(entry != vm_map_to_entry(dst_map));
2261:
2262: /*
2263: * Check protection again
2264: */
2265:
2266: if ( ! (entry->protection & VM_PROT_WRITE)) {
2267: vm_map_unlock(dst_map);
2268: return(KERN_PROTECTION_FAILURE);
2269: }
2270:
2271: /*
2272: * Adjust to source size first
2273: */
2274:
2275: if (copy_size < size) {
2276: vm_map_clip_end(dst_map, entry, entry->vme_start + copy_size);
2277: size = copy_size;
2278: }
2279:
2280: /*
2281: * Adjust to destination size
2282: */
2283:
2284: if (size < copy_size) {
2285: vm_map_copy_clip_end(copy, copy_entry,
2286: copy_entry->vme_start + size);
2287: copy_size = size;
2288: }
2289:
2290: assert((entry->vme_end - entry->vme_start) == size);
2291: assert((tmp_entry->vme_end - tmp_entry->vme_start) == size);
2292: assert((copy_entry->vme_end - copy_entry->vme_start) == size);
2293:
2294: /*
2295: * If the destination contains temporary unshared memory,
2296: * we can perform the copy by throwing it away and
2297: * installing the source data.
2298: */
2299:
2300: object = entry->object.vm_object;
2301: if (!entry->is_shared &&
2302: ((object == VM_OBJECT_NULL) || object->temporary)) {
2303: vm_object_t old_object = entry->object.vm_object;
2304: vm_offset_t old_offset = entry->offset;
2305:
2306: entry->object = copy_entry->object;
2307: entry->offset = copy_entry->offset;
2308: entry->needs_copy = copy_entry->needs_copy;
2309: entry->wired_count = 0;
2310: entry->user_wired_count = 0;
2311:
2312: vm_map_copy_entry_unlink(copy, copy_entry);
2313: vm_map_copy_entry_dispose(copy, copy_entry);
2314:
2315: vm_object_pmap_protect(
2316: old_object,
2317: old_offset,
2318: size,
2319: dst_map->pmap,
2320: tmp_entry->vme_start,
2321: VM_PROT_NONE);
2322:
2323: vm_object_deallocate(old_object);
2324:
2325: /*
2326: * Set up for the next iteration. The map
2327: * has not been unlocked, so the next
2328: * address should be at the end of this
2329: * entry, and the next map entry should be
2330: * the one following it.
2331: */
2332:
2333: start = tmp_entry->vme_end;
2334: tmp_entry = tmp_entry->vme_next;
2335: } else {
2336: vm_map_version_t version;
2337: vm_object_t dst_object = entry->object.vm_object;
2338: vm_offset_t dst_offset = entry->offset;
2339: kern_return_t r;
2340:
2341: /*
2342: * Take an object reference, and record
2343: * the map version information so that the
2344: * map can be safely unlocked.
2345: */
2346:
2347: vm_object_reference(dst_object);
2348:
2349: version.main_timestamp = dst_map->timestamp;
2350:
2351: vm_map_unlock(dst_map);
2352:
2353: /*
2354: * Copy as much as possible in one pass
2355: */
2356:
2357: copy_size = size;
2358: r = vm_fault_copy(
2359: copy_entry->object.vm_object,
2360: copy_entry->offset,
2361: ©_size,
2362: dst_object,
2363: dst_offset,
2364: dst_map,
2365: &version,
2366: FALSE /* XXX interruptible */ );
2367:
2368: /*
2369: * Release the object reference
2370: */
2371:
2372: vm_object_deallocate(dst_object);
2373:
2374: /*
2375: * If a hard error occurred, return it now
2376: */
2377:
2378: if (r != KERN_SUCCESS)
2379: return(r);
2380:
2381: if (copy_size != 0) {
2382: /*
2383: * Dispose of the copied region
2384: */
2385:
2386: vm_map_copy_clip_end(copy, copy_entry,
2387: copy_entry->vme_start + copy_size);
2388: vm_map_copy_entry_unlink(copy, copy_entry);
2389: vm_object_deallocate(copy_entry->object.vm_object);
2390: vm_map_copy_entry_dispose(copy, copy_entry);
2391: }
2392:
2393: /*
2394: * Pick up in the destination map where we left off.
2395: *
2396: * Use the version information to avoid a lookup
2397: * in the normal case.
2398: */
2399:
2400: start += copy_size;
2401: vm_map_lock(dst_map);
2402: if ((version.main_timestamp + 1) == dst_map->timestamp) {
2403: /* We can safely use saved tmp_entry value */
2404:
2405: vm_map_clip_end(dst_map, tmp_entry, start);
2406: tmp_entry = tmp_entry->vme_next;
2407: } else {
2408: /* Must do lookup of tmp_entry */
2409:
2410: if (!vm_map_lookup_entry(dst_map, start, &tmp_entry)) {
2411: vm_map_unlock(dst_map);
2412: return(KERN_INVALID_ADDRESS);
2413: }
2414: vm_map_clip_start(dst_map, tmp_entry, start);
2415: }
2416: }
2417:
2418: }
2419: vm_map_unlock(dst_map);
2420:
2421: /*
2422: * Throw away the vm_map_copy object
2423: */
2424: vm_map_copy_discard(copy);
2425:
2426: return(KERN_SUCCESS);
2427: }
2428:
2429: /*
2430: * Macro: vm_map_copy_insert
2431: *
2432: * Description:
2433: * Link a copy chain ("copy") into a map at the
2434: * specified location (after "where").
2435: * Side effects:
2436: * The copy chain is destroyed.
2437: * Warning:
2438: * The arguments are evaluated multiple times.
2439: */
2440: #define vm_map_copy_insert(map, where, copy) \
2441: MACRO_BEGIN \
2442: (((where)->vme_next)->vme_prev = vm_map_copy_last_entry(copy)) \
2443: ->vme_next = ((where)->vme_next); \
2444: ((where)->vme_next = vm_map_copy_first_entry(copy)) \
2445: ->vme_prev = (where); \
2446: (map)->hdr.nentries += (copy)->cpy_hdr.nentries; \
2447: zfree(vm_map_copy_zone, (vm_offset_t) copy); \
2448: MACRO_END
2449:
2450: /*
2451: * Routine: vm_map_copyout
2452: *
2453: * Description:
2454: * Copy out a copy chain ("copy") into newly-allocated
2455: * space in the destination map.
2456: *
2457: * If successful, consumes the copy object.
2458: * Otherwise, the caller is responsible for it.
2459: */
2460: kern_return_t vm_map_copyout(dst_map, dst_addr, copy)
2461: register
2462: vm_map_t dst_map;
2463: vm_offset_t *dst_addr; /* OUT */
2464: register
2465: vm_map_copy_t copy;
2466: {
2467: vm_size_t size;
2468: vm_size_t adjustment;
2469: vm_offset_t start;
2470: vm_offset_t vm_copy_start;
2471: vm_map_entry_t last;
2472: register
2473: vm_map_entry_t entry;
2474:
2475: /*
2476: * Check for null copy object.
2477: */
2478:
2479: if (copy == VM_MAP_COPY_NULL) {
2480: *dst_addr = 0;
2481: return(KERN_SUCCESS);
2482: }
2483:
2484: /*
2485: * Check for special copy object, created
2486: * by vm_map_copyin_object.
2487: */
2488:
2489: if (copy->type == VM_MAP_COPY_OBJECT) {
2490: vm_object_t object = copy->cpy_object;
2491: vm_size_t offset = copy->offset;
2492: vm_size_t tmp_size = copy->size;
2493: kern_return_t kr;
2494:
2495: *dst_addr = 0;
2496: kr = vm_map_enter(dst_map, dst_addr, tmp_size,
2497: (vm_offset_t) 0, TRUE,
2498: object, offset, FALSE,
2499: VM_PROT_DEFAULT, VM_PROT_ALL,
2500: VM_INHERIT_DEFAULT);
2501: if (kr != KERN_SUCCESS)
2502: return(kr);
2503: zfree(vm_map_copy_zone, (vm_offset_t) copy);
2504: return(KERN_SUCCESS);
2505: }
2506:
2507: if (copy->type == VM_MAP_COPY_PAGE_LIST)
2508: return(vm_map_copyout_page_list(dst_map, dst_addr, copy));
2509:
2510: /*
2511: * Find space for the data
2512: */
2513:
2514: vm_copy_start = trunc_page(copy->offset);
2515: size = round_page(copy->offset + copy->size) - vm_copy_start;
2516:
2517: StartAgain: ;
2518:
2519: vm_map_lock(dst_map);
2520: start = ((last = dst_map->first_free) == vm_map_to_entry(dst_map)) ?
2521: vm_map_min(dst_map) : last->vme_end;
2522:
2523: while (TRUE) {
2524: vm_map_entry_t next = last->vme_next;
2525: vm_offset_t end = start + size;
2526:
2527: if ((end > dst_map->max_offset) || (end < start)) {
2528: if (dst_map->wait_for_space) {
2529: if (size <= (dst_map->max_offset - dst_map->min_offset)) {
2530: assert_wait((event_t) dst_map, TRUE);
2531: vm_map_unlock(dst_map);
2532: thread_block((void (*)()) 0);
2533: goto StartAgain;
2534: }
2535: }
2536: vm_map_unlock(dst_map);
2537: return(KERN_NO_SPACE);
2538: }
2539:
2540: if ((next == vm_map_to_entry(dst_map)) ||
2541: (next->vme_start >= end))
2542: break;
2543:
2544: last = next;
2545: start = last->vme_end;
2546: }
2547:
2548: /*
2549: * Since we're going to just drop the map
2550: * entries from the copy into the destination
2551: * map, they must come from the same pool.
2552: */
2553:
2554: if (copy->cpy_hdr.entries_pageable != dst_map->hdr.entries_pageable) {
2555: /*
2556: * Mismatches occur when dealing with the default
2557: * pager.
2558: */
2559: zone_t old_zone;
2560: vm_map_entry_t next, new;
2561:
2562: /*
2563: * Find the zone that the copies were allocated from
2564: */
2565: old_zone = (copy->cpy_hdr.entries_pageable)
2566: ? vm_map_entry_zone
2567: : vm_map_kentry_zone;
2568: entry = vm_map_copy_first_entry(copy);
2569:
2570: /*
2571: * Reinitialize the copy so that vm_map_copy_entry_link
2572: * will work.
2573: */
2574: copy->cpy_hdr.nentries = 0;
2575: copy->cpy_hdr.entries_pageable = dst_map->hdr.entries_pageable;
2576: vm_map_copy_first_entry(copy) =
2577: vm_map_copy_last_entry(copy) =
2578: vm_map_copy_to_entry(copy);
2579:
2580: /*
2581: * Copy each entry.
2582: */
2583: while (entry != vm_map_copy_to_entry(copy)) {
2584: new = vm_map_copy_entry_create(copy);
2585: vm_map_entry_copy_full(new, entry);
2586: vm_map_copy_entry_link(copy,
2587: vm_map_copy_last_entry(copy),
2588: new);
2589: next = entry->vme_next;
2590: zfree(old_zone, (vm_offset_t) entry);
2591: entry = next;
2592: }
2593: }
2594:
2595: /*
2596: * Adjust the addresses in the copy chain, and
2597: * reset the region attributes.
2598: */
2599:
2600: adjustment = start - vm_copy_start;
2601: for (entry = vm_map_copy_first_entry(copy);
2602: entry != vm_map_copy_to_entry(copy);
2603: entry = entry->vme_next) {
2604: entry->vme_start += adjustment;
2605: entry->vme_end += adjustment;
2606:
2607: entry->inheritance = VM_INHERIT_DEFAULT;
2608: entry->protection = VM_PROT_DEFAULT;
2609: entry->max_protection = VM_PROT_ALL;
2610: entry->projected_on = 0;
2611:
2612: /*
2613: * If the entry is now wired,
2614: * map the pages into the destination map.
2615: */
2616: if (entry->wired_count != 0) {
2617: register vm_offset_t va;
2618: vm_offset_t offset;
2619: register vm_object_t object;
2620:
2621: object = entry->object.vm_object;
2622: offset = entry->offset;
2623: va = entry->vme_start;
2624:
2625: pmap_pageable(dst_map->pmap,
2626: entry->vme_start,
2627: entry->vme_end,
2628: TRUE);
2629:
2630: while (va < entry->vme_end) {
2631: register vm_page_t m;
2632:
2633: /*
2634: * Look up the page in the object.
2635: * Assert that the page will be found in the
2636: * top object:
2637: * either
2638: * the object was newly created by
2639: * vm_object_copy_slowly, and has
2640: * copies of all of the pages from
2641: * the source object
2642: * or
2643: * the object was moved from the old
2644: * map entry; because the old map
2645: * entry was wired, all of the pages
2646: * were in the top-level object.
2647: * (XXX not true if we wire pages for
2648: * reading)
2649: */
2650: vm_object_lock(object);
2651: vm_object_paging_begin(object);
2652:
2653: m = vm_page_lookup(object, offset);
2654: if (m == VM_PAGE_NULL || m->wire_count == 0 ||
2655: m->absent)
2656: panic("vm_map_copyout: wiring 0x%x", m);
2657:
2658: m->busy = TRUE;
2659: vm_object_unlock(object);
2660:
2661: PMAP_ENTER(dst_map->pmap, va, m,
2662: entry->protection, TRUE);
2663:
2664: vm_object_lock(object);
2665: PAGE_WAKEUP_DONE(m);
2666: /* the page is wired, so we don't have to activate */
2667: vm_object_paging_end(object);
2668: vm_object_unlock(object);
2669:
2670: offset += PAGE_SIZE;
2671: va += PAGE_SIZE;
2672: }
2673: }
2674:
2675:
2676: }
2677:
2678: /*
2679: * Correct the page alignment for the result
2680: */
2681:
2682: *dst_addr = start + (copy->offset - vm_copy_start);
2683:
2684: /*
2685: * Update the hints and the map size
2686: */
2687:
2688: if (dst_map->first_free == last)
2689: dst_map->first_free = vm_map_copy_last_entry(copy);
2690: SAVE_HINT(dst_map, vm_map_copy_last_entry(copy));
2691:
2692: dst_map->size += size;
2693:
2694: /*
2695: * Link in the copy
2696: */
2697:
2698: vm_map_copy_insert(dst_map, last, copy);
2699:
2700: vm_map_unlock(dst_map);
2701:
2702: /*
2703: * XXX If wiring_required, call vm_map_pageable
2704: */
2705:
2706: return(KERN_SUCCESS);
2707: }
2708:
2709: /*
2710: *
2711: * vm_map_copyout_page_list:
2712: *
2713: * Version of vm_map_copyout() for page list vm map copies.
2714: *
2715: */
2716: kern_return_t vm_map_copyout_page_list(dst_map, dst_addr, copy)
2717: register
2718: vm_map_t dst_map;
2719: vm_offset_t *dst_addr; /* OUT */
2720: register
2721: vm_map_copy_t copy;
2722: {
2723: vm_size_t size;
2724: vm_offset_t start;
2725: vm_offset_t end;
2726: vm_offset_t offset;
2727: vm_map_entry_t last;
2728: register
2729: vm_object_t object;
2730: vm_page_t *page_list, m;
2731: vm_map_entry_t entry;
2732: vm_offset_t old_last_offset;
2733: boolean_t cont_invoked, needs_wakeup = FALSE;
2734: kern_return_t result = KERN_SUCCESS;
2735: vm_map_copy_t orig_copy;
2736: vm_offset_t dst_offset;
2737: boolean_t must_wire;
2738:
2739: /*
2740: * Make sure the pages are stolen, because we are
2741: * going to put them in a new object. Assume that
2742: * all pages are identical to first in this regard.
2743: */
2744:
2745: page_list = ©->cpy_page_list[0];
2746: if ((*page_list)->tabled)
2747: vm_map_copy_steal_pages(copy);
2748:
2749: /*
2750: * Find space for the data
2751: */
2752:
2753: size = round_page(copy->offset + copy->size) -
2754: trunc_page(copy->offset);
2755: StartAgain:
2756: vm_map_lock(dst_map);
2757: must_wire = dst_map->wiring_required;
2758:
2759: last = dst_map->first_free;
2760: if (last == vm_map_to_entry(dst_map)) {
2761: start = vm_map_min(dst_map);
2762: } else {
2763: start = last->vme_end;
2764: }
2765:
2766: while (TRUE) {
2767: vm_map_entry_t next = last->vme_next;
2768: end = start + size;
2769:
2770: if ((end > dst_map->max_offset) || (end < start)) {
2771: if (dst_map->wait_for_space) {
2772: if (size <= (dst_map->max_offset -
2773: dst_map->min_offset)) {
2774: assert_wait((event_t) dst_map, TRUE);
2775: vm_map_unlock(dst_map);
2776: thread_block((void (*)()) 0);
2777: goto StartAgain;
2778: }
2779: }
2780: vm_map_unlock(dst_map);
2781: return(KERN_NO_SPACE);
2782: }
2783:
2784: if ((next == vm_map_to_entry(dst_map)) ||
2785: (next->vme_start >= end)) {
2786: break;
2787: }
2788:
2789: last = next;
2790: start = last->vme_end;
2791: }
2792:
2793: /*
2794: * See whether we can avoid creating a new entry (and object) by
2795: * extending one of our neighbors. [So far, we only attempt to
2796: * extend from below.]
2797: *
2798: * The code path below here is a bit twisted. If any of the
2799: * extension checks fails, we branch to create_object. If
2800: * it all works, we fall out the bottom and goto insert_pages.
2801: */
2802: if (last == vm_map_to_entry(dst_map) ||
2803: last->vme_end != start ||
2804: last->is_shared != FALSE ||
2805: last->is_sub_map != FALSE ||
2806: last->inheritance != VM_INHERIT_DEFAULT ||
2807: last->protection != VM_PROT_DEFAULT ||
2808: last->max_protection != VM_PROT_ALL ||
2809: (must_wire ? (last->wired_count != 1 ||
2810: last->user_wired_count != 1) :
2811: (last->wired_count != 0))) {
2812: goto create_object;
2813: }
2814:
2815: /*
2816: * If this entry needs an object, make one.
2817: */
2818: if (last->object.vm_object == VM_OBJECT_NULL) {
2819: object = vm_object_allocate(
2820: (vm_size_t)(last->vme_end - last->vme_start + size));
2821: last->object.vm_object = object;
2822: last->offset = 0;
2823: vm_object_lock(object);
2824: }
2825: else {
2826: vm_offset_t prev_offset = last->offset;
2827: vm_size_t prev_size = start - last->vme_start;
2828: vm_size_t new_size;
2829:
2830: /*
2831: * This is basically vm_object_coalesce.
2832: */
2833:
2834: object = last->object.vm_object;
2835: vm_object_lock(object);
2836:
2837: /*
2838: * Try to collapse the object first
2839: */
2840: vm_object_collapse(object);
2841:
2842: /*
2843: * Can't coalesce if pages not mapped to
2844: * last may be in use anyway:
2845: * . more than one reference
2846: * . paged out
2847: * . shadows another object
2848: * . has a copy elsewhere
2849: * . paging references (pages might be in page-list)
2850: */
2851:
2852: if ((object->ref_count > 1) ||
2853: object->pager_created ||
2854: (object->shadow != VM_OBJECT_NULL) ||
2855: (object->copy != VM_OBJECT_NULL) ||
2856: (object->paging_in_progress != 0)) {
2857: vm_object_unlock(object);
2858: goto create_object;
2859: }
2860:
2861: /*
2862: * Extend the object if necessary. Don't have to call
2863: * vm_object_page_remove because the pages aren't mapped,
2864: * and vm_page_replace will free up any old ones it encounters.
2865: */
2866: new_size = prev_offset + prev_size + size;
2867: if (new_size > object->size)
2868: object->size = new_size;
2869: }
2870:
2871: /*
2872: * Coalesced the two objects - can extend
2873: * the previous map entry to include the
2874: * new range.
2875: */
2876: dst_map->size += size;
2877: last->vme_end = end;
2878:
2879: SAVE_HINT(dst_map, last);
2880:
2881: goto insert_pages;
2882:
2883: create_object:
2884:
2885: /*
2886: * Create object
2887: */
2888: object = vm_object_allocate(size);
2889:
2890: /*
2891: * Create entry
2892: */
2893:
2894: entry = vm_map_entry_create(dst_map);
2895:
2896: entry->object.vm_object = object;
2897: entry->offset = 0;
2898:
2899: entry->is_shared = FALSE;
2900: entry->is_sub_map = FALSE;
2901: entry->needs_copy = FALSE;
2902:
2903: if (must_wire) {
2904: entry->wired_count = 1;
2905: entry->user_wired_count = 1;
2906: } else {
2907: entry->wired_count = 0;
2908: entry->user_wired_count = 0;
2909: }
2910:
2911: entry->in_transition = TRUE;
2912: entry->needs_wakeup = FALSE;
2913:
2914: entry->vme_start = start;
2915: entry->vme_end = start + size;
2916:
2917: entry->inheritance = VM_INHERIT_DEFAULT;
2918: entry->protection = VM_PROT_DEFAULT;
2919: entry->max_protection = VM_PROT_ALL;
2920: entry->projected_on = 0;
2921:
2922: vm_object_lock(object);
2923:
2924: /*
2925: * Update the hints and the map size
2926: */
2927: if (dst_map->first_free == last) {
2928: dst_map->first_free = entry;
2929: }
2930: SAVE_HINT(dst_map, entry);
2931: dst_map->size += size;
2932:
2933: /*
2934: * Link in the entry
2935: */
2936: vm_map_entry_link(dst_map, last, entry);
2937: last = entry;
2938:
2939: /*
2940: * Transfer pages into new object.
2941: * Scan page list in vm_map_copy.
2942: */
2943: insert_pages:
2944: dst_offset = copy->offset & PAGE_MASK;
2945: cont_invoked = FALSE;
2946: orig_copy = copy;
2947: last->in_transition = TRUE;
2948: old_last_offset = last->offset
2949: + (start - last->vme_start);
2950:
2951: vm_page_lock_queues();
2952:
2953: for (offset = 0; offset < size; offset += PAGE_SIZE) {
2954: m = *page_list;
2955: assert(m && !m->tabled);
2956:
2957: /*
2958: * Must clear busy bit in page before inserting it.
2959: * Ok to skip wakeup logic because nobody else
2960: * can possibly know about this page.
2961: * The page is dirty in its new object.
2962: */
2963:
2964: assert(!m->wanted);
2965:
2966: m->busy = FALSE;
2967: m->dirty = TRUE;
2968: vm_page_replace(m, object, old_last_offset + offset);
2969: if (must_wire) {
2970: vm_page_wire(m);
2971: PMAP_ENTER(dst_map->pmap,
2972: last->vme_start + m->offset - last->offset,
2973: m, last->protection, TRUE);
2974: } else {
2975: vm_page_activate(m);
2976: }
2977:
2978: *page_list++ = VM_PAGE_NULL;
2979: if (--(copy->cpy_npages) == 0 &&
2980: vm_map_copy_has_cont(copy)) {
2981: vm_map_copy_t new_copy;
2982:
2983: /*
2984: * Ok to unlock map because entry is
2985: * marked in_transition.
2986: */
2987: cont_invoked = TRUE;
2988: vm_page_unlock_queues();
2989: vm_object_unlock(object);
2990: vm_map_unlock(dst_map);
2991: vm_map_copy_invoke_cont(copy, &new_copy, &result);
2992:
2993: if (result == KERN_SUCCESS) {
2994:
2995: /*
2996: * If we got back a copy with real pages,
2997: * steal them now. Either all of the
2998: * pages in the list are tabled or none
2999: * of them are; mixtures are not possible.
3000: *
3001: * Save original copy for consume on
3002: * success logic at end of routine.
3003: */
3004: if (copy != orig_copy)
3005: vm_map_copy_discard(copy);
3006:
3007: if ((copy = new_copy) != VM_MAP_COPY_NULL) {
3008: page_list = ©->cpy_page_list[0];
3009: if ((*page_list)->tabled)
3010: vm_map_copy_steal_pages(copy);
3011: }
3012: }
3013: else {
3014: /*
3015: * Continuation failed.
3016: */
3017: vm_map_lock(dst_map);
3018: goto error;
3019: }
3020:
3021: vm_map_lock(dst_map);
3022: vm_object_lock(object);
3023: vm_page_lock_queues();
3024: }
3025: }
3026:
3027: vm_page_unlock_queues();
3028: vm_object_unlock(object);
3029:
3030: *dst_addr = start + dst_offset;
3031:
3032: /*
3033: * Clear the in transition bits. This is easy if we
3034: * didn't have a continuation.
3035: */
3036: error:
3037: if (!cont_invoked) {
3038: /*
3039: * We didn't unlock the map, so nobody could
3040: * be waiting.
3041: */
3042: last->in_transition = FALSE;
3043: assert(!last->needs_wakeup);
3044: needs_wakeup = FALSE;
3045: }
3046: else {
3047: if (!vm_map_lookup_entry(dst_map, start, &entry))
3048: panic("vm_map_copyout_page_list: missing entry");
3049:
3050: /*
3051: * Clear transition bit for all constituent entries that
3052: * were in the original entry. Also check for waiters.
3053: */
3054: while((entry != vm_map_to_entry(dst_map)) &&
3055: (entry->vme_start < end)) {
3056: assert(entry->in_transition);
3057: entry->in_transition = FALSE;
3058: if(entry->needs_wakeup) {
3059: entry->needs_wakeup = FALSE;
3060: needs_wakeup = TRUE;
3061: }
3062: entry = entry->vme_next;
3063: }
3064: }
3065:
3066: if (result != KERN_SUCCESS)
3067: vm_map_delete(dst_map, start, end);
3068:
3069: vm_map_unlock(dst_map);
3070:
3071: if (needs_wakeup)
3072: vm_map_entry_wakeup(dst_map);
3073:
3074: /*
3075: * Consume on success logic.
3076: */
3077: if (copy != orig_copy) {
3078: zfree(vm_map_copy_zone, (vm_offset_t) copy);
3079: }
3080: if (result == KERN_SUCCESS) {
3081: zfree(vm_map_copy_zone, (vm_offset_t) orig_copy);
3082: }
3083:
3084: return(result);
3085: }
3086:
3087: /*
3088: * Routine: vm_map_copyin
3089: *
3090: * Description:
3091: * Copy the specified region (src_addr, len) from the
3092: * source address space (src_map), possibly removing
3093: * the region from the source address space (src_destroy).
3094: *
3095: * Returns:
3096: * A vm_map_copy_t object (copy_result), suitable for
3097: * insertion into another address space (using vm_map_copyout),
3098: * copying over another address space region (using
3099: * vm_map_copy_overwrite). If the copy is unused, it
3100: * should be destroyed (using vm_map_copy_discard).
3101: *
3102: * In/out conditions:
3103: * The source map should not be locked on entry.
3104: */
3105: kern_return_t vm_map_copyin(src_map, src_addr, len, src_destroy, copy_result)
3106: vm_map_t src_map;
3107: vm_offset_t src_addr;
3108: vm_size_t len;
3109: boolean_t src_destroy;
3110: vm_map_copy_t *copy_result; /* OUT */
3111: {
3112: vm_map_entry_t tmp_entry; /* Result of last map lookup --
3113: * in multi-level lookup, this
3114: * entry contains the actual
3115: * vm_object/offset.
3116: */
3117:
3118: vm_offset_t src_start; /* Start of current entry --
3119: * where copy is taking place now
3120: */
3121: vm_offset_t src_end; /* End of entire region to be
3122: * copied */
3123:
3124: register
3125: vm_map_copy_t copy; /* Resulting copy */
3126:
3127: /*
3128: * Check for copies of zero bytes.
3129: */
3130:
3131: if (len == 0) {
3132: *copy_result = VM_MAP_COPY_NULL;
3133: return(KERN_SUCCESS);
3134: }
3135:
3136: /*
3137: * Compute start and end of region
3138: */
3139:
3140: src_start = trunc_page(src_addr);
3141: src_end = round_page(src_addr + len);
3142:
3143: /*
3144: * Check that the end address doesn't overflow
3145: */
3146:
3147: if (src_end <= src_start)
3148: if ((src_end < src_start) || (src_start != 0))
3149: return(KERN_INVALID_ADDRESS);
3150:
3151: /*
3152: * Allocate a header element for the list.
3153: *
3154: * Use the start and end in the header to
3155: * remember the endpoints prior to rounding.
3156: */
3157:
3158: copy = (vm_map_copy_t) zalloc(vm_map_copy_zone);
3159: vm_map_copy_first_entry(copy) =
3160: vm_map_copy_last_entry(copy) = vm_map_copy_to_entry(copy);
3161: copy->type = VM_MAP_COPY_ENTRY_LIST;
3162: copy->cpy_hdr.nentries = 0;
3163: copy->cpy_hdr.entries_pageable = TRUE;
3164:
3165: copy->offset = src_addr;
3166: copy->size = len;
3167:
3168: #define RETURN(x) \
3169: MACRO_BEGIN \
3170: vm_map_unlock(src_map); \
3171: vm_map_copy_discard(copy); \
3172: MACRO_RETURN(x); \
3173: MACRO_END
3174:
3175: /*
3176: * Find the beginning of the region.
3177: */
3178:
3179: vm_map_lock(src_map);
3180:
3181: if (!vm_map_lookup_entry(src_map, src_start, &tmp_entry))
3182: RETURN(KERN_INVALID_ADDRESS);
3183: vm_map_clip_start(src_map, tmp_entry, src_start);
3184:
3185: /*
3186: * Go through entries until we get to the end.
3187: */
3188:
3189: while (TRUE) {
3190: register
3191: vm_map_entry_t src_entry = tmp_entry; /* Top-level entry */
3192: vm_size_t src_size; /* Size of source
3193: * map entry (in both
3194: * maps)
3195: */
3196:
3197: register
3198: vm_object_t src_object; /* Object to copy */
3199: vm_offset_t src_offset;
3200:
3201: boolean_t src_needs_copy; /* Should source map
3202: * be made read-only
3203: * for copy-on-write?
3204: */
3205:
3206: register
3207: vm_map_entry_t new_entry; /* Map entry for copy */
3208: boolean_t new_entry_needs_copy; /* Will new entry be COW? */
3209:
3210: boolean_t was_wired; /* Was source wired? */
3211: vm_map_version_t version; /* Version before locks
3212: * dropped to make copy
3213: */
3214:
3215: /*
3216: * Verify that the region can be read.
3217: */
3218:
3219: if (! (src_entry->protection & VM_PROT_READ))
3220: RETURN(KERN_PROTECTION_FAILURE);
3221:
3222: /*
3223: * Clip against the endpoints of the entire region.
3224: */
3225:
3226: vm_map_clip_end(src_map, src_entry, src_end);
3227:
3228: src_size = src_entry->vme_end - src_start;
3229: src_object = src_entry->object.vm_object;
3230: src_offset = src_entry->offset;
3231: was_wired = (src_entry->wired_count != 0);
3232:
3233: /*
3234: * Create a new address map entry to
3235: * hold the result. Fill in the fields from
3236: * the appropriate source entries.
3237: */
3238:
3239: new_entry = vm_map_copy_entry_create(copy);
3240: vm_map_entry_copy(new_entry, src_entry);
3241:
3242: /*
3243: * Attempt non-blocking copy-on-write optimizations.
3244: */
3245:
3246: if (src_destroy &&
3247: (src_object == VM_OBJECT_NULL ||
3248: (src_object->temporary && !src_object->use_shared_copy)))
3249: {
3250: /*
3251: * If we are destroying the source, and the object
3252: * is temporary, and not shared writable,
3253: * we can move the object reference
3254: * from the source to the copy. The copy is
3255: * copy-on-write only if the source is.
3256: * We make another reference to the object, because
3257: * destroying the source entry will deallocate it.
3258: */
3259: vm_object_reference(src_object);
3260:
3261: /*
3262: * Copy is always unwired. vm_map_copy_entry
3263: * set its wired count to zero.
3264: */
3265:
3266: goto CopySuccessful;
3267: }
3268:
3269: if (!was_wired &&
3270: vm_object_copy_temporary(
3271: &new_entry->object.vm_object,
3272: &new_entry->offset,
3273: &src_needs_copy,
3274: &new_entry_needs_copy)) {
3275:
3276: new_entry->needs_copy = new_entry_needs_copy;
3277:
3278: /*
3279: * Handle copy-on-write obligations
3280: */
3281:
3282: if (src_needs_copy && !tmp_entry->needs_copy) {
3283: vm_object_pmap_protect(
3284: src_object,
3285: src_offset,
3286: src_size,
3287: (src_entry->is_shared ? PMAP_NULL
3288: : src_map->pmap),
3289: src_entry->vme_start,
3290: src_entry->protection &
3291: ~VM_PROT_WRITE);
3292:
3293: tmp_entry->needs_copy = TRUE;
3294: }
3295:
3296: /*
3297: * The map has never been unlocked, so it's safe to
3298: * move to the next entry rather than doing another
3299: * lookup.
3300: */
3301:
3302: goto CopySuccessful;
3303: }
3304:
3305: new_entry->needs_copy = FALSE;
3306:
3307: /*
3308: * Take an object reference, so that we may
3309: * release the map lock(s).
3310: */
3311:
3312: assert(src_object != VM_OBJECT_NULL);
3313: vm_object_reference(src_object);
3314:
3315: /*
3316: * Record the timestamp for later verification.
3317: * Unlock the map.
3318: */
3319:
3320: version.main_timestamp = src_map->timestamp;
3321: vm_map_unlock(src_map);
3322:
3323: /*
3324: * Perform the copy
3325: */
3326:
3327: if (was_wired) {
3328: vm_object_lock(src_object);
3329: (void) vm_object_copy_slowly(
3330: src_object,
3331: src_offset,
3332: src_size,
3333: FALSE,
3334: &new_entry->object.vm_object);
3335: new_entry->offset = 0;
3336: new_entry->needs_copy = FALSE;
3337: } else {
3338: kern_return_t result;
3339:
3340: result = vm_object_copy_strategically(src_object,
3341: src_offset,
3342: src_size,
3343: &new_entry->object.vm_object,
3344: &new_entry->offset,
3345: &new_entry_needs_copy);
3346:
3347: new_entry->needs_copy = new_entry_needs_copy;
3348:
3349:
3350: if (result != KERN_SUCCESS) {
3351: vm_map_copy_entry_dispose(copy, new_entry);
3352:
3353: vm_map_lock(src_map);
3354: RETURN(result);
3355: }
3356:
3357: }
3358:
3359: /*
3360: * Throw away the extra reference
3361: */
3362:
3363: vm_object_deallocate(src_object);
3364:
3365: /*
3366: * Verify that the map has not substantially
3367: * changed while the copy was being made.
3368: */
3369:
3370: vm_map_lock(src_map); /* Increments timestamp once! */
3371:
3372: if ((version.main_timestamp + 1) == src_map->timestamp)
3373: goto CopySuccessful;
3374:
3375: /*
3376: * Simple version comparison failed.
3377: *
3378: * Retry the lookup and verify that the
3379: * same object/offset are still present.
3380: *
3381: * [Note: a memory manager that colludes with
3382: * the calling task can detect that we have
3383: * cheated. While the map was unlocked, the
3384: * mapping could have been changed and restored.]
3385: */
3386:
3387: if (!vm_map_lookup_entry(src_map, src_start, &tmp_entry)) {
3388: vm_map_copy_entry_dispose(copy, new_entry);
3389: RETURN(KERN_INVALID_ADDRESS);
3390: }
3391:
3392: src_entry = tmp_entry;
3393: vm_map_clip_start(src_map, src_entry, src_start);
3394:
3395: if ((src_entry->protection & VM_PROT_READ) == VM_PROT_NONE)
3396: goto VerificationFailed;
3397:
3398: if (src_entry->vme_end < new_entry->vme_end)
3399: src_size = (new_entry->vme_end = src_entry->vme_end) - src_start;
3400:
3401: if ((src_entry->object.vm_object != src_object) ||
3402: (src_entry->offset != src_offset) ) {
3403:
3404: /*
3405: * Verification failed.
3406: *
3407: * Start over with this top-level entry.
3408: */
3409:
3410: VerificationFailed: ;
3411:
3412: vm_object_deallocate(new_entry->object.vm_object);
3413: vm_map_copy_entry_dispose(copy, new_entry);
3414: tmp_entry = src_entry;
3415: continue;
3416: }
3417:
3418: /*
3419: * Verification succeeded.
3420: */
3421:
3422: CopySuccessful: ;
3423:
3424: /*
3425: * Link in the new copy entry.
3426: */
3427:
3428: vm_map_copy_entry_link(copy, vm_map_copy_last_entry(copy),
3429: new_entry);
3430:
3431: /*
3432: * Determine whether the entire region
3433: * has been copied.
3434: */
3435: src_start = new_entry->vme_end;
3436: if ((src_start >= src_end) && (src_end != 0))
3437: break;
3438:
3439: /*
3440: * Verify that there are no gaps in the region
3441: */
3442:
3443: tmp_entry = src_entry->vme_next;
3444: if (tmp_entry->vme_start != src_start)
3445: RETURN(KERN_INVALID_ADDRESS);
3446: }
3447:
3448: /*
3449: * If the source should be destroyed, do it now, since the
3450: * copy was successful.
3451: */
3452: if (src_destroy)
3453: (void) vm_map_delete(src_map, trunc_page(src_addr), src_end);
3454:
3455: vm_map_unlock(src_map);
3456:
3457: *copy_result = copy;
3458: return(KERN_SUCCESS);
3459:
3460: #undef RETURN
3461: }
3462:
3463: /*
3464: * vm_map_copyin_object:
3465: *
3466: * Create a copy object from an object.
3467: * Our caller donates an object reference.
3468: */
3469:
3470: kern_return_t vm_map_copyin_object(object, offset, size, copy_result)
3471: vm_object_t object;
3472: vm_offset_t offset; /* offset of region in object */
3473: vm_size_t size; /* size of region in object */
3474: vm_map_copy_t *copy_result; /* OUT */
3475: {
3476: vm_map_copy_t copy; /* Resulting copy */
3477:
3478: /*
3479: * We drop the object into a special copy object
3480: * that contains the object directly. These copy objects
3481: * are distinguished by entries_pageable == FALSE
3482: * and null links.
3483: */
3484:
3485: copy = (vm_map_copy_t) zalloc(vm_map_copy_zone);
3486: vm_map_copy_first_entry(copy) =
3487: vm_map_copy_last_entry(copy) = VM_MAP_ENTRY_NULL;
3488: copy->type = VM_MAP_COPY_OBJECT;
3489: copy->cpy_object = object;
3490: copy->offset = offset;
3491: copy->size = size;
3492:
3493: *copy_result = copy;
3494: return(KERN_SUCCESS);
3495: }
3496:
3497: /*
3498: * vm_map_copyin_page_list_cont:
3499: *
3500: * Continuation routine for vm_map_copyin_page_list.
3501: *
3502: * If vm_map_copyin_page_list can't fit the entire vm range
3503: * into a single page list object, it creates a continuation.
3504: * When the target of the operation has used the pages in the
3505: * initial page list, it invokes the continuation, which calls
3506: * this routine. If an error happens, the continuation is aborted
3507: * (abort arg to this routine is TRUE). To avoid deadlocks, the
3508: * pages are discarded from the initial page list before invoking
3509: * the continuation.
3510: *
3511: * NOTE: This is not the same sort of continuation used by
3512: * the scheduler.
3513: */
3514:
3515: kern_return_t vm_map_copyin_page_list_cont(cont_args, copy_result)
3516: vm_map_copyin_args_t cont_args;
3517: vm_map_copy_t *copy_result; /* OUT */
3518: {
3519: kern_return_t result = 0; /* '=0' to quiet gcc warnings */
3520: register boolean_t do_abort, src_destroy, src_destroy_only;
3521:
3522: /*
3523: * Check for cases that only require memory destruction.
3524: */
3525: do_abort = (copy_result == (vm_map_copy_t *) 0);
3526: src_destroy = (cont_args->destroy_len != (vm_size_t) 0);
3527: src_destroy_only = (cont_args->src_len == (vm_size_t) 0);
3528:
3529: if (do_abort || src_destroy_only) {
3530: if (src_destroy)
3531: result = vm_map_remove(cont_args->map,
3532: cont_args->destroy_addr,
3533: cont_args->destroy_addr + cont_args->destroy_len);
3534: if (!do_abort)
3535: *copy_result = VM_MAP_COPY_NULL;
3536: }
3537: else {
3538: result = vm_map_copyin_page_list(cont_args->map,
3539: cont_args->src_addr, cont_args->src_len, src_destroy,
3540: cont_args->steal_pages, copy_result, TRUE);
3541:
3542: if (src_destroy && !cont_args->steal_pages &&
3543: vm_map_copy_has_cont(*copy_result)) {
3544: vm_map_copyin_args_t new_args;
3545: /*
3546: * Transfer old destroy info.
3547: */
3548: new_args = (vm_map_copyin_args_t)
3549: (*copy_result)->cpy_cont_args;
3550: new_args->destroy_addr = cont_args->destroy_addr;
3551: new_args->destroy_len = cont_args->destroy_len;
3552: }
3553: }
3554:
3555: vm_map_deallocate(cont_args->map);
3556: kfree((vm_offset_t)cont_args, sizeof(vm_map_copyin_args_data_t));
3557:
3558: return(result);
3559: }
3560:
3561: /*
3562: * vm_map_copyin_page_list:
3563: *
3564: * This is a variant of vm_map_copyin that copies in a list of pages.
3565: * If steal_pages is TRUE, the pages are only in the returned list.
3566: * If steal_pages is FALSE, the pages are busy and still in their
3567: * objects. A continuation may be returned if not all the pages fit:
3568: * the recipient of this copy_result must be prepared to deal with it.
3569: */
3570:
3571: kern_return_t vm_map_copyin_page_list(src_map, src_addr, len, src_destroy,
3572: steal_pages, copy_result, is_cont)
3573: vm_map_t src_map;
3574: vm_offset_t src_addr;
3575: vm_size_t len;
3576: boolean_t src_destroy;
3577: boolean_t steal_pages;
3578: vm_map_copy_t *copy_result; /* OUT */
3579: boolean_t is_cont;
3580: {
3581: vm_map_entry_t src_entry;
3582: vm_page_t m;
3583: vm_offset_t src_start;
3584: vm_offset_t src_end;
3585: vm_size_t src_size;
3586: register
3587: vm_object_t src_object;
3588: register
3589: vm_offset_t src_offset;
3590: vm_offset_t src_last_offset;
3591: register
3592: vm_map_copy_t copy; /* Resulting copy */
3593: kern_return_t result = KERN_SUCCESS;
3594: boolean_t need_map_lookup;
3595: vm_map_copyin_args_t cont_args;
3596:
3597: /*
3598: * If steal_pages is FALSE, this leaves busy pages in
3599: * the object. A continuation must be used if src_destroy
3600: * is true in this case (!steal_pages && src_destroy).
3601: *
3602: * XXX Still have a more general problem of what happens
3603: * XXX if the same page occurs twice in a list. Deadlock
3604: * XXX can happen if vm_fault_page was called. A
3605: * XXX possible solution is to use a continuation if vm_fault_page
3606: * XXX is called and we cross a map entry boundary.
3607: */
3608:
3609: /*
3610: * Check for copies of zero bytes.
3611: */
3612:
3613: if (len == 0) {
3614: *copy_result = VM_MAP_COPY_NULL;
3615: return(KERN_SUCCESS);
3616: }
3617:
3618: /*
3619: * Compute start and end of region
3620: */
3621:
3622: src_start = trunc_page(src_addr);
3623: src_end = round_page(src_addr + len);
3624:
3625: /*
3626: * Check that the end address doesn't overflow
3627: */
3628:
3629: if (src_end <= src_start && (src_end < src_start || src_start != 0)) {
3630: return KERN_INVALID_ADDRESS;
3631: }
3632:
3633: /*
3634: * Allocate a header element for the page list.
3635: *
3636: * Record original offset and size, as caller may not
3637: * be page-aligned.
3638: */
3639:
3640: copy = (vm_map_copy_t) zalloc(vm_map_copy_zone);
3641: copy->type = VM_MAP_COPY_PAGE_LIST;
3642: copy->cpy_npages = 0;
3643: copy->offset = src_addr;
3644: copy->size = len;
3645: copy->cpy_cont = ((kern_return_t (*)()) 0);
3646: copy->cpy_cont_args = (char *) VM_MAP_COPYIN_ARGS_NULL;
3647:
3648: /*
3649: * Find the beginning of the region.
3650: */
3651:
3652: do_map_lookup:
3653:
3654: vm_map_lock(src_map);
3655:
3656: if (!vm_map_lookup_entry(src_map, src_start, &src_entry)) {
3657: result = KERN_INVALID_ADDRESS;
3658: goto error;
3659: }
3660: need_map_lookup = FALSE;
3661:
3662: /*
3663: * Go through entries until we get to the end.
3664: */
3665:
3666: while (TRUE) {
3667:
3668: if (! (src_entry->protection & VM_PROT_READ)) {
3669: result = KERN_PROTECTION_FAILURE;
3670: goto error;
3671: }
3672:
3673: if (src_end > src_entry->vme_end)
3674: src_size = src_entry->vme_end - src_start;
3675: else
3676: src_size = src_end - src_start;
3677:
3678: src_object = src_entry->object.vm_object;
3679: src_offset = src_entry->offset +
3680: (src_start - src_entry->vme_start);
3681:
3682: /*
3683: * If src_object is NULL, allocate it now;
3684: * we're going to fault on it shortly.
3685: */
3686: if (src_object == VM_OBJECT_NULL) {
3687: src_object = vm_object_allocate((vm_size_t)
3688: src_entry->vme_end -
3689: src_entry->vme_start);
3690: src_entry->object.vm_object = src_object;
3691: }
3692:
3693: /*
3694: * Iterate over pages. Fault in ones that aren't present.
3695: */
3696: src_last_offset = src_offset + src_size;
3697: for (; (src_offset < src_last_offset && !need_map_lookup);
3698: src_offset += PAGE_SIZE, src_start += PAGE_SIZE) {
3699:
3700: if (copy->cpy_npages == VM_MAP_COPY_PAGE_LIST_MAX) {
3701: make_continuation:
3702: /*
3703: * At this point we have the max number of
3704: * pages busy for this thread that we're
3705: * willing to allow. Stop here and record
3706: * arguments for the remainder. Note:
3707: * this means that this routine isn't atomic,
3708: * but that's the breaks. Note that only
3709: * the first vm_map_copy_t that comes back
3710: * from this routine has the right offset
3711: * and size; those from continuations are
3712: * page rounded, and short by the amount
3713: * already done.
3714: *
3715: * Reset src_end so the src_destroy
3716: * code at the bottom doesn't do
3717: * something stupid.
3718: */
3719:
3720: cont_args = (vm_map_copyin_args_t)
3721: kalloc(sizeof(vm_map_copyin_args_data_t));
3722: cont_args->map = src_map;
3723: vm_map_reference(src_map);
3724: cont_args->src_addr = src_start;
3725: cont_args->src_len = len - (src_start - src_addr);
3726: if (src_destroy) {
3727: cont_args->destroy_addr = cont_args->src_addr;
3728: cont_args->destroy_len = cont_args->src_len;
3729: }
3730: else {
3731: cont_args->destroy_addr = (vm_offset_t) 0;
3732: cont_args->destroy_len = (vm_offset_t) 0;
3733: }
3734: cont_args->steal_pages = steal_pages;
3735:
3736: copy->cpy_cont_args = (char *) cont_args;
3737: copy->cpy_cont = vm_map_copyin_page_list_cont;
3738:
3739: src_end = src_start;
3740: vm_map_clip_end(src_map, src_entry, src_end);
3741: break;
3742: }
3743:
3744: /*
3745: * Try to find the page of data.
3746: */
3747: vm_object_lock(src_object);
3748: vm_object_paging_begin(src_object);
3749: if (((m = vm_page_lookup(src_object, src_offset)) !=
3750: VM_PAGE_NULL) && !m->busy && !m->fictitious &&
3751: !m->absent && !m->error) {
3752:
3753: /*
3754: * This is the page. Mark it busy
3755: * and keep the paging reference on
3756: * the object whilst we do our thing.
3757: */
3758: m->busy = TRUE;
3759:
3760: /*
3761: * Also write-protect the page, so
3762: * that the map`s owner cannot change
3763: * the data. The busy bit will prevent
3764: * faults on the page from succeeding
3765: * until the copy is released; after
3766: * that, the page can be re-entered
3767: * as writable, since we didn`t alter
3768: * the map entry. This scheme is a
3769: * cheap copy-on-write.
3770: *
3771: * Don`t forget the protection and
3772: * the page_lock value!
3773: *
3774: * If the source is being destroyed
3775: * AND not shared writable, we don`t
3776: * have to protect the page, since
3777: * we will destroy the (only)
3778: * writable mapping later.
3779: */
3780: if (!src_destroy ||
3781: src_object->use_shared_copy)
3782: {
3783: pmap_page_protect(m->phys_addr,
3784: src_entry->protection
3785: & ~m->page_lock
3786: & ~VM_PROT_WRITE);
3787: }
3788:
3789: }
3790: else {
3791: vm_prot_t result_prot;
3792: vm_page_t top_page;
3793: kern_return_t kr;
3794:
3795: /*
3796: * Have to fault the page in; must
3797: * unlock the map to do so. While
3798: * the map is unlocked, anything
3799: * can happen, we must lookup the
3800: * map entry before continuing.
3801: */
3802: vm_map_unlock(src_map);
3803: need_map_lookup = TRUE;
3804: retry:
3805: result_prot = VM_PROT_READ;
3806:
3807: kr = vm_fault_page(src_object, src_offset,
3808: VM_PROT_READ, FALSE, FALSE,
3809: &result_prot, &m, &top_page,
3810: FALSE, (void (*)()) 0);
3811: /*
3812: * Cope with what happened.
3813: */
3814: switch (kr) {
3815: case VM_FAULT_SUCCESS:
3816: break;
3817: case VM_FAULT_INTERRUPTED: /* ??? */
3818: case VM_FAULT_RETRY:
3819: vm_object_lock(src_object);
3820: vm_object_paging_begin(src_object);
3821: goto retry;
3822: case VM_FAULT_MEMORY_SHORTAGE:
3823: VM_PAGE_WAIT((void (*)()) 0);
3824: vm_object_lock(src_object);
3825: vm_object_paging_begin(src_object);
3826: goto retry;
3827: case VM_FAULT_FICTITIOUS_SHORTAGE:
3828: vm_page_more_fictitious();
3829: vm_object_lock(src_object);
3830: vm_object_paging_begin(src_object);
3831: goto retry;
3832: case VM_FAULT_MEMORY_ERROR:
3833: /*
3834: * Something broke. If this
3835: * is a continuation, return
3836: * a partial result if possible,
3837: * else fail the whole thing.
3838: * In the continuation case, the
3839: * next continuation call will
3840: * get this error if it persists.
3841: */
3842: vm_map_lock(src_map);
3843: if (is_cont &&
3844: copy->cpy_npages != 0)
3845: goto make_continuation;
3846:
3847: result = KERN_MEMORY_ERROR;
3848: goto error;
3849: }
3850:
3851: if (top_page != VM_PAGE_NULL) {
3852: vm_object_lock(src_object);
3853: VM_PAGE_FREE(top_page);
3854: vm_object_paging_end(src_object);
3855: vm_object_unlock(src_object);
3856: }
3857:
3858: /*
3859: * We do not need to write-protect
3860: * the page, since it cannot have
3861: * been in the pmap (and we did not
3862: * enter it above). The busy bit
3863: * will protect the page from being
3864: * entered as writable until it is
3865: * unlocked.
3866: */
3867:
3868: }
3869:
3870: /*
3871: * The page is busy, its object is locked, and
3872: * we have a paging reference on it. Either
3873: * the map is locked, or need_map_lookup is
3874: * TRUE.
3875: *
3876: * Put the page in the page list.
3877: */
3878: copy->cpy_page_list[copy->cpy_npages++] = m;
3879: vm_object_unlock(m->object);
3880: }
3881:
3882: /*
3883: * DETERMINE whether the entire region
3884: * has been copied.
3885: */
3886: if (src_start >= src_end && src_end != 0) {
3887: if (need_map_lookup)
3888: vm_map_lock(src_map);
3889: break;
3890: }
3891:
3892: /*
3893: * If need_map_lookup is TRUE, have to start over with
3894: * another map lookup. Note that we dropped the map
3895: * lock (to call vm_fault_page) above only in this case.
3896: */
3897: if (need_map_lookup)
3898: goto do_map_lookup;
3899:
3900: /*
3901: * Verify that there are no gaps in the region
3902: */
3903:
3904: src_start = src_entry->vme_end;
3905: src_entry = src_entry->vme_next;
3906: if (src_entry->vme_start != src_start) {
3907: result = KERN_INVALID_ADDRESS;
3908: goto error;
3909: }
3910: }
3911:
3912: /*
3913: * If steal_pages is true, make sure all
3914: * pages in the copy are not in any object
3915: * We try to remove them from the original
3916: * object, but we may have to copy them.
3917: *
3918: * At this point every page in the list is busy
3919: * and holds a paging reference to its object.
3920: * When we're done stealing, every page is busy,
3921: * and in no object (m->tabled == FALSE).
3922: */
3923: src_start = trunc_page(src_addr);
3924: if (steal_pages) {
3925: register int i;
3926: vm_offset_t unwire_end;
3927:
3928: unwire_end = src_start;
3929: for (i = 0; i < copy->cpy_npages; i++) {
3930:
3931: /*
3932: * Remove the page from its object if it
3933: * can be stolen. It can be stolen if:
3934: *
3935: * (1) The source is being destroyed,
3936: * the object is temporary, and
3937: * not shared.
3938: * (2) The page is not precious.
3939: *
3940: * The not shared check consists of two
3941: * parts: (a) there are no objects that
3942: * shadow this object. (b) it is not the
3943: * object in any shared map entries (i.e.,
3944: * use_shared_copy is not set).
3945: *
3946: * The first check (a) means that we can't
3947: * steal pages from objects that are not
3948: * at the top of their shadow chains. This
3949: * should not be a frequent occurrence.
3950: *
3951: * Stealing wired pages requires telling the
3952: * pmap module to let go of them.
3953: *
3954: * NOTE: stealing clean pages from objects
3955: * whose mappings survive requires a call to
3956: * the pmap module. Maybe later.
3957: */
3958: m = copy->cpy_page_list[i];
3959: src_object = m->object;
3960: vm_object_lock(src_object);
3961:
3962: if (src_destroy &&
3963: src_object->temporary &&
3964: (!src_object->shadowed) &&
3965: (!src_object->use_shared_copy) &&
3966: !m->precious) {
3967: vm_offset_t page_vaddr;
3968:
3969: page_vaddr = src_start + (i * PAGE_SIZE);
3970: if (m->wire_count > 0) {
3971:
3972: assert(m->wire_count == 1);
3973: /*
3974: * In order to steal a wired
3975: * page, we have to unwire it
3976: * first. We do this inline
3977: * here because we have the page.
3978: *
3979: * Step 1: Unwire the map entry.
3980: * Also tell the pmap module
3981: * that this piece of the
3982: * pmap is pageable.
3983: */
3984: vm_object_unlock(src_object);
3985: if (page_vaddr >= unwire_end) {
3986: if (!vm_map_lookup_entry(src_map,
3987: page_vaddr, &src_entry))
3988: panic("vm_map_copyin_page_list: missing wired map entry");
3989:
3990: vm_map_clip_start(src_map, src_entry,
3991: page_vaddr);
3992: vm_map_clip_end(src_map, src_entry,
3993: src_start + src_size);
3994:
3995: assert(src_entry->wired_count > 0);
3996: src_entry->wired_count = 0;
3997: src_entry->user_wired_count = 0;
3998: unwire_end = src_entry->vme_end;
3999: pmap_pageable(vm_map_pmap(src_map),
4000: page_vaddr, unwire_end, TRUE);
4001: }
4002:
4003: /*
4004: * Step 2: Unwire the page.
4005: * pmap_remove handles this for us.
4006: */
4007: vm_object_lock(src_object);
4008: }
4009:
4010: /*
4011: * Don't need to remove the mapping;
4012: * vm_map_delete will handle it.
4013: *
4014: * Steal the page. Setting the wire count
4015: * to zero is vm_page_unwire without
4016: * activating the page.
4017: */
4018: vm_page_lock_queues();
4019: vm_page_remove(m);
4020: if (m->wire_count > 0) {
4021: m->wire_count = 0;
4022: vm_page_wire_count--;
4023: } else {
4024: VM_PAGE_QUEUES_REMOVE(m);
4025: }
4026: vm_page_unlock_queues();
4027: }
4028: else {
4029: /*
4030: * Have to copy this page. Have to
4031: * unlock the map while copying,
4032: * hence no further page stealing.
4033: * Hence just copy all the pages.
4034: * Unlock the map while copying;
4035: * This means no further page stealing.
4036: */
4037: vm_object_unlock(src_object);
4038: vm_map_unlock(src_map);
4039:
4040: vm_map_copy_steal_pages(copy);
4041:
4042: vm_map_lock(src_map);
4043: break;
4044: }
4045:
4046: vm_object_paging_end(src_object);
4047: vm_object_unlock(src_object);
4048: }
4049:
4050: /*
4051: * If the source should be destroyed, do it now, since the
4052: * copy was successful.
4053: */
4054:
4055: if (src_destroy) {
4056: (void) vm_map_delete(src_map, src_start, src_end);
4057: }
4058: }
4059: else {
4060: /*
4061: * !steal_pages leaves busy pages in the map.
4062: * This will cause src_destroy to hang. Use
4063: * a continuation to prevent this.
4064: */
4065: if (src_destroy && !vm_map_copy_has_cont(copy)) {
4066: cont_args = (vm_map_copyin_args_t)
4067: kalloc(sizeof(vm_map_copyin_args_data_t));
4068: vm_map_reference(src_map);
4069: cont_args->map = src_map;
4070: cont_args->src_addr = (vm_offset_t) 0;
4071: cont_args->src_len = (vm_size_t) 0;
4072: cont_args->destroy_addr = src_start;
4073: cont_args->destroy_len = src_end - src_start;
4074: cont_args->steal_pages = FALSE;
4075:
4076: copy->cpy_cont_args = (char *) cont_args;
4077: copy->cpy_cont = vm_map_copyin_page_list_cont;
4078: }
4079:
4080: }
4081:
4082: vm_map_unlock(src_map);
4083:
4084: *copy_result = copy;
4085: return(result);
4086:
4087: error:
4088: vm_map_unlock(src_map);
4089: vm_map_copy_discard(copy);
4090: return(result);
4091: }
4092:
4093: /*
4094: * vm_map_fork:
4095: *
4096: * Create and return a new map based on the old
4097: * map, according to the inheritance values on the
4098: * regions in that map.
4099: *
4100: * The source map must not be locked.
4101: */
4102: vm_map_t vm_map_fork(old_map)
4103: vm_map_t old_map;
4104: {
4105: vm_map_t new_map;
4106: register
4107: vm_map_entry_t old_entry;
4108: register
4109: vm_map_entry_t new_entry;
4110: pmap_t new_pmap = pmap_create((vm_size_t) 0);
4111: vm_size_t new_size = 0;
4112: vm_size_t entry_size;
4113: register
4114: vm_object_t object;
4115:
4116: vm_map_lock(old_map);
4117:
4118: new_map = vm_map_create(new_pmap,
4119: old_map->min_offset,
4120: old_map->max_offset,
4121: old_map->hdr.entries_pageable);
4122:
4123: for (
4124: old_entry = vm_map_first_entry(old_map);
4125: old_entry != vm_map_to_entry(old_map);
4126: ) {
4127: if (old_entry->is_sub_map)
4128: panic("vm_map_fork: encountered a submap");
4129:
4130: entry_size = (old_entry->vme_end - old_entry->vme_start);
4131:
4132: switch (old_entry->inheritance) {
4133: case VM_INHERIT_NONE:
4134: break;
4135:
4136: case VM_INHERIT_SHARE:
4137: /*
4138: * New sharing code. New map entry
4139: * references original object. Temporary
4140: * objects use asynchronous copy algorithm for
4141: * future copies. First make sure we have
4142: * the right object. If we need a shadow,
4143: * or someone else already has one, then
4144: * make a new shadow and share it.
4145: */
4146:
4147: object = old_entry->object.vm_object;
4148: if (object == VM_OBJECT_NULL) {
4149: object = vm_object_allocate(
4150: (vm_size_t)(old_entry->vme_end -
4151: old_entry->vme_start));
4152: old_entry->offset = 0;
4153: old_entry->object.vm_object = object;
4154: assert(!old_entry->needs_copy);
4155: }
4156: else if (old_entry->needs_copy || object->shadowed ||
4157: (object->temporary && !old_entry->is_shared &&
4158: object->size > (vm_size_t)(old_entry->vme_end -
4159: old_entry->vme_start))) {
4160:
4161: assert(object->temporary);
4162: assert(!(object->shadowed && old_entry->is_shared));
4163: vm_object_shadow(
4164: &old_entry->object.vm_object,
4165: &old_entry->offset,
4166: (vm_size_t) (old_entry->vme_end -
4167: old_entry->vme_start));
4168:
4169: /*
4170: * If we're making a shadow for other than
4171: * copy on write reasons, then we have
4172: * to remove write permission.
4173: */
4174:
4175: if (!old_entry->needs_copy &&
4176: (old_entry->protection & VM_PROT_WRITE)) {
4177: pmap_protect(vm_map_pmap(old_map),
4178: old_entry->vme_start,
4179: old_entry->vme_end,
4180: old_entry->protection &
4181: ~VM_PROT_WRITE);
4182: }
4183: old_entry->needs_copy = FALSE;
4184: object = old_entry->object.vm_object;
4185: }
4186:
4187: /*
4188: * Set use_shared_copy to indicate that
4189: * object must use shared (delayed) copy-on
4190: * write. This is ignored for permanent objects.
4191: * Bump the reference count for the new entry
4192: */
4193:
4194: vm_object_lock(object);
4195: object->use_shared_copy = TRUE;
4196: object->ref_count++;
4197: vm_object_unlock(object);
4198:
4199: if (old_entry->projected_on != 0) {
4200: /*
4201: * If entry is projected buffer, clone the
4202: * entry exactly.
4203: */
4204:
4205: vm_map_entry_copy_full(new_entry, old_entry);
4206:
4207: } else {
4208: /*
4209: * Clone the entry, using object ref from above.
4210: * Mark both entries as shared.
4211: */
4212:
4213: new_entry = vm_map_entry_create(new_map);
4214: vm_map_entry_copy(new_entry, old_entry);
4215: old_entry->is_shared = TRUE;
4216: new_entry->is_shared = TRUE;
4217: }
4218:
4219: /*
4220: * Insert the entry into the new map -- we
4221: * know we're inserting at the end of the new
4222: * map.
4223: */
4224:
4225: vm_map_entry_link(
4226: new_map,
4227: vm_map_last_entry(new_map),
4228: new_entry);
4229:
4230: /*
4231: * Update the physical map
4232: */
4233:
4234: pmap_copy(new_map->pmap, old_map->pmap,
4235: new_entry->vme_start,
4236: entry_size,
4237: old_entry->vme_start);
4238:
4239: new_size += entry_size;
4240: break;
4241:
4242: case VM_INHERIT_COPY:
4243: if (old_entry->wired_count == 0) {
4244: boolean_t src_needs_copy;
4245: boolean_t new_entry_needs_copy;
4246:
4247: new_entry = vm_map_entry_create(new_map);
4248: vm_map_entry_copy(new_entry, old_entry);
4249:
4250: if (vm_object_copy_temporary(
4251: &new_entry->object.vm_object,
4252: &new_entry->offset,
4253: &src_needs_copy,
4254: &new_entry_needs_copy)) {
4255:
4256: /*
4257: * Handle copy-on-write obligations
4258: */
4259:
4260: if (src_needs_copy && !old_entry->needs_copy) {
4261: vm_object_pmap_protect(
4262: old_entry->object.vm_object,
4263: old_entry->offset,
4264: entry_size,
4265: (old_entry->is_shared ?
4266: PMAP_NULL :
4267: old_map->pmap),
4268: old_entry->vme_start,
4269: old_entry->protection &
4270: ~VM_PROT_WRITE);
4271:
4272: old_entry->needs_copy = TRUE;
4273: }
4274:
4275: new_entry->needs_copy = new_entry_needs_copy;
4276:
4277: /*
4278: * Insert the entry at the end
4279: * of the map.
4280: */
4281:
4282: vm_map_entry_link(new_map,
4283: vm_map_last_entry(new_map),
4284: new_entry);
4285:
4286:
4287: new_size += entry_size;
4288: break;
4289: }
4290:
4291: vm_map_entry_dispose(new_map, new_entry);
4292: }
4293:
4294: /* INNER BLOCK (copy cannot be optimized) */ {
4295:
4296: vm_offset_t start = old_entry->vme_start;
4297: vm_map_copy_t copy;
4298: vm_map_entry_t last = vm_map_last_entry(new_map);
4299:
4300: vm_map_unlock(old_map);
4301: if (vm_map_copyin(old_map,
4302: start,
4303: entry_size,
4304: FALSE,
4305: ©)
4306: != KERN_SUCCESS) {
4307: vm_map_lock(old_map);
4308: if (!vm_map_lookup_entry(old_map, start, &last))
4309: last = last->vme_next;
4310: old_entry = last;
4311: /*
4312: * For some error returns, want to
4313: * skip to the next element.
4314: */
4315:
4316: continue;
4317: }
4318:
4319: /*
4320: * Insert the copy into the new map
4321: */
4322:
4323: vm_map_copy_insert(new_map, last, copy);
4324: new_size += entry_size;
4325:
4326: /*
4327: * Pick up the traversal at the end of
4328: * the copied region.
4329: */
4330:
4331: vm_map_lock(old_map);
4332: start += entry_size;
4333: if (!vm_map_lookup_entry(old_map, start, &last))
4334: last = last->vme_next;
4335: else
4336: vm_map_clip_start(old_map, last, start);
4337: old_entry = last;
4338:
4339: continue;
4340: /* INNER BLOCK (copy cannot be optimized) */ }
4341: }
4342: old_entry = old_entry->vme_next;
4343: }
4344:
4345: new_map->size = new_size;
4346: vm_map_unlock(old_map);
4347:
4348: return(new_map);
4349: }
4350:
4351: /*
4352: * vm_map_lookup:
4353: *
4354: * Finds the VM object, offset, and
4355: * protection for a given virtual address in the
4356: * specified map, assuming a page fault of the
4357: * type specified.
4358: *
4359: * Returns the (object, offset, protection) for
4360: * this address, whether it is wired down, and whether
4361: * this map has the only reference to the data in question.
4362: * In order to later verify this lookup, a "version"
4363: * is returned.
4364: *
4365: * The map should not be locked; it will not be
4366: * locked on exit. In order to guarantee the
4367: * existence of the returned object, it is returned
4368: * locked.
4369: *
4370: * If a lookup is requested with "write protection"
4371: * specified, the map may be changed to perform virtual
4372: * copying operations, although the data referenced will
4373: * remain the same.
4374: */
4375: kern_return_t vm_map_lookup(var_map, vaddr, fault_type, out_version,
4376: object, offset, out_prot, wired)
4377: vm_map_t *var_map; /* IN/OUT */
4378: register vm_offset_t vaddr;
4379: register vm_prot_t fault_type;
4380:
4381: vm_map_version_t *out_version; /* OUT */
4382: vm_object_t *object; /* OUT */
4383: vm_offset_t *offset; /* OUT */
4384: vm_prot_t *out_prot; /* OUT */
4385: boolean_t *wired; /* OUT */
4386: {
4387: register vm_map_entry_t entry;
4388: register vm_map_t map = *var_map;
4389: register vm_prot_t prot;
4390:
4391: RetryLookup: ;
4392:
4393: /*
4394: * Lookup the faulting address.
4395: */
4396:
4397: vm_map_lock_read(map);
4398:
4399: #define RETURN(why) \
4400: { \
4401: vm_map_unlock_read(map); \
4402: return(why); \
4403: }
4404:
4405: /*
4406: * If the map has an interesting hint, try it before calling
4407: * full blown lookup routine.
4408: */
4409:
4410: simple_lock(&map->hint_lock);
4411: entry = map->hint;
4412: simple_unlock(&map->hint_lock);
4413:
4414: if ((entry == vm_map_to_entry(map)) ||
4415: (vaddr < entry->vme_start) || (vaddr >= entry->vme_end)) {
4416: vm_map_entry_t tmp_entry;
4417:
4418: /*
4419: * Entry was either not a valid hint, or the vaddr
4420: * was not contained in the entry, so do a full lookup.
4421: */
4422: if (!vm_map_lookup_entry(map, vaddr, &tmp_entry))
4423: RETURN(KERN_INVALID_ADDRESS);
4424:
4425: entry = tmp_entry;
4426: }
4427:
4428: /*
4429: * Handle submaps.
4430: */
4431:
4432: if (entry->is_sub_map) {
4433: vm_map_t old_map = map;
4434:
4435: *var_map = map = entry->object.sub_map;
4436: vm_map_unlock_read(old_map);
4437: goto RetryLookup;
4438: }
4439:
4440: /*
4441: * Check whether this task is allowed to have
4442: * this page.
4443: */
4444:
4445: prot = entry->protection;
4446:
4447: if ((fault_type & (prot)) != fault_type)
4448: if ((prot & VM_PROT_NOTIFY) && (fault_type & VM_PROT_WRITE)) {
4449: RETURN(KERN_WRITE_PROTECTION_FAILURE);
4450: } else {
4451: RETURN(KERN_PROTECTION_FAILURE);
4452: }
4453:
4454: /*
4455: * If this page is not pageable, we have to get
4456: * it for all possible accesses.
4457: */
4458:
4459: if (*wired = (entry->wired_count != 0))
4460: prot = fault_type = entry->protection;
4461:
4462: /*
4463: * If the entry was copy-on-write, we either ...
4464: */
4465:
4466: if (entry->needs_copy) {
4467: /*
4468: * If we want to write the page, we may as well
4469: * handle that now since we've got the map locked.
4470: *
4471: * If we don't need to write the page, we just
4472: * demote the permissions allowed.
4473: */
4474:
4475: if (fault_type & VM_PROT_WRITE) {
4476: /*
4477: * Make a new object, and place it in the
4478: * object chain. Note that no new references
4479: * have appeared -- one just moved from the
4480: * map to the new object.
4481: */
4482:
4483: if (vm_map_lock_read_to_write(map)) {
4484: goto RetryLookup;
4485: }
4486: map->timestamp++;
4487:
4488: vm_object_shadow(
4489: &entry->object.vm_object,
4490: &entry->offset,
4491: (vm_size_t) (entry->vme_end - entry->vme_start));
4492:
4493: entry->needs_copy = FALSE;
4494:
4495: vm_map_lock_write_to_read(map);
4496: }
4497: else {
4498: /*
4499: * We're attempting to read a copy-on-write
4500: * page -- don't allow writes.
4501: */
4502:
4503: prot &= (~VM_PROT_WRITE);
4504: }
4505: }
4506:
4507: /*
4508: * Create an object if necessary.
4509: */
4510: if (entry->object.vm_object == VM_OBJECT_NULL) {
4511:
4512: if (vm_map_lock_read_to_write(map)) {
4513: goto RetryLookup;
4514: }
4515:
4516: entry->object.vm_object = vm_object_allocate(
4517: (vm_size_t)(entry->vme_end - entry->vme_start));
4518: entry->offset = 0;
4519: vm_map_lock_write_to_read(map);
4520: }
4521:
4522: /*
4523: * Return the object/offset from this entry. If the entry
4524: * was copy-on-write or empty, it has been fixed up. Also
4525: * return the protection.
4526: */
4527:
4528: *offset = (vaddr - entry->vme_start) + entry->offset;
4529: *object = entry->object.vm_object;
4530: *out_prot = prot;
4531:
4532: /*
4533: * Lock the object to prevent it from disappearing
4534: */
4535:
4536: vm_object_lock(*object);
4537:
4538: /*
4539: * Save the version number and unlock the map.
4540: */
4541:
4542: out_version->main_timestamp = map->timestamp;
4543:
4544: RETURN(KERN_SUCCESS);
4545:
4546: #undef RETURN
4547: }
4548:
4549: /*
4550: * vm_map_verify:
4551: *
4552: * Verifies that the map in question has not changed
4553: * since the given version. If successful, the map
4554: * will not change until vm_map_verify_done() is called.
4555: */
4556: boolean_t vm_map_verify(map, version)
4557: register
4558: vm_map_t map;
4559: register
4560: vm_map_version_t *version; /* REF */
4561: {
4562: boolean_t result;
4563:
4564: vm_map_lock_read(map);
4565: result = (map->timestamp == version->main_timestamp);
4566:
4567: if (!result)
4568: vm_map_unlock_read(map);
4569:
4570: return(result);
4571: }
4572:
4573: /*
4574: * vm_map_verify_done:
4575: *
4576: * Releases locks acquired by a vm_map_verify.
4577: *
4578: * This is now a macro in vm/vm_map.h. It does a
4579: * vm_map_unlock_read on the map.
4580: */
4581:
4582: /*
4583: * vm_region:
4584: *
4585: * User call to obtain information about a region in
4586: * a task's address map.
4587: */
4588:
4589: kern_return_t vm_region(map, address, size,
4590: protection, max_protection,
4591: inheritance, is_shared,
4592: object_name, offset_in_object)
4593: vm_map_t map;
4594: vm_offset_t *address; /* IN/OUT */
4595: vm_size_t *size; /* OUT */
4596: vm_prot_t *protection; /* OUT */
4597: vm_prot_t *max_protection; /* OUT */
4598: vm_inherit_t *inheritance; /* OUT */
4599: boolean_t *is_shared; /* OUT */
4600: ipc_port_t *object_name; /* OUT */
4601: vm_offset_t *offset_in_object; /* OUT */
4602: {
4603: vm_map_entry_t tmp_entry;
4604: register
4605: vm_map_entry_t entry;
4606: register
4607: vm_offset_t tmp_offset;
4608: vm_offset_t start;
4609:
4610: if (map == VM_MAP_NULL)
4611: return(KERN_INVALID_ARGUMENT);
4612:
4613: start = *address;
4614:
4615: vm_map_lock_read(map);
4616: if (!vm_map_lookup_entry(map, start, &tmp_entry)) {
4617: if ((entry = tmp_entry->vme_next) == vm_map_to_entry(map)) {
4618: vm_map_unlock_read(map);
4619: return(KERN_NO_SPACE);
4620: }
4621: } else {
4622: entry = tmp_entry;
4623: }
4624:
4625: start = entry->vme_start;
4626: *protection = entry->protection;
4627: *max_protection = entry->max_protection;
4628: *inheritance = entry->inheritance;
4629: *address = start;
4630: *size = (entry->vme_end - start);
4631:
4632: tmp_offset = entry->offset;
4633:
4634:
4635: if (entry->is_sub_map) {
4636: *is_shared = FALSE;
4637: *object_name = IP_NULL;
4638: *offset_in_object = tmp_offset;
4639: } else {
4640: *is_shared = entry->is_shared;
4641: *object_name = vm_object_name(entry->object.vm_object);
4642: *offset_in_object = tmp_offset;
4643: }
4644:
4645: vm_map_unlock_read(map);
4646:
4647: return(KERN_SUCCESS);
4648: }
4649:
4650: /*
4651: * Routine: vm_map_simplify
4652: *
4653: * Description:
4654: * Attempt to simplify the map representation in
4655: * the vicinity of the given starting address.
4656: * Note:
4657: * This routine is intended primarily to keep the
4658: * kernel maps more compact -- they generally don't
4659: * benefit from the "expand a map entry" technology
4660: * at allocation time because the adjacent entry
4661: * is often wired down.
4662: */
4663: void vm_map_simplify(map, start)
4664: vm_map_t map;
4665: vm_offset_t start;
4666: {
4667: vm_map_entry_t this_entry;
4668: vm_map_entry_t prev_entry;
4669:
4670: vm_map_lock(map);
4671: if (
4672: (vm_map_lookup_entry(map, start, &this_entry)) &&
4673: ((prev_entry = this_entry->vme_prev) != vm_map_to_entry(map)) &&
4674:
4675: (prev_entry->vme_end == start) &&
4676:
4677: (prev_entry->is_shared == FALSE) &&
4678: (prev_entry->is_sub_map == FALSE) &&
4679:
4680: (this_entry->is_shared == FALSE) &&
4681: (this_entry->is_sub_map == FALSE) &&
4682:
4683: (prev_entry->inheritance == this_entry->inheritance) &&
4684: (prev_entry->protection == this_entry->protection) &&
4685: (prev_entry->max_protection == this_entry->max_protection) &&
4686: (prev_entry->wired_count == this_entry->wired_count) &&
4687: (prev_entry->user_wired_count == this_entry->user_wired_count) &&
4688:
4689: (prev_entry->needs_copy == this_entry->needs_copy) &&
4690:
4691: (prev_entry->object.vm_object == this_entry->object.vm_object) &&
4692: ((prev_entry->offset + (prev_entry->vme_end - prev_entry->vme_start))
4693: == this_entry->offset) &&
4694: (prev_entry->projected_on == 0) &&
4695: (this_entry->projected_on == 0)
4696: ) {
4697: if (map->first_free == this_entry)
4698: map->first_free = prev_entry;
4699:
4700: SAVE_HINT(map, prev_entry);
4701: vm_map_entry_unlink(map, this_entry);
4702: prev_entry->vme_end = this_entry->vme_end;
4703: vm_object_deallocate(this_entry->object.vm_object);
4704: vm_map_entry_dispose(map, this_entry);
4705: }
4706: vm_map_unlock(map);
4707: }
4708:
4709:
4710: /*
4711: * Routine: vm_map_machine_attribute
4712: * Purpose:
4713: * Provide machine-specific attributes to mappings,
4714: * such as cachability etc. for machines that provide
4715: * them. NUMA architectures and machines with big/strange
4716: * caches will use this.
4717: * Note:
4718: * Responsibilities for locking and checking are handled here,
4719: * everything else in the pmap module. If any non-volatile
4720: * information must be kept, the pmap module should handle
4721: * it itself. [This assumes that attributes do not
4722: * need to be inherited, which seems ok to me]
4723: */
4724: kern_return_t vm_map_machine_attribute(map, address, size, attribute, value)
4725: vm_map_t map;
4726: vm_offset_t address;
4727: vm_size_t size;
4728: vm_machine_attribute_t attribute;
4729: vm_machine_attribute_val_t* value; /* IN/OUT */
4730: {
4731: kern_return_t ret;
4732:
4733: if (address < vm_map_min(map) ||
4734: (address + size) > vm_map_max(map))
4735: return KERN_INVALID_ARGUMENT;
4736:
4737: vm_map_lock(map);
4738:
4739: ret = pmap_attribute(map->pmap, address, size, attribute, value);
4740:
4741: vm_map_unlock(map);
4742:
4743: return ret;
4744: }
4745:
4746: #include <mach_kdb.h>
4747:
4748:
4749: #if MACH_KDB
4750:
4751: #define printf kdbprintf
4752:
4753: /*
4754: * vm_map_print: [ debug ]
4755: */
4756: void vm_map_print(map)
4757: register vm_map_t map;
4758: {
4759: register vm_map_entry_t entry;
4760: extern int indent;
4761:
4762: iprintf("Task map 0x%X: pmap=0x%X,",
4763: (vm_offset_t) map, (vm_offset_t) (map->pmap));
4764: printf("ref=%d,nentries=%d,", map->ref_count, map->hdr.nentries);
4765: printf("version=%d\n", map->timestamp);
4766: indent += 2;
4767: for (entry = vm_map_first_entry(map);
4768: entry != vm_map_to_entry(map);
4769: entry = entry->vme_next) {
4770: static char *inheritance_name[3] = { "share", "copy", "none"};
4771:
4772: iprintf("map entry 0x%X: ", (vm_offset_t) entry);
4773: printf("start=0x%X, end=0x%X, ",
4774: (vm_offset_t) entry->vme_start, (vm_offset_t) entry->vme_end);
4775: printf("prot=%X/%X/%s, ",
4776: entry->protection,
4777: entry->max_protection,
4778: inheritance_name[entry->inheritance]);
4779: if (entry->wired_count != 0) {
4780: printf("wired(");
4781: if (entry->user_wired_count != 0)
4782: printf("u");
4783: if (entry->wired_count >
4784: ((entry->user_wired_count == 0) ? 0 : 1))
4785: printf("k");
4786: printf(") ");
4787: }
4788: if (entry->in_transition) {
4789: printf("in transition");
4790: if (entry->needs_wakeup)
4791: printf("(wake request)");
4792: printf(", ");
4793: }
4794: if (entry->is_sub_map) {
4795: printf("submap=0x%X, offset=0x%X\n",
4796: (vm_offset_t) entry->object.sub_map,
4797: (vm_offset_t) entry->offset);
4798: } else {
4799: printf("object=0x%X, offset=0x%X",
4800: (vm_offset_t) entry->object.vm_object,
4801: (vm_offset_t) entry->offset);
4802: if (entry->is_shared)
4803: printf(", shared");
4804: if (entry->needs_copy)
4805: printf(", copy needed");
4806: printf("\n");
4807:
4808: if ((entry->vme_prev == vm_map_to_entry(map)) ||
4809: (entry->vme_prev->object.vm_object != entry->object.vm_object)) {
4810: indent += 2;
4811: vm_object_print(entry->object.vm_object);
4812: indent -= 2;
4813: }
4814: }
4815: }
4816: indent -= 2;
4817: }
4818:
4819: /*
4820: * Routine: vm_map_copy_print
4821: * Purpose:
4822: * Pretty-print a copy object for ddb.
4823: */
4824:
4825: void vm_map_copy_print(copy)
4826: vm_map_copy_t copy;
4827: {
4828: extern int indent;
4829: int i, npages;
4830:
4831: printf("copy object 0x%x\n", copy);
4832:
4833: indent += 2;
4834:
4835: iprintf("type=%d", copy->type);
4836: switch (copy->type) {
4837: case VM_MAP_COPY_ENTRY_LIST:
4838: printf("[entry_list]");
4839: break;
4840:
4841: case VM_MAP_COPY_OBJECT:
4842: printf("[object]");
4843: break;
4844:
4845: case VM_MAP_COPY_PAGE_LIST:
4846: printf("[page_list]");
4847: break;
4848:
4849: default:
4850: printf("[bad type]");
4851: break;
4852: }
4853: printf(", offset=0x%x", copy->offset);
4854: printf(", size=0x%x\n", copy->size);
4855:
4856: switch (copy->type) {
4857: case VM_MAP_COPY_ENTRY_LIST:
4858: /* XXX add stuff here */
4859: break;
4860:
4861: case VM_MAP_COPY_OBJECT:
4862: iprintf("object=0x%x\n", copy->cpy_object);
4863: break;
4864:
4865: case VM_MAP_COPY_PAGE_LIST:
4866: iprintf("npages=%d", copy->cpy_npages);
4867: printf(", cont=%x", copy->cpy_cont);
4868: printf(", cont_args=%x\n", copy->cpy_cont_args);
4869: if (copy->cpy_npages < 0) {
4870: npages = 0;
4871: } else if (copy->cpy_npages > VM_MAP_COPY_PAGE_LIST_MAX) {
4872: npages = VM_MAP_COPY_PAGE_LIST_MAX;
4873: } else {
4874: npages = copy->cpy_npages;
4875: }
4876: iprintf("copy->cpy_page_list[0..%d] = {", npages);
4877: for (i = 0; i < npages - 1; i++) {
4878: printf("0x%x, ", copy->cpy_page_list[i]);
4879: }
4880: if (npages > 0) {
4881: printf("0x%x", copy->cpy_page_list[npages - 1]);
4882: }
4883: printf("}\n");
4884: break;
4885: }
4886:
4887: indent -=2;
4888: }
4889: #endif /* MACH_KDB */
4890:
4891: #if NORMA_IPC
4892: /*
4893: * This should one day be eliminated;
4894: * we should always construct the right flavor of copy object
4895: * the first time. Troublesome areas include vm_read, where vm_map_copyin
4896: * is called without knowing whom the copy object is for.
4897: * There are also situations where we do want a lazy data structure
4898: * even if we are sending to a remote port...
4899: */
4900:
4901: /*
4902: * Convert a copy to a page list. The copy argument is in/out
4903: * because we probably have to allocate a new vm_map_copy structure.
4904: * We take responsibility for discarding the old structure and
4905: * use a continuation to do so. Postponing this discard ensures
4906: * that the objects containing the pages we've marked busy will stick
4907: * around.
4908: */
4909: kern_return_t
4910: vm_map_convert_to_page_list(caller_copy)
4911: vm_map_copy_t *caller_copy;
4912: {
4913: vm_map_entry_t entry, next_entry;
4914: vm_offset_t va;
4915: vm_offset_t offset;
4916: vm_object_t object;
4917: kern_return_t result;
4918: vm_map_copy_t copy, new_copy;
4919: int i, num_pages = 0;
4920:
4921: zone_t entry_zone;
4922:
4923: copy = *caller_copy;
4924:
4925: /*
4926: * We may not have to do anything,
4927: * or may not be able to do anything.
4928: */
4929: if (copy == VM_MAP_COPY_NULL || copy->type == VM_MAP_COPY_PAGE_LIST) {
4930: return KERN_SUCCESS;
4931: }
4932: if (copy->type == VM_MAP_COPY_OBJECT) {
4933: return vm_map_convert_to_page_list_from_object(caller_copy);
4934: }
4935: if (copy->type != VM_MAP_COPY_ENTRY_LIST) {
4936: panic("vm_map_convert_to_page_list: copy type %d!\n",
4937: copy->type);
4938: }
4939:
4940: /*
4941: * Allocate the new copy. Set its continuation to
4942: * discard the old one.
4943: */
4944: new_copy = (vm_map_copy_t) zalloc(vm_map_copy_zone);
4945: new_copy->type = VM_MAP_COPY_PAGE_LIST;
4946: new_copy->cpy_npages = 0;
4947: new_copy->offset = copy->offset;
4948: new_copy->size = copy->size;
4949: new_copy->cpy_cont = vm_map_copy_discard_cont;
4950: new_copy->cpy_cont_args = (char *) copy;
4951:
4952: /*
4953: * Iterate over entries.
4954: */
4955: for (entry = vm_map_copy_first_entry(copy);
4956: entry != vm_map_copy_to_entry(copy);
4957: entry = entry->vme_next) {
4958:
4959: object = entry->object.vm_object;
4960: offset = entry->offset;
4961: /*
4962: * Iterate over pages.
4963: */
4964: for (va = entry->vme_start;
4965: va < entry->vme_end;
4966: va += PAGE_SIZE, offset += PAGE_SIZE) {
4967:
4968: vm_page_t m;
4969:
4970: if (new_copy->cpy_npages == VM_MAP_COPY_PAGE_LIST_MAX) {
4971: /*
4972: * What a mess. We need a continuation
4973: * to do the page list, but also one
4974: * to discard the old copy. The right
4975: * thing to do is probably to copy
4976: * out the old copy into the kernel
4977: * map (or some temporary task holding
4978: * map if we're paranoid about large
4979: * copies), and then copyin the page
4980: * list that we really wanted with
4981: * src_destroy. LATER.
4982: */
4983: panic("vm_map_convert_to_page_list: num\n");
4984: }
4985:
4986: /*
4987: * Try to find the page of data.
4988: */
4989: vm_object_lock(object);
4990: vm_object_paging_begin(object);
4991: if (((m = vm_page_lookup(object, offset)) !=
4992: VM_PAGE_NULL) && !m->busy && !m->fictitious &&
4993: !m->absent && !m->error) {
4994:
4995: /*
4996: * This is the page. Mark it busy
4997: * and keep the paging reference on
4998: * the object whilst we do our thing.
4999: */
5000: m->busy = TRUE;
5001:
5002: /*
5003: * Also write-protect the page, so
5004: * that the map`s owner cannot change
5005: * the data. The busy bit will prevent
5006: * faults on the page from succeeding
5007: * until the copy is released; after
5008: * that, the page can be re-entered
5009: * as writable, since we didn`t alter
5010: * the map entry. This scheme is a
5011: * cheap copy-on-write.
5012: *
5013: * Don`t forget the protection and
5014: * the page_lock value!
5015: */
5016:
5017: pmap_page_protect(m->phys_addr,
5018: entry->protection
5019: & ~m->page_lock
5020: & ~VM_PROT_WRITE);
5021:
5022: }
5023: else {
5024: vm_prot_t result_prot;
5025: vm_page_t top_page;
5026: kern_return_t kr;
5027:
5028: retry:
5029: result_prot = VM_PROT_READ;
5030:
5031: kr = vm_fault_page(object, offset,
5032: VM_PROT_READ, FALSE, FALSE,
5033: &result_prot, &m, &top_page,
5034: FALSE, (void (*)()) 0);
5035: if (kr == VM_FAULT_MEMORY_SHORTAGE) {
5036: VM_PAGE_WAIT((void (*)()) 0);
5037: vm_object_lock(object);
5038: vm_object_paging_begin(object);
5039: goto retry;
5040: }
5041: if (kr != VM_FAULT_SUCCESS) {
5042: /* XXX what about data_error? */
5043: vm_object_lock(object);
5044: vm_object_paging_begin(object);
5045: goto retry;
5046: }
5047: if (top_page != VM_PAGE_NULL) {
5048: vm_object_lock(object);
5049: VM_PAGE_FREE(top_page);
5050: vm_object_paging_end(object);
5051: vm_object_unlock(object);
5052: }
5053: }
5054: assert(m);
5055: m->busy = TRUE;
5056: new_copy->cpy_page_list[new_copy->cpy_npages++] = m;
5057: vm_object_unlock(object);
5058: }
5059: }
5060:
5061: *caller_copy = new_copy;
5062: return KERN_SUCCESS;
5063: }
5064:
5065: kern_return_t
5066: vm_map_convert_to_page_list_from_object(caller_copy)
5067: vm_map_copy_t *caller_copy;
5068: {
5069: vm_object_t object;
5070: vm_offset_t offset;
5071: vm_map_copy_t copy, new_copy;
5072:
5073: copy = *caller_copy;
5074: assert(copy->type == VM_MAP_COPY_OBJECT);
5075: object = copy->cpy_object;
5076: assert(object->size == round_page(object->size));
5077:
5078: /*
5079: * Allocate the new copy. Set its continuation to
5080: * discard the old one.
5081: */
5082: new_copy = (vm_map_copy_t) zalloc(vm_map_copy_zone);
5083: new_copy->type = VM_MAP_COPY_PAGE_LIST;
5084: new_copy->cpy_npages = 0;
5085: new_copy->offset = copy->offset;
5086: new_copy->size = copy->size;
5087: new_copy->cpy_cont = vm_map_copy_discard_cont;
5088: new_copy->cpy_cont_args = (char *) copy;
5089:
5090: /*
5091: * XXX memory_object_lock_request can probably bust this
5092: * XXX See continuation comment in previous routine for solution.
5093: */
5094: assert(object->size <= VM_MAP_COPY_PAGE_LIST_MAX * PAGE_SIZE);
5095:
5096: for (offset = 0; offset < object->size; offset += PAGE_SIZE) {
5097: vm_page_t m;
5098:
5099: /*
5100: * Try to find the page of data.
5101: */
5102: vm_object_lock(object);
5103: vm_object_paging_begin(object);
5104: m = vm_page_lookup(object, offset);
5105: if ((m != VM_PAGE_NULL) && !m->busy && !m->fictitious &&
5106: !m->absent && !m->error) {
5107:
5108: /*
5109: * This is the page. Mark it busy
5110: * and keep the paging reference on
5111: * the object whilst we do our thing.
5112: */
5113: m->busy = TRUE;
5114: }
5115: else {
5116: vm_prot_t result_prot;
5117: vm_page_t top_page;
5118: kern_return_t kr;
5119:
5120: retry:
5121: result_prot = VM_PROT_READ;
5122:
5123: kr = vm_fault_page(object, offset,
5124: VM_PROT_READ, FALSE, FALSE,
5125: &result_prot, &m, &top_page,
5126: FALSE, (void (*)()) 0);
5127: if (kr == VM_FAULT_MEMORY_SHORTAGE) {
5128: VM_PAGE_WAIT((void (*)()) 0);
5129: vm_object_lock(object);
5130: vm_object_paging_begin(object);
5131: goto retry;
5132: }
5133: if (kr != VM_FAULT_SUCCESS) {
5134: /* XXX what about data_error? */
5135: vm_object_lock(object);
5136: vm_object_paging_begin(object);
5137: goto retry;
5138: }
5139:
5140: if (top_page != VM_PAGE_NULL) {
5141: vm_object_lock(object);
5142: VM_PAGE_FREE(top_page);
5143: vm_object_paging_end(object);
5144: vm_object_unlock(object);
5145: }
5146: }
5147: assert(m);
5148: m->busy = TRUE;
5149: new_copy->cpy_page_list[new_copy->cpy_npages++] = m;
5150: vm_object_unlock(object);
5151: }
5152:
5153: *caller_copy = new_copy;
5154: return (KERN_SUCCESS);
5155: }
5156:
5157: kern_return_t
5158: vm_map_convert_from_page_list(copy)
5159: vm_map_copy_t copy;
5160: {
5161: vm_object_t object;
5162: int i;
5163: vm_map_entry_t new_entry;
5164: vm_page_t *page_list;
5165:
5166: /*
5167: * Check type of copy object.
5168: */
5169: if (copy->type == VM_MAP_COPY_ENTRY_LIST) {
5170: return KERN_SUCCESS;
5171: }
5172: if (copy->type == VM_MAP_COPY_OBJECT) {
5173: printf("vm_map_convert_from_page_list: COPY_OBJECT?");
5174: return KERN_SUCCESS;
5175: }
5176: if (copy->type != VM_MAP_COPY_PAGE_LIST) {
5177: panic("vm_map_convert_from_page_list 0x%x %d",
5178: copy,
5179: copy->type);
5180: }
5181:
5182: /*
5183: * Make sure the pages are loose. This may be
5184: * a "Can't Happen", but just to be safe ...
5185: */
5186: page_list = ©->cpy_page_list[0];
5187: if ((*page_list)->tabled)
5188: vm_map_copy_steal_pages(copy);
5189:
5190: /*
5191: * Create object, and stuff pages into it.
5192: */
5193: object = vm_object_allocate(copy->cpy_npages);
5194: for (i = 0; i < copy->cpy_npages; i++) {
5195: register vm_page_t m = *page_list++;
5196: vm_page_insert(m, object, i * PAGE_SIZE);
5197: m->busy = FALSE;
5198: m->dirty = TRUE;
5199: vm_page_activate(m);
5200: }
5201:
5202: /*
5203: * XXX If this page list contained a continuation, then
5204: * XXX we're screwed. The right thing to do is probably do
5205: * XXX the copyout, and then copyin the entry list we really
5206: * XXX wanted.
5207: */
5208: if (vm_map_copy_has_cont(copy))
5209: panic("convert_from_page_list: continuation");
5210:
5211: /*
5212: * Change type of copy object
5213: */
5214: vm_map_copy_first_entry(copy) =
5215: vm_map_copy_last_entry(copy) = vm_map_copy_to_entry(copy);
5216: copy->type = VM_MAP_COPY_ENTRY_LIST;
5217: copy->cpy_hdr.nentries = 0;
5218: copy->cpy_hdr.entries_pageable = TRUE;
5219:
5220: /*
5221: * Allocate and initialize an entry for object
5222: */
5223: new_entry = vm_map_copy_entry_create(copy);
5224: new_entry->vme_start = trunc_page(copy->offset);
5225: new_entry->vme_end = round_page(copy->offset + copy->size);
5226: new_entry->object.vm_object = object;
5227: new_entry->offset = 0;
5228: new_entry->is_shared = FALSE;
5229: new_entry->is_sub_map = FALSE;
5230: new_entry->needs_copy = FALSE;
5231: new_entry->protection = VM_PROT_DEFAULT;
5232: new_entry->max_protection = VM_PROT_ALL;
5233: new_entry->inheritance = VM_INHERIT_DEFAULT;
5234: new_entry->wired_count = 0;
5235: new_entry->user_wired_count = 0;
5236: new_entry->projected_on = 0;
5237:
5238: /*
5239: * Insert entry into copy object, and return.
5240: */
5241: vm_map_copy_entry_link(copy, vm_map_copy_last_entry(copy), new_entry);
5242: return(KERN_SUCCESS);
5243: }
5244: #endif /* NORMA_IPC */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.