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