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