diff options
Diffstat (limited to 'vm/vm_map.h')
| -rw-r--r-- | vm/vm_map.h | 585 | 
1 files changed, 585 insertions, 0 deletions
diff --git a/vm/vm_map.h b/vm/vm_map.h new file mode 100644 index 0000000..a4949e4 --- /dev/null +++ b/vm/vm_map.h @@ -0,0 +1,585 @@ +/* + * Mach Operating System + * Copyright (c) 1991,1990,1989,1988,1987 Carnegie Mellon University. + * Copyright (c) 1993,1994 The University of Utah and + * the Computer Systems Laboratory (CSL). + * All rights reserved. + * + * Permission to use, copy, modify and distribute this software and its + * documentation is hereby granted, provided that both the copyright + * notice and this permission notice appear in all copies of the + * software, derivative works or modified versions, and any portions + * thereof, and that both notices appear in supporting documentation. + * + * CARNEGIE MELLON, THE UNIVERSITY OF UTAH AND CSL ALLOW FREE USE OF + * THIS SOFTWARE IN ITS "AS IS" CONDITION, AND DISCLAIM ANY LIABILITY + * OF ANY KIND FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF + * THIS SOFTWARE. + * + * Carnegie Mellon requests users of this software to return to + * + *  Software Distribution Coordinator  or  Software.Distribution@CS.CMU.EDU + *  School of Computer Science + *  Carnegie Mellon University + *  Pittsburgh PA 15213-3890 + * + * any improvements or extensions that they make and grant Carnegie Mellon + * the rights to redistribute these changes. + */ +/* + *	File:	vm/vm_map.h + *	Author:	Avadis Tevanian, Jr., Michael Wayne Young + *	Date:	1985 + * + *	Virtual memory map module definitions. + * + * Contributors: + *	avie, dlb, mwyoung + */ + +#ifndef	_VM_VM_MAP_H_ +#define _VM_VM_MAP_H_ + +#include <mach/kern_return.h> +#include <mach/boolean.h> +#include <mach/machine/vm_types.h> +#include <mach/vm_attributes.h> +#include <mach/vm_prot.h> +#include <mach/vm_inherit.h> +#include <mach/vm_wire.h> +#include <mach/vm_sync.h> +#include <vm/pmap.h> +#include <vm/vm_object.h> +#include <vm/vm_page.h> +#include <vm/vm_types.h> +#include <kern/list.h> +#include <kern/lock.h> +#include <kern/rbtree.h> +#include <kern/macros.h> + +/* TODO: make it dynamic */ +#define KENTRY_DATA_SIZE (256*PAGE_SIZE) + +/* + *	Types defined: + * + *	vm_map_entry_t		an entry in an address map. + *	vm_map_version_t	a timestamp of a map, for use with vm_map_lookup + *	vm_map_copy_t		represents memory copied from an address map, + *				 used for inter-map copy operations + */ + +/* + *	Type:		vm_map_object_t [internal use only] + * + *	Description: + *		The target of an address mapping, either a virtual + *		memory object or a sub map (of the kernel map). + */ +typedef union vm_map_object { +	struct vm_object	*vm_object;	/* object object */ +	struct vm_map		*sub_map;	/* belongs to another map */ +} vm_map_object_t; + +/* + *	Type:		vm_map_entry_t [internal use only] + * + *	Description: + *		A single mapping within an address map. + * + *	Implementation: + *		Address map entries consist of start and end addresses, + *		a VM object (or sub map) and offset into that object, + *		and user-exported inheritance and protection information. + *		Control information for virtual copy operations is also + *		stored in the address map entry. + */ +struct vm_map_links { +	struct vm_map_entry	*prev;		/* previous entry */ +	struct vm_map_entry	*next;		/* next entry */ +	vm_offset_t		start;		/* start address */ +	vm_offset_t		end;		/* end address */ +}; + +struct vm_map_entry { +	struct vm_map_links	links;		/* links to other entries */ +#define vme_prev		links.prev +#define vme_next		links.next +#define vme_start		links.start +#define vme_end			links.end +	struct rbtree_node	tree_node;	/* links to other entries in tree */ +	struct rbtree_node	gap_node;	/* links to other entries in gap tree */ +	struct list		gap_list;	/* links to other entries with +						   the same gap size */ +	vm_size_t		gap_size;	/* size of available memory +						   following this entry */ +	union vm_map_object	object;		/* object I point to */ +	vm_offset_t		offset;		/* offset into object */ +	unsigned int +	/* boolean_t */		in_gap_tree:1,	/* entry is in the gap tree if true, +						   or linked to other entries with +						   the same gap size if false */ +	/* boolean_t */		is_shared:1,	/* region is shared */ +	/* boolean_t */		is_sub_map:1,	/* Is "object" a submap? */ +	/* boolean_t */		in_transition:1, /* Entry being changed */ +	/* boolean_t */		needs_wakeup:1,  /* Waiters on in_transition */ +		/* Only used when object is a vm_object: */ +	/* boolean_t */		needs_copy:1;    /* does object need to be copied */ + +		/* Only in task maps: */ +	vm_prot_t		protection;	/* protection code */ +	vm_prot_t		max_protection;	/* maximum protection */ +	vm_inherit_t		inheritance;	/* inheritance */ +	unsigned short		wired_count;	/* can be paged if = 0 */ +	vm_prot_t		wired_access;	/* wiring access types, as accepted +						   by vm_map_pageable; used on wiring +						   scans when protection != VM_PROT_NONE */ +	struct vm_map_entry     *projected_on;  /* 0 for normal map entry +           or persistent kernel map projected buffer entry; +           -1 for non-persistent kernel map projected buffer entry; +           pointer to corresponding kernel map entry for user map +           projected buffer entry */ +}; + +typedef struct vm_map_entry	*vm_map_entry_t; + +#define VM_MAP_ENTRY_NULL	((vm_map_entry_t) 0) + +/* + *	Type:		struct vm_map_header + * + *	Description: + *		Header for a vm_map and a vm_map_copy. + */ +struct vm_map_header { +	struct vm_map_links	links;		/* first, last, min, max */ +	struct rbtree		tree;		/* Sorted tree of entries */ +	struct rbtree		gap_tree;	/* Sorted tree of gap lists +						   for allocations */ +	int			nentries;	/* Number of entries */ +}; + +/* + *	Type:		vm_map_t [exported; contents invisible] + * + *	Description: + *		An address map -- a directory relating valid + *		regions of a task's address space to the corresponding + *		virtual memory objects. + * + *	Implementation: + *		Maps are doubly-linked lists of map entries, sorted + *		by address.  They're also contained in a red-black tree. + *		One hint is used to start searches again at the last + *		successful search, insertion, or removal.  If the hint + *		lookup failed (i.e. the hint didn't refer to the requested + *		entry), a BST lookup is performed.  Another hint is used to + *		quickly find free space. + */ +struct vm_map { +	lock_data_t		lock;		/* Lock for map data */ +	struct vm_map_header	hdr;		/* Map entry header */ +#define min_offset		hdr.links.start	/* start of range */ +#define max_offset		hdr.links.end	/* end of range */ +	pmap_t			pmap;		/* Physical map */ +	vm_size_t		size;		/* virtual size */ +	vm_size_t		size_wired;	/* wired size */ +	int			ref_count;	/* Reference count */ +	decl_simple_lock_data(,	ref_lock)	/* Lock for ref_count field */ +	vm_map_entry_t		hint;		/* hint for quick lookups */ +	decl_simple_lock_data(,	hint_lock)	/* lock for hint storage */ +	vm_map_entry_t		first_free;	/* First free space hint */ + +	/* Flags */ +	unsigned int	wait_for_space:1,	/* Should callers wait +						   for space? */ +	/* boolean_t */ wiring_required:1;	/* New mappings are wired? */ + +	unsigned int		timestamp;	/* Version number */ + +	const char		*name;		/* Associated name */ +}; + +#define vm_map_to_entry(map)	((struct vm_map_entry *) &(map)->hdr.links) +#define vm_map_first_entry(map)	((map)->hdr.links.next) +#define vm_map_last_entry(map)	((map)->hdr.links.prev) + +/* + *	Type:		vm_map_version_t [exported; contents invisible] + * + *	Description: + *		Map versions may be used to quickly validate a previous + *		lookup operation. + * + *	Usage note: + *		Because they are bulky objects, map versions are usually + *		passed by reference. + * + *	Implementation: + *		Just a timestamp for the main map. + */ +typedef struct vm_map_version { +	unsigned int	main_timestamp; +} vm_map_version_t; + +/* + *	Type:		vm_map_copy_t [exported; contents invisible] + * + *	Description: + *		A map copy object represents a region of virtual memory + *		that has been copied from an address map but is still + *		in transit. + * + *		A map copy object may only be used by a single thread + *		at a time. + * + *	Implementation: + * 		There are three formats for map copy objects. + *		The first is very similar to the main + *		address map in structure, and as a result, some + *		of the internal maintenance functions/macros can + *		be used with either address maps or map copy objects. + * + *		The map copy object contains a header links + *		entry onto which the other entries that represent + *		the region are chained. + * + *		The second format is a single vm object.  This is used + *		primarily in the pageout path.  The third format is a + *		list of vm pages.  An optional continuation provides + *		a hook to be called to obtain more of the memory, + *		or perform other operations.  The continuation takes 3 + *		arguments, a saved arg buffer, a pointer to a new vm_map_copy + *		(returned) and an abort flag (abort if TRUE). + */ + +#define VM_MAP_COPY_PAGE_LIST_MAX	64 + +struct vm_map_copy; +struct vm_map_copyin_args_data; +typedef kern_return_t (*vm_map_copy_cont_fn)(struct vm_map_copyin_args_data*, struct vm_map_copy**); + +typedef struct vm_map_copy { +	int			type; +#define VM_MAP_COPY_ENTRY_LIST	1 +#define VM_MAP_COPY_OBJECT	2 +#define VM_MAP_COPY_PAGE_LIST	3 +	vm_offset_t		offset; +	vm_size_t		size; +	union { +	    struct vm_map_header	hdr;	/* ENTRY_LIST */ +	    struct {				/* OBJECT */ +	    	vm_object_t		object; +	    } c_o; +	    struct {				/* PAGE_LIST */ +		vm_page_t		page_list[VM_MAP_COPY_PAGE_LIST_MAX]; +		int			npages; +		vm_map_copy_cont_fn cont; +		struct vm_map_copyin_args_data* cont_args; +	    } c_p; +	} c_u; +} *vm_map_copy_t; + +#define cpy_hdr			c_u.hdr + +#define cpy_object		c_u.c_o.object + +#define cpy_page_list		c_u.c_p.page_list +#define cpy_npages		c_u.c_p.npages +#define cpy_cont		c_u.c_p.cont +#define cpy_cont_args		c_u.c_p.cont_args + +#define	VM_MAP_COPY_NULL	((vm_map_copy_t) 0) + +/* + *	Useful macros for entry list copy objects + */ + +#define vm_map_copy_to_entry(copy)		\ +		((struct vm_map_entry *) &(copy)->cpy_hdr.links) +#define vm_map_copy_first_entry(copy)		\ +		((copy)->cpy_hdr.links.next) +#define vm_map_copy_last_entry(copy)		\ +		((copy)->cpy_hdr.links.prev) + +/* + *	Continuation macros for page list copy objects + */ + +#define	vm_map_copy_invoke_cont(old_copy, new_copy, result)		\ +MACRO_BEGIN								\ +	vm_map_copy_page_discard(old_copy);				\ +	*result = (*((old_copy)->cpy_cont))((old_copy)->cpy_cont_args,	\ +					    new_copy);			\ +	(old_copy)->cpy_cont = (kern_return_t (*)()) 0;			\ +MACRO_END + +#define	vm_map_copy_invoke_extend_cont(old_copy, new_copy, result)	\ +MACRO_BEGIN								\ +	*result = (*((old_copy)->cpy_cont))((old_copy)->cpy_cont_args,	\ +					    new_copy);			\ +	(old_copy)->cpy_cont = (kern_return_t (*)()) 0;			\ +MACRO_END + +#define vm_map_copy_abort_cont(old_copy)				\ +MACRO_BEGIN								\ +	vm_map_copy_page_discard(old_copy);				\ +	(*((old_copy)->cpy_cont))((old_copy)->cpy_cont_args,		\ +				  (vm_map_copy_t *) 0);			\ +	(old_copy)->cpy_cont = (kern_return_t (*)()) 0;			\ +	(old_copy)->cpy_cont_args = VM_MAP_COPYIN_ARGS_NULL;		\ +MACRO_END + +#define vm_map_copy_has_cont(copy)					\ +    (((copy)->cpy_cont) != (kern_return_t (*)()) 0) + +/* + *	Continuation structures for vm_map_copyin_page_list. + */ + +typedef	struct vm_map_copyin_args_data { +	vm_map_t	map; +	vm_offset_t	src_addr; +	vm_size_t	src_len; +	vm_offset_t	destroy_addr; +	vm_size_t	destroy_len; +	boolean_t	steal_pages; +} vm_map_copyin_args_data_t, *vm_map_copyin_args_t; + +#define	VM_MAP_COPYIN_ARGS_NULL	((vm_map_copyin_args_t) 0) + +/* + *	Macros:		vm_map_lock, etc. [internal use only] + *	Description: + *		Perform locking on the data portion of a map. + */ + +#define vm_map_lock_init(map)			\ +MACRO_BEGIN					\ +	lock_init(&(map)->lock, TRUE);		\ +	(map)->timestamp = 0;			\ +MACRO_END + +void vm_map_lock(struct vm_map *map); +void vm_map_unlock(struct vm_map *map); + +#define vm_map_lock_read(map)	lock_read(&(map)->lock) +#define vm_map_unlock_read(map)	lock_read_done(&(map)->lock) +#define vm_map_lock_write_to_read(map) \ +		lock_write_to_read(&(map)->lock) +#define vm_map_lock_read_to_write(map) \ +		(lock_read_to_write(&(map)->lock) || (((map)->timestamp++), 0)) +#define vm_map_lock_set_recursive(map) \ +		lock_set_recursive(&(map)->lock) +#define vm_map_lock_clear_recursive(map) \ +		lock_clear_recursive(&(map)->lock) + +/* + *	Exported procedures that operate on vm_map_t. + */ + +/* Initialize the module */ +extern void		vm_map_init(void); + +/* Initialize an empty map */ +extern void		vm_map_setup(vm_map_t, pmap_t, vm_offset_t, vm_offset_t); +/* Create an empty map */ +extern vm_map_t		vm_map_create(pmap_t, vm_offset_t, vm_offset_t); +/* Create a map in the image of an existing map */ +extern vm_map_t		vm_map_fork(vm_map_t); + +/* Gain a reference to an existing map */ +extern void		vm_map_reference(vm_map_t); +/* Lose a reference */ +extern void		vm_map_deallocate(vm_map_t); + +/* Enter a mapping */ +extern kern_return_t	vm_map_enter(vm_map_t, vm_offset_t *, vm_size_t, +				     vm_offset_t, boolean_t, vm_object_t, +				     vm_offset_t, boolean_t, vm_prot_t, +				     vm_prot_t, vm_inherit_t); +/* Enter a mapping primitive */ +extern kern_return_t	vm_map_find_entry(vm_map_t, vm_offset_t *, vm_size_t, +					  vm_offset_t, vm_object_t, +					  vm_map_entry_t *); +/* Deallocate a region */ +extern kern_return_t	vm_map_remove(vm_map_t, vm_offset_t, vm_offset_t); +/* Change protection */ +extern kern_return_t	vm_map_protect(vm_map_t, vm_offset_t, vm_offset_t, +				       vm_prot_t, boolean_t); +/* Change inheritance */ +extern kern_return_t	vm_map_inherit(vm_map_t, vm_offset_t, vm_offset_t, +				       vm_inherit_t); + +/* Look up an address */ +extern kern_return_t	vm_map_lookup(vm_map_t *, vm_offset_t, vm_prot_t, +				      vm_map_version_t *, vm_object_t *, +				      vm_offset_t *, vm_prot_t *, boolean_t *); +/* Find a map entry */ +extern boolean_t	vm_map_lookup_entry(vm_map_t, vm_offset_t, +					    vm_map_entry_t *); +/* Verify that a previous lookup is still valid */ +extern boolean_t	vm_map_verify(vm_map_t, vm_map_version_t *); +/* vm_map_verify_done is now a macro -- see below */ +/* Make a copy of a region */ +extern kern_return_t	vm_map_copyin(vm_map_t, vm_offset_t, vm_size_t, +				      boolean_t, vm_map_copy_t *); +/* Make a copy of a region using a page list copy */ +extern kern_return_t	vm_map_copyin_page_list(vm_map_t, vm_offset_t, +						vm_size_t, boolean_t, +						boolean_t, vm_map_copy_t *, +						boolean_t); +/* Place a copy into a map */ +extern kern_return_t	vm_map_copyout(vm_map_t, vm_offset_t *, vm_map_copy_t); +/* Overwrite existing memory with a copy */ +extern kern_return_t	vm_map_copy_overwrite(vm_map_t, vm_offset_t, +					      vm_map_copy_t, boolean_t); +/* Discard a copy without using it */ +extern void		vm_map_copy_discard(vm_map_copy_t); +extern void		vm_map_copy_page_discard(vm_map_copy_t); +extern vm_map_copy_t	vm_map_copy_copy(vm_map_copy_t); +/* Page list continuation version of previous */ +extern kern_return_t	vm_map_copy_discard_cont(vm_map_copyin_args_t, +						 vm_map_copy_t *); + +extern boolean_t	vm_map_coalesce_entry(vm_map_t, vm_map_entry_t); + +/* Add or remove machine- dependent attributes from map regions */ +extern kern_return_t	vm_map_machine_attribute(vm_map_t, vm_offset_t, +						 vm_size_t, +						 vm_machine_attribute_t, +						 vm_machine_attribute_val_t *); + +extern kern_return_t	vm_map_msync(vm_map_t, +				     vm_offset_t, vm_size_t, vm_sync_t); + +/* Delete entry from map */ +extern void		vm_map_entry_delete(vm_map_t, vm_map_entry_t); + +kern_return_t vm_map_delete( +    vm_map_t   	map, +    vm_offset_t    	start, +    vm_offset_t    	end); + +kern_return_t vm_map_copyout_page_list( +    vm_map_t    	dst_map, +    vm_offset_t 	*dst_addr,  /* OUT */ +    vm_map_copy_t   	copy); + +void vm_map_copy_page_discard (vm_map_copy_t copy); + +boolean_t vm_map_lookup_entry( +	vm_map_t	map, +	vm_offset_t	address, +	vm_map_entry_t	*entry); /* OUT */ + +static inline void vm_map_set_name(vm_map_t map, const char *name) +{ +	map->name = name; +} + + +/* + *	Functions implemented as macros + */ +#define		vm_map_min(map)		((map)->min_offset) +						/* Lowest valid address in +						 * a map */ + +#define		vm_map_max(map)		((map)->max_offset) +						/* Highest valid address */ + +#define		vm_map_pmap(map)	((map)->pmap) +						/* Physical map associated +						 * with this address map */ + +#define		vm_map_verify_done(map, version)    (vm_map_unlock_read(map)) +						/* Operation that required +						 * a verified lookup is +						 * now complete */ +/* + *	Pageability functions. + */ +extern kern_return_t	vm_map_pageable(vm_map_t, vm_offset_t, vm_offset_t, +					vm_prot_t, boolean_t, boolean_t); + +extern kern_return_t	vm_map_pageable_all(vm_map_t, vm_wire_t); + +/* + *	Submap object.  Must be used to create memory to be put + *	in a submap by vm_map_submap. + */ +extern vm_object_t	vm_submap_object; + +/* + *  vm_map_copyin_object: + * + *  Create a copy object from an object. + *  Our caller donates an object reference. + */ +extern kern_return_t vm_map_copyin_object( +    vm_object_t object, +    vm_offset_t offset,     /* offset of region in object */ +    vm_size_t   size,       /* size of region in object */ +    vm_map_copy_t   *copy_result);   /* OUT */ + +/* + *  vm_map_submap:      [ kernel use only ] + * + *  Mark the given range as handled by a subordinate map. + * + *  This range must have been created with vm_map_find using + *  the vm_submap_object, and no other operations may have been + *  performed on this range prior to calling vm_map_submap. + * + *  Only a limited number of operations can be performed + *  within this rage after calling vm_map_submap: + *      vm_fault + *  [Don't try vm_map_copyin!] + * + *  To remove a submapping, one must first remove the + *  range from the superior map, and then destroy the + *  submap (if desired).  [Better yet, don't try it.] + */ +extern kern_return_t vm_map_submap( +    vm_map_t   map, +    vm_offset_t    start, +    vm_offset_t    end, +    vm_map_t        submap); + +/* + *	Wait and wakeup macros for in_transition map entries. + */ +#define vm_map_entry_wait(map, interruptible)    	\ +        MACRO_BEGIN                                     \ +        assert_wait((event_t)&(map)->hdr, interruptible);	\ +        vm_map_unlock(map);                             \ +	thread_block((void (*)()) 0);			\ +        MACRO_END + +#define vm_map_entry_wakeup(map)        thread_wakeup((event_t)&(map)->hdr) + +/* + *      This routine is called only when it is known that + *      the entry must be split. + */ +extern void _vm_map_clip_start( +        struct vm_map_header *map_header, +        vm_map_entry_t entry, +        vm_offset_t	start, +        boolean_t	link_gap); + +/* + *      vm_map_clip_end:        [ internal use only ] + * + *      Asserts that the given entry ends at or before + *      the specified address; if necessary, + *      it splits the entry into two. + */ +void _vm_map_clip_end( +	struct vm_map_header 	*map_header, +	vm_map_entry_t		entry, +	vm_offset_t		end, +	boolean_t		link_gap); + +#endif	/* _VM_VM_MAP_H_ */  | 
